forked from Imagelibrary/lwip
Compare commits
239 Commits
merged_fro
...
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 |
181
CHANGELOG
181
CHANGELOG
@@ -1,12 +1,187 @@
|
||||
TODO
|
||||
FUTURE
|
||||
|
||||
* TODO: The lwIP source code makes some invalid assumptions on processor
|
||||
word-length, storage sizes and alignment. See the mailing lists for
|
||||
problems with exoteric architectures showing these problems.
|
||||
We still have to fix this neatly.
|
||||
problems with exoteric (/DSP) architectures showing these problems.
|
||||
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
|
||||
|
||||
(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)
|
||||
|
||||
++ 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
|
||||
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.
|
||||
|
||||
FEATURES
|
||||
@@ -42,29 +42,11 @@ CVS source tree.
|
||||
The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and
|
||||
contributions (such as platform ports) are in the 'contrib' module.
|
||||
|
||||
The CVS main trunk is the stable branch, which contains bug fixes and
|
||||
tested features. The latest stable branch 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 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
|
||||
See doc/savannah.txt for details on CVS server access for users and
|
||||
developers.
|
||||
|
||||
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:
|
||||
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/
|
||||
|
||||
@@ -6,7 +6,7 @@ in lwIP development.
|
||||
2 How to contribute to lwIP
|
||||
|
||||
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
|
||||
to fixes or questions might often come late. Hopefully the bug and patch tracking
|
||||
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:
|
||||
|
||||
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).
|
||||
4. one space between keyword and opening bracket.
|
||||
5. no space between function and opening bracket.
|
||||
6. one space and no newline before opening curly braces of a block.
|
||||
7. spaces surrounding assignment and comparisons.
|
||||
8. use current source code style as further reference.
|
||||
7. closing curly brace on a single line.
|
||||
8. spaces surrounding assignment and comparisons.
|
||||
9. use current source code style as further reference.
|
||||
|
||||
2.2 Source code documentation style:
|
||||
|
||||
1. JavaDoc compliant and Doxygen compatible.
|
||||
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.
|
||||
|
||||
2.3 Bug reports and patches:
|
||||
@@ -55,9 +56,7 @@ features of Savannah help us not lose users' input.
|
||||
|
||||
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
|
||||
could benefit others[1] you might want to post an url to a tarball or zip from which it can be imported
|
||||
to the contrib CVS module. Then you get CVS access and have to maintain your port :)
|
||||
|
||||
[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.
|
||||
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
|
||||
you think it could benefit others[1] you might want discuss this on the mailing list. You
|
||||
can also ask for CVS access to submit and maintain your port in the contrib CVS module.
|
||||
|
||||
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
|
||||
to use for communication with the TCP/IP code: the sequential API
|
||||
(often just called "the API") and the raw TCP/IP interface. This
|
||||
document is intended as a description of the latter. For lwIP versions
|
||||
lower than 0.5, this API was not documented.
|
||||
to use for communication with the TCP/IP code:
|
||||
* low-level "core" / "callback" or "raw" API.
|
||||
* higher-level "sequential" API.
|
||||
|
||||
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
|
||||
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
|
||||
code and the application program must reside in different execution
|
||||
contexts (threads).
|
||||
|
||||
** The remainder of this document discusses the "raw" API. **
|
||||
|
||||
The raw TCP/IP interface allows the application program to integrate
|
||||
better with the TCP/IP code. Program execution is event based by
|
||||
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
|
||||
program using the raw TCP/IP interface.
|
||||
|
||||
|
||||
--- Callbacks
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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.
|
||||
|
||||
@@ -2,7 +2,7 @@ Daily Use Guide for using Savannah for lwIP
|
||||
|
||||
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)
|
||||
3 - Merging from DEVEL branch to main trunk (stable branch)
|
||||
4 - How to release lwIP
|
||||
@@ -15,21 +15,53 @@ Table of Contents:
|
||||
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
|
||||
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
|
||||
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
|
||||
|
||||
Or, obtain a stable branch (updated with bug fixes only) as follows:
|
||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_7 -d lwip-0.7 lwip
|
||||
|
||||
Or, obtain a specific (fixed) release as follows:
|
||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_7_0 -d lwip-0.7.0 lwip
|
||||
|
||||
Or, obtain a development branch (considered unstable!) 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)
|
||||
--------------------------------------------------
|
||||
@@ -74,46 +106,25 @@ tagged tree. Export is similar to a checkout, except that the CVS metadata
|
||||
is not created locally.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
cd lwip-releases
|
||||
gpg -b lwip-0.6.3.tar.gz
|
||||
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
|
||||
Savannah conventions so that it shows up in the Files list real nice):
|
||||
Upload these files using anonymous FTP:
|
||||
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
|
||||
|
||||
mkdir stable.pkg
|
||||
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.
|
||||
---
|
||||
ncftp>mput *0.6.3.*
|
||||
|
||||
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
|
||||
and buffer management etc.
|
||||
core/ - The core of the TPC/IP stack; protocol implementations,
|
||||
memory and buffer management, and the low-level raw API.
|
||||
|
||||
include/ - lwIP include files.
|
||||
|
||||
netif/ - Generic network interface device drivers are kept here.
|
||||
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
|
||||
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.
|
||||
*
|
||||
* 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;
|
||||
} else {
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
@@ -280,9 +280,10 @@ netconn_delete(struct netconn *conn)
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
pbuf_free((struct pbuf *)mem);
|
||||
if(mem != NULL)
|
||||
pbuf_free((struct pbuf *)mem);
|
||||
} else {
|
||||
netbuf_delete((struct netbuf *)mem);
|
||||
netbuf_delete((struct netbuf *)mem);
|
||||
}
|
||||
}
|
||||
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);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
if (conn->err == ERR_OK) {
|
||||
dataptr = (void *)((char *)dataptr + len);
|
||||
dataptr = (void *)((u8_t *)dataptr + len);
|
||||
size -= len;
|
||||
} else if (conn->err == ERR_MEM) {
|
||||
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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#if LWIP_RAW
|
||||
static int
|
||||
static u8_t
|
||||
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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/api.h"
|
||||
#include "lwip/arch.h"
|
||||
@@ -84,9 +87,12 @@ static int err_to_errno_table[11] = {
|
||||
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) \
|
||||
((err) < (sizeof(err_to_errno_table)/sizeof(int))) ? \
|
||||
err_to_errno_table[-(err)] : EIO
|
||||
(-(err) >= 0 && -(err) < ERR_TO_ERRNO_TABLE_SIZE ? \
|
||||
err_to_errno_table[-(err)] : EIO)
|
||||
|
||||
#ifdef ERRNO
|
||||
#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);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
|
||||
} else {
|
||||
#if SOCKETS_DEBUG > 0
|
||||
#if SOCKETS_DEBUG
|
||||
addr = netbuf_fromaddr(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_RCVLOWAT: */
|
||||
/* UNIMPL case SO_SNDLOWAT: */
|
||||
#ifdef SO_REUSE
|
||||
#if SO_REUSE
|
||||
case SO_REUSEADDR:
|
||||
case SO_REUSEPORT:
|
||||
#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: */
|
||||
case SO_KEEPALIVE:
|
||||
/* UNIMPL case SO_OOBINCLUDE: */
|
||||
#ifdef SO_REUSE
|
||||
#if SO_REUSE
|
||||
case SO_REUSEADDR:
|
||||
case SO_REUSEPORT:
|
||||
#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") );
|
||||
break;
|
||||
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));
|
||||
break;
|
||||
} /* 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_RCVLOWAT: */
|
||||
/* UNIMPL case SO_SNDLOWAT: */
|
||||
#ifdef SO_REUSE
|
||||
#if SO_REUSE
|
||||
case SO_REUSEADDR:
|
||||
case SO_REUSEPORT:
|
||||
#endif /* SO_REUSE */
|
||||
@@ -1264,7 +1270,7 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
|
||||
/* UNIMPL case SO_DONTROUTE: */
|
||||
case SO_KEEPALIVE:
|
||||
/* UNIMPL case SO_OOBINCLUDE: */
|
||||
#ifdef SO_REUSE
|
||||
#if SO_REUSE
|
||||
case SO_REUSEADDR:
|
||||
case SO_REUSEPORT:
|
||||
#endif /* SO_REUSE */
|
||||
@@ -1306,7 +1312,7 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
|
||||
break;
|
||||
case TCP_KEEPALIVE:
|
||||
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;
|
||||
} /* switch */
|
||||
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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
@@ -46,34 +47,51 @@
|
||||
static void (* tcpip_init_done)(void *arg) = NULL;
|
||||
static void *tcpip_init_done_arg;
|
||||
static sys_mbox_t mbox;
|
||||
|
||||
#if LWIP_TCP
|
||||
static int tcpip_tcp_timer_active = 0;
|
||||
|
||||
|
||||
|
||||
static void
|
||||
tcpip_tcp_timer(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
/* call TCP timer handler */
|
||||
tcp_tmr();
|
||||
/* timer still needed? */
|
||||
if (tcp_active_pcbs || tcp_tw_pcbs) {
|
||||
/* restart timer */
|
||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||
} else {
|
||||
tcpip_tcp_timer_active = 0;
|
||||
/* disable timer */
|
||||
tcpip_tcp_timer_active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if !NO_SYS
|
||||
void
|
||||
tcp_timer_needed(void)
|
||||
{
|
||||
/* timer is off but needed again? */
|
||||
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);
|
||||
}
|
||||
}
|
||||
#endif /* !NO_SYS */
|
||||
#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
|
||||
tcpip_thread(void *arg)
|
||||
{
|
||||
@@ -87,6 +105,9 @@ tcpip_thread(void *arg)
|
||||
#endif
|
||||
#if LWIP_TCP
|
||||
tcp_init();
|
||||
#endif
|
||||
#if IP_REASSEMBLY
|
||||
sys_timeout(1000, ip_timer, NULL);
|
||||
#endif
|
||||
if (tcpip_init_done != NULL) {
|
||||
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-2003 Axon Digital Design B.V., The Netherlands.
|
||||
* Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -67,20 +67,26 @@
|
||||
* to remove the DHCP client.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "netif/etharp.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/dhcp.h"
|
||||
|
||||
#if LWIP_DHCP /* don't build if not configured for use in lwipopt.h */
|
||||
|
||||
/** 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;
|
||||
|
||||
/** DHCP client state machine functions */
|
||||
@@ -94,8 +100,7 @@ static void dhcp_check(struct netif *netif);
|
||||
static void dhcp_bind(struct netif *netif);
|
||||
static err_t dhcp_decline(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, unsigned char new_state);
|
||||
static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
|
||||
|
||||
/** 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);
|
||||
@@ -139,10 +144,10 @@ static void dhcp_option_trailer(struct dhcp *dhcp);
|
||||
static void dhcp_handle_nak(struct netif *netif) {
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
u16_t msecs = 10 * 1000;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%u\n", netif,
|
||||
netif->name[0], netif->name[1], (unsigned int)netif->num));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
|
||||
(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;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -158,8 +163,8 @@ static void dhcp_check(struct netif *netif)
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (unsigned int)netif->name[0],
|
||||
(unsigned int)netif->name[1]));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
|
||||
(s16_t)netif->name[1]));
|
||||
/* create an ARP query for the offered IP address, expecting that no host
|
||||
responds, as the IP address should not be in use. */
|
||||
result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
|
||||
@@ -169,7 +174,7 @@ static void dhcp_check(struct netif *netif)
|
||||
dhcp->tries++;
|
||||
msecs = 500;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -183,15 +188,15 @@ static void dhcp_handle_offer(struct netif *netif)
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
/* obtain the server address */
|
||||
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,
|
||||
netif->name[0], netif->name[1], netif->num));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
|
||||
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
if (option_ptr != NULL)
|
||||
{
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
@@ -210,7 +215,7 @@ static err_t dhcp_select(struct netif *netif)
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
err_t result;
|
||||
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 */
|
||||
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_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_ROUTER);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
|
||||
|
||||
dhcp_option_trailer(dhcp);
|
||||
/* shrink the pbuf to the actual content length */
|
||||
@@ -255,7 +261,7 @@ static err_t dhcp_select(struct netif *netif)
|
||||
dhcp->tries++;
|
||||
msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -291,18 +297,20 @@ void dhcp_coarse_tmr()
|
||||
/**
|
||||
* DHCP transaction timeout handling
|
||||
*
|
||||
* A DHCP server is expected to respond within a
|
||||
* short period of time.
|
||||
* A DHCP server is expected to respond within a short period of time.
|
||||
* This timer checks whether an outstanding DHCP request is timed out.
|
||||
*
|
||||
*/
|
||||
void dhcp_fine_tmr()
|
||||
{
|
||||
struct netif *netif = netif_list;
|
||||
/* loop through clients */
|
||||
/* loop through netif's */
|
||||
while (netif != NULL) {
|
||||
/* only act on DHCP configured interfaces */
|
||||
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) {
|
||||
/* { netif->dhcp->request_timeout == 0 } */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
|
||||
/* this clients' request timeout triggered */
|
||||
dhcp_timeout(netif);
|
||||
@@ -381,8 +389,8 @@ static void dhcp_t1_timeout(struct netif *netif)
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_t1_timeout()\n"));
|
||||
if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
|
||||
/* just retry to renew */
|
||||
/* note that the rebind timer will eventually time-out if renew does not work */
|
||||
/* just retry to renew - note that the rebind timer (t2) will
|
||||
* eventually time-out if renew tries fail. */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
|
||||
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
|
||||
*/
|
||||
@@ -478,6 +485,19 @@ static void dhcp_handle_ack(struct netif *netif)
|
||||
if (option_ptr != NULL) {
|
||||
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;
|
||||
|
||||
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) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
|
||||
dhcp = mem_malloc(sizeof(struct dhcp));
|
||||
if (dhcp == NULL) {
|
||||
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;
|
||||
}
|
||||
/* store this dhcp client in the netif */
|
||||
netif->dhcp = dhcp;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): created new udp pcb\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp"));
|
||||
/* already has DHCP client attached */
|
||||
} else {
|
||||
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 */
|
||||
result = dhcp_discover(netif);
|
||||
if (result != ERR_OK) {
|
||||
/* free resources allocated above */
|
||||
dhcp_stop(netif);
|
||||
return ERR_MEM;
|
||||
}
|
||||
netif->flags |= NETIF_FLAG_DHCP;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -609,10 +633,11 @@ void dhcp_inform(struct netif *netif)
|
||||
*/
|
||||
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"));
|
||||
/* 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)) {
|
||||
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
|
||||
were offered by the DHCP server? */
|
||||
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);
|
||||
|
||||
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||
udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
|
||||
udp_send(dhcp->pcb, dhcp->p_out);
|
||||
/* @todo: should we really connect here? we are performing sendto() */
|
||||
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);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
|
||||
} else {
|
||||
@@ -665,7 +692,7 @@ static err_t dhcp_decline(struct netif *netif)
|
||||
dhcp->tries++;
|
||||
msecs = 10*1000;
|
||||
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;
|
||||
}
|
||||
#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_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_ROUTER);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
|
||||
|
||||
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 */
|
||||
udp_recv(dhcp->pcb, dhcp_recv, netif);
|
||||
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);
|
||||
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"));
|
||||
dhcp_delete_request(netif);
|
||||
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++;
|
||||
msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -741,22 +763,22 @@ static void dhcp_bind(struct netif *netif)
|
||||
struct ip_addr sn_mask, gw_addr;
|
||||
LWIP_ASSERT("dhcp_bind: netif != NULL", netif != 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? */
|
||||
if (dhcp->offered_t1_renew != 0xffffffffUL) {
|
||||
/* 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;
|
||||
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 */
|
||||
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;
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
/* bring the interface up */
|
||||
netif_set_up(netif);
|
||||
/* netif is now bound to DHCP leased address */
|
||||
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 */
|
||||
msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
/* set remote IP association to any DHCP server */
|
||||
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);
|
||||
/* broadcast to server */
|
||||
udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
|
||||
dhcp_delete_request(netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind: REBINDING\n"));
|
||||
} else {
|
||||
@@ -893,7 +918,7 @@ static err_t dhcp_rebind(struct netif *netif)
|
||||
dhcp->tries++;
|
||||
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -902,7 +927,7 @@ static err_t dhcp_rebind(struct netif *netif)
|
||||
*
|
||||
* @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;
|
||||
err_t result;
|
||||
@@ -911,8 +936,13 @@ static err_t dhcp_release(struct netif *netif)
|
||||
|
||||
/* idle DHCP client */
|
||||
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 */
|
||||
result = dhcp_create_request(netif);
|
||||
if (result == ERR_OK) {
|
||||
@@ -934,11 +964,14 @@ static err_t dhcp_release(struct netif *netif)
|
||||
dhcp->tries++;
|
||||
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
||||
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 */
|
||||
netif_set_ipaddr(netif, IP_ADDR_ANY);
|
||||
netif_set_gw(netif, IP_ADDR_ANY);
|
||||
netif_set_netmask(netif, IP_ADDR_ANY);
|
||||
|
||||
/* TODO: netif_down(netif); */
|
||||
return result;
|
||||
}
|
||||
@@ -980,7 +1013,7 @@ void dhcp_stop(struct netif *netif)
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@@ -1076,7 +1109,7 @@ static err_t dhcp_unfold_reply(struct dhcp *dhcp)
|
||||
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) {
|
||||
ptr = (u8_t *)dhcp->options_in;
|
||||
/* proceed through options */
|
||||
@@ -1089,7 +1122,7 @@ static err_t dhcp_unfold_reply(struct dhcp *dhcp)
|
||||
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;
|
||||
}
|
||||
@@ -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 msg_type;
|
||||
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,
|
||||
(unsigned int)(ntohl(addr->addr) >> 24 & 0xff), (unsigned int)(ntohl(addr->addr) >> 16 & 0xff),
|
||||
(unsigned int)(ntohl(addr->addr) >> 8 & 0xff), (unsigned int)(ntohl(addr->addr) & 0xff), port));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %u\n", p->len));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %u\n", p->tot_len));
|
||||
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,
|
||||
(u16_t)(ntohl(addr->addr) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff),
|
||||
(u16_t)(ntohl(addr->addr) >> 8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
|
||||
/* prevent warnings about unused arguments */
|
||||
(void)pcb; (void)addr; (void)port;
|
||||
dhcp->p = p;
|
||||
/* TODO: check packet length before reading them */
|
||||
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);
|
||||
dhcp->p = NULL;
|
||||
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 */
|
||||
for (i = 0; i < netif->hwaddr_len; 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",
|
||||
i, netif->hwaddr[i], i, reply_msg->chaddr[i]));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
|
||||
(u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
|
||||
pbuf_free(p);
|
||||
dhcp->p = NULL;
|
||||
return;
|
||||
@@ -1243,10 +1276,10 @@ static err_t dhcp_create_request(struct netif *netif)
|
||||
dhcp->msg_out->xid = htonl(dhcp->xid);
|
||||
dhcp->msg_out->secs = 0;
|
||||
dhcp->msg_out->flags = 0;
|
||||
dhcp->msg_out->ciaddr = netif->ip_addr.addr;
|
||||
dhcp->msg_out->yiaddr = 0;
|
||||
dhcp->msg_out->siaddr = 0;
|
||||
dhcp->msg_out->giaddr = 0;
|
||||
dhcp->msg_out->ciaddr.addr = netif->ip_addr.addr;
|
||||
dhcp->msg_out->yiaddr.addr = 0;
|
||||
dhcp->msg_out->siaddr.addr = 0;
|
||||
dhcp->msg_out->giaddr.addr = 0;
|
||||
for (i = 0; i < DHCP_CHADDR_LEN; i++) {
|
||||
/* copy netif hardware address, pad with zeroes */
|
||||
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;
|
||||
/* packet is too small, or not 4 byte aligned? */
|
||||
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);
|
||||
/* add a fill/padding byte */
|
||||
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;
|
||||
/* 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)) {
|
||||
/* 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? */
|
||||
if (options[offset] == DHCP_OPTION_OVERLOAD) {
|
||||
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 */
|
||||
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];
|
||||
/* skip option */
|
||||
} 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 */
|
||||
offset++;
|
||||
/* 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 */
|
||||
while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
|
||||
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];
|
||||
/* skip option */
|
||||
} 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 */
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1396,7 +1429,7 @@ static u16_t dhcp_get_option_short(u8_t *ptr)
|
||||
u16_t value;
|
||||
value = *ptr++ << 8;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1415,6 +1448,8 @@ static u32_t dhcp_get_option_long(u8_t *ptr)
|
||||
value |= (u32_t)(*ptr++) << 16;
|
||||
value |= (u32_t)(*ptr++) << 8;
|
||||
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;
|
||||
}
|
||||
|
||||
#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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -46,36 +46,195 @@
|
||||
#include "lwip/def.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
|
||||
lwip_chksum(void *dataptr, int len)
|
||||
lwip_standard_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc;
|
||||
u16_t src;
|
||||
u8_t *octetptr;
|
||||
|
||||
LWIP_DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %d)\n", (void *)dataptr, len));
|
||||
for(acc = 0; len > 1; len -= 2) {
|
||||
/* acc = acc + *((u16_t *)dataptr)++;*/
|
||||
acc += *(u16_t *)dataptr;
|
||||
dataptr = (void *)((u16_t *)dataptr + 1);
|
||||
acc = 0;
|
||||
/* dataptr may be at odd or even addresses */
|
||||
octetptr = (u8_t*)dataptr;
|
||||
while (len > 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;
|
||||
}
|
||||
|
||||
/* add up any odd byte */
|
||||
if (len == 1) {
|
||||
acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8);
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", (unsigned int)(*(u8_t *)dataptr)));
|
||||
} else {
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: no odd byte\n"));
|
||||
if (len > 0)
|
||||
{
|
||||
/* accumulate remaining octet */
|
||||
src = (*octetptr) << 8;
|
||||
acc += src;
|
||||
}
|
||||
acc = (acc >> 16) + (acc & 0xffffUL);
|
||||
|
||||
/* add deferred carry bits */
|
||||
acc = (acc >> 16) + (acc & 0x0000ffffUL);
|
||||
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:
|
||||
*
|
||||
* 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) {
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||
(void *)q, (void *)q->next));
|
||||
acc += lwip_chksum(q->payload, q->len);
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%lx \n", acc));*/
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
@@ -105,7 +264,7 @@ inet_chksum_pseudo(struct pbuf *p,
|
||||
swapped = 1 - swapped;
|
||||
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) {
|
||||
@@ -121,8 +280,8 @@ inet_chksum_pseudo(struct pbuf *p,
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
|
||||
return ~(acc & 0xffffUL);
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/* inet_chksum:
|
||||
@@ -136,11 +295,11 @@ inet_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc;
|
||||
|
||||
acc = lwip_chksum(dataptr, len);
|
||||
acc = LWIP_CHKSUM(dataptr, len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
return ~(acc & 0xffff);
|
||||
return (u16_t)~(acc & 0xffff);
|
||||
}
|
||||
|
||||
u16_t
|
||||
@@ -153,7 +312,7 @@ inet_chksum_pbuf(struct pbuf *p)
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
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) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
@@ -166,7 +325,7 @@ inet_chksum_pbuf(struct pbuf *p)
|
||||
if (swapped) {
|
||||
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 */
|
||||
@@ -206,10 +365,11 @@ inet_chksum_pbuf(struct pbuf *p)
|
||||
*/
|
||||
/* */
|
||||
/* 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;
|
||||
int base, n;
|
||||
s32_t base, n;
|
||||
char c;
|
||||
u32_t parts[4];
|
||||
u32_t* pp = parts;
|
||||
@@ -232,12 +392,12 @@ inet_chksum_pbuf(struct pbuf *p)
|
||||
base = 8;
|
||||
}
|
||||
for (;;) {
|
||||
if (isascii(c) && isdigit(c)) {
|
||||
val = (val * base) + (c - '0');
|
||||
if (isdigit(c)) {
|
||||
val = (val * base) + (s16_t)(c - '0');
|
||||
c = *++cp;
|
||||
} else if (base == 16 && isascii(c) && isxdigit(c)) {
|
||||
} else if (base == 16 && isxdigit(c)) {
|
||||
val = (val << 4) |
|
||||
(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
(s16_t)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
@@ -300,18 +460,19 @@ inet_chksum_pbuf(struct pbuf *p)
|
||||
/* Convert numeric IP address into decimal dotted ASCII representation.
|
||||
* 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];
|
||||
u8_t inv[3];
|
||||
u8_t *rp;
|
||||
static char str[16];
|
||||
u32_t s_addr = addr.s_addr;
|
||||
char inv[3];
|
||||
char *rp;
|
||||
u8_t *ap;
|
||||
u8_t rem;
|
||||
u8_t n;
|
||||
u8_t i;
|
||||
|
||||
rp = str;
|
||||
ap = (u8_t *)&addr;
|
||||
ap = (u8_t *)&s_addr;
|
||||
for(n = 0; n < 4; n++) {
|
||||
i = 0;
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
is not implemented. */
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
void
|
||||
icmp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
unsigned char type;
|
||||
unsigned char code;
|
||||
u8_t type;
|
||||
u8_t code;
|
||||
struct icmp_echo_hdr *iecho;
|
||||
struct ip_hdr *iphdr;
|
||||
struct ip_addr tmpaddr;
|
||||
@@ -61,7 +60,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
iphdr = p->payload;
|
||||
hlen = IPH_HL(iphdr) * 4;
|
||||
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);
|
||||
ICMP_STATS_INC(icmp.lenerr);
|
||||
snmp_inc_icmpinerrors();
|
||||
@@ -72,9 +71,9 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
code = *(((u8_t *)p->payload)+1);
|
||||
switch (type) {
|
||||
case ICMP_ECHO:
|
||||
if (ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) ||
|
||||
ip_addr_ismulticast(&iphdr->dest)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("Smurf.\n"));
|
||||
/* broadcast or multicast destination address? */
|
||||
if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
|
||||
ICMP_STATS_INC(icmp.err);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
@@ -117,7 +116,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
|
||||
break;
|
||||
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.drop);
|
||||
}
|
||||
@@ -140,7 +139,7 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
||||
ICMPH_TYPE_SET(idur, ICMP_DUR);
|
||||
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 */
|
||||
idur->chksum = 0;
|
||||
@@ -178,7 +177,7 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
||||
ICMPH_CODE_SET(tehdr, t);
|
||||
|
||||
/* 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 */
|
||||
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.
|
||||
*
|
||||
* 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/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/ip.h"
|
||||
@@ -63,69 +60,17 @@
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
|
||||
/* ip_init:
|
||||
*
|
||||
/**
|
||||
* Initializes the IP layer.
|
||||
*/
|
||||
|
||||
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
|
||||
* searches the list of network interfaces linearly. A match is found
|
||||
* 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 */
|
||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
/* 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;
|
||||
}
|
||||
@@ -150,14 +95,13 @@ ip_route(struct ip_addr *dest)
|
||||
}
|
||||
#if IP_FORWARD
|
||||
|
||||
/* ip_forward:
|
||||
*
|
||||
/**
|
||||
* Forwards an IP packet. It finds an appropriate route for the
|
||||
* packet, decrements the TTL value of the packet, adjusts the
|
||||
* 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)
|
||||
{
|
||||
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. */
|
||||
netif = ip_route((struct ip_addr *)&(iphdr->dest));
|
||||
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));
|
||||
snmp_inc_ipnoroutes();
|
||||
return;
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
/* Do not forward packets onto the same network interface on which
|
||||
they arrived. */
|
||||
* they arrived. */
|
||||
if (netif == inp) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
|
||||
snmp_inc_ipnoroutes();
|
||||
return;
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
snmp_inc_icmpouttimeexcds();
|
||||
}
|
||||
return;
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
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");
|
||||
/* transmit pbuf on chosen interface */
|
||||
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
|
||||
return netif;
|
||||
}
|
||||
#endif /* IP_FORWARD */
|
||||
|
||||
/* ip_input:
|
||||
*
|
||||
/**
|
||||
* This function is called by the network interface device driver when
|
||||
* 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
|
||||
@@ -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.
|
||||
*
|
||||
* Finally, the packet is sent to the upper layer protocol input function.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
err_t
|
||||
ip_input(struct pbuf *p, struct netif *inp) {
|
||||
static struct ip_hdr *iphdr;
|
||||
static struct netif *netif;
|
||||
static u16_t iphdrlen;
|
||||
struct ip_hdr *iphdr;
|
||||
struct netif *netif;
|
||||
u16_t iphdrlen;
|
||||
|
||||
IP_STATS_INC(ip.recv);
|
||||
snmp_inc_ipinreceives();
|
||||
@@ -234,7 +181,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
/* identify the IP header */
|
||||
iphdr = p->payload;
|
||||
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);
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.err);
|
||||
@@ -249,7 +196,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
|
||||
/* header length exceeds first pbuf length? */
|
||||
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));
|
||||
/* free (drop) packet pbufs */
|
||||
pbuf_free(p);
|
||||
@@ -260,9 +207,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
}
|
||||
|
||||
/* verify checksum */
|
||||
#if CHECKSUM_CHECK_IP
|
||||
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);
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.chkerr);
|
||||
@@ -270,45 +218,44 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
snmp_inc_ipindiscards();
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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)));
|
||||
|
||||
/* is this packet for us? */
|
||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
/* match packet against an interface, i.e. is this packet for us? */
|
||||
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",
|
||||
iphdr->dest.addr, netif->ip_addr.addr,
|
||||
iphdr->dest.addr & netif->netmask.addr,
|
||||
netif->ip_addr.addr & netif->netmask.addr,
|
||||
iphdr->dest.addr & ~(netif->netmask.addr)));
|
||||
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->netmask.addr,
|
||||
netif->ip_addr.addr & netif->netmask.addr,
|
||||
iphdr->dest.addr & ~(netif->netmask.addr)));
|
||||
|
||||
/* interface configured? */
|
||||
if (!ip_addr_isany(&(netif->ip_addr)))
|
||||
/* interface is up and configured? */
|
||||
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
|
||||
{
|
||||
/* unicast to this interface address? */
|
||||
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
|
||||
/* or broadcast matching this interface network address? */
|
||||
(ip_addr_isbroadcast(&(iphdr->dest), &(netif->netmask)) &&
|
||||
ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) ||
|
||||
/* or restricted broadcast? */
|
||||
ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
||||
netif->name[0], netif->name[1]));
|
||||
/* break out of for loop */
|
||||
break;
|
||||
/* or broadcast on this interface network address? */
|
||||
ip_addr_isbroadcast(&(iphdr->dest), netif)) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
||||
netif->name[0], netif->name[1]));
|
||||
/* break out of for loop */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LWIP_DHCP
|
||||
/* 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.
|
||||
According to RFC 1542 section 3.1.1, referred by RFC 2131). */
|
||||
* 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).
|
||||
*/
|
||||
if (netif == NULL) {
|
||||
/* remote port is DHCP server? */
|
||||
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)));
|
||||
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"));
|
||||
@@ -317,13 +264,13 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_DHCP */
|
||||
/* packet not for us? */
|
||||
/* packet not for us? */
|
||||
if (netif == NULL) {
|
||||
/* packet not for us, route or discard */
|
||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
|
||||
#if IP_FORWARD
|
||||
/* 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 */
|
||||
ip_forward(p, iphdr, inp);
|
||||
}
|
||||
@@ -335,30 +282,30 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
pbuf_free(p);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#if IP_REASSEMBLY
|
||||
/* packet consists of multiple fragments? */
|
||||
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));
|
||||
/* reassemble the packet*/
|
||||
p = ip_reass(p);
|
||||
/* packet not fully reassembled yet? */
|
||||
if (p == NULL) {
|
||||
return ERR_OK;
|
||||
}
|
||||
iphdr = p->payload;
|
||||
}
|
||||
#else /* IP_REASSEMBLY */
|
||||
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
|
||||
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
|
||||
ntohs(IPH_OFFSET(iphdr))));
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
|
||||
ntohs(IPH_OFFSET(iphdr))));
|
||||
IP_STATS_INC(ip.opterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipunknownprotos();
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* IP_REASSEMBLY */
|
||||
}
|
||||
|
||||
#if IP_OPTIONS == 0
|
||||
#if IP_OPTIONS == 0 /* no support for IP options in the IP header? */
|
||||
if (iphdrlen > IP_HLEN) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
|
||||
pbuf_free(p);
|
||||
@@ -372,10 +319,11 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
/* send to upper layers */
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
|
||||
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 (!raw_input(p, inp)) {
|
||||
/* raw input did not eat the packet? */
|
||||
if (raw_input(p, inp) == 0) {
|
||||
#endif /* LWIP_RAW */
|
||||
|
||||
switch (IPH_PROTO(iphdr)) {
|
||||
@@ -398,19 +346,18 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
break;
|
||||
default:
|
||||
/* send ICMP destination protocol unreachable unless is was a broadcast */
|
||||
if (!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) &&
|
||||
!ip_addr_ismulticast(&(iphdr->dest))) {
|
||||
if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
|
||||
!ip_addr_ismulticast(&(iphdr->dest))) {
|
||||
p->payload = iphdr;
|
||||
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
||||
}
|
||||
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.drop);
|
||||
snmp_inc_ipunknownprotos();
|
||||
|
||||
}
|
||||
#if LWIP_RAW
|
||||
} /* LWIP_RAW */
|
||||
@@ -418,9 +365,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ip_output_if:
|
||||
*
|
||||
/**
|
||||
* Sends an IP packet on a network interface. This function constructs
|
||||
* the IP header and calculates the IP header checksum. If the source
|
||||
* 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 proto, struct netif *netif)
|
||||
{
|
||||
static struct ip_hdr *iphdr;
|
||||
static u16_t ip_id = 0;
|
||||
struct ip_hdr *iphdr;
|
||||
u16_t ip_id = 0;
|
||||
|
||||
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);
|
||||
#if CHECKSUM_GEN_IP
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
#endif
|
||||
} else {
|
||||
iphdr = p->payload;
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* ip_output:
|
||||
*
|
||||
/**
|
||||
* Simple interface to ip_output_if. It finds the outgoing network
|
||||
* 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;
|
||||
|
||||
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);
|
||||
snmp_inc_ipoutdiscards();
|
||||
@@ -522,35 +468,35 @@ ip_debug_print(struct pbuf *p)
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("IP header:\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_HL(iphdr),
|
||||
IPH_TOS(iphdr),
|
||||
ntohs(IPH_LEN(iphdr))));
|
||||
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_OFFSET(iphdr)) >> 15 & 1,
|
||||
ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
|
||||
ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
|
||||
ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
|
||||
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_PROTO(iphdr),
|
||||
ntohs(IPH_CHKSUM(iphdr))));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (src)\n",
|
||||
ntohl(iphdr->src.addr) >> 24 & 0xff,
|
||||
ntohl(iphdr->src.addr) >> 16 & 0xff,
|
||||
ntohl(iphdr->src.addr) >> 8 & 0xff,
|
||||
ntohl(iphdr->src.addr) & 0xff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
|
||||
ip4_addr1(&iphdr->src),
|
||||
ip4_addr2(&iphdr->src),
|
||||
ip4_addr3(&iphdr->src),
|
||||
ip4_addr4(&iphdr->src)));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (dest)\n",
|
||||
ntohl(iphdr->dest.addr) >> 24 & 0xff,
|
||||
ntohl(iphdr->dest.addr) >> 16 & 0xff,
|
||||
ntohl(iphdr->dest.addr) >> 8 & 0xff,
|
||||
ntohl(iphdr->dest.addr) & 0xff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
|
||||
ip4_addr1(&iphdr->dest),
|
||||
ip4_addr2(&iphdr->dest),
|
||||
ip4_addr3(&iphdr->dest),
|
||||
ip4_addr4(&iphdr->dest)));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
}
|
||||
#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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -32,7 +32,41 @@
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.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_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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -31,20 +37,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* ip_frag.c
|
||||
*
|
||||
* This is the code for IP segmentation and reassembly
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/sys.h"
|
||||
/* #include "lwip/sys.h" */
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
|
||||
@@ -79,7 +78,7 @@ copy_from_pbuf(struct pbuf *p, u16_t * offset,
|
||||
#define IP_REASS_TMO 1000
|
||||
|
||||
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,
|
||||
0x0f, 0x07, 0x03, 0x01
|
||||
};
|
||||
@@ -89,18 +88,26 @@ static u8_t ip_reassflags;
|
||||
|
||||
static u8_t ip_reasstmr;
|
||||
|
||||
/* Reassembly timer */
|
||||
static void
|
||||
ip_reass_timer(void *arg)
|
||||
/**
|
||||
* Reassembly timer base function
|
||||
* for both NO_SYS == 0 and 1 (!).
|
||||
*
|
||||
* Should be called every 1000 msec.
|
||||
*/
|
||||
void
|
||||
ip_reass_tmr(void)
|
||||
{
|
||||
(void)arg;
|
||||
if (ip_reasstmr > 1) {
|
||||
if (ip_reasstmr > 0) {
|
||||
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 *
|
||||
ip_reass(struct pbuf *p)
|
||||
{
|
||||
@@ -120,7 +127,6 @@ ip_reass(struct pbuf *p)
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: new packet\n"));
|
||||
memcpy(iphdr, fraghdr, IP_HLEN);
|
||||
ip_reasstmr = IP_REASS_MAXAGE;
|
||||
sys_timeout(IP_REASS_TMO, ip_reass_timer, NULL);
|
||||
ip_reassflags = 0;
|
||||
/* Clear the bitmap. */
|
||||
memset(ip_reassbitmap, 0, sizeof(ip_reassbitmap));
|
||||
@@ -132,7 +138,8 @@ ip_reass(struct pbuf *p)
|
||||
if (ip_addr_cmp(&iphdr->src, &fraghdr->src) &&
|
||||
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
|
||||
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);
|
||||
/* Find out the offset in the reassembly buffer where we should
|
||||
copy the fragment. */
|
||||
@@ -143,9 +150,8 @@ ip_reass(struct pbuf *p)
|
||||
reassembly buffer, we discard the entire packet. */
|
||||
if (offset > IP_REASS_BUFSIZE || offset + len > IP_REASS_BUFSIZE) {
|
||||
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));
|
||||
sys_untimeout(ip_reass_timer, NULL);
|
||||
ip_reasstmr = 0;
|
||||
goto nullreturn;
|
||||
}
|
||||
@@ -153,7 +159,7 @@ ip_reass(struct pbuf *p)
|
||||
/* Copy the fragment into the reassembly buffer, at the right
|
||||
offset. */
|
||||
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));
|
||||
i = IPH_HL(fraghdr) * 4;
|
||||
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)) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: updating single byte in bitmap.\n"));
|
||||
/* If the two endpoints are in the same byte, we only update
|
||||
that byte. */
|
||||
/* If the two endpoints are in the same byte, we only update that byte. */
|
||||
LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||
offset / (8 * 8) < sizeof(ip_reassbitmap));
|
||||
ip_reassbitmap[offset / (8 * 8)] |=
|
||||
bitmap_bits[(offset / 8) & 7] &
|
||||
~bitmap_bits[((offset + len) / 8) & 7];
|
||||
bitmap_bits[(offset / 8) & 7] &
|
||||
~bitmap_bits[((offset + len) / 8) & 7];
|
||||
} else {
|
||||
/* If the two endpoints are in different bytes, we update the
|
||||
bytes in the endpoints and fill the stuff inbetween with
|
||||
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];
|
||||
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)));
|
||||
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)] |=
|
||||
~bitmap_bits[((offset + len) / 8) & 7];
|
||||
~bitmap_bits[((offset + len) / 8) & 7];
|
||||
}
|
||||
|
||||
/* 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_reasslen = offset + len;
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -202,23 +213,27 @@ ip_reass(struct pbuf *p)
|
||||
if (ip_reassflags & IP_REASS_FLAG_LASTFRAG) {
|
||||
/* Check all bytes up to and including all but the last byte in
|
||||
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) {
|
||||
if (ip_reassbitmap[i] != 0xff) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: last fragment seen, bitmap %d/%d failed (%x)\n",
|
||||
i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
|
||||
goto nullreturn;
|
||||
}
|
||||
if (ip_reassbitmap[i] != 0xff) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: last fragment seen, bitmap %"S16_F"/%"S16_F" failed (%"X16_F")\n",
|
||||
i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
|
||||
goto nullreturn;
|
||||
}
|
||||
}
|
||||
/* Check the last byte in the bitmap. It should contain just the
|
||||
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)] !=
|
||||
(u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: last fragment seen, bitmap %d didn't contain %x (%x)\n",
|
||||
ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7],
|
||||
ip_reassbitmap[ip_reasslen / (8 * 8)]));
|
||||
goto nullreturn;
|
||||
(u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("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_reassbitmap[ip_reasslen / (8 * 8)]));
|
||||
goto nullreturn;
|
||||
}
|
||||
|
||||
/* 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
|
||||
buffer, so we allocate a pbuf and copy the packet into it. We
|
||||
also reset the timer. */
|
||||
sys_untimeout(ip_reass_timer, NULL);
|
||||
ip_reasstmr = 0;
|
||||
pbuf_free(p);
|
||||
p = pbuf_alloc(PBUF_LINK, ip_reasslen, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
i = 0;
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
/* Copy enough bytes to fill this pbuf in the chain. The
|
||||
available data in the pbuf is given by the q->len
|
||||
variable. */
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: memcpy from %p (%d) to %p, %d bytes\n",
|
||||
&ip_reassbuf[i], i, q->payload,
|
||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
|
||||
memcpy(q->payload, &ip_reassbuf[i],
|
||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
|
||||
i += q->len;
|
||||
}
|
||||
IPFRAG_STATS_INC(ip_frag.fw);
|
||||
i = 0;
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
/* Copy enough bytes to fill this pbuf in the chain. The
|
||||
available data in the pbuf is given by the q->len variable. */
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: memcpy from %p (%"S16_F") to %p, %"S16_F" bytes\n",
|
||||
(void *)&ip_reassbuf[i], i, q->payload,
|
||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
|
||||
memcpy(q->payload, &ip_reassbuf[i],
|
||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
|
||||
i += q->len;
|
||||
}
|
||||
IPFRAG_STATS_INC(ip_frag.fw);
|
||||
} 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));
|
||||
return p;
|
||||
@@ -270,9 +283,9 @@ nullreturn:
|
||||
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)
|
||||
*/
|
||||
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 */
|
||||
rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF);
|
||||
if (rambuf == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
rambuf->tot_len = rambuf->len = mtu;
|
||||
rambuf->payload = MEM_ALIGN((void *)buf);
|
||||
|
||||
|
||||
/* Copy the IP header in it */
|
||||
iphdr = rambuf->payload;
|
||||
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.
|
||||
*/
|
||||
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
|
||||
pbuf_chain(header, rambuf);
|
||||
netif->output(netif, header, dest);
|
||||
IPFRAG_STATS_INC(ip_frag.xmit);
|
||||
pbuf_free(header);
|
||||
|
||||
if (header != NULL) {
|
||||
pbuf_chain(header, rambuf);
|
||||
netif->output(netif, header, dest);
|
||||
IPFRAG_STATS_INC(ip_frag.xmit);
|
||||
pbuf_free(header);
|
||||
} else {
|
||||
pbuf_free(rambuf);
|
||||
return ERR_MEM;
|
||||
}
|
||||
left -= cop;
|
||||
}
|
||||
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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -46,7 +46,7 @@
|
||||
void
|
||||
icmp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
unsigned char type;
|
||||
u8_t type;
|
||||
struct icmp_echo_hdr *iecho;
|
||||
struct ip_hdr *iphdr;
|
||||
struct ip_addr tmpaddr;
|
||||
@@ -57,7 +57,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
/* TODO: check length before accessing payload! */
|
||||
|
||||
type = ((char *)p->payload)[0];
|
||||
type = ((u8_t *)p->payload)[0];
|
||||
|
||||
switch (type) {
|
||||
case ICMP6_ECHO:
|
||||
@@ -74,16 +74,16 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
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
|
||||
++lwip_stats.icmp.chkerr;
|
||||
#endif /* ICMP_STATS */
|
||||
/* 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(&(iphdr->src), &(iphdr->dest));
|
||||
ip_addr_set(&(iphdr->dest), &tmpaddr);
|
||||
@@ -94,17 +94,17 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
} else {
|
||||
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
|
||||
++lwip_stats.icmp.xmit;
|
||||
#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,
|
||||
iphdr->hoplim, IP_PROTO_ICMP, inp);
|
||||
break;
|
||||
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
|
||||
++lwip_stats.icmp.proterr;
|
||||
++lwip_stats.icmp.drop;
|
||||
@@ -127,10 +127,10 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
||||
iphdr = p->payload;
|
||||
|
||||
idur = q->payload;
|
||||
idur->type = (char)ICMP6_DUR;
|
||||
idur->icode = (char)t;
|
||||
idur->type = (u8_t)ICMP6_DUR;
|
||||
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 */
|
||||
idur->chksum = 0;
|
||||
@@ -158,11 +158,11 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
||||
iphdr = p->payload;
|
||||
|
||||
tehdr = q->payload;
|
||||
tehdr->type = (char)ICMP6_TE;
|
||||
tehdr->icode = (char)t;
|
||||
tehdr->type = (u8_t)ICMP6_TE;
|
||||
tehdr->icode = (u8_t)t;
|
||||
|
||||
/* 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 */
|
||||
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.
|
||||
*
|
||||
* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -217,7 +217,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
#if IP_DEBUG
|
||||
/* LWIP_DEBUGF("ip_input: \n");
|
||||
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 */
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
/* send ICMP destination protocol unreachable */
|
||||
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %u\n",
|
||||
LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %"U16_F"\n",
|
||||
iphdr->nexthdr));
|
||||
|
||||
#ifdef IP_STATS
|
||||
@@ -266,7 +266,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
|
||||
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)) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
|
||||
#ifdef IP_STATS
|
||||
@@ -275,7 +275,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
|
||||
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;
|
||||
|
||||
@@ -303,7 +303,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
++lwip_stats.ip.xmit;
|
||||
#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
|
||||
ip_debug_print(p);
|
||||
#endif /* IP_DEBUG */
|
||||
@@ -324,7 +324,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
{
|
||||
struct netif *netif;
|
||||
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
|
||||
++lwip_stats.ip.rterr;
|
||||
#endif /* IP_STATS */
|
||||
@@ -339,45 +339,45 @@ void
|
||||
ip_debug_print(struct pbuf *p)
|
||||
{
|
||||
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, ("+-------------------------------+\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->tclass1, iphdr->tclass2,
|
||||
iphdr->flow1, iphdr->flow2));
|
||||
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),
|
||||
iphdr->nexthdr,
|
||||
iphdr->hoplim));
|
||||
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]) & 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]) & 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]) & 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]) & 0xffff));
|
||||
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]) & 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]) & 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]) & 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]) & 0xffff));
|
||||
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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -34,8 +34,8 @@
|
||||
#include "lwip/inet.h"
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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];*/
|
||||
}
|
||||
|
||||
int
|
||||
u8_t
|
||||
ip_addr_isany(struct ip_addr *addr)
|
||||
{
|
||||
if (addr == NULL) return 1;
|
||||
@@ -76,7 +76,7 @@ ip_addr_isany(struct ip_addr *addr)
|
||||
void
|
||||
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]) & 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.
|
||||
*
|
||||
* 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/opt.h"
|
||||
@@ -54,6 +55,8 @@ struct mem {
|
||||
u16_t used;
|
||||
#elif MEM_ALIGNMENT == 4
|
||||
u32_t used;
|
||||
#elif MEM_ALIGNMENT == 8
|
||||
u64_t used;
|
||||
#else
|
||||
#error "unhandled MEM_ALIGNMENT size"
|
||||
#endif /* MEM_ALIGNMENT */
|
||||
@@ -292,13 +295,13 @@ mem_malloc(mem_size_t size)
|
||||
}
|
||||
sys_sem_signal(mem_sem);
|
||||
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.",
|
||||
(unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
|
||||
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
|
||||
++lwip_stats.mem.err;
|
||||
#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.
|
||||
*
|
||||
* 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;
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_NOASSERT
|
||||
#if MEMP_SANITY_CHECK
|
||||
static int
|
||||
memp_sanity(void)
|
||||
{
|
||||
int i, c;
|
||||
s16_t i, c;
|
||||
struct memp *m, *n;
|
||||
|
||||
for(i = 0; i < MEMP_MAX; i++) {
|
||||
@@ -140,7 +140,7 @@ memp_sanity(void)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif /* LWIP_DEBUG */
|
||||
#endif /* MEMP_SANITY_CHECK*/
|
||||
|
||||
void
|
||||
memp_init(void)
|
||||
@@ -217,12 +217,12 @@ memp_malloc(memp_t type)
|
||||
sys_sem_signal(mutex);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
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));
|
||||
return mem;
|
||||
} 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
|
||||
++lwip_stats.memp[type].err;
|
||||
#endif /* MEMP_STATS */
|
||||
@@ -261,7 +261,9 @@ memp_free(memp_t type, void *mem)
|
||||
memp->next = memp_tab[type];
|
||||
memp_tab[type] = memp;
|
||||
|
||||
#if MEMP_SANITY_CHECK
|
||||
LWIP_ASSERT("memp sanity", memp_sanity());
|
||||
#endif
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -39,23 +39,24 @@
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
|
||||
struct netif *netif_list = NULL;
|
||||
struct netif *netif_default = NULL;
|
||||
|
||||
/**
|
||||
* 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 netmask network mask for the new netif
|
||||
* @param gw default gateway IP address for the new netif
|
||||
* @param state opaque data passed to the new netif
|
||||
* @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.
|
||||
*/
|
||||
@@ -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 (* input)(struct pbuf *p, struct netif *netif))
|
||||
{
|
||||
static int netifnum = 0;
|
||||
|
||||
static s16_t netifnum = 0;
|
||||
|
||||
#if LWIP_DHCP
|
||||
/* 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? */
|
||||
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"));
|
||||
pcb = tcp_active_pcbs;
|
||||
while (pcb != NULL) {
|
||||
@@ -186,7 +186,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
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? */
|
||||
if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {
|
||||
/* The PCB is listening to the old ipaddr and
|
||||
@@ -197,36 +197,44 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
}
|
||||
#endif
|
||||
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],
|
||||
(unsigned int)(ntohl(netif->ip_addr.addr) >> 24 & 0xff),
|
||||
(unsigned int)(ntohl(netif->ip_addr.addr) >> 16 & 0xff),
|
||||
(unsigned int)(ntohl(netif->ip_addr.addr) >> 8 & 0xff),
|
||||
(unsigned int)(ntohl(netif->ip_addr.addr) & 0xff)));
|
||||
ip4_addr1(&netif->ip_addr),
|
||||
ip4_addr2(&netif->ip_addr),
|
||||
ip4_addr3(&netif->ip_addr),
|
||||
ip4_addr4(&netif->ip_addr)));
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_gw(struct netif *netif, struct ip_addr *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",
|
||||
netif->name[0], netif->name[1],
|
||||
(unsigned int)(ntohl(netif->gw.addr) >> 24 & 0xff),
|
||||
(unsigned int)(ntohl(netif->gw.addr) >> 16 & 0xff),
|
||||
(unsigned int)(ntohl(netif->gw.addr) >> 8 & 0xff),
|
||||
(unsigned int)(ntohl(netif->gw.addr) & 0xff)));
|
||||
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],
|
||||
ip4_addr1(&netif->gw),
|
||||
ip4_addr2(&netif->gw),
|
||||
ip4_addr3(&netif->gw),
|
||||
ip4_addr4(&netif->gw)));
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_netmask(struct netif *netif, struct ip_addr *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",
|
||||
netif->name[0], netif->name[1],
|
||||
(unsigned int)(ntohl(netif->netmask.addr) >> 24 & 0xff),
|
||||
(unsigned int)(ntohl(netif->netmask.addr) >> 16 & 0xff),
|
||||
(unsigned int)(ntohl(netif->netmask.addr) >> 8 & 0xff),
|
||||
(unsigned int)(ntohl(netif->netmask.addr) & 0xff)));
|
||||
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],
|
||||
ip4_addr1(&netif->netmask),
|
||||
ip4_addr2(&netif->netmask),
|
||||
ip4_addr3(&netif->netmask),
|
||||
ip4_addr4(&netif->netmask)));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -237,6 +245,41 @@ netif_set_default(struct netif *netif)
|
||||
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
|
||||
netif_init(void)
|
||||
{
|
||||
|
||||
186
src/core/pbuf.c
186
src/core/pbuf.c
@@ -11,12 +11,15 @@
|
||||
* list. This is called a "pbuf chain".
|
||||
*
|
||||
* Multiple packets may be queued, also using this singly linked list.
|
||||
* This is called a "packet queue". So, a packet queue consists of one
|
||||
* or more pbuf chains, each of which consist of one or more pbufs.
|
||||
* This is called a "packet queue".
|
||||
*
|
||||
* 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
|
||||
* subtle. 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 as of yet.
|
||||
* precise but subtle.
|
||||
*
|
||||
* 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
|
||||
@@ -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.
|
||||
*
|
||||
* 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/stats.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#include "lwip/sys.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
|
||||
static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
|
||||
@@ -99,8 +100,7 @@ pbuf_init(void)
|
||||
struct pbuf *p, *q = NULL;
|
||||
u16_t i;
|
||||
|
||||
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
|
||||
LWIP_ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0);
|
||||
pbuf_pool = (struct pbuf *)MEM_ALIGN(pbuf_pool_memory);
|
||||
|
||||
#if PBUF_STATS
|
||||
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
|
||||
* 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;
|
||||
u16_t offset;
|
||||
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 */
|
||||
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 */
|
||||
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
|
||||
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 */
|
||||
p->tot_len = length;
|
||||
/* 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->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
|
||||
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;
|
||||
/* calculate remaining length to be allocated */
|
||||
rem_len -= q->len;
|
||||
@@ -303,7 +303,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
||||
break;
|
||||
case PBUF_RAM:
|
||||
/* 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) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -314,9 +314,9 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
||||
p->flags = PBUF_FLAG_RAM;
|
||||
|
||||
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
|
||||
((u32_t)p->payload % MEM_ALIGNMENT) == 0);
|
||||
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
|
||||
break;
|
||||
/* pbuf references existing (static constant) ROM payload? */
|
||||
/* pbuf references existing (non-volatile static constant) ROM payload? */
|
||||
case PBUF_ROM:
|
||||
/* pbuf references existing (externally allocated) RAM payload? */
|
||||
case PBUF_REF:
|
||||
@@ -338,7 +338,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
||||
}
|
||||
/* set reference count */
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -450,76 +450,82 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
|
||||
*
|
||||
* 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.
|
||||
* (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
|
||||
* 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.
|
||||
* @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
|
||||
pbuf_header(struct pbuf *p, s16_t header_size)
|
||||
pbuf_header(struct pbuf *p, s16_t header_size_increment)
|
||||
{
|
||||
void *payload;
|
||||
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
if ((header_size_increment == 0) || (p == NULL)) return 0;
|
||||
|
||||
/* remember current payload pointer */
|
||||
payload = p->payload;
|
||||
|
||||
/* pbuf types containing payloads? */
|
||||
if (p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL) {
|
||||
/* set new payload pointer */
|
||||
p->payload = (u8_t *)p->payload - header_size;
|
||||
p->payload = (u8_t *)p->payload - header_size_increment;
|
||||
/* boundary check fails? */
|
||||
if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p\n",
|
||||
(u8_t *)p->payload,
|
||||
(u8_t *)p + sizeof(struct pbuf)) );\
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
|
||||
(void *)p->payload,
|
||||
(void *)(p + 1)));\
|
||||
/* restore old payload pointer */
|
||||
p->payload = payload;
|
||||
/* bail out unsuccesfully */
|
||||
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) {
|
||||
/* 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 */
|
||||
p->payload = (u8_t *)p->payload - header_size;
|
||||
p->payload = (u8_t *)p->payload - header_size_increment;
|
||||
} else {
|
||||
/* cannot expand payload to front (yet!)
|
||||
* bail out unsuccesfully */
|
||||
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 */
|
||||
p->len += header_size;
|
||||
p->tot_len += header_size;
|
||||
p->len += header_size_increment;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereference a pbuf (chain) and deallocate any no-longer-used
|
||||
* pbufs at the head of this chain.
|
||||
* Dereference a pbuf chain or queue and deallocate any no-longer-used
|
||||
* pbufs at the head of this chain or queue.
|
||||
*
|
||||
* Decrements the pbuf reference count. If it reaches
|
||||
* zero, the pbuf is deallocated.
|
||||
* Decrements the pbuf reference count. If it reaches zero, the pbuf is
|
||||
* deallocated.
|
||||
*
|
||||
* 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
|
||||
* decrementing. (This might de-allocate the whole chain.)
|
||||
* up to the first pbuf which has a non-zero reference count after
|
||||
* decrementing. So, when all reference counts are one, the whole
|
||||
* chain is free'd.
|
||||
*
|
||||
* @param pbuf The pbuf (chain) to be dereferenced.
|
||||
*
|
||||
* @return the number of pbufs that were de-allocated
|
||||
* 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
|
||||
* that refer to the pbuf (or into the pbuf).
|
||||
*
|
||||
@@ -542,6 +548,8 @@ pbuf_free(struct pbuf *p)
|
||||
u8_t count;
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
/* if assertions are disabled, proceed with debug output */
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
|
||||
return 0;
|
||||
@@ -576,7 +584,7 @@ pbuf_free(struct pbuf *p)
|
||||
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
|
||||
p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
|
||||
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) {
|
||||
memp_free(MEMP_PBUF, p);
|
||||
/* p->flags == PBUF_FLAG_RAM */
|
||||
@@ -589,8 +597,8 @@ pbuf_free(struct pbuf *p)
|
||||
/* p->ref > 0, this pbuf is still referenced to */
|
||||
/* (and so the remaining pbufs in chain as well) */
|
||||
} else {
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, (unsigned int)p->ref));
|
||||
/* stop walking through chain */
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, (u16_t)p->ref));
|
||||
/* stop walking through the chain */
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
@@ -653,8 +661,8 @@ pbuf_cat(struct pbuf *h, struct pbuf *t)
|
||||
{
|
||||
struct pbuf *p;
|
||||
|
||||
LWIP_ASSERT("h != NULL", h != NULL);
|
||||
LWIP_ASSERT("t != NULL", t != NULL);
|
||||
LWIP_ASSERT("h != NULL (programmer violates API)", h != NULL);
|
||||
LWIP_ASSERT("t != NULL (programmer violates API)", t != NULL);
|
||||
if ((h == NULL) || (t == NULL)) return;
|
||||
|
||||
/* 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 } */
|
||||
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 */
|
||||
p->tot_len += t->tot_len;
|
||||
/* chain last pbuf of head (p) with first of tail (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));
|
||||
}
|
||||
|
||||
/* For packet queueing. Note that queued packets must be dequeued first
|
||||
* before calling any pbuf functions. */
|
||||
/* For packet queueing. Note that queued packets MUST be dequeued first
|
||||
* using pbuf_dequeue() before calling other pbuf_() functions. */
|
||||
#if ARP_QUEUEING
|
||||
/**
|
||||
* 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 n packet to be queued
|
||||
*
|
||||
* Both packets MUST be given, and must be different.
|
||||
*/
|
||||
void
|
||||
pbuf_queue(struct pbuf *p, struct pbuf *n)
|
||||
{
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
LWIP_ASSERT("n != NULL", n != NULL);
|
||||
|
||||
if ((p == NULL) || (n == NULL))
|
||||
#if PBUF_DEBUG /* remember head of queue */
|
||||
struct pbuf *q = p;
|
||||
#endif
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* iterate through all packets on queue */
|
||||
while (p->next != NULL) {
|
||||
@@ -720,25 +739,39 @@ pbuf_queue(struct pbuf *p, struct pbuf *n)
|
||||
#if PBUF_DEBUG
|
||||
/* iterate through all pbufs in packet */
|
||||
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 */
|
||||
LWIP_ASSERT("p->next != NULL", p->next != NULL);
|
||||
p = p->next;
|
||||
/* { p->tot_len == p->len => p is last pbuf of a packet } */
|
||||
}
|
||||
#endif
|
||||
/* now p->tot_len == p->len */
|
||||
/* { p is last pbuf of a packet } */
|
||||
/* 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 */
|
||||
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);
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
* @return first packet on the remaining queue (NULL if no further packets).
|
||||
*
|
||||
@@ -749,19 +782,28 @@ pbuf_dequeue(struct pbuf *p)
|
||||
struct pbuf *q;
|
||||
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) {
|
||||
/* make sure invariant condition holds */
|
||||
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
|
||||
/* make sure each packet is complete */
|
||||
LWIP_ASSERT("p->next != NULL", p->next != NULL);
|
||||
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;
|
||||
/* dequeue p from queue */
|
||||
/* dequeue packet p from queue */
|
||||
p->next = NULL;
|
||||
/* q is now referenced to one less time */
|
||||
pbuf_free(q);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: dereferencing remaining queue %p\n", (void *)q));
|
||||
/* any next packet on queue? */
|
||||
if (q != NULL) {
|
||||
/* 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;
|
||||
}
|
||||
#endif
|
||||
@@ -779,7 +821,7 @@ pbuf_dequeue(struct pbuf *p)
|
||||
*
|
||||
* @note You MUST explicitly use p = pbuf_take(p);
|
||||
* 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().
|
||||
* 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 */
|
||||
if (p->len <= PBUF_POOL_BUFSIZE) {
|
||||
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 {
|
||||
/* no replacement pbuf yet */
|
||||
q = NULL;
|
||||
@@ -816,7 +860,9 @@ pbuf_take(struct pbuf *p)
|
||||
/* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
|
||||
if (q == NULL) {
|
||||
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? */
|
||||
if (q != NULL)
|
||||
@@ -899,8 +945,10 @@ pbuf_dechain(struct pbuf *p)
|
||||
/* q is no longer referenced by p, free it */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
|
||||
tail_gone = pbuf_free(q);
|
||||
if (tail_gone > 0) LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
|
||||
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
|
||||
if (tail_gone > 0) {
|
||||
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 */
|
||||
}
|
||||
/* 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
|
||||
* 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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -35,20 +38,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* raw.c
|
||||
*
|
||||
* The code for the Raw Access to the IP
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/raw.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
@@ -57,11 +55,10 @@
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#if LWIP_RAW
|
||||
/* The list of RAW PCBs */
|
||||
|
||||
/** The list of RAW PCBs */
|
||||
static struct raw_pcb *raw_pcbs = NULL;
|
||||
|
||||
|
||||
void
|
||||
raw_init(void)
|
||||
{
|
||||
@@ -69,42 +66,54 @@ raw_init(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if in incoming IP packet is covered by a RAW pcb and
|
||||
* and process it if possible
|
||||
* Determine if in incoming IP packet is covered by a RAW PCB
|
||||
* and if so, pass it to a user-provided receive callback 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 netif network interface on which the datagram was received.
|
||||
* @return 0 if packet is not eated (pbuf needs to be freed then)
|
||||
* or 1 if the packet has been eaten (pbuf needs not to be freed
|
||||
* then)
|
||||
* @Return - 1 if the packet has been eaten by a RAW PCB receive
|
||||
* callback function. The caller MAY NOT not reference the
|
||||
* 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)
|
||||
{
|
||||
struct raw_pcb *pcb;
|
||||
struct ip_hdr *iphdr;
|
||||
int proto;
|
||||
int rc = 0;
|
||||
s16_t proto;
|
||||
u8_t eaten = 0;
|
||||
|
||||
iphdr = p->payload;
|
||||
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->recv) {
|
||||
if (!pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)))
|
||||
return 0;
|
||||
/* receive callback function available? */
|
||||
if (pcb->recv != NULL) {
|
||||
/* 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);
|
||||
rc = 1;
|
||||
break;
|
||||
/* no receive callback function was set for this raw PCB */
|
||||
/* drop the packet */
|
||||
}
|
||||
pcb = pcb->next;
|
||||
}
|
||||
return rc;
|
||||
return eaten;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,7 +125,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
||||
*
|
||||
* @return lwIP error code.
|
||||
* - 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.
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
*
|
||||
@@ -139,7 +148,7 @@ raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
||||
*
|
||||
* @return lwIP error code
|
||||
*
|
||||
* @see raw_disconnect() and raw_send_to()
|
||||
* @see raw_disconnect() and raw_sendto()
|
||||
*/
|
||||
err_t
|
||||
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
|
||||
* is received. If the callback function returns a value unequal 0
|
||||
* the raw packet is "eaten" and not forwarded to any other raw pcb
|
||||
* including lwip itself
|
||||
* Set the callback function for received packets that match the
|
||||
* raw PCB's protocol and binding.
|
||||
*
|
||||
* 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
|
||||
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),
|
||||
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
|
||||
* modify the IP headers (this is inconsitent with the receive callback where
|
||||
* you actually get the IP headers), you can only specifiy the ip payload here.
|
||||
* It requires some more changes in LWIP. (there will be a raw_send() function
|
||||
* then)
|
||||
* modify the IP headers (this is inconsistent with the receive callback where
|
||||
* 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
|
||||
* then.)
|
||||
*
|
||||
* @param pcb the raw pcb which to send
|
||||
* @param p the ip payload to send
|
||||
* @param ipaddr the destination address of the whole IP packet
|
||||
* @param p the IP payload to send
|
||||
* @param ipaddr the destination address of the IP packet
|
||||
*
|
||||
*/
|
||||
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;
|
||||
struct netif *netif;
|
||||
struct ip_addr *src_ip;
|
||||
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? */
|
||||
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);
|
||||
/* new header pbuf could not be allocated? */
|
||||
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;
|
||||
}
|
||||
/* chain header q in front of given pbuf p */
|
||||
pbuf_chain(q, p);
|
||||
/* { 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 {
|
||||
/* first pbuf q equals given pbuf */
|
||||
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) {
|
||||
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
|
||||
/* ++lwip_stats.raw.rterr;*/
|
||||
#endif /* RAW_STATS */
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
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()
|
||||
*
|
||||
* @param pcb the raw pcb which to send
|
||||
* @param p the ip payload to send
|
||||
* @param ipaddr the destination address of the whole IP packet
|
||||
* @param p the IP payload to send
|
||||
* @param ipaddr the destination address of the IP packet
|
||||
*
|
||||
*/
|
||||
err_t
|
||||
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) {
|
||||
/* make list start at 2nd pcb */
|
||||
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) {
|
||||
/* find pcb in raw_pcbs list */
|
||||
if (pcb2->next != NULL && pcb2->next == pcb) {
|
||||
@@ -303,7 +320,6 @@ raw_new(u16_t proto) {
|
||||
pcb->next = raw_pcbs;
|
||||
raw_pcbs = 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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -30,6 +30,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
@@ -47,5 +48,68 @@ stats_init(void)
|
||||
{
|
||||
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 */
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
struct sswt_cb
|
||||
{
|
||||
int timeflag;
|
||||
s16_t timeflag;
|
||||
sys_sem_t *psem;
|
||||
};
|
||||
|
||||
@@ -170,10 +170,11 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
||||
|
||||
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));
|
||||
|
||||
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
|
||||
|
||||
if (timeouts->next == NULL) {
|
||||
timeouts->next = timeout;
|
||||
return;
|
||||
@@ -186,14 +187,13 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
||||
} else {
|
||||
for(t = timeouts->next; t != NULL; t = t->next) {
|
||||
timeout->time -= t->time;
|
||||
if (t->next == NULL ||
|
||||
t->next->time > timeout->time) {
|
||||
if (t->next != NULL) {
|
||||
t->next->time -= timeout->time;
|
||||
}
|
||||
timeout->next = t->next;
|
||||
t->next = timeout;
|
||||
break;
|
||||
if (t->next == NULL || t->next->time > timeout->time) {
|
||||
if (t->next != NULL) {
|
||||
t->next->time -= timeout->time;
|
||||
}
|
||||
timeout->next = t->next;
|
||||
t->next = timeout;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
351
src/core/tcp.c
351
src/core/tcp.c
@@ -2,10 +2,15 @@
|
||||
* @file
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -36,16 +41,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* 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 <string.h>
|
||||
|
||||
#include "lwip/opt.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};
|
||||
|
||||
/* 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
|
||||
state in which they accept or send
|
||||
data. */
|
||||
struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
|
||||
|
||||
/** List of all TCP PCBs in LISTEN state */
|
||||
union tcp_listen_pcbs_t tcp_listen_pcbs;
|
||||
/** List of all TCP PCBs that are in a state in which
|
||||
* 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;
|
||||
|
||||
static u8_t tcp_timer;
|
||||
|
||||
static u16_t tcp_new_port(void);
|
||||
|
||||
|
||||
/*
|
||||
* tcp_init():
|
||||
*
|
||||
/**
|
||||
* Initializes the TCP layer.
|
||||
*/
|
||||
|
||||
void
|
||||
tcp_init(void)
|
||||
{
|
||||
/* Clear globals. */
|
||||
tcp_listen_pcbs = NULL;
|
||||
tcp_listen_pcbs.listen_pcbs = NULL;
|
||||
tcp_active_pcbs = NULL;
|
||||
tcp_tw_pcbs = NULL;
|
||||
tcp_tmp_pcb = NULL;
|
||||
@@ -96,13 +90,10 @@ tcp_init(void)
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_tmr():
|
||||
*
|
||||
/**
|
||||
* Called periodically to dispatch TCP timers.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
tcp_tmr(void)
|
||||
{
|
||||
@@ -116,13 +107,10 @@ tcp_tmr(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_close():
|
||||
*
|
||||
/**
|
||||
* Closes the connection held by the PCB.
|
||||
*
|
||||
*/
|
||||
|
||||
err_t
|
||||
tcp_close(struct tcp_pcb *pcb)
|
||||
{
|
||||
@@ -134,9 +122,21 @@ tcp_close(struct tcp_pcb *pcb)
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||
#endif /* TCP_DEBUG */
|
||||
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:
|
||||
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);
|
||||
pcb = NULL;
|
||||
break;
|
||||
@@ -172,15 +172,12 @@ tcp_close(struct tcp_pcb *pcb)
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_abort()
|
||||
*
|
||||
/**
|
||||
* 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
|
||||
* killed because of shortage of memory.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
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
|
||||
* IP address is not given (i.e., ipaddr == NULL), the IP address of
|
||||
* 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)
|
||||
{
|
||||
struct tcp_pcb *cpcb;
|
||||
#ifdef SO_REUSE
|
||||
int reuse_port_all_set = 1;
|
||||
#endif /* SO_REUSE */
|
||||
|
||||
if (port == 0) {
|
||||
port = tcp_new_port();
|
||||
}
|
||||
#ifndef SO_REUSE
|
||||
/* 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) {
|
||||
if (cpcb->local_port == port) {
|
||||
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)) {
|
||||
pcb->local_ip = *ipaddr;
|
||||
}
|
||||
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;
|
||||
}
|
||||
#if LWIP_CALLBACK_API
|
||||
@@ -386,16 +282,13 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
|
||||
}
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
/*
|
||||
* tcp_listen():
|
||||
*
|
||||
/**
|
||||
* Set the state of the connection to be LISTEN, which means that it
|
||||
* is able to accept incoming connections. The protocol control block
|
||||
* is reallocated in order to consume less memory. Setting the
|
||||
* connection to LISTEN is an irreversible process.
|
||||
*
|
||||
*/
|
||||
|
||||
struct tcp_pcb *
|
||||
tcp_listen(struct tcp_pcb *pcb)
|
||||
{
|
||||
@@ -421,19 +314,16 @@ tcp_listen(struct tcp_pcb *pcb)
|
||||
#if LWIP_CALLBACK_API
|
||||
lpcb->accept = tcp_accept_null;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
TCP_REG(&tcp_listen_pcbs, lpcb);
|
||||
TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb);
|
||||
return (struct tcp_pcb *)lpcb;
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_recved():
|
||||
*
|
||||
/**
|
||||
* This function should be called by the application when it has
|
||||
* processed the data. The purpose is to advertise a larger window
|
||||
* when the data has been processed.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
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) &&
|
||||
!(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);
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_new_port():
|
||||
*
|
||||
/**
|
||||
* A nastly hack featuring 'goto' statements that allocates a
|
||||
* new TCP local port.
|
||||
*/
|
||||
|
||||
static u16_t
|
||||
tcp_new_port(void)
|
||||
{
|
||||
@@ -483,7 +390,7 @@ tcp_new_port(void)
|
||||
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) {
|
||||
goto again;
|
||||
}
|
||||
@@ -491,14 +398,11 @@ tcp_new_port(void)
|
||||
return port;
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_connect():
|
||||
*
|
||||
/**
|
||||
* Connects to another host. The function given as the "connected"
|
||||
* argument will be called when the connection has been established.
|
||||
*
|
||||
*/
|
||||
|
||||
err_t
|
||||
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))
|
||||
@@ -507,7 +411,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
|
||||
err_t ret;
|
||||
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) {
|
||||
pcb->remote_ip = *ipaddr;
|
||||
} else {
|
||||
@@ -546,14 +450,11 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_slowtmr():
|
||||
*
|
||||
/**
|
||||
* 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
|
||||
* various timers such as the inactivity timer in each PCB.
|
||||
*/
|
||||
|
||||
void
|
||||
tcp_slowtmr(void)
|
||||
{
|
||||
@@ -569,7 +470,9 @@ tcp_slowtmr(void)
|
||||
/* Steps through all of the active PCBs. */
|
||||
prev = NULL;
|
||||
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) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));
|
||||
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) {
|
||||
|
||||
/* 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));
|
||||
|
||||
/* Double retransmission time-out unless we are trying to
|
||||
@@ -598,7 +501,6 @@ tcp_slowtmr(void)
|
||||
if (pcb->state != SYN_SENT) {
|
||||
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
|
||||
}
|
||||
tcp_rexmit(pcb);
|
||||
/* Reduce congestion window and ssthresh. */
|
||||
eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
|
||||
pcb->ssthresh = eff_wnd >> 1;
|
||||
@@ -606,9 +508,12 @@ tcp_slowtmr(void)
|
||||
pcb->ssthresh = pcb->mss * 2;
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
if (pcb->state == FIN_WAIT_2) {
|
||||
@@ -622,7 +527,7 @@ tcp_slowtmr(void)
|
||||
/* Check if KEEPALIVE should be sent */
|
||||
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) {
|
||||
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_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 */
|
||||
if (pcb->state == SYN_RCVD) {
|
||||
if ((u32_t)(tcp_ticks - pcb->tmr) >
|
||||
TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
|
||||
TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
|
||||
++pcb_remove;
|
||||
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 (pcb_remove) {
|
||||
@@ -730,12 +642,9 @@ tcp_slowtmr(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_fasttmr():
|
||||
*
|
||||
/**
|
||||
* Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
|
||||
*/
|
||||
|
||||
void
|
||||
tcp_fasttmr(void)
|
||||
{
|
||||
@@ -751,13 +660,10 @@ tcp_fasttmr(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_segs_free():
|
||||
*
|
||||
/**
|
||||
* Deallocates a list of TCP segments (tcp_seg structures).
|
||||
*
|
||||
*/
|
||||
|
||||
u8_t
|
||||
tcp_segs_free(struct tcp_seg *seg)
|
||||
{
|
||||
@@ -771,13 +677,10 @@ tcp_segs_free(struct tcp_seg *seg)
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_seg_free():
|
||||
*
|
||||
/**
|
||||
* Frees a TCP segment.
|
||||
*
|
||||
*/
|
||||
|
||||
u8_t
|
||||
tcp_seg_free(struct tcp_seg *seg)
|
||||
{
|
||||
@@ -795,13 +698,10 @@ tcp_seg_free(struct tcp_seg *seg)
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_setprio():
|
||||
*
|
||||
/**
|
||||
* Sets the priority of a connection.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
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
|
||||
|
||||
/*
|
||||
* tcp_seg_copy():
|
||||
*
|
||||
/**
|
||||
* Returns a copy of the given TCP segment.
|
||||
*
|
||||
*/
|
||||
|
||||
struct tcp_seg *
|
||||
tcp_seg_copy(struct tcp_seg *seg)
|
||||
{
|
||||
@@ -825,7 +722,7 @@ tcp_seg_copy(struct tcp_seg *seg)
|
||||
if (cseg == 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);
|
||||
return cseg;
|
||||
}
|
||||
@@ -869,7 +766,7 @@ tcp_kill_prio(u8_t prio)
|
||||
}
|
||||
}
|
||||
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));
|
||||
tcp_abort(inactive);
|
||||
}
|
||||
@@ -891,7 +788,7 @@ tcp_kill_timewait(void)
|
||||
}
|
||||
}
|
||||
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));
|
||||
tcp_abort(inactive);
|
||||
}
|
||||
@@ -951,12 +848,13 @@ tcp_alloc(u8_t prio)
|
||||
return pcb;
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_new():
|
||||
*
|
||||
/**
|
||||
* Creates a new TCP protocol control block but doesn't place it on
|
||||
* 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 *
|
||||
@@ -980,14 +878,11 @@ tcp_arg(struct tcp_pcb *pcb, void *arg)
|
||||
}
|
||||
#if LWIP_CALLBACK_API
|
||||
|
||||
/*
|
||||
* tcp_recv():
|
||||
*
|
||||
/**
|
||||
* Used to specify the function that should be called when a TCP
|
||||
* connection receives data.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
tcp_recv(struct tcp_pcb *pcb,
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_sent():
|
||||
*
|
||||
/**
|
||||
* Used to specify the function that should be called when TCP data
|
||||
* has been successfully delivered to the remote host.
|
||||
*
|
||||
@@ -1010,14 +903,11 @@ tcp_sent(struct tcp_pcb *pcb,
|
||||
pcb->sent = sent;
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_err():
|
||||
*
|
||||
/**
|
||||
* Used to specify the function that should be called when a fatal error
|
||||
* has occured on the connection.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
tcp_err(struct tcp_pcb *pcb,
|
||||
void (* errf)(void *arg, err_t err))
|
||||
@@ -1025,14 +915,11 @@ tcp_err(struct tcp_pcb *pcb,
|
||||
pcb->errf = errf;
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_accept():
|
||||
*
|
||||
/**
|
||||
* Used for specifying the function that should be called when a
|
||||
* LISTENing connection has been connected to another host.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
tcp_accept(struct tcp_pcb *pcb,
|
||||
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 */
|
||||
|
||||
|
||||
/*
|
||||
* tcp_poll():
|
||||
*
|
||||
/**
|
||||
* Used to specify the function that should be called periodically
|
||||
* from TCP. The interval is specified in terms of the TCP coarse
|
||||
* timer interval, which is called twice a second.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
tcp_poll(struct tcp_pcb *pcb,
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_pcb_purge():
|
||||
*
|
||||
/**
|
||||
* Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
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.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
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());
|
||||
}
|
||||
|
||||
/*
|
||||
* tcp_next_iss():
|
||||
*
|
||||
/**
|
||||
* Calculates a new initial sequence number for new connections.
|
||||
*
|
||||
*/
|
||||
|
||||
u32_t
|
||||
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, ("+-------------------------------+\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)));
|
||||
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)));
|
||||
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)));
|
||||
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_FLAGS(tcphdr) >> 5 & 1,
|
||||
TCPH_FLAGS(tcphdr) >> 4 & 1,
|
||||
@@ -1166,7 +1041,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
|
||||
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("), win)\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)));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||
}
|
||||
@@ -1247,28 +1122,28 @@ tcp_debug_print_pcbs(void)
|
||||
struct tcp_pcb *pcb;
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
|
||||
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->snd_nxt, pcb->rcv_nxt));
|
||||
tcp_debug_print_state(pcb->state);
|
||||
}
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
|
||||
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",
|
||||
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
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->snd_nxt, pcb->rcv_nxt));
|
||||
tcp_debug_print_state(pcb->state);
|
||||
}
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
|
||||
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->snd_nxt, pcb->rcv_nxt));
|
||||
tcp_debug_print_state(pcb->state);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
s16_t
|
||||
tcp_pcbs_sane(void)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,9 +2,13 @@
|
||||
* @file
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -35,27 +39,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* tcp_output.c
|
||||
*
|
||||
* The output functions of TCP.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#if LWIP_TCP
|
||||
@@ -63,24 +57,36 @@
|
||||
/* Forward declarations.*/
|
||||
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
|
||||
|
||||
|
||||
|
||||
err_t
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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,
|
||||
arg, len, (unsigned int)copy));
|
||||
if (pcb->state == SYN_SENT ||
|
||||
pcb->state == SYN_RCVD ||
|
||||
pcb->state == ESTABLISHED ||
|
||||
pcb->state == CLOSE_WAIT) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", copy=%"U16_F")\n", (void *)pcb,
|
||||
arg, len, (u16_t)copy));
|
||||
/* connection is in valid state for data transmission? */
|
||||
if (pcb->state == ESTABLISHED ||
|
||||
pcb->state == CLOSE_WAIT ||
|
||||
pcb->state == SYN_SENT ||
|
||||
pcb->state == SYN_RCVD) {
|
||||
if (len > 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
|
||||
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
u8_t flags, u8_t copy,
|
||||
u8_t *optdata, u8_t optlen)
|
||||
u8_t flags, u8_t copy,
|
||||
u8_t *optdata, u8_t optlen)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_seg *seg, *useg, *queue;
|
||||
@@ -103,41 +123,46 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
void *ptr;
|
||||
u8_t queuelen;
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%u)\n",
|
||||
(void *)pcb, arg, len, (unsigned int)flags, (unsigned int)copy));
|
||||
left = len;
|
||||
ptr = arg;
|
||||
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, (u16_t)flags, (u16_t)copy));
|
||||
LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
|
||||
len == 0 || optlen == 0);
|
||||
LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
|
||||
arg == NULL || optdata == NULL);
|
||||
/* fail on too much data */
|
||||
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;
|
||||
}
|
||||
left = len;
|
||||
ptr = arg;
|
||||
|
||||
/* seqno will be the sequence number of the first segment enqueued
|
||||
* by the call to this function. */
|
||||
seqno = pcb->snd_lbb;
|
||||
|
||||
queue = NULL;
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %u\n", (unsigned int)pcb->snd_queuelen));
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
|
||||
|
||||
/* Check if the queue length exceeds the configured maximum queue
|
||||
* length. If so, we return an error. */
|
||||
/* If total number of pbufs on the unsent/unacked queues exceeds the
|
||||
* configured maximum, return an error */
|
||||
queuelen = pcb->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));
|
||||
goto memerr;
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||
TCP_STATS_INC(tcp.memerr);
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
if (pcb->snd_queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
|
||||
pcb->unsent != NULL);
|
||||
if (queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
|
||||
pcb->unacked != 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
|
||||
* the local "queue" variable. */
|
||||
useg = queue = seg = NULL;
|
||||
seglen = 0;
|
||||
while (queue == NULL || left > 0) {
|
||||
|
||||
/* 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->p = NULL;
|
||||
|
||||
/* first segment of to-be-queued data? */
|
||||
if (queue == NULL) {
|
||||
useg = queue = seg;
|
||||
queue = seg;
|
||||
}
|
||||
/* subsequent segments of to-be-queued data */
|
||||
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);
|
||||
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
|
||||
* and data copied into pbuf, otherwise data comes from
|
||||
* ROM or other static memory, and need not be copied. If
|
||||
* optdata is != NULL, we have options instead of data. */
|
||||
|
||||
/* options? */
|
||||
if (optdata != NULL) {
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
|
||||
goto memerr;
|
||||
@@ -174,9 +204,10 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
++queuelen;
|
||||
seg->dataptr = seg->p->payload;
|
||||
}
|
||||
/* copy from volatile memory? */
|
||||
else if (copy) {
|
||||
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;
|
||||
}
|
||||
++queuelen;
|
||||
@@ -187,8 +218,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
}
|
||||
/* do not copy data */
|
||||
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
|
||||
* link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
|
||||
* instead of PBUF_REF here.
|
||||
@@ -198,6 +228,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
goto memerr;
|
||||
}
|
||||
++queuelen;
|
||||
/* reference the non-volatile payload data */
|
||||
p->payload = ptr;
|
||||
seg->dataptr = ptr;
|
||||
|
||||
@@ -212,28 +243,22 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
++queuelen;
|
||||
|
||||
/* Concatenate the headers and data pbufs together. */
|
||||
pbuf_cat(seg->p, p);
|
||||
pbuf_cat(seg->p/*header*/, p/*data*/);
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
/* Now that there are more segments queued, we check again if the
|
||||
length of the queue exceeds the configured maximum. */
|
||||
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;
|
||||
}
|
||||
|
||||
seg->len = seglen;
|
||||
#if 0 /* Was commented out. TODO: can someone say why this is here? */
|
||||
if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
|
||||
++seg->len;
|
||||
}
|
||||
#endif
|
||||
/* Build TCP header. */
|
||||
|
||||
/* build TCP header */
|
||||
if (pbuf_header(seg->p, TCP_HLEN)) {
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
|
||||
|
||||
TCP_STATS_INC(tcp.err);
|
||||
goto memerr;
|
||||
}
|
||||
@@ -256,17 +281,16 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
segments such as SYN|ACK. */
|
||||
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) + TCP_TCPLEN(seg),
|
||||
flags));
|
||||
(u16_t)flags));
|
||||
|
||||
left -= 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
|
||||
segments in the queue variable, we add them to the end of the
|
||||
pcb->unsent queue. */
|
||||
@@ -276,6 +300,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
else {
|
||||
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,
|
||||
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 &&
|
||||
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
|
||||
!(flags & (TCP_SYN | TCP_FIN)) &&
|
||||
/* fit within max seg size */
|
||||
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_cat(useg->p, queue->p);
|
||||
useg->len += queue->len;
|
||||
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) {
|
||||
seg = NULL;
|
||||
}
|
||||
memp_free(MEMP_TCP_SEG, queue);
|
||||
}
|
||||
else {
|
||||
/* empty list */
|
||||
if (useg == NULL) {
|
||||
/* initialize list with this segment */
|
||||
pcb->unsent = queue;
|
||||
|
||||
}
|
||||
/* enqueue segment */
|
||||
else {
|
||||
useg->next = queue;
|
||||
}
|
||||
@@ -309,13 +337,15 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
++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
|
||||
@@ -325,7 +355,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
memerr:
|
||||
memerr:
|
||||
TCP_STATS_INC(tcp.memerr);
|
||||
|
||||
if (queue != NULL) {
|
||||
@@ -334,9 +364,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
if (pcb->snd_queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != 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;
|
||||
}
|
||||
|
||||
@@ -349,7 +378,7 @@ tcp_output(struct tcp_pcb *pcb)
|
||||
struct tcp_seg *seg, *useg;
|
||||
u32_t wnd;
|
||||
#if TCP_CWND_DEBUG
|
||||
int i = 0;
|
||||
s16_t i = 0;
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
|
||||
/* 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);
|
||||
|
||||
|
||||
seg = pcb->unsent;
|
||||
|
||||
/* useg should point to last segment on unacked queue */
|
||||
@@ -370,24 +398,24 @@ tcp_output(struct tcp_pcb *pcb)
|
||||
if (useg != NULL) {
|
||||
for (; useg->next != NULL; useg = useg->next);
|
||||
}
|
||||
|
||||
|
||||
/* If the TF_ACK_NOW flag is set, we check if there is data that is
|
||||
to be sent. If data is to be sent out, we'll just piggyback our
|
||||
acknowledgement with the outgoing segment. If no data will be
|
||||
sent (either because the ->unsent queue is empty or because the
|
||||
window doesn't allow it) we'll have to construct an empty ACK
|
||||
segment and send it. */
|
||||
/* If the TF_ACK_NOW flag is set and no data will be sent (either
|
||||
* because the ->unsent queue is empty or because the window does
|
||||
* not allow it), construct an empty ACK segment and send it.
|
||||
*
|
||||
* If data is to be sent, we will just piggyback the ACK (see below).
|
||||
*/
|
||||
if (pcb->flags & TF_ACK_NOW &&
|
||||
(seg == NULL ||
|
||||
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);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
||||
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->src = htons(pcb->local_port);
|
||||
@@ -400,10 +428,10 @@ tcp_output(struct tcp_pcb *pcb)
|
||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
#endif
|
||||
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
pbuf_free(p);
|
||||
@@ -413,26 +441,26 @@ tcp_output(struct tcp_pcb *pcb)
|
||||
|
||||
#if TCP_OUTPUT_DEBUG
|
||||
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 */
|
||||
#if TCP_CWND_DEBUG
|
||||
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->lastack));
|
||||
} 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,
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
|
||||
ntohl(seg->tcphdr->seqno), pcb->lastack));
|
||||
}
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
|
||||
/* data available and window allows it to be sent? */
|
||||
while (seg != NULL &&
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
|
||||
#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,
|
||||
ntohl(seg->tcphdr->seqno) + seg->len -
|
||||
pcb->lastack,
|
||||
@@ -455,13 +483,26 @@ tcp_output(struct tcp_pcb *pcb)
|
||||
/* put segment on unacknowledged list if length > 0 */
|
||||
if (TCP_TCPLEN(seg) > 0) {
|
||||
seg->next = NULL;
|
||||
/* unacked list is empty? */
|
||||
if (pcb->unacked == NULL) {
|
||||
pcb->unacked = seg;
|
||||
useg = seg;
|
||||
/* unacked list is not empty? */
|
||||
} else {
|
||||
useg->next = seg;
|
||||
useg = useg->next;
|
||||
/* In the case of fast retransmit, the packet should not go to the tail
|
||||
* 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 {
|
||||
tcp_seg_free(seg);
|
||||
}
|
||||
@@ -470,6 +511,9 @@ tcp_output(struct tcp_pcb *pcb)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually send a TCP segment over IP
|
||||
*/
|
||||
static void
|
||||
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->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) +
|
||||
seg->len));
|
||||
|
||||
@@ -518,10 +562,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
seg->p->payload = seg->tcphdr;
|
||||
|
||||
seg->tcphdr->chksum = 0;
|
||||
#if CHECKSUM_GEN_TCP
|
||||
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
|
||||
&(pcb->local_ip),
|
||||
&(pcb->remote_ip),
|
||||
IP_PROTO_TCP, seg->p->tot_len);
|
||||
#endif
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
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);
|
||||
|
||||
tcphdr->chksum = 0;
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
|
||||
#endif
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
/* 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);
|
||||
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
|
||||
@@ -571,14 +648,11 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Move all unacked segments to the unsent queue. */
|
||||
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
|
||||
|
||||
seg->next = pcb->unsent;
|
||||
/* Move the first unacked segment to the unsent queue */
|
||||
seg = pcb->unacked->next;
|
||||
pcb->unacked->next = pcb->unsent;
|
||||
pcb->unsent = pcb->unacked;
|
||||
|
||||
pcb->unacked = NULL;
|
||||
|
||||
pcb->unacked = seg;
|
||||
|
||||
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||
|
||||
@@ -592,17 +666,18 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tcp_keepalive(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct pbuf *p;
|
||||
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_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);
|
||||
|
||||
@@ -621,8 +696,9 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
/* Send output to IP */
|
||||
@@ -630,7 +706,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
||||
|
||||
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 */
|
||||
|
||||
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.
|
||||
*
|
||||
* 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/def.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
@@ -64,83 +66,12 @@ struct udp_pcb *udp_pcbs = NULL;
|
||||
|
||||
static struct udp_pcb *pcb_cache = NULL;
|
||||
|
||||
|
||||
void
|
||||
udp_init(void)
|
||||
{
|
||||
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.
|
||||
*
|
||||
@@ -156,16 +87,11 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct udp_hdr *udphdr;
|
||||
struct udp_pcb *pcb;
|
||||
struct udp_pcb *uncon_pcb;
|
||||
struct ip_hdr *iphdr;
|
||||
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;
|
||||
|
||||
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)))) {
|
||||
/* 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.drop);
|
||||
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);
|
||||
|
||||
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);
|
||||
dest = ntohs(udphdr->dest);
|
||||
@@ -192,117 +118,46 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
udp_debug_print(udphdr);
|
||||
|
||||
/* 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_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
|
||||
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
|
||||
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
|
||||
|
||||
#ifdef SO_REUSE
|
||||
pcb_temp = udp_pcbs;
|
||||
|
||||
again_1:
|
||||
|
||||
/* 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 */
|
||||
local_match = 0;
|
||||
uncon_pcb = NULL;
|
||||
/* Iterate through the UDP pcb list for a matching pcb */
|
||||
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
/* 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_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));
|
||||
|
||||
/* PCB remote port matches UDP source port? */
|
||||
if ((pcb->remote_port == src) &&
|
||||
/* 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... */
|
||||
/* compare PCB local addr+port to UDP destination addr+port */
|
||||
if ((pcb->local_port == dest) &&
|
||||
(ip_addr_isany(&pcb->local_ip) ||
|
||||
/* PCB local IP address matches UDP destination IP 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_1 = 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 */
|
||||
local_match = 1;
|
||||
if ((uncon_pcb == NULL) &&
|
||||
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
|
||||
/* the first unconnected matching PCB */
|
||||
uncon_pcb = pcb;
|
||||
}
|
||||
}
|
||||
/* compare PCB remote addr+port to UDP source addr+port */
|
||||
if ((local_match != 0) &&
|
||||
(pcb->remote_port == src) &&
|
||||
(ip_addr_isany(&pcb->remote_ip) ||
|
||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)))) {
|
||||
/* the first fully matching PCB */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* no fully matching pcb found? then look for an unconnected pcb */
|
||||
if (pcb == NULL) {
|
||||
/* Iterate through the UDP PCB list for a pcb that matches
|
||||
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;
|
||||
}
|
||||
}
|
||||
pcb = uncon_pcb;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
#endif /* IPv4 */
|
||||
/* Do the UDP Lite checksum */
|
||||
#if CHECKSUM_CHECK_UDP
|
||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||
(struct ip_addr *)&(iphdr->dest),
|
||||
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
|
||||
@@ -326,7 +182,9 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if CHECKSUM_CHECK_UDP
|
||||
if (udphdr->chksum != 0) {
|
||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||
(struct ip_addr *)&(iphdr->dest),
|
||||
@@ -340,45 +198,24 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
pbuf_header(p, -UDP_HLEN);
|
||||
if (pcb != NULL) {
|
||||
snmp_inc_udpindatagrams();
|
||||
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
|
||||
#ifdef SO_REUSE
|
||||
/* First socket should receive now */
|
||||
if(reuse_port_1 || reuse_port_2) {
|
||||
/* 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;
|
||||
/* callback */
|
||||
if (pcb->recv != NULL)
|
||||
{
|
||||
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
|
||||
}
|
||||
} 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"));
|
||||
|
||||
/* 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) &&
|
||||
!ip_addr_ismulticast(&iphdr->dest)) {
|
||||
if (!ip_addr_isbroadcast(&iphdr->dest, inp) &&
|
||||
!ip_addr_ismulticast(&iphdr->dest)) {
|
||||
|
||||
/* adjust pbuf pointer */
|
||||
p->payload = iphdr;
|
||||
@@ -396,6 +233,47 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
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.
|
||||
*
|
||||
@@ -405,10 +283,9 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
* @return lwIP error code.
|
||||
* - ERR_OK. Successful. No error occured.
|
||||
* - ERR_MEM. Out of memory.
|
||||
* - ERR_USE. The specified ipaddr and port are already bound to by
|
||||
* another UDP PCB.
|
||||
* - ERR_RTE. Could not find route to destination address.
|
||||
*
|
||||
* @see udp_disconnect()
|
||||
* @see udp_disconnect() udp_sendto()
|
||||
*/
|
||||
err_t
|
||||
udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
@@ -430,10 +307,18 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
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? */
|
||||
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);
|
||||
/* new header pbuf could not be allocated? */
|
||||
if (q == NULL) {
|
||||
@@ -445,23 +330,19 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
/* { 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));
|
||||
/* adding a header within p succeeded */
|
||||
} else {
|
||||
} else {
|
||||
/* first pbuf q equals given pbuf */
|
||||
q = 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->src = htons(pcb->local_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) {
|
||||
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? */
|
||||
/* PCB local address is IP_ANY_ADDR? */
|
||||
if (ip_addr_isany(&pcb->local_ip)) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
src_ip = &(netif->ip_addr);
|
||||
@@ -470,42 +351,52 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
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? */
|
||||
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 */
|
||||
udphdr->len = htons(pcb->chksum_len);
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip),
|
||||
IP_PROTO_UDP, pcb->chksum_len);
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
|
||||
#else
|
||||
udphdr->chksum = 0x0000;
|
||||
#endif
|
||||
/* 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);
|
||||
snmp_inc_udpoutdatagrams();
|
||||
/* UDP */
|
||||
} 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);
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
||||
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' */
|
||||
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04x\n", udphdr->chksum));
|
||||
snmp_inc_udpoutdatagrams();
|
||||
#else
|
||||
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"));
|
||||
/* output to IP */
|
||||
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) {
|
||||
/* free the header */
|
||||
/* p is also still referenced by the caller, and will live on */
|
||||
pbuf_free(q);
|
||||
/* free the header pbuf */
|
||||
pbuf_free(q); q = NULL;
|
||||
/* { p is still referenced by the caller, and will live on } */
|
||||
}
|
||||
|
||||
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;
|
||||
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 = "));
|
||||
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;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
#ifndef SO_REUSE
|
||||
/* this code does not allow upper layer to share a UDP port for
|
||||
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
|
||||
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_cmp(&(ipcb->local_ip), ipaddr))) {
|
||||
/* 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;
|
||||
}
|
||||
#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);
|
||||
/* no port specified? */
|
||||
if (port == 0) {
|
||||
@@ -642,11 +487,11 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
pcb->next = udp_pcbs;
|
||||
udp_pcbs = pcb;
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %u.%u.%u.%u, port %u\n",
|
||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %u.%u.%u.%u, port %u\n",
|
||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
|
||||
|
||||
/* Insert UDP PCB into the list of active UDP PCBs. */
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -780,18 +629,17 @@ udp_new(void) {
|
||||
}
|
||||
|
||||
#if UDP_DEBUG
|
||||
int
|
||||
void
|
||||
udp_debug_print(struct udp_hdr *udphdr)
|
||||
{
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\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)));
|
||||
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)));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||
return 0;
|
||||
}
|
||||
#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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -39,14 +39,17 @@
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
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_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u16_t proto_len);
|
||||
|
||||
u32_t inet_addr(const char *cp);
|
||||
int inet_aton(const char *cp, struct in_addr *addr);
|
||||
u8_t *inet_ntoa(u32_t addr); /* returns ptr to static buffer; not reentrant! */
|
||||
s8_t inet_aton(const char *cp, struct in_addr *addr);
|
||||
char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */
|
||||
|
||||
#ifdef 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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -40,10 +40,8 @@
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
struct netif;
|
||||
|
||||
void ip_init(void);
|
||||
u8_t ip_lookup(void *header, struct netif *inp);
|
||||
struct netif *ip_route(struct ip_addr *dest);
|
||||
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,
|
||||
@@ -129,7 +127,7 @@ PACK_STRUCT_END
|
||||
|
||||
#define IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12)
|
||||
#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_ID(hdr) ((hdr)->_id)
|
||||
#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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -34,6 +34,40 @@
|
||||
|
||||
#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
|
||||
* for the wildcard and the broadcast address
|
||||
*/
|
||||
@@ -76,33 +110,22 @@
|
||||
|
||||
#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) | \
|
||||
((u32_t)(c & 0xff) << 8) | (u32_t)(d & 0xff))
|
||||
|
||||
#define ip_addr_set(dest, src) (dest)->addr = \
|
||||
((src) == NULL? 0:\
|
||||
((struct ip_addr *)src)->addr)
|
||||
#define ip_addr_maskcmp(addr1, addr2, mask) (((addr1)->addr & \
|
||||
(src)->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) == \
|
||||
((addr2)->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_isbroadcast(addr1, mask) (((((addr1)->addr) & ~((mask)->addr)) == \
|
||||
(0xffffffff & ~((mask)->addr))) || \
|
||||
((addr1)->addr == 0xffffffff) || \
|
||||
((addr1)->addr == 0x00000000))
|
||||
u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
|
||||
|
||||
#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", \
|
||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \
|
||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \
|
||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \
|
||||
ipaddr?(unsigned int)ntohl((ipaddr)->addr) & 0xff:0U))
|
||||
#define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
|
||||
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \
|
||||
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \
|
||||
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \
|
||||
ipaddr?(u16_t)ntohl((ipaddr)->addr) & 0xff:0U))
|
||||
|
||||
/* cast to unsigned int, as it is used as argument to printf functions
|
||||
* which expect integer arguments */
|
||||
#define ip4_addr1(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff)
|
||||
#define ip4_addr2(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff)
|
||||
#define ip4_addr3(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff)
|
||||
#define ip4_addr4(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr)) & 0xff)
|
||||
* which expect integer arguments. CSi: use cc.h formatters (conversion chars)! */
|
||||
#define ip4_addr1(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff)
|
||||
#define ip4_addr2(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff)
|
||||
#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
|
||||
#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff)
|
||||
#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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -38,8 +38,9 @@
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
struct pbuf * ip_reass(struct pbuf *);
|
||||
err_t ip_frag(struct pbuf *, struct netif *, struct ip_addr *);
|
||||
void ip_reass_tmr(void);
|
||||
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__ */
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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);
|
||||
|
||||
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 _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.
|
||||
*
|
||||
* 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 */
|
||||
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,
|
||||
unsigned char ttl, unsigned char proto,
|
||||
u8_t ttl, u8_t proto,
|
||||
struct netif *netif);
|
||||
|
||||
#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.
|
||||
*
|
||||
* 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[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);
|
||||
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);
|
||||
int ip_addr_isany(struct ip_addr *addr);
|
||||
u8_t ip_addr_isany(struct ip_addr *addr);
|
||||
|
||||
|
||||
#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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -75,7 +75,7 @@ struct api_msg_msg {
|
||||
struct {
|
||||
void *dataptr;
|
||||
u16_t len;
|
||||
unsigned char copy;
|
||||
u8_t copy;
|
||||
} w;
|
||||
sys_mbox_t mbox;
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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...
|
||||
* 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)
|
||||
#else /* LWIP_DEBUG */
|
||||
# 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.
|
||||
*
|
||||
* 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_gw_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_t1_renew; /* recommended renew time (usually 50% 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(u16_t secs);
|
||||
PACK_STRUCT_FIELD(u16_t flags);
|
||||
PACK_STRUCT_FIELD(u32_t ciaddr);
|
||||
PACK_STRUCT_FIELD(u32_t yiaddr);
|
||||
PACK_STRUCT_FIELD(u32_t siaddr);
|
||||
PACK_STRUCT_FIELD(u32_t giaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr ciaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr yiaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr siaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr giaddr);
|
||||
#define DHCP_CHADDR_LEN 16U
|
||||
PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]);
|
||||
#define DHCP_SNAME_LEN 64U
|
||||
@@ -82,8 +86,12 @@ struct dhcp_msg
|
||||
PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]);
|
||||
PACK_STRUCT_FIELD(u32_t cookie);
|
||||
#define DHCP_MIN_OPTIONS_LEN 68U
|
||||
/** make sure user does not configure this too small */
|
||||
#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
|
||||
# undef DHCP_OPTIONS_LEN
|
||||
#endif
|
||||
/** allow this to be configured in lwipopts.h, but not too small */
|
||||
#if ((!defined(DHCP_OPTIONS_LEN)) || (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
|
||||
#if (!defined(DHCP_OPTIONS_LEN))
|
||||
/** set this to be sufficient for your options in outgoing DHCP msgs */
|
||||
# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN
|
||||
#endif
|
||||
@@ -96,11 +104,13 @@ PACK_STRUCT_END
|
||||
|
||||
/** start DHCP configuration */
|
||||
err_t dhcp_start(struct netif *netif);
|
||||
/** enforce early lease renewal (not needed normally)*/
|
||||
err_t dhcp_renew(struct netif *netif);
|
||||
/** release the DHCP lease, usually called before dhcp_stop()*/
|
||||
err_t dhcp_release(struct netif *netif);
|
||||
/** stop DHCP configuration */
|
||||
void dhcp_stop(struct netif *netif);
|
||||
/** enforce lease renewal */
|
||||
err_t dhcp_renew(struct netif *netif);
|
||||
/** inform server of our IP address */
|
||||
/** inform server of our manual IP address */
|
||||
void dhcp_inform(struct netif *netif);
|
||||
|
||||
/** 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 */
|
||||
#define DHCP_OPTION_PAD 0
|
||||
#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_IP_TTL 23
|
||||
#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.
|
||||
*
|
||||
* 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_IF -11 /* Low-level netif error */
|
||||
#define ERR_ISCONN -12 /* Already connected. */
|
||||
|
||||
|
||||
#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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -40,7 +40,9 @@
|
||||
|
||||
#include "lwip/inet.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
|
||||
across all types of interfaces in use */
|
||||
@@ -50,7 +52,8 @@
|
||||
|
||||
/** whether the network interface is 'up'. this is
|
||||
* 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
|
||||
/** if set, the netif has broadcast capability */
|
||||
#define NETIF_FLAG_BROADCAST 0x2U
|
||||
@@ -59,52 +62,55 @@
|
||||
/** if set, the interface is configured using DHCP */
|
||||
#define NETIF_FLAG_DHCP 0x08U
|
||||
/** if set, the interface has an active link
|
||||
* (set by the interface) */
|
||||
* (set by the network interface driver) */
|
||||
#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 {
|
||||
/** pointer to next in linked list */
|
||||
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 */
|
||||
struct ip_addr ip_addr;
|
||||
struct ip_addr netmask;
|
||||
struct ip_addr gw;
|
||||
|
||||
/** 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);
|
||||
/** This function is called by the IP module when it wants
|
||||
to send a packet on the interface. This function typically
|
||||
first resolves the hardware address, then sends the packet. */
|
||||
* to send a packet on the interface. This function typically
|
||||
* first resolves the hardware address, then sends the packet. */
|
||||
err_t (* output)(struct netif *netif, struct pbuf *p,
|
||||
struct ip_addr *ipaddr);
|
||||
/** This function is called by the ARP module when it wants
|
||||
to send a packet on the interface. This function outputs
|
||||
the pbuf as-is on the link medium. */
|
||||
* to send a packet on the interface. This function outputs
|
||||
* the pbuf as-is on the link medium. */
|
||||
err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
|
||||
/** 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;
|
||||
#if LWIP_DHCP
|
||||
/** the DHCP client state information for this netif */
|
||||
struct dhcp *dhcp;
|
||||
#endif
|
||||
/** number of bytes used in hwaddr */
|
||||
unsigned char hwaddr_len;
|
||||
u8_t hwaddr_len;
|
||||
/** 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) */
|
||||
u16_t mtu;
|
||||
/** flags (see NETIF_FLAG_ above) */
|
||||
u8_t flags;
|
||||
/** link type */
|
||||
u8_t link_type;
|
||||
/** descriptive abbreviation */
|
||||
char name[2];
|
||||
/** number of this interface */
|
||||
u8_t num;
|
||||
/** NETIF_FLAG_* */
|
||||
u8_t flags;
|
||||
};
|
||||
|
||||
/** 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_netmask(struct netif *netif, struct ip_addr *netmast);
|
||||
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__ */
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* 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
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_SANITY_CHECK
|
||||
#define MEMP_SANITY_CHECK 0
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
should be set high. */
|
||||
@@ -142,10 +146,10 @@ a lot of data that needs to be copied, this should be set high. */
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
#define PBUF_LINK_HLEN 0
|
||||
#define PBUF_LINK_HLEN 14
|
||||
#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
|
||||
* 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
|
||||
#define ARP_QUEUEING 1
|
||||
#endif
|
||||
/** If enabled, the first packet queued will not be overwritten by
|
||||
* later packets. If disabled, later packets overwrite early packets
|
||||
* in the queue. Default is disabled, which is recommended.
|
||||
*/
|
||||
#ifndef ARP_QUEUE_FIRST
|
||||
#define ARP_QUEUE_FIRST 0
|
||||
|
||||
/* This option is deprecated */
|
||||
#ifdef ETHARP_QUEUE_FIRST
|
||||
#error ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h.
|
||||
#endif
|
||||
/**
|
||||
* If defined to 1, cache entries are updated or added for every kind of ARP traffic
|
||||
* or broadcast IP traffic. Recommended for routers.
|
||||
* If defined to 0, only existing cache entries are updated. Entries are added when
|
||||
* lwIP is sending to them. Recommended for embedded devices.
|
||||
*/
|
||||
#ifndef ETHARP_ALWAYS_INSERT
|
||||
#define ETHARP_ALWAYS_INSERT 1
|
||||
|
||||
/* This option is removed to comply with the ARP standard */
|
||||
#ifdef ETHARP_ALWAYS_INSERT
|
||||
#error ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h.
|
||||
#endif
|
||||
|
||||
/* ---------- IP options ---------- */
|
||||
@@ -218,6 +224,10 @@ a lot of data that needs to be copied, this should be set high. */
|
||||
|
||||
/* ---------- RAW options ---------- */
|
||||
|
||||
#ifndef LWIP_RAW
|
||||
#define LWIP_RAW 1
|
||||
#endif
|
||||
|
||||
#ifndef RAW_TTL
|
||||
#define RAW_TTL 255
|
||||
#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) */
|
||||
#ifndef LWIP_HAVE_LOOPIF
|
||||
#define LWIP_HAVE_LOOPIF 1
|
||||
#define LWIP_HAVE_LOOPIF 0
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_EVENT_API
|
||||
@@ -336,8 +346,10 @@ a lot of data that needs to be copied, this should be set high. */
|
||||
|
||||
/* ---------- Socket Options ---------- */
|
||||
/* Enable SO_REUSEADDR and SO_REUSEPORT options */
|
||||
#ifndef SO_REUSE
|
||||
# define SO_REUSE 1
|
||||
#ifdef SO_REUSE
|
||||
/* 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
|
||||
|
||||
|
||||
@@ -348,63 +360,68 @@ a lot of data that needs to be copied, this should be set high. */
|
||||
|
||||
#if LWIP_STATS
|
||||
|
||||
#ifndef LWIP_STATS_DISPLAY
|
||||
#define LWIP_STATS_DISPLAY 0
|
||||
#endif
|
||||
|
||||
#ifndef LINK_STATS
|
||||
#define LINK_STATS 1
|
||||
#define LINK_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef IP_STATS
|
||||
#define IP_STATS 1
|
||||
#define IP_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef IPFRAG_STATS
|
||||
#define IPFRAG_STATS 1
|
||||
#define IPFRAG_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef ICMP_STATS
|
||||
#define ICMP_STATS 1
|
||||
#define ICMP_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef UDP_STATS
|
||||
#define UDP_STATS 1
|
||||
#define UDP_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef TCP_STATS
|
||||
#define TCP_STATS 1
|
||||
#define TCP_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef MEM_STATS
|
||||
#define MEM_STATS 1
|
||||
#define MEM_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_STATS
|
||||
#define MEMP_STATS 1
|
||||
#define MEMP_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef PBUF_STATS
|
||||
#define PBUF_STATS 1
|
||||
#define PBUF_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef SYS_STATS
|
||||
#define SYS_STATS 1
|
||||
#define SYS_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef RAW_STATS
|
||||
#define RAW_STATS 0
|
||||
#define RAW_STATS 0
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define LINK_STATS 0
|
||||
#define IP_STATS 0
|
||||
#define IPFRAG_STATS 0
|
||||
#define ICMP_STATS 0
|
||||
#define UDP_STATS 0
|
||||
#define TCP_STATS 0
|
||||
#define MEM_STATS 0
|
||||
#define MEMP_STATS 0
|
||||
#define PBUF_STATS 0
|
||||
#define SYS_STATS 0
|
||||
#define RAW_STATS 0
|
||||
#define LINK_STATS 0
|
||||
#define IP_STATS 0
|
||||
#define IPFRAG_STATS 0
|
||||
#define ICMP_STATS 0
|
||||
#define UDP_STATS 0
|
||||
#define TCP_STATS 0
|
||||
#define MEM_STATS 0
|
||||
#define MEMP_STATS 0
|
||||
#define PBUF_STATS 0
|
||||
#define SYS_STATS 0
|
||||
#define RAW_STATS 0
|
||||
#define LWIP_STATS_DISPLAY 0
|
||||
|
||||
#endif /* LWIP_STATS */
|
||||
|
||||
@@ -495,6 +512,31 @@ a lot of data that needs to be copied, this should be set high. */
|
||||
|
||||
#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 */
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -53,8 +53,8 @@ typedef enum {
|
||||
PBUF_POOL
|
||||
} pbuf_flag;
|
||||
|
||||
/* Definitions for the pbuf flag field (these are not the flags that
|
||||
are passed to pbuf_alloc()). */
|
||||
/* Definitions for the pbuf flag field. These are NOT the flags that
|
||||
* are passed to pbuf_alloc(). */
|
||||
#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_POOL 0x02U /* Flags that the pbuf comes from the pbuf pool */
|
||||
@@ -79,10 +79,10 @@ struct pbuf {
|
||||
*/
|
||||
u16_t tot_len;
|
||||
|
||||
/* length of this buffer */
|
||||
/** length of this buffer */
|
||||
u16_t len;
|
||||
|
||||
/* flags telling the type of pbuf */
|
||||
/** flags telling the type of pbuf, see PBUF_FLAG_ */
|
||||
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);
|
||||
|
||||
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);
|
||||
struct pbuf *pbuf_take(struct pbuf *f);
|
||||
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__ */
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -46,7 +46,7 @@ struct raw_pcb {
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
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 ip_addr *addr),
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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];
|
||||
} 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 {
|
||||
long tv_sec; /* seconds */
|
||||
long tv_usec; /* and microseconds */
|
||||
};
|
||||
#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.
|
||||
*
|
||||
* 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)
|
||||
#endif
|
||||
|
||||
/* Display of statistics */
|
||||
#if LWIP_STATS_DISPLAY
|
||||
void stats_display(void);
|
||||
#else
|
||||
#define stats_display()
|
||||
#endif
|
||||
|
||||
#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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -40,8 +40,6 @@
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/icmp.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
struct tcp_pcb;
|
||||
@@ -107,6 +105,7 @@ void tcp_input (struct pbuf *p, struct netif *inp);
|
||||
/* Used within the TCP code only: */
|
||||
err_t tcp_output (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_GT(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_SYN 0x02U
|
||||
#define TCP_RST 0x04U
|
||||
@@ -210,18 +213,13 @@ enum tcp_state {
|
||||
TIME_WAIT = 10
|
||||
};
|
||||
|
||||
|
||||
/* the TCP protocol control block */
|
||||
struct tcp_pcb {
|
||||
/* Common members of all PCB types */
|
||||
/** common PCB members */
|
||||
IP_PCB;
|
||||
|
||||
/* Protocol specific PCB members */
|
||||
|
||||
struct tcp_pcb *next; /* for the linked list */
|
||||
|
||||
enum tcp_state state; /* TCP state */
|
||||
|
||||
/** protocol specific PCB members */
|
||||
struct tcp_pcb *next; /* for the linked list */
|
||||
enum tcp_state state; /* TCP state */
|
||||
u8_t prio;
|
||||
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_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */
|
||||
|
||||
/* receiver varables */
|
||||
/* receiver variables */
|
||||
u32_t rcv_nxt; /* next seqno expected */
|
||||
u16_t rcv_wnd; /* receiver window */
|
||||
|
||||
@@ -250,10 +248,10 @@ struct tcp_pcb {
|
||||
|
||||
u16_t mss; /* maximum segment size */
|
||||
|
||||
/* RTT estimation variables. */
|
||||
u16_t rttest; /* RTT estimate in 500ms ticks */
|
||||
/* RTT (round trip time) estimation variables */
|
||||
u32_t rttest; /* RTT estimate in 500ms ticks */
|
||||
u32_t rtseq; /* sequence number being timed */
|
||||
s16_t sa, sv;
|
||||
s16_t sa, sv; /* @todo document this */
|
||||
|
||||
u16_t rto; /* retransmission time-out */
|
||||
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) \
|
||||
if((pcb)->recv != NULL) \
|
||||
{ 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) \
|
||||
if((pcb)->connected != NULL) \
|
||||
(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))
|
||||
#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 *next; /* used when putting segements on a queue */
|
||||
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_state(enum tcp_state s);
|
||||
void tcp_debug_print_pcbs(void);
|
||||
int tcp_pcbs_sane(void);
|
||||
s16_t tcp_pcbs_sane(void);
|
||||
#else
|
||||
# define tcp_debug_print(tcphdr)
|
||||
# define tcp_debug_print_flags(flags)
|
||||
@@ -457,7 +455,11 @@ void tcp_timer_needed(void);
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
state in which they accept or send
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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,
|
||||
u16_t port),
|
||||
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);
|
||||
|
||||
#define udp_flags(pcb) ((pcb)->flags)
|
||||
#define udp_setflags(pcb, f) ((pcb)->flags = (f))
|
||||
|
||||
|
||||
/* 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_init (void);
|
||||
|
||||
#if UDP_DEBUG
|
||||
int udp_debug_print(struct udp_hdr *udphdr);
|
||||
void udp_debug_print(struct udp_hdr *udphdr);
|
||||
#else
|
||||
#define udp_debug_print(udphdr)
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -33,6 +35,10 @@
|
||||
#ifndef __NETIF_ETHARP_H__
|
||||
#define __NETIF_ETHARP_H__
|
||||
|
||||
#ifndef ETH_PAD_SIZE
|
||||
#define ETH_PAD_SIZE 0
|
||||
#endif
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
@@ -46,15 +52,30 @@ struct eth_addr {
|
||||
PACK_STRUCT_FIELD(u8_t addr[6]);
|
||||
} 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 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 src);
|
||||
PACK_STRUCT_FIELD(u16_t type);
|
||||
} 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
|
||||
/** the ARP message */
|
||||
struct etharp_hdr {
|
||||
@@ -64,35 +85,42 @@ struct etharp_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
|
||||
PACK_STRUCT_FIELD(u16_t opcode);
|
||||
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 ip_addr dipaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr2 dipaddr);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
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
|
||||
# include "arch/epstruct.h"
|
||||
#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_IP 0x0800
|
||||
|
||||
void etharp_init(void);
|
||||
void etharp_tmr(void);
|
||||
struct pbuf *etharp_ip_input(struct netif *netif, struct pbuf *p);
|
||||
struct pbuf *etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
|
||||
void etharp_ip_input(struct netif *netif, struct pbuf *p);
|
||||
void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
|
||||
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);
|
||||
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__ */
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* 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
|
||||
don't contain any hardware or architecture specific code. The files
|
||||
do not contain any hardware or architecture specific code. The files
|
||||
are:
|
||||
|
||||
etharp.c
|
||||
Implements the ARP (Address Resolution Protocol) over
|
||||
Ethernet. The code in this file should be used together with
|
||||
Ethernet device drivers.
|
||||
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
|
||||
An example of how an Ethernet device driver could look. This
|
||||
file can be used as a "skeleton" for developing new Ethernet
|
||||
network device drivers. It uses the etharp.c ARP code.
|
||||
!!!THIS FILE IS NOT IN SYNC WITH CURRENT CODE !!!!
|
||||
|
||||
loopif.c
|
||||
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.
|
||||
*
|
||||
* 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
|
||||
* search-and-replace for the word "ethernetif" to replace it with
|
||||
* 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"
|
||||
@@ -44,12 +42,13 @@
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.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 IFNAME0 'e'
|
||||
#define IFNAME1 't'
|
||||
#define IFNAME1 'n'
|
||||
|
||||
struct ethernetif {
|
||||
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,
|
||||
struct ip_addr *ipaddr);
|
||||
|
||||
|
||||
static void
|
||||
low_level_init(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif;
|
||||
|
||||
ethernetif = netif->state;
|
||||
struct ethernetif *ethernetif = netif->state;
|
||||
|
||||
/* set MAC hardware address length */
|
||||
netif->hwaddr_len = 6;
|
||||
@@ -77,7 +73,7 @@ low_level_init(struct netif *netif)
|
||||
/* set MAC hardware address */
|
||||
netif->hwaddr[0] = ;
|
||||
...
|
||||
netif->hwaddr[6] = ;
|
||||
netif->hwaddr[5] = ;
|
||||
|
||||
/* maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
@@ -97,14 +93,18 @@ low_level_init(struct netif *netif)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
/* 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
|
||||
@@ -113,8 +113,12 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
|
||||
}
|
||||
|
||||
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++;
|
||||
#endif /* LINK_STATS */
|
||||
|
||||
@@ -130,8 +134,9 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
|
||||
*/
|
||||
|
||||
static struct pbuf *
|
||||
low_level_input(struct ethernetif *ethernetif)
|
||||
low_level_input(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif = netif->state;
|
||||
struct pbuf *p, *q;
|
||||
u16_t len;
|
||||
|
||||
@@ -139,25 +144,39 @@ low_level_input(struct ethernetif *ethernetif)
|
||||
variable. */
|
||||
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. */
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
|
||||
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
|
||||
packet into the pbuf. */
|
||||
* packet into the pbuf. */
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
/* Read enough bytes to fill this pbuf in the chain. The
|
||||
available data in the pbuf is given by the q->len
|
||||
variable. */
|
||||
* available data in the pbuf is given by the q->len
|
||||
* variable. */
|
||||
read data into(q->payload, q->len);
|
||||
}
|
||||
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++;
|
||||
#endif /* LINK_STATS */
|
||||
} else {
|
||||
drop packet();
|
||||
#ifdef LINK_STATS
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.memerr++;
|
||||
lwip_stats.link.drop++;
|
||||
#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
|
||||
* 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,
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* resolve hardware address, then send (or queue) packet */
|
||||
return etharp_output(netif, ipaddr, p);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -282,43 +221,47 @@ ethernetif_input(struct netif *netif)
|
||||
struct eth_hdr *ethhdr;
|
||||
struct pbuf *p;
|
||||
|
||||
|
||||
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) {
|
||||
|
||||
#ifdef LINK_STATS
|
||||
lwip_stats.link.recv++;
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.recv++;
|
||||
#endif /* LINK_STATS */
|
||||
|
||||
ethhdr = p->payload;
|
||||
ethhdr = p->payload;
|
||||
|
||||
switch (htons(ethhdr->type)) {
|
||||
case ETHTYPE_IP:
|
||||
arp_ip_input(netif, p);
|
||||
pbuf_header(p, -14);
|
||||
netif->input(p, netif);
|
||||
break;
|
||||
switch (htons(ethhdr->type)) {
|
||||
/* IP packet? */
|
||||
case ETHTYPE_IP:
|
||||
/* update ARP table */
|
||||
etharp_ip_input(netif, p);
|
||||
/* skip Ethernet header */
|
||||
pbuf_header(p, -sizeof(struct eth_hdr));
|
||||
/* pass to network layer */
|
||||
netif->input(p, netif);
|
||||
break;
|
||||
|
||||
case ETHTYPE_ARP:
|
||||
p = arp_arp_input(netif, ethernetif->ethaddr, p);
|
||||
if (p != NULL) {
|
||||
low_level_output(ethernetif, p);
|
||||
pbuf_free(p);
|
||||
}
|
||||
/* pass p to ARP module */
|
||||
etharp_arp_input(netif, ethernetif->ethaddr, p);
|
||||
break;
|
||||
default:
|
||||
pbuf_free(p);
|
||||
p = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
arp_timer(void *arg)
|
||||
{
|
||||
arp_tmr();
|
||||
etharp_tmr();
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
}
|
||||
|
||||
@@ -331,12 +274,19 @@ arp_timer(void *arg)
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
err_t
|
||||
ethernetif_init(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *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->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
@@ -346,8 +296,11 @@ ethernetif_init(struct netif *netif)
|
||||
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
|
||||
|
||||
low_level_init(netif);
|
||||
arp_init();
|
||||
|
||||
etharp_init();
|
||||
|
||||
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.
|
||||
*
|
||||
* 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 pbuf *q, *r;
|
||||
char *ptr;
|
||||
u8_t *ptr;
|
||||
void **arg;
|
||||
|
||||
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
|
||||
|
||||
@@ -610,7 +610,7 @@ int get_secret(
|
||||
|
||||
addrs = NULL;
|
||||
|
||||
if(!client || !client[0] && strcmp(client, ppp_settings.user)) {
|
||||
if(!client || !client[0] || strcmp(client, ppp_settings.user)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* 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
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ppp.h"
|
||||
#if PPP_SUPPORT > 0
|
||||
#include "auth.h"
|
||||
@@ -178,6 +180,20 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
|
||||
/*** 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.
|
||||
*/
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ppp.h"
|
||||
#if PPP_SUPPORT > 0
|
||||
#include "fsm.h"
|
||||
@@ -1232,7 +1235,7 @@ static int lcp_reqci(fsm *f,
|
||||
ho->neg_mru = 1; /* Remember he sent MRU */
|
||||
ho->mru = cishort; /* And remember value */
|
||||
#if TRACELCP > 0
|
||||
sprintf(&traceBuf[traceNdx], " MRU %d", cishort);
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort);
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
break;
|
||||
@@ -1265,7 +1268,7 @@ static int lcp_reqci(fsm *f,
|
||||
ho->neg_asyncmap = 1;
|
||||
ho->asyncmap = cilong;
|
||||
#if TRACELCP > 0
|
||||
sprintf(&traceBuf[traceNdx], " ASYNCMAP=%lX", cilong);
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong);
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
break;
|
||||
@@ -1317,7 +1320,7 @@ static int lcp_reqci(fsm *f,
|
||||
}
|
||||
ho->neg_upap = 1;
|
||||
#if TRACELCP > 0
|
||||
sprintf(&traceBuf[traceNdx], " PAP (%X)", cishort);
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort);
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
break;
|
||||
@@ -1355,7 +1358,7 @@ static int lcp_reqci(fsm *f,
|
||||
break;
|
||||
}
|
||||
#if TRACELCP > 0
|
||||
sprintf(&traceBuf[traceNdx], " CHAP %X,%d", cishort, cichar);
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, cichar);
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
ho->chap_mdtype = cichar; /* save md type */
|
||||
@@ -1387,7 +1390,7 @@ static int lcp_reqci(fsm *f,
|
||||
GETSHORT(cishort, p);
|
||||
GETLONG(cilong, p);
|
||||
#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);
|
||||
#endif
|
||||
|
||||
@@ -1419,7 +1422,7 @@ static int lcp_reqci(fsm *f,
|
||||
}
|
||||
GETLONG(cilong, p);
|
||||
#if TRACELCP > 0
|
||||
sprintf(&traceBuf[traceNdx], " MAGICNUMBER (%lX)", cilong);
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong);
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
|
||||
@@ -1442,7 +1445,7 @@ static int lcp_reqci(fsm *f,
|
||||
|
||||
case CI_PCOMPRESSION:
|
||||
#if TRACELCP > 0
|
||||
sprintf(&traceBuf[traceNdx], " PCOMPRESSION");
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION");
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
if (!ao->neg_pcompression ||
|
||||
@@ -1455,7 +1458,7 @@ static int lcp_reqci(fsm *f,
|
||||
|
||||
case CI_ACCOMPRESSION:
|
||||
#if TRACELCP > 0
|
||||
sprintf(&traceBuf[traceNdx], " ACCOMPRESSION");
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION");
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
if (!ao->neg_accompression ||
|
||||
@@ -1468,7 +1471,7 @@ static int lcp_reqci(fsm *f,
|
||||
|
||||
case CI_MRRU:
|
||||
#if TRACELCP > 0
|
||||
sprintf(&traceBuf[traceNdx], " CI_MRRU");
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU");
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
orc = CONFREJ;
|
||||
@@ -1476,7 +1479,7 @@ static int lcp_reqci(fsm *f,
|
||||
|
||||
case CI_SSNHF:
|
||||
#if TRACELCP > 0
|
||||
sprintf(&traceBuf[traceNdx], " CI_SSNHF");
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF");
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
orc = CONFREJ;
|
||||
@@ -1484,7 +1487,7 @@ static int lcp_reqci(fsm *f,
|
||||
|
||||
case CI_EPDISC:
|
||||
#if TRACELCP > 0
|
||||
sprintf(&traceBuf[traceNdx], " CI_EPDISC");
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC");
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
orc = CONFREJ;
|
||||
@@ -1492,7 +1495,7 @@ static int lcp_reqci(fsm *f,
|
||||
|
||||
default:
|
||||
#if TRACELCP
|
||||
sprintf(&traceBuf[traceNdx], " unknown %d", citype);
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype);
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
orc = CONFREJ;
|
||||
|
||||
@@ -78,6 +78,9 @@
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ppp.h"
|
||||
#if PPP_SUPPORT > 0
|
||||
#include "randm.h"
|
||||
@@ -1233,7 +1236,7 @@ static void pppMain(void *arg)
|
||||
pppInProc(pd, p->payload, c);
|
||||
} else {
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ppp.h"
|
||||
#include "vj.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
|
||||
#if VJ_SUPPORT > 0
|
||||
|
||||
#if LINK_STATS
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* by another file.They are sio_open, sio_recv and sio_send
|
||||
*/
|
||||
* This is an arch independent SLIP netif. The specific serial hooks must be
|
||||
* provided by another file. They are sio_open, sio_recv and sio_send
|
||||
*/
|
||||
|
||||
#include "netif/slipif.h"
|
||||
#include "lwip/opt.h"
|
||||
@@ -55,32 +55,32 @@
|
||||
* Send a pbuf doing the necessary SLIP encapsulation
|
||||
*
|
||||
* Uses the serial layer's sio_send()
|
||||
*/
|
||||
*/
|
||||
err_t
|
||||
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
{
|
||||
struct pbuf *q;
|
||||
int i;
|
||||
u16_t i;
|
||||
u8_t c;
|
||||
|
||||
/* Send pbuf out on the serial I/O device. */
|
||||
sio_send(SLIP_END, netif->state);
|
||||
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
for(i = 0; i < q->len; i++) {
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
for (i = 0; i < q->len; i++) {
|
||||
c = ((u8_t *)q->payload)[i];
|
||||
switch (c) {
|
||||
case SLIP_END:
|
||||
sio_send(SLIP_ESC, netif->state);
|
||||
sio_send(SLIP_ESC_END, netif->state);
|
||||
break;
|
||||
sio_send(SLIP_ESC, netif->state);
|
||||
sio_send(SLIP_ESC_END, netif->state);
|
||||
break;
|
||||
case SLIP_ESC:
|
||||
sio_send(SLIP_ESC, netif->state);
|
||||
sio_send(SLIP_ESC_ESC, netif->state);
|
||||
break;
|
||||
sio_send(SLIP_ESC, netif->state);
|
||||
sio_send(SLIP_ESC_ESC, netif->state);
|
||||
break;
|
||||
default:
|
||||
sio_send(c, netif->state);
|
||||
break;
|
||||
sio_send(c, netif->state);
|
||||
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()
|
||||
*
|
||||
* @return The IP packet when SLIP_END is received
|
||||
*/
|
||||
*/
|
||||
static struct pbuf *
|
||||
slipif_input( struct netif * netif )
|
||||
slipif_input(struct netif *netif)
|
||||
{
|
||||
u8_t c;
|
||||
struct pbuf *p, *q;
|
||||
int recved;
|
||||
int i;
|
||||
u16_t recved;
|
||||
u16_t i;
|
||||
|
||||
q = p = NULL;
|
||||
recved = i = 0;
|
||||
@@ -112,13 +112,13 @@ slipif_input( struct netif * netif )
|
||||
switch (c) {
|
||||
case SLIP_END:
|
||||
if (recved > 0) {
|
||||
/* Received whole packet. */
|
||||
pbuf_realloc(q, recved);
|
||||
|
||||
LINK_STATS_INC(link.recv);
|
||||
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
|
||||
return q;
|
||||
/* Received whole packet. */
|
||||
pbuf_realloc(q, recved);
|
||||
|
||||
LINK_STATS_INC(link.recv);
|
||||
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
|
||||
return q;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -126,51 +126,54 @@ slipif_input( struct netif * netif )
|
||||
c = sio_recv(netif->state);
|
||||
switch (c) {
|
||||
case SLIP_ESC_END:
|
||||
c = SLIP_END;
|
||||
break;
|
||||
c = SLIP_END;
|
||||
break;
|
||||
case SLIP_ESC_ESC:
|
||||
c = SLIP_ESC;
|
||||
break;
|
||||
c = SLIP_ESC;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
|
||||
default:
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
|
||||
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
|
||||
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
|
||||
|
||||
if (p == NULL) {
|
||||
LINK_STATS_INC(link.drop);
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
|
||||
}
|
||||
|
||||
if (q != NULL) {
|
||||
pbuf_cat(q, p);
|
||||
} else {
|
||||
q = p;
|
||||
}
|
||||
if (p == NULL) {
|
||||
LINK_STATS_INC(link.drop);
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
|
||||
}
|
||||
|
||||
if (q != NULL) {
|
||||
pbuf_cat(q, p);
|
||||
} else {
|
||||
q = p;
|
||||
}
|
||||
}
|
||||
if (p != NULL && recved < MAX_SIZE) {
|
||||
((u8_t *)p->payload)[i] = c;
|
||||
recved++;
|
||||
i++;
|
||||
if (i >= p->len) {
|
||||
i = 0;
|
||||
p = NULL;
|
||||
}
|
||||
((u8_t *)p->payload)[i] = c;
|
||||
recved++;
|
||||
i++;
|
||||
if (i >= p->len) {
|
||||
i = 0;
|
||||
if (p->next != NULL && p->next->len > 0)
|
||||
p = p->next;
|
||||
else
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* The SLIP input thread
|
||||
* The SLIP input thread.
|
||||
*
|
||||
* Feed the IP layer with incoming packets
|
||||
*/
|
||||
*/
|
||||
static void
|
||||
slipif_loop(void *nf)
|
||||
{
|
||||
@@ -188,21 +191,22 @@ slipif_loop(void *nf)
|
||||
*
|
||||
* Call the arch specific sio_open and remember
|
||||
* the opened device in the state field of the netif.
|
||||
*/
|
||||
*/
|
||||
err_t
|
||||
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[1] = 'l';
|
||||
netif->output = slipif_output;
|
||||
netif->mtu = 1500;
|
||||
netif->mtu = 1500;
|
||||
netif->flags = NETIF_FLAG_POINTTOPOINT;
|
||||
|
||||
netif->state = sio_open(netif->num);
|
||||
if (!netif->state)
|
||||
return ERR_IF;
|
||||
return ERR_IF;
|
||||
|
||||
sys_thread_new(slipif_loop, netif, SLIPIF_THREAD_PRIO);
|
||||
return ERR_OK;
|
||||
|
||||
Reference in New Issue
Block a user