Compare commits

...

87 Commits

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

114
CHANGELOG
View File

@@ -1,13 +1,51 @@
TODO
* TODO: Fix unaligned 16-bit access in checksum routine.
* TODO: Fix assumptions on storage sizes wherever we cast.
* TODO: See why large ICMP (ping) packets do not work (fragmentation?).
HISTORY
(current)
(DEVEL)
++ Bug fixes:
* Fixed DHCP which did not include the IP address in DECLINE messages.
(STABLE-0_6_5)
++ Bug fixes:
* Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic.
* Packets sent from ARP queue had invalid source hardware address.
++ Changes:
* Pass-by ARP requests do now update the cache.
++ New features:
* No longer dependent on ctype.h.
* New socket options.
* Raw IP pcb support.
(STABLE-0_6_4)
++ Bug fixes:
* Some debug formatters and casts fixed.
* Numereous fixes in PPP.
++ Changes:
* DEBUGF now is LWIP_DEBUGF
* pbuf_dechain() has been re-enabled.
* Mentioned the changed use of CVS branches in README.
(STABLE-0_6_3)
++ Bug fixes:
* Fixed pool pbuf memory leak in pbuf_alloc().
Occured if not enough PBUF_POOL pbufs for a packet pbuf chain.
Reported by Savin Zlobec.
@@ -20,11 +58,11 @@ HISTORY
* Added PPP stack contributed by Marc Boucher
++ Changes:
* Now drops short packets for ICMP/UDP/TCP protocols. More robust.
* ARP queueuing now queues the latest packet instead of the first.
This is the recommended behaviour, but can be overridden in
This is the RFC recommended behaviour, but can be overridden in
lwipopts.h.
(0.6.2)
@@ -80,10 +118,10 @@ HISTORY
* netif's have a dhcp field that must be initialized to NULL by the driver.
See the contrib/ports/c16x cs8900 driver as a driver example.
(0.5.x) This file has been unmaintained up to 0.6.1. All changes are
logged in CVS but have not been explained here.
(0.5.3) Changes since version 0.5.2
++ Bugfixes:
@@ -115,7 +153,7 @@ HISTORY
* pbuf_dechain() did not update the ->tot_len field of the tail.
* Aborted TCP connections were not handled correctly in all
situations.
situations.
++ Other changes:
@@ -123,7 +161,7 @@ HISTORY
* The ->len field in the tcp_seg structure now counts the actual
amount of data, and does not add one for SYN and FIN segments.
(0.5.1) Changes since version 0.5.0
++ New features:
@@ -133,16 +171,16 @@ HISTORY
* Preliminary support for cross platform packed structs.
* ARP timer now implemented.
++ Bugfixes:
* TCP output queue length was badly initialized when opening
connections.
* TCP delayed ACKs were not sent correctly.
* Explicit initialization of BSS segment variables.
* read() in BSD socket library could drop data.
* Problems with memory alignment.
@@ -156,7 +194,7 @@ HISTORY
* IP multicast address tests had endianess problems.
* ARP requests had wrong destination hardware address.
* ARP requests had wrong destination hardware address.
++ Other changes:
@@ -166,8 +204,8 @@ HISTORY
* TCP and UDP ->dest_* struct members where changed to ->remote_*.
* ntoh* macros are now null definitions for big endian CPUs.
* ntoh* macros are now null definitions for big endian CPUs.
(0.5.0) Changes since version 0.4.2
++ New features:
@@ -175,9 +213,9 @@ HISTORY
* Redesigned operating system emulation layer to make porting easier.
* Better control over TCP output buffers.
* Documenation added.
++ Bugfixes:
* Locking issues in buffer management.
@@ -190,7 +228,7 @@ HISTORY
* Directory structure somewhat changed; the core/ tree has been
collapsed.
(0.4.2) Changes since version 0.4.1
++ New features:
@@ -213,7 +251,7 @@ HISTORY
* Variable++ have in appliciable cases been translated to ++variable
since some compilers generate better code in the latter case.
(0.4.1) Changes since version 0.4
++ New features:
@@ -225,43 +263,43 @@ HISTORY
* UDP: experimental support for UDP-Lite extensions.
++ Bugfixes:
* TCP: out of order segments were in some cases handled incorrectly,
and this has now been fixed. Delayed acknowledgements was broken
in 0.4, has now been fixed. Binding to an address that is in use
now results in an error. Reset connections sometimes hung an
application; this has been fixed.
application; this has been fixed.
* Checksum calculation sometimes failed for chained pbufs with odd
lengths. This has been fixed.
* API: a lot of bug fixes in the API. The UDP API has been improved
and tested. Error reporting and handling has been
improved. Logical flaws and race conditions for incoming TCP
connections has been found and removed.
connections has been found and removed.
* Memory manager: alignment issues. Reallocating memory sometimes
failed, this has been fixed.
* Generic library: bcopy was flawed and has been fixed.
* Generic library: bcopy was flawed and has been fixed.
++ Other changes:
* API: all datatypes has been changed from generic ones such as
ints, to specified ones such as u16_t. Functions that return
errors now have the correct type (err_t).
* General: A lot of code cleaned up and debugging code removed. Many
portability issues have been fixed.
* The license was changed; the advertising clause was removed.
* The license was changed; the advertising clause was removed.
* C64 port added.
* Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri
Kosunen, Mikael Caleres, and Frits Wilmink for reporting and
fixing bugs!
(0.4) Changes since version 0.3.1
* Memory management has been radically changed; instead of
@@ -269,14 +307,14 @@ HISTORY
rapidly allocated and deallocated is now kept in pools. Allocation
and deallocation from those memory pools is very fast. The shared
heap is still present but is used less frequently.
* The memory, memory pool, and packet buffer subsystems now support
4-, 2-, or 1-byte alignment.
* "Out of memory" situations are handled in a more robust way.
* Stack usage has been reduced.
* Easier configuration of lwIP parameters such as memory usage,
TTLs, statistics gathering, etc. All configuration parameters are
now kept in a single header file "lwipopts.h".
@@ -290,7 +328,7 @@ HISTORY
* The code for the RTXC architecture has been implemented, tested
and put to use.
* Bugs have been found and corrected in the TCP, UDP, IP, API, and
the Internet checksum modules.
@@ -299,7 +337,7 @@ HISTORY
* The license has been changed slightly to conform more with the
original BSD license, including the advertisement clause.
(0.3.1) Changes since version 0.3
* Fix of a fatal bug in the buffer management. Pbufs with allocated
@@ -325,10 +363,10 @@ HISTORY
to free some memory and retry the allocation.
* Much testing has been done with limited memory
configurations. lwIP now does a better job when overloaded.
configurations. lwIP now does a better job when overloaded.
* Some bugfixes and improvements to the buffer (pbuf) subsystem.
* Many bugfixes in the TCP code:
- Fixed a bug in tcp_close().
@@ -355,15 +393,15 @@ HISTORY
- TCP retransmission timeout backoffs are not correctly computed
(ala BSD). After a number of retransmissions, TCP now gives up
the connection.
* TCP connections now are kept on three lists, one for active
connections, one for listening connections, and one for
connections that are in TIME-WAIT. This greatly speeds up the fast
timeout processing for sending delayed ACKs.
* TCP now provides proper feedback to the application when a
connection has been successfully set up.
* More comments have been added to the code. The code has also been
somewhat cleaned up.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

24
README
View File

@@ -34,16 +34,31 @@ and developers using the stack often submit bug fixes, improvements,
and additions to the stack to further increase its usefulness.
Development of lwIP is hosted on Savannah, a central point for
software development, maintenance and distribution. A core team
will improve lwIP by the use of Savannah's interface and CVS.
software development, maintenance and distribution. Everyone can
help improve lwIP by use of Savannah's interface, CVS and the
mailing list. A core team of developers will commit changes to the
CVS source tree.
The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and
contributions (such as platform ports) are in the 'contrib' module.
The current lwIP CVS tree can be checked out by doing:
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
@@ -58,9 +73,6 @@ The current CVS trees are web-browsable:
Submit patches and bugs via the lwIP project page:
http://savannah.nongnu.org/projects/lwip/
The main branch is the active development branch, whereas the 'STABLE'
branch aims to be bug-free, without the latest changes. Keep track of
the lwIP users mailing list for the statusses of both.
DOCUMENTATION

View File

