Compare commits

..

87 Commits

Author SHA1 Message Date
jani
3505c9d792 remove udp_lookup and ip_lookup.they were unused 2004-01-23 08:13:07 +00:00
likewise
5a9a11ae36 Changed unused return type struct pbuf * into void for etharp_*_input(). 2004-01-22 21:17:18 +00:00
likewise
94275444db Globally updated the Copyright notices to mention 2004, except for the PPP folder. 2004-01-22 21:00:45 +00:00
likewise
2d6c314c64 Corrected some comments. Strongened assertions. Preparation for gratuitous ARP sending. 2004-01-22 20:41:22 +00:00
jani
9ac8e17203 fix logic in get_secret. Was a gcc warning 2004-01-21 12:11:41 +00:00
kieranm
58761b590f Fixed bug in handling of SYN_SENT, where it would move to established on an ACK or a SYN, rather than an ACK *and* a SYN. 2004-01-13 12:10:10 +00:00
jani
48fb31fe75 fix for null pcb from Ralf 2004-01-07 12:43:23 +00:00
jani
8516810993 make SYN_RCVD case fallthrough to ESTABLISHED since they have the same code.Clean up some TCP_DEBUG and OOSEQ ifdefs 2004-01-07 10:41:23 +00:00
jani
981f006ecd get rid of DEMO_DEBUG in core code 2004-01-07 10:32:27 +00:00
kieranm
ee221f4a74 Fixed bug in dequeueing of FIN from out of order segment queue.
Now examines flags of out of order segment instead of received segment.
2003-12-31 14:12:55 +00:00
likewise
0fb33aebf6 Mentioned DHCP DECLINE message bug fix. 2003-11-28 14:26:32 +00:00
likewise
6f04382f4e The DECLINE message did not include the IP address that was declined. 2003-11-28 14:23:40 +00:00
jani
b8d1ff810d netif_add fills in a preallocated struct netif, does no longer use malloc 2003-11-24 08:23:54 +00:00
likewise
00ce7401d3 Replaced wrong references RFC 2131 to be 2132. 2003-11-21 20:11:06 +00:00
jani
70872ee2a1 Do not initialize memp with zeros, the users initialize the fields themselves 2003-11-19 09:34:53 +00:00
jani
d1d7752e63 Auch\! 2003-11-18 14:44:48 +00:00
likewise
9a2732e9eb update_arp_entry() now accepts multiple packets on the queue to be sent out.
However, code to actually put multiple packets on the queue is a next step.
2003-11-18 01:34:23 +00:00
likewise
2c1cf05524 Removed (late) sending of pbufs during dequeue.
Pbufs should be sent from the queue once an ARP entry state goes from PENDING to STABLE.
Non-PENDING entries MUST NOT have queued packets (TODO).
2003-11-18 00:53:54 +00:00
likewise
94225531f8 Remaining part of bug #6601 fix. 2003-11-18 00:49:58 +00:00
likewise
ed195ed4ca Documentation and comment clearifications. 2003-11-18 00:48:05 +00:00
likewise
90e409f95f Fix bug #6601 where UDP no longer sends added pbuf headers. 2003-11-18 00:32:22 +00:00
likewise
c8303f2fde Documentation and comment clearifications. 2003-11-18 00:31:30 +00:00
likewise
eb84532b3a etharp queueing functionality separated in queueing functions. Fixed couple of GCC 3.3.1 warnings in TCP. 2003-11-15 00:41:47 +00:00
likewise
c13adc3616 Added and clearified comment for upcoming code refactoring. 2003-11-14 19:23:08 +00:00
likewise
5c9aa074eb Merged from main to DEVEL. Includes mention of release 0.6.5. 2003-11-14 16:24:30 +00:00
jani
91706a08e1 make loopif optional 2003-11-14 13:39:05 +00:00
likewise
de7aab7bc8 Clearified exact merge steps. 2003-11-14 13:00:08 +00:00
jani
3e1f7bd2fc small performance improvement 2003-11-14 12:20:27 +00:00
likewise
23499a07d5 Small change in Changelog TODO item. 2003-11-14 09:43:23 +00:00
likewise
b76cd006d5 Applied patch #1779 (considered a workaround) for bug #2595.
Removed all horizontal line seperators as they serve no use.
2003-11-14 09:42:51 +00:00
jani
29f735d11a tcp_seg_copy only used when OOSEQ is on 2003-11-13 14:39:44 +00:00
jani
18417fe7e6 Simplify 2003-11-05 09:27:48 +00:00
jani
2e6d032691 patch #2200 from Karl Jeacle, fixes tcp_output 2003-11-05 09:21:14 +00:00
jani
4c4fd7e408 group some functions under the same ifdef/endif 2003-11-05 09:07:46 +00:00
jani
1d61ebaa36 prevent rcv_wnd wrapping in tcp_recved.patch #2201 2003-11-05 08:32:25 +00:00
jani
2b6f48cc09 make asserts independent of debug, make lwipopts override debug.h 2003-11-04 12:08:06 +00:00
jani
3122375323 Get rid of some ifdefs which did not affect the generated code anyway. 2003-11-04 11:47:50 +00:00
jani
fde27c5f52 Add pbuf_cat and use it where pbuf_chain followed by pbuf_free was used before 2003-11-03 07:57:20 +00:00
jani
1047fee2bd Add defaults for RAW_TTL and RAW_STATS 2003-10-28 13:36:28 +00:00
jani
05fc81c231 consistency with rest of lwip except PPP: drop 2003-10-28 11:51:35 +00:00
jani
21a4b68fec Use #if not #ifdef for all STATS options. They are turned on off by defining them to 1 or 0. Make use of XXX_STATS_INC macros for udp, ip, tcp, ip_frag, link and icmp. Add IPFRAG_STATS option 2003-10-28 11:44:43 +00:00
jani
09b0d716d2 USP->UDP typo 2003-10-28 10:33:24 +00:00
jani
e6f5d8f86b Allow separately selecting various STATS options 2003-10-28 10:32:39 +00:00
jani
1157b0982b change ifdefs to ifs for SYS_LIGHTWEIGHT_PROT.Reported by Andreas Becker 2003-10-22 10:46:24 +00:00
jani
889555ab15 remove deprecated and commented out pbuf_ref_chain() function 2003-10-22 08:28:57 +00:00
jani
ceb956140e only set pbuf pool flag once at pool init not at every allocation. Correct some comments 2003-10-21 07:12:15 +00:00
jani
fbc0ce9214 close comment.it does not build otherwise 2003-10-08 10:01:40 +00:00
likewise
4152bdf0c0 Clearified comment. Removed TODO in comment. 2003-10-06 14:54:23 +00:00
likewise
1d63310054 Updated CHANGELOG to reflect recent changes. 2003-10-02 22:57:41 +00:00
likewise
9a83833e30 Update and insert on ARP requests as well. Made etharp_arp_input() RFC826 compliant, and efficient. 2003-10-02 22:50:52 +00:00
likewise
5df9545dcc Several source comment changes. 2003-10-02 21:43:18 +00:00
likewise
73a095572e Updated CHANGELOG to reflect recent changes. Clearified docs on merging. 2003-09-25 22:42:22 +00:00
kieranm
f62288c744 Fixed update_arp_entry to insert the correct source address into the ethernet frame sent when a ARP reply is received. 2003-09-25 17:15:47 +00:00
kieranm
8668c2f254 Initialise snd_wl1 to seqno - 1 to force window update. Causes bug for uni-directional traffic. 2003-09-23 08:33:16 +00:00
kieranm
dff08f9739 Applied patch #1912, but had to make changes to get it to compile 2003-09-22 09:38:09 +00:00
jani
385a8845c9 add default value for MEMP_NUM_RAW_PCB 2003-09-15 08:43:31 +00:00
jani
2881387553 fix ppp_trace calls which led to lots of warnings. The ## construct was not supported by all tools anyway 2003-09-10 18:21:17 +00:00
jani
26507e5ab5 make ppp_trace only called from PPP DEBUG macros if debug is on.More cleanups needed in the PPP debug system 2003-09-10 18:10:14 +00:00
kieranm
1163a1c3ce Changes from Patch #1871 (more Raw IP functionality) 2003-09-10 17:14:27 +00:00
jani
5f6aececba terminate comment to avoid gcc warning 2003-09-02 12:00:48 +00:00
jani
a046c795a3 minor compiler warning fixes 2003-09-02 11:56:40 +00:00
kieranm
5b73921be3 Handle UDPLITE as well as UDP 2003-08-21 10:47:46 +00:00
kieranm
cca1607ab5 Applied patch #1399 to implement socket options 2003-08-21 09:59:21 +00:00
kieranm
0d4190b909 Added patch #1756 (with a couple of modifications) to provide raw IP functionality 2003-08-20 16:46:16 +00:00
jani
2f35d6e307 Add isascii and friends macros in inet.c so there's no dependency on ctype.h 2003-07-25 13:06:37 +00:00
likewise
23f6866009 Fixed a absolute path to a relative one. Added *.pkg for safety. 2003-07-20 11:48:24 +00:00
marcbou
f70d30b91d Added PPPAUTHTYPE_ANY 2003-07-04 15:55:11 +00:00
robert
d400f77dea Wrapping MEM_ALIGN macros in #ifndef 2003-07-02 17:09:28 +00:00
marcbou
f8dd991949 change #if 0's to #ifdef LWIP_UDP_TODO for temporary convenience.. 2003-06-27 19:45:19 +00:00
marcbou
b7d3687ea4 Added authType to pppSetAuth() and CHAP client support
(build unix port with -DLWIP_PPP_CHAP_TEST to test it)
2003-06-27 19:35:10 +00:00
marcbou
a4a597da99 fixed 'numereous' misspelling. 2003-06-25 12:43:57 +00:00
jani
cee4f976a8 define and detect ECE (ECN echo) and CWR (congestion window reduced) flags. Behaviour not affected.Based on patch #1600 by arbon 2003-06-23 22:33:56 +00:00
jani
b77b7cc1e2 Harmful statement introduced to avoid duplicate code in eth timer and to fix the compile warning in only one place 2003-06-23 22:24:11 +00:00
jani
092bcca5f7 C comment style for this line.Again :) 2003-06-23 22:21:51 +00:00
leonwoestenberg
d12ce425b0 Updated the Changelog to reflect known changes. 2003-06-23 18:02:50 +00:00
marcbou
77eea999d9 Applied Patch #1326 (TCP: readability, debugging, performance fixes by floriZ)
with various improvements and adaptations.
2003-06-19 14:26:21 +00:00
marcbou
cea3ff9d38 Change TCP_TMR_INTERVAL from 100 to 250ms.
tcp_fasttmr() and tcp_slowtmr() call frequencies should remain unchanged,
but system load will be reduced. Closes patch #1495. Please email me
if you see any issues with this. Non-standard TCP timer definitions in
contrib/ports/v2pro/lwipopts.h might need adjustment as a consequence
of this change.
2003-06-19 12:45:32 +00:00
marcbou
6657b656f5 Eliminated memp_mallocp() and memp_freep() in favour of memp_malloc()
and memp_free() respectively. Protection is always used, except while
zeroing out memory ;-). Closes patch #1184. If you see any issues
with this change please email me.
2003-06-19 12:32:24 +00:00
marcbou
d5e08d7d78 Workaround for [hn]to[nh][ls] naming collisions on some platforms (only used if LWIP_PREFIX_BYTEORDER_FUNCS is defined). Closes patch #1490. 2003-06-19 12:16:42 +00:00
marcbou
98bd3028f2 pbuf_dechain() needed by PPP. 2003-06-19 11:34:02 +00:00
likewise
a9cd9d185c Patch #1625. Check ipaddr != NULL, also in ip_addr_debug_print() macro. 2003-06-19 10:33:58 +00:00
marcbou
d61b274a09 Patch #1623: Add missing pbuf_free() call after pbuf_chain() in slipif_input() 2003-06-19 10:24:32 +00:00
likewise
7be9cb71fe Patch #1624. Fixes ip_addr_debug_print() macro formatters. 2003-06-19 10:01:19 +00:00
likewise
d717d627c2 Fixes bug reported on lwip-users by Florian Zschocke on 13-06-2003 16:07.
The lwip_select() could truncate the timeout to become 0 (wait forever).
2003-06-17 14:04:54 +00:00
likewise
9e513a7bf0 Added the basics of doing a merge from DEVEL to main. 2003-06-17 11:41:08 +00:00
likewise
a59f230bc1 Changed documentation to reflect changes to CVS repository. 2003-06-13 08:28:22 +00:00
likewise
14802bcadb Initial commit. 2003-06-13 08:02:39 +00:00
58 changed files with 1754 additions and 2353 deletions

138
CHANGELOG
View File

