Compare commits

..

29 Commits

Author SHA1 Message Date
likewise
a552a9993e Fixed the variable types in inet_ntoa() to comply with API change. 2004-04-26 13:15:26 +00:00
likewise
a74a801f35 Removed the forward declaration of netif. 2004-04-26 13:03:36 +00:00
likewise
7eae414a2f Prepare for 0.7.2 release. Mention 0.7.2 in the Changelog before tagging STABLE-0_7_2. 2004-04-26 10:56:23 +00:00
likewise
84be06c4da Mention the merged fixed from HEAD. 2004-04-23 16:51:13 +00:00
likewise
0912877fd7 Several fixed from HEAD merged in. 2004-04-23 16:16:48 +00:00
likewise
52dd00b217 Removed ip_lookup() like in HEAD. 2004-04-23 15:49:42 +00:00
likewise
2eab21d3cf Set point-to-point flag on SLIP (merged from HEAD). 2004-04-23 15:46:29 +00:00
likewise
a5ce8ca555 Important fix from HEAD merged. 2004-04-23 15:45:53 +00:00
likewise
2c02689d5c Updated with current API (merged from HEAD). 2004-04-23 15:45:15 +00:00
likewise
a52d3548a0 Merged listen_pcb union fix from HEAD. 2004-04-23 15:43:44 +00:00
likewise
3cf8dfa55e Indentation white space fix from HEAD. 2004-04-23 15:42:21 +00:00
likewise
0be1bad42f Merged stats_display_*() fucntions from HEAD. 2004-04-23 15:41:22 +00:00
likewise
d995bc01b3 Removed ip_lookup() like in HEAD. 2004-04-23 15:40:25 +00:00
likewise
d95256817e Merged several cast fixes from HEAD. 2004-04-23 15:38:42 +00:00
likewise
d7c6590b8f Merged udp_sendto() from HEAD. 2004-04-23 15:36:17 +00:00
likewise
70128cf2b9 Mentioned the merge from HEAD. 2004-04-23 15:24:08 +00:00
likewise
a94db2ed71 Merged updated documentation from HEAD. 2004-04-23 15:18:49 +00:00
likewise
a0f45e9d27 Fixed documentation. Updated copyright years. 2004-04-23 15:12:25 +00:00
likewise
31c58725ce Fixed cast in memp_alloc(). Updated copyright years. 2004-04-23 15:11:53 +00:00
likewise
95ac72a0f2 #if LWIP_DHCP fix. 2004-04-23 15:09:24 +00:00
likewise
13386978a1 Updated copyright years. 2004-04-23 15:08:12 +00:00
likewise
95e738a955 #ifdef SO_REUSE to #if SO_REUSE. Updated copyright years. 2004-04-23 14:53:18 +00:00
likewise
3efda64604 Mentioned SO_REUSE #if fix. 2004-03-23 00:40:15 +00:00
likewise
98f546664e Made #ifdef's into #if's for SO_REUSE. 2004-03-23 00:32:36 +00:00
likewise
4e44c2b993 Added missing #if LWIP_DHCP #endif pair. 2004-03-11 19:23:07 +00:00
likewise
30fde02666 Mentioned another ARP fix and named this 0.7.1 for release. 2004-02-05 19:15:24 +00:00
likewise
100eaa9855 Removed updating ARP cache using destination address (which is wrong for requests and replies are unicast anyway). 2004-02-05 19:13:33 +00:00
likewise
3d287a950f Mention ARP fix. 2004-02-05 18:31:57 +00:00
likewise
3aa6a385da Was updating ARP cache from a re-cycled ARP reply pbuf in some cases. Fixed.
Reported on lwip-users by Stephen Chen on february 4th 2004.
2004-02-05 18:29:08 +00:00
60 changed files with 2376 additions and 2855 deletions

188
CHANGELOG
View File

@@ -2,185 +2,39 @@ FUTURE
* TODO: The lwIP source code makes some invalid assumptions on processor
word-length, storage sizes and alignment. See the mailing lists for
problems with exoteric (/DSP) architectures showing these problems.
We still have to fix some of these issues neatly.
* TODO: the ARP layer is not protected against concurrent access. If
you run from a multitasking OS, serialize access to ARP (called from
your network device driver and from a timeout thread.)
* TODO: the PPP code is broken in a few ways. There are namespace
collisions on BSD systems and many assumptions on word-length
(sizeof(int)). In ppp.c an assumption is made on the availability of
a thread subsystem. Either PPP needs to be moved to contrib/ports/???
or rearranged to be more generic.
problems with exoteric architectures showing these problems.
Neat fixes are needed.
HISTORY
(CVS HEAD)
(STABLE-0_7 branch)
* [New changes go here]
(STABLE-1_1_1)
2006-03-03 Christiaan Simons
* ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap
access and added pbuf_alloc() return value checks.
2006-01-01 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is
now handled by the checksum routine properly.
2006-02-27 Leon Woestenberg <leon.woestenberg@gmx.net>
* pbuf.c: Fix alignment; pbuf_init() would not work unless
pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.)
2005-12-20 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch
submitted by Mitrani Hiroshi.
2005-12-15 Christiaan Simons
* inet.c: Disabled the added summing routine to preserve code space.
2005-12-14 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson.
Added Curt McDowell's optimized checksumming routine for future
inclusion. Need to create test case for unaliged, aligned, odd,
even length combination of cases on various endianess machines.
2005-12-09 Christiaan Simons
* inet.c: Rewrote standard checksum routine in proper portable C.
2005-11-25 Christiaan Simons
* udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only.
* *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t,
u32_t, s32_t typedefs. This solves most debug word-length assumes.
2005-07-17 Leon Woestenberg <leon.woestenberg@gmx.net>
* inet.c: Fixed unaligned 16-bit access in the standard checksum
routine by Peter Jolasson.
* slipif.c: Fixed implementation assumption of single-pbuf datagrams.
2005-02-04 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch.
* tcp_{out|in}.c: Applied patch fixing unaligned access.
2005-01-04 Leon Woestenberg <leon.woestenberg@gmx.net>
* pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement.
2005-01-03 Leon Woestenberg <leon.woestenberg@gmx.net>
* udp.c: UDP pcb->recv() was called even when it was NULL.
(STABLE-1_1_0)
2004-12-28 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.*: Disabled multiple packets on the ARP queue.
This clashes with TCP queueing.
2004-11-28 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.*: Fixed race condition from ARP request to ARP timeout.
Halved the ARP period, doubled the period counts.
ETHARP_MAX_PENDING now should be at least 2. This prevents
the counter from reaching 0 right away (which would allow
too little time for ARP responses to be received).
2004-11-25 Leon Woestenberg <leon.woestenberg@gmx.net>
* dhcp.c: Decline messages were not multicast but unicast.
* etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD.
Do not try hard to insert arbitrary packet's source address,
etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD.
etharp_query() now always DOES call ETHARP_TRY_HARD so that users
querying an address will see it appear in the cache (DHCP could
suffer from this when a server invalidly gave an in-use address.)
* ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are
comparing network addresses (identifiers), not the network masks
themselves.
* ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given
IP address actually belongs to the network of the given interface.
2004-11-24 Kieran Mansley <kjm25@cam.ac.uk>
* tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state.
(STABLE-1_1_0-RC1)
2004-10-16 Kieran Mansley <kjm25@cam.ac.uk>
* tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately,
even if one is already pending, if the rcv_wnd is above a threshold
(currently TCP_WND/2). This avoids waiting for a timer to expire to send a
delayed ACK in order to open the window if the stack is only receiving data.
2004-09-12 Kieran Mansley <kjm25@cam.ac.uk>
* tcp*.*: Retransmit time-out handling improvement by Sam Jansen.
2004-08-20 Tony Mountifield <tony@softins.co.uk>
* etharp.c: Make sure the first pbuf queued on an ARP entry
is properly ref counted.
2004-07-27 Tony Mountifield <tony@softins.co.uk>
* debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler
warnings about comparison.
* pbuf.c: Stopped compiler complaining of empty if statement
when LWIP_DEBUGF() empty. Closed an unclosed comment.
* tcp.c: Stopped compiler complaining of empty if statement
when LWIP_DEBUGF() empty.
* ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons().
* inet.c: Added a couple of casts to quiet the compiler.
No need to test isascii(c) before isdigit(c) or isxdigit(c).
2004-07-22 Tony Mountifield <tony@softins.co.uk>
* inet.c: Made data types consistent in inet_ntoa().
Added casts for return values of checksum routines, to pacify compiler.
* ip_frag.c, tcp_out.c, sockets.c, pbuf.c
Small corrections to some debugging statements, to pacify compiler.
2004-07-21 Tony Mountifield <tony@softins.co.uk>
* etharp.c: Removed spurious semicolon and added missing end-of-comment.
* ethernetif.c Updated low_level_output() to match prototype for
netif->linkoutput and changed low_level_input() similarly for consistency.
* api_msg.c: Changed recv_raw() from int to u8_t, to match prototype
of raw_recv() in raw.h and so avoid compiler error.
* sockets.c: Added trivial (int) cast to keep compiler happier.
* ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros.
(STABLE-1_0_0)
++ Changes:
2004-07-05 Leon Woestenberg <leon.woestenberg@gmx.net>
* sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure
your cc.h file defines this either 1 or 0. If non-defined,
defaults to 1.
* .c: Added <string.h> and <errno.h> includes where used.
* etharp.c: Made some array indices unsigned.
2004-06-27 Leon Woestenberg <leon.woestenberg@gmx.net>
* netif.*: Added netif_set_up()/down().
* dhcp.c: Changes to restart program flow.
2004-05-07 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.c: In find_entry(), instead of a list traversal per candidate, do a
single-pass lookup for different candidates. Should exploit locality.
2004-04-29 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp*.c: Cleaned up source comment documentation for Doxygen processing.
* opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC.
* etharp.c: update_arp_entry() only adds new ARP entries when adviced to by
the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option.
(STABLE-0_7_2)
++ 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.
* memp.c: Fixed cast in mem_malloc().
* sockets.c, tcp_in.c, udp.c: #ifdef SO_REUSE now #if SO_REUSE.
* dhcp.c: #if LWIP_DHCP fixed.
* 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.
2004-03-23 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp.c: #ifdef SO_REUSE now #if SO_REUSE.
2004-03-11 Leon Woestenberg <leon.woestenberg@gmx.net>
* dhcp.c: Added missing #if LWIP_DHCP #endif pair.
(STABLE-0_7_1)
++ Bug fixes:
* Fixed updating the ARP cache from a request pbuf that was recycled earlier for reply.
* Removed updating ARP cache using destination address (which is wrong for requests and
does not work for replies as those are unicast anyway).
(STABLE-0_7_0)

26
README
View File

@@ -7,7 +7,7 @@ Science (SICS).
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
while still having a full scale TCP. This making lwIP suitable for use
in embedded systems with tens of kilobytes of free RAM and room for
in embedded systems with tenths of kilobytes of free RAM and room for
around 40 kilobytes of code ROM.
FEATURES
@@ -42,11 +42,29 @@ CVS source tree.
The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and
contributions (such as platform ports) are in the 'contrib' module.
See doc/savannah.txt for details on CVS server access for users and
developers.
The CVS main trunk is the stable branch, which contains bug fixes and
tested features. The latest stable branch can be checked out by doing:
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co lwip
The 'STABLE' tag in the stable branch will represent the most stable
revision (which may be somewhat older to protect us from errors
introduced by merges). This 'STABLE' tagged version can be checked out
by doing:
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co -r STABLE lwip
The 'DEVEL' branch is the active development branch, which contains
bleeding edge changes, and may be instable. It can be checkout by doing:
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co -r DEVEL lwip
The current contrib CVS tree can be checked out by doing:
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co contrib
Last night's CVS tar ball can be downloaded from:
http://savannah.gnu.org/cvs.backups/lwip.tar.gz [CHANGED - NEEDS FIXING]
http://savannah.gnu.org/cvs.backups/lwip.tar.gz
The current CVS trees are web-browsable:
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/

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, Christiaan Simons
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
@@ -289,98 +289,4 @@ level of complexity of UDP, the interface is significantly simpler.
void *recv_arg)
Specifies a callback function that should be called when a UDP
datagram is received.
--- System initalization
A truly complete and generic sequence for initializing the lwip stack
cannot be given because it depends on the build configuration (lwipopts.h)
and additional initializations for your runtime environment (e.g. timers).
We can give you some idea on how to proceed when using the raw API.
We assume a configuration using a single Ethernet netif and the
UDP and TCP transport layers, IPv4 and the DHCP client.
Call these functions in the order of appearance:
- stats_init()
Clears the structure where runtime statistics are gathered.
- sys_init()
Not of much use since we set the NO_SYS 1 option in lwipopts.h,
to be called for easy configuration changes.
- mem_init()
Initializes the dynamic memory heap defined by MEM_SIZE.
- memp_init()
Initializes the memory pools defined by MEMP_NUM_x.
- pbuf_init()
Initializes the pbuf memory pool defined by PBUF_POOL_SIZE.
- etharp_init()
Initializes the ARP table and queue.
Note: you must call etharp_tmr at a 10 second regular interval
after this initialization.
- ip_init()
Doesn't do much, it should be called to handle future changes.
- udp_init()
Clears the UDP PCB list.
- tcp_init()
Clears the TCP PCB list and clears some internal TCP timers.
Note: you must call tcp_fasttmr() and tcp_slowtmr() at the
predefined regular intervals after this initialization.
- netif_add(struct netif *netif, struct ip_addr *ipaddr,
struct ip_addr *netmask, struct ip_addr *gw,
void *state, err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif))
Adds your network interface to the netif_list. Allocate a struct
netif and pass a pointer to this structure as the first argument.
Give pointers to cleared ip_addr structures when using DHCP,
or fill them with sane numbers otherwise. The state pointer may be NULL.
The init function pointer must point to a initialization function for
your ethernet netif interface. The following code illustrates it's use.
err_t netif_if_init(struct netif *netif)
{
u8_t i;
for(i = 0; i < 6; i++) netif->hwaddr[i] = some_eth_addr[i];
init_my_eth_device();
return ERR_OK;
}
The input function pointer must point to the lwip ip_input().
- netif_set_default(struct netif *netif)
Registers the default network interface.
- netif_set_up(struct netif *netif)
When the netif is fully configured this function must be called.
- dhcp_start(struct netif *netif)
Creates a new DHCP client for this interface on the first call.
Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at
the predefined regular intervals after starting the client.
You can peek in the netif->dhcp struct for the actual DHCP status.
datagram is received.