@@ -4,13 +4,14 @@ Table of Contents:
1 - Anonymous CVS checkouts and updates (to be elaborated)
2 - Committers/developers CVS access using SSH (to be written)
3 - How to release lwIP
3 - Merging from DEVEL branch to main trunk (stable branch)
4 - How to release lwIP
1 Anonymous CVS checkouts and updates
-------------------------------------
Obtain lwIP from the STABLE tree (on the CVS main trunk)
Obtain lwIP from the CVS main trunk (stable)
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip
@@ -23,9 +24,39 @@ cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_6_
Or, obtain a development branch as follows:
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-devel lwip
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-DEVEL lwip
3 How to release lwIP
3 Merging from DEVEL branch to main trunk (stable)
---------------------------------------------------------
Merging is a delicate process in CVS and requires the
following disciplined steps in order to prevent conflicts
in the future. Conflicts can be hard to solve!
Merging from branch A to branch B requires that the A branch
has a tag indicating the previous merger. This tag is called
'merged_from_A_to_B'. After merging, the tag is moved in the
A branch to remember this merger for future merge actions.
IMPORTANT: AFTER COMMITTING A SUCCESFUL MERGE IN THE
REPOSITORY, THE TAG MUST BE SET ON THE SOURCE BRANCH OF THE
MERGE ACTION (REPLACING EXISTING TAGS WITH THE SAME NAME).
Merge all changes in DEVEL since our last merge to main:
In the working copy of the main trunk:
cvs update -P -jmerged_from_DEVEL_to_main -jDEVEL
(This will apply the changes between 'merged_from_DEVEL_to_main'
and 'DEVEL' to your work set of files)
If this worked out OK, we now move the tag in the DEVEL branch
to this merge point, so we can use this point for future merges:
cvs rtag -F -r DEVEL merged_from_DEVEL_to_main lwip
4 How to release lwIP
---------------------
First, checkout a clean copy of the branch to be released. Tag this set with
@@ -38,7 +69,7 @@ is not created locally.
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip export -r STABLE-0_6_3 -d lwip-0.6.3 lwip
Archive this directory using tar.
Archive this directory using tar, gzip'd, bzip2'd and zip'd.
tar czvf lwip-0.6.3.tar.gz lwip-0.6.3
@@ -51,17 +82,15 @@ 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):
mkdir stable.pkg
cd stable.pkg
mkdir 0.6.3
cd 0.6.3
mkdir stable.pkg 0.6.3
We can now copy the tar archive we made earlier into the release directory:
cp /../../../lwip-0.6.3.tar.gz .
cp ../../../lwip-0.6.3.tar.gz .
Finally, synchronize this directory upwards to Savannah:
rsync -n -e "ssh -1" -t -u -v -r . likewise@savannah.nongnu.org:/upload/lwip
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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -38,13 +38,13 @@
#include "lwip/api_msg.h"
#include "lwip/memp.h"
/*-----------------------------------------------------------------------------------*/
struct
netbuf *netbuf_new(void)
{
struct netbuf *buf;
buf = memp_mallocp(MEMP_NETBUF);
buf = memp_malloc(MEMP_NETBUF);
if (buf != NULL) {
buf->p = NULL;
buf->ptr = NULL;
@@ -53,7 +53,7 @@ netbuf *netbuf_new(void)
return NULL;
}
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_delete(struct netbuf *buf)
{
@@ -62,10 +62,10 @@ netbuf_delete(struct netbuf *buf)
pbuf_free(buf->p);
buf->p = buf->ptr = NULL;
}
memp_freep(MEMP_NETBUF, buf);
memp_free(MEMP_NETBUF, buf);
}
}
/*-----------------------------------------------------------------------------------*/
void *
netbuf_alloc(struct netbuf *buf, u16_t size)
{
@@ -80,7 +80,7 @@ netbuf_alloc(struct netbuf *buf, u16_t size)
buf->ptr = buf->p;
return buf->p->payload;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_free(struct netbuf *buf)
{
@@ -89,7 +89,7 @@ netbuf_free(struct netbuf *buf)
}
buf->p = buf->ptr = NULL;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
{
@@ -101,21 +101,21 @@ netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
buf->p->len = buf->p->tot_len = size;
buf->ptr = buf->p;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_chain(struct netbuf *head, struct netbuf *tail)
{
pbuf_chain(head->p, tail->p);
head->ptr = head->p;
memp_freep(MEMP_NETBUF, tail);
memp_free(MEMP_NETBUF, tail);
}
/*-----------------------------------------------------------------------------------*/
u16_t
netbuf_len(struct netbuf *buf)
{
return buf->p->tot_len;
}
/*-----------------------------------------------------------------------------------*/
err_t
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
{
@@ -126,7 +126,7 @@ netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
*len = buf->ptr->len;
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
s8_t
netbuf_next(struct netbuf *buf)
{
@@ -139,13 +139,13 @@ netbuf_next(struct netbuf *buf)
}
return 0;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_first(struct netbuf *buf)
{
buf->ptr = buf->p;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
{
@@ -154,7 +154,7 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
left = 0;
if (buf == NULL) {
if(buf == NULL || dataptr == NULL) {
return;
}
@@ -174,39 +174,43 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
}
}
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
{
netbuf_copy_partial(buf, dataptr, len, 0);
}
/*-----------------------------------------------------------------------------------*/
struct ip_addr *
netbuf_fromaddr(struct netbuf *buf)
{
return buf->fromaddr;
}
/*-----------------------------------------------------------------------------------*/
u16_t
netbuf_fromport(struct netbuf *buf)
{
return buf->fromport;
}
/*-----------------------------------------------------------------------------------*/
struct
netconn *netconn_new(enum netconn_type t)
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
{
struct netconn *conn;
struct api_msg *msg;
conn = memp_mallocp(MEMP_NETCONN);
conn = memp_malloc(MEMP_NETCONN);
if (conn == NULL) {
return NULL;
}
conn->err = ERR_OK;
conn->type = t;
conn->pcb.tcp = NULL;
if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
memp_freep(MEMP_NETCONN, conn);
memp_free(MEMP_NETCONN, conn);
return NULL;
}
conn->recvmbox = SYS_MBOX_NULL;
@@ -214,25 +218,44 @@ netconn *netconn_new(enum netconn_type t)
conn->sem = SYS_SEM_NULL;
conn->state = NETCONN_NONE;
conn->socket = 0;
conn->callback = 0;
conn->callback = callback;
conn->recv_avail = 0;
if((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
memp_free(MEMP_NETCONN, conn);
return NULL;
}
msg->type = API_MSG_NEWCONN;
msg->msg.msg.bc.port = proto; /* misusing the port field */
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_free(MEMP_API_MSG, msg);
if ( conn->err != ERR_OK ) {
memp_free(MEMP_NETCONN, conn);
return NULL;
}
return conn;
}
/*-----------------------------------------------------------------------------------*/
struct
netconn *netconn_new(enum netconn_type t)
{
return netconn_new_with_proto_and_callback(t,0,NULL);
}
struct
netconn *netconn_new_with_callback(enum netconn_type t,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
{
struct netconn *conn;
/* get a netconn and then initialize callback pointer and socket */
conn = netconn_new(t);
if (conn)
conn->callback = callback;
return conn;
return netconn_new_with_proto_and_callback(t,0,callback);
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_delete(struct netconn *conn)
{
@@ -243,7 +266,7 @@ netconn_delete(struct netconn *conn)
return ERR_OK;
}
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return ERR_MEM;
}
@@ -251,7 +274,7 @@ netconn_delete(struct netconn *conn)
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
memp_free(MEMP_API_MSG, msg);
/* Drain the recvmbox. */
if (conn->recvmbox != SYS_MBOX_NULL) {
@@ -286,18 +309,21 @@ netconn_delete(struct netconn *conn)
memp_free(MEMP_NETCONN, conn);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
enum netconn_type
netconn_type(struct netconn *conn)
{
return conn->type;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_peer(struct netconn *conn, struct ip_addr *addr,
u16_t *port)
{
switch (conn->type) {
case NETCONN_RAW:
/* return an error as connecting is only a helper for upper layers */
return ERR_CONN;
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
case NETCONN_UDP:
@@ -316,12 +342,16 @@ netconn_peer(struct netconn *conn, struct ip_addr *addr,
}
return (conn->err = ERR_OK);
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_addr(struct netconn *conn, struct ip_addr **addr,
u16_t *port)
{
switch (conn->type) {
case NETCONN_RAW:
*addr = &(conn->pcb.raw->local_ip);
*port = conn->pcb.raw->protocol;
break;
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
case NETCONN_UDP:
@@ -335,7 +365,7 @@ netconn_addr(struct netconn *conn, struct ip_addr **addr,
}
return (conn->err = ERR_OK);
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_bind(struct netconn *conn, struct ip_addr *addr,
u16_t port)
@@ -353,7 +383,7 @@ netconn_bind(struct netconn *conn, struct ip_addr *addr,
}
}
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
msg->type = API_MSG_BIND;
@@ -362,11 +392,11 @@ netconn_bind(struct netconn *conn, struct ip_addr *addr,
msg->msg.msg.bc.port = port;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_connect(struct netconn *conn, struct ip_addr *addr,
u16_t port)
@@ -384,7 +414,7 @@ netconn_connect(struct netconn *conn, struct ip_addr *addr,
}
}
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return ERR_MEM;
}
msg->type = API_MSG_CONNECT;
@@ -393,7 +423,7 @@ netconn_connect(struct netconn *conn, struct ip_addr *addr,
msg->msg.msg.bc.port = port;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
@@ -406,18 +436,18 @@ netconn_disconnect(struct netconn *conn)
return ERR_VAL;
}
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return ERR_MEM;
}
msg->type = API_MSG_DISCONNECT;
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_listen(struct netconn *conn)
{
@@ -434,17 +464,17 @@ netconn_listen(struct netconn *conn)
}
}
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
msg->type = API_MSG_LISTEN;
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
struct netconn *
netconn_accept(struct netconn *conn)
{
@@ -461,7 +491,7 @@ netconn_accept(struct netconn *conn)
return newconn;
}
/*-----------------------------------------------------------------------------------*/
struct netbuf *
netconn_recv(struct netconn *conn)
{
@@ -490,7 +520,7 @@ netconn_recv(struct netconn *conn)
}
buf = memp_mallocp(MEMP_NETBUF);
buf = memp_malloc(MEMP_NETBUF);
if (buf == NULL) {
conn->err = ERR_MEM;
@@ -514,7 +544,7 @@ netconn_recv(struct netconn *conn)
/* If we are closed, we indicate that we no longer wish to receive
data by setting conn->recvmbox to SYS_MBOX_NULL. */
if (p == NULL) {
memp_freep(MEMP_NETBUF, buf);
memp_free(MEMP_NETBUF, buf);
sys_mbox_free(conn->recvmbox);
conn->recvmbox = SYS_MBOX_NULL;
return NULL;
@@ -526,7 +556,7 @@ netconn_recv(struct netconn *conn)
buf->fromaddr = NULL;
/* Let the stack know that we have taken the data. */
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
conn->err = ERR_MEM;
return buf;
}
@@ -540,7 +570,7 @@ netconn_recv(struct netconn *conn)
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
memp_free(MEMP_API_MSG, msg);
} else {
sys_mbox_fetch(conn->recvmbox, (void **)&buf);
conn->recv_avail -= buf->p->tot_len;
@@ -557,7 +587,7 @@ netconn_recv(struct netconn *conn)
return buf;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_send(struct netconn *conn, struct netbuf *buf)
{
@@ -571,7 +601,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
return conn->err;
}
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
@@ -582,10 +612,10 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
{
@@ -607,7 +637,7 @@ netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
}
}
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
msg->type = API_MSG_WRITE;
@@ -652,7 +682,7 @@ netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
}
}
ret:
memp_freep(MEMP_API_MSG, msg);
memp_free(MEMP_API_MSG, msg);
conn->state = NETCONN_NONE;
if (conn->sem != SYS_SEM_NULL) {
sys_sem_free(conn->sem);
@@ -661,7 +691,7 @@ netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_close(struct netconn *conn)
{
@@ -670,7 +700,7 @@ netconn_close(struct netconn *conn)
if (conn == NULL) {
return ERR_VAL;
}
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
@@ -686,13 +716,13 @@ netconn_close(struct netconn *conn)
goto again;
}
conn->state = NETCONN_NONE;
memp_freep(MEMP_API_MSG, msg);
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_err(struct netconn *conn)
{
return conn->err;
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -37,6 +37,37 @@
#include "lwip/sys.h"
#include "lwip/tcpip.h"
#if LWIP_RAW
static int
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
struct ip_addr *addr)
{
struct netbuf *buf;
struct netconn *conn;
conn = arg;
if (!conn) return 0;
if (conn->recvmbox != SYS_MBOX_NULL) {
if (!(buf = memp_malloc(MEMP_NETBUF))) {
return 0;
}
pbuf_ref(p);
buf->p = p;
buf->ptr = p;
buf->fromaddr = addr;
buf->fromport = pcb->protocol;
conn->recv_avail += p->tot_len;
/* Register event with callback */
if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
sys_mbox_post(conn->recvmbox, buf);
}
return 0; /* do not eat the packet */
}
#endif
#if LWIP_UDP
static void
recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
@@ -52,7 +83,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
return;
}
if (conn->recvmbox != SYS_MBOX_NULL) {
buf = memp_mallocp(MEMP_NETBUF);
buf = memp_malloc(MEMP_NETBUF);
if (buf == NULL) {
pbuf_free(p);
return;
@@ -72,7 +103,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
}
#endif /* LWIP_UDP */
#if LWIP_TCP
/*-----------------------------------------------------------------------------------*/
static err_t
recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
@@ -103,7 +134,7 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
poll_tcp(void *arg, struct tcp_pcb *pcb)
{
@@ -117,7 +148,7 @@ poll_tcp(void *arg, struct tcp_pcb *pcb)
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
{
@@ -134,7 +165,7 @@ sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static void
err_tcp(void *arg, err_t err)
{
@@ -165,7 +196,7 @@ err_tcp(void *arg, err_t err)
sys_sem_signal(conn->sem);
}
}
/*-----------------------------------------------------------------------------------*/
static void
setup_tcp(struct netconn *conn)
{
@@ -178,7 +209,7 @@ setup_tcp(struct netconn *conn)
tcp_poll(pcb, poll_tcp, 4);
tcp_err(pcb, err_tcp);
}
/*-----------------------------------------------------------------------------------*/
static err_t
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
{
@@ -193,7 +224,7 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
#endif /* API_MSG_DEBUG */
conn = (struct netconn *)arg;
mbox = conn->acceptmbox;
newconn = memp_mallocp(MEMP_NETCONN);
newconn = memp_malloc(MEMP_NETCONN);
if (newconn == NULL) {
return ERR_MEM;
}
@@ -234,17 +265,83 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
return ERR_OK;
}
#endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/
static void
do_newconn(struct api_msg_msg *msg)
{
if(msg->conn->pcb.tcp != NULL) {
/* This "new" connection already has a PCB allocated. */
/* Is this an error condition? Should it be deleted?
We currently just are happy and return. */
sys_mbox_post(msg->conn->mbox, NULL);
return;
}
msg->conn->err = ERR_OK;
/* Allocate a PCB for this connection */
switch(msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDPNOCHKSUM:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDP:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
msg->conn->pcb.tcp = tcp_new();
if(msg->conn->pcb.tcp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
setup_tcp(msg->conn);
break;
#endif
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_delconn(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
raw_remove(msg->conn->pcb.raw);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
@@ -287,12 +384,18 @@ do_delconn(struct api_msg_msg *msg)
sys_mbox_post(msg->conn->mbox, NULL);
}
}
/*-----------------------------------------------------------------------------------*/
static void
do_bind(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp == NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new();
@@ -319,6 +422,11 @@ do_bind(struct api_msg_msg *msg)
}
}
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
@@ -339,7 +447,7 @@ do_bind(struct api_msg_msg *msg)
sys_mbox_post(msg->conn->mbox, NULL);
}
#if LWIP_TCP
/*-----------------------------------------------------------------------------------*/
static err_t
do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
@@ -359,12 +467,18 @@ do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
return ERR_OK;
}
#endif
/*-----------------------------------------------------------------------------------*/
static void
do_connect(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp == NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new();
@@ -410,6 +524,12 @@ do_connect(struct api_msg_msg *msg)
}
}
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
sys_mbox_post(msg->conn->mbox, NULL);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
@@ -428,6 +548,7 @@ do_connect(struct api_msg_msg *msg)
do_connected);
/*tcp_output(msg->conn->pcb.tcp);*/
#endif
default:
break;
}
@@ -438,6 +559,11 @@ do_disconnect(struct api_msg_msg *msg)
{
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
/* Do nothing as connecting is only a helper for upper lwip layers */
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
@@ -453,12 +579,17 @@ do_disconnect(struct api_msg_msg *msg)
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_listen(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
@@ -491,12 +622,17 @@ do_listen(struct api_msg_msg *msg)
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_accept(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
@@ -511,12 +647,17 @@ do_accept(struct api_msg_msg *msg)
}
}
}
/*-----------------------------------------------------------------------------------*/
static void
do_send(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
raw_send(msg->conn->pcb.raw, msg->msg.p);
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
@@ -532,7 +673,7 @@ do_send(struct api_msg_msg *msg)
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_recv(struct api_msg_msg *msg)
{
@@ -545,7 +686,7 @@ do_recv(struct api_msg_msg *msg)
#endif
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_write(struct api_msg_msg *msg)
{
@@ -554,6 +695,11 @@ do_write(struct api_msg_msg *msg)
#endif
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->err = ERR_VAL;
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
@@ -571,7 +717,7 @@ do_write(struct api_msg_msg *msg)
segments when new outgoing data arrives from the user if any
previously transmitted data on the connection remains
unacknowledged. */
if (err == ERR_OK && msg->conn->pcb.tcp->unacked == NULL) {
if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL || (msg->conn->pcb.tcp->flags & TF_NODELAY)) ) {
tcp_output(msg->conn->pcb.tcp);
}
msg->conn->err = err;
@@ -588,7 +734,7 @@ do_write(struct api_msg_msg *msg)
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_close(struct api_msg_msg *msg)
{
@@ -598,6 +744,10 @@ do_close(struct api_msg_msg *msg)
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
@@ -619,7 +769,7 @@ do_close(struct api_msg_msg *msg)
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
typedef void (* api_msg_decode)(struct api_msg_msg *msg);
static api_msg_decode decode[API_MSG_MAX] = {
do_newconn,
@@ -639,12 +789,12 @@ api_msg_input(struct api_msg *msg)
{
decode[msg->type](&(msg->msg));
}
/*-----------------------------------------------------------------------------------*/
void
api_msg_post(struct api_msg *msg)
{
tcpip_apimsg(msg);
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -47,13 +47,13 @@ static char *err_strerr[] = {"Ok.",
"Address in use."
};
/*-----------------------------------------------------------------------------------*/
char *
lwip_strerr(err_t err)
{
return err_strerr[-err];
}
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_DEBUG */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -99,7 +99,7 @@ static int err_to_errno_table[11] = {
set_errno(sk->err); \
} while (0)
/*-----------------------------------------------------------------------------------*/
static struct lwip_socket *
get_socket(int s)
{
@@ -121,7 +121,7 @@ get_socket(int s)
return sock;
}
/*-----------------------------------------------------------------------------------*/
static int
alloc_socket(struct netconn *newconn)
{
@@ -150,7 +150,7 @@ alloc_socket(struct netconn *newconn)
sys_sem_signal(socksem);
return -1;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
@@ -164,6 +164,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -197,16 +198,14 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
newconn->socket = newsock;
sys_sem_signal(socksem);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port));
#endif
sock_set_errno(sock, 0);
return newsock;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
{
@@ -217,17 +216,16 @@ lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
local_port = ((struct sockaddr_in *)name)->sin_port;
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port)));
#endif
err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
@@ -241,7 +239,7 @@ lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_close(int s)
{
@@ -257,6 +255,7 @@ lwip_close(int s)
sock = get_socket(s);
if (!sock) {
sys_sem_signal(socksem);
set_errno(EBADF);
return -1;
}
@@ -271,7 +270,7 @@ lwip_close(int s)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
{
@@ -280,6 +279,7 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -293,11 +293,9 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
remote_port = ((struct sockaddr_in *)name)->sin_port;
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
#endif
err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
}
@@ -312,7 +310,7 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_listen(int s, int backlog)
{
@@ -322,6 +320,7 @@ lwip_listen(int s, int backlog)
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -336,7 +335,7 @@ lwip_listen(int s, int backlog)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
struct sockaddr *from, socklen_t *fromlen)
@@ -351,6 +350,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -411,11 +411,9 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
memcpy(from, &sin, *fromlen);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
#endif
} else {
#if SOCKETS_DEBUG > 0
addr = netbuf_fromaddr(buf);
@@ -444,19 +442,19 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
sock_set_errno(sock, 0);
return copylen;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_read(int s, void *mem, int len)
{
return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
}
/*-----------------------------------------------------------------------------------*/
int
lwip_recv(int s, void *mem, int len, unsigned int flags)
{
return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
}
/*-----------------------------------------------------------------------------------*/
int
lwip_send(int s, void *data, int size, unsigned int flags)
{
@@ -468,11 +466,15 @@ lwip_send(int s, void *data, int size, unsigned int flags)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
switch (netconn_type(sock->conn)) {
case NETCONN_RAW:
case NETCONN_UDP:
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
/* create a buffer */
buf = netbuf_new();
@@ -509,7 +511,7 @@ lwip_send(int s, void *data, int size, unsigned int flags)
sock_set_errno(sock, 0);
return size;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_sendto(int s, void *data, int size, unsigned int flags,
struct sockaddr *to, socklen_t tolen)
@@ -521,6 +523,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -530,11 +533,9 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
remote_port = ((struct sockaddr_in *)to)->sin_port;
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags));
ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));
#endif
netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
@@ -548,7 +549,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
netconn_disconnect(sock->conn);
return ret;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_socket(int domain, int type, int protocol)
{
@@ -557,6 +558,10 @@ lwip_socket(int domain, int type, int protocol)
/* create a netconn */
switch (type) {
case SOCK_RAW:
conn = netconn_new_with_proto_and_callback(NETCONN_RAW, protocol, event_callback);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
break;
case SOCK_DGRAM:
conn = netconn_new_with_callback(NETCONN_UDP, event_callback);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
@@ -589,14 +594,14 @@ lwip_socket(int domain, int type, int protocol)
set_errno(0);
return i;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_write(int s, void *data, int size)
{
return lwip_send(s, data, size, 0);
}
/*-----------------------------------------------------------------------------------*/
static int
lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
{
@@ -643,7 +648,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
}
/*-----------------------------------------------------------------------------------*/
int
lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
struct timeval *timeout)
@@ -723,7 +728,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
/* Wait forever */
msectimeout = 0;
else
msectimeout = ((timeout->tv_sec * 1000) + (timeout->tv_usec /1000));
msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
@@ -789,7 +794,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
return nready;
}
/*-----------------------------------------------------------------------------------*/
static void
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
{
@@ -878,7 +883,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
}
/*-----------------------------------------------------------------------------------*/
int lwip_shutdown(int s, int how)
@@ -895,6 +900,7 @@ int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -905,11 +911,9 @@ int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
/* get the IP address and port of the remote host */
netconn_peer(sock->conn, &naddr, &sin.sin_port);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
#endif
sin.sin_port = htons(sin.sin_port);
sin.sin_addr.s_addr = naddr.addr;
@@ -930,6 +934,7 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -940,11 +945,9 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
/* get the IP address and port of the remote host */
netconn_addr(sock->conn, &naddr, &sin.sin_port);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
#endif
sin.sin_port = htons(sin.sin_port);
sin.sin_addr.s_addr = naddr->addr;
@@ -959,32 +962,190 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)
{
int err = ENOSYS;
int err = 0;
struct lwip_socket *sock = get_socket(s);
if (!sock) {
if(!sock) {
set_errno(EBADF);
return -1;
}
if (level == SOL_SOCKET) {
switch (optname) {
if( NULL == optval || NULL == optlen ) {
sock_set_errno( sock, EFAULT );
return -1;
}
/* Do length and type checks for the various options first, to keep it readable. */
switch( level ) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch(optname) {
case SO_ACCEPTCONN:
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_ERROR:
if (!optval || !optlen || (*optlen != sizeof(int))) {
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINLINE: */
/* UNIMPL case SO_RCVBUF: */
/* UNIMPL case SO_SNDBUF: */
/* UNIMPL case SO_RCVLOWAT: */
/* UNIMPL case SO_SNDLOWAT: */
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
case SO_TYPE:
/* UNIMPL case SO_USELOOPBACK: */
if( *optlen < sizeof(int) ) {
err = EINVAL;
break;
}
*(int *)optval = sock->err;
sock->err = 0;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
err = 0;
break;
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch(optname) {
/* UNIMPL case IP_HDRINCL: */
/* UNIMPL case IP_RCVDSTADDR: */
/* UNIMPL case IP_RCVIF: */
case IP_TTL:
case IP_TOS:
if( *optlen < sizeof(int) ) {
err = EINVAL;
}
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
if( *optlen < sizeof(int) ) {
err = EINVAL;
break;
}
} else {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
/* If this is no TCP socket, ignore any options. */
if ( sock->conn->type != NETCONN_TCP ) return 0;
switch( optname ) {
case TCP_NODELAY:
case TCP_KEEPALIVE:
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* UNDEFINED LEVEL */
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
err = ENOPROTOOPT;
} /* switch */
if( 0 != err ) {
sock_set_errno(sock, err);
return -1;
}
/* Now do the actual option processing */
switch(level) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch( optname ) {
/* The option flags */
case SO_ACCEPTCONN:
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINCLUDE: */
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
/*case SO_USELOOPBACK: UNIMPL */
*(int*)optval = sock->conn->pcb.tcp->so_options & optname;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", s, optname, (*(int*)optval?"on":"off")));
break;
case SO_TYPE:
switch (sock->conn->type) {
case NETCONN_RAW:
*(int*)optval = SOCK_RAW;
break;
case NETCONN_TCP:
*(int*)optval = SOCK_STREAM;
break;
case NETCONN_UDP:
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
*(int*)optval = SOCK_DGRAM;
break;
default: /* unrecognized socket type */
*(int*)optval = sock->conn->type;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", s, *(int *)optval));
} /* switch */
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", s, *(int *)optval));
break;
case SO_ERROR:
*(int *)optval = sock->err;
sock->err = 0;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
break;
} /* switch */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch( optname ) {
case IP_TTL:
*(int*)optval = sock->conn->pcb.tcp->ttl;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", s, *(int *)optval));
break;
case IP_TOS:
*(int*)optval = sock->conn->pcb.tcp->tos;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", s, *(int *)optval));
break;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
switch( optname ) {
case TCP_NODELAY:
*(int*)optval = (sock->conn->pcb.tcp->flags & TF_NODELAY);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") );
break;
case TCP_KEEPALIVE:
*(int*)optval = sock->conn->pcb.tcp->keepalive;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
break;
} /* switch */
break;
}
sock_set_errno(sock, err);
return err ? -1 : 0;
}
@@ -992,27 +1153,165 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
{
struct lwip_socket *sock = get_socket(s);
int err = ENOSYS;
int err = 0;
if (!sock) {
if(!sock) {
set_errno(EBADF);
return -1;
}
if (level == SOL_SOCKET) {
switch (optname) {
case SO_REUSEADDR:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, ..)\n", s));
/* XXX just pretend we support this for now */
err = 0;
if( NULL == optval ) {
sock_set_errno( sock, EFAULT );
return -1;
}
/* Do length and type checks for the various options first, to keep it readable. */
switch( level ) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch(optname) {
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINLINE: */
/* UNIMPL case SO_RCVBUF: */
/* UNIMPL case SO_SNDBUF: */
/* UNIMPL case SO_RCVLOWAT: */
/* UNIMPL case SO_SNDLOWAT: */
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
/* UNIMPL case SO_USELOOPBACK: */
if( optlen < sizeof(int) ) {
err = EINVAL;
}
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch(optname) {
/* UNIMPL case IP_HDRINCL: */
/* UNIMPL case IP_RCVDSTADDR: */
/* UNIMPL case IP_RCVIF: */
case IP_TTL:
case IP_TOS:
if( optlen < sizeof(int) ) {
err = EINVAL;
}
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
if( optlen < sizeof(int) ) {
err = EINVAL;
break;
}
} else {
/* If this is no TCP socket, ignore any options. */
if ( sock->conn->type != NETCONN_TCP ) return 0;
switch( optname ) {
case TCP_NODELAY:
case TCP_KEEPALIVE:
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* UNDEFINED LEVEL */
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
err = ENOPROTOOPT;
} /* switch */
if( 0 != err ) {
sock_set_errno(sock, err);
return -1;
}
/* Now do the actual option processing */
switch(level) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch(optname) {
/* The option flags */
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINCLUDE: */
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
/* UNIMPL case SO_USELOOPBACK: */
if ( *(int*)optval ) {
sock->conn->pcb.tcp->so_options |= optname;
} else {
sock->conn->pcb.tcp->so_options &= ~optname;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(int*)optval?"on":"off")));
break;
} /* switch */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch( optname ) {
case IP_TTL:
sock->conn->pcb.tcp->ttl = (u8_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n", s, sock->conn->pcb.tcp->ttl));
break;
case IP_TOS:
sock->conn->pcb.tcp->tos = (u8_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n", s, sock->conn->pcb.tcp->tos));
break;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
switch( optname ) {
case TCP_NODELAY:
if ( *(int*)optval ) {
sock->conn->pcb.tcp->flags |= TF_NODELAY;
} else {
sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s, (*(int *)optval)?"on":"off") );
break;
case TCP_KEEPALIVE:
sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %u\n", s, sock->conn->pcb.tcp->keepalive));
break;
} /* switch */
break;
} /* switch */
sock_set_errno(sock, err);
return err ? -1 : 0;
}
@@ -1021,7 +1320,8 @@ int lwip_ioctl(int s, long cmd, void *argp)
{
struct lwip_socket *sock = get_socket(s);
if (!sock) {
if(!sock) {
set_errno(EBADF);
return -1;
}
@@ -1035,7 +1335,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
*((u16_t*)argp) = sock->conn->recv_avail;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
sock_set_errno(sock, 0);
sock_set_errno(sock, 0);
return 0;
case FIONBIO:
@@ -1044,7 +1344,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
else
sock->flags &= ~O_NONBLOCK;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
sock_set_errno(sock, 0);
sock_set_errno(sock, 0);
return 0;
default:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -50,7 +50,7 @@ static sys_mbox_t mbox;
static int tcpip_tcp_timer_active = 0;
/*-----------------------------------------------------------------------------------*/
static void
tcpip_tcp_timer(void *arg)
{
@@ -73,7 +73,7 @@ tcp_timer_needed(void)
}
}
#endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/
static void
tcpip_thread(void *arg)
{
@@ -110,16 +110,16 @@ tcpip_thread(void *arg)
default:
break;
}
memp_freep(MEMP_TCPIP_MSG, msg);
memp_free(MEMP_TCPIP_MSG, msg);
}
}
/*-----------------------------------------------------------------------------------*/
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG);
msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) {
pbuf_free(p);
return ERR_MEM;
@@ -131,13 +131,13 @@ tcpip_input(struct pbuf *p, struct netif *inp)
sys_mbox_post(mbox, msg);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
err_t
tcpip_callback(void (*f)(void *ctx), void *ctx)
{
struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG);
msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) {
return ERR_MEM;
}
@@ -148,12 +148,12 @@ tcpip_callback(void (*f)(void *ctx), void *ctx)
sys_mbox_post(mbox, msg);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
tcpip_apimsg(struct api_msg *apimsg)
{
struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG);
msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) {
memp_free(MEMP_API_MSG, apimsg);
return;
@@ -162,7 +162,7 @@ tcpip_apimsg(struct api_msg *apimsg)
msg->msg.apimsg = apimsg;
sys_mbox_post(mbox, msg);
}
/*-----------------------------------------------------------------------------------*/
void
tcpip_init(void (* initfunc)(void *), void *arg)
{
@@ -171,7 +171,7 @@ tcpip_init(void (* initfunc)(void *), void *arg)
mbox = sys_mbox_new();
sys_thread_new(tcpip_thread, NULL, TCPIP_THREAD_PRIO);
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -6,8 +6,8 @@
/*
*
* Copyright (c) 2001-2003 Leon Woestenberg <leon.woestenberg@gmx.net>
* Copyright (c) 2001-2003 Axon Digital Design B.V., The Netherlands.
* Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
* Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -192,6 +192,7 @@ static void dhcp_handle_offer(struct netif *netif)
/* remember offered address */
ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08lx\n", dhcp->offered_ip_addr.addr));
dhcp_select(netif);
}
}
@@ -646,6 +647,9 @@ static err_t dhcp_decline(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_REQUESTED_IP, 4);
dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
dhcp_option_trailer(dhcp);
/* resize pbuf to reflect true size of options */
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -30,14 +30,14 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* inet.c
*
* Functions common to all TCP/IP modules, such as the Internet checksum and the
* byte order functions.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -47,7 +47,7 @@
#include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
static u16_t
lwip_chksum(void *dataptr, int len)
{
@@ -75,12 +75,12 @@ lwip_chksum(void *dataptr, int len)
return (u16_t)acc;
}
/*-----------------------------------------------------------------------------------*/
/* inet_chksum_pseudo:
*
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
*/
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest,
@@ -124,13 +124,13 @@ inet_chksum_pseudo(struct pbuf *p,
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
return ~(acc & 0xffffUL);
}
/*-----------------------------------------------------------------------------------*/
/* inet_chksum:
*
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
* and ICMP.
*/
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum(void *dataptr, u16_t len)
{
@@ -142,7 +142,7 @@ inet_chksum(void *dataptr, u16_t len)
}
return ~(acc & 0xffff);
}
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pbuf(struct pbuf *p)
{
@@ -169,7 +169,17 @@ inet_chksum_pbuf(struct pbuf *p)
return ~(acc & 0xffffUL);
}
/*-----------------------------------------------------------------------------------*/
/* Here for now until needed in other places in lwIP */
#ifndef isascii
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
#define isascii(c) in_range(c, 0x20, 0x7f)
#define isdigit(c) in_range(c, '0', '9')
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
#define islower(c) in_range(c, 'a', 'z')
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
#endif
/*
* Ascii internet address interpretation routine.
* The value returned is in network order.
@@ -318,24 +328,24 @@ u8_t *inet_ntoa(u32_t addr)
return str;
}
/*-----------------------------------------------------------------------------------*/
#ifndef BYTE_ORDER
#error BYTE_ORDER is not defined
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
/*-----------------------------------------------------------------------------------*/
u16_t
htons(u16_t n)
{
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
}
/*-----------------------------------------------------------------------------------*/
u16_t
ntohs(u16_t n)
{
return htons(n);
}
/*-----------------------------------------------------------------------------------*/
u32_t
htonl(u32_t n)
{
@@ -344,11 +354,11 @@ htonl(u32_t n)
((n & 0xff0000) >> 8) |
((n & 0xff000000) >> 24);
}
/*-----------------------------------------------------------------------------------*/
u32_t
ntohl(u32_t n)
{
return htonl(n);
}
/*-----------------------------------------------------------------------------------*/
#endif /* BYTE_ORDER == LITTLE_ENDIAN */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -30,14 +30,14 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* inet6.c
*
* Functions common to all TCP/IP modules, such as the Internet checksum and the
* byte order functions.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -45,7 +45,7 @@
#include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
/* chksum:
*
* Sums up all 16 bit words in a memory portion. Also includes any odd byte.
@@ -54,7 +54,7 @@
* For now, this is not optimized. Must be optimized for the particular processor
* arcitecture on which it is to run. Preferebly coded in assembler.
*/
/*-----------------------------------------------------------------------------------*/
static u32_t
chksum(void *dataptr, u16_t len)
{
@@ -74,12 +74,12 @@ chksum(void *dataptr, u16_t len)
return acc;
}
/*-----------------------------------------------------------------------------------*/
/* inet_chksum_pseudo:
*
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
*/
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest,
@@ -122,13 +122,13 @@ inet_chksum_pseudo(struct pbuf *p,
}
return ~(acc & 0xffff);
}
/*-----------------------------------------------------------------------------------*/
/* inet_chksum:
*
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
* and ICMP.
*/
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum(void *dataptr, u16_t len)
{
@@ -139,7 +139,7 @@ inet_chksum(void *dataptr, u16_t len)
sum += (sum >> 16);
return ~(sum & 0xffff);
}
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pbuf(struct pbuf *p)
{
@@ -165,4 +165,4 @@ inet_chksum_pbuf(struct pbuf *p)
}
return ~(acc & 0xffff);
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -43,7 +43,7 @@
#include "lwip/stats.h"
#include "lwip/snmp.h"
/*-----------------------------------------------------------------------------------*/
void
icmp_input(struct pbuf *p, struct netif *inp)
{
@@ -54,9 +54,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
struct ip_addr tmpaddr;
u16_t hlen;
#ifdef ICMP_STATS
++lwip_stats.icmp.recv;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.recv);
snmp_inc_icmpinmsgs();
@@ -65,9 +63,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len));
pbuf_free(p);
#ifdef ICMP_STATS
++lwip_stats.icmp.lenerr;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.lenerr);
snmp_inc_icmpinerrors();
return;
}
@@ -79,20 +75,15 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) ||
ip_addr_ismulticast(&iphdr->dest)) {
LWIP_DEBUGF(ICMP_DEBUG, ("Smurf.\n"));
#ifdef ICMP_STATS
++lwip_stats.icmp.err;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.err);
pbuf_free(p);
return;
}
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
LWIP_DEBUGF(DEMO_DEBUG, ("Pong!\n"));
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
pbuf_free(p);
#ifdef ICMP_STATS
++lwip_stats.icmp.lenerr;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.lenerr);
snmp_inc_icmpinerrors();
return;
@@ -101,9 +92,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (inet_chksum_pbuf(p) != 0) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
pbuf_free(p);
#ifdef ICMP_STATS
++lwip_stats.icmp.chkerr;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.chkerr);
snmp_inc_icmpinerrors();
return;
}
@@ -117,28 +106,24 @@ icmp_input(struct pbuf *p, struct netif *inp)
} else {
iecho->chksum += htons(ICMP_ECHO << 8);
}
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of echo replies attempted to send */
snmp_inc_icmpoutechoreps();
pbuf_header(p, hlen);
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
IPH_TTL(iphdr), IP_PROTO_ICMP, inp);
ip_output_if(p, &(iphdr->src), IP_HDRINCL,
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
break;
default:
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code));
#ifdef ICMP_STATS
++lwip_stats.icmp.proterr;
++lwip_stats.icmp.drop;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.proterr);
ICMP_STATS_INC(icmp.drop);
}
pbuf_free(p);
}
/*-----------------------------------------------------------------------------------*/
void
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
{
@@ -160,19 +145,17 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
/* calculate checksum */
idur->chksum = 0;
idur->chksum = inet_chksum(idur, q->len);
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpoutdestunreachs();
ip_output(q, NULL, &(iphdr->src),
ICMP_TTL, IP_PROTO_ICMP);
ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q);
}
/*-----------------------------------------------------------------------------------*/
#if IP_FORWARD
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
@@ -184,13 +167,11 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
iphdr = p->payload;
#if ICMP_DEBUG
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
#endif /* ICMP_DEBNUG */
tehdr = q->payload;
ICMPH_TYPE_SET(tehdr, ICMP_TE);
@@ -202,19 +183,17 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
/* calculate checksum */
tehdr->chksum = 0;
tehdr->chksum = inet_chksum(tehdr, q->len);
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpouttimeexcds();
ip_output(q, NULL, &(iphdr->src),
ICMP_TTL, IP_PROTO_ICMP);
ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q);
}
#endif /* IP_FORWARDING > 0 */
#endif /* IP_FORWARD */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -31,13 +31,13 @@
*/
/*-----------------------------------------------------------------------------------*/
/* ip.c
*
* This is the code for the IP layer.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -49,6 +49,7 @@
#include "lwip/inet.h"
#include "lwip/netif.h"
#include "lwip/icmp.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
@@ -61,67 +62,17 @@
# include "lwip/dhcp.h"
#endif /* LWIP_DHCP */
/*-----------------------------------------------------------------------------------*/
/* ip_init:
*
* Initializes the IP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_init(void)
{
}
/*-----------------------------------------------------------------------------------*/
/* ip_lookup:
*
* An experimental feature that will be changed in future versions. Do
* not depend on it yet...
*/
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
u8_t
ip_lookup(void *header, struct netif *inp)
{
struct ip_hdr *iphdr;
iphdr = header;
/* not IP v4? */
if (IPH_V(iphdr) != 4) {
return 0;
}
/* Immediately accept/decline packets that are fragments or has
options. */
#if IP_REASSEMBLY == 0
/* if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
return 0;
}*/
#endif /* IP_REASSEMBLY == 0 */
#if IP_OPTIONS == 0
if (IPH_HL(iphdr) != 5) {
return 0;
}
#endif /* IP_OPTIONS == 0 */
switch (IPH_PROTO(iphdr)) {
#if LWIP_UDP > 0
case IP_PROTO_UDP:
return udp_lookup(iphdr, inp);
#endif /* LWIP_UDP */
#if LWIP_TCP > 0
case IP_PROTO_TCP:
return 1;
#endif /* LWIP_TCP */
case IP_PROTO_ICMP:
return 1;
default:
return 0;
}
}
#endif /* LWIP_DEBUG */
/*-----------------------------------------------------------------------------------*/
/* ip_route:
*
* Finds the appropriate network interface for a given IP address. It
@@ -129,7 +80,7 @@ ip_lookup(void *header, struct netif *inp)
* if the masked IP address of the network interface equals the masked
* IP address given to the function.
*/
/*-----------------------------------------------------------------------------------*/
struct netif *
ip_route(struct ip_addr *dest)
{
@@ -147,14 +98,14 @@ ip_route(struct ip_addr *dest)
return netif_default;
}
#if IP_FORWARD
/*-----------------------------------------------------------------------------------*/
/* ip_forward:
*
* Forwards an IP packet. It finds an appropriate route for the
* packet, decrements the TTL value of the packet, adjusts the
* checksum and outputs the packet on the appropriate interface.
*/
/*-----------------------------------------------------------------------------------*/
static void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
{
@@ -199,10 +150,8 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
iphdr->dest.addr));
#ifdef IP_STATS
++lwip_stats.ip.fw;
++lwip_stats.ip.xmit;
#endif /* IP_STATS */
IP_STATS_INC(ip.fw);
IP_STATS_INC(ip.xmit);
snmp_inc_ipforwdatagrams();
PERF_STOP("ip_forward");
@@ -210,7 +159,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
}
#endif /* IP_FORWARD */
/*-----------------------------------------------------------------------------------*/
/* ip_input:
*
* This function is called by the network interface device driver when
@@ -221,30 +170,24 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
*
* Finally, the packet is sent to the upper layer protocol input function.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_input(struct pbuf *p, struct netif *inp) {
static struct ip_hdr *iphdr;
static struct netif *netif;
static u16_t iphdrlen;
#ifdef IP_STATS
++lwip_stats.ip.recv;
#endif /* IP_STATS */
IP_STATS_INC(ip.recv);
snmp_inc_ipinreceives();
/* identify the IP header */
iphdr = p->payload;
if (IPH_V(iphdr) != 4) {
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %u\n", IPH_V(iphdr)));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.err;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.err);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
@@ -259,10 +202,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
iphdrlen, p->len));
/* free (drop) packet pbufs */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.lenerr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.lenerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipindiscards();
return ERR_OK;
}
@@ -271,14 +212,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
if (inet_chksum(iphdr, iphdrlen) != 0) {
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.chkerr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.chkerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipindiscards();
return ERR_OK;
}
@@ -363,10 +300,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
ntohs(IPH_OFFSET(iphdr))));
#ifdef IP_STATS
++lwip_stats.ip.opterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
@@ -376,30 +311,31 @@ ip_input(struct pbuf *p, struct netif *inp) {
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);
#ifdef IP_STATS
++lwip_stats.ip.opterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
#endif /* IP_OPTIONS == 0 */
/* send to upper layers */
#if IP_DEBUG
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
ip_debug_print(p);
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
#endif /* IP_DEBUG */
#if LWIP_RAW
if (!raw_input(p, inp)) {
#endif /* LWIP_RAW */
switch (IPH_PROTO(iphdr)) {
#if LWIP_UDP > 0
#if LWIP_UDP
case IP_PROTO_UDP:
case IP_PROTO_UDPLITE:
snmp_inc_ipindelivers();
udp_input(p, inp);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP > 0
#if LWIP_TCP
case IP_PROTO_TCP:
snmp_inc_ipindelivers();
tcp_input(p, inp);
@@ -420,17 +356,18 @@ ip_input(struct pbuf *p, struct netif *inp) {
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
#ifdef IP_STATS
++lwip_stats.ip.proterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.proterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
}
#if LWIP_RAW
} /* LWIP_RAW */
#endif
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* ip_output_if:
*
* Sends an IP packet on a network interface. This function constructs
@@ -438,10 +375,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
* IP address is NULL, the IP address of the outgoing network
* interface is filled in as source address.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl,
ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t tos,
u8_t proto, struct netif *netif)
{
static struct ip_hdr *iphdr;
@@ -453,9 +390,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
if (pbuf_header(p, IP_HLEN)) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
#ifdef IP_STATS
++lwip_stats.ip.err;
#endif /* IP_STATS */
IP_STATS_INC(ip.err);
snmp_inc_ipoutdiscards();
return ERR_BUF;
}
@@ -467,7 +402,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
ip_addr_set(&(iphdr->dest), dest);
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
IPH_LEN_SET(iphdr, htons(p->tot_len));
IPH_OFFSET_SET(iphdr, htons(IP_DF));
IPH_ID_SET(iphdr, htons(ip_id));
@@ -492,44 +427,39 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
return ip_frag(p,netif,dest);
#endif
#ifdef IP_STATS
lwip_stats.ip.xmit++;
#endif /* IP_STATS */
IP_STATS_INC(ip.xmit);
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
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.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto)
u8_t ttl, u8_t tos, u8_t proto)
{
struct netif *netif;
if ((netif = ip_route(dest)) == NULL) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr));
#ifdef IP_STATS
++lwip_stats.ip.rterr;
#endif /* IP_STATS */
IP_STATS_INC(ip.rterr);
snmp_inc_ipoutdiscards();
return ERR_RTE;
}
return ip_output_if (p, src, dest, ttl, proto, netif);
return ip_output_if(p, src, dest, ttl, tos, proto, netif);
}
/*-----------------------------------------------------------------------------------*/
#if IP_DEBUG
void
ip_debug_print(struct pbuf *p)
@@ -573,7 +503,7 @@ ip_debug_print(struct pbuf *p)
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -31,13 +31,13 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* ip_frag.c
*
* This is the code for IP segmentation and reassembly
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
#include "lwip/sys.h"
@@ -109,9 +109,7 @@ ip_reass(struct pbuf *p)
u16_t offset, len;
u16_t i;
#ifdef IP_STATS
++lwip_stats.ip_frag.recv;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.recv);
iphdr = (struct ip_hdr *) ip_reassbuf;
fraghdr = (struct ip_hdr *) p->payload;
@@ -135,9 +133,7 @@ ip_reass(struct pbuf *p)
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n"));
#ifdef IP_STATS
++lwip_stats.ip_frag.cachehit;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.cachehit);
/* Find out the offset in the reassembly buffer where we should
copy the fragment. */
len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
@@ -255,13 +251,9 @@ ip_reass(struct pbuf *p)
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
i += q->len;
}
#ifdef IP_STATS
++lwip_stats.ip_frag.fw;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.fw);
} else {
#ifdef IP_STATS
++lwip_stats.ip_frag.memerr;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.memerr);
}
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
return p;
@@ -269,9 +261,7 @@ ip_reass(struct pbuf *p)
}
nullreturn:
#ifdef IP_STATS
++lwip_stats.ip_frag.drop;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.drop);
pbuf_free(p);
return NULL;
}
@@ -347,9 +337,7 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
pbuf_chain(header, rambuf);
netif->output(netif, header, dest);
#ifdef IP_STATS
++lwip_stats.ip_frag.xmit;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.xmit);
pbuf_free(header);
left -= cop;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -42,7 +42,7 @@
#include "lwip/stats.h"
/*-----------------------------------------------------------------------------------*/
void
icmp_input(struct pbuf *p, struct netif *inp)
{
@@ -113,7 +113,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
pbuf_free(p);
}
/*-----------------------------------------------------------------------------------*/
void
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
{
@@ -143,7 +143,7 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
(struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
pbuf_free(q);
}
/*-----------------------------------------------------------------------------------*/
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -31,13 +31,13 @@
*/
/*-----------------------------------------------------------------------------------*/
/* ip.c
*
* This is the code for the IP layer for IPv6.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -53,24 +53,24 @@
#include "lwip/stats.h"
#include "arch/perf.h"
/*-----------------------------------------------------------------------------------*/
/* ip_init:
*
* Initializes the IP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_init(void)
{
}
/*-----------------------------------------------------------------------------------*/
/* 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 IP address given to the function.
*/
/*-----------------------------------------------------------------------------------*/
struct netif *
ip_route(struct ip_addr *dest)
{
@@ -84,14 +84,14 @@ ip_route(struct ip_addr *dest)
return netif_default;
}
/*-----------------------------------------------------------------------------------*/
/* ip_forward:
*
* Forwards an IP packet. It finds an appropriate route for the packet, decrements
* the TTL value of the packet, adjusts the checksum and outputs the packet on the
* appropriate interface.
*/
/*-----------------------------------------------------------------------------------*/
static void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
{
@@ -142,7 +142,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
}
/*-----------------------------------------------------------------------------------*/
/* ip_input:
*
* This function is called by the network interface device driver when an IP packet is
@@ -152,7 +152,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
*
* Finally, the packet is sent to the upper layer protocol input function.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_input(struct pbuf *p, struct netif *inp) {
struct ip_hdr *iphdr;
@@ -249,14 +249,14 @@ ip_input(struct pbuf *p, struct netif *inp) {
PERF_STOP("ip_input");
}
/*-----------------------------------------------------------------------------------*/
/* 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 interface is filled in as source address.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl,
@@ -311,13 +311,13 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
PERF_STOP("ip_output_if");
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.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto)
@@ -333,7 +333,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
return ip_output_if (p, src, dest, ttl, proto, netif);
}
/*-----------------------------------------------------------------------------------*/
#if IP_DEBUG
void
ip_debug_print(struct pbuf *p)
@@ -383,4 +383,4 @@ ip_debug_print(struct pbuf *p)
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -33,7 +33,7 @@
#include "lwip/ip_addr.h"
#include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
int
ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
struct ip_addr *mask)
@@ -44,7 +44,7 @@ ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
(addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3]));
}
/*-----------------------------------------------------------------------------------*/
int
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
{
@@ -53,7 +53,7 @@ ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
addr1->addr[2] == addr2->addr[2] &&
addr1->addr[3] == addr2->addr[3]);
}
/*-----------------------------------------------------------------------------------*/
void
ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
{
@@ -63,7 +63,7 @@ ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
dest->addr[2] = src->addr[2];
dest->addr[3] = src->addr[3];*/
}
/*-----------------------------------------------------------------------------------*/
int
ip_addr_isany(struct ip_addr *addr)
{
@@ -71,7 +71,7 @@ ip_addr_isany(struct ip_addr *addr)
return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0);
}
/*-----------------------------------------------------------------------------------*/
/*#if IP_DEBUG*/
void
ip_addr_debug_print(struct ip_addr *addr)
@@ -87,4 +87,4 @@ ip_addr_debug_print(struct ip_addr *addr)
ntohl(addr->addr[3]) & 0xffff);
}
/*#endif*/ /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -127,7 +127,7 @@ mem_init(void)
lfree = (struct mem *)ram;
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.avail = MEM_SIZE;
#endif /* MEM_STATS */
}
@@ -148,7 +148,7 @@ mem_free(void *rmem)
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
#ifdef MEM_STATS
#if MEM_STATS
++lwip_stats.mem.err;
#endif /* MEM_STATS */
sys_sem_signal(mem_sem);
@@ -164,7 +164,7 @@ mem_free(void *rmem)
lfree = mem;
}
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
#endif /* MEM_STATS */
@@ -183,7 +183,7 @@ mem_reallocm(void *rmem, mem_size_t newsize)
mem_free(rmem);
return nmem;
}
/*-----------------------------------------------------------------------------------*/
void *
mem_realloc(void *rmem, mem_size_t newsize)
{
@@ -215,7 +215,7 @@ mem_realloc(void *rmem, mem_size_t newsize)
ptr = (u8_t *)mem - ram;
size = mem->next - ptr - SIZEOF_STRUCT_MEM;
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.used -= (size - newsize);
#endif /* MEM_STATS */
@@ -273,7 +273,7 @@ mem_malloc(mem_size_t size)
mem2->used = 0;
mem->used = 1;
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
/* if (lwip_stats.mem.max < lwip_stats.mem.used) {
lwip_stats.mem.max = lwip_stats.mem.used;
@@ -299,7 +299,7 @@ mem_malloc(mem_size_t size)
}
}
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size));
#ifdef MEM_STATS
#if MEM_STATS
++lwip_stats.mem.err;
#endif /* MEM_STATS */
sys_sem_signal(mem_sem);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -36,6 +36,7 @@
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/raw.h"
#include "lwip/tcp.h"
#include "lwip/api.h"
#include "lwip/api_msg.h"
@@ -54,6 +55,7 @@ static struct memp *memp_tab[MEMP_MAX];
static const u16_t memp_sizes[MEMP_MAX] = {
sizeof(struct pbuf),
sizeof(struct raw_pcb),
sizeof(struct udp_pcb),
sizeof(struct tcp_pcb),
sizeof(struct tcp_pcb_listen),
@@ -67,6 +69,7 @@ static const u16_t memp_sizes[MEMP_MAX] = {
static const u16_t memp_num[MEMP_MAX] = {
MEMP_NUM_PBUF,
MEMP_NUM_RAW_PCB,
MEMP_NUM_UDP_PCB,
MEMP_NUM_TCP_PCB,
MEMP_NUM_TCP_PCB_LISTEN,
@@ -81,6 +84,9 @@ static const u16_t memp_num[MEMP_MAX] = {
static u8_t memp_memory[(MEMP_NUM_PBUF *
MEM_ALIGN_SIZE(sizeof(struct pbuf) +
sizeof(struct memp)) +
MEMP_NUM_RAW_PCB *
MEM_ALIGN_SIZE(sizeof(struct raw_pcb) +
sizeof(struct memp)) +
MEMP_NUM_UDP_PCB *
MEM_ALIGN_SIZE(sizeof(struct udp_pcb) +
sizeof(struct memp)) +
@@ -109,12 +115,12 @@ static u8_t memp_memory[(MEMP_NUM_PBUF *
MEM_ALIGN_SIZE(sizeof(struct sys_timeout) +
sizeof(struct memp)))];
/*-----------------------------------------------------------------------------------*/
#if !SYS_LIGHTWEIGHT_PROT
static sys_sem_t mutex;
#endif
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
#ifndef LWIP_NOASSERT
static int
memp_sanity(void)
{
@@ -135,7 +141,7 @@ memp_sanity(void)
return 1;
}
#endif /* LWIP_DEBUG */
/*-----------------------------------------------------------------------------------*/
void
memp_init(void)
{
@@ -143,7 +149,7 @@ memp_init(void)
u16_t i, j;
u16_t size;
#ifdef MEMP_STATS
#if MEMP_STATS
for(i = 0; i < MEMP_MAX; ++i) {
lwip_stats.memp[i].used = lwip_stats.memp[i].max =
lwip_stats.memp[i].err = 0;
@@ -176,74 +182,79 @@ memp_init(void)
}
/*-----------------------------------------------------------------------------------*/
void *
memp_malloc(memp_t type)
{
struct memp *memp;
void *mem;
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
#endif
LWIP_ASSERT("memp_malloc: type < MEMP_MAX", type < MEMP_MAX);
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
memp = memp_tab[type];
if (memp != NULL) {
memp_tab[type] = memp->next;
memp->next = NULL;
#ifdef MEMP_STATS
#if MEMP_STATS
++lwip_stats.memp[type].used;
if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
lwip_stats.memp[type].max = lwip_stats.memp[type].used;
}
#endif /* MEMP_STATS */
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
LWIP_ASSERT("memp_malloc: memp properly aligned",
((u32_t)MEM_ALIGN((u8_t *)memp + sizeof(struct memp)) % MEM_ALIGNMENT) == 0);
mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp));
/* initialize memp memory with zeroes */
memset(mem, 0, memp_sizes[type]);
return mem;
} else {
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %d\n", type));
#ifdef MEMP_STATS
#if MEMP_STATS
++lwip_stats.memp[type].err;
#endif /* MEMP_STATS */
return NULL;
}
}
/*-----------------------------------------------------------------------------------*/
void *
memp_mallocp(memp_t type)
{
void *mem;
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
mem = memp_malloc(type);
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
return mem;
return NULL;
}
}
/*-----------------------------------------------------------------------------------*/
void
memp_free(memp_t type, void *mem)
{
struct memp *memp;
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */
if (mem == NULL) {
return;
}
memp = (struct memp *)((u8_t *)mem - sizeof(struct memp));
#ifdef MEMP_STATS
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
#if MEMP_STATS
lwip_stats.memp[type].used--;
#endif /* MEMP_STATS */
@@ -252,26 +263,10 @@ memp_free(memp_t type, void *mem)
LWIP_ASSERT("memp sanity", memp_sanity());
return;
}
/*-----------------------------------------------------------------------------------*/
void
memp_freep(memp_t type, void *mem)
{
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
memp_free(type, mem);
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -39,7 +39,6 @@
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/netif.h"
#include "lwip/ip_addr.h"
#include "lwip/tcp.h"
@@ -61,22 +60,15 @@ struct netif *netif_default = NULL;
* @return netif, or NULL if failed.
*/
struct netif *
netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
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))
{
struct netif *netif;
static int netifnum = 0;
/* allocate netif structure */
netif = mem_malloc(sizeof(struct netif));
if (netif == NULL) {
LWIP_DEBUGF(NETIF_DEBUG, ("netif_add(): out of memory for netif\n"));
return NULL;
}
#if LWIP_DHCP
/* netif not under DHCP control by default */
netif->dhcp = NULL;
@@ -90,14 +82,12 @@ netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
/* call user specified initialization function for netif */
if (init(netif) != ERR_OK) {
mem_free(netif);
return NULL;
}
/* add this netif to the list */
netif->next = netif_list;
netif_list = netif;
#if NETIF_DEBUG
LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
netif->name[0], netif->name[1]));
ip_addr_debug_print(NETIF_DEBUG, ipaddr);
@@ -106,7 +96,6 @@ netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
ip_addr_debug_print(NETIF_DEBUG, gw);
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
#endif /* NETIF_DEBUG */
return netif;
}
@@ -144,7 +133,6 @@ void netif_remove(struct netif * netif)
/* reset default netif */
netif_default = NULL;
LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
mem_free( netif );
}
struct netif *
@@ -170,7 +158,7 @@ netif_find(char *name)
LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
return NULL;
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
{
@@ -191,7 +179,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
/* this connection must be aborted */
struct tcp_pcb *next = pcb->next;
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting pcb %p\n", (void *)pcb));
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
tcp_abort(pcb);
pcb = next;
} else {
@@ -202,8 +190,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
/* PCB bound to current local interface address? */
if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {
/* The PCB is listening to the old ipaddr and
* is set to listen to the new one instead
* TODO: how do we know it is _listening_? */
* is set to listen to the new one instead */
ip_addr_set(&(lpcb->local_ip), ipaddr);
}
}
@@ -217,7 +204,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
(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)
{
@@ -229,7 +216,7 @@ netif_set_gw(struct netif *netif, struct ip_addr *gw)
(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)
{
@@ -241,7 +228,7 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
(unsigned int)(ntohl(netif->netmask.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->netmask.addr) & 0xff)));
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_default(struct netif *netif)
{
@@ -249,10 +236,10 @@ netif_set_default(struct netif *netif)
LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
}
/*-----------------------------------------------------------------------------------*/
void
netif_init(void)
{
netif_list = netif_default = NULL;
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -28,7 +28,7 @@
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -102,7 +102,7 @@ pbuf_init(void)
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
LWIP_ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0);
#ifdef PBUF_STATS
#if PBUF_STATS
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
#endif /* PBUF_STATS */
@@ -113,6 +113,7 @@ pbuf_init(void)
p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));
p->flags = PBUF_FLAG_POOL;
q = p;
p = p->next;
}
@@ -143,7 +144,7 @@ pbuf_pool_alloc(void)
/* Next, check the actual pbuf pool, but if the pool is locked, we
pretend to be out of buffers and return NULL. */
if (pbuf_pool_free_lock) {
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
return NULL;
@@ -156,7 +157,7 @@ pbuf_pool_alloc(void)
pbuf_pool = p->next;
}
#if !SYS_LIGHTWEIGHT_PROT
#ifdef PBUF_STATS
#if PBUF_STATS
} else {
++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
@@ -164,7 +165,7 @@ pbuf_pool_alloc(void)
pbuf_pool_alloc_lock = 0;
#endif /* SYS_LIGHTWEIGHT_PROT */
#ifdef PBUF_STATS
#if PBUF_STATS
if (p != NULL) {
++lwip_stats.pbuf.used;
if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) {
@@ -243,7 +244,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
p = pbuf_pool_alloc();
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
if (p == NULL) {
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */
return NULL;
@@ -258,8 +259,6 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
p->tot_len = length;
/* set the length of the first pbuf in the chain */
p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length;
/* set pbuf type */
p->flags = PBUF_FLAG_POOL;
/* set reference count (needed here in case we fail) */
p->ref = 1;
@@ -274,7 +273,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
q = pbuf_pool_alloc();
if (q == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */
/* free chain so far allocated */
@@ -289,7 +288,6 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
q->tot_len = rem_len;
/* this pbuf length is pool size, unless smaller sized tail */
q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
q->flags = PBUF_FLAG_POOL;
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
((u32_t)q->payload % MEM_ALIGNMENT) == 0);
@@ -300,7 +298,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
r = q;
}
/* end of chain */
//r->next = NULL;
/*r->next = NULL;*/
break;
case PBUF_RAM:
@@ -323,7 +321,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
/* pbuf references existing (externally allocated) RAM payload? */
case PBUF_REF:
/* only allocate memory for the pbuf structure */
p = memp_mallocp(MEMP_PBUF);
p = memp_malloc(MEMP_PBUF);
if (p == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", flag == PBUF_ROM?"ROM":"REF"));
return NULL;
@@ -345,7 +343,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
}
#ifdef PBUF_STATS
#if PBUF_STATS
#define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
#else /* PBUF_STATS */
#define DEC_PBUF_STATS
@@ -412,7 +410,7 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
/* first, step over any pbufs that should remain in the chain */
rem_len = new_len;
q = p;
/* this pbuf should be kept? */
/* should this pbuf be kept? */
while (rem_len > q->len) {
/* decrease remaining length by pbuf length */
rem_len -= q->len;
@@ -506,29 +504,33 @@ pbuf_header(struct pbuf *p, s16_t header_size)
}
/**
* Free a pbuf (chain) from usage, de-allocate non-used head of chain.
* 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.
*
* For a pbuf chain, this is repeated for each pbuf in the chain, until
* a non-zero reference count is encountered, or the end of the chain is
* reached.
* For a pbuf chain, this is repeated for each pbuf in the chain,
* up to a pbuf which has a non-zero reference count after
* decrementing. (This might de-allocate the whole chain.)
*
* @param pbuf pbuf (chain) to be freed from one user.
* @param pbuf The pbuf (chain) to be dereferenced.
*
* @return the number of unreferenced pbufs that were de-allocated
* @return the number of pbufs that were de-allocated
* from the head of the chain.
*
* @note May not be called on a packet queue.
* @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).
*
* @internal examples:
*
* Assuming existing chains a->b->c with the following reference
* counts, calling pbuf_free(a) results in:
*
* 1->2->3 becomes ...1->3
* 3->3->3 becomes 2->3->3
* 1->1->2 becomes ....->1
* 1->1->2 becomes ......1
* 2->1->1 becomes 1->1->1
* 1->1->1 becomes .......
*
@@ -576,7 +578,7 @@ pbuf_free(struct pbuf *p)
PBUF_POOL_FREE(p);
/* a ROM or RAM referencing pbuf */
} else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
memp_freep(MEMP_PBUF, p);
memp_free(MEMP_PBUF, p);
/* p->flags == PBUF_FLAG_RAM */
} else {
mem_free(p);
@@ -619,7 +621,6 @@ pbuf_clen(struct pbuf *p)
}
/**
*
* Increment the reference count of the pbuf.
*
* @param p pbuf to increase reference counter of
@@ -638,12 +639,47 @@ pbuf_ref(struct pbuf *p)
}
/**
*
* Chain two pbufs (or pbuf chains) together. They must belong to the same packet.
*
* Concatenate two pbufs (each may be a pbuf chain) and take over
* the caller's reference of the tail pbuf.
*
* @note The caller MAY NOT reference the tail pbuf afterwards.
* Use pbuf_chain() for that purpose.
*
* @see pbuf_chain()
*/
void
pbuf_cat(struct pbuf *h, struct pbuf *t)
{
struct pbuf *p;
LWIP_ASSERT("h != NULL", h != NULL);
LWIP_ASSERT("t != NULL", t != NULL);
if ((h == NULL) || (t == NULL)) return;
/* proceed to last pbuf of chain */
for (p = h; p->next != NULL; p = p->next) {
/* add total length of second chain to all totals of first chain */
p->tot_len += t->tot_len;
}
/* { 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);
/* 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;
}
/**
* Chain two pbufs (or pbuf chains) together.
*
* The caller MUST call pbuf_free(t) once it has stopped
* using it. Use pbuf_cat() instead if you no longer use t.
*
* @param h head pbuf (chain)
* @param t tail pbuf (chain)
* @note May not be called on a packet queue.
* @note The pbufs MUST belong to the same packet.
* @note MAY NOT be called on a packet queue.
*
* The ->tot_len fields of all pbufs of the head chain are adjusted.
* The ->next field of the last pbuf of the head chain is adjusted.
@@ -653,28 +689,10 @@ pbuf_ref(struct pbuf *p)
void
pbuf_chain(struct pbuf *h, struct pbuf *t)
{
struct pbuf *p;
LWIP_ASSERT("h != NULL", h != NULL);
LWIP_ASSERT("t != NULL", t != NULL);
if (t == NULL)
return;
/* proceed to last pbuf of chain */
for (p = h; p->next != NULL; p = p->next) {
/* add total length of second chain to all totals of first chain */
p->tot_len += t->tot_len;
}
/* p is last pbuf of first h chain */
LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
/* add total length of second chain to last pbuf total of first chain */
p->tot_len += t->tot_len;
/* chain last pbuf of h chain (p) with first of tail (t) */
p->next = t;
/* t is now referenced to one more time */
pbuf_cat(h, t);
/* t is now referenced by h */
pbuf_ref(t);
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)p, (void *)t));
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
}
/* For packet queueing. Note that queued packets must be dequeued first
@@ -711,9 +729,9 @@ pbuf_queue(struct pbuf *p, struct pbuf *n)
/* proceed to next packet on queue */
p = p->next;
}
/* chain last pbuf of h chain (p) with first of tail (t) */
/* chain last pbuf of queue with n */
p->next = n;
/* t is now referenced to one more time */
/* n is now referenced to one more time */
pbuf_ref(n);
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_queue: referencing queued packet %p\n", (void *)n));
}
@@ -764,7 +782,7 @@ pbuf_dequeue(struct pbuf *p)
* by pbuf_take()!
*
* @note Any replaced pbufs will be freed through pbuf_free().
* This may allocate them if they become no longer referenced.
* This may deallocate them if they become no longer referenced.
*
* @param p Head of pbuf chain to process
*
@@ -853,7 +871,6 @@ pbuf_take(struct pbuf *p)
return head;
}
#if 0 /* TODO: See if we might need this for future features */
/**
* Dechains the first pbuf from its succeeding pbufs in the chain.
*
@@ -890,28 +907,3 @@ pbuf_dechain(struct pbuf *p)
LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
return (tail_gone > 0? NULL: q);
}
#endif /* pbuf_dechain() */
/* TODO: This function is unused in the lwIP stack and will be deprecated. This is due
* to the new way chains are built. */
#if 0
/**
*
* Increment the reference count of all pbufs in a chain.
*
* @param p first pbuf of chain
*
*/
void
pbuf_ref_chain(struct pbuf *p)
{
SYS_ARCH_DECL_PROTECT(old_level);
SYS_ARCH_PROTECT(old_level);
while (p != NULL) {
++p->ref;
p = p->next;
}
SYS_ARCH_UNPROTECT(old_level);
}
#endif