@@ -1,145 +1,17 @@
FUTURE
TODO
* 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 (/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: Fix unaligned 16-bit access in checksum routine.
* TODO: Fix assumptions on storage sizes wherever we cast.
* TODO: See why large ICMP (ping) packets do not work (fragmentation?).
HISTORY
(HEAD)
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:
* Fixed TCP bug for SYN_SENT to ESTABLISHED state transition.
* Fixed TCP bug in dequeueing of FIN from out of order segment queue.
* Fixed two possible NULL references in rare cases.
(STABLE-0_6_6)
(DEVEL)
++ Bug fixes:
* Fixed DHCP which did not include the IP address in DECLINE messages.
++ Changes:
* etharp.c has been hauled over a bit.
(STABLE-0_6_5)
++ Bug fixes:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2002 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,

View File

@@ -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 bug reports, fixes, enhancements, platform ports etc.
trying to contribute bugreports, 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,20 +14,19 @@ features of Savannah help us not lose users' input.
2.1 Source code style:
1. do not use tabs.
2. indentation is two spaces per level (i.e. per tab).
2. identation is two spaces per level.
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. closing curly brace on a single line.
8. spaces surrounding assignment and comparisons.
9. use current source code style as further reference.
7. spaces surrounding assignment and comparisons.
8. 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 implementation.)
(This forces you to synchronize documentation and behaviour.)
3. Use current documentation style as further reference.
2.3 Bug reports and patches:
@@ -56,7 +55,9 @@ features of Savannah help us not lose users' input.
2.4 Platform porters:
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.
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.

View File

@@ -1,21 +1,20 @@
Raw TCP/IP interface for lwIP
Raw TCP/IP interface for lwIP 0.5
Authors: Adam Dunkels, Leon Woestenberg
Author: Adam Dunkels
lwIP provides two Application Program's Interfaces (APIs) for programs
to use for communication with the TCP/IP code:
* low-level "core" / "callback" or "raw" API.
* higher-level "sequential" API.
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.
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 blocking open-read-write-close
model of execution is based on the 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
@@ -35,6 +34,7 @@ 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,11 +272,6 @@ 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.

View File

@@ -2,70 +2,33 @@ Daily Use Guide for using Savannah for lwIP
Table of Contents:
1 - Obtaining lwIP from the CVS repository
1 - Anonymous CVS checkouts and updates (to be elaborated)
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
1 Anonymous CVS checkouts and updates
-------------------------------------
1 Obtaining lwIP from the CVS repository
----------------------------------------
Obtain lwIP from the CVS main trunk (stable)
To perform an anonymous CVS checkout of the main trunk (this is where
bug fixes and incremental enhancements occur), do this:
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip
export CVS_RSH=ssh
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip
Or, obtain a specific release as follows:
(If SSH asks about authenticity of the host, you can check the key
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_6_3 -d lwip-0.6.3 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 development branch as follows:
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
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-DEVEL 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 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@subversions.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:your_login@subversions.gnu.org:/cvsroot/lwip checkout 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.
3 Merging from DEVEL branch to main trunk (stable)
--------------------------------------------------
---------------------------------------------------------
Merging is a delicate process in CVS and requires the
following disciplined steps in order to prevent conflicts
@@ -88,9 +51,6 @@ cvs update -P -jmerged_from_DEVEL_to_main -jDEVEL
(This will apply the changes between 'merged_from_DEVEL_to_main'
and 'DEVEL' to your work set of files)
We can now commit the merge result.
cvs commit -R -m "Merged from DEVEL to main."
If this worked out OK, we now move the tag in the DEVEL branch
to this merge point, so we can use this point for future merges:
@@ -106,25 +66,47 @@ Login CVS using pserver authentication, then export a clean copy of the
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 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip export -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
Now, sign the archives with a detached GPG binary signature as follows:
First, make a local release directory to work in, I use "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
mkdir lwip-releases
cd lwip-releases
Upload these files using anonymous FTP:
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
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):
ncftp>mput *0.6.3.*
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.
---
Additionally, you may post a news item on Savannah, like this:

View File

@@ -1,13 +1,11 @@
api/ - The code for the high-level wrapper API. Not needed if
you use the lowel-level call-back/raw API.
api/ - The code for the API.
core/ - The core of the TPC/IP stack; protocol implementations,
memory and buffer management, and the low-level raw API.
core/ - The core files including protocol implementations, memory
and buffer management etc.
include/ - lwIP include files.
netif/ - Generic network interface device drivers are kept here,
as well as the ARP module.
netif/ - Generic network interface device drivers are kept here.
For more information on the various subdirectories, check the FILES
file in each directory.

View File

@@ -280,10 +280,9 @@ 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) {
if(mem != NULL)
pbuf_free((struct pbuf *)mem);
pbuf_free((struct pbuf *)mem);
} else {
netbuf_delete((struct netbuf *)mem);
netbuf_delete((struct netbuf *)mem);
}
}
sys_mbox_free(conn->recvmbox);

View File

@@ -38,7 +38,7 @@
#include "lwip/tcpip.h"
#if LWIP_RAW
static u8_t
static int
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
struct ip_addr *addr)
{

View File

@@ -32,9 +32,6 @@
*
*/
#include <string.h>
#include <errno.h>
#include "lwip/opt.h"
#include "lwip/api.h"
#include "lwip/arch.h"
@@ -418,7 +415,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
#if SOCKETS_DEBUG > 0
addr = netbuf_fromaddr(buf);
port = netbuf_fromport(buf);
@@ -996,7 +993,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: */
#if SO_REUSE
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
@@ -1082,7 +1079,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: */
#if SO_REUSE
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
@@ -1141,7 +1138,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 = (int)sock->conn->pcb.tcp->keepalive;
*(int*)optval = sock->conn->pcb.tcp->keepalive;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
break;
} /* switch */
@@ -1185,7 +1182,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: */
#if SO_REUSE
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
@@ -1267,7 +1264,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: */
#if SO_REUSE
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
@@ -1309,7 +1306,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) -> %lu\n", s, sock->conn->pcb.tcp->keepalive));
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %u\n", s, sock->conn->pcb.tcp->keepalive));
break;
} /* switch */
break;

View File

@@ -46,39 +46,32 @@
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 {
/* disable timer */
tcpip_tcp_timer_active = 0;
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)) {
/* enable and start timer */
tcpip_tcp_timer_active = 1;
tcpip_tcp_timer_active = 1;
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
}
}
#endif /* !NO_SYS */
#endif /* LWIP_TCP */
static void

View File

@@ -67,26 +67,20 @@
* 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. We simply increment, starting
* with this value (easy to match with a packet analyzer) */
* unique for each DHCP request. */
static u32_t xid = 0xABCD0000;
/** DHCP client state machine functions */
@@ -100,6 +94,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);
/** receive, unfold, parse and free incoming messages */
@@ -234,11 +229,10 @@ 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, 4/*num options*/);
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
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 */
@@ -297,20 +291,18 @@ void dhcp_coarse_tmr()
/**
* DHCP transaction timeout handling
*
* A DHCP server is expected to respond within a short period of time.
* This timer checks whether an outstanding DHCP request is timed out.
*
* A DHCP server is expected to respond within a
* short period of time.
*/
void dhcp_fine_tmr()
{
struct netif *netif = netif_list;
/* loop through netif's */
/* loop through clients */
while (netif != NULL) {
/* only act on DHCP configured interfaces */
if (netif->dhcp != NULL) {
/* timer is active (non zero), and is about to trigger now */
/* timer is active (non zero), and triggers (zeroes) 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);
@@ -389,8 +381,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 (t2) will
* eventually time-out if renew tries fail. */
/* just retry to renew */
/* note that the rebind timer will eventually time-out if renew does not work */
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
dhcp_renew(netif);
}
@@ -412,6 +404,7 @@ static void dhcp_t2_timeout(struct netif *netif)
}
/**
* Extract options from the server ACK message.
*
* @param netif the netif under DHCP control
*/
@@ -485,19 +478,6 @@ 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)]));
}
}
}
/**
@@ -520,43 +500,39 @@ err_t dhcp_start(struct netif *netif)
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));
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(): allocated dhcp"));
/* already has DHCP client attached */
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"));
} 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;
}
@@ -679,10 +655,8 @@ 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);
/* @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);
udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
udp_send(dhcp->pcb, dhcp->p_out);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
} else {
@@ -719,11 +693,10 @@ 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, 4/*num options*/);
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
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);
@@ -733,9 +706,15 @@ 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"));
@@ -807,8 +786,6 @@ static void dhcp_bind(struct netif *netif)
netif_set_netmask(netif, &sn_mask);
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08lx\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);
}
@@ -904,11 +881,10 @@ 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 {
@@ -926,7 +902,7 @@ static err_t dhcp_rebind(struct netif *netif)
*
* @param netif network interface which must release its lease
*/
err_t dhcp_release(struct netif *netif)
static err_t dhcp_release(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
err_t result;
@@ -935,13 +911,8 @@ 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) {
@@ -963,14 +934,11 @@ 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));
/* bring the interface down */
netif_set_down(netif);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %u msecs\n", msecs));
/* 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;
}
@@ -1275,10 +1243,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.addr = netif->ip_addr.addr;
dhcp->msg_out->yiaddr.addr = 0;
dhcp->msg_out->siaddr.addr = 0;
dhcp->msg_out->giaddr.addr = 0;
dhcp->msg_out->ciaddr = netif->ip_addr.addr;
dhcp->msg_out->yiaddr = 0;
dhcp->msg_out->siaddr = 0;
dhcp->msg_out->giaddr = 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*/;
@@ -1450,5 +1418,3 @@ static u32_t dhcp_get_option_long(u8_t *ptr)
LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%lu\n", value));
return value;
}
#endif /* LWIP_DHCP */

View File