View File

@@ -15,15 +15,20 @@ Table of Contents:
To perform an anonymous CVS checkout of the main trunk (this is where
bug fixes and incremental enhancements occur), do this:
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout lwip
export CVS_RSH=ssh
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip
(If SSH asks about authenticity of the host, you can check the key
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
Or, obtain a stable branch (updated with bug fixes only) as follows:
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
-r STABLE-0_7 -d lwip-0.7 lwip
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_7 -d lwip-0.7 lwip
Or, obtain a specific (fixed) release as follows:
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
-r STABLE-0_7_0 -d lwip-0.7.0 lwip
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_7_0 -d lwip-0.7.0 lwip
Or, obtain a development branch (considered unstable!) as follows:
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-DEVEL lwip
3 Committers/developers CVS access using SSH
--------------------------------------------
@@ -42,7 +47,7 @@ a while so that Savannah can update its configuration (This can take minutes).
Try to login using SSH:
ssh -v your_login@cvs.sv.gnu.org
ssh -v your_login@subversions.gnu.org
If it tells you:
@@ -53,16 +58,12 @@ 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 -z3 -d:ext:your_login@cvs.sv.gnu.org:/sources/lwip co lwip
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.
(If SSH asks about authenticity of the host, you can check the key
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
3 Merging from DEVEL branch to main trunk (stable)
--------------------------------------------------
@@ -106,25 +107,46 @@ tagged tree. Export is similar to a checkout, except that the CVS metadata
is not created locally.
export CVS_RSH=ssh
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
-r STABLE-0_6_3 -d lwip-0.6.3 lwip
cvs -d:ext: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

@@ -165,7 +165,7 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
offset -= p->len;
} else {
for(i = offset; i < p->len; ++i) {
((u8_t *)dataptr)[left] = ((u8_t *)p->payload)[i];
((char *)dataptr)[left] = ((char *)p->payload)[i];
if (++left >= len) {
return;
}
@@ -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);
@@ -673,7 +672,7 @@ netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
if (conn->err == ERR_OK) {
dataptr = (void *)((u8_t *)dataptr + len);
dataptr = (void *)((char *)dataptr + len);
size -= len;
} else if (conn->err == ERR_MEM) {
conn->err = ERR_OK;

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"
@@ -87,12 +84,9 @@ static int err_to_errno_table[11] = {
EADDRINUSE /* ERR_USE -10 Address in use. */
};
#define ERR_TO_ERRNO_TABLE_SIZE \
(sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
#define err_to_errno(err) \
(-(err) >= 0 && -(err) < ERR_TO_ERRNO_TABLE_SIZE ? \
err_to_errno_table[-(err)] : EIO)
((err) < (sizeof(err_to_errno_table)/sizeof(int))) ? \
err_to_errno_table[-(err)] : EIO
#ifdef ERRNO
#define set_errno(err) errno = (err)
@@ -421,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);
@@ -1144,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 */
@@ -1312,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

@@ -38,7 +38,6 @@
#include "lwip/pbuf.h"
#include "lwip/ip.h"
#include "lwip/ip_frag.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
@@ -47,51 +46,34 @@
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 */
#if IP_REASSEMBLY
static void
ip_timer(void *data)
{
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
ip_reass_tmr();
sys_timeout(1000, ip_timer, NULL);
}
#endif
static void
tcpip_thread(void *arg)
{
@@ -105,9 +87,6 @@ tcpip_thread(void *arg)
#endif
#if LWIP_TCP
tcp_init();
#endif
#if IP_REASSEMBLY
sys_timeout(1000, ip_timer, NULL);
#endif
if (tcpip_init_done != NULL) {
tcpip_init_done(tcpip_init_done_arg);

View File

@@ -67,9 +67,6 @@
* to remove the DHCP client.
*
*/
#include <string.h>
#include "lwip/stats.h"
#include "lwip/mem.h"
#include "lwip/udp.h"
@@ -85,8 +82,7 @@
#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,7 +96,8 @@ 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 void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
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 */
static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
@@ -144,10 +141,10 @@ static void dhcp_option_trailer(struct dhcp *dhcp);
static void dhcp_handle_nak(struct netif *netif) {
struct dhcp *dhcp = netif->dhcp;
u16_t msecs = 10 * 1000;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%u\n", netif,
netif->name[0], netif->name[1], (unsigned int)netif->num));
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_handle_nak(): set request timeout %"U16_F" msecs\n", msecs));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_handle_nak(): set request timeout %u msecs\n", msecs));
dhcp_set_state(dhcp, DHCP_BACKING_OFF);
}
@@ -163,8 +160,8 @@ static void dhcp_check(struct netif *netif)
struct dhcp *dhcp = netif->dhcp;
err_t result;
u16_t msecs;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
(s16_t)netif->name[1]));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (unsigned int)netif->name[0],
(unsigned int)netif->name[1]));
/* create an ARP query for the offered IP address, expecting that no host
responds, as the IP address should not be in use. */
result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
@@ -174,7 +171,7 @@ static void dhcp_check(struct netif *netif)
dhcp->tries++;
msecs = 500;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_check(): set request timeout %u msecs\n", msecs));
dhcp_set_state(dhcp, DHCP_CHECKING);
}
@@ -188,15 +185,15 @@ static void dhcp_handle_offer(struct netif *netif)
struct dhcp *dhcp = netif->dhcp;
/* obtain the server address */
u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%u\n", netif,
netif->name[0], netif->name[1], netif->num));
if (option_ptr != NULL)
{
dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", dhcp->server_ip_addr.addr));
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): server 0x%08lx\n", dhcp->server_ip_addr.addr));
/* remember offered address */
ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08lx\n", dhcp->offered_ip_addr.addr));
dhcp_select(netif);
}
@@ -215,7 +212,7 @@ static err_t dhcp_select(struct netif *netif)
struct dhcp *dhcp = netif->dhcp;
err_t result;
u32_t msecs;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
/* create and initialize the DHCP message header */
result = dhcp_create_request(netif);
@@ -234,11 +231,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 */
@@ -261,7 +257,7 @@ static err_t dhcp_select(struct netif *netif)
dhcp->tries++;
msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_select(): set request timeout %"U32_F" msecs\n", msecs));
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_select(): set request timeout %u msecs\n", msecs));
return result;
}
@@ -297,20 +293,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 +383,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 +406,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 +480,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)]));
}
}
}
/**
@@ -519,44 +501,40 @@ err_t dhcp_start(struct netif *netif)
err_t result = ERR_OK;
LWIP_ASSERT("netif != NULL", netif != NULL);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
netif->flags &= ~NETIF_FLAG_DHCP;
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));
/* 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;
}
@@ -633,11 +611,10 @@ void dhcp_inform(struct netif *netif)
*/
void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
{
LWIP_ASSERT("netif != NULL", netif != NULL);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
/* is a DHCP client doing an ARP check? */
/* is this DHCP client doing an ARP check? */
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", addr->addr));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx\n", addr->addr));
/* did a host respond with the address we
were offered by the DHCP server? */
if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
@@ -680,10 +657,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 {
@@ -692,7 +667,7 @@ static err_t dhcp_decline(struct netif *netif)
dhcp->tries++;
msecs = 10*1000;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_decline(): set request timeout %u msecs\n", msecs));
return result;
}
#endif
@@ -720,11 +695,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);
@@ -747,7 +721,7 @@ static err_t dhcp_discover(struct netif *netif)
dhcp->tries++;
msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover(): set request timeout %u msecs\n", msecs));
return result;
}
@@ -763,22 +737,22 @@ static void dhcp_bind(struct netif *netif)
struct ip_addr sn_mask, gw_addr;
LWIP_ASSERT("dhcp_bind: netif != NULL", netif != NULL);
LWIP_ASSERT("dhcp_bind: dhcp != NULL", dhcp != NULL);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
/* temporary DHCP lease? */
if (dhcp->offered_t1_renew != 0xffffffffUL) {
/* set renewal period timer */
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t1 renewal timer %lu secs\n", dhcp->offered_t1_renew));
dhcp->t1_timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
if (dhcp->t1_timeout == 0) dhcp->t1_timeout = 1;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t1_renew*1000));
}
/* set renewal period timer */
if (dhcp->offered_t2_rebind != 0xffffffffUL) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t2 rebind timer %lu secs\n", dhcp->offered_t2_rebind));
dhcp->t2_timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
if (dhcp->t2_timeout == 0) dhcp->t2_timeout = 1;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t2_rebind*1000));
}
/* copy offered network mask */
ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
@@ -802,14 +776,12 @@ static void dhcp_bind(struct netif *netif)
gw_addr.addr |= htonl(0x00000001);
}
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): IP: 0x%08lx\n", dhcp->offered_ip_addr.addr));
netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", sn_mask.addr));
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): SN: 0x%08lx\n", sn_mask.addr));
netif_set_netmask(netif, &sn_mask);
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", gw_addr.addr));
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);
}
@@ -865,7 +837,7 @@ err_t dhcp_renew(struct netif *netif)
/* back-off on retries, but to a maximum of 20 seconds */
msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew(): set request timeout %u msecs\n", msecs));
return result;
}
@@ -918,7 +890,7 @@ static err_t dhcp_rebind(struct netif *netif)
dhcp->tries++;
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind(): set request timeout %u msecs\n", msecs));
return result;
}
@@ -927,7 +899,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;
@@ -936,13 +908,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) {
@@ -964,14 +931,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 %"U16_F" 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;
}
@@ -1013,7 +977,7 @@ void dhcp_stop(struct netif *netif)
*
* TODO: we might also want to reset the timeout here?
*/
static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state)
{
if (new_state != dhcp->state)
{
@@ -1109,7 +1073,7 @@ static err_t dhcp_unfold_reply(struct dhcp *dhcp)
j = 0;
}
}
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes into dhcp->msg_in[]\n", i));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes into dhcp->msg_in[]\n", i));
if (dhcp->options_in != NULL) {
ptr = (u8_t *)dhcp->options_in;
/* proceed through options */
@@ -1122,7 +1086,7 @@ static err_t dhcp_unfold_reply(struct dhcp *dhcp)
j = 0;
}
}
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes to dhcp->options_in[]\n", i));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes to dhcp->options_in[]\n", i));
}
return ERR_OK;
}
@@ -1158,17 +1122,17 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
u8_t *options_ptr;
u8_t msg_type;
u8_t i;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
(u16_t)(ntohl(addr->addr) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff),
(u16_t)(ntohl(addr->addr) >> 8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %u.%u.%u.%u port %u\n", p,
(unsigned int)(ntohl(addr->addr) >> 24 & 0xff), (unsigned int)(ntohl(addr->addr) >> 16 & 0xff),
(unsigned int)(ntohl(addr->addr) >> 8 & 0xff), (unsigned int)(ntohl(addr->addr) & 0xff), port));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %u\n", p->len));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %u\n", p->tot_len));
/* prevent warnings about unused arguments */
(void)pcb; (void)addr; (void)port;
dhcp->p = p;
/* TODO: check packet length before reading them */
if (reply_msg->op != DHCP_BOOTREPLY) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("not a DHCP reply message, but type %u\n", reply_msg->op));
pbuf_free(p);
dhcp->p = NULL;
return;
@@ -1176,8 +1140,8 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
/* iterate through hardware address and match against DHCP message */
for (i = 0; i < netif->hwaddr_len; i++) {
if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
(u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%u]==%02x != reply_msg->chaddr[%u]==%02x\n",
i, netif->hwaddr[i], i, reply_msg->chaddr[i]));
pbuf_free(p);
dhcp->p = NULL;
return;
@@ -1276,10 +1240,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*/;
@@ -1317,7 +1281,7 @@ static void dhcp_option_trailer(struct dhcp *dhcp)
dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
/* packet is too small, or not 4 byte aligned? */
while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
/* LWIP_DEBUGF(DHCP_DEBUG,("dhcp_option_trailer:dhcp->options_out_len=%"U16_F", DHCP_OPTIONS_LEN=%"U16_F, dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
/* LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_option_trailer: dhcp->options_out_len=%u, DHCP_OPTIONS_LEN=%u", dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
/* add a fill/padding byte */
dhcp->msg_out->options[dhcp->options_out_len++] = 0;
@@ -1344,7 +1308,7 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
u16_t offset = 0;
/* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
/* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
/* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%u, q->len=%u", msg_offset, q->len)); */
/* are the sname and/or file field overloaded with options? */
if (options[offset] == DHCP_OPTION_OVERLOAD) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("overloaded message detected\n"));
@@ -1354,11 +1318,11 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
}
/* requested option found */
else if (options[offset] == option_type) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset %"U16_F" in options\n", offset));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset %u in options\n", offset));
return &options[offset];
/* skip option */
} else {
LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", options[offset]));
LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %u in options\n", options[offset]));
/* skip option type */
offset++;
/* skip option length, and then length bytes */
@@ -1387,11 +1351,11 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
/* at least 1 byte to read and no end marker */
while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
if (options[offset] == option_type) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset=%"U16_F"\n", offset));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset=%u\n", offset));
return &options[offset];
/* skip option */
} else {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("skipping option %"U16_F"\n", options[offset]));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("skipping option %u\n", options[offset]));
/* skip option type */
offset++;
offset += 1 + options[offset];
@@ -1412,7 +1376,7 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
*/
static u8_t dhcp_get_option_byte(u8_t *ptr)
{
LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%"U16_F"\n", (u16_t)(*ptr)));
LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%u\n", *ptr));
return *ptr;
}
@@ -1429,7 +1393,7 @@ static u16_t dhcp_get_option_short(u8_t *ptr)
u16_t value;
value = *ptr++ << 8;
value |= *ptr;
LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%"U16_F"\n", value));
LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%u\n", value));
return value;
}
@@ -1448,7 +1412,7 @@ static u32_t dhcp_get_option_long(u8_t *ptr)
value |= (u32_t)(*ptr++) << 16;
value |= (u32_t)(*ptr++) << 8;
value |= (u32_t)(*ptr++);
LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%"U32_F"\n", value));
LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%lu\n", value));
return value;
}