310
src/core/raw.c Normal file
View File

@@ -0,0 +1,310 @@
/**
* @file
* Raw Access module
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/* raw.c
*
* The code for the Raw Access to the IP
*
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/memp.h"
#include "lwip/inet.h"
#include "lwip/netif.h"
#include "lwip/ip_addr.h"
#include "lwip/raw.h"
#include "lwip/stats.h"
#include "arch/perf.h"
#include "lwip/snmp.h"
#if LWIP_RAW
/* The list of RAW PCBs */
static struct raw_pcb *raw_pcbs = NULL;
void
raw_init(void)
{
raw_pcbs = NULL;
}
/**
* 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
*
* @param pbuf pbuf to be demultiplexed to a RAW PCB.
* @param netif network interface on which the datagram was received.
* @return 0 if packet is not eated (pbuf needs to be freed then)
* or 1 if the packet has been eaten (pbuf needs not to be freed
* then)
*
*/
int
raw_input(struct pbuf *p, struct netif *inp)
{
struct raw_pcb *pcb;
struct ip_hdr *iphdr;
int proto;
int rc = 0;
iphdr = p->payload;
proto = IPH_PROTO(iphdr);
for(pcb = raw_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->protocol == proto) {
if (pcb->recv) {
if (!pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)))
return 0;
}
pbuf_free(p);
rc = 1;
break;
}
}
return rc;
}
/**
* Bind a RAW PCB.
*
* @param pcb RAW PCB to be bound with a local address ipaddr.
* @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
* bind to all local interfaces.
*
* @return lwIP error code.
* - ERR_OK. Successful. No error occured.
* - ERR_USE. The specified ipaddr is already bound to by
* another RAW PCB.
*
* @see raw_disconnect()
*/
err_t
raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
{
ip_addr_set(&pcb->local_ip, ipaddr);
return ERR_OK;
}
/**
* Connect an RAW PCB. This function is required by upper layers
* of lwip. Using the raw api you could use raw_send_to() instead
*
* This will associate the RAW PCB with the remote address.
*
* @param pcb RAW PCB to be connected with remote address ipaddr and port.
* @param ipaddr remote IP address to connect with.
*
* @return lwIP error code
*
* @see raw_disconnect() and raw_send_to()
*/
err_t
raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
{
ip_addr_set(&pcb->remote_ip, ipaddr);
return ERR_OK;
}
/**
* 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,
int (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
struct ip_addr *addr),
void *recv_arg)
{
/* remember recv() callback and user data */
pcb->recv = recv;
pcb->recv_arg = recv_arg;
}
/**
* Send the raw IP packet to the given address. Note that actually you cannot
* modify the IP headers (this is inconsitent with the receive callback where
* you actually get the IP headers), you can only specifiy the ip payload here.
* It requires some more changes in LWIP. (there will be a raw_send() function
* then)
*
* @param pcb the raw pcb which to send
* @param p the ip payload to send
* @param ipaddr the destination address of the whole IP packet
*
*/
err_t
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_send_to\n"));
/* not enough space to add an IP header to first pbuf in given p chain? */
if (pbuf_header(p, IP_HLEN)) {
/* allocate header in new pbuf */
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
/* new header pbuf could not be allocated? */
if (q == NULL) {
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_send_to: could not allocate header\n"));
return ERR_MEM;
}
/* chain header q in front of given pbuf p */
pbuf_chain(q, p);
/* { first pbuf q points to header pbuf } */
LWIP_DEBUGF(RAW_DEBUG, ("raw_send_to: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
} else {
/* first pbuf q equals given pbuf */
q = p;
pbuf_header(q, -IP_HLEN);
}
if ((netif = ip_route(ipaddr)) == NULL) {
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 */
if (q != p) {
pbuf_free(q);
}
return ERR_RTE;
}
if (ip_addr_isany(&pcb->local_ip)) {
/* use outgoing network interface IP address as source address */
src_ip = &(netif->ip_addr);
} else {
/* use RAW PCB local IP address as source address */
src_ip = &(pcb->local_ip);
}
err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
/* did we chain a header earlier? */
if (q != p) {
/* free the header */
pbuf_free(q);
}
return err;
}
/**
* Send the raw IP packet to the address given by raw_connect()
*
* @param pcb the raw pcb which to send
* @param p the ip payload to send
* @param ipaddr the destination address of the whole IP packet
*
*/
err_t
raw_send(struct raw_pcb *pcb, struct pbuf *p)
{
return raw_send_to(pcb,p,&pcb->remote_ip);
}
/**
* Remove an RAW PCB.
*
* @param pcb RAW PCB to be removed. The PCB is removed from the list of
* RAW PCB's and the data structure is freed from memory.
*
* @see raw_new()
*/
void
raw_remove(struct raw_pcb *pcb)
{
struct raw_pcb *pcb2;
/* pcb to be removed is first in list? */
if (raw_pcbs == pcb) {
/* make list start at 2nd pcb */
raw_pcbs = raw_pcbs->next;
/* 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) {
/* remove pcb from list */
pcb2->next = pcb->next;
}
}
memp_free(MEMP_RAW_PCB, pcb);
}
/**
* Create a RAW PCB.
*
* @return The RAW PCB which was created. NULL if the PCB data structure
* could not be allocated.
*
* @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP)
*
* @see raw_remove()
*/
struct raw_pcb *
raw_new(u16_t proto) {
struct raw_pcb *pcb;
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_new\n"));
pcb = memp_malloc(MEMP_RAW_PCB);
/* could allocate RAW PCB? */
if (pcb != NULL) {
/* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct raw_pcb));
pcb->protocol = proto;
pcb->ttl = RAW_TTL;
pcb->next = raw_pcbs;
raw_pcbs = pcb;
}
return pcb;
}
#endif /* LWIP_RAW */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -41,11 +41,11 @@
#if LWIP_STATS
struct stats_ lwip_stats;
/*-----------------------------------------------------------------------------------*/
void
stats_init(void)
{
memset(&lwip_stats, 0, sizeof(struct stats_));
}
#endif /* LWIP_STATS */
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -44,7 +44,7 @@ struct sswt_cb
};
/*-----------------------------------------------------------------------------------*/
void
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
{
@@ -96,7 +96,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
}
}
/*-----------------------------------------------------------------------------------*/
void
sys_sem_wait(sys_sem_t sem)
{
@@ -152,7 +152,7 @@ sys_sem_wait(sys_sem_t sem)
}
}
/*-----------------------------------------------------------------------------------*/
void
sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{
@@ -203,7 +203,7 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
/* Go through timeout list (for this task only) and remove the first matching entry,
even though the timeout has not triggered yet.
*/
/*-----------------------------------------------------------------------------------*/
void
sys_untimeout(sys_timeout_handler h, void *arg)
{
@@ -238,7 +238,7 @@ sys_untimeout(sys_timeout_handler h, void *arg)
/*-----------------------------------------------------------------------------------*/
static void
sswt_handler(void *arg)
{
@@ -252,7 +252,7 @@ sswt_handler(void *arg)
/* Wait for a semaphore with timeout (specified in ms) */
/* timeout = 0: wait forever */
/* Returns 0 on timeout. 1 otherwise */
/*-----------------------------------------------------------------------------------*/
int
sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
{
@@ -279,7 +279,7 @@ sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
}
/*-----------------------------------------------------------------------------------*/
void
sys_msleep(u32_t ms)
{
@@ -289,6 +289,6 @@ sys_msleep(u32_t ms)
sys_sem_free(delaysem);
}
/*-----------------------------------------------------------------------------------*/
#endif /* NO_SYS */

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -36,7 +36,7 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* tcp.c
*
* This file contains common functions for the TCP implementation, such as functinos
@@ -44,7 +44,7 @@
* related to input and output is found in tcp_input.c and tcp_output.c respectively.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -74,13 +74,13 @@ static u8_t tcp_timer;
static u16_t tcp_new_port(void);
/*-----------------------------------------------------------------------------------*/
/*
* tcp_init():
*
* Initializes the TCP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_init(void)
{
@@ -95,41 +95,34 @@ tcp_init(void)
tcp_timer = 0;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_tmr():
*
* Called periodically to dispatch TCP timers.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_tmr(void)
{
++tcp_timer;
if (tcp_timer == 10) {
tcp_timer = 0;
}
if (tcp_timer & 1) {
/* Call tcp_fasttmr() every 200 ms, i.e., every other timer
tcp_tmr() is called. */
tcp_fasttmr();
}
if (tcp_timer == 0 || tcp_timer == 5) {
/* Call tcp_slowtmr() every 500 ms, i.e., every fifth timer
/* Call tcp_fasttmr() every 250 ms */
tcp_fasttmr();
if (++tcp_timer & 1) {
/* Call tcp_tmr() every 500 ms, i.e., every other timer
tcp_tmr() is called. */
tcp_slowtmr();
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_close():
*
* Closes the connection held by the PCB.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_close(struct tcp_pcb *pcb)
{
@@ -154,11 +147,6 @@ tcp_close(struct tcp_pcb *pcb)
pcb = NULL;
break;
case SYN_RCVD:
err = tcp_send_ctrl(pcb, TCP_FIN);
if (err == ERR_OK) {
pcb->state = FIN_WAIT_1;
}
break;
case ESTABLISHED:
err = tcp_send_ctrl(pcb, TCP_FIN);
if (err == ERR_OK) {
@@ -183,7 +171,7 @@ tcp_close(struct tcp_pcb *pcb)
}
return err;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_abort()
*
@@ -192,7 +180,7 @@ tcp_close(struct tcp_pcb *pcb)
* killed because of shortage of memory.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_abort(struct tcp_pcb *pcb)
{
@@ -240,7 +228,7 @@ tcp_abort(struct tcp_pcb *pcb)
tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_bind():
*
@@ -249,16 +237,19 @@ tcp_abort(struct tcp_pcb *pcb)
* the outgoing network interface is used instead.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct tcp_pcb *cpcb;
#ifdef SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
if (port == 0) {
port = tcp_new_port();
}
#ifndef SO_REUSE
/* Check if the address already is in use. */
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs;
cpcb != NULL; cpcb = cpcb->next) {
@@ -280,6 +271,102 @@ tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
}
}
}
#else /* SO_REUSE */
/* Search through list of PCB's in LISTEN state.
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
But no two PCB's bound to same local port and same local address is valid.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
}
}
}
}
/* Search through list of PCB's in a state in which they can accept or send data. Same decription as for
PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */
for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
}
}
}
}
/* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port}
can be rebound. The same applies when SOF_REUSEPORT is set.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n"));
return ERR_USE;
}
else if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
}
}
}
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
{IP, port} can't be reused. */
if(!reuse_port_all_set) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n"));
return ERR_USE;
}
#endif /* SO_REUSE */
if (!ip_addr_isany(ipaddr)) {
pcb->local_ip = *ipaddr;
}
@@ -298,7 +385,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
return ERR_ABRT;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_listen():
*
@@ -308,7 +395,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
* connection to LISTEN is an irreversible process.
*
*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_listen(struct tcp_pcb *pcb)
{
@@ -325,6 +412,10 @@ tcp_listen(struct tcp_pcb *pcb)
lpcb->callback_arg = pcb->callback_arg;
lpcb->local_port = pcb->local_port;
lpcb->state = LISTEN;
lpcb->so_options = pcb->so_options;
lpcb->so_options |= SOF_ACCEPTCONN;
lpcb->ttl = pcb->ttl;
lpcb->tos = pcb->tos;
ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
memp_free(MEMP_TCP_PCB, pcb);
#if LWIP_CALLBACK_API
@@ -333,7 +424,7 @@ tcp_listen(struct tcp_pcb *pcb)
TCP_REG(&tcp_listen_pcbs, lpcb);
return (struct tcp_pcb *)lpcb;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_recved():
*
@@ -342,13 +433,14 @@ tcp_listen(struct tcp_pcb *pcb)
* when the data has been processed.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_recved(struct tcp_pcb *pcb, u16_t len)
{
pcb->rcv_wnd += len;
if (pcb->rcv_wnd > TCP_WND) {
if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
pcb->rcv_wnd = TCP_WND;
} else {
pcb->rcv_wnd += len;
}
if (!(pcb->flags & TF_ACK_DELAY) &&
!(pcb->flags & TF_ACK_NOW)) {
@@ -358,14 +450,14 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
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,7 +490,7 @@ tcp_new_port(void)
}
return port;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_connect():
*
@@ -406,7 +498,7 @@ tcp_new_port(void)
* 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))
@@ -453,7 +545,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
}
return ret;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_slowtmr():
*
@@ -461,7 +553,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
* 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)
{
@@ -527,6 +619,21 @@ tcp_slowtmr(void)
}
}
/* Check if KEEPALIVE should be sent */
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
tcp_abort(pcb);
}
else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + pcb->keep_cnt * TCP_KEEPINTVL) / TCP_SLOW_INTERVAL) {
tcp_keepalive(pcb);
pcb->keep_cnt++;
}
}
/* If this PCB has queued out of sequence data, but has been
inactive for too long, will drop the data (it will eventually
be retransmitted). */
@@ -622,13 +729,13 @@ tcp_slowtmr(void)
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_fasttmr():
*
* Is called every TCP_FINE_TIMEOUT (100 ms) and sends delayed ACKs.
* Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_fasttmr(void)
{
@@ -643,75 +750,72 @@ tcp_fasttmr(void)
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_segs_free():
*
* Deallocates a list of TCP segments (tcp_seg structures).
*
*/
/*-----------------------------------------------------------------------------------*/
u8_t
tcp_segs_free(struct tcp_seg *seg)
{
u8_t count = 0;
struct tcp_seg *next;
again:
if (seg != NULL) {
while (seg != NULL) {
next = seg->next;
count += tcp_seg_free(seg);
seg = next;
goto again;
}
return count;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_seg_free():
*
* Frees a TCP segment.
*
*/
/*-----------------------------------------------------------------------------------*/
u8_t
tcp_seg_free(struct tcp_seg *seg)
{
u8_t count = 0;
if (seg != NULL) {
if (seg->p == NULL) {
memp_free(MEMP_TCP_SEG, seg);
} else {
if (seg->p != NULL) {
count = pbuf_free(seg->p);
#if TCP_DEBUG
seg->p = NULL;
#endif /* TCP_DEBUG */
memp_free(MEMP_TCP_SEG, seg);
}
memp_free(MEMP_TCP_SEG, seg);
}
return count;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_setprio():
*
* Sets the priority of a connection.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
{
pcb->prio = 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)
{
@@ -725,7 +829,8 @@ tcp_seg_copy(struct tcp_seg *seg)
pbuf_ref(cseg->p);
return cseg;
}
/*-----------------------------------------------------------------------------------*/
#endif
#if LWIP_CALLBACK_API
static err_t
tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
@@ -739,7 +844,7 @@ tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
return ERR_OK;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
static void
tcp_kill_prio(u8_t prio)
{
@@ -770,7 +875,7 @@ tcp_kill_prio(u8_t prio)
}
}
/*-----------------------------------------------------------------------------------*/
static void
tcp_kill_timewait(void)
{
@@ -792,8 +897,8 @@ tcp_kill_timewait(void)
}
}
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_alloc(u8_t prio)
{
@@ -817,6 +922,8 @@ tcp_alloc(u8_t prio)
pcb->snd_buf = TCP_SND_BUF;
pcb->snd_queuelen = 0;
pcb->rcv_wnd = TCP_WND;
pcb->tos = 0;
pcb->ttl = TCP_TTL;
pcb->mss = TCP_MSS;
pcb->rto = 3000 / TCP_SLOW_INTERVAL;
pcb->sa = 0;
@@ -836,10 +943,14 @@ tcp_alloc(u8_t prio)
#if LWIP_CALLBACK_API
pcb->recv = tcp_recv_null;
#endif /* LWIP_CALLBACK_API */
/* Init KEEPALIVE timer */
pcb->keepalive = TCP_KEEPDEFAULT;
pcb->keep_cnt = 0;
}
return pcb;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_new():
*
@@ -847,13 +958,13 @@ tcp_alloc(u8_t prio)
* any of the TCP PCB lists.
*
*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_new(void)
{
return tcp_alloc(TCP_PRIO_NORMAL);
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_arg():
*
@@ -861,13 +972,14 @@ tcp_new(void)
* functions.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_arg(struct tcp_pcb *pcb, void *arg)
{
pcb->callback_arg = arg;
}
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
/*
* tcp_recv():
*
@@ -875,16 +987,14 @@ tcp_arg(struct tcp_pcb *pcb, void *arg)
* connection receives data.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_recv(struct tcp_pcb *pcb,
err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
{
pcb->recv = recv;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_sent():
*
@@ -892,16 +1002,14 @@ tcp_recv(struct tcp_pcb *pcb,
* has been successfully delivered to the remote host.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_sent(struct tcp_pcb *pcb,
err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
{
pcb->sent = sent;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_err():
*
@@ -909,16 +1017,31 @@ tcp_sent(struct tcp_pcb *pcb,
* has occured on the connection.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_err(struct tcp_pcb *pcb,
void (* errf)(void *arg, err_t err))
{
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))
{
((struct tcp_pcb_listen *)pcb)->accept = accept;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_poll():
*
@@ -927,7 +1050,7 @@ tcp_err(struct tcp_pcb *pcb,
* 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)
@@ -937,31 +1060,14 @@ tcp_poll(struct tcp_pcb *pcb,
#endif /* LWIP_CALLBACK_API */
pcb->pollinterval = interval;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_accept():
*
* Used for specifying the function that should be called when a
* LISTENing connection has been connected to another host.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_accept(struct tcp_pcb *pcb,
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
{
((struct tcp_pcb_listen *)pcb)->accept = accept;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_pcb_purge():
*
* Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_pcb_purge(struct tcp_pcb *pcb)
{
@@ -971,7 +1077,6 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
#if TCP_DEBUG
if (pcb->unsent != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));
}
@@ -982,28 +1087,23 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
if (pcb->ooseq != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
}
#endif
#endif /* TCP_DEBUG */
tcp_segs_free(pcb->unsent);
#if TCP_QUEUE_OOSEQ
tcp_segs_free(pcb->ooseq);
pcb->ooseq = NULL;
#endif /* TCP_QUEUE_OOSEQ */
tcp_segs_free(pcb->unsent);
tcp_segs_free(pcb->unacked);
pcb->unacked = pcb->unsent =
#if TCP_QUEUE_OOSEQ
pcb->ooseq =
#endif /* TCP_QUEUE_OOSEQ */
NULL;
pcb->unacked = pcb->unsent = NULL;
}
}
/*-----------------------------------------------------------------------------------*/
/*
* 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)
{
@@ -1022,14 +1122,14 @@ 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)
{
@@ -1038,31 +1138,31 @@ tcp_next_iss(void)
iss += tcp_ticks; /* XXX */
return iss;
}
/*-----------------------------------------------------------------------------------*/
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
void
tcp_debug_print(struct tcp_hdr *tcphdr)
{
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %04x | %04x | (src port, dest port)\n",
tcphdr->src, tcphdr->dest));
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, ("| %08lu | (seq no)\n",
tcphdr->seqno));
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (seq no)\n",
ntohl(tcphdr->seqno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %08lu | (ack no)\n",
tcphdr->ackno));
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (ack no)\n",
ntohl(tcphdr->ackno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u| %5u | (offset, flags (",
TCPH_OFFSET(tcphdr),
TCPH_FLAGS(tcphdr) >> 4 & 1,
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,
TCPH_FLAGS(tcphdr) >> 3 & 1,
TCPH_FLAGS(tcphdr) >> 2 & 1,
TCPH_FLAGS(tcphdr) >> 1 & 1,
TCPH_FLAGS(tcphdr) & 1,
tcphdr->wnd));
ntohs(tcphdr->wnd)));
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
@@ -1070,7 +1170,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_state(enum tcp_state s)
{
@@ -1111,7 +1211,7 @@ tcp_debug_print_state(enum tcp_state s)
break;
}
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_flags(u8_t flags)
{
@@ -1133,8 +1233,14 @@ tcp_debug_print_flags(u8_t flags)
if (flags & TCP_URG) {
LWIP_DEBUGF(TCP_DEBUG, ("URG "));
}
if (flags & TCP_ECE) {
LWIP_DEBUGF(TCP_DEBUG, ("ECE "));
}
if (flags & TCP_CWR) {
LWIP_DEBUGF(TCP_DEBUG, ("CWR "));
}
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_pcbs(void)
{
@@ -1161,7 +1267,7 @@ tcp_debug_print_pcbs(void)
tcp_debug_print_state(pcb->state);
}
}
/*-----------------------------------------------------------------------------------*/
int
tcp_pcbs_sane(void)
{
@@ -1178,7 +1284,7 @@ tcp_pcbs_sane(void)
}
#endif /* TCP_DEBUG */
#endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -36,7 +36,7 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* tcp_input.c
*
* The input processing functions of TCP.
@@ -45,7 +45,7 @@
* tcp_process() -> tcp_receive() (-> application).
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/def.h"
@@ -85,7 +85,7 @@ static void tcp_parseopt(struct tcp_pcb *pcb);
static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
static err_t tcp_timewait_input(struct tcp_pcb *pcb);
/*-----------------------------------------------------------------------------------*/
/* tcp_input:
*
* The initial input processing of TCP. It verifies the TCP header, demultiplexes
@@ -93,34 +93,38 @@ static err_t tcp_timewait_input(struct tcp_pcb *pcb);
* the TCP finite state machine. This function is called by the IP layer (in
* ip_input()).
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_input(struct pbuf *p, struct netif *inp)
{
struct tcp_pcb *pcb, *prev;
struct tcp_pcb_listen *lpcb;
u8_t offset;
u8_t hdrlen;
err_t err;
#ifdef SO_REUSE
struct tcp_pcb *pcb_temp;
int reuse = 0;
int reuse_port = 0;
#endif /* SO_REUSE */
PERF_START;
#ifdef TCP_STATS
++lwip_stats.tcp.recv;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.recv);
iphdr = p->payload;
tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
#if TCP_INPUT_DEBUG
tcp_debug_print(tcphdr);
#endif
/* remove header from payload */
if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
/* drop short packets */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%u bytes) discarded\n", p->tot_len));
#ifdef TCP_STATS
++lwip_stats.tcp.lenerr;
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.lenerr);
TCP_STATS_INC(tcp.drop);
pbuf_free(p);
return;
}
@@ -142,10 +146,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
#if TCP_DEBUG
tcp_debug_print(tcphdr);
#endif /* TCP_DEBUG */
#ifdef TCP_STATS
++lwip_stats.tcp.chkerr;
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.chkerr);
TCP_STATS_INC(tcp.drop);
pbuf_free(p);
return;
@@ -154,8 +156,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Move the payload pointer in the pbuf so that it points to the
TCP data instead of the TCP header. */
offset = TCPH_OFFSET(tcphdr) >> 4;
pbuf_header(p, -(offset * 4));
hdrlen = TCPH_HDRLEN(tcphdr);
pbuf_header(p, -(hdrlen * 4));
/* Convert fields in TCP header to host byte order. */
tcphdr->src = ntohs(tcphdr->src);
@@ -170,7 +172,17 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Demultiplex an incoming segment. First, we check if it is destined
for an active connection. */
prev = NULL;
#ifdef SO_REUSE
pcb_temp = tcp_active_pcbs;
again_1:
/* Iterate through the TCP pcb list for a fully matching pcb */
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
@@ -179,6 +191,32 @@ tcp_input(struct pbuf *p, struct netif *inp)
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
#ifdef SO_REUSE
if(pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(TCP_INPUT_DEBUG,("tcp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port = 1;
p->ref++;
/* We want to search on next socket after receiving */
pcb_temp = pcb->next;
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
/* Move this PCB to the front of the list so that subsequent
lookups will be faster (we exploit locality in TCP segment
arrivals). */
@@ -323,33 +361,50 @@ tcp_input(struct pbuf *p, struct netif *inp)
tcp_debug_print_state(pcb->state);
#endif /* TCP_DEBUG */
#endif /* TCP_INPUT_DEBUG */
#ifdef SO_REUSE
/* First socket should receive now */
if(reuse_port) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: searching next PCB.\n"));
reuse_port = 0;
/* We are searching connected sockets */
goto again_1;
}
#endif /* SO_REUSE */
} else {
#ifdef SO_REUSE
if(reuse) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: freeing PBUF with reference counter set to %i\n", p->ref));
pbuf_free(p);
goto end;
}
#endif /* SO_REUSE */
/* If no matching PCB was found, send a TCP RST (reset) to the
sender. */
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
#ifdef TCP_STATS
++lwip_stats.tcp.proterr;
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.proterr);
TCP_STATS_INC(tcp.drop);
tcp_rst(ackno, seqno + tcplen,
&(iphdr->dest), &(iphdr->src),
tcphdr->dest, tcphdr->src);
}
pbuf_free(p);
}
#ifdef SO_REUSE
end:
#endif /* SO_REUSE */
LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
PERF_STOP("tcp_input");
}
/*-----------------------------------------------------------------------------------*/
/* tcp_listen_input():
*
* Called by tcp_input() when a segment arrives for a listening
* connection.
*/
/*-----------------------------------------------------------------------------------*/
static err_t
tcp_listen_input(struct tcp_pcb_listen *pcb)
{
@@ -366,16 +421,14 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
&(iphdr->dest), &(iphdr->src),
tcphdr->dest, tcphdr->src);
} else if (flags & TCP_SYN) {
LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection request %u -> %u.\n", tcphdr->src, tcphdr->dest));
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %u -> %u.\n", tcphdr->src, tcphdr->dest));
npcb = tcp_alloc(pcb->prio);
/* If a new PCB could not be created (probably due to lack of memory),
we don't do anything, but rely on the sender will retransmit the
SYN at a time when we have more memory available. */
if (npcb == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
#ifdef TCP_STATS
++lwip_stats.tcp.memerr;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.memerr);
return ERR_MEM;
}
/* Set up the new PCB. */
@@ -387,12 +440,13 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
npcb->rcv_nxt = seqno + 1;
npcb->snd_wnd = tcphdr->wnd;
npcb->ssthresh = npcb->snd_wnd;
npcb->snd_wl1 = seqno;
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
npcb->callback_arg = pcb->callback_arg;
#if LWIP_CALLBACK_API
npcb->accept = pcb->accept;
#endif /* LWIP_CALLBACK_API */
/* inherit socket options */
npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
/* Register the new PCB so that we can begin receiving segments
for it. */
TCP_REG(&tcp_active_pcbs, npcb);
@@ -411,13 +465,13 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* tcp_timewait_input():
*
* Called by tcp_input() when a segment arrives for a connection in
* TIME_WAIT.
*/
/*-----------------------------------------------------------------------------------*/
static err_t
tcp_timewait_input(struct tcp_pcb *pcb)
{
@@ -429,7 +483,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
}
return tcp_output(pcb);
}
/*-----------------------------------------------------------------------------------*/
/* tcp_process
*
* Implements the TCP state machine. Called by tcp_input. In some
@@ -437,7 +491,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
* argument will be freed by the caller (tcp_input()) unless the
* recv_data pointer in the pcb is set.
*/
/*-----------------------------------------------------------------------------------*/
static err_t
tcp_process(struct tcp_pcb *pcb)
{
@@ -479,17 +533,19 @@ tcp_process(struct tcp_pcb *pcb)
/* Update the PCB (in)activity timer. */
pcb->tmr = tcp_ticks;
pcb->keep_cnt = 0;
/* Do different things depending on the TCP state. */
switch (pcb->state) {
case SYN_SENT:
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %lu pcb->snd_nxt %lu unacked %lu\n", ackno,
pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
if (flags & (TCP_ACK | TCP_SYN) &&
ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
if ((flags & TCP_ACK) && (flags & TCP_SYN)
&& ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
pcb->rcv_nxt = seqno + 1;
pcb->lastack = ackno;
pcb->snd_wnd = pcb->snd_wl1 = tcphdr->wnd;
pcb->snd_wnd = tcphdr->wnd;
pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
pcb->state = ESTABLISHED;
pcb->cwnd = pcb->mss;
--pcb->snd_queuelen;
@@ -502,7 +558,7 @@ tcp_process(struct tcp_pcb *pcb)
tcp_parseopt(pcb);
/* Call the user specified function to call when sucessfully
connected. */
* connected. */
TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
tcp_ack(pcb);
}
@@ -511,22 +567,24 @@ tcp_process(struct tcp_pcb *pcb)
if (flags & TCP_ACK &&
!(flags & TCP_RST)) {
if (TCP_SEQ_LT(pcb->lastack, ackno) &&
TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) {
TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) {
pcb->state = ESTABLISHED;
LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection established %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
/* Call the accept function. */
TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
if (err != ERR_OK) {
/* If the accept function returns with an error, we abort
the connection. */
tcp_abort(pcb);
return ERR_ABRT;
}
/* If there was any data contained within this ACK,
we'd better pass it on to the application as well. */
tcp_receive(pcb);
pcb->cwnd = pcb->mss;
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
#if LWIP_CALLBACK_API
LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
#endif
/* Call the accept function. */
TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
if (err != ERR_OK) {
/* If the accept function returns with an error, we abort
* the connection. */
tcp_abort(pcb);
return ERR_ABRT;
}
/* If there was any data contained within this ACK,
* we'd better pass it on to the application as well. */
tcp_receive(pcb);
pcb->cwnd = pcb->mss;
}
}
break;
@@ -543,7 +601,7 @@ tcp_process(struct tcp_pcb *pcb)
tcp_receive(pcb);
if (flags & TCP_FIN) {
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
LWIP_DEBUGF(DEMO_DEBUG,
LWIP_DEBUGF(TCP_DEBUG,
("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
tcp_ack_now(pcb);
tcp_pcb_purge(pcb);
@@ -561,7 +619,7 @@ tcp_process(struct tcp_pcb *pcb)
case FIN_WAIT_2:
tcp_receive(pcb);
if (flags & TCP_FIN) {
LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
tcp_ack_now(pcb);
tcp_pcb_purge(pcb);
TCP_RMV(&tcp_active_pcbs, pcb);
@@ -572,7 +630,7 @@ tcp_process(struct tcp_pcb *pcb)
case CLOSING:
tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
tcp_ack_now(pcb);
tcp_pcb_purge(pcb);
TCP_RMV(&tcp_active_pcbs, pcb);
@@ -583,7 +641,7 @@ tcp_process(struct tcp_pcb *pcb)
case LAST_ACK:
tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
pcb->state = CLOSED;
recv_flags = TF_CLOSED;
}
@@ -594,7 +652,7 @@ tcp_process(struct tcp_pcb *pcb)
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* tcp_receive:
*
* Called by tcp_process. Checks if the given segment is an ACK for outstanding
@@ -606,7 +664,7 @@ tcp_process(struct tcp_pcb *pcb)
* If the incoming segment constitutes an ACK for a segment that was used for RTT
* estimation, the RTT is estimated here as well.
*/
/*-----------------------------------------------------------------------------------*/
static void
tcp_receive(struct tcp_pcb *pcb)
{
@@ -934,7 +992,7 @@ tcp_receive(struct tcp_pcb *pcb)
inseg.p = NULL;
}
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN."));
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
recv_flags = TF_GOT_FIN;
}
@@ -957,15 +1015,14 @@ tcp_receive(struct tcp_pcb *pcb)
/* Chain this pbuf onto the pbuf that we will pass to
the application. */
if (recv_data) {
pbuf_chain(recv_data, cseg->p);
pbuf_free(cseg->p);
pbuf_cat(recv_data, cseg->p);
} else {
recv_data = cseg->p;
}
cseg->p = NULL;
}
if (flags & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN."));
if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
recv_flags = TF_GOT_FIN;
}
@@ -1103,7 +1160,7 @@ tcp_receive(struct tcp_pcb *pcb)
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_parseopt:
*
@@ -1111,7 +1168,7 @@ tcp_receive(struct tcp_pcb *pcb)
* from uIP with only small changes.)
*
*/
/*-----------------------------------------------------------------------------------*/
static void
tcp_parseopt(struct tcp_pcb *pcb)
{
@@ -1122,8 +1179,8 @@ tcp_parseopt(struct tcp_pcb *pcb)
opts = (u8_t *)tcphdr + TCP_HLEN;
/* Parse the TCP MSS option, if present. */
if ((TCPH_OFFSET(tcphdr) & 0xf0) > 0x50) {
for(c = 0; c < ((TCPH_OFFSET(tcphdr) >> 4) - 5) << 2 ;) {
if(TCPH_HDRLEN(tcphdr) > 0x5) {
for(c = 0; c < (TCPH_HDRLEN(tcphdr) - 5) << 2 ;) {
opt = opts[c];
if (opt == 0x00) {
/* End of options. */
@@ -1153,5 +1210,5 @@ tcp_parseopt(struct tcp_pcb *pcb)
}
}
#endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/

View File

@@ -4,7 +4,7 @@
* Transmission Control Protocol, outgoing traffic
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -35,13 +35,13 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* tcp_output.c
*
* The output functions of TCP.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/def.h"
@@ -64,14 +64,14 @@
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)
{
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
}
/*-----------------------------------------------------------------------------------*/
err_t
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
{
@@ -90,7 +90,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
return ERR_CONN;
}
}
/*-----------------------------------------------------------------------------------*/
err_t
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
u8_t flags, u8_t copy,
@@ -133,7 +133,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
pcb->unsent != NULL);
}
seg = NULL;
seg = useg = NULL;
seglen = 0;
/* First, break up the data into segments and tuck them together in
@@ -154,12 +154,13 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
seg->p = NULL;
if (queue == NULL) {
queue = seg;
useg = queue = seg;
}
else {
/* Attach the segment to the end of the queued segments. */
for (useg = queue; useg->next != NULL; useg = useg->next);
LWIP_ASSERT("useg != NULL", useg != NULL);
useg->next = seg;
useg = seg;
}
/* If copy is set, memory should be allocated
@@ -210,9 +211,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
}
++queuelen;
/* Chain the headers and data pbufs together. */
pbuf_chain(seg->p, p);
pbuf_free(p);
/* Concatenate the headers and data pbufs together. */
pbuf_cat(seg->p, p);
p = NULL;
}
@@ -234,9 +234,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
#ifdef TCP_STATS
++lwip_stats.tcp.err;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.err);
goto memerr;
}
seg->tcphdr = seg->p->payload;
@@ -249,10 +247,10 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* Copy the options into the header, if they are present. */
if (optdata == NULL) {
TCPH_OFFSET_SET(seg->tcphdr, 5 << 4);
TCPH_HDRLEN_SET(seg->tcphdr, 5);
}
else {
TCPH_OFFSET_SET(seg->tcphdr, (5 + optlen / 4) << 4);
TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
/* Copy options into data portion of segment.
Options can thus only be sent in non data carrying
segments such as SYN|ACK. */
@@ -288,11 +286,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
useg->len + queue->len <= pcb->mss) {
/* Remove TCP header from first segment. */
pbuf_header(queue->p, -TCP_HLEN);
pbuf_chain(useg->p, queue->p);
/* Free buffer which was merged. Note that the previous pbuf_chain call
* will have incremented the ref count, so here the ref count will still
* be 1 for the 1 pointer still being used on this buffer. */
pbuf_free(queue->p);
pbuf_cat(useg->p, queue->p);
useg->len += queue->len;
useg->next = queue->next;
@@ -327,14 +321,12 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* Set the PSH flag in the last segment that we enqueued, but only
if the segment has data (indicated by seglen > 0). */
if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_PSH);
TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
}
return ERR_OK;
memerr:
#ifdef TCP_STATS
++lwip_stats.tcp.memerr;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.memerr);
if (queue != NULL) {
tcp_segs_free(queue);
@@ -347,7 +339,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
return ERR_MEM;
}
/*-----------------------------------------------------------------------------------*/
/* find out what we can send and send it */
err_t
tcp_output(struct tcp_pcb *pcb)
@@ -373,6 +365,13 @@ tcp_output(struct tcp_pcb *pcb)
seg = pcb->unsent;
/* useg should point to last segment on unacked queue */
useg = pcb->unacked;
if (useg != NULL) {
for (; useg->next != NULL; useg = useg->next);
}
/* If the TF_ACK_NOW flag is set, we check if there is data that is
to be sent. If data is to be sent out, we'll just piggyback our
acknowledgement with the outgoing segment. If no data will be
@@ -398,13 +397,14 @@ tcp_output(struct tcp_pcb *pcb)
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_OFFSET_SET(tcphdr, 5 << 4);
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
IP_PROTO_TCP, p->tot_len);
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
pbuf_free(p);
@@ -443,7 +443,7 @@ tcp_output(struct tcp_pcb *pcb)
pcb->unsent = seg->next;
if (pcb->state != SYN_SENT) {
TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_ACK);
TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
}
@@ -457,11 +457,10 @@ tcp_output(struct tcp_pcb *pcb)
seg->next = NULL;
if (pcb->unacked == NULL) {
pcb->unacked = seg;
useg = seg;
} else {
for (useg = pcb->unacked; useg->next != NULL; useg = useg->next);
useg->next = seg;
useg = useg->next;
}
} else {
tcp_seg_free(seg);
@@ -470,7 +469,7 @@ tcp_output(struct tcp_pcb *pcb)
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static void
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
{
@@ -523,14 +522,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
&(pcb->local_ip),
&(pcb->remote_ip),
IP_PROTO_TCP, seg->p->tot_len);
#ifdef TCP_STATS
++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.xmit);
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
}
/*-----------------------------------------------------------------------------------*/
void
tcp_rst(u32_t seqno, u32_t ackno,
struct ip_addr *local_ip, struct ip_addr *remote_ip,
@@ -552,20 +549,19 @@ tcp_rst(u32_t seqno, u32_t ackno,
TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
tcphdr->wnd = htons(TCP_WND);
tcphdr->urgp = 0;
TCPH_OFFSET_SET(tcphdr, 5 << 4);
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
IP_PROTO_TCP, p->tot_len);
#ifdef TCP_STATS
++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */
ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP);
TCP_STATS_INC(tcp.xmit);
/* Send output with hardcoded TTL since we have no access to the pcb */
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
}
/*-----------------------------------------------------------------------------------*/
void
tcp_rexmit(struct tcp_pcb *pcb)
{
@@ -595,6 +591,48 @@ tcp_rexmit(struct tcp_pcb *pcb)
tcp_output(pcb);
}
void
tcp_keepalive(struct tcp_pcb *pcb)
{
struct pbuf *p;
struct tcp_hdr *tcphdr;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %ld pcb->tmr %ld pcb->keep_cnt %ld\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if(p == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n"));
return;
}
tcphdr = p->payload;
tcphdr->src = htons(pcb->local_port);
tcphdr->dest = htons(pcb->remote_port);
tcphdr->seqno = htonl(pcb->snd_nxt - 1);
tcphdr->ackno = htonl(pcb->rcv_nxt);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
TCP_STATS_INC(tcp.xmit);
/* Send output to IP */
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
}
#endif /* LWIP_TCP */