@@ -46,21 +46,10 @@
#include "lwip/def.h"
#include "lwip/inet.h"
#include "lwip/sys.h"
/* This is a reference implementation of the checksum algorithm
- it may not work on all architectures, and all processors, particularly
if they have issues with alignment and 16 bit access.
- in this case you will need to port it to your architecture and
#define LWIP_CHKSUM <your_checksum_routine>
in your sys_arch.h
*/
#ifndef LWIP_CHKSUM
#define LWIP_CHKSUM lwip_standard_chksum
static u16_t
lwip_standard_chksum(void *dataptr, int len)
lwip_chksum(void *dataptr, int len)
{
u32_t acc;
@@ -86,7 +75,6 @@ lwip_standard_chksum(void *dataptr, int len)
return (u16_t)acc;
}
#endif
/* inet_chksum_pseudo:
*
@@ -108,7 +96,7 @@ 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);
acc += lwip_chksum(q->payload, q->len);
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%lx \n", acc));*/
while (acc >> 16) {
acc = (acc & 0xffffUL) + (acc >> 16);
@@ -134,7 +122,7 @@ inet_chksum_pseudo(struct pbuf *p,
acc = (acc & 0xffffUL) + (acc >> 16);
}
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
return (u16_t)~(acc & 0xffffUL);
return ~(acc & 0xffffUL);
}
/* inet_chksum:
@@ -148,11 +136,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 (u16_t)~(acc & 0xffff);
return ~(acc & 0xffff);
}
u16_t
@@ -165,7 +153,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);
}
@@ -178,7 +166,7 @@ inet_chksum_pbuf(struct pbuf *p)
if (swapped) {
acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
}
return (u16_t)~(acc & 0xffffUL);
return ~(acc & 0xffffUL);
}
/* Here for now until needed in other places in lwIP */
@@ -244,12 +232,12 @@ inet_chksum_pbuf(struct pbuf *p)
base = 8;
}
for (;;) {
if (isdigit(c)) {
val = (val * base) + (int)(c - '0');
if (isascii(c) && isdigit(c)) {
val = (val * base) + (c - '0');
c = *++cp;
} else if (base == 16 && isxdigit(c)) {
} else if (base == 16 && isascii(c) && isxdigit(c)) {
val = (val << 4) |
(int)(c + 10 - (islower(c) ? 'a' : 'A'));
(c + 10 - (islower(c) ? 'a' : 'A'));
c = *++cp;
} else
break;
@@ -312,19 +300,18 @@ inet_chksum_pbuf(struct pbuf *p)
/* Convert numeric IP address into decimal dotted ASCII representation.
* returns ptr to static buffer; not reentrant!
*/
char *inet_ntoa(struct in_addr addr)
u8_t *inet_ntoa(u32_t addr)
{
static char str[16];
u32_t s_addr = addr.s_addr;
char inv[3];
char *rp;
static u8_t str[16];
u8_t inv[3];
u8_t *rp;
u8_t *ap;
u8_t rem;
u8_t n;
u8_t i;
rp = str;
ap = (u8_t *)&s_addr;
ap = (u8_t *)&addr;
for(n = 0; n < 4; n++) {
i = 0;
do {

View File

@@ -72,9 +72,9 @@ icmp_input(struct pbuf *p, struct netif *inp)
code = *(((u8_t *)p->payload)+1);
switch (type) {
case ICMP_ECHO:
/* 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"));
if (ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) ||
ip_addr_ismulticast(&iphdr->dest)) {
LWIP_DEBUGF(ICMP_DEBUG, ("Smurf.\n"));
ICMP_STATS_INC(icmp.err);
pbuf_free(p);
return;

View File

@@ -1,10 +1,3 @@
/* @file
*
* This is the IP layer implementation for incoming and outgoing IP traffic.
*
* @see ip_frag.c
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
@@ -37,8 +30,18 @@
*
*/
/* 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"
@@ -60,17 +63,18 @@
#endif /* LWIP_DHCP */
/**
/* ip_init:
*
* Initializes the IP layer.
*/
void
ip_init(void)
{
/* no initializations as of yet */
}
/**
/* 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
@@ -85,7 +89,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_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
if (ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
/* return netif on which to forward IP packet */
return netif;
}
@@ -95,13 +99,14 @@ 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 struct netif *
static void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
{
struct netif *netif;
@@ -113,14 +118,14 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%lx found\n",
iphdr->dest.addr));
snmp_inc_ipnoroutes();
return (struct netif *)NULL;
return;
}
/* 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 (struct netif *)NULL;
return;
}
/* decrement TTL */
@@ -132,7 +137,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
icmp_time_exceeded(p, ICMP_TE_TTL);
snmp_inc_icmpouttimeexcds();
}
return (struct netif *)NULL;
return;
}
/* Incrementally update the IP checksum. */
@@ -152,11 +157,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
@@ -164,16 +169,13 @@ 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) {
struct ip_hdr *iphdr;
struct netif *netif;
u16_t iphdrlen;
static struct ip_hdr *iphdr;
static struct netif *netif;
static u16_t iphdrlen;
IP_STATS_INC(ip.recv);
snmp_inc_ipinreceives();
@@ -207,7 +209,6 @@ 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)));
@@ -218,40 +219,41 @@ 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)));
/* match packet against an interface, i.e. is this packet for us? */
for (netif = netif_list; netif != NULL; netif = netif->next) {
/* 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)));
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 is up and configured? */
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
/* interface configured? */
if (!ip_addr_isany(&(netif->ip_addr)))
{
/* unicast to this interface address? */
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
/* 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;
/* 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;
}
}
}
#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) {
@@ -264,13 +266,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)) {
if (!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask))) {
/* try to forward IP packet on (other) interfaces */
ip_forward(p, iphdr, inp);
}
@@ -282,30 +284,30 @@ ip_input(struct pbuf *p, struct netif *inp) {
pbuf_free(p);
return ERR_OK;
}
/* packet consists of multiple fragments? */
#if IP_REASSEMBLY
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04x tot_len=%u len=%u MF=%u offset=%u), 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 == 0, no packet fragment reassembly code present */
}
#else /* IP_REASSEMBLY */
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
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))));
ntohs(IPH_OFFSET(iphdr))));
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
#endif /* IP_REASSEMBLY */
}
#endif /* IP_REASSEMBLY */
#if IP_OPTIONS == 0 /* no support for IP options in the IP header? */
#if IP_OPTIONS == 0
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);
@@ -322,8 +324,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
#if LWIP_RAW
/* raw input did not eat the packet? */
if (raw_input(p, inp) == 0) {
if (!raw_input(p, inp)) {
#endif /* LWIP_RAW */
switch (IPH_PROTO(iphdr)) {
@@ -346,8 +347,8 @@ 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) &&
!ip_addr_ismulticast(&(iphdr->dest))) {
if (!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) &&
!ip_addr_ismulticast(&(iphdr->dest))) {
p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PROTO);
}
@@ -358,6 +359,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
IP_STATS_INC(ip.proterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
}
#if LWIP_RAW
} /* LWIP_RAW */
@@ -365,7 +367,9 @@ 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
@@ -377,8 +381,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)
{
struct ip_hdr *iphdr;
u16_t ip_id = 0;
static struct ip_hdr *iphdr;
static u16_t ip_id = 0;
snmp_inc_ipoutrequests();
@@ -411,9 +415,7 @@ 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);
@@ -435,7 +437,8 @@ 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.
*/
@@ -486,17 +489,17 @@ ip_debug_print(struct pbuf *p)
IPH_PROTO(iphdr),
ntohs(IPH_CHKSUM(iphdr))));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | %3u | %3u | (src)\n",
ip4_addr1(&iphdr->src),
ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src),
ip4_addr4(&iphdr->src)));
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, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | %3u | %3u | (dest)\n",
ip4_addr1(&iphdr->dest),
ip4_addr2(&iphdr->dest),
ip4_addr3(&iphdr->dest),
ip4_addr4(&iphdr->dest)));
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, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */

View File

@@ -32,41 +32,7 @@
#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;
}

View File

@@ -1,9 +1,3 @@
/* @file
*
* This is the IP packet segmentation and reassembly implementation.
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
@@ -37,6 +31,14 @@
*
*/
/* ip_frag.c
*
* This is the code for IP segmentation and reassembly
*
*/
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/ip.h"
@@ -243,7 +245,7 @@ ip_reass(struct pbuf *p)
variable. */
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: memcpy from %p (%d) to %p, %d bytes\n",
(void *)&ip_reassbuf[i], i, q->payload,
&ip_reassbuf[i], i, q->payload,
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
memcpy(q->payload, &ip_reassbuf[i],
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
@@ -292,6 +294,7 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
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);

View File

@@ -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_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
if (ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
return netif;
}
}

View File

@@ -35,7 +35,7 @@
int
ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
ip_addr_maskcmp(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]) &&

View File

@@ -36,7 +36,6 @@
*
*/
#include <string.h>
#include "lwip/arch.h"
#include "lwip/opt.h"
@@ -55,8 +54,6 @@ 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 */
@@ -295,7 +292,7 @@ mem_malloc(mem_size_t size)
}
sys_sem_signal(mem_sem);
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
(u32_t)mem + SIZEOF_STRUCT_MEM + size <= (u32_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;

View File

@@ -120,7 +120,7 @@ static u8_t memp_memory[(MEMP_NUM_PBUF *
static sys_sem_t mutex;
#endif
#if MEMP_SANITY_CHECK
#ifndef LWIP_NOASSERT
static int
memp_sanity(void)
{
@@ -140,7 +140,7 @@ memp_sanity(void)
}
return 1;
}
#endif /* MEMP_SANITY_CHECK*/
#endif /* LWIP_DEBUG */
void
memp_init(void)
@@ -217,7 +217,7 @@ memp_malloc(memp_t type)
sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
LWIP_ASSERT("memp_malloc: memp properly aligned",
((mem_ptr_t)MEM_ALIGN((u8_t *)memp + sizeof(struct memp)) % MEM_ALIGNMENT) == 0);
((u32_t)MEM_ALIGN((u8_t *)memp + sizeof(struct memp)) % MEM_ALIGNMENT) == 0);
mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp));
return mem;
@@ -261,9 +261,7 @@ 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);

View File

@@ -39,24 +39,23 @@
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/ip_addr.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 is called to pass
* ingress packets up in the protocol layer stack.
* @param input callback function that...
*
* @return netif, or NULL if failed.
*/
@@ -68,6 +67,7 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
err_t (* input)(struct pbuf *p, struct netif *netif))
{
static int 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; defined by tcp.h */
extern struct tcp_pcb *tcp_active_pcbs;
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.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
for (lpcb = tcp_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,20 +197,12 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
}
#endif
ip_addr_set(&(netif->ip_addr), ipaddr);
#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 %u.%u.%u.%u\n",
netif->name[0], netif->name[1],
ip4_addr1(&netif->ip_addr),
ip4_addr2(&netif->ip_addr),
ip4_addr3(&netif->ip_addr),
ip4_addr4(&netif->ip_addr)));
(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)));
}
void
@@ -218,11 +210,11 @@ 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],
ip4_addr1(&netif->gw),
ip4_addr2(&netif->gw),
ip4_addr3(&netif->gw),
ip4_addr4(&netif->gw)));
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)));
}
void
@@ -230,11 +222,11 @@ 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],
ip4_addr1(&netif->netmask),
ip4_addr2(&netif->netmask),
ip4_addr3(&netif->netmask),
ip4_addr4(&netif->netmask)));
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)));
}
void
@@ -245,41 +237,6 @@ 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)
{

View File

@@ -11,15 +11,12 @@
* 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. 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.
*
* 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.
* The differences between a pbuf chain and a packet queue are very
* precise but subtle.
* 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.
*
* 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
@@ -103,7 +100,7 @@ pbuf_init(void)
u16_t i;
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
LWIP_ASSERT("pbuf_init: pool aligned", (mem_ptr_t)pbuf_pool % MEM_ALIGNMENT == 0);
LWIP_ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0);
#if PBUF_STATS
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
@@ -183,7 +180,7 @@ pbuf_pool_alloc(void)
/**
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
* Allocates a pbuf.
*
* The actual memory allocated for the pbuf is determined by the
* layer at which the pbuf is allocated and the requested size
@@ -257,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",
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
((u32_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 */
@@ -293,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",
((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
((u32_t)q->payload % MEM_ALIGNMENT) == 0);
q->ref = 1;
/* calculate remaining length to be allocated */
rem_len -= q->len;
@@ -306,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) + offset) + MEM_ALIGN_SIZE(length));
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + length + offset));
if (p == NULL) {
return NULL;
}
@@ -317,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",
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
((u32_t)p->payload % MEM_ALIGNMENT) == 0);
break;
/* pbuf references existing (non-volatile static constant) ROM payload? */
/* pbuf references existing (static constant) ROM payload? */
case PBUF_ROM:
/* pbuf references existing (externally allocated) RAM payload? */
case PBUF_REF:
@@ -453,82 +450,76 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
*
* The ->payload, ->tot_len and ->len fields are adjusted.
*
* @param hdr_size_inc Number of bytes to increment header size which
* @param hdr_size 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 non-zero on failure, zero on success.
* @return 1 on failure, 0 on success.
*
* @note May not be called on a packet queue.
*/
u8_t
pbuf_header(struct pbuf *p, s16_t header_size_increment)
pbuf_header(struct pbuf *p, s16_t header_size)
{
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_increment;
p->payload = (u8_t *)p->payload - header_size;
/* 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 (not enough space for new header size)\n",
(void *)p->payload,
(void *)(p + 1)));\
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p\n",
(u8_t *)p->payload,
(u8_t *)p + sizeof(struct pbuf)) );\
/* restore old payload pointer */
p->payload = payload;
/* bail out unsuccesfully */
return 1;
}
/* pbuf types refering to external payloads? */
/* pbuf types refering to payloads? */
} else if (p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_ROM) {
/* hide a header in the payload? */
if ((header_size_increment < 0) && (header_size_increment - p->len <= 0)) {
if ((header_size < 0) && (header_size - p->len <= 0)) {
/* increase payload pointer */
p->payload = (u8_t *)p->payload - header_size_increment;
p->payload = (u8_t *)p->payload - header_size;
} 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_increment;
p->tot_len += header_size_increment;
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n",
(void *)payload, (void *)p->payload, header_size_increment));
p->len += header_size;
p->tot_len += header_size;
return 0;
}
/**
* Dereference a pbuf chain or queue and deallocate any no-longer-used
* pbufs at the head of this chain or queue.
* Dereference a pbuf (chain) and deallocate any no-longer-used
* pbufs at the head of this chain.
*
* 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 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.
* up to a pbuf which has a non-zero reference count after
* decrementing. (This might de-allocate the whole chain.)
*
* @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 (Not verified to work yet).
* @note MUST NOT be called on a packet queue.
* @note the reference counter of a pbuf equals the number of pointers
* that refer to the pbuf (or into the pbuf).
*
@@ -551,8 +542,6 @@ 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;
@@ -587,7 +576,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);
/* is this a ROM or RAM referencing pbuf? */
/* 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 */
@@ -601,7 +590,7 @@ pbuf_free(struct pbuf *p)
/* (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 the chain */
/* stop walking through chain */
p = NULL;
}
}
@@ -664,8 +653,8 @@ pbuf_cat(struct pbuf *h, struct pbuf *t)
{
struct pbuf *p;
LWIP_ASSERT("h != NULL (programmer violates API)", h != NULL);
LWIP_ASSERT("t != NULL (programmer violates API)", t != NULL);
LWIP_ASSERT("h != NULL", h != NULL);
LWIP_ASSERT("t != NULL", t != NULL);
if ((h == NULL) || (t == NULL)) return;
/* proceed to last pbuf of chain */
@@ -675,14 +664,10 @@ 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.
*/
}
/**
@@ -710,8 +695,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
* using pbuf_dequeue() before calling other pbuf_() functions. */
/* For packet queueing. Note that queued packets must be dequeued first
* before calling any pbuf functions. */
#if ARP_QUEUEING
/**
* Add a packet to the end of a queue.
@@ -719,22 +704,15 @@ 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)
{
#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"))
LWIP_ASSERT("p != NULL", p != NULL);
LWIP_ASSERT("n != NULL", n != NULL);
if ((p == NULL) || (n == NULL))
return;
}
/* iterate through all packets on queue */
while (p->next != NULL) {
@@ -742,39 +720,25 @@ 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 } */
}
/* { p is last pbuf of a packet } */
/* proceed to next packet on queue */
#endif
/* proceed to next pbuf */
if (p->next != NULL) p = p->next;
/* now p->tot_len == p->len */
/* proceed to next packet on queue */
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 by the (packet p in the) queue */
/* n is now referenced to one more time */
pbuf_ref(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
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_queue: referencing queued packet %p\n", (void *)n));
}
/**
* 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).
*
@@ -785,28 +749,19 @@ pbuf_dequeue(struct pbuf *p)
struct pbuf *q;
LWIP_ASSERT("p != NULL", p != NULL);
/* iterate through all pbufs in packet p */
/* 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 the last pbuf of the first packet */
/* remember next packet on queue in q */
/* remember next packet on queue */
q = p->next;
/* dequeue packet p from queue */
/* dequeue p from queue */
p->next = NULL;
/* 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"));
}
/* 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));
return q;
}
#endif
@@ -824,7 +779,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 a (differently located) copy through pbuf_take()!
* by pbuf_take()!
*
* @note Any replaced pbufs will be freed through pbuf_free().
* This may deallocate them if they become no longer referenced.
@@ -852,9 +807,7 @@ 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;
@@ -863,9 +816,7 @@ 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)
@@ -948,10 +899,8 @@ 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) */