View File

@@ -46,195 +46,36 @@
#include "lwip/def.h"
#include "lwip/inet.h"
#include "lwip/sys.h"
/* This is a reference implementation of the checksum algorithm, with the
* aim of being simple, correct and fully portable. Checksumming is the
* first thing you would want to optimize for your platform. You will
* need to port it to your architecture and in your sys_arch.h:
*
* #define LWIP_CHKSUM <your_checksum_routine>
*/
#ifndef LWIP_CHKSUM
#define LWIP_CHKSUM lwip_standard_chksum
/**
* lwip checksum
*
* @param dataptr points to start of data to be summed at any boundary
* @param len length of data to be summed
* @return host order (!) lwip checksum (non-inverted Internet sum)
*
* @note accumulator size limits summable lenght to 64k
* @note host endianess is irrelevant (p3 RFC1071)
*/
static u16_t
lwip_standard_chksum(void *dataptr, u16_t len)
lwip_chksum(void *dataptr, int len)
{
u32_t acc;
u16_t src;
u8_t *octetptr;
acc = 0;
/* dataptr may be at odd or even addresses */
octetptr = (u8_t*)dataptr;
while (len > 1)
{
/* declare first octet as most significant
thus assume network order, ignoring host order */
src = (*octetptr) << 8;
octetptr++;
/* declare second octet as least significant */
src |= (*octetptr);
octetptr++;
acc += src;
len -= 2;
LWIP_DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %d)\n", (void *)dataptr, len));
for(acc = 0; len > 1; len -= 2) {
/* acc = acc + *((u16_t *)dataptr)++;*/
acc += *(u16_t *)dataptr;
dataptr = (void *)((u16_t *)dataptr + 1);
}
if (len > 0)
{
/* accumulate remaining octet */
src = (*octetptr) << 8;
acc += src;
/* add up any odd byte */
if (len == 1) {
acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8);
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", (unsigned int)(*(u8_t *)dataptr)));
} else {
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: no odd byte\n"));
}
/* add deferred carry bits */
acc = (acc >> 16) + (acc & 0x0000ffffUL);
acc = (acc >> 16) + (acc & 0xffffUL);
if ((acc & 0xffff0000) != 0) {
acc = (acc >> 16) + (acc & 0x0000ffffUL);
acc = (acc >> 16) + (acc & 0xffffUL);
}
/* This maybe a little confusing: reorder sum using htons()
instead of ntohs() since it has a little less call overhead.
The caller must invert bits for Internet sum ! */
return htons((u16_t)acc);
return (u16_t)acc;
}
#endif
#if 0
/*
* Curt McDowell
* Broadcom Corp.
* csm@broadcom.com
*
* IP checksum two bytes at a time with support for
* unaligned buffer.
* Works for len up to and including 0x20000.
* by Curt McDowell, Broadcom Corp. 12/08/2005
*/
static u16_t
lwip_standard_chksum2(void *dataptr, int len)
{
u8_t *pb = dataptr;
u16_t *ps, t = 0;
u32_t sum = 0;
int odd = ((u32_t)pb & 1);
/* Get aligned to u16_t */
if (odd && len > 0) {
((u8_t *)&t)[1] = *pb++;
len--;
}
/* Add the bulk of the data */
ps = (u16_t *)pb;
while (len > 1) {
sum += *ps++;
len -= 2;
}
/* Consume left-over byte, if any */
if (len > 0)
((u8_t *)&t)[0] = *(u8_t *)ps;;
/* Add end bytes */
sum += t;
/* Fold 32-bit sum to 16 bits */
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
/* Swap if alignment was odd */
if (odd)
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
return sum;
}
/**
* An optimized checksum routine. Basically, it uses loop-unrolling on
* the checksum loop, treating the head and tail bytes specially, whereas
* the inner loop acts on 8 bytes at a time.
*
* @arg start of buffer to be checksummed. May be an odd byte address.
* @len number of bytes in the buffer to be checksummed.
*
* @todo First argument type conflicts with generic checksum routine.
*
* by Curt McDowell, Broadcom Corp. December 8th, 2005
*/
static u16_t
lwip_standard_chksum4(u8_t *pb, int len)
{
u16_t *ps, t = 0;
u32_t *pl;
u32_t sum = 0, tmp;
/* starts at odd byte address? */
int odd = ((u32_t)pb & 1);
if (odd && len > 0) {
((u8_t *)&t)[1] = *pb++;
len--;
}
ps = (u16_t *)pb;
if (((u32_t)ps & 3) && len > 1) {
sum += *ps++;
len -= 2;
}
pl = (u32_t *)ps;
while (len > 7) {
tmp = sum + *pl++; /* ping */
if (tmp < sum)
tmp++; /* add back carry */
sum = tmp + *pl++; /* pong */
if (sum < tmp)
sum++; /* add back carry */
len -= 8;
}
/* make room in upper bits */
sum = (sum >> 16) + (sum & 0xffff);
ps = (u16_t *)pl;
/* 16-bit aligned word remaining? */
while (len > 1) {
sum += *ps++;
len -= 2;
}
/* dangling tail byte remaining? */
if (len > 0) /* include odd byte */
((u8_t *)&t)[0] = *(u8_t *)ps;
sum += t; /* add end bytes */
while (sum >> 16) /* combine halves */
sum = (sum >> 16) + (sum & 0xffff);
if (odd)
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
return sum;
}
#endif
/* inet_chksum_pseudo:
*
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
@@ -255,8 +96,8 @@ inet_chksum_pseudo(struct pbuf *p,
for(q = p; q != NULL; q = q->next) {
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
(void *)q, (void *)q->next));
acc += LWIP_CHKSUM(q->payload, q->len);
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
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);
}
@@ -264,7 +105,7 @@ inet_chksum_pseudo(struct pbuf *p,
swapped = 1 - swapped;
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
}
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%lx \n", acc));*/
}
if (swapped) {
@@ -280,8 +121,8 @@ inet_chksum_pseudo(struct pbuf *p,
while (acc >> 16) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
return (u16_t)~(acc & 0xffffUL);
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
return ~(acc & 0xffffUL);
}
/* inet_chksum:
@@ -295,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
@@ -312,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);
}
@@ -325,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 */
@@ -365,11 +206,10 @@ inet_chksum_pbuf(struct pbuf *p)
*/
/* */
/* inet_aton */
s8_t
inet_aton(const char *cp, struct in_addr *addr)
int inet_aton(const char *cp, struct in_addr *addr)
{
u32_t val;
s32_t base, n;
int base, n;
char c;
u32_t parts[4];
u32_t* pp = parts;
@@ -392,12 +232,12 @@ inet_chksum_pbuf(struct pbuf *p)
base = 8;
}
for (;;) {
if (isdigit(c)) {
val = (val * base) + (s16_t)(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) |
(s16_t)(c + 10 - (islower(c) ? 'a' : 'A'));
(c + 10 - (islower(c) ? 'a' : 'A'));
c = *++cp;
} else
break;
@@ -466,7 +306,7 @@ char *inet_ntoa(struct in_addr addr)
u32_t s_addr = addr.s_addr;
char inv[3];
char *rp;
u8_t *ap;
char *ap;
u8_t rem;
u8_t n;
u8_t i;

View File

@@ -33,21 +33,22 @@
/* Some ICMP messages should be passed to the transport protocols. This
is not implemented. */
#include <string.h>
#include "lwip/opt.h"
#include "lwip/icmp.h"
#include "lwip/inet.h"
#include "lwip/ip.h"
#include "lwip/def.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
void
icmp_input(struct pbuf *p, struct netif *inp)
{
u8_t type;
u8_t code;
unsigned char type;
unsigned char code;
struct icmp_echo_hdr *iecho;
struct ip_hdr *iphdr;
struct ip_addr tmpaddr;
@@ -60,7 +61,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
iphdr = p->payload;
hlen = IPH_HL(iphdr) * 4;
if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len));
pbuf_free(p);
ICMP_STATS_INC(icmp.lenerr);
snmp_inc_icmpinerrors();
@@ -71,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;
@@ -116,7 +117,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
break;
default:
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", (s16_t)type, (s16_t)code));
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code));
ICMP_STATS_INC(icmp.proterr);
ICMP_STATS_INC(icmp.drop);
}
@@ -139,7 +140,7 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
ICMPH_TYPE_SET(idur, ICMP_DUR);
ICMPH_CODE_SET(idur, t);
memcpy((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);
/* calculate checksum */
idur->chksum = 0;
@@ -177,7 +178,7 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
ICMPH_CODE_SET(tehdr, t);
/* copy fields from original packet */
memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
/* calculate checksum */
tehdr->chksum = 0;

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;
@@ -110,17 +115,17 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
/* Find network interface where to forward this IP packet to. */
netif = ip_route((struct ip_addr *)&(iphdr->dest));
if (netif == NULL) {
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n",
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. */
@@ -142,7 +147,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
}
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
iphdr->dest.addr));
IP_STATS_INC(ip.fw);
@@ -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();
@@ -181,7 +183,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
/* identify the IP header */
iphdr = p->payload;
if (IPH_V(iphdr) != 4) {
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %u\n", IPH_V(iphdr)));
ip_debug_print(p);
pbuf_free(p);
IP_STATS_INC(ip.err);
@@ -196,7 +198,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
/* header length exceeds first pbuf length? */
if (iphdrlen > p->len) {
LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet droppped.\n",
LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %u) does not fit in first pbuf (len %u), IP packet droppped.\n",
iphdrlen, p->len));
/* free (drop) packet pbufs */
pbuf_free(p);
@@ -207,10 +209,9 @@ 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%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
ip_debug_print(p);
pbuf_free(p);
IP_STATS_INC(ip.chkerr);
@@ -218,44 +219,45 @@ 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%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
iphdr->dest.addr, netif->ip_addr.addr,
iphdr->dest.addr & netif->netmask.addr,
netif->ip_addr.addr & netif->netmask.addr,
iphdr->dest.addr & ~(netif->netmask.addr)));
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)));
/* 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) {
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %u\n",
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
@@ -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%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
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%"X16_F") (while IP_REASSEMBLY == 0).\n",
ntohs(IPH_OFFSET(iphdr))));
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
ntohs(IPH_OFFSET(iphdr))));
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
#endif /* IP_REASSEMBLY */
}
#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);
@@ -319,11 +321,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
/* send to upper layers */
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
ip_debug_print(p);
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
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,18 +347,19 @@ 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);
}
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
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);
@@ -427,7 +429,7 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
IP_STATS_INC(ip.xmit);
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
ip_debug_print(p);
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
@@ -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.
*/
@@ -447,7 +450,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
struct netif *netif;
if ((netif = ip_route(dest)) == NULL) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr));
IP_STATS_INC(ip.rterr);
snmp_inc_ipoutdiscards();
@@ -468,35 +471,35 @@ ip_debug_print(struct pbuf *p)
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n",
LWIP_DEBUGF(IP_DEBUG, ("|%2d |%2d | 0x%02x | %5u | (v, hl, tos, len)\n",
IPH_V(iphdr),
IPH_HL(iphdr),
IPH_TOS(iphdr),
ntohs(IPH_LEN(iphdr))));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n",
LWIP_DEBUGF(IP_DEBUG, ("| %5u |%u%u%u| %4u | (id, flags, offset)\n",
ntohs(IPH_ID(iphdr)),
ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n",
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | 0x%04x | (ttl, proto, chksum)\n",
IPH_TTL(iphdr),
IPH_PROTO(iphdr),
ntohs(IPH_CHKSUM(iphdr))));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
ip4_addr1(&iphdr->src),
ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src),
ip4_addr4(&iphdr->src)));
LWIP_DEBUGF(IP_DEBUG, ("| %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, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
ip4_addr1(&iphdr->dest),
ip4_addr2(&iphdr->dest),
ip4_addr3(&iphdr->dest),
ip4_addr4(&iphdr->dest)));
LWIP_DEBUGF(IP_DEBUG, ("| %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,13 +31,20 @@
*
*/
#include <string.h>
/* ip_frag.c
*
* This is the code for IP segmentation and reassembly
*
*/
#include "lwip/opt.h"
/* #include "lwip/sys.h" */
#include "lwip/sys.h"
#include "lwip/ip.h"
#include "lwip/ip_frag.h"
#include "lwip/netif.h"
#include "lwip/stats.h"
@@ -78,7 +79,7 @@ copy_from_pbuf(struct pbuf *p, u16_t * offset,
#define IP_REASS_TMO 1000
static u8_t ip_reassbuf[IP_HLEN + IP_REASS_BUFSIZE];
static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8) + 1];
static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8)];
static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f,
0x0f, 0x07, 0x03, 0x01
};
@@ -88,26 +89,18 @@ static u8_t ip_reassflags;
static u8_t ip_reasstmr;
/**
* Reassembly timer base function
* for both NO_SYS == 0 and 1 (!).
*
* Should be called every 1000 msec.
*/
void
ip_reass_tmr(void)
/* Reassembly timer */
static void
ip_reass_timer(void *arg)
{
if (ip_reasstmr > 0) {
(void)arg;
if (ip_reasstmr > 1) {
ip_reasstmr--;
}
sys_timeout(IP_REASS_TMO, ip_reass_timer, NULL);
} else if (ip_reasstmr == 1)
ip_reasstmr = 0;
}
/**
* Reassembles incoming IP fragments into an IP datagram.
*
* @param p points to a pbuf chain of the fragment
* @return NULL if reassembly is incomplete, ? otherwise
*/
struct pbuf *
ip_reass(struct pbuf *p)
{
@@ -127,6 +120,7 @@ ip_reass(struct pbuf *p)
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: new packet\n"));
memcpy(iphdr, fraghdr, IP_HLEN);
ip_reasstmr = IP_REASS_MAXAGE;
sys_timeout(IP_REASS_TMO, ip_reass_timer, NULL);
ip_reassflags = 0;
/* Clear the bitmap. */
memset(ip_reassbitmap, 0, sizeof(ip_reassbitmap));
@@ -138,8 +132,7 @@ ip_reass(struct pbuf *p)
if (ip_addr_cmp(&iphdr->src, &fraghdr->src) &&
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n",
ntohs(IPH_ID(fraghdr))));
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n"));
IPFRAG_STATS_INC(ip_frag.cachehit);
/* Find out the offset in the reassembly buffer where we should
copy the fragment. */
@@ -150,8 +143,9 @@ ip_reass(struct pbuf *p)
reassembly buffer, we discard the entire packet. */
if (offset > IP_REASS_BUFSIZE || offset + len > IP_REASS_BUFSIZE) {
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: fragment outside of buffer (%"S16_F":%"S16_F"/%"S16_F").\n", offset,
("ip_reass: fragment outside of buffer (%d:%d/%d).\n", offset,
offset + len, IP_REASS_BUFSIZE));
sys_untimeout(ip_reass_timer, NULL);
ip_reasstmr = 0;
goto nullreturn;
}
@@ -159,7 +153,7 @@ ip_reass(struct pbuf *p)
/* Copy the fragment into the reassembly buffer, at the right
offset. */
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: copying with offset %"S16_F" into %"S16_F":%"S16_F"\n", offset,
("ip_reass: copying with offset %d into %d:%d\n", offset,
IP_HLEN + offset, IP_HLEN + offset + len));
i = IPH_HL(fraghdr) * 4;
copy_from_pbuf(p, &i, &ip_reassbuf[IP_HLEN + offset], len);
@@ -168,29 +162,24 @@ ip_reass(struct pbuf *p)
if (offset / (8 * 8) == (offset + len) / (8 * 8)) {
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: updating single byte in bitmap.\n"));
/* If the two endpoints are in the same byte, we only update that byte. */
LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)",
offset / (8 * 8) < sizeof(ip_reassbitmap));
/* If the two endpoints are in the same byte, we only update
that byte. */
ip_reassbitmap[offset / (8 * 8)] |=
bitmap_bits[(offset / 8) & 7] &
~bitmap_bits[((offset + len) / 8) & 7];
bitmap_bits[(offset / 8) & 7] &
~bitmap_bits[((offset + len) / 8) & 7];
} else {
/* If the two endpoints are in different bytes, we update the
bytes in the endpoints and fill the stuff inbetween with
0xff. */
LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)",
offset / (8 * 8) < sizeof(ip_reassbitmap));
ip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7];
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: updating many bytes in bitmap (%"S16_F":%"S16_F").\n",
("ip_reass: updating many bytes in bitmap (%d:%d).\n",
1 + offset / (8 * 8), (offset + len) / (8 * 8)));
for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
ip_reassbitmap[i] = 0xff;
ip_reassbitmap[i] = 0xff;
}
LWIP_ASSERT("(offset + len) / (8 * 8) < sizeof(ip_reassbitmap)",
(offset + len) / (8 * 8) < sizeof(ip_reassbitmap));
ip_reassbitmap[(offset + len) / (8 * 8)] |=
~bitmap_bits[((offset + len) / 8) & 7];
~bitmap_bits[((offset + len) / 8) & 7];
}
/* If this fragment has the More Fragments flag set to zero, we
@@ -203,7 +192,7 @@ ip_reass(struct pbuf *p)
ip_reassflags |= IP_REASS_FLAG_LASTFRAG;
ip_reasslen = offset + len;
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: last fragment seen, total len %"S16_F"\n",
("ip_reass: last fragment seen, total len %d\n",
ip_reasslen));
}
@@ -213,27 +202,23 @@ ip_reass(struct pbuf *p)
if (ip_reassflags & IP_REASS_FLAG_LASTFRAG) {
/* Check all bytes up to and including all but the last byte in
the bitmap. */
LWIP_ASSERT("ip_reasslen / (8 * 8) - 1 < sizeof(ip_reassbitmap)",
ip_reasslen / (8 * 8) - 1 < sizeof(ip_reassbitmap));
for (i = 0; i < ip_reasslen / (8 * 8) - 1; ++i) {
if (ip_reassbitmap[i] != 0xff) {
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: last fragment seen, bitmap %"S16_F"/%"S16_F" failed (%"X16_F")\n",
i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
goto nullreturn;
}
if (ip_reassbitmap[i] != 0xff) {
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: last fragment seen, bitmap %d/%d failed (%x)\n",
i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
goto nullreturn;
}
}
/* Check the last byte in the bitmap. It should contain just the
right amount of bits. */
LWIP_ASSERT("ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap)",
ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap));
if (ip_reassbitmap[ip_reasslen / (8 * 8)] !=
(u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) {
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: last fragment seen, bitmap %"S16_F" didn't contain %"X16_F" (%"X16_F")\n",
ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7],
ip_reassbitmap[ip_reasslen / (8 * 8)]));
goto nullreturn;
(u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) {
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: last fragment seen, bitmap %d didn't contain %x (%x)\n",
ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7],
ip_reassbitmap[ip_reasslen / (8 * 8)]));
goto nullreturn;
}
/* Pretend to be a "normal" (i.e., not fragmented) IP packet
@@ -248,25 +233,27 @@ ip_reass(struct pbuf *p)
/* If we have come this far, we have a full packet in the
buffer, so we allocate a pbuf and copy the packet into it. We
also reset the timer. */
sys_untimeout(ip_reass_timer, NULL);
ip_reasstmr = 0;
pbuf_free(p);
p = pbuf_alloc(PBUF_LINK, ip_reasslen, PBUF_POOL);
if (p != NULL) {
i = 0;
for (q = p; q != NULL; q = q->next) {
/* Copy enough bytes to fill this pbuf in the chain. The
available data in the pbuf is given by the q->len variable. */
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: memcpy from %p (%"S16_F") to %p, %"S16_F" bytes\n",
(void *)&ip_reassbuf[i], i, q->payload,
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
memcpy(q->payload, &ip_reassbuf[i],
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
i += q->len;
}
IPFRAG_STATS_INC(ip_frag.fw);
i = 0;
for (q = p; q != NULL; q = q->next) {
/* Copy enough bytes to fill this pbuf in the chain. The
available data in the pbuf is given by the q->len
variable. */
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: memcpy from %p (%d) to %p, %d bytes\n",
&ip_reassbuf[i], i, q->payload,
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
memcpy(q->payload, &ip_reassbuf[i],
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
i += q->len;
}
IPFRAG_STATS_INC(ip_frag.fw);
} else {
IPFRAG_STATS_INC(ip_frag.memerr);
IPFRAG_STATS_INC(ip_frag.memerr);
}
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
return p;
@@ -283,9 +270,9 @@ nullreturn:
static u8_t buf[MEM_ALIGN_SIZE(MAX_MTU)];
/**
* Fragment an IP datagram if too large for the netif.
* Fragment an IP packet if too large
*
* Chop the datagram in MTU sized chunks and send them in order
* Chop the packet in mtu sized chunks and send them in order
* by using a fixed size static memory buffer (PBUF_ROM)
*/
err_t
@@ -304,12 +291,10 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
/* Get a RAM based MTU sized pbuf */
rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF);
if (rambuf == NULL) {
return ERR_MEM;
}
rambuf->tot_len = rambuf->len = mtu;
rambuf->payload = MEM_ALIGN((void *)buf);
/* Copy the IP header in it */
iphdr = rambuf->payload;
memcpy(iphdr, p->payload, IP_HLEN);
@@ -350,15 +335,11 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
* worked would make things simpler.
*/
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
if (header != NULL) {
pbuf_chain(header, rambuf);
netif->output(netif, header, dest);
IPFRAG_STATS_INC(ip_frag.xmit);
pbuf_free(header);
} else {
pbuf_free(rambuf);
return ERR_MEM;
}
pbuf_chain(header, rambuf);
netif->output(netif, header, dest);
IPFRAG_STATS_INC(ip_frag.xmit);
pbuf_free(header);
left -= cop;
}
pbuf_free(rambuf);