View File

@@ -4,7 +4,7 @@
*
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -35,13 +35,13 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* udp.c
*
* The code for the User Datagram Protocol UDP.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
#include "lwip/def.h"
@@ -64,87 +64,13 @@ struct udp_pcb *udp_pcbs = NULL;
static struct udp_pcb *pcb_cache = NULL;
#if UDP_DEBUG
int udp_debug_print(struct udp_hdr *udphdr);
#endif /* UDP_DEBUG */
/*-----------------------------------------------------------------------------------*/
void
udp_init(void)
{
udp_pcbs = pcb_cache = NULL;
}
/*-----------------------------------------------------------------------------------*/
/* udp_lookup:
*
* An experimental feature that will be changed in future versions. Do
* not depend on it yet...
*/
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
u8_t
udp_lookup(struct ip_hdr *iphdr, struct netif *inp)
{
struct udp_pcb *pcb;
struct udp_hdr *udphdr;
u16_t src, dest;
PERF_START;
(void)inp;
udphdr = (struct udp_hdr *)(u8_t *)iphdr + IPH_HL(iphdr) * 4;
src = ntohs(udphdr->src);
dest = ntohs(udphdr->dest);
pcb = pcb_cache;
if (pcb != NULL &&
pcb->remote_port == src &&
pcb->local_port == dest &&
(ip_addr_isany(&pcb->remote_ip) ||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
return 1;
}
else {
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->remote_port == src &&
pcb->local_port == dest &&
(ip_addr_isany(&pcb->remote_ip) ||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
pcb_cache = pcb;
break;
}
}
if (pcb == NULL) {
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->remote_port == 0 &&
pcb->local_port == dest &&
(ip_addr_isany(&pcb->remote_ip) ||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
break;
}
}
}
}
PERF_STOP("udp_lookup");
if (pcb != NULL) {
return 1;
}
else {
return 1;
}
}
#endif /* LWIP_DEBUG */
/**
* Process an incoming UDP datagram.
*
@@ -163,21 +89,24 @@ udp_input(struct pbuf *p, struct netif *inp)
struct ip_hdr *iphdr;
u16_t src, dest;
#ifdef SO_REUSE
struct udp_pcb *pcb_temp;
int reuse = 0;
int reuse_port_1 = 0;
int reuse_port_2 = 0;
#endif /* SO_REUSE */
PERF_START;
#ifdef UDP_STATS
++lwip_stats.udp.recv;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.recv);
iphdr = p->payload;
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
/* drop short packets */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
#ifdef UDP_STATS
++lwip_stats.udp.lenerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.lenerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
@@ -190,9 +119,7 @@ udp_input(struct pbuf *p, struct netif *inp)
src = ntohs(udphdr->src);
dest = ntohs(udphdr->dest);
#if UDP_DEBUG
udp_debug_print(udphdr);
#endif /* UDP_DEBUG */
/* print the UDP source and destination */
LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n",
@@ -200,8 +127,18 @@ udp_input(struct pbuf *p, struct netif *inp)
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
#ifdef SO_REUSE
pcb_temp = udp_pcbs;
again_1:
/* Iterate through the UDP pcb list for a fully matching pcb */
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
/* Iterate through the UDP pcb list for a fully matching pcb */
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
/* print the PCB local and remote address */
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),
@@ -221,6 +158,27 @@ udp_input(struct pbuf *p, struct netif *inp)
(ip_addr_isany(&pcb->local_ip) ||
/* PCB local IP address matches UDP destination IP address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
#ifdef SO_REUSE
if(pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port_1 = 1;
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
break;
}
}
@@ -228,7 +186,16 @@ udp_input(struct pbuf *p, struct netif *inp)
if (pcb == NULL) {
/* Iterate through the UDP PCB list for a pcb that matches
the local address. */
#ifdef SO_REUSE
pcb_temp = udp_pcbs;
again_2:
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
@@ -242,7 +209,28 @@ udp_input(struct pbuf *p, struct netif *inp)
(ip_addr_isany(&pcb->local_ip) ||
/* ...matching interface address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
break;
#ifdef SO_REUSE
if(pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port_2 = 1;
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
break;
}
}
}
@@ -262,10 +250,8 @@ udp_input(struct pbuf *p, struct netif *inp)
(struct ip_addr *)&(iphdr->dest),
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
#ifdef UDP_STATS
++lwip_stats.udp.chkerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
@@ -277,10 +263,8 @@ udp_input(struct pbuf *p, struct netif *inp)
IP_PROTO_UDP, p->tot_len) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n"));
#ifdef UDP_STATS
++lwip_stats.udp.chkerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
@@ -291,7 +275,33 @@ udp_input(struct pbuf *p, struct netif *inp)
if (pcb != NULL) {
snmp_inc_udpindatagrams();
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
#ifdef SO_REUSE
/* First socket should receive now */
if(reuse_port_1 || reuse_port_2) {
/* We want to search on next socket after receiving */
pcb_temp = pcb->next;
if(reuse_port_1) {
/* We are searching connected sockets */
reuse_port_1 = 0;
reuse_port_2 = 0;
goto again_1;
} else {
/* We are searching unconnected sockets */
reuse_port_1 = 0;
reuse_port_2 = 0;
goto again_2;
}
}
#endif /* SO_REUSE */
} else {
#ifdef SO_REUSE
if(reuse) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
pbuf_free(p);
goto end;
}
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
/* No match was found, send ICMP destination port unreachable unless
@@ -304,10 +314,8 @@ udp_input(struct pbuf *p, struct netif *inp)
p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PORT);
}
#ifdef UDP_STATS
++lwip_stats.udp.proterr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.proterr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpnoports();
pbuf_free(p);
}
@@ -372,7 +380,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
q = p;
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
}
/* { q now represents the packet to be sent */
udphdr = q->payload;
udphdr->src = htons(pcb->local_port);
udphdr->dest = htons(pcb->remote_port);
@@ -380,9 +388,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
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));
#ifdef UDP_STATS
++lwip_stats.udp.rterr;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/* using IP_ANY_ADDR? */
@@ -407,7 +413,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
/* output to IP */
err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDPLITE, netif);
err = ip_output_if (q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
snmp_inc_udpoutdatagrams();
} else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len));
@@ -422,18 +428,17 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
snmp_inc_udpoutdatagrams();
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
/* output to IP */
err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDP, netif);
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
}
/* did we chain a header earlier? */
if (q != p) {
/* free the header */
/* p is also still referenced by the caller, and will live on */
pbuf_free(q);
}
#ifdef UDP_STATS
++lwip_stats.udp.xmit;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.xmit);
return err;
}
@@ -457,7 +462,13 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
u8_t rebind;
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = %lx, port = %u)\n", ipaddr->addr, port));
#ifdef SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
ip_addr_debug_print(UDP_DEBUG, ipaddr);
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port));
rebind = 0;
/* Check for double bind and rebind of the same pcb */
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
@@ -468,11 +479,13 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
/* pcb already in list, just rebind */
rebind = 1;
}
#ifndef SO_REUSE
/* this code does not allow upper layer to share a UDP port for
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
combine with implementation of UDP PCB flags. Leon Woestenberg. */
#if 0
#ifdef LWIP_UDP_TODO
/* port matches that of PCB in list? */
else if ((ipcb->local_port == port) &&
/* IP address matches, or one is IP_ADDR_ANY? */
@@ -484,8 +497,52 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t 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 */
}
/* bind local address */
#ifdef SO_REUSE
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
{IP, port} can't be reused. */
if(!reuse_port_all_set) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n"));
return ERR_USE;
}
#endif /* SO_REUSE */
ip_addr_set(&pcb->local_ip, ipaddr);
/* no port specified? */
if (port == 0) {
@@ -550,16 +607,14 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
pcb->remote_port = port;
pcb->flags |= UDP_FLAGS_CONNECTED;
/** TODO: this functionality belongs in upper layers */
#if 0
#ifdef LWIP_UDP_TODO
/* Nail down local IP for netconn_addr()/getsockname() */
if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
struct netif *netif;
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
#ifdef UDP_STATS
++lwip_stats.udp.rterr;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/** TODO: this will bind the udp pcb locally, to the interface which
@@ -594,7 +649,7 @@ udp_disconnect(struct udp_pcb *pcb)
{
pcb->flags &= ~UDP_FLAGS_CONNECTED;
}
/*-----------------------------------------------------------------------------------*/
void
udp_recv(struct udp_pcb *pcb,
void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
@@ -647,10 +702,13 @@ udp_new(void) {
if (pcb != NULL) {
/* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct udp_pcb));
pcb->ttl = UDP_TTL;
}
return pcb;
}
/*-----------------------------------------------------------------------------------*/
#if UDP_DEBUG
int
udp_debug_print(struct udp_hdr *udphdr)
@@ -666,7 +724,7 @@ udp_debug_print(struct udp_hdr *udphdr)
return 0;
}
#endif /* UDP_DEBUG */
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_UDP */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -67,6 +67,13 @@ u8_t *inet_ntoa(u32_t addr); /* returns ptr to static buffer; not reentrant! */
#define htonl(x) (x)
#define ntohl(x) (x)
#else
#ifdef LWIP_PREFIX_BYTEORDER_FUNCS
/* workaround for naming collisions on some platforms */
#define htons lwip_htons
#define ntohs lwip_ntohs
#define htonl lwip_htonl
#define ntohl lwip_ntohl
#endif
u16_t htons(u16_t x);
u16_t ntohs(u16_t x);
u32_t htonl(u32_t x);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -43,13 +43,12 @@
struct netif;
void ip_init(void);
u8_t ip_lookup(void *header, struct netif *inp);
struct netif *ip_route(struct ip_addr *dest);
err_t ip_input(struct pbuf *p, struct netif *inp);
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto);
u8_t ttl, u8_t tos, u8_t proto);
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto,
u8_t ttl, u8_t tos, u8_t proto,
struct netif *netif);
#define IP_HLEN 20
@@ -67,6 +66,36 @@ err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
#endif /* IP_HDRINCL */
#define IP_HDRINCL NULL
/* This is the common part of all PCB types. It needs to be at the
beginning of a PCB type definition. It is located here so that
changes to this common part are made in one location instead of
having to change all PCB structs. */
#define IP_PCB struct ip_addr local_ip; \
struct ip_addr remote_ip; \
/* Socket options */ \
u16_t so_options; \
/* Type Of Service */ \
u8_t tos; \
/* Time To Live */ \
u8_t ttl
/*
* Option flags per-socket. These are the same like SO_XXX.
*/
#define SOF_DEBUG (u16_t)0x0001U /* turn on debugging info recording */
#define SOF_ACCEPTCONN (u16_t)0x0002U /* socket has had listen() */
#define SOF_REUSEADDR (u16_t)0x0004U /* allow local address reuse */
#define SOF_KEEPALIVE (u16_t)0x0008U /* keep connections alive */
#define SOF_DONTROUTE (u16_t)0x0010U /* just use interface addresses */
#define SOF_BROADCAST (u16_t)0x0020U /* permit sending of broadcast msgs */
#define SOF_USELOOPBACK (u16_t)0x0040U /* bypass hardware when possible */
#define SOF_LINGER (u16_t)0x0080U /* linger on close if data present */
#define SOF_OOBINLINE (u16_t)0x0100U /* leave received OOB data in line */
#define SOF_REUSEPORT (u16_t)0x0200U /* allow local address & port reuse */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
@@ -117,6 +146,8 @@ PACK_STRUCT_END
#if IP_DEBUG
void ip_debug_print(struct pbuf *p);
#else
#define ip_debug_print(p)
#endif /* IP_DEBUG */
#endif /* __LWIP_IP_H__ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -118,11 +118,11 @@ extern const struct ip_addr ip_addr_broadcast;
#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))
#define ip_addr_debug_print(ipaddr) LWIP_DEBUGF(LWIP_DEBUG, ("%d.%d.%d.%d", \
(unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff, \
(unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff, \
(unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff, \
(unsigned int)ntohl((ipaddr)->addr) & 0xff))
#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 */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -38,6 +38,7 @@
#include "lwip/ip.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
@@ -50,7 +51,8 @@ enum netconn_type {
NETCONN_TCP,
NETCONN_UDP,
NETCONN_UDPLITE,
NETCONN_UDPNOCHKSUM
NETCONN_UDPNOCHKSUM,
NETCONN_RAW
};
enum netconn_state {
@@ -82,6 +84,7 @@ struct netconn {
union {
struct tcp_pcb *tcp;
struct udp_pcb *udp;
struct raw_pcb *raw;
} pcb;
err_t err;
sys_mbox_t mbox;
@@ -121,6 +124,9 @@ struct netconn * netconn_new (enum netconn_type type);
struct
netconn *netconn_new_with_callback(enum netconn_type t,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len));
struct
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len));
err_t netconn_delete (struct netconn *conn);
enum netconn_type netconn_type (struct netconn *conn);
err_t netconn_peer (struct netconn *conn,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -61,19 +61,19 @@
/** flag for LWIP_DEBUGF to halt after printing this debug message */
#define DBG_HALT 0x08U
#ifdef LWIP_DEBUG
# ifndef LWIP_NOASSERT
#ifndef LWIP_NOASSERT
# define LWIP_ASSERT(x,y) do { if(!(y)) LWIP_PLATFORM_ASSERT(x); } while(0)
# else
#else
# define LWIP_ASSERT(x,y)
# endif
#endif
#ifdef LWIP_DEBUG
/** print debug message only if debug message type is enabled...
* AND is of correct type AND is at least DBG_LEVEL
*/
# define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && (((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0)
# define LWIP_ERROR(x) do { LWIP_PLATFORM_DIAG(x); } while(0)
#else /* LWIP_DEBUG */
# define LWIP_ASSERT(x,y)
# define LWIP_DEBUGF(debug,x)
# define LWIP_ERROR(x)
#endif /* LWIP_DEBUG */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,6 +1,38 @@
/** @file
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIP_DHCP_H__
#define __LWIP_DHCP_H__
@@ -191,10 +223,10 @@ void dhcp_fine_tmr(void);
#define DHCP_OPTION_MESSAGE_TYPE_LEN 1
#define DHCP_OPTION_SERVER_ID 54 /* RFC 2131 9.7, server IP address */
#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2131 9.8, requested option types */
#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */
#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */
#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2131 9.10, message size accepted >= 576 */
#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */
#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2
#define DHCP_OPTION_T1 58 /* T1 renewal time */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -49,9 +49,13 @@ void mem_free(void *mem);
void *mem_realloc(void *mem, mem_size_t size);
void *mem_reallocm(void *mem, mem_size_t size);
#ifndef MEM_ALIGN_SIZE
#define MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1))
#endif
#ifndef MEM_ALIGN
#define MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))
#endif
#endif /* __LWIP_MEM_H__ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -37,6 +37,7 @@
typedef enum {
MEMP_PBUF,
MEMP_RAW_PCB,
MEMP_UDP_PCB,
MEMP_TCP_PCB,
MEMP_TCP_PCB_LISTEN,
@@ -58,8 +59,5 @@ void *memp_malloc(memp_t type);
void *memp_realloc(memp_t fromtype, memp_t totype, void *mem);
void memp_free(memp_t type, void *mem);
void *memp_mallocp(memp_t type);
void memp_freep(memp_t type, void *mem);
#endif /* __LWIP_MEMP_H__ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -115,7 +115,7 @@ extern struct netif *netif_default;
/* netif_init() must be called first. */
void netif_init(void);
struct netif *netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
struct netif *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),

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -32,9 +32,9 @@
#ifndef __LWIP_OPT_H__
#define __LWIP_OPT_H__
#include "lwip/debug.h"
/* Include user defined options first */
#include "lwipopts.h"
#include "lwip/debug.h"
/* Define default values for unconfigured parameters. */
@@ -74,6 +74,11 @@ a lot of data that needs to be copied, this should be set high. */
#define MEMP_NUM_PBUF 16
#endif
/* Number of raw connection PCBs */
#ifndef MEMP_NUM_RAW_PCB
#define MEMP_NUM_RAW_PCB 4
#endif
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#ifndef MEMP_NUM_UDP_PCB
@@ -211,6 +216,12 @@ a lot of data that needs to be copied, this should be set high. */
#define ICMP_TTL 255
#endif
/* ---------- RAW options ---------- */
#ifndef RAW_TTL
#define RAW_TTL 255
#endif
/* ---------- DHCP options ---------- */
#ifndef LWIP_DHCP
@@ -288,8 +299,10 @@ a lot of data that needs to be copied, this should be set high. */
#define TCP_SNDLOWAT TCP_SND_BUF/2
#endif
/* Support loop interface (127.0.0.1) */
#ifndef LWIP_HAVE_LOOPIF
#define LWIP_HAVE_LOOPIF 1
#endif
#ifndef LWIP_EVENT_API
#define LWIP_EVENT_API 0
@@ -320,6 +333,14 @@ a lot of data that needs to be copied, this should be set high. */
#define DEFAULT_THREAD_PRIO 1
#endif
/* ---------- Socket Options ---------- */
/* Enable SO_REUSEADDR and SO_REUSEPORT options */
#ifndef SO_REUSE
# define SO_REUSE 1
#endif
/* ---------- Statistics options ---------- */
#ifndef LWIP_STATS
#define LWIP_STATS 1
@@ -327,15 +348,63 @@ a lot of data that needs to be copied, this should be set high. */
#if LWIP_STATS
#define LINK_STATS
#define IP_STATS
#define ICMP_STATS
#define UDP_STATS
#define TCP_STATS
#define MEM_STATS
#define MEMP_STATS
#define PBUF_STATS
#define SYS_STATS
#ifndef LINK_STATS
#define LINK_STATS 1
#endif
#ifndef IP_STATS
#define IP_STATS 1
#endif
#ifndef IPFRAG_STATS
#define IPFRAG_STATS 1
#endif
#ifndef ICMP_STATS
#define ICMP_STATS 1
#endif
#ifndef UDP_STATS
#define UDP_STATS 1
#endif
#ifndef TCP_STATS
#define TCP_STATS 1
#endif
#ifndef MEM_STATS
#define MEM_STATS 1
#endif
#ifndef MEMP_STATS
#define MEMP_STATS 1
#endif
#ifndef PBUF_STATS
#define PBUF_STATS 1
#endif
#ifndef SYS_STATS
#define SYS_STATS 1
#endif
#ifndef RAW_STATS
#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
#endif /* LWIP_STATS */
@@ -433,10 +502,6 @@ a lot of data that needs to be copied, this should be set high. */
#define DBG_TYPES_ON 0
#endif
#ifndef DEMO_DEBUG
#define DEMO_DEBUG DBG_OFF
#endif
#ifndef ETHARP_DEBUG
#define ETHARP_DEBUG DBG_OFF
#endif
@@ -477,6 +542,10 @@ a lot of data that needs to be copied, this should be set high. */
#define IP_REASS_DEBUG DBG_OFF
#endif
#ifndef RAW_DEBUG
#define RAW_DEBUG DBG_OFF
#endif
#ifndef MEM_DEBUG
#define MEM_DEBUG DBG_OFF
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -29,7 +29,7 @@
* Author: Adam Dunkels <adam@sics.se>
*
*/
/*-----------------------------------------------------------------------------------*/
#ifndef __LWIP_PBUF_H__
#define __LWIP_PBUF_H__
@@ -108,10 +108,9 @@ void pbuf_ref(struct pbuf *p);
void pbuf_ref_chain(struct pbuf *p);
u8_t pbuf_free(struct pbuf *p);
u8_t pbuf_clen(struct pbuf *p);
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);
#if 0 /* see remark in code */
struct pbuf *pbuf_dechain(struct pbuf *p);
#endif
#endif /* __LWIP_PBUF_H__ */