View File

@@ -1,9 +1,6 @@
/**
* @file
*
* Implementation of raw protocol PCBs for low-level handling of
* different types of protocols besides (or overriding) those
* already available in lwIP.
* Raw Access module
*
*/
/*
@@ -38,15 +35,20 @@
*
*/
#include <string.h>
/* raw.c
*
* The code for the Raw Access to the IP
*
*/
#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/ip_addr.h"
#include "lwip/raw.h"
#include "lwip/stats.h"
@@ -55,10 +57,11 @@
#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)
{
@@ -66,54 +69,42 @@ raw_init(void)
}
/**
* Determine if in incoming IP packet is covered by a RAW PCB
* and if so, pass it to a user-provided receive callback function.
* Determine if in incoming IP packet is covered by a RAW pcb and
* and process it if possible
*
* Given an incoming IP datagram (as a chain of pbufs) this function
* finds a corresponding RAW PCB and calls the corresponding receive
* callback function.
* finds a corresponding RAW PCB and
*
* @param pbuf pbuf to be demultiplexed to a RAW PCB.
* @param netif network interface on which the datagram was received.
* @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).
* @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)
*
*/
u8_t
int
raw_input(struct pbuf *p, struct netif *inp)
{
struct raw_pcb *pcb;
struct ip_hdr *iphdr;
int proto;
u8_t eaten = 0;
int rc = 0;
iphdr = p->payload;
proto = IPH_PROTO(iphdr);
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)) {
for(pcb = raw_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->protocol == proto) {
/* 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;
}
if (pcb->recv) {
if (!pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)))
return 0;
}
/* no receive callback function was set for this raw PCB */
/* drop the packet */
pbuf_free(p);
rc = 1;
break;
}
pcb = pcb->next;
}
return eaten;
return rc;
}
/**
@@ -125,7 +116,7 @@ raw_input(struct pbuf *p, struct netif *inp)
*
* @return lwIP error code.
* - ERR_OK. Successful. No error occured.
* - ERR_USE. The specified IP address is already bound to by
* - ERR_USE. The specified ipaddr is already bound to by
* another RAW PCB.
*
* @see raw_disconnect()
@@ -139,7 +130,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_sendto() instead
* of lwip. Using the raw api you could use raw_send_to() instead
*
* This will associate the RAW PCB with the remote address.
*
@@ -148,7 +139,7 @@ raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
*
* @return lwIP error code
*
* @see raw_disconnect() and raw_sendto()
* @see raw_disconnect() and raw_send_to()
*/
err_t
raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
@@ -159,21 +150,14 @@ raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
/**
* 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.
* 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
*/
void
raw_recv(struct raw_pcb *pcb,
u8_t (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
int (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
struct ip_addr *addr),
void *recv_arg)
{
@@ -184,25 +168,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 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.)
* 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)
*
* @param pcb the raw pcb which to send
* @param p the IP payload to send
* @param ipaddr the destination address of the IP packet
* @param p the ip payload to send
* @param ipaddr the destination address of the whole IP packet
*
*/
err_t
raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
raw_send_to(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_sendto\n"));
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_send_to\n"));
/* not enough space to add an IP header to first pbuf in given p chain? */
if (pbuf_header(p, IP_HLEN)) {
@@ -210,13 +194,13 @@ raw_sendto(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_sendto: could not allocate header\n"));
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_send_to: 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_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
LWIP_DEBUGF(RAW_DEBUG, ("raw_send_to: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
} else {
/* first pbuf q equals given pbuf */
q = p;
@@ -224,11 +208,10 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
}
if ((netif = ip_route(ipaddr)) == NULL) {
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%lx\n", ipaddr->addr));
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_send_to: No route to 0x%lx\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);
}
@@ -257,14 +240,14 @@ raw_sendto(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 IP packet
* @param p the ip payload to send
* @param ipaddr the destination address of the whole IP packet
*
*/
err_t
raw_send(struct raw_pcb *pcb, struct pbuf *p)
{
return raw_sendto(pcb, p, &pcb->remote_ip);
return raw_send_to(pcb,p,&pcb->remote_ip);
}
/**
@@ -283,7 +266,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) {
@@ -320,6 +303,7 @@ raw_new(u16_t proto) {
pcb->next = raw_pcbs;
raw_pcbs = pcb;
}
return pcb;
}

View File

@@ -30,7 +30,6 @@
*
*/
#include <string.h>
#include "lwip/opt.h"
@@ -48,68 +47,5 @@ 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: %d\n\t", proto->xmit));
LWIP_PLATFORM_DIAG(("rexmit: %d\n\t", proto->rexmit));
LWIP_PLATFORM_DIAG(("recv: %d\n\t", proto->recv));
LWIP_PLATFORM_DIAG(("fw: %d\n\t", proto->fw));
LWIP_PLATFORM_DIAG(("drop: %d\n\t", proto->drop));
LWIP_PLATFORM_DIAG(("chkerr: %d\n\t", proto->chkerr));
LWIP_PLATFORM_DIAG(("lenerr: %d\n\t", proto->lenerr));
LWIP_PLATFORM_DIAG(("memerr: %d\n\t", proto->memerr));
LWIP_PLATFORM_DIAG(("rterr: %d\n\t", proto->rterr));
LWIP_PLATFORM_DIAG(("proterr: %d\n\t", proto->proterr));
LWIP_PLATFORM_DIAG(("opterr: %d\n\t", proto->opterr));
LWIP_PLATFORM_DIAG(("err: %d\n\t", proto->err));
LWIP_PLATFORM_DIAG(("cachehit: %d\n", proto->cachehit));
}
void
stats_display_pbuf(struct stats_pbuf *pbuf)
{
LWIP_PLATFORM_DIAG(("\nPBUF\n\t"));
LWIP_PLATFORM_DIAG(("avail: %d\n\t", pbuf->avail));
LWIP_PLATFORM_DIAG(("used: %d\n\t", pbuf->used));
LWIP_PLATFORM_DIAG(("max: %d\n\t", pbuf->max));
LWIP_PLATFORM_DIAG(("err: %d\n\t", pbuf->err));
LWIP_PLATFORM_DIAG(("alloc_locked: %d\n\t", pbuf->alloc_locked));
LWIP_PLATFORM_DIAG(("refresh_locked: %d\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: %d\n\t", mem->avail));
LWIP_PLATFORM_DIAG(("used: %d\n\t", mem->used));
LWIP_PLATFORM_DIAG(("max: %d\n\t", mem->max));
LWIP_PLATFORM_DIAG(("err: %d\n", mem->err));
}
void
stats_display(void)
{
int 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 */

View File

@@ -174,7 +174,6 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
(void *)timeout, msecs, (void *)h, (void *)arg));
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
if (timeouts->next == NULL) {
timeouts->next = timeout;
return;
@@ -187,13 +186,14 @@ 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;
}
}
}

View File

@@ -2,11 +2,6 @@
* @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.
*
*/
/*
@@ -41,7 +36,16 @@
*
*/
#include <string.h>
/* tcp.c
*
* This file contains common functions for the TCP implementation, such as functinos
* for manipulating the data structures and the TCP timer functions. TCP functions
* related to input and output is found in tcp_input.c and tcp_output.c respectively.
*
*/
#include "lwip/opt.h"
#include "lwip/def.h"
@@ -58,28 +62,30 @@ const u8_t tcp_backoff[13] =
{ 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
/* The TCP PCB lists. */
/** 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_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. */
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.listen_pcbs = NULL;
tcp_listen_pcbs = NULL;
tcp_active_pcbs = NULL;
tcp_tw_pcbs = NULL;
tcp_tmp_pcb = NULL;
@@ -90,10 +96,13 @@ tcp_init(void)
}
/**
/*
* tcp_tmr():
*
* Called periodically to dispatch TCP timers.
*
*/
void
tcp_tmr(void)
{
@@ -107,10 +116,13 @@ tcp_tmr(void)
}
}
/**
/*
* tcp_close():
*
* Closes the connection held by the PCB.
*
*/
err_t
tcp_close(struct tcp_pcb *pcb)
{
@@ -122,21 +134,9 @@ 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.pcbs, pcb);
tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs, pcb);
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
pcb = NULL;
break;
@@ -172,12 +172,15 @@ 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)
{
@@ -226,7 +229,9 @@ 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.
@@ -237,16 +242,16 @@ err_t
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct tcp_pcb *cpcb;
#if SO_REUSE
#ifdef SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
if (port == 0) {
port = tcp_new_port();
}
#if SO_REUSE == 0
#ifndef SO_REUSE
/* Check if the address already is in use. */
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs;
cpcb != NULL; cpcb = cpcb->next) {
if (cpcb->local_port == port) {
if (ip_addr_isany(&(cpcb->local_ip)) ||
@@ -279,7 +284,7 @@ tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
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.pcbs; cpcb != NULL; cpcb = cpcb->next) {
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) {
@@ -381,13 +386,16 @@ 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)
{
@@ -413,16 +421,19 @@ tcp_listen(struct tcp_pcb *pcb)
#if LWIP_CALLBACK_API
lpcb->accept = tcp_accept_null;
#endif /* LWIP_CALLBACK_API */
TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb);
TCP_REG(&tcp_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)
{
@@ -433,37 +444,20 @@ 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",
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)
{
@@ -489,7 +483,7 @@ tcp_new_port(void)
goto again;
}
}
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->local_port == port) {
goto again;
}
@@ -497,11 +491,14 @@ 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))
@@ -549,11 +546,14 @@ 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,9 +569,7 @@ 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);
@@ -600,6 +598,7 @@ 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;
@@ -609,10 +608,7 @@ tcp_slowtmr(void)
pcb->cwnd = pcb->mss;
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\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) {
@@ -734,9 +730,12 @@ tcp_slowtmr(void)
}
}
/**
/*
* tcp_fasttmr():
*
* Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
*/
void
tcp_fasttmr(void)
{
@@ -752,10 +751,13 @@ tcp_fasttmr(void)
}
}
/**
/*
* tcp_segs_free():
*
* Deallocates a list of TCP segments (tcp_seg structures).
*
*/
u8_t
tcp_segs_free(struct tcp_seg *seg)
{
@@ -769,10 +771,13 @@ 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)
{
@@ -790,10 +795,13 @@ 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)
{
@@ -801,10 +809,13 @@ 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)
{
@@ -858,7 +869,7 @@ tcp_kill_prio(u8_t prio)
}
}
if (inactive != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%ld)\n",
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB 0x%p (%ld)\n",
(void *)inactive, inactivity));
tcp_abort(inactive);
}
@@ -880,7 +891,7 @@ tcp_kill_timewait(void)
}
}
if (inactive != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%ld)\n",
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB 0x%p (%ld)\n",
(void *)inactive, inactivity));
tcp_abort(inactive);
}
@@ -940,13 +951,12 @@ 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 *
@@ -970,11 +980,14 @@ 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))
@@ -982,7 +995,9 @@ 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.
*
@@ -995,11 +1010,14 @@ 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))
@@ -1007,11 +1025,14 @@ 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))
@@ -1021,12 +1042,15 @@ 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)
@@ -1037,10 +1061,13 @@ 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)
{
@@ -1070,10 +1097,13 @@ 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)
{
@@ -1093,10 +1123,13 @@ 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)
{
@@ -1220,7 +1253,7 @@ tcp_debug_print_pcbs(void)
tcp_debug_print_state(pcb->state);
}
LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
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 ",
pcb->local_port, pcb->remote_port,
pcb->snd_nxt, pcb->rcv_nxt));

View File