View File

@@ -46,7 +46,7 @@
void
icmp_input(struct pbuf *p, struct netif *inp)
{
u8_t type;
unsigned char type;
struct icmp_echo_hdr *iecho;
struct ip_hdr *iphdr;
struct ip_addr tmpaddr;
@@ -57,7 +57,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
/* TODO: check length before accessing payload! */
type = ((u8_t *)p->payload)[0];
type = ((char *)p->payload)[0];
switch (type) {
case ICMP6_ECHO:
@@ -74,16 +74,16 @@ icmp_input(struct pbuf *p, struct netif *inp)
return;
}
iecho = p->payload;
iphdr = (struct ip_hdr *)((u8_t *)p->payload - IP_HLEN);
iphdr = (struct ip_hdr *)((char *)p->payload - IP_HLEN);
if (inet_chksum_pbuf(p) != 0) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
#ifdef ICMP_STATS
++lwip_stats.icmp.chkerr;
#endif /* ICMP_STATS */
/* return;*/
}
LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %"S16_F" p->tot_len %"S16_F"\n", p->len, p->tot_len));
LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %d p->tot_len %d\n", p->len, p->tot_len));
ip_addr_set(&tmpaddr, &(iphdr->src));
ip_addr_set(&(iphdr->src), &(iphdr->dest));
ip_addr_set(&(iphdr->dest), &tmpaddr);
@@ -94,17 +94,17 @@ icmp_input(struct pbuf *p, struct netif *inp)
} else {
iecho->chksum += htons(ICMP6_ECHO << 8);
}
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
/* LWIP_DEBUGF("icmp: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
/* LWIP_DEBUGF("icmp: p->len %u p->tot_len %u\n", p->len, p->tot_len);*/
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
iphdr->hoplim, IP_PROTO_ICMP, inp);
break;
default:
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" not supported.\n", (s16_t)type));
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d not supported.\n", (int)type));
#ifdef ICMP_STATS
++lwip_stats.icmp.proterr;
++lwip_stats.icmp.drop;
@@ -127,10 +127,10 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
iphdr = p->payload;
idur = q->payload;
idur->type = (u8_t)ICMP6_DUR;
idur->icode = (u8_t)t;
idur->type = (char)ICMP6_DUR;
idur->icode = (char)t;
memcpy((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);
/* calculate checksum */
idur->chksum = 0;
@@ -158,11 +158,11 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
iphdr = p->payload;
tehdr = q->payload;
tehdr->type = (u8_t)ICMP6_TE;
tehdr->icode = (u8_t)t;
tehdr->type = (char)ICMP6_TE;
tehdr->icode = (char)t;
/* copy fields from original packet */
memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
/* calculate checksum */
tehdr->chksum = 0;

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;
}
}
@@ -217,7 +217,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
#if IP_DEBUG
/* LWIP_DEBUGF("ip_input: \n");
ip_debug_print(p);
LWIP_DEBUGF("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
LWIP_DEBUGF("ip_input: p->len %u p->tot_len %u\n", p->len, p->tot_len);*/
#endif /* IP_DEBUG */
@@ -237,7 +237,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
/* send ICMP destination protocol unreachable */
icmp_dest_unreach(p, ICMP_DUR_PROTO);
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %"U16_F"\n",
LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %u\n",
iphdr->nexthdr));
#ifdef IP_STATS
@@ -266,7 +266,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
PERF_START;
printf("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len);
printf("len %u tot_len %u\n", p->len, p->tot_len);
if (pbuf_header(p, IP_HLEN)) {
LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
#ifdef IP_STATS
@@ -275,7 +275,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
return ERR_BUF;
}
printf("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len);
printf("len %u tot_len %u\n", p->len, p->tot_len);
iphdr = p->payload;
@@ -303,7 +303,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
++lwip_stats.ip.xmit;
#endif /* IP_STATS */
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %"U16_F")\n", netif->name[0], netif->name[1], p->tot_len));
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %u)\n", netif->name[0], netif->name[1], p->tot_len));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
@@ -324,7 +324,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
{
struct netif *netif;
if ((netif = ip_route(dest)) == NULL) {
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%lx\n", dest->addr));
#ifdef IP_STATS
++lwip_stats.ip.rterr;
#endif /* IP_STATS */
@@ -339,45 +339,45 @@ void
ip_debug_print(struct pbuf *p)
{
struct ip_hdr *iphdr = p->payload;
u8_t *payload;
char *payload;
payload = (u8_t *)iphdr + IP_HLEN;
payload = (char *)iphdr + IP_HLEN;
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" | %"X16_F"%"X16_F" | %"X16_F"%"X16_F" | (v, traffic class, flow label)\n",
LWIP_DEBUGF(IP_DEBUG, ("|%2d | %x%x | %x%x | (v, traffic class, flow label)\n",
iphdr->v,
iphdr->tclass1, iphdr->tclass2,
iphdr->flow1, iphdr->flow2));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" | %2"U16_F" | %2"U16_F" | (len, nexthdr, hoplim)\n",
LWIP_DEBUGF(IP_DEBUG, ("| %5u | %2u | %2u | (len, nexthdr, hoplim)\n",
ntohs(iphdr->len),
iphdr->nexthdr,
iphdr->hoplim));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
ntohl(iphdr->src.addr[0]) >> 16 & 0xffff,
ntohl(iphdr->src.addr[0]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
ntohl(iphdr->src.addr[1]) >> 16 & 0xffff,
ntohl(iphdr->src.addr[1]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
ntohl(iphdr->src.addr[2]) >> 16 & 0xffff,
ntohl(iphdr->src.addr[2]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
ntohl(iphdr->src.addr[3]) >> 16 & 0xffff,
ntohl(iphdr->src.addr[3]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
ntohl(iphdr->dest.addr[0]) >> 16 & 0xffff,
ntohl(iphdr->dest.addr[0]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
ntohl(iphdr->dest.addr[1]) >> 16 & 0xffff,
ntohl(iphdr->dest.addr[1]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
ntohl(iphdr->dest.addr[2]) >> 16 & 0xffff,
ntohl(iphdr->dest.addr[2]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
ntohl(iphdr->dest.addr[3]) >> 16 & 0xffff,
ntohl(iphdr->dest.addr[3]) & 0xffff));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));

View File

@@ -34,8 +34,8 @@
#include "lwip/inet.h"
u8_t
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)
{
return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) &&
@@ -45,7 +45,7 @@ ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
}
u8_t
int
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
{
return(addr1->addr[0] == addr2->addr[0] &&
@@ -64,7 +64,7 @@ ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
dest->addr[3] = src->addr[3];*/
}
u8_t
int
ip_addr_isany(struct ip_addr *addr)
{
if (addr == NULL) return 1;
@@ -76,7 +76,7 @@ ip_addr_isany(struct ip_addr *addr)
void
ip_addr_debug_print(struct ip_addr *addr)
{
printf("%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F",
printf("%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx",
ntohl(addr->addr[0]) >> 16 & 0xffff,
ntohl(addr->addr[0]) & 0xffff,
ntohl(addr->addr[1]) >> 16 & 0xffff,

View File

@@ -36,7 +36,6 @@
*
*/
#include <string.h>
#include "lwip/arch.h"
#include "lwip/opt.h"
@@ -301,7 +300,7 @@ mem_malloc(mem_size_t size)
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
}
}
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size));
#if MEM_STATS
++lwip_stats.mem.err;
#endif /* MEM_STATS */

View File

@@ -124,7 +124,7 @@ static sys_sem_t mutex;
static int
memp_sanity(void)
{
s16_t i, c;
int i, c;
struct memp *m, *n;
for(i = 0; i < MEMP_MAX; i++) {
@@ -222,7 +222,7 @@ memp_malloc(memp_t type)
mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp));
return mem;
} else {
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %"S16_F"\n", type));
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %d\n", type));
#if MEMP_STATS
++lwip_stats.memp[type].err;
#endif /* MEMP_STATS */

View File

@@ -67,7 +67,8 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif))
{
static s16_t netifnum = 0;
static int netifnum = 0;
#if LWIP_DHCP
/* netif not under DHCP control by default */
@@ -197,44 +198,36 @@ 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 %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
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
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 %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
ip4_addr1(&netif->gw),
ip4_addr2(&netif->gw),
ip4_addr3(&netif->gw),
ip4_addr4(&netif->gw)));
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %u.%u.%u.%u\n",
netif->name[0], netif->name[1],
(unsigned int)(ntohl(netif->gw.addr) >> 24 & 0xff),
(unsigned int)(ntohl(netif->gw.addr) >> 16 & 0xff),
(unsigned int)(ntohl(netif->gw.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->gw.addr) & 0xff)));
}
void
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
{
ip_addr_set(&(netif->netmask), netmask);
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
ip4_addr1(&netif->netmask),
ip4_addr2(&netif->netmask),
ip4_addr3(&netif->netmask),
ip4_addr4(&netif->netmask)));
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %u.%u.%u.%u\n",
netif->name[0], netif->name[1],
(unsigned int)(ntohl(netif->netmask.addr) >> 24 & 0xff),
(unsigned int)(ntohl(netif->netmask.addr) >> 16 & 0xff),
(unsigned int)(ntohl(netif->netmask.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->netmask.addr) & 0xff)));
}
void
@@ -245,41 +238,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
@@ -62,18 +59,20 @@
*
*/
#include <string.h>
#include "lwip/opt.h"
#include "lwip/stats.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "arch/perf.h"
static u8_t pbuf_pool_memory[MEM_ALIGNMENT - 1 + PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf))];
static u8_t pbuf_pool_memory[(PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf)))];
#if !SYS_LIGHTWEIGHT_PROT
static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
@@ -100,7 +99,8 @@ pbuf_init(void)
struct pbuf *p, *q = NULL;
u16_t i;
pbuf_pool = (struct pbuf *)MEM_ALIGN(pbuf_pool_memory);
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
LWIP_ASSERT("pbuf_init: pool aligned", (mem_ptr_t)pbuf_pool % MEM_ALIGNMENT == 0);
#if PBUF_STATS
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
@@ -180,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
@@ -214,7 +214,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
struct pbuf *p, *q, *r;
u16_t offset;
s32_t rem_len; /* remaining length */
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F")\n", length));
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u)\n", length));
/* determine header offset */
offset = 0;
@@ -303,7 +303,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
break;
case PBUF_RAM:
/* If pbuf is to be allocated in RAM, allocate memory for it. */
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + offset) + MEM_ALIGN_SIZE(length));
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + length + offset));
if (p == NULL) {
return NULL;
}
@@ -316,7 +316,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
((mem_ptr_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:
@@ -338,7 +338,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
}
/* set reference count */
p->ref = 1;
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u) == %p\n", length, (void *)p));
return p;
}
@@ -450,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 (%"S16_F")\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).
*
@@ -548,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;
@@ -584,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 */
@@ -597,8 +589,8 @@ pbuf_free(struct pbuf *p)
/* p->ref > 0, this pbuf is still referenced to */
/* (and so the remaining pbufs in chain as well) */
} else {
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, (u16_t)p->ref));
/* stop walking through the chain */
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, (unsigned int)p->ref));
/* stop walking through chain */
p = NULL;
}
}
@@ -661,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 */
@@ -672,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.
*/
}
/**
@@ -707,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.
@@ -716,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) {
@@ -739,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).
*
@@ -782,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
@@ -821,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.
@@ -849,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;
@@ -860,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)
@@ -945,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,7 +35,12 @@
*
*/
#include <string.h>
/* raw.c
*
* The code for the Raw Access to the IP
*
*/
#include "lwip/opt.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;
s16_t proto;
u8_t eaten = 0;
int proto;
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%"X32_F"\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"
@@ -53,48 +52,48 @@ void
stats_display_proto(struct stats_proto *proto, char *name)
{
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
LWIP_PLATFORM_DIAG(("xmit: %"S16_F"\n\t", proto->xmit));
LWIP_PLATFORM_DIAG(("rexmit: %"S16_F"\n\t", proto->rexmit));
LWIP_PLATFORM_DIAG(("recv: %"S16_F"\n\t", proto->recv));
LWIP_PLATFORM_DIAG(("fw: %"S16_F"\n\t", proto->fw));
LWIP_PLATFORM_DIAG(("drop: %"S16_F"\n\t", proto->drop));
LWIP_PLATFORM_DIAG(("chkerr: %"S16_F"\n\t", proto->chkerr));
LWIP_PLATFORM_DIAG(("lenerr: %"S16_F"\n\t", proto->lenerr));
LWIP_PLATFORM_DIAG(("memerr: %"S16_F"\n\t", proto->memerr));
LWIP_PLATFORM_DIAG(("rterr: %"S16_F"\n\t", proto->rterr));
LWIP_PLATFORM_DIAG(("proterr: %"S16_F"\n\t", proto->proterr));
LWIP_PLATFORM_DIAG(("opterr: %"S16_F"\n\t", proto->opterr));
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", proto->err));
LWIP_PLATFORM_DIAG(("cachehit: %"S16_F"\n", proto->cachehit));
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: %"S16_F"\n\t", pbuf->avail));
LWIP_PLATFORM_DIAG(("used: %"S16_F"\n\t", pbuf->used));
LWIP_PLATFORM_DIAG(("max: %"S16_F"\n\t", pbuf->max));
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", pbuf->err));
LWIP_PLATFORM_DIAG(("alloc_locked: %"S16_F"\n\t", pbuf->alloc_locked));
LWIP_PLATFORM_DIAG(("refresh_locked: %"S16_F"\n", pbuf->refresh_locked));
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: %"S16_F"\n\t", mem->avail));
LWIP_PLATFORM_DIAG(("used: %"S16_F"\n\t", mem->used));
LWIP_PLATFORM_DIAG(("max: %"S16_F"\n\t", mem->max));
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n", mem->err));
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)
{
s16_t i;
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");

View File

@@ -39,7 +39,7 @@
struct sswt_cb
{
s16_t timeflag;
int timeflag;
sys_sem_t *psem;
};
@@ -170,7 +170,7 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
timeouts = sys_arch_timeouts();
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n",
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%lu h=%p arg=%p\n",
(void *)timeout, msecs, (void *)h, (void *)arg));
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);

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"
@@ -59,22 +63,26 @@ const u8_t tcp_backoff[13] =
/* The TCP PCB lists. */
/** List of all TCP PCBs in LISTEN state */
/* List of all TCP PCBs in LISTEN state. */
union tcp_listen_pcbs_t tcp_listen_pcbs;
/** List of all TCP PCBs that are in a state in which
* they accept or send data. */
struct tcp_pcb *tcp_active_pcbs;
/** List of all TCP PCBs in TIME-WAIT state */
struct tcp_pcb *tcp_tw_pcbs;
struct tcp_pcb *tcp_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)
{
@@ -90,10 +98,13 @@ tcp_init(void)
}
/**
/*
* tcp_tmr():
*
* Called periodically to dispatch TCP timers.
*
*/
void
tcp_tmr(void)
{
@@ -107,10 +118,13 @@ tcp_tmr(void)
}
}
/**
/*
* tcp_close():
*
* Closes the connection held by the PCB.
*
*/
err_t
tcp_close(struct tcp_pcb *pcb)
{
@@ -122,18 +136,6 @@ 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);
@@ -172,12 +174,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 +231,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,10 +244,14 @@ err_t
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct tcp_pcb *cpcb;
#if SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
if (port == 0) {
port = tcp_new_port();
}
#if SO_REUSE == 0
/* Check if the address already is in use. */
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
cpcb != NULL; cpcb = cpcb->next) {
@@ -262,12 +273,107 @@ tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
}
}
}
#else /* SO_REUSE */
/* Search through list of PCB's in LISTEN state.
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
But no two PCB's bound to same local port and same local address is valid.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
}
}
}
}
/* Search through list of PCB's in a state in which they can accept or send data. Same decription as for
PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */
for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
}
}
}
}
/* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port}
can be rebound. The same applies when SOF_REUSEPORT is set.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n"));
return ERR_USE;
}
else if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
}
}
}
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
{IP, port} can't be reused. */
if(!reuse_port_all_set) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n"));
return ERR_USE;
}
#endif /* SO_REUSE */
if (!ip_addr_isany(ipaddr)) {
pcb->local_ip = *ipaddr;
}
pcb->local_port = port;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port));
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %u\n", port));
return ERR_OK;
}
#if LWIP_CALLBACK_API
@@ -282,13 +388,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)
{
@@ -318,12 +427,15 @@ tcp_listen(struct tcp_pcb *pcb)
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)
{
@@ -345,26 +457,19 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
* 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 %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n",
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)
{
@@ -398,11 +503,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))
@@ -411,7 +519,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
err_t ret;
u32_t iss;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %u\n", port));
if (ipaddr != NULL) {
pcb->remote_ip = *ipaddr;
} else {
@@ -450,11 +558,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)
{
@@ -470,9 +581,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);
@@ -493,7 +602,7 @@ tcp_slowtmr(void)
if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
/* Time for a retransmission. */
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"U16_F" pcb->rto %"U16_F"\n",
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %u pcb->rto %u\n",
pcb->rtime, pcb->rto));
/* Double retransmission time-out unless we are trying to
@@ -501,6 +610,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;
@@ -508,12 +618,9 @@ tcp_slowtmr(void)
pcb->ssthresh = pcb->mss * 2;
}
pcb->cwnd = pcb->mss;
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\n",
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) {
@@ -527,7 +634,7 @@ tcp_slowtmr(void)
/* Check if KEEPALIVE should be sent */
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
@@ -555,19 +662,12 @@ tcp_slowtmr(void)
/* Check if this PCB has stayed too long in SYN-RCVD */
if (pcb->state == SYN_RCVD) {
if ((u32_t)(tcp_ticks - pcb->tmr) >
TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
++pcb_remove;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
}
}
/* Check if this PCB has stayed too long in LAST-ACK */
if (pcb->state == LAST_ACK) {
if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
++pcb_remove;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n"));
}
}
/* If the PCB should be removed, do it. */
if (pcb_remove) {
@@ -642,9 +742,12 @@ tcp_slowtmr(void)
}
}
/**
/*
* tcp_fasttmr():
*
* Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
*/
void
tcp_fasttmr(void)
{
@@ -660,10 +763,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)
{
@@ -677,10 +783,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)
{
@@ -698,10 +807,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)
{
@@ -709,10 +821,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)
{
@@ -722,7 +837,7 @@ tcp_seg_copy(struct tcp_seg *seg)
if (cseg == NULL) {
return NULL;
}
memcpy((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg));
memcpy((char *)cseg, (const char *)seg, sizeof(struct tcp_seg));
pbuf_ref(cseg->p);
return cseg;
}
@@ -766,7 +881,7 @@ tcp_kill_prio(u8_t prio)
}
}
if (inactive != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB 0x%p (%ld)\n",
(void *)inactive, inactivity));
tcp_abort(inactive);
}
@@ -788,7 +903,7 @@ tcp_kill_timewait(void)
}
}
if (inactive != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n",
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB 0x%p (%ld)\n",
(void *)inactive, inactivity));
tcp_abort(inactive);
}
@@ -848,13 +963,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 *
@@ -878,11 +992,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))
@@ -890,7 +1007,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.
*
@@ -903,11 +1022,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))
@@ -915,11 +1037,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))
@@ -929,12 +1054,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)
@@ -945,10 +1073,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)
{
@@ -978,10 +1109,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)
{
@@ -1001,10 +1135,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)
{
@@ -1020,16 +1157,16 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
{
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
LWIP_DEBUGF(TCP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
ntohs(tcphdr->src), ntohs(tcphdr->dest)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n",
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (seq no)\n",
ntohl(tcphdr->seqno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n",
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (ack no)\n",
ntohl(tcphdr->ackno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (",
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u%u| %5u | (hdrlen, flags (",
TCPH_HDRLEN(tcphdr),
TCPH_FLAGS(tcphdr) >> 5 & 1,
TCPH_FLAGS(tcphdr) >> 4 & 1,
@@ -1041,7 +1178,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n",
LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04x | %5u | (chksum, urgp)\n",
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
}
@@ -1122,28 +1259,28 @@ tcp_debug_print_pcbs(void)
struct tcp_pcb *pcb;
LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
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));
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) {
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
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));
tcp_debug_print_state(pcb->state);
}
LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
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));
tcp_debug_print_state(pcb->state);
}
}
s16_t
int
tcp_pcbs_sane(void)
{
struct tcp_pcb *pcb;

File diff suppressed because it is too large Load Diff

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,17 +35,27 @@
*
*/
#include <string.h>
/* tcp_output.c
*
* The output functions of TCP.
*
*/
#include "lwip/def.h"
#include "lwip/opt.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/inet.h"
#include "lwip/tcp.h"
#include "lwip/stats.h"
#if LWIP_TCP
@@ -60,33 +66,27 @@ 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()
/*
* NB. tcp_write() enqueues data for sending, but does not send it
* straight away. 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().
*/
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=%"U16_F", copy=%"U16_F")\n", (void *)pcb,
arg, len, (u16_t)copy));
/* connection is in valid state for data transmission? */
if (pcb->state == ESTABLISHED ||
pcb->state == CLOSE_WAIT ||
pcb->state == SYN_SENT ||
pcb->state == SYN_RCVD) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb,
arg, len, (unsigned int)copy));
if (pcb->state == SYN_SENT ||
pcb->state == SYN_RCVD ||
pcb->state == ESTABLISHED ||
pcb->state == CLOSE_WAIT) {
if (len > 0) {
return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
}
@@ -97,24 +97,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;
@@ -123,46 +109,41 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
void *ptr;
u8_t queuelen;
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", copy=%"U16_F")\n",
(void *)pcb, arg, len, (u16_t)flags, (u16_t)copy));
LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
len == 0 || optlen == 0);
LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
arg == NULL || optdata == NULL);
/* fail on too much data */
if (len > pcb->snd_buf) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
return ERR_MEM;
}
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%u)\n",
(void *)pcb, arg, len, (unsigned int)flags, (unsigned int)copy));
left = len;
ptr = arg;
/* 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;
}
/* seqno will be the sequence number of the first segment enqueued
* by the call to this function. */
seqno = pcb->snd_lbb;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
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 %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
TCP_STATS_INC(tcp.memerr);
return ERR_MEM;
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
@@ -178,25 +159,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;
@@ -204,10 +180,9 @@ 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 %"U16_F"\n", seglen));
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %u\n", seglen));
goto memerr;
}
++queuelen;
@@ -218,7 +193,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.
@@ -228,7 +204,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;
@@ -243,22 +218,28 @@ 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;
}
/* Now that there are more segments queued, we check again if the
length of the queue exceeds the configured maximum. */
if (queuelen > TCP_SND_QUEUELEN) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %u (%u)\n", queuelen, TCP_SND_QUEUELEN));
goto memerr;
}
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;
}
@@ -281,16 +262,17 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
segments such as SYN|ACK. */
memcpy(seg->dataptr, optdata, optlen);
}
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n",
ntohl(seg->tcphdr->seqno),
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
(u16_t)flags));
flags));
left -= seglen;
seqno += seglen;
ptr = (void *)((u8_t *)ptr + seglen);
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. */
@@ -300,7 +282,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. */
@@ -308,27 +289,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 %"U16_F"\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;
}
@@ -337,15 +315,13 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
++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: %"S16_F" (after enqueued)\n", pcb->snd_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
@@ -355,7 +331,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
}
return ERR_OK;
memerr:
memerr:
TCP_STATS_INC(tcp.memerr);
if (queue != NULL) {
@@ -364,8 +340,9 @@ memerr:
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: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
return ERR_MEM;
}
@@ -378,7 +355,7 @@ tcp_output(struct tcp_pcb *pcb)
struct tcp_seg *seg, *useg;
u32_t wnd;
#if TCP_CWND_DEBUG
s16_t i = 0;
int i = 0;
#endif /* TCP_CWND_DEBUG */
/* First, check if we are invoked by the TCP input processing
@@ -391,6 +368,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 */
@@ -398,24 +376,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 %"U32_F"\n", pcb->rcv_nxt));
/* remove ACK flags from the PCB, as we send an empty ACK now */
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %lu\n", pcb->rcv_nxt));
tcphdr = p->payload;
tcphdr->src = htons(pcb->local_port);
@@ -428,10 +406,9 @@ 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);
@@ -441,26 +418,26 @@ tcp_output(struct tcp_pcb *pcb)
#if TCP_OUTPUT_DEBUG
if (seg == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", (void*)pcb->unsent));
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", pcb->unsent));
}
#endif /* TCP_OUTPUT_DEBUG */
#if TCP_CWND_DEBUG
if (seg == NULL) {
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", seg == NULL, ack %"U32_F"\n",
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n",
pcb->snd_wnd, pcb->cwnd, wnd,
pcb->lastack));
} else {
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\n",
pcb->snd_wnd, pcb->cwnd, wnd,
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
ntohl(seg->tcphdr->seqno), pcb->lastack));
}
#endif /* TCP_CWND_DEBUG */
/* data available and window allows it to be sent? */
while (seg != NULL &&
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
#if TCP_CWND_DEBUG
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\n",
pcb->snd_wnd, pcb->cwnd, wnd,
ntohl(seg->tcphdr->seqno) + seg->len -
pcb->lastack,
@@ -483,26 +460,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);
}
@@ -511,9 +475,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)
{
@@ -548,9 +509,9 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
pcb->rttest = tcp_ticks;
pcb->rtseq = ntohl(seg->tcphdr->seqno);
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq));
}
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\n",
htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
seg->len));
@@ -562,12 +523,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,
@@ -598,45 +557,14 @@ tcp_rst(u32_t seqno, u32_t ackno,
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
IP_PROTO_TCP, p->tot_len);
#endif
TCP_STATS_INC(tcp.xmit);
/* Send output with hardcoded TTL since we have no access to the pcb */
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
}
/* requeue all unacked segments for retransmission */
void
tcp_rexmit_rto(struct tcp_pcb *pcb)
{
struct tcp_seg *seg;
if (pcb->unacked == NULL) {
return;
}
/* Move all unacked segments to the head of the unsent queue */
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
/* concatenate unsent queue after unacked queue */
seg->next = pcb->unsent;
/* unsent queue is the concatenated queue (of unacked, unsent) */
pcb->unsent = pcb->unacked;
/* unacked queue is now empty */
pcb->unacked = NULL;
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
/* increment number of retransmissions */
++pcb->nrtx;
/* Don't take any RTT measurements after retransmitting. */
pcb->rttest = 0;
/* Do the actual retransmission */
tcp_output(pcb);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
}
void
@@ -648,11 +576,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);
@@ -666,18 +597,17 @@ tcp_rexmit(struct tcp_pcb *pcb)
}
void
tcp_keepalive(struct tcp_pcb *pcb)
{
struct pbuf *p;
struct tcp_hdr *tcphdr;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt %"U16_F"\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);
@@ -696,9 +626,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 */
@@ -706,7 +635,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
}
#endif /* LWIP_TCP */

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"
@@ -66,6 +64,7 @@ struct udp_pcb *udp_pcbs = NULL;
static struct udp_pcb *pcb_cache = NULL;
void
udp_init(void)
{
@@ -87,11 +86,16 @@ udp_input(struct pbuf *p, struct netif *inp)
{
struct udp_hdr *udphdr;
struct udp_pcb *pcb;
struct udp_pcb *uncon_pcb;
struct ip_hdr *iphdr;
u16_t src, dest;
u8_t local_match;
#if SO_REUSE
struct udp_pcb *pcb_temp;
int reuse = 0;
int reuse_port_1 = 0;
int reuse_port_2 = 0;
#endif /* SO_REUSE */
PERF_START;
UDP_STATS_INC(udp.recv);
@@ -100,7 +104,7 @@ udp_input(struct pbuf *p, struct netif *inp)
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
/* drop short packets */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len));
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
UDP_STATS_INC(udp.lenerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
@@ -110,7 +114,7 @@ udp_input(struct pbuf *p, struct netif *inp)
udphdr = (struct udp_hdr *)((u8_t *)p->payload - UDP_HLEN);
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %u\n", p->tot_len));
src = ntohs(udphdr->src);
dest = ntohs(udphdr->dest);
@@ -118,46 +122,117 @@ udp_input(struct pbuf *p, struct netif *inp)
udp_debug_print(udphdr);
/* print the UDP source and destination */
LWIP_DEBUGF(UDP_DEBUG, ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n",
ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest),
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
local_match = 0;
uncon_pcb = NULL;
/* Iterate through the UDP pcb list for a matching pcb */
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#if SO_REUSE
pcb_temp = udp_pcbs;
again_1:
/* Iterate through the UDP pcb list for a fully matching pcb */
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
/* Iterate through the UDP pcb list for a fully matching pcb */
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
/* print the PCB local and remote address */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
/* compare PCB local addr+port to UDP destination addr+port */
if ((pcb->local_port == dest) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
local_match = 1;
if ((uncon_pcb == NULL) &&
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
/* the first unconnected matching PCB */
uncon_pcb = pcb;
}
}
/* compare PCB remote addr+port to UDP source addr+port */
if ((local_match != 0) &&
(pcb->remote_port == src) &&
/* PCB remote port matches UDP source port? */
if ((pcb->remote_port == src) &&
/* PCB local port matches UDP destination port? */
(pcb->local_port == dest) &&
/* accepting from any remote (source) IP address? or... */
(ip_addr_isany(&pcb->remote_ip) ||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)))) {
/* the first fully matching PCB */
/* PCB remote IP address matches UDP source IP address? */
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
/* accepting on any local (netif) IP address? or... */
(ip_addr_isany(&pcb->local_ip) ||
/* 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) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port_1 = 1;
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
break;
}
}
/* no fully matching pcb found? then look for an unconnected pcb */
if (pcb == NULL) {
pcb = uncon_pcb;
/* Iterate through the UDP PCB list for a pcb that matches
the local address. */
#if SO_REUSE
pcb_temp = udp_pcbs;
again_2:
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
/* unconnected? */
if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) &&
/* destination port matches? */
(pcb->local_port == dest) &&
/* not bound to a specific (local) interface address? or... */
(ip_addr_isany(&pcb->local_ip) ||
/* ...matching interface address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
#if SO_REUSE
if(pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port_2 = 1;
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
break;
}
}
}
/* Check checksum if this is a match or if it was directed at us. */
@@ -171,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) {
@@ -182,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),
@@ -198,24 +270,45 @@ udp_input(struct pbuf *p, struct netif *inp)
goto end;
}
}
#endif
}
pbuf_header(p, -UDP_HLEN);
if (pcb != NULL) {
snmp_inc_udpindatagrams();
/* callback */
if (pcb->recv != NULL)
{
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
}
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
#if SO_REUSE
/* First socket should receive now */
if(reuse_port_1 || reuse_port_2) {
/* We want to search on next socket after receiving */
pcb_temp = pcb->next;
if(reuse_port_1) {
/* We are searching connected sockets */
reuse_port_1 = 0;
reuse_port_2 = 0;
goto again_1;
} else {
/* We are searching unconnected sockets */
reuse_port_1 = 0;
reuse_port_2 = 0;
goto again_2;
}
}
#endif /* SO_REUSE */
} else {
#if SO_REUSE
if(reuse) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
pbuf_free(p);
goto end;
}
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
/* No match was found, send ICMP destination port unreachable unless
destination address was broadcast/multicast. */
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;
@@ -257,10 +350,9 @@ 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 */
/* remember 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 */
@@ -268,7 +360,7 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
pcb->remote_port = dst_port;
/* send to the packet destination address */
err = udp_send(pcb, p);
/* restore PCB remote peer address */
/* reset PCB remote peer address */
pcb->remote_ip.addr = pcb_remote_ip.addr;
pcb->remote_port = pcb_remote_port;
return err;
@@ -307,14 +399,6 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
return err;
}
}
/* find the outgoing network interface for this packet */
netif = ip_route(&(pcb->remote_ip));
/* no outgoing network interface could be found? */
if (netif == NULL) {
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%"X32_F"\n", pcb->remote_ip.addr));
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/* not enough space to add an UDP header to first pbuf in given p chain? */
if (pbuf_header(p, UDP_HLEN)) {
@@ -342,6 +426,12 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* in UDP, 0 checksum means 'no checksum' */
udphdr->chksum = 0x0000;
/* find the outgoing network interface for this packet */
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? */
if (ip_addr_isany(&pcb->local_ip)) {
/* use outgoing network interface IP address as source address */
@@ -351,40 +441,32 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
src_ip = &(pcb->local_ip);
}
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %u\n", q->tot_len));
/* UDP Lite protocol? */
if (pcb->flags & UDP_FLAGS_UDPLITE) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len));
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %u\n", q->tot_len));
/* set UDP message length in UDP header */
udphdr->len = htons(pcb->chksum_len);
/* calculate checksum */
#if CHECKSUM_GEN_UDP
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip),
IP_PROTO_UDP, pcb->chksum_len);
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
#else
udphdr->chksum = 0x0000;
#endif
/* output to IP */
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
err = ip_output_if (q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
/* UDP */
} else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
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%04"X16_F"\n", udphdr->chksum));
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04x\n", udphdr->chksum));
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
/* output to IP */
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
@@ -423,10 +505,12 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
u8_t rebind;
#if SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
ip_addr_debug_print(UDP_DEBUG, ipaddr);
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %"U16_F")\n", port));
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port));
rebind = 0;
/* Check for double bind and rebind of the same pcb */
@@ -439,6 +523,7 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
rebind = 1;
}
#if SO_REUSE == 0
/* 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
@@ -451,13 +536,56 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
ip_addr_isany(ipaddr) ||
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
/* other PCB already binds to this local IP and port */
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %u already bound by another pcb\n", port));
return ERR_USE;
}
#endif
#else /* SO_REUSE */
/* Search through list of PCB's.
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
But no two PCB's bound to same local port and same local address is valid.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
else if (ipcb->local_port == port) {
if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
}
}
#endif /* SO_REUSE */
}
#if SO_REUSE
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
{IP, port} can't be reused. */
if(!reuse_port_all_set) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n"));
return ERR_USE;
}
#endif /* SO_REUSE */
ip_addr_set(&pcb->local_ip, ipaddr);
/* no port specified? */
if (port == 0) {
@@ -487,11 +615,11 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
pcb->next = udp_pcbs;
udp_pcbs = pcb;
}
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
(u16_t)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
(u16_t)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
(u16_t)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
(u16_t)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %u.%u.%u.%u, port %u\n",
(unsigned int)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
(unsigned int)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
(unsigned int)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
(unsigned int)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
return ERR_OK;
}
/**
@@ -540,11 +668,11 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
pcb->local_ip.addr = 0;
}
#endif
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
(u16_t)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
(u16_t)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
(u16_t)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
(u16_t)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %u.%u.%u.%u, port %u\n",
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
(unsigned int)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
/* Insert UDP PCB into the list of active UDP PCBs. */
for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
@@ -629,17 +757,18 @@ udp_new(void) {
}
#if UDP_DEBUG
void
int
udp_debug_print(struct udp_hdr *udphdr)
{
LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
LWIP_DEBUGF(UDP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
ntohs(udphdr->src), ntohs(udphdr->dest)));
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n",
LWIP_DEBUGF(UDP_DEBUG, ("| %5u | 0x%04x | (len, chksum)\n",
ntohs(udphdr->len), ntohs(udphdr->chksum)));
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
return 0;
}
#endif /* UDP_DEBUG */

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