74
src/include/lwip/raw.h Normal file
View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIP_RAW_H__
#define __LWIP_RAW_H__
#include "lwip/arch.h"
#include "lwip/pbuf.h"
#include "lwip/inet.h"
#include "lwip/ip.h"
struct raw_pcb {
/* Common members of all PCB types */
IP_PCB;
struct raw_pcb *next;
u16_t protocol;
int (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
struct ip_addr *addr);
void *recv_arg;
};
/* The following functions is the application layer interface to the
RAW code. */
struct raw_pcb * raw_new (u16_t proto);
void raw_remove (struct raw_pcb *pcb);
err_t raw_bind (struct raw_pcb *pcb, struct ip_addr *ipaddr);
err_t raw_connect (struct raw_pcb *pcb, struct ip_addr *ipaddr);
void raw_recv (struct raw_pcb *pcb,
int (* recv)(void *arg, struct raw_pcb *pcb,
struct pbuf *p,
struct ip_addr *addr),
void *recv_arg);
err_t raw_send_to (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr);
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
/* The following functions are the lower layer interface to RAW. */
int raw_input (struct pbuf *p, struct netif *inp);
void raw_init (void);
#endif /* __LWIP_RAW_H__ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2001, 2002 Leon Woestenberg <leon.woestenberg@axon.tv>
* Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands.
* Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
* Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -70,6 +70,7 @@ struct sockaddr {
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */
#define SO_DONTLINGER (int)(~SO_LINGER)
@@ -117,6 +118,36 @@ struct linger {
#define MSG_DONTWAIT 0x40 /* Nonblocking i/o for this operation only */
/*
* Options for level IPPROTO_IP
*/
#define IP_TOS 1
#define IP_TTL 2
#define IPTOS_TOS_MASK 0x1E
#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
#define IPTOS_LOWDELAY 0x10
#define IPTOS_THROUGHPUT 0x08
#define IPTOS_RELIABILITY 0x04
#define IPTOS_LOWCOST 0x02
#define IPTOS_MINCOST IPTOS_LOWCOST
/*
* Definitions for IP precedence (also in ip_tos) (hopefully unused)
*/
#define IPTOS_PREC_MASK 0xe0
#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK)
#define IPTOS_PREC_NETCONTROL 0xe0
#define IPTOS_PREC_INTERNETCONTROL 0xc0
#define IPTOS_PREC_CRITIC_ECP 0xa0
#define IPTOS_PREC_FLASHOVERRIDE 0x80
#define IPTOS_PREC_FLASH 0x60
#define IPTOS_PREC_IMMEDIATE 0x40
#define IPTOS_PREC_PRIORITY 0x20
#define IPTOS_PREC_ROUTINE 0x00
/*
* Commands for ioctlsocket(), taken from the BSD file fcntl.h.
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -101,9 +101,49 @@ extern struct stats_ lwip_stats;
void stats_init(void);
#define STATS_INC(x) ++lwip_stats.x
#else
#define stats_init()
#define STATS_INC(x)
#endif /* LWIP_STATS */
#if TCP_STATS
#define TCP_STATS_INC(x) STATS_INC(x)
#else
#define TCP_STATS_INC(x)
#endif
#if UDP_STATS
#define UDP_STATS_INC(x) STATS_INC(x)
#else
#define UDP_STATS_INC(x)
#endif
#if ICMP_STATS
#define ICMP_STATS_INC(x) STATS_INC(x)
#else
#define ICMP_STATS_INC(x)
#endif
#if IP_STATS
#define IP_STATS_INC(x) STATS_INC(x)
#else
#define IP_STATS_INC(x)
#endif
#if IPFRAG_STATS
#define IPFRAG_STATS_INC(x) STATS_INC(x)
#else
#define IPFRAG_STATS_INC(x)
#endif
#if LINK_STATS
#define LINK_STATS_INC(x) STATS_INC(x)
#else
#define LINK_STATS_INC(x)
#endif
#endif /* __LWIP_STATS_H__ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -53,7 +53,7 @@ void tcp_init (void); /* Must be called first to
initialize TCP. */
void tcp_tmr (void); /* Must be called every
TCP_TMR_INTERVAL
ms. (Typically 100 ms). */
ms. (Typically 250 ms). */
/* Application program's interface: */
struct tcp_pcb * tcp_new (void);
struct tcp_pcb * tcp_alloc (u8_t prio);
@@ -115,30 +115,32 @@ void tcp_rexmit (struct tcp_pcb *pcb);
#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
#define TCP_FIN 0x01
#define TCP_SYN 0x02
#define TCP_RST 0x04
#define TCP_PSH 0x08
#define TCP_ACK 0x10
#define TCP_URG 0x20
#define TCP_FIN 0x01U
#define TCP_SYN 0x02U
#define TCP_RST 0x04U
#define TCP_PSH 0x08U
#define TCP_ACK 0x10U
#define TCP_URG 0x20U
#define TCP_ECE 0x40U
#define TCP_CWR 0x80U
#define TCP_FLAGS 0x3f
#define TCP_FLAGS 0x3fU
/* Length of the TCP header, excluding options. */
#define TCP_HLEN 20
#ifndef TCP_TMR_INTERVAL
#define TCP_TMR_INTERVAL 100 /* The TCP timer interval in
#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in
milliseconds. */
#endif /* TCP_TMR_INTERVAL */
#ifndef TCP_FAST_INTERVAL
#define TCP_FAST_INTERVAL 200 /* the fine grained timeout in
#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in
milliseconds */
#endif /* TCP_FAST_INTERVAL */
#ifndef TCP_SLOW_INTERVAL
#define TCP_SLOW_INTERVAL 500 /* the coarse grained timeout in
#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in
milliseconds */
#endif /* TCP_SLOW_INTERVAL */
@@ -149,6 +151,19 @@ void tcp_rexmit (struct tcp_pcb *pcb);
#define TCP_MSL 60000 /* The maximum segment lifetime in microseconds */
/*
* User-settable options (used with setsockopt).
*/
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keepalive miliseconds */
/* Keepalive values */
#define TCP_KEEPDEFAULT 7200000 /* KEEPALIVE timer in miliseconds */
#define TCP_KEEPINTVL 75000 /* Time between KEEPALIVE probes in miliseconds */
#define TCP_KEEPCNT 9 /* Counter for KEEPALIVE probes */
#define TCP_MAXIDLE TCP_KEEPCNT * TCP_KEEPINTVL /* Maximum KEEPALIVE probe time */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
@@ -158,7 +173,7 @@ struct tcp_hdr {
PACK_STRUCT_FIELD(u16_t dest);
PACK_STRUCT_FIELD(u32_t seqno);
PACK_STRUCT_FIELD(u32_t ackno);
PACK_STRUCT_FIELD(u16_t _offset_flags);
PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
PACK_STRUCT_FIELD(u16_t wnd);
PACK_STRUCT_FIELD(u16_t chksum);
PACK_STRUCT_FIELD(u16_t urgp);
@@ -168,11 +183,15 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
#define TCPH_OFFSET(hdr) (ntohs((hdr)->_offset_flags) >> 8)
#define TCPH_FLAGS(hdr) (ntohs((hdr)->_offset_flags) & 0xff)
#define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
#define TCPH_OFFSET_SET(hdr, offset) (hdr)->_offset_flags = htons(((offset) << 8) | TCPH_FLAGS(hdr))
#define TCPH_FLAGS_SET(hdr, flags) (hdr)->_offset_flags = htons((TCPH_OFFSET(hdr) << 8) | (flags))
#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons((ntohs((phdr)->_hdrlen_rsvd_flags) & ~TCP_FLAGS) | (flags))
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (flags))
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & TCP_FIN || \
TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0))
@@ -194,17 +213,30 @@ enum tcp_state {
/* the TCP protocol control block */
struct tcp_pcb {
/* 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 */
u8_t prio;
void *callback_arg;
struct ip_addr local_ip;
u16_t local_port;
enum tcp_state state; /* TCP state */
struct ip_addr remote_ip;
u16_t remote_port;
u8_t flags;
#define TF_ACK_DELAY (u8_t)0x01U /* Delayed ACK. */
#define TF_ACK_NOW (u8_t)0x02U /* Immediate ACK. */
#define TF_INFR (u8_t)0x04U /* In fast recovery. */
#define TF_RESET (u8_t)0x08U /* Connection was reset. */
#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
#define TF_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */
/* receiver varables */
u32_t rcv_nxt; /* next seqno expected */
u16_t rcv_wnd; /* receiver window */
@@ -217,14 +249,6 @@ struct tcp_pcb {
u16_t rtime;
u16_t mss; /* maximum segment size */
u8_t flags;
#define TF_ACK_DELAY 0x01U /* Delayed ACK. */
#define TF_ACK_NOW 0x02U /* Immediate ACK. */
#define TF_INFR 0x04U /* In fast recovery. */
#define TF_RESET 0x08U /* Connection was reset. */
#define TF_CLOSED 0x10U /* Connection was sucessfully closed. */
#define TF_GOT_FIN 0x20U /* Connection was closed by the remote end. */
/* RTT estimation variables. */
u16_t rttest; /* RTT estimate in 500ms ticks */
@@ -282,21 +306,32 @@ struct tcp_pcb {
/* Function to be called whenever a fatal error occurs. */
void (* errf)(void *arg, err_t err);
#endif /* LWIP_CALLBACK_API */
/* idle time before KEEPALIVE is sent */
u32_t keepalive;
/* KEEPALIVE counter */
u8_t keep_cnt;
};
struct tcp_pcb_listen {
/* Common members of all PCB types */
IP_PCB;
/* Protocol specific PCB members */
struct tcp_pcb_listen *next; /* for the linked list */
u8_t prio;
void *callback_arg;
struct ip_addr local_ip;
u16_t local_port;
/* Even if state is obviously LISTEN this is here for
* field compatibility with tpc_pcb to which it is cast sometimes
* Until a cleaner solution emerges this is here.FIXME
*/
enum tcp_state state; /* TCP state */
u8_t prio;
void *callback_arg;
u16_t local_port;
#if LWIP_CALLBACK_API
/* Function to call when a listener has been connected. */
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
@@ -396,6 +431,8 @@ void tcp_rst(u32_t seqno, u32_t ackno,
u32_t tcp_next_iss(void);
void tcp_keepalive(struct tcp_pcb *pcb);
extern struct tcp_pcb *tcp_input_pcb;
extern u32_t tcp_ticks;
@@ -406,7 +443,11 @@ void tcp_debug_print_state(enum tcp_state s);
void tcp_debug_print_pcbs(void);
int tcp_pcbs_sane(void);
#else
#define tcp_pcbs_sane() 1
# define tcp_debug_print(tcphdr)
# define tcp_debug_print_flags(flags)
# define tcp_debug_print_state(s)
# define tcp_debug_print_pcbs()
# define tcp_pcbs_sane() 1
#endif /* TCP_DEBUG */
#if NO_SYS

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -38,8 +38,6 @@
#include "lwip/inet.h"
#include "lwip/ip.h"
#include "lwip/err.h"
#define UDP_HLEN 8
struct udp_hdr {
@@ -54,12 +52,16 @@ struct udp_hdr {
#define UDP_FLAGS_CONNECTED 0x04U
struct udp_pcb {
/* Common members of all PCB types */
IP_PCB;
/* Protocol specific PCB members */
struct udp_pcb *next;
struct ip_addr local_ip, remote_ip;
u8_t flags;
u16_t local_port, remote_port;
u8_t flags;
u16_t chksum_len;
void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
@@ -89,11 +91,14 @@ err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);
/* The following functions are the lower layer interface to UDP. */
u8_t udp_lookup (struct ip_hdr *iphdr, struct netif *inp);
void udp_input (struct pbuf *p, struct netif *inp);
void udp_init (void);
#if UDP_DEBUG
int udp_debug_print(struct udp_hdr *udphdr);
#else
#define udp_debug_print(udphdr)
#endif
#endif /* __LWIP_UDP_H__ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -4,12 +4,14 @@
*
* Functionally, ARP is divided into two parts. The first maps an IP address
* to a physical address when sending a packet, and the second part answers
* requests from other machines.
* requests from other machines for our physical address.
*
* This implementation complies with RFC 826 (Ethernet ARP) and supports
* Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6.
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -40,6 +42,13 @@
*
*/
/**
* TODO:
* - pbufs should be sent from the queue once an ARP entry state
* goes from PENDING to STABLE.
* - Non-PENDING entries MUST NOT have queued packets.
*/
/*
* TODO:
*
@@ -111,6 +120,9 @@ struct etharp_entry {
struct eth_addr ethaddr;
enum etharp_state state;
#if ARP_QUEUEING
/**
* Pointer to queue of pending outgoing packets on this ARP entry.
* Must be at most a single packet for now. */
struct pbuf *p;
#endif
u8_t ctime;
@@ -119,22 +131,27 @@ struct etharp_entry {
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
static struct pbuf *update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
static s8_t find_arp_entry(void);
#define ARP_INSERT_FLAG 1
static struct pbuf *update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
#if ARP_QUEUEING
static struct pbuf *etharp_enqueue(s8_t i, struct pbuf *q);
static u8_t etharp_dequeue(s8_t i);
#endif
/**
* Initializes ARP module.
*/
void
etharp_init(void)
{
u8_t i;
s8_t i;
/* clear ARP entries */
for(i = 0; i < ARP_TABLE_SIZE; ++i) {
arp_table[i].state = ETHARP_STATE_EMPTY;
#if ARP_QUEUEING
arp_table[i].p = NULL;
#endif
arp_table[i].ctime = 0;
}
}
@@ -147,32 +164,31 @@ etharp_init(void)
void
etharp_tmr(void)
{
u8_t i;
s8_t i;
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
/* remove expired entries from the ARP table */
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
arp_table[i].ctime++;
/* a resolved/stable entry? */
if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
/* entry has become old? */
(arp_table[i].ctime >= ARP_MAXAGE)) {
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
arp_table[i].state = ETHARP_STATE_EMPTY;
#if ARP_QUEUEING
if (arp_table[i].p != NULL) {
/* remove any queued packet */
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing packet queue %p.\n", i, (void *)(arp_table[i].p)));
pbuf_free(arp_table[i].p);
arp_table[i].p = NULL;
}
#endif
goto empty;
/* an unresolved/pending entry? */
} else if ((arp_table[i].state == ETHARP_STATE_PENDING) &&
/* entry unresolved/pending for too long? */
(arp_table[i].ctime >= ARP_MAXPENDING)) {
arp_table[i].state = ETHARP_STATE_EMPTY;
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i));
empty:
/* empty old entry */
arp_table[i].state = ETHARP_STATE_EMPTY;
#if ARP_QUEUEING
/* and empty packet queue */
if (arp_table[i].p != NULL) {
/* remove any queued packet */
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing packet queue %p.\n", i, (void *)(arp_table[i].p)));
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %u, packet queue %p.\n", i, (void *)(arp_table[i].p)));
pbuf_free(arp_table[i].p);
arp_table[i].p = NULL;
}
@@ -182,55 +198,125 @@ etharp_tmr(void)
}
/**
* Return an empty ARP entry or, if the table is full, ARP_TABLE_SIZE if all
* entries are pending, otherwise the oldest entry.
* Return an empty ARP entry (possibly recycling the oldest stable entry).
*
* @return The ARP entry index that is available, ARP_TABLE_SIZE if no usable
* @return The ARP entry index that is available, ERR_MEM if no usable
* entry is found.
*/
static u8_t
static s8_t
find_arp_entry(void)
{
u8_t i, j, maxtime;
s8_t i, j;
u8_t maxtime = 0;
/* Try to find an unused entry in the ARP table. */
j = ARP_TABLE_SIZE;
/* search ARP table for an unused or old entry */
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
/* empty entry? */
if (arp_table[i].state == ETHARP_STATE_EMPTY) {
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found empty entry %u\n", i));
break;
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning empty entry %u\n", i));
return i;
/* stable entry? */
} else if (arp_table[i].state == ETHARP_STATE_STABLE) {
/* remember entry with oldest stable entry in j */
if (arp_table[i].ctime >= maxtime) maxtime = arp_table[j = i].ctime;
}
}
/* no empty entry found? */
if (i == ARP_TABLE_SIZE) {
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j));
/* fall-back to oldest stable */
i = j;
}
/* no available entry found? */
if (i == ARP_TABLE_SIZE) {
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: no replacable entry could be found\n"));
/* return failure */
return ERR_MEM;
}
/* If no unused entry is found, we try to find the oldest entry and
throw it away. If all entries are new and have 0 ctime drop one */
if (i == ARP_TABLE_SIZE) {
maxtime = 0;
j = ARP_TABLE_SIZE;
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
/* remember entry with oldest stable entry in j*/
if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
#if ARP_QUEUEING /* do not want to re-use an entry with queued packets */
(arp_table[i].p == NULL) &&
/* clean up the recycled stable entry */
if (arp_table[i].state == ETHARP_STATE_STABLE) {
#if ARP_QUEUEING
/* free packets on queue */
etharp_dequeue(i);
#endif
(arp_table[i].ctime >= maxtime)) {
maxtime = arp_table[i].ctime;
j = i;
}
}
if (j != ARP_TABLE_SIZE) {
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j));
} else {
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: no replacable entry could be found\n"));
}
i = j;
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_arp_entry: recycling oldest stable entry %u\n", i));
arp_table[i].state = ETHARP_STATE_EMPTY;
arp_table[i].ctime = 0;
}
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning %u, state %u\n", i, arp_table[i].state));
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning %u\n", i));
return i;
}
#if ARP_QUEUEING
/*
* Enqueues a pbuf (chain) on an ARP entry.
*
* Places the pbuf (chain) on the queue (if space allows). The
* caller may safely free the pbuf (chain) afterwards, as the
* pbufs will be referenced by the queue and copies are made of
* pbufs referencing external payloads.
*
* @ i the ARP entry index
* @arg q the pbuf (chain) to be queued on the ARP entry
*
* @return Returns the new head of queue of the ARP entry.
*
*/
static struct pbuf *
etharp_enqueue(s8_t i, struct pbuf *q)
{
/* any pbuf to queue? */
if (q != NULL) {
/* queue later packet over earliers? TODO: Implement multiple pbuf queue */
#if ARP_QUEUE_FIRST == 0
/* remove any pbufs on queue */
u8_t deq = etharp_dequeue(i);
if (deq > 0) LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dequeued %u pbufs from ARP entry %u. Should not occur.\n", deq, i));
#endif
/* packet can be queued? TODO: Implement multiple pbuf queue */
if (arp_table[i].p == NULL) {
/* copy any PBUF_REF referenced payloads into PBUF_RAM */
q = pbuf_take(q);
/* add pbuf to queue */
arp_table[i].p = q;
/* pbuf (chain) now queued, increase the reference count */
pbuf_ref(q);
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i));
}
}
return arp_table[i].p;
}
/**
* Dequeues any pbufs queued on an ARP entry
*
* @return number of pbufs removed from the queue
*
* TODO: decide what is a sensible return value?
*/
static u8_t
etharp_dequeue(s8_t i)
{
/* queued packets on a stable entry (work in progress) */
if (arp_table[i].p != NULL) {
/* queue no longer references pbuf */
pbuf_free(arp_table[i].p);
arp_table[i].p = NULL;
return 1;
} else {
return 0;
}
}
#endif
/**
* Update (or insert) a IP/MAC address pair in the ARP cache.
*
* If a pending entry is resolved, any queued packets will be sent
* at this point.
*
* @param ipaddr IP address of the inserted ARP entry.
* @param ethaddr Ethernet address of the inserted ARP entry.
* @param flags Defines behaviour:
@@ -245,7 +331,7 @@ find_arp_entry(void)
static struct pbuf *
update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
{
u8_t i, k;
s8_t i, k;
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n"));
LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0);
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: %u.%u.%u.%u - %02x:%02x:%02x:%02x:%02x:%02x\n", ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr),
@@ -269,7 +355,7 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
arp_table[i].state = ETHARP_STATE_STABLE;
/* fall-through to next if */
}
/* stable entry? (possible just marked to become stable) */
/* stable entry? (possibly just marked to become stable) */
if (arp_table[i].state == ETHARP_STATE_STABLE) {
#if ARP_QUEUEING
struct pbuf *p;
@@ -282,29 +368,50 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
}
/* reset time stamp */
arp_table[i].ctime = 0;
/* this is where we will send out queued packets! */
#if ARP_QUEUEING
/* get the first packet on the queue (if any) */
p = arp_table[i].p;
/* queued packet present? */
if (p != NULL) {
/* NULL attached buffer immediately */
arp_table[i].p = NULL;
/* (another) queued packet present? */
while (p != NULL) {
struct pbuf *q, *n;
/* search for second packet on queue (n) */
q = p;
while (q->tot_len > q->len) {
LWIP_ASSERT("q->next != NULL (while q->tot_len > q->len)", q->next != NULL);
/* proceed to next pbuf of this packet */
q = q->next;
}
/* { q = last pbuf of this packet, q->tot_len == q->len } */
LWIP_ASSERT("q->tot_len == q->len", q->tot_len == q->len);
/* remember next packet on queue */
n = q->next;
/* { n = first pbuf of next packet, or NULL if no next packet } */
/* terminate this packet pbuf chain */
q->next = NULL;
/* fill-in Ethernet header */
ethhdr = p->payload;
for (k = 0; k < netif->hwaddr_len; ++k) {
ethhdr->dest.addr[k] = ethaddr->addr[k];
ethhdr->src.addr[k] = netif->hwaddr[k];
}
ethhdr->type = htons(ETHTYPE_IP);
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet.\n"));
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet %p.\n", (void *)p));
/* send the queued IP packet */
netif->linkoutput(netif, p);
/* free the queued IP packet */
pbuf_free(p);
/* proceed to next packet on queue */
p = n;
}
/* NULL attached buffer*/
arp_table[i].p = NULL;
#endif
/* IP addresses should only occur once in the ARP entry, we are done */
return NULL;
}
} /* if */
} /* for */
} /* if STABLE */
} /* for all ARP entries */
/* no matching ARP entry was found */
LWIP_ASSERT("update_arp_entry: i == ARP_TABLE_SIZE", i == ARP_TABLE_SIZE);
@@ -316,21 +423,10 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: adding entry to table\n"));
/* find an empty or old entry. */
i = find_arp_entry();
if (i == ARP_TABLE_SIZE) {
if (i == ERR_MEM) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no available entry found\n"));
return NULL;
}
/* see if find_arp_entry() gave us an old stable, or empty entry to re-use */
if (arp_table[i].state == ETHARP_STATE_STABLE) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: overwriting old stable entry %u\n", i));
/* stable entries should have no queued packets (TODO: allow later) */
#if ARP_QUEUEING
LWIP_ASSERT("update_arp_entry: arp_table[i].p == NULL", arp_table[i].p == NULL);
#endif
} else {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("update_arp_entry: filling empty entry %u with state %u\n", i, arp_table[i].state));
LWIP_ASSERT("update_arp_entry: arp_table[i].state == ETHARP_STATE_EMPTY", arp_table[i].state == ETHARP_STATE_EMPTY);
}
/* set IP address */
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
/* set Ethernet hardware address */
@@ -354,7 +450,7 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
}
/**
* Updates the ARP table using the given packet.
* Updates the ARP table using the given IP packet.
*
* Uses the incoming IP packet's source address to update the
* ARP cache for the local network. The function does not alter
@@ -368,7 +464,7 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
*
* @see pbuf_free()
*/
struct pbuf *
void
etharp_ip_input(struct netif *netif, struct pbuf *p)
{
struct ethip_hdr *hdr;
@@ -379,18 +475,19 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
/* source is on local network? */
if (!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
/* do nothing */
return NULL;
return;
}
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
/* update ARP table, ask to insert entry */
update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG);
return NULL;
return;
}
/**
* Responds to ARP requests, updates ARP entries and sends queued IP packets.
* Responds to ARP requests to us. Upon ARP replies to us, add entry to cache
* send out queued IP packets. Updates cache with snooped address pairs.
*
* Should be called for incoming ARP packets. The pbuf in the argument
* is freed by this function.
@@ -403,20 +500,31 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
*
* @see pbuf_free()
*/
struct pbuf *
void
etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
{
struct etharp_hdr *hdr;
u8_t i;
u8_t for_us;
/* drop short ARP packets */
if (p->tot_len < sizeof(struct etharp_hdr)) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
pbuf_free(p);
return NULL;
return;
}
hdr = p->payload;
/* this interface is not configured? */
if (netif->ip_addr.addr == 0) {
for_us = 0;
} else {
/* ARP packet directed to us? */
for_us = ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr));
}
/* first, let's answer */
switch (htons(hdr->opcode)) {
/* ARP request? */
@@ -430,12 +538,10 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
if (netif->ip_addr.addr == 0) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
pbuf_free(p);
return NULL;
return;
}
/* update the ARP cache */
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
/* ARP request for our address? */
if (ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
if (for_us) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
/* re-use pbuf to send ARP reply */
@@ -444,7 +550,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr));
ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
for(i = 0; i < netif->hwaddr_len; ++i) {
for (i = 0; i < netif->hwaddr_len; ++i) {
hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
hdr->shwaddr.addr[i] = ethaddr->addr[i];
hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];
@@ -454,46 +560,45 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
hdr->hwtype = htons(HWTYPE_ETHERNET);
ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
hdr->proto = htons(ETHTYPE_IP);
hdr->proto = htons(ETHTYPE_IP);
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
hdr->ethhdr.type = htons(ETHTYPE_ARP);
hdr->ethhdr.type = htons(ETHTYPE_ARP);
/* return ARP reply */
netif->linkoutput(netif, p);
/* request was not directed to us */
} else {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n"));
}
break;
case ARP_REPLY:
/* ARP reply. We insert or update the ARP table. */
/* ARP reply. We insert or update the ARP table later. */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
/* DHCP needs to know about ARP replies */
dhcp_arp_reply(netif, &hdr->sipaddr);
/* DHCP wants to know about ARP replies to our wanna-have-address */
if (for_us) dhcp_arp_reply(netif, &hdr->sipaddr);
#endif
/* ARP reply directed to us? */
if (ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is for us\n"));
/* update_the ARP cache, ask to insert */
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG);
/* ARP reply not directed to us */
} else {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is not for us\n"));
/* update the destination address pair */
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
/* update the destination address pair */
update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0);
}
break;
default:
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode)));
break;
}
/* add or update entries in the ARP cache */
if (for_us) {
/* insert IP address in ARP cache (assume requester wants to talk to us)
* we might even send out a queued packet to this host */
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG);
/* request was not directed to us, but snoop for updates anyway */
} else {
/* update or insert the source IP address in the cache */
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
/* update or insert the destination IP address pair in the cache */
update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0);
}
/* free ARP packet */
pbuf_free(p);
p = NULL;
/* nothing to send, we did it! */
return NULL;
}
/**
@@ -503,47 +608,43 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
* returned, ready to be sent.
*
* If ARP does not have the Ethernet address in cache the packet is
* queued and a ARP request is sent (on a best-effort basis). This
* ARP request is returned as a pbuf, which should be sent by the
* caller.
*
* If ARP failed to allocate resources, NULL is returned.
* queued (if enabled and space available) and a ARP request is sent.
* This ARP request is returned as a pbuf, which should be sent by
* the caller.
*
* A returned non-NULL packet should be sent by the caller.
*
* If ARP failed to allocate resources, NULL is returned.
*
* @param netif The lwIP network interface which the IP packet will be sent on.
* @param ipaddr The IP address of the packet destination.
* @param pbuf The pbuf(s) containing the IP packet to be sent.
*
* @return If non-NULL, a packet ready to be sent.
* @return If non-NULL, a packet ready to be sent by caller.
*
*/
struct pbuf *
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
{
struct eth_addr *dest, *srcaddr, mcastaddr;
struct eth_hdr *ethhdr;
u8_t i;
s8_t i;
/* Make room for Ethernet header. */
/* make room for Ethernet header */
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
/* The pbuf_header() call shouldn't fail, and we'll just bail
out if it does.. */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
#ifdef LINK_STATS
++lwip_stats.link.lenerr;
#endif /* LINK_STATS */
LINK_STATS_INC(link.lenerr);
return NULL;
}
/* obtain source Ethernet address of the given interface */
srcaddr = (struct eth_addr *)netif->hwaddr;
/* assume unresolved Ethernet address */
dest = NULL;
/* Construct Ethernet header. Start with looking up deciding which
MAC address to use as a destination address. Broadcasts and
multicasts are special, all other addresses are looked up in the
ARP table. */
MAC address to use as a destination address. Broadcasts and
multicasts are special, all other addresses are looked up in the
ARP table. */
/* destination IP address is an IP broadcast address? */
if (ip_addr_isany(ipaddr) ||
@@ -555,7 +656,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
else if (ip_addr_ismulticast(ipaddr)) {
/* Hash IP multicast address to MAC address. */
mcastaddr.addr[0] = 0x01;
mcastaddr.addr[1] = 0x0;
mcastaddr.addr[1] = 0x00;
mcastaddr.addr[2] = 0x5e;
mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
mcastaddr.addr[4] = ip4_addr3(ipaddr);
@@ -565,25 +666,26 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
}
/* destination IP address is an IP unicast address */
else {
/* destination IP network address not on local network? */
/* this occurs if the packet is routed to the default gateway on this interface */
/* destination IP network address not on local network?
* IP layer wants us to forward to the default gateway */
if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
/* gateway available? */
/* interface has default gateway? */
if (netif->gw.addr != 0)
{
/* use the gateway IP address */
/* route to default gateway IP address */
ipaddr = &(netif->gw);
}
/* no gateway available? */
else
{
/* IP destination address outside local network, but no gateway available */
/* { packet is discarded } */
return NULL;
}
}
/* Ethernet address for IP destination address is in ARP cache? */
for(i = 0; i < ARP_TABLE_SIZE; ++i) {
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
/* match found? */
if (arp_table[i].state == ETHARP_STATE_STABLE &&
ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
@@ -594,7 +696,9 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
/* could not find the destination Ethernet address in ARP cache? */
if (dest == NULL) {
/* ARP query for the IP address, submit this IP packet for queueing */
/* TODO: How do we handle netif->ipaddr == ipaddr? */
etharp_query(netif, ipaddr, q);
/* { packet was queued (ERR_OK), or discarded } */
/* return nothing */
return NULL;
}
@@ -607,8 +711,11 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
/* destination Ethernet address known */
if (dest != NULL) {
/* A valid IP->MAC address mapping was found, so we construct the
Ethernet header for the outgoing packet. */
/* obtain source Ethernet address of the given interface */
srcaddr = (struct eth_addr *)netif->hwaddr;
/* A valid IP->MAC address mapping was found, fill in the
* Ethernet header for the outgoing packet */
ethhdr = q->payload;
for(i = 0; i < netif->hwaddr_len; i++) {
@@ -649,9 +756,8 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
{
struct eth_addr *srcaddr;
struct etharp_hdr *hdr;
struct pbuf *p;
err_t result = ERR_OK;
u8_t i;
s8_t i;
u8_t perform_arp_request = 1;
/* prevent 'unused argument' warning if ARP_QUEUEING == 0 */
(void)q;
@@ -661,7 +767,7 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
if (ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
if (arp_table[i].state == ETHARP_STATE_PENDING) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already pending as entry %u\n", i));
/* break out of for-loop, user may wish to queue a packet on a stable entry */
/* break out of for-loop, user may wish to queue a packet on a pending entry */
/* TODO: we will issue a new ARP request, which should not occur too often */
/* we might want to run a faster timer on ARP to limit this */
break;
@@ -678,56 +784,26 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
/* queried address not yet in ARP table? */
if (i == ARP_TABLE_SIZE) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: IP address not found in ARP table\n"));
/* find an available entry */
/* find an available (unused or old) entry */
i = find_arp_entry();
/* bail out if no ARP entries are available */
if (i == ARP_TABLE_SIZE) {
LWIP_DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available.\n"));
if (i == ERR_MEM) {
LWIP_DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available. Should seldom occur.\n"));
return ERR_MEM;
}
/* we will now recycle entry i */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: created ARP table entry %u.\n", i));
/* i is available, create ARP entry */
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
arp_table[i].ctime = 0;
arp_table[i].state = ETHARP_STATE_PENDING;
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
/* queried address was already in ARP table */
} else {
#if ARP_QUEUEING
/* free queued packet, as entry is now invalidated */
if (arp_table[i].p != NULL) {
pbuf_free(arp_table[i].p);
arp_table[i].p = NULL;
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n"));
}
etharp_enqueue(i, q);
#endif
}
#if ARP_QUEUEING
/* any pbuf to queue and queue is empty? */
if (q != NULL) {
/* yield later packets over older packets? */
#if ARP_QUEUE_FIRST == 0
/* earlier queued packet on this entry? */
if (arp_table[i].p != NULL) {
pbuf_free(arp_table[i].p);
arp_table[i].p = NULL;
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n"));
/* fall-through into next if */
}
#endif
/* packet can be queued? */
if (arp_table[i].p == NULL) {
/* copy PBUF_REF referenced payloads into PBUF_RAM */
q = pbuf_take(q);
/* remember pbuf to queue, if any */
arp_table[i].p = q;
/* pbufs are queued, increase the reference count */
pbuf_ref(q);
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i));
}
}
#endif
/* ARP request? */
if (perform_arp_request)
{
struct pbuf *p;
/* allocate a pbuf for the outgoing ARP request packet */
p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
/* could allocate pbuf? */
@@ -736,10 +812,12 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n"));
hdr = p->payload;
hdr->opcode = htons(ARP_REQUEST);
for(j = 0; j < netif->hwaddr_len; ++j)
for (j = 0; j < netif->hwaddr_len; ++j)
{
hdr->dhwaddr.addr[j] = 0x00;
hdr->shwaddr.addr[j] = srcaddr->addr[j];
/* the hardware address is what we ask for, in
* a request it is a don't-care, we use 0's */
hdr->dhwaddr.addr[j] = 0x00;
}
ip_addr_set(&(hdr->dipaddr), ipaddr);
ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
@@ -749,7 +827,7 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
hdr->proto = htons(ETHTYPE_IP);
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
for(j = 0; j < netif->hwaddr_len; ++j)
for (j = 0; j < netif->hwaddr_len; ++j)
{
hdr->ethhdr.dest.addr[j] = 0xff;
hdr->ethhdr.src.addr[j] = srcaddr->addr[j];

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -63,7 +63,7 @@ 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)
{
@@ -87,7 +87,7 @@ low_level_init(struct netif *netif)
/* Do whatever else is needed to initialize interface. */
}
/*-----------------------------------------------------------------------------------*/
/*
* low_level_output():
*
@@ -96,7 +96,7 @@ low_level_init(struct netif *netif)
* might be chained.
*
*/
/*-----------------------------------------------------------------------------------*/
static err_t
low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
@@ -120,7 +120,7 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* low_level_input():
*
@@ -128,7 +128,7 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
* packet from the interface into the pbuf.
*
*/
/*-----------------------------------------------------------------------------------*/
static struct pbuf *
low_level_input(struct ethernetif *ethernetif)
{
@@ -165,7 +165,7 @@ low_level_input(struct ethernetif *ethernetif)
return p;
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_output():
*
@@ -174,7 +174,7 @@ low_level_input(struct ethernetif *ethernetif)
* do the actuall transmission of the packet.
*
*/
/*-----------------------------------------------------------------------------------*/
static err_t
ethernetif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr)
@@ -264,7 +264,7 @@ ethernetif_output(struct netif *netif, struct pbuf *p,
return low_level_output(ethernetif, p);
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_input():
*
@@ -274,7 +274,7 @@ ethernetif_output(struct netif *netif, struct pbuf *p,
* interface.
*
*/
/*-----------------------------------------------------------------------------------*/
static void
ethernetif_input(struct netif *netif)
{
@@ -314,14 +314,14 @@ ethernetif_input(struct netif *netif)
}
}
}
/*-----------------------------------------------------------------------------------*/
static void
arp_timer(void *arg)
{
arp_tmr();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_init():
*
@@ -330,7 +330,7 @@ arp_timer(void *arg)
* actual setup of the hardware.
*
*/
/*-----------------------------------------------------------------------------------*/
void
ethernetif_init(struct netif *netif)
{
@@ -350,4 +350,4 @@ ethernetif_init(struct netif *netif)
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -29,9 +29,12 @@
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/mem.h"
#include "lwip/opt.h"
#if LWIP_HAVE_LOOPIF
#include "netif/loopif.h"
#include "lwip/mem.h"
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
#include "netif/tcpdump.h"
@@ -40,13 +43,23 @@
#include "lwip/tcp.h"
#include "lwip/ip.h"
/*-----------------------------------------------------------------------------------*/
static void
loopif_input( void * arg )
{
struct netif *netif = (struct netif *)( ((void **)arg)[ 0 ] );
struct pbuf *r = (struct pbuf *)( ((void **)arg)[ 1 ] );
mem_free( arg );
netif -> input( r, netif );
}
static err_t
loopif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr)
{
struct pbuf *q, *r;
char *ptr;
void **arg;
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
tcpdump(p);
@@ -60,21 +73,43 @@ loopif_output(struct netif *netif, struct pbuf *p,
memcpy(ptr, q->payload, q->len);
ptr += q->len;
}
netif->input(r, netif);
arg = mem_malloc( sizeof( void *[2]));
if( NULL == arg ) {
return ERR_MEM;
}
arg[0] = netif;
arg[1] = r;
/**
* workaround (patch #1779) to try to prevent bug #2595:
* When connecting to "localhost" with the loopif interface,
* tcp_output doesn't get the opportunity to finnish sending the
* segment before tcp_process gets it, resulting in tcp_process
* referencing pcb->unacked-> which still is NULL.
*
* TODO: Is there still a race condition here? Leon
*/
sys_timeout( 1, loopif_input, arg );
return ERR_OK;
}
return ERR_MEM;
}
/*-----------------------------------------------------------------------------------*/
err_t
loopif_init(struct netif *netif)
{
netif->name[0] = 'l';
netif->name[1] = 'o';
#if 0 /** TODO: I think this should be enabled, or not? Leon */
netif->input = loopif_input;
#endif
netif->output = loopif_output;
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_HAVE_LOOPIF */

View File

@@ -122,7 +122,7 @@ static int get_pap_passwd (int, char *, char *);
static int have_pap_secret (void);
static int have_chap_secret (char *, char *, u32_t);
static int ip_addr_check (u32_t, struct wordlist *);
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
#if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT > 0 */
static void set_allowed_addrs(int unit, struct wordlist *addrs);
static void free_wordlist (struct wordlist *);
#endif
@@ -194,7 +194,7 @@ void link_terminated(int unit)
if (logged_in)
logout();
lcp_phase[unit] = PHASE_DEAD;
ppp_trace(LOG_NOTICE, "Connection terminated.\n");
AUTHDEBUG((LOG_NOTICE, "Connection terminated.\n"));
pppMainWakeup(unit);
}
@@ -257,7 +257,7 @@ void link_established(int unit)
* of "" and a password of "". If that's not OK, boot it out.
*/
if (!wo->neg_upap || !null_login(unit)) {
ppp_trace(LOG_WARNING, "peer refused to authenticate\n");
AUTHDEBUG((LOG_WARNING, "peer refused to authenticate\n"));
lcp_close(unit, "peer refused to authenticate");
return;
}
@@ -294,7 +294,7 @@ void link_established(int unit)
if (ppp_settings.passwd[0] == 0) {
passwd_from_file = 1;
if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd))
ppp_trace(LOG_ERR, "No secret found for PAP login\n");
AUTHDEBUG((LOG_ERR, "No secret found for PAP login\n"));
}
upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd);
auth |= PAP_WITHPEER;
@@ -337,8 +337,8 @@ void auth_peer_success(int unit, u16_t protocol, char *name, int namelen)
pbit = PAP_PEER;
break;
default:
ppp_trace(LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
protocol);
AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
protocol));
return;
}
@@ -400,8 +400,8 @@ void auth_withpeer_success(int unit, u16_t protocol)
pbit = PAP_WITHPEER;
break;
default:
ppp_trace(LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
protocol);
AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
protocol));
pbit = 0;
}
@@ -476,7 +476,7 @@ void auth_reset(int unit)
AUTHDEBUG((LOG_INFO, "auth_reset: %d\n", unit));
ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL));
ao->neg_chap = !ppp_settings.refuse_chap && have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0);
ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/;
if (go->neg_upap && !have_pap_secret())
go->neg_upap = 0;
@@ -541,7 +541,7 @@ int check_passwd(
* On 10'th, drop the connection.
*/
if (attempts++ >= 10) {
ppp_trace(LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user);
AUTHDEBUG((LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user));
/*ppp_panic("Excess Bad Logins");*/
}
if (attempts > 3) {
@@ -605,7 +605,24 @@ int get_secret(
)
{
#if 1
int len;
struct wordlist *addrs;
addrs = NULL;
if(!client || !client[0] || strcmp(client, ppp_settings.user)) {
return 0;
}
len = strlen(ppp_settings.passwd);
if (len > MAXSECRETLEN) {
AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
len = MAXSECRETLEN;
}
BCOPY(ppp_settings.passwd, secret, len);
*secret_len = len;
return 1;
#else
int ret = 0, len;
struct wordlist *addrs;
@@ -623,7 +640,7 @@ int get_secret(
len = strlen(secbuf);
if (len > MAXSECRETLEN) {
ppp_trace(LOG_ERR, "Secret for %s on %s is too long\n", client, server);
AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
len = MAXSECRETLEN;
}
BCOPY(secbuf, secret, len);
@@ -736,7 +753,7 @@ static void check_idle(void *arg)
itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle);
if (itime >= ppp_settings.idle_time_limit) {
/* link is idle: shut it down. */
ppp_trace(LOG_INFO, "Terminating connection due to lack of activity.\n");
AUTHDEBUG((LOG_INFO, "Terminating connection due to lack of activity.\n"));
lcp_close(0, "Link inactive");
} else {
TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime);
@@ -750,7 +767,7 @@ static void connect_time_expired(void *arg)
{
(void)arg;
ppp_trace(LOG_INFO, "Connect time expired\n");
AUTHDEBUG((LOG_INFO, "Connect time expired\n"));
lcp_close(0, "Connect time expired"); /* Close connection */
}
@@ -841,7 +858,7 @@ static int have_chap_secret(char *client, char *server, u32_t remote)
}
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
#if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT > 0 */
/*
* set_allowed_addrs() - set the list of allowed addresses.
*/
@@ -891,7 +908,7 @@ static int ip_addr_check(u32_t addr, struct wordlist *addrs)
return 1;
}
#if PAP_SUPPORT > 0 || CHAP_SUPPORT
#if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT */
/*
* free_wordlist - release memory allocated for a wordlist.
*/

View File

@@ -245,7 +245,7 @@ static void ChapChallengeTimeout(void *arg)
if (cstate->chal_transmits >= cstate->max_transmits) {
/* give up on peer */
ppp_trace(LOG_ERR, "Peer failed to respond to CHAP challenge\n");
CHAPDEBUG((LOG_ERR, "Peer failed to respond to CHAP challenge\n"));
cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, PPP_CHAP);
return;
@@ -405,7 +405,7 @@ static void ChapInput(int unit, u_char *inpacket, int packet_len)
break;
default: /* Need code reject? */
ppp_trace(LOG_WARNING, "Unknown CHAP code (%d) received.\n", code);
CHAPDEBUG((LOG_WARNING, "Unknown CHAP code (%d) received.\n", code));
break;
}
}
@@ -466,7 +466,7 @@ static void ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int le
if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
secret, &secret_len, 0)) {
secret_len = 0; /* assume null secret if can't find one */
ppp_trace(LOG_WARNING, "No CHAP secret found for authenticating us to %s\n", rhostname);
CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating us to %s\n", rhostname));
}
/* cancel response send timeout if necessary */
@@ -576,8 +576,8 @@ static void ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len
if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
secret, &secret_len, 1)) {
/* CHAPDEBUG((LOG_WARNING, TL_CHAP, "No CHAP secret found for authenticating %s\n", rhostname)); */
ppp_trace(LOG_WARNING, "No CHAP secret found for authenticating %s\n",
rhostname);
CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating %s\n",
rhostname));
} else {
/* generate MD based on negotiated type */
@@ -614,7 +614,7 @@ static void ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len
if (cstate->chal_interval != 0)
TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
} else {
ppp_trace(LOG_ERR, "CHAP peer authentication failed\n");
CHAPDEBUG((LOG_ERR, "CHAP peer authentication failed\n"));
cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, PPP_CHAP);
}
@@ -675,7 +675,7 @@ static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int l
if (len > 0)
PRINTMSG(inp, len);
ppp_trace(LOG_ERR, "CHAP authentication failed\n");
CHAPDEBUG((LOG_ERR, "CHAP authentication failed\n"));
auth_withpeer_fail(cstate->unit, PPP_CHAP);
}