@@ -2,12 +2,6 @@
* @file
*
* Transmission Control Protocol, incoming traffic
*
* The input processing functions of TCP.
*
* These functions are generally called in the order (ip_input() ->) tcp_input() ->
* tcp_process() -> tcp_receive() (-> application).
*
*/
/*
@@ -42,10 +36,21 @@
*
*/
/* tcp_input.c
*
* The input processing functions of TCP.
*
* These functions are generally called in the order (ip_input() ->) tcp_input() ->
* tcp_process() -> tcp_receive() (-> application).
*
*/
#include "lwip/def.h"
#include "lwip/opt.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
@@ -97,7 +102,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
u8_t hdrlen;
err_t err;
#if SO_REUSE
#ifdef SO_REUSE
struct tcp_pcb *pcb_temp;
int reuse = 0;
int reuse_port = 0;
@@ -125,13 +130,12 @@ tcp_input(struct pbuf *p, struct netif *inp)
}
/* Don't even process incoming broadcasts/multicasts. */
if (ip_addr_isbroadcast(&(iphdr->dest), inp) ||
ip_addr_ismulticast(&(iphdr->dest))) {
if (ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) ||
ip_addr_ismulticast(&(iphdr->dest))) {
pbuf_free(p);
return;
}
#if CHECKSUM_CHECK_TCP
/* Verify TCP checksum. */
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
(struct ip_addr *)&(iphdr->dest),
@@ -148,7 +152,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
pbuf_free(p);
return;
}
#endif
/* Move the payload pointer in the pbuf so that it points to the
TCP data instead of the TCP header. */
@@ -169,7 +173,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
for an active connection. */
prev = NULL;
#if SO_REUSE
#ifdef SO_REUSE
pcb_temp = tcp_active_pcbs;
again_1:
@@ -187,7 +191,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
#if SO_REUSE
#ifdef SO_REUSE
if(pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
@@ -251,7 +255,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Finally, if we still did not get a match, we check all PCBs that
are LISTENing for incoming connections. */
prev = NULL;
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
for(lpcb = tcp_listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
if ((ip_addr_isany(&(lpcb->local_ip)) ||
ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
lpcb->local_port == tcphdr->dest) {
@@ -261,9 +265,9 @@ tcp_input(struct pbuf *p, struct netif *inp)
if (prev != NULL) {
((struct tcp_pcb_listen *)prev)->next = lpcb->next;
/* our successor is the remainder of the listening list */
lpcb->next = tcp_listen_pcbs.listen_pcbs;
lpcb->next = tcp_listen_pcbs;
/* put this listening pcb at the head of the listening list */
tcp_listen_pcbs.listen_pcbs = lpcb;
tcp_listen_pcbs = lpcb;
}
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
@@ -351,13 +355,13 @@ tcp_input(struct pbuf *p, struct netif *inp)
increase the reference counter in the pbuf. If so, the buffer
isn't actually deallocated by the call to pbuf_free(), only the
reference count is decreased. */
if (inseg.p != NULL) pbuf_free(inseg.p);
pbuf_free(inseg.p);
#if TCP_INPUT_DEBUG
#if TCP_DEBUG
tcp_debug_print_state(pcb->state);
#endif /* TCP_DEBUG */
#endif /* TCP_INPUT_DEBUG */
#if SO_REUSE
#ifdef SO_REUSE
/* First socket should receive now */
if(reuse_port) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: searching next PCB.\n"));
@@ -369,7 +373,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
#endif /* SO_REUSE */
} else {
#if SO_REUSE
#ifdef SO_REUSE
if(reuse) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: freeing PBUF with reference counter set to %i\n", p->ref));
pbuf_free(p);
@@ -388,7 +392,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
}
pbuf_free(p);
}
#if SO_REUSE
#ifdef SO_REUSE
end:
#endif /* SO_REUSE */
LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
@@ -503,14 +507,12 @@ tcp_process(struct tcp_pcb *pcb)
/* First, determine if the reset is acceptable. */
if (pcb->state == SYN_SENT) {
if (ackno == pcb->snd_nxt) {
acceptable = 1;
acceptable = 1;
}
} else {
/*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
*/
if(TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)){
acceptable = 1;
if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
acceptable = 1;
}
}
@@ -540,7 +542,6 @@ tcp_process(struct tcp_pcb *pcb)
pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
if ((flags & TCP_ACK) && (flags & TCP_SYN)
&& ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
pcb->snd_buf ++;
pcb->rcv_nxt = seqno + 1;
pcb->lastack = ackno;
pcb->snd_wnd = tcphdr->wnd;
@@ -565,9 +566,8 @@ tcp_process(struct tcp_pcb *pcb)
case SYN_RCVD:
if (flags & TCP_ACK &&
!(flags & TCP_RST)) {
/*if (TCP_SEQ_LT(pcb->lastack, ackno) &&
TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) { */
if(TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
if (TCP_SEQ_LT(pcb->lastack, ackno) &&
TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) {
pcb->state = ESTABLISHED;
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
#if LWIP_CALLBACK_API
@@ -676,7 +676,6 @@ tcp_receive(struct tcp_pcb *pcb)
s32_t off;
int m;
u32_t right_wnd_edge;
u16_t new_tot_len;
if (flags & TCP_ACK) {
@@ -704,50 +703,43 @@ tcp_receive(struct tcp_pcb *pcb)
pcb->acked = 0;
if (pcb->snd_wl1 + pcb->snd_wnd == right_wnd_edge){
++pcb->dupacks;
if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
if (!(pcb->flags & TF_INFR)) {
/* This is fast retransmit. Retransmit the first unacked segment. */
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %u (%lu), fast retransmit %lu\n",
(unsigned int)pcb->dupacks, pcb->lastack,
ntohl(pcb->unacked->tcphdr->seqno)));
tcp_rexmit(pcb);
/* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
/*pcb->ssthresh = LWIP_MAX((pcb->snd_max -
pcb->lastack) / 2,
2 * pcb->mss);*/
/* Set ssthresh to half of the minimum of the currenct cwnd and the advertised window */
if(pcb->cwnd > pcb->snd_wnd)
pcb->ssthresh = pcb->snd_wnd / 2;
else
pcb->ssthresh = pcb->cwnd / 2;
++pcb->dupacks;
if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
if (!(pcb->flags & TF_INFR)) {
/* This is fast retransmit. Retransmit the first unacked segment. */
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %u (%lu), fast retransmit %lu\n",
(unsigned int)pcb->dupacks, pcb->lastack,
ntohl(pcb->unacked->tcphdr->seqno)));
tcp_rexmit(pcb);
/* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
pcb->ssthresh = LWIP_MAX((pcb->snd_max -
pcb->lastack) / 2,
2 * pcb->mss);
pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
pcb->flags |= TF_INFR;
} else {
/* Inflate the congestion window, but not if it means that
the value overflows. */
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
pcb->cwnd += pcb->mss;
}
}
}
} else {
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %lu %lu\n",
pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
pcb->flags |= TF_INFR;
} else {
/* Inflate the congestion window, but not if it means that
the value overflows. */
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
pcb->cwnd += pcb->mss;
}
} else
/*if (TCP_SEQ_LT(pcb->lastack, ackno) &&
TCP_SEQ_LEQ(ackno, pcb->snd_max)) { */
if(TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){
}
}
} else {
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %lu %lu\n",
pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
}
} else if (TCP_SEQ_LT(pcb->lastack, ackno) &&
TCP_SEQ_LEQ(ackno, pcb->snd_max)) {
/* We come here when the ACK acknowledges new data. */
/* Reset the "IN Fast Retransmit" flag, since we are no longer
in fast retransmit. Also reset the congestion window to the
slow start threshold. */
if (pcb->flags & TF_INFR) {
pcb->flags &= ~TF_INFR;
pcb->cwnd = pcb->ssthresh;
pcb->flags &= ~TF_INFR;
pcb->cwnd = pcb->ssthresh;
}
/* Reset the number of retransmissions. */
@@ -768,85 +760,86 @@ tcp_receive(struct tcp_pcb *pcb)
ssthresh). */
if (pcb->state >= ESTABLISHED) {
if (pcb->cwnd < pcb->ssthresh) {
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
pcb->cwnd += pcb->mss;
}
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
pcb->cwnd += pcb->mss;
}
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %u\n", pcb->cwnd));
} else {
u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
if (new_cwnd > pcb->cwnd) {
pcb->cwnd = new_cwnd;
}
u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
if (new_cwnd > pcb->cwnd) {
pcb->cwnd = new_cwnd;
}
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %u\n", pcb->cwnd));
}
}
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %lu, unacked->seqno %lu:%lu\n",
ackno,
pcb->unacked != NULL?
ntohl(pcb->unacked->tcphdr->seqno): 0,
pcb->unacked != NULL?
ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
ackno,
pcb->unacked != NULL?
ntohl(pcb->unacked->tcphdr->seqno): 0,
pcb->unacked != NULL?
ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
/* Remove segment from the unacknowledged list if the incoming
ACK acknowlegdes them. */
ACK acknowlegdes them. */
while (pcb->unacked != NULL &&
TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
TCP_TCPLEN(pcb->unacked), ackno)) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n",
ntohl(pcb->unacked->tcphdr->seqno),
ntohl(pcb->unacked->tcphdr->seqno) +
TCP_TCPLEN(pcb->unacked)));
TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
TCP_TCPLEN(pcb->unacked), ackno)) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n",
ntohl(pcb->unacked->tcphdr->seqno),
ntohl(pcb->unacked->tcphdr->seqno) +
TCP_TCPLEN(pcb->unacked)));
next = pcb->unacked;
pcb->unacked = pcb->unacked->next;
next = pcb->unacked;
pcb->unacked = pcb->unacked->next;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
pcb->snd_queuelen -= pbuf_clen(next->p);
tcp_seg_free(next);
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
pcb->snd_queuelen -= pbuf_clen(next->p);
tcp_seg_free(next);
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unacked)\n", (unsigned int)pcb->snd_queuelen));
if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL);
}
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unacked)\n", (unsigned int)pcb->snd_queuelen));
if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL);
}
}
pcb->polltmr = 0;
}
/* We go through the ->unsent list to see if any of the segments
on the list are acknowledged by the ACK. This may seem
strange since an "unsent" segment shouldn't be acked. The
rationale is that lwIP puts all outstanding segments on the
->unsent list after a retransmission, so these segments may
in fact have been sent once. */
while (pcb->unsent != NULL &&
/*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) &&
TCP_SEQ_LEQ(ackno, pcb->snd_max)*/
TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_max)
) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unsent\n",
ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
TCP_TCPLEN(pcb->unsent)));
/* We go through the ->unsent list to see if any of the segments
on the list are acknowledged by the ACK. This may seem
strange since an "unsent" segment shouldn't be acked. The
rationale is that lwIP puts all outstanding segments on the
->unsent list after a retransmission, so these segments may
in fact have been sent once. */
while (pcb->unsent != NULL &&
TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent),
ackno) &&
TCP_SEQ_LEQ(ackno, pcb->snd_max)) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unsent\n",
ntohl(pcb->unsent->tcphdr->seqno),
ntohl(pcb->unsent->tcphdr->seqno) +
TCP_TCPLEN(pcb->unsent)));
next = pcb->unsent;
pcb->unsent = pcb->unsent->next;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
pcb->snd_queuelen -= pbuf_clen(next->p);
tcp_seg_free(next);
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unsent)\n", (unsigned int)pcb->snd_queuelen));
if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_receive: valid queue length",
pcb->unacked != NULL || pcb->unsent != NULL);
next = pcb->unsent;
pcb->unsent = pcb->unsent->next;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
pcb->snd_queuelen -= pbuf_clen(next->p);
tcp_seg_free(next);
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unsent)\n", (unsigned int)pcb->snd_queuelen));
if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL);
}
if (pcb->unsent != NULL) {
pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);
}
}
if (pcb->unsent != NULL) {
pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);
}
}
/* End of ACK for new data processing. */
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %u rtseq %lu ackno %lu\n",
pcb->rttest, pcb->rtseq, ackno));
pcb->rttest, pcb->rtseq, ackno));
/* RTT estimation calculations. This is done by checking if the
incoming segment acknowledges the segment we use to take a
@@ -855,20 +848,20 @@ tcp_receive(struct tcp_pcb *pcb)
m = tcp_ticks - pcb->rttest;
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %u ticks (%u msec).\n",
m, m * TCP_SLOW_INTERVAL));
m, m * TCP_SLOW_INTERVAL));
/* This is taken directly from VJs original code in his paper */
m = m - (pcb->sa >> 3);
pcb->sa += m;
if (m < 0) {
m = -m;
m = -m;
}
m = m - (pcb->sv >> 2);
pcb->sv += m;
pcb->rto = (pcb->sa >> 3) + pcb->sv;
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %u (%u miliseconds)\n",
pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
pcb->rttest = 0;
}
@@ -879,309 +872,290 @@ tcp_receive(struct tcp_pcb *pcb)
if (tcplen > 0) {
/* This code basically does three things:
+) If the incoming segment contains data that is the next
in-sequence data, this data is passed to the application. This
might involve trimming the first edge of the data. The rcv_nxt
variable and the advertised window are adjusted.
+) If the incoming segment contains data that is the next
in-sequence data, this data is passed to the application. This
might involve trimming the first edge of the data. The rcv_nxt
variable and the advertised window are adjusted.
+) If the incoming segment has data that is above the next
sequence number expected (->rcv_nxt), the segment is placed on
the ->ooseq queue. This is done by finding the appropriate
place in the ->ooseq queue (which is ordered by sequence
number) and trim the segment in both ends if needed. An
immediate ACK is sent to indicate that we received an
out-of-sequence segment.
+) If the incoming segment has data that is above the next
sequence number expected (->rcv_nxt), the segment is placed on
the ->ooseq queue. This is done by finding the appropriate
place in the ->ooseq queue (which is ordered by sequence
number) and trim the segment in both ends if needed. An
immediate ACK is sent to indicate that we received an
out-of-sequence segment.
+) Finally, we check if the first segment on the ->ooseq queue
now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
rcv_nxt > ooseq->seqno, we must trim the first edge of the
segment on ->ooseq before we adjust rcv_nxt. The data in the
segments that are now on sequence are chained onto the
incoming segment so that we only need to call the application
once.
+) Finally, we check if the first segment on the ->ooseq queue
now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
rcv_nxt > ooseq->seqno, we must trim the first edge of the
segment on ->ooseq before we adjust rcv_nxt. The data in the
segments that are now on sequence are chained onto the
incoming segment so that we only need to call the application
once.
*/
/* First, we check if we must trim the first edge. We have to do
this if the sequence number of the incoming segment is less
than rcv_nxt, and the sequence number plus the length of the
segment is larger than rcv_nxt. */
/* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
if(TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno+1, seqno+tcplen-1)){
/* Trimming the first edge is done by pushing the payload
pointer in the pbuf downwards. This is somewhat tricky since
we do not want to discard the full contents of the pbuf up to
the new starting point of the data since we have to keep the
TCP header which is present in the first pbuf in the chain.
What is done is really quite a nasty hack: the first pbuf in
the pbuf chain is pointed to by inseg.p. Since we need to be
able to deallocate the whole pbuf, we cannot change this
inseg.p pointer to point to any of the later pbufs in the
chain. Instead, we point the ->payload pointer in the first
pbuf to data in one of the later pbufs. We also set the
inseg.data pointer to point to the right place. This way, the
->p pointer will still point to the first pbuf, but the
->p->payload pointer will point to data in another pbuf.
After we are done with adjusting the pbuf pointers we must
adjust the ->data pointer in the seg and the segment
length.*/
off = pcb->rcv_nxt - seqno;
p = inseg.p;
if (inseg.p->len < off) {
new_tot_len = inseg.p->tot_len - off;
while (p->len < off) {
off -= p->len;
/* KJM following line changed (with addition of new_tot_len var)
to fix bug #9076
inseg.p->tot_len -= p->len; */
p->tot_len = new_tot_len;
p->len = 0;
p = p->next;
}
pbuf_header(p, -off);
} else {
pbuf_header(inseg.p, -off);
}
/* KJM following line changed to use p->payload rather than inseg->p->payload
to fix bug #9076 */
inseg.dataptr = p->payload;
inseg.len -= pcb->rcv_nxt - seqno;
inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {
/* Trimming the first edge is done by pushing the payload
pointer in the pbuf downwards. This is somewhat tricky since
we do not want to discard the full contents of the pbuf up to
the new starting point of the data since we have to keep the
TCP header which is present in the first pbuf in the chain.
What is done is really quite a nasty hack: the first pbuf in
the pbuf chain is pointed to by inseg.p. Since we need to be
able to deallocate the whole pbuf, we cannot change this
inseg.p pointer to point to any of the later pbufs in the
chain. Instead, we point the ->payload pointer in the first
pbuf to data in one of the later pbufs. We also set the
inseg.data pointer to point to the right place. This way, the
->p pointer will still point to the first pbuf, but the
->p->payload pointer will point to data in another pbuf.
After we are done with adjusting the pbuf pointers we must
adjust the ->data pointer in the seg and the segment
length.*/
off = pcb->rcv_nxt - seqno;
if (inseg.p->len < off) {
p = inseg.p;
while (p->len < off) {
off -= p->len;
inseg.p->tot_len -= p->len;
p->len = 0;
p = p->next;
}
else{
if(TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
/* the whole segment is < rcv_nxt */
/* must be a duplicate of a packet that has already been correctly handled */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno));
tcp_ack_now(pcb);
pbuf_header(p, -off);
} else {
pbuf_header(inseg.p, -off);
}
inseg.dataptr = inseg.p->payload;
inseg.len -= pcb->rcv_nxt - seqno;
inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
}
else{
/* the whole segment is < rcv_nxt */
/* must be a duplicate of a packet that has already been correctly handled */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno));
tcp_ack_now(pcb);
}
}
/* The sequence number must be within the window (above rcv_nxt
and below rcv_nxt + rcv_wnd) in order to be further
processed. */
/*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
if(TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)){
if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
if (pcb->rcv_nxt == seqno) {
/* The incoming segment is the next in sequence. We check if
/* The incoming segment is the next in sequence. We check if
we have to trim the end of the segment and update rcv_nxt
and pass the data to the application. */
#if TCP_QUEUE_OOSEQ
if (pcb->ooseq != NULL &&
TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) {
/* We have to trim the second edge of the incoming
if (pcb->ooseq != NULL &&
TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) {
/* We have to trim the second edge of the incoming
segment. */
inseg.len = pcb->ooseq->tcphdr->seqno - seqno;
pbuf_realloc(inseg.p, inseg.len);
}
inseg.len = pcb->ooseq->tcphdr->seqno - seqno;
pbuf_realloc(inseg.p, inseg.len);
}
#endif /* TCP_QUEUE_OOSEQ */
tcplen = TCP_TCPLEN(&inseg);
tcplen = TCP_TCPLEN(&inseg);
pcb->rcv_nxt += tcplen;
pcb->rcv_nxt += tcplen;
/* Update the receiver's (our) window. */
if (pcb->rcv_wnd < tcplen) {
pcb->rcv_wnd = 0;
} else {
pcb->rcv_wnd -= tcplen;
}
/* Update the receiver's (our) window. */
if (pcb->rcv_wnd < tcplen) {
pcb->rcv_wnd = 0;
} else {
pcb->rcv_wnd -= tcplen;
}
/* If there is data in the segment, we make preparations to
pass this up to the application. The ->recv_data variable
is used for holding the pbuf that goes to the
application. The code for reassembling out-of-sequence data
chains its data on this pbuf as well.
/* If there is data in the segment, we make preparations to
pass this up to the application. The ->recv_data variable
is used for holding the pbuf that goes to the
application. The code for reassembling out-of-sequence data
chains its data on this pbuf as well.
If the segment was a FIN, we set the TF_GOT_FIN flag that will
be used to indicate to the application that the remote side has
closed its end of the connection. */
if (inseg.p->tot_len > 0) {
recv_data = inseg.p;
/* Since this pbuf now is the responsibility of the
application, we delete our reference to it so that we won't
(mistakingly) deallocate it. */
inseg.p = NULL;
}
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
recv_flags = TF_GOT_FIN;
}
If the segment was a FIN, we set the TF_GOT_FIN flag that will
be used to indicate to the application that the remote side has
closed its end of the connection. */
if (inseg.p->tot_len > 0) {
recv_data = inseg.p;
/* Since this pbuf now is the responsibility of the
application, we delete our reference to it so that we won't
(mistakingly) deallocate it. */
inseg.p = NULL;
}
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
recv_flags = TF_GOT_FIN;
}
#if TCP_QUEUE_OOSEQ
/* We now check if we have segments on the ->ooseq queue that
/* We now check if we have segments on the ->ooseq queue that
is now in sequence. */
while (pcb->ooseq != NULL &&
pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
while (pcb->ooseq != NULL &&
pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
cseg = pcb->ooseq;
seqno = pcb->ooseq->tcphdr->seqno;
cseg = pcb->ooseq;
seqno = pcb->ooseq->tcphdr->seqno;
pcb->rcv_nxt += TCP_TCPLEN(cseg);
if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) {
pcb->rcv_wnd = 0;
} else {
pcb->rcv_wnd -= TCP_TCPLEN(cseg);
}
if (cseg->p->tot_len > 0) {
/* Chain this pbuf onto the pbuf that we will pass to
the application. */
if (recv_data) {
pcb->rcv_nxt += TCP_TCPLEN(cseg);
if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) {
pcb->rcv_wnd = 0;
} else {
pcb->rcv_wnd -= TCP_TCPLEN(cseg);
}
if (cseg->p->tot_len > 0) {
/* Chain this pbuf onto the pbuf that we will pass to
the application. */
if (recv_data) {
pbuf_cat(recv_data, cseg->p);
} else {
recv_data = cseg->p;
}
cseg->p = NULL;
}
if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
recv_flags = TF_GOT_FIN;
}
recv_data = cseg->p;
}
cseg->p = NULL;
}
if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
recv_flags = TF_GOT_FIN;
}
pcb->ooseq = cseg->next;
tcp_seg_free(cseg);
}
pcb->ooseq = cseg->next;
tcp_seg_free(cseg);
}
#endif /* TCP_QUEUE_OOSEQ */
/* Acknowledge the segment(s). */
tcp_ack(pcb);
/* Acknowledge the segment(s). */
tcp_ack(pcb);
} else {
/* We get here if the incoming segment is out-of-sequence. */
tcp_ack_now(pcb);
/* We get here if the incoming segment is out-of-sequence. */
tcp_ack_now(pcb);
#if TCP_QUEUE_OOSEQ
/* We queue the segment on the ->ooseq queue. */
if (pcb->ooseq == NULL) {
pcb->ooseq = tcp_seg_copy(&inseg);
} else {
/* If the queue is not empty, we walk through the queue and
try to find a place where the sequence number of the
incoming segment is between the sequence numbers of the
previous and the next segment on the ->ooseq queue. That is
the place where we put the incoming segment. If needed, we
trim the second edges of the previous and the incoming
segment so that it will fit into the sequence.
/* We queue the segment on the ->ooseq queue. */
if (pcb->ooseq == NULL) {
pcb->ooseq = tcp_seg_copy(&inseg);
} else {
/* If the queue is not empty, we walk through the queue and
try to find a place where the sequence number of the
incoming segment is between the sequence numbers of the
previous and the next segment on the ->ooseq queue. That is
the place where we put the incoming segment. If needed, we
trim the second edges of the previous and the incoming
segment so that it will fit into the sequence.
If the incoming segment has the same sequence number as a
segment on the ->ooseq queue, we discard the segment that
contains less data. */
If the incoming segment has the same sequence number as a
segment on the ->ooseq queue, we discard the segment that
contains less data. */
prev = NULL;
for(next = pcb->ooseq; next != NULL; next = next->next) {
if (seqno == next->tcphdr->seqno) {
/* The sequence number of the incoming segment is the
prev = NULL;
for(next = pcb->ooseq; next != NULL; next = next->next) {
if (seqno == next->tcphdr->seqno) {
/* The sequence number of the incoming segment is the
same as the sequence number of the segment on
->ooseq. We check the lengths to see which one to
discard. */
if (inseg.len > next->len) {
/* The incoming segment is larger than the old
if (inseg.len > next->len) {
/* The incoming segment is larger than the old
segment. We replace the old segment with the new
one. */
cseg = tcp_seg_copy(&inseg);
if (cseg != NULL) {
cseg->next = next->next;
if (prev != NULL) {
prev->next = cseg;
} else {
pcb->ooseq = cseg;
}
}
break;
} else {
/* Either the lenghts are the same or the incoming
cseg = tcp_seg_copy(&inseg);
if (cseg != NULL) {
cseg->next = next->next;
if (prev != NULL) {
prev->next = cseg;
} else {
pcb->ooseq = cseg;
}
}
break;
} else {
/* Either the lenghts are the same or the incoming
segment was smaller than the old one; in either
case, we ditch the incoming segment. */
break;
}
} else {
if (prev == NULL) {
if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
/* The sequence number of the incoming segment is lower
than the sequence number of the first segment on the
queue. We put the incoming segment first on the
queue. */
break;
}
} else {
if (prev == NULL) {
if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
/* The sequence number of the incoming segment is lower
than the sequence number of the first segment on the
queue. We put the incoming segment first on the
queue. */
if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
/* We need to trim the incoming segment. */
inseg.len = next->tcphdr->seqno - seqno;
pbuf_realloc(inseg.p, inseg.len);
}
cseg = tcp_seg_copy(&inseg);
if (cseg != NULL) {
cseg->next = next;
pcb->ooseq = cseg;
}
break;
}
} else
/*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){
/* The sequence number of the incoming segment is in
if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
/* We need to trim the incoming segment. */
inseg.len = next->tcphdr->seqno - seqno;
pbuf_realloc(inseg.p, inseg.len);
}
cseg = tcp_seg_copy(&inseg);
if (cseg != NULL) {
cseg->next = next;
pcb->ooseq = cseg;
}
break;
}
} else if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
/* The sequence number of the incoming segment is in
between the sequence numbers of the previous and
the next segment on ->ooseq. We trim and insert the
incoming segment and trim the previous segment, if
needed. */
if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
/* We need to trim the incoming segment. */
inseg.len = next->tcphdr->seqno - seqno;
pbuf_realloc(inseg.p, inseg.len);
}
if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
/* We need to trim the incoming segment. */
inseg.len = next->tcphdr->seqno - seqno;
pbuf_realloc(inseg.p, inseg.len);
}
cseg = tcp_seg_copy(&inseg);
if (cseg != NULL) {
cseg->next = next;
prev->next = cseg;
if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
/* We need to trim the prev segment. */
prev->len = seqno - prev->tcphdr->seqno;
pbuf_realloc(prev->p, prev->len);
}
}
break;
}
/* If the "next" segment is the last segment on the
cseg = tcp_seg_copy(&inseg);
if (cseg != NULL) {
cseg->next = next;
prev->next = cseg;
if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
/* We need to trim the prev segment. */
prev->len = seqno - prev->tcphdr->seqno;
pbuf_realloc(prev->p, prev->len);
}
}
break;
}
/* If the "next" segment is the last segment on the
ooseq queue, we add the incoming segment to the end
of the list. */
if (next->next == NULL &&
TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
next->next = tcp_seg_copy(&inseg);
if (next->next != NULL) {
if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
/* We need to trim the last segment. */
next->len = seqno - next->tcphdr->seqno;
pbuf_realloc(next->p, next->len);
}
}
break;
}
}
prev = next;
}
if (next->next == NULL &&
TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
next->next = tcp_seg_copy(&inseg);
if (next->next != NULL) {
if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
/* We need to trim the last segment. */
next->len = seqno - next->tcphdr->seqno;
pbuf_realloc(next->p, next->len);
}
}
break;
}
}
prev = next;
}
}
#endif /* TCP_QUEUE_OOSEQ */
}
} else {
/*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
tcp_ack_now(pcb);
}
}
} else {
/* Segments with length 0 is taken care of here. Segments that
fall out of the window are ACKed. */
/*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
tcp_ack_now(pcb);
}
}
@@ -1215,7 +1189,7 @@ tcp_parseopt(struct tcp_pcb *pcb)
++c;
/* NOP option. */
} else if (opt == 0x02 &&
opts[c + 1] == 0x04) {
opts[c + 1] == 0x04) {
/* An MSS option with the right option length. */
mss = (opts[c + 2] << 8) | opts[c + 3];
pcb->mss = mss > TCP_MSS? TCP_MSS: mss;

View File

@@ -2,11 +2,7 @@
* @file
*
* Transmission Control Protocol, outgoing traffic
*
* The output functions of TCP.
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
@@ -39,6 +35,15 @@
*
*/
/* tcp_output.c
*
* The output functions of TCP.
*
*/
#include "lwip/def.h"
#include "lwip/opt.h"
@@ -46,7 +51,6 @@
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/inet.h"
@@ -59,36 +63,24 @@
/* 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));
/* 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 (pcb->state == SYN_SENT ||
pcb->state == SYN_RCVD ||
pcb->state == ESTABLISHED ||
pcb->state == CLOSE_WAIT) {
if (len > 0) {
return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
}
@@ -99,24 +91,10 @@ 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;
@@ -127,43 +105,39 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
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));
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);
left = len;
ptr = arg;
/* 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));
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));
/* If total number of pbufs on the unsent/unacked queues exceeds the
* configured maximum, return an error */
/* Check if the queue length exceeds the configured maximum queue
* length. If so, we 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;
}
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);
if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_enqueue: valid queue length", 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
@@ -179,25 +153,20 @@ 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) {
queue = seg;
useg = 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;
@@ -205,7 +174,6 @@ 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));
@@ -219,7 +187,8 @@ 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.
@@ -229,7 +198,6 @@ 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;
@@ -244,7 +212,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
++queuelen;
/* Concatenate the headers and data pbufs together. */
pbuf_cat(seg->p/*header*/, p/*data*/);
pbuf_cat(seg->p, p);
p = NULL;
}
@@ -256,10 +224,16 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
}
seg->len = seglen;
/* build TCP header */
#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. */
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;
}
@@ -292,6 +266,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
ptr = (void *)((char *)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. */
@@ -301,7 +276,6 @@ 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. */
@@ -309,27 +283,24 @@ 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 of our to-be-queued list */
/* Remove TCP header from first segment. */
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 segments, new len %u\n", useg->len));
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining, new len %u\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;
}
@@ -339,12 +310,12 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
}
pcb->snd_lbb += len;
pcb->snd_buf -= len;
/* update number of segments on the queues */
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);
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
@@ -363,6 +334,7 @@ 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));
return ERR_MEM;
@@ -390,6 +362,7 @@ 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 */
@@ -397,24 +370,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 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 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 (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));
/* 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);
@@ -427,10 +400,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);
@@ -455,7 +428,7 @@ tcp_output(struct tcp_pcb *pcb)
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
@@ -482,26 +455,13 @@ 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 {
/* 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;
}
useg->next = seg;
useg = useg->next;
}
/* do not queue empty segments on the unacked list */
} else {
tcp_seg_free(seg);
}
@@ -510,9 +470,6 @@ 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)
{
@@ -561,12 +518,10 @@ 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,
@@ -597,10 +552,9 @@ 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);
@@ -608,36 +562,6 @@ tcp_rst(u32_t seqno, u32_t ackno,
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\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
tcp_rexmit(struct tcp_pcb *pcb)
{
@@ -647,11 +571,14 @@ tcp_rexmit(struct tcp_pcb *pcb)
return;
}
/* Move the first unacked segment to the unsent queue */
seg = pcb->unacked->next;
pcb->unacked->next = pcb->unsent;
/* Move all unacked segments to the unsent queue. */
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
seg->next = pcb->unsent;
pcb->unsent = pcb->unacked;
pcb->unacked = seg;
pcb->unacked = NULL;
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
@@ -665,7 +592,6 @@ tcp_rexmit(struct tcp_pcb *pcb)
}
void
tcp_keepalive(struct tcp_pcb *pcb)
{
@@ -676,7 +602,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
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 %lu pcb->tmr %lu pcb->keep_cnt %u\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %ld pcb->tmr %ld pcb->keep_cnt %ld\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
@@ -695,9 +621,8 @@ 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 */

View File

@@ -42,17 +42,15 @@
*
*/
#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"
@@ -91,7 +89,7 @@ udp_input(struct pbuf *p, struct netif *inp)
struct ip_hdr *iphdr;
u16_t src, dest;
#if SO_REUSE
#ifdef SO_REUSE
struct udp_pcb *pcb_temp;
int reuse = 0;
int reuse_port_1 = 0;
@@ -130,16 +128,16 @@ udp_input(struct pbuf *p, struct netif *inp)
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
#if SO_REUSE
#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) {
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) {
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
/* print the PCB local and remote address */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
@@ -160,8 +158,8 @@ udp_input(struct pbuf *p, struct netif *inp)
(ip_addr_isany(&pcb->local_ip) ||
/* PCB local IP address matches UDP destination IP address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
#if SO_REUSE
if (pcb->so_options & SOF_REUSEPORT) {
#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"));
@@ -175,7 +173,7 @@ udp_input(struct pbuf *p, struct netif *inp)
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if (reuse) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
@@ -189,14 +187,14 @@ udp_input(struct pbuf *p, struct netif *inp)
/* Iterate through the UDP PCB list for a pcb that matches
the local address. */
#if SO_REUSE
#ifdef SO_REUSE
pcb_temp = udp_pcbs;
again_2:
for (pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
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),
@@ -211,9 +209,9 @@ udp_input(struct pbuf *p, struct netif *inp)
(ip_addr_isany(&pcb->local_ip) ||
/* ...matching interface address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
#if SO_REUSE
if (pcb->so_options & SOF_REUSEPORT) {
if (reuse) {
#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 {
@@ -226,7 +224,7 @@ udp_input(struct pbuf *p, struct netif *inp)
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if (reuse) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
@@ -248,7 +246,6 @@ 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) {
@@ -259,9 +256,7 @@ 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),
@@ -275,13 +270,12 @@ 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);
#if SO_REUSE
#ifdef SO_REUSE
/* First socket should receive now */
if(reuse_port_1 || reuse_port_2) {
/* We want to search on next socket after receiving */
@@ -301,7 +295,7 @@ udp_input(struct pbuf *p, struct netif *inp)
}
#endif /* SO_REUSE */
} else {
#if SO_REUSE
#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);
@@ -311,10 +305,10 @@ udp_input(struct pbuf *p, struct netif *inp)
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) &&
!ip_addr_ismulticast(&iphdr->dest)) {
if (!ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) &&
!ip_addr_ismulticast(&iphdr->dest)) {
/* adjust pbuf pointer */
p->payload = iphdr;
@@ -332,47 +326,6 @@ 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.
*
@@ -382,9 +335,10 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
* @return lwIP error code.
* - ERR_OK. Successful. No error occured.
* - ERR_MEM. Out of memory.
* - ERR_RTE. Could not find route to destination address.
* - ERR_USE. The specified ipaddr and port are already bound to by
* another UDP PCB.
*
* @see udp_disconnect() udp_sendto()
* @see udp_disconnect()
*/
err_t
udp_send(struct udp_pcb *pcb, struct pbuf *p)
@@ -409,7 +363,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* not enough space to add an UDP header to first pbuf in given p chain? */
if (pbuf_header(p, UDP_HLEN)) {
/* allocate header in a seperate new pbuf */
/* allocate header in new pbuf */
q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
/* new header pbuf could not be allocated? */
if (q == NULL) {
@@ -421,27 +375,23 @@ 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);
/* in UDP, 0 checksum means 'no checksum' */
udphdr->chksum = 0x0000;
udphdr->chksum = 0x0000;
/* find the outgoing network interface for this packet */
netif = ip_route(&(pcb->remote_ip));
/* no outgoing network interface could be found? */
if (netif == NULL) {
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;
}
/* PCB local address is IP_ANY_ADDR? */
/* using IP_ANY_ADDR? */
if (ip_addr_isany(&pcb->local_ip)) {
/* use outgoing network interface IP address as source address */
src_ip = &(netif->ip_addr);
@@ -458,44 +408,34 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* 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);
/* UDP */
snmp_inc_udpoutdatagrams();
} else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\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;
}
#else
udphdr->chksum = 0x0000;
#endif
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04x\n", udphdr->chksum));
snmp_inc_udpoutdatagrams();
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 seperate header pbuf earlier? */
/* did we chain a header earlier? */
if (q != p) {
/* free the header pbuf */
pbuf_free(q); q = NULL;
/* { p is still referenced by the caller, and will live on } */
/* free the header */
/* p is also still referenced by the caller, and will live on */
pbuf_free(q);
}
UDP_STATS_INC(udp.xmit);
@@ -522,7 +462,7 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
u8_t rebind;
#if SO_REUSE
#ifdef SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
@@ -540,7 +480,7 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
rebind = 1;
}
#if SO_REUSE == 0
#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
@@ -594,7 +534,7 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
}
#if 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) {
@@ -707,10 +647,6 @@ 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;
}