@@ -39,16 +39,13 @@
#include "lwip/ip_addr.h"
u16_t inet_chksum(void *dataptr, u16_t len);
#if 0 /* optimized routine */
u16_t inet_chksum4(u8_t *dataptr, u16_t len);
#endif
u16_t inet_chksum_pbuf(struct pbuf *p);
u16_t inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest,
u8_t proto, u16_t proto_len);
u32_t inet_addr(const char *cp);
s8_t inet_aton(const char *cp, struct in_addr *addr);
int inet_aton(const char *cp, struct in_addr *addr);
char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */
#ifdef htons

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

@@ -46,25 +46,11 @@ PACK_STRUCT_END
# 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;
@@ -116,16 +102,8 @@ extern const struct ip_addr ip_addr_broadcast;
#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,23 +111,26 @@ 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))
#define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \
ipaddr?(u16_t)ntohl((ipaddr)->addr) & 0xff:0U))
#define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%u.%u.%u.%u", \
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \
ipaddr?(unsigned int)ntohl((ipaddr)->addr) & 0xff:0U))
/* cast to unsigned int, as it is used as argument to printf functions
* which expect integer arguments. CSi: use cc.h formatters (conversion chars)! */
#define ip4_addr1(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff)
#define ip4_addr2(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff)
#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff)
* which expect integer arguments */
#define ip4_addr1(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff)
#define ip4_addr2(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff)
#define ip4_addr3(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff)
#define ip4_addr4(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr)) & 0xff)
#endif /* __LWIP_IP_ADDR_H__ */

