Compare commits
240 Commits
STABLE-0_7
...
STABLE-1_1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fef5c4c9a0 | ||
|
|
61dc2e7dd5 | ||
|
|
11a820458f | ||
|
|
9e7418090d | ||
|
|
0b3b713123 | ||
|
|
00f8cf57cd | ||
|
|
c55c375b0a | ||
|
|
db76ca248b | ||
|
|
182e1909b2 | ||
|
|
3aea7bc053 | ||
|
|
39c35732de | ||
|
|
6c8850698d | ||
|
|
818a726679 | ||
|
|
f8663a7129 | ||
|
|
7571fe5d13 | ||
|
|
60dc1c22f7 | ||
|
|
02b575e9e4 | ||
|
|
6facaf8f05 | ||
|
|
319a972e75 | ||
|
|
61cdbb30a6 | ||
|
|
5088a38b9f | ||
|
|
f5c6a6d075 | ||
|
|
b5340dd739 | ||
|
|
e1dcfcbb76 | ||
|
|
43d448e73f | ||
|
|
33fbb06604 | ||
|
|
e1b215aa73 | ||
|
|
6a17ef925d | ||
|
|
7599985a0a | ||
|
|
07c0bc288a | ||
|
|
f05d392920 | ||
|
|
e11d57c883 | ||
|
|
baf377679a | ||
|
|
f9355136d8 | ||
|
|
bb76e69567 | ||
|
|
533fc217d4 | ||
|
|
ac5c6695c1 | ||
|
|
3160488352 | ||
|
|
8579e4144f | ||
|
|
6880fa62f8 | ||
|
|
2cf4287197 | ||
|
|
86c774443c | ||
|
|
3b715f4602 | ||
|
|
ec0c2bea6e | ||
|
|
1b3682cfa9 | ||
|
|
2a9ee35411 | ||
|
|
0e0a7d82de | ||
|
|
dfa96852f0 | ||
|
|
a549ec0382 | ||
|
|
c61f01b206 | ||
|
|
15257f4524 | ||
|
|
089378ef87 | ||
|
|
805f495d84 | ||
|
|
928dd94ba6 | ||
|
|
b429918b32 | ||
|
|
62a37a4876 | ||
|
|
0e96ece6c6 | ||
|
|
f1eca32536 | ||
|
|
ed59dc1ada | ||
|
|
a5cd3fcafd | ||
|
|
f3def542ee | ||
|
|
aa249922df | ||
|
|
37a0c57bed | ||
|
|
90b7e68b4e | ||
|
|
1a0c497007 | ||
|
|
fd49ee3c8d | ||
|
|
3488a5c3c4 | ||
|
|
ae4955f59e | ||
|
|
fab107a9df | ||
|
|
bb87d19e84 | ||
|
|
4e309b7992 | ||
|
|
64aa4c716d | ||
|
|
6b0852a21f | ||
|
|
8afd3e882e | ||
|
|
791fa28817 | ||
|
|
3fab752640 | ||
|
|
67dd939d83 | ||
|
|
ec9b447be1 | ||
|
|
99e3fe9ae1 | ||
|
|
eb99d21022 | ||
|
|
793cbcdff8 | ||
|
|
751557bcbf | ||
|
|
252dcd8626 | ||
|
|
0ad7ea16d2 | ||
|
|
79842d4fdd | ||
|
|
1e1f5d5462 | ||
|
|
19d8ffe177 | ||
|
|
4cb8192c1d | ||
|
|
2ed5bc5195 | ||
|
|
fae1397468 | ||
|
|
e871548772 | ||
|
|
a3d27e30e0 | ||
|
|
89abd1f58e | ||
|
|
fae709d9ea | ||
|
|
36df79b207 | ||
|
|
b9ebcd7738 | ||
|
|
515fb5a3fd | ||
|
|
785f90d9fa | ||
|
|
22ac311496 | ||
|
|
0e31ca73c0 | ||
|
|
98ba558fa5 | ||
|
|
c4ef1e5c19 | ||
|
|
1fa0d66f15 | ||
|
|
4680307a34 | ||
|
|
42a6fa972d | ||
|
|
1da6c35a6d | ||
|
|
7c427a4dce | ||
|
|
c2abae538b | ||
|
|
eb69032773 | ||
|
|
fb5452910f | ||
|
|
a6d37fcb25 | ||
|
|
fb18e1f036 | ||
|
|
786cbee510 | ||
|
|
a4f5673ff3 | ||
|
|
1121f2b7f7 | ||
|
|
4d30218eb2 | ||
|
|
d7699ca81d | ||
|
|
afc3bc6b65 | ||
|
|
6f066fca82 | ||
|
|
5e24ae49a6 | ||
|
|
bf74ffe974 | ||
|
|
2074861b57 | ||
|
|
58b64d42f1 | ||
|
|
a6ab0405ea | ||
|
|
8273b54108 | ||
|
|
c356f560e8 | ||
|
|
8d052ecf24 | ||
|
|
45e36d9f56 | ||
|
|
c222d8b672 | ||
|
|
efed3f1f0d | ||
|
|
7524893802 | ||
|
|
25a0273b05 | ||
|
|
ce0410b205 | ||
|
|
efe5ce5c78 | ||
|
|
07f52b4b96 | ||
|
|
0be3598990 | ||
|
|
c3284c30cd | ||
|
|
2d94bf4998 | ||
|
|
31c1e72b8c | ||
|
|
d11fcafad8 | ||
|
|
27c6d299cf | ||
|
|
450dd65165 | ||
|
|
26819e6c39 | ||
|
|
6587efb3e8 | ||
|
|
8d2200f29b | ||
|
|
e4295396ac | ||
|
|
5c7a70df28 | ||
|
|
16a7a8258f | ||
|
|
fb1f61b212 | ||
|
|
c3137df39c | ||
|
|
2df9cd7262 | ||
|
|
a23f6afbee | ||
|
|
e37f7fafc1 | ||
|
|
7b803465ad | ||
|
|
273612b251 | ||
|
|
e2bc8e86e2 | ||
|
|
79110ba469 | ||
|
|
9dd10e46ab | ||
|
|
29df95c514 | ||
|
|
015cb1a35d | ||
|
|
b217b020a5 | ||
|
|
0c960a82ce | ||
|
|
e84cc8c0ad | ||
|
|
c69b93b246 | ||
|
|
5e13b9528d | ||
|
|
8bb3cab9d2 | ||
|
|
ed201c35d2 | ||
|
|
4eadc22a36 | ||
|
|
4e2260c74c | ||
|
|
a5148c14a1 | ||
|
|
955d6206ee | ||
|
|
5df22b3468 | ||
|
|
aef86ec5ef | ||
|
|
94d3b04d68 | ||
|
|
d31830225c | ||
|
|
8f309a3fec | ||
|
|
1fe4edbe1c | ||
|
|
fe1696cef7 | ||
|
|
de2e311e6e | ||
|
|
384fb3c353 | ||
|
|
8603e19516 | ||
|
|
7a2751043a | ||
|
|
e2b0c6c702 | ||
|
|
5b12c61a81 | ||
|
|
b8ee8808b4 | ||
|
|
2db9551750 | ||
|
|
7dc51270ee | ||
|
|
237b5a2467 | ||
|
|
110e5af36c | ||
|
|
7d4aef9576 | ||
|
|
811b360df7 | ||
|
|
d91b54882a | ||
|
|
9106a1f2d5 | ||
|
|
2e2dada561 | ||
|
|
6d704c728e | ||
|
|
6c6f32f17f | ||
|
|
0e4ce326c2 | ||
|
|
d27448da8a | ||
|
|
d36b723056 | ||
|
|
2c8aa6f6f4 | ||
|
|
6f7c8fb355 | ||
|
|
82f852abf3 | ||
|
|
239c6fe070 | ||
|
|
579d2ad811 | ||
|
|
0cb355cd7c | ||
|
|
86135d12b9 | ||
|
|
10d42c6fa3 | ||
|
|
6434f7efad | ||
|
|
bfdf19f56c | ||
|
|
79c7a7a43d | ||
|
|
175053085a | ||
|
|
3d90c062fd | ||
|
|
fda71b1230 | ||
|
|
a916de3b66 | ||
|
|
30e5dfddb9 | ||
|
|
f9dea9d35b | ||
|
|
4ea55b1bbc | ||
|
|
caf3c16826 | ||
|
|
a6f1111469 | ||
|
|
33d0096b81 | ||
|
|
ed4c5d88a3 | ||
|
|
e85a892111 | ||
|
|
70cd10beae | ||
|
|
3a784509df | ||
|
|
5c7189124c | ||
|
|
f81c2744cc | ||
|
|
4bf3359574 | ||
|
|
47984b0496 | ||
|
|
3c339323ed | ||
|
|
7399722a88 | ||
|
|
7bfea6edb7 | ||
|
|
f75da2c393 | ||
|
|
475576ec20 | ||
|
|
f6a8e1df03 | ||
|
|
e1c4bfad05 | ||
|
|
1ed40e7983 | ||
|
|
035fcce9de | ||
|
|
19eed5ff8a | ||
|
|
7129d4797c | ||
|
|
707d31a083 |
181
CHANGELOG
181
CHANGELOG
@@ -1,12 +1,187 @@
|
|||||||
TODO
|
FUTURE
|
||||||
|
|
||||||
* TODO: The lwIP source code makes some invalid assumptions on processor
|
* TODO: The lwIP source code makes some invalid assumptions on processor
|
||||||
word-length, storage sizes and alignment. See the mailing lists for
|
word-length, storage sizes and alignment. See the mailing lists for
|
||||||
problems with exoteric architectures showing these problems.
|
problems with exoteric (/DSP) architectures showing these problems.
|
||||||
We still have to fix this neatly.
|
We still have to fix some of these issues neatly.
|
||||||
|
|
||||||
|
* TODO: the ARP layer is not protected against concurrent access. If
|
||||||
|
you run from a multitasking OS, serialize access to ARP (called from
|
||||||
|
your network device driver and from a timeout thread.)
|
||||||
|
|
||||||
|
* TODO: the PPP code is broken in a few ways. There are namespace
|
||||||
|
collisions on BSD systems and many assumptions on word-length
|
||||||
|
(sizeof(int)). In ppp.c an assumption is made on the availability of
|
||||||
|
a thread subsystem. Either PPP needs to be moved to contrib/ports/???
|
||||||
|
or rearranged to be more generic.
|
||||||
|
|
||||||
HISTORY
|
HISTORY
|
||||||
|
|
||||||
|
(CVS HEAD)
|
||||||
|
|
||||||
|
* [New changes go here]
|
||||||
|
|
||||||
|
(STABLE-1_1_1)
|
||||||
|
|
||||||
|
2006-03-03 Christiaan Simons
|
||||||
|
* ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap
|
||||||
|
access and added pbuf_alloc() return value checks.
|
||||||
|
|
||||||
|
2006-01-01 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is
|
||||||
|
now handled by the checksum routine properly.
|
||||||
|
|
||||||
|
2006-02-27 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* pbuf.c: Fix alignment; pbuf_init() would not work unless
|
||||||
|
pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.)
|
||||||
|
|
||||||
|
2005-12-20 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch
|
||||||
|
submitted by Mitrani Hiroshi.
|
||||||
|
|
||||||
|
2005-12-15 Christiaan Simons
|
||||||
|
* inet.c: Disabled the added summing routine to preserve code space.
|
||||||
|
|
||||||
|
2005-12-14 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson.
|
||||||
|
Added Curt McDowell's optimized checksumming routine for future
|
||||||
|
inclusion. Need to create test case for unaliged, aligned, odd,
|
||||||
|
even length combination of cases on various endianess machines.
|
||||||
|
|
||||||
|
2005-12-09 Christiaan Simons
|
||||||
|
* inet.c: Rewrote standard checksum routine in proper portable C.
|
||||||
|
|
||||||
|
2005-11-25 Christiaan Simons
|
||||||
|
* udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only.
|
||||||
|
* *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t,
|
||||||
|
u32_t, s32_t typedefs. This solves most debug word-length assumes.
|
||||||
|
|
||||||
|
2005-07-17 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* inet.c: Fixed unaligned 16-bit access in the standard checksum
|
||||||
|
routine by Peter Jolasson.
|
||||||
|
* slipif.c: Fixed implementation assumption of single-pbuf datagrams.
|
||||||
|
|
||||||
|
2005-02-04 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch.
|
||||||
|
* tcp_{out|in}.c: Applied patch fixing unaligned access.
|
||||||
|
|
||||||
|
2005-01-04 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement.
|
||||||
|
|
||||||
|
2005-01-03 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* udp.c: UDP pcb->recv() was called even when it was NULL.
|
||||||
|
|
||||||
|
(STABLE-1_1_0)
|
||||||
|
|
||||||
|
2004-12-28 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* etharp.*: Disabled multiple packets on the ARP queue.
|
||||||
|
This clashes with TCP queueing.
|
||||||
|
|
||||||
|
2004-11-28 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* etharp.*: Fixed race condition from ARP request to ARP timeout.
|
||||||
|
Halved the ARP period, doubled the period counts.
|
||||||
|
ETHARP_MAX_PENDING now should be at least 2. This prevents
|
||||||
|
the counter from reaching 0 right away (which would allow
|
||||||
|
too little time for ARP responses to be received).
|
||||||
|
|
||||||
|
2004-11-25 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* dhcp.c: Decline messages were not multicast but unicast.
|
||||||
|
* etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD.
|
||||||
|
Do not try hard to insert arbitrary packet's source address,
|
||||||
|
etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD.
|
||||||
|
etharp_query() now always DOES call ETHARP_TRY_HARD so that users
|
||||||
|
querying an address will see it appear in the cache (DHCP could
|
||||||
|
suffer from this when a server invalidly gave an in-use address.)
|
||||||
|
* ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are
|
||||||
|
comparing network addresses (identifiers), not the network masks
|
||||||
|
themselves.
|
||||||
|
* ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given
|
||||||
|
IP address actually belongs to the network of the given interface.
|
||||||
|
|
||||||
|
2004-11-24 Kieran Mansley <kjm25@cam.ac.uk>
|
||||||
|
* tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state.
|
||||||
|
|
||||||
|
(STABLE-1_1_0-RC1)
|
||||||
|
|
||||||
|
2004-10-16 Kieran Mansley <kjm25@cam.ac.uk>
|
||||||
|
* tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately,
|
||||||
|
even if one is already pending, if the rcv_wnd is above a threshold
|
||||||
|
(currently TCP_WND/2). This avoids waiting for a timer to expire to send a
|
||||||
|
delayed ACK in order to open the window if the stack is only receiving data.
|
||||||
|
|
||||||
|
2004-09-12 Kieran Mansley <kjm25@cam.ac.uk>
|
||||||
|
* tcp*.*: Retransmit time-out handling improvement by Sam Jansen.
|
||||||
|
|
||||||
|
2004-08-20 Tony Mountifield <tony@softins.co.uk>
|
||||||
|
* etharp.c: Make sure the first pbuf queued on an ARP entry
|
||||||
|
is properly ref counted.
|
||||||
|
|
||||||
|
2004-07-27 Tony Mountifield <tony@softins.co.uk>
|
||||||
|
* debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler
|
||||||
|
warnings about comparison.
|
||||||
|
* pbuf.c: Stopped compiler complaining of empty if statement
|
||||||
|
when LWIP_DEBUGF() empty. Closed an unclosed comment.
|
||||||
|
* tcp.c: Stopped compiler complaining of empty if statement
|
||||||
|
when LWIP_DEBUGF() empty.
|
||||||
|
* ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons().
|
||||||
|
* inet.c: Added a couple of casts to quiet the compiler.
|
||||||
|
No need to test isascii(c) before isdigit(c) or isxdigit(c).
|
||||||
|
|
||||||
|
2004-07-22 Tony Mountifield <tony@softins.co.uk>
|
||||||
|
* inet.c: Made data types consistent in inet_ntoa().
|
||||||
|
Added casts for return values of checksum routines, to pacify compiler.
|
||||||
|
* ip_frag.c, tcp_out.c, sockets.c, pbuf.c
|
||||||
|
Small corrections to some debugging statements, to pacify compiler.
|
||||||
|
|
||||||
|
2004-07-21 Tony Mountifield <tony@softins.co.uk>
|
||||||
|
* etharp.c: Removed spurious semicolon and added missing end-of-comment.
|
||||||
|
* ethernetif.c Updated low_level_output() to match prototype for
|
||||||
|
netif->linkoutput and changed low_level_input() similarly for consistency.
|
||||||
|
* api_msg.c: Changed recv_raw() from int to u8_t, to match prototype
|
||||||
|
of raw_recv() in raw.h and so avoid compiler error.
|
||||||
|
* sockets.c: Added trivial (int) cast to keep compiler happier.
|
||||||
|
* ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros.
|
||||||
|
|
||||||
|
(STABLE-1_0_0)
|
||||||
|
|
||||||
|
++ Changes:
|
||||||
|
|
||||||
|
2004-07-05 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure
|
||||||
|
your cc.h file defines this either 1 or 0. If non-defined,
|
||||||
|
defaults to 1.
|
||||||
|
* .c: Added <string.h> and <errno.h> includes where used.
|
||||||
|
* etharp.c: Made some array indices unsigned.
|
||||||
|
|
||||||
|
2004-06-27 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* netif.*: Added netif_set_up()/down().
|
||||||
|
* dhcp.c: Changes to restart program flow.
|
||||||
|
|
||||||
|
2004-05-07 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* etharp.c: In find_entry(), instead of a list traversal per candidate, do a
|
||||||
|
single-pass lookup for different candidates. Should exploit locality.
|
||||||
|
|
||||||
|
2004-04-29 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* tcp*.c: Cleaned up source comment documentation for Doxygen processing.
|
||||||
|
* opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC.
|
||||||
|
* etharp.c: update_arp_entry() only adds new ARP entries when adviced to by
|
||||||
|
the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option.
|
||||||
|
|
||||||
|
++ Bug fixes:
|
||||||
|
|
||||||
|
2004-04-27 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution
|
||||||
|
suggested by Timmy Brolin. Fix for 32-bit processors that cannot access
|
||||||
|
non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix
|
||||||
|
is to prefix the 14-bit Ethernet headers with two padding bytes.
|
||||||
|
|
||||||
|
2004-04-23 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* ip_addr.c: Fix in the ip_addr_isbroadcast() check.
|
||||||
|
* etharp.c: Fixed the case where the packet that initiates the ARP request
|
||||||
|
is not queued, and gets lost. Fixed the case where the packets destination
|
||||||
|
address is already known; we now always queue the packet and perform an ARP
|
||||||
|
request.
|
||||||
|
|
||||||
(STABLE-0_7_0)
|
(STABLE-0_7_0)
|
||||||
|
|
||||||
++ Bug fixes:
|
++ Bug fixes:
|
||||||
|
|||||||
26
README
26
README
@@ -7,7 +7,7 @@ Science (SICS).
|
|||||||
|
|
||||||
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
|
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
|
||||||
while still having a full scale TCP. This making lwIP suitable for use
|
while still having a full scale TCP. This making lwIP suitable for use
|
||||||
in embedded systems with tenths of kilobytes of free RAM and room for
|
in embedded systems with tens of kilobytes of free RAM and room for
|
||||||
around 40 kilobytes of code ROM.
|
around 40 kilobytes of code ROM.
|
||||||
|
|
||||||
FEATURES
|
FEATURES
|
||||||
@@ -42,29 +42,11 @@ CVS source tree.
|
|||||||
The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and
|
The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and
|
||||||
contributions (such as platform ports) are in the 'contrib' module.
|
contributions (such as platform ports) are in the 'contrib' module.
|
||||||
|
|
||||||
The CVS main trunk is the stable branch, which contains bug fixes and
|
See doc/savannah.txt for details on CVS server access for users and
|
||||||
tested features. The latest stable branch can be checked out by doing:
|
developers.
|
||||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
|
||||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co lwip
|
|
||||||
|
|
||||||
The 'STABLE' tag in the stable branch will represent the most stable
|
|
||||||
revision (which may be somewhat older to protect us from errors
|
|
||||||
introduced by merges). This 'STABLE' tagged version can be checked out
|
|
||||||
by doing:
|
|
||||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
|
||||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co -r STABLE lwip
|
|
||||||
|
|
||||||
The 'DEVEL' branch is the active development branch, which contains
|
|
||||||
bleeding edge changes, and may be instable. It can be checkout by doing:
|
|
||||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
|
||||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co -r DEVEL lwip
|
|
||||||
|
|
||||||
The current contrib CVS tree can be checked out by doing:
|
|
||||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
|
||||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co contrib
|
|
||||||
|
|
||||||
Last night's CVS tar ball can be downloaded from:
|
Last night's CVS tar ball can be downloaded from:
|
||||||
http://savannah.gnu.org/cvs.backups/lwip.tar.gz
|
http://savannah.gnu.org/cvs.backups/lwip.tar.gz [CHANGED - NEEDS FIXING]
|
||||||
|
|
||||||
The current CVS trees are web-browsable:
|
The current CVS trees are web-browsable:
|
||||||
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/
|
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ in lwIP development.
|
|||||||
2 How to contribute to lwIP
|
2 How to contribute to lwIP
|
||||||
|
|
||||||
Here is a short list of suggestions to anybody working with lwIP and
|
Here is a short list of suggestions to anybody working with lwIP and
|
||||||
trying to contribute bugreports, fixes, enhancements, platform ports etc.
|
trying to contribute bug reports, fixes, enhancements, platform ports etc.
|
||||||
First of all as you may already know lwIP is a volunteer project so feedback
|
First of all as you may already know lwIP is a volunteer project so feedback
|
||||||
to fixes or questions might often come late. Hopefully the bug and patch tracking
|
to fixes or questions might often come late. Hopefully the bug and patch tracking
|
||||||
features of Savannah help us not lose users' input.
|
features of Savannah help us not lose users' input.
|
||||||
@@ -14,19 +14,20 @@ features of Savannah help us not lose users' input.
|
|||||||
2.1 Source code style:
|
2.1 Source code style:
|
||||||
|
|
||||||
1. do not use tabs.
|
1. do not use tabs.
|
||||||
2. identation is two spaces per level.
|
2. indentation is two spaces per level (i.e. per tab).
|
||||||
3. end debug messages with a trailing newline (\n).
|
3. end debug messages with a trailing newline (\n).
|
||||||
4. one space between keyword and opening bracket.
|
4. one space between keyword and opening bracket.
|
||||||
5. no space between function and opening bracket.
|
5. no space between function and opening bracket.
|
||||||
6. one space and no newline before opening curly braces of a block.
|
6. one space and no newline before opening curly braces of a block.
|
||||||
7. spaces surrounding assignment and comparisons.
|
7. closing curly brace on a single line.
|
||||||
8. use current source code style as further reference.
|
8. spaces surrounding assignment and comparisons.
|
||||||
|
9. use current source code style as further reference.
|
||||||
|
|
||||||
2.2 Source code documentation style:
|
2.2 Source code documentation style:
|
||||||
|
|
||||||
1. JavaDoc compliant and Doxygen compatible.
|
1. JavaDoc compliant and Doxygen compatible.
|
||||||
2. Function documentation above functions in .c files, not .h files.
|
2. Function documentation above functions in .c files, not .h files.
|
||||||
(This forces you to synchronize documentation and behaviour.)
|
(This forces you to synchronize documentation and implementation.)
|
||||||
3. Use current documentation style as further reference.
|
3. Use current documentation style as further reference.
|
||||||
|
|
||||||
2.3 Bug reports and patches:
|
2.3 Bug reports and patches:
|
||||||
@@ -55,9 +56,7 @@ features of Savannah help us not lose users' input.
|
|||||||
|
|
||||||
2.4 Platform porters:
|
2.4 Platform porters:
|
||||||
|
|
||||||
1. If you've ported lwIP to a platform (an OS, a uC/processor or a combination of these) and you think it
|
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
|
||||||
could benefit others[1] you might want to post an url to a tarball or zip from which it can be imported
|
you think it could benefit others[1] you might want discuss this on the mailing list. You
|
||||||
to the contrib CVS module. Then you get CVS access and have to maintain your port :)
|
can also ask for CVS access to submit and maintain your port in the contrib CVS module.
|
||||||
|
|
||||||
[1] - lwIP CVS should not be just a place to keep your port so you don't have to set up your own CVS :)
|
|
||||||
Especially welcome are ports to common enough OS/hardware that others can have access too.
|
|
||||||
117
doc/rawapi.txt
117
doc/rawapi.txt
@@ -1,20 +1,21 @@
|
|||||||
Raw TCP/IP interface for lwIP 0.5
|
Raw TCP/IP interface for lwIP
|
||||||
|
|
||||||
Author: Adam Dunkels
|
Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons
|
||||||
|
|
||||||
lwIP provides two Application Program's Interfaces (APIs) for programs
|
lwIP provides two Application Program's Interfaces (APIs) for programs
|
||||||
to use for communication with the TCP/IP code: the sequential API
|
to use for communication with the TCP/IP code:
|
||||||
(often just called "the API") and the raw TCP/IP interface. This
|
* low-level "core" / "callback" or "raw" API.
|
||||||
document is intended as a description of the latter. For lwIP versions
|
* higher-level "sequential" API.
|
||||||
lower than 0.5, this API was not documented.
|
|
||||||
|
|
||||||
The sequential API provides a way for ordinary, sequential, programs
|
The sequential API provides a way for ordinary, sequential, programs
|
||||||
to use the lwIP stack. It is quite similar to the BSD socket API. The
|
to use the lwIP stack. It is quite similar to the BSD socket API. The
|
||||||
model of execution is based on the open-read-write-close
|
model of execution is based on the blocking open-read-write-close
|
||||||
paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
|
paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
|
||||||
code and the application program must reside in different execution
|
code and the application program must reside in different execution
|
||||||
contexts (threads).
|
contexts (threads).
|
||||||
|
|
||||||
|
** The remainder of this document discusses the "raw" API. **
|
||||||
|
|
||||||
The raw TCP/IP interface allows the application program to integrate
|
The raw TCP/IP interface allows the application program to integrate
|
||||||
better with the TCP/IP code. Program execution is event based by
|
better with the TCP/IP code. Program execution is event based by
|
||||||
having callback functions being called from within the TCP/IP
|
having callback functions being called from within the TCP/IP
|
||||||
@@ -34,7 +35,6 @@ Both APIs can be used simultaneously by different application
|
|||||||
programs. In fact, the sequential API is implemented as an application
|
programs. In fact, the sequential API is implemented as an application
|
||||||
program using the raw TCP/IP interface.
|
program using the raw TCP/IP interface.
|
||||||
|
|
||||||
|
|
||||||
--- Callbacks
|
--- Callbacks
|
||||||
|
|
||||||
Program execution is driven by callbacks. Each callback is an ordinary
|
Program execution is driven by callbacks. Each callback is an ordinary
|
||||||
@@ -272,6 +272,11 @@ level of complexity of UDP, the interface is significantly simpler.
|
|||||||
Sets the remote end of the pcb. This function does not generate any
|
Sets the remote end of the pcb. This function does not generate any
|
||||||
network traffic, but only set the remote address of the pcb.
|
network traffic, but only set the remote address of the pcb.
|
||||||
|
|
||||||
|
- err_t udp_disconnect(struct udp_pcb *pcb)
|
||||||
|
|
||||||
|
Remove the remote end of the pcb. This function does not generate
|
||||||
|
any network traffic, but only removes the remote address of the pcb.
|
||||||
|
|
||||||
- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||||
|
|
||||||
Sends the pbuf p. The pbuf is not deallocated.
|
Sends the pbuf p. The pbuf is not deallocated.
|
||||||
@@ -284,4 +289,98 @@ level of complexity of UDP, the interface is significantly simpler.
|
|||||||
void *recv_arg)
|
void *recv_arg)
|
||||||
|
|
||||||
Specifies a callback function that should be called when a UDP
|
Specifies a callback function that should be called when a UDP
|
||||||
datagram is received.
|
datagram is received.
|
||||||
|
|
||||||
|
|
||||||
|
--- System initalization
|
||||||
|
|
||||||
|
A truly complete and generic sequence for initializing the lwip stack
|
||||||
|
cannot be given because it depends on the build configuration (lwipopts.h)
|
||||||
|
and additional initializations for your runtime environment (e.g. timers).
|
||||||
|
|
||||||
|
We can give you some idea on how to proceed when using the raw API.
|
||||||
|
We assume a configuration using a single Ethernet netif and the
|
||||||
|
UDP and TCP transport layers, IPv4 and the DHCP client.
|
||||||
|
|
||||||
|
Call these functions in the order of appearance:
|
||||||
|
|
||||||
|
- stats_init()
|
||||||
|
|
||||||
|
Clears the structure where runtime statistics are gathered.
|
||||||
|
|
||||||
|
- sys_init()
|
||||||
|
|
||||||
|
Not of much use since we set the NO_SYS 1 option in lwipopts.h,
|
||||||
|
to be called for easy configuration changes.
|
||||||
|
|
||||||
|
- mem_init()
|
||||||
|
|
||||||
|
Initializes the dynamic memory heap defined by MEM_SIZE.
|
||||||
|
|
||||||
|
- memp_init()
|
||||||
|
|
||||||
|
Initializes the memory pools defined by MEMP_NUM_x.
|
||||||
|
|
||||||
|
- pbuf_init()
|
||||||
|
|
||||||
|
Initializes the pbuf memory pool defined by PBUF_POOL_SIZE.
|
||||||
|
|
||||||
|
- etharp_init()
|
||||||
|
|
||||||
|
Initializes the ARP table and queue.
|
||||||
|
Note: you must call etharp_tmr at a 10 second regular interval
|
||||||
|
after this initialization.
|
||||||
|
|
||||||
|
- ip_init()
|
||||||
|
|
||||||
|
Doesn't do much, it should be called to handle future changes.
|
||||||
|
|
||||||
|
- udp_init()
|
||||||
|
|
||||||
|
Clears the UDP PCB list.
|
||||||
|
|
||||||
|
- tcp_init()
|
||||||
|
|
||||||
|
Clears the TCP PCB list and clears some internal TCP timers.
|
||||||
|
Note: you must call tcp_fasttmr() and tcp_slowtmr() at the
|
||||||
|
predefined regular intervals after this initialization.
|
||||||
|
|
||||||
|
- netif_add(struct netif *netif, struct ip_addr *ipaddr,
|
||||||
|
struct ip_addr *netmask, struct ip_addr *gw,
|
||||||
|
void *state, err_t (* init)(struct netif *netif),
|
||||||
|
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||||
|
|
||||||
|
Adds your network interface to the netif_list. Allocate a struct
|
||||||
|
netif and pass a pointer to this structure as the first argument.
|
||||||
|
Give pointers to cleared ip_addr structures when using DHCP,
|
||||||
|
or fill them with sane numbers otherwise. The state pointer may be NULL.
|
||||||
|
|
||||||
|
The init function pointer must point to a initialization function for
|
||||||
|
your ethernet netif interface. The following code illustrates it's use.
|
||||||
|
|
||||||
|
err_t netif_if_init(struct netif *netif)
|
||||||
|
{
|
||||||
|
u8_t i;
|
||||||
|
|
||||||
|
for(i = 0; i < 6; i++) netif->hwaddr[i] = some_eth_addr[i];
|
||||||
|
init_my_eth_device();
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
The input function pointer must point to the lwip ip_input().
|
||||||
|
|
||||||
|
- netif_set_default(struct netif *netif)
|
||||||
|
|
||||||
|
Registers the default network interface.
|
||||||
|
|
||||||
|
- netif_set_up(struct netif *netif)
|
||||||
|
|
||||||
|
When the netif is fully configured this function must be called.
|
||||||
|
|
||||||
|
- dhcp_start(struct netif *netif)
|
||||||
|
|
||||||
|
Creates a new DHCP client for this interface on the first call.
|
||||||
|
Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at
|
||||||
|
the predefined regular intervals after starting the client.
|
||||||
|
|
||||||
|
You can peek in the netif->dhcp struct for the actual DHCP status.
|
||||||
|
|||||||
104
doc/savannah.txt
104
doc/savannah.txt
@@ -2,32 +2,69 @@ Daily Use Guide for using Savannah for lwIP
|
|||||||
|
|
||||||
Table of Contents:
|
Table of Contents:
|
||||||
|
|
||||||
1 - Anonymous CVS checkouts and updates (to be elaborated)
|
1 - Obtaining lwIP from the CVS repository
|
||||||
2 - Committers/developers CVS access using SSH (to be written)
|
2 - Committers/developers CVS access using SSH (to be written)
|
||||||
3 - Merging from DEVEL branch to main trunk (stable branch)
|
3 - Merging from DEVEL branch to main trunk (stable branch)
|
||||||
4 - How to release lwIP
|
4 - How to release lwIP
|
||||||
|
|
||||||
|
|
||||||
1 Anonymous CVS checkouts and updates
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
Obtain lwIP from the CVS main trunk (stable)
|
1 Obtaining lwIP from the CVS repository
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
To perform an anonymous CVS checkout of the main trunk (this is where
|
||||||
|
bug fixes and incremental enhancements occur), do this:
|
||||||
|
|
||||||
|
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout lwip
|
||||||
|
|
||||||
|
Or, obtain a stable branch (updated with bug fixes only) as follows:
|
||||||
|
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
|
||||||
|
-r STABLE-0_7 -d lwip-0.7 lwip
|
||||||
|
|
||||||
|
Or, obtain a specific (fixed) release as follows:
|
||||||
|
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
|
||||||
|
-r STABLE-0_7_0 -d lwip-0.7.0 lwip
|
||||||
|
|
||||||
|
3 Committers/developers CVS access using SSH
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption.
|
||||||
|
As such, CVS commits to the server occur through a SSH tunnel for project members.
|
||||||
|
To create a SSH2 key pair in UNIX-like environments, do this:
|
||||||
|
|
||||||
|
ssh-keygen -t dsa
|
||||||
|
|
||||||
|
Under Windows, a recommended SSH client is "PuTTY", freely available with good
|
||||||
|
documentation and a graphic user interface. Use its key generator.
|
||||||
|
|
||||||
|
Now paste the id_dsa.pub contents into your Savannah account public key list. Wait
|
||||||
|
a while so that Savannah can update its configuration (This can take minutes).
|
||||||
|
|
||||||
|
Try to login using SSH:
|
||||||
|
|
||||||
|
ssh -v your_login@cvs.sv.gnu.org
|
||||||
|
|
||||||
|
If it tells you:
|
||||||
|
|
||||||
|
Authenticating with public key "your_key_name"...
|
||||||
|
Server refused to allocate pty
|
||||||
|
|
||||||
|
then you could login; Savannah refuses to give you a shell - which is OK, as we
|
||||||
|
are allowed to use SSH for CVS only. Now, you should be able to do this:
|
||||||
|
|
||||||
export CVS_RSH=ssh
|
export CVS_RSH=ssh
|
||||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip
|
cvs -z3 -d:ext:your_login@cvs.sv.gnu.org:/sources/lwip co lwip
|
||||||
|
|
||||||
|
after which you can edit your local files with bug fixes or new features and
|
||||||
|
commit them. Make sure you know what you are doing when using CVS to make
|
||||||
|
changes on the repository. If in doubt, ask on the lwip-members mailing list.
|
||||||
|
|
||||||
(If SSH asks about authenticity of the host, you can check the key
|
(If SSH asks about authenticity of the host, you can check the key
|
||||||
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
|
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
|
||||||
|
|
||||||
Or, obtain a specific release as follows:
|
|
||||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_6_3 -d lwip-0.6.3 lwip
|
|
||||||
|
|
||||||
Or, obtain a development branch as follows:
|
|
||||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-DEVEL lwip
|
|
||||||
|
|
||||||
|
|
||||||
3 Merging from DEVEL branch to main trunk (stable)
|
3 Merging from DEVEL branch to main trunk (stable)
|
||||||
---------------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
Merging is a delicate process in CVS and requires the
|
Merging is a delicate process in CVS and requires the
|
||||||
following disciplined steps in order to prevent conflicts
|
following disciplined steps in order to prevent conflicts
|
||||||
@@ -69,46 +106,25 @@ tagged tree. Export is similar to a checkout, except that the CVS metadata
|
|||||||
is not created locally.
|
is not created locally.
|
||||||
|
|
||||||
export CVS_RSH=ssh
|
export CVS_RSH=ssh
|
||||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip export -r STABLE-0_6_3 -d lwip-0.6.3 lwip
|
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
|
||||||
|
-r STABLE-0_6_3 -d lwip-0.6.3 lwip
|
||||||
|
|
||||||
Archive this directory using tar, gzip'd, bzip2'd and zip'd.
|
Archive this directory using tar, gzip'd, bzip2'd and zip'd.
|
||||||
|
|
||||||
tar czvf lwip-0.6.3.tar.gz lwip-0.6.3
|
tar czvf lwip-0.6.3.tar.gz lwip-0.6.3
|
||||||
|
tar cjvf lwip-0.6.3.tar.bz2 lwip-0.6.3
|
||||||
|
zip -r lwip-0.6.3.zip lwip-0.6.3
|
||||||
|
|
||||||
First, make a local release directory to work in, I use "lwip-releases":
|
Now, sign the archives with a detached GPG binary signature as follows:
|
||||||
|
|
||||||
mkdir lwip-releases
|
gpg -b lwip-0.6.3.tar.gz
|
||||||
cd lwip-releases
|
gpg -b lwip-0.6.3.tar.bz2
|
||||||
|
gpg -b lwip-0.6.3.zip
|
||||||
|
|
||||||
Now, make a new release by creating a new directory for it (these are
|
Upload these files using anonymous FTP:
|
||||||
Savannah conventions so that it shows up in the Files list real nice):
|
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
|
||||||
|
|
||||||
mkdir stable.pkg
|
ncftp>mput *0.6.3.*
|
||||||
mkdir stable.pkg 0.6.3
|
|
||||||
|
|
||||||
We can now copy the tar archive we made earlier into the release directory:
|
|
||||||
|
|
||||||
cp ../../../lwip-0.6.3.tar.gz .
|
|
||||||
|
|
||||||
Finally, synchronize this directory upwards to Savannah:
|
|
||||||
|
|
||||||
rsync -n -e "ssh -1" -t -u -v -r *.pkg likewise@savannah.nongnu.org:/upload/lwip
|
|
||||||
|
|
||||||
This does a "dry run": no files are modified! After you have confirmed that
|
|
||||||
this is what you intended to do, remove "-n" and actually synchronize for
|
|
||||||
real. The release should now be available here:
|
|
||||||
|
|
||||||
http://savannah.nongnu.org/files/?group=lwip
|
|
||||||
|
|
||||||
---
|
|
||||||
Explanation of rsync options used:
|
|
||||||
|
|
||||||
-t: preserve file timestamps
|
|
||||||
-u: do not overwrite existing files, unless they are older
|
|
||||||
-v: be verbose (long format file attributes)
|
|
||||||
-r: recurse into directories
|
|
||||||
-n: dry-run, do not modify anything.
|
|
||||||
---
|
|
||||||
|
|
||||||
Additionally, you may post a news item on Savannah, like this:
|
Additionally, you may post a news item on Savannah, like this:
|
||||||
|
|
||||||
|
|||||||
10
src/FILES
10
src/FILES
@@ -1,11 +1,13 @@
|
|||||||
api/ - The code for the API.
|
api/ - The code for the high-level wrapper API. Not needed if
|
||||||
|
you use the lowel-level call-back/raw API.
|
||||||
|
|
||||||
core/ - The core files including protocol implementations, memory
|
core/ - The core of the TPC/IP stack; protocol implementations,
|
||||||
and buffer management etc.
|
memory and buffer management, and the low-level raw API.
|
||||||
|
|
||||||
include/ - lwIP include files.
|
include/ - lwIP include files.
|
||||||
|
|
||||||
netif/ - Generic network interface device drivers are kept here.
|
netif/ - Generic network interface device drivers are kept here,
|
||||||
|
as well as the ARP module.
|
||||||
|
|
||||||
For more information on the various subdirectories, check the FILES
|
For more information on the various subdirectories, check the FILES
|
||||||
file in each directory.
|
file in each directory.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -165,7 +165,7 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
|||||||
offset -= p->len;
|
offset -= p->len;
|
||||||
} else {
|
} else {
|
||||||
for(i = offset; i < p->len; ++i) {
|
for(i = offset; i < p->len; ++i) {
|
||||||
((char *)dataptr)[left] = ((char *)p->payload)[i];
|
((u8_t *)dataptr)[left] = ((u8_t *)p->payload)[i];
|
||||||
if (++left >= len) {
|
if (++left >= len) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -280,9 +280,10 @@ netconn_delete(struct netconn *conn)
|
|||||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||||
while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
|
while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
|
||||||
if (conn->type == NETCONN_TCP) {
|
if (conn->type == NETCONN_TCP) {
|
||||||
pbuf_free((struct pbuf *)mem);
|
if(mem != NULL)
|
||||||
|
pbuf_free((struct pbuf *)mem);
|
||||||
} else {
|
} else {
|
||||||
netbuf_delete((struct netbuf *)mem);
|
netbuf_delete((struct netbuf *)mem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_mbox_free(conn->recvmbox);
|
sys_mbox_free(conn->recvmbox);
|
||||||
@@ -672,7 +673,7 @@ netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
|
|||||||
api_msg_post(msg);
|
api_msg_post(msg);
|
||||||
sys_mbox_fetch(conn->mbox, NULL);
|
sys_mbox_fetch(conn->mbox, NULL);
|
||||||
if (conn->err == ERR_OK) {
|
if (conn->err == ERR_OK) {
|
||||||
dataptr = (void *)((char *)dataptr + len);
|
dataptr = (void *)((u8_t *)dataptr + len);
|
||||||
size -= len;
|
size -= len;
|
||||||
} else if (conn->err == ERR_MEM) {
|
} else if (conn->err == ERR_MEM) {
|
||||||
conn->err = ERR_OK;
|
conn->err = ERR_OK;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
#include "lwip/tcpip.h"
|
#include "lwip/tcpip.h"
|
||||||
|
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
static int
|
static u8_t
|
||||||
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||||
struct ip_addr *addr)
|
struct ip_addr *addr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -32,6 +32,9 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/api.h"
|
#include "lwip/api.h"
|
||||||
#include "lwip/arch.h"
|
#include "lwip/arch.h"
|
||||||
@@ -84,9 +87,12 @@ static int err_to_errno_table[11] = {
|
|||||||
EADDRINUSE /* ERR_USE -10 Address in use. */
|
EADDRINUSE /* ERR_USE -10 Address in use. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ERR_TO_ERRNO_TABLE_SIZE \
|
||||||
|
(sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
|
||||||
|
|
||||||
#define err_to_errno(err) \
|
#define err_to_errno(err) \
|
||||||
((err) < (sizeof(err_to_errno_table)/sizeof(int))) ? \
|
(-(err) >= 0 && -(err) < ERR_TO_ERRNO_TABLE_SIZE ? \
|
||||||
err_to_errno_table[-(err)] : EIO
|
err_to_errno_table[-(err)] : EIO)
|
||||||
|
|
||||||
#ifdef ERRNO
|
#ifdef ERRNO
|
||||||
#define set_errno(err) errno = (err)
|
#define set_errno(err) errno = (err)
|
||||||
@@ -415,7 +421,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
|||||||
ip_addr_debug_print(SOCKETS_DEBUG, addr);
|
ip_addr_debug_print(SOCKETS_DEBUG, addr);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
|
||||||
} else {
|
} else {
|
||||||
#if SOCKETS_DEBUG > 0
|
#if SOCKETS_DEBUG
|
||||||
addr = netbuf_fromaddr(buf);
|
addr = netbuf_fromaddr(buf);
|
||||||
port = netbuf_fromport(buf);
|
port = netbuf_fromport(buf);
|
||||||
|
|
||||||
@@ -993,7 +999,7 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
|
|||||||
/* UNIMPL case SO_SNDBUF: */
|
/* UNIMPL case SO_SNDBUF: */
|
||||||
/* UNIMPL case SO_RCVLOWAT: */
|
/* UNIMPL case SO_RCVLOWAT: */
|
||||||
/* UNIMPL case SO_SNDLOWAT: */
|
/* UNIMPL case SO_SNDLOWAT: */
|
||||||
#ifdef SO_REUSE
|
#if SO_REUSE
|
||||||
case SO_REUSEADDR:
|
case SO_REUSEADDR:
|
||||||
case SO_REUSEPORT:
|
case SO_REUSEPORT:
|
||||||
#endif /* SO_REUSE */
|
#endif /* SO_REUSE */
|
||||||
@@ -1079,7 +1085,7 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
|
|||||||
/* UNIMPL case SO_DONTROUTE: */
|
/* UNIMPL case SO_DONTROUTE: */
|
||||||
case SO_KEEPALIVE:
|
case SO_KEEPALIVE:
|
||||||
/* UNIMPL case SO_OOBINCLUDE: */
|
/* UNIMPL case SO_OOBINCLUDE: */
|
||||||
#ifdef SO_REUSE
|
#if SO_REUSE
|
||||||
case SO_REUSEADDR:
|
case SO_REUSEADDR:
|
||||||
case SO_REUSEPORT:
|
case SO_REUSEPORT:
|
||||||
#endif /* SO_REUSE */
|
#endif /* SO_REUSE */
|
||||||
@@ -1138,7 +1144,7 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
|
|||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") );
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") );
|
||||||
break;
|
break;
|
||||||
case TCP_KEEPALIVE:
|
case TCP_KEEPALIVE:
|
||||||
*(int*)optval = sock->conn->pcb.tcp->keepalive;
|
*(int*)optval = (int)sock->conn->pcb.tcp->keepalive;
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
|
||||||
break;
|
break;
|
||||||
} /* switch */
|
} /* switch */
|
||||||
@@ -1182,7 +1188,7 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
|
|||||||
/* UNIMPL case SO_SNDBUF: */
|
/* UNIMPL case SO_SNDBUF: */
|
||||||
/* UNIMPL case SO_RCVLOWAT: */
|
/* UNIMPL case SO_RCVLOWAT: */
|
||||||
/* UNIMPL case SO_SNDLOWAT: */
|
/* UNIMPL case SO_SNDLOWAT: */
|
||||||
#ifdef SO_REUSE
|
#if SO_REUSE
|
||||||
case SO_REUSEADDR:
|
case SO_REUSEADDR:
|
||||||
case SO_REUSEPORT:
|
case SO_REUSEPORT:
|
||||||
#endif /* SO_REUSE */
|
#endif /* SO_REUSE */
|
||||||
@@ -1264,7 +1270,7 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
|
|||||||
/* UNIMPL case SO_DONTROUTE: */
|
/* UNIMPL case SO_DONTROUTE: */
|
||||||
case SO_KEEPALIVE:
|
case SO_KEEPALIVE:
|
||||||
/* UNIMPL case SO_OOBINCLUDE: */
|
/* UNIMPL case SO_OOBINCLUDE: */
|
||||||
#ifdef SO_REUSE
|
#if SO_REUSE
|
||||||
case SO_REUSEADDR:
|
case SO_REUSEADDR:
|
||||||
case SO_REUSEPORT:
|
case SO_REUSEPORT:
|
||||||
#endif /* SO_REUSE */
|
#endif /* SO_REUSE */
|
||||||
@@ -1306,7 +1312,7 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
|
|||||||
break;
|
break;
|
||||||
case TCP_KEEPALIVE:
|
case TCP_KEEPALIVE:
|
||||||
sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval);
|
sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %u\n", s, sock->conn->pcb.tcp->keepalive));
|
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %lu\n", s, sock->conn->pcb.tcp->keepalive));
|
||||||
break;
|
break;
|
||||||
} /* switch */
|
} /* switch */
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -38,6 +38,7 @@
|
|||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
|
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
|
#include "lwip/ip_frag.h"
|
||||||
#include "lwip/udp.h"
|
#include "lwip/udp.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
|
|
||||||
@@ -46,34 +47,51 @@
|
|||||||
static void (* tcpip_init_done)(void *arg) = NULL;
|
static void (* tcpip_init_done)(void *arg) = NULL;
|
||||||
static void *tcpip_init_done_arg;
|
static void *tcpip_init_done_arg;
|
||||||
static sys_mbox_t mbox;
|
static sys_mbox_t mbox;
|
||||||
|
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
static int tcpip_tcp_timer_active = 0;
|
static int tcpip_tcp_timer_active = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tcpip_tcp_timer(void *arg)
|
tcpip_tcp_timer(void *arg)
|
||||||
{
|
{
|
||||||
(void)arg;
|
(void)arg;
|
||||||
|
|
||||||
|
/* call TCP timer handler */
|
||||||
tcp_tmr();
|
tcp_tmr();
|
||||||
|
/* timer still needed? */
|
||||||
if (tcp_active_pcbs || tcp_tw_pcbs) {
|
if (tcp_active_pcbs || tcp_tw_pcbs) {
|
||||||
|
/* restart timer */
|
||||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||||
} else {
|
} else {
|
||||||
tcpip_tcp_timer_active = 0;
|
/* disable timer */
|
||||||
|
tcpip_tcp_timer_active = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !NO_SYS
|
||||||
void
|
void
|
||||||
tcp_timer_needed(void)
|
tcp_timer_needed(void)
|
||||||
{
|
{
|
||||||
|
/* timer is off but needed again? */
|
||||||
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
|
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
|
||||||
tcpip_tcp_timer_active = 1;
|
/* enable and start timer */
|
||||||
|
tcpip_tcp_timer_active = 1;
|
||||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* !NO_SYS */
|
||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
|
|
||||||
|
#if IP_REASSEMBLY
|
||||||
|
static void
|
||||||
|
ip_timer(void *data)
|
||||||
|
{
|
||||||
|
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
|
||||||
|
ip_reass_tmr();
|
||||||
|
sys_timeout(1000, ip_timer, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tcpip_thread(void *arg)
|
tcpip_thread(void *arg)
|
||||||
{
|
{
|
||||||
@@ -87,6 +105,9 @@ tcpip_thread(void *arg)
|
|||||||
#endif
|
#endif
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
tcp_init();
|
tcp_init();
|
||||||
|
#endif
|
||||||
|
#if IP_REASSEMBLY
|
||||||
|
sys_timeout(1000, ip_timer, NULL);
|
||||||
#endif
|
#endif
|
||||||
if (tcpip_init_done != NULL) {
|
if (tcpip_init_done != NULL) {
|
||||||
tcpip_init_done(tcpip_init_done_arg);
|
tcpip_init_done(tcpip_init_done_arg);
|
||||||
|
|||||||
227
src/core/dhcp.c
227
src/core/dhcp.c
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Copyright (c) 2001-2003 Leon Woestenberg <leon.woestenberg@gmx.net>
|
* Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
* Copyright (c) 2001-2003 Axon Digital Design B.V., The Netherlands.
|
* Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -67,20 +67,26 @@
|
|||||||
* to remove the DHCP client.
|
* to remove the DHCP client.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/udp.h"
|
#include "lwip/udp.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
#include "netif/etharp.h"
|
#include "netif/etharp.h"
|
||||||
|
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/dhcp.h"
|
#include "lwip/dhcp.h"
|
||||||
|
|
||||||
|
#if LWIP_DHCP /* don't build if not configured for use in lwipopt.h */
|
||||||
|
|
||||||
/** global transaction identifier, must be
|
/** global transaction identifier, must be
|
||||||
* unique for each DHCP request. */
|
* unique for each DHCP request. We simply increment, starting
|
||||||
|
* with this value (easy to match with a packet analyzer) */
|
||||||
static u32_t xid = 0xABCD0000;
|
static u32_t xid = 0xABCD0000;
|
||||||
|
|
||||||
/** DHCP client state machine functions */
|
/** DHCP client state machine functions */
|
||||||
@@ -94,8 +100,7 @@ static void dhcp_check(struct netif *netif);
|
|||||||
static void dhcp_bind(struct netif *netif);
|
static void dhcp_bind(struct netif *netif);
|
||||||
static err_t dhcp_decline(struct netif *netif);
|
static err_t dhcp_decline(struct netif *netif);
|
||||||
static err_t dhcp_rebind(struct netif *netif);
|
static err_t dhcp_rebind(struct netif *netif);
|
||||||
static err_t dhcp_release(struct netif *netif);
|
static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
|
||||||
static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state);
|
|
||||||
|
|
||||||
/** receive, unfold, parse and free incoming messages */
|
/** receive, unfold, parse and free incoming messages */
|
||||||
static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
|
static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
|
||||||
@@ -139,10 +144,10 @@ static void dhcp_option_trailer(struct dhcp *dhcp);
|
|||||||
static void dhcp_handle_nak(struct netif *netif) {
|
static void dhcp_handle_nak(struct netif *netif) {
|
||||||
struct dhcp *dhcp = netif->dhcp;
|
struct dhcp *dhcp = netif->dhcp;
|
||||||
u16_t msecs = 10 * 1000;
|
u16_t msecs = 10 * 1000;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%u\n", netif,
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
|
||||||
netif->name[0], netif->name[1], (unsigned int)netif->num));
|
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_handle_nak(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_handle_nak(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
dhcp_set_state(dhcp, DHCP_BACKING_OFF);
|
dhcp_set_state(dhcp, DHCP_BACKING_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,8 +163,8 @@ static void dhcp_check(struct netif *netif)
|
|||||||
struct dhcp *dhcp = netif->dhcp;
|
struct dhcp *dhcp = netif->dhcp;
|
||||||
err_t result;
|
err_t result;
|
||||||
u16_t msecs;
|
u16_t msecs;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (unsigned int)netif->name[0],
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
|
||||||
(unsigned int)netif->name[1]));
|
(s16_t)netif->name[1]));
|
||||||
/* create an ARP query for the offered IP address, expecting that no host
|
/* create an ARP query for the offered IP address, expecting that no host
|
||||||
responds, as the IP address should not be in use. */
|
responds, as the IP address should not be in use. */
|
||||||
result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
|
result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
|
||||||
@@ -169,7 +174,7 @@ static void dhcp_check(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = 500;
|
msecs = 500;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_check(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
dhcp_set_state(dhcp, DHCP_CHECKING);
|
dhcp_set_state(dhcp, DHCP_CHECKING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,15 +188,15 @@ static void dhcp_handle_offer(struct netif *netif)
|
|||||||
struct dhcp *dhcp = netif->dhcp;
|
struct dhcp *dhcp = netif->dhcp;
|
||||||
/* obtain the server address */
|
/* obtain the server address */
|
||||||
u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
|
u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%u\n", netif,
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
|
||||||
netif->name[0], netif->name[1], netif->num));
|
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||||
if (option_ptr != NULL)
|
if (option_ptr != NULL)
|
||||||
{
|
{
|
||||||
dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
|
dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): server 0x%08lx\n", dhcp->server_ip_addr.addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", dhcp->server_ip_addr.addr));
|
||||||
/* remember offered address */
|
/* remember offered address */
|
||||||
ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
|
ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08lx\n", dhcp->offered_ip_addr.addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
|
||||||
|
|
||||||
dhcp_select(netif);
|
dhcp_select(netif);
|
||||||
}
|
}
|
||||||
@@ -210,7 +215,7 @@ static err_t dhcp_select(struct netif *netif)
|
|||||||
struct dhcp *dhcp = netif->dhcp;
|
struct dhcp *dhcp = netif->dhcp;
|
||||||
err_t result;
|
err_t result;
|
||||||
u32_t msecs;
|
u32_t msecs;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||||
|
|
||||||
/* create and initialize the DHCP message header */
|
/* create and initialize the DHCP message header */
|
||||||
result = dhcp_create_request(netif);
|
result = dhcp_create_request(netif);
|
||||||
@@ -229,10 +234,11 @@ static err_t dhcp_select(struct netif *netif)
|
|||||||
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
|
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
|
||||||
dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
|
dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
|
||||||
|
|
||||||
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
|
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
|
||||||
dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
|
dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
|
||||||
dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
|
dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
|
||||||
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
|
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
|
||||||
|
dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
|
||||||
|
|
||||||
dhcp_option_trailer(dhcp);
|
dhcp_option_trailer(dhcp);
|
||||||
/* shrink the pbuf to the actual content length */
|
/* shrink the pbuf to the actual content length */
|
||||||
@@ -255,7 +261,7 @@ static err_t dhcp_select(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000;
|
msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_select(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_select(): set request timeout %"U32_F" msecs\n", msecs));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,18 +297,20 @@ void dhcp_coarse_tmr()
|
|||||||
/**
|
/**
|
||||||
* DHCP transaction timeout handling
|
* DHCP transaction timeout handling
|
||||||
*
|
*
|
||||||
* A DHCP server is expected to respond within a
|
* A DHCP server is expected to respond within a short period of time.
|
||||||
* short period of time.
|
* This timer checks whether an outstanding DHCP request is timed out.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void dhcp_fine_tmr()
|
void dhcp_fine_tmr()
|
||||||
{
|
{
|
||||||
struct netif *netif = netif_list;
|
struct netif *netif = netif_list;
|
||||||
/* loop through clients */
|
/* loop through netif's */
|
||||||
while (netif != NULL) {
|
while (netif != NULL) {
|
||||||
/* only act on DHCP configured interfaces */
|
/* only act on DHCP configured interfaces */
|
||||||
if (netif->dhcp != NULL) {
|
if (netif->dhcp != NULL) {
|
||||||
/* timer is active (non zero), and triggers (zeroes) now */
|
/* timer is active (non zero), and is about to trigger now */
|
||||||
if (netif->dhcp->request_timeout-- == 1) {
|
if (netif->dhcp->request_timeout-- == 1) {
|
||||||
|
/* { netif->dhcp->request_timeout == 0 } */
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
|
||||||
/* this clients' request timeout triggered */
|
/* this clients' request timeout triggered */
|
||||||
dhcp_timeout(netif);
|
dhcp_timeout(netif);
|
||||||
@@ -381,8 +389,8 @@ static void dhcp_t1_timeout(struct netif *netif)
|
|||||||
struct dhcp *dhcp = netif->dhcp;
|
struct dhcp *dhcp = netif->dhcp;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_t1_timeout()\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_t1_timeout()\n"));
|
||||||
if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
|
if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
|
||||||
/* just retry to renew */
|
/* just retry to renew - note that the rebind timer (t2) will
|
||||||
/* note that the rebind timer will eventually time-out if renew does not work */
|
* eventually time-out if renew tries fail. */
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
|
||||||
dhcp_renew(netif);
|
dhcp_renew(netif);
|
||||||
}
|
}
|
||||||
@@ -404,7 +412,6 @@ static void dhcp_t2_timeout(struct netif *netif)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract options from the server ACK message.
|
|
||||||
*
|
*
|
||||||
* @param netif the netif under DHCP control
|
* @param netif the netif under DHCP control
|
||||||
*/
|
*/
|
||||||
@@ -478,6 +485,19 @@ static void dhcp_handle_ack(struct netif *netif)
|
|||||||
if (option_ptr != NULL) {
|
if (option_ptr != NULL) {
|
||||||
dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
|
dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* DNS servers */
|
||||||
|
option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_DNS_SERVER);
|
||||||
|
if (option_ptr != NULL) {
|
||||||
|
u8_t n;
|
||||||
|
dhcp->dns_count = dhcp_get_option_byte(&option_ptr[1]);
|
||||||
|
/* limit to at most DHCP_MAX_DNS DNS servers */
|
||||||
|
if (dhcp->dns_count > DHCP_MAX_DNS) dhcp->dns_count = DHCP_MAX_DNS;
|
||||||
|
for (n = 0; n < dhcp->dns_count; n++)
|
||||||
|
{
|
||||||
|
dhcp->offered_dns_addr[n].addr = htonl(dhcp_get_option_long(&option_ptr[2+(n<<2)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -499,40 +519,44 @@ err_t dhcp_start(struct netif *netif)
|
|||||||
err_t result = ERR_OK;
|
err_t result = ERR_OK;
|
||||||
|
|
||||||
LWIP_ASSERT("netif != NULL", netif != NULL);
|
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||||
|
netif->flags &= ~NETIF_FLAG_DHCP;
|
||||||
|
|
||||||
|
/* no DHCP client attached yet? */
|
||||||
if (dhcp == NULL) {
|
if (dhcp == NULL) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
|
||||||
dhcp = mem_malloc(sizeof(struct dhcp));
|
dhcp = mem_malloc(sizeof(struct dhcp));
|
||||||
if (dhcp == NULL) {
|
if (dhcp == NULL) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
|
||||||
netif->flags &= ~NETIF_FLAG_DHCP;
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
/* clear data structure */
|
|
||||||
memset(dhcp, 0, sizeof(struct dhcp));
|
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp"));
|
|
||||||
dhcp->pcb = udp_new();
|
|
||||||
if (dhcp->pcb == NULL) {
|
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
|
|
||||||
mem_free((void *)dhcp);
|
|
||||||
dhcp = NULL;
|
|
||||||
netif->flags &= ~NETIF_FLAG_DHCP;
|
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
/* store this dhcp client in the netif */
|
/* store this dhcp client in the netif */
|
||||||
netif->dhcp = dhcp;
|
netif->dhcp = dhcp;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): created new udp pcb\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp"));
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
|
/* already has DHCP client attached */
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clear data structure */
|
||||||
|
memset(dhcp, 0, sizeof(struct dhcp));
|
||||||
|
/* allocate UDP PCB */
|
||||||
|
dhcp->pcb = udp_new();
|
||||||
|
if (dhcp->pcb == NULL) {
|
||||||
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
|
||||||
|
mem_free((void *)dhcp);
|
||||||
|
netif->dhcp = dhcp = NULL;
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
|
||||||
/* (re)start the DHCP negotiation */
|
/* (re)start the DHCP negotiation */
|
||||||
result = dhcp_discover(netif);
|
result = dhcp_discover(netif);
|
||||||
if (result != ERR_OK) {
|
if (result != ERR_OK) {
|
||||||
/* free resources allocated above */
|
/* free resources allocated above */
|
||||||
dhcp_stop(netif);
|
dhcp_stop(netif);
|
||||||
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
|
netif->flags |= NETIF_FLAG_DHCP;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,10 +633,11 @@ void dhcp_inform(struct netif *netif)
|
|||||||
*/
|
*/
|
||||||
void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
|
void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
|
||||||
{
|
{
|
||||||
|
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
|
||||||
/* is this DHCP client doing an ARP check? */
|
/* is a DHCP client doing an ARP check? */
|
||||||
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
|
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx\n", addr->addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", addr->addr));
|
||||||
/* did a host respond with the address we
|
/* did a host respond with the address we
|
||||||
were offered by the DHCP server? */
|
were offered by the DHCP server? */
|
||||||
if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
|
if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
|
||||||
@@ -655,8 +680,10 @@ static err_t dhcp_decline(struct netif *netif)
|
|||||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||||
|
|
||||||
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||||
udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
|
/* @todo: should we really connect here? we are performing sendto() */
|
||||||
udp_send(dhcp->pcb, dhcp->p_out);
|
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||||
|
/* per section 4.4.4, broadcast DECLINE messages */
|
||||||
|
udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
|
||||||
dhcp_delete_request(netif);
|
dhcp_delete_request(netif);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
|
||||||
} else {
|
} else {
|
||||||
@@ -665,7 +692,7 @@ static err_t dhcp_decline(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = 10*1000;
|
msecs = 10*1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_decline(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -693,10 +720,11 @@ static err_t dhcp_discover(struct netif *netif)
|
|||||||
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
|
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
|
||||||
dhcp_option_short(dhcp, 576);
|
dhcp_option_short(dhcp, 576);
|
||||||
|
|
||||||
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
|
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
|
||||||
dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
|
dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
|
||||||
dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
|
dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
|
||||||
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
|
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
|
||||||
|
dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
|
||||||
|
|
||||||
dhcp_option_trailer(dhcp);
|
dhcp_option_trailer(dhcp);
|
||||||
|
|
||||||
@@ -706,15 +734,9 @@ static err_t dhcp_discover(struct netif *netif)
|
|||||||
/* set receive callback function with netif as user data */
|
/* set receive callback function with netif as user data */
|
||||||
udp_recv(dhcp->pcb, dhcp_recv, netif);
|
udp_recv(dhcp->pcb, dhcp_recv, netif);
|
||||||
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||||
udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
|
|
||||||
|
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: send()ing\n"));
|
|
||||||
|
|
||||||
udp_send(dhcp->pcb, dhcp->p_out);
|
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: bind()ing\n"));
|
|
||||||
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: connect()ing\n"));
|
|
||||||
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||||
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
|
||||||
|
udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
|
||||||
dhcp_delete_request(netif);
|
dhcp_delete_request(netif);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover: SELECTING\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover: SELECTING\n"));
|
||||||
@@ -725,7 +747,7 @@ static err_t dhcp_discover(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
|
msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,22 +763,22 @@ static void dhcp_bind(struct netif *netif)
|
|||||||
struct ip_addr sn_mask, gw_addr;
|
struct ip_addr sn_mask, gw_addr;
|
||||||
LWIP_ASSERT("dhcp_bind: netif != NULL", netif != NULL);
|
LWIP_ASSERT("dhcp_bind: netif != NULL", netif != NULL);
|
||||||
LWIP_ASSERT("dhcp_bind: dhcp != NULL", dhcp != NULL);
|
LWIP_ASSERT("dhcp_bind: dhcp != NULL", dhcp != NULL);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||||
|
|
||||||
/* temporary DHCP lease? */
|
/* temporary DHCP lease? */
|
||||||
if (dhcp->offered_t1_renew != 0xffffffffUL) {
|
if (dhcp->offered_t1_renew != 0xffffffffUL) {
|
||||||
/* set renewal period timer */
|
/* set renewal period timer */
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t1 renewal timer %lu secs\n", dhcp->offered_t1_renew));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
|
||||||
dhcp->t1_timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
|
dhcp->t1_timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
|
||||||
if (dhcp->t1_timeout == 0) dhcp->t1_timeout = 1;
|
if (dhcp->t1_timeout == 0) dhcp->t1_timeout = 1;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t1_renew*1000));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000));
|
||||||
}
|
}
|
||||||
/* set renewal period timer */
|
/* set renewal period timer */
|
||||||
if (dhcp->offered_t2_rebind != 0xffffffffUL) {
|
if (dhcp->offered_t2_rebind != 0xffffffffUL) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t2 rebind timer %lu secs\n", dhcp->offered_t2_rebind));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
|
||||||
dhcp->t2_timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
|
dhcp->t2_timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
|
||||||
if (dhcp->t2_timeout == 0) dhcp->t2_timeout = 1;
|
if (dhcp->t2_timeout == 0) dhcp->t2_timeout = 1;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t2_rebind*1000));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
|
||||||
}
|
}
|
||||||
/* copy offered network mask */
|
/* copy offered network mask */
|
||||||
ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
|
ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
|
||||||
@@ -780,12 +802,14 @@ static void dhcp_bind(struct netif *netif)
|
|||||||
gw_addr.addr |= htonl(0x00000001);
|
gw_addr.addr |= htonl(0x00000001);
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): IP: 0x%08lx\n", dhcp->offered_ip_addr.addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
|
||||||
netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
|
netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): SN: 0x%08lx\n", sn_mask.addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", sn_mask.addr));
|
||||||
netif_set_netmask(netif, &sn_mask);
|
netif_set_netmask(netif, &sn_mask);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08lx\n", gw_addr.addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", gw_addr.addr));
|
||||||
netif_set_gw(netif, &gw_addr);
|
netif_set_gw(netif, &gw_addr);
|
||||||
|
/* bring the interface up */
|
||||||
|
netif_set_up(netif);
|
||||||
/* netif is now bound to DHCP leased address */
|
/* netif is now bound to DHCP leased address */
|
||||||
dhcp_set_state(dhcp, DHCP_BOUND);
|
dhcp_set_state(dhcp, DHCP_BOUND);
|
||||||
}
|
}
|
||||||
@@ -841,7 +865,7 @@ err_t dhcp_renew(struct netif *netif)
|
|||||||
/* back-off on retries, but to a maximum of 20 seconds */
|
/* back-off on retries, but to a maximum of 20 seconds */
|
||||||
msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
|
msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -881,10 +905,11 @@ static err_t dhcp_rebind(struct netif *netif)
|
|||||||
|
|
||||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||||
|
|
||||||
|
/* set remote IP association to any DHCP server */
|
||||||
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||||
udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
|
|
||||||
udp_send(dhcp->pcb, dhcp->p_out);
|
|
||||||
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||||
|
/* broadcast to server */
|
||||||
|
udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
|
||||||
dhcp_delete_request(netif);
|
dhcp_delete_request(netif);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind: REBINDING\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind: REBINDING\n"));
|
||||||
} else {
|
} else {
|
||||||
@@ -893,7 +918,7 @@ static err_t dhcp_rebind(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,7 +927,7 @@ static err_t dhcp_rebind(struct netif *netif)
|
|||||||
*
|
*
|
||||||
* @param netif network interface which must release its lease
|
* @param netif network interface which must release its lease
|
||||||
*/
|
*/
|
||||||
static err_t dhcp_release(struct netif *netif)
|
err_t dhcp_release(struct netif *netif)
|
||||||
{
|
{
|
||||||
struct dhcp *dhcp = netif->dhcp;
|
struct dhcp *dhcp = netif->dhcp;
|
||||||
err_t result;
|
err_t result;
|
||||||
@@ -911,8 +936,13 @@ static err_t dhcp_release(struct netif *netif)
|
|||||||
|
|
||||||
/* idle DHCP client */
|
/* idle DHCP client */
|
||||||
dhcp_set_state(dhcp, DHCP_OFF);
|
dhcp_set_state(dhcp, DHCP_OFF);
|
||||||
|
/* clean old DHCP offer */
|
||||||
|
dhcp->server_ip_addr.addr = 0;
|
||||||
|
dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0;
|
||||||
|
dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0;
|
||||||
|
dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
|
||||||
|
dhcp->dns_count = 0;
|
||||||
|
|
||||||
/* create and initialize the DHCP message header */
|
/* create and initialize the DHCP message header */
|
||||||
result = dhcp_create_request(netif);
|
result = dhcp_create_request(netif);
|
||||||
if (result == ERR_OK) {
|
if (result == ERR_OK) {
|
||||||
@@ -934,11 +964,14 @@ static err_t dhcp_release(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
|
/* bring the interface down */
|
||||||
|
netif_set_down(netif);
|
||||||
/* remove IP address from interface */
|
/* remove IP address from interface */
|
||||||
netif_set_ipaddr(netif, IP_ADDR_ANY);
|
netif_set_ipaddr(netif, IP_ADDR_ANY);
|
||||||
netif_set_gw(netif, IP_ADDR_ANY);
|
netif_set_gw(netif, IP_ADDR_ANY);
|
||||||
netif_set_netmask(netif, IP_ADDR_ANY);
|
netif_set_netmask(netif, IP_ADDR_ANY);
|
||||||
|
|
||||||
/* TODO: netif_down(netif); */
|
/* TODO: netif_down(netif); */
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -980,7 +1013,7 @@ void dhcp_stop(struct netif *netif)
|
|||||||
*
|
*
|
||||||
* TODO: we might also want to reset the timeout here?
|
* TODO: we might also want to reset the timeout here?
|
||||||
*/
|
*/
|
||||||
static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state)
|
static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
|
||||||
{
|
{
|
||||||
if (new_state != dhcp->state)
|
if (new_state != dhcp->state)
|
||||||
{
|
{
|
||||||
@@ -1076,7 +1109,7 @@ static err_t dhcp_unfold_reply(struct dhcp *dhcp)
|
|||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes into dhcp->msg_in[]\n", i));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes into dhcp->msg_in[]\n", i));
|
||||||
if (dhcp->options_in != NULL) {
|
if (dhcp->options_in != NULL) {
|
||||||
ptr = (u8_t *)dhcp->options_in;
|
ptr = (u8_t *)dhcp->options_in;
|
||||||
/* proceed through options */
|
/* proceed through options */
|
||||||
@@ -1089,7 +1122,7 @@ static err_t dhcp_unfold_reply(struct dhcp *dhcp)
|
|||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes to dhcp->options_in[]\n", i));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes to dhcp->options_in[]\n", i));
|
||||||
}
|
}
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
@@ -1125,17 +1158,17 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
|
|||||||
u8_t *options_ptr;
|
u8_t *options_ptr;
|
||||||
u8_t msg_type;
|
u8_t msg_type;
|
||||||
u8_t i;
|
u8_t i;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %u.%u.%u.%u port %u\n", p,
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
|
||||||
(unsigned int)(ntohl(addr->addr) >> 24 & 0xff), (unsigned int)(ntohl(addr->addr) >> 16 & 0xff),
|
(u16_t)(ntohl(addr->addr) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff),
|
||||||
(unsigned int)(ntohl(addr->addr) >> 8 & 0xff), (unsigned int)(ntohl(addr->addr) & 0xff), port));
|
(u16_t)(ntohl(addr->addr) >> 8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port));
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %u\n", p->len));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %u\n", p->tot_len));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
|
||||||
/* prevent warnings about unused arguments */
|
/* prevent warnings about unused arguments */
|
||||||
(void)pcb; (void)addr; (void)port;
|
(void)pcb; (void)addr; (void)port;
|
||||||
dhcp->p = p;
|
dhcp->p = p;
|
||||||
/* TODO: check packet length before reading them */
|
/* TODO: check packet length before reading them */
|
||||||
if (reply_msg->op != DHCP_BOOTREPLY) {
|
if (reply_msg->op != DHCP_BOOTREPLY) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("not a DHCP reply message, but type %u\n", reply_msg->op));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
dhcp->p = NULL;
|
dhcp->p = NULL;
|
||||||
return;
|
return;
|
||||||
@@ -1143,8 +1176,8 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
|
|||||||
/* iterate through hardware address and match against DHCP message */
|
/* iterate through hardware address and match against DHCP message */
|
||||||
for (i = 0; i < netif->hwaddr_len; i++) {
|
for (i = 0; i < netif->hwaddr_len; i++) {
|
||||||
if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
|
if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%u]==%02x != reply_msg->chaddr[%u]==%02x\n",
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
|
||||||
i, netif->hwaddr[i], i, reply_msg->chaddr[i]));
|
(u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
dhcp->p = NULL;
|
dhcp->p = NULL;
|
||||||
return;
|
return;
|
||||||
@@ -1243,10 +1276,10 @@ static err_t dhcp_create_request(struct netif *netif)
|
|||||||
dhcp->msg_out->xid = htonl(dhcp->xid);
|
dhcp->msg_out->xid = htonl(dhcp->xid);
|
||||||
dhcp->msg_out->secs = 0;
|
dhcp->msg_out->secs = 0;
|
||||||
dhcp->msg_out->flags = 0;
|
dhcp->msg_out->flags = 0;
|
||||||
dhcp->msg_out->ciaddr = netif->ip_addr.addr;
|
dhcp->msg_out->ciaddr.addr = netif->ip_addr.addr;
|
||||||
dhcp->msg_out->yiaddr = 0;
|
dhcp->msg_out->yiaddr.addr = 0;
|
||||||
dhcp->msg_out->siaddr = 0;
|
dhcp->msg_out->siaddr.addr = 0;
|
||||||
dhcp->msg_out->giaddr = 0;
|
dhcp->msg_out->giaddr.addr = 0;
|
||||||
for (i = 0; i < DHCP_CHADDR_LEN; i++) {
|
for (i = 0; i < DHCP_CHADDR_LEN; i++) {
|
||||||
/* copy netif hardware address, pad with zeroes */
|
/* copy netif hardware address, pad with zeroes */
|
||||||
dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
|
dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
|
||||||
@@ -1284,7 +1317,7 @@ static void dhcp_option_trailer(struct dhcp *dhcp)
|
|||||||
dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
|
dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
|
||||||
/* packet is too small, or not 4 byte aligned? */
|
/* packet is too small, or not 4 byte aligned? */
|
||||||
while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
|
while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
|
||||||
/* LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_option_trailer: dhcp->options_out_len=%u, DHCP_OPTIONS_LEN=%u", dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
|
/* LWIP_DEBUGF(DHCP_DEBUG,("dhcp_option_trailer:dhcp->options_out_len=%"U16_F", DHCP_OPTIONS_LEN=%"U16_F, dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
|
||||||
LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
|
LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
|
||||||
/* add a fill/padding byte */
|
/* add a fill/padding byte */
|
||||||
dhcp->msg_out->options[dhcp->options_out_len++] = 0;
|
dhcp->msg_out->options[dhcp->options_out_len++] = 0;
|
||||||
@@ -1311,7 +1344,7 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
|
|||||||
u16_t offset = 0;
|
u16_t offset = 0;
|
||||||
/* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
|
/* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
|
||||||
while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
|
while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
|
||||||
/* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%u, q->len=%u", msg_offset, q->len)); */
|
/* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
|
||||||
/* are the sname and/or file field overloaded with options? */
|
/* are the sname and/or file field overloaded with options? */
|
||||||
if (options[offset] == DHCP_OPTION_OVERLOAD) {
|
if (options[offset] == DHCP_OPTION_OVERLOAD) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("overloaded message detected\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("overloaded message detected\n"));
|
||||||
@@ -1321,11 +1354,11 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
|
|||||||
}
|
}
|
||||||
/* requested option found */
|
/* requested option found */
|
||||||
else if (options[offset] == option_type) {
|
else if (options[offset] == option_type) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset %u in options\n", offset));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset %"U16_F" in options\n", offset));
|
||||||
return &options[offset];
|
return &options[offset];
|
||||||
/* skip option */
|
/* skip option */
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %u in options\n", options[offset]));
|
LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", options[offset]));
|
||||||
/* skip option type */
|
/* skip option type */
|
||||||
offset++;
|
offset++;
|
||||||
/* skip option length, and then length bytes */
|
/* skip option length, and then length bytes */
|
||||||
@@ -1354,11 +1387,11 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
|
|||||||
/* at least 1 byte to read and no end marker */
|
/* at least 1 byte to read and no end marker */
|
||||||
while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
|
while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
|
||||||
if (options[offset] == option_type) {
|
if (options[offset] == option_type) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset=%u\n", offset));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset=%"U16_F"\n", offset));
|
||||||
return &options[offset];
|
return &options[offset];
|
||||||
/* skip option */
|
/* skip option */
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("skipping option %u\n", options[offset]));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("skipping option %"U16_F"\n", options[offset]));
|
||||||
/* skip option type */
|
/* skip option type */
|
||||||
offset++;
|
offset++;
|
||||||
offset += 1 + options[offset];
|
offset += 1 + options[offset];
|
||||||
@@ -1379,7 +1412,7 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
|
|||||||
*/
|
*/
|
||||||
static u8_t dhcp_get_option_byte(u8_t *ptr)
|
static u8_t dhcp_get_option_byte(u8_t *ptr)
|
||||||
{
|
{
|
||||||
LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%u\n", *ptr));
|
LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%"U16_F"\n", (u16_t)(*ptr)));
|
||||||
return *ptr;
|
return *ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1396,7 +1429,7 @@ static u16_t dhcp_get_option_short(u8_t *ptr)
|
|||||||
u16_t value;
|
u16_t value;
|
||||||
value = *ptr++ << 8;
|
value = *ptr++ << 8;
|
||||||
value |= *ptr;
|
value |= *ptr;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%u\n", value));
|
LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%"U16_F"\n", value));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1415,6 +1448,8 @@ static u32_t dhcp_get_option_long(u8_t *ptr)
|
|||||||
value |= (u32_t)(*ptr++) << 16;
|
value |= (u32_t)(*ptr++) << 16;
|
||||||
value |= (u32_t)(*ptr++) << 8;
|
value |= (u32_t)(*ptr++) << 8;
|
||||||
value |= (u32_t)(*ptr++);
|
value |= (u32_t)(*ptr++);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%lu\n", value));
|
LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%"U32_F"\n", value));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_DHCP */
|
||||||
|
|||||||
237
src/core/inet.c
237
src/core/inet.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -46,36 +46,195 @@
|
|||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
|
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
|
/* This is a reference implementation of the checksum algorithm, with the
|
||||||
|
* aim of being simple, correct and fully portable. Checksumming is the
|
||||||
|
* first thing you would want to optimize for your platform. You will
|
||||||
|
* need to port it to your architecture and in your sys_arch.h:
|
||||||
|
*
|
||||||
|
* #define LWIP_CHKSUM <your_checksum_routine>
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_CHKSUM
|
||||||
|
#define LWIP_CHKSUM lwip_standard_chksum
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lwip checksum
|
||||||
|
*
|
||||||
|
* @param dataptr points to start of data to be summed at any boundary
|
||||||
|
* @param len length of data to be summed
|
||||||
|
* @return host order (!) lwip checksum (non-inverted Internet sum)
|
||||||
|
*
|
||||||
|
* @note accumulator size limits summable lenght to 64k
|
||||||
|
* @note host endianess is irrelevant (p3 RFC1071)
|
||||||
|
*/
|
||||||
static u16_t
|
static u16_t
|
||||||
lwip_chksum(void *dataptr, int len)
|
lwip_standard_chksum(void *dataptr, u16_t len)
|
||||||
{
|
{
|
||||||
u32_t acc;
|
u32_t acc;
|
||||||
|
u16_t src;
|
||||||
|
u8_t *octetptr;
|
||||||
|
|
||||||
LWIP_DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %d)\n", (void *)dataptr, len));
|
acc = 0;
|
||||||
for(acc = 0; len > 1; len -= 2) {
|
/* dataptr may be at odd or even addresses */
|
||||||
/* acc = acc + *((u16_t *)dataptr)++;*/
|
octetptr = (u8_t*)dataptr;
|
||||||
acc += *(u16_t *)dataptr;
|
while (len > 1)
|
||||||
dataptr = (void *)((u16_t *)dataptr + 1);
|
{
|
||||||
|
/* declare first octet as most significant
|
||||||
|
thus assume network order, ignoring host order */
|
||||||
|
src = (*octetptr) << 8;
|
||||||
|
octetptr++;
|
||||||
|
/* declare second octet as least significant */
|
||||||
|
src |= (*octetptr);
|
||||||
|
octetptr++;
|
||||||
|
acc += src;
|
||||||
|
len -= 2;
|
||||||
}
|
}
|
||||||
|
if (len > 0)
|
||||||
/* add up any odd byte */
|
{
|
||||||
if (len == 1) {
|
/* accumulate remaining octet */
|
||||||
acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8);
|
src = (*octetptr) << 8;
|
||||||
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", (unsigned int)(*(u8_t *)dataptr)));
|
acc += src;
|
||||||
} else {
|
|
||||||
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: no odd byte\n"));
|
|
||||||
}
|
}
|
||||||
acc = (acc >> 16) + (acc & 0xffffUL);
|
/* add deferred carry bits */
|
||||||
|
acc = (acc >> 16) + (acc & 0x0000ffffUL);
|
||||||
if ((acc & 0xffff0000) != 0) {
|
if ((acc & 0xffff0000) != 0) {
|
||||||
acc = (acc >> 16) + (acc & 0xffffUL);
|
acc = (acc >> 16) + (acc & 0x0000ffffUL);
|
||||||
|
}
|
||||||
|
/* This maybe a little confusing: reorder sum using htons()
|
||||||
|
instead of ntohs() since it has a little less call overhead.
|
||||||
|
The caller must invert bits for Internet sum ! */
|
||||||
|
return htons((u16_t)acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Curt McDowell
|
||||||
|
* Broadcom Corp.
|
||||||
|
* csm@broadcom.com
|
||||||
|
*
|
||||||
|
* IP checksum two bytes at a time with support for
|
||||||
|
* unaligned buffer.
|
||||||
|
* Works for len up to and including 0x20000.
|
||||||
|
* by Curt McDowell, Broadcom Corp. 12/08/2005
|
||||||
|
*/
|
||||||
|
|
||||||
|
static u16_t
|
||||||
|
lwip_standard_chksum2(void *dataptr, int len)
|
||||||
|
{
|
||||||
|
u8_t *pb = dataptr;
|
||||||
|
u16_t *ps, t = 0;
|
||||||
|
u32_t sum = 0;
|
||||||
|
int odd = ((u32_t)pb & 1);
|
||||||
|
|
||||||
|
/* Get aligned to u16_t */
|
||||||
|
if (odd && len > 0) {
|
||||||
|
((u8_t *)&t)[1] = *pb++;
|
||||||
|
len--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (u16_t)acc;
|
/* Add the bulk of the data */
|
||||||
|
ps = (u16_t *)pb;
|
||||||
|
while (len > 1) {
|
||||||
|
sum += *ps++;
|
||||||
|
len -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consume left-over byte, if any */
|
||||||
|
if (len > 0)
|
||||||
|
((u8_t *)&t)[0] = *(u8_t *)ps;;
|
||||||
|
|
||||||
|
/* Add end bytes */
|
||||||
|
sum += t;
|
||||||
|
|
||||||
|
/* Fold 32-bit sum to 16 bits */
|
||||||
|
while (sum >> 16)
|
||||||
|
sum = (sum & 0xffff) + (sum >> 16);
|
||||||
|
|
||||||
|
/* Swap if alignment was odd */
|
||||||
|
if (odd)
|
||||||
|
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
|
||||||
|
|
||||||
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optimized checksum routine. Basically, it uses loop-unrolling on
|
||||||
|
* the checksum loop, treating the head and tail bytes specially, whereas
|
||||||
|
* the inner loop acts on 8 bytes at a time.
|
||||||
|
*
|
||||||
|
* @arg start of buffer to be checksummed. May be an odd byte address.
|
||||||
|
* @len number of bytes in the buffer to be checksummed.
|
||||||
|
*
|
||||||
|
* @todo First argument type conflicts with generic checksum routine.
|
||||||
|
*
|
||||||
|
* by Curt McDowell, Broadcom Corp. December 8th, 2005
|
||||||
|
*/
|
||||||
|
|
||||||
|
static u16_t
|
||||||
|
lwip_standard_chksum4(u8_t *pb, int len)
|
||||||
|
{
|
||||||
|
u16_t *ps, t = 0;
|
||||||
|
u32_t *pl;
|
||||||
|
u32_t sum = 0, tmp;
|
||||||
|
/* starts at odd byte address? */
|
||||||
|
int odd = ((u32_t)pb & 1);
|
||||||
|
|
||||||
|
if (odd && len > 0) {
|
||||||
|
((u8_t *)&t)[1] = *pb++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
ps = (u16_t *)pb;
|
||||||
|
|
||||||
|
if (((u32_t)ps & 3) && len > 1) {
|
||||||
|
sum += *ps++;
|
||||||
|
len -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl = (u32_t *)ps;
|
||||||
|
|
||||||
|
while (len > 7) {
|
||||||
|
tmp = sum + *pl++; /* ping */
|
||||||
|
if (tmp < sum)
|
||||||
|
tmp++; /* add back carry */
|
||||||
|
|
||||||
|
sum = tmp + *pl++; /* pong */
|
||||||
|
if (sum < tmp)
|
||||||
|
sum++; /* add back carry */
|
||||||
|
|
||||||
|
len -= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make room in upper bits */
|
||||||
|
sum = (sum >> 16) + (sum & 0xffff);
|
||||||
|
|
||||||
|
ps = (u16_t *)pl;
|
||||||
|
|
||||||
|
/* 16-bit aligned word remaining? */
|
||||||
|
while (len > 1) {
|
||||||
|
sum += *ps++;
|
||||||
|
len -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dangling tail byte remaining? */
|
||||||
|
if (len > 0) /* include odd byte */
|
||||||
|
((u8_t *)&t)[0] = *(u8_t *)ps;
|
||||||
|
|
||||||
|
sum += t; /* add end bytes */
|
||||||
|
|
||||||
|
while (sum >> 16) /* combine halves */
|
||||||
|
sum = (sum >> 16) + (sum & 0xffff);
|
||||||
|
|
||||||
|
if (odd)
|
||||||
|
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* inet_chksum_pseudo:
|
/* inet_chksum_pseudo:
|
||||||
*
|
*
|
||||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||||
@@ -96,8 +255,8 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||||||
for(q = p; q != NULL; q = q->next) {
|
for(q = p; q != NULL; q = q->next) {
|
||||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||||
(void *)q, (void *)q->next));
|
(void *)q, (void *)q->next));
|
||||||
acc += lwip_chksum(q->payload, q->len);
|
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%lx \n", acc));*/
|
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||||
while (acc >> 16) {
|
while (acc >> 16) {
|
||||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||||
}
|
}
|
||||||
@@ -105,7 +264,7 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||||||
swapped = 1 - swapped;
|
swapped = 1 - swapped;
|
||||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||||
}
|
}
|
||||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%lx \n", acc));*/
|
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (swapped) {
|
if (swapped) {
|
||||||
@@ -121,8 +280,8 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||||||
while (acc >> 16) {
|
while (acc >> 16) {
|
||||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
|
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||||
return ~(acc & 0xffffUL);
|
return (u16_t)~(acc & 0xffffUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* inet_chksum:
|
/* inet_chksum:
|
||||||
@@ -136,11 +295,11 @@ inet_chksum(void *dataptr, u16_t len)
|
|||||||
{
|
{
|
||||||
u32_t acc;
|
u32_t acc;
|
||||||
|
|
||||||
acc = lwip_chksum(dataptr, len);
|
acc = LWIP_CHKSUM(dataptr, len);
|
||||||
while (acc >> 16) {
|
while (acc >> 16) {
|
||||||
acc = (acc & 0xffff) + (acc >> 16);
|
acc = (acc & 0xffff) + (acc >> 16);
|
||||||
}
|
}
|
||||||
return ~(acc & 0xffff);
|
return (u16_t)~(acc & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16_t
|
u16_t
|
||||||
@@ -153,7 +312,7 @@ inet_chksum_pbuf(struct pbuf *p)
|
|||||||
acc = 0;
|
acc = 0;
|
||||||
swapped = 0;
|
swapped = 0;
|
||||||
for(q = p; q != NULL; q = q->next) {
|
for(q = p; q != NULL; q = q->next) {
|
||||||
acc += lwip_chksum(q->payload, q->len);
|
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||||
while (acc >> 16) {
|
while (acc >> 16) {
|
||||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||||
}
|
}
|
||||||
@@ -166,7 +325,7 @@ inet_chksum_pbuf(struct pbuf *p)
|
|||||||
if (swapped) {
|
if (swapped) {
|
||||||
acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
|
acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
|
||||||
}
|
}
|
||||||
return ~(acc & 0xffffUL);
|
return (u16_t)~(acc & 0xffffUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Here for now until needed in other places in lwIP */
|
/* Here for now until needed in other places in lwIP */
|
||||||
@@ -206,10 +365,11 @@ inet_chksum_pbuf(struct pbuf *p)
|
|||||||
*/
|
*/
|
||||||
/* */
|
/* */
|
||||||
/* inet_aton */
|
/* inet_aton */
|
||||||
int inet_aton(const char *cp, struct in_addr *addr)
|
s8_t
|
||||||
|
inet_aton(const char *cp, struct in_addr *addr)
|
||||||
{
|
{
|
||||||
u32_t val;
|
u32_t val;
|
||||||
int base, n;
|
s32_t base, n;
|
||||||
char c;
|
char c;
|
||||||
u32_t parts[4];
|
u32_t parts[4];
|
||||||
u32_t* pp = parts;
|
u32_t* pp = parts;
|
||||||
@@ -232,12 +392,12 @@ inet_chksum_pbuf(struct pbuf *p)
|
|||||||
base = 8;
|
base = 8;
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (isascii(c) && isdigit(c)) {
|
if (isdigit(c)) {
|
||||||
val = (val * base) + (c - '0');
|
val = (val * base) + (s16_t)(c - '0');
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
} else if (base == 16 && isascii(c) && isxdigit(c)) {
|
} else if (base == 16 && isxdigit(c)) {
|
||||||
val = (val << 4) |
|
val = (val << 4) |
|
||||||
(c + 10 - (islower(c) ? 'a' : 'A'));
|
(s16_t)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
@@ -300,18 +460,19 @@ inet_chksum_pbuf(struct pbuf *p)
|
|||||||
/* Convert numeric IP address into decimal dotted ASCII representation.
|
/* Convert numeric IP address into decimal dotted ASCII representation.
|
||||||
* returns ptr to static buffer; not reentrant!
|
* returns ptr to static buffer; not reentrant!
|
||||||
*/
|
*/
|
||||||
u8_t *inet_ntoa(u32_t addr)
|
char *inet_ntoa(struct in_addr addr)
|
||||||
{
|
{
|
||||||
static u8_t str[16];
|
static char str[16];
|
||||||
u8_t inv[3];
|
u32_t s_addr = addr.s_addr;
|
||||||
u8_t *rp;
|
char inv[3];
|
||||||
|
char *rp;
|
||||||
u8_t *ap;
|
u8_t *ap;
|
||||||
u8_t rem;
|
u8_t rem;
|
||||||
u8_t n;
|
u8_t n;
|
||||||
u8_t i;
|
u8_t i;
|
||||||
|
|
||||||
rp = str;
|
rp = str;
|
||||||
ap = (u8_t *)&addr;
|
ap = (u8_t *)&s_addr;
|
||||||
for(n = 0; n < 4; n++) {
|
for(n = 0; n < 4; n++) {
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -33,22 +33,21 @@
|
|||||||
/* Some ICMP messages should be passed to the transport protocols. This
|
/* Some ICMP messages should be passed to the transport protocols. This
|
||||||
is not implemented. */
|
is not implemented. */
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
#include "lwip/icmp.h"
|
#include "lwip/icmp.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
#include "lwip/snmp.h"
|
#include "lwip/snmp.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
icmp_input(struct pbuf *p, struct netif *inp)
|
icmp_input(struct pbuf *p, struct netif *inp)
|
||||||
{
|
{
|
||||||
unsigned char type;
|
u8_t type;
|
||||||
unsigned char code;
|
u8_t code;
|
||||||
struct icmp_echo_hdr *iecho;
|
struct icmp_echo_hdr *iecho;
|
||||||
struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
struct ip_addr tmpaddr;
|
struct ip_addr tmpaddr;
|
||||||
@@ -61,7 +60,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
hlen = IPH_HL(iphdr) * 4;
|
hlen = IPH_HL(iphdr) * 4;
|
||||||
if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
|
if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
ICMP_STATS_INC(icmp.lenerr);
|
ICMP_STATS_INC(icmp.lenerr);
|
||||||
snmp_inc_icmpinerrors();
|
snmp_inc_icmpinerrors();
|
||||||
@@ -72,9 +71,9 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
code = *(((u8_t *)p->payload)+1);
|
code = *(((u8_t *)p->payload)+1);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ICMP_ECHO:
|
case ICMP_ECHO:
|
||||||
if (ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) ||
|
/* broadcast or multicast destination address? */
|
||||||
ip_addr_ismulticast(&iphdr->dest)) {
|
if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("Smurf.\n"));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
|
||||||
ICMP_STATS_INC(icmp.err);
|
ICMP_STATS_INC(icmp.err);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
return;
|
return;
|
||||||
@@ -117,7 +116,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
|
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", (s16_t)type, (s16_t)code));
|
||||||
ICMP_STATS_INC(icmp.proterr);
|
ICMP_STATS_INC(icmp.proterr);
|
||||||
ICMP_STATS_INC(icmp.drop);
|
ICMP_STATS_INC(icmp.drop);
|
||||||
}
|
}
|
||||||
@@ -140,7 +139,7 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
|||||||
ICMPH_TYPE_SET(idur, ICMP_DUR);
|
ICMPH_TYPE_SET(idur, ICMP_DUR);
|
||||||
ICMPH_CODE_SET(idur, t);
|
ICMPH_CODE_SET(idur, t);
|
||||||
|
|
||||||
memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);
|
memcpy((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
|
||||||
|
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
idur->chksum = 0;
|
idur->chksum = 0;
|
||||||
@@ -178,7 +177,7 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
|||||||
ICMPH_CODE_SET(tehdr, t);
|
ICMPH_CODE_SET(tehdr, t);
|
||||||
|
|
||||||
/* copy fields from original packet */
|
/* copy fields from original packet */
|
||||||
memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
|
memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
|
||||||
|
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
tehdr->chksum = 0;
|
tehdr->chksum = 0;
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
|
/* @file
|
||||||
|
*
|
||||||
|
* This is the IP layer implementation for incoming and outgoing IP traffic.
|
||||||
|
*
|
||||||
|
* @see ip_frag.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -30,18 +37,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ip.c
|
|
||||||
*
|
|
||||||
* This is the code for the IP layer.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
@@ -63,69 +60,17 @@
|
|||||||
#endif /* LWIP_DHCP */
|
#endif /* LWIP_DHCP */
|
||||||
|
|
||||||
|
|
||||||
/* ip_init:
|
/**
|
||||||
*
|
|
||||||
* Initializes the IP layer.
|
* Initializes the IP layer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ip_init(void)
|
ip_init(void)
|
||||||
{
|
{
|
||||||
|
/* no initializations as of yet */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ip_lookup:
|
/**
|
||||||
*
|
|
||||||
* An experimental feature that will be changed in future versions. Do
|
|
||||||
* not depend on it yet...
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef LWIP_DEBUG
|
|
||||||
u8_t
|
|
||||||
ip_lookup(void *header, struct netif *inp)
|
|
||||||
{
|
|
||||||
struct ip_hdr *iphdr;
|
|
||||||
|
|
||||||
iphdr = header;
|
|
||||||
|
|
||||||
/* not IP v4? */
|
|
||||||
if (IPH_V(iphdr) != 4) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Immediately accept/decline packets that are fragments or has
|
|
||||||
options. */
|
|
||||||
#if IP_REASSEMBLY == 0
|
|
||||||
/* if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
|
|
||||||
return 0;
|
|
||||||
}*/
|
|
||||||
#endif /* IP_REASSEMBLY == 0 */
|
|
||||||
|
|
||||||
#if IP_OPTIONS == 0
|
|
||||||
if (IPH_HL(iphdr) != 5) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* IP_OPTIONS == 0 */
|
|
||||||
|
|
||||||
switch (IPH_PROTO(iphdr)) {
|
|
||||||
#if LWIP_UDP
|
|
||||||
case IP_PROTO_UDP:
|
|
||||||
case IP_PROTO_UDPLITE:
|
|
||||||
return udp_lookup(iphdr, inp);
|
|
||||||
#endif /* LWIP_UDP */
|
|
||||||
#if LWIP_TCP
|
|
||||||
case IP_PROTO_TCP:
|
|
||||||
return 1;
|
|
||||||
#endif /* LWIP_TCP */
|
|
||||||
case IP_PROTO_ICMP:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* LWIP_DEBUG */
|
|
||||||
|
|
||||||
/* ip_route:
|
|
||||||
*
|
|
||||||
* Finds the appropriate network interface for a given IP address. It
|
* Finds the appropriate network interface for a given IP address. It
|
||||||
* searches the list of network interfaces linearly. A match is found
|
* searches the list of network interfaces linearly. A match is found
|
||||||
* if the masked IP address of the network interface equals the masked
|
* if the masked IP address of the network interface equals the masked
|
||||||
@@ -140,7 +85,7 @@ ip_route(struct ip_addr *dest)
|
|||||||
/* iterate through netifs */
|
/* iterate through netifs */
|
||||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||||
/* network mask matches? */
|
/* network mask matches? */
|
||||||
if (ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
||||||
/* return netif on which to forward IP packet */
|
/* return netif on which to forward IP packet */
|
||||||
return netif;
|
return netif;
|
||||||
}
|
}
|
||||||
@@ -150,14 +95,13 @@ ip_route(struct ip_addr *dest)
|
|||||||
}
|
}
|
||||||
#if IP_FORWARD
|
#if IP_FORWARD
|
||||||
|
|
||||||
/* ip_forward:
|
/**
|
||||||
*
|
|
||||||
* Forwards an IP packet. It finds an appropriate route for the
|
* Forwards an IP packet. It finds an appropriate route for the
|
||||||
* packet, decrements the TTL value of the packet, adjusts the
|
* packet, decrements the TTL value of the packet, adjusts the
|
||||||
* checksum and outputs the packet on the appropriate interface.
|
* checksum and outputs the packet on the appropriate interface.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static struct netif *
|
||||||
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||||
{
|
{
|
||||||
struct netif *netif;
|
struct netif *netif;
|
||||||
@@ -166,17 +110,17 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
|||||||
/* Find network interface where to forward this IP packet to. */
|
/* Find network interface where to forward this IP packet to. */
|
||||||
netif = ip_route((struct ip_addr *)&(iphdr->dest));
|
netif = ip_route((struct ip_addr *)&(iphdr->dest));
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%lx found\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n",
|
||||||
iphdr->dest.addr));
|
iphdr->dest.addr));
|
||||||
snmp_inc_ipnoroutes();
|
snmp_inc_ipnoroutes();
|
||||||
return;
|
return (struct netif *)NULL;
|
||||||
}
|
}
|
||||||
/* Do not forward packets onto the same network interface on which
|
/* Do not forward packets onto the same network interface on which
|
||||||
they arrived. */
|
* they arrived. */
|
||||||
if (netif == inp) {
|
if (netif == inp) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
|
||||||
snmp_inc_ipnoroutes();
|
snmp_inc_ipnoroutes();
|
||||||
return;
|
return (struct netif *)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* decrement TTL */
|
/* decrement TTL */
|
||||||
@@ -188,7 +132,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
|||||||
icmp_time_exceeded(p, ICMP_TE_TTL);
|
icmp_time_exceeded(p, ICMP_TE_TTL);
|
||||||
snmp_inc_icmpouttimeexcds();
|
snmp_inc_icmpouttimeexcds();
|
||||||
}
|
}
|
||||||
return;
|
return (struct netif *)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Incrementally update the IP checksum. */
|
/* Incrementally update the IP checksum. */
|
||||||
@@ -198,7 +142,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
|||||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
|
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
|
||||||
iphdr->dest.addr));
|
iphdr->dest.addr));
|
||||||
|
|
||||||
IP_STATS_INC(ip.fw);
|
IP_STATS_INC(ip.fw);
|
||||||
@@ -208,11 +152,11 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
|||||||
PERF_STOP("ip_forward");
|
PERF_STOP("ip_forward");
|
||||||
/* transmit pbuf on chosen interface */
|
/* transmit pbuf on chosen interface */
|
||||||
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
|
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
|
||||||
|
return netif;
|
||||||
}
|
}
|
||||||
#endif /* IP_FORWARD */
|
#endif /* IP_FORWARD */
|
||||||
|
|
||||||
/* ip_input:
|
/**
|
||||||
*
|
|
||||||
* This function is called by the network interface device driver when
|
* This function is called by the network interface device driver when
|
||||||
* an IP packet is received. The function does the basic checks of the
|
* an IP packet is received. The function does the basic checks of the
|
||||||
* IP header such as packet size being at least larger than the header
|
* IP header such as packet size being at least larger than the header
|
||||||
@@ -220,13 +164,16 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
|||||||
* forwarded (using ip_forward). The IP checksum is always checked.
|
* forwarded (using ip_forward). The IP checksum is always checked.
|
||||||
*
|
*
|
||||||
* Finally, the packet is sent to the upper layer protocol input function.
|
* Finally, the packet is sent to the upper layer protocol input function.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
err_t
|
err_t
|
||||||
ip_input(struct pbuf *p, struct netif *inp) {
|
ip_input(struct pbuf *p, struct netif *inp) {
|
||||||
static struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
static struct netif *netif;
|
struct netif *netif;
|
||||||
static u16_t iphdrlen;
|
u16_t iphdrlen;
|
||||||
|
|
||||||
IP_STATS_INC(ip.recv);
|
IP_STATS_INC(ip.recv);
|
||||||
snmp_inc_ipinreceives();
|
snmp_inc_ipinreceives();
|
||||||
@@ -234,7 +181,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
/* identify the IP header */
|
/* identify the IP header */
|
||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
if (IPH_V(iphdr) != 4) {
|
if (IPH_V(iphdr) != 4) {
|
||||||
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %u\n", IPH_V(iphdr)));
|
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
IP_STATS_INC(ip.err);
|
IP_STATS_INC(ip.err);
|
||||||
@@ -249,7 +196,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
|
|
||||||
/* header length exceeds first pbuf length? */
|
/* header length exceeds first pbuf length? */
|
||||||
if (iphdrlen > p->len) {
|
if (iphdrlen > p->len) {
|
||||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %u) does not fit in first pbuf (len %u), IP packet droppped.\n",
|
LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet droppped.\n",
|
||||||
iphdrlen, p->len));
|
iphdrlen, p->len));
|
||||||
/* free (drop) packet pbufs */
|
/* free (drop) packet pbufs */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@@ -260,9 +207,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* verify checksum */
|
/* verify checksum */
|
||||||
|
#if CHECKSUM_CHECK_IP
|
||||||
if (inet_chksum(iphdr, iphdrlen) != 0) {
|
if (inet_chksum(iphdr, iphdrlen) != 0) {
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
|
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
IP_STATS_INC(ip.chkerr);
|
IP_STATS_INC(ip.chkerr);
|
||||||
@@ -270,45 +218,44 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
snmp_inc_ipindiscards();
|
snmp_inc_ipindiscards();
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Trim pbuf. This should have been done at the netif layer,
|
/* Trim pbuf. This should have been done at the netif layer,
|
||||||
but we'll do it anyway just to be sure that its done. */
|
* but we'll do it anyway just to be sure that its done. */
|
||||||
pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
|
pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
|
||||||
|
|
||||||
/* is this packet for us? */
|
/* match packet against an interface, i.e. is this packet for us? */
|
||||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%lx netif->ip_addr 0x%lx (0x%lx, 0x%lx, 0x%lx)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
|
||||||
iphdr->dest.addr, netif->ip_addr.addr,
|
iphdr->dest.addr, netif->ip_addr.addr,
|
||||||
iphdr->dest.addr & netif->netmask.addr,
|
iphdr->dest.addr & netif->netmask.addr,
|
||||||
netif->ip_addr.addr & netif->netmask.addr,
|
netif->ip_addr.addr & netif->netmask.addr,
|
||||||
iphdr->dest.addr & ~(netif->netmask.addr)));
|
iphdr->dest.addr & ~(netif->netmask.addr)));
|
||||||
|
|
||||||
/* interface configured? */
|
/* interface is up and configured? */
|
||||||
if (!ip_addr_isany(&(netif->ip_addr)))
|
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
|
||||||
{
|
{
|
||||||
/* unicast to this interface address? */
|
/* unicast to this interface address? */
|
||||||
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
|
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
|
||||||
/* or broadcast matching this interface network address? */
|
/* or broadcast on this interface network address? */
|
||||||
(ip_addr_isbroadcast(&(iphdr->dest), &(netif->netmask)) &&
|
ip_addr_isbroadcast(&(iphdr->dest), netif)) {
|
||||||
ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) ||
|
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
||||||
/* or restricted broadcast? */
|
netif->name[0], netif->name[1]));
|
||||||
ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) {
|
/* break out of for loop */
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
break;
|
||||||
netif->name[0], netif->name[1]));
|
|
||||||
/* break out of for loop */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if LWIP_DHCP
|
#if LWIP_DHCP
|
||||||
/* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
|
/* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
|
||||||
using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
|
* using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
|
||||||
According to RFC 1542 section 3.1.1, referred by RFC 2131). */
|
* According to RFC 1542 section 3.1.1, referred by RFC 2131).
|
||||||
|
*/
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
/* remote port is DHCP server? */
|
/* remote port is DHCP server? */
|
||||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
|
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
|
||||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %u\n",
|
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
|
||||||
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
|
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
|
||||||
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
|
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
|
||||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
|
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
|
||||||
@@ -317,13 +264,13 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* LWIP_DHCP */
|
#endif /* LWIP_DHCP */
|
||||||
/* packet not for us? */
|
/* packet not for us? */
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
/* packet not for us, route or discard */
|
/* packet not for us, route or discard */
|
||||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
|
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
|
||||||
#if IP_FORWARD
|
#if IP_FORWARD
|
||||||
/* non-broadcast packet? */
|
/* non-broadcast packet? */
|
||||||
if (!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask))) {
|
if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
|
||||||
/* try to forward IP packet on (other) interfaces */
|
/* try to forward IP packet on (other) interfaces */
|
||||||
ip_forward(p, iphdr, inp);
|
ip_forward(p, iphdr, inp);
|
||||||
}
|
}
|
||||||
@@ -335,30 +282,30 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
/* packet consists of multiple fragments? */
|
||||||
#if IP_REASSEMBLY
|
|
||||||
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
|
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04x tot_len=%u len=%u MF=%u offset=%u), calling ip_reass()\n",
|
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
|
||||||
|
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
|
||||||
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
|
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
|
||||||
|
/* reassemble the packet*/
|
||||||
p = ip_reass(p);
|
p = ip_reass(p);
|
||||||
|
/* packet not fully reassembled yet? */
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
}
|
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
|
||||||
#else /* IP_REASSEMBLY */
|
|
||||||
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
|
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
|
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
|
||||||
ntohs(IPH_OFFSET(iphdr))));
|
ntohs(IPH_OFFSET(iphdr))));
|
||||||
IP_STATS_INC(ip.opterr);
|
IP_STATS_INC(ip.opterr);
|
||||||
IP_STATS_INC(ip.drop);
|
IP_STATS_INC(ip.drop);
|
||||||
snmp_inc_ipunknownprotos();
|
snmp_inc_ipunknownprotos();
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
|
||||||
#endif /* IP_REASSEMBLY */
|
#endif /* IP_REASSEMBLY */
|
||||||
|
}
|
||||||
|
|
||||||
#if IP_OPTIONS == 0
|
#if IP_OPTIONS == 0 /* no support for IP options in the IP header? */
|
||||||
if (iphdrlen > IP_HLEN) {
|
if (iphdrlen > IP_HLEN) {
|
||||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
|
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@@ -372,10 +319,11 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
/* send to upper layers */
|
/* send to upper layers */
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
|
||||||
|
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
if (!raw_input(p, inp)) {
|
/* raw input did not eat the packet? */
|
||||||
|
if (raw_input(p, inp) == 0) {
|
||||||
#endif /* LWIP_RAW */
|
#endif /* LWIP_RAW */
|
||||||
|
|
||||||
switch (IPH_PROTO(iphdr)) {
|
switch (IPH_PROTO(iphdr)) {
|
||||||
@@ -398,19 +346,18 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* send ICMP destination protocol unreachable unless is was a broadcast */
|
/* send ICMP destination protocol unreachable unless is was a broadcast */
|
||||||
if (!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) &&
|
if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
|
||||||
!ip_addr_ismulticast(&(iphdr->dest))) {
|
!ip_addr_ismulticast(&(iphdr->dest))) {
|
||||||
p->payload = iphdr;
|
p->payload = iphdr;
|
||||||
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
||||||
}
|
}
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
|
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
|
||||||
|
|
||||||
IP_STATS_INC(ip.proterr);
|
IP_STATS_INC(ip.proterr);
|
||||||
IP_STATS_INC(ip.drop);
|
IP_STATS_INC(ip.drop);
|
||||||
snmp_inc_ipunknownprotos();
|
snmp_inc_ipunknownprotos();
|
||||||
|
|
||||||
}
|
}
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
} /* LWIP_RAW */
|
} /* LWIP_RAW */
|
||||||
@@ -418,9 +365,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/* ip_output_if:
|
|
||||||
*
|
|
||||||
* Sends an IP packet on a network interface. This function constructs
|
* Sends an IP packet on a network interface. This function constructs
|
||||||
* the IP header and calculates the IP header checksum. If the source
|
* the IP header and calculates the IP header checksum. If the source
|
||||||
* IP address is NULL, the IP address of the outgoing network
|
* IP address is NULL, the IP address of the outgoing network
|
||||||
@@ -432,8 +377,8 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
u8_t ttl, u8_t tos,
|
u8_t ttl, u8_t tos,
|
||||||
u8_t proto, struct netif *netif)
|
u8_t proto, struct netif *netif)
|
||||||
{
|
{
|
||||||
static struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
static u16_t ip_id = 0;
|
u16_t ip_id = 0;
|
||||||
|
|
||||||
snmp_inc_ipoutrequests();
|
snmp_inc_ipoutrequests();
|
||||||
|
|
||||||
@@ -466,7 +411,9 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
}
|
}
|
||||||
|
|
||||||
IPH_CHKSUM_SET(iphdr, 0);
|
IPH_CHKSUM_SET(iphdr, 0);
|
||||||
|
#if CHECKSUM_GEN_IP
|
||||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
dest = &(iphdr->dest);
|
dest = &(iphdr->dest);
|
||||||
@@ -480,7 +427,7 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
|
|
||||||
IP_STATS_INC(ip.xmit);
|
IP_STATS_INC(ip.xmit);
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
||||||
@@ -488,8 +435,7 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
return netif->output(netif, p, dest);
|
return netif->output(netif, p, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ip_output:
|
/**
|
||||||
*
|
|
||||||
* Simple interface to ip_output_if. It finds the outgoing network
|
* Simple interface to ip_output_if. It finds the outgoing network
|
||||||
* interface and calls upon ip_output_if to do the actual work.
|
* interface and calls upon ip_output_if to do the actual work.
|
||||||
*/
|
*/
|
||||||
@@ -501,7 +447,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
struct netif *netif;
|
struct netif *netif;
|
||||||
|
|
||||||
if ((netif = ip_route(dest)) == NULL) {
|
if ((netif = ip_route(dest)) == NULL) {
|
||||||
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr));
|
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
|
||||||
|
|
||||||
IP_STATS_INC(ip.rterr);
|
IP_STATS_INC(ip.rterr);
|
||||||
snmp_inc_ipoutdiscards();
|
snmp_inc_ipoutdiscards();
|
||||||
@@ -522,35 +468,35 @@ ip_debug_print(struct pbuf *p)
|
|||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("|%2d |%2d | 0x%02x | %5u | (v, hl, tos, len)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n",
|
||||||
IPH_V(iphdr),
|
IPH_V(iphdr),
|
||||||
IPH_HL(iphdr),
|
IPH_HL(iphdr),
|
||||||
IPH_TOS(iphdr),
|
IPH_TOS(iphdr),
|
||||||
ntohs(IPH_LEN(iphdr))));
|
ntohs(IPH_LEN(iphdr))));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %5u |%u%u%u| %4u | (id, flags, offset)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n",
|
||||||
ntohs(IPH_ID(iphdr)),
|
ntohs(IPH_ID(iphdr)),
|
||||||
ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
|
ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
|
||||||
ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
|
ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
|
||||||
ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
|
ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
|
||||||
ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
|
ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | 0x%04x | (ttl, proto, chksum)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n",
|
||||||
IPH_TTL(iphdr),
|
IPH_TTL(iphdr),
|
||||||
IPH_PROTO(iphdr),
|
IPH_PROTO(iphdr),
|
||||||
ntohs(IPH_CHKSUM(iphdr))));
|
ntohs(IPH_CHKSUM(iphdr))));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (src)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
|
||||||
ntohl(iphdr->src.addr) >> 24 & 0xff,
|
ip4_addr1(&iphdr->src),
|
||||||
ntohl(iphdr->src.addr) >> 16 & 0xff,
|
ip4_addr2(&iphdr->src),
|
||||||
ntohl(iphdr->src.addr) >> 8 & 0xff,
|
ip4_addr3(&iphdr->src),
|
||||||
ntohl(iphdr->src.addr) & 0xff));
|
ip4_addr4(&iphdr->src)));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (dest)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
|
||||||
ntohl(iphdr->dest.addr) >> 24 & 0xff,
|
ip4_addr1(&iphdr->dest),
|
||||||
ntohl(iphdr->dest.addr) >> 16 & 0xff,
|
ip4_addr2(&iphdr->dest),
|
||||||
ntohl(iphdr->dest.addr) >> 8 & 0xff,
|
ip4_addr3(&iphdr->dest),
|
||||||
ntohl(iphdr->dest.addr) & 0xff));
|
ip4_addr4(&iphdr->dest)));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
}
|
}
|
||||||
#endif /* IP_DEBUG */
|
#endif /* IP_DEBUG */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -32,7 +32,41 @@
|
|||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
|
/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
|
||||||
const struct ip_addr ip_addr_any = { 0x00000000UL };
|
const struct ip_addr ip_addr_any = { 0x00000000UL };
|
||||||
const struct ip_addr ip_addr_broadcast = { 0xffffffffUL };
|
const struct ip_addr ip_addr_broadcast = { 0xffffffffUL };
|
||||||
|
|
||||||
|
/* Determine if an address is a broadcast address on a network interface
|
||||||
|
*
|
||||||
|
* @param addr address to be checked
|
||||||
|
* @param netif the network interface against which the address is checked
|
||||||
|
* @return returns non-zero if the address is a broadcast address
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
u8_t ip_addr_isbroadcast(struct ip_addr *addr, struct netif *netif)
|
||||||
|
{
|
||||||
|
/* all ones (broadcast) or all zeroes (old skool broadcast) */
|
||||||
|
if ((addr->addr == ip_addr_broadcast.addr) ||
|
||||||
|
(addr->addr == ip_addr_any.addr))
|
||||||
|
return 1;
|
||||||
|
/* no broadcast support on this network interface? */
|
||||||
|
else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0)
|
||||||
|
/* the given address cannot be a broadcast address
|
||||||
|
* nor can we check against any broadcast addresses */
|
||||||
|
return 0;
|
||||||
|
/* address matches network interface address exactly? => no broadcast */
|
||||||
|
else if (addr->addr == netif->ip_addr.addr)
|
||||||
|
return 0;
|
||||||
|
/* on the same (sub) network... */
|
||||||
|
else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask))
|
||||||
|
/* ...and host identifier bits are all ones? =>... */
|
||||||
|
&& ((addr->addr & ~netif->netmask.addr) ==
|
||||||
|
(ip_addr_broadcast.addr & ~netif->netmask.addr)))
|
||||||
|
/* => network broadcast address */
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
|
/* @file
|
||||||
|
*
|
||||||
|
* This is the IP packet segmentation and reassembly implementation.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -31,20 +37,13 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
/* ip_frag.c
|
|
||||||
*
|
|
||||||
* This is the code for IP segmentation and reassembly
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/sys.h"
|
/* #include "lwip/sys.h" */
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/ip_frag.h"
|
#include "lwip/ip_frag.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -79,7 +78,7 @@ copy_from_pbuf(struct pbuf *p, u16_t * offset,
|
|||||||
#define IP_REASS_TMO 1000
|
#define IP_REASS_TMO 1000
|
||||||
|
|
||||||
static u8_t ip_reassbuf[IP_HLEN + IP_REASS_BUFSIZE];
|
static u8_t ip_reassbuf[IP_HLEN + IP_REASS_BUFSIZE];
|
||||||
static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8)];
|
static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8) + 1];
|
||||||
static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f,
|
static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f,
|
||||||
0x0f, 0x07, 0x03, 0x01
|
0x0f, 0x07, 0x03, 0x01
|
||||||
};
|
};
|
||||||
@@ -89,18 +88,26 @@ static u8_t ip_reassflags;
|
|||||||
|
|
||||||
static u8_t ip_reasstmr;
|
static u8_t ip_reasstmr;
|
||||||
|
|
||||||
/* Reassembly timer */
|
/**
|
||||||
static void
|
* Reassembly timer base function
|
||||||
ip_reass_timer(void *arg)
|
* for both NO_SYS == 0 and 1 (!).
|
||||||
|
*
|
||||||
|
* Should be called every 1000 msec.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ip_reass_tmr(void)
|
||||||
{
|
{
|
||||||
(void)arg;
|
if (ip_reasstmr > 0) {
|
||||||
if (ip_reasstmr > 1) {
|
|
||||||
ip_reasstmr--;
|
ip_reasstmr--;
|
||||||
sys_timeout(IP_REASS_TMO, ip_reass_timer, NULL);
|
}
|
||||||
} else if (ip_reasstmr == 1)
|
|
||||||
ip_reasstmr = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reassembles incoming IP fragments into an IP datagram.
|
||||||
|
*
|
||||||
|
* @param p points to a pbuf chain of the fragment
|
||||||
|
* @return NULL if reassembly is incomplete, ? otherwise
|
||||||
|
*/
|
||||||
struct pbuf *
|
struct pbuf *
|
||||||
ip_reass(struct pbuf *p)
|
ip_reass(struct pbuf *p)
|
||||||
{
|
{
|
||||||
@@ -120,7 +127,6 @@ ip_reass(struct pbuf *p)
|
|||||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: new packet\n"));
|
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: new packet\n"));
|
||||||
memcpy(iphdr, fraghdr, IP_HLEN);
|
memcpy(iphdr, fraghdr, IP_HLEN);
|
||||||
ip_reasstmr = IP_REASS_MAXAGE;
|
ip_reasstmr = IP_REASS_MAXAGE;
|
||||||
sys_timeout(IP_REASS_TMO, ip_reass_timer, NULL);
|
|
||||||
ip_reassflags = 0;
|
ip_reassflags = 0;
|
||||||
/* Clear the bitmap. */
|
/* Clear the bitmap. */
|
||||||
memset(ip_reassbitmap, 0, sizeof(ip_reassbitmap));
|
memset(ip_reassbitmap, 0, sizeof(ip_reassbitmap));
|
||||||
@@ -132,7 +138,8 @@ ip_reass(struct pbuf *p)
|
|||||||
if (ip_addr_cmp(&iphdr->src, &fraghdr->src) &&
|
if (ip_addr_cmp(&iphdr->src, &fraghdr->src) &&
|
||||||
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
|
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
|
||||||
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
|
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n"));
|
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n",
|
||||||
|
ntohs(IPH_ID(fraghdr))));
|
||||||
IPFRAG_STATS_INC(ip_frag.cachehit);
|
IPFRAG_STATS_INC(ip_frag.cachehit);
|
||||||
/* Find out the offset in the reassembly buffer where we should
|
/* Find out the offset in the reassembly buffer where we should
|
||||||
copy the fragment. */
|
copy the fragment. */
|
||||||
@@ -143,9 +150,8 @@ ip_reass(struct pbuf *p)
|
|||||||
reassembly buffer, we discard the entire packet. */
|
reassembly buffer, we discard the entire packet. */
|
||||||
if (offset > IP_REASS_BUFSIZE || offset + len > IP_REASS_BUFSIZE) {
|
if (offset > IP_REASS_BUFSIZE || offset + len > IP_REASS_BUFSIZE) {
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: fragment outside of buffer (%d:%d/%d).\n", offset,
|
("ip_reass: fragment outside of buffer (%"S16_F":%"S16_F"/%"S16_F").\n", offset,
|
||||||
offset + len, IP_REASS_BUFSIZE));
|
offset + len, IP_REASS_BUFSIZE));
|
||||||
sys_untimeout(ip_reass_timer, NULL);
|
|
||||||
ip_reasstmr = 0;
|
ip_reasstmr = 0;
|
||||||
goto nullreturn;
|
goto nullreturn;
|
||||||
}
|
}
|
||||||
@@ -153,7 +159,7 @@ ip_reass(struct pbuf *p)
|
|||||||
/* Copy the fragment into the reassembly buffer, at the right
|
/* Copy the fragment into the reassembly buffer, at the right
|
||||||
offset. */
|
offset. */
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: copying with offset %d into %d:%d\n", offset,
|
("ip_reass: copying with offset %"S16_F" into %"S16_F":%"S16_F"\n", offset,
|
||||||
IP_HLEN + offset, IP_HLEN + offset + len));
|
IP_HLEN + offset, IP_HLEN + offset + len));
|
||||||
i = IPH_HL(fraghdr) * 4;
|
i = IPH_HL(fraghdr) * 4;
|
||||||
copy_from_pbuf(p, &i, &ip_reassbuf[IP_HLEN + offset], len);
|
copy_from_pbuf(p, &i, &ip_reassbuf[IP_HLEN + offset], len);
|
||||||
@@ -162,24 +168,29 @@ ip_reass(struct pbuf *p)
|
|||||||
if (offset / (8 * 8) == (offset + len) / (8 * 8)) {
|
if (offset / (8 * 8) == (offset + len) / (8 * 8)) {
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: updating single byte in bitmap.\n"));
|
("ip_reass: updating single byte in bitmap.\n"));
|
||||||
/* If the two endpoints are in the same byte, we only update
|
/* If the two endpoints are in the same byte, we only update that byte. */
|
||||||
that byte. */
|
LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||||
|
offset / (8 * 8) < sizeof(ip_reassbitmap));
|
||||||
ip_reassbitmap[offset / (8 * 8)] |=
|
ip_reassbitmap[offset / (8 * 8)] |=
|
||||||
bitmap_bits[(offset / 8) & 7] &
|
bitmap_bits[(offset / 8) & 7] &
|
||||||
~bitmap_bits[((offset + len) / 8) & 7];
|
~bitmap_bits[((offset + len) / 8) & 7];
|
||||||
} else {
|
} else {
|
||||||
/* If the two endpoints are in different bytes, we update the
|
/* If the two endpoints are in different bytes, we update the
|
||||||
bytes in the endpoints and fill the stuff inbetween with
|
bytes in the endpoints and fill the stuff inbetween with
|
||||||
0xff. */
|
0xff. */
|
||||||
|
LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||||
|
offset / (8 * 8) < sizeof(ip_reassbitmap));
|
||||||
ip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7];
|
ip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7];
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: updating many bytes in bitmap (%d:%d).\n",
|
("ip_reass: updating many bytes in bitmap (%"S16_F":%"S16_F").\n",
|
||||||
1 + offset / (8 * 8), (offset + len) / (8 * 8)));
|
1 + offset / (8 * 8), (offset + len) / (8 * 8)));
|
||||||
for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
|
for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
|
||||||
ip_reassbitmap[i] = 0xff;
|
ip_reassbitmap[i] = 0xff;
|
||||||
}
|
}
|
||||||
|
LWIP_ASSERT("(offset + len) / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||||
|
(offset + len) / (8 * 8) < sizeof(ip_reassbitmap));
|
||||||
ip_reassbitmap[(offset + len) / (8 * 8)] |=
|
ip_reassbitmap[(offset + len) / (8 * 8)] |=
|
||||||
~bitmap_bits[((offset + len) / 8) & 7];
|
~bitmap_bits[((offset + len) / 8) & 7];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this fragment has the More Fragments flag set to zero, we
|
/* If this fragment has the More Fragments flag set to zero, we
|
||||||
@@ -192,7 +203,7 @@ ip_reass(struct pbuf *p)
|
|||||||
ip_reassflags |= IP_REASS_FLAG_LASTFRAG;
|
ip_reassflags |= IP_REASS_FLAG_LASTFRAG;
|
||||||
ip_reasslen = offset + len;
|
ip_reasslen = offset + len;
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: last fragment seen, total len %d\n",
|
("ip_reass: last fragment seen, total len %"S16_F"\n",
|
||||||
ip_reasslen));
|
ip_reasslen));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,23 +213,27 @@ ip_reass(struct pbuf *p)
|
|||||||
if (ip_reassflags & IP_REASS_FLAG_LASTFRAG) {
|
if (ip_reassflags & IP_REASS_FLAG_LASTFRAG) {
|
||||||
/* Check all bytes up to and including all but the last byte in
|
/* Check all bytes up to and including all but the last byte in
|
||||||
the bitmap. */
|
the bitmap. */
|
||||||
|
LWIP_ASSERT("ip_reasslen / (8 * 8) - 1 < sizeof(ip_reassbitmap)",
|
||||||
|
ip_reasslen / (8 * 8) - 1 < sizeof(ip_reassbitmap));
|
||||||
for (i = 0; i < ip_reasslen / (8 * 8) - 1; ++i) {
|
for (i = 0; i < ip_reasslen / (8 * 8) - 1; ++i) {
|
||||||
if (ip_reassbitmap[i] != 0xff) {
|
if (ip_reassbitmap[i] != 0xff) {
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: last fragment seen, bitmap %d/%d failed (%x)\n",
|
("ip_reass: last fragment seen, bitmap %"S16_F"/%"S16_F" failed (%"X16_F")\n",
|
||||||
i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
|
i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
|
||||||
goto nullreturn;
|
goto nullreturn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Check the last byte in the bitmap. It should contain just the
|
/* Check the last byte in the bitmap. It should contain just the
|
||||||
right amount of bits. */
|
right amount of bits. */
|
||||||
|
LWIP_ASSERT("ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||||
|
ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap));
|
||||||
if (ip_reassbitmap[ip_reasslen / (8 * 8)] !=
|
if (ip_reassbitmap[ip_reasslen / (8 * 8)] !=
|
||||||
(u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) {
|
(u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) {
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: last fragment seen, bitmap %d didn't contain %x (%x)\n",
|
("ip_reass: last fragment seen, bitmap %"S16_F" didn't contain %"X16_F" (%"X16_F")\n",
|
||||||
ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7],
|
ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7],
|
||||||
ip_reassbitmap[ip_reasslen / (8 * 8)]));
|
ip_reassbitmap[ip_reasslen / (8 * 8)]));
|
||||||
goto nullreturn;
|
goto nullreturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pretend to be a "normal" (i.e., not fragmented) IP packet
|
/* Pretend to be a "normal" (i.e., not fragmented) IP packet
|
||||||
@@ -233,27 +248,25 @@ ip_reass(struct pbuf *p)
|
|||||||
/* If we have come this far, we have a full packet in the
|
/* If we have come this far, we have a full packet in the
|
||||||
buffer, so we allocate a pbuf and copy the packet into it. We
|
buffer, so we allocate a pbuf and copy the packet into it. We
|
||||||
also reset the timer. */
|
also reset the timer. */
|
||||||
sys_untimeout(ip_reass_timer, NULL);
|
|
||||||
ip_reasstmr = 0;
|
ip_reasstmr = 0;
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
p = pbuf_alloc(PBUF_LINK, ip_reasslen, PBUF_POOL);
|
p = pbuf_alloc(PBUF_LINK, ip_reasslen, PBUF_POOL);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
i = 0;
|
i = 0;
|
||||||
for (q = p; q != NULL; q = q->next) {
|
for (q = p; q != NULL; q = q->next) {
|
||||||
/* Copy enough bytes to fill this pbuf in the chain. The
|
/* Copy enough bytes to fill this pbuf in the chain. The
|
||||||
available data in the pbuf is given by the q->len
|
available data in the pbuf is given by the q->len variable. */
|
||||||
variable. */
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
("ip_reass: memcpy from %p (%"S16_F") to %p, %"S16_F" bytes\n",
|
||||||
("ip_reass: memcpy from %p (%d) to %p, %d bytes\n",
|
(void *)&ip_reassbuf[i], i, q->payload,
|
||||||
&ip_reassbuf[i], i, q->payload,
|
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
|
||||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
|
memcpy(q->payload, &ip_reassbuf[i],
|
||||||
memcpy(q->payload, &ip_reassbuf[i],
|
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
|
||||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
|
i += q->len;
|
||||||
i += q->len;
|
}
|
||||||
}
|
IPFRAG_STATS_INC(ip_frag.fw);
|
||||||
IPFRAG_STATS_INC(ip_frag.fw);
|
|
||||||
} else {
|
} else {
|
||||||
IPFRAG_STATS_INC(ip_frag.memerr);
|
IPFRAG_STATS_INC(ip_frag.memerr);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
|
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
|
||||||
return p;
|
return p;
|
||||||
@@ -270,9 +283,9 @@ nullreturn:
|
|||||||
static u8_t buf[MEM_ALIGN_SIZE(MAX_MTU)];
|
static u8_t buf[MEM_ALIGN_SIZE(MAX_MTU)];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment an IP packet if too large
|
* Fragment an IP datagram if too large for the netif.
|
||||||
*
|
*
|
||||||
* Chop the packet in mtu sized chunks and send them in order
|
* Chop the datagram in MTU sized chunks and send them in order
|
||||||
* by using a fixed size static memory buffer (PBUF_ROM)
|
* by using a fixed size static memory buffer (PBUF_ROM)
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
@@ -291,10 +304,12 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
|||||||
|
|
||||||
/* Get a RAM based MTU sized pbuf */
|
/* Get a RAM based MTU sized pbuf */
|
||||||
rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF);
|
rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF);
|
||||||
|
if (rambuf == NULL) {
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
rambuf->tot_len = rambuf->len = mtu;
|
rambuf->tot_len = rambuf->len = mtu;
|
||||||
rambuf->payload = MEM_ALIGN((void *)buf);
|
rambuf->payload = MEM_ALIGN((void *)buf);
|
||||||
|
|
||||||
|
|
||||||
/* Copy the IP header in it */
|
/* Copy the IP header in it */
|
||||||
iphdr = rambuf->payload;
|
iphdr = rambuf->payload;
|
||||||
memcpy(iphdr, p->payload, IP_HLEN);
|
memcpy(iphdr, p->payload, IP_HLEN);
|
||||||
@@ -335,11 +350,15 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
|||||||
* worked would make things simpler.
|
* worked would make things simpler.
|
||||||
*/
|
*/
|
||||||
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
|
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
|
||||||
pbuf_chain(header, rambuf);
|
if (header != NULL) {
|
||||||
netif->output(netif, header, dest);
|
pbuf_chain(header, rambuf);
|
||||||
IPFRAG_STATS_INC(ip_frag.xmit);
|
netif->output(netif, header, dest);
|
||||||
pbuf_free(header);
|
IPFRAG_STATS_INC(ip_frag.xmit);
|
||||||
|
pbuf_free(header);
|
||||||
|
} else {
|
||||||
|
pbuf_free(rambuf);
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
left -= cop;
|
left -= cop;
|
||||||
}
|
}
|
||||||
pbuf_free(rambuf);
|
pbuf_free(rambuf);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
void
|
void
|
||||||
icmp_input(struct pbuf *p, struct netif *inp)
|
icmp_input(struct pbuf *p, struct netif *inp)
|
||||||
{
|
{
|
||||||
unsigned char type;
|
u8_t type;
|
||||||
struct icmp_echo_hdr *iecho;
|
struct icmp_echo_hdr *iecho;
|
||||||
struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
struct ip_addr tmpaddr;
|
struct ip_addr tmpaddr;
|
||||||
@@ -57,7 +57,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
|
|
||||||
/* TODO: check length before accessing payload! */
|
/* TODO: check length before accessing payload! */
|
||||||
|
|
||||||
type = ((char *)p->payload)[0];
|
type = ((u8_t *)p->payload)[0];
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ICMP6_ECHO:
|
case ICMP6_ECHO:
|
||||||
@@ -74,16 +74,16 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
iecho = p->payload;
|
iecho = p->payload;
|
||||||
iphdr = (struct ip_hdr *)((char *)p->payload - IP_HLEN);
|
iphdr = (struct ip_hdr *)((u8_t *)p->payload - IP_HLEN);
|
||||||
if (inet_chksum_pbuf(p) != 0) {
|
if (inet_chksum_pbuf(p) != 0) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
||||||
|
|
||||||
#ifdef ICMP_STATS
|
#ifdef ICMP_STATS
|
||||||
++lwip_stats.icmp.chkerr;
|
++lwip_stats.icmp.chkerr;
|
||||||
#endif /* ICMP_STATS */
|
#endif /* ICMP_STATS */
|
||||||
/* return;*/
|
/* return;*/
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %d p->tot_len %d\n", p->len, p->tot_len));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %"S16_F" p->tot_len %"S16_F"\n", p->len, p->tot_len));
|
||||||
ip_addr_set(&tmpaddr, &(iphdr->src));
|
ip_addr_set(&tmpaddr, &(iphdr->src));
|
||||||
ip_addr_set(&(iphdr->src), &(iphdr->dest));
|
ip_addr_set(&(iphdr->src), &(iphdr->dest));
|
||||||
ip_addr_set(&(iphdr->dest), &tmpaddr);
|
ip_addr_set(&(iphdr->dest), &tmpaddr);
|
||||||
@@ -94,17 +94,17 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
} else {
|
} else {
|
||||||
iecho->chksum += htons(ICMP6_ECHO << 8);
|
iecho->chksum += htons(ICMP6_ECHO << 8);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
||||||
#ifdef ICMP_STATS
|
#ifdef ICMP_STATS
|
||||||
++lwip_stats.icmp.xmit;
|
++lwip_stats.icmp.xmit;
|
||||||
#endif /* ICMP_STATS */
|
#endif /* ICMP_STATS */
|
||||||
|
|
||||||
/* LWIP_DEBUGF("icmp: p->len %u p->tot_len %u\n", p->len, p->tot_len);*/
|
/* LWIP_DEBUGF("icmp: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
|
||||||
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
|
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
|
||||||
iphdr->hoplim, IP_PROTO_ICMP, inp);
|
iphdr->hoplim, IP_PROTO_ICMP, inp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d not supported.\n", (int)type));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" not supported.\n", (s16_t)type));
|
||||||
#ifdef ICMP_STATS
|
#ifdef ICMP_STATS
|
||||||
++lwip_stats.icmp.proterr;
|
++lwip_stats.icmp.proterr;
|
||||||
++lwip_stats.icmp.drop;
|
++lwip_stats.icmp.drop;
|
||||||
@@ -127,10 +127,10 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
|||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
|
|
||||||
idur = q->payload;
|
idur = q->payload;
|
||||||
idur->type = (char)ICMP6_DUR;
|
idur->type = (u8_t)ICMP6_DUR;
|
||||||
idur->icode = (char)t;
|
idur->icode = (u8_t)t;
|
||||||
|
|
||||||
memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);
|
memcpy((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
|
||||||
|
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
idur->chksum = 0;
|
idur->chksum = 0;
|
||||||
@@ -158,11 +158,11 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
|||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
|
|
||||||
tehdr = q->payload;
|
tehdr = q->payload;
|
||||||
tehdr->type = (char)ICMP6_TE;
|
tehdr->type = (u8_t)ICMP6_TE;
|
||||||
tehdr->icode = (char)t;
|
tehdr->icode = (u8_t)t;
|
||||||
|
|
||||||
/* copy fields from original packet */
|
/* copy fields from original packet */
|
||||||
memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
|
memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
|
||||||
|
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
tehdr->chksum = 0;
|
tehdr->chksum = 0;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -77,7 +77,7 @@ ip_route(struct ip_addr *dest)
|
|||||||
struct netif *netif;
|
struct netif *netif;
|
||||||
|
|
||||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||||
if (ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
||||||
return netif;
|
return netif;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,7 +217,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
#if IP_DEBUG
|
#if IP_DEBUG
|
||||||
/* LWIP_DEBUGF("ip_input: \n");
|
/* LWIP_DEBUGF("ip_input: \n");
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
LWIP_DEBUGF("ip_input: p->len %u p->tot_len %u\n", p->len, p->tot_len);*/
|
LWIP_DEBUGF("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
|
||||||
#endif /* IP_DEBUG */
|
#endif /* IP_DEBUG */
|
||||||
|
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
/* send ICMP destination protocol unreachable */
|
/* send ICMP destination protocol unreachable */
|
||||||
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %u\n",
|
LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %"U16_F"\n",
|
||||||
iphdr->nexthdr));
|
iphdr->nexthdr));
|
||||||
|
|
||||||
#ifdef IP_STATS
|
#ifdef IP_STATS
|
||||||
@@ -266,7 +266,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
|
|
||||||
PERF_START;
|
PERF_START;
|
||||||
|
|
||||||
printf("len %u tot_len %u\n", p->len, p->tot_len);
|
printf("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len);
|
||||||
if (pbuf_header(p, IP_HLEN)) {
|
if (pbuf_header(p, IP_HLEN)) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
|
||||||
#ifdef IP_STATS
|
#ifdef IP_STATS
|
||||||
@@ -275,7 +275,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
|
|
||||||
return ERR_BUF;
|
return ERR_BUF;
|
||||||
}
|
}
|
||||||
printf("len %u tot_len %u\n", p->len, p->tot_len);
|
printf("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len);
|
||||||
|
|
||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
|
|
||||||
@@ -303,7 +303,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
++lwip_stats.ip.xmit;
|
++lwip_stats.ip.xmit;
|
||||||
#endif /* IP_STATS */
|
#endif /* IP_STATS */
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %u)\n", netif->name[0], netif->name[1], p->tot_len));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %"U16_F")\n", netif->name[0], netif->name[1], p->tot_len));
|
||||||
#if IP_DEBUG
|
#if IP_DEBUG
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
#endif /* IP_DEBUG */
|
#endif /* IP_DEBUG */
|
||||||
@@ -324,7 +324,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
{
|
{
|
||||||
struct netif *netif;
|
struct netif *netif;
|
||||||
if ((netif = ip_route(dest)) == NULL) {
|
if ((netif = ip_route(dest)) == NULL) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%lx\n", dest->addr));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
|
||||||
#ifdef IP_STATS
|
#ifdef IP_STATS
|
||||||
++lwip_stats.ip.rterr;
|
++lwip_stats.ip.rterr;
|
||||||
#endif /* IP_STATS */
|
#endif /* IP_STATS */
|
||||||
@@ -339,45 +339,45 @@ void
|
|||||||
ip_debug_print(struct pbuf *p)
|
ip_debug_print(struct pbuf *p)
|
||||||
{
|
{
|
||||||
struct ip_hdr *iphdr = p->payload;
|
struct ip_hdr *iphdr = p->payload;
|
||||||
char *payload;
|
u8_t *payload;
|
||||||
|
|
||||||
payload = (char *)iphdr + IP_HLEN;
|
payload = (u8_t *)iphdr + IP_HLEN;
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("|%2d | %x%x | %x%x | (v, traffic class, flow label)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" | %"X16_F"%"X16_F" | %"X16_F"%"X16_F" | (v, traffic class, flow label)\n",
|
||||||
iphdr->v,
|
iphdr->v,
|
||||||
iphdr->tclass1, iphdr->tclass2,
|
iphdr->tclass1, iphdr->tclass2,
|
||||||
iphdr->flow1, iphdr->flow2));
|
iphdr->flow1, iphdr->flow2));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %5u | %2u | %2u | (len, nexthdr, hoplim)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" | %2"U16_F" | %2"U16_F" | (len, nexthdr, hoplim)\n",
|
||||||
ntohs(iphdr->len),
|
ntohs(iphdr->len),
|
||||||
iphdr->nexthdr,
|
iphdr->nexthdr,
|
||||||
iphdr->hoplim));
|
iphdr->hoplim));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
|
||||||
ntohl(iphdr->src.addr[0]) >> 16 & 0xffff,
|
ntohl(iphdr->src.addr[0]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->src.addr[0]) & 0xffff));
|
ntohl(iphdr->src.addr[0]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
|
||||||
ntohl(iphdr->src.addr[1]) >> 16 & 0xffff,
|
ntohl(iphdr->src.addr[1]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->src.addr[1]) & 0xffff));
|
ntohl(iphdr->src.addr[1]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
|
||||||
ntohl(iphdr->src.addr[2]) >> 16 & 0xffff,
|
ntohl(iphdr->src.addr[2]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->src.addr[2]) & 0xffff));
|
ntohl(iphdr->src.addr[2]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
|
||||||
ntohl(iphdr->src.addr[3]) >> 16 & 0xffff,
|
ntohl(iphdr->src.addr[3]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->src.addr[3]) & 0xffff));
|
ntohl(iphdr->src.addr[3]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
|
||||||
ntohl(iphdr->dest.addr[0]) >> 16 & 0xffff,
|
ntohl(iphdr->dest.addr[0]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->dest.addr[0]) & 0xffff));
|
ntohl(iphdr->dest.addr[0]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
|
||||||
ntohl(iphdr->dest.addr[1]) >> 16 & 0xffff,
|
ntohl(iphdr->dest.addr[1]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->dest.addr[1]) & 0xffff));
|
ntohl(iphdr->dest.addr[1]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
|
||||||
ntohl(iphdr->dest.addr[2]) >> 16 & 0xffff,
|
ntohl(iphdr->dest.addr[2]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->dest.addr[2]) & 0xffff));
|
ntohl(iphdr->dest.addr[2]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
|
||||||
ntohl(iphdr->dest.addr[3]) >> 16 & 0xffff,
|
ntohl(iphdr->dest.addr[3]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->dest.addr[3]) & 0xffff));
|
ntohl(iphdr->dest.addr[3]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -34,8 +34,8 @@
|
|||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
|
|
||||||
|
|
||||||
int
|
u8_t
|
||||||
ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
||||||
struct ip_addr *mask)
|
struct ip_addr *mask)
|
||||||
{
|
{
|
||||||
return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) &&
|
return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) &&
|
||||||
@@ -45,7 +45,7 @@ ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
u8_t
|
||||||
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
|
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
|
||||||
{
|
{
|
||||||
return(addr1->addr[0] == addr2->addr[0] &&
|
return(addr1->addr[0] == addr2->addr[0] &&
|
||||||
@@ -64,7 +64,7 @@ ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
|
|||||||
dest->addr[3] = src->addr[3];*/
|
dest->addr[3] = src->addr[3];*/
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
u8_t
|
||||||
ip_addr_isany(struct ip_addr *addr)
|
ip_addr_isany(struct ip_addr *addr)
|
||||||
{
|
{
|
||||||
if (addr == NULL) return 1;
|
if (addr == NULL) return 1;
|
||||||
@@ -76,7 +76,7 @@ ip_addr_isany(struct ip_addr *addr)
|
|||||||
void
|
void
|
||||||
ip_addr_debug_print(struct ip_addr *addr)
|
ip_addr_debug_print(struct ip_addr *addr)
|
||||||
{
|
{
|
||||||
printf("%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx",
|
printf("%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F",
|
||||||
ntohl(addr->addr[0]) >> 16 & 0xffff,
|
ntohl(addr->addr[0]) >> 16 & 0xffff,
|
||||||
ntohl(addr->addr[0]) & 0xffff,
|
ntohl(addr->addr[0]) & 0xffff,
|
||||||
ntohl(addr->addr[1]) >> 16 & 0xffff,
|
ntohl(addr->addr[1]) >> 16 & 0xffff,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "lwip/arch.h"
|
#include "lwip/arch.h"
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
@@ -54,6 +55,8 @@ struct mem {
|
|||||||
u16_t used;
|
u16_t used;
|
||||||
#elif MEM_ALIGNMENT == 4
|
#elif MEM_ALIGNMENT == 4
|
||||||
u32_t used;
|
u32_t used;
|
||||||
|
#elif MEM_ALIGNMENT == 8
|
||||||
|
u64_t used;
|
||||||
#else
|
#else
|
||||||
#error "unhandled MEM_ALIGNMENT size"
|
#error "unhandled MEM_ALIGNMENT size"
|
||||||
#endif /* MEM_ALIGNMENT */
|
#endif /* MEM_ALIGNMENT */
|
||||||
@@ -292,13 +295,13 @@ mem_malloc(mem_size_t size)
|
|||||||
}
|
}
|
||||||
sys_sem_signal(mem_sem);
|
sys_sem_signal(mem_sem);
|
||||||
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
|
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
|
||||||
(u32_t)mem + SIZEOF_STRUCT_MEM + size <= (u32_t)ram_end);
|
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
|
||||||
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
|
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
|
||||||
(unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
|
(unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
|
||||||
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
|
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size));
|
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
|
||||||
#if MEM_STATS
|
#if MEM_STATS
|
||||||
++lwip_stats.mem.err;
|
++lwip_stats.mem.err;
|
||||||
#endif /* MEM_STATS */
|
#endif /* MEM_STATS */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -120,11 +120,11 @@ static u8_t memp_memory[(MEMP_NUM_PBUF *
|
|||||||
static sys_sem_t mutex;
|
static sys_sem_t mutex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LWIP_NOASSERT
|
#if MEMP_SANITY_CHECK
|
||||||
static int
|
static int
|
||||||
memp_sanity(void)
|
memp_sanity(void)
|
||||||
{
|
{
|
||||||
int i, c;
|
s16_t i, c;
|
||||||
struct memp *m, *n;
|
struct memp *m, *n;
|
||||||
|
|
||||||
for(i = 0; i < MEMP_MAX; i++) {
|
for(i = 0; i < MEMP_MAX; i++) {
|
||||||
@@ -140,7 +140,7 @@ memp_sanity(void)
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif /* LWIP_DEBUG */
|
#endif /* MEMP_SANITY_CHECK*/
|
||||||
|
|
||||||
void
|
void
|
||||||
memp_init(void)
|
memp_init(void)
|
||||||
@@ -217,12 +217,12 @@ memp_malloc(memp_t type)
|
|||||||
sys_sem_signal(mutex);
|
sys_sem_signal(mutex);
|
||||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||||
LWIP_ASSERT("memp_malloc: memp properly aligned",
|
LWIP_ASSERT("memp_malloc: memp properly aligned",
|
||||||
((u32_t)MEM_ALIGN((u8_t *)memp + sizeof(struct memp)) % MEM_ALIGNMENT) == 0);
|
((mem_ptr_t)MEM_ALIGN((u8_t *)memp + sizeof(struct memp)) % MEM_ALIGNMENT) == 0);
|
||||||
|
|
||||||
mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp));
|
mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp));
|
||||||
return mem;
|
return mem;
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %d\n", type));
|
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %"S16_F"\n", type));
|
||||||
#if MEMP_STATS
|
#if MEMP_STATS
|
||||||
++lwip_stats.memp[type].err;
|
++lwip_stats.memp[type].err;
|
||||||
#endif /* MEMP_STATS */
|
#endif /* MEMP_STATS */
|
||||||
@@ -261,7 +261,9 @@ memp_free(memp_t type, void *mem)
|
|||||||
memp->next = memp_tab[type];
|
memp->next = memp_tab[type];
|
||||||
memp_tab[type] = memp;
|
memp_tab[type] = memp;
|
||||||
|
|
||||||
|
#if MEMP_SANITY_CHECK
|
||||||
LWIP_ASSERT("memp sanity", memp_sanity());
|
LWIP_ASSERT("memp sanity", memp_sanity());
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SYS_LIGHTWEIGHT_PROT
|
#if SYS_LIGHTWEIGHT_PROT
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
SYS_ARCH_UNPROTECT(old_level);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -39,23 +39,24 @@
|
|||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
|
|
||||||
|
|
||||||
struct netif *netif_list = NULL;
|
struct netif *netif_list = NULL;
|
||||||
struct netif *netif_default = NULL;
|
struct netif *netif_default = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a network interface to the list of lwIP netifs.
|
* Add a network interface to the list of lwIP netifs.
|
||||||
*
|
*
|
||||||
|
* @param netif a pre-allocated netif structure
|
||||||
* @param ipaddr IP address for the new netif
|
* @param ipaddr IP address for the new netif
|
||||||
* @param netmask network mask for the new netif
|
* @param netmask network mask for the new netif
|
||||||
* @param gw default gateway IP address for the new netif
|
* @param gw default gateway IP address for the new netif
|
||||||
* @param state opaque data passed to the new netif
|
* @param state opaque data passed to the new netif
|
||||||
* @param init callback function that initializes the interface
|
* @param init callback function that initializes the interface
|
||||||
* @param input callback function that...
|
* @param input callback function that is called to pass
|
||||||
|
* ingress packets up in the protocol layer stack.
|
||||||
*
|
*
|
||||||
* @return netif, or NULL if failed.
|
* @return netif, or NULL if failed.
|
||||||
*/
|
*/
|
||||||
@@ -66,8 +67,7 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
|||||||
err_t (* init)(struct netif *netif),
|
err_t (* init)(struct netif *netif),
|
||||||
err_t (* input)(struct pbuf *p, struct netif *netif))
|
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||||
{
|
{
|
||||||
static int netifnum = 0;
|
static s16_t netifnum = 0;
|
||||||
|
|
||||||
|
|
||||||
#if LWIP_DHCP
|
#if LWIP_DHCP
|
||||||
/* netif not under DHCP control by default */
|
/* netif not under DHCP control by default */
|
||||||
@@ -171,7 +171,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
|||||||
/* address is actually being changed? */
|
/* address is actually being changed? */
|
||||||
if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
|
if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
|
||||||
{
|
{
|
||||||
extern struct tcp_pcb *tcp_active_pcbs;
|
/* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */
|
||||||
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n"));
|
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n"));
|
||||||
pcb = tcp_active_pcbs;
|
pcb = tcp_active_pcbs;
|
||||||
while (pcb != NULL) {
|
while (pcb != NULL) {
|
||||||
@@ -186,7 +186,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
|||||||
pcb = pcb->next;
|
pcb = pcb->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (lpcb = tcp_listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||||
/* PCB bound to current local interface address? */
|
/* PCB bound to current local interface address? */
|
||||||
if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {
|
if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {
|
||||||
/* The PCB is listening to the old ipaddr and
|
/* The PCB is listening to the old ipaddr and
|
||||||
@@ -197,36 +197,44 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ip_addr_set(&(netif->ip_addr), ipaddr);
|
ip_addr_set(&(netif->ip_addr), ipaddr);
|
||||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %u.%u.%u.%u\n",
|
#if 0 /* only allowed for Ethernet interfaces TODO: how can we check? */
|
||||||
|
/** For Ethernet network interfaces, we would like to send a
|
||||||
|
* "gratuitous ARP"; this is an ARP packet sent by a node in order
|
||||||
|
* to spontaneously cause other nodes to update an entry in their
|
||||||
|
* ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6.
|
||||||
|
*/
|
||||||
|
etharp_query(netif, ipaddr, NULL);
|
||||||
|
#endif
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||||
netif->name[0], netif->name[1],
|
netif->name[0], netif->name[1],
|
||||||
(unsigned int)(ntohl(netif->ip_addr.addr) >> 24 & 0xff),
|
ip4_addr1(&netif->ip_addr),
|
||||||
(unsigned int)(ntohl(netif->ip_addr.addr) >> 16 & 0xff),
|
ip4_addr2(&netif->ip_addr),
|
||||||
(unsigned int)(ntohl(netif->ip_addr.addr) >> 8 & 0xff),
|
ip4_addr3(&netif->ip_addr),
|
||||||
(unsigned int)(ntohl(netif->ip_addr.addr) & 0xff)));
|
ip4_addr4(&netif->ip_addr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
netif_set_gw(struct netif *netif, struct ip_addr *gw)
|
netif_set_gw(struct netif *netif, struct ip_addr *gw)
|
||||||
{
|
{
|
||||||
ip_addr_set(&(netif->gw), gw);
|
ip_addr_set(&(netif->gw), gw);
|
||||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %u.%u.%u.%u\n",
|
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||||
netif->name[0], netif->name[1],
|
netif->name[0], netif->name[1],
|
||||||
(unsigned int)(ntohl(netif->gw.addr) >> 24 & 0xff),
|
ip4_addr1(&netif->gw),
|
||||||
(unsigned int)(ntohl(netif->gw.addr) >> 16 & 0xff),
|
ip4_addr2(&netif->gw),
|
||||||
(unsigned int)(ntohl(netif->gw.addr) >> 8 & 0xff),
|
ip4_addr3(&netif->gw),
|
||||||
(unsigned int)(ntohl(netif->gw.addr) & 0xff)));
|
ip4_addr4(&netif->gw)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
|
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
|
||||||
{
|
{
|
||||||
ip_addr_set(&(netif->netmask), netmask);
|
ip_addr_set(&(netif->netmask), netmask);
|
||||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %u.%u.%u.%u\n",
|
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||||
netif->name[0], netif->name[1],
|
netif->name[0], netif->name[1],
|
||||||
(unsigned int)(ntohl(netif->netmask.addr) >> 24 & 0xff),
|
ip4_addr1(&netif->netmask),
|
||||||
(unsigned int)(ntohl(netif->netmask.addr) >> 16 & 0xff),
|
ip4_addr2(&netif->netmask),
|
||||||
(unsigned int)(ntohl(netif->netmask.addr) >> 8 & 0xff),
|
ip4_addr3(&netif->netmask),
|
||||||
(unsigned int)(ntohl(netif->netmask.addr) & 0xff)));
|
ip4_addr4(&netif->netmask)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -237,6 +245,41 @@ netif_set_default(struct netif *netif)
|
|||||||
netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
|
netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bring an interface up, available for processing
|
||||||
|
* traffic.
|
||||||
|
*
|
||||||
|
* @note: Enabling DHCP on a down interface will make it come
|
||||||
|
* up once configured.
|
||||||
|
*
|
||||||
|
* @see dhcp_start()
|
||||||
|
*/
|
||||||
|
void netif_set_up(struct netif *netif)
|
||||||
|
{
|
||||||
|
netif->flags |= NETIF_FLAG_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask if an interface is up
|
||||||
|
*/
|
||||||
|
u8_t netif_is_up(struct netif *netif)
|
||||||
|
{
|
||||||
|
return (netif->flags & NETIF_FLAG_UP)?1:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bring an interface down, disabling any traffic processing.
|
||||||
|
*
|
||||||
|
* @note: Enabling DHCP on a down interface will make it come
|
||||||
|
* up once configured.
|
||||||
|
*
|
||||||
|
* @see dhcp_start()
|
||||||
|
*/
|
||||||
|
void netif_set_down(struct netif *netif)
|
||||||
|
{
|
||||||
|
netif->flags &= ~NETIF_FLAG_UP;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
netif_init(void)
|
netif_init(void)
|
||||||
{
|
{
|
||||||
|
|||||||
186
src/core/pbuf.c
186
src/core/pbuf.c
@@ -11,12 +11,15 @@
|
|||||||
* list. This is called a "pbuf chain".
|
* list. This is called a "pbuf chain".
|
||||||
*
|
*
|
||||||
* Multiple packets may be queued, also using this singly linked list.
|
* Multiple packets may be queued, also using this singly linked list.
|
||||||
* This is called a "packet queue". So, a packet queue consists of one
|
* This is called a "packet queue".
|
||||||
* or more pbuf chains, each of which consist of one or more pbufs.
|
*
|
||||||
|
* So, a packet queue consists of one or more pbuf chains, each of
|
||||||
|
* which consist of one or more pbufs. Currently, queues are only
|
||||||
|
* supported in a limited section of lwIP, this is the etharp queueing
|
||||||
|
* code. Outside of this section no packet queues are supported yet.
|
||||||
|
*
|
||||||
* The differences between a pbuf chain and a packet queue are very
|
* The differences between a pbuf chain and a packet queue are very
|
||||||
* subtle. Currently, queues are only supported in a limited section
|
* precise but subtle.
|
||||||
* of lwIP, this is the etharp queueing code. Outside of this section
|
|
||||||
* no packet queues are supported as of yet.
|
|
||||||
*
|
*
|
||||||
* The last pbuf of a packet has a ->tot_len field that equals the
|
* The last pbuf of a packet has a ->tot_len field that equals the
|
||||||
* ->len field. It can be found by traversing the list. If the last
|
* ->len field. It can be found by traversing the list. If the last
|
||||||
@@ -28,7 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -59,20 +62,18 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/memp.h"
|
#include "lwip/memp.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
|
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
#include "arch/perf.h"
|
#include "arch/perf.h"
|
||||||
|
|
||||||
static u8_t pbuf_pool_memory[(PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf)))];
|
static u8_t pbuf_pool_memory[MEM_ALIGNMENT - 1 + PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf))];
|
||||||
|
|
||||||
#if !SYS_LIGHTWEIGHT_PROT
|
#if !SYS_LIGHTWEIGHT_PROT
|
||||||
static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
|
static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
|
||||||
@@ -99,8 +100,7 @@ pbuf_init(void)
|
|||||||
struct pbuf *p, *q = NULL;
|
struct pbuf *p, *q = NULL;
|
||||||
u16_t i;
|
u16_t i;
|
||||||
|
|
||||||
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
|
pbuf_pool = (struct pbuf *)MEM_ALIGN(pbuf_pool_memory);
|
||||||
LWIP_ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0);
|
|
||||||
|
|
||||||
#if PBUF_STATS
|
#if PBUF_STATS
|
||||||
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
|
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
|
||||||
@@ -180,7 +180,7 @@ pbuf_pool_alloc(void)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates a pbuf.
|
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
|
||||||
*
|
*
|
||||||
* The actual memory allocated for the pbuf is determined by the
|
* The actual memory allocated for the pbuf is determined by the
|
||||||
* layer at which the pbuf is allocated and the requested size
|
* layer at which the pbuf is allocated and the requested size
|
||||||
@@ -214,7 +214,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
|||||||
struct pbuf *p, *q, *r;
|
struct pbuf *p, *q, *r;
|
||||||
u16_t offset;
|
u16_t offset;
|
||||||
s32_t rem_len; /* remaining length */
|
s32_t rem_len; /* remaining length */
|
||||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u)\n", length));
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F")\n", length));
|
||||||
|
|
||||||
/* determine header offset */
|
/* determine header offset */
|
||||||
offset = 0;
|
offset = 0;
|
||||||
@@ -254,7 +254,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
|||||||
/* make the payload pointer point 'offset' bytes into pbuf data memory */
|
/* make the payload pointer point 'offset' bytes into pbuf data memory */
|
||||||
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
|
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
|
||||||
LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
|
LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
|
||||||
((u32_t)p->payload % MEM_ALIGNMENT) == 0);
|
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
|
||||||
/* the total length of the pbuf chain is the requested size */
|
/* the total length of the pbuf chain is the requested size */
|
||||||
p->tot_len = length;
|
p->tot_len = length;
|
||||||
/* set the length of the first pbuf in the chain */
|
/* set the length of the first pbuf in the chain */
|
||||||
@@ -290,7 +290,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
|||||||
q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
|
q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
|
||||||
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
|
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
|
||||||
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
|
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
|
||||||
((u32_t)q->payload % MEM_ALIGNMENT) == 0);
|
((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
|
||||||
q->ref = 1;
|
q->ref = 1;
|
||||||
/* calculate remaining length to be allocated */
|
/* calculate remaining length to be allocated */
|
||||||
rem_len -= q->len;
|
rem_len -= q->len;
|
||||||
@@ -303,7 +303,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
|||||||
break;
|
break;
|
||||||
case PBUF_RAM:
|
case PBUF_RAM:
|
||||||
/* If pbuf is to be allocated in RAM, allocate memory for it. */
|
/* If pbuf is to be allocated in RAM, allocate memory for it. */
|
||||||
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + length + offset));
|
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + offset) + MEM_ALIGN_SIZE(length));
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -314,9 +314,9 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
|||||||
p->flags = PBUF_FLAG_RAM;
|
p->flags = PBUF_FLAG_RAM;
|
||||||
|
|
||||||
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
|
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
|
||||||
((u32_t)p->payload % MEM_ALIGNMENT) == 0);
|
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
|
||||||
break;
|
break;
|
||||||
/* pbuf references existing (static constant) ROM payload? */
|
/* pbuf references existing (non-volatile static constant) ROM payload? */
|
||||||
case PBUF_ROM:
|
case PBUF_ROM:
|
||||||
/* pbuf references existing (externally allocated) RAM payload? */
|
/* pbuf references existing (externally allocated) RAM payload? */
|
||||||
case PBUF_REF:
|
case PBUF_REF:
|
||||||
@@ -338,7 +338,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
|||||||
}
|
}
|
||||||
/* set reference count */
|
/* set reference count */
|
||||||
p->ref = 1;
|
p->ref = 1;
|
||||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u) == %p\n", length, (void *)p));
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,76 +450,82 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
|
|||||||
*
|
*
|
||||||
* The ->payload, ->tot_len and ->len fields are adjusted.
|
* The ->payload, ->tot_len and ->len fields are adjusted.
|
||||||
*
|
*
|
||||||
* @param hdr_size Number of bytes to increment header size which
|
* @param hdr_size_inc Number of bytes to increment header size which
|
||||||
* increases the size of the pbuf. New space is on the front.
|
* increases the size of the pbuf. New space is on the front.
|
||||||
* (Using a negative value decreases the header size.)
|
* (Using a negative value decreases the header size.)
|
||||||
|
* If hdr_size_inc is 0, this function does nothing and returns succesful.
|
||||||
*
|
*
|
||||||
* PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
|
* PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
|
||||||
* the call will fail. A check is made that the increase in header size does
|
* the call will fail. A check is made that the increase in header size does
|
||||||
* not move the payload pointer in front of the start of the buffer.
|
* not move the payload pointer in front of the start of the buffer.
|
||||||
* @return 1 on failure, 0 on success.
|
* @return non-zero on failure, zero on success.
|
||||||
*
|
*
|
||||||
* @note May not be called on a packet queue.
|
|
||||||
*/
|
*/
|
||||||
u8_t
|
u8_t
|
||||||
pbuf_header(struct pbuf *p, s16_t header_size)
|
pbuf_header(struct pbuf *p, s16_t header_size_increment)
|
||||||
{
|
{
|
||||||
void *payload;
|
void *payload;
|
||||||
|
|
||||||
|
LWIP_ASSERT("p != NULL", p != NULL);
|
||||||
|
if ((header_size_increment == 0) || (p == NULL)) return 0;
|
||||||
|
|
||||||
/* remember current payload pointer */
|
/* remember current payload pointer */
|
||||||
payload = p->payload;
|
payload = p->payload;
|
||||||
|
|
||||||
/* pbuf types containing payloads? */
|
/* pbuf types containing payloads? */
|
||||||
if (p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL) {
|
if (p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL) {
|
||||||
/* set new payload pointer */
|
/* set new payload pointer */
|
||||||
p->payload = (u8_t *)p->payload - header_size;
|
p->payload = (u8_t *)p->payload - header_size_increment;
|
||||||
/* boundary check fails? */
|
/* boundary check fails? */
|
||||||
if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
|
if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
|
||||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p\n",
|
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
|
||||||
(u8_t *)p->payload,
|
(void *)p->payload,
|
||||||
(u8_t *)p + sizeof(struct pbuf)) );\
|
(void *)(p + 1)));\
|
||||||
/* restore old payload pointer */
|
/* restore old payload pointer */
|
||||||
p->payload = payload;
|
p->payload = payload;
|
||||||
/* bail out unsuccesfully */
|
/* bail out unsuccesfully */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* pbuf types refering to payloads? */
|
/* pbuf types refering to external payloads? */
|
||||||
} else if (p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_ROM) {
|
} else if (p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_ROM) {
|
||||||
/* hide a header in the payload? */
|
/* hide a header in the payload? */
|
||||||
if ((header_size < 0) && (header_size - p->len <= 0)) {
|
if ((header_size_increment < 0) && (header_size_increment - p->len <= 0)) {
|
||||||
/* increase payload pointer */
|
/* increase payload pointer */
|
||||||
p->payload = (u8_t *)p->payload - header_size;
|
p->payload = (u8_t *)p->payload - header_size_increment;
|
||||||
} else {
|
} else {
|
||||||
/* cannot expand payload to front (yet!)
|
/* cannot expand payload to front (yet!)
|
||||||
* bail out unsuccesfully */
|
* bail out unsuccesfully */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", (void *)payload, (void *)p->payload, header_size) );
|
|
||||||
/* modify pbuf length fields */
|
/* modify pbuf length fields */
|
||||||
p->len += header_size;
|
p->len += header_size_increment;
|
||||||
p->tot_len += header_size;
|
p->tot_len += header_size_increment;
|
||||||
|
|
||||||
|
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%"S16_F")\n",
|
||||||
|
(void *)payload, (void *)p->payload, header_size_increment));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dereference a pbuf (chain) and deallocate any no-longer-used
|
* Dereference a pbuf chain or queue and deallocate any no-longer-used
|
||||||
* pbufs at the head of this chain.
|
* pbufs at the head of this chain or queue.
|
||||||
*
|
*
|
||||||
* Decrements the pbuf reference count. If it reaches
|
* Decrements the pbuf reference count. If it reaches zero, the pbuf is
|
||||||
* zero, the pbuf is deallocated.
|
* deallocated.
|
||||||
*
|
*
|
||||||
* For a pbuf chain, this is repeated for each pbuf in the chain,
|
* For a pbuf chain, this is repeated for each pbuf in the chain,
|
||||||
* up to a pbuf which has a non-zero reference count after
|
* up to the first pbuf which has a non-zero reference count after
|
||||||
* decrementing. (This might de-allocate the whole chain.)
|
* decrementing. So, when all reference counts are one, the whole
|
||||||
|
* chain is free'd.
|
||||||
*
|
*
|
||||||
* @param pbuf The pbuf (chain) to be dereferenced.
|
* @param pbuf The pbuf (chain) to be dereferenced.
|
||||||
*
|
*
|
||||||
* @return the number of pbufs that were de-allocated
|
* @return the number of pbufs that were de-allocated
|
||||||
* from the head of the chain.
|
* from the head of the chain.
|
||||||
*
|
*
|
||||||
* @note MUST NOT be called on a packet queue.
|
* @note MUST NOT be called on a packet queue (Not verified to work yet).
|
||||||
* @note the reference counter of a pbuf equals the number of pointers
|
* @note the reference counter of a pbuf equals the number of pointers
|
||||||
* that refer to the pbuf (or into the pbuf).
|
* that refer to the pbuf (or into the pbuf).
|
||||||
*
|
*
|
||||||
@@ -542,6 +548,8 @@ pbuf_free(struct pbuf *p)
|
|||||||
u8_t count;
|
u8_t count;
|
||||||
SYS_ARCH_DECL_PROTECT(old_level);
|
SYS_ARCH_DECL_PROTECT(old_level);
|
||||||
|
|
||||||
|
LWIP_ASSERT("p != NULL", p != NULL);
|
||||||
|
/* if assertions are disabled, proceed with debug output */
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
|
||||||
return 0;
|
return 0;
|
||||||
@@ -576,7 +584,7 @@ pbuf_free(struct pbuf *p)
|
|||||||
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
|
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
|
||||||
p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
|
p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
|
||||||
PBUF_POOL_FREE(p);
|
PBUF_POOL_FREE(p);
|
||||||
/* a ROM or RAM referencing pbuf */
|
/* is this a ROM or RAM referencing pbuf? */
|
||||||
} else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
|
} else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
|
||||||
memp_free(MEMP_PBUF, p);
|
memp_free(MEMP_PBUF, p);
|
||||||
/* p->flags == PBUF_FLAG_RAM */
|
/* p->flags == PBUF_FLAG_RAM */
|
||||||
@@ -589,8 +597,8 @@ pbuf_free(struct pbuf *p)
|
|||||||
/* p->ref > 0, this pbuf is still referenced to */
|
/* p->ref > 0, this pbuf is still referenced to */
|
||||||
/* (and so the remaining pbufs in chain as well) */
|
/* (and so the remaining pbufs in chain as well) */
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, (unsigned int)p->ref));
|
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, (u16_t)p->ref));
|
||||||
/* stop walking through chain */
|
/* stop walking through the chain */
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -653,8 +661,8 @@ pbuf_cat(struct pbuf *h, struct pbuf *t)
|
|||||||
{
|
{
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
|
|
||||||
LWIP_ASSERT("h != NULL", h != NULL);
|
LWIP_ASSERT("h != NULL (programmer violates API)", h != NULL);
|
||||||
LWIP_ASSERT("t != NULL", t != NULL);
|
LWIP_ASSERT("t != NULL (programmer violates API)", t != NULL);
|
||||||
if ((h == NULL) || (t == NULL)) return;
|
if ((h == NULL) || (t == NULL)) return;
|
||||||
|
|
||||||
/* proceed to last pbuf of chain */
|
/* proceed to last pbuf of chain */
|
||||||
@@ -664,10 +672,14 @@ pbuf_cat(struct pbuf *h, struct pbuf *t)
|
|||||||
}
|
}
|
||||||
/* { p is last pbuf of first h chain, p->next == NULL } */
|
/* { p is last pbuf of first h chain, p->next == NULL } */
|
||||||
LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
|
LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
|
||||||
|
LWIP_ASSERT("p->next == NULL", p->next == NULL);
|
||||||
/* add total length of second chain to last pbuf total of first chain */
|
/* add total length of second chain to last pbuf total of first chain */
|
||||||
p->tot_len += t->tot_len;
|
p->tot_len += t->tot_len;
|
||||||
/* chain last pbuf of head (p) with first of tail (t) */
|
/* chain last pbuf of head (p) with first of tail (t) */
|
||||||
p->next = t;
|
p->next = t;
|
||||||
|
/* p->next now references t, but the caller will drop its reference to t,
|
||||||
|
* so netto there is no change to the reference count of t.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -695,8 +707,8 @@ pbuf_chain(struct pbuf *h, struct pbuf *t)
|
|||||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For packet queueing. Note that queued packets must be dequeued first
|
/* For packet queueing. Note that queued packets MUST be dequeued first
|
||||||
* before calling any pbuf functions. */
|
* using pbuf_dequeue() before calling other pbuf_() functions. */
|
||||||
#if ARP_QUEUEING
|
#if ARP_QUEUEING
|
||||||
/**
|
/**
|
||||||
* Add a packet to the end of a queue.
|
* Add a packet to the end of a queue.
|
||||||
@@ -704,15 +716,22 @@ pbuf_chain(struct pbuf *h, struct pbuf *t)
|
|||||||
* @param q pointer to first packet on the queue
|
* @param q pointer to first packet on the queue
|
||||||
* @param n packet to be queued
|
* @param n packet to be queued
|
||||||
*
|
*
|
||||||
|
* Both packets MUST be given, and must be different.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
pbuf_queue(struct pbuf *p, struct pbuf *n)
|
pbuf_queue(struct pbuf *p, struct pbuf *n)
|
||||||
{
|
{
|
||||||
LWIP_ASSERT("p != NULL", p != NULL);
|
#if PBUF_DEBUG /* remember head of queue */
|
||||||
LWIP_ASSERT("n != NULL", n != NULL);
|
struct pbuf *q = p;
|
||||||
|
#endif
|
||||||
if ((p == NULL) || (n == NULL))
|
/* programmer stupidity checks */
|
||||||
|
LWIP_ASSERT("p == NULL in pbuf_queue: this indicates a programmer error\n", p != NULL);
|
||||||
|
LWIP_ASSERT("n == NULL in pbuf_queue: this indicates a programmer error\n", n != NULL);
|
||||||
|
LWIP_ASSERT("p == n in pbuf_queue: this indicates a programmer error\n", p != n);
|
||||||
|
if ((p == NULL) || (n == NULL) || (p == n)){
|
||||||
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_HALT | 3, ("pbuf_queue: programmer argument error\n"));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* iterate through all packets on queue */
|
/* iterate through all packets on queue */
|
||||||
while (p->next != NULL) {
|
while (p->next != NULL) {
|
||||||
@@ -720,25 +739,39 @@ pbuf_queue(struct pbuf *p, struct pbuf *n)
|
|||||||
#if PBUF_DEBUG
|
#if PBUF_DEBUG
|
||||||
/* iterate through all pbufs in packet */
|
/* iterate through all pbufs in packet */
|
||||||
while (p->tot_len != p->len) {
|
while (p->tot_len != p->len) {
|
||||||
|
/* make sure invariant condition holds */
|
||||||
|
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
|
||||||
/* make sure each packet is complete */
|
/* make sure each packet is complete */
|
||||||
LWIP_ASSERT("p->next != NULL", p->next != NULL);
|
LWIP_ASSERT("p->next != NULL", p->next != NULL);
|
||||||
p = p->next;
|
p = p->next;
|
||||||
|
/* { p->tot_len == p->len => p is last pbuf of a packet } */
|
||||||
}
|
}
|
||||||
#endif
|
/* { p is last pbuf of a packet } */
|
||||||
/* now p->tot_len == p->len */
|
|
||||||
/* proceed to next packet on queue */
|
/* proceed to next packet on queue */
|
||||||
p = p->next;
|
#endif
|
||||||
|
/* proceed to next pbuf */
|
||||||
|
if (p->next != NULL) p = p->next;
|
||||||
}
|
}
|
||||||
|
/* { p->tot_len == p->len and p->next == NULL } ==>
|
||||||
|
* { p is last pbuf of last packet on queue } */
|
||||||
/* chain last pbuf of queue with n */
|
/* chain last pbuf of queue with n */
|
||||||
p->next = n;
|
p->next = n;
|
||||||
/* n is now referenced to one more time */
|
/* n is now referenced to by the (packet p in the) queue */
|
||||||
pbuf_ref(n);
|
pbuf_ref(n);
|
||||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_queue: referencing queued packet %p\n", (void *)n));
|
#if PBUF_DEBUG
|
||||||
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2,
|
||||||
|
("pbuf_queue: newly queued packet %p sits after packet %p in queue %p\n",
|
||||||
|
(void *)n, (void *)p, (void *)q));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a packet from the head of a queue.
|
* Remove a packet from the head of a queue.
|
||||||
*
|
*
|
||||||
|
* The caller MUST reference the remainder of the queue (as returned). The
|
||||||
|
* caller MUST NOT call pbuf_ref() as it implicitly takes over the reference
|
||||||
|
* from p.
|
||||||
|
*
|
||||||
* @param p pointer to first packet on the queue which will be dequeued.
|
* @param p pointer to first packet on the queue which will be dequeued.
|
||||||
* @return first packet on the remaining queue (NULL if no further packets).
|
* @return first packet on the remaining queue (NULL if no further packets).
|
||||||
*
|
*
|
||||||
@@ -749,19 +782,28 @@ pbuf_dequeue(struct pbuf *p)
|
|||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
LWIP_ASSERT("p != NULL", p != NULL);
|
LWIP_ASSERT("p != NULL", p != NULL);
|
||||||
|
|
||||||
/* iterate through all pbufs in packet */
|
/* iterate through all pbufs in packet p */
|
||||||
while (p->tot_len != p->len) {
|
while (p->tot_len != p->len) {
|
||||||
|
/* make sure invariant condition holds */
|
||||||
|
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
|
||||||
/* make sure each packet is complete */
|
/* make sure each packet is complete */
|
||||||
LWIP_ASSERT("p->next != NULL", p->next != NULL);
|
LWIP_ASSERT("p->next != NULL", p->next != NULL);
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
/* remember next packet on queue */
|
/* { p->tot_len == p->len } => p is the last pbuf of the first packet */
|
||||||
|
/* remember next packet on queue in q */
|
||||||
q = p->next;
|
q = p->next;
|
||||||
/* dequeue p from queue */
|
/* dequeue packet p from queue */
|
||||||
p->next = NULL;
|
p->next = NULL;
|
||||||
/* q is now referenced to one less time */
|
/* any next packet on queue? */
|
||||||
pbuf_free(q);
|
if (q != NULL) {
|
||||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: dereferencing remaining queue %p\n", (void *)q));
|
/* although q is no longer referenced by p, it MUST be referenced by
|
||||||
|
* the caller, who is maintaining this packet queue. So, we do not call
|
||||||
|
* pbuf_free(q) here, resulting in an implicit pbuf_ref(q) for the caller. */
|
||||||
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: first remaining packet on queue is %p\n", (void *)q));
|
||||||
|
} else {
|
||||||
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: no further packets on queue\n"));
|
||||||
|
}
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -779,7 +821,7 @@ pbuf_dequeue(struct pbuf *p)
|
|||||||
*
|
*
|
||||||
* @note You MUST explicitly use p = pbuf_take(p);
|
* @note You MUST explicitly use p = pbuf_take(p);
|
||||||
* The pbuf you give as argument, may have been replaced
|
* The pbuf you give as argument, may have been replaced
|
||||||
* by pbuf_take()!
|
* by a (differently located) copy through pbuf_take()!
|
||||||
*
|
*
|
||||||
* @note Any replaced pbufs will be freed through pbuf_free().
|
* @note Any replaced pbufs will be freed through pbuf_free().
|
||||||
* This may deallocate them if they become no longer referenced.
|
* This may deallocate them if they become no longer referenced.
|
||||||
@@ -807,7 +849,9 @@ pbuf_take(struct pbuf *p)
|
|||||||
/* PBUF_POOL buffers are faster if we can use them */
|
/* PBUF_POOL buffers are faster if we can use them */
|
||||||
if (p->len <= PBUF_POOL_BUFSIZE) {
|
if (p->len <= PBUF_POOL_BUFSIZE) {
|
||||||
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
|
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
|
||||||
if (q == NULL) LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
|
if (q == NULL) {
|
||||||
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* no replacement pbuf yet */
|
/* no replacement pbuf yet */
|
||||||
q = NULL;
|
q = NULL;
|
||||||
@@ -816,7 +860,9 @@ pbuf_take(struct pbuf *p)
|
|||||||
/* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
|
/* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
|
||||||
if (q == NULL) {
|
if (q == NULL) {
|
||||||
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);
|
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);
|
||||||
if (q == NULL) LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));
|
if (q == NULL) {
|
||||||
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* replacement pbuf could be allocated? */
|
/* replacement pbuf could be allocated? */
|
||||||
if (q != NULL)
|
if (q != NULL)
|
||||||
@@ -899,8 +945,10 @@ pbuf_dechain(struct pbuf *p)
|
|||||||
/* q is no longer referenced by p, free it */
|
/* q is no longer referenced by p, free it */
|
||||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
|
||||||
tail_gone = pbuf_free(q);
|
tail_gone = pbuf_free(q);
|
||||||
if (tail_gone > 0) LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
|
if (tail_gone > 0) {
|
||||||
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
|
||||||
|
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
|
||||||
|
}
|
||||||
/* return remaining tail or NULL if deallocated */
|
/* return remaining tail or NULL if deallocated */
|
||||||
}
|
}
|
||||||
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
|
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
|
||||||
|
|||||||
120
src/core/raw.c
120
src/core/raw.c
@@ -1,10 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Raw Access module
|
*
|
||||||
|
* Implementation of raw protocol PCBs for low-level handling of
|
||||||
|
* different types of protocols besides (or overriding) those
|
||||||
|
* already available in lwIP.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -35,20 +38,15 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
/* raw.c
|
|
||||||
*
|
|
||||||
* The code for the Raw Access to the IP
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/memp.h"
|
#include "lwip/memp.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/netif.h"
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
#include "lwip/raw.h"
|
#include "lwip/raw.h"
|
||||||
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
@@ -57,11 +55,10 @@
|
|||||||
#include "lwip/snmp.h"
|
#include "lwip/snmp.h"
|
||||||
|
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
/* The list of RAW PCBs */
|
|
||||||
|
|
||||||
|
/** The list of RAW PCBs */
|
||||||
static struct raw_pcb *raw_pcbs = NULL;
|
static struct raw_pcb *raw_pcbs = NULL;
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
raw_init(void)
|
raw_init(void)
|
||||||
{
|
{
|
||||||
@@ -69,42 +66,54 @@ raw_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if in incoming IP packet is covered by a RAW pcb and
|
* Determine if in incoming IP packet is covered by a RAW PCB
|
||||||
* and process it if possible
|
* and if so, pass it to a user-provided receive callback function.
|
||||||
*
|
*
|
||||||
* Given an incoming IP datagram (as a chain of pbufs) this function
|
* Given an incoming IP datagram (as a chain of pbufs) this function
|
||||||
* finds a corresponding RAW PCB and
|
* finds a corresponding RAW PCB and calls the corresponding receive
|
||||||
|
* callback function.
|
||||||
*
|
*
|
||||||
* @param pbuf pbuf to be demultiplexed to a RAW PCB.
|
* @param pbuf pbuf to be demultiplexed to a RAW PCB.
|
||||||
* @param netif network interface on which the datagram was received.
|
* @param netif network interface on which the datagram was received.
|
||||||
* @return 0 if packet is not eated (pbuf needs to be freed then)
|
* @Return - 1 if the packet has been eaten by a RAW PCB receive
|
||||||
* or 1 if the packet has been eaten (pbuf needs not to be freed
|
* callback function. The caller MAY NOT not reference the
|
||||||
* then)
|
* packet any longer, and MAY NOT call pbuf_free().
|
||||||
|
* @return - 0 if packet is not eaten (pbuf is still referenced by the
|
||||||
|
* caller).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int
|
u8_t
|
||||||
raw_input(struct pbuf *p, struct netif *inp)
|
raw_input(struct pbuf *p, struct netif *inp)
|
||||||
{
|
{
|
||||||
struct raw_pcb *pcb;
|
struct raw_pcb *pcb;
|
||||||
struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
int proto;
|
s16_t proto;
|
||||||
int rc = 0;
|
u8_t eaten = 0;
|
||||||
|
|
||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
proto = IPH_PROTO(iphdr);
|
proto = IPH_PROTO(iphdr);
|
||||||
|
|
||||||
for(pcb = raw_pcbs; pcb != NULL; pcb = pcb->next) {
|
pcb = raw_pcbs;
|
||||||
|
/* loop through all raw pcbs until the packet is eaten by one */
|
||||||
|
/* this allows multiple pcbs to match against the packet by design */
|
||||||
|
while ((eaten == 0) && (pcb != NULL)) {
|
||||||
if (pcb->protocol == proto) {
|
if (pcb->protocol == proto) {
|
||||||
if (pcb->recv) {
|
/* receive callback function available? */
|
||||||
if (!pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)))
|
if (pcb->recv != NULL) {
|
||||||
return 0;
|
/* the receive callback function did not eat the packet? */
|
||||||
|
if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0)
|
||||||
|
{
|
||||||
|
/* receive function ate the packet */
|
||||||
|
p = NULL;
|
||||||
|
eaten = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pbuf_free(p);
|
/* no receive callback function was set for this raw PCB */
|
||||||
rc = 1;
|
/* drop the packet */
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
pcb = pcb->next;
|
||||||
}
|
}
|
||||||
return rc;
|
return eaten;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -116,7 +125,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
|||||||
*
|
*
|
||||||
* @return lwIP error code.
|
* @return lwIP error code.
|
||||||
* - ERR_OK. Successful. No error occured.
|
* - ERR_OK. Successful. No error occured.
|
||||||
* - ERR_USE. The specified ipaddr is already bound to by
|
* - ERR_USE. The specified IP address is already bound to by
|
||||||
* another RAW PCB.
|
* another RAW PCB.
|
||||||
*
|
*
|
||||||
* @see raw_disconnect()
|
* @see raw_disconnect()
|
||||||
@@ -130,7 +139,7 @@ raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect an RAW PCB. This function is required by upper layers
|
* Connect an RAW PCB. This function is required by upper layers
|
||||||
* of lwip. Using the raw api you could use raw_send_to() instead
|
* of lwip. Using the raw api you could use raw_sendto() instead
|
||||||
*
|
*
|
||||||
* This will associate the RAW PCB with the remote address.
|
* This will associate the RAW PCB with the remote address.
|
||||||
*
|
*
|
||||||
@@ -139,7 +148,7 @@ raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
|||||||
*
|
*
|
||||||
* @return lwIP error code
|
* @return lwIP error code
|
||||||
*
|
*
|
||||||
* @see raw_disconnect() and raw_send_to()
|
* @see raw_disconnect() and raw_sendto()
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
||||||
@@ -150,14 +159,21 @@ raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the callback function if a RAW packet with the pcb's protocol
|
* Set the callback function for received packets that match the
|
||||||
* is received. If the callback function returns a value unequal 0
|
* raw PCB's protocol and binding.
|
||||||
* the raw packet is "eaten" and not forwarded to any other raw pcb
|
*
|
||||||
* including lwip itself
|
* The callback function MUST either
|
||||||
|
* - eat the packet by calling pbuf_free() and returning non-zero. The
|
||||||
|
* packet will not be passed to other raw PCBs or other protocol layers.
|
||||||
|
* - not free the packet, and return zero. The packet will be matched
|
||||||
|
* against further PCBs and/or forwarded to another protocol layers.
|
||||||
|
*
|
||||||
|
* @return non-zero if the packet was free()d, zero if the packet remains
|
||||||
|
* available for others.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
raw_recv(struct raw_pcb *pcb,
|
raw_recv(struct raw_pcb *pcb,
|
||||||
int (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
|
u8_t (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
|
||||||
struct ip_addr *addr),
|
struct ip_addr *addr),
|
||||||
void *recv_arg)
|
void *recv_arg)
|
||||||
{
|
{
|
||||||
@@ -168,25 +184,25 @@ raw_recv(struct raw_pcb *pcb,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the raw IP packet to the given address. Note that actually you cannot
|
* Send the raw IP packet to the given address. Note that actually you cannot
|
||||||
* modify the IP headers (this is inconsitent with the receive callback where
|
* modify the IP headers (this is inconsistent with the receive callback where
|
||||||
* you actually get the IP headers), you can only specifiy the ip payload here.
|
* you actually get the IP headers), you can only specify the IP payload here.
|
||||||
* It requires some more changes in LWIP. (there will be a raw_send() function
|
* It requires some more changes in lwIP. (there will be a raw_send() function
|
||||||
* then)
|
* then.)
|
||||||
*
|
*
|
||||||
* @param pcb the raw pcb which to send
|
* @param pcb the raw pcb which to send
|
||||||
* @param p the ip payload to send
|
* @param p the IP payload to send
|
||||||
* @param ipaddr the destination address of the whole IP packet
|
* @param ipaddr the destination address of the IP packet
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||||
{
|
{
|
||||||
err_t err;
|
err_t err;
|
||||||
struct netif *netif;
|
struct netif *netif;
|
||||||
struct ip_addr *src_ip;
|
struct ip_addr *src_ip;
|
||||||
struct pbuf *q; /* q will be sent down the stack */
|
struct pbuf *q; /* q will be sent down the stack */
|
||||||
|
|
||||||
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_send_to\n"));
|
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_sendto\n"));
|
||||||
|
|
||||||
/* not enough space to add an IP header to first pbuf in given p chain? */
|
/* not enough space to add an IP header to first pbuf in given p chain? */
|
||||||
if (pbuf_header(p, IP_HLEN)) {
|
if (pbuf_header(p, IP_HLEN)) {
|
||||||
@@ -194,13 +210,13 @@ raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
|||||||
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
|
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
|
||||||
/* new header pbuf could not be allocated? */
|
/* new header pbuf could not be allocated? */
|
||||||
if (q == NULL) {
|
if (q == NULL) {
|
||||||
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_send_to: could not allocate header\n"));
|
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_sendto: could not allocate header\n"));
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
/* chain header q in front of given pbuf p */
|
/* chain header q in front of given pbuf p */
|
||||||
pbuf_chain(q, p);
|
pbuf_chain(q, p);
|
||||||
/* { first pbuf q points to header pbuf } */
|
/* { first pbuf q points to header pbuf } */
|
||||||
LWIP_DEBUGF(RAW_DEBUG, ("raw_send_to: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||||
} else {
|
} else {
|
||||||
/* first pbuf q equals given pbuf */
|
/* first pbuf q equals given pbuf */
|
||||||
q = p;
|
q = p;
|
||||||
@@ -208,10 +224,11 @@ raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((netif = ip_route(ipaddr)) == NULL) {
|
if ((netif = ip_route(ipaddr)) == NULL) {
|
||||||
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_send_to: No route to 0x%lx\n", ipaddr->addr));
|
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
|
||||||
#if RAW_STATS
|
#if RAW_STATS
|
||||||
/* ++lwip_stats.raw.rterr;*/
|
/* ++lwip_stats.raw.rterr;*/
|
||||||
#endif /* RAW_STATS */
|
#endif /* RAW_STATS */
|
||||||
|
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||||
if (q != p) {
|
if (q != p) {
|
||||||
pbuf_free(q);
|
pbuf_free(q);
|
||||||
}
|
}
|
||||||
@@ -240,14 +257,14 @@ raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
|||||||
* Send the raw IP packet to the address given by raw_connect()
|
* Send the raw IP packet to the address given by raw_connect()
|
||||||
*
|
*
|
||||||
* @param pcb the raw pcb which to send
|
* @param pcb the raw pcb which to send
|
||||||
* @param p the ip payload to send
|
* @param p the IP payload to send
|
||||||
* @param ipaddr the destination address of the whole IP packet
|
* @param ipaddr the destination address of the IP packet
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
raw_send(struct raw_pcb *pcb, struct pbuf *p)
|
raw_send(struct raw_pcb *pcb, struct pbuf *p)
|
||||||
{
|
{
|
||||||
return raw_send_to(pcb,p,&pcb->remote_ip);
|
return raw_sendto(pcb, p, &pcb->remote_ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -266,7 +283,7 @@ raw_remove(struct raw_pcb *pcb)
|
|||||||
if (raw_pcbs == pcb) {
|
if (raw_pcbs == pcb) {
|
||||||
/* make list start at 2nd pcb */
|
/* make list start at 2nd pcb */
|
||||||
raw_pcbs = raw_pcbs->next;
|
raw_pcbs = raw_pcbs->next;
|
||||||
/* pcb not 1st in list */
|
/* pcb not 1st in list */
|
||||||
} else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
|
} else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
|
||||||
/* find pcb in raw_pcbs list */
|
/* find pcb in raw_pcbs list */
|
||||||
if (pcb2->next != NULL && pcb2->next == pcb) {
|
if (pcb2->next != NULL && pcb2->next == pcb) {
|
||||||
@@ -303,7 +320,6 @@ raw_new(u16_t proto) {
|
|||||||
pcb->next = raw_pcbs;
|
pcb->next = raw_pcbs;
|
||||||
raw_pcbs = pcb;
|
raw_pcbs = pcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pcb;
|
return pcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
@@ -47,5 +48,68 @@ stats_init(void)
|
|||||||
{
|
{
|
||||||
memset(&lwip_stats, 0, sizeof(struct stats_));
|
memset(&lwip_stats, 0, sizeof(struct stats_));
|
||||||
}
|
}
|
||||||
|
#if LWIP_STATS_DISPLAY
|
||||||
|
void
|
||||||
|
stats_display_proto(struct stats_proto *proto, char *name)
|
||||||
|
{
|
||||||
|
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
||||||
|
LWIP_PLATFORM_DIAG(("xmit: %"S16_F"\n\t", proto->xmit));
|
||||||
|
LWIP_PLATFORM_DIAG(("rexmit: %"S16_F"\n\t", proto->rexmit));
|
||||||
|
LWIP_PLATFORM_DIAG(("recv: %"S16_F"\n\t", proto->recv));
|
||||||
|
LWIP_PLATFORM_DIAG(("fw: %"S16_F"\n\t", proto->fw));
|
||||||
|
LWIP_PLATFORM_DIAG(("drop: %"S16_F"\n\t", proto->drop));
|
||||||
|
LWIP_PLATFORM_DIAG(("chkerr: %"S16_F"\n\t", proto->chkerr));
|
||||||
|
LWIP_PLATFORM_DIAG(("lenerr: %"S16_F"\n\t", proto->lenerr));
|
||||||
|
LWIP_PLATFORM_DIAG(("memerr: %"S16_F"\n\t", proto->memerr));
|
||||||
|
LWIP_PLATFORM_DIAG(("rterr: %"S16_F"\n\t", proto->rterr));
|
||||||
|
LWIP_PLATFORM_DIAG(("proterr: %"S16_F"\n\t", proto->proterr));
|
||||||
|
LWIP_PLATFORM_DIAG(("opterr: %"S16_F"\n\t", proto->opterr));
|
||||||
|
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", proto->err));
|
||||||
|
LWIP_PLATFORM_DIAG(("cachehit: %"S16_F"\n", proto->cachehit));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
stats_display_pbuf(struct stats_pbuf *pbuf)
|
||||||
|
{
|
||||||
|
LWIP_PLATFORM_DIAG(("\nPBUF\n\t"));
|
||||||
|
LWIP_PLATFORM_DIAG(("avail: %"S16_F"\n\t", pbuf->avail));
|
||||||
|
LWIP_PLATFORM_DIAG(("used: %"S16_F"\n\t", pbuf->used));
|
||||||
|
LWIP_PLATFORM_DIAG(("max: %"S16_F"\n\t", pbuf->max));
|
||||||
|
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", pbuf->err));
|
||||||
|
LWIP_PLATFORM_DIAG(("alloc_locked: %"S16_F"\n\t", pbuf->alloc_locked));
|
||||||
|
LWIP_PLATFORM_DIAG(("refresh_locked: %"S16_F"\n", pbuf->refresh_locked));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
stats_display_mem(struct stats_mem *mem, char *name)
|
||||||
|
{
|
||||||
|
LWIP_PLATFORM_DIAG(("\n MEM %s\n\t", name));
|
||||||
|
LWIP_PLATFORM_DIAG(("avail: %"S16_F"\n\t", mem->avail));
|
||||||
|
LWIP_PLATFORM_DIAG(("used: %"S16_F"\n\t", mem->used));
|
||||||
|
LWIP_PLATFORM_DIAG(("max: %"S16_F"\n\t", mem->max));
|
||||||
|
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n", mem->err));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
stats_display(void)
|
||||||
|
{
|
||||||
|
s16_t i;
|
||||||
|
char * memp_names[] = {"PBUF", "RAW_PCB", "UDP_PCB", "TCP_PCB", "TCP_PCB_LISTEN",
|
||||||
|
"TCP_SEG", "NETBUF", "NETCONN", "API_MSG", "TCP_MSG", "TIMEOUT"};
|
||||||
|
stats_display_proto(&lwip_stats.link, "LINK");
|
||||||
|
stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG");
|
||||||
|
stats_display_proto(&lwip_stats.ip, "IP");
|
||||||
|
stats_display_proto(&lwip_stats.icmp, "ICMP");
|
||||||
|
stats_display_proto(&lwip_stats.udp, "UDP");
|
||||||
|
stats_display_proto(&lwip_stats.tcp, "TCP");
|
||||||
|
stats_display_pbuf(&lwip_stats.pbuf);
|
||||||
|
stats_display_mem(&lwip_stats.mem, "HEAP");
|
||||||
|
for (i = 0; i < MEMP_MAX; i++) {
|
||||||
|
stats_display_mem(&lwip_stats.memp[i], memp_names[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif /* LWIP_STATS_DISPLAY */
|
||||||
#endif /* LWIP_STATS */
|
#endif /* LWIP_STATS */
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
struct sswt_cb
|
struct sswt_cb
|
||||||
{
|
{
|
||||||
int timeflag;
|
s16_t timeflag;
|
||||||
sys_sem_t *psem;
|
sys_sem_t *psem;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -170,10 +170,11 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
|||||||
|
|
||||||
timeouts = sys_arch_timeouts();
|
timeouts = sys_arch_timeouts();
|
||||||
|
|
||||||
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%lu h=%p arg=%p\n",
|
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n",
|
||||||
(void *)timeout, msecs, (void *)h, (void *)arg));
|
(void *)timeout, msecs, (void *)h, (void *)arg));
|
||||||
|
|
||||||
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
|
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
|
||||||
|
|
||||||
if (timeouts->next == NULL) {
|
if (timeouts->next == NULL) {
|
||||||
timeouts->next = timeout;
|
timeouts->next = timeout;
|
||||||
return;
|
return;
|
||||||
@@ -186,14 +187,13 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
|||||||
} else {
|
} else {
|
||||||
for(t = timeouts->next; t != NULL; t = t->next) {
|
for(t = timeouts->next; t != NULL; t = t->next) {
|
||||||
timeout->time -= t->time;
|
timeout->time -= t->time;
|
||||||
if (t->next == NULL ||
|
if (t->next == NULL || t->next->time > timeout->time) {
|
||||||
t->next->time > timeout->time) {
|
if (t->next != NULL) {
|
||||||
if (t->next != NULL) {
|
t->next->time -= timeout->time;
|
||||||
t->next->time -= timeout->time;
|
}
|
||||||
}
|
timeout->next = t->next;
|
||||||
timeout->next = t->next;
|
t->next = timeout;
|
||||||
t->next = timeout;
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
351
src/core/tcp.c
351
src/core/tcp.c
@@ -2,10 +2,15 @@
|
|||||||
* @file
|
* @file
|
||||||
*
|
*
|
||||||
* Transmission Control Protocol for IP
|
* Transmission Control Protocol for IP
|
||||||
|
*
|
||||||
|
* This file contains common functions for the TCP implementation, such as functinos
|
||||||
|
* for manipulating the data structures and the TCP timer functions. TCP functions
|
||||||
|
* related to input and output is found in tcp_in.c and tcp_out.c respectively.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -36,16 +41,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
/* tcp.c
|
|
||||||
*
|
|
||||||
* This file contains common functions for the TCP implementation, such as functinos
|
|
||||||
* for manipulating the data structures and the TCP timer functions. TCP functions
|
|
||||||
* related to input and output is found in tcp_input.c and tcp_output.c respectively.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
@@ -62,30 +58,28 @@ const u8_t tcp_backoff[13] =
|
|||||||
{ 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
|
{ 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
|
||||||
|
|
||||||
/* The TCP PCB lists. */
|
/* The TCP PCB lists. */
|
||||||
struct tcp_pcb_listen *tcp_listen_pcbs; /* List of all TCP PCBs in LISTEN state. */
|
|
||||||
struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
|
/** List of all TCP PCBs in LISTEN state */
|
||||||
state in which they accept or send
|
union tcp_listen_pcbs_t tcp_listen_pcbs;
|
||||||
data. */
|
/** List of all TCP PCBs that are in a state in which
|
||||||
struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
|
* they accept or send data. */
|
||||||
|
struct tcp_pcb *tcp_active_pcbs;
|
||||||
|
/** List of all TCP PCBs in TIME-WAIT state */
|
||||||
|
struct tcp_pcb *tcp_tw_pcbs;
|
||||||
|
|
||||||
struct tcp_pcb *tcp_tmp_pcb;
|
struct tcp_pcb *tcp_tmp_pcb;
|
||||||
|
|
||||||
static u8_t tcp_timer;
|
static u8_t tcp_timer;
|
||||||
|
|
||||||
static u16_t tcp_new_port(void);
|
static u16_t tcp_new_port(void);
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* tcp_init():
|
|
||||||
*
|
|
||||||
* Initializes the TCP layer.
|
* Initializes the TCP layer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_init(void)
|
tcp_init(void)
|
||||||
{
|
{
|
||||||
/* Clear globals. */
|
/* Clear globals. */
|
||||||
tcp_listen_pcbs = NULL;
|
tcp_listen_pcbs.listen_pcbs = NULL;
|
||||||
tcp_active_pcbs = NULL;
|
tcp_active_pcbs = NULL;
|
||||||
tcp_tw_pcbs = NULL;
|
tcp_tw_pcbs = NULL;
|
||||||
tcp_tmp_pcb = NULL;
|
tcp_tmp_pcb = NULL;
|
||||||
@@ -96,13 +90,10 @@ tcp_init(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_tmr():
|
|
||||||
*
|
|
||||||
* Called periodically to dispatch TCP timers.
|
* Called periodically to dispatch TCP timers.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_tmr(void)
|
tcp_tmr(void)
|
||||||
{
|
{
|
||||||
@@ -116,13 +107,10 @@ tcp_tmr(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_close():
|
|
||||||
*
|
|
||||||
* Closes the connection held by the PCB.
|
* Closes the connection held by the PCB.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
err_t
|
err_t
|
||||||
tcp_close(struct tcp_pcb *pcb)
|
tcp_close(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
@@ -134,9 +122,21 @@ tcp_close(struct tcp_pcb *pcb)
|
|||||||
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||||
#endif /* TCP_DEBUG */
|
#endif /* TCP_DEBUG */
|
||||||
switch (pcb->state) {
|
switch (pcb->state) {
|
||||||
|
case CLOSED:
|
||||||
|
/* Closing a pcb in the CLOSED state might seem erroneous,
|
||||||
|
* however, it is in this state once allocated and as yet unused
|
||||||
|
* and the user needs some way to free it should the need arise.
|
||||||
|
* Calling tcp_close() with a pcb that has already been closed, (i.e. twice)
|
||||||
|
* 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;
|
||||||
|
memp_free(MEMP_TCP_PCB, pcb);
|
||||||
|
pcb = NULL;
|
||||||
|
break;
|
||||||
case LISTEN:
|
case LISTEN:
|
||||||
err = ERR_OK;
|
err = ERR_OK;
|
||||||
tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs, pcb);
|
tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb);
|
||||||
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
|
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
|
||||||
pcb = NULL;
|
pcb = NULL;
|
||||||
break;
|
break;
|
||||||
@@ -172,15 +172,12 @@ tcp_close(struct tcp_pcb *pcb)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_abort()
|
|
||||||
*
|
|
||||||
* Aborts a connection by sending a RST to the remote host and deletes
|
* Aborts a connection by sending a RST to the remote host and deletes
|
||||||
* the local protocol control block. This is done when a connection is
|
* the local protocol control block. This is done when a connection is
|
||||||
* killed because of shortage of memory.
|
* killed because of shortage of memory.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_abort(struct tcp_pcb *pcb)
|
tcp_abort(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
@@ -229,9 +226,7 @@ tcp_abort(struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_bind():
|
|
||||||
*
|
|
||||||
* Binds the connection to a local portnumber and IP address. If the
|
* Binds the connection to a local portnumber and IP address. If the
|
||||||
* IP address is not given (i.e., ipaddr == NULL), the IP address of
|
* IP address is not given (i.e., ipaddr == NULL), the IP address of
|
||||||
* the outgoing network interface is used instead.
|
* the outgoing network interface is used instead.
|
||||||
@@ -242,16 +237,12 @@ err_t
|
|||||||
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||||
{
|
{
|
||||||
struct tcp_pcb *cpcb;
|
struct tcp_pcb *cpcb;
|
||||||
#ifdef SO_REUSE
|
|
||||||
int reuse_port_all_set = 1;
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
port = tcp_new_port();
|
port = tcp_new_port();
|
||||||
}
|
}
|
||||||
#ifndef SO_REUSE
|
|
||||||
/* Check if the address already is in use. */
|
/* Check if the address already is in use. */
|
||||||
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs;
|
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
|
||||||
cpcb != NULL; cpcb = cpcb->next) {
|
cpcb != NULL; cpcb = cpcb->next) {
|
||||||
if (cpcb->local_port == port) {
|
if (cpcb->local_port == port) {
|
||||||
if (ip_addr_isany(&(cpcb->local_ip)) ||
|
if (ip_addr_isany(&(cpcb->local_ip)) ||
|
||||||
@@ -271,107 +262,12 @@ tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* SO_REUSE */
|
|
||||||
/* Search through list of PCB's in LISTEN state.
|
|
||||||
|
|
||||||
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
|
|
||||||
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
|
|
||||||
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
|
|
||||||
But no two PCB's bound to same local port and same local address is valid.
|
|
||||||
|
|
||||||
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
|
|
||||||
all PCB's must have the SOF_REUSEPORT option set.
|
|
||||||
|
|
||||||
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
|
|
||||||
address is already in use. */
|
|
||||||
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs; cpcb != NULL; cpcb = cpcb->next) {
|
|
||||||
if(cpcb->local_port == port) {
|
|
||||||
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
|
|
||||||
if(pcb->so_options & SOF_REUSEPORT) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n"));
|
|
||||||
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
|
|
||||||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
|
|
||||||
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search through list of PCB's in a state in which they can accept or send data. Same decription as for
|
|
||||||
PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */
|
|
||||||
for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) {
|
|
||||||
if(cpcb->local_port == port) {
|
|
||||||
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
|
|
||||||
if(pcb->so_options & SOF_REUSEPORT) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n"));
|
|
||||||
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
|
|
||||||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
|
|
||||||
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port}
|
|
||||||
can be rebound. The same applies when SOF_REUSEPORT is set.
|
|
||||||
|
|
||||||
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
|
|
||||||
all PCB's must have the SOF_REUSEPORT option set.
|
|
||||||
|
|
||||||
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
|
|
||||||
address is already in use. */
|
|
||||||
for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
|
|
||||||
if(cpcb->local_port == port) {
|
|
||||||
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
|
|
||||||
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
else if(pcb->so_options & SOF_REUSEPORT) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n"));
|
|
||||||
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
|
|
||||||
{IP, port} can't be reused. */
|
|
||||||
if(!reuse_port_all_set) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
if (!ip_addr_isany(ipaddr)) {
|
if (!ip_addr_isany(ipaddr)) {
|
||||||
pcb->local_ip = *ipaddr;
|
pcb->local_ip = *ipaddr;
|
||||||
}
|
}
|
||||||
pcb->local_port = port;
|
pcb->local_port = port;
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %u\n", port));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port));
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
@@ -386,16 +282,13 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
|
|||||||
}
|
}
|
||||||
#endif /* LWIP_CALLBACK_API */
|
#endif /* LWIP_CALLBACK_API */
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_listen():
|
|
||||||
*
|
|
||||||
* Set the state of the connection to be LISTEN, which means that it
|
* Set the state of the connection to be LISTEN, which means that it
|
||||||
* is able to accept incoming connections. The protocol control block
|
* is able to accept incoming connections. The protocol control block
|
||||||
* is reallocated in order to consume less memory. Setting the
|
* is reallocated in order to consume less memory. Setting the
|
||||||
* connection to LISTEN is an irreversible process.
|
* connection to LISTEN is an irreversible process.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct tcp_pcb *
|
struct tcp_pcb *
|
||||||
tcp_listen(struct tcp_pcb *pcb)
|
tcp_listen(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
@@ -421,19 +314,16 @@ tcp_listen(struct tcp_pcb *pcb)
|
|||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
lpcb->accept = tcp_accept_null;
|
lpcb->accept = tcp_accept_null;
|
||||||
#endif /* LWIP_CALLBACK_API */
|
#endif /* LWIP_CALLBACK_API */
|
||||||
TCP_REG(&tcp_listen_pcbs, lpcb);
|
TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb);
|
||||||
return (struct tcp_pcb *)lpcb;
|
return (struct tcp_pcb *)lpcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_recved():
|
|
||||||
*
|
|
||||||
* This function should be called by the application when it has
|
* This function should be called by the application when it has
|
||||||
* processed the data. The purpose is to advertise a larger window
|
* processed the data. The purpose is to advertise a larger window
|
||||||
* when the data has been processed.
|
* when the data has been processed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
||||||
{
|
{
|
||||||
@@ -444,20 +334,37 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
|||||||
}
|
}
|
||||||
if (!(pcb->flags & TF_ACK_DELAY) &&
|
if (!(pcb->flags & TF_ACK_DELAY) &&
|
||||||
!(pcb->flags & TF_ACK_NOW)) {
|
!(pcb->flags & TF_ACK_NOW)) {
|
||||||
|
/*
|
||||||
|
* We send an ACK here (if one is not already pending, hence
|
||||||
|
* the above tests) as tcp_recved() implies that the application
|
||||||
|
* has processed some data, and so we can open the receiver's
|
||||||
|
* window to allow more to be transmitted. This could result in
|
||||||
|
* two ACKs being sent for each received packet in some limited cases
|
||||||
|
* (where the application is only receiving data, and is slow to
|
||||||
|
* process it) but it is necessary to guarantee that the sender can
|
||||||
|
* continue to transmit.
|
||||||
|
*/
|
||||||
tcp_ack(pcb);
|
tcp_ack(pcb);
|
||||||
|
}
|
||||||
|
else if (pcb->flags & TF_ACK_DELAY && pcb->rcv_wnd >= TCP_WND/2) {
|
||||||
|
/* If we can send a window update such that there is a full
|
||||||
|
* segment available in the window, do so now. This is sort of
|
||||||
|
* nagle-like in its goals, and tries to hit a compromise between
|
||||||
|
* sending acks each time the window is updated, and only sending
|
||||||
|
* window updates when a timer expires. The "threshold" used
|
||||||
|
* above (currently TCP_WND/2) can be tuned to be more or less
|
||||||
|
* aggressive */
|
||||||
|
tcp_ack_now(pcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n",
|
||||||
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
|
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_new_port():
|
|
||||||
*
|
|
||||||
* A nastly hack featuring 'goto' statements that allocates a
|
* A nastly hack featuring 'goto' statements that allocates a
|
||||||
* new TCP local port.
|
* new TCP local port.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static u16_t
|
static u16_t
|
||||||
tcp_new_port(void)
|
tcp_new_port(void)
|
||||||
{
|
{
|
||||||
@@ -483,7 +390,7 @@ tcp_new_port(void)
|
|||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs; pcb != NULL; pcb = pcb->next) {
|
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
if (pcb->local_port == port) {
|
if (pcb->local_port == port) {
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
@@ -491,14 +398,11 @@ tcp_new_port(void)
|
|||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_connect():
|
|
||||||
*
|
|
||||||
* Connects to another host. The function given as the "connected"
|
* Connects to another host. The function given as the "connected"
|
||||||
* argument will be called when the connection has been established.
|
* argument will be called when the connection has been established.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
err_t
|
err_t
|
||||||
tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
|
tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
|
||||||
err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
|
err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
|
||||||
@@ -507,7 +411,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
|
|||||||
err_t ret;
|
err_t ret;
|
||||||
u32_t iss;
|
u32_t iss;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %u\n", port));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
|
||||||
if (ipaddr != NULL) {
|
if (ipaddr != NULL) {
|
||||||
pcb->remote_ip = *ipaddr;
|
pcb->remote_ip = *ipaddr;
|
||||||
} else {
|
} else {
|
||||||
@@ -546,14 +450,11 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_slowtmr():
|
|
||||||
*
|
|
||||||
* Called every 500 ms and implements the retransmission timer and the timer that
|
* Called every 500 ms and implements the retransmission timer and the timer that
|
||||||
* removes PCBs that have been in TIME-WAIT for enough time. It also increments
|
* removes PCBs that have been in TIME-WAIT for enough time. It also increments
|
||||||
* various timers such as the inactivity timer in each PCB.
|
* various timers such as the inactivity timer in each PCB.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_slowtmr(void)
|
tcp_slowtmr(void)
|
||||||
{
|
{
|
||||||
@@ -569,7 +470,9 @@ tcp_slowtmr(void)
|
|||||||
/* Steps through all of the active PCBs. */
|
/* Steps through all of the active PCBs. */
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
pcb = tcp_active_pcbs;
|
pcb = tcp_active_pcbs;
|
||||||
if (pcb == NULL) LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
|
if (pcb == NULL) {
|
||||||
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
|
||||||
|
}
|
||||||
while (pcb != NULL) {
|
while (pcb != NULL) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));
|
||||||
LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED);
|
LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED);
|
||||||
@@ -590,7 +493,7 @@ tcp_slowtmr(void)
|
|||||||
if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
|
if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
|
||||||
|
|
||||||
/* Time for a retransmission. */
|
/* Time for a retransmission. */
|
||||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %u pcb->rto %u\n",
|
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"U16_F" pcb->rto %"U16_F"\n",
|
||||||
pcb->rtime, pcb->rto));
|
pcb->rtime, pcb->rto));
|
||||||
|
|
||||||
/* Double retransmission time-out unless we are trying to
|
/* Double retransmission time-out unless we are trying to
|
||||||
@@ -598,7 +501,6 @@ tcp_slowtmr(void)
|
|||||||
if (pcb->state != SYN_SENT) {
|
if (pcb->state != SYN_SENT) {
|
||||||
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
|
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
|
||||||
}
|
}
|
||||||
tcp_rexmit(pcb);
|
|
||||||
/* Reduce congestion window and ssthresh. */
|
/* Reduce congestion window and ssthresh. */
|
||||||
eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
|
eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
|
||||||
pcb->ssthresh = eff_wnd >> 1;
|
pcb->ssthresh = eff_wnd >> 1;
|
||||||
@@ -606,9 +508,12 @@ tcp_slowtmr(void)
|
|||||||
pcb->ssthresh = pcb->mss * 2;
|
pcb->ssthresh = pcb->mss * 2;
|
||||||
}
|
}
|
||||||
pcb->cwnd = pcb->mss;
|
pcb->cwnd = pcb->mss;
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n",
|
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\n",
|
||||||
pcb->cwnd, pcb->ssthresh));
|
pcb->cwnd, pcb->ssthresh));
|
||||||
}
|
|
||||||
|
/* The following needs to be called AFTER cwnd is set to one mss - STJ */
|
||||||
|
tcp_rexmit_rto(pcb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Check if this PCB has stayed too long in FIN-WAIT-2 */
|
/* Check if this PCB has stayed too long in FIN-WAIT-2 */
|
||||||
if (pcb->state == FIN_WAIT_2) {
|
if (pcb->state == FIN_WAIT_2) {
|
||||||
@@ -622,7 +527,7 @@ tcp_slowtmr(void)
|
|||||||
/* Check if KEEPALIVE should be sent */
|
/* Check if KEEPALIVE should be sent */
|
||||||
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
|
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
|
||||||
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
|
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
|
||||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
||||||
|
|
||||||
@@ -650,12 +555,19 @@ tcp_slowtmr(void)
|
|||||||
/* Check if this PCB has stayed too long in SYN-RCVD */
|
/* Check if this PCB has stayed too long in SYN-RCVD */
|
||||||
if (pcb->state == SYN_RCVD) {
|
if (pcb->state == SYN_RCVD) {
|
||||||
if ((u32_t)(tcp_ticks - pcb->tmr) >
|
if ((u32_t)(tcp_ticks - pcb->tmr) >
|
||||||
TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
|
TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
|
||||||
++pcb_remove;
|
++pcb_remove;
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if this PCB has stayed too long in LAST-ACK */
|
||||||
|
if (pcb->state == LAST_ACK) {
|
||||||
|
if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
|
||||||
|
++pcb_remove;
|
||||||
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* If the PCB should be removed, do it. */
|
/* If the PCB should be removed, do it. */
|
||||||
if (pcb_remove) {
|
if (pcb_remove) {
|
||||||
@@ -730,12 +642,9 @@ tcp_slowtmr(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_fasttmr():
|
|
||||||
*
|
|
||||||
* Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
|
* Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_fasttmr(void)
|
tcp_fasttmr(void)
|
||||||
{
|
{
|
||||||
@@ -751,13 +660,10 @@ tcp_fasttmr(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_segs_free():
|
|
||||||
*
|
|
||||||
* Deallocates a list of TCP segments (tcp_seg structures).
|
* Deallocates a list of TCP segments (tcp_seg structures).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
u8_t
|
u8_t
|
||||||
tcp_segs_free(struct tcp_seg *seg)
|
tcp_segs_free(struct tcp_seg *seg)
|
||||||
{
|
{
|
||||||
@@ -771,13 +677,10 @@ tcp_segs_free(struct tcp_seg *seg)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_seg_free():
|
|
||||||
*
|
|
||||||
* Frees a TCP segment.
|
* Frees a TCP segment.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
u8_t
|
u8_t
|
||||||
tcp_seg_free(struct tcp_seg *seg)
|
tcp_seg_free(struct tcp_seg *seg)
|
||||||
{
|
{
|
||||||
@@ -795,13 +698,10 @@ tcp_seg_free(struct tcp_seg *seg)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_setprio():
|
|
||||||
*
|
|
||||||
* Sets the priority of a connection.
|
* Sets the priority of a connection.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
|
tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
|
||||||
{
|
{
|
||||||
@@ -809,13 +709,10 @@ tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
|
|||||||
}
|
}
|
||||||
#if TCP_QUEUE_OOSEQ
|
#if TCP_QUEUE_OOSEQ
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_seg_copy():
|
|
||||||
*
|
|
||||||
* Returns a copy of the given TCP segment.
|
* Returns a copy of the given TCP segment.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct tcp_seg *
|
struct tcp_seg *
|
||||||
tcp_seg_copy(struct tcp_seg *seg)
|
tcp_seg_copy(struct tcp_seg *seg)
|
||||||
{
|
{
|
||||||
@@ -825,7 +722,7 @@ tcp_seg_copy(struct tcp_seg *seg)
|
|||||||
if (cseg == NULL) {
|
if (cseg == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memcpy((char *)cseg, (const char *)seg, sizeof(struct tcp_seg));
|
memcpy((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg));
|
||||||
pbuf_ref(cseg->p);
|
pbuf_ref(cseg->p);
|
||||||
return cseg;
|
return cseg;
|
||||||
}
|
}
|
||||||
@@ -869,7 +766,7 @@ tcp_kill_prio(u8_t prio)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inactive != NULL) {
|
if (inactive != NULL) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB 0x%p (%ld)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",
|
||||||
(void *)inactive, inactivity));
|
(void *)inactive, inactivity));
|
||||||
tcp_abort(inactive);
|
tcp_abort(inactive);
|
||||||
}
|
}
|
||||||
@@ -891,7 +788,7 @@ tcp_kill_timewait(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inactive != NULL) {
|
if (inactive != NULL) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB 0x%p (%ld)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n",
|
||||||
(void *)inactive, inactivity));
|
(void *)inactive, inactivity));
|
||||||
tcp_abort(inactive);
|
tcp_abort(inactive);
|
||||||
}
|
}
|
||||||
@@ -951,12 +848,13 @@ tcp_alloc(u8_t prio)
|
|||||||
return pcb;
|
return pcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_new():
|
|
||||||
*
|
|
||||||
* Creates a new TCP protocol control block but doesn't place it on
|
* Creates a new TCP protocol control block but doesn't place it on
|
||||||
* any of the TCP PCB lists.
|
* any of the TCP PCB lists.
|
||||||
*
|
*
|
||||||
|
* @internal: Maybe there should be a idle TCP PCB list where these
|
||||||
|
* PCBs are put on. We can then implement port reservation using
|
||||||
|
* tcp_bind(). Currently, we lack this (BSD socket type of) feature.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct tcp_pcb *
|
struct tcp_pcb *
|
||||||
@@ -980,14 +878,11 @@ tcp_arg(struct tcp_pcb *pcb, void *arg)
|
|||||||
}
|
}
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_recv():
|
|
||||||
*
|
|
||||||
* Used to specify the function that should be called when a TCP
|
* Used to specify the function that should be called when a TCP
|
||||||
* connection receives data.
|
* connection receives data.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_recv(struct tcp_pcb *pcb,
|
tcp_recv(struct tcp_pcb *pcb,
|
||||||
err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
|
err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
|
||||||
@@ -995,9 +890,7 @@ tcp_recv(struct tcp_pcb *pcb,
|
|||||||
pcb->recv = recv;
|
pcb->recv = recv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_sent():
|
|
||||||
*
|
|
||||||
* Used to specify the function that should be called when TCP data
|
* Used to specify the function that should be called when TCP data
|
||||||
* has been successfully delivered to the remote host.
|
* has been successfully delivered to the remote host.
|
||||||
*
|
*
|
||||||
@@ -1010,14 +903,11 @@ tcp_sent(struct tcp_pcb *pcb,
|
|||||||
pcb->sent = sent;
|
pcb->sent = sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_err():
|
|
||||||
*
|
|
||||||
* Used to specify the function that should be called when a fatal error
|
* Used to specify the function that should be called when a fatal error
|
||||||
* has occured on the connection.
|
* has occured on the connection.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_err(struct tcp_pcb *pcb,
|
tcp_err(struct tcp_pcb *pcb,
|
||||||
void (* errf)(void *arg, err_t err))
|
void (* errf)(void *arg, err_t err))
|
||||||
@@ -1025,14 +915,11 @@ tcp_err(struct tcp_pcb *pcb,
|
|||||||
pcb->errf = errf;
|
pcb->errf = errf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_accept():
|
|
||||||
*
|
|
||||||
* Used for specifying the function that should be called when a
|
* Used for specifying the function that should be called when a
|
||||||
* LISTENing connection has been connected to another host.
|
* LISTENing connection has been connected to another host.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_accept(struct tcp_pcb *pcb,
|
tcp_accept(struct tcp_pcb *pcb,
|
||||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
|
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
|
||||||
@@ -1042,15 +929,12 @@ tcp_accept(struct tcp_pcb *pcb,
|
|||||||
#endif /* LWIP_CALLBACK_API */
|
#endif /* LWIP_CALLBACK_API */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_poll():
|
|
||||||
*
|
|
||||||
* Used to specify the function that should be called periodically
|
* Used to specify the function that should be called periodically
|
||||||
* from TCP. The interval is specified in terms of the TCP coarse
|
* from TCP. The interval is specified in terms of the TCP coarse
|
||||||
* timer interval, which is called twice a second.
|
* timer interval, which is called twice a second.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_poll(struct tcp_pcb *pcb,
|
tcp_poll(struct tcp_pcb *pcb,
|
||||||
err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
|
err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
|
||||||
@@ -1061,13 +945,10 @@ tcp_poll(struct tcp_pcb *pcb,
|
|||||||
pcb->pollinterval = interval;
|
pcb->pollinterval = interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_pcb_purge():
|
|
||||||
*
|
|
||||||
* Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
|
* Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_pcb_purge(struct tcp_pcb *pcb)
|
tcp_pcb_purge(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
@@ -1097,13 +978,10 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_pcb_remove():
|
|
||||||
*
|
|
||||||
* Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
|
* Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
|
tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
@@ -1123,13 +1001,10 @@ tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
|
|||||||
LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
|
LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* tcp_next_iss():
|
|
||||||
*
|
|
||||||
* Calculates a new initial sequence number for new connections.
|
* Calculates a new initial sequence number for new connections.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
u32_t
|
u32_t
|
||||||
tcp_next_iss(void)
|
tcp_next_iss(void)
|
||||||
{
|
{
|
||||||
@@ -1145,16 +1020,16 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
|
|||||||
{
|
{
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
|
||||||
ntohs(tcphdr->src), ntohs(tcphdr->dest)));
|
ntohs(tcphdr->src), ntohs(tcphdr->dest)));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (seq no)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n",
|
||||||
ntohl(tcphdr->seqno)));
|
ntohl(tcphdr->seqno)));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (ack no)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n",
|
||||||
ntohl(tcphdr->ackno)));
|
ntohl(tcphdr->ackno)));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u%u| %5u | (hdrlen, flags (",
|
LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (",
|
||||||
TCPH_HDRLEN(tcphdr),
|
TCPH_HDRLEN(tcphdr),
|
||||||
TCPH_FLAGS(tcphdr) >> 5 & 1,
|
TCPH_FLAGS(tcphdr) >> 5 & 1,
|
||||||
TCPH_FLAGS(tcphdr) >> 4 & 1,
|
TCPH_FLAGS(tcphdr) >> 4 & 1,
|
||||||
@@ -1166,7 +1041,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
|
|||||||
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
|
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04x | %5u | (chksum, urgp)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n",
|
||||||
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
|
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
}
|
}
|
||||||
@@ -1247,28 +1122,28 @@ tcp_debug_print_pcbs(void)
|
|||||||
struct tcp_pcb *pcb;
|
struct tcp_pcb *pcb;
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
|
||||||
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",
|
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
|
||||||
pcb->local_port, pcb->remote_port,
|
pcb->local_port, pcb->remote_port,
|
||||||
pcb->snd_nxt, pcb->rcv_nxt));
|
pcb->snd_nxt, pcb->rcv_nxt));
|
||||||
tcp_debug_print_state(pcb->state);
|
tcp_debug_print_state(pcb->state);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
|
||||||
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs; pcb != NULL; pcb = pcb->next) {
|
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",
|
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
|
||||||
pcb->local_port, pcb->remote_port,
|
pcb->local_port, pcb->remote_port,
|
||||||
pcb->snd_nxt, pcb->rcv_nxt));
|
pcb->snd_nxt, pcb->rcv_nxt));
|
||||||
tcp_debug_print_state(pcb->state);
|
tcp_debug_print_state(pcb->state);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
|
||||||
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",
|
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
|
||||||
pcb->local_port, pcb->remote_port,
|
pcb->local_port, pcb->remote_port,
|
||||||
pcb->snd_nxt, pcb->rcv_nxt));
|
pcb->snd_nxt, pcb->rcv_nxt));
|
||||||
tcp_debug_print_state(pcb->state);
|
tcp_debug_print_state(pcb->state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
s16_t
|
||||||
tcp_pcbs_sane(void)
|
tcp_pcbs_sane(void)
|
||||||
{
|
{
|
||||||
struct tcp_pcb *pcb;
|
struct tcp_pcb *pcb;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,9 +2,13 @@
|
|||||||
* @file
|
* @file
|
||||||
*
|
*
|
||||||
* Transmission Control Protocol, outgoing traffic
|
* Transmission Control Protocol, outgoing traffic
|
||||||
|
*
|
||||||
|
* The output functions of TCP.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -35,27 +39,17 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
/* tcp_output.c
|
|
||||||
*
|
|
||||||
* The output functions of TCP.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/memp.h"
|
#include "lwip/memp.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
@@ -63,24 +57,36 @@
|
|||||||
/* Forward declarations.*/
|
/* Forward declarations.*/
|
||||||
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
|
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_t
|
err_t
|
||||||
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
|
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
|
||||||
{
|
{
|
||||||
|
/* no data, no length, flags, copy=1, no optdata, no optdatalen */
|
||||||
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
|
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write data for sending (but does not send it immediately).
|
||||||
|
*
|
||||||
|
* It waits in the expectation of more data being sent soon (as
|
||||||
|
* it can send them more efficiently by combining them together).
|
||||||
|
* To prompt the system to send data now, call tcp_output() after
|
||||||
|
* calling tcp_write().
|
||||||
|
*
|
||||||
|
* @arg pcb Protocol control block of the TCP connection to enqueue data for.
|
||||||
|
*
|
||||||
|
* @see tcp_write()
|
||||||
|
*/
|
||||||
|
|
||||||
err_t
|
err_t
|
||||||
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
|
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
|
||||||
{
|
{
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb,
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", copy=%"U16_F")\n", (void *)pcb,
|
||||||
arg, len, (unsigned int)copy));
|
arg, len, (u16_t)copy));
|
||||||
if (pcb->state == SYN_SENT ||
|
/* connection is in valid state for data transmission? */
|
||||||
pcb->state == SYN_RCVD ||
|
if (pcb->state == ESTABLISHED ||
|
||||||
pcb->state == ESTABLISHED ||
|
pcb->state == CLOSE_WAIT ||
|
||||||
pcb->state == CLOSE_WAIT) {
|
pcb->state == SYN_SENT ||
|
||||||
|
pcb->state == SYN_RCVD) {
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
|
return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
|
||||||
}
|
}
|
||||||
@@ -91,10 +97,24 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue either data or TCP options (but not both) for tranmission
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @arg pcb Protocol control block for the TCP connection to enqueue data for.
|
||||||
|
* @arg arg Pointer to the data to be enqueued for sending.
|
||||||
|
* @arg len Data length in bytes
|
||||||
|
* @arg flags
|
||||||
|
* @arg copy 1 if data must be copied, 0 if data is non-volatile and can be
|
||||||
|
* referenced.
|
||||||
|
* @arg optdata
|
||||||
|
* @arg optlen
|
||||||
|
*/
|
||||||
err_t
|
err_t
|
||||||
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||||
u8_t flags, u8_t copy,
|
u8_t flags, u8_t copy,
|
||||||
u8_t *optdata, u8_t optlen)
|
u8_t *optdata, u8_t optlen)
|
||||||
{
|
{
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
struct tcp_seg *seg, *useg, *queue;
|
struct tcp_seg *seg, *useg, *queue;
|
||||||
@@ -103,41 +123,46 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
void *ptr;
|
void *ptr;
|
||||||
u8_t queuelen;
|
u8_t queuelen;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%u)\n",
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", copy=%"U16_F")\n",
|
||||||
(void *)pcb, arg, len, (unsigned int)flags, (unsigned int)copy));
|
(void *)pcb, arg, len, (u16_t)flags, (u16_t)copy));
|
||||||
left = len;
|
LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
|
||||||
ptr = arg;
|
len == 0 || optlen == 0);
|
||||||
|
LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
|
||||||
|
arg == NULL || optdata == NULL);
|
||||||
/* fail on too much data */
|
/* fail on too much data */
|
||||||
if (len > pcb->snd_buf) {
|
if (len > pcb->snd_buf) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%u > snd_buf=%u)\n", len, pcb->snd_buf));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
|
left = len;
|
||||||
|
ptr = arg;
|
||||||
|
|
||||||
/* seqno will be the sequence number of the first segment enqueued
|
/* seqno will be the sequence number of the first segment enqueued
|
||||||
* by the call to this function. */
|
* by the call to this function. */
|
||||||
seqno = pcb->snd_lbb;
|
seqno = pcb->snd_lbb;
|
||||||
|
|
||||||
queue = NULL;
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
|
||||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %u\n", (unsigned int)pcb->snd_queuelen));
|
|
||||||
|
|
||||||
/* Check if the queue length exceeds the configured maximum queue
|
/* If total number of pbufs on the unsent/unacked queues exceeds the
|
||||||
* length. If so, we return an error. */
|
* configured maximum, return an error */
|
||||||
queuelen = pcb->snd_queuelen;
|
queuelen = pcb->snd_queuelen;
|
||||||
if (queuelen >= TCP_SND_QUEUELEN) {
|
if (queuelen >= TCP_SND_QUEUELEN) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %u (max %u)\n", queuelen, TCP_SND_QUEUELEN));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||||
goto memerr;
|
TCP_STATS_INC(tcp.memerr);
|
||||||
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
|
if (queuelen != 0) {
|
||||||
if (pcb->snd_queuelen != 0) {
|
LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
|
||||||
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
|
pcb->unacked != NULL || pcb->unsent != NULL);
|
||||||
pcb->unsent != NULL);
|
} else {
|
||||||
|
LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
|
||||||
|
pcb->unacked == NULL && pcb->unsent == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
seg = useg = NULL;
|
|
||||||
seglen = 0;
|
|
||||||
|
|
||||||
/* First, break up the data into segments and tuck them together in
|
/* First, break up the data into segments and tuck them together in
|
||||||
* the local "queue" variable. */
|
* the local "queue" variable. */
|
||||||
|
useg = queue = seg = NULL;
|
||||||
|
seglen = 0;
|
||||||
while (queue == NULL || left > 0) {
|
while (queue == NULL || left > 0) {
|
||||||
|
|
||||||
/* The segment length should be the MSS if the data to be enqueued
|
/* The segment length should be the MSS if the data to be enqueued
|
||||||
@@ -153,20 +178,25 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
seg->next = NULL;
|
seg->next = NULL;
|
||||||
seg->p = NULL;
|
seg->p = NULL;
|
||||||
|
|
||||||
|
/* first segment of to-be-queued data? */
|
||||||
if (queue == NULL) {
|
if (queue == NULL) {
|
||||||
useg = queue = seg;
|
queue = seg;
|
||||||
}
|
}
|
||||||
|
/* subsequent segments of to-be-queued data */
|
||||||
else {
|
else {
|
||||||
/* Attach the segment to the end of the queued segments. */
|
/* Attach the segment to the end of the queued segments */
|
||||||
LWIP_ASSERT("useg != NULL", useg != NULL);
|
LWIP_ASSERT("useg != NULL", useg != NULL);
|
||||||
useg->next = seg;
|
useg->next = seg;
|
||||||
useg = seg;
|
|
||||||
}
|
}
|
||||||
|
/* remember last segment of to-be-queued data for next iteration */
|
||||||
|
useg = seg;
|
||||||
|
|
||||||
/* If copy is set, memory should be allocated
|
/* If copy is set, memory should be allocated
|
||||||
* and data copied into pbuf, otherwise data comes from
|
* and data copied into pbuf, otherwise data comes from
|
||||||
* ROM or other static memory, and need not be copied. If
|
* ROM or other static memory, and need not be copied. If
|
||||||
* optdata is != NULL, we have options instead of data. */
|
* optdata is != NULL, we have options instead of data. */
|
||||||
|
|
||||||
|
/* options? */
|
||||||
if (optdata != NULL) {
|
if (optdata != NULL) {
|
||||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
|
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
|
||||||
goto memerr;
|
goto memerr;
|
||||||
@@ -174,9 +204,10 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
++queuelen;
|
++queuelen;
|
||||||
seg->dataptr = seg->p->payload;
|
seg->dataptr = seg->p->payload;
|
||||||
}
|
}
|
||||||
|
/* copy from volatile memory? */
|
||||||
else if (copy) {
|
else if (copy) {
|
||||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
|
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %u\n", seglen));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
|
||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
++queuelen;
|
++queuelen;
|
||||||
@@ -187,8 +218,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
}
|
}
|
||||||
/* do not copy data */
|
/* do not copy data */
|
||||||
else {
|
else {
|
||||||
|
/* First, allocate a pbuf for holding the data.
|
||||||
/* first, allocate a pbuf for holding the data.
|
|
||||||
* since the referenced data is available at least until it is sent out on the
|
* since the referenced data is available at least until it is sent out on the
|
||||||
* link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
|
* link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
|
||||||
* instead of PBUF_REF here.
|
* instead of PBUF_REF here.
|
||||||
@@ -198,6 +228,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
++queuelen;
|
++queuelen;
|
||||||
|
/* reference the non-volatile payload data */
|
||||||
p->payload = ptr;
|
p->payload = ptr;
|
||||||
seg->dataptr = ptr;
|
seg->dataptr = ptr;
|
||||||
|
|
||||||
@@ -212,28 +243,22 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
++queuelen;
|
++queuelen;
|
||||||
|
|
||||||
/* Concatenate the headers and data pbufs together. */
|
/* Concatenate the headers and data pbufs together. */
|
||||||
pbuf_cat(seg->p, p);
|
pbuf_cat(seg->p/*header*/, p/*data*/);
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now that there are more segments queued, we check again if the
|
/* Now that there are more segments queued, we check again if the
|
||||||
length of the queue exceeds the configured maximum. */
|
length of the queue exceeds the configured maximum. */
|
||||||
if (queuelen > TCP_SND_QUEUELEN) {
|
if (queuelen > TCP_SND_QUEUELEN) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %u (%u)\n", queuelen, TCP_SND_QUEUELEN));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
seg->len = seglen;
|
seg->len = seglen;
|
||||||
#if 0 /* Was commented out. TODO: can someone say why this is here? */
|
|
||||||
if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
|
/* build TCP header */
|
||||||
++seg->len;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* Build TCP header. */
|
|
||||||
if (pbuf_header(seg->p, TCP_HLEN)) {
|
if (pbuf_header(seg->p, TCP_HLEN)) {
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
|
||||||
|
|
||||||
TCP_STATS_INC(tcp.err);
|
TCP_STATS_INC(tcp.err);
|
||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
@@ -256,17 +281,16 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
segments such as SYN|ACK. */
|
segments such as SYN|ACK. */
|
||||||
memcpy(seg->dataptr, optdata, optlen);
|
memcpy(seg->dataptr, optdata, optlen);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n",
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
|
||||||
ntohl(seg->tcphdr->seqno),
|
ntohl(seg->tcphdr->seqno),
|
||||||
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
|
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
|
||||||
flags));
|
(u16_t)flags));
|
||||||
|
|
||||||
left -= seglen;
|
left -= seglen;
|
||||||
seqno += seglen;
|
seqno += seglen;
|
||||||
ptr = (void *)((char *)ptr + seglen);
|
ptr = (void *)((u8_t *)ptr + seglen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Now that the data to be enqueued has been broken up into TCP
|
/* Now that the data to be enqueued has been broken up into TCP
|
||||||
segments in the queue variable, we add them to the end of the
|
segments in the queue variable, we add them to the end of the
|
||||||
pcb->unsent queue. */
|
pcb->unsent queue. */
|
||||||
@@ -276,6 +300,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
else {
|
else {
|
||||||
for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
|
for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
|
||||||
}
|
}
|
||||||
|
/* { useg is last segment on the unsent queue, NULL if list is empty } */
|
||||||
|
|
||||||
/* If there is room in the last pbuf on the unsent queue,
|
/* If there is room in the last pbuf on the unsent queue,
|
||||||
chain the first pbuf on the queue together with that. */
|
chain the first pbuf on the queue together with that. */
|
||||||
@@ -283,24 +308,27 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
TCP_TCPLEN(useg) != 0 &&
|
TCP_TCPLEN(useg) != 0 &&
|
||||||
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
|
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
|
||||||
!(flags & (TCP_SYN | TCP_FIN)) &&
|
!(flags & (TCP_SYN | TCP_FIN)) &&
|
||||||
|
/* fit within max seg size */
|
||||||
useg->len + queue->len <= pcb->mss) {
|
useg->len + queue->len <= pcb->mss) {
|
||||||
/* Remove TCP header from first segment. */
|
/* Remove TCP header from first segment of our to-be-queued list */
|
||||||
pbuf_header(queue->p, -TCP_HLEN);
|
pbuf_header(queue->p, -TCP_HLEN);
|
||||||
pbuf_cat(useg->p, queue->p);
|
pbuf_cat(useg->p, queue->p);
|
||||||
useg->len += queue->len;
|
useg->len += queue->len;
|
||||||
useg->next = queue->next;
|
useg->next = queue->next;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining, new len %u\n", useg->len));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
|
||||||
if (seg == queue) {
|
if (seg == queue) {
|
||||||
seg = NULL;
|
seg = NULL;
|
||||||
}
|
}
|
||||||
memp_free(MEMP_TCP_SEG, queue);
|
memp_free(MEMP_TCP_SEG, queue);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
/* empty list */
|
||||||
if (useg == NULL) {
|
if (useg == NULL) {
|
||||||
|
/* initialize list with this segment */
|
||||||
pcb->unsent = queue;
|
pcb->unsent = queue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/* enqueue segment */
|
||||||
else {
|
else {
|
||||||
useg->next = queue;
|
useg->next = queue;
|
||||||
}
|
}
|
||||||
@@ -309,13 +337,15 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
++len;
|
++len;
|
||||||
}
|
}
|
||||||
pcb->snd_lbb += len;
|
pcb->snd_lbb += len;
|
||||||
pcb->snd_buf -= len;
|
|
||||||
pcb->snd_queuelen = queuelen;
|
|
||||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen));
|
|
||||||
if (pcb->snd_queuelen != 0) {
|
|
||||||
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
|
|
||||||
pcb->unsent != NULL);
|
|
||||||
|
|
||||||
|
pcb->snd_buf -= len;
|
||||||
|
|
||||||
|
/* update number of segments on the queues */
|
||||||
|
pcb->snd_queuelen = queuelen;
|
||||||
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
|
||||||
|
if (pcb->snd_queuelen != 0) {
|
||||||
|
LWIP_ASSERT("tcp_enqueue: valid queue length",
|
||||||
|
pcb->unacked != NULL || pcb->unsent != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the PSH flag in the last segment that we enqueued, but only
|
/* Set the PSH flag in the last segment that we enqueued, but only
|
||||||
@@ -325,7 +355,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
memerr:
|
memerr:
|
||||||
TCP_STATS_INC(tcp.memerr);
|
TCP_STATS_INC(tcp.memerr);
|
||||||
|
|
||||||
if (queue != NULL) {
|
if (queue != NULL) {
|
||||||
@@ -334,9 +364,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
if (pcb->snd_queuelen != 0) {
|
if (pcb->snd_queuelen != 0) {
|
||||||
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
|
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
|
||||||
pcb->unsent != NULL);
|
pcb->unsent != NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
|
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,7 +378,7 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
struct tcp_seg *seg, *useg;
|
struct tcp_seg *seg, *useg;
|
||||||
u32_t wnd;
|
u32_t wnd;
|
||||||
#if TCP_CWND_DEBUG
|
#if TCP_CWND_DEBUG
|
||||||
int i = 0;
|
s16_t i = 0;
|
||||||
#endif /* TCP_CWND_DEBUG */
|
#endif /* TCP_CWND_DEBUG */
|
||||||
|
|
||||||
/* First, check if we are invoked by the TCP input processing
|
/* First, check if we are invoked by the TCP input processing
|
||||||
@@ -362,7 +391,6 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
|
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
|
||||||
|
|
||||||
|
|
||||||
seg = pcb->unsent;
|
seg = pcb->unsent;
|
||||||
|
|
||||||
/* useg should point to last segment on unacked queue */
|
/* useg should point to last segment on unacked queue */
|
||||||
@@ -370,24 +398,24 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
if (useg != NULL) {
|
if (useg != NULL) {
|
||||||
for (; useg->next != NULL; useg = useg->next);
|
for (; useg->next != NULL; useg = useg->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If the TF_ACK_NOW flag is set, we check if there is data that is
|
/* If the TF_ACK_NOW flag is set and no data will be sent (either
|
||||||
to be sent. If data is to be sent out, we'll just piggyback our
|
* because the ->unsent queue is empty or because the window does
|
||||||
acknowledgement with the outgoing segment. If no data will be
|
* not allow it), construct an empty ACK segment and send it.
|
||||||
sent (either because the ->unsent queue is empty or because the
|
*
|
||||||
window doesn't allow it) we'll have to construct an empty ACK
|
* If data is to be sent, we will just piggyback the ACK (see below).
|
||||||
segment and send it. */
|
*/
|
||||||
if (pcb->flags & TF_ACK_NOW &&
|
if (pcb->flags & TF_ACK_NOW &&
|
||||||
(seg == NULL ||
|
(seg == NULL ||
|
||||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
|
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
|
||||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
|
||||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
||||||
return ERR_BUF;
|
return ERR_BUF;
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %lu\n", pcb->rcv_nxt));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
|
||||||
|
/* remove ACK flags from the PCB, as we send an empty ACK now */
|
||||||
|
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||||
|
|
||||||
tcphdr = p->payload;
|
tcphdr = p->payload;
|
||||||
tcphdr->src = htons(pcb->local_port);
|
tcphdr->src = htons(pcb->local_port);
|
||||||
@@ -400,10 +428,10 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||||
|
|
||||||
tcphdr->chksum = 0;
|
tcphdr->chksum = 0;
|
||||||
|
#if CHECKSUM_GEN_TCP
|
||||||
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
|
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
|
||||||
IP_PROTO_TCP, p->tot_len);
|
IP_PROTO_TCP, p->tot_len);
|
||||||
|
#endif
|
||||||
|
|
||||||
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||||
IP_PROTO_TCP);
|
IP_PROTO_TCP);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@@ -413,26 +441,26 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
#if TCP_OUTPUT_DEBUG
|
#if TCP_OUTPUT_DEBUG
|
||||||
if (seg == NULL) {
|
if (seg == NULL) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", pcb->unsent));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", (void*)pcb->unsent));
|
||||||
}
|
}
|
||||||
#endif /* TCP_OUTPUT_DEBUG */
|
#endif /* TCP_OUTPUT_DEBUG */
|
||||||
#if TCP_CWND_DEBUG
|
#if TCP_CWND_DEBUG
|
||||||
if (seg == NULL) {
|
if (seg == NULL) {
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n",
|
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", seg == NULL, ack %"U32_F"\n",
|
||||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||||
pcb->lastack));
|
pcb->lastack));
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\n",
|
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
|
||||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
|
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
|
||||||
ntohl(seg->tcphdr->seqno), pcb->lastack));
|
ntohl(seg->tcphdr->seqno), pcb->lastack));
|
||||||
}
|
}
|
||||||
#endif /* TCP_CWND_DEBUG */
|
#endif /* TCP_CWND_DEBUG */
|
||||||
|
/* data available and window allows it to be sent? */
|
||||||
while (seg != NULL &&
|
while (seg != NULL &&
|
||||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
|
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
|
||||||
#if TCP_CWND_DEBUG
|
#if TCP_CWND_DEBUG
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\n",
|
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
|
||||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||||
ntohl(seg->tcphdr->seqno) + seg->len -
|
ntohl(seg->tcphdr->seqno) + seg->len -
|
||||||
pcb->lastack,
|
pcb->lastack,
|
||||||
@@ -455,13 +483,26 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
/* put segment on unacknowledged list if length > 0 */
|
/* put segment on unacknowledged list if length > 0 */
|
||||||
if (TCP_TCPLEN(seg) > 0) {
|
if (TCP_TCPLEN(seg) > 0) {
|
||||||
seg->next = NULL;
|
seg->next = NULL;
|
||||||
|
/* unacked list is empty? */
|
||||||
if (pcb->unacked == NULL) {
|
if (pcb->unacked == NULL) {
|
||||||
pcb->unacked = seg;
|
pcb->unacked = seg;
|
||||||
useg = seg;
|
useg = seg;
|
||||||
|
/* unacked list is not empty? */
|
||||||
} else {
|
} else {
|
||||||
useg->next = seg;
|
/* In the case of fast retransmit, the packet should not go to the tail
|
||||||
useg = useg->next;
|
* of the unacked queue, but rather at the head. We need to check for
|
||||||
|
* this case. -STJ Jul 27, 2004 */
|
||||||
|
if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
|
||||||
|
/* add segment to head of unacked list */
|
||||||
|
seg->next = pcb->unacked;
|
||||||
|
pcb->unacked = seg;
|
||||||
|
} else {
|
||||||
|
/* add segment to tail of unacked list */
|
||||||
|
useg->next = seg;
|
||||||
|
useg = useg->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/* do not queue empty segments on the unacked list */
|
||||||
} else {
|
} else {
|
||||||
tcp_seg_free(seg);
|
tcp_seg_free(seg);
|
||||||
}
|
}
|
||||||
@@ -470,6 +511,9 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually send a TCP segment over IP
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
@@ -504,9 +548,9 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
pcb->rttest = tcp_ticks;
|
pcb->rttest = tcp_ticks;
|
||||||
pcb->rtseq = ntohl(seg->tcphdr->seqno);
|
pcb->rtseq = ntohl(seg->tcphdr->seqno);
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq));
|
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\n",
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
|
||||||
htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
|
htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
|
||||||
seg->len));
|
seg->len));
|
||||||
|
|
||||||
@@ -518,10 +562,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
seg->p->payload = seg->tcphdr;
|
seg->p->payload = seg->tcphdr;
|
||||||
|
|
||||||
seg->tcphdr->chksum = 0;
|
seg->tcphdr->chksum = 0;
|
||||||
|
#if CHECKSUM_GEN_TCP
|
||||||
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
|
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
|
||||||
&(pcb->local_ip),
|
&(pcb->local_ip),
|
||||||
&(pcb->remote_ip),
|
&(pcb->remote_ip),
|
||||||
IP_PROTO_TCP, seg->p->tot_len);
|
IP_PROTO_TCP, seg->p->tot_len);
|
||||||
|
#endif
|
||||||
TCP_STATS_INC(tcp.xmit);
|
TCP_STATS_INC(tcp.xmit);
|
||||||
|
|
||||||
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||||
@@ -552,14 +598,45 @@ tcp_rst(u32_t seqno, u32_t ackno,
|
|||||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||||
|
|
||||||
tcphdr->chksum = 0;
|
tcphdr->chksum = 0;
|
||||||
|
#if CHECKSUM_GEN_TCP
|
||||||
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
|
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
|
||||||
IP_PROTO_TCP, p->tot_len);
|
IP_PROTO_TCP, p->tot_len);
|
||||||
|
#endif
|
||||||
TCP_STATS_INC(tcp.xmit);
|
TCP_STATS_INC(tcp.xmit);
|
||||||
/* Send output with hardcoded TTL since we have no access to the pcb */
|
/* Send output with hardcoded TTL since we have no access to the pcb */
|
||||||
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
|
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
|
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* requeue all unacked segments for retransmission */
|
||||||
|
void
|
||||||
|
tcp_rexmit_rto(struct tcp_pcb *pcb)
|
||||||
|
{
|
||||||
|
struct tcp_seg *seg;
|
||||||
|
|
||||||
|
if (pcb->unacked == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move all unacked segments to the head of the unsent queue */
|
||||||
|
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
|
||||||
|
/* concatenate unsent queue after unacked queue */
|
||||||
|
seg->next = pcb->unsent;
|
||||||
|
/* unsent queue is the concatenated queue (of unacked, unsent) */
|
||||||
|
pcb->unsent = pcb->unacked;
|
||||||
|
/* unacked queue is now empty */
|
||||||
|
pcb->unacked = NULL;
|
||||||
|
|
||||||
|
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||||
|
/* increment number of retransmissions */
|
||||||
|
++pcb->nrtx;
|
||||||
|
|
||||||
|
/* Don't take any RTT measurements after retransmitting. */
|
||||||
|
pcb->rttest = 0;
|
||||||
|
|
||||||
|
/* Do the actual retransmission */
|
||||||
|
tcp_output(pcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -571,14 +648,11 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move all unacked segments to the unsent queue. */
|
/* Move the first unacked segment to the unsent queue */
|
||||||
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
|
seg = pcb->unacked->next;
|
||||||
|
pcb->unacked->next = pcb->unsent;
|
||||||
seg->next = pcb->unsent;
|
|
||||||
pcb->unsent = pcb->unacked;
|
pcb->unsent = pcb->unacked;
|
||||||
|
pcb->unacked = seg;
|
||||||
pcb->unacked = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||||
|
|
||||||
@@ -592,17 +666,18 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
tcp_keepalive(struct tcp_pcb *pcb)
|
tcp_keepalive(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
struct tcp_hdr *tcphdr;
|
struct tcp_hdr *tcphdr;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %ld pcb->tmr %ld pcb->keep_cnt %ld\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
|
||||||
|
|
||||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||||
|
|
||||||
@@ -621,8 +696,9 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||||
|
|
||||||
tcphdr->chksum = 0;
|
tcphdr->chksum = 0;
|
||||||
|
#if CHECKSUM_GEN_TCP
|
||||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
|
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
|
||||||
|
#endif
|
||||||
TCP_STATS_INC(tcp.xmit);
|
TCP_STATS_INC(tcp.xmit);
|
||||||
|
|
||||||
/* Send output to IP */
|
/* Send output to IP */
|
||||||
@@ -630,7 +706,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
|
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
|
|||||||
430
src/core/udp.c
430
src/core/udp.c
@@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -42,15 +42,17 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/memp.h"
|
#include "lwip/memp.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/udp.h"
|
#include "lwip/udp.h"
|
||||||
#include "lwip/icmp.h"
|
#include "lwip/icmp.h"
|
||||||
#include "lwip/ip_addr.h"
|
|
||||||
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
@@ -64,83 +66,12 @@ struct udp_pcb *udp_pcbs = NULL;
|
|||||||
|
|
||||||
static struct udp_pcb *pcb_cache = NULL;
|
static struct udp_pcb *pcb_cache = NULL;
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
udp_init(void)
|
udp_init(void)
|
||||||
{
|
{
|
||||||
udp_pcbs = pcb_cache = NULL;
|
udp_pcbs = pcb_cache = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* udp_lookup:
|
|
||||||
*
|
|
||||||
* An experimental feature that will be changed in future versions. Do
|
|
||||||
* not depend on it yet...
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef LWIP_DEBUG
|
|
||||||
u8_t
|
|
||||||
udp_lookup(struct ip_hdr *iphdr, struct netif *inp)
|
|
||||||
{
|
|
||||||
struct udp_pcb *pcb;
|
|
||||||
struct udp_hdr *udphdr;
|
|
||||||
u16_t src, dest;
|
|
||||||
|
|
||||||
PERF_START;
|
|
||||||
(void)inp;
|
|
||||||
|
|
||||||
udphdr = (struct udp_hdr *)(u8_t *)iphdr + IPH_HL(iphdr) * 4;
|
|
||||||
|
|
||||||
src = ntohs(udphdr->src);
|
|
||||||
dest = ntohs(udphdr->dest);
|
|
||||||
|
|
||||||
pcb = pcb_cache;
|
|
||||||
if (pcb != NULL &&
|
|
||||||
pcb->remote_port == src &&
|
|
||||||
pcb->local_port == dest &&
|
|
||||||
(ip_addr_isany(&pcb->remote_ip) ||
|
|
||||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
|
|
||||||
(ip_addr_isany(&pcb->local_ip) ||
|
|
||||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
|
||||||
if (pcb->remote_port == src &&
|
|
||||||
pcb->local_port == dest &&
|
|
||||||
(ip_addr_isany(&pcb->remote_ip) ||
|
|
||||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
|
|
||||||
(ip_addr_isany(&pcb->local_ip) ||
|
|
||||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
|
||||||
pcb_cache = pcb;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pcb == NULL) {
|
|
||||||
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
|
||||||
if (pcb->remote_port == 0 &&
|
|
||||||
pcb->local_port == dest &&
|
|
||||||
(ip_addr_isany(&pcb->remote_ip) ||
|
|
||||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
|
|
||||||
(ip_addr_isany(&pcb->local_ip) ||
|
|
||||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PERF_STOP("udp_lookup");
|
|
||||||
|
|
||||||
if (pcb != NULL) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* LWIP_DEBUG */
|
|
||||||
/**
|
/**
|
||||||
* Process an incoming UDP datagram.
|
* Process an incoming UDP datagram.
|
||||||
*
|
*
|
||||||
@@ -156,16 +87,11 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
{
|
{
|
||||||
struct udp_hdr *udphdr;
|
struct udp_hdr *udphdr;
|
||||||
struct udp_pcb *pcb;
|
struct udp_pcb *pcb;
|
||||||
|
struct udp_pcb *uncon_pcb;
|
||||||
struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
u16_t src, dest;
|
u16_t src, dest;
|
||||||
|
u8_t local_match;
|
||||||
|
|
||||||
#ifdef SO_REUSE
|
|
||||||
struct udp_pcb *pcb_temp;
|
|
||||||
int reuse = 0;
|
|
||||||
int reuse_port_1 = 0;
|
|
||||||
int reuse_port_2 = 0;
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
PERF_START;
|
PERF_START;
|
||||||
|
|
||||||
UDP_STATS_INC(udp.recv);
|
UDP_STATS_INC(udp.recv);
|
||||||
@@ -174,7 +100,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
|
|
||||||
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
|
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
|
||||||
/* drop short packets */
|
/* drop short packets */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len));
|
||||||
UDP_STATS_INC(udp.lenerr);
|
UDP_STATS_INC(udp.lenerr);
|
||||||
UDP_STATS_INC(udp.drop);
|
UDP_STATS_INC(udp.drop);
|
||||||
snmp_inc_udpinerrors();
|
snmp_inc_udpinerrors();
|
||||||
@@ -184,7 +110,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
|
|
||||||
udphdr = (struct udp_hdr *)((u8_t *)p->payload - UDP_HLEN);
|
udphdr = (struct udp_hdr *)((u8_t *)p->payload - UDP_HLEN);
|
||||||
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %u\n", p->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
|
||||||
|
|
||||||
src = ntohs(udphdr->src);
|
src = ntohs(udphdr->src);
|
||||||
dest = ntohs(udphdr->dest);
|
dest = ntohs(udphdr->dest);
|
||||||
@@ -192,117 +118,46 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
udp_debug_print(udphdr);
|
udp_debug_print(udphdr);
|
||||||
|
|
||||||
/* print the UDP source and destination */
|
/* print the UDP source and destination */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n",
|
LWIP_DEBUGF(UDP_DEBUG, ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
||||||
ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest),
|
ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest),
|
||||||
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
|
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
|
||||||
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
|
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
|
||||||
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
|
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
|
||||||
|
|
||||||
#ifdef SO_REUSE
|
local_match = 0;
|
||||||
pcb_temp = udp_pcbs;
|
uncon_pcb = NULL;
|
||||||
|
/* Iterate through the UDP pcb list for a matching pcb */
|
||||||
again_1:
|
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
|
|
||||||
/* Iterate through the UDP pcb list for a fully matching pcb */
|
|
||||||
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
|
|
||||||
#else /* SO_REUSE */
|
|
||||||
/* Iterate through the UDP pcb list for a fully matching pcb */
|
|
||||||
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
/* print the PCB local and remote address */
|
/* print the PCB local and remote address */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
|
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
||||||
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
|
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
|
||||||
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
|
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
|
||||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
|
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
|
||||||
|
|
||||||
/* PCB remote port matches UDP source port? */
|
/* compare PCB local addr+port to UDP destination addr+port */
|
||||||
if ((pcb->remote_port == src) &&
|
if ((pcb->local_port == dest) &&
|
||||||
/* PCB local port matches UDP destination port? */
|
|
||||||
(pcb->local_port == dest) &&
|
|
||||||
/* accepting from any remote (source) IP address? or... */
|
|
||||||
(ip_addr_isany(&pcb->remote_ip) ||
|
|
||||||
/* PCB remote IP address matches UDP source IP address? */
|
|
||||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
|
|
||||||
/* accepting on any local (netif) IP address? or... */
|
|
||||||
(ip_addr_isany(&pcb->local_ip) ||
|
(ip_addr_isany(&pcb->local_ip) ||
|
||||||
/* PCB local IP address matches UDP destination IP address? */
|
|
||||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
||||||
#ifdef SO_REUSE
|
local_match = 1;
|
||||||
if(pcb->so_options & SOF_REUSEPORT) {
|
if ((uncon_pcb == NULL) &&
|
||||||
if(reuse) {
|
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
|
||||||
/* We processed one PCB already */
|
/* the first unconnected matching PCB */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
|
uncon_pcb = pcb;
|
||||||
} else {
|
}
|
||||||
/* First PCB with this address */
|
}
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
|
/* compare PCB remote addr+port to UDP source addr+port */
|
||||||
reuse = 1;
|
if ((local_match != 0) &&
|
||||||
}
|
(pcb->remote_port == src) &&
|
||||||
|
(ip_addr_isany(&pcb->remote_ip) ||
|
||||||
reuse_port_1 = 1;
|
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)))) {
|
||||||
p->ref++;
|
/* the first fully matching PCB */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
|
|
||||||
} else {
|
|
||||||
if(reuse) {
|
|
||||||
/* We processed one PCB already */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* no fully matching pcb found? then look for an unconnected pcb */
|
/* no fully matching pcb found? then look for an unconnected pcb */
|
||||||
if (pcb == NULL) {
|
if (pcb == NULL) {
|
||||||
/* Iterate through the UDP PCB list for a pcb that matches
|
pcb = uncon_pcb;
|
||||||
the local address. */
|
|
||||||
|
|
||||||
#ifdef SO_REUSE
|
|
||||||
pcb_temp = udp_pcbs;
|
|
||||||
|
|
||||||
again_2:
|
|
||||||
|
|
||||||
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
|
|
||||||
#else /* SO_REUSE */
|
|
||||||
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
|
|
||||||
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
|
|
||||||
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
|
|
||||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
|
||||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
|
|
||||||
/* unconnected? */
|
|
||||||
if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) &&
|
|
||||||
/* destination port matches? */
|
|
||||||
(pcb->local_port == dest) &&
|
|
||||||
/* not bound to a specific (local) interface address? or... */
|
|
||||||
(ip_addr_isany(&pcb->local_ip) ||
|
|
||||||
/* ...matching interface address? */
|
|
||||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
|
||||||
#ifdef SO_REUSE
|
|
||||||
if(pcb->so_options & SOF_REUSEPORT) {
|
|
||||||
if(reuse) {
|
|
||||||
/* We processed one PCB already */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
|
|
||||||
} else {
|
|
||||||
/* First PCB with this address */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
|
|
||||||
reuse = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
reuse_port_2 = 1;
|
|
||||||
p->ref++;
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
|
|
||||||
} else {
|
|
||||||
if(reuse) {
|
|
||||||
/* We processed one PCB already */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check checksum if this is a match or if it was directed at us. */
|
/* Check checksum if this is a match or if it was directed at us. */
|
||||||
@@ -316,6 +171,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
|
if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
|
||||||
#endif /* IPv4 */
|
#endif /* IPv4 */
|
||||||
/* Do the UDP Lite checksum */
|
/* Do the UDP Lite checksum */
|
||||||
|
#if CHECKSUM_CHECK_UDP
|
||||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||||
(struct ip_addr *)&(iphdr->dest),
|
(struct ip_addr *)&(iphdr->dest),
|
||||||
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
|
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
|
||||||
@@ -326,7 +182,9 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
#if CHECKSUM_CHECK_UDP
|
||||||
if (udphdr->chksum != 0) {
|
if (udphdr->chksum != 0) {
|
||||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||||
(struct ip_addr *)&(iphdr->dest),
|
(struct ip_addr *)&(iphdr->dest),
|
||||||
@@ -340,45 +198,24 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pbuf_header(p, -UDP_HLEN);
|
pbuf_header(p, -UDP_HLEN);
|
||||||
if (pcb != NULL) {
|
if (pcb != NULL) {
|
||||||
snmp_inc_udpindatagrams();
|
snmp_inc_udpindatagrams();
|
||||||
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
|
/* callback */
|
||||||
#ifdef SO_REUSE
|
if (pcb->recv != NULL)
|
||||||
/* First socket should receive now */
|
{
|
||||||
if(reuse_port_1 || reuse_port_2) {
|
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
|
||||||
/* We want to search on next socket after receiving */
|
}
|
||||||
pcb_temp = pcb->next;
|
|
||||||
|
|
||||||
if(reuse_port_1) {
|
|
||||||
/* We are searching connected sockets */
|
|
||||||
reuse_port_1 = 0;
|
|
||||||
reuse_port_2 = 0;
|
|
||||||
goto again_1;
|
|
||||||
} else {
|
} else {
|
||||||
/* We are searching unconnected sockets */
|
|
||||||
reuse_port_1 = 0;
|
|
||||||
reuse_port_2 = 0;
|
|
||||||
goto again_2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
} else {
|
|
||||||
#ifdef SO_REUSE
|
|
||||||
if(reuse) {
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
|
|
||||||
pbuf_free(p);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
|
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
|
||||||
|
|
||||||
/* No match was found, send ICMP destination port unreachable unless
|
/* No match was found, send ICMP destination port unreachable unless
|
||||||
destination address was broadcast/multicast. */
|
destination address was broadcast/multicast. */
|
||||||
|
|
||||||
if (!ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) &&
|
if (!ip_addr_isbroadcast(&iphdr->dest, inp) &&
|
||||||
!ip_addr_ismulticast(&iphdr->dest)) {
|
!ip_addr_ismulticast(&iphdr->dest)) {
|
||||||
|
|
||||||
/* adjust pbuf pointer */
|
/* adjust pbuf pointer */
|
||||||
p->payload = iphdr;
|
p->payload = iphdr;
|
||||||
@@ -396,6 +233,47 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
|
|
||||||
PERF_STOP("udp_input");
|
PERF_STOP("udp_input");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send data to a specified address using UDP.
|
||||||
|
*
|
||||||
|
* @param pcb UDP PCB used to send the data.
|
||||||
|
* @param pbuf chain of pbuf's to be sent.
|
||||||
|
* @param dst_ip Destination IP address.
|
||||||
|
* @param dst_port Destination UDP port.
|
||||||
|
*
|
||||||
|
* If the PCB already has a remote address association, it will
|
||||||
|
* be restored after the data is sent.
|
||||||
|
*
|
||||||
|
* @return lwIP error code.
|
||||||
|
* - ERR_OK. Successful. No error occured.
|
||||||
|
* - ERR_MEM. Out of memory.
|
||||||
|
* - ERR_RTE. Could not find route to destination address.
|
||||||
|
*
|
||||||
|
* @see udp_disconnect() udp_send()
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
||||||
|
struct ip_addr *dst_ip, u16_t dst_port)
|
||||||
|
{
|
||||||
|
err_t err;
|
||||||
|
/* temporary space for current PCB remote address */
|
||||||
|
struct ip_addr pcb_remote_ip;
|
||||||
|
u16_t pcb_remote_port;
|
||||||
|
/* remember current remote peer address of PCB */
|
||||||
|
pcb_remote_ip.addr = pcb->remote_ip.addr;
|
||||||
|
pcb_remote_port = pcb->remote_port;
|
||||||
|
/* copy packet destination address to PCB remote peer address */
|
||||||
|
pcb->remote_ip.addr = dst_ip->addr;
|
||||||
|
pcb->remote_port = dst_port;
|
||||||
|
/* send to the packet destination address */
|
||||||
|
err = udp_send(pcb, p);
|
||||||
|
/* restore PCB remote peer address */
|
||||||
|
pcb->remote_ip.addr = pcb_remote_ip.addr;
|
||||||
|
pcb->remote_port = pcb_remote_port;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send data using UDP.
|
* Send data using UDP.
|
||||||
*
|
*
|
||||||
@@ -405,10 +283,9 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
* @return lwIP error code.
|
* @return lwIP error code.
|
||||||
* - ERR_OK. Successful. No error occured.
|
* - ERR_OK. Successful. No error occured.
|
||||||
* - ERR_MEM. Out of memory.
|
* - ERR_MEM. Out of memory.
|
||||||
* - ERR_USE. The specified ipaddr and port are already bound to by
|
* - ERR_RTE. Could not find route to destination address.
|
||||||
* another UDP PCB.
|
|
||||||
*
|
*
|
||||||
* @see udp_disconnect()
|
* @see udp_disconnect() udp_sendto()
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||||
@@ -430,10 +307,18 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* find the outgoing network interface for this packet */
|
||||||
|
netif = ip_route(&(pcb->remote_ip));
|
||||||
|
/* no outgoing network interface could be found? */
|
||||||
|
if (netif == NULL) {
|
||||||
|
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%"X32_F"\n", pcb->remote_ip.addr));
|
||||||
|
UDP_STATS_INC(udp.rterr);
|
||||||
|
return ERR_RTE;
|
||||||
|
}
|
||||||
|
|
||||||
/* not enough space to add an UDP header to first pbuf in given p chain? */
|
/* not enough space to add an UDP header to first pbuf in given p chain? */
|
||||||
if (pbuf_header(p, UDP_HLEN)) {
|
if (pbuf_header(p, UDP_HLEN)) {
|
||||||
/* allocate header in new pbuf */
|
/* allocate header in a seperate new pbuf */
|
||||||
q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
|
q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
|
||||||
/* new header pbuf could not be allocated? */
|
/* new header pbuf could not be allocated? */
|
||||||
if (q == NULL) {
|
if (q == NULL) {
|
||||||
@@ -445,23 +330,19 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
|||||||
/* { first pbuf q points to header pbuf } */
|
/* { first pbuf q points to header pbuf } */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||||
/* adding a header within p succeeded */
|
/* adding a header within p succeeded */
|
||||||
} else {
|
} else {
|
||||||
/* first pbuf q equals given pbuf */
|
/* first pbuf q equals given pbuf */
|
||||||
q = p;
|
q = p;
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
|
||||||
}
|
}
|
||||||
/* { q now represents the packet to be sent */
|
/* { q now represents the packet to be sent } */
|
||||||
udphdr = q->payload;
|
udphdr = q->payload;
|
||||||
udphdr->src = htons(pcb->local_port);
|
udphdr->src = htons(pcb->local_port);
|
||||||
udphdr->dest = htons(pcb->remote_port);
|
udphdr->dest = htons(pcb->remote_port);
|
||||||
udphdr->chksum = 0x0000;
|
/* in UDP, 0 checksum means 'no checksum' */
|
||||||
|
udphdr->chksum = 0x0000;
|
||||||
|
|
||||||
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
|
/* PCB local address is IP_ANY_ADDR? */
|
||||||
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr));
|
|
||||||
UDP_STATS_INC(udp.rterr);
|
|
||||||
return ERR_RTE;
|
|
||||||
}
|
|
||||||
/* using IP_ANY_ADDR? */
|
|
||||||
if (ip_addr_isany(&pcb->local_ip)) {
|
if (ip_addr_isany(&pcb->local_ip)) {
|
||||||
/* use outgoing network interface IP address as source address */
|
/* use outgoing network interface IP address as source address */
|
||||||
src_ip = &(netif->ip_addr);
|
src_ip = &(netif->ip_addr);
|
||||||
@@ -470,42 +351,52 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
|||||||
src_ip = &(pcb->local_ip);
|
src_ip = &(pcb->local_ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %u\n", q->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
|
||||||
|
|
||||||
/* UDP Lite protocol? */
|
/* UDP Lite protocol? */
|
||||||
if (pcb->flags & UDP_FLAGS_UDPLITE) {
|
if (pcb->flags & UDP_FLAGS_UDPLITE) {
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %u\n", q->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len));
|
||||||
/* set UDP message length in UDP header */
|
/* set UDP message length in UDP header */
|
||||||
udphdr->len = htons(pcb->chksum_len);
|
udphdr->len = htons(pcb->chksum_len);
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
|
#if CHECKSUM_GEN_UDP
|
||||||
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip),
|
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip),
|
||||||
IP_PROTO_UDP, pcb->chksum_len);
|
IP_PROTO_UDP, pcb->chksum_len);
|
||||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||||
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
|
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
|
||||||
|
#else
|
||||||
|
udphdr->chksum = 0x0000;
|
||||||
|
#endif
|
||||||
/* output to IP */
|
/* output to IP */
|
||||||
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
|
||||||
err = ip_output_if (q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
err = ip_output_if (q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
||||||
snmp_inc_udpoutdatagrams();
|
/* UDP */
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
|
||||||
udphdr->len = htons(q->tot_len);
|
udphdr->len = htons(q->tot_len);
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
|
#if CHECKSUM_GEN_UDP
|
||||||
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
||||||
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &pcb->remote_ip, IP_PROTO_UDP, q->tot_len);
|
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &pcb->remote_ip, IP_PROTO_UDP, q->tot_len);
|
||||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||||
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
|
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04x\n", udphdr->chksum));
|
#else
|
||||||
snmp_inc_udpoutdatagrams();
|
udphdr->chksum = 0x0000;
|
||||||
|
#endif
|
||||||
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
|
||||||
/* output to IP */
|
/* output to IP */
|
||||||
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
||||||
}
|
}
|
||||||
|
/* TODO: must this be increased even if error occured? */
|
||||||
|
snmp_inc_udpoutdatagrams();
|
||||||
|
|
||||||
/* did we chain a header earlier? */
|
/* did we chain a seperate header pbuf earlier? */
|
||||||
if (q != p) {
|
if (q != p) {
|
||||||
/* free the header */
|
/* free the header pbuf */
|
||||||
/* p is also still referenced by the caller, and will live on */
|
pbuf_free(q); q = NULL;
|
||||||
pbuf_free(q);
|
/* { p is still referenced by the caller, and will live on } */
|
||||||
}
|
}
|
||||||
|
|
||||||
UDP_STATS_INC(udp.xmit);
|
UDP_STATS_INC(udp.xmit);
|
||||||
@@ -532,12 +423,10 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
{
|
{
|
||||||
struct udp_pcb *ipcb;
|
struct udp_pcb *ipcb;
|
||||||
u8_t rebind;
|
u8_t rebind;
|
||||||
#ifdef SO_REUSE
|
|
||||||
int reuse_port_all_set = 1;
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
|
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
|
||||||
ip_addr_debug_print(UDP_DEBUG, ipaddr);
|
ip_addr_debug_print(UDP_DEBUG, ipaddr);
|
||||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port));
|
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %"U16_F")\n", port));
|
||||||
|
|
||||||
rebind = 0;
|
rebind = 0;
|
||||||
/* Check for double bind and rebind of the same pcb */
|
/* Check for double bind and rebind of the same pcb */
|
||||||
@@ -550,7 +439,6 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
rebind = 1;
|
rebind = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SO_REUSE
|
|
||||||
/* this code does not allow upper layer to share a UDP port for
|
/* this code does not allow upper layer to share a UDP port for
|
||||||
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
|
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
|
||||||
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
|
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
|
||||||
@@ -563,56 +451,13 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
ip_addr_isany(ipaddr) ||
|
ip_addr_isany(ipaddr) ||
|
||||||
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
|
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
|
||||||
/* other PCB already binds to this local IP and port */
|
/* other PCB already binds to this local IP and port */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %u already bound by another pcb\n", port));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
|
||||||
return ERR_USE;
|
return ERR_USE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* SO_REUSE */
|
|
||||||
/* Search through list of PCB's.
|
|
||||||
|
|
||||||
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
|
|
||||||
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
|
|
||||||
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
|
|
||||||
But no two PCB's bound to same local port and same local address is valid.
|
|
||||||
|
|
||||||
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
|
|
||||||
all PCB's must have the SOF_REUSEPORT option set.
|
|
||||||
|
|
||||||
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
|
|
||||||
address is already in use. */
|
|
||||||
else if (ipcb->local_port == port) {
|
|
||||||
if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {
|
|
||||||
if(pcb->so_options & SOF_REUSEPORT) {
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n"));
|
|
||||||
reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) ||
|
|
||||||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) {
|
|
||||||
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SO_REUSE
|
|
||||||
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
|
|
||||||
{IP, port} can't be reused. */
|
|
||||||
if(!reuse_port_all_set) {
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
ip_addr_set(&pcb->local_ip, ipaddr);
|
||||||
/* no port specified? */
|
/* no port specified? */
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
@@ -642,11 +487,11 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
pcb->next = udp_pcbs;
|
pcb->next = udp_pcbs;
|
||||||
udp_pcbs = pcb;
|
udp_pcbs = pcb;
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %u.%u.%u.%u, port %u\n",
|
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
|
||||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
|
(u16_t)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
|
(u16_t)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
|
(u16_t)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
|
(u16_t)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -695,11 +540,11 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
pcb->local_ip.addr = 0;
|
pcb->local_ip.addr = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %u.%u.%u.%u, port %u\n",
|
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
|
||||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
|
(u16_t)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
|
(u16_t)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
|
(u16_t)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
|
(u16_t)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
|
||||||
|
|
||||||
/* Insert UDP PCB into the list of active UDP PCBs. */
|
/* Insert UDP PCB into the list of active UDP PCBs. */
|
||||||
for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
||||||
@@ -717,6 +562,10 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
void
|
void
|
||||||
udp_disconnect(struct udp_pcb *pcb)
|
udp_disconnect(struct udp_pcb *pcb)
|
||||||
{
|
{
|
||||||
|
/* reset remote address association */
|
||||||
|
ip_addr_set(&pcb->remote_ip, IP_ADDR_ANY);
|
||||||
|
pcb->remote_port = 0;
|
||||||
|
/* mark PCB as unconnected */
|
||||||
pcb->flags &= ~UDP_FLAGS_CONNECTED;
|
pcb->flags &= ~UDP_FLAGS_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,18 +629,17 @@ udp_new(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if UDP_DEBUG
|
#if UDP_DEBUG
|
||||||
int
|
void
|
||||||
udp_debug_print(struct udp_hdr *udphdr)
|
udp_debug_print(struct udp_hdr *udphdr)
|
||||||
{
|
{
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
|
LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
|
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
|
||||||
ntohs(udphdr->src), ntohs(udphdr->dest)));
|
ntohs(udphdr->src), ntohs(udphdr->dest)));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("| %5u | 0x%04x | (len, chksum)\n",
|
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n",
|
||||||
ntohs(udphdr->len), ntohs(udphdr->chksum)));
|
ntohs(udphdr->len), ntohs(udphdr->chksum)));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif /* UDP_DEBUG */
|
#endif /* UDP_DEBUG */
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
|
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
#define ICMP_ER 0 /* echo reply */
|
#define ICMP_ER 0 /* echo reply */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -39,14 +39,17 @@
|
|||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
|
||||||
u16_t inet_chksum(void *dataptr, u16_t len);
|
u16_t inet_chksum(void *dataptr, u16_t len);
|
||||||
|
#if 0 /* optimized routine */
|
||||||
|
u16_t inet_chksum4(u8_t *dataptr, u16_t len);
|
||||||
|
#endif
|
||||||
u16_t inet_chksum_pbuf(struct pbuf *p);
|
u16_t inet_chksum_pbuf(struct pbuf *p);
|
||||||
u16_t inet_chksum_pseudo(struct pbuf *p,
|
u16_t inet_chksum_pseudo(struct pbuf *p,
|
||||||
struct ip_addr *src, struct ip_addr *dest,
|
struct ip_addr *src, struct ip_addr *dest,
|
||||||
u8_t proto, u16_t proto_len);
|
u8_t proto, u16_t proto_len);
|
||||||
|
|
||||||
u32_t inet_addr(const char *cp);
|
u32_t inet_addr(const char *cp);
|
||||||
int inet_aton(const char *cp, struct in_addr *addr);
|
s8_t inet_aton(const char *cp, struct in_addr *addr);
|
||||||
u8_t *inet_ntoa(u32_t addr); /* returns ptr to static buffer; not reentrant! */
|
char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */
|
||||||
|
|
||||||
#ifdef htons
|
#ifdef htons
|
||||||
#undef htons
|
#undef htons
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -40,10 +40,8 @@
|
|||||||
|
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
|
|
||||||
struct netif;
|
|
||||||
|
|
||||||
void ip_init(void);
|
void ip_init(void);
|
||||||
u8_t ip_lookup(void *header, struct netif *inp);
|
|
||||||
struct netif *ip_route(struct ip_addr *dest);
|
struct netif *ip_route(struct ip_addr *dest);
|
||||||
err_t ip_input(struct pbuf *p, struct netif *inp);
|
err_t ip_input(struct pbuf *p, struct netif *inp);
|
||||||
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||||
@@ -129,7 +127,7 @@ PACK_STRUCT_END
|
|||||||
|
|
||||||
#define IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12)
|
#define IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12)
|
||||||
#define IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f)
|
#define IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f)
|
||||||
#define IPH_TOS(hdr) (htons((ntohs((hdr)->_v_hl_tos) & 0xff)))
|
#define IPH_TOS(hdr) (ntohs((hdr)->_v_hl_tos) & 0xff)
|
||||||
#define IPH_LEN(hdr) ((hdr)->_len)
|
#define IPH_LEN(hdr) ((hdr)->_len)
|
||||||
#define IPH_ID(hdr) ((hdr)->_id)
|
#define IPH_ID(hdr) ((hdr)->_id)
|
||||||
#define IPH_OFFSET(hdr) ((hdr)->_offset)
|
#define IPH_OFFSET(hdr) ((hdr)->_offset)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -34,6 +34,40 @@
|
|||||||
|
|
||||||
#include "lwip/arch.h"
|
#include "lwip/arch.h"
|
||||||
|
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct ip_addr {
|
||||||
|
PACK_STRUCT_FIELD(u32_t addr);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct ip_addr2 {
|
||||||
|
PACK_STRUCT_FIELD(u16_t addrw[2]);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* For compatibility with BSD code */
|
||||||
|
struct in_addr {
|
||||||
|
u32_t s_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct netif;
|
||||||
|
|
||||||
|
extern const struct ip_addr ip_addr_any;
|
||||||
|
extern const struct ip_addr ip_addr_broadcast;
|
||||||
|
|
||||||
/** IP_ADDR_ can be used as a fixed IP address
|
/** IP_ADDR_ can be used as a fixed IP address
|
||||||
* for the wildcard and the broadcast address
|
* for the wildcard and the broadcast address
|
||||||
*/
|
*/
|
||||||
@@ -76,33 +110,22 @@
|
|||||||
|
|
||||||
#define IN_LOOPBACKNET 127 /* official! */
|
#define IN_LOOPBACKNET 127 /* official! */
|
||||||
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/bpstruct.h"
|
|
||||||
#endif
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ip_addr {
|
|
||||||
PACK_STRUCT_FIELD(u32_t addr);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
||||||
# include "arch/epstruct.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* For compatibility with BSD code */
|
|
||||||
struct in_addr {
|
|
||||||
u32_t s_addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const struct ip_addr ip_addr_any;
|
|
||||||
extern const struct ip_addr ip_addr_broadcast;
|
|
||||||
|
|
||||||
#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = htonl(((u32_t)(a & 0xff) << 24) | ((u32_t)(b & 0xff) << 16) | \
|
#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = htonl(((u32_t)(a & 0xff) << 24) | ((u32_t)(b & 0xff) << 16) | \
|
||||||
((u32_t)(c & 0xff) << 8) | (u32_t)(d & 0xff))
|
((u32_t)(c & 0xff) << 8) | (u32_t)(d & 0xff))
|
||||||
|
|
||||||
#define ip_addr_set(dest, src) (dest)->addr = \
|
#define ip_addr_set(dest, src) (dest)->addr = \
|
||||||
((src) == NULL? 0:\
|
((src) == NULL? 0:\
|
||||||
((struct ip_addr *)src)->addr)
|
(src)->addr)
|
||||||
#define ip_addr_maskcmp(addr1, addr2, mask) (((addr1)->addr & \
|
/**
|
||||||
|
* Determine if two address are on the same network.
|
||||||
|
*
|
||||||
|
* @arg addr1 IP address 1
|
||||||
|
* @arg addr2 IP address 2
|
||||||
|
* @arg mask network identifier mask
|
||||||
|
* @return !0 if the network identifiers of both address match
|
||||||
|
*/
|
||||||
|
#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \
|
||||||
(mask)->addr) == \
|
(mask)->addr) == \
|
||||||
((addr2)->addr & \
|
((addr2)->addr & \
|
||||||
(mask)->addr))
|
(mask)->addr))
|
||||||
@@ -110,26 +133,23 @@ extern const struct ip_addr ip_addr_broadcast;
|
|||||||
|
|
||||||
#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0)
|
#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0)
|
||||||
|
|
||||||
#define ip_addr_isbroadcast(addr1, mask) (((((addr1)->addr) & ~((mask)->addr)) == \
|
u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
|
||||||
(0xffffffff & ~((mask)->addr))) || \
|
|
||||||
((addr1)->addr == 0xffffffff) || \
|
|
||||||
((addr1)->addr == 0x00000000))
|
|
||||||
|
|
||||||
#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))
|
#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))
|
||||||
|
|
||||||
|
|
||||||
#define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%u.%u.%u.%u", \
|
#define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
|
||||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \
|
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \
|
||||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \
|
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \
|
||||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \
|
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \
|
||||||
ipaddr?(unsigned int)ntohl((ipaddr)->addr) & 0xff:0U))
|
ipaddr?(u16_t)ntohl((ipaddr)->addr) & 0xff:0U))
|
||||||
|
|
||||||
/* cast to unsigned int, as it is used as argument to printf functions
|
/* cast to unsigned int, as it is used as argument to printf functions
|
||||||
* which expect integer arguments */
|
* which expect integer arguments. CSi: use cc.h formatters (conversion chars)! */
|
||||||
#define ip4_addr1(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff)
|
#define ip4_addr1(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff)
|
||||||
#define ip4_addr2(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff)
|
#define ip4_addr2(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff)
|
||||||
#define ip4_addr3(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff)
|
#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
|
||||||
#define ip4_addr4(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr)) & 0xff)
|
#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff)
|
||||||
#endif /* __LWIP_IP_ADDR_H__ */
|
#endif /* __LWIP_IP_ADDR_H__ */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -38,8 +38,9 @@
|
|||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
|
||||||
struct pbuf * ip_reass(struct pbuf *);
|
void ip_reass_tmr(void);
|
||||||
err_t ip_frag(struct pbuf *, struct netif *, struct ip_addr *);
|
struct pbuf * ip_reass(struct pbuf *p);
|
||||||
|
err_t ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest);
|
||||||
|
|
||||||
#endif /* __LWIP_IP_FRAG_H__ */
|
#endif /* __LWIP_IP_FRAG_H__ */
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -45,7 +45,7 @@ u16_t inet_chksum_pseudo(struct pbuf *p,
|
|||||||
u8_t proto, u32_t proto_len);
|
u8_t proto, u32_t proto_len);
|
||||||
|
|
||||||
u32_t inet_addr(const char *cp);
|
u32_t inet_addr(const char *cp);
|
||||||
int inet_aton(const char *cp, struct in_addr *addr);
|
s8_t inet_aton(const char *cp, struct in_addr *addr);
|
||||||
|
|
||||||
#ifndef _MACHINE_ENDIAN_H_
|
#ifndef _MACHINE_ENDIAN_H_
|
||||||
#ifndef _NETINET_IN_H
|
#ifndef _NETINET_IN_H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -81,10 +81,10 @@ void ip_input(struct pbuf *p, struct netif *inp);
|
|||||||
|
|
||||||
/* source and destination addresses in network byte order, please */
|
/* source and destination addresses in network byte order, please */
|
||||||
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||||
unsigned char ttl, unsigned char proto);
|
u8_t ttl, u8_t proto);
|
||||||
|
|
||||||
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||||
unsigned char ttl, unsigned char proto,
|
u8_t ttl, u8_t proto,
|
||||||
struct netif *netif);
|
struct netif *netif);
|
||||||
|
|
||||||
#if IP_DEBUG
|
#if IP_DEBUG
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -45,11 +45,11 @@ struct ip_addr {
|
|||||||
(ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \
|
(ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \
|
||||||
(ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0)
|
(ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0)
|
||||||
|
|
||||||
int ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
u8_t ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
||||||
struct ip_addr *mask);
|
struct ip_addr *mask);
|
||||||
int ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2);
|
u8_t ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2);
|
||||||
void ip_addr_set(struct ip_addr *dest, struct ip_addr *src);
|
void ip_addr_set(struct ip_addr *dest, struct ip_addr *src);
|
||||||
int ip_addr_isany(struct ip_addr *addr);
|
u8_t ip_addr_isany(struct ip_addr *addr);
|
||||||
|
|
||||||
|
|
||||||
#if IP_DEBUG
|
#if IP_DEBUG
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -75,7 +75,7 @@ struct api_msg_msg {
|
|||||||
struct {
|
struct {
|
||||||
void *dataptr;
|
void *dataptr;
|
||||||
u16_t len;
|
u16_t len;
|
||||||
unsigned char copy;
|
u8_t copy;
|
||||||
} w;
|
} w;
|
||||||
sys_mbox_t mbox;
|
sys_mbox_t mbox;
|
||||||
u16_t len;
|
u16_t len;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
/** print debug message only if debug message type is enabled...
|
/** print debug message only if debug message type is enabled...
|
||||||
* AND is of correct type AND is at least DBG_LEVEL
|
* AND is of correct type AND is at least DBG_LEVEL
|
||||||
*/
|
*/
|
||||||
# define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && (((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0)
|
# define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && ((s16_t)((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0)
|
||||||
# define LWIP_ERROR(x) do { LWIP_PLATFORM_DIAG(x); } while(0)
|
# define LWIP_ERROR(x) do { LWIP_PLATFORM_DIAG(x); } while(0)
|
||||||
#else /* LWIP_DEBUG */
|
#else /* LWIP_DEBUG */
|
||||||
# define LWIP_DEBUGF(debug,x)
|
# define LWIP_DEBUGF(debug,x)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ struct dhcp
|
|||||||
struct ip_addr offered_sn_mask;
|
struct ip_addr offered_sn_mask;
|
||||||
struct ip_addr offered_gw_addr;
|
struct ip_addr offered_gw_addr;
|
||||||
struct ip_addr offered_bc_addr;
|
struct ip_addr offered_bc_addr;
|
||||||
|
#define DHCP_MAX_DNS 2
|
||||||
|
u32_t dns_count; /* actual number of DNS servers obtained */
|
||||||
|
struct ip_addr offered_dns_addr[DHCP_MAX_DNS]; /* DNS server addresses */
|
||||||
|
|
||||||
u32_t offered_t0_lease; /* lease period (in seconds) */
|
u32_t offered_t0_lease; /* lease period (in seconds) */
|
||||||
u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
|
u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
|
||||||
u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */
|
u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */
|
||||||
@@ -70,10 +74,10 @@ struct dhcp_msg
|
|||||||
PACK_STRUCT_FIELD(u32_t xid);
|
PACK_STRUCT_FIELD(u32_t xid);
|
||||||
PACK_STRUCT_FIELD(u16_t secs);
|
PACK_STRUCT_FIELD(u16_t secs);
|
||||||
PACK_STRUCT_FIELD(u16_t flags);
|
PACK_STRUCT_FIELD(u16_t flags);
|
||||||
PACK_STRUCT_FIELD(u32_t ciaddr);
|
PACK_STRUCT_FIELD(struct ip_addr ciaddr);
|
||||||
PACK_STRUCT_FIELD(u32_t yiaddr);
|
PACK_STRUCT_FIELD(struct ip_addr yiaddr);
|
||||||
PACK_STRUCT_FIELD(u32_t siaddr);
|
PACK_STRUCT_FIELD(struct ip_addr siaddr);
|
||||||
PACK_STRUCT_FIELD(u32_t giaddr);
|
PACK_STRUCT_FIELD(struct ip_addr giaddr);
|
||||||
#define DHCP_CHADDR_LEN 16U
|
#define DHCP_CHADDR_LEN 16U
|
||||||
PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]);
|
PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]);
|
||||||
#define DHCP_SNAME_LEN 64U
|
#define DHCP_SNAME_LEN 64U
|
||||||
@@ -82,8 +86,12 @@ struct dhcp_msg
|
|||||||
PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]);
|
PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]);
|
||||||
PACK_STRUCT_FIELD(u32_t cookie);
|
PACK_STRUCT_FIELD(u32_t cookie);
|
||||||
#define DHCP_MIN_OPTIONS_LEN 68U
|
#define DHCP_MIN_OPTIONS_LEN 68U
|
||||||
|
/** make sure user does not configure this too small */
|
||||||
|
#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
|
||||||
|
# undef DHCP_OPTIONS_LEN
|
||||||
|
#endif
|
||||||
/** allow this to be configured in lwipopts.h, but not too small */
|
/** allow this to be configured in lwipopts.h, but not too small */
|
||||||
#if ((!defined(DHCP_OPTIONS_LEN)) || (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
|
#if (!defined(DHCP_OPTIONS_LEN))
|
||||||
/** set this to be sufficient for your options in outgoing DHCP msgs */
|
/** set this to be sufficient for your options in outgoing DHCP msgs */
|
||||||
# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN
|
# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN
|
||||||
#endif
|
#endif
|
||||||
@@ -96,11 +104,13 @@ PACK_STRUCT_END
|
|||||||
|
|
||||||
/** start DHCP configuration */
|
/** start DHCP configuration */
|
||||||
err_t dhcp_start(struct netif *netif);
|
err_t dhcp_start(struct netif *netif);
|
||||||
|
/** enforce early lease renewal (not needed normally)*/
|
||||||
|
err_t dhcp_renew(struct netif *netif);
|
||||||
|
/** release the DHCP lease, usually called before dhcp_stop()*/
|
||||||
|
err_t dhcp_release(struct netif *netif);
|
||||||
/** stop DHCP configuration */
|
/** stop DHCP configuration */
|
||||||
void dhcp_stop(struct netif *netif);
|
void dhcp_stop(struct netif *netif);
|
||||||
/** enforce lease renewal */
|
/** inform server of our manual IP address */
|
||||||
err_t dhcp_renew(struct netif *netif);
|
|
||||||
/** inform server of our IP address */
|
|
||||||
void dhcp_inform(struct netif *netif);
|
void dhcp_inform(struct netif *netif);
|
||||||
|
|
||||||
/** if enabled, check whether the offered IP address is not in use, using ARP */
|
/** if enabled, check whether the offered IP address is not in use, using ARP */
|
||||||
@@ -174,7 +184,8 @@ void dhcp_fine_tmr(void);
|
|||||||
/** BootP options */
|
/** BootP options */
|
||||||
#define DHCP_OPTION_PAD 0
|
#define DHCP_OPTION_PAD 0
|
||||||
#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */
|
#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */
|
||||||
#define DHCP_OPTION_ROUTER 3
|
#define DHCP_OPTION_ROUTER 3
|
||||||
|
#define DHCP_OPTION_DNS_SERVER 6
|
||||||
#define DHCP_OPTION_HOSTNAME 12
|
#define DHCP_OPTION_HOSTNAME 12
|
||||||
#define DHCP_OPTION_IP_TTL 23
|
#define DHCP_OPTION_IP_TTL 23
|
||||||
#define DHCP_OPTION_MTU 26
|
#define DHCP_OPTION_MTU 26
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -59,6 +59,7 @@ typedef s8_t err_t;
|
|||||||
#define ERR_USE -10 /* Address in use. */
|
#define ERR_USE -10 /* Address in use. */
|
||||||
|
|
||||||
#define ERR_IF -11 /* Low-level netif error */
|
#define ERR_IF -11 /* Low-level netif error */
|
||||||
|
#define ERR_ISCONN -12 /* Already connected. */
|
||||||
|
|
||||||
|
|
||||||
#ifdef LWIP_DEBUG
|
#ifdef LWIP_DEBUG
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -40,7 +40,9 @@
|
|||||||
|
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/dhcp.h"
|
#if LWIP_DHCP
|
||||||
|
# include "lwip/dhcp.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/** must be the maximum of all used hardware address lengths
|
/** must be the maximum of all used hardware address lengths
|
||||||
across all types of interfaces in use */
|
across all types of interfaces in use */
|
||||||
@@ -50,7 +52,8 @@
|
|||||||
|
|
||||||
/** whether the network interface is 'up'. this is
|
/** whether the network interface is 'up'. this is
|
||||||
* a software flag used to control whether this network
|
* a software flag used to control whether this network
|
||||||
* interface is enabled and processes traffic */
|
* interface is enabled and processes traffic.
|
||||||
|
*/
|
||||||
#define NETIF_FLAG_UP 0x1U
|
#define NETIF_FLAG_UP 0x1U
|
||||||
/** if set, the netif has broadcast capability */
|
/** if set, the netif has broadcast capability */
|
||||||
#define NETIF_FLAG_BROADCAST 0x2U
|
#define NETIF_FLAG_BROADCAST 0x2U
|
||||||
@@ -59,52 +62,55 @@
|
|||||||
/** if set, the interface is configured using DHCP */
|
/** if set, the interface is configured using DHCP */
|
||||||
#define NETIF_FLAG_DHCP 0x08U
|
#define NETIF_FLAG_DHCP 0x08U
|
||||||
/** if set, the interface has an active link
|
/** if set, the interface has an active link
|
||||||
* (set by the interface) */
|
* (set by the network interface driver) */
|
||||||
#define NETIF_FLAG_LINK_UP 0x10U
|
#define NETIF_FLAG_LINK_UP 0x10U
|
||||||
|
|
||||||
/** generic data structure used for all lwIP network interfaces */
|
/** Generic data structure used for all lwIP network interfaces.
|
||||||
|
* The following fields should be filled in by the initialization
|
||||||
|
* function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
|
||||||
|
|
||||||
struct netif {
|
struct netif {
|
||||||
/** pointer to next in linked list */
|
/** pointer to next in linked list */
|
||||||
struct netif *next;
|
struct netif *next;
|
||||||
/** The following fields should be filled in by the
|
|
||||||
initialization function for the device driver. */
|
|
||||||
|
|
||||||
/** IP address configuration in network byte order */
|
/** IP address configuration in network byte order */
|
||||||
struct ip_addr ip_addr;
|
struct ip_addr ip_addr;
|
||||||
struct ip_addr netmask;
|
struct ip_addr netmask;
|
||||||
struct ip_addr gw;
|
struct ip_addr gw;
|
||||||
|
|
||||||
/** This function is called by the network device driver
|
/** This function is called by the network device driver
|
||||||
to pass a packet up the TCP/IP stack. */
|
* to pass a packet up the TCP/IP stack. */
|
||||||
err_t (* input)(struct pbuf *p, struct netif *inp);
|
err_t (* input)(struct pbuf *p, struct netif *inp);
|
||||||
/** This function is called by the IP module when it wants
|
/** This function is called by the IP module when it wants
|
||||||
to send a packet on the interface. This function typically
|
* to send a packet on the interface. This function typically
|
||||||
first resolves the hardware address, then sends the packet. */
|
* first resolves the hardware address, then sends the packet. */
|
||||||
err_t (* output)(struct netif *netif, struct pbuf *p,
|
err_t (* output)(struct netif *netif, struct pbuf *p,
|
||||||
struct ip_addr *ipaddr);
|
struct ip_addr *ipaddr);
|
||||||
/** This function is called by the ARP module when it wants
|
/** This function is called by the ARP module when it wants
|
||||||
to send a packet on the interface. This function outputs
|
* to send a packet on the interface. This function outputs
|
||||||
the pbuf as-is on the link medium. */
|
* the pbuf as-is on the link medium. */
|
||||||
err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
|
err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
|
||||||
/** This field can be set by the device driver and could point
|
/** This field can be set by the device driver and could point
|
||||||
to state information for the device. */
|
* to state information for the device. */
|
||||||
void *state;
|
void *state;
|
||||||
#if LWIP_DHCP
|
#if LWIP_DHCP
|
||||||
/** the DHCP client state information for this netif */
|
/** the DHCP client state information for this netif */
|
||||||
struct dhcp *dhcp;
|
struct dhcp *dhcp;
|
||||||
#endif
|
#endif
|
||||||
/** number of bytes used in hwaddr */
|
/** number of bytes used in hwaddr */
|
||||||
unsigned char hwaddr_len;
|
u8_t hwaddr_len;
|
||||||
/** link level hardware address of this interface */
|
/** link level hardware address of this interface */
|
||||||
unsigned char hwaddr[NETIF_MAX_HWADDR_LEN];
|
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
|
||||||
/** maximum transfer unit (in bytes) */
|
/** maximum transfer unit (in bytes) */
|
||||||
u16_t mtu;
|
u16_t mtu;
|
||||||
|
/** flags (see NETIF_FLAG_ above) */
|
||||||
|
u8_t flags;
|
||||||
|
/** link type */
|
||||||
|
u8_t link_type;
|
||||||
/** descriptive abbreviation */
|
/** descriptive abbreviation */
|
||||||
char name[2];
|
char name[2];
|
||||||
/** number of this interface */
|
/** number of this interface */
|
||||||
u8_t num;
|
u8_t num;
|
||||||
/** NETIF_FLAG_* */
|
|
||||||
u8_t flags;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The list of network interfaces. */
|
/** The list of network interfaces. */
|
||||||
@@ -137,5 +143,8 @@ void netif_set_default(struct netif *netif);
|
|||||||
void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr);
|
void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr);
|
||||||
void netif_set_netmask(struct netif *netif, struct ip_addr *netmast);
|
void netif_set_netmask(struct netif *netif, struct ip_addr *netmast);
|
||||||
void netif_set_gw(struct netif *netif, struct ip_addr *gw);
|
void netif_set_gw(struct netif *netif, struct ip_addr *gw);
|
||||||
|
void netif_set_up(struct netif *netif);
|
||||||
|
void netif_set_down(struct netif *netif);
|
||||||
|
u8_t netif_is_up(struct netif *netif);
|
||||||
|
|
||||||
#endif /* __LWIP_NETIF_H__ */
|
#endif /* __LWIP_NETIF_H__ */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -67,6 +67,10 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
#define MEM_SIZE 1600
|
#define MEM_SIZE 1600
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MEMP_SANITY_CHECK
|
||||||
|
#define MEMP_SANITY_CHECK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
|
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
|
||||||
sends a lot of data out of ROM (or other static memory), this
|
sends a lot of data out of ROM (or other static memory), this
|
||||||
should be set high. */
|
should be set high. */
|
||||||
@@ -142,10 +146,10 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
|
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
|
||||||
link level header. */
|
link level header. Defaults to 14 for Ethernet. */
|
||||||
|
|
||||||
#ifndef PBUF_LINK_HLEN
|
#ifndef PBUF_LINK_HLEN
|
||||||
#define PBUF_LINK_HLEN 0
|
#define PBUF_LINK_HLEN 14
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -159,26 +163,28 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* If enabled, outgoing packets are queued during hardware address
|
* If enabled, outgoing packets are queued during hardware address
|
||||||
* resolution. The etharp.c implementation queues 1 packet only.
|
* resolution.
|
||||||
|
*
|
||||||
|
* This feature has not stabilized yet. Single-packet queueing is
|
||||||
|
* believed to be stable, multi-packet queueing is believed to
|
||||||
|
* clash with the TCP segment queueing.
|
||||||
|
*
|
||||||
|
* As multi-packet-queueing is currently disabled, enabling this
|
||||||
|
* _should_ work, but we need your testing feedback on lwip-users.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef ARP_QUEUEING
|
#ifndef ARP_QUEUEING
|
||||||
#define ARP_QUEUEING 1
|
#define ARP_QUEUEING 1
|
||||||
#endif
|
#endif
|
||||||
/** If enabled, the first packet queued will not be overwritten by
|
|
||||||
* later packets. If disabled, later packets overwrite early packets
|
/* This option is deprecated */
|
||||||
* in the queue. Default is disabled, which is recommended.
|
#ifdef ETHARP_QUEUE_FIRST
|
||||||
*/
|
#error ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h.
|
||||||
#ifndef ARP_QUEUE_FIRST
|
|
||||||
#define ARP_QUEUE_FIRST 0
|
|
||||||
#endif
|
#endif
|
||||||
/**
|
|
||||||
* If defined to 1, cache entries are updated or added for every kind of ARP traffic
|
/* This option is removed to comply with the ARP standard */
|
||||||
* or broadcast IP traffic. Recommended for routers.
|
#ifdef ETHARP_ALWAYS_INSERT
|
||||||
* If defined to 0, only existing cache entries are updated. Entries are added when
|
#error ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h.
|
||||||
* lwIP is sending to them. Recommended for embedded devices.
|
|
||||||
*/
|
|
||||||
#ifndef ETHARP_ALWAYS_INSERT
|
|
||||||
#define ETHARP_ALWAYS_INSERT 1
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ---------- IP options ---------- */
|
/* ---------- IP options ---------- */
|
||||||
@@ -218,6 +224,10 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
|
|
||||||
/* ---------- RAW options ---------- */
|
/* ---------- RAW options ---------- */
|
||||||
|
|
||||||
|
#ifndef LWIP_RAW
|
||||||
|
#define LWIP_RAW 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef RAW_TTL
|
#ifndef RAW_TTL
|
||||||
#define RAW_TTL 255
|
#define RAW_TTL 255
|
||||||
#endif
|
#endif
|
||||||
@@ -301,7 +311,7 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
|
|
||||||
/* Support loop interface (127.0.0.1) */
|
/* Support loop interface (127.0.0.1) */
|
||||||
#ifndef LWIP_HAVE_LOOPIF
|
#ifndef LWIP_HAVE_LOOPIF
|
||||||
#define LWIP_HAVE_LOOPIF 1
|
#define LWIP_HAVE_LOOPIF 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LWIP_EVENT_API
|
#ifndef LWIP_EVENT_API
|
||||||
@@ -336,8 +346,10 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
|
|
||||||
/* ---------- Socket Options ---------- */
|
/* ---------- Socket Options ---------- */
|
||||||
/* Enable SO_REUSEADDR and SO_REUSEPORT options */
|
/* Enable SO_REUSEADDR and SO_REUSEPORT options */
|
||||||
#ifndef SO_REUSE
|
#ifdef SO_REUSE
|
||||||
# define SO_REUSE 1
|
/* I removed the lot since this was an ugly hack. It broke the raw-API.
|
||||||
|
It also came with many ugly goto's, Christiaan Simons. */
|
||||||
|
#error "SO_REUSE currently unavailable, this was a hack"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -348,63 +360,68 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
|
|
||||||
#if LWIP_STATS
|
#if LWIP_STATS
|
||||||
|
|
||||||
|
#ifndef LWIP_STATS_DISPLAY
|
||||||
|
#define LWIP_STATS_DISPLAY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef LINK_STATS
|
#ifndef LINK_STATS
|
||||||
#define LINK_STATS 1
|
#define LINK_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IP_STATS
|
#ifndef IP_STATS
|
||||||
#define IP_STATS 1
|
#define IP_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IPFRAG_STATS
|
#ifndef IPFRAG_STATS
|
||||||
#define IPFRAG_STATS 1
|
#define IPFRAG_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ICMP_STATS
|
#ifndef ICMP_STATS
|
||||||
#define ICMP_STATS 1
|
#define ICMP_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef UDP_STATS
|
#ifndef UDP_STATS
|
||||||
#define UDP_STATS 1
|
#define UDP_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TCP_STATS
|
#ifndef TCP_STATS
|
||||||
#define TCP_STATS 1
|
#define TCP_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MEM_STATS
|
#ifndef MEM_STATS
|
||||||
#define MEM_STATS 1
|
#define MEM_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MEMP_STATS
|
#ifndef MEMP_STATS
|
||||||
#define MEMP_STATS 1
|
#define MEMP_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PBUF_STATS
|
#ifndef PBUF_STATS
|
||||||
#define PBUF_STATS 1
|
#define PBUF_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SYS_STATS
|
#ifndef SYS_STATS
|
||||||
#define SYS_STATS 1
|
#define SYS_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef RAW_STATS
|
#ifndef RAW_STATS
|
||||||
#define RAW_STATS 0
|
#define RAW_STATS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define LINK_STATS 0
|
#define LINK_STATS 0
|
||||||
#define IP_STATS 0
|
#define IP_STATS 0
|
||||||
#define IPFRAG_STATS 0
|
#define IPFRAG_STATS 0
|
||||||
#define ICMP_STATS 0
|
#define ICMP_STATS 0
|
||||||
#define UDP_STATS 0
|
#define UDP_STATS 0
|
||||||
#define TCP_STATS 0
|
#define TCP_STATS 0
|
||||||
#define MEM_STATS 0
|
#define MEM_STATS 0
|
||||||
#define MEMP_STATS 0
|
#define MEMP_STATS 0
|
||||||
#define PBUF_STATS 0
|
#define PBUF_STATS 0
|
||||||
#define SYS_STATS 0
|
#define SYS_STATS 0
|
||||||
#define RAW_STATS 0
|
#define RAW_STATS 0
|
||||||
|
#define LWIP_STATS_DISPLAY 0
|
||||||
|
|
||||||
#endif /* LWIP_STATS */
|
#endif /* LWIP_STATS */
|
||||||
|
|
||||||
@@ -495,6 +512,31 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
|
|
||||||
#endif /* PPP_SUPPORT */
|
#endif /* PPP_SUPPORT */
|
||||||
|
|
||||||
|
/* checksum options - set to zero for hardware checksum support */
|
||||||
|
|
||||||
|
#ifndef CHECKSUM_GEN_IP
|
||||||
|
#define CHECKSUM_GEN_IP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CHECKSUM_GEN_UDP
|
||||||
|
#define CHECKSUM_GEN_UDP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CHECKSUM_GEN_TCP
|
||||||
|
#define CHECKSUM_GEN_TCP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CHECKSUM_CHECK_IP
|
||||||
|
#define CHECKSUM_CHECK_IP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CHECKSUM_CHECK_UDP
|
||||||
|
#define CHECKSUM_CHECK_UDP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CHECKSUM_CHECK_TCP
|
||||||
|
#define CHECKSUM_CHECK_TCP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Debugging options all default to off */
|
/* Debugging options all default to off */
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -53,8 +53,8 @@ typedef enum {
|
|||||||
PBUF_POOL
|
PBUF_POOL
|
||||||
} pbuf_flag;
|
} pbuf_flag;
|
||||||
|
|
||||||
/* Definitions for the pbuf flag field (these are not the flags that
|
/* Definitions for the pbuf flag field. These are NOT the flags that
|
||||||
are passed to pbuf_alloc()). */
|
* are passed to pbuf_alloc(). */
|
||||||
#define PBUF_FLAG_RAM 0x00U /* Flags that pbuf data is stored in RAM */
|
#define PBUF_FLAG_RAM 0x00U /* Flags that pbuf data is stored in RAM */
|
||||||
#define PBUF_FLAG_ROM 0x01U /* Flags that pbuf data is stored in ROM */
|
#define PBUF_FLAG_ROM 0x01U /* Flags that pbuf data is stored in ROM */
|
||||||
#define PBUF_FLAG_POOL 0x02U /* Flags that the pbuf comes from the pbuf pool */
|
#define PBUF_FLAG_POOL 0x02U /* Flags that the pbuf comes from the pbuf pool */
|
||||||
@@ -79,10 +79,10 @@ struct pbuf {
|
|||||||
*/
|
*/
|
||||||
u16_t tot_len;
|
u16_t tot_len;
|
||||||
|
|
||||||
/* length of this buffer */
|
/** length of this buffer */
|
||||||
u16_t len;
|
u16_t len;
|
||||||
|
|
||||||
/* flags telling the type of pbuf */
|
/** flags telling the type of pbuf, see PBUF_FLAG_ */
|
||||||
u16_t flags;
|
u16_t flags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,11 +94,6 @@ struct pbuf {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* pbuf_init():
|
|
||||||
|
|
||||||
Initializes the pbuf module. The num parameter determines how many
|
|
||||||
pbufs that should be allocated to the pbuf pool, and the size
|
|
||||||
parameter specifies the size of the data allocated to those. */
|
|
||||||
void pbuf_init(void);
|
void pbuf_init(void);
|
||||||
|
|
||||||
struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag);
|
struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag);
|
||||||
@@ -112,5 +107,7 @@ void pbuf_cat(struct pbuf *h, struct pbuf *t);
|
|||||||
void pbuf_chain(struct pbuf *h, struct pbuf *t);
|
void pbuf_chain(struct pbuf *h, struct pbuf *t);
|
||||||
struct pbuf *pbuf_take(struct pbuf *f);
|
struct pbuf *pbuf_take(struct pbuf *f);
|
||||||
struct pbuf *pbuf_dechain(struct pbuf *p);
|
struct pbuf *pbuf_dechain(struct pbuf *p);
|
||||||
|
void pbuf_queue(struct pbuf *p, struct pbuf *n);
|
||||||
|
struct pbuf * pbuf_dequeue(struct pbuf *p);
|
||||||
|
|
||||||
#endif /* __LWIP_PBUF_H__ */
|
#endif /* __LWIP_PBUF_H__ */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -46,7 +46,7 @@ struct raw_pcb {
|
|||||||
|
|
||||||
u16_t protocol;
|
u16_t protocol;
|
||||||
|
|
||||||
int (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
u8_t (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||||
struct ip_addr *addr);
|
struct ip_addr *addr);
|
||||||
void *recv_arg;
|
void *recv_arg;
|
||||||
};
|
};
|
||||||
@@ -59,15 +59,15 @@ err_t raw_bind (struct raw_pcb *pcb, struct ip_addr *ipaddr);
|
|||||||
err_t raw_connect (struct raw_pcb *pcb, struct ip_addr *ipaddr);
|
err_t raw_connect (struct raw_pcb *pcb, struct ip_addr *ipaddr);
|
||||||
|
|
||||||
void raw_recv (struct raw_pcb *pcb,
|
void raw_recv (struct raw_pcb *pcb,
|
||||||
int (* recv)(void *arg, struct raw_pcb *pcb,
|
u8_t (* recv)(void *arg, struct raw_pcb *pcb,
|
||||||
struct pbuf *p,
|
struct pbuf *p,
|
||||||
struct ip_addr *addr),
|
struct ip_addr *addr),
|
||||||
void *recv_arg);
|
void *recv_arg);
|
||||||
err_t raw_send_to (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr);
|
err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr);
|
||||||
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
|
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
|
||||||
|
|
||||||
/* The following functions are the lower layer interface to RAW. */
|
/* The following functions are the lower layer interface to RAW. */
|
||||||
int raw_input (struct pbuf *p, struct netif *inp);
|
u8_t raw_input (struct pbuf *p, struct netif *inp);
|
||||||
void raw_init (void);
|
void raw_init (void);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -205,10 +205,20 @@ struct linger {
|
|||||||
unsigned char fd_bits [(FD_SETSIZE+7)/8];
|
unsigned char fd_bits [(FD_SETSIZE+7)/8];
|
||||||
} fd_set;
|
} fd_set;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* only define this in sockets.c so it does not interfere
|
||||||
|
* with other projects namespaces where timeval is present
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_TIMEVAL_PRIVATE
|
||||||
|
#define LWIP_TIMEVAL_PRIVATE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LWIP_TIMEVAL_PRIVATE
|
||||||
struct timeval {
|
struct timeval {
|
||||||
long tv_sec; /* seconds */
|
long tv_sec; /* seconds */
|
||||||
long tv_usec; /* and microseconds */
|
long tv_usec; /* and microseconds */
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -144,6 +144,13 @@ void stats_init(void);
|
|||||||
#define LINK_STATS_INC(x)
|
#define LINK_STATS_INC(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Display of statistics */
|
||||||
|
#if LWIP_STATS_DISPLAY
|
||||||
|
void stats_display(void);
|
||||||
|
#else
|
||||||
|
#define stats_display()
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __LWIP_STATS_H__ */
|
#endif /* __LWIP_STATS_H__ */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -40,8 +40,6 @@
|
|||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/icmp.h"
|
#include "lwip/icmp.h"
|
||||||
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
|
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
|
|
||||||
struct tcp_pcb;
|
struct tcp_pcb;
|
||||||
@@ -107,6 +105,7 @@ void tcp_input (struct pbuf *p, struct netif *inp);
|
|||||||
/* Used within the TCP code only: */
|
/* Used within the TCP code only: */
|
||||||
err_t tcp_output (struct tcp_pcb *pcb);
|
err_t tcp_output (struct tcp_pcb *pcb);
|
||||||
void tcp_rexmit (struct tcp_pcb *pcb);
|
void tcp_rexmit (struct tcp_pcb *pcb);
|
||||||
|
void tcp_rexmit_rto (struct tcp_pcb *pcb);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -114,7 +113,11 @@ void tcp_rexmit (struct tcp_pcb *pcb);
|
|||||||
#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
|
#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
|
||||||
#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
|
#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
|
||||||
#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
|
#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
|
||||||
|
/* is b<=a<=c? */
|
||||||
|
#if 0 /* see bug #10548 */
|
||||||
|
#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
|
||||||
|
#endif
|
||||||
|
#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
|
||||||
#define TCP_FIN 0x01U
|
#define TCP_FIN 0x01U
|
||||||
#define TCP_SYN 0x02U
|
#define TCP_SYN 0x02U
|
||||||
#define TCP_RST 0x04U
|
#define TCP_RST 0x04U
|
||||||
@@ -210,18 +213,13 @@ enum tcp_state {
|
|||||||
TIME_WAIT = 10
|
TIME_WAIT = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* the TCP protocol control block */
|
/* the TCP protocol control block */
|
||||||
struct tcp_pcb {
|
struct tcp_pcb {
|
||||||
/* Common members of all PCB types */
|
/** common PCB members */
|
||||||
IP_PCB;
|
IP_PCB;
|
||||||
|
/** protocol specific PCB members */
|
||||||
/* Protocol specific PCB members */
|
struct tcp_pcb *next; /* for the linked list */
|
||||||
|
enum tcp_state state; /* TCP state */
|
||||||
struct tcp_pcb *next; /* for the linked list */
|
|
||||||
|
|
||||||
enum tcp_state state; /* TCP state */
|
|
||||||
|
|
||||||
u8_t prio;
|
u8_t prio;
|
||||||
void *callback_arg;
|
void *callback_arg;
|
||||||
|
|
||||||
@@ -237,7 +235,7 @@ struct tcp_pcb {
|
|||||||
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
|
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
|
||||||
#define TF_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */
|
#define TF_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */
|
||||||
|
|
||||||
/* receiver varables */
|
/* receiver variables */
|
||||||
u32_t rcv_nxt; /* next seqno expected */
|
u32_t rcv_nxt; /* next seqno expected */
|
||||||
u16_t rcv_wnd; /* receiver window */
|
u16_t rcv_wnd; /* receiver window */
|
||||||
|
|
||||||
@@ -250,10 +248,10 @@ struct tcp_pcb {
|
|||||||
|
|
||||||
u16_t mss; /* maximum segment size */
|
u16_t mss; /* maximum segment size */
|
||||||
|
|
||||||
/* RTT estimation variables. */
|
/* RTT (round trip time) estimation variables */
|
||||||
u16_t rttest; /* RTT estimate in 500ms ticks */
|
u32_t rttest; /* RTT estimate in 500ms ticks */
|
||||||
u32_t rtseq; /* sequence number being timed */
|
u32_t rtseq; /* sequence number being timed */
|
||||||
s16_t sa, sv;
|
s16_t sa, sv; /* @todo document this */
|
||||||
|
|
||||||
u16_t rto; /* retransmission time-out */
|
u16_t rto; /* retransmission time-out */
|
||||||
u8_t nrtx; /* number of retransmissions */
|
u8_t nrtx; /* number of retransmissions */
|
||||||
@@ -377,7 +375,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
|
|||||||
#define TCP_EVENT_RECV(pcb,p,err,ret) \
|
#define TCP_EVENT_RECV(pcb,p,err,ret) \
|
||||||
if((pcb)->recv != NULL) \
|
if((pcb)->recv != NULL) \
|
||||||
{ ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
|
{ ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
|
||||||
pbuf_free(p); }
|
if (p) pbuf_free(p); }
|
||||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
|
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
|
||||||
if((pcb)->connected != NULL) \
|
if((pcb)->connected != NULL) \
|
||||||
(ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
|
(ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
|
||||||
@@ -389,7 +387,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
|
|||||||
(errf)((arg),(err))
|
(errf)((arg),(err))
|
||||||
#endif /* LWIP_EVENT_API */
|
#endif /* LWIP_EVENT_API */
|
||||||
|
|
||||||
/* This structure is used to repressent TCP segments when queued. */
|
/* This structure represents a TCP segment on the unsent and unacked queues */
|
||||||
struct tcp_seg {
|
struct tcp_seg {
|
||||||
struct tcp_seg *next; /* used when putting segements on a queue */
|
struct tcp_seg *next; /* used when putting segements on a queue */
|
||||||
struct pbuf *p; /* buffer containing data + TCP header */
|
struct pbuf *p; /* buffer containing data + TCP header */
|
||||||
@@ -441,7 +439,7 @@ void tcp_debug_print(struct tcp_hdr *tcphdr);
|
|||||||
void tcp_debug_print_flags(u8_t flags);
|
void tcp_debug_print_flags(u8_t flags);
|
||||||
void tcp_debug_print_state(enum tcp_state s);
|
void tcp_debug_print_state(enum tcp_state s);
|
||||||
void tcp_debug_print_pcbs(void);
|
void tcp_debug_print_pcbs(void);
|
||||||
int tcp_pcbs_sane(void);
|
s16_t tcp_pcbs_sane(void);
|
||||||
#else
|
#else
|
||||||
# define tcp_debug_print(tcphdr)
|
# define tcp_debug_print(tcphdr)
|
||||||
# define tcp_debug_print_flags(flags)
|
# define tcp_debug_print_flags(flags)
|
||||||
@@ -457,7 +455,11 @@ void tcp_timer_needed(void);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The TCP PCB lists. */
|
/* The TCP PCB lists. */
|
||||||
extern struct tcp_pcb_listen *tcp_listen_pcbs; /* List of all TCP PCBs in LISTEN state. */
|
union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
|
||||||
|
struct tcp_pcb_listen *listen_pcbs;
|
||||||
|
struct tcp_pcb *pcbs;
|
||||||
|
};
|
||||||
|
extern union tcp_listen_pcbs_t tcp_listen_pcbs;
|
||||||
extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
|
extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
|
||||||
state in which they accept or send
|
state in which they accept or send
|
||||||
data. */
|
data. */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -84,19 +84,18 @@ void udp_recv (struct udp_pcb *pcb,
|
|||||||
struct ip_addr *addr,
|
struct ip_addr *addr,
|
||||||
u16_t port),
|
u16_t port),
|
||||||
void *recv_arg);
|
void *recv_arg);
|
||||||
|
err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port);
|
||||||
err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);
|
err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);
|
||||||
|
|
||||||
#define udp_flags(pcb) ((pcb)->flags)
|
#define udp_flags(pcb) ((pcb)->flags)
|
||||||
#define udp_setflags(pcb, f) ((pcb)->flags = (f))
|
#define udp_setflags(pcb, f) ((pcb)->flags = (f))
|
||||||
|
|
||||||
|
|
||||||
/* The following functions are the lower layer interface to UDP. */
|
/* The following functions are the lower layer interface to UDP. */
|
||||||
u8_t udp_lookup (struct ip_hdr *iphdr, struct netif *inp);
|
|
||||||
void udp_input (struct pbuf *p, struct netif *inp);
|
void udp_input (struct pbuf *p, struct netif *inp);
|
||||||
void udp_init (void);
|
void udp_init (void);
|
||||||
|
|
||||||
#if UDP_DEBUG
|
#if UDP_DEBUG
|
||||||
int udp_debug_print(struct udp_hdr *udphdr);
|
void udp_debug_print(struct udp_hdr *udphdr);
|
||||||
#else
|
#else
|
||||||
#define udp_debug_print(udphdr)
|
#define udp_debug_print(udphdr)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||||
|
* Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
|
||||||
|
* Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -33,6 +35,10 @@
|
|||||||
#ifndef __NETIF_ETHARP_H__
|
#ifndef __NETIF_ETHARP_H__
|
||||||
#define __NETIF_ETHARP_H__
|
#define __NETIF_ETHARP_H__
|
||||||
|
|
||||||
|
#ifndef ETH_PAD_SIZE
|
||||||
|
#define ETH_PAD_SIZE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
@@ -46,15 +52,30 @@ struct eth_addr {
|
|||||||
PACK_STRUCT_FIELD(u8_t addr[6]);
|
PACK_STRUCT_FIELD(u8_t addr[6]);
|
||||||
} PACK_STRUCT_STRUCT;
|
} PACK_STRUCT_STRUCT;
|
||||||
PACK_STRUCT_END
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
PACK_STRUCT_BEGIN
|
PACK_STRUCT_BEGIN
|
||||||
struct eth_hdr {
|
struct eth_hdr {
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
|
||||||
|
#endif
|
||||||
PACK_STRUCT_FIELD(struct eth_addr dest);
|
PACK_STRUCT_FIELD(struct eth_addr dest);
|
||||||
PACK_STRUCT_FIELD(struct eth_addr src);
|
PACK_STRUCT_FIELD(struct eth_addr src);
|
||||||
PACK_STRUCT_FIELD(u16_t type);
|
PACK_STRUCT_FIELD(u16_t type);
|
||||||
} PACK_STRUCT_STRUCT;
|
} PACK_STRUCT_STRUCT;
|
||||||
PACK_STRUCT_END
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
PACK_STRUCT_BEGIN
|
PACK_STRUCT_BEGIN
|
||||||
/** the ARP message */
|
/** the ARP message */
|
||||||
struct etharp_hdr {
|
struct etharp_hdr {
|
||||||
@@ -64,35 +85,42 @@ struct etharp_hdr {
|
|||||||
PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
|
PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
|
||||||
PACK_STRUCT_FIELD(u16_t opcode);
|
PACK_STRUCT_FIELD(u16_t opcode);
|
||||||
PACK_STRUCT_FIELD(struct eth_addr shwaddr);
|
PACK_STRUCT_FIELD(struct eth_addr shwaddr);
|
||||||
PACK_STRUCT_FIELD(struct ip_addr sipaddr);
|
PACK_STRUCT_FIELD(struct ip_addr2 sipaddr);
|
||||||
PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
|
PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
|
||||||
PACK_STRUCT_FIELD(struct ip_addr dipaddr);
|
PACK_STRUCT_FIELD(struct ip_addr2 dipaddr);
|
||||||
} PACK_STRUCT_STRUCT;
|
} PACK_STRUCT_STRUCT;
|
||||||
PACK_STRUCT_END
|
PACK_STRUCT_END
|
||||||
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct ethip_hdr {
|
|
||||||
PACK_STRUCT_FIELD(struct eth_hdr eth);
|
|
||||||
PACK_STRUCT_FIELD(struct ip_hdr ip);
|
|
||||||
};
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
# include "arch/epstruct.h"
|
# include "arch/epstruct.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ARP_TMR_INTERVAL 10000
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/bpstruct.h"
|
||||||
|
#endif
|
||||||
|
PACK_STRUCT_BEGIN
|
||||||
|
struct ethip_hdr {
|
||||||
|
PACK_STRUCT_FIELD(struct eth_hdr eth);
|
||||||
|
PACK_STRUCT_FIELD(struct ip_hdr ip);
|
||||||
|
} PACK_STRUCT_STRUCT;
|
||||||
|
PACK_STRUCT_END
|
||||||
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
|
# include "arch/epstruct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** 5 seconds period */
|
||||||
|
#define ARP_TMR_INTERVAL 5000
|
||||||
|
|
||||||
#define ETHTYPE_ARP 0x0806
|
#define ETHTYPE_ARP 0x0806
|
||||||
#define ETHTYPE_IP 0x0800
|
#define ETHTYPE_IP 0x0800
|
||||||
|
|
||||||
void etharp_init(void);
|
void etharp_init(void);
|
||||||
void etharp_tmr(void);
|
void etharp_tmr(void);
|
||||||
struct pbuf *etharp_ip_input(struct netif *netif, struct pbuf *p);
|
void etharp_ip_input(struct netif *netif, struct pbuf *p);
|
||||||
struct pbuf *etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
|
void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
|
||||||
struct pbuf *p);
|
struct pbuf *p);
|
||||||
struct pbuf *etharp_output(struct netif *netif, struct ip_addr *ipaddr,
|
err_t etharp_output(struct netif *netif, struct ip_addr *ipaddr,
|
||||||
struct pbuf *q);
|
struct pbuf *q);
|
||||||
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q);
|
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q);
|
||||||
|
err_t etharp_request(struct netif *netif, struct ip_addr *ipaddr);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __NETIF_ARP_H__ */
|
#endif /* __NETIF_ARP_H__ */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
This directory contains generic network interface device drivers that
|
This directory contains generic network interface device drivers that
|
||||||
don't contain any hardware or architecture specific code. The files
|
do not contain any hardware or architecture specific code. The files
|
||||||
are:
|
are:
|
||||||
|
|
||||||
etharp.c
|
etharp.c
|
||||||
Implements the ARP (Address Resolution Protocol) over
|
Implements the ARP (Address Resolution Protocol) over
|
||||||
Ethernet. The code in this file should be used together with
|
Ethernet. The code in this file should be used together with
|
||||||
Ethernet device drivers.
|
Ethernet device drivers. Note that this module has been
|
||||||
|
largely made Ethernet independent so you should be able to
|
||||||
|
adapt this for other link layers (such as Firewire).
|
||||||
|
|
||||||
ethernetif.c
|
ethernetif.c
|
||||||
An example of how an Ethernet device driver could look. This
|
An example of how an Ethernet device driver could look. This
|
||||||
file can be used as a "skeleton" for developing new Ethernet
|
file can be used as a "skeleton" for developing new Ethernet
|
||||||
network device drivers. It uses the etharp.c ARP code.
|
network device drivers. It uses the etharp.c ARP code.
|
||||||
!!!THIS FILE IS NOT IN SYNC WITH CURRENT CODE !!!!
|
|
||||||
|
|
||||||
loopif.c
|
loopif.c
|
||||||
An example network interface that shows how a "loopback"
|
An example network interface that shows how a "loopback"
|
||||||
|
|||||||
1001
src/netif/etharp.c
1001
src/netif/etharp.c
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -35,8 +35,6 @@
|
|||||||
* drivers for lwIP. Add code to the low_level functions and do a
|
* drivers for lwIP. Add code to the low_level functions and do a
|
||||||
* search-and-replace for the word "ethernetif" to replace it with
|
* search-and-replace for the word "ethernetif" to replace it with
|
||||||
* something that better describes your network interface.
|
* something that better describes your network interface.
|
||||||
*
|
|
||||||
* THIS CODE NEEDS TO BE FIXED - IT IS NOT In SYNC WITH CURRENT ETHARP API
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
@@ -44,12 +42,13 @@
|
|||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
#include <lwip/stats.h>
|
||||||
|
|
||||||
#include "netif/arp.h"
|
#include "netif/etharp.h"
|
||||||
|
|
||||||
/* Define those to better describe your network interface. */
|
/* Define those to better describe your network interface. */
|
||||||
#define IFNAME0 'e'
|
#define IFNAME0 'e'
|
||||||
#define IFNAME1 't'
|
#define IFNAME1 'n'
|
||||||
|
|
||||||
struct ethernetif {
|
struct ethernetif {
|
||||||
struct eth_addr *ethaddr;
|
struct eth_addr *ethaddr;
|
||||||
@@ -63,13 +62,10 @@ static void ethernetif_input(struct netif *netif);
|
|||||||
static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
|
static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
|
||||||
struct ip_addr *ipaddr);
|
struct ip_addr *ipaddr);
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
low_level_init(struct netif *netif)
|
low_level_init(struct netif *netif)
|
||||||
{
|
{
|
||||||
struct ethernetif *ethernetif;
|
struct ethernetif *ethernetif = netif->state;
|
||||||
|
|
||||||
ethernetif = netif->state;
|
|
||||||
|
|
||||||
/* set MAC hardware address length */
|
/* set MAC hardware address length */
|
||||||
netif->hwaddr_len = 6;
|
netif->hwaddr_len = 6;
|
||||||
@@ -77,7 +73,7 @@ low_level_init(struct netif *netif)
|
|||||||
/* set MAC hardware address */
|
/* set MAC hardware address */
|
||||||
netif->hwaddr[0] = ;
|
netif->hwaddr[0] = ;
|
||||||
...
|
...
|
||||||
netif->hwaddr[6] = ;
|
netif->hwaddr[5] = ;
|
||||||
|
|
||||||
/* maximum transfer unit */
|
/* maximum transfer unit */
|
||||||
netif->mtu = 1500;
|
netif->mtu = 1500;
|
||||||
@@ -97,14 +93,18 @@ low_level_init(struct netif *netif)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
static err_t
|
static err_t
|
||||||
low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
|
low_level_output(struct netif *netif, struct pbuf *p)
|
||||||
{
|
{
|
||||||
|
struct ethernetif *ethernetif = netif->state;
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
|
|
||||||
initiate transfer();
|
initiate transfer();
|
||||||
|
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
||||||
|
#endif
|
||||||
|
|
||||||
for(q = p; q != NULL; q = q->next) {
|
for(q = p; q != NULL; q = q->next) {
|
||||||
/* Send the data from the pbuf to the interface, one pbuf at a
|
/* Send the data from the pbuf to the interface, one pbuf at a
|
||||||
time. The size of the data in each pbuf is kept in the ->len
|
time. The size of the data in each pbuf is kept in the ->len
|
||||||
@@ -113,8 +113,12 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
signal that packet should be sent();
|
signal that packet should be sent();
|
||||||
|
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef LINK_STATS
|
#if LINK_STATS
|
||||||
lwip_stats.link.xmit++;
|
lwip_stats.link.xmit++;
|
||||||
#endif /* LINK_STATS */
|
#endif /* LINK_STATS */
|
||||||
|
|
||||||
@@ -130,8 +134,9 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static struct pbuf *
|
static struct pbuf *
|
||||||
low_level_input(struct ethernetif *ethernetif)
|
low_level_input(struct netif *netif)
|
||||||
{
|
{
|
||||||
|
struct ethernetif *ethernetif = netif->state;
|
||||||
struct pbuf *p, *q;
|
struct pbuf *p, *q;
|
||||||
u16_t len;
|
u16_t len;
|
||||||
|
|
||||||
@@ -139,25 +144,39 @@ low_level_input(struct ethernetif *ethernetif)
|
|||||||
variable. */
|
variable. */
|
||||||
len = ;
|
len = ;
|
||||||
|
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We allocate a pbuf chain of pbufs from the pool. */
|
/* We allocate a pbuf chain of pbufs from the pool. */
|
||||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||||
|
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
|
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We iterate over the pbuf chain until we have read the entire
|
/* We iterate over the pbuf chain until we have read the entire
|
||||||
packet into the pbuf. */
|
* packet into the pbuf. */
|
||||||
for(q = p; q != NULL; q = q->next) {
|
for(q = p; q != NULL; q = q->next) {
|
||||||
/* Read enough bytes to fill this pbuf in the chain. The
|
/* Read enough bytes to fill this pbuf in the chain. The
|
||||||
available data in the pbuf is given by the q->len
|
* available data in the pbuf is given by the q->len
|
||||||
variable. */
|
* variable. */
|
||||||
read data into(q->payload, q->len);
|
read data into(q->payload, q->len);
|
||||||
}
|
}
|
||||||
acknowledge that packet has been read();
|
acknowledge that packet has been read();
|
||||||
#ifdef LINK_STATS
|
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LINK_STATS
|
||||||
lwip_stats.link.recv++;
|
lwip_stats.link.recv++;
|
||||||
#endif /* LINK_STATS */
|
#endif /* LINK_STATS */
|
||||||
} else {
|
} else {
|
||||||
drop packet();
|
drop packet();
|
||||||
#ifdef LINK_STATS
|
#if LINK_STATS
|
||||||
lwip_stats.link.memerr++;
|
lwip_stats.link.memerr++;
|
||||||
lwip_stats.link.drop++;
|
lwip_stats.link.drop++;
|
||||||
#endif /* LINK_STATS */
|
#endif /* LINK_STATS */
|
||||||
@@ -171,7 +190,7 @@ low_level_input(struct ethernetif *ethernetif)
|
|||||||
*
|
*
|
||||||
* This function is called by the TCP/IP stack when an IP packet
|
* This function is called by the TCP/IP stack when an IP packet
|
||||||
* should be sent. It calls the function called low_level_output() to
|
* should be sent. It calls the function called low_level_output() to
|
||||||
* do the actuall transmission of the packet.
|
* do the actual transmission of the packet.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -179,90 +198,10 @@ static err_t
|
|||||||
ethernetif_output(struct netif *netif, struct pbuf *p,
|
ethernetif_output(struct netif *netif, struct pbuf *p,
|
||||||
struct ip_addr *ipaddr)
|
struct ip_addr *ipaddr)
|
||||||
{
|
{
|
||||||
struct ethernetif *ethernetif;
|
|
||||||
struct pbuf *q;
|
|
||||||
struct eth_hdr *ethhdr;
|
|
||||||
struct eth_addr *dest, mcastaddr;
|
|
||||||
struct ip_addr *queryaddr;
|
|
||||||
err_t err;
|
|
||||||
u8_t i;
|
|
||||||
|
|
||||||
ethernetif = netif->state;
|
/* resolve hardware address, then send (or queue) packet */
|
||||||
|
return etharp_output(netif, ipaddr, p);
|
||||||
/* Make room for Ethernet header. */
|
|
||||||
if (pbuf_header(p, 14) != 0) {
|
|
||||||
/* The pbuf_header() call shouldn't fail, but we allocate an extra
|
|
||||||
pbuf just in case. */
|
|
||||||
q = pbuf_alloc(PBUF_LINK, 14, PBUF_RAM);
|
|
||||||
if (q == NULL) {
|
|
||||||
#ifdef LINK_STATS
|
|
||||||
lwip_stats.link.drop++;
|
|
||||||
lwip_stats.link.memerr++;
|
|
||||||
#endif /* LINK_STATS */
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
pbuf_chain(q, p);
|
|
||||||
p = q;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Construct Ethernet header. Start with looking up deciding which
|
|
||||||
MAC address to use as a destination address. Broadcasts and
|
|
||||||
multicasts are special, all other addresses are looked up in the
|
|
||||||
ARP table. */
|
|
||||||
queryaddr = ipaddr;
|
|
||||||
if (ip_addr_isany(ipaddr) ||
|
|
||||||
ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
|
|
||||||
dest = (struct eth_addr *)ðbroadcast;
|
|
||||||
} else if (ip_addr_ismulticast(ipaddr)) {
|
|
||||||
/* Hash IP multicast address to MAC address. */
|
|
||||||
mcastaddr.addr[0] = 0x01;
|
|
||||||
mcastaddr.addr[1] = 0x0;
|
|
||||||
mcastaddr.addr[2] = 0x5e;
|
|
||||||
mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
|
|
||||||
mcastaddr.addr[4] = ip4_addr3(ipaddr);
|
|
||||||
mcastaddr.addr[5] = ip4_addr4(ipaddr);
|
|
||||||
dest = &mcastaddr;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
|
|
||||||
/* Use destination IP address if the destination is on the same
|
|
||||||
subnet as we are. */
|
|
||||||
queryaddr = ipaddr;
|
|
||||||
} else {
|
|
||||||
/* Otherwise we use the default router as the address to send
|
|
||||||
the Ethernet frame to. */
|
|
||||||
queryaddr = &(netif->gw);
|
|
||||||
}
|
|
||||||
dest = arp_lookup(queryaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* If the arp_lookup() didn't find an address, we send out an ARP
|
|
||||||
query for the IP address. */
|
|
||||||
if (dest == NULL) {
|
|
||||||
q = arp_query(netif, ethernetif->ethaddr, queryaddr);
|
|
||||||
if (q != NULL) {
|
|
||||||
err = low_level_output(ethernetif, q);
|
|
||||||
pbuf_free(q);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
#ifdef LINK_STATS
|
|
||||||
lwip_stats.link.drop++;
|
|
||||||
lwip_stats.link.memerr++;
|
|
||||||
#endif /* LINK_STATS */
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
ethhdr = p->payload;
|
|
||||||
|
|
||||||
for(i = 0; i < 6; i++) {
|
|
||||||
ethhdr->dest.addr[i] = dest->addr[i];
|
|
||||||
ethhdr->src.addr[i] = ethernetif->ethaddr->addr[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
ethhdr->type = htons(ETHTYPE_IP);
|
|
||||||
|
|
||||||
return low_level_output(ethernetif, p);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -282,43 +221,47 @@ ethernetif_input(struct netif *netif)
|
|||||||
struct eth_hdr *ethhdr;
|
struct eth_hdr *ethhdr;
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
|
|
||||||
|
|
||||||
ethernetif = netif->state;
|
ethernetif = netif->state;
|
||||||
|
|
||||||
p = low_level_input(ethernetif);
|
/* move received packet into a new pbuf */
|
||||||
|
p = low_level_input(netif);
|
||||||
|
/* no packet could be read, silently ignore this */
|
||||||
|
if (p == NULL) return;
|
||||||
|
/* points to packet payload, which starts with an Ethernet header */
|
||||||
|
ethhdr = p->payload;
|
||||||
|
|
||||||
if (p != NULL) {
|
#if LINK_STATS
|
||||||
|
lwip_stats.link.recv++;
|
||||||
#ifdef LINK_STATS
|
|
||||||
lwip_stats.link.recv++;
|
|
||||||
#endif /* LINK_STATS */
|
#endif /* LINK_STATS */
|
||||||
|
|
||||||
ethhdr = p->payload;
|
ethhdr = p->payload;
|
||||||
|
|
||||||
switch (htons(ethhdr->type)) {
|
switch (htons(ethhdr->type)) {
|
||||||
case ETHTYPE_IP:
|
/* IP packet? */
|
||||||
arp_ip_input(netif, p);
|
case ETHTYPE_IP:
|
||||||
pbuf_header(p, -14);
|
/* update ARP table */
|
||||||
netif->input(p, netif);
|
etharp_ip_input(netif, p);
|
||||||
break;
|
/* skip Ethernet header */
|
||||||
|
pbuf_header(p, -sizeof(struct eth_hdr));
|
||||||
|
/* pass to network layer */
|
||||||
|
netif->input(p, netif);
|
||||||
|
break;
|
||||||
|
|
||||||
case ETHTYPE_ARP:
|
case ETHTYPE_ARP:
|
||||||
p = arp_arp_input(netif, ethernetif->ethaddr, p);
|
/* pass p to ARP module */
|
||||||
if (p != NULL) {
|
etharp_arp_input(netif, ethernetif->ethaddr, p);
|
||||||
low_level_output(ethernetif, p);
|
|
||||||
pbuf_free(p);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
|
p = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
arp_timer(void *arg)
|
arp_timer(void *arg)
|
||||||
{
|
{
|
||||||
arp_tmr();
|
etharp_tmr();
|
||||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,12 +274,19 @@ arp_timer(void *arg)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
err_t
|
||||||
ethernetif_init(struct netif *netif)
|
ethernetif_init(struct netif *netif)
|
||||||
{
|
{
|
||||||
struct ethernetif *ethernetif;
|
struct ethernetif *ethernetif;
|
||||||
|
|
||||||
ethernetif = mem_malloc(sizeof(struct ethernetif));
|
ethernetif = mem_malloc(sizeof(struct ethernetif));
|
||||||
|
|
||||||
|
if (ethernetif == NULL)
|
||||||
|
{
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
netif->state = ethernetif;
|
netif->state = ethernetif;
|
||||||
netif->name[0] = IFNAME0;
|
netif->name[0] = IFNAME0;
|
||||||
netif->name[1] = IFNAME1;
|
netif->name[1] = IFNAME1;
|
||||||
@@ -346,8 +296,11 @@ ethernetif_init(struct netif *netif)
|
|||||||
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
|
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
|
||||||
|
|
||||||
low_level_init(netif);
|
low_level_init(netif);
|
||||||
arp_init();
|
|
||||||
|
etharp_init();
|
||||||
|
|
||||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -58,7 +58,7 @@ loopif_output(struct netif *netif, struct pbuf *p,
|
|||||||
struct ip_addr *ipaddr)
|
struct ip_addr *ipaddr)
|
||||||
{
|
{
|
||||||
struct pbuf *q, *r;
|
struct pbuf *q, *r;
|
||||||
char *ptr;
|
u8_t *ptr;
|
||||||
void **arg;
|
void **arg;
|
||||||
|
|
||||||
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
|
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
|
||||||
|
|||||||
@@ -610,7 +610,7 @@ int get_secret(
|
|||||||
|
|
||||||
addrs = NULL;
|
addrs = NULL;
|
||||||
|
|
||||||
if(!client || !client[0] && strcmp(client, ppp_settings.user)) {
|
if(!client || !client[0] || strcmp(client, ppp_settings.user)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
*
|
*
|
||||||
* $Id: chpms.h,v 1.2 2003/11/14 14:56:31 likewise Exp $
|
* $Id: chpms.h,v 1.3 2004/02/07 00:30:03 likewise Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CHPMS_H
|
#ifndef CHPMS_H
|
||||||
|
|||||||
@@ -49,6 +49,8 @@
|
|||||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "ppp.h"
|
#include "ppp.h"
|
||||||
#if PPP_SUPPORT > 0
|
#if PPP_SUPPORT > 0
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
@@ -178,6 +180,20 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
|
|||||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||||
/**********************************/
|
/**********************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non-standard inet_ntoa left here for compat with original ppp
|
||||||
|
* sources. Assumes u32_t instead of struct in_addr.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char * _inet_ntoa(u32_t n)
|
||||||
|
{
|
||||||
|
struct in_addr ia;
|
||||||
|
ia.s_addr = n;
|
||||||
|
return inet_ntoa(ia);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define inet_ntoa _inet_ntoa
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ipcp_init - Initialize IPCP.
|
* ipcp_init - Initialize IPCP.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -49,6 +49,9 @@
|
|||||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "ppp.h"
|
#include "ppp.h"
|
||||||
#if PPP_SUPPORT > 0
|
#if PPP_SUPPORT > 0
|
||||||
#include "fsm.h"
|
#include "fsm.h"
|
||||||
@@ -1232,7 +1235,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
ho->neg_mru = 1; /* Remember he sent MRU */
|
ho->neg_mru = 1; /* Remember he sent MRU */
|
||||||
ho->mru = cishort; /* And remember value */
|
ho->mru = cishort; /* And remember value */
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " MRU %d", cishort);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@@ -1265,7 +1268,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
ho->neg_asyncmap = 1;
|
ho->neg_asyncmap = 1;
|
||||||
ho->asyncmap = cilong;
|
ho->asyncmap = cilong;
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " ASYNCMAP=%lX", cilong);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@@ -1317,7 +1320,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
}
|
}
|
||||||
ho->neg_upap = 1;
|
ho->neg_upap = 1;
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " PAP (%X)", cishort);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@@ -1355,7 +1358,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " CHAP %X,%d", cishort, cichar);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, cichar);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
ho->chap_mdtype = cichar; /* save md type */
|
ho->chap_mdtype = cichar; /* save md type */
|
||||||
@@ -1387,7 +1390,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
GETSHORT(cishort, p);
|
GETSHORT(cishort, p);
|
||||||
GETLONG(cilong, p);
|
GETLONG(cilong, p);
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " QUALITY (%x %x)", cishort, (unsigned int) cilong);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " QUALITY (%x %x)", cishort, (unsigned int) cilong);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1419,7 +1422,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
}
|
}
|
||||||
GETLONG(cilong, p);
|
GETLONG(cilong, p);
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " MAGICNUMBER (%lX)", cilong);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1442,7 +1445,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
case CI_PCOMPRESSION:
|
case CI_PCOMPRESSION:
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " PCOMPRESSION");
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION");
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
if (!ao->neg_pcompression ||
|
if (!ao->neg_pcompression ||
|
||||||
@@ -1455,7 +1458,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
case CI_ACCOMPRESSION:
|
case CI_ACCOMPRESSION:
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " ACCOMPRESSION");
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION");
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
if (!ao->neg_accompression ||
|
if (!ao->neg_accompression ||
|
||||||
@@ -1468,7 +1471,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
case CI_MRRU:
|
case CI_MRRU:
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " CI_MRRU");
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU");
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
orc = CONFREJ;
|
orc = CONFREJ;
|
||||||
@@ -1476,7 +1479,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
case CI_SSNHF:
|
case CI_SSNHF:
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " CI_SSNHF");
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF");
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
orc = CONFREJ;
|
orc = CONFREJ;
|
||||||
@@ -1484,7 +1487,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
case CI_EPDISC:
|
case CI_EPDISC:
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " CI_EPDISC");
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC");
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
orc = CONFREJ;
|
orc = CONFREJ;
|
||||||
@@ -1492,7 +1495,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
#if TRACELCP
|
#if TRACELCP
|
||||||
sprintf(&traceBuf[traceNdx], " unknown %d", citype);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
orc = CONFREJ;
|
orc = CONFREJ;
|
||||||
|
|||||||
@@ -78,6 +78,9 @@
|
|||||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "ppp.h"
|
#include "ppp.h"
|
||||||
#if PPP_SUPPORT > 0
|
#if PPP_SUPPORT > 0
|
||||||
#include "randm.h"
|
#include "randm.h"
|
||||||
@@ -1233,7 +1236,7 @@ static void pppMain(void *arg)
|
|||||||
pppInProc(pd, p->payload, c);
|
pppInProc(pd, p->payload, c);
|
||||||
} else {
|
} else {
|
||||||
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
|
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
|
||||||
sys_msleep(250); /* give other tasks a chance to run */
|
sys_msleep(1); /* give other tasks a chance to run */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,12 @@
|
|||||||
* for a 16 bit processor.
|
* for a 16 bit processor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "ppp.h"
|
#include "ppp.h"
|
||||||
#include "vj.h"
|
#include "vj.h"
|
||||||
#include "pppdebug.h"
|
#include "pppdebug.h"
|
||||||
|
|
||||||
|
|
||||||
#if VJ_SUPPORT > 0
|
#if VJ_SUPPORT > 0
|
||||||
|
|
||||||
#if LINK_STATS
|
#if LINK_STATS
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Definitions for tcp compression routines.
|
* Definitions for tcp compression routines.
|
||||||
*
|
*
|
||||||
* $Id: vj.h,v 1.3 2003/11/14 14:56:31 likewise Exp $
|
* $Id: vj.h,v 1.4 2004/02/07 00:30:03 likewise Exp $
|
||||||
*
|
*
|
||||||
* Copyright (c) 1989 Regents of the University of California.
|
* Copyright (c) 1989 Regents of the University of California.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, Swedish Institute of Computer Science.
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -32,9 +32,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is an arch independent SLIP netif. The specific serial hooks must be provided
|
* This is an arch independent SLIP netif. The specific serial hooks must be
|
||||||
* by another file.They are sio_open, sio_recv and sio_send
|
* provided by another file. They are sio_open, sio_recv and sio_send
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "netif/slipif.h"
|
#include "netif/slipif.h"
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
@@ -55,32 +55,32 @@
|
|||||||
* Send a pbuf doing the necessary SLIP encapsulation
|
* Send a pbuf doing the necessary SLIP encapsulation
|
||||||
*
|
*
|
||||||
* Uses the serial layer's sio_send()
|
* Uses the serial layer's sio_send()
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
|
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
|
||||||
{
|
{
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
int i;
|
u16_t i;
|
||||||
u8_t c;
|
u8_t c;
|
||||||
|
|
||||||
/* Send pbuf out on the serial I/O device. */
|
/* Send pbuf out on the serial I/O device. */
|
||||||
sio_send(SLIP_END, netif->state);
|
sio_send(SLIP_END, netif->state);
|
||||||
|
|
||||||
for(q = p; q != NULL; q = q->next) {
|
for (q = p; q != NULL; q = q->next) {
|
||||||
for(i = 0; i < q->len; i++) {
|
for (i = 0; i < q->len; i++) {
|
||||||
c = ((u8_t *)q->payload)[i];
|
c = ((u8_t *)q->payload)[i];
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case SLIP_END:
|
case SLIP_END:
|
||||||
sio_send(SLIP_ESC, netif->state);
|
sio_send(SLIP_ESC, netif->state);
|
||||||
sio_send(SLIP_ESC_END, netif->state);
|
sio_send(SLIP_ESC_END, netif->state);
|
||||||
break;
|
break;
|
||||||
case SLIP_ESC:
|
case SLIP_ESC:
|
||||||
sio_send(SLIP_ESC, netif->state);
|
sio_send(SLIP_ESC, netif->state);
|
||||||
sio_send(SLIP_ESC_ESC, netif->state);
|
sio_send(SLIP_ESC_ESC, netif->state);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sio_send(c, netif->state);
|
sio_send(c, netif->state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,14 +94,14 @@ slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
|
|||||||
* Poll the serial layer by calling sio_recv()
|
* Poll the serial layer by calling sio_recv()
|
||||||
*
|
*
|
||||||
* @return The IP packet when SLIP_END is received
|
* @return The IP packet when SLIP_END is received
|
||||||
*/
|
*/
|
||||||
static struct pbuf *
|
static struct pbuf *
|
||||||
slipif_input( struct netif * netif )
|
slipif_input(struct netif *netif)
|
||||||
{
|
{
|
||||||
u8_t c;
|
u8_t c;
|
||||||
struct pbuf *p, *q;
|
struct pbuf *p, *q;
|
||||||
int recved;
|
u16_t recved;
|
||||||
int i;
|
u16_t i;
|
||||||
|
|
||||||
q = p = NULL;
|
q = p = NULL;
|
||||||
recved = i = 0;
|
recved = i = 0;
|
||||||
@@ -112,13 +112,13 @@ slipif_input( struct netif * netif )
|
|||||||
switch (c) {
|
switch (c) {
|
||||||
case SLIP_END:
|
case SLIP_END:
|
||||||
if (recved > 0) {
|
if (recved > 0) {
|
||||||
/* Received whole packet. */
|
/* Received whole packet. */
|
||||||
pbuf_realloc(q, recved);
|
pbuf_realloc(q, recved);
|
||||||
|
|
||||||
LINK_STATS_INC(link.recv);
|
LINK_STATS_INC(link.recv);
|
||||||
|
|
||||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
|
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -126,51 +126,54 @@ slipif_input( struct netif * netif )
|
|||||||
c = sio_recv(netif->state);
|
c = sio_recv(netif->state);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case SLIP_ESC_END:
|
case SLIP_ESC_END:
|
||||||
c = SLIP_END;
|
c = SLIP_END;
|
||||||
break;
|
break;
|
||||||
case SLIP_ESC_ESC:
|
case SLIP_ESC_ESC:
|
||||||
c = SLIP_ESC;
|
c = SLIP_ESC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
|
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
|
||||||
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
|
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
|
||||||
|
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
LINK_STATS_INC(link.drop);
|
LINK_STATS_INC(link.drop);
|
||||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
|
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q != NULL) {
|
if (q != NULL) {
|
||||||
pbuf_cat(q, p);
|
pbuf_cat(q, p);
|
||||||
} else {
|
} else {
|
||||||
q = p;
|
q = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p != NULL && recved < MAX_SIZE) {
|
if (p != NULL && recved < MAX_SIZE) {
|
||||||
((u8_t *)p->payload)[i] = c;
|
((u8_t *)p->payload)[i] = c;
|
||||||
recved++;
|
recved++;
|
||||||
i++;
|
i++;
|
||||||
if (i >= p->len) {
|
if (i >= p->len) {
|
||||||
i = 0;
|
i = 0;
|
||||||
p = NULL;
|
if (p->next != NULL && p->next->len > 0)
|
||||||
}
|
p = p->next;
|
||||||
|
else
|
||||||
|
p = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SLIP input thread
|
* The SLIP input thread.
|
||||||
*
|
*
|
||||||
* Feed the IP layer with incoming packets
|
* Feed the IP layer with incoming packets
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
slipif_loop(void *nf)
|
slipif_loop(void *nf)
|
||||||
{
|
{
|
||||||
@@ -188,21 +191,22 @@ slipif_loop(void *nf)
|
|||||||
*
|
*
|
||||||
* Call the arch specific sio_open and remember
|
* Call the arch specific sio_open and remember
|
||||||
* the opened device in the state field of the netif.
|
* the opened device in the state field of the netif.
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
slipif_init(struct netif *netif)
|
slipif_init(struct netif *netif)
|
||||||
{
|
{
|
||||||
|
|
||||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%x\n", (int)netif->num));
|
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num));
|
||||||
|
|
||||||
netif->name[0] = 's';
|
netif->name[0] = 's';
|
||||||
netif->name[1] = 'l';
|
netif->name[1] = 'l';
|
||||||
netif->output = slipif_output;
|
netif->output = slipif_output;
|
||||||
netif->mtu = 1500;
|
netif->mtu = 1500;
|
||||||
|
netif->flags = NETIF_FLAG_POINTTOPOINT;
|
||||||
|
|
||||||
netif->state = sio_open(netif->num);
|
netif->state = sio_open(netif->num);
|
||||||
if (!netif->state)
|
if (!netif->state)
|
||||||
return ERR_IF;
|
return ERR_IF;
|
||||||
|
|
||||||
sys_thread_new(slipif_loop, netif, SLIPIF_THREAD_PRIO);
|
sys_thread_new(slipif_loop, netif, SLIPIF_THREAD_PRIO);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user