View File

@@ -37,7 +37,6 @@
#include "lwip/opt.h"
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#define ICMP_ER 0 /* echo reply */

View File

@@ -46,7 +46,7 @@ u16_t inet_chksum_pseudo(struct pbuf *p,
u32_t inet_addr(const char *cp);
int inet_aton(const char *cp, struct in_addr *addr);
char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */
u8_t *inet_ntoa(u32_t addr); /* returns ptr to static buffer; not reentrant! */
#ifdef htons
#undef htons

View File

@@ -40,6 +40,7 @@
#include "lwip/err.h"
struct netif;
void ip_init(void);
struct netif *ip_route(struct ip_addr *dest);
@@ -127,7 +128,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) (ntohs((hdr)->_v_hl_tos) & 0xff)
#define IPH_TOS(hdr) (htons((ntohs((hdr)->_v_hl_tos) & 0xff)))
#define IPH_LEN(hdr) ((hdr)->_len)
#define IPH_ID(hdr) ((hdr)->_id)
#define IPH_OFFSET(hdr) ((hdr)->_offset)

View File

@@ -34,40 +34,6 @@
#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
*/
@@ -110,22 +76,33 @@ extern const struct ip_addr ip_addr_broadcast;
#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:\
(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 & \
((struct ip_addr *)src)->addr)
#define ip_addr_maskcmp(addr1, addr2, mask) (((addr1)->addr & \
(mask)->addr) == \
((addr2)->addr & \
(mask)->addr))
@@ -133,7 +110,10 @@ extern const struct ip_addr ip_addr_broadcast;
#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0)
u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
#define ip_addr_isbroadcast(addr1, mask) (((((addr1)->addr) & ~((mask)->addr)) == \
(0xffffffff & ~((mask)->addr))) || \
((addr1)->addr == 0xffffffff) || \
((addr1)->addr == 0x00000000))
#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))