View File

@@ -38,9 +38,8 @@
#include "lwip/netif.h"
#include "lwip/ip_addr.h"
void ip_reass_tmr(void);
struct pbuf * ip_reass(struct pbuf *p);
err_t ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest);
struct pbuf * ip_reass(struct pbuf *);
err_t ip_frag(struct pbuf *, struct netif *, struct ip_addr *);
#endif /* __LWIP_IP_FRAG_H__ */

View File

@@ -45,7 +45,7 @@ u16_t inet_chksum_pseudo(struct pbuf *p,
u8_t proto, u32_t proto_len);
u32_t inet_addr(const char *cp);
s8_t inet_aton(const char *cp, struct in_addr *addr);
int inet_aton(const char *cp, struct in_addr *addr);
#ifndef _MACHINE_ENDIAN_H_
#ifndef _NETINET_IN_H

View File

@@ -81,10 +81,10 @@ void ip_input(struct pbuf *p, struct netif *inp);
/* source and destination addresses in network byte order, please */
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto);
unsigned char ttl, unsigned char proto);
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto,
unsigned char ttl, unsigned char proto,
struct netif *netif);
#if IP_DEBUG

View File

@@ -45,11 +45,11 @@ struct ip_addr {
(ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \
(ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0)
u8_t 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);
u8_t ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2);
int ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2);
void ip_addr_set(struct ip_addr *dest, struct ip_addr *src);
u8_t ip_addr_isany(struct ip_addr *addr);
int ip_addr_isany(struct ip_addr *addr);
#if IP_DEBUG