View File

@@ -29,7 +29,7 @@
* Ported to lwIP.
* 98-01-30 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
* Original built from BSD network code.
******************************************************************************
******************************************************************************/
/*
* chap.h - Challenge Handshake Authentication Protocol definitions.
*
@@ -51,7 +51,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: chpms.h,v 1.1 2003/05/27 14:37:56 jani Exp $
* $Id: chpms.h,v 1.1.6.1 2003/09/02 12:00:48 jani Exp $
*/
#ifndef CHPMS_H

View File

@@ -1192,12 +1192,12 @@ static void ipcp_up(fsm *f)
ho->hisaddr = wo->hisaddr;
if (ho->hisaddr == 0) {
ppp_trace(LOG_ERR, "Could not determine remote IP address\n");
IPCPDEBUG((LOG_ERR, "Could not determine remote IP address\n"));
ipcp_close(f->unit, "Could not determine remote IP address");
return;
}
if (go->ouraddr == 0) {
ppp_trace(LOG_ERR, "Could not determine local IP address\n");
IPCPDEBUG((LOG_ERR, "Could not determine local IP address\n"));
ipcp_close(f->unit, "Could not determine local IP address");
return;
}
@@ -1210,8 +1210,8 @@ static void ipcp_up(fsm *f)
* Check that the peer is allowed to use the IP address it wants.
*/
if (!auth_ip_addr(f->unit, ho->hisaddr)) {
ppp_trace(LOG_ERR, "Peer is not authorized to use remote address %s\n",
inet_ntoa(ho->hisaddr));
IPCPDEBUG((LOG_ERR, "Peer is not authorized to use remote address %s\n",
inet_ntoa(ho->hisaddr)));
ipcp_close(f->unit, "Unauthorized remote IP address");
return;
}