View File

@@ -45,7 +45,7 @@ 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_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
int ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
struct ip_addr *mask);
int ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2);
void ip_addr_set(struct ip_addr *dest, struct ip_addr *src);

View File

@@ -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) && ((int)((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) && (((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)

View File

@@ -1,6 +1,38 @@
/** @file
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIP_DHCP_H__
#define __LWIP_DHCP_H__
@@ -43,10 +75,6 @@ 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) */
@@ -74,10 +102,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(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);
PACK_STRUCT_FIELD(u32_t ciaddr);
PACK_STRUCT_FIELD(u32_t yiaddr);
PACK_STRUCT_FIELD(u32_t siaddr);
PACK_STRUCT_FIELD(u32_t giaddr);
#define DHCP_CHADDR_LEN 16U
PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]);
#define DHCP_SNAME_LEN 64U
@@ -86,12 +114,8 @@ 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))
#if ((!defined(DHCP_OPTIONS_LEN)) || (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
/** set this to be sufficient for your options in outgoing DHCP msgs */
# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN
#endif
@@ -104,13 +128,11 @@ 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);
/** inform server of our manual IP address */
/** enforce lease renewal */
err_t dhcp_renew(struct netif *netif);
/** inform server of our IP address */
void dhcp_inform(struct netif *netif);
/** if enabled, check whether the offered IP address is not in use, using ARP */
@@ -184,8 +206,7 @@ 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_DNS_SERVER 6
#define DHCP_OPTION_ROUTER 3
#define DHCP_OPTION_HOSTNAME 12
#define DHCP_OPTION_IP_TTL 23
#define DHCP_OPTION_MTU 26