View File

@@ -75,7 +75,7 @@ struct api_msg_msg {
struct {
void *dataptr;
u16_t len;
u8_t copy;
unsigned char copy;
} w;
sys_mbox_t mbox;
u16_t len;

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) && ((s16_t)((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

@@ -43,10 +43,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 +70,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 +82,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 +96,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 +174,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

@@ -52,8 +52,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,55 +61,52 @@
/** 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 */
struct dhcp *dhcp;
#endif
/** number of bytes used in hwaddr */
u8_t hwaddr_len;
unsigned char hwaddr_len;
/** link level hardware address of this interface */
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
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 +139,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

@@ -68,7 +68,7 @@ a lot of data that needs to be copied, this should be set high. */
#endif
#ifndef MEMP_SANITY_CHECK
#define MEMP_SANITY_CHECK 0
#define MEMP_SANITY_CHECK 0
#endif
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
@@ -146,10 +146,10 @@ a lot of data that needs to be copied, this should be set high. */
#endif
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
link level header. 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 +163,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 ---------- */
@@ -311,7 +309,7 @@ a lot of data that needs to be copied, this should be set high. */
/* Support loop interface (127.0.0.1) */
#ifndef LWIP_HAVE_LOOPIF
#define LWIP_HAVE_LOOPIF 0
#define LWIP_HAVE_LOOPIF 1
#endif
#ifndef LWIP_EVENT_API
@@ -346,10 +344,8 @@ a lot of data that needs to be copied, this should be set high. */
/* ---------- Socket Options ---------- */
/* Enable SO_REUSEADDR and SO_REUSEPORT options */
#ifdef SO_REUSE
/* I removed the lot since this was an ugly hack. It broke the raw-API.
It also came with many ugly goto's, Christiaan Simons. */
#error "SO_REUSE currently unavailable, this was a hack"
#ifndef SO_REUSE
# define SO_REUSE 1
#endif
@@ -365,63 +361,63 @@ a lot of data that needs to be copied, this should be set high. */
#endif
#ifndef LINK_STATS
#define LINK_STATS 1
#define LINK_STATS 1
#endif
#ifndef IP_STATS
#define IP_STATS 1
#define IP_STATS 1
#endif
#ifndef IPFRAG_STATS
#define IPFRAG_STATS 1
#define IPFRAG_STATS 1
#endif
#ifndef ICMP_STATS
#define ICMP_STATS 1
#define ICMP_STATS 1
#endif
#ifndef UDP_STATS
#define UDP_STATS 1
#define UDP_STATS 1
#endif
#ifndef TCP_STATS
#define TCP_STATS 1
#define TCP_STATS 1
#endif
#ifndef MEM_STATS
#define MEM_STATS 1
#define MEM_STATS 1
#endif
#ifndef MEMP_STATS
#define MEMP_STATS 1
#define MEMP_STATS 1
#endif
#ifndef PBUF_STATS
#define PBUF_STATS 1
#define PBUF_STATS 1
#endif
#ifndef SYS_STATS
#define SYS_STATS 1
#define SYS_STATS 1
#endif
#ifndef RAW_STATS
#define RAW_STATS 0
#define RAW_STATS 0
#endif
#else
#define LINK_STATS 0
#define IP_STATS 0
#define IPFRAG_STATS 0
#define ICMP_STATS 0
#define UDP_STATS 0
#define TCP_STATS 0
#define MEM_STATS 0
#define MEMP_STATS 0
#define PBUF_STATS 0
#define SYS_STATS 0
#define RAW_STATS 0
#define LWIP_STATS_DISPLAY 0
#define LINK_STATS 0
#define IP_STATS 0
#define IPFRAG_STATS 0
#define ICMP_STATS 0
#define UDP_STATS 0
#define TCP_STATS 0
#define MEM_STATS 0
#define MEMP_STATS 0
#define PBUF_STATS 0
#define SYS_STATS 0
#define RAW_STATS 0
#define LWIP_STATS_DISPLAY 0
#endif /* LWIP_STATS */
@@ -512,31 +508,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

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

@@ -105,7 +105,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 +112,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 +208,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 +235,7 @@ struct tcp_pcb {
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
#define TF_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */
/* receiver variables */
/* receiver varables */
u32_t rcv_nxt; /* next seqno expected */
u16_t rcv_wnd; /* receiver window */
@@ -248,10 +248,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 +375,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
#define TCP_EVENT_RECV(pcb,p,err,ret) \
if((pcb)->recv != NULL) \
{ ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
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 +387,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 */
@@ -439,7 +439,7 @@ void tcp_debug_print(struct tcp_hdr *tcphdr);
void tcp_debug_print_flags(u8_t flags);
void tcp_debug_print_state(enum tcp_state s);
void tcp_debug_print_pcbs(void);
s16_t tcp_pcbs_sane(void);
int tcp_pcbs_sane(void);
#else
# define tcp_debug_print(tcphdr)
# define tcp_debug_print_flags(flags)

View File

@@ -95,7 +95,7 @@ void udp_input (struct pbuf *p, struct netif *inp);
void udp_init (void);
#if UDP_DEBUG
void udp_debug_print(struct udp_hdr *udphdr);
int udp_debug_print(struct udp_hdr *udphdr);
#else
#define udp_debug_print(udphdr)
#endif

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

@@ -42,7 +42,6 @@
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include <lwip/stats.h>
#include "netif/etharp.h"
@@ -62,10 +61,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;
@@ -93,18 +95,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 +111,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 +128,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 +137,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 */
@@ -198,10 +177,30 @@ 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;
/* resolve the link destination hardware address */
p = etharp_output(netif, ipaddr, p);
/* network hardware address obtained? */
if (p == NULL)
{
/* we cannot tell if the packet was sent: the packet could */
/* have been queued on an ARP entry that was already pending. */
return ERR_OK;
}
/* send out the packet */
return low_level_output(ethernetif, p);
}
/*
@@ -219,43 +218,42 @@ ethernetif_input(struct netif *netif)
{
struct ethernetif *ethernetif;
struct eth_hdr *ethhdr;
struct pbuf *p;
struct pbuf *p, *q;
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
if (p != NULL)
return;
#ifdef LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
ethhdr = p->payload;
q = NULL;
switch (htons(ethhdr->type)) {
/* IP packet? */
case ETHTYPE_IP:
/* update ARP table */
etharp_ip_input(netif, p);
/* skip Ethernet header */
pbuf_header(p, -sizeof(struct eth_hdr));
/* pass to network layer */
netif->input(p, netif);
break;
case ETHTYPE_IP:
q = etharp_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);
q = etharp_arp_input(netif, ethernetif->ethaddr, p);
break;
default:
pbuf_free(p);
p = NULL;
break;
}
if (q != NULL) {
low_level_output(ethernetif, q);
pbuf_free(q);
q = NULL;
}
}
static void
@@ -274,7 +272,7 @@ arp_timer(void *arg)
*
*/
err_t
void
ethernetif_init(struct netif *netif)
{
struct ethernetif *ethernetif;
@@ -300,7 +298,5 @@ ethernetif_init(struct netif *netif)
etharp_init();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
return ERR_OK;
}

View File

@@ -58,7 +58,7 @@ loopif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr)
{
struct pbuf *q, *r;
u8_t *ptr;
char *ptr;
void **arg;
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)