View File

@@ -216,7 +216,7 @@ static void upap_timeout(void *arg)
if (u->us_transmits >= u->us_maxtransmits) {
/* give up in disgust */
ppp_trace(LOG_ERR, "No response to PAP authenticate-requests\n");
UPAPDEBUG((LOG_ERR, "No response to PAP authenticate-requests\n"));
u->us_clientstate = UPAPCS_BADAUTH;
auth_withpeer_fail(u->us_unit, PPP_PAP);
return;
@@ -299,11 +299,11 @@ static void upap_protrej(int unit)
upap_state *u = &upap[unit];
if (u->us_clientstate == UPAPCS_AUTHREQ) {
ppp_trace(LOG_ERR, "PAP authentication failed due to protocol-reject\n");
UPAPDEBUG((LOG_ERR, "PAP authentication failed due to protocol-reject\n"));
auth_withpeer_fail(unit, PPP_PAP);
}
if (u->us_serverstate == UPAPSS_LISTEN) {
ppp_trace(LOG_ERR, "PAP authentication of peer failed (protocol-reject)\n");
UPAPDEBUG((LOG_ERR, "PAP authentication of peer failed (protocol-reject)\n"));
auth_peer_fail(unit, PPP_PAP);
}
upap_lowerdown(unit);
@@ -518,7 +518,7 @@ static void upap_rauthnak(
u->us_clientstate = UPAPCS_BADAUTH;
ppp_trace(LOG_ERR, "PAP authentication failed\n");
UPAPDEBUG((LOG_ERR, "PAP authentication failed\n"));
auth_withpeer_fail(u->us_unit, PPP_PAP);
}

View File

@@ -121,6 +121,7 @@ typedef enum {
PDDATA /* Process data byte. */
} PPPDevStates;
#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07])
/************************/
/*** LOCAL DATA TYPES ***/
@@ -141,7 +142,6 @@ typedef struct PPPControl_s {
char inEscaped; /* Escape next character. */
u16_t inProtocol; /* The input protocol code. */
u16_t inFCS; /* Input Frame Check Sequence value. */
u16_t inLen; /* Input packet length. */
int mtu; /* Peer's mru */
int pcomp; /* Does peer accept protocol compression? */
int accomp; /* Does peer accept addr/ctl compression? */
@@ -153,12 +153,12 @@ typedef struct PPPControl_s {
struct vjcompress vjComp; /* Van Jabobsen compression header. */
#endif
struct netif *netif;
struct netif netif;
struct ip_addr our_ipaddr, his_ipaddr, netmask, dns1, dns2;
struct ppp_addrs addrs;
void (*linkStatusCB)(void *arg, int errCode);
void *linkStatusArg;
void (*linkStatusCB)(void *ctx, int errCode, void *arg);
void *linkStatusCtx;
} PPPControl;
@@ -180,10 +180,6 @@ struct npioctl {
static void pppMain(void *pd);
static void pppDrop(PPPControl *pc);
static void pppInProc(int pd, u_char *s, int l);
static struct pbuf *pppMPutC(u_char c, ext_accm *outACCM, struct pbuf *nb);
static struct pbuf *pppMPutRaw(u_char c, struct pbuf *nb);
#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07])
/******************************/
@@ -294,13 +290,12 @@ void pppInit(void)
memset(&ppp_settings, 0, sizeof(ppp_settings));
ppp_settings.usepeerdns = 1;
ppp_settings.refuse_chap = (CHAP_SUPPORT == 0);
pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL);
magicInit();
for (i = 0; i < NUM_PPP; i++) {
pppControl[i].openFlag = 0;
pppControl[i].netif = NULL;
subnetMask = htonl(0xffffff00);
@@ -311,25 +306,69 @@ void pppInit(void)
(*protp->init)(i);
}
#ifdef LINK_STATS
#if LINK_STATS
/* Clear the statistics. */
memset(&lwip_stats.link, 0, sizeof(lwip_stats.link));
#endif
}
void pppSetAuth(const char *user, const char *passwd)
void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
{
if(user) {
strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0';
} else
ppp_settings.user[0] = '\0';
switch(authType) {
case PPPAUTHTYPE_NONE:
default:
#ifdef LWIP_PPP_STRICT_PAP_REJECT
ppp_settings.refuse_pap = 1;
#else
/* some providers request pap and accept an empty login/pw */
ppp_settings.refuse_pap = 0;
#endif
ppp_settings.refuse_chap = 1;
break;
case PPPAUTHTYPE_ANY:
/* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
* RFC 1994 says:
*
* In practice, within or associated with each PPP server, there is a
* database which associates "user" names with authentication
* information ("secrets"). It is not anticipated that a particular
* named user would be authenticated by multiple methods. This would
* make the user vulnerable to attacks which negotiate the least secure
* method from among a set (such as PAP rather than CHAP). If the same
* secret was used, PAP would reveal the secret to be used later with
* CHAP.
*
* Instead, for each user name there should be an indication of exactly
* one method used to authenticate that user name. If a user needs to
* make use of different authentication methods under different
* circumstances, then distinct user names SHOULD be employed, each of
* which identifies exactly one authentication method.
*
*/
ppp_settings.refuse_pap = 0;
ppp_settings.refuse_chap = 0;
break;
case PPPAUTHTYPE_PAP:
ppp_settings.refuse_pap = 0;
ppp_settings.refuse_chap = 1;
break;
case PPPAUTHTYPE_CHAP:
ppp_settings.refuse_pap = 1;
ppp_settings.refuse_chap = 0;
break;
}
if(passwd) {
strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1);
ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0';
} else
ppp_settings.passwd[0] = '\0';
if(user) {
strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0';
} else
ppp_settings.user[0] = '\0';
if(passwd) {
strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1);
ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0';
} else
ppp_settings.passwd[0] = '\0';
}
/* Open a new PPP connection using the given I/O device.
@@ -339,7 +378,7 @@ void pppSetAuth(const char *user, const char *passwd)
* established before calling this.
* Return a new PPP connection descriptor on success or
* an error code (negative) on failure. */
int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *arg, int errCode), void *linkStatusArg)
int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
{
PPPControl *pc;
int pd;
@@ -384,7 +423,7 @@ int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *arg, int errCode), void *lin
pc->outACCM[15] = 0x60;
pc->linkStatusCB = linkStatusCB;
pc->linkStatusArg = linkStatusArg;
pc->linkStatusCtx = linkStatusCtx;
sys_thread_new(pppMain, (void*)pd, PPP_THREAD_PRIO);
if(!linkStatusCB) {
@@ -442,7 +481,7 @@ static void nPut(PPPControl *pc, struct pbuf *nb)
if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
PPPDEBUG((LOG_WARNING,
"PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.err++;
#endif /* LINK_STATS */
pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
@@ -451,22 +490,60 @@ static void nPut(PPPControl *pc, struct pbuf *nb)
}
pbuf_free(nb);
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.xmit++;
#endif /* LINK_STATS */
}
/*
* pppAppend - append given character to end of given pbuf. If outACCM
* is not NULL and the character needs to be escaped, do so.
* If pbuf is full, append another.
* Return the current pbuf.
*/
static struct pbuf *pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
{
struct pbuf *tb = nb;
/* Make sure there is room for the character and an escape code.
* Sure we don't quite fill the buffer if the character doesn't
* get escaped but is one character worth complicating this? */
/* Note: We assume no packet header. */
if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) {
tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (tb) {
nb->next = tb;
}
#if LINK_STATS
else {
lwip_stats.link.memerr++;
}
#endif /* LINK_STATS */
nb = tb;
}
if (nb) {
if (outACCM && ESCAPE_P(*outACCM, c)) {
*((u_char*)nb->payload + nb->len++) = PPP_ESCAPE;
*((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS;
}
else
*((u_char*)nb->payload + nb->len++) = c;
}
return tb;
}
/* Send a packet on the given connection. */
static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
{
int pd = (int)netif->state;
u_short protocol = PPP_IP;
int pd = (int)netif->state;
u_short protocol = PPP_IP;
PPPControl *pc = &pppControl[pd];
u_int fcsOut = PPP_INITFCS;
struct pbuf *headMB = NULL, *tailMB = NULL, *p;
u_char c;
(void)ipaddr;
(void)ipaddr;
/* Validate parameters. */
/* We let any protocol value go through - it can't hurt us
@@ -474,7 +551,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n",
pd, protocol, pb));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.opterr++;
lwip_stats.link.drop++;
#endif
@@ -484,7 +561,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
/* Check that the link is up. */
if (lcp_phase[pd] == PHASE_DEAD) {
PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.rterr++;
lwip_stats.link.drop++;
#endif
@@ -495,7 +572,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) {
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif /* LINK_STATS */
@@ -522,7 +599,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
break;
default:
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.proterr++;
lwip_stats.link.drop++;
#endif
@@ -536,22 +613,22 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
/* Build the PPP header. */
if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG)
tailMB = pppMPutRaw(PPP_FLAG, tailMB);
tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
pc->lastXMit = sys_jiffies();
if (!pc->accomp) {
fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS);
tailMB = pppMPutC(PPP_ALLSTATIONS, &pc->outACCM, tailMB);
tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM);
fcsOut = PPP_FCS(fcsOut, PPP_UI);
tailMB = pppMPutC(PPP_UI, &pc->outACCM, tailMB);
tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM);
}
if (!pc->pcomp || protocol > 0xFF) {
c = (protocol >> 8) & 0xFF;
fcsOut = PPP_FCS(fcsOut, c);
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
tailMB = pppAppend(c, tailMB, &pc->outACCM);
}
c = protocol & 0xFF;
fcsOut = PPP_FCS(fcsOut, c);
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
tailMB = pppAppend(c, tailMB, &pc->outACCM);
/* Load packet. */
for(p = pb; p; p = p->next) {
@@ -567,16 +644,16 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
fcsOut = PPP_FCS(fcsOut, c);
/* Copy to output buffer escaping special characters. */
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
tailMB = pppAppend(c, tailMB, &pc->outACCM);
}
}
/* Add FCS and trailing flag. */
c = ~fcsOut & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
tailMB = pppAppend(c, tailMB, &pc->outACCM);
c = (~fcsOut >> 8) & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
tailMB = pppMPutRaw(PPP_FLAG, tailMB);
tailMB = pppAppend(c, tailMB, &pc->outACCM);
tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
/* If we failed to complete the packet, throw it away. */
if (!tailMB) {
@@ -584,7 +661,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
"pppifOutput[%d]: Alloc err - dropping proto=%d\n",
pd, protocol));
pbuf_free(headMB);
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif
@@ -673,7 +750,7 @@ int pppWrite(int pd, const u_char *s, int n)
struct pbuf *headMB = NULL, *tailMB;
headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) {
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.proterr++;
#endif /* LINK_STATS */
@@ -685,7 +762,7 @@ int pppWrite(int pd, const u_char *s, int n)
/* If the link has been idle, we'll send a fresh flag character to
* flush any noise. */
if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG)
tailMB = pppMPutRaw(PPP_FLAG, tailMB);
tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
pc->lastXMit = sys_jiffies();
/* Load output buffer. */
@@ -696,24 +773,24 @@ int pppWrite(int pd, const u_char *s, int n)
fcsOut = PPP_FCS(fcsOut, c);
/* Copy to output buffer escaping special characters. */
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
tailMB = pppAppend(c, tailMB, &pc->outACCM);
}
/* Add FCS and trailing flag. */
c = ~fcsOut & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
tailMB = pppAppend(c, tailMB, &pc->outACCM);
c = (~fcsOut >> 8) & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
tailMB = pppMPutRaw(PPP_FLAG, tailMB);
tailMB = pppAppend(c, tailMB, &pc->outACCM);
tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
/* If we failed to complete the packet, throw it away.
* Otherwise send it. */
if (!tailMB) {
PPPDEBUG((LOG_WARNING,
"pppWrite[%d]: Alloc err - dropping nBuf len=%d\n", pd, headMB->len));
"pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
/* "pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
pbuf_free(headMB);
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.proterr++;
#endif /* LINK_STATS */
@@ -925,15 +1002,14 @@ int sifup(int pd)
st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else {
if(pc->netif)
netif_remove(pc->netif);
pc->netif = netif_add(&pc->our_ipaddr, &pc->netmask, &pc->his_ipaddr, (void *)pd, pppifNetifInit, ip_input);
if(pc->netif) {
pc->if_up = 1;
pc->errCode = 0;
netif_remove(&pc->netif);
if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, &pc->addrs.his_ipaddr, (void *)pd, pppifNetifInit, ip_input)) {
pc->if_up = 1;
pc->errCode = PPPERR_NONE;
if(pc->linkStatusCB)
pc->linkStatusCB(pc->linkStatusArg, pc->errCode);
PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
if(pc->linkStatusCB)
pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
} else {
st = 0;
PPPDEBUG((LOG_ERR, "sifup[%d]: netif_add failed\n", pd));
@@ -948,10 +1024,10 @@ int sifup(int pd)
*/
int sifnpmode(int u, int proto, enum NPmode mode)
{
(void)u;
(void)proto;
(void)mode;
return 0;
(void)u;
(void)proto;
(void)mode;
return 0;
}
/*
@@ -967,11 +1043,10 @@ int sifdown(int pd)
PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
} else {
pc->if_up = 0;
if(pc->netif)
netif_remove(pc->netif);
pc->netif = NULL;
if(pc->linkStatusCB)
pc->linkStatusCB(pc->linkStatusArg, PPPERR_CONNECT);
netif_remove(&pc->netif);
PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
if(pc->linkStatusCB)
pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
}
return st;
}
@@ -995,11 +1070,11 @@ int sifaddr(
st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else {
memcpy(&pc->our_ipaddr, &o, sizeof(o));
memcpy(&pc->his_ipaddr, &h, sizeof(h));
memcpy(&pc->netmask, &m, sizeof(m));
memcpy(&pc->dns1, &ns1, sizeof(ns1));
memcpy(&pc->dns2, &ns2, sizeof(ns2));
memcpy(&pc->addrs.our_ipaddr, &o, sizeof(o));
memcpy(&pc->addrs.his_ipaddr, &h, sizeof(h));
memcpy(&pc->addrs.netmask, &m, sizeof(m));
memcpy(&pc->addrs.dns1, &ns1, sizeof(ns1));
memcpy(&pc->addrs.dns2, &ns2, sizeof(ns2));
}
return st;
}
@@ -1023,11 +1098,11 @@ int cifaddr(
st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else {
IP4_ADDR(&pc->our_ipaddr, 0,0,0,0);
IP4_ADDR(&pc->his_ipaddr, 0,0,0,0);
IP4_ADDR(&pc->netmask, 255,255,255,0);
IP4_ADDR(&pc->dns1, 0,0,0,0);
IP4_ADDR(&pc->dns2, 0,0,0,0);
IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
IP4_ADDR(&pc->addrs.netmask, 255,255,255,0);
IP4_ADDR(&pc->addrs.dns1, 0,0,0,0);
IP4_ADDR(&pc->addrs.dns2, 0,0,0,0);
}
return st;
}
@@ -1046,7 +1121,7 @@ int sifdefaultroute(int pd, u32_t l, u32_t g)
st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else {
netif_set_default(pc->netif);
netif_set_default(&pc->netif);
}
/* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */
@@ -1077,6 +1152,7 @@ int cifdefaultroute(int pd, u32_t l, u32_t g)
void
pppMainWakeup(int pd)
{
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d\n", pd));
sio_read_abort(pppControl[pd].fd);
}
@@ -1091,6 +1167,7 @@ pppStartCB(void *arg)
{
int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %d\n", pd));
lcp_lowerup(pd);
lcp_open(pd); /* Start protocol */
}
@@ -1100,6 +1177,7 @@ pppStopCB(void *arg)
{
int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %d\n", pd));
lcp_close(pd, "User request");
}
@@ -1108,6 +1186,7 @@ pppHupCB(void *arg)
{
int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %d\n", pd));
lcp_lowerdown(pd);
link_terminated(pd);
}
@@ -1134,30 +1213,37 @@ static void pppMain(void *arg)
/*
* Start the connection and handle incoming events (packet or timeout).
*/
ppp_trace(LOG_NOTICE, "Connecting\n");
PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd));
tcpip_callback(pppStartCB, arg);
while (lcp_phase[pd] != PHASE_DEAD) {
if (pc->kill_link) {
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d kill_link -> pppStopCB\n", pd));
pc->errCode = PPPERR_USER;
/* This will leave us at PHASE_DEAD. */
tcpip_callback(pppStopCB, arg);
pc->kill_link = 0;
}
else if (pc->sig_hup) {
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sig_hup -> pppHupCB\n", pd));
pc->sig_hup = 0;
tcpip_callback(pppHupCB, arg);
} else {
int c = sio_read(pc->fd, p->payload, p->len);
if(c > 0) {
pppInProc(pd, p->payload, c);
} else {
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
sys_msleep(250); /* give other tasks a chance to run */
}
}
}
PPPDEBUG((LOG_INFO, "pppMain: unit %d: PHASE_DEAD\n", pd));
pbuf_free(p);
out:
PPPDEBUG((LOG_DEBUG, "pppMain: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
if(pc->linkStatusCB)
pc->linkStatusCB(pc->linkStatusArg, pc->errCode ? pc->errCode : PPPERR_PROTOCOL);
pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
pc->openFlag = 0;
}
@@ -1207,7 +1293,7 @@ static void pppInput(void *arg)
pbuf_header(nb, -(int)sizeof(struct pppInputHeader));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
@@ -1227,13 +1313,13 @@ static void pppInput(void *arg)
switch(protocol) {
case PPP_VJC_COMP: /* VJ compressed TCP */
#if VJ_SUPPORT > 0
PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in nBuf len=%d\n", pd, nb->len));
PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
/*
* Clip off the VJ header and prepend the rebuilt TCP/IP header and
* pass the result to IP.
*/
if (vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) {
pppControl[pd].netif->input(nb, pppControl[pd].netif);
pppControl[pd].netif.input(nb, &pppControl[pd].netif);
return;
}
/* Something's wrong so drop it. */
@@ -1245,13 +1331,13 @@ static void pppInput(void *arg)
break;
case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */
#if VJ_SUPPORT > 0
PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in nBuf len=%d\n", pd, nb->len));
PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
/*
* Process the TCP/IP header for VJ header compression and then pass
* the packet to IP.
*/
if (vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) {
pppControl[pd].netif->input(nb, pppControl[pd].netif);
pppControl[pd].netif.input(nb, &pppControl[pd].netif);
return;
}
/* Something's wrong so drop it. */
@@ -1264,8 +1350,8 @@ static void pppInput(void *arg)
#endif /* VJ_SUPPORT > 0 */
break;
case PPP_IP: /* Internet Protocol */
PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in nBuf len=%d", pd, nb->len));
pppControl[pd].netif->input(nb, pppControl[pd].netif);
PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len));
pppControl[pd].netif.input(nb, &pppControl[pd].netif);
return;
default:
{
@@ -1297,7 +1383,7 @@ static void pppInput(void *arg)
}
drop:
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.drop++;
#endif
@@ -1316,7 +1402,9 @@ static void pppDrop(PPPControl *pc)
#if 0
PPPDEBUG((LOG_INFO, "pppDrop: %d:%.*H\n", pc->inHead->len, min(60, pc->inHead->len * 2), pc->inHead->payload));
#endif
PPPDEBUG((LOG_INFO, "pppDrop: nBuf len=%d\n", pc->inHead->len));
PPPDEBUG((LOG_INFO, "pppDrop: pbuf len=%d\n", pc->inHead->len));
if (pc->inTail && (pc->inTail != pc->inHead))
pbuf_free(pc->inTail);
pbuf_free(pc->inHead);
pc->inHead = NULL;
pc->inTail = NULL;
@@ -1325,7 +1413,7 @@ static void pppDrop(PPPControl *pc)
vj_uncompress_err(&pc->vjComp);
#endif
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.drop++;
#endif /* LINK_STATS */
}
@@ -1363,7 +1451,7 @@ static void pppInProc(int pd, u_char *s, int l)
PPPDEBUG((LOG_WARNING,
"pppInProc[%d]: Dropping incomplete packet %d\n",
pd, pc->inState));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.lenerr++;
#endif
pppDrop(pc);
@@ -1373,7 +1461,7 @@ static void pppInProc(int pd, u_char *s, int l)
PPPDEBUG((LOG_INFO,
"pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n",
pd, pc->inFCS, pc->inProtocol));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.chkerr++;
#endif
pppDrop(pc);
@@ -1382,26 +1470,31 @@ static void pppInProc(int pd, u_char *s, int l)
else {
/* Trim off the checksum. */
if(pc->inTail->len >= 2) {
pc->inTail->len -= 2;
pc->inLen -= 2;
if(pc->inTail->len >= 2) {
pc->inTail->len -= 2;
/* Update the packet header. */
pc->inHead->tot_len = pc->inLen;
} else {
pc->inHead->tot_len = pc->inLen;
pbuf_realloc(pc->inHead, pc->inLen - 2);
}
pc->inTail->tot_len = pc->inTail->len;
if (pc->inTail != pc->inHead) {
pbuf_cat(pc->inHead, pc->inTail);
}
} else {
pc->inTail->tot_len = pc->inTail->len;
if (pc->inTail != pc->inHead) {
pbuf_cat(pc->inHead, pc->inTail);
}
pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2);
}
/* Dispatch the packet thereby consuming it. */
if(tcpip_callback(pppInput, pc->inHead) != ERR_OK) {
if(tcpip_callback(pppInput, pc->inHead) != ERR_OK) {
PPPDEBUG((LOG_ERR,
"pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd));
pbuf_free(pc->inHead);
#ifdef LINK_STATS
lwip_stats.link.drop++;
"pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd));
pbuf_free(pc->inHead);
#if LINK_STATS
lwip_stats.link.drop++;
#endif
}
}
pc->inHead = NULL;
pc->inTail = NULL;
}
@@ -1480,40 +1573,40 @@ static void pppInProc(int pd, u_char *s, int l)
case PDDATA: /* Process data byte. */
/* Make space to receive processed data. */
if (pc->inTail == NULL || pc->inTail->len == PBUF_POOL_BUFSIZE) {
if(pc->inTail) {
pc->inTail->tot_len = pc->inTail->len;
if (pc->inTail != pc->inHead) {
pbuf_cat(pc->inHead, pc->inTail);
}
}
/* If we haven't started a packet, we need a packet header. */
nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (nextNBuf == NULL) {
/* No free buffers. Drop the input packet and let the
* higher layers deal with it. Continue processing
* the received nBuf chain in case a new packet starts. */
* the received pbuf chain in case a new packet starts. */
PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
#endif /* LINK_STATS */
pppDrop(pc);
pc->inState = PDSTART; /* Wait for flag sequence. */
break;
} else {
if (pc->inHead == NULL) {
struct pppInputHeader *pih = nextNBuf->payload;
pih->unit = pd;
pih->proto = pc->inProtocol;
nextNBuf->len += sizeof(*pih);
pc->inLen = nextNBuf->len;
pc->inHead = nextNBuf;
}
else { /* Since if inHead is not NULL, then neither is inTail! */
pc->inTail->next = nextNBuf;
}
pc->inTail = nextNBuf;
}
if (pc->inHead == NULL) {
struct pppInputHeader *pih = nextNBuf->payload;
pih->unit = pd;
pih->proto = pc->inProtocol;
nextNBuf->len += sizeof(*pih);
pc->inHead = nextNBuf;
}
pc->inTail = nextNBuf;
}
/* Load character into buffer. */
((u_char*)pc->inTail->payload)[pc->inTail->len++] = curChar;
pc->inLen++;
break;
}
@@ -1524,74 +1617,4 @@ static void pppInProc(int pd, u_char *s, int l)
avRandomize();
}
/*
* pppMPutC - append given character to end of given nBuf. If the character
* needs to be escaped, do so. If nBuf is full, append another.
* Return the current nBuf.
*/
static struct pbuf *pppMPutC(u_char c, ext_accm *outACCM, struct pbuf *nb)
{
struct pbuf *tb = nb;
/* Make sure there is room for the character and an escape code.
* Sure we don't quite fill the buffer if the character doesn't
* get escaped but is one character worth complicating this? */
/* Note: We assume no packet header. */
if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) {
tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (tb) {
nb->next = tb;
}
#ifdef LINK_STATS
else {
lwip_stats.link.memerr++;
}
#endif /* LINK_STATS */
nb = tb;
}
if (nb) {
if (ESCAPE_P(*outACCM, c)) {
*((u_char*)nb->payload + nb->len++) = PPP_ESCAPE;
*((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS;
}
else
*((u_char*)nb->payload + nb->len++) = c;
}
return tb;
}
/*
* pppMPutRaw - append given character to end of given nBuf without escaping
* it. If nBuf is full, append another.
* This is normally used to add the flag character to a packet.
* Return the current nBuf.
*/
static struct pbuf *pppMPutRaw(u_char c, struct pbuf *nb)
{
struct pbuf *tb = nb;
/* Make sure there is room for the character and an escape code.
* Sure we don't quite fill the buffer if the character doesn't
* get escaped but is one character worth complicating this? */
/* Note: We assume no packet header. */
if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) {
tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (tb) {
nb->next = tb;
}
#ifdef LINK_STATS
else {
lwip_stats.link.memerr++;
}
#endif /* LINK_STATS */
nb = tb;
}
if (nb) {
*((u_char*)nb->payload + nb->len++) = c;
}
return tb;
}
#endif /* PPP_SUPPORT */

