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

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. and additions to the stack to further increase its usefulness.
Development of lwIP is hosted on Savannah, a central point for Development of lwIP is hosted on Savannah, a central point for
software development, maintenance and distribution. A core team software development, maintenance and distribution. Everyone can
will improve lwIP by the use of Savannah's interface and CVS. 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 The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and
contributions (such as platform ports) are in the 'contrib' module. contributions (such as platform ports) are in the 'contrib' module.
The 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 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co lwip 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: The current contrib CVS tree can be checked out by doing:
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co contrib 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: Submit patches and bugs via the lwIP project page:
http://savannah.nongnu.org/projects/lwip/ 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 DOCUMENTATION

View File

@@ -4,13 +4,14 @@ Table of Contents:
1 - Anonymous CVS checkouts and updates (to be elaborated) 1 - Anonymous CVS checkouts and updates (to be elaborated)
2 - Committers/developers CVS access using SSH (to be written) 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 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 login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip 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: 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 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 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 login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip export -r STABLE-0_6_3 -d lwip-0.6.3 lwip cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip 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 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): Savannah conventions so that it shows up in the Files list real nice):
mkdir stable.pkg mkdir stable.pkg
cd stable.pkg mkdir stable.pkg 0.6.3
mkdir 0.6.3
cd 0.6.3
We can now copy the tar archive we made earlier into the release directory: 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: 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 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 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -38,13 +38,13 @@
#include "lwip/api_msg.h" #include "lwip/api_msg.h"
#include "lwip/memp.h" #include "lwip/memp.h"
/*-----------------------------------------------------------------------------------*/
struct struct
netbuf *netbuf_new(void) netbuf *netbuf_new(void)
{ {
struct netbuf *buf; struct netbuf *buf;
buf = memp_mallocp(MEMP_NETBUF); buf = memp_malloc(MEMP_NETBUF);
if (buf != NULL) { if (buf != NULL) {
buf->p = NULL; buf->p = NULL;
buf->ptr = NULL; buf->ptr = NULL;
@@ -53,7 +53,7 @@ netbuf *netbuf_new(void)
return NULL; return NULL;
} }
} }
/*-----------------------------------------------------------------------------------*/
void void
netbuf_delete(struct netbuf *buf) netbuf_delete(struct netbuf *buf)
{ {
@@ -62,10 +62,10 @@ netbuf_delete(struct netbuf *buf)
pbuf_free(buf->p); pbuf_free(buf->p);
buf->p = buf->ptr = NULL; buf->p = buf->ptr = NULL;
} }
memp_freep(MEMP_NETBUF, buf); memp_free(MEMP_NETBUF, buf);
} }
} }
/*-----------------------------------------------------------------------------------*/
void * void *
netbuf_alloc(struct netbuf *buf, u16_t size) netbuf_alloc(struct netbuf *buf, u16_t size)
{ {
@@ -80,7 +80,7 @@ netbuf_alloc(struct netbuf *buf, u16_t size)
buf->ptr = buf->p; buf->ptr = buf->p;
return buf->p->payload; return buf->p->payload;
} }
/*-----------------------------------------------------------------------------------*/
void void
netbuf_free(struct netbuf *buf) netbuf_free(struct netbuf *buf)
{ {
@@ -89,7 +89,7 @@ netbuf_free(struct netbuf *buf)
} }
buf->p = buf->ptr = NULL; buf->p = buf->ptr = NULL;
} }
/*-----------------------------------------------------------------------------------*/
void void
netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size) 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->p->len = buf->p->tot_len = size;
buf->ptr = buf->p; buf->ptr = buf->p;
} }
/*-----------------------------------------------------------------------------------*/
void void
netbuf_chain(struct netbuf *head, struct netbuf *tail) netbuf_chain(struct netbuf *head, struct netbuf *tail)
{ {
pbuf_chain(head->p, tail->p); pbuf_chain(head->p, tail->p);
head->ptr = head->p; head->ptr = head->p;
memp_freep(MEMP_NETBUF, tail); memp_free(MEMP_NETBUF, tail);
} }
/*-----------------------------------------------------------------------------------*/
u16_t u16_t
netbuf_len(struct netbuf *buf) netbuf_len(struct netbuf *buf)
{ {
return buf->p->tot_len; return buf->p->tot_len;
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) 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; *len = buf->ptr->len;
return ERR_OK; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
s8_t s8_t
netbuf_next(struct netbuf *buf) netbuf_next(struct netbuf *buf)
{ {
@@ -139,13 +139,13 @@ netbuf_next(struct netbuf *buf)
} }
return 0; return 0;
} }
/*-----------------------------------------------------------------------------------*/
void void
netbuf_first(struct netbuf *buf) netbuf_first(struct netbuf *buf)
{ {
buf->ptr = buf->p; buf->ptr = buf->p;
} }
/*-----------------------------------------------------------------------------------*/
void void
netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset) 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; left = 0;
if (buf == NULL) { if(buf == NULL || dataptr == NULL) {
return; return;
} }
@@ -174,39 +174,43 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
} }
} }
} }
/*-----------------------------------------------------------------------------------*/
void void
netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len) netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
{ {
netbuf_copy_partial(buf, dataptr, len, 0); netbuf_copy_partial(buf, dataptr, len, 0);
} }
/*-----------------------------------------------------------------------------------*/
struct ip_addr * struct ip_addr *
netbuf_fromaddr(struct netbuf *buf) netbuf_fromaddr(struct netbuf *buf)
{ {
return buf->fromaddr; return buf->fromaddr;
} }
/*-----------------------------------------------------------------------------------*/
u16_t u16_t
netbuf_fromport(struct netbuf *buf) netbuf_fromport(struct netbuf *buf)
{ {
return buf->fromport; return buf->fromport;
} }
/*-----------------------------------------------------------------------------------*/
struct 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 netconn *conn;
struct api_msg *msg;
conn = memp_mallocp(MEMP_NETCONN); conn = memp_malloc(MEMP_NETCONN);
if (conn == NULL) { if (conn == NULL) {
return NULL; return NULL;
} }
conn->err = ERR_OK;
conn->type = t; conn->type = t;
conn->pcb.tcp = NULL; conn->pcb.tcp = NULL;
if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) { if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
memp_freep(MEMP_NETCONN, conn); memp_free(MEMP_NETCONN, conn);
return NULL; return NULL;
} }
conn->recvmbox = SYS_MBOX_NULL; conn->recvmbox = SYS_MBOX_NULL;
@@ -214,25 +218,44 @@ netconn *netconn_new(enum netconn_type t)
conn->sem = SYS_SEM_NULL; conn->sem = SYS_SEM_NULL;
conn->state = NETCONN_NONE; conn->state = NETCONN_NONE;
conn->socket = 0; conn->socket = 0;
conn->callback = 0; conn->callback = callback;
conn->recv_avail = 0; 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; return conn;
} }
/*-----------------------------------------------------------------------------------*/
struct
netconn *netconn_new(enum netconn_type t)
{
return netconn_new_with_proto_and_callback(t,0,NULL);
}
struct struct
netconn *netconn_new_with_callback(enum netconn_type t, netconn *netconn_new_with_callback(enum netconn_type t,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len)) void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
{ {
struct netconn *conn; return netconn_new_with_proto_and_callback(t,0,callback);
/* get a netconn and then initialize callback pointer and socket */
conn = netconn_new(t);
if (conn)
conn->callback = callback;
return conn;
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
netconn_delete(struct netconn *conn) netconn_delete(struct netconn *conn)
{ {
@@ -243,7 +266,7 @@ netconn_delete(struct netconn *conn)
return ERR_OK; return ERR_OK;
} }
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) { if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return ERR_MEM; return ERR_MEM;
} }
@@ -251,7 +274,7 @@ netconn_delete(struct netconn *conn)
msg->msg.conn = conn; msg->msg.conn = conn;
api_msg_post(msg); api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL); sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg); memp_free(MEMP_API_MSG, msg);
/* Drain the recvmbox. */ /* Drain the recvmbox. */
if (conn->recvmbox != SYS_MBOX_NULL) { if (conn->recvmbox != SYS_MBOX_NULL) {
@@ -286,18 +309,21 @@ netconn_delete(struct netconn *conn)
memp_free(MEMP_NETCONN, conn); memp_free(MEMP_NETCONN, conn);
return ERR_OK; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
enum netconn_type enum netconn_type
netconn_type(struct netconn *conn) netconn_type(struct netconn *conn)
{ {
return conn->type; return conn->type;
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
netconn_peer(struct netconn *conn, struct ip_addr *addr, netconn_peer(struct netconn *conn, struct ip_addr *addr,
u16_t *port) u16_t *port)
{ {
switch (conn->type) { 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_UDPLITE:
case NETCONN_UDPNOCHKSUM: case NETCONN_UDPNOCHKSUM:
case NETCONN_UDP: case NETCONN_UDP:
@@ -316,12 +342,16 @@ netconn_peer(struct netconn *conn, struct ip_addr *addr,
} }
return (conn->err = ERR_OK); return (conn->err = ERR_OK);
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
netconn_addr(struct netconn *conn, struct ip_addr **addr, netconn_addr(struct netconn *conn, struct ip_addr **addr,
u16_t *port) u16_t *port)
{ {
switch (conn->type) { switch (conn->type) {
case NETCONN_RAW:
*addr = &(conn->pcb.raw->local_ip);
*port = conn->pcb.raw->protocol;
break;
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM: case NETCONN_UDPNOCHKSUM:
case NETCONN_UDP: case NETCONN_UDP:
@@ -335,7 +365,7 @@ netconn_addr(struct netconn *conn, struct ip_addr **addr,
} }
return (conn->err = ERR_OK); return (conn->err = ERR_OK);
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
netconn_bind(struct netconn *conn, struct ip_addr *addr, netconn_bind(struct netconn *conn, struct ip_addr *addr,
u16_t port) 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); return (conn->err = ERR_MEM);
} }
msg->type = API_MSG_BIND; msg->type = API_MSG_BIND;
@@ -362,11 +392,11 @@ netconn_bind(struct netconn *conn, struct ip_addr *addr,
msg->msg.msg.bc.port = port; msg->msg.msg.bc.port = port;
api_msg_post(msg); api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL); sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg); memp_free(MEMP_API_MSG, msg);
return conn->err; return conn->err;
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
netconn_connect(struct netconn *conn, struct ip_addr *addr, netconn_connect(struct netconn *conn, struct ip_addr *addr,
u16_t port) 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; return ERR_MEM;
} }
msg->type = API_MSG_CONNECT; msg->type = API_MSG_CONNECT;
@@ -393,7 +423,7 @@ netconn_connect(struct netconn *conn, struct ip_addr *addr,
msg->msg.msg.bc.port = port; msg->msg.msg.bc.port = port;
api_msg_post(msg); api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL); sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg); memp_free(MEMP_API_MSG, msg);
return conn->err; return conn->err;
} }
@@ -406,18 +436,18 @@ netconn_disconnect(struct netconn *conn)
return ERR_VAL; return ERR_VAL;
} }
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) { if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return ERR_MEM; return ERR_MEM;
} }
msg->type = API_MSG_DISCONNECT; msg->type = API_MSG_DISCONNECT;
msg->msg.conn = conn; msg->msg.conn = conn;
api_msg_post(msg); api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL); sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg); memp_free(MEMP_API_MSG, msg);
return conn->err; return conn->err;
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
netconn_listen(struct netconn *conn) 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); return (conn->err = ERR_MEM);
} }
msg->type = API_MSG_LISTEN; msg->type = API_MSG_LISTEN;
msg->msg.conn = conn; msg->msg.conn = conn;
api_msg_post(msg); api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL); sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg); memp_free(MEMP_API_MSG, msg);
return conn->err; return conn->err;
} }
/*-----------------------------------------------------------------------------------*/
struct netconn * struct netconn *
netconn_accept(struct netconn *conn) netconn_accept(struct netconn *conn)
{ {
@@ -461,7 +491,7 @@ netconn_accept(struct netconn *conn)
return newconn; return newconn;
} }
/*-----------------------------------------------------------------------------------*/
struct netbuf * struct netbuf *
netconn_recv(struct netconn *conn) 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) { if (buf == NULL) {
conn->err = ERR_MEM; 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 /* If we are closed, we indicate that we no longer wish to receive
data by setting conn->recvmbox to SYS_MBOX_NULL. */ data by setting conn->recvmbox to SYS_MBOX_NULL. */
if (p == NULL) { if (p == NULL) {
memp_freep(MEMP_NETBUF, buf); memp_free(MEMP_NETBUF, buf);
sys_mbox_free(conn->recvmbox); sys_mbox_free(conn->recvmbox);
conn->recvmbox = SYS_MBOX_NULL; conn->recvmbox = SYS_MBOX_NULL;
return NULL; return NULL;
@@ -526,7 +556,7 @@ netconn_recv(struct netconn *conn)
buf->fromaddr = NULL; buf->fromaddr = NULL;
/* Let the stack know that we have taken the data. */ /* 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; conn->err = ERR_MEM;
return buf; return buf;
} }
@@ -540,7 +570,7 @@ netconn_recv(struct netconn *conn)
api_msg_post(msg); api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL); sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg); memp_free(MEMP_API_MSG, msg);
} else { } else {
sys_mbox_fetch(conn->recvmbox, (void **)&buf); sys_mbox_fetch(conn->recvmbox, (void **)&buf);
conn->recv_avail -= buf->p->tot_len; conn->recv_avail -= buf->p->tot_len;
@@ -557,7 +587,7 @@ netconn_recv(struct netconn *conn)
return buf; return buf;
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
netconn_send(struct netconn *conn, struct netbuf *buf) netconn_send(struct netconn *conn, struct netbuf *buf)
{ {
@@ -571,7 +601,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
return conn->err; return conn->err;
} }
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) { if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM); return (conn->err = ERR_MEM);
} }
@@ -582,10 +612,10 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
api_msg_post(msg); api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL); sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg); memp_free(MEMP_API_MSG, msg);
return conn->err; return conn->err;
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy) 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); return (conn->err = ERR_MEM);
} }
msg->type = API_MSG_WRITE; msg->type = API_MSG_WRITE;
@@ -652,7 +682,7 @@ netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
} }
} }
ret: ret:
memp_freep(MEMP_API_MSG, msg); memp_free(MEMP_API_MSG, msg);
conn->state = NETCONN_NONE; conn->state = NETCONN_NONE;
if (conn->sem != SYS_SEM_NULL) { if (conn->sem != SYS_SEM_NULL) {
sys_sem_free(conn->sem); 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; return conn->err;
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
netconn_close(struct netconn *conn) netconn_close(struct netconn *conn)
{ {
@@ -670,7 +700,7 @@ netconn_close(struct netconn *conn)
if (conn == NULL) { if (conn == NULL) {
return ERR_VAL; return ERR_VAL;
} }
if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) { if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM); return (conn->err = ERR_MEM);
} }
@@ -686,13 +716,13 @@ netconn_close(struct netconn *conn)
goto again; goto again;
} }
conn->state = NETCONN_NONE; conn->state = NETCONN_NONE;
memp_freep(MEMP_API_MSG, msg); memp_free(MEMP_API_MSG, msg);
return conn->err; return conn->err;
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
netconn_err(struct netconn *conn) netconn_err(struct netconn *conn)
{ {
return conn->err; 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -37,6 +37,37 @@
#include "lwip/sys.h" #include "lwip/sys.h"
#include "lwip/tcpip.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 #if LWIP_UDP
static void static void
recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, 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; return;
} }
if (conn->recvmbox != SYS_MBOX_NULL) { if (conn->recvmbox != SYS_MBOX_NULL) {
buf = memp_mallocp(MEMP_NETBUF); buf = memp_malloc(MEMP_NETBUF);
if (buf == NULL) { if (buf == NULL) {
pbuf_free(p); pbuf_free(p);
return; return;
@@ -72,7 +103,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
} }
#endif /* LWIP_UDP */ #endif /* LWIP_UDP */
#if LWIP_TCP #if LWIP_TCP
/*-----------------------------------------------------------------------------------*/
static err_t static err_t
recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) 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; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
static err_t static err_t
poll_tcp(void *arg, struct tcp_pcb *pcb) poll_tcp(void *arg, struct tcp_pcb *pcb)
{ {
@@ -117,7 +148,7 @@ poll_tcp(void *arg, struct tcp_pcb *pcb)
} }
return ERR_OK; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
static err_t static err_t
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) 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; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
static void static void
err_tcp(void *arg, err_t err) err_tcp(void *arg, err_t err)
{ {
@@ -165,7 +196,7 @@ err_tcp(void *arg, err_t err)
sys_sem_signal(conn->sem); sys_sem_signal(conn->sem);
} }
} }
/*-----------------------------------------------------------------------------------*/
static void static void
setup_tcp(struct netconn *conn) setup_tcp(struct netconn *conn)
{ {
@@ -178,7 +209,7 @@ setup_tcp(struct netconn *conn)
tcp_poll(pcb, poll_tcp, 4); tcp_poll(pcb, poll_tcp, 4);
tcp_err(pcb, err_tcp); tcp_err(pcb, err_tcp);
} }
/*-----------------------------------------------------------------------------------*/
static err_t static err_t
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) 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 */ #endif /* API_MSG_DEBUG */
conn = (struct netconn *)arg; conn = (struct netconn *)arg;
mbox = conn->acceptmbox; mbox = conn->acceptmbox;
newconn = memp_mallocp(MEMP_NETCONN); newconn = memp_malloc(MEMP_NETCONN);
if (newconn == NULL) { if (newconn == NULL) {
return ERR_MEM; return ERR_MEM;
} }
@@ -234,17 +265,83 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
return ERR_OK; return ERR_OK;
} }
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/
static void static void
do_newconn(struct api_msg_msg *msg) 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 static void
do_delconn(struct api_msg_msg *msg) do_delconn(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
raw_remove(msg->conn->pcb.raw);
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@@ -287,12 +384,18 @@ do_delconn(struct api_msg_msg *msg)
sys_mbox_post(msg->conn->mbox, NULL); sys_mbox_post(msg->conn->mbox, NULL);
} }
} }
/*-----------------------------------------------------------------------------------*/
static void static void
do_bind(struct api_msg_msg *msg) do_bind(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp == NULL) { if (msg->conn->pcb.tcp == NULL) {
switch (msg->conn->type) { 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 #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new(); msg->conn->pcb.udp = udp_new();
@@ -319,6 +422,11 @@ do_bind(struct api_msg_msg *msg)
} }
} }
switch (msg->conn->type) { 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 #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@@ -339,7 +447,7 @@ do_bind(struct api_msg_msg *msg)
sys_mbox_post(msg->conn->mbox, NULL); sys_mbox_post(msg->conn->mbox, NULL);
} }
#if LWIP_TCP #if LWIP_TCP
/*-----------------------------------------------------------------------------------*/
static err_t static err_t
do_connected(void *arg, struct tcp_pcb *pcb, err_t err) 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; return ERR_OK;
} }
#endif #endif
/*-----------------------------------------------------------------------------------*/
static void static void
do_connect(struct api_msg_msg *msg) do_connect(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp == NULL) { if (msg->conn->pcb.tcp == NULL) {
switch (msg->conn->type) { 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 #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new(); msg->conn->pcb.udp = udp_new();
@@ -410,6 +524,12 @@ do_connect(struct api_msg_msg *msg)
} }
} }
switch (msg->conn->type) { 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 #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@@ -428,6 +548,7 @@ do_connect(struct api_msg_msg *msg)
do_connected); do_connected);
/*tcp_output(msg->conn->pcb.tcp);*/ /*tcp_output(msg->conn->pcb.tcp);*/
#endif #endif
default: default:
break; break;
} }
@@ -438,6 +559,11 @@ do_disconnect(struct api_msg_msg *msg)
{ {
switch (msg->conn->type) { 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 #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@@ -453,12 +579,17 @@ do_disconnect(struct api_msg_msg *msg)
sys_mbox_post(msg->conn->mbox, NULL); sys_mbox_post(msg->conn->mbox, NULL);
} }
/*-----------------------------------------------------------------------------------*/
static void static void
do_listen(struct api_msg_msg *msg) do_listen(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { 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 #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@@ -491,12 +622,17 @@ do_listen(struct api_msg_msg *msg)
} }
sys_mbox_post(msg->conn->mbox, NULL); sys_mbox_post(msg->conn->mbox, NULL);
} }
/*-----------------------------------------------------------------------------------*/
static void static void
do_accept(struct api_msg_msg *msg) do_accept(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { 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 #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@@ -511,12 +647,17 @@ do_accept(struct api_msg_msg *msg)
} }
} }
} }
/*-----------------------------------------------------------------------------------*/
static void static void
do_send(struct api_msg_msg *msg) do_send(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
raw_send(msg->conn->pcb.raw, msg->msg.p);
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@@ -532,7 +673,7 @@ do_send(struct api_msg_msg *msg)
} }
sys_mbox_post(msg->conn->mbox, NULL); sys_mbox_post(msg->conn->mbox, NULL);
} }
/*-----------------------------------------------------------------------------------*/
static void static void
do_recv(struct api_msg_msg *msg) do_recv(struct api_msg_msg *msg)
{ {
@@ -545,7 +686,7 @@ do_recv(struct api_msg_msg *msg)
#endif #endif
sys_mbox_post(msg->conn->mbox, NULL); sys_mbox_post(msg->conn->mbox, NULL);
} }
/*-----------------------------------------------------------------------------------*/
static void static void
do_write(struct api_msg_msg *msg) do_write(struct api_msg_msg *msg)
{ {
@@ -554,6 +695,11 @@ do_write(struct api_msg_msg *msg)
#endif #endif
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->err = ERR_VAL;
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@@ -571,7 +717,7 @@ do_write(struct api_msg_msg *msg)
segments when new outgoing data arrives from the user if any segments when new outgoing data arrives from the user if any
previously transmitted data on the connection remains previously transmitted data on the connection remains
unacknowledged. */ 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); tcp_output(msg->conn->pcb.tcp);
} }
msg->conn->err = err; msg->conn->err = err;
@@ -588,7 +734,7 @@ do_write(struct api_msg_msg *msg)
} }
sys_mbox_post(msg->conn->mbox, NULL); sys_mbox_post(msg->conn->mbox, NULL);
} }
/*-----------------------------------------------------------------------------------*/
static void static void
do_close(struct api_msg_msg *msg) do_close(struct api_msg_msg *msg)
{ {
@@ -598,6 +744,10 @@ do_close(struct api_msg_msg *msg)
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@@ -619,7 +769,7 @@ do_close(struct api_msg_msg *msg)
} }
sys_mbox_post(msg->conn->mbox, NULL); sys_mbox_post(msg->conn->mbox, NULL);
} }
/*-----------------------------------------------------------------------------------*/
typedef void (* api_msg_decode)(struct api_msg_msg *msg); typedef void (* api_msg_decode)(struct api_msg_msg *msg);
static api_msg_decode decode[API_MSG_MAX] = { static api_msg_decode decode[API_MSG_MAX] = {
do_newconn, do_newconn,
@@ -639,12 +789,12 @@ api_msg_input(struct api_msg *msg)
{ {
decode[msg->type](&(msg->msg)); decode[msg->type](&(msg->msg));
} }
/*-----------------------------------------------------------------------------------*/
void void
api_msg_post(struct api_msg *msg) api_msg_post(struct api_msg *msg)
{ {
tcpip_apimsg(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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -47,13 +47,13 @@ static char *err_strerr[] = {"Ok.",
"Address in use." "Address in use."
}; };
/*-----------------------------------------------------------------------------------*/
char * char *
lwip_strerr(err_t err) lwip_strerr(err_t err)
{ {
return err_strerr[-err]; return err_strerr[-err];
} }
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_DEBUG */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -99,7 +99,7 @@ static int err_to_errno_table[11] = {
set_errno(sk->err); \ set_errno(sk->err); \
} while (0) } while (0)
/*-----------------------------------------------------------------------------------*/
static struct lwip_socket * static struct lwip_socket *
get_socket(int s) get_socket(int s)
{ {
@@ -121,7 +121,7 @@ get_socket(int s)
return sock; return sock;
} }
/*-----------------------------------------------------------------------------------*/
static int static int
alloc_socket(struct netconn *newconn) alloc_socket(struct netconn *newconn)
{ {
@@ -150,7 +150,7 @@ alloc_socket(struct netconn *newconn)
sys_sem_signal(socksem); sys_sem_signal(socksem);
return -1; return -1;
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) 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)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@@ -197,16 +198,14 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
newconn->socket = newsock; newconn->socket = newsock;
sys_sem_signal(socksem); sys_sem_signal(socksem);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
ip_addr_debug_print(SOCKETS_DEBUG, &naddr); ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port)); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port));
#endif
sock_set_errno(sock, 0); sock_set_errno(sock, 0);
return newsock; return newsock;
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_bind(int s, struct sockaddr *name, socklen_t namelen) 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); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr; local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
local_port = ((struct sockaddr_in *)name)->sin_port; local_port = ((struct sockaddr_in *)name)->sin_port;
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &local_addr); ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port))); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port)));
#endif
err = netconn_bind(sock->conn, &local_addr, ntohs(local_port)); 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); sock_set_errno(sock, 0);
return 0; return 0;
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_close(int s) lwip_close(int s)
{ {
@@ -257,6 +255,7 @@ lwip_close(int s)
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
sys_sem_signal(socksem); sys_sem_signal(socksem);
set_errno(EBADF);
return -1; return -1;
} }
@@ -271,7 +270,7 @@ lwip_close(int s)
sock_set_errno(sock, 0); sock_set_errno(sock, 0);
return 0; return 0;
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_connect(int s, struct sockaddr *name, socklen_t namelen) 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); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; 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_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
remote_port = ((struct sockaddr_in *)name)->sin_port; remote_port = ((struct sockaddr_in *)name)->sin_port;
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr); ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port))); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
#endif
err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); 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); sock_set_errno(sock, 0);
return 0; return 0;
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_listen(int s, int backlog) 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)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@@ -336,7 +335,7 @@ lwip_listen(int s, int backlog)
sock_set_errno(sock, 0); sock_set_errno(sock, 0);
return 0; return 0;
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_recvfrom(int s, void *mem, int len, unsigned int flags, lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
struct sockaddr *from, socklen_t *fromlen) 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)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@@ -411,11 +411,9 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
memcpy(from, &sin, *fromlen); memcpy(from, &sin, *fromlen);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, addr); ip_addr_debug_print(SOCKETS_DEBUG, addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen)); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
#endif
} else { } else {
#if SOCKETS_DEBUG > 0 #if SOCKETS_DEBUG > 0
addr = netbuf_fromaddr(buf); addr = netbuf_fromaddr(buf);
@@ -444,19 +442,19 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
sock_set_errno(sock, 0); sock_set_errno(sock, 0);
return copylen; return copylen;
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_read(int s, void *mem, int len) lwip_read(int s, void *mem, int len)
{ {
return lwip_recvfrom(s, mem, len, 0, NULL, NULL); return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_recv(int s, void *mem, int len, unsigned int flags) lwip_recv(int s, void *mem, int len, unsigned int flags)
{ {
return lwip_recvfrom(s, mem, len, flags, NULL, NULL); return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_send(int s, void *data, int size, unsigned int flags) 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); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
switch (netconn_type(sock->conn)) { switch (netconn_type(sock->conn)) {
case NETCONN_RAW:
case NETCONN_UDP: case NETCONN_UDP:
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
/* create a buffer */ /* create a buffer */
buf = netbuf_new(); buf = netbuf_new();
@@ -509,7 +511,7 @@ lwip_send(int s, void *data, int size, unsigned int flags)
sock_set_errno(sock, 0); sock_set_errno(sock, 0);
return size; return size;
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_sendto(int s, void *data, int size, unsigned int flags, lwip_sendto(int s, void *data, int size, unsigned int flags,
struct sockaddr *to, socklen_t tolen) 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); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; 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_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
remote_port = ((struct sockaddr_in *)to)->sin_port; 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)); 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); ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port))); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));
#endif
netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); 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); netconn_disconnect(sock->conn);
return ret; return ret;
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_socket(int domain, int type, int protocol) lwip_socket(int domain, int type, int protocol)
{ {
@@ -557,6 +558,10 @@ lwip_socket(int domain, int type, int protocol)
/* create a netconn */ /* create a netconn */
switch (type) { 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: case SOCK_DGRAM:
conn = netconn_new_with_callback(NETCONN_UDP, event_callback); 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)); 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); set_errno(0);
return i; return i;
} }
/*-----------------------------------------------------------------------------------*/
int int
lwip_write(int s, void *data, int size) lwip_write(int s, void *data, int size)
{ {
return lwip_send(s, data, size, 0); return lwip_send(s, data, size, 0);
} }
/*-----------------------------------------------------------------------------------*/
static int static int
lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset) 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 int
lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
struct timeval *timeout) struct timeval *timeout)
@@ -723,7 +728,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
/* Wait forever */ /* Wait forever */
msectimeout = 0; msectimeout = 0;
else 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); 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; return nready;
} }
/*-----------------------------------------------------------------------------------*/
static void static void
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) 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) 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); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; 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 */ /* get the IP address and port of the remote host */
netconn_peer(sock->conn, &naddr, &sin.sin_port); netconn_peer(sock->conn, &naddr, &sin.sin_port);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &naddr); ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port)); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
#endif
sin.sin_port = htons(sin.sin_port); sin.sin_port = htons(sin.sin_port);
sin.sin_addr.s_addr = naddr.addr; 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); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; 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 */ /* get the IP address and port of the remote host */
netconn_addr(sock->conn, &naddr, &sin.sin_port); netconn_addr(sock->conn, &naddr, &sin.sin_port);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, naddr); ip_addr_debug_print(SOCKETS_DEBUG, naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port)); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
#endif
sin.sin_port = htons(sin.sin_port); sin.sin_port = htons(sin.sin_port);
sin.sin_addr.s_addr = naddr->addr; 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 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); struct lwip_socket *sock = get_socket(s);
if (!sock) { if(!sock) {
set_errno(EBADF);
return -1; return -1;
} }
if (level == SOL_SOCKET) { if( NULL == optval || NULL == optlen ) {
switch (optname) { 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: 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; err = EINVAL;
break;
} }
*(int *)optval = sock->err; break;
sock->err = 0;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
err = 0;
break;
default: default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname)); 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; 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); sock_set_errno(sock, err);
return err ? -1 : 0; 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) int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
{ {
struct lwip_socket *sock = get_socket(s); struct lwip_socket *sock = get_socket(s);
int err = ENOSYS; int err = 0;
if (!sock) { if(!sock) {
set_errno(EBADF);
return -1; return -1;
} }
if (level == SOL_SOCKET) { if( NULL == optval ) {
switch (optname) { sock_set_errno( sock, EFAULT );
case SO_REUSEADDR: return -1;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, ..)\n", s)); }
/* XXX just pretend we support this for now */
err = 0;
/* 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; break;
default: 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; 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)); 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); sock_set_errno(sock, err);
return err ? -1 : 0; return err ? -1 : 0;
} }
@@ -1021,7 +1320,8 @@ int lwip_ioctl(int s, long cmd, void *argp)
{ {
struct lwip_socket *sock = get_socket(s); struct lwip_socket *sock = get_socket(s);
if (!sock) { if(!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@@ -1035,7 +1335,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
*((u16_t*)argp) = sock->conn->recv_avail; *((u16_t*)argp) = sock->conn->recv_avail;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp))); 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; return 0;
case FIONBIO: case FIONBIO:
@@ -1044,7 +1344,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
else else
sock->flags &= ~O_NONBLOCK; sock->flags &= ~O_NONBLOCK;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(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; return 0;
default: 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -50,7 +50,7 @@ static sys_mbox_t mbox;
static int tcpip_tcp_timer_active = 0; static int tcpip_tcp_timer_active = 0;
/*-----------------------------------------------------------------------------------*/
static void static void
tcpip_tcp_timer(void *arg) tcpip_tcp_timer(void *arg)
{ {
@@ -73,7 +73,7 @@ tcp_timer_needed(void)
} }
} }
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/
static void static void
tcpip_thread(void *arg) tcpip_thread(void *arg)
{ {
@@ -110,16 +110,16 @@ tcpip_thread(void *arg)
default: default:
break; break;
} }
memp_freep(MEMP_TCPIP_MSG, msg); memp_free(MEMP_TCPIP_MSG, msg);
} }
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
tcpip_input(struct pbuf *p, struct netif *inp) tcpip_input(struct pbuf *p, struct netif *inp)
{ {
struct tcpip_msg *msg; struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG); msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) { if (msg == NULL) {
pbuf_free(p); pbuf_free(p);
return ERR_MEM; return ERR_MEM;
@@ -131,13 +131,13 @@ tcpip_input(struct pbuf *p, struct netif *inp)
sys_mbox_post(mbox, msg); sys_mbox_post(mbox, msg);
return ERR_OK; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
tcpip_callback(void (*f)(void *ctx), void *ctx) tcpip_callback(void (*f)(void *ctx), void *ctx)
{ {
struct tcpip_msg *msg; struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG); msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) { if (msg == NULL) {
return ERR_MEM; return ERR_MEM;
} }
@@ -148,12 +148,12 @@ tcpip_callback(void (*f)(void *ctx), void *ctx)
sys_mbox_post(mbox, msg); sys_mbox_post(mbox, msg);
return ERR_OK; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
void void
tcpip_apimsg(struct api_msg *apimsg) tcpip_apimsg(struct api_msg *apimsg)
{ {
struct tcpip_msg *msg; struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG); msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) { if (msg == NULL) {
memp_free(MEMP_API_MSG, apimsg); memp_free(MEMP_API_MSG, apimsg);
return; return;
@@ -162,7 +162,7 @@ tcpip_apimsg(struct api_msg *apimsg)
msg->msg.apimsg = apimsg; msg->msg.apimsg = apimsg;
sys_mbox_post(mbox, msg); sys_mbox_post(mbox, msg);
} }
/*-----------------------------------------------------------------------------------*/
void void
tcpip_init(void (* initfunc)(void *), void *arg) tcpip_init(void (* initfunc)(void *), void *arg)
{ {
@@ -171,7 +171,7 @@ tcpip_init(void (* initfunc)(void *), void *arg)
mbox = sys_mbox_new(); mbox = sys_mbox_new();
sys_thread_new(tcpip_thread, NULL, TCPIP_THREAD_PRIO); 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-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
* Copyright (c) 2001-2003 Axon Digital Design B.V., The Netherlands. * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -192,6 +192,7 @@ static void dhcp_handle_offer(struct netif *netif)
/* remember offered address */ /* remember offered address */
ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr); ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08lx\n", dhcp->offered_ip_addr.addr)); LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08lx\n", dhcp->offered_ip_addr.addr));
dhcp_select(netif); 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(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
dhcp_option_short(dhcp, 576); dhcp_option_short(dhcp, 576);
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
dhcp_option_trailer(dhcp); dhcp_option_trailer(dhcp);
/* resize pbuf to reflect true size of options */ /* resize pbuf to reflect true size of options */
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -30,14 +30,14 @@
* *
*/ */
/*-----------------------------------------------------------------------------------*/
/* inet.c /* inet.c
* *
* Functions common to all TCP/IP modules, such as the Internet checksum and the * Functions common to all TCP/IP modules, such as the Internet checksum and the
* byte order functions. * byte order functions.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h" #include "lwip/opt.h"
@@ -47,7 +47,7 @@
#include "lwip/inet.h" #include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
static u16_t static u16_t
lwip_chksum(void *dataptr, int len) lwip_chksum(void *dataptr, int len)
{ {
@@ -75,12 +75,12 @@ lwip_chksum(void *dataptr, int len)
return (u16_t)acc; return (u16_t)acc;
} }
/*-----------------------------------------------------------------------------------*/
/* inet_chksum_pseudo: /* inet_chksum_pseudo:
* *
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
*/ */
/*-----------------------------------------------------------------------------------*/
u16_t u16_t
inet_chksum_pseudo(struct pbuf *p, inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest, 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)); LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
return ~(acc & 0xffffUL); return ~(acc & 0xffffUL);
} }
/*-----------------------------------------------------------------------------------*/
/* inet_chksum: /* inet_chksum:
* *
* Calculates the Internet checksum over a portion of memory. Used primarely for IP * Calculates the Internet checksum over a portion of memory. Used primarely for IP
* and ICMP. * and ICMP.
*/ */
/*-----------------------------------------------------------------------------------*/
u16_t u16_t
inet_chksum(void *dataptr, u16_t len) inet_chksum(void *dataptr, u16_t len)
{ {
@@ -142,7 +142,7 @@ inet_chksum(void *dataptr, u16_t len)
} }
return ~(acc & 0xffff); return ~(acc & 0xffff);
} }
/*-----------------------------------------------------------------------------------*/
u16_t u16_t
inet_chksum_pbuf(struct pbuf *p) inet_chksum_pbuf(struct pbuf *p)
{ {
@@ -169,7 +169,17 @@ inet_chksum_pbuf(struct pbuf *p)
return ~(acc & 0xffffUL); 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. * Ascii internet address interpretation routine.
* The value returned is in network order. * The value returned is in network order.
@@ -318,24 +328,24 @@ u8_t *inet_ntoa(u32_t addr)
return str; return str;
} }
/*-----------------------------------------------------------------------------------*/
#ifndef BYTE_ORDER #ifndef BYTE_ORDER
#error BYTE_ORDER is not defined #error BYTE_ORDER is not defined
#endif #endif
#if BYTE_ORDER == LITTLE_ENDIAN #if BYTE_ORDER == LITTLE_ENDIAN
/*-----------------------------------------------------------------------------------*/
u16_t u16_t
htons(u16_t n) htons(u16_t n)
{ {
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
} }
/*-----------------------------------------------------------------------------------*/
u16_t u16_t
ntohs(u16_t n) ntohs(u16_t n)
{ {
return htons(n); return htons(n);
} }
/*-----------------------------------------------------------------------------------*/
u32_t u32_t
htonl(u32_t n) htonl(u32_t n)
{ {
@@ -344,11 +354,11 @@ htonl(u32_t n)
((n & 0xff0000) >> 8) | ((n & 0xff0000) >> 8) |
((n & 0xff000000) >> 24); ((n & 0xff000000) >> 24);
} }
/*-----------------------------------------------------------------------------------*/
u32_t u32_t
ntohl(u32_t n) ntohl(u32_t n)
{ {
return htonl(n); return htonl(n);
} }
/*-----------------------------------------------------------------------------------*/
#endif /* BYTE_ORDER == LITTLE_ENDIAN */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -30,14 +30,14 @@
* *
*/ */
/*-----------------------------------------------------------------------------------*/
/* inet6.c /* inet6.c
* *
* Functions common to all TCP/IP modules, such as the Internet checksum and the * Functions common to all TCP/IP modules, such as the Internet checksum and the
* byte order functions. * byte order functions.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h" #include "lwip/opt.h"
@@ -45,7 +45,7 @@
#include "lwip/inet.h" #include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
/* chksum: /* chksum:
* *
* Sums up all 16 bit words in a memory portion. Also includes any odd byte. * 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 * For now, this is not optimized. Must be optimized for the particular processor
* arcitecture on which it is to run. Preferebly coded in assembler. * arcitecture on which it is to run. Preferebly coded in assembler.
*/ */
/*-----------------------------------------------------------------------------------*/
static u32_t static u32_t
chksum(void *dataptr, u16_t len) chksum(void *dataptr, u16_t len)
{ {
@@ -74,12 +74,12 @@ chksum(void *dataptr, u16_t len)
return acc; return acc;
} }
/*-----------------------------------------------------------------------------------*/
/* inet_chksum_pseudo: /* inet_chksum_pseudo:
* *
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
*/ */
/*-----------------------------------------------------------------------------------*/
u16_t u16_t
inet_chksum_pseudo(struct pbuf *p, inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest, struct ip_addr *src, struct ip_addr *dest,
@@ -122,13 +122,13 @@ inet_chksum_pseudo(struct pbuf *p,
} }
return ~(acc & 0xffff); return ~(acc & 0xffff);
} }
/*-----------------------------------------------------------------------------------*/
/* inet_chksum: /* inet_chksum:
* *
* Calculates the Internet checksum over a portion of memory. Used primarely for IP * Calculates the Internet checksum over a portion of memory. Used primarely for IP
* and ICMP. * and ICMP.
*/ */
/*-----------------------------------------------------------------------------------*/
u16_t u16_t
inet_chksum(void *dataptr, u16_t len) inet_chksum(void *dataptr, u16_t len)
{ {
@@ -139,7 +139,7 @@ inet_chksum(void *dataptr, u16_t len)
sum += (sum >> 16); sum += (sum >> 16);
return ~(sum & 0xffff); return ~(sum & 0xffff);
} }
/*-----------------------------------------------------------------------------------*/
u16_t u16_t
inet_chksum_pbuf(struct pbuf *p) inet_chksum_pbuf(struct pbuf *p)
{ {
@@ -165,4 +165,4 @@ inet_chksum_pbuf(struct pbuf *p)
} }
return ~(acc & 0xffff); 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -43,7 +43,7 @@
#include "lwip/stats.h" #include "lwip/stats.h"
#include "lwip/snmp.h" #include "lwip/snmp.h"
/*-----------------------------------------------------------------------------------*/
void void
icmp_input(struct pbuf *p, struct netif *inp) icmp_input(struct pbuf *p, struct netif *inp)
{ {
@@ -54,9 +54,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
struct ip_addr tmpaddr; struct ip_addr tmpaddr;
u16_t hlen; u16_t hlen;
#ifdef ICMP_STATS ICMP_STATS_INC(icmp.recv);
++lwip_stats.icmp.recv;
#endif /* ICMP_STATS */
snmp_inc_icmpinmsgs(); 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)) { if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len)); LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len));
pbuf_free(p); pbuf_free(p);
#ifdef ICMP_STATS ICMP_STATS_INC(icmp.lenerr);
++lwip_stats.icmp.lenerr;
#endif /* ICMP_STATS */
snmp_inc_icmpinerrors(); snmp_inc_icmpinerrors();
return; return;
} }
@@ -79,20 +75,15 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) || if (ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) ||
ip_addr_ismulticast(&iphdr->dest)) { ip_addr_ismulticast(&iphdr->dest)) {
LWIP_DEBUGF(ICMP_DEBUG, ("Smurf.\n")); LWIP_DEBUGF(ICMP_DEBUG, ("Smurf.\n"));
#ifdef ICMP_STATS ICMP_STATS_INC(icmp.err);
++lwip_stats.icmp.err;
#endif /* ICMP_STATS */
pbuf_free(p); pbuf_free(p);
return; return;
} }
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
LWIP_DEBUGF(DEMO_DEBUG, ("Pong!\n"));
if (p->tot_len < sizeof(struct icmp_echo_hdr)) { if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
pbuf_free(p); pbuf_free(p);
#ifdef ICMP_STATS ICMP_STATS_INC(icmp.lenerr);
++lwip_stats.icmp.lenerr;
#endif /* ICMP_STATS */
snmp_inc_icmpinerrors(); snmp_inc_icmpinerrors();
return; return;
@@ -101,9 +92,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (inet_chksum_pbuf(p) != 0) { if (inet_chksum_pbuf(p) != 0) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
pbuf_free(p); pbuf_free(p);
#ifdef ICMP_STATS ICMP_STATS_INC(icmp.chkerr);
++lwip_stats.icmp.chkerr;
#endif /* ICMP_STATS */
snmp_inc_icmpinerrors(); snmp_inc_icmpinerrors();
return; return;
} }
@@ -117,28 +106,24 @@ icmp_input(struct pbuf *p, struct netif *inp)
} else { } else {
iecho->chksum += htons(ICMP_ECHO << 8); iecho->chksum += htons(ICMP_ECHO << 8);
} }
#ifdef ICMP_STATS ICMP_STATS_INC(icmp.xmit);
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
/* increase number of messages attempted to send */ /* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs(); snmp_inc_icmpoutmsgs();
/* increase number of echo replies attempted to send */ /* increase number of echo replies attempted to send */
snmp_inc_icmpoutechoreps(); snmp_inc_icmpoutechoreps();
pbuf_header(p, hlen); pbuf_header(p, hlen);
ip_output_if (p, &(iphdr->src), IP_HDRINCL, ip_output_if(p, &(iphdr->src), IP_HDRINCL,
IPH_TTL(iphdr), IP_PROTO_ICMP, inp); IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
break; break;
default: default:
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code)); LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code));
#ifdef ICMP_STATS ICMP_STATS_INC(icmp.proterr);
++lwip_stats.icmp.proterr; ICMP_STATS_INC(icmp.drop);
++lwip_stats.icmp.drop;
#endif /* ICMP_STATS */
} }
pbuf_free(p); pbuf_free(p);
} }
/*-----------------------------------------------------------------------------------*/
void void
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) 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 */ /* calculate checksum */
idur->chksum = 0; idur->chksum = 0;
idur->chksum = inet_chksum(idur, q->len); idur->chksum = inet_chksum(idur, q->len);
#ifdef ICMP_STATS ICMP_STATS_INC(icmp.xmit);
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
/* increase number of messages attempted to send */ /* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs(); snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */ /* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpoutdestunreachs(); snmp_inc_icmpoutdestunreachs();
ip_output(q, NULL, &(iphdr->src), ip_output(q, NULL, &(iphdr->src),
ICMP_TTL, IP_PROTO_ICMP); ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q); pbuf_free(q);
} }
/*-----------------------------------------------------------------------------------*/
#if IP_FORWARD #if IP_FORWARD
void void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) 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); q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
iphdr = p->payload; iphdr = p->payload;
#if ICMP_DEBUG
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src)); ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
LWIP_DEBUGF(ICMP_DEBUG, (" to ")); LWIP_DEBUGF(ICMP_DEBUG, (" to "));
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest)); ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
LWIP_DEBUGF(ICMP_DEBUG, ("\n")); LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
#endif /* ICMP_DEBNUG */
tehdr = q->payload; tehdr = q->payload;
ICMPH_TYPE_SET(tehdr, ICMP_TE); ICMPH_TYPE_SET(tehdr, ICMP_TE);
@@ -202,19 +183,17 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
/* calculate checksum */ /* calculate checksum */
tehdr->chksum = 0; tehdr->chksum = 0;
tehdr->chksum = inet_chksum(tehdr, q->len); tehdr->chksum = inet_chksum(tehdr, q->len);
#ifdef ICMP_STATS ICMP_STATS_INC(icmp.xmit);
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
/* increase number of messages attempted to send */ /* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs(); snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */ /* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpouttimeexcds(); snmp_inc_icmpouttimeexcds();
ip_output(q, NULL, &(iphdr->src), ip_output(q, NULL, &(iphdr->src),
ICMP_TTL, IP_PROTO_ICMP); ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q); 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -31,13 +31,13 @@
*/ */
/*-----------------------------------------------------------------------------------*/
/* ip.c /* ip.c
* *
* This is the code for the IP layer. * This is the code for the IP layer.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h" #include "lwip/opt.h"
@@ -49,6 +49,7 @@
#include "lwip/inet.h" #include "lwip/inet.h"
#include "lwip/netif.h" #include "lwip/netif.h"
#include "lwip/icmp.h" #include "lwip/icmp.h"
#include "lwip/raw.h"
#include "lwip/udp.h" #include "lwip/udp.h"
#include "lwip/tcp.h" #include "lwip/tcp.h"
@@ -61,67 +62,17 @@
# include "lwip/dhcp.h" # include "lwip/dhcp.h"
#endif /* LWIP_DHCP */ #endif /* LWIP_DHCP */
/*-----------------------------------------------------------------------------------*/
/* ip_init: /* ip_init:
* *
* Initializes the IP layer. * Initializes the IP layer.
*/ */
/*-----------------------------------------------------------------------------------*/
void void
ip_init(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: /* ip_route:
* *
* Finds the appropriate network interface for a given IP address. It * 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 * if the masked IP address of the network interface equals the masked
* IP address given to the function. * IP address given to the function.
*/ */
/*-----------------------------------------------------------------------------------*/
struct netif * struct netif *
ip_route(struct ip_addr *dest) ip_route(struct ip_addr *dest)
{ {
@@ -147,14 +98,14 @@ ip_route(struct ip_addr *dest)
return netif_default; return netif_default;
} }
#if IP_FORWARD #if IP_FORWARD
/*-----------------------------------------------------------------------------------*/
/* ip_forward: /* ip_forward:
* *
* Forwards an IP packet. It finds an appropriate route for the * Forwards an IP packet. It finds an appropriate route for the
* packet, decrements the TTL value of the packet, adjusts the * packet, decrements the TTL value of the packet, adjusts the
* checksum and outputs the packet on the appropriate interface. * checksum and outputs the packet on the appropriate interface.
*/ */
/*-----------------------------------------------------------------------------------*/
static void static void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) 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", LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
iphdr->dest.addr)); iphdr->dest.addr));
#ifdef IP_STATS IP_STATS_INC(ip.fw);
++lwip_stats.ip.fw; IP_STATS_INC(ip.xmit);
++lwip_stats.ip.xmit;
#endif /* IP_STATS */
snmp_inc_ipforwdatagrams(); snmp_inc_ipforwdatagrams();
PERF_STOP("ip_forward"); 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)); netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
} }
#endif /* IP_FORWARD */ #endif /* IP_FORWARD */
/*-----------------------------------------------------------------------------------*/
/* ip_input: /* ip_input:
* *
* This function is called by the network interface device driver when * 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. * Finally, the packet is sent to the upper layer protocol input function.
*/ */
/*-----------------------------------------------------------------------------------*/
err_t err_t
ip_input(struct pbuf *p, struct netif *inp) { ip_input(struct pbuf *p, struct netif *inp) {
static struct ip_hdr *iphdr; static struct ip_hdr *iphdr;
static struct netif *netif; static struct netif *netif;
static u16_t iphdrlen; static u16_t iphdrlen;
#ifdef IP_STATS IP_STATS_INC(ip.recv);
++lwip_stats.ip.recv;
#endif /* IP_STATS */
snmp_inc_ipinreceives(); snmp_inc_ipinreceives();
/* identify the IP header */ /* identify the IP header */
iphdr = p->payload; iphdr = p->payload;
if (IPH_V(iphdr) != 4) { if (IPH_V(iphdr) != 4) {
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %u\n", IPH_V(iphdr))); LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %u\n", IPH_V(iphdr)));
#if IP_DEBUG
ip_debug_print(p); ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p); pbuf_free(p);
#ifdef IP_STATS IP_STATS_INC(ip.err);
++lwip_stats.ip.err; IP_STATS_INC(ip.drop);
++lwip_stats.ip.drop;
#endif /* IP_STATS */
snmp_inc_ipunknownprotos(); snmp_inc_ipunknownprotos();
return ERR_OK; return ERR_OK;
} }
@@ -259,10 +202,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
iphdrlen, p->len)); iphdrlen, p->len));
/* free (drop) packet pbufs */ /* free (drop) packet pbufs */
pbuf_free(p); pbuf_free(p);
#ifdef IP_STATS IP_STATS_INC(ip.lenerr);
++lwip_stats.ip.lenerr; IP_STATS_INC(ip.drop);
++lwip_stats.ip.drop;
#endif /* IP_STATS */
snmp_inc_ipindiscards(); snmp_inc_ipindiscards();
return ERR_OK; return ERR_OK;
} }
@@ -271,14 +212,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
if (inet_chksum(iphdr, iphdrlen) != 0) { if (inet_chksum(iphdr, iphdrlen) != 0) {
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen))); LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
#if IP_DEBUG
ip_debug_print(p); ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p); pbuf_free(p);
#ifdef IP_STATS IP_STATS_INC(ip.chkerr);
++lwip_stats.ip.chkerr; IP_STATS_INC(ip.drop);
++lwip_stats.ip.drop;
#endif /* IP_STATS */
snmp_inc_ipindiscards(); snmp_inc_ipindiscards();
return ERR_OK; return ERR_OK;
} }
@@ -363,10 +300,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
pbuf_free(p); pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n", LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
ntohs(IPH_OFFSET(iphdr)))); ntohs(IPH_OFFSET(iphdr))));
#ifdef IP_STATS IP_STATS_INC(ip.opterr);
++lwip_stats.ip.opterr; IP_STATS_INC(ip.drop);
++lwip_stats.ip.drop;
#endif /* IP_STATS */
snmp_inc_ipunknownprotos(); snmp_inc_ipunknownprotos();
return ERR_OK; return ERR_OK;
} }
@@ -376,30 +311,31 @@ ip_input(struct pbuf *p, struct netif *inp) {
if (iphdrlen > IP_HLEN) { if (iphdrlen > IP_HLEN) {
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n")); LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
pbuf_free(p); pbuf_free(p);
#ifdef IP_STATS IP_STATS_INC(ip.opterr);
++lwip_stats.ip.opterr; IP_STATS_INC(ip.drop);
++lwip_stats.ip.drop;
#endif /* IP_STATS */
snmp_inc_ipunknownprotos(); snmp_inc_ipunknownprotos();
return ERR_OK; return ERR_OK;
} }
#endif /* IP_OPTIONS == 0 */ #endif /* IP_OPTIONS == 0 */
/* send to upper layers */ /* send to upper layers */
#if IP_DEBUG
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
ip_debug_print(p); ip_debug_print(p);
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len)); LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %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)) { switch (IPH_PROTO(iphdr)) {
#if LWIP_UDP > 0 #if LWIP_UDP
case IP_PROTO_UDP: case IP_PROTO_UDP:
case IP_PROTO_UDPLITE:
snmp_inc_ipindelivers(); snmp_inc_ipindelivers();
udp_input(p, inp); udp_input(p, inp);
break; break;
#endif /* LWIP_UDP */ #endif /* LWIP_UDP */
#if LWIP_TCP > 0 #if LWIP_TCP
case IP_PROTO_TCP: case IP_PROTO_TCP:
snmp_inc_ipindelivers(); snmp_inc_ipindelivers();
tcp_input(p, inp); 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))); LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
#ifdef IP_STATS IP_STATS_INC(ip.proterr);
++lwip_stats.ip.proterr; IP_STATS_INC(ip.drop);
++lwip_stats.ip.drop;
#endif /* IP_STATS */
snmp_inc_ipunknownprotos(); snmp_inc_ipunknownprotos();
} }
#if LWIP_RAW
} /* LWIP_RAW */
#endif
return ERR_OK; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
/* ip_output_if: /* ip_output_if:
* *
* Sends an IP packet on a network interface. This function constructs * Sends an IP packet on a network interface. This function constructs
@@ -438,10 +375,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
* IP address is NULL, the IP address of the outgoing network * IP address is NULL, the IP address of the outgoing network
* interface is filled in as source address. * interface is filled in as source address.
*/ */
/*-----------------------------------------------------------------------------------*/
err_t err_t
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t ttl, u8_t tos,
u8_t proto, struct netif *netif) u8_t proto, struct netif *netif)
{ {
static struct ip_hdr *iphdr; 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)) { if (pbuf_header(p, IP_HLEN)) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n")); LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
#ifdef IP_STATS IP_STATS_INC(ip.err);
++lwip_stats.ip.err;
#endif /* IP_STATS */
snmp_inc_ipoutdiscards(); snmp_inc_ipoutdiscards();
return ERR_BUF; 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); 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_LEN_SET(iphdr, htons(p->tot_len));
IPH_OFFSET_SET(iphdr, htons(IP_DF)); IPH_OFFSET_SET(iphdr, htons(IP_DF));
IPH_ID_SET(iphdr, htons(ip_id)); 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); return ip_frag(p,netif,dest);
#endif #endif
#ifdef IP_STATS IP_STATS_INC(ip.xmit);
lwip_stats.ip.xmit++;
#endif /* IP_STATS */
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num)); LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
#if IP_DEBUG
ip_debug_print(p); ip_debug_print(p);
#endif /* IP_DEBUG */
LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
return netif->output(netif, p, dest); return netif->output(netif, p, dest);
} }
/*-----------------------------------------------------------------------------------*/
/* ip_output: /* ip_output:
* *
* Simple interface to ip_output_if. It finds the outgoing network * Simple interface to ip_output_if. It finds the outgoing network
* interface and calls upon ip_output_if to do the actual work. * interface and calls upon ip_output_if to do the actual work.
*/ */
/*-----------------------------------------------------------------------------------*/
err_t err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, 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; struct netif *netif;
if ((netif = ip_route(dest)) == NULL) { if ((netif = ip_route(dest)) == NULL) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr)); LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr));
#ifdef IP_STATS IP_STATS_INC(ip.rterr);
++lwip_stats.ip.rterr;
#endif /* IP_STATS */
snmp_inc_ipoutdiscards(); snmp_inc_ipoutdiscards();
return ERR_RTE; 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 #if IP_DEBUG
void void
ip_debug_print(struct pbuf *p) ip_debug_print(struct pbuf *p)
@@ -573,7 +503,7 @@ ip_debug_print(struct pbuf *p)
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
} }
#endif /* IP_DEBUG */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -31,13 +31,13 @@
* *
*/ */
/*-----------------------------------------------------------------------------------*/
/* ip_frag.c /* ip_frag.c
* *
* This is the code for IP segmentation and reassembly * This is the code for IP segmentation and reassembly
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h" #include "lwip/opt.h"
#include "lwip/sys.h" #include "lwip/sys.h"
@@ -109,9 +109,7 @@ ip_reass(struct pbuf *p)
u16_t offset, len; u16_t offset, len;
u16_t i; u16_t i;
#ifdef IP_STATS IPFRAG_STATS_INC(ip_frag.recv);
++lwip_stats.ip_frag.recv;
#endif /* IP_STATS */
iphdr = (struct ip_hdr *) ip_reassbuf; iphdr = (struct ip_hdr *) ip_reassbuf;
fraghdr = (struct ip_hdr *) p->payload; fraghdr = (struct ip_hdr *) p->payload;
@@ -135,9 +133,7 @@ ip_reass(struct pbuf *p)
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) && ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
IPH_ID(iphdr) == IPH_ID(fraghdr)) { IPH_ID(iphdr) == IPH_ID(fraghdr)) {
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n")); LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n"));
#ifdef IP_STATS IPFRAG_STATS_INC(ip_frag.cachehit);
++lwip_stats.ip_frag.cachehit;
#endif /* IP_STATS */
/* Find out the offset in the reassembly buffer where we should /* Find out the offset in the reassembly buffer where we should
copy the fragment. */ copy the fragment. */
len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; 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); q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
i += q->len; i += q->len;
} }
#ifdef IP_STATS IPFRAG_STATS_INC(ip_frag.fw);
++lwip_stats.ip_frag.fw;
#endif /* IP_STATS */
} else { } else {
#ifdef IP_STATS IPFRAG_STATS_INC(ip_frag.memerr);
++lwip_stats.ip_frag.memerr;
#endif /* IP_STATS */
} }
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p)); LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
return p; return p;
@@ -269,9 +261,7 @@ ip_reass(struct pbuf *p)
} }
nullreturn: nullreturn:
#ifdef IP_STATS IPFRAG_STATS_INC(ip_frag.drop);
++lwip_stats.ip_frag.drop;
#endif /* IP_STATS */
pbuf_free(p); pbuf_free(p);
return NULL; 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); header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
pbuf_chain(header, rambuf); pbuf_chain(header, rambuf);
netif->output(netif, header, dest); netif->output(netif, header, dest);
#ifdef IP_STATS IPFRAG_STATS_INC(ip_frag.xmit);
++lwip_stats.ip_frag.xmit;
#endif /* IP_STATS */
pbuf_free(header); pbuf_free(header);
left -= cop; 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -42,7 +42,7 @@
#include "lwip/stats.h" #include "lwip/stats.h"
/*-----------------------------------------------------------------------------------*/
void void
icmp_input(struct pbuf *p, struct netif *inp) icmp_input(struct pbuf *p, struct netif *inp)
{ {
@@ -113,7 +113,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
pbuf_free(p); pbuf_free(p);
} }
/*-----------------------------------------------------------------------------------*/
void void
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) 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); (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
pbuf_free(q); pbuf_free(q);
} }
/*-----------------------------------------------------------------------------------*/
void void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -31,13 +31,13 @@
*/ */
/*-----------------------------------------------------------------------------------*/
/* ip.c /* ip.c
* *
* This is the code for the IP layer for IPv6. * This is the code for the IP layer for IPv6.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h" #include "lwip/opt.h"
@@ -53,24 +53,24 @@
#include "lwip/stats.h" #include "lwip/stats.h"
#include "arch/perf.h" #include "arch/perf.h"
/*-----------------------------------------------------------------------------------*/
/* ip_init: /* ip_init:
* *
* Initializes the IP layer. * Initializes the IP layer.
*/ */
/*-----------------------------------------------------------------------------------*/
void void
ip_init(void) ip_init(void)
{ {
} }
/*-----------------------------------------------------------------------------------*/
/* ip_route: /* ip_route:
* *
* Finds the appropriate network interface for a given IP address. It searches the * 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 * 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. * the network interface equals the masked IP address given to the function.
*/ */
/*-----------------------------------------------------------------------------------*/
struct netif * struct netif *
ip_route(struct ip_addr *dest) ip_route(struct ip_addr *dest)
{ {
@@ -84,14 +84,14 @@ ip_route(struct ip_addr *dest)
return netif_default; return netif_default;
} }
/*-----------------------------------------------------------------------------------*/
/* ip_forward: /* ip_forward:
* *
* Forwards an IP packet. It finds an appropriate route for the packet, decrements * 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 * the TTL value of the packet, adjusts the checksum and outputs the packet on the
* appropriate interface. * appropriate interface.
*/ */
/*-----------------------------------------------------------------------------------*/
static void static void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr) 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)); netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
} }
/*-----------------------------------------------------------------------------------*/
/* ip_input: /* ip_input:
* *
* This function is called by the network interface device driver when an IP packet is * 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. * Finally, the packet is sent to the upper layer protocol input function.
*/ */
/*-----------------------------------------------------------------------------------*/
void void
ip_input(struct pbuf *p, struct netif *inp) { ip_input(struct pbuf *p, struct netif *inp) {
struct ip_hdr *iphdr; struct ip_hdr *iphdr;
@@ -249,14 +249,14 @@ ip_input(struct pbuf *p, struct netif *inp) {
PERF_STOP("ip_input"); PERF_STOP("ip_input");
} }
/*-----------------------------------------------------------------------------------*/
/* ip_output_if: /* ip_output_if:
* *
* Sends an IP packet on a network interface. This function constructs the IP header * 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, * 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. * the IP address of the outgoing network interface is filled in as source address.
*/ */
/*-----------------------------------------------------------------------------------*/
err_t err_t
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, 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"); PERF_STOP("ip_output_if");
return netif->output(netif, p, dest); return netif->output(netif, p, dest);
} }
/*-----------------------------------------------------------------------------------*/
/* ip_output: /* ip_output:
* *
* Simple interface to ip_output_if. It finds the outgoing network interface and * Simple interface to ip_output_if. It finds the outgoing network interface and
* calls upon ip_output_if to do the actual work. * calls upon ip_output_if to do the actual work.
*/ */
/*-----------------------------------------------------------------------------------*/
err_t err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto) 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); return ip_output_if (p, src, dest, ttl, proto, netif);
} }
/*-----------------------------------------------------------------------------------*/
#if IP_DEBUG #if IP_DEBUG
void void
ip_debug_print(struct pbuf *p) ip_debug_print(struct pbuf *p)
@@ -383,4 +383,4 @@ ip_debug_print(struct pbuf *p)
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
} }
#endif /* IP_DEBUG */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -33,7 +33,7 @@
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "lwip/inet.h" #include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
int int
ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2, ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
struct ip_addr *mask) 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])); (addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3]));
} }
/*-----------------------------------------------------------------------------------*/
int int
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2) 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[2] == addr2->addr[2] &&
addr1->addr[3] == addr2->addr[3]); addr1->addr[3] == addr2->addr[3]);
} }
/*-----------------------------------------------------------------------------------*/
void void
ip_addr_set(struct ip_addr *dest, struct ip_addr *src) 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[2] = src->addr[2];
dest->addr[3] = src->addr[3];*/ dest->addr[3] = src->addr[3];*/
} }
/*-----------------------------------------------------------------------------------*/
int int
ip_addr_isany(struct ip_addr *addr) 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); return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0);
} }
/*-----------------------------------------------------------------------------------*/
/*#if IP_DEBUG*/ /*#if IP_DEBUG*/
void void
ip_addr_debug_print(struct ip_addr *addr) 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); ntohl(addr->addr[3]) & 0xffff);
} }
/*#endif*/ /* IP_DEBUG */ /*#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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -127,7 +127,7 @@ mem_init(void)
lfree = (struct mem *)ram; lfree = (struct mem *)ram;
#ifdef MEM_STATS #if MEM_STATS
lwip_stats.mem.avail = MEM_SIZE; lwip_stats.mem.avail = MEM_SIZE;
#endif /* MEM_STATS */ #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) { if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n")); LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
#ifdef MEM_STATS #if MEM_STATS
++lwip_stats.mem.err; ++lwip_stats.mem.err;
#endif /* MEM_STATS */ #endif /* MEM_STATS */
sys_sem_signal(mem_sem); sys_sem_signal(mem_sem);
@@ -164,7 +164,7 @@ mem_free(void *rmem)
lfree = mem; lfree = mem;
} }
#ifdef MEM_STATS #if MEM_STATS
lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram); lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
#endif /* MEM_STATS */ #endif /* MEM_STATS */
@@ -183,7 +183,7 @@ mem_reallocm(void *rmem, mem_size_t newsize)
mem_free(rmem); mem_free(rmem);
return nmem; return nmem;
} }
/*-----------------------------------------------------------------------------------*/
void * void *
mem_realloc(void *rmem, mem_size_t newsize) 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; ptr = (u8_t *)mem - ram;
size = mem->next - ptr - SIZEOF_STRUCT_MEM; size = mem->next - ptr - SIZEOF_STRUCT_MEM;
#ifdef MEM_STATS #if MEM_STATS
lwip_stats.mem.used -= (size - newsize); lwip_stats.mem.used -= (size - newsize);
#endif /* MEM_STATS */ #endif /* MEM_STATS */
@@ -273,7 +273,7 @@ mem_malloc(mem_size_t size)
mem2->used = 0; mem2->used = 0;
mem->used = 1; mem->used = 1;
#ifdef MEM_STATS #if MEM_STATS
lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM); lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
/* if (lwip_stats.mem.max < lwip_stats.mem.used) { /* if (lwip_stats.mem.max < lwip_stats.mem.used) {
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)); 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; ++lwip_stats.mem.err;
#endif /* MEM_STATS */ #endif /* MEM_STATS */
sys_sem_signal(mem_sem); 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -36,6 +36,7 @@
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "lwip/udp.h" #include "lwip/udp.h"
#include "lwip/raw.h"
#include "lwip/tcp.h" #include "lwip/tcp.h"
#include "lwip/api.h" #include "lwip/api.h"
#include "lwip/api_msg.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] = { static const u16_t memp_sizes[MEMP_MAX] = {
sizeof(struct pbuf), sizeof(struct pbuf),
sizeof(struct raw_pcb),
sizeof(struct udp_pcb), sizeof(struct udp_pcb),
sizeof(struct tcp_pcb), sizeof(struct tcp_pcb),
sizeof(struct tcp_pcb_listen), 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] = { static const u16_t memp_num[MEMP_MAX] = {
MEMP_NUM_PBUF, MEMP_NUM_PBUF,
MEMP_NUM_RAW_PCB,
MEMP_NUM_UDP_PCB, MEMP_NUM_UDP_PCB,
MEMP_NUM_TCP_PCB, MEMP_NUM_TCP_PCB,
MEMP_NUM_TCP_PCB_LISTEN, 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 * static u8_t memp_memory[(MEMP_NUM_PBUF *
MEM_ALIGN_SIZE(sizeof(struct pbuf) + MEM_ALIGN_SIZE(sizeof(struct pbuf) +
sizeof(struct memp)) + sizeof(struct memp)) +
MEMP_NUM_RAW_PCB *
MEM_ALIGN_SIZE(sizeof(struct raw_pcb) +
sizeof(struct memp)) +
MEMP_NUM_UDP_PCB * MEMP_NUM_UDP_PCB *
MEM_ALIGN_SIZE(sizeof(struct udp_pcb) + MEM_ALIGN_SIZE(sizeof(struct udp_pcb) +
sizeof(struct memp)) + sizeof(struct memp)) +
@@ -109,12 +115,12 @@ static u8_t memp_memory[(MEMP_NUM_PBUF *
MEM_ALIGN_SIZE(sizeof(struct sys_timeout) + MEM_ALIGN_SIZE(sizeof(struct sys_timeout) +
sizeof(struct memp)))]; sizeof(struct memp)))];
/*-----------------------------------------------------------------------------------*/
#if !SYS_LIGHTWEIGHT_PROT #if !SYS_LIGHTWEIGHT_PROT
static sys_sem_t mutex; static sys_sem_t mutex;
#endif #endif
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG #ifndef LWIP_NOASSERT
static int static int
memp_sanity(void) memp_sanity(void)
{ {
@@ -135,7 +141,7 @@ memp_sanity(void)
return 1; return 1;
} }
#endif /* LWIP_DEBUG */ #endif /* LWIP_DEBUG */
/*-----------------------------------------------------------------------------------*/
void void
memp_init(void) memp_init(void)
{ {
@@ -143,7 +149,7 @@ memp_init(void)
u16_t i, j; u16_t i, j;
u16_t size; u16_t size;
#ifdef MEMP_STATS #if MEMP_STATS
for(i = 0; i < MEMP_MAX; ++i) { for(i = 0; i < MEMP_MAX; ++i) {
lwip_stats.memp[i].used = lwip_stats.memp[i].max = lwip_stats.memp[i].used = lwip_stats.memp[i].max =
lwip_stats.memp[i].err = 0; lwip_stats.memp[i].err = 0;
@@ -176,74 +182,79 @@ memp_init(void)
} }
/*-----------------------------------------------------------------------------------*/
void * void *
memp_malloc(memp_t type) memp_malloc(memp_t type)
{ {
struct memp *memp; struct memp *memp;
void *mem; void *mem;
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
#endif
LWIP_ASSERT("memp_malloc: type < MEMP_MAX", type < MEMP_MAX); 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]; memp = memp_tab[type];
if (memp != NULL) { if (memp != NULL) {
memp_tab[type] = memp->next; memp_tab[type] = memp->next;
memp->next = NULL; memp->next = NULL;
#ifdef MEMP_STATS #if MEMP_STATS
++lwip_stats.memp[type].used; ++lwip_stats.memp[type].used;
if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) { if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
lwip_stats.memp[type].max = lwip_stats.memp[type].used; lwip_stats.memp[type].max = lwip_stats.memp[type].used;
} }
#endif /* MEMP_STATS */ #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", LWIP_ASSERT("memp_malloc: memp properly aligned",
((u32_t)MEM_ALIGN((u8_t *)memp + sizeof(struct memp)) % MEM_ALIGNMENT) == 0); ((u32_t)MEM_ALIGN((u8_t *)memp + sizeof(struct memp)) % MEM_ALIGNMENT) == 0);
mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp)); mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp));
/* initialize memp memory with zeroes */
memset(mem, 0, memp_sizes[type]);
return mem; return mem;
} else { } else {
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %d\n", type)); LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %d\n", type));
#ifdef MEMP_STATS #if MEMP_STATS
++lwip_stats.memp[type].err; ++lwip_stats.memp[type].err;
#endif /* MEMP_STATS */ #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 #if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_UNPROTECT(old_level); SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */ #else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex); sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */ #endif /* SYS_LIGHTWEIGHT_PROT */
return mem; return NULL;
}
} }
/*-----------------------------------------------------------------------------------*/
void void
memp_free(memp_t type, void *mem) memp_free(memp_t type, void *mem)
{ {
struct memp *memp; struct memp *memp;
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */
if (mem == NULL) { if (mem == NULL) {
return; return;
} }
memp = (struct memp *)((u8_t *)mem - sizeof(struct memp)); 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--; lwip_stats.memp[type].used--;
#endif /* MEMP_STATS */ #endif /* MEMP_STATS */
@@ -252,26 +263,10 @@ memp_free(memp_t type, void *mem)
LWIP_ASSERT("memp sanity", memp_sanity()); 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 #if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_UNPROTECT(old_level); SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */ #else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex); sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -39,7 +39,6 @@
#include "lwip/opt.h" #include "lwip/opt.h"
#include "lwip/def.h" #include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/netif.h" #include "lwip/netif.h"
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "lwip/tcp.h" #include "lwip/tcp.h"
@@ -61,22 +60,15 @@ struct netif *netif_default = NULL;
* @return netif, or NULL if failed. * @return netif, or NULL if failed.
*/ */
struct netif * 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, struct ip_addr *gw,
void *state, void *state,
err_t (* init)(struct netif *netif), err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif)) err_t (* input)(struct pbuf *p, struct netif *netif))
{ {
struct netif *netif;
static int netifnum = 0; 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 #if LWIP_DHCP
/* netif not under DHCP control by default */ /* netif not under DHCP control by default */
netif->dhcp = NULL; netif->dhcp = NULL;
@@ -90,14 +82,12 @@ netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
/* call user specified initialization function for netif */ /* call user specified initialization function for netif */
if (init(netif) != ERR_OK) { if (init(netif) != ERR_OK) {
mem_free(netif);
return NULL; return NULL;
} }
/* add this netif to the list */ /* add this netif to the list */
netif->next = netif_list; netif->next = netif_list;
netif_list = netif; netif_list = netif;
#if NETIF_DEBUG
LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ", LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
netif->name[0], netif->name[1])); netif->name[0], netif->name[1]));
ip_addr_debug_print(NETIF_DEBUG, ipaddr); 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 ")); LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
ip_addr_debug_print(NETIF_DEBUG, gw); ip_addr_debug_print(NETIF_DEBUG, gw);
LWIP_DEBUGF(NETIF_DEBUG, ("\n")); LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
#endif /* NETIF_DEBUG */
return netif; return netif;
} }
@@ -144,7 +133,6 @@ void netif_remove(struct netif * netif)
/* reset default netif */ /* reset default netif */
netif_default = NULL; netif_default = NULL;
LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
mem_free( netif );
} }
struct 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])); LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
return NULL; return NULL;
} }
/*-----------------------------------------------------------------------------------*/
void void
netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr) 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))) { if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
/* this connection must be aborted */ /* this connection must be aborted */
struct tcp_pcb *next = pcb->next; 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); tcp_abort(pcb);
pcb = next; pcb = next;
} else { } else {
@@ -202,8 +190,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
/* PCB bound to current local interface address? */ /* PCB bound to current local interface address? */
if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) { if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {
/* The PCB is listening to the old ipaddr and /* The PCB is listening to the old ipaddr and
* is set to listen to the new one instead * is set to listen to the new one instead */
* TODO: how do we know it is _listening_? */
ip_addr_set(&(lpcb->local_ip), ipaddr); 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) >> 8 & 0xff),
(unsigned int)(ntohl(netif->ip_addr.addr) & 0xff))); (unsigned int)(ntohl(netif->ip_addr.addr) & 0xff)));
} }
/*-----------------------------------------------------------------------------------*/
void void
netif_set_gw(struct netif *netif, struct ip_addr *gw) 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) >> 8 & 0xff),
(unsigned int)(ntohl(netif->gw.addr) & 0xff))); (unsigned int)(ntohl(netif->gw.addr) & 0xff)));
} }
/*-----------------------------------------------------------------------------------*/
void void
netif_set_netmask(struct netif *netif, struct ip_addr *netmask) 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) >> 8 & 0xff),
(unsigned int)(ntohl(netif->netmask.addr) & 0xff))); (unsigned int)(ntohl(netif->netmask.addr) & 0xff)));
} }
/*-----------------------------------------------------------------------------------*/
void void
netif_set_default(struct netif *netif) 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", LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
} }
/*-----------------------------------------------------------------------------------*/
void void
netif_init(void) netif_init(void)
{ {
netif_list = netif_default = NULL; 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -102,7 +102,7 @@ pbuf_init(void)
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0]; pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
LWIP_ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 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; lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
#endif /* PBUF_STATS */ #endif /* PBUF_STATS */
@@ -113,6 +113,7 @@ pbuf_init(void)
p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf)); p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));
p->len = p->tot_len = PBUF_POOL_BUFSIZE; p->len = p->tot_len = PBUF_POOL_BUFSIZE;
p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf))); p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));
p->flags = PBUF_FLAG_POOL;
q = p; q = p;
p = p->next; p = p->next;
} }
@@ -143,7 +144,7 @@ pbuf_pool_alloc(void)
/* Next, check the actual pbuf pool, but if the pool is locked, we /* Next, check the actual pbuf pool, but if the pool is locked, we
pretend to be out of buffers and return NULL. */ pretend to be out of buffers and return NULL. */
if (pbuf_pool_free_lock) { if (pbuf_pool_free_lock) {
#ifdef PBUF_STATS #if PBUF_STATS
++lwip_stats.pbuf.alloc_locked; ++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */ #endif /* PBUF_STATS */
return NULL; return NULL;
@@ -156,7 +157,7 @@ pbuf_pool_alloc(void)
pbuf_pool = p->next; pbuf_pool = p->next;
} }
#if !SYS_LIGHTWEIGHT_PROT #if !SYS_LIGHTWEIGHT_PROT
#ifdef PBUF_STATS #if PBUF_STATS
} else { } else {
++lwip_stats.pbuf.alloc_locked; ++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */ #endif /* PBUF_STATS */
@@ -164,7 +165,7 @@ pbuf_pool_alloc(void)
pbuf_pool_alloc_lock = 0; pbuf_pool_alloc_lock = 0;
#endif /* SYS_LIGHTWEIGHT_PROT */ #endif /* SYS_LIGHTWEIGHT_PROT */
#ifdef PBUF_STATS #if PBUF_STATS
if (p != NULL) { if (p != NULL) {
++lwip_stats.pbuf.used; ++lwip_stats.pbuf.used;
if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) { 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(); p = pbuf_pool_alloc();
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
if (p == NULL) { if (p == NULL) {
#ifdef PBUF_STATS #if PBUF_STATS
++lwip_stats.pbuf.err; ++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */ #endif /* PBUF_STATS */
return NULL; return NULL;
@@ -258,8 +259,6 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
p->tot_len = length; p->tot_len = length;
/* set the length of the first pbuf in the chain */ /* set the length of the first pbuf in the chain */
p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length; 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) */ /* set reference count (needed here in case we fail) */
p->ref = 1; p->ref = 1;
@@ -274,7 +273,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
q = pbuf_pool_alloc(); q = pbuf_pool_alloc();
if (q == NULL) { if (q == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n")); LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));
#ifdef PBUF_STATS #if PBUF_STATS
++lwip_stats.pbuf.err; ++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */ #endif /* PBUF_STATS */
/* free chain so far allocated */ /* 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; q->tot_len = rem_len;
/* this pbuf length is pool size, unless smaller sized tail */ /* this pbuf length is pool size, unless smaller sized tail */
q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len; q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
q->flags = PBUF_FLAG_POOL;
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf)); q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
((u32_t)q->payload % MEM_ALIGNMENT) == 0); ((u32_t)q->payload % MEM_ALIGNMENT) == 0);
@@ -300,7 +298,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
r = q; r = q;
} }
/* end of chain */ /* end of chain */
//r->next = NULL; /*r->next = NULL;*/
break; break;
case PBUF_RAM: 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? */ /* pbuf references existing (externally allocated) RAM payload? */
case PBUF_REF: case PBUF_REF:
/* only allocate memory for the pbuf structure */ /* only allocate memory for the pbuf structure */
p = memp_mallocp(MEMP_PBUF); p = memp_malloc(MEMP_PBUF);
if (p == NULL) { 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")); 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; 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) #define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
#else /* PBUF_STATS */ #else /* PBUF_STATS */
#define DEC_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 */ /* first, step over any pbufs that should remain in the chain */
rem_len = new_len; rem_len = new_len;
q = p; q = p;
/* this pbuf should be kept? */ /* should this pbuf be kept? */
while (rem_len > q->len) { while (rem_len > q->len) {
/* decrease remaining length by pbuf length */ /* decrease remaining length by pbuf length */
rem_len -= q->len; 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 * Decrements the pbuf reference count. If it reaches
* zero, the pbuf is deallocated. * zero, the pbuf is deallocated.
* *
* For a pbuf chain, this is repeated for each pbuf in the chain, until * For a pbuf chain, this is repeated for each pbuf in the chain,
* a non-zero reference count is encountered, or the end of the chain is * up to a pbuf which has a non-zero reference count after
* reached. * 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. * 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 * @note the reference counter of a pbuf equals the number of pointers
* that refer to the pbuf (or into the pbuf). * that refer to the pbuf (or into the pbuf).
* *
* @internal examples: * @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 * 1->2->3 becomes ...1->3
* 3->3->3 becomes 2->3->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 * 2->1->1 becomes 1->1->1
* 1->1->1 becomes ....... * 1->1->1 becomes .......
* *
@@ -576,7 +578,7 @@ pbuf_free(struct pbuf *p)
PBUF_POOL_FREE(p); PBUF_POOL_FREE(p);
/* a ROM or RAM referencing pbuf */ /* a ROM or RAM referencing pbuf */
} else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) { } else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
memp_freep(MEMP_PBUF, p); memp_free(MEMP_PBUF, p);
/* p->flags == PBUF_FLAG_RAM */ /* p->flags == PBUF_FLAG_RAM */
} else { } else {
mem_free(p); mem_free(p);
@@ -619,7 +621,6 @@ pbuf_clen(struct pbuf *p)
} }
/** /**
*
* Increment the reference count of the pbuf. * Increment the reference count of the pbuf.
* *
* @param p pbuf to increase reference counter of * @param p pbuf to increase reference counter of
@@ -638,12 +639,47 @@ pbuf_ref(struct pbuf *p)
} }
/** /**
* * Concatenate two pbufs (each may be a pbuf chain) and take over
* Chain two pbufs (or pbuf chains) together. They must belong to the same packet. * 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 h head pbuf (chain)
* @param t tail 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 ->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. * The ->next field of the last pbuf of the head chain is adjusted.
@@ -653,28 +689,10 @@ pbuf_ref(struct pbuf *p)
void void
pbuf_chain(struct pbuf *h, struct pbuf *t) pbuf_chain(struct pbuf *h, struct pbuf *t)
{ {
struct pbuf *p; pbuf_cat(h, t);
/* t is now referenced by h */
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_ref(t); 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 /* 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 */ /* proceed to next packet on queue */
p = p->next; 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; p->next = n;
/* t is now referenced to one more time */ /* n is now referenced to one more time */
pbuf_ref(n); pbuf_ref(n);
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_queue: referencing queued packet %p\n", (void *)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()! * by pbuf_take()!
* *
* @note Any replaced pbufs will be freed through pbuf_free(). * @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 * @param p Head of pbuf chain to process
* *
@@ -853,7 +871,6 @@ pbuf_take(struct pbuf *p)
return head; 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. * 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); LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
return (tail_gone > 0? NULL: q); 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -41,11 +41,11 @@
#if LWIP_STATS #if LWIP_STATS
struct stats_ lwip_stats; struct stats_ lwip_stats;
/*-----------------------------------------------------------------------------------*/
void void
stats_init(void) stats_init(void)
{ {
memset(&lwip_stats, 0, sizeof(struct stats_)); memset(&lwip_stats, 0, sizeof(struct stats_));
} }
#endif /* LWIP_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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -44,7 +44,7 @@ struct sswt_cb
}; };
/*-----------------------------------------------------------------------------------*/
void void
sys_mbox_fetch(sys_mbox_t mbox, void **msg) sys_mbox_fetch(sys_mbox_t mbox, void **msg)
{ {
@@ -96,7 +96,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
} }
} }
/*-----------------------------------------------------------------------------------*/
void void
sys_sem_wait(sys_sem_t sem) sys_sem_wait(sys_sem_t sem)
{ {
@@ -152,7 +152,7 @@ sys_sem_wait(sys_sem_t sem)
} }
} }
/*-----------------------------------------------------------------------------------*/
void void
sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg) 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, /* Go through timeout list (for this task only) and remove the first matching entry,
even though the timeout has not triggered yet. even though the timeout has not triggered yet.
*/ */
/*-----------------------------------------------------------------------------------*/
void void
sys_untimeout(sys_timeout_handler h, void *arg) sys_untimeout(sys_timeout_handler h, void *arg)
{ {
@@ -238,7 +238,7 @@ sys_untimeout(sys_timeout_handler h, void *arg)
/*-----------------------------------------------------------------------------------*/
static void static void
sswt_handler(void *arg) sswt_handler(void *arg)
{ {
@@ -252,7 +252,7 @@ sswt_handler(void *arg)
/* Wait for a semaphore with timeout (specified in ms) */ /* Wait for a semaphore with timeout (specified in ms) */
/* timeout = 0: wait forever */ /* timeout = 0: wait forever */
/* Returns 0 on timeout. 1 otherwise */ /* Returns 0 on timeout. 1 otherwise */
/*-----------------------------------------------------------------------------------*/
int int
sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout) 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 void
sys_msleep(u32_t ms) sys_msleep(u32_t ms)
{ {
@@ -289,6 +289,6 @@ sys_msleep(u32_t ms)
sys_sem_free(delaysem); sys_sem_free(delaysem);
} }
/*-----------------------------------------------------------------------------------*/
#endif /* NO_SYS */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -36,7 +36,7 @@
* *
*/ */
/*-----------------------------------------------------------------------------------*/
/* tcp.c /* tcp.c
* *
* This file contains common functions for the TCP implementation, such as functinos * 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. * related to input and output is found in tcp_input.c and tcp_output.c respectively.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h" #include "lwip/opt.h"
@@ -74,13 +74,13 @@ static u8_t tcp_timer;
static u16_t tcp_new_port(void); static u16_t tcp_new_port(void);
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_init(): * tcp_init():
* *
* Initializes the TCP layer. * Initializes the TCP layer.
*/ */
/*-----------------------------------------------------------------------------------*/
void void
tcp_init(void) tcp_init(void)
{ {
@@ -95,41 +95,34 @@ tcp_init(void)
tcp_timer = 0; tcp_timer = 0;
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_tmr(): * tcp_tmr():
* *
* Called periodically to dispatch TCP timers. * Called periodically to dispatch TCP timers.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
void void
tcp_tmr(void) tcp_tmr(void)
{ {
++tcp_timer; /* Call tcp_fasttmr() every 250 ms */
if (tcp_timer == 10) { tcp_fasttmr();
tcp_timer = 0;
} if (++tcp_timer & 1) {
/* Call tcp_tmr() every 500 ms, i.e., every other timer
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
tcp_tmr() is called. */ tcp_tmr() is called. */
tcp_slowtmr(); tcp_slowtmr();
} }
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_close(): * tcp_close():
* *
* Closes the connection held by the PCB. * Closes the connection held by the PCB.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
err_t err_t
tcp_close(struct tcp_pcb *pcb) tcp_close(struct tcp_pcb *pcb)
{ {
@@ -154,11 +147,6 @@ tcp_close(struct tcp_pcb *pcb)
pcb = NULL; pcb = NULL;
break; break;
case SYN_RCVD: case SYN_RCVD:
err = tcp_send_ctrl(pcb, TCP_FIN);
if (err == ERR_OK) {
pcb->state = FIN_WAIT_1;
}
break;
case ESTABLISHED: case ESTABLISHED:
err = tcp_send_ctrl(pcb, TCP_FIN); err = tcp_send_ctrl(pcb, TCP_FIN);
if (err == ERR_OK) { if (err == ERR_OK) {
@@ -183,7 +171,7 @@ tcp_close(struct tcp_pcb *pcb)
} }
return err; return err;
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_abort() * tcp_abort()
* *
@@ -192,7 +180,7 @@ tcp_close(struct tcp_pcb *pcb)
* killed because of shortage of memory. * killed because of shortage of memory.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
void void
tcp_abort(struct tcp_pcb *pcb) tcp_abort(struct tcp_pcb *pcb)
{ {
@@ -240,7 +228,7 @@ tcp_abort(struct tcp_pcb *pcb)
tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port); tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
} }
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_bind(): * tcp_bind():
* *
@@ -249,16 +237,19 @@ tcp_abort(struct tcp_pcb *pcb)
* the outgoing network interface is used instead. * the outgoing network interface is used instead.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
err_t err_t
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{ {
struct tcp_pcb *cpcb; struct tcp_pcb *cpcb;
#ifdef SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
if (port == 0) { if (port == 0) {
port = tcp_new_port(); port = tcp_new_port();
} }
#ifndef SO_REUSE
/* Check if the address already is in use. */ /* Check if the address already is in use. */
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs; for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs;
cpcb != NULL; cpcb = cpcb->next) { 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)) { if (!ip_addr_isany(ipaddr)) {
pcb->local_ip = *ipaddr; pcb->local_ip = *ipaddr;
} }
@@ -298,7 +385,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
return ERR_ABRT; return ERR_ABRT;
} }
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_listen(): * 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. * connection to LISTEN is an irreversible process.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb * struct tcp_pcb *
tcp_listen(struct tcp_pcb *pcb) tcp_listen(struct tcp_pcb *pcb)
{ {
@@ -325,6 +412,10 @@ tcp_listen(struct tcp_pcb *pcb)
lpcb->callback_arg = pcb->callback_arg; lpcb->callback_arg = pcb->callback_arg;
lpcb->local_port = pcb->local_port; lpcb->local_port = pcb->local_port;
lpcb->state = LISTEN; 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); ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
memp_free(MEMP_TCP_PCB, pcb); memp_free(MEMP_TCP_PCB, pcb);
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
@@ -333,7 +424,7 @@ tcp_listen(struct tcp_pcb *pcb)
TCP_REG(&tcp_listen_pcbs, lpcb); TCP_REG(&tcp_listen_pcbs, lpcb);
return (struct tcp_pcb *)lpcb; return (struct tcp_pcb *)lpcb;
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_recved(): * tcp_recved():
* *
@@ -342,13 +433,14 @@ tcp_listen(struct tcp_pcb *pcb)
* when the data has been processed. * when the data has been processed.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
void void
tcp_recved(struct tcp_pcb *pcb, u16_t len) tcp_recved(struct tcp_pcb *pcb, u16_t len)
{ {
pcb->rcv_wnd += len; if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
if (pcb->rcv_wnd > TCP_WND) {
pcb->rcv_wnd = TCP_WND; pcb->rcv_wnd = TCP_WND;
} else {
pcb->rcv_wnd += len;
} }
if (!(pcb->flags & TF_ACK_DELAY) && if (!(pcb->flags & TF_ACK_DELAY) &&
!(pcb->flags & TF_ACK_NOW)) { !(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", LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n",
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_new_port(): * tcp_new_port():
* *
* A nastly hack featuring 'goto' statements that allocates a * A nastly hack featuring 'goto' statements that allocates a
* new TCP local port. * new TCP local port.
*/ */
/*-----------------------------------------------------------------------------------*/
static u16_t static u16_t
tcp_new_port(void) tcp_new_port(void)
{ {
@@ -398,7 +490,7 @@ tcp_new_port(void)
} }
return port; return port;
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_connect(): * tcp_connect():
* *
@@ -406,7 +498,7 @@ tcp_new_port(void)
* argument will be called when the connection has been established. * argument will be called when the connection has been established.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
err_t err_t
tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port, tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)) err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
@@ -453,7 +545,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
} }
return ret; return ret;
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_slowtmr(): * 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 * removes PCBs that have been in TIME-WAIT for enough time. It also increments
* various timers such as the inactivity timer in each PCB. * various timers such as the inactivity timer in each PCB.
*/ */
/*-----------------------------------------------------------------------------------*/
void void
tcp_slowtmr(void) tcp_slowtmr(void)
{ {
@@ -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 /* If this PCB has queued out of sequence data, but has been
inactive for too long, will drop the data (it will eventually inactive for too long, will drop the data (it will eventually
be retransmitted). */ be retransmitted). */
@@ -622,13 +729,13 @@ tcp_slowtmr(void)
} }
} }
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_fasttmr(): * 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 void
tcp_fasttmr(void) tcp_fasttmr(void)
{ {
@@ -643,75 +750,72 @@ tcp_fasttmr(void)
} }
} }
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_segs_free(): * tcp_segs_free():
* *
* Deallocates a list of TCP segments (tcp_seg structures). * Deallocates a list of TCP segments (tcp_seg structures).
* *
*/ */
/*-----------------------------------------------------------------------------------*/
u8_t u8_t
tcp_segs_free(struct tcp_seg *seg) tcp_segs_free(struct tcp_seg *seg)
{ {
u8_t count = 0; u8_t count = 0;
struct tcp_seg *next; struct tcp_seg *next;
again: while (seg != NULL) {
if (seg != NULL) {
next = seg->next; next = seg->next;
count += tcp_seg_free(seg); count += tcp_seg_free(seg);
seg = next; seg = next;
goto again;
} }
return count; return count;
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_seg_free(): * tcp_seg_free():
* *
* Frees a TCP segment. * Frees a TCP segment.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
u8_t u8_t
tcp_seg_free(struct tcp_seg *seg) tcp_seg_free(struct tcp_seg *seg)
{ {
u8_t count = 0; u8_t count = 0;
if (seg != NULL) { if (seg != NULL) {
if (seg->p == NULL) { if (seg->p != NULL) {
memp_free(MEMP_TCP_SEG, seg);
} else {
count = pbuf_free(seg->p); count = pbuf_free(seg->p);
#if TCP_DEBUG #if TCP_DEBUG
seg->p = NULL; seg->p = NULL;
#endif /* TCP_DEBUG */ #endif /* TCP_DEBUG */
memp_free(MEMP_TCP_SEG, seg);
} }
memp_free(MEMP_TCP_SEG, seg);
} }
return count; return count;
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_setprio(): * tcp_setprio():
* *
* Sets the priority of a connection. * Sets the priority of a connection.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
void void
tcp_setprio(struct tcp_pcb *pcb, u8_t prio) tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
{ {
pcb->prio = prio; pcb->prio = prio;
} }
/*-----------------------------------------------------------------------------------*/ #if TCP_QUEUE_OOSEQ
/* /*
* tcp_seg_copy(): * tcp_seg_copy():
* *
* Returns a copy of the given TCP segment. * Returns a copy of the given TCP segment.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
struct tcp_seg * struct tcp_seg *
tcp_seg_copy(struct tcp_seg *seg) tcp_seg_copy(struct tcp_seg *seg)
{ {
@@ -725,7 +829,8 @@ tcp_seg_copy(struct tcp_seg *seg)
pbuf_ref(cseg->p); pbuf_ref(cseg->p);
return cseg; return cseg;
} }
/*-----------------------------------------------------------------------------------*/ #endif
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
static err_t static err_t
tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) 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; return ERR_OK;
} }
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
static void static void
tcp_kill_prio(u8_t prio) tcp_kill_prio(u8_t prio)
{ {
@@ -770,7 +875,7 @@ tcp_kill_prio(u8_t prio)
} }
} }
/*-----------------------------------------------------------------------------------*/
static void static void
tcp_kill_timewait(void) tcp_kill_timewait(void)
{ {
@@ -792,8 +897,8 @@ tcp_kill_timewait(void)
} }
} }
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb * struct tcp_pcb *
tcp_alloc(u8_t prio) tcp_alloc(u8_t prio)
{ {
@@ -817,6 +922,8 @@ tcp_alloc(u8_t prio)
pcb->snd_buf = TCP_SND_BUF; pcb->snd_buf = TCP_SND_BUF;
pcb->snd_queuelen = 0; pcb->snd_queuelen = 0;
pcb->rcv_wnd = TCP_WND; pcb->rcv_wnd = TCP_WND;
pcb->tos = 0;
pcb->ttl = TCP_TTL;
pcb->mss = TCP_MSS; pcb->mss = TCP_MSS;
pcb->rto = 3000 / TCP_SLOW_INTERVAL; pcb->rto = 3000 / TCP_SLOW_INTERVAL;
pcb->sa = 0; pcb->sa = 0;
@@ -836,10 +943,14 @@ tcp_alloc(u8_t prio)
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
pcb->recv = tcp_recv_null; pcb->recv = tcp_recv_null;
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
/* Init KEEPALIVE timer */
pcb->keepalive = TCP_KEEPDEFAULT;
pcb->keep_cnt = 0;
} }
return pcb; return pcb;
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_new(): * tcp_new():
* *
@@ -847,13 +958,13 @@ tcp_alloc(u8_t prio)
* any of the TCP PCB lists. * any of the TCP PCB lists.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb * struct tcp_pcb *
tcp_new(void) tcp_new(void)
{ {
return tcp_alloc(TCP_PRIO_NORMAL); return tcp_alloc(TCP_PRIO_NORMAL);
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_arg(): * tcp_arg():
* *
@@ -861,13 +972,14 @@ tcp_new(void)
* functions. * functions.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
void void
tcp_arg(struct tcp_pcb *pcb, void *arg) tcp_arg(struct tcp_pcb *pcb, void *arg)
{ {
pcb->callback_arg = arg; pcb->callback_arg = arg;
} }
/*-----------------------------------------------------------------------------------*/ #if LWIP_CALLBACK_API
/* /*
* tcp_recv(): * tcp_recv():
* *
@@ -875,16 +987,14 @@ tcp_arg(struct tcp_pcb *pcb, void *arg)
* connection receives data. * connection receives data.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void void
tcp_recv(struct tcp_pcb *pcb, tcp_recv(struct tcp_pcb *pcb,
err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)) err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
{ {
pcb->recv = recv; pcb->recv = recv;
} }
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_sent(): * tcp_sent():
* *
@@ -892,16 +1002,14 @@ tcp_recv(struct tcp_pcb *pcb,
* has been successfully delivered to the remote host. * has been successfully delivered to the remote host.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void void
tcp_sent(struct tcp_pcb *pcb, tcp_sent(struct tcp_pcb *pcb,
err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len)) err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
{ {
pcb->sent = sent; pcb->sent = sent;
} }
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_err(): * tcp_err():
* *
@@ -909,16 +1017,31 @@ tcp_sent(struct tcp_pcb *pcb,
* has occured on the connection. * has occured on the connection.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void void
tcp_err(struct tcp_pcb *pcb, tcp_err(struct tcp_pcb *pcb,
void (* errf)(void *arg, err_t err)) void (* errf)(void *arg, err_t err))
{ {
pcb->errf = errf; 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 */ #endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_poll(): * tcp_poll():
* *
@@ -927,7 +1050,7 @@ tcp_err(struct tcp_pcb *pcb,
* timer interval, which is called twice a second. * timer interval, which is called twice a second.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
void void
tcp_poll(struct tcp_pcb *pcb, tcp_poll(struct tcp_pcb *pcb,
err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval) err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
@@ -937,31 +1060,14 @@ tcp_poll(struct tcp_pcb *pcb,
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
pcb->pollinterval = interval; 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(): * tcp_pcb_purge():
* *
* Purges a TCP PCB. Removes any buffered data and frees the buffer memory. * Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
void void
tcp_pcb_purge(struct tcp_pcb *pcb) tcp_pcb_purge(struct tcp_pcb *pcb)
{ {
@@ -971,7 +1077,6 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
#if TCP_DEBUG
if (pcb->unsent != NULL) { if (pcb->unsent != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); 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) { if (pcb->ooseq != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); 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); tcp_segs_free(pcb->ooseq);
pcb->ooseq = NULL;
#endif /* TCP_QUEUE_OOSEQ */ #endif /* TCP_QUEUE_OOSEQ */
tcp_segs_free(pcb->unsent);
tcp_segs_free(pcb->unacked); tcp_segs_free(pcb->unacked);
pcb->unacked = pcb->unsent = pcb->unacked = pcb->unsent = NULL;
#if TCP_QUEUE_OOSEQ
pcb->ooseq =
#endif /* TCP_QUEUE_OOSEQ */
NULL;
} }
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_pcb_remove(): * tcp_pcb_remove():
* *
* Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
void void
tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
{ {
@@ -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()); LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_next_iss(): * tcp_next_iss():
* *
* Calculates a new initial sequence number for new connections. * Calculates a new initial sequence number for new connections.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
u32_t u32_t
tcp_next_iss(void) tcp_next_iss(void)
{ {
@@ -1038,31 +1138,31 @@ tcp_next_iss(void)
iss += tcp_ticks; /* XXX */ iss += tcp_ticks; /* XXX */
return iss; return iss;
} }
/*-----------------------------------------------------------------------------------*/
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
void void
tcp_debug_print(struct tcp_hdr *tcphdr) tcp_debug_print(struct tcp_hdr *tcphdr)
{ {
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %04x | %04x | (src port, dest port)\n", LWIP_DEBUGF(TCP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
tcphdr->src, tcphdr->dest)); ntohs(tcphdr->src), ntohs(tcphdr->dest)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %08lu | (seq no)\n", LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (seq no)\n",
tcphdr->seqno)); ntohl(tcphdr->seqno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %08lu | (ack no)\n", LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (ack no)\n",
tcphdr->ackno)); ntohl(tcphdr->ackno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u| %5u | (offset, flags (", LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u%u| %5u | (hdrlen, flags (",
TCPH_OFFSET(tcphdr), TCPH_HDRLEN(tcphdr),
TCPH_FLAGS(tcphdr) >> 4 & 1, TCPH_FLAGS(tcphdr) >> 5 & 1,
TCPH_FLAGS(tcphdr) >> 4 & 1, TCPH_FLAGS(tcphdr) >> 4 & 1,
TCPH_FLAGS(tcphdr) >> 3 & 1, TCPH_FLAGS(tcphdr) >> 3 & 1,
TCPH_FLAGS(tcphdr) >> 2 & 1, TCPH_FLAGS(tcphdr) >> 2 & 1,
TCPH_FLAGS(tcphdr) >> 1 & 1, TCPH_FLAGS(tcphdr) >> 1 & 1,
TCPH_FLAGS(tcphdr) & 1, TCPH_FLAGS(tcphdr) & 1,
tcphdr->wnd)); ntohs(tcphdr->wnd)));
tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
@@ -1070,7 +1170,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
} }
/*-----------------------------------------------------------------------------------*/
void void
tcp_debug_print_state(enum tcp_state s) tcp_debug_print_state(enum tcp_state s)
{ {
@@ -1111,7 +1211,7 @@ tcp_debug_print_state(enum tcp_state s)
break; break;
} }
} }
/*-----------------------------------------------------------------------------------*/
void void
tcp_debug_print_flags(u8_t flags) tcp_debug_print_flags(u8_t flags)
{ {
@@ -1133,8 +1233,14 @@ tcp_debug_print_flags(u8_t flags)
if (flags & TCP_URG) { if (flags & TCP_URG) {
LWIP_DEBUGF(TCP_DEBUG, ("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 void
tcp_debug_print_pcbs(void) tcp_debug_print_pcbs(void)
{ {
@@ -1161,7 +1267,7 @@ tcp_debug_print_pcbs(void)
tcp_debug_print_state(pcb->state); tcp_debug_print_state(pcb->state);
} }
} }
/*-----------------------------------------------------------------------------------*/
int int
tcp_pcbs_sane(void) tcp_pcbs_sane(void)
{ {
@@ -1178,7 +1284,7 @@ tcp_pcbs_sane(void)
} }
#endif /* TCP_DEBUG */ #endif /* TCP_DEBUG */
#endif /* LWIP_TCP */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -36,7 +36,7 @@
* *
*/ */
/*-----------------------------------------------------------------------------------*/
/* tcp_input.c /* tcp_input.c
* *
* The input processing functions of TCP. * The input processing functions of TCP.
@@ -45,7 +45,7 @@
* tcp_process() -> tcp_receive() (-> application). * tcp_process() -> tcp_receive() (-> application).
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#include "lwip/def.h" #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_listen_input(struct tcp_pcb_listen *pcb);
static err_t tcp_timewait_input(struct tcp_pcb *pcb); static err_t tcp_timewait_input(struct tcp_pcb *pcb);
/*-----------------------------------------------------------------------------------*/
/* tcp_input: /* tcp_input:
* *
* The initial input processing of TCP. It verifies the TCP header, demultiplexes * 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 * the TCP finite state machine. This function is called by the IP layer (in
* ip_input()). * ip_input()).
*/ */
/*-----------------------------------------------------------------------------------*/
void void
tcp_input(struct pbuf *p, struct netif *inp) tcp_input(struct pbuf *p, struct netif *inp)
{ {
struct tcp_pcb *pcb, *prev; struct tcp_pcb *pcb, *prev;
struct tcp_pcb_listen *lpcb; struct tcp_pcb_listen *lpcb;
u8_t offset; u8_t hdrlen;
err_t err; err_t err;
#ifdef SO_REUSE
struct tcp_pcb *pcb_temp;
int reuse = 0;
int reuse_port = 0;
#endif /* SO_REUSE */
PERF_START; PERF_START;
TCP_STATS_INC(tcp.recv);
#ifdef TCP_STATS
++lwip_stats.tcp.recv;
#endif /* TCP_STATS */
iphdr = p->payload; iphdr = p->payload;
tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4); 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 */ /* remove header from payload */
if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) { if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
/* drop short packets */ /* drop short packets */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%u bytes) discarded\n", p->tot_len)); LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%u bytes) discarded\n", p->tot_len));
#ifdef TCP_STATS TCP_STATS_INC(tcp.lenerr);
++lwip_stats.tcp.lenerr; TCP_STATS_INC(tcp.drop);
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
pbuf_free(p); pbuf_free(p);
return; return;
} }
@@ -142,10 +146,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
#if TCP_DEBUG #if TCP_DEBUG
tcp_debug_print(tcphdr); tcp_debug_print(tcphdr);
#endif /* TCP_DEBUG */ #endif /* TCP_DEBUG */
#ifdef TCP_STATS TCP_STATS_INC(tcp.chkerr);
++lwip_stats.tcp.chkerr; TCP_STATS_INC(tcp.drop);
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
pbuf_free(p); pbuf_free(p);
return; 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 /* Move the payload pointer in the pbuf so that it points to the
TCP data instead of the TCP header. */ TCP data instead of the TCP header. */
offset = TCPH_OFFSET(tcphdr) >> 4; hdrlen = TCPH_HDRLEN(tcphdr);
pbuf_header(p, -(offset * 4)); pbuf_header(p, -(hdrlen * 4));
/* Convert fields in TCP header to host byte order. */ /* Convert fields in TCP header to host byte order. */
tcphdr->src = ntohs(tcphdr->src); 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 /* Demultiplex an incoming segment. First, we check if it is destined
for an active connection. */ for an active connection. */
prev = NULL; 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) { 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 != CLOSED", pcb->state != CLOSED);
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); 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->remote_ip), &(iphdr->src)) &&
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) { 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 /* Move this PCB to the front of the list so that subsequent
lookups will be faster (we exploit locality in TCP segment lookups will be faster (we exploit locality in TCP segment
arrivals). */ arrivals). */
@@ -323,33 +361,50 @@ tcp_input(struct pbuf *p, struct netif *inp)
tcp_debug_print_state(pcb->state); tcp_debug_print_state(pcb->state);
#endif /* TCP_DEBUG */ #endif /* TCP_DEBUG */
#endif /* TCP_INPUT_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 { } 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 /* If no matching PCB was found, send a TCP RST (reset) to the
sender. */ sender. */
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
#ifdef TCP_STATS TCP_STATS_INC(tcp.proterr);
++lwip_stats.tcp.proterr; TCP_STATS_INC(tcp.drop);
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
tcp_rst(ackno, seqno + tcplen, tcp_rst(ackno, seqno + tcplen,
&(iphdr->dest), &(iphdr->src), &(iphdr->dest), &(iphdr->src),
tcphdr->dest, tcphdr->src); tcphdr->dest, tcphdr->src);
} }
pbuf_free(p); pbuf_free(p);
} }
#ifdef SO_REUSE
end:
#endif /* SO_REUSE */
LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
PERF_STOP("tcp_input"); PERF_STOP("tcp_input");
} }
/*-----------------------------------------------------------------------------------*/
/* tcp_listen_input(): /* tcp_listen_input():
* *
* Called by tcp_input() when a segment arrives for a listening * Called by tcp_input() when a segment arrives for a listening
* connection. * connection.
*/ */
/*-----------------------------------------------------------------------------------*/
static err_t static err_t
tcp_listen_input(struct tcp_pcb_listen *pcb) tcp_listen_input(struct tcp_pcb_listen *pcb)
{ {
@@ -366,16 +421,14 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
&(iphdr->dest), &(iphdr->src), &(iphdr->dest), &(iphdr->src),
tcphdr->dest, tcphdr->src); tcphdr->dest, tcphdr->src);
} else if (flags & TCP_SYN) { } 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); npcb = tcp_alloc(pcb->prio);
/* If a new PCB could not be created (probably due to lack of memory), /* 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 we don't do anything, but rely on the sender will retransmit the
SYN at a time when we have more memory available. */ SYN at a time when we have more memory available. */
if (npcb == NULL) { if (npcb == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
#ifdef TCP_STATS TCP_STATS_INC(tcp.memerr);
++lwip_stats.tcp.memerr;
#endif /* TCP_STATS */
return ERR_MEM; return ERR_MEM;
} }
/* Set up the new PCB. */ /* Set up the new PCB. */
@@ -387,12 +440,13 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
npcb->rcv_nxt = seqno + 1; npcb->rcv_nxt = seqno + 1;
npcb->snd_wnd = tcphdr->wnd; npcb->snd_wnd = tcphdr->wnd;
npcb->ssthresh = npcb->snd_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; npcb->callback_arg = pcb->callback_arg;
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
npcb->accept = pcb->accept; npcb->accept = pcb->accept;
#endif /* LWIP_CALLBACK_API */ #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 /* Register the new PCB so that we can begin receiving segments
for it. */ for it. */
TCP_REG(&tcp_active_pcbs, npcb); TCP_REG(&tcp_active_pcbs, npcb);
@@ -411,13 +465,13 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
} }
return ERR_OK; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
/* tcp_timewait_input(): /* tcp_timewait_input():
* *
* Called by tcp_input() when a segment arrives for a connection in * Called by tcp_input() when a segment arrives for a connection in
* TIME_WAIT. * TIME_WAIT.
*/ */
/*-----------------------------------------------------------------------------------*/
static err_t static err_t
tcp_timewait_input(struct tcp_pcb *pcb) tcp_timewait_input(struct tcp_pcb *pcb)
{ {
@@ -429,7 +483,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
} }
return tcp_output(pcb); return tcp_output(pcb);
} }
/*-----------------------------------------------------------------------------------*/
/* tcp_process /* tcp_process
* *
* Implements the TCP state machine. Called by tcp_input. In some * 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 * argument will be freed by the caller (tcp_input()) unless the
* recv_data pointer in the pcb is set. * recv_data pointer in the pcb is set.
*/ */
/*-----------------------------------------------------------------------------------*/
static err_t static err_t
tcp_process(struct tcp_pcb *pcb) tcp_process(struct tcp_pcb *pcb)
{ {
@@ -479,17 +533,19 @@ tcp_process(struct tcp_pcb *pcb)
/* Update the PCB (in)activity timer. */ /* Update the PCB (in)activity timer. */
pcb->tmr = tcp_ticks; pcb->tmr = tcp_ticks;
pcb->keep_cnt = 0;
/* Do different things depending on the TCP state. */ /* Do different things depending on the TCP state. */
switch (pcb->state) { switch (pcb->state) {
case SYN_SENT: case SYN_SENT:
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %lu pcb->snd_nxt %lu unacked %lu\n", ackno, 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))); pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
if (flags & (TCP_ACK | TCP_SYN) && if ((flags & TCP_ACK) && (flags & TCP_SYN)
ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
pcb->rcv_nxt = seqno + 1; pcb->rcv_nxt = seqno + 1;
pcb->lastack = ackno; 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->state = ESTABLISHED;
pcb->cwnd = pcb->mss; pcb->cwnd = pcb->mss;
--pcb->snd_queuelen; --pcb->snd_queuelen;
@@ -502,7 +558,7 @@ tcp_process(struct tcp_pcb *pcb)
tcp_parseopt(pcb); tcp_parseopt(pcb);
/* Call the user specified function to call when sucessfully /* Call the user specified function to call when sucessfully
connected. */ * connected. */
TCP_EVENT_CONNECTED(pcb, ERR_OK, err); TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
tcp_ack(pcb); tcp_ack(pcb);
} }
@@ -511,22 +567,24 @@ tcp_process(struct tcp_pcb *pcb)
if (flags & TCP_ACK && if (flags & TCP_ACK &&
!(flags & TCP_RST)) { !(flags & TCP_RST)) {
if (TCP_SEQ_LT(pcb->lastack, ackno) && if (TCP_SEQ_LT(pcb->lastack, ackno) &&
TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) { TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) {
pcb->state = ESTABLISHED; pcb->state = ESTABLISHED;
LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection established %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest)); LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); #if LWIP_CALLBACK_API
/* Call the accept function. */ LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
TCP_EVENT_ACCEPT(pcb, ERR_OK, err); #endif
if (err != ERR_OK) { /* Call the accept function. */
/* If the accept function returns with an error, we abort TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
the connection. */ if (err != ERR_OK) {
tcp_abort(pcb); /* If the accept function returns with an error, we abort
return ERR_ABRT; * the connection. */
} tcp_abort(pcb);
/* If there was any data contained within this ACK, return ERR_ABRT;
we'd better pass it on to the application as well. */ }
tcp_receive(pcb); /* If there was any data contained within this ACK,
pcb->cwnd = pcb->mss; * we'd better pass it on to the application as well. */
tcp_receive(pcb);
pcb->cwnd = pcb->mss;
} }
} }
break; break;
@@ -543,7 +601,7 @@ tcp_process(struct tcp_pcb *pcb)
tcp_receive(pcb); tcp_receive(pcb);
if (flags & TCP_FIN) { if (flags & TCP_FIN) {
if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 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 connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
tcp_ack_now(pcb); tcp_ack_now(pcb);
tcp_pcb_purge(pcb); tcp_pcb_purge(pcb);
@@ -561,7 +619,7 @@ tcp_process(struct tcp_pcb *pcb)
case FIN_WAIT_2: case FIN_WAIT_2:
tcp_receive(pcb); tcp_receive(pcb);
if (flags & TCP_FIN) { 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_ack_now(pcb);
tcp_pcb_purge(pcb); tcp_pcb_purge(pcb);
TCP_RMV(&tcp_active_pcbs, pcb); TCP_RMV(&tcp_active_pcbs, pcb);
@@ -572,7 +630,7 @@ tcp_process(struct tcp_pcb *pcb)
case CLOSING: case CLOSING:
tcp_receive(pcb); tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 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_ack_now(pcb);
tcp_pcb_purge(pcb); tcp_pcb_purge(pcb);
TCP_RMV(&tcp_active_pcbs, pcb); TCP_RMV(&tcp_active_pcbs, pcb);
@@ -583,7 +641,7 @@ tcp_process(struct tcp_pcb *pcb)
case LAST_ACK: case LAST_ACK:
tcp_receive(pcb); tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 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; pcb->state = CLOSED;
recv_flags = TF_CLOSED; recv_flags = TF_CLOSED;
} }
@@ -594,7 +652,7 @@ tcp_process(struct tcp_pcb *pcb)
return ERR_OK; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
/* tcp_receive: /* tcp_receive:
* *
* Called by tcp_process. Checks if the given segment is an ACK for outstanding * 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 * If the incoming segment constitutes an ACK for a segment that was used for RTT
* estimation, the RTT is estimated here as well. * estimation, the RTT is estimated here as well.
*/ */
/*-----------------------------------------------------------------------------------*/
static void static void
tcp_receive(struct tcp_pcb *pcb) tcp_receive(struct tcp_pcb *pcb)
{ {
@@ -934,7 +992,7 @@ tcp_receive(struct tcp_pcb *pcb)
inseg.p = NULL; inseg.p = NULL;
} }
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { 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; 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 /* Chain this pbuf onto the pbuf that we will pass to
the application. */ the application. */
if (recv_data) { if (recv_data) {
pbuf_chain(recv_data, cseg->p); pbuf_cat(recv_data, cseg->p);
pbuf_free(cseg->p);
} else { } else {
recv_data = cseg->p; recv_data = cseg->p;
} }
cseg->p = NULL; cseg->p = NULL;
} }
if (flags & TCP_FIN) { if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.")); LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
recv_flags = TF_GOT_FIN; recv_flags = TF_GOT_FIN;
} }
@@ -1103,7 +1160,7 @@ tcp_receive(struct tcp_pcb *pcb)
} }
} }
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* tcp_parseopt: * tcp_parseopt:
* *
@@ -1111,7 +1168,7 @@ tcp_receive(struct tcp_pcb *pcb)
* from uIP with only small changes.) * from uIP with only small changes.)
* *
*/ */
/*-----------------------------------------------------------------------------------*/
static void static void
tcp_parseopt(struct tcp_pcb *pcb) tcp_parseopt(struct tcp_pcb *pcb)
{ {
@@ -1122,8 +1179,8 @@ tcp_parseopt(struct tcp_pcb *pcb)
opts = (u8_t *)tcphdr + TCP_HLEN; opts = (u8_t *)tcphdr + TCP_HLEN;
/* Parse the TCP MSS option, if present. */ /* Parse the TCP MSS option, if present. */
if ((TCPH_OFFSET(tcphdr) & 0xf0) > 0x50) { if(TCPH_HDRLEN(tcphdr) > 0x5) {
for(c = 0; c < ((TCPH_OFFSET(tcphdr) >> 4) - 5) << 2 ;) { for(c = 0; c < (TCPH_HDRLEN(tcphdr) - 5) << 2 ;) {
opt = opts[c]; opt = opts[c];
if (opt == 0x00) { if (opt == 0x00) {
/* End of options. */ /* End of options. */
@@ -1153,5 +1210,5 @@ tcp_parseopt(struct tcp_pcb *pcb)
} }
} }
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/

View File

@@ -4,7 +4,7 @@
* Transmission Control Protocol, outgoing traffic * 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -35,13 +35,13 @@
* *
*/ */
/*-----------------------------------------------------------------------------------*/
/* tcp_output.c /* tcp_output.c
* *
* The output functions of TCP. * The output functions of TCP.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#include "lwip/def.h" #include "lwip/def.h"
@@ -64,14 +64,14 @@
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb); static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
/*-----------------------------------------------------------------------------------*/
err_t err_t
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags) tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
{ {
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0); return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy) tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
{ {
@@ -90,7 +90,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
return ERR_CONN; return ERR_CONN;
} }
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len, tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
u8_t flags, u8_t copy, u8_t flags, u8_t copy,
@@ -133,7 +133,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
pcb->unsent != NULL); pcb->unsent != NULL);
} }
seg = NULL; seg = useg = NULL;
seglen = 0; seglen = 0;
/* First, break up the data into segments and tuck them together in /* First, break up the data into segments and tuck them together in
@@ -154,12 +154,13 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
seg->p = NULL; seg->p = NULL;
if (queue == NULL) { if (queue == NULL) {
queue = seg; useg = queue = seg;
} }
else { else {
/* Attach the segment to the end of the queued segments. */ /* 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->next = seg;
useg = seg;
} }
/* If copy is set, memory should be allocated /* If copy is set, memory should be allocated
@@ -210,9 +211,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
} }
++queuelen; ++queuelen;
/* Chain the headers and data pbufs together. */ /* Concatenate the headers and data pbufs together. */
pbuf_chain(seg->p, p); pbuf_cat(seg->p, p);
pbuf_free(p);
p = NULL; 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")); LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
#ifdef TCP_STATS TCP_STATS_INC(tcp.err);
++lwip_stats.tcp.err;
#endif /* TCP_STATS */
goto memerr; goto memerr;
} }
seg->tcphdr = seg->p->payload; 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. */ /* Copy the options into the header, if they are present. */
if (optdata == NULL) { if (optdata == NULL) {
TCPH_OFFSET_SET(seg->tcphdr, 5 << 4); TCPH_HDRLEN_SET(seg->tcphdr, 5);
} }
else { 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. /* Copy options into data portion of segment.
Options can thus only be sent in non data carrying Options can thus only be sent in non data carrying
segments such as SYN|ACK. */ 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) { useg->len + queue->len <= pcb->mss) {
/* Remove TCP header from first segment. */ /* Remove TCP header from first segment. */
pbuf_header(queue->p, -TCP_HLEN); pbuf_header(queue->p, -TCP_HLEN);
pbuf_chain(useg->p, queue->p); pbuf_cat(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);
useg->len += queue->len; useg->len += queue->len;
useg->next = queue->next; 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 /* Set the PSH flag in the last segment that we enqueued, but only
if the segment has data (indicated by seglen > 0). */ if the segment has data (indicated by seglen > 0). */
if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) { 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; return ERR_OK;
memerr: memerr:
#ifdef TCP_STATS TCP_STATS_INC(tcp.memerr);
++lwip_stats.tcp.memerr;
#endif /* TCP_STATS */
if (queue != NULL) { if (queue != NULL) {
tcp_segs_free(queue); 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)); LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
return ERR_MEM; return ERR_MEM;
} }
/*-----------------------------------------------------------------------------------*/
/* find out what we can send and send it */ /* find out what we can send and send it */
err_t err_t
tcp_output(struct tcp_pcb *pcb) tcp_output(struct tcp_pcb *pcb)
@@ -373,6 +365,13 @@ tcp_output(struct tcp_pcb *pcb)
seg = pcb->unsent; 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 /* 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 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 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); TCPH_FLAGS_SET(tcphdr, TCP_ACK);
tcphdr->wnd = htons(pcb->rcv_wnd); tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0; tcphdr->urgp = 0;
TCPH_OFFSET_SET(tcphdr, 5 << 4); TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0; tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip), tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
IP_PROTO_TCP, p->tot_len); IP_PROTO_TCP, p->tot_len);
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); IP_PROTO_TCP);
pbuf_free(p); pbuf_free(p);
@@ -443,7 +443,7 @@ tcp_output(struct tcp_pcb *pcb)
pcb->unsent = seg->next; pcb->unsent = seg->next;
if (pcb->state != SYN_SENT) { 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); pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
} }
@@ -457,11 +457,10 @@ tcp_output(struct tcp_pcb *pcb)
seg->next = NULL; seg->next = NULL;
if (pcb->unacked == NULL) { if (pcb->unacked == NULL) {
pcb->unacked = seg; pcb->unacked = seg;
useg = seg;
} else { } else {
for (useg = pcb->unacked; useg->next != NULL; useg = useg->next);
useg->next = seg; useg->next = seg;
useg = useg->next;
} }
} else { } else {
tcp_seg_free(seg); tcp_seg_free(seg);
@@ -470,7 +469,7 @@ tcp_output(struct tcp_pcb *pcb)
} }
return ERR_OK; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
static void static void
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
{ {
@@ -523,14 +522,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
&(pcb->local_ip), &(pcb->local_ip),
&(pcb->remote_ip), &(pcb->remote_ip),
IP_PROTO_TCP, seg->p->tot_len); IP_PROTO_TCP, seg->p->tot_len);
#ifdef TCP_STATS TCP_STATS_INC(tcp.xmit);
++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */
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); IP_PROTO_TCP);
} }
/*-----------------------------------------------------------------------------------*/
void void
tcp_rst(u32_t seqno, u32_t ackno, tcp_rst(u32_t seqno, u32_t ackno,
struct ip_addr *local_ip, struct ip_addr *remote_ip, 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); TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
tcphdr->wnd = htons(TCP_WND); tcphdr->wnd = htons(TCP_WND);
tcphdr->urgp = 0; tcphdr->urgp = 0;
TCPH_OFFSET_SET(tcphdr, 5 << 4); TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0; tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip, tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
IP_PROTO_TCP, p->tot_len); IP_PROTO_TCP, p->tot_len);
#ifdef TCP_STATS TCP_STATS_INC(tcp.xmit);
++lwip_stats.tcp.xmit; /* Send output with hardcoded TTL since we have no access to the pcb */
#endif /* TCP_STATS */ ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP);
pbuf_free(p); pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno)); LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
} }
/*-----------------------------------------------------------------------------------*/
void void
tcp_rexmit(struct tcp_pcb *pcb) tcp_rexmit(struct tcp_pcb *pcb)
{ {
@@ -595,6 +591,48 @@ tcp_rexmit(struct tcp_pcb *pcb)
tcp_output(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 */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -35,13 +35,13 @@
* *
*/ */
/*-----------------------------------------------------------------------------------*/
/* udp.c /* udp.c
* *
* The code for the User Datagram Protocol UDP. * The code for the User Datagram Protocol UDP.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h" #include "lwip/opt.h"
#include "lwip/def.h" #include "lwip/def.h"
@@ -64,87 +64,13 @@ struct udp_pcb *udp_pcbs = NULL;
static struct udp_pcb *pcb_cache = NULL; static struct udp_pcb *pcb_cache = NULL;
#if UDP_DEBUG
int udp_debug_print(struct udp_hdr *udphdr);
#endif /* UDP_DEBUG */
/*-----------------------------------------------------------------------------------*/
void void
udp_init(void) udp_init(void)
{ {
udp_pcbs = pcb_cache = NULL; udp_pcbs = pcb_cache = NULL;
} }
/*-----------------------------------------------------------------------------------*/
/* udp_lookup:
*
* An experimental feature that will be changed in future versions. Do
* not depend on it yet...
*/
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
u8_t
udp_lookup(struct ip_hdr *iphdr, struct netif *inp)
{
struct udp_pcb *pcb;
struct udp_hdr *udphdr;
u16_t src, dest;
PERF_START;
(void)inp;
udphdr = (struct udp_hdr *)(u8_t *)iphdr + IPH_HL(iphdr) * 4;
src = ntohs(udphdr->src);
dest = ntohs(udphdr->dest);
pcb = pcb_cache;
if (pcb != NULL &&
pcb->remote_port == src &&
pcb->local_port == dest &&
(ip_addr_isany(&pcb->remote_ip) ||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
return 1;
}
else {
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->remote_port == src &&
pcb->local_port == dest &&
(ip_addr_isany(&pcb->remote_ip) ||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
pcb_cache = pcb;
break;
}
}
if (pcb == NULL) {
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->remote_port == 0 &&
pcb->local_port == dest &&
(ip_addr_isany(&pcb->remote_ip) ||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
break;
}
}
}
}
PERF_STOP("udp_lookup");
if (pcb != NULL) {
return 1;
}
else {
return 1;
}
}
#endif /* LWIP_DEBUG */
/** /**
* Process an incoming UDP datagram. * Process an incoming UDP datagram.
* *
@@ -163,21 +89,24 @@ udp_input(struct pbuf *p, struct netif *inp)
struct ip_hdr *iphdr; struct ip_hdr *iphdr;
u16_t src, dest; 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; PERF_START;
#ifdef UDP_STATS UDP_STATS_INC(udp.recv);
++lwip_stats.udp.recv;
#endif /* UDP_STATS */
iphdr = p->payload; iphdr = p->payload;
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) { if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
/* drop short packets */ /* drop short packets */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len)); LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
#ifdef UDP_STATS UDP_STATS_INC(udp.lenerr);
++lwip_stats.udp.lenerr; UDP_STATS_INC(udp.drop);
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
snmp_inc_udpinerrors(); snmp_inc_udpinerrors();
pbuf_free(p); pbuf_free(p);
goto end; goto end;
@@ -190,9 +119,7 @@ udp_input(struct pbuf *p, struct netif *inp)
src = ntohs(udphdr->src); src = ntohs(udphdr->src);
dest = ntohs(udphdr->dest); dest = ntohs(udphdr->dest);
#if UDP_DEBUG
udp_debug_print(udphdr); udp_debug_print(udphdr);
#endif /* UDP_DEBUG */
/* print the UDP source and destination */ /* print the UDP source and destination */
LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n", LWIP_DEBUGF(UDP_DEBUG, ("udp (%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_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src), ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src))); ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
#ifdef SO_REUSE
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 */ /* Iterate through the UDP pcb list for a fully matching pcb */
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
/* print the PCB local and remote address */ /* print the PCB local and remote address */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n", LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip), 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) || (ip_addr_isany(&pcb->local_ip) ||
/* PCB local IP address matches UDP destination IP address? */ /* PCB local IP address matches UDP destination IP address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) { ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
#ifdef SO_REUSE
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; break;
} }
} }
@@ -228,7 +186,16 @@ udp_input(struct pbuf *p, struct netif *inp)
if (pcb == NULL) { if (pcb == NULL) {
/* Iterate through the UDP PCB list for a pcb that matches /* Iterate through the UDP PCB list for a pcb that matches
the local address. */ 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) { 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", 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_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port, ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
@@ -242,7 +209,28 @@ udp_input(struct pbuf *p, struct netif *inp)
(ip_addr_isany(&pcb->local_ip) || (ip_addr_isany(&pcb->local_ip) ||
/* ...matching interface address? */ /* ...matching interface address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) { 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), (struct ip_addr *)&(iphdr->dest),
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) { IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP Lite datagram discarded due to failing checksum\n")); LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
#ifdef UDP_STATS UDP_STATS_INC(udp.chkerr);
++lwip_stats.udp.chkerr; UDP_STATS_INC(udp.drop);
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
snmp_inc_udpinerrors(); snmp_inc_udpinerrors();
pbuf_free(p); pbuf_free(p);
goto end; goto end;
@@ -277,10 +263,8 @@ udp_input(struct pbuf *p, struct netif *inp)
IP_PROTO_UDP, p->tot_len) != 0) { IP_PROTO_UDP, p->tot_len) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n")); LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n"));
#ifdef UDP_STATS UDP_STATS_INC(udp.chkerr);
++lwip_stats.udp.chkerr; UDP_STATS_INC(udp.drop);
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
snmp_inc_udpinerrors(); snmp_inc_udpinerrors();
pbuf_free(p); pbuf_free(p);
goto end; goto end;
@@ -291,7 +275,33 @@ udp_input(struct pbuf *p, struct netif *inp)
if (pcb != NULL) { if (pcb != NULL) {
snmp_inc_udpindatagrams(); snmp_inc_udpindatagrams();
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src); 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 { } else {
#ifdef SO_REUSE
if(reuse) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
pbuf_free(p);
goto end;
}
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n")); LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
/* No match was found, send ICMP destination port unreachable unless /* No match was found, send ICMP destination port unreachable unless
@@ -304,10 +314,8 @@ udp_input(struct pbuf *p, struct netif *inp)
p->payload = iphdr; p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PORT); icmp_dest_unreach(p, ICMP_DUR_PORT);
} }
#ifdef UDP_STATS UDP_STATS_INC(udp.proterr);
++lwip_stats.udp.proterr; UDP_STATS_INC(udp.drop);
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
snmp_inc_udpnoports(); snmp_inc_udpnoports();
pbuf_free(p); pbuf_free(p);
} }
@@ -372,7 +380,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
q = p; q = p;
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
} }
/* { q now represents the packet to be sent */
udphdr = q->payload; udphdr = q->payload;
udphdr->src = htons(pcb->local_port); udphdr->src = htons(pcb->local_port);
udphdr->dest = htons(pcb->remote_port); udphdr->dest = htons(pcb->remote_port);
@@ -380,9 +388,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) { if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr)); LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr));
#ifdef UDP_STATS UDP_STATS_INC(udp.rterr);
++lwip_stats.udp.rterr;
#endif /* UDP_STATS */
return ERR_RTE; return ERR_RTE;
} }
/* using IP_ANY_ADDR? */ /* 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' */ /* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff; if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
/* output to IP */ /* 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(); snmp_inc_udpoutdatagrams();
} else { } else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len)); LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len));
@@ -422,18 +428,17 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
snmp_inc_udpoutdatagrams(); snmp_inc_udpoutdatagrams();
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n")); LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
/* output to IP */ /* output to IP */
err = ip_output_if (q, src_ip, &pcb->remote_ip, 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? */ /* did we chain a header earlier? */
if (q != p) { if (q != p) {
/* free the header */ /* free the header */
/* p is also still referenced by the caller, and will live on */
pbuf_free(q); pbuf_free(q);
} }
#ifdef UDP_STATS UDP_STATS_INC(udp.xmit);
++lwip_stats.udp.xmit;
#endif /* UDP_STATS */
return err; return err;
} }
@@ -457,7 +462,13 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{ {
struct udp_pcb *ipcb; struct udp_pcb *ipcb;
u8_t rebind; u8_t rebind;
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; rebind = 0;
/* Check for double bind and rebind of the same pcb */ /* Check for double bind and rebind of the same pcb */
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { 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 */ /* pcb already in list, just rebind */
rebind = 1; rebind = 1;
} }
#ifndef SO_REUSE
/* this code does not allow upper layer to share a UDP port for /* this code does not allow upper layer to share a UDP port for
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
combine with implementation of UDP PCB flags. Leon Woestenberg. */ combine with implementation of UDP PCB flags. Leon Woestenberg. */
#if 0 #ifdef LWIP_UDP_TODO
/* port matches that of PCB in list? */ /* port matches that of PCB in list? */
else if ((ipcb->local_port == port) && else if ((ipcb->local_port == port) &&
/* IP address matches, or one is IP_ADDR_ANY? */ /* 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; return ERR_USE;
} }
#endif #endif
#else /* SO_REUSE */
/* Search through list of PCB's.
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
But no two PCB's bound to same local port and same local address is valid.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
else if (ipcb->local_port == port) {
if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
}
}
#endif /* SO_REUSE */
} }
/* 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); ip_addr_set(&pcb->local_ip, ipaddr);
/* no port specified? */ /* no port specified? */
if (port == 0) { 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->remote_port = port;
pcb->flags |= UDP_FLAGS_CONNECTED; pcb->flags |= UDP_FLAGS_CONNECTED;
/** TODO: this functionality belongs in upper layers */ /** TODO: this functionality belongs in upper layers */
#if 0 #ifdef LWIP_UDP_TODO
/* Nail down local IP for netconn_addr()/getsockname() */ /* Nail down local IP for netconn_addr()/getsockname() */
if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) { if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
struct netif *netif; struct netif *netif;
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) { if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr)); LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
#ifdef UDP_STATS UDP_STATS_INC(udp.rterr);
++lwip_stats.udp.rterr;
#endif /* UDP_STATS */
return ERR_RTE; return ERR_RTE;
} }
/** TODO: this will bind the udp pcb locally, to the interface which /** 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; pcb->flags &= ~UDP_FLAGS_CONNECTED;
} }
/*-----------------------------------------------------------------------------------*/
void void
udp_recv(struct udp_pcb *pcb, udp_recv(struct udp_pcb *pcb,
void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
@@ -647,10 +702,13 @@ udp_new(void) {
if (pcb != NULL) { if (pcb != NULL) {
/* initialize PCB to all zeroes */ /* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct udp_pcb)); memset(pcb, 0, sizeof(struct udp_pcb));
pcb->ttl = UDP_TTL;
} }
return pcb; return pcb;
} }
/*-----------------------------------------------------------------------------------*/
#if UDP_DEBUG #if UDP_DEBUG
int int
udp_debug_print(struct udp_hdr *udphdr) udp_debug_print(struct udp_hdr *udphdr)
@@ -666,7 +724,7 @@ udp_debug_print(struct udp_hdr *udphdr)
return 0; return 0;
} }
#endif /* UDP_DEBUG */ #endif /* UDP_DEBUG */
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_UDP */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -67,6 +67,13 @@ u8_t *inet_ntoa(u32_t addr); /* returns ptr to static buffer; not reentrant! */
#define htonl(x) (x) #define htonl(x) (x)
#define ntohl(x) (x) #define ntohl(x) (x)
#else #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 htons(u16_t x);
u16_t ntohs(u16_t x); u16_t ntohs(u16_t x);
u32_t htonl(u32_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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -43,13 +43,12 @@
struct netif; struct netif;
void ip_init(void); void ip_init(void);
u8_t ip_lookup(void *header, struct netif *inp);
struct netif *ip_route(struct ip_addr *dest); struct netif *ip_route(struct ip_addr *dest);
err_t ip_input(struct pbuf *p, struct netif *inp); err_t ip_input(struct pbuf *p, struct netif *inp);
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
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, 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); struct netif *netif);
#define IP_HLEN 20 #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 */ #endif /* IP_HDRINCL */
#define IP_HDRINCL NULL #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 #ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h" # include "arch/bpstruct.h"
#endif #endif
@@ -117,6 +146,8 @@ PACK_STRUCT_END
#if IP_DEBUG #if IP_DEBUG
void ip_debug_print(struct pbuf *p); void ip_debug_print(struct pbuf *p);
#else
#define ip_debug_print(p)
#endif /* IP_DEBUG */ #endif /* IP_DEBUG */
#endif /* __LWIP_IP_H__ */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -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_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))
#define ip_addr_debug_print(ipaddr) LWIP_DEBUGF(LWIP_DEBUG, ("%d.%d.%d.%d", \ #define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%u.%u.%u.%u", \
(unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff, \ ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \
(unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff, \ ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \
(unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff, \ ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \
(unsigned int)ntohl((ipaddr)->addr) & 0xff)) ipaddr?(unsigned int)ntohl((ipaddr)->addr) & 0xff:0U))
/* cast to unsigned int, as it is used as argument to printf functions /* cast to unsigned int, as it is used as argument to printf functions
* which expect integer arguments */ * which expect integer arguments */

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -38,6 +38,7 @@
#include "lwip/ip.h" #include "lwip/ip.h"
#include "lwip/raw.h"
#include "lwip/udp.h" #include "lwip/udp.h"
#include "lwip/tcp.h" #include "lwip/tcp.h"
@@ -50,7 +51,8 @@ enum netconn_type {
NETCONN_TCP, NETCONN_TCP,
NETCONN_UDP, NETCONN_UDP,
NETCONN_UDPLITE, NETCONN_UDPLITE,
NETCONN_UDPNOCHKSUM NETCONN_UDPNOCHKSUM,
NETCONN_RAW
}; };
enum netconn_state { enum netconn_state {
@@ -82,6 +84,7 @@ struct netconn {
union { union {
struct tcp_pcb *tcp; struct tcp_pcb *tcp;
struct udp_pcb *udp; struct udp_pcb *udp;
struct raw_pcb *raw;
} pcb; } pcb;
err_t err; err_t err;
sys_mbox_t mbox; sys_mbox_t mbox;
@@ -121,6 +124,9 @@ struct netconn * netconn_new (enum netconn_type type);
struct struct
netconn *netconn_new_with_callback(enum netconn_type t, netconn *netconn_new_with_callback(enum netconn_type t,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len)); 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); err_t netconn_delete (struct netconn *conn);
enum netconn_type netconn_type (struct netconn *conn); enum netconn_type netconn_type (struct netconn *conn);
err_t netconn_peer (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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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

View File

@@ -1,6 +1,38 @@
/** @file /** @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__ #ifndef __LWIP_DHCP_H__
#define __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_MESSAGE_TYPE_LEN 1
#define DHCP_OPTION_SERVER_ID 54 /* RFC 2131 9.7, server IP address */ #define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */
#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2131 9.8, requested option types */ #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_MAX_MSG_SIZE_LEN 2
#define DHCP_OPTION_T1 58 /* T1 renewal time */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -49,9 +49,13 @@ void mem_free(void *mem);
void *mem_realloc(void *mem, mem_size_t size); void *mem_realloc(void *mem, mem_size_t size);
void *mem_reallocm(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)) #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))) #define MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))
#endif
#endif /* __LWIP_MEM_H__ */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -37,6 +37,7 @@
typedef enum { typedef enum {
MEMP_PBUF, MEMP_PBUF,
MEMP_RAW_PCB,
MEMP_UDP_PCB, MEMP_UDP_PCB,
MEMP_TCP_PCB, MEMP_TCP_PCB,
MEMP_TCP_PCB_LISTEN, 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_realloc(memp_t fromtype, memp_t totype, void *mem);
void memp_free(memp_t type, 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__ */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -115,7 +115,7 @@ extern struct netif *netif_default;
/* netif_init() must be called first. */ /* netif_init() must be called first. */
void netif_init(void); 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, struct ip_addr *gw,
void *state, void *state,
err_t (* init)(struct netif *netif), 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -32,9 +32,9 @@
#ifndef __LWIP_OPT_H__ #ifndef __LWIP_OPT_H__
#define __LWIP_OPT_H__ #define __LWIP_OPT_H__
#include "lwip/debug.h"
/* Include user defined options first */ /* Include user defined options first */
#include "lwipopts.h" #include "lwipopts.h"
#include "lwip/debug.h"
/* Define default values for unconfigured parameters. */ /* 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 #define MEMP_NUM_PBUF 16
#endif #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 /* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */ per active UDP "connection". */
#ifndef MEMP_NUM_UDP_PCB #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 #define ICMP_TTL 255
#endif #endif
/* ---------- RAW options ---------- */
#ifndef RAW_TTL
#define RAW_TTL 255
#endif
/* ---------- DHCP options ---------- */ /* ---------- DHCP options ---------- */
#ifndef LWIP_DHCP #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 #define TCP_SNDLOWAT TCP_SND_BUF/2
#endif #endif
/* Support loop interface (127.0.0.1) */
#ifndef LWIP_HAVE_LOOPIF
#define LWIP_HAVE_LOOPIF 1
#endif
#ifndef LWIP_EVENT_API #ifndef LWIP_EVENT_API
#define LWIP_EVENT_API 0 #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 #define DEFAULT_THREAD_PRIO 1
#endif #endif
/* ---------- Socket Options ---------- */
/* Enable SO_REUSEADDR and SO_REUSEPORT options */
#ifndef SO_REUSE
# define SO_REUSE 1
#endif
/* ---------- Statistics options ---------- */ /* ---------- Statistics options ---------- */
#ifndef LWIP_STATS #ifndef LWIP_STATS
#define LWIP_STATS 1 #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 #if LWIP_STATS
#define LINK_STATS #ifndef LINK_STATS
#define IP_STATS #define LINK_STATS 1
#define ICMP_STATS #endif
#define UDP_STATS
#define TCP_STATS #ifndef IP_STATS
#define MEM_STATS #define IP_STATS 1
#define MEMP_STATS #endif
#define PBUF_STATS
#define SYS_STATS #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 */ #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 #define DBG_TYPES_ON 0
#endif #endif
#ifndef DEMO_DEBUG
#define DEMO_DEBUG DBG_OFF
#endif
#ifndef ETHARP_DEBUG #ifndef ETHARP_DEBUG
#define ETHARP_DEBUG DBG_OFF #define ETHARP_DEBUG DBG_OFF
#endif #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 #define IP_REASS_DEBUG DBG_OFF
#endif #endif
#ifndef RAW_DEBUG
#define RAW_DEBUG DBG_OFF
#endif
#ifndef MEM_DEBUG #ifndef MEM_DEBUG
#define MEM_DEBUG DBG_OFF #define MEM_DEBUG DBG_OFF
#endif #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -29,7 +29,7 @@
* Author: Adam Dunkels <adam@sics.se> * Author: Adam Dunkels <adam@sics.se>
* *
*/ */
/*-----------------------------------------------------------------------------------*/
#ifndef __LWIP_PBUF_H__ #ifndef __LWIP_PBUF_H__
#define __LWIP_PBUF_H__ #define __LWIP_PBUF_H__
@@ -108,10 +108,9 @@ void pbuf_ref(struct pbuf *p);
void pbuf_ref_chain(struct pbuf *p); void pbuf_ref_chain(struct pbuf *p);
u8_t pbuf_free(struct pbuf *p); u8_t pbuf_free(struct pbuf *p);
u8_t pbuf_clen(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); void pbuf_chain(struct pbuf *h, struct pbuf *t);
struct pbuf *pbuf_take(struct pbuf *f); struct pbuf *pbuf_take(struct pbuf *f);
#if 0 /* see remark in code */
struct pbuf *pbuf_dechain(struct pbuf *p); struct pbuf *pbuf_dechain(struct pbuf *p);
#endif
#endif /* __LWIP_PBUF_H__ */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

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

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -70,6 +70,7 @@ struct sockaddr {
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ #define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */ #define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ #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) #define SO_DONTLINGER (int)(~SO_LINGER)
@@ -117,6 +118,36 @@ struct linger {
#define MSG_DONTWAIT 0x40 /* Nonblocking i/o for this operation only */ #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. * 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -101,9 +101,49 @@ extern struct stats_ lwip_stats;
void stats_init(void); void stats_init(void);
#define STATS_INC(x) ++lwip_stats.x
#else #else
#define stats_init() #define stats_init()
#define STATS_INC(x)
#endif /* LWIP_STATS */ #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__ */ #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -53,7 +53,7 @@ void tcp_init (void); /* Must be called first to
initialize TCP. */ initialize TCP. */
void tcp_tmr (void); /* Must be called every void tcp_tmr (void); /* Must be called every
TCP_TMR_INTERVAL TCP_TMR_INTERVAL
ms. (Typically 100 ms). */ ms. (Typically 250 ms). */
/* Application program's interface: */ /* Application program's interface: */
struct tcp_pcb * tcp_new (void); struct tcp_pcb * tcp_new (void);
struct tcp_pcb * tcp_alloc (u8_t prio); 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_GT(a,b) ((s32_t)((a)-(b)) > 0)
#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0) #define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
#define TCP_FIN 0x01 #define TCP_FIN 0x01U
#define TCP_SYN 0x02 #define TCP_SYN 0x02U
#define TCP_RST 0x04 #define TCP_RST 0x04U
#define TCP_PSH 0x08 #define TCP_PSH 0x08U
#define TCP_ACK 0x10 #define TCP_ACK 0x10U
#define TCP_URG 0x20 #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. */ /* Length of the TCP header, excluding options. */
#define TCP_HLEN 20 #define TCP_HLEN 20
#ifndef TCP_TMR_INTERVAL #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. */ milliseconds. */
#endif /* TCP_TMR_INTERVAL */ #endif /* TCP_TMR_INTERVAL */
#ifndef TCP_FAST_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 */ milliseconds */
#endif /* TCP_FAST_INTERVAL */ #endif /* TCP_FAST_INTERVAL */
#ifndef TCP_SLOW_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 */ milliseconds */
#endif /* TCP_SLOW_INTERVAL */ #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 */ #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 #ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h" # include "arch/bpstruct.h"
#endif #endif
@@ -158,7 +173,7 @@ struct tcp_hdr {
PACK_STRUCT_FIELD(u16_t dest); PACK_STRUCT_FIELD(u16_t dest);
PACK_STRUCT_FIELD(u32_t seqno); PACK_STRUCT_FIELD(u32_t seqno);
PACK_STRUCT_FIELD(u32_t ackno); 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 wnd);
PACK_STRUCT_FIELD(u16_t chksum); PACK_STRUCT_FIELD(u16_t chksum);
PACK_STRUCT_FIELD(u16_t urgp); PACK_STRUCT_FIELD(u16_t urgp);
@@ -168,11 +183,15 @@ PACK_STRUCT_END
# include "arch/epstruct.h" # include "arch/epstruct.h"
#endif #endif
#define TCPH_OFFSET(hdr) (ntohs((hdr)->_offset_flags) >> 8) #define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
#define TCPH_FLAGS(hdr) (ntohs((hdr)->_offset_flags) & 0xff) #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_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
#define TCPH_FLAGS_SET(hdr, flags) (hdr)->_offset_flags = htons((TCPH_OFFSET(hdr) << 8) | (flags)) #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 || \ #define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & TCP_FIN || \
TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0)) TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0))
@@ -194,17 +213,30 @@ enum tcp_state {
/* the TCP protocol control block */ /* the TCP protocol control block */
struct tcp_pcb { struct tcp_pcb {
/* Common members of all PCB types */
IP_PCB;
/* Protocol specific PCB members */
struct tcp_pcb *next; /* for the linked list */ struct tcp_pcb *next; /* for the linked list */
enum tcp_state state; /* TCP state */
u8_t prio; u8_t prio;
void *callback_arg; void *callback_arg;
struct ip_addr local_ip;
u16_t local_port; u16_t local_port;
enum tcp_state state; /* TCP state */
struct ip_addr remote_ip;
u16_t remote_port; 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 */ /* receiver varables */
u32_t rcv_nxt; /* next seqno expected */ u32_t rcv_nxt; /* next seqno expected */
u16_t rcv_wnd; /* receiver window */ u16_t rcv_wnd; /* receiver window */
@@ -217,14 +249,6 @@ struct tcp_pcb {
u16_t rtime; u16_t rtime;
u16_t mss; /* maximum segment size */ 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. */ /* RTT estimation variables. */
u16_t rttest; /* RTT estimate in 500ms ticks */ u16_t rttest; /* RTT estimate in 500ms ticks */
@@ -282,21 +306,32 @@ struct tcp_pcb {
/* Function to be called whenever a fatal error occurs. */ /* Function to be called whenever a fatal error occurs. */
void (* errf)(void *arg, err_t err); void (* errf)(void *arg, err_t err);
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
/* idle time before KEEPALIVE is sent */
u32_t keepalive;
/* KEEPALIVE counter */
u8_t keep_cnt;
}; };
struct tcp_pcb_listen { 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 */ 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 /* Even if state is obviously LISTEN this is here for
* field compatibility with tpc_pcb to which it is cast sometimes * field compatibility with tpc_pcb to which it is cast sometimes
* Until a cleaner solution emerges this is here.FIXME * Until a cleaner solution emerges this is here.FIXME
*/ */
enum tcp_state state; /* TCP state */ enum tcp_state state; /* TCP state */
u8_t prio;
void *callback_arg;
u16_t local_port;
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
/* Function to call when a listener has been connected. */ /* Function to call when a listener has been connected. */
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err); 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); u32_t tcp_next_iss(void);
void tcp_keepalive(struct tcp_pcb *pcb);
extern struct tcp_pcb *tcp_input_pcb; extern struct tcp_pcb *tcp_input_pcb;
extern u32_t tcp_ticks; extern u32_t tcp_ticks;
@@ -406,7 +443,11 @@ void tcp_debug_print_state(enum tcp_state s);
void tcp_debug_print_pcbs(void); void tcp_debug_print_pcbs(void);
int tcp_pcbs_sane(void); int tcp_pcbs_sane(void);
#else #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 */ #endif /* TCP_DEBUG */
#if NO_SYS #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@@ -4,12 +4,14 @@
* *
* Functionally, ARP is divided into two parts. The first maps an IP address * 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 * 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -40,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: * TODO:
* *
@@ -111,6 +120,9 @@ struct etharp_entry {
struct eth_addr ethaddr; struct eth_addr ethaddr;
enum etharp_state state; enum etharp_state state;
#if ARP_QUEUEING #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; struct pbuf *p;
#endif #endif
u8_t ctime; u8_t ctime;
@@ -119,22 +131,27 @@ struct etharp_entry {
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
static struct etharp_entry arp_table[ARP_TABLE_SIZE]; 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 #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. * Initializes ARP module.
*/ */
void void
etharp_init(void) etharp_init(void)
{ {
u8_t i; s8_t i;
/* clear ARP entries */ /* clear ARP entries */
for(i = 0; i < ARP_TABLE_SIZE; ++i) { for(i = 0; i < ARP_TABLE_SIZE; ++i) {
arp_table[i].state = ETHARP_STATE_EMPTY; arp_table[i].state = ETHARP_STATE_EMPTY;
#if ARP_QUEUEING #if ARP_QUEUEING
arp_table[i].p = NULL; arp_table[i].p = NULL;
#endif #endif
arp_table[i].ctime = 0;
} }
} }
@@ -147,32 +164,31 @@ etharp_init(void)
void void
etharp_tmr(void) etharp_tmr(void)
{ {
u8_t i; s8_t i;
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
/* remove expired entries from the ARP table */ /* remove expired entries from the ARP table */
for (i = 0; i < ARP_TABLE_SIZE; ++i) { for (i = 0; i < ARP_TABLE_SIZE; ++i) {
arp_table[i].ctime++; arp_table[i].ctime++;
/* a resolved/stable entry? */
if ((arp_table[i].state == ETHARP_STATE_STABLE) && if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
/* entry has become old? */
(arp_table[i].ctime >= ARP_MAXAGE)) { (arp_table[i].ctime >= ARP_MAXAGE)) {
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i)); LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
arp_table[i].state = ETHARP_STATE_EMPTY; goto empty;
#if ARP_QUEUEING /* an unresolved/pending entry? */
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
} else if ((arp_table[i].state == ETHARP_STATE_PENDING) && } else if ((arp_table[i].state == ETHARP_STATE_PENDING) &&
/* entry unresolved/pending for too long? */
(arp_table[i].ctime >= ARP_MAXPENDING)) { (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)); 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 #if ARP_QUEUEING
/* and empty packet queue */
if (arp_table[i].p != NULL) { if (arp_table[i].p != NULL) {
/* remove any queued packet */ /* 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); pbuf_free(arp_table[i].p);
arp_table[i].p = NULL; 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 * Return an empty ARP entry (possibly recycling the oldest stable entry).
* entries are pending, otherwise the oldest 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. * entry is found.
*/ */
static u8_t static s8_t
find_arp_entry(void) 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) { for (i = 0; i < ARP_TABLE_SIZE; ++i) {
/* empty entry? */
if (arp_table[i].state == ETHARP_STATE_EMPTY) { if (arp_table[i].state == ETHARP_STATE_EMPTY) {
LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found empty entry %u\n", i)); LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning empty entry %u\n", i));
break; 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 /* clean up the recycled stable entry */
throw it away. If all entries are new and have 0 ctime drop one */ if (arp_table[i].state == ETHARP_STATE_STABLE) {
if (i == ARP_TABLE_SIZE) { #if ARP_QUEUEING
maxtime = 0; /* free packets on queue */
j = ARP_TABLE_SIZE; etharp_dequeue(i);
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) &&
#endif #endif
(arp_table[i].ctime >= maxtime)) { LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_arp_entry: recycling oldest stable entry %u\n", i));
maxtime = arp_table[i].ctime; arp_table[i].state = ETHARP_STATE_EMPTY;
j = i; arp_table[i].ctime = 0;
}
}
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, ("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; 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. * 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 ipaddr IP address of the inserted ARP entry.
* @param ethaddr Ethernet address of the inserted ARP entry. * @param ethaddr Ethernet address of the inserted ARP entry.
* @param flags Defines behaviour: * @param flags Defines behaviour:
@@ -245,7 +331,7 @@ find_arp_entry(void)
static struct pbuf * static struct pbuf *
update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags) 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_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n"));
LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0); 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), 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; arp_table[i].state = ETHARP_STATE_STABLE;
/* fall-through to next if */ /* 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_table[i].state == ETHARP_STATE_STABLE) {
#if ARP_QUEUEING #if ARP_QUEUEING
struct pbuf *p; struct pbuf *p;
@@ -282,29 +368,50 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
} }
/* reset time stamp */ /* reset time stamp */
arp_table[i].ctime = 0; arp_table[i].ctime = 0;
/* this is where we will send out queued packets! */
#if ARP_QUEUEING #if ARP_QUEUEING
/* get the first packet on the queue (if any) */
p = arp_table[i].p; p = arp_table[i].p;
/* queued packet present? */ /* (another) queued packet present? */
if (p != NULL) { while (p != NULL) {
/* NULL attached buffer immediately */ struct pbuf *q, *n;
arp_table[i].p = NULL; /* 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 */ /* fill-in Ethernet header */
ethhdr = p->payload; ethhdr = p->payload;
for (k = 0; k < netif->hwaddr_len; ++k) { for (k = 0; k < netif->hwaddr_len; ++k) {
ethhdr->dest.addr[k] = ethaddr->addr[k]; ethhdr->dest.addr[k] = ethaddr->addr[k];
ethhdr->src.addr[k] = netif->hwaddr[k];
} }
ethhdr->type = htons(ETHTYPE_IP); 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 */ /* send the queued IP packet */
netif->linkoutput(netif, p); netif->linkoutput(netif, p);
/* free the queued IP packet */ /* free the queued IP packet */
pbuf_free(p); pbuf_free(p);
/* proceed to next packet on queue */
p = n;
} }
/* NULL attached buffer*/
arp_table[i].p = NULL;
#endif #endif
/* IP addresses should only occur once in the ARP entry, we are done */
return NULL; return NULL;
} }
} /* if */ } /* if STABLE */
} /* for */ } /* for all ARP entries */
/* no matching ARP entry was found */ /* no matching ARP entry was found */
LWIP_ASSERT("update_arp_entry: i == ARP_TABLE_SIZE", i == ARP_TABLE_SIZE); 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")); LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: adding entry to table\n"));
/* find an empty or old entry. */ /* find an empty or old entry. */
i = find_arp_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")); LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no available entry found\n"));
return NULL; 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 */ /* set IP address */
ip_addr_set(&arp_table[i].ipaddr, ipaddr); ip_addr_set(&arp_table[i].ipaddr, ipaddr);
/* set Ethernet hardware address */ /* 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 * Uses the incoming IP packet's source address to update the
* ARP cache for the local network. The function does not alter * 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() * @see pbuf_free()
*/ */
struct pbuf * void
etharp_ip_input(struct netif *netif, struct pbuf *p) etharp_ip_input(struct netif *netif, struct pbuf *p)
{ {
struct ethip_hdr *hdr; struct ethip_hdr *hdr;
@@ -379,18 +475,19 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
/* source is on local network? */ /* source is on local network? */
if (!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) { if (!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
/* do nothing */ /* do nothing */
return NULL; return;
} }
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
/* update ARP table, ask to insert entry */ /* update ARP table, ask to insert entry */
update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG); 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 * Should be called for incoming ARP packets. The pbuf in the argument
* is freed by this function. * is freed by this function.
@@ -403,20 +500,31 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
* *
* @see pbuf_free() * @see pbuf_free()
*/ */
struct pbuf * void
etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
{ {
struct etharp_hdr *hdr; struct etharp_hdr *hdr;
u8_t i; u8_t i;
u8_t for_us;
/* drop short ARP packets */ /* drop short ARP packets */
if (p->tot_len < sizeof(struct etharp_hdr)) { 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); pbuf_free(p);
return NULL; return;
} }
hdr = p->payload; 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)) { switch (htons(hdr->opcode)) {
/* ARP request? */ /* 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) { if (netif->ip_addr.addr == 0) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
pbuf_free(p); pbuf_free(p);
return NULL; return;
} }
/* update the ARP cache */
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
/* ARP request for our address? */ /* 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")); 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 */ /* 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->dipaddr), &(hdr->sipaddr));
ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); 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->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
hdr->shwaddr.addr[i] = ethaddr->addr[i]; hdr->shwaddr.addr[i] = ethaddr->addr[i];
hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.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); hdr->hwtype = htons(HWTYPE_ETHERNET);
ARPH_HWLEN_SET(hdr, netif->hwaddr_len); 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)); ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
hdr->ethhdr.type = htons(ETHTYPE_ARP); hdr->ethhdr.type = htons(ETHTYPE_ARP);
/* return ARP reply */ /* return ARP reply */
netif->linkoutput(netif, p); netif->linkoutput(netif, p);
/* request was not directed to us */
} else { } else {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n")); LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n"));
} }
break; break;
case ARP_REPLY: 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")); LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
/* DHCP needs to know about ARP replies */ /* DHCP wants to know about ARP replies to our wanna-have-address */
dhcp_arp_reply(netif, &hdr->sipaddr); if (for_us) dhcp_arp_reply(netif, &hdr->sipaddr);
#endif #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; break;
default: default:
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode))); LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode)));
break; 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 */ /* free ARP packet */
pbuf_free(p); pbuf_free(p);
p = NULL; 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. * returned, ready to be sent.
* *
* If ARP does not have the Ethernet address in cache the packet is * 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 * queued (if enabled and space available) and a ARP request is sent.
* ARP request is returned as a pbuf, which should be sent by the * This ARP request is returned as a pbuf, which should be sent by
* caller. * the caller.
*
* If ARP failed to allocate resources, NULL is returned.
* *
* A returned non-NULL packet 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 netif The lwIP network interface which the IP packet will be sent on.
* @param ipaddr The IP address of the packet destination. * @param ipaddr The IP address of the packet destination.
* @param pbuf The pbuf(s) containing the IP packet to be sent. * @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 * struct pbuf *
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
{ {
struct eth_addr *dest, *srcaddr, mcastaddr; struct eth_addr *dest, *srcaddr, mcastaddr;
struct eth_hdr *ethhdr; 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) { if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
/* The pbuf_header() call shouldn't fail, and we'll just bail /* The pbuf_header() call shouldn't fail, and we'll just bail
out if it does.. */ out if it does.. */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n")); LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
#ifdef LINK_STATS LINK_STATS_INC(link.lenerr);
++lwip_stats.link.lenerr;
#endif /* LINK_STATS */
return NULL; return NULL;
} }
/* obtain source Ethernet address of the given interface */
srcaddr = (struct eth_addr *)netif->hwaddr;
/* assume unresolved Ethernet address */ /* assume unresolved Ethernet address */
dest = NULL; dest = NULL;
/* Construct Ethernet header. Start with looking up deciding which /* Construct Ethernet header. Start with looking up deciding which
MAC address to use as a destination address. Broadcasts and MAC address to use as a destination address. Broadcasts and
multicasts are special, all other addresses are looked up in the multicasts are special, all other addresses are looked up in the
ARP table. */ ARP table. */
/* destination IP address is an IP broadcast address? */ /* destination IP address is an IP broadcast address? */
if (ip_addr_isany(ipaddr) || 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)) { else if (ip_addr_ismulticast(ipaddr)) {
/* Hash IP multicast address to MAC address. */ /* Hash IP multicast address to MAC address. */
mcastaddr.addr[0] = 0x01; mcastaddr.addr[0] = 0x01;
mcastaddr.addr[1] = 0x0; mcastaddr.addr[1] = 0x00;
mcastaddr.addr[2] = 0x5e; mcastaddr.addr[2] = 0x5e;
mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
mcastaddr.addr[4] = ip4_addr3(ipaddr); 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 */ /* destination IP address is an IP unicast address */
else { else {
/* destination IP network address not on local network? */ /* destination IP network address not on local network?
/* this occurs if the packet is routed to the default gateway on this interface */ * IP layer wants us to forward to the default gateway */
if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
/* gateway available? */ /* interface has default gateway? */
if (netif->gw.addr != 0) if (netif->gw.addr != 0)
{ {
/* use the gateway IP address */ /* route to default gateway IP address */
ipaddr = &(netif->gw); ipaddr = &(netif->gw);
} }
/* no gateway available? */ /* no gateway available? */
else else
{ {
/* IP destination address outside local network, but no gateway available */ /* IP destination address outside local network, but no gateway available */
/* { packet is discarded } */
return NULL; return NULL;
} }
} }
/* Ethernet address for IP destination address is in ARP cache? */ /* 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? */ /* match found? */
if (arp_table[i].state == ETHARP_STATE_STABLE && if (arp_table[i].state == ETHARP_STATE_STABLE &&
ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { 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? */ /* could not find the destination Ethernet address in ARP cache? */
if (dest == NULL) { if (dest == NULL) {
/* ARP query for the IP address, submit this IP packet for queueing */ /* 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); etharp_query(netif, ipaddr, q);
/* { packet was queued (ERR_OK), or discarded } */
/* return nothing */ /* return nothing */
return NULL; return NULL;
} }
@@ -607,8 +711,11 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
/* destination Ethernet address known */ /* destination Ethernet address known */
if (dest != NULL) { if (dest != NULL) {
/* A valid IP->MAC address mapping was found, so we construct the /* obtain source Ethernet address of the given interface */
Ethernet header for the outgoing packet. */ 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; ethhdr = q->payload;
for(i = 0; i < netif->hwaddr_len; i++) { 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 eth_addr *srcaddr;
struct etharp_hdr *hdr; struct etharp_hdr *hdr;
struct pbuf *p;
err_t result = ERR_OK; err_t result = ERR_OK;
u8_t i; s8_t i;
u8_t perform_arp_request = 1; u8_t perform_arp_request = 1;
/* prevent 'unused argument' warning if ARP_QUEUEING == 0 */ /* prevent 'unused argument' warning if ARP_QUEUEING == 0 */
(void)q; (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 (ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
if (arp_table[i].state == ETHARP_STATE_PENDING) { 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)); 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 */ /* 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 */ /* we might want to run a faster timer on ARP to limit this */
break; 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? */ /* queried address not yet in ARP table? */
if (i == ARP_TABLE_SIZE) { if (i == ARP_TABLE_SIZE) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: IP address not found in ARP table\n")); 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(); i = find_arp_entry();
/* bail out if no ARP entries are available */ /* bail out if no ARP entries are available */
if (i == ARP_TABLE_SIZE) { if (i == ERR_MEM) {
LWIP_DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available.\n")); LWIP_DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available. Should seldom occur.\n"));
return ERR_MEM; 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 */ /* 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; 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 #if ARP_QUEUEING
/* free queued packet, as entry is now invalidated */ etharp_enqueue(i, q);
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"));
}
#endif #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? */ /* ARP request? */
if (perform_arp_request) if (perform_arp_request)
{ {
struct pbuf *p;
/* allocate a pbuf for the outgoing ARP request packet */ /* allocate a pbuf for the outgoing ARP request packet */
p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM); p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
/* could allocate pbuf? */ /* 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")); LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n"));
hdr = p->payload; hdr = p->payload;
hdr->opcode = htons(ARP_REQUEST); 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]; 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->dipaddr), ipaddr);
ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); 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); hdr->proto = htons(ETHTYPE_IP);
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); 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.dest.addr[j] = 0xff;
hdr->ethhdr.src.addr[j] = srcaddr->addr[j]; 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -63,7 +63,7 @@ static void ethernetif_input(struct netif *netif);
static err_t ethernetif_output(struct netif *netif, struct pbuf *p, static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr); struct ip_addr *ipaddr);
/*-----------------------------------------------------------------------------------*/
static void static void
low_level_init(struct netif *netif) low_level_init(struct netif *netif)
{ {
@@ -87,7 +87,7 @@ low_level_init(struct netif *netif)
/* Do whatever else is needed to initialize interface. */ /* Do whatever else is needed to initialize interface. */
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* low_level_output(): * low_level_output():
* *
@@ -96,7 +96,7 @@ low_level_init(struct netif *netif)
* might be chained. * might be chained.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
static err_t static err_t
low_level_output(struct ethernetif *ethernetif, struct pbuf *p) 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; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* low_level_input(): * low_level_input():
* *
@@ -128,7 +128,7 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
* packet from the interface into the pbuf. * packet from the interface into the pbuf.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
static struct pbuf * static struct pbuf *
low_level_input(struct ethernetif *ethernetif) low_level_input(struct ethernetif *ethernetif)
{ {
@@ -165,7 +165,7 @@ low_level_input(struct ethernetif *ethernetif)
return p; return p;
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* ethernetif_output(): * ethernetif_output():
* *
@@ -174,7 +174,7 @@ low_level_input(struct ethernetif *ethernetif)
* do the actuall transmission of the packet. * do the actuall transmission of the packet.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
static err_t static err_t
ethernetif_output(struct netif *netif, struct pbuf *p, ethernetif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr) struct ip_addr *ipaddr)
@@ -264,7 +264,7 @@ ethernetif_output(struct netif *netif, struct pbuf *p,
return low_level_output(ethernetif, p); return low_level_output(ethernetif, p);
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* ethernetif_input(): * ethernetif_input():
* *
@@ -274,7 +274,7 @@ ethernetif_output(struct netif *netif, struct pbuf *p,
* interface. * interface.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
static void static void
ethernetif_input(struct netif *netif) ethernetif_input(struct netif *netif)
{ {
@@ -314,14 +314,14 @@ ethernetif_input(struct netif *netif)
} }
} }
} }
/*-----------------------------------------------------------------------------------*/
static void static void
arp_timer(void *arg) arp_timer(void *arg)
{ {
arp_tmr(); arp_tmr();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
} }
/*-----------------------------------------------------------------------------------*/
/* /*
* ethernetif_init(): * ethernetif_init():
* *
@@ -330,7 +330,7 @@ arp_timer(void *arg)
* actual setup of the hardware. * actual setup of the hardware.
* *
*/ */
/*-----------------------------------------------------------------------------------*/
void void
ethernetif_init(struct netif *netif) ethernetif_init(struct netif *netif)
{ {
@@ -350,4 +350,4 @@ ethernetif_init(struct netif *netif)
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@@ -29,9 +29,12 @@
* Author: Adam Dunkels <adam@sics.se> * Author: Adam Dunkels <adam@sics.se>
* *
*/ */
#include "lwip/mem.h"
#include "lwip/opt.h" #include "lwip/opt.h"
#if LWIP_HAVE_LOOPIF
#include "netif/loopif.h" #include "netif/loopif.h"
#include "lwip/mem.h"
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP) #if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
#include "netif/tcpdump.h" #include "netif/tcpdump.h"
@@ -40,13 +43,23 @@
#include "lwip/tcp.h" #include "lwip/tcp.h"
#include "lwip/ip.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 static err_t
loopif_output(struct netif *netif, struct pbuf *p, loopif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr) struct ip_addr *ipaddr)
{ {
struct pbuf *q, *r; struct pbuf *q, *r;
char *ptr; char *ptr;
void **arg;
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP) #if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
tcpdump(p); tcpdump(p);
@@ -60,21 +73,43 @@ loopif_output(struct netif *netif, struct pbuf *p,
memcpy(ptr, q->payload, q->len); memcpy(ptr, q->payload, q->len);
ptr += 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_OK;
} }
return ERR_MEM; return ERR_MEM;
} }
/*-----------------------------------------------------------------------------------*/
err_t err_t
loopif_init(struct netif *netif) loopif_init(struct netif *netif)
{ {
netif->name[0] = 'l'; netif->name[0] = 'l';
netif->name[1] = 'o'; 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; netif->output = loopif_output;
return ERR_OK; 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_pap_secret (void);
static int have_chap_secret (char *, char *, u32_t); static int have_chap_secret (char *, char *, u32_t);
static int ip_addr_check (u32_t, struct wordlist *); 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 set_allowed_addrs(int unit, struct wordlist *addrs);
static void free_wordlist (struct wordlist *); static void free_wordlist (struct wordlist *);
#endif #endif
@@ -194,7 +194,7 @@ void link_terminated(int unit)
if (logged_in) if (logged_in)
logout(); logout();
lcp_phase[unit] = PHASE_DEAD; lcp_phase[unit] = PHASE_DEAD;
ppp_trace(LOG_NOTICE, "Connection terminated.\n"); AUTHDEBUG((LOG_NOTICE, "Connection terminated.\n"));
pppMainWakeup(unit); pppMainWakeup(unit);
} }
@@ -257,7 +257,7 @@ void link_established(int unit)
* of "" and a password of "". If that's not OK, boot it out. * of "" and a password of "". If that's not OK, boot it out.
*/ */
if (!wo->neg_upap || !null_login(unit)) { 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"); lcp_close(unit, "peer refused to authenticate");
return; return;
} }
@@ -294,7 +294,7 @@ void link_established(int unit)
if (ppp_settings.passwd[0] == 0) { if (ppp_settings.passwd[0] == 0) {
passwd_from_file = 1; passwd_from_file = 1;
if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd)) 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); upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd);
auth |= PAP_WITHPEER; auth |= PAP_WITHPEER;
@@ -337,8 +337,8 @@ void auth_peer_success(int unit, u16_t protocol, char *name, int namelen)
pbit = PAP_PEER; pbit = PAP_PEER;
break; break;
default: default:
ppp_trace(LOG_WARNING, "auth_peer_success: unknown protocol %x\n", AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
protocol); protocol));
return; return;
} }
@@ -400,8 +400,8 @@ void auth_withpeer_success(int unit, u16_t protocol)
pbit = PAP_WITHPEER; pbit = PAP_WITHPEER;
break; break;
default: default:
ppp_trace(LOG_WARNING, "auth_peer_success: unknown protocol %x\n", AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
protocol); protocol));
pbit = 0; pbit = 0;
} }
@@ -476,7 +476,7 @@ void auth_reset(int unit)
AUTHDEBUG((LOG_INFO, "auth_reset: %d\n", 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_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()) if (go->neg_upap && !have_pap_secret())
go->neg_upap = 0; go->neg_upap = 0;
@@ -541,7 +541,7 @@ int check_passwd(
* On 10'th, drop the connection. * On 10'th, drop the connection.
*/ */
if (attempts++ >= 10) { 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");*/ /*ppp_panic("Excess Bad Logins");*/
} }
if (attempts > 3) { if (attempts > 3) {
@@ -605,7 +605,24 @@ int get_secret(
) )
{ {
#if 1 #if 1
int len;
struct wordlist *addrs;
addrs = NULL;
if(!client || !client[0] || strcmp(client, ppp_settings.user)) {
return 0; 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 #else
int ret = 0, len; int ret = 0, len;
struct wordlist *addrs; struct wordlist *addrs;
@@ -623,7 +640,7 @@ int get_secret(
len = strlen(secbuf); len = strlen(secbuf);
if (len > MAXSECRETLEN) { 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; len = MAXSECRETLEN;
} }
BCOPY(secbuf, secret, len); BCOPY(secbuf, secret, len);
@@ -736,7 +753,7 @@ static void check_idle(void *arg)
itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle);
if (itime >= ppp_settings.idle_time_limit) { if (itime >= ppp_settings.idle_time_limit) {
/* link is idle: shut it down. */ /* 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"); lcp_close(0, "Link inactive");
} else { } else {
TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime); TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime);
@@ -750,7 +767,7 @@ static void connect_time_expired(void *arg)
{ {
(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 */ 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. * 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; return 1;
} }
#if PAP_SUPPORT > 0 || CHAP_SUPPORT #if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT */
/* /*
* free_wordlist - release memory allocated for a wordlist. * 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) { if (cstate->chal_transmits >= cstate->max_transmits) {
/* give up on peer */ /* 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; cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, PPP_CHAP); auth_peer_fail(cstate->unit, PPP_CHAP);
return; return;
@@ -405,7 +405,7 @@ static void ChapInput(int unit, u_char *inpacket, int packet_len)
break; break;
default: /* Need code reject? */ 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; 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, if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
secret, &secret_len, 0)) { secret, &secret_len, 0)) {
secret_len = 0; /* assume null secret if can't find one */ 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 */ /* 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, if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
secret, &secret_len, 1)) { secret, &secret_len, 1)) {
/* CHAPDEBUG((LOG_WARNING, TL_CHAP, "No CHAP secret found for authenticating %s\n", rhostname)); */ /* 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", CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating %s\n",
rhostname); rhostname));
} else { } else {
/* generate MD based on negotiated type */ /* 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) if (cstate->chal_interval != 0)
TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval); TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
} else { } else {
ppp_trace(LOG_ERR, "CHAP peer authentication failed\n"); CHAPDEBUG((LOG_ERR, "CHAP peer authentication failed\n"));
cstate->serverstate = CHAPSS_BADAUTH; cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, PPP_CHAP); 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) if (len > 0)
PRINTMSG(inp, len); 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); auth_withpeer_fail(cstate->unit, PPP_CHAP);
} }

View File

@@ -29,7 +29,7 @@
* Ported to lwIP. * Ported to lwIP.
* 98-01-30 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. * 98-01-30 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
* Original built from BSD network code. * Original built from BSD network code.
****************************************************************************** ******************************************************************************/
/* /*
* chap.h - Challenge Handshake Authentication Protocol definitions. * chap.h - Challenge Handshake Authentication Protocol definitions.
* *
@@ -51,7 +51,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* *
* $Id: chpms.h,v 1.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 #ifndef CHPMS_H

View File

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

View File

@@ -216,7 +216,7 @@ static void upap_timeout(void *arg)
if (u->us_transmits >= u->us_maxtransmits) { if (u->us_transmits >= u->us_maxtransmits) {
/* give up in disgust */ /* 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; u->us_clientstate = UPAPCS_BADAUTH;
auth_withpeer_fail(u->us_unit, PPP_PAP); auth_withpeer_fail(u->us_unit, PPP_PAP);
return; return;
@@ -299,11 +299,11 @@ static void upap_protrej(int unit)
upap_state *u = &upap[unit]; upap_state *u = &upap[unit];
if (u->us_clientstate == UPAPCS_AUTHREQ) { 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); auth_withpeer_fail(unit, PPP_PAP);
} }
if (u->us_serverstate == UPAPSS_LISTEN) { 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); auth_peer_fail(unit, PPP_PAP);
} }
upap_lowerdown(unit); upap_lowerdown(unit);
@@ -518,7 +518,7 @@ static void upap_rauthnak(
u->us_clientstate = UPAPCS_BADAUTH; 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); auth_withpeer_fail(u->us_unit, PPP_PAP);
} }

View File

@@ -121,6 +121,7 @@ typedef enum {
PDDATA /* Process data byte. */ PDDATA /* Process data byte. */
} PPPDevStates; } PPPDevStates;
#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07])
/************************/ /************************/
/*** LOCAL DATA TYPES ***/ /*** LOCAL DATA TYPES ***/
@@ -141,7 +142,6 @@ typedef struct PPPControl_s {
char inEscaped; /* Escape next character. */ char inEscaped; /* Escape next character. */
u16_t inProtocol; /* The input protocol code. */ u16_t inProtocol; /* The input protocol code. */
u16_t inFCS; /* Input Frame Check Sequence value. */ u16_t inFCS; /* Input Frame Check Sequence value. */
u16_t inLen; /* Input packet length. */
int mtu; /* Peer's mru */ int mtu; /* Peer's mru */
int pcomp; /* Does peer accept protocol compression? */ int pcomp; /* Does peer accept protocol compression? */
int accomp; /* Does peer accept addr/ctl compression? */ int accomp; /* Does peer accept addr/ctl compression? */
@@ -153,12 +153,12 @@ typedef struct PPPControl_s {
struct vjcompress vjComp; /* Van Jabobsen compression header. */ struct vjcompress vjComp; /* Van Jabobsen compression header. */
#endif #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 (*linkStatusCB)(void *ctx, int errCode, void *arg);
void *linkStatusArg; void *linkStatusCtx;
} PPPControl; } PPPControl;
@@ -180,10 +180,6 @@ struct npioctl {
static void pppMain(void *pd); static void pppMain(void *pd);
static void pppDrop(PPPControl *pc); static void pppDrop(PPPControl *pc);
static void pppInProc(int pd, u_char *s, int l); 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)); memset(&ppp_settings, 0, sizeof(ppp_settings));
ppp_settings.usepeerdns = 1; ppp_settings.usepeerdns = 1;
ppp_settings.refuse_chap = (CHAP_SUPPORT == 0); pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL);
magicInit(); magicInit();
for (i = 0; i < NUM_PPP; i++) { for (i = 0; i < NUM_PPP; i++) {
pppControl[i].openFlag = 0; pppControl[i].openFlag = 0;
pppControl[i].netif = NULL;
subnetMask = htonl(0xffffff00); subnetMask = htonl(0xffffff00);
@@ -311,25 +306,69 @@ void pppInit(void)
(*protp->init)(i); (*protp->init)(i);
} }
#ifdef LINK_STATS #if LINK_STATS
/* Clear the statistics. */ /* Clear the statistics. */
memset(&lwip_stats.link, 0, sizeof(lwip_stats.link)); memset(&lwip_stats.link, 0, sizeof(lwip_stats.link));
#endif #endif
} }
void pppSetAuth(const char *user, const char *passwd) void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
{ {
if(user) { switch(authType) {
strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1); case PPPAUTHTYPE_NONE:
ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0'; default:
} else #ifdef LWIP_PPP_STRICT_PAP_REJECT
ppp_settings.user[0] = '\0'; 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) { if(user) {
strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1); strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0'; ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0';
} else } else
ppp_settings.passwd[0] = '\0'; 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. /* 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. * established before calling this.
* Return a new PPP connection descriptor on success or * Return a new PPP connection descriptor on success or
* an error code (negative) on failure. */ * 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; PPPControl *pc;
int pd; 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->outACCM[15] = 0x60;
pc->linkStatusCB = linkStatusCB; pc->linkStatusCB = linkStatusCB;
pc->linkStatusArg = linkStatusArg; pc->linkStatusCtx = linkStatusCtx;
sys_thread_new(pppMain, (void*)pd, PPP_THREAD_PRIO); sys_thread_new(pppMain, (void*)pd, PPP_THREAD_PRIO);
if(!linkStatusCB) { 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) { if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
PPPDEBUG((LOG_WARNING, PPPDEBUG((LOG_WARNING,
"PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c)); "PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c));
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.err++; lwip_stats.link.err++;
#endif /* LINK_STATS */ #endif /* LINK_STATS */
pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */ pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
@@ -451,22 +490,60 @@ static void nPut(PPPControl *pc, struct pbuf *nb)
} }
pbuf_free(nb); pbuf_free(nb);
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.xmit++; lwip_stats.link.xmit++;
#endif /* LINK_STATS */ #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. */ /* Send a packet on the given connection. */
static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr) static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
{ {
int pd = (int)netif->state; int pd = (int)netif->state;
u_short protocol = PPP_IP; u_short protocol = PPP_IP;
PPPControl *pc = &pppControl[pd]; PPPControl *pc = &pppControl[pd];
u_int fcsOut = PPP_INITFCS; u_int fcsOut = PPP_INITFCS;
struct pbuf *headMB = NULL, *tailMB = NULL, *p; struct pbuf *headMB = NULL, *tailMB = NULL, *p;
u_char c; u_char c;
(void)ipaddr; (void)ipaddr;
/* Validate parameters. */ /* Validate parameters. */
/* We let any protocol value go through - it can't hurt us /* 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) { if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n", PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n",
pd, protocol, pb)); pd, protocol, pb));
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.opterr++; lwip_stats.link.opterr++;
lwip_stats.link.drop++; lwip_stats.link.drop++;
#endif #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. */ /* Check that the link is up. */
if (lcp_phase[pd] == PHASE_DEAD) { if (lcp_phase[pd] == PHASE_DEAD) {
PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd)); PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd));
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.rterr++; lwip_stats.link.rterr++;
lwip_stats.link.drop++; lwip_stats.link.drop++;
#endif #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); headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) { if (headMB == NULL) {
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd)); PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd));
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.memerr++; lwip_stats.link.memerr++;
lwip_stats.link.drop++; lwip_stats.link.drop++;
#endif /* LINK_STATS */ #endif /* LINK_STATS */
@@ -522,7 +599,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
break; break;
default: default:
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd)); PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd));
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.proterr++; lwip_stats.link.proterr++;
lwip_stats.link.drop++; lwip_stats.link.drop++;
#endif #endif
@@ -536,22 +613,22 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
/* Build the PPP header. */ /* Build the PPP header. */
if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG)
tailMB = pppMPutRaw(PPP_FLAG, tailMB); tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
pc->lastXMit = sys_jiffies(); pc->lastXMit = sys_jiffies();
if (!pc->accomp) { if (!pc->accomp) {
fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS); 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); 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) { if (!pc->pcomp || protocol > 0xFF) {
c = (protocol >> 8) & 0xFF; c = (protocol >> 8) & 0xFF;
fcsOut = PPP_FCS(fcsOut, c); fcsOut = PPP_FCS(fcsOut, c);
tailMB = pppMPutC(c, &pc->outACCM, tailMB); tailMB = pppAppend(c, tailMB, &pc->outACCM);
} }
c = protocol & 0xFF; c = protocol & 0xFF;
fcsOut = PPP_FCS(fcsOut, c); fcsOut = PPP_FCS(fcsOut, c);
tailMB = pppMPutC(c, &pc->outACCM, tailMB); tailMB = pppAppend(c, tailMB, &pc->outACCM);
/* Load packet. */ /* Load packet. */
for(p = pb; p; p = p->next) { 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); fcsOut = PPP_FCS(fcsOut, c);
/* Copy to output buffer escaping special characters. */ /* Copy to output buffer escaping special characters. */
tailMB = pppMPutC(c, &pc->outACCM, tailMB); tailMB = pppAppend(c, tailMB, &pc->outACCM);
} }
} }
/* Add FCS and trailing flag. */ /* Add FCS and trailing flag. */
c = ~fcsOut & 0xFF; c = ~fcsOut & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB); tailMB = pppAppend(c, tailMB, &pc->outACCM);
c = (~fcsOut >> 8) & 0xFF; c = (~fcsOut >> 8) & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB); tailMB = pppAppend(c, tailMB, &pc->outACCM);
tailMB = pppMPutRaw(PPP_FLAG, tailMB); tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
/* If we failed to complete the packet, throw it away. */ /* If we failed to complete the packet, throw it away. */
if (!tailMB) { 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", "pppifOutput[%d]: Alloc err - dropping proto=%d\n",
pd, protocol)); pd, protocol));
pbuf_free(headMB); pbuf_free(headMB);
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.memerr++; lwip_stats.link.memerr++;
lwip_stats.link.drop++; lwip_stats.link.drop++;
#endif #endif
@@ -673,7 +750,7 @@ int pppWrite(int pd, const u_char *s, int n)
struct pbuf *headMB = NULL, *tailMB; struct pbuf *headMB = NULL, *tailMB;
headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) { if (headMB == NULL) {
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.memerr++; lwip_stats.link.memerr++;
lwip_stats.link.proterr++; lwip_stats.link.proterr++;
#endif /* LINK_STATS */ #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 /* If the link has been idle, we'll send a fresh flag character to
* flush any noise. */ * flush any noise. */
if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG)
tailMB = pppMPutRaw(PPP_FLAG, tailMB); tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
pc->lastXMit = sys_jiffies(); pc->lastXMit = sys_jiffies();
/* Load output buffer. */ /* Load output buffer. */
@@ -696,24 +773,24 @@ int pppWrite(int pd, const u_char *s, int n)
fcsOut = PPP_FCS(fcsOut, c); fcsOut = PPP_FCS(fcsOut, c);
/* Copy to output buffer escaping special characters. */ /* Copy to output buffer escaping special characters. */
tailMB = pppMPutC(c, &pc->outACCM, tailMB); tailMB = pppAppend(c, tailMB, &pc->outACCM);
} }
/* Add FCS and trailing flag. */ /* Add FCS and trailing flag. */
c = ~fcsOut & 0xFF; c = ~fcsOut & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB); tailMB = pppAppend(c, tailMB, &pc->outACCM);
c = (~fcsOut >> 8) & 0xFF; c = (~fcsOut >> 8) & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB); tailMB = pppAppend(c, tailMB, &pc->outACCM);
tailMB = pppMPutRaw(PPP_FLAG, tailMB); tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
/* If we failed to complete the packet, throw it away. /* If we failed to complete the packet, throw it away.
* Otherwise send it. */ * Otherwise send it. */
if (!tailMB) { if (!tailMB) {
PPPDEBUG((LOG_WARNING, 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)); */ /* "pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
pbuf_free(headMB); pbuf_free(headMB);
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.memerr++; lwip_stats.link.memerr++;
lwip_stats.link.proterr++; lwip_stats.link.proterr++;
#endif /* LINK_STATS */ #endif /* LINK_STATS */
@@ -925,15 +1002,14 @@ int sifup(int pd)
st = 0; st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else { } else {
if(pc->netif) netif_remove(&pc->netif);
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->netif = netif_add(&pc->our_ipaddr, &pc->netmask, &pc->his_ipaddr, (void *)pd, pppifNetifInit, ip_input); pc->if_up = 1;
if(pc->netif) { pc->errCode = PPPERR_NONE;
pc->if_up = 1;
pc->errCode = 0;
if(pc->linkStatusCB) PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
pc->linkStatusCB(pc->linkStatusArg, pc->errCode); if(pc->linkStatusCB)
pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
} else { } else {
st = 0; st = 0;
PPPDEBUG((LOG_ERR, "sifup[%d]: netif_add failed\n", pd)); 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) int sifnpmode(int u, int proto, enum NPmode mode)
{ {
(void)u; (void)u;
(void)proto; (void)proto;
(void)mode; (void)mode;
return 0; return 0;
} }
/* /*
@@ -967,11 +1043,10 @@ int sifdown(int pd)
PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd)); PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
} else { } else {
pc->if_up = 0; pc->if_up = 0;
if(pc->netif) netif_remove(&pc->netif);
netif_remove(pc->netif); PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
pc->netif = NULL; if(pc->linkStatusCB)
if(pc->linkStatusCB) pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
pc->linkStatusCB(pc->linkStatusArg, PPPERR_CONNECT);
} }
return st; return st;
} }
@@ -995,11 +1070,11 @@ int sifaddr(
st = 0; st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else { } else {
memcpy(&pc->our_ipaddr, &o, sizeof(o)); memcpy(&pc->addrs.our_ipaddr, &o, sizeof(o));
memcpy(&pc->his_ipaddr, &h, sizeof(h)); memcpy(&pc->addrs.his_ipaddr, &h, sizeof(h));
memcpy(&pc->netmask, &m, sizeof(m)); memcpy(&pc->addrs.netmask, &m, sizeof(m));
memcpy(&pc->dns1, &ns1, sizeof(ns1)); memcpy(&pc->addrs.dns1, &ns1, sizeof(ns1));
memcpy(&pc->dns2, &ns2, sizeof(ns2)); memcpy(&pc->addrs.dns2, &ns2, sizeof(ns2));
} }
return st; return st;
} }
@@ -1023,11 +1098,11 @@ int cifaddr(
st = 0; st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else { } else {
IP4_ADDR(&pc->our_ipaddr, 0,0,0,0); IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
IP4_ADDR(&pc->his_ipaddr, 0,0,0,0); IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
IP4_ADDR(&pc->netmask, 255,255,255,0); IP4_ADDR(&pc->addrs.netmask, 255,255,255,0);
IP4_ADDR(&pc->dns1, 0,0,0,0); IP4_ADDR(&pc->addrs.dns1, 0,0,0,0);
IP4_ADDR(&pc->dns2, 0,0,0,0); IP4_ADDR(&pc->addrs.dns2, 0,0,0,0);
} }
return st; return st;
} }
@@ -1046,7 +1121,7 @@ int sifdefaultroute(int pd, u32_t l, u32_t g)
st = 0; st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else { } else {
netif_set_default(pc->netif); netif_set_default(&pc->netif);
} }
/* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */ /* 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 void
pppMainWakeup(int pd) pppMainWakeup(int pd)
{ {
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d\n", pd));
sio_read_abort(pppControl[pd].fd); sio_read_abort(pppControl[pd].fd);
} }
@@ -1091,6 +1167,7 @@ pppStartCB(void *arg)
{ {
int pd = (int)arg; int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %d\n", pd));
lcp_lowerup(pd); lcp_lowerup(pd);
lcp_open(pd); /* Start protocol */ lcp_open(pd); /* Start protocol */
} }
@@ -1100,6 +1177,7 @@ pppStopCB(void *arg)
{ {
int pd = (int)arg; int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %d\n", pd));
lcp_close(pd, "User request"); lcp_close(pd, "User request");
} }
@@ -1108,6 +1186,7 @@ pppHupCB(void *arg)
{ {
int pd = (int)arg; int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %d\n", pd));
lcp_lowerdown(pd); lcp_lowerdown(pd);
link_terminated(pd); link_terminated(pd);
} }
@@ -1134,30 +1213,37 @@ static void pppMain(void *arg)
/* /*
* Start the connection and handle incoming events (packet or timeout). * 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); tcpip_callback(pppStartCB, arg);
while (lcp_phase[pd] != PHASE_DEAD) { while (lcp_phase[pd] != PHASE_DEAD) {
if (pc->kill_link) { if (pc->kill_link) {
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d kill_link -> pppStopCB\n", pd));
pc->errCode = PPPERR_USER; pc->errCode = PPPERR_USER;
/* This will leave us at PHASE_DEAD. */ /* This will leave us at PHASE_DEAD. */
tcpip_callback(pppStopCB, arg); tcpip_callback(pppStopCB, arg);
pc->kill_link = 0; pc->kill_link = 0;
} }
else if (pc->sig_hup) { else if (pc->sig_hup) {
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sig_hup -> pppHupCB\n", pd));
pc->sig_hup = 0; pc->sig_hup = 0;
tcpip_callback(pppHupCB, arg); tcpip_callback(pppHupCB, arg);
} else { } else {
int c = sio_read(pc->fd, p->payload, p->len); int c = sio_read(pc->fd, p->payload, p->len);
if(c > 0) { if(c > 0) {
pppInProc(pd, p->payload, c); 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); pbuf_free(p);
out: out:
PPPDEBUG((LOG_DEBUG, "pppMain: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
if(pc->linkStatusCB) 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; pc->openFlag = 0;
} }
@@ -1207,7 +1293,7 @@ static void pppInput(void *arg)
pbuf_header(nb, -(int)sizeof(struct pppInputHeader)); pbuf_header(nb, -(int)sizeof(struct pppInputHeader));
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.recv++; lwip_stats.link.recv++;
#endif /* LINK_STATS */ #endif /* LINK_STATS */
@@ -1227,13 +1313,13 @@ static void pppInput(void *arg)
switch(protocol) { switch(protocol) {
case PPP_VJC_COMP: /* VJ compressed TCP */ case PPP_VJC_COMP: /* VJ compressed TCP */
#if VJ_SUPPORT > 0 #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 * Clip off the VJ header and prepend the rebuilt TCP/IP header and
* pass the result to IP. * pass the result to IP.
*/ */
if (vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) { 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; return;
} }
/* Something's wrong so drop it. */ /* Something's wrong so drop it. */
@@ -1245,13 +1331,13 @@ static void pppInput(void *arg)
break; break;
case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */
#if VJ_SUPPORT > 0 #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 * Process the TCP/IP header for VJ header compression and then pass
* the packet to IP. * the packet to IP.
*/ */
if (vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) { 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; return;
} }
/* Something's wrong so drop it. */ /* Something's wrong so drop it. */
@@ -1264,8 +1350,8 @@ static void pppInput(void *arg)
#endif /* VJ_SUPPORT > 0 */ #endif /* VJ_SUPPORT > 0 */
break; break;
case PPP_IP: /* Internet Protocol */ case PPP_IP: /* Internet Protocol */
PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in nBuf len=%d", pd, nb->len)); PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len));
pppControl[pd].netif->input(nb, pppControl[pd].netif); pppControl[pd].netif.input(nb, &pppControl[pd].netif);
return; return;
default: default:
{ {
@@ -1297,7 +1383,7 @@ static void pppInput(void *arg)
} }
drop: drop:
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.drop++; lwip_stats.link.drop++;
#endif #endif
@@ -1316,7 +1402,9 @@ static void pppDrop(PPPControl *pc)
#if 0 #if 0
PPPDEBUG((LOG_INFO, "pppDrop: %d:%.*H\n", pc->inHead->len, min(60, pc->inHead->len * 2), pc->inHead->payload)); PPPDEBUG((LOG_INFO, "pppDrop: %d:%.*H\n", pc->inHead->len, min(60, pc->inHead->len * 2), pc->inHead->payload));
#endif #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); pbuf_free(pc->inHead);
pc->inHead = NULL; pc->inHead = NULL;
pc->inTail = NULL; pc->inTail = NULL;
@@ -1325,7 +1413,7 @@ static void pppDrop(PPPControl *pc)
vj_uncompress_err(&pc->vjComp); vj_uncompress_err(&pc->vjComp);
#endif #endif
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.drop++; lwip_stats.link.drop++;
#endif /* LINK_STATS */ #endif /* LINK_STATS */
} }
@@ -1363,7 +1451,7 @@ static void pppInProc(int pd, u_char *s, int l)
PPPDEBUG((LOG_WARNING, PPPDEBUG((LOG_WARNING,
"pppInProc[%d]: Dropping incomplete packet %d\n", "pppInProc[%d]: Dropping incomplete packet %d\n",
pd, pc->inState)); pd, pc->inState));
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.lenerr++; lwip_stats.link.lenerr++;
#endif #endif
pppDrop(pc); pppDrop(pc);
@@ -1373,7 +1461,7 @@ static void pppInProc(int pd, u_char *s, int l)
PPPDEBUG((LOG_INFO, PPPDEBUG((LOG_INFO,
"pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n", "pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n",
pd, pc->inFCS, pc->inProtocol)); pd, pc->inFCS, pc->inProtocol));
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.chkerr++; lwip_stats.link.chkerr++;
#endif #endif
pppDrop(pc); pppDrop(pc);
@@ -1382,26 +1470,31 @@ static void pppInProc(int pd, u_char *s, int l)
else { else {
/* Trim off the checksum. */ /* Trim off the checksum. */
if(pc->inTail->len >= 2) { if(pc->inTail->len >= 2) {
pc->inTail->len -= 2; pc->inTail->len -= 2;
pc->inLen -= 2;
/* Update the packet header. */ pc->inTail->tot_len = pc->inTail->len;
pc->inHead->tot_len = pc->inLen; if (pc->inTail != pc->inHead) {
} else { pbuf_cat(pc->inHead, pc->inTail);
pc->inHead->tot_len = pc->inLen; }
pbuf_realloc(pc->inHead, pc->inLen - 2); } 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. */ /* 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, PPPDEBUG((LOG_ERR,
"pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd)); "pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd));
pbuf_free(pc->inHead); pbuf_free(pc->inHead);
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.drop++; lwip_stats.link.drop++;
#endif #endif
} }
pc->inHead = NULL; pc->inHead = NULL;
pc->inTail = NULL; pc->inTail = NULL;
} }
@@ -1480,40 +1573,40 @@ static void pppInProc(int pd, u_char *s, int l)
case PDDATA: /* Process data byte. */ case PDDATA: /* Process data byte. */
/* Make space to receive processed data. */ /* Make space to receive processed data. */
if (pc->inTail == NULL || pc->inTail->len == PBUF_POOL_BUFSIZE) { 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. */ /* If we haven't started a packet, we need a packet header. */
nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (nextNBuf == NULL) { if (nextNBuf == NULL) {
/* No free buffers. Drop the input packet and let the /* No free buffers. Drop the input packet and let the
* higher layers deal with it. Continue processing * 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)); PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd));
#ifdef LINK_STATS #if LINK_STATS
lwip_stats.link.memerr++; lwip_stats.link.memerr++;
#endif /* LINK_STATS */ #endif /* LINK_STATS */
pppDrop(pc); pppDrop(pc);
pc->inState = PDSTART; /* Wait for flag sequence. */ pc->inState = PDSTART; /* Wait for flag sequence. */
break; 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. */ /* Load character into buffer. */
((u_char*)pc->inTail->payload)[pc->inTail->len++] = curChar; ((u_char*)pc->inTail->payload)[pc->inTail->len++] = curChar;
pc->inLen++;
break; break;
} }
@@ -1524,74 +1617,4 @@ static void pppInProc(int pd, u_char *s, int l)
avRandomize(); 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 */ #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 BCMP(s0, s1, l) memcmp((u_char *)(s0), (u_char *)(s1), (l))
#define BCOPY(s, d, l) memcpy((d), (s), (l)) #define BCOPY(s, d, l) memcpy((d), (s), (l))
#define BZERO(s, n) memset(s, 0, n) #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); } #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. * MAKEHEADER - Add PPP Header fields to a packet.
@@ -313,11 +316,14 @@ struct ppp_settings {
int maxconnect; /* Maximum connect time (seconds) */ int maxconnect; /* Maximum connect time (seconds) */
char user[MAXNAMELEN + 1];/* Username for PAP */ 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 our_name[MAXNAMELEN + 1]; /* Our name for authentication purposes */
char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */ 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 *** *** PUBLIC DATA STRUCTURES ***
@@ -337,7 +343,33 @@ extern struct protent *ppp_protocols[];/* Table of pointers to supported protoco
/* Initialize the PPP subsystem. */ /* Initialize the PPP subsystem. */
void pppInit(void); 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. * 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 * Return a new PPP connection descriptor on success or
* an error code (negative) on failure. * 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. * 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 #if PPP_DEBUG > 0
#define AUTHDEBUG(a) ppp_trace##a #define AUTHDEBUG(a) ppp_trace a
#define IPCPDEBUG(a) ppp_trace##a #define IPCPDEBUG(a) ppp_trace a
#define UPAPDEBUG(a) ppp_trace##a #define UPAPDEBUG(a) ppp_trace a
#define LCPDEBUG(a) ppp_trace##a #define LCPDEBUG(a) ppp_trace a
#define FSMDEBUG(a) ppp_trace##a #define FSMDEBUG(a) ppp_trace a
#define CHAPDEBUG(a) ppp_trace##a #define CHAPDEBUG(a) ppp_trace a
#define PPPDEBUG(a) ppp_trace a
#define PPPDEBUG(a) ppp_trace##a
#define TRACELCP 1 #define TRACELCP 1

View File

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

View File

@@ -35,7 +35,7 @@
#if VJ_SUPPORT > 0 #if VJ_SUPPORT > 0
#ifdef LINK_STATS #if LINK_STATS
#define INCR(counter) ++comp->stats.counter #define INCR(counter) ++comp->stats.counter
#else #else
#define INCR(counter) #define INCR(counter)
@@ -574,6 +574,33 @@ int vj_uncompress_tcp(
/* Remove the compressed header and prepend the uncompressed header. */ /* Remove the compressed header and prepend the uncompressed header. */
pbuf_header(n0, -vjlen); 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)) { if(pbuf_header(n0, cs->cs_hlen)) {
struct pbuf *np; struct pbuf *np;
@@ -584,9 +611,10 @@ int vj_uncompress_tcp(
*nb = NULL; *nb = NULL;
goto bad; goto bad;
} }
pbuf_chain(np, n0); pbuf_cat(np, n0);
n0 = np; n0 = np;
} }
LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen);
memcpy(n0->payload, &cs->cs_ip, cs->cs_hlen); memcpy(n0->payload, &cs->cs_ip, cs->cs_hlen);
*nb = n0; *nb = n0;

View File

@@ -1,7 +1,7 @@
/* /*
* Definitions for tcp compression routines. * 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. * Copyright (c) 1989 Regents of the University of California.
* All rights reserved. * All rights reserved.
@@ -136,7 +136,7 @@ struct vjcompress {
u_short flags; u_short flags;
u_char maxSlotIndex; u_char maxSlotIndex;
u_char compressSlot; /* Flag indicating OK to compress slot ID. */ u_char compressSlot; /* Flag indicating OK to compress slot ID. */
#ifdef LINK_STATS #if LINK_STATS
struct vjstat stats; struct vjstat stats;
#endif #endif
struct cstate tstate[MAX_SLOTS]; /* xmit connection states */ 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -115,9 +115,7 @@ slipif_input( struct netif * netif )
/* Received whole packet. */ /* Received whole packet. */
pbuf_realloc(q, recved); pbuf_realloc(q, recved);
#ifdef LINK_STATS LINK_STATS_INC(link.recv);
++lwip_stats.link.recv;
#endif /* LINK_STATS */
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n")); LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
return q; return q;
@@ -141,15 +139,13 @@ slipif_input( struct netif * netif )
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL); p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
#ifdef LINK_STATS
if (p == NULL) { if (p == NULL) {
++lwip_stats.link.drop; LINK_STATS_INC(link.drop);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
} }
#endif /* LINK_STATS */
if (q != NULL) { if (q != NULL) {
pbuf_chain(q, p); pbuf_cat(q, p);
} else { } else {
q = p; q = p;
} }