View File

@@ -51,7 +51,6 @@
* 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 $
*/
#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"

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"
@@ -1235,7 +1232,7 @@ static int lcp_reqci(fsm *f,
ho->neg_mru = 1; /* Remember he sent MRU */
ho->mru = cishort; /* And remember value */
#if TRACELCP > 0
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort);
sprintf(&traceBuf[traceNdx], " MRU %d", cishort);
traceNdx = strlen(traceBuf);
#endif
break;
@@ -1268,7 +1265,7 @@ static int lcp_reqci(fsm *f,
ho->neg_asyncmap = 1;
ho->asyncmap = cilong;
#if TRACELCP > 0
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong);
sprintf(&traceBuf[traceNdx], " ASYNCMAP=%lX", cilong);
traceNdx = strlen(traceBuf);
#endif
break;
@@ -1320,7 +1317,7 @@ static int lcp_reqci(fsm *f,
}
ho->neg_upap = 1;
#if TRACELCP > 0
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort);
sprintf(&traceBuf[traceNdx], " PAP (%X)", cishort);
traceNdx = strlen(traceBuf);
#endif
break;
@@ -1358,7 +1355,7 @@ static int lcp_reqci(fsm *f,
break;
}
#if TRACELCP > 0
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, cichar);
sprintf(&traceBuf[traceNdx], " CHAP %X,%d", cishort, cichar);
traceNdx = strlen(traceBuf);
#endif
ho->chap_mdtype = cichar; /* save md type */
@@ -1390,7 +1387,7 @@ static int lcp_reqci(fsm *f,
GETSHORT(cishort, p);
GETLONG(cilong, p);
#if TRACELCP > 0
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " QUALITY (%x %x)", cishort, (unsigned int) cilong);
sprintf(&traceBuf[traceNdx], " QUALITY (%x %x)", cishort, (unsigned int) cilong);
traceNdx = strlen(traceBuf);
#endif
@@ -1422,7 +1419,7 @@ static int lcp_reqci(fsm *f,
}
GETLONG(cilong, p);
#if TRACELCP > 0
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong);
sprintf(&traceBuf[traceNdx], " MAGICNUMBER (%lX)", cilong);
traceNdx = strlen(traceBuf);
#endif
@@ -1445,7 +1442,7 @@ static int lcp_reqci(fsm *f,
case CI_PCOMPRESSION:
#if TRACELCP > 0
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION");
sprintf(&traceBuf[traceNdx], " PCOMPRESSION");
traceNdx = strlen(traceBuf);
#endif
if (!ao->neg_pcompression ||
@@ -1458,7 +1455,7 @@ static int lcp_reqci(fsm *f,
case CI_ACCOMPRESSION:
#if TRACELCP > 0
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION");
sprintf(&traceBuf[traceNdx], " ACCOMPRESSION");
traceNdx = strlen(traceBuf);
#endif
if (!ao->neg_accompression ||
@@ -1471,7 +1468,7 @@ static int lcp_reqci(fsm *f,
case CI_MRRU:
#if TRACELCP > 0
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU");
sprintf(&traceBuf[traceNdx], " CI_MRRU");
traceNdx = strlen(traceBuf);
#endif
orc = CONFREJ;
@@ -1479,7 +1476,7 @@ static int lcp_reqci(fsm *f,
case CI_SSNHF:
#if TRACELCP > 0
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF");
sprintf(&traceBuf[traceNdx], " CI_SSNHF");
traceNdx = strlen(traceBuf);
#endif
orc = CONFREJ;
@@ -1487,7 +1484,7 @@ static int lcp_reqci(fsm *f,
case CI_EPDISC:
#if TRACELCP > 0
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC");
sprintf(&traceBuf[traceNdx], " CI_EPDISC");
traceNdx = strlen(traceBuf);
#endif
orc = CONFREJ;
@@ -1495,7 +1492,7 @@ static int lcp_reqci(fsm *f,
default:
#if TRACELCP
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype);
sprintf(&traceBuf[traceNdx], " unknown %d", citype);
traceNdx = strlen(traceBuf);
#endif
orc = CONFREJ;

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,8 +1,6 @@
/*
* Definitions for tcp compression routines.
*
* $Id: vj.h,v 1.4 2004/02/07 00:30:03 likewise Exp $
*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved.
*

View File

@@ -32,9 +32,9 @@
*/
/*
* This is an arch independent SLIP netif. The specific serial hooks must be
* provided by another file. They are sio_open, sio_recv and sio_send
*/
* This is an arch independent SLIP netif. The specific serial hooks must be provided
* by another file.They are sio_open, sio_recv and sio_send
*/
#include "netif/slipif.h"
#include "lwip/opt.h"
@@ -55,32 +55,32 @@
* Send a pbuf doing the necessary SLIP encapsulation
*
* Uses the serial layer's sio_send()
*/
*/
err_t
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
{
struct pbuf *q;
u16_t i;
int i;
u8_t c;
/* Send pbuf out on the serial I/O device. */
sio_send(SLIP_END, netif->state);
for (q = p; q != NULL; q = q->next) {
for (i = 0; i < q->len; i++) {
for(q = p; q != NULL; q = q->next) {
for(i = 0; i < q->len; i++) {
c = ((u8_t *)q->payload)[i];
switch (c) {
case SLIP_END:
sio_send(SLIP_ESC, netif->state);
sio_send(SLIP_ESC_END, netif->state);
break;
sio_send(SLIP_ESC, netif->state);
sio_send(SLIP_ESC_END, netif->state);
break;
case SLIP_ESC:
sio_send(SLIP_ESC, netif->state);
sio_send(SLIP_ESC_ESC, netif->state);
break;
sio_send(SLIP_ESC, netif->state);
sio_send(SLIP_ESC_ESC, netif->state);
break;
default:
sio_send(c, netif->state);
break;
sio_send(c, netif->state);
break;
}
}
}
@@ -94,14 +94,14 @@ slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
* Poll the serial layer by calling sio_recv()
*
* @return The IP packet when SLIP_END is received
*/
*/
static struct pbuf *
slipif_input(struct netif *netif)
slipif_input( struct netif * netif )
{
u8_t c;
struct pbuf *p, *q;
u16_t recved;
u16_t i;
int recved;
int i;
q = p = NULL;
recved = i = 0;
@@ -112,13 +112,13 @@ slipif_input(struct netif *netif)
switch (c) {
case SLIP_END:
if (recved > 0) {
/* Received whole packet. */
pbuf_realloc(q, recved);
LINK_STATS_INC(link.recv);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
return q;
/* Received whole packet. */
pbuf_realloc(q, recved);
LINK_STATS_INC(link.recv);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
return q;
}
break;
@@ -126,54 +126,51 @@ slipif_input(struct netif *netif)
c = sio_recv(netif->state);
switch (c) {
case SLIP_ESC_END:
c = SLIP_END;
break;
c = SLIP_END;
break;
case SLIP_ESC_ESC:
c = SLIP_ESC;
break;
c = SLIP_ESC;
break;
}
/* FALLTHROUGH */
default:
if (p == NULL) {
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
if (p == NULL) {
LINK_STATS_INC(link.drop);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
}
if (q != NULL) {
pbuf_cat(q, p);
} else {
q = p;
}
if (p == NULL) {
LINK_STATS_INC(link.drop);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
}
if (q != NULL) {
pbuf_cat(q, p);
} else {
q = p;
}
}
if (p != NULL && recved < MAX_SIZE) {
((u8_t *)p->payload)[i] = c;
recved++;
i++;
if (i >= p->len) {
i = 0;
if (p->next != NULL && p->next->len > 0)
p = p->next;
else
p = NULL;
}
((u8_t *)p->payload)[i] = c;
recved++;
i++;
if (i >= p->len) {
i = 0;
p = NULL;
}
}
break;
}
}
return NULL;
}
/**
* The SLIP input thread.
* The SLIP input thread
*
* Feed the IP layer with incoming packets
*/
*/
static void
slipif_loop(void *nf)
{
@@ -191,22 +188,22 @@ slipif_loop(void *nf)
*
* Call the arch specific sio_open and remember
* the opened device in the state field of the netif.
*/
*/
err_t
slipif_init(struct netif *netif)
{
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num));
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%x\n", (int)netif->num));
netif->name[0] = 's';
netif->name[1] = 'l';
netif->output = slipif_output;
netif->mtu = 1500;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_POINTTOPOINT;
netif->state = sio_open(netif->num);
if (!netif->state)
return ERR_IF;
return ERR_IF;
sys_thread_new(slipif_loop, netif, SLIPIF_THREAD_PRIO);
return ERR_OK;