View File

@@ -208,8 +208,11 @@ enum NPmode {
#define BCMP(s0, s1, l) memcmp((u_char *)(s0), (u_char *)(s1), (l))
#define BCOPY(s, d, l) memcpy((d), (s), (l))
#define BZERO(s, n) memset(s, 0, n)
#if PPP_DEBUG
#define PRINTMSG(m, l) { m[l] = '\0'; ppp_trace(LOG_INFO, "Remote message: %s\n", m); }
#else
#define PRINTMSG(m, l)
#endif
/*
* MAKEHEADER - Add PPP Header fields to a packet.
@@ -313,11 +316,14 @@ struct ppp_settings {
int maxconnect; /* Maximum connect time (seconds) */
char user[MAXNAMELEN + 1];/* Username for PAP */
char passwd[MAXNAMELEN + 1]; /* Password for PAP */
char passwd[MAXSECRETLEN + 1]; /* Password for PAP, secret for CHAP */
char our_name[MAXNAMELEN + 1]; /* Our name for authentication purposes */
char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */
};
struct ppp_addrs {
struct ip_addr our_ipaddr, his_ipaddr, netmask, dns1, dns2;
};
/*****************************
*** PUBLIC DATA STRUCTURES ***
@@ -337,7 +343,33 @@ extern struct protent *ppp_protocols[];/* Table of pointers to supported protoco
/* Initialize the PPP subsystem. */
void pppInit(void);
void pppSetAuth(const char *user, const char *passwd);
/* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
* RFC 1994 says:
*
* In practice, within or associated with each PPP server, there is a
* database which associates "user" names with authentication
* information ("secrets"). It is not anticipated that a particular
* named user would be authenticated by multiple methods. This would
* make the user vulnerable to attacks which negotiate the least secure
* method from among a set (such as PAP rather than CHAP). If the same
* secret was used, PAP would reveal the secret to be used later with
* CHAP.
*
* Instead, for each user name there should be an indication of exactly
* one method used to authenticate that user name. If a user needs to
* make use of different authentication methods under different
* circumstances, then distinct user names SHOULD be employed, each of
* which identifies exactly one authentication method.
*
*/
enum pppAuthType {
PPPAUTHTYPE_NONE,
PPPAUTHTYPE_ANY,
PPPAUTHTYPE_PAP,
PPPAUTHTYPE_CHAP
};
void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd);
/*
* Open a new PPP connection using the given I/O device.
@@ -346,7 +378,7 @@ void pppSetAuth(const char *user, const char *passwd);
* Return a new PPP connection descriptor on success or
* an error code (negative) on failure.
*/
int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *arg, int errCode), void *linkStatusArg);
int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx);
/*
* Close a PPP connection and release the descriptor.

View File

@@ -61,14 +61,13 @@ void ppp_trace(int level, const char *format,...);
#if PPP_DEBUG > 0
#define AUTHDEBUG(a) ppp_trace##a
#define IPCPDEBUG(a) ppp_trace##a
#define UPAPDEBUG(a) ppp_trace##a
#define LCPDEBUG(a) ppp_trace##a
#define FSMDEBUG(a) ppp_trace##a
#define CHAPDEBUG(a) ppp_trace##a
#define PPPDEBUG(a) ppp_trace##a
#define AUTHDEBUG(a) ppp_trace a
#define IPCPDEBUG(a) ppp_trace a
#define UPAPDEBUG(a) ppp_trace a
#define LCPDEBUG(a) ppp_trace a
#define FSMDEBUG(a) ppp_trace a
#define CHAPDEBUG(a) ppp_trace a
#define PPPDEBUG(a) ppp_trace a
#define TRACELCP 1

View File

@@ -32,6 +32,7 @@
*****************************************************************************/
#include "ppp.h"
#if PPP_SUPPORT > 0
#include "md5.h"
#include "randm.h"
@@ -237,4 +238,5 @@ u32_t avRandom()
#endif /* MD5_SUPPORT */
#endif /* PPP_SUPPORT */

View File

@@ -35,7 +35,7 @@
#if VJ_SUPPORT > 0
#ifdef LINK_STATS
#if LINK_STATS
#define INCR(counter) ++comp->stats.counter
#else
#define INCR(counter)
@@ -574,6 +574,33 @@ int vj_uncompress_tcp(
/* Remove the compressed header and prepend the uncompressed header. */
pbuf_header(n0, -vjlen);
if(MEM_ALIGN(n0->payload) != n0->payload) {
struct pbuf *np, *q;
u8_t *bufptr;
np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL);
if(!np) {
PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: realign failed\n"));
*nb = NULL;
goto bad;
}
pbuf_header(np, -cs->cs_hlen);
bufptr = n0->payload;
for(q = np; q != NULL; q = q->next) {
memcpy(q->payload, bufptr, q->len);
bufptr += q->len;
}
if(n0->next) {
pbuf_chain(np, n0->next);
pbuf_dechain(n0);
}
pbuf_free(n0);
n0 = np;
}
if(pbuf_header(n0, cs->cs_hlen)) {
struct pbuf *np;
@@ -584,9 +611,10 @@ int vj_uncompress_tcp(
*nb = NULL;
goto bad;
}
pbuf_chain(np, n0);
pbuf_cat(np, n0);
n0 = np;
}
LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen);
memcpy(n0->payload, &cs->cs_ip, cs->cs_hlen);
*nb = n0;

View File

@@ -1,7 +1,7 @@
/*
* Definitions for tcp compression routines.
*
* $Id: vj.h,v 1.2 2003/06/02 11:12:56 jani Exp $
* $Id: vj.h,v 1.2.6.1 2003/10/28 11:44:45 jani Exp $
*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved.
@@ -136,7 +136,7 @@ struct vjcompress {
u_short flags;
u_char maxSlotIndex;
u_char compressSlot; /* Flag indicating OK to compress slot ID. */
#ifdef LINK_STATS
#if LINK_STATS
struct vjstat stats;
#endif
struct cstate tstate[MAX_SLOTS]; /* xmit connection states */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -115,9 +115,7 @@ slipif_input( struct netif * netif )
/* Received whole packet. */
pbuf_realloc(q, recved);
#ifdef LINK_STATS
++lwip_stats.link.recv;
#endif /* LINK_STATS */
LINK_STATS_INC(link.recv);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
return q;
@@ -141,15 +139,13 @@ slipif_input( struct netif * netif )
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
#ifdef LINK_STATS
if (p == NULL) {
++lwip_stats.link.drop;
LINK_STATS_INC(link.drop);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
}
#endif /* LINK_STATS */
if (q != NULL) {
pbuf_chain(q, p);
pbuf_cat(q, p);
} else {
q = p;
}