View File

@@ -59,7 +59,6 @@ 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

View File

@@ -40,9 +40,7 @@
#include "lwip/inet.h"
#include "lwip/pbuf.h"
#if LWIP_DHCP
# include "lwip/dhcp.h"
#endif
#include "lwip/dhcp.h"
/** must be the maximum of all used hardware address lengths
across all types of interfaces in use */
@@ -52,8 +50,7 @@
/** 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
@@ -62,36 +59,35 @@
/** if set, the interface is configured using DHCP */
#define NETIF_FLAG_DHCP 0x08U
/** if set, the interface has an active link
* (set by the network interface driver) */
* (set by the interface) */
#define NETIF_FLAG_LINK_UP 0x10U
/** 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 */
/** generic data structure used for all lwIP network interfaces */
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 */
@@ -103,14 +99,12 @@ struct netif {
unsigned char 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. */
@@ -143,8 +137,5 @@ 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__ */

View File

@@ -67,10 +67,6 @@ 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. */
@@ -146,10 +142,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. Defaults to 14 for Ethernet. */
link level header. */
#ifndef PBUF_LINK_HLEN
#define PBUF_LINK_HLEN 14
#define PBUF_LINK_HLEN 0
#endif
@@ -163,28 +159,26 @@ a lot of data that needs to be copied, this should be set high. */
/**
* If enabled, outgoing packets are queued during hardware address
* 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.
*
* resolution. The etharp.c implementation queues 1 packet only.
*/
#ifndef ARP_QUEUEING
#define ARP_QUEUEING 1
#endif
/* This option is deprecated */
#ifdef ETHARP_QUEUE_FIRST
#error ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h.
/** 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
#endif
/* 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.
/**
* 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
#endif
/* ---------- IP options ---------- */
@@ -224,10 +218,6 @@ 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
@@ -347,7 +337,7 @@ 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 0
# define SO_REUSE 1
#endif
@@ -358,10 +348,6 @@ 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
#endif
@@ -419,7 +405,6 @@ a lot of data that needs to be copied, this should be set high. */
#define PBUF_STATS 0
#define SYS_STATS 0
#define RAW_STATS 0
#define LWIP_STATS_DISPLAY 0
#endif /* LWIP_STATS */
@@ -510,31 +495,6 @@ 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 */

View File

@@ -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, see PBUF_FLAG_ */
/* flags telling the type of pbuf */
u16_t flags;
/**
@@ -94,6 +94,11 @@ 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);
@@ -107,7 +112,5 @@ 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__ */

View File

@@ -46,7 +46,7 @@ struct raw_pcb {
u16_t protocol;
u8_t (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
int (* 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,
u8_t (* recv)(void *arg, struct raw_pcb *pcb,
int (* recv)(void *arg, struct raw_pcb *pcb,
struct pbuf *p,
struct ip_addr *addr),
void *recv_arg);
err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr);
err_t raw_send_to (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. */
u8_t raw_input (struct pbuf *p, struct netif *inp);
int raw_input (struct pbuf *p, struct netif *inp);
void raw_init (void);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2001, 2002 Leon Woestenberg <leon.woestenberg@axon.tv>
* Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands.
* Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
* 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,

View File

@@ -205,20 +205,10 @@ 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

View File

@@ -144,13 +144,6 @@ 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__ */

View File

@@ -40,6 +40,8 @@
#include "lwip/ip.h"
#include "lwip/icmp.h"
#include "lwip/sys.h"
#include "lwip/err.h"
struct tcp_pcb;
@@ -105,7 +107,6 @@ 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);
@@ -113,11 +114,7 @@ void tcp_rexmit_rto (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
@@ -213,13 +210,18 @@ enum tcp_state {
TIME_WAIT = 10
};
/* the TCP protocol control block */
struct tcp_pcb {
/** common PCB members */
/* Common members of all PCB types */
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;
@@ -235,7 +237,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 variables */
/* receiver varables */
u32_t rcv_nxt; /* next seqno expected */
u16_t rcv_wnd; /* receiver window */
@@ -248,10 +250,10 @@ struct tcp_pcb {
u16_t mss; /* maximum segment size */
/* RTT (round trip time) estimation variables */
u32_t rttest; /* RTT estimate in 500ms ticks */
/* RTT estimation variables. */
u16_t rttest; /* RTT estimate in 500ms ticks */
u32_t rtseq; /* sequence number being timed */
s16_t sa, sv; /* @todo document this */
s16_t sa, sv;
u16_t rto; /* retransmission time-out */
u8_t nrtx; /* number of retransmissions */
@@ -375,7 +377,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 { \
if (p) pbuf_free(p); }
pbuf_free(p); }
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
if((pcb)->connected != NULL) \
(ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
@@ -387,7 +389,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
(errf)((arg),(err))
#endif /* LWIP_EVENT_API */
/* This structure represents a TCP segment on the unsent and unacked queues */
/* This structure is used to repressent TCP segments when queued. */
struct tcp_seg {
struct tcp_seg *next; /* used when putting segements on a queue */
struct pbuf *p; /* buffer containing data + TCP header */
@@ -455,11 +457,7 @@ void tcp_timer_needed(void);
#endif
/* The TCP PCB lists. */
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_listen *tcp_listen_pcbs; /* List of all TCP PCBs in LISTEN state. */
extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
state in which they accept or send
data. */

View File

@@ -84,12 +84,12 @@ 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. */
void udp_input (struct pbuf *p, struct netif *inp);
void udp_init (void);

View File

@@ -1,7 +1,5 @@
/*
* 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.
* 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,10 +33,6 @@
#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"
@@ -52,30 +46,15 @@ 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 {
@@ -85,42 +64,35 @@ 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_addr2 sipaddr);
PACK_STRUCT_FIELD(struct ip_addr sipaddr);
PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
PACK_STRUCT_FIELD(struct ip_addr2 dipaddr);
PACK_STRUCT_FIELD(struct ip_addr dipaddr);
} 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 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 ARP_TMR_INTERVAL 10000
#define ETHTYPE_ARP 0x0806
#define ETHTYPE_IP 0x0800
void etharp_init(void);
void etharp_tmr(void);
void etharp_ip_input(struct netif *netif, struct pbuf *p);
void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
struct pbuf *etharp_ip_input(struct netif *netif, struct pbuf *p);
struct pbuf *etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
struct pbuf *p);
err_t etharp_output(struct netif *netif, struct ip_addr *ipaddr,
struct pbuf *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__ */

View File

@@ -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

View File

@@ -1,18 +1,17 @@
This directory contains generic network interface device drivers that
do not contain any hardware or architecture specific code. The files
don't contain any hardware or architecture specific code. The files
are:
etharp.c
Implements the ARP (Address Resolution Protocol) over
Ethernet. The code in this file should be used together with
Ethernet device drivers. Note that this module has been
largely made Ethernet independent so you should be able to
adapt this for other link layers (such as Firewire).
Ethernet device drivers.
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"

File diff suppressed because it is too large Load Diff

View File

@@ -35,6 +35,8 @@
* 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"
@@ -42,13 +44,12 @@
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include <lwip/stats.h>
#include "netif/etharp.h"
#include "netif/arp.h"
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 'n'
#define IFNAME1 't'
struct ethernetif {
struct eth_addr *ethaddr;
@@ -62,10 +63,13 @@ 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 = netif->state;
struct ethernetif *ethernetif;
ethernetif = netif->state;
/* set MAC hardware address length */
netif->hwaddr_len = 6;
@@ -73,7 +77,7 @@ low_level_init(struct netif *netif)
/* set MAC hardware address */
netif->hwaddr[0] = ;
...
netif->hwaddr[5] = ;
netif->hwaddr[6] = ;
/* maximum transfer unit */
netif->mtu = 1500;
@@ -93,18 +97,14 @@ low_level_init(struct netif *netif)
*
*/
static err_t
low_level_output(struct netif *netif, struct pbuf *p)
low_level_output(struct ethernetif *ethernetif, 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,12 +113,8 @@ low_level_output(struct netif *netif, struct pbuf *p)
}
signal that packet should be sent();
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
#if LINK_STATS
#ifdef LINK_STATS
lwip_stats.link.xmit++;
#endif /* LINK_STATS */
@@ -134,9 +130,8 @@ low_level_output(struct netif *netif, struct pbuf *p)
*/
static struct pbuf *
low_level_input(struct netif *netif)
low_level_input(struct ethernetif *ethernetif)
{
struct ethernetif *ethernetif = netif->state;
struct pbuf *p, *q;
u16_t len;
@@ -144,39 +139,25 @@ low_level_input(struct netif *netif)
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();
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
#if LINK_STATS
#ifdef LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
} else {
drop packet();
#if LINK_STATS
#ifdef LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif /* LINK_STATS */
@@ -190,7 +171,7 @@ low_level_input(struct netif *netif)
*
* 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 actual transmission of the packet.
* do the actuall transmission of the packet.
*
*/
@@ -198,10 +179,90 @@ 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;
/* resolve hardware address, then send (or queue) packet */
return etharp_output(netif, ipaddr, p);
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 *)&ethbroadcast;
} 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);
}
/*
@@ -221,47 +282,43 @@ ethernetif_input(struct netif *netif)
struct eth_hdr *ethhdr;
struct pbuf *p;
ethernetif = netif->state;
/* 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;
p = low_level_input(ethernetif);
#if LINK_STATS
lwip_stats.link.recv++;
if (p != NULL) {
#ifdef LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
ethhdr = p->payload;
ethhdr = p->payload;
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;
switch (htons(ethhdr->type)) {
case ETHTYPE_IP:
arp_ip_input(netif, p);
pbuf_header(p, -14);
netif->input(p, netif);
break;
case ETHTYPE_ARP:
/* pass p to ARP module */
etharp_arp_input(netif, ethernetif->ethaddr, p);
p = arp_arp_input(netif, ethernetif->ethaddr, p);
if (p != NULL) {
low_level_output(ethernetif, p);
pbuf_free(p);
}
break;
default:
pbuf_free(p);
p = NULL;
break;
}
}
}
static void
arp_timer(void *arg)
{
etharp_tmr();
arp_tmr();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
}
@@ -274,19 +331,12 @@ arp_timer(void *arg)
*
*/
err_t
void
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;
@@ -296,11 +346,8 @@ ethernetif_init(struct netif *netif)
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
low_level_init(netif);
etharp_init();
arp_init();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
return ERR_OK;
}

View File

@@ -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.3 2004/02/07 00:30:03 likewise Exp $
* $Id: chpms.h,v 1.1.6.1 2003/09/02 12:00:48 jani Exp $
*/
#ifndef CHPMS_H

View File

@@ -49,8 +49,6 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <string.h>
#include "ppp.h"
#if PPP_SUPPORT > 0
#include "auth.h"
@@ -180,20 +178,6 @@ 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.
*/

View File

@@ -49,9 +49,6 @@
* 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"

View File

@@ -78,9 +78,6 @@
* 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"
@@ -1236,7 +1233,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(1); /* give other tasks a chance to run */
sys_msleep(250); /* give other tasks a chance to run */
}
}
}

View File

@@ -28,12 +28,11 @@
* for a 16 bit processor.
*/
#include <string.h>
#include "ppp.h"
#include "vj.h"
#include "pppdebug.h"
#if VJ_SUPPORT > 0
#if LINK_STATS

View File

@@ -1,7 +1,7 @@
/*
* Definitions for tcp compression routines.
*
* $Id: vj.h,v 1.4 2004/02/07 00:30:03 likewise Exp $
* $Id: vj.h,v 1.2.6.1 2003/10/28 11:44:45 jani Exp $
*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved.

View File

@@ -199,7 +199,6 @@ slipif_init(struct netif *netif)
netif->name[1] = 'l';
netif->output = slipif_output;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_POINTTOPOINT;
netif->state = sio_open(netif->num);
if (!netif->state)