Compare commits

...

207 Commits

Author SHA1 Message Date
likewise
ec0c2bea6e Changed behaviour into implementation. 2005-01-01 18:06:21 +00:00
likewise
1b3682cfa9 Updated CHANGELOG. 2004-12-30 01:28:16 +00:00
likewise
2a9ee35411 Removed assertion that always equaled true. 2004-12-27 14:50:03 +00:00
likewise
0e0a7d82de Re-enabled ARP packet queueing. (Now that multi-packet queueing is disabled in etharp.c). 2004-12-27 14:45:12 +00:00
likewise
dfa96852f0 Disabled queueing more than 1 packet on a ARP entry, as I suspect this clashes with the TCP segment queueing. 2004-12-27 14:44:19 +00:00
likewise
a549ec0382 Added inline source documentation. 2004-12-27 14:42:02 +00:00
likewise
c61f01b206 tcp_write(): optimize order of valid states checks, most common first.
added assertion: when the queues are NULL, queuelen must be zero.
remove ACK flags from a PCB, only when we could succesfully sent
an empty ACK packet.
2004-12-26 01:36:37 +00:00
likewise
15257f4524 Update comment on ETHARP_QUEUEING. Defaulted to being disabled. 2004-12-24 21:58:53 +00:00
christiaans
089378ef87 christiaans: cosmetic change debug formatters as requested by Tom. 2004-12-07 08:16:27 +00:00
christiaans
805f495d84 christiaans: Fixed SO_REUSE default to 0. Actually we should fix udp so it won't depend on the socket layer. 2004-12-06 11:50:53 +00:00
likewise
928dd94ba6 etharp.c: Corrected DHCP_DOES_ARP_CHECK behaviour. 2004-11-30 17:22:18 +00:00
likewise
b429918b32 etharp.c: re-arranged code in find_entry(), supposedly making it more readable for all cases. 2004-11-29 11:01:20 +00:00
likewise
62a37a4876 Updates the FILES contents to better reflect the current state. 2004-11-29 09:39:51 +00:00
likewise
0e96ece6c6 Surround definition of tcp_timer_needed with #if !NO_SYS #endif. (see lwip-users 15-11-2004). 2004-11-28 18:23:00 +00:00
likewise
f1eca32536 Mentioned ARP race fix. 2004-11-28 18:06:47 +00:00
likewise
ed59dc1ada Prevented a race condition between a new ARP request and the ARP timer.
Timeouts stay the same (halved the ARP timer, doubled the counts), but
ETHARP_MAX_PENDING should be at least 2 to prevent it from reaching 0 right away,
giving too little time for any ARP responses to be noted.
2004-11-28 18:00:20 +00:00
likewise
a5cd3fcafd Added a missing "not" in the comment, the code was correct. 2004-11-25 14:04:45 +00:00
likewise
f3def542ee Compile dammit 2004-11-25 14:03:31 +00:00
likewise
aa249922df Removed redundant closing bracket. 2004-11-25 13:59:06 +00:00
likewise
37a0c57bed 2004-11-25 Leon Woestenberg <leon.woestenberg@gmx.net>
* ip.c: Exploit the fact that ip_addr_isbroadcast() now checks that the
     given IP address actually belongs to the network of the given interface.
2004-11-25 13:57:05 +00:00
likewise
90b7e68b4e Removed the Smurf. 2004-11-25 13:52:34 +00:00
likewise
1a0c497007 Mentioned Kieran's and my changes - Leon. 2004-11-25 13:33:57 +00:00
likewise
fd49ee3c8d 2004-11-25 Leon Woestenberg <leon.woestenberg@gmx.net>
* ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are
    comparing network addresses (identifiers), not the network masks
    themselves.
  * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given
    IP address actually belongs to the network of the given interface.
2004-11-25 13:33:07 +00:00
likewise
3488a5c3c4 2004-11-25 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD.
    Do not try hard to insert arbitrary packet's source address,
    etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD.
    etharp_query() now always DOES call ETHARP_TRY_HARD so that users
    querying an address will see it appear in the cache (DHCP could
    suffer from this when a server invalidly gave an in-use address.)
2004-11-25 13:32:31 +00:00
likewise
ae4955f59e Replaced erronous LWIP_ERRORF with LWIP_DEBUGF 2004-11-25 11:23:37 +00:00
likewise
fab107a9df DECLINE message was unicast instead of broadcast 2004-11-25 11:10:53 +00:00
kieranm
bb87d19e84 Kieran Mansley - kjm25@cam.ac.uk - 24th Nov 2004
* Increase pcb->snd_buf by 1 when an ACK is received in SYN_SENT state to ensure correct operation
2004-11-24 17:05:41 +00:00
kieranm
4e309b7992 Kieran Mansley - kjm25@cam.ac.uk - 24th Nov 2004
* Changed pcb->rttest from u16_t to u32_t - comparisons with tcp_ticks (which is u32_t) were failing after 9 hours of operation
2004-11-24 17:04:34 +00:00
kieranm
64aa4c716d Kieran Mansley - kjm25@cam.ac.uk - 24th Nov 2004
* Increased argument checking at start of pbuf_queue() and made resulting errors more verbose
2004-11-24 17:03:03 +00:00
jani
6b0852a21f reduce msleep interval from 250 to 1 ms in ppp 2004-11-09 13:03:32 +00:00
jani
8afd3e882e #if directive style fix 2004-11-09 11:44:06 +00:00
likewise
791fa28817 Removed static declaration of dhcp_release(). 2004-11-04 19:19:29 +00:00
christiaans
3fab752640 Removed struct netif; forward decl. is already included from ip_addr.h.
Hit me if it breaks exsisting code.
2004-10-29 14:57:38 +00:00
christiaans
67dd939d83 Match update_arp_entry() to prototype. 2004-10-28 08:21:33 +00:00
likewise
ec9b447be1 17th October 2004 Leon Woestenberg <leon.woestenberg@gmx.net>
rawapi.txt: Explicitly name full nomenclature for two different API's.
2004-10-17 21:28:25 +00:00
likewise
99e3fe9ae1 17th October 2004 Leon Woestenberg <leon.woestenberg@gmx.net>
ethernetif.c: Fix lwip/stats.h support, reported by Andrew McGeachie.
2004-10-17 18:13:18 +00:00
likewise
eb99d21022 Mentioned adapted TCP behaviour; send ACK even if one was pending, iff rcv_wnd is above threshold. 2004-10-16 15:12:56 +00:00
likewise
793cbcdff8 Mentioned adapted TCP behaviour; send ACK even if one was pending, iff rcv_wnd is above threshold. 2004-10-16 15:07:26 +00:00
kieranm
751557bcbf 16th October 2004 - Kieran Mansley - kjm25@cam.ac.uk
- Add code to tcp_recved() to send an ACK (window update)
immediately, even if one is already pending, if the rcv_wnd is above a
threshold (currently TCP_WND/2)
 - This avoids waiting for a timer to expire to send a delayed ACK in
order to open the window if the stack is only receiving data.
2004-10-16 12:57:52 +00:00
likewise
252dcd8626 Reverted back the TCP_BETWEEN macro. It does not work on all archs. 2004-10-14 12:24:52 +00:00
likewise
0ad7ea16d2 Bring interface up/down with netif_set_up/down(). Fixes bug 10547. 2004-10-14 11:57:53 +00:00
likewise
79842d4fdd Mentioned TCP retransmit time-out changes contributed by Sam Jansen, committed Kieran Mansley. 2004-10-13 21:40:51 +00:00
kieranm
1e1f5d5462 Kieran Mansley - kjm25@cam.ac.uk - 20th September 2004
* Change the return type of ethernetif_init from void to err_t to avoid confusing porters.
2004-09-20 17:00:31 +00:00
kieranm
19d8ffe177 Kieran Mansley - kjm25@cam.ac.uk - 20th September 2004
* Check if the pbuf is NULL before freeing it, when draining the mbox as part of netconn_delete.
2004-09-20 16:58:01 +00:00
kieranm
4cb8192c1d Kieran Mansley - kjm25@cam.ac.uk - 20th September 2004
* Corrected "out by one" error on one of the TCP_SEQ_BETWEEN macro calls introduced recently
2004-09-20 16:53:48 +00:00
kieranm
2ed5bc5195 Kieran Mansley - kjm25@cam.ac.uk - 12th September 2004
Applied patch from Sam Jansen as detailed in
http://lists.gnu.org/archive/html/lwip-users/2004-07/msg00106.html
to correctly handle retransmission after a retransmission timeout
2004-09-12 16:34:06 +00:00
kieranm
fae1397468 Rename lwip_chksum and add LWIP_CHKSUM macro so that ports can "override" the standard implementation with one of their own. 2004-09-12 16:17:58 +00:00
kieranm
e871548772 Fixed typo (missing "{") in previous checkin 2004-09-12 16:03:54 +00:00
kieranm
a3d27e30e0 Add TCP_SEQ_BETWEEN macro for comparing a range of sequence numbers 2004-09-12 15:56:12 +00:00
likewise
89abd1f58e Do no longer try to free pbuf when TCP_EVENT_RECV() is called without a callback handler, and without packet.
The standard HTTP server failed on this (as reported by three users).
2004-09-08 22:33:46 +00:00
softins
fae709d9ea Added my July and August updates. 2004-08-20 16:56:20 +00:00
softins
36df79b207 Make sure the first pbuf queued on an ARP entry is properly ref counted. 2004-08-20 09:17:52 +00:00
likewise
b9ebcd7738 Ingress TCP keep-alive with garbage byte support. 2004-08-17 09:32:31 +00:00
likewise
515fb5a3fd First packet on queue generated assertion failure. Reported by David Haas on lwip-users on Friday 13th. 2004-08-17 08:39:43 +00:00
likewise
785f90d9fa Updated the use of Savannah docs (merged from STABLE-0_7 branch). 2004-08-11 00:15:03 +00:00
likewise
22ac311496 Support for PACK_STRUCT_USE_INCLUDES was broken.
Added one missing PACK_STRUCT_END.
2004-08-10 14:50:44 +00:00
likewise
0e31ca73c0 Have PBUF_LINK_HLEN default to 14 bytes (for Ethernet). 2004-08-10 14:41:12 +00:00
likewise
98ba558fa5 Mentioned 1.0.0. 2004-07-29 11:28:27 +00:00
softins
c4ef1e5c19 Add (int) cast in LWIP_DEBUGF() to avoid compiler warnings about comparison. 2004-07-27 16:19:16 +00:00
softins
1fa0d66f15 Stop compiler complaining of empty if statement when LWIP_DEBUGF() empty. 2004-07-27 16:08:26 +00:00
softins
4680307a34 Stop compiler complaining of empty if statement when LWIP_DEBUGF() empty.
Close an unclosed comment.
2004-07-27 16:08:05 +00:00
softins
42a6fa972d Corrected IPH_TOS() macro: returns a byte, so doesn't need htons(). 2004-07-27 14:46:24 +00:00
softins
1da6c35a6d Added a couple of casts to quiet the compiler.
No need to test isascii(c) before isdigit(c) or isxdigit(c).
2004-07-27 14:43:58 +00:00
likewise
7c427a4dce Made some comments more explicit. 2004-07-25 23:41:01 +00:00
likewise
c2abae538b pbuf_free() assert triggered by NULLified inseg.p. Reported by Karl Jeacle on 25-7-2004 on lwip-users. 2004-07-25 23:17:07 +00:00
kieranm
eb69032773 Kieran Mansley - kjm25@cam.ac.uk - 23rd July 2004
Now handle CLOSED state in tcp_close() explicitely, and free the pcb.
This is for the case that a pcb has been allocated but never used (so
is in the default "CLOSED" state) and needs to be freed.
2004-07-23 13:07:00 +00:00
likewise
fb5452910f I hate it when it takes twice to fix a typo 2004-07-22 22:10:17 +00:00
likewise
a6d37fcb25 Removed copy-paste errors. 2004-07-22 22:07:00 +00:00
likewise
fb18e1f036 Removed obsolete debug define. 2004-07-22 21:56:31 +00:00
likewise
786cbee510 Support for learning DNS servers through DHCP. 2004-07-22 21:56:09 +00:00
softins
a4f5673ff3 Small corrections to some debugging statements, to pacify compiler. 2004-07-22 08:06:00 +00:00
softins
1121f2b7f7 Made data types consistent in inet_ntoa().
Added casts for return values of checksum routines, to pacify compiler.
2004-07-22 08:03:02 +00:00
softins
4d30218eb2 Updated low_level_output() to match prototype for netif->linkoutput
and changed low_level_input() similarly for consistency.
2004-07-21 09:31:03 +00:00
softins
d7699ca81d Changed debug statements to use the tidier ip4_addrN() macros. 2004-07-21 09:23:11 +00:00
softins
afc3bc6b65 Added trivial (int) cast to keep compiler happier. 2004-07-21 08:57:05 +00:00
softins
6f066fca82 Changed recv_raw() from int to u8_t, to match prototype of raw_recv() in raw.h
and so avoid compiler error.
2004-07-21 08:55:26 +00:00
softins
5e24ae49a6 Removed spurious semicolon and added missing end-of-comment. 2004-07-21 08:36:15 +00:00
likewise
bf74ffe974 Outgoing packets caused ARP requests even when the destination IP was already cached.
Matched documentation.
2004-07-20 23:18:09 +00:00
likewise
2074861b57 Outgoing packets caused ARP requests even when the destination IP was already cached. 2004-07-20 23:07:54 +00:00
likewise
58b64d42f1 Additional fix for TCP retransmit fix (as discussed by Sam Jansen en Kieran Mansley on lwip-devel, July 13 2004). 2004-07-14 23:21:53 +00:00
likewise
a6ab0405ea Disabled some code by #if 0 #endif rather than /* */. 2004-07-14 23:19:08 +00:00
kieranm
8273b54108 Kieran Mansley - 14th July 2004
* Only move a single segment from the unacked queue to the unsent queue when performing a retransmit
2004-07-14 09:48:27 +00:00
kieranm
c356f560e8 Kieran Mansley - 14th July 2004
* Fixed whitespace indenting in parts of tcp_in.c
 * Changed adjustment of ssthresh in response to fast retransmit
 * Commented out iteration of unsent list when new ACK received as we no longer put all unacked data on unsent list when retransmitting
2004-07-14 09:45:01 +00:00
likewise
8d052ecf24 Source documentation added. 2004-07-12 20:42:16 +00:00
likewise
45e36d9f56 Dependencies on C library memset() etc., so include <string.h>. 2004-07-05 00:00:21 +00:00
likewise
c222d8b672 Updated with latest changes. 2004-07-04 23:52:40 +00:00
likewise
efed3f1f0d Mentioned placement of closing curly brace (block end). 2004-07-04 23:44:43 +00:00
likewise
7524893802 Dependencies on C library memset() etc., so include <string.h>. 2004-07-04 23:43:38 +00:00
likewise
25a0273b05 LWIP_TIMEVAL_PRIVATE must be defined in architecture cc.h file, either 1 or 0. Defaults to 1.
Dependencies on C library memset() etc., so include <string.h> and <errno.h>.
2004-07-04 23:43:02 +00:00
likewise
ce0410b205 LWIP_TIMEVAL_PRIVATE must be defined in architecture cc.h file, either 1 or 0. Defaults to 1. 2004-07-04 23:42:14 +00:00
likewise
efe5ce5c78 Made loop counters unsigned where possible. 2004-07-04 23:40:44 +00:00
likewise
07f52b4b96 Fixed compile errors. 2004-06-30 22:14:03 +00:00
likewise
0be3598990 Style fixes. 2004-06-30 18:42:54 +00:00
likewise
c3284c30cd Make restarting() DHCP on on interface more robust by cleaning old state information. 2004-06-30 18:42:33 +00:00
likewise
2d94bf4998 Bug fix: etharp_output() should not free pbufs.
Bug was introduced in 1.60 and reported by Tim Newsham on 30-Jun-2004 on lwip-users.
2004-06-30 18:41:39 +00:00
likewise
31c1e72b8c ip_forward() returns netif on which packet was forwarded. 2004-06-30 18:39:17 +00:00
likewise
d11fcafad8 Added netif up/down basics. 2004-06-30 18:38:07 +00:00
kieranm
27c6d299cf Kieran Mansley - kjm25@cam.ac.uk - 30th May 2004
* Fixed bug #9160 after discussion on mailing list
 - alters use of MEM_ALIGN_SIZE in pbuf_alloc when calling mem_malloc for a PBUF_RAM pbuf
2004-05-30 14:04:30 +00:00
kieranm
450dd65165 Kieran Mansley - kjm25@cam.ac.uk - 26th May 2004
* Fixed bug 9076 (changes to pbuf tot_len and seg dataptr when trimming front edge of a received packet)
2004-05-26 10:04:15 +00:00
likewise
26819e6c39 Fixed documentation for internal function. 2004-05-13 00:28:38 +00:00
likewise
6587efb3e8 Fixed #if ETHARP_QUEUEING to #if ARP_QUEUEING. 2004-05-07 01:20:28 +00:00
likewise
8d2200f29b Optimized search loop a bit. Conditional code for ETHARP_QUEUEING option. 2004-05-07 01:06:56 +00:00
likewise
e4295396ac Re-instantiated the pack directives. Nested structs do break individual field natural alignment on arm-gcc. 2004-05-06 03:27:13 +00:00
likewise
5c7a70df28 Fixed wrong argument to find_entry() in etharp_query(). 2004-05-06 02:55:53 +00:00
likewise
16a7a8258f Fixed ETH_EMPTY into ETHARP_STABLE_EMPTY. 2004-05-06 02:54:06 +00:00
likewise
fb1f61b212 Do not empty entries unless allowed to in find_entry(). 2004-05-06 02:51:15 +00:00
likewise
c3137df39c More fixes. 2004-05-06 02:49:10 +00:00
likewise
2df9cd7262 Exported etharp_request(). 2004-05-06 02:43:47 +00:00
likewise
a23f6afbee Fixed typos. 2004-05-06 02:38:42 +00:00
likewise
e37f7fafc1 Optimized through re-use of common code. Results in 50 lines less and more modular code.
Work towards timed out and retries of ARP requests. Currently, one timed out ARP request.
2004-05-06 02:35:27 +00:00
likewise
7b803465ad Simplified update_arp_entry(). 2004-05-06 00:14:39 +00:00
likewise
273612b251 Prevent non-unicast addresses from polluting the ARP cache. 2004-05-05 23:47:33 +00:00
likewise
e2bc8e86e2 Removed a closing bracket, left over after removing pack directives. 2004-05-05 23:04:17 +00:00
likewise
79110ba469 Removed all structure packing directives. Protocol header fields are naturally aligned by design.
(Earlier, the 14-byte ethernet header screwed this up, this had already been fixed by adding two pad bytes.)
Assumption is that compilers do not align with larger-than-sizeof(type) boundaries.
Pre-tag PRE_PACK_REMOVE. Post-tag POST_TAG_REMOVE.
2004-05-05 19:16:51 +00:00
likewise
9dd10e46ab Fix three bugs during tests. 2004-05-05 18:33:01 +00:00
likewise
29df95c514 As etharp already sends packets from the queue asynchronously, also make it send packet submitted through etharp_output().
etharp_output() now returns err_t.
etharp_query() now sends a packet directly if the IP address is stable.
2004-05-05 18:28:42 +00:00
likewise
015cb1a35d etharp_*_input() return value (pbuf) removed; it has not been used since the packet queue
implementation. Packets are always sent to the network interface on behalf of ARP.
2004-05-05 15:59:12 +00:00
likewise
b217b020a5 Changed PAD_ETH_SIZE into ETH_PAD_SIZE for consistency with de-facto lwIP naming convention. 2004-05-05 15:09:13 +00:00
likewise
0c960a82ce The recv callback has u8_t return type. Fixed theraw_pcb struct to reflect this. 2004-05-05 14:30:28 +00:00
likewise
e84cc8c0ad Remember head of queue in pbuf_queue() iff PBUF_DEBUG to generate senseful debug report. 2004-05-05 14:28:41 +00:00
likewise
c69b93b246 The recv callback has u8_t return type. Fixed the raw_recv() prototype to reflect this. 2004-05-05 14:21:05 +00:00
likewise
5e13b9528d Adpated comments to match Doxygen/JavaDoc style. 2004-05-05 14:12:28 +00:00
likewise
8bb3cab9d2 Adpated comments to match Doxygen/JavaDoc style. 2004-05-05 13:28:44 +00:00
likewise
ed201c35d2 Made raw_input() more generic allowing multiple matches until someone eats the packet. 2004-05-05 13:27:27 +00:00
likewise
4eadc22a36 Some updates on "gratuitious ARP" from RFC3220. Cleanup of some code and comments. 2004-05-03 17:50:11 +00:00
jani
4e2260c74c by default there's no eth padding to preserve preious beahviour 2004-05-03 09:42:58 +00:00
likewise
a5148c14a1 Fixed use of struct ip_addr in DHCP header. 2004-04-30 01:00:21 +00:00
likewise
955d6206ee Fixed hasty job prototype for pbuf_queue(). 2004-04-30 00:58:55 +00:00
likewise
5df22b3468 Added missing prototypes for pbuf_*queue(). 2004-04-30 00:57:20 +00:00
likewise
aef86ec5ef DHCP header used u32_t where struct ip_addr is more appropriate. 2004-04-30 00:51:49 +00:00
likewise
94d3b04d68 Applied cleaner new patch for bug #8708.
Implemented multiple packets on the outgoing queue in etharp.c.
Removed etharp.c specific queueing functions.
Fixed generic pbuf.c queueing functions.
2004-04-30 00:25:03 +00:00
likewise
d31830225c Updated list of fixes/changes to the code. 2004-04-29 21:56:06 +00:00
likewise
8f309a3fec Clean-up source comment documentation for Doxygen. 2004-04-29 21:50:39 +00:00
likewise
1fe4edbe1c Fix buggy comment. 2004-04-29 21:49:12 +00:00
likewise
fe1696cef7 Clean-up source comment documentation for Doxygen. 2004-04-29 21:48:31 +00:00
likewise
de2e311e6e Updated documentation. 2004-04-28 23:40:53 +00:00
likewise
384fb3c353 Corrected comparison by adding missing parentheses. 2004-04-28 23:36:39 +00:00
likewise
8603e19516 Removed ETHARP_ALWAYS_INSERT. 2004-04-28 23:20:18 +00:00
likewise
7a2751043a Removed ETHARP_ALWAYS_INSERT. Whitespace cleanup. 2004-04-28 23:19:38 +00:00
likewise
e2b0c6c702 Fixed a cast. 2004-04-28 23:18:57 +00:00
likewise
5b12c61a81 Removed old broadcast check macro. 2004-04-28 23:18:20 +00:00
likewise
b8ee8808b4 Updated release procedure to match Savannah changes. 2004-04-28 20:35:17 +00:00
likewise
2db9551750 Patch of bug #8708 applied which should fix header alignment issues on 32-bit processors.
While this patch might need further clean-up, it is applied to make sure this gets attention.
2004-04-28 00:26:35 +00:00
likewise
7dc51270ee Documented latest fixes in HEAD. 2004-04-23 16:49:35 +00:00
likewise
237b5a2467 Fix in the ip_addr_isbroadcast() check. 2004-04-23 16:45:06 +00:00
likewise
110e5af36c Two trivial typo fixes. 2004-04-23 15:24:36 +00:00
jani
7d4aef9576 spelling fix from Tony Mountfield 2004-04-22 09:50:22 +00:00
jani
811b360df7 more uptodate eth driver skeleton from Tony Mountfield 2004-04-22 09:47:47 +00:00
likewise
d91b54882a Fixed #ifdef LWIP_DHCP to #if LWIP_DHCP. 2004-04-16 22:36:48 +00:00
likewise
9106a1f2d5 Fixed #ifdef LWIP_DHCP position. Fixed extranous comma in function arguments. 2004-04-16 22:34:25 +00:00
likewise
2e2dada561 etharp_query(): Fixed the case where the packet that initiates the ARP request is not queued, and gets lost.
etharp_query(): Fixed the case where the packets destination address is already known.
As a result, we now always queue the packet and perform an ARP request, unless the entry is stable and no packet is submitted for transmission.
2004-04-14 19:12:10 +00:00
jani
6d704c728e do not export struct timeval to external users of socket.h to avoid conflicts 2004-03-26 13:21:35 +00:00
jani
6c6f32f17f fix recursive inclusion by forward defining struct netif 2004-03-26 13:21:10 +00:00
jani
0e4ce326c2 warnign fixe for stat_display 2004-03-26 13:11:35 +00:00
jani
d27448da8a fix up stats_display which was added in previous commit 2004-03-26 12:47:57 +00:00
jani
d36b723056 fix SO_REUSE ifdef fixes 2004-03-26 12:40:58 +00:00
kieranm
2c8aa6f6f4 Kieran Mansley - kjm25@cam.ac.uk - 23rd March 2003
- Changed all #ifdef SO_REUSE into #if SO_REUSE
2004-03-23 19:33:53 +00:00
likewise
6f7c8fb355 Made #ifdef's into #if's for SO_REUSE. 2004-03-23 00:19:38 +00:00
likewise
82f852abf3 Fix cyclic dependencies by careful re-ordering of #includes.
This is really nasty. Can we forward-declare pointers to structs?
2004-03-12 00:10:07 +00:00
likewise
239c6fe070 Removed offending #include. 2004-03-11 21:39:47 +00:00
likewise
579d2ad811 Disabling ip_addr_isbroadcast() due to recursive header dependencies.
Currently, patch #2679 is broken, but will be neatly fixed once this is solved.
2004-03-11 21:37:56 +00:00
likewise
0cb355cd7c Added netif #include. 2004-03-11 21:28:37 +00:00
likewise
86135d12b9 Fix prototype. 2004-03-11 21:25:28 +00:00
likewise
10d42c6fa3 Replaced ip_addr_isbroadcast() macro by function.
Overrides patch #2679, as this must be solved inside ip_addr_isbroadcast(), inspired by BSD.
2004-03-11 21:20:10 +00:00
likewise
6434f7efad Missing newline at EOF. Gave compiler warning. 2004-03-11 20:52:25 +00:00
likewise
bfdf19f56c Make udp_disconnect() clear its remote address association. 2004-03-11 20:45:09 +00:00
likewise
79c7a7a43d Using udp_sendto() where appropriate. 2004-03-11 20:25:35 +00:00
likewise
175053085a Fixed @return in udp_sendto() docs, @see in udp_send*() docs. 2004-03-11 20:04:16 +00:00
likewise
3d90c062fd Added udp_sendto() docs. Fixed udp_send() docs. 2004-03-11 20:01:26 +00:00
likewise
fda71b1230 Fixed udp_sendto() -> instead of . 2004-03-11 19:52:47 +00:00
likewise
a916de3b66 Added udp_sendto(). 2004-03-11 19:41:22 +00:00
jani
30e5dfddb9 fix inet_ntoa prototype to be standard, and fix ppp code that used the non-standard version 2004-03-10 13:23:04 +00:00
kieranm
f9dea9d35b Kieran Mansley - kieranm@gtemail.net - 9th Mar 2004
- Added comment to tcp_write() to remind of the importance of call to
   tcp_output() to send any enqueued data.
2004-03-09 15:55:37 +00:00
jani
4ea55b1bbc only include sys.h once. Noted by Tom Barker 2004-03-09 14:03:11 +00:00
kieranm
caf3c16826 Kieran Mansley, kjm25@cam.ac.uk, 08th Mar 2004
- added a comment to tcp_recved() to clarify reasons for call to tcp_ack()
2004-03-08 14:41:25 +00:00
likewise
a6f1111469 Matched interface documentation for netif_add() API change in 1.28.2.5. 2004-03-04 16:19:53 +00:00
jani
33d0096b81 add switch for MEMP_SANITY_CHECK defaulting to off 2004-02-26 10:43:09 +00:00
likewise
ed4c5d88a3 Added replacement for ip_addr_isbroadcast() macro, code is dead for review and testing (#if 0). 2004-02-24 21:59:17 +00:00
jani
e85a892111 add default option for LWIP_RAW 2004-02-23 14:28:03 +00:00
kieranm
70cd10beae 23/02/2003 - Kieran Mansley - kieranm@gtemail.net
* Applied patch #2679

 * Sets netif->flags at line 202 to NETIF_FLAG_POINTTOPOINT
2004-02-23 10:15:06 +00:00
kieranm
3a784509df 23/02/2003 - Kieran Mansley - kieranm@gtemail.net
* Applied patch #2679

 * Adds check to line 75 for NETIF_FLAG_BROADCAST
2004-02-23 10:13:12 +00:00
kieranm
5c7189124c 23/02/2003 - Kieran Mansley - kieranm@gtemail.net
* Applied patch #2679

 * Adds check to line 314 for NETIF_FLAG_BROADCAST
2004-02-23 10:11:55 +00:00
kieranm
f81c2744cc 23/02/2003 - Kieran Mansley - kieranm@gtemail.net
* Applied patch #2679

 * Adds check to line 133 for NETIF_FLAG_BROADCAST
2004-02-23 10:07:39 +00:00
lukem
4bf3359574 Added ability to disable checksum generation and checking at compile-time 2004-02-20 01:46:03 +00:00
lukem
47984b0496 removed redundant redeclaration of tcp_active_pcbs (already defined by tcp.h) 2004-02-20 00:51:49 +00:00
lukem
3c339323ed added 8-byte alignment for 64-bit architectures 2004-02-20 00:45:47 +00:00
jani
7399722a88 indentation fix 2004-02-18 09:01:33 +00:00
likewise
7bfea6edb7 Applied Ian Wienand's patches (4-2-2004). Was partly applied earlier. 2004-02-16 21:33:42 +00:00
jani
f75da2c393 ip_lookup and udp_lookup not use remove declarations 2004-02-09 10:23:41 +00:00
likewise
475576ec20 Updated some copyright notices to include 2004 (a few were forgotten earlier). 2004-02-07 23:24:09 +00:00
likewise
f6a8e1df03 Added up-to-date explanation of CVS over SSH on Savannah. 2004-02-07 00:47:15 +00:00
likewise
e1c4bfad05 Merged from DEVEL, except for the API change in etharp.c. 2004-02-07 00:30:03 +00:00
likewise
1ed40e7983 Applied alias.diff by Ian Wienand on lwip-devel on February 4th 2004.
Using union to make explicit either tcp_listen_pcb or tcp_pcb.
2004-02-06 23:48:40 +00:00
likewise
035fcce9de Applied mem.diff by Ian Wienand on lwip-devel on February 4th 2004.
Stops some warnings.
2004-02-06 23:44:59 +00:00
likewise
19eed5ff8a Applied dhcp.diff by Ian Wienand on lwip-devel on February 4th 2004.
DHCP tries to build even if LWIP_DHCP is turned off.
2004-02-06 23:43:44 +00:00
likewise
7129d4797c Merged ARP fixes from STABLE. Should have made those fixes in HEAD first. 2004-02-06 22:28:37 +00:00
likewise
707d31a083 Merged from main. 2004-02-05 18:47:55 +00:00
likewise
79e66ac841 Savannah now does anonymous CVS access using empty-password SSH. 2004-01-20 13:51:54 +00:00
likewise
1b96391cdf Merged from DEVEL to main. Two TCP fixes and two NULL reference fixes. 2004-01-20 13:23:52 +00:00
uid67528
eed8ea5bc1 Merged from DEVEL. etharp prepared for queueing feature. DHCP fix. 2003-12-28 02:38:51 +00:00
likewise
a646b5374f Merge from DEVEL. Assert used field not available without callback API. 2003-11-18 01:52:24 +00:00
likewise
fa9b1ba947 Merge from DEVEL. Includes important UDP fix for bug #6601. 2003-11-18 01:40:08 +00:00
likewise
7d58c0c2be Prepared Changelog for upcoming release 0.6.5. Fixed missing 0.6.4 number in history. 2003-11-14 16:20:47 +00:00
likewise
3c71c378bc An overriden merge from DEVEL to main was needed as small changes had been made to main. 2003-11-14 14:56:30 +00:00
likewise
e4a6d199fe Merged from DEVEL into main tree. 2003-11-14 13:17:23 +00:00
likewise
bdfdc2bb83 Made hton/ntoh argument name in prototypes match those in functions. 2003-07-07 09:11:17 +00:00
marcbou
351e590e01 Merged from DEVEL. 2003-06-27 20:46:11 +00:00
79 changed files with 4785 additions and 2688 deletions

163
CHANGELOG
View File

@@ -1,11 +1,168 @@
FUTURE
* TODO: The lwIP source code makes some invalid assumptions on processor
word-length, storage sizes and alignment. See the mailing lists for
problems with exoteric (/DSP) architectures showing these problems.
We still have to fix some of these issues neatly.
* TODO: the ARP layer is not protected against concurrent access. If
you run from a multitasking OS, serialize access to ARP (called from
your network device driver and from a timeout thread.)
HISTORY
(current)
(HEAD)
2004-12-28 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.*: Disabled multiple packets on the ARP queue.
This clashes with TCP queueing.
2004-11-28 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.*: Fixed race condition from ARP request to ARP timeout.
Halved the ARP period, doubled the period counts.
ETHARP_MAX_PENDING now should be at least 2. This prevents
the counter from reaching 0 right away (which would allow
too little time for ARP responses to be received).
2004-11-25 Leon Woestenberg <leon.woestenberg@gmx.net>
* dhcp.c: Decline messages were not multicast but unicast.
* etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD.
Do not try hard to insert arbitrary packet's source address,
etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD.
etharp_query() now always DOES call ETHARP_TRY_HARD so that users
querying an address will see it appear in the cache (DHCP could
suffer from this when a server invalidly gave an in-use address.)
* ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are
comparing network addresses (identifiers), not the network masks
themselves.
* ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given
IP address actually belongs to the network of the given interface.
2004-11-24 Kieran Mansley <kjm25@cam.ac.uk>
* tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state.
(STABLE-1_1_0-RC1)
2004-10-16 Kieran Mansley <kjm25@cam.ac.uk>
* tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately,
even if one is already pending, if the rcv_wnd is above a threshold
(currently TCP_WND/2). This avoids waiting for a timer to expire to send a
delayed ACK in order to open the window if the stack is only receiving data.
2004-09-12 Kieran Mansley <kjm25@cam.ac.uk>
* tcp*.*: Retransmit time-out handling improvement by Sam Jansen.
2004-08-20 Tony Mountifield <tony@softins.co.uk>
* etharp.c: Make sure the first pbuf queued on an ARP entry
is properly ref counted.
2004-07-27 Tony Mountifield <tony@softins.co.uk>
* debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler
warnings about comparison.
* pbuf.c: Stopped compiler complaining of empty if statement
when LWIP_DEBUGF() empty. Closed an unclosed comment.
* tcp.c: Stopped compiler complaining of empty if statement
when LWIP_DEBUGF() empty.
* ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons().
* inet.c: Added a couple of casts to quiet the compiler.
No need to test isascii(c) before isdigit(c) or isxdigit(c).
2004-07-22 Tony Mountifield <tony@softins.co.uk>
* inet.c: Made data types consistent in inet_ntoa().
Added casts for return values of checksum routines, to pacify compiler.
* ip_frag.c, tcp_out.c, sockets.c, pbuf.c
Small corrections to some debugging statements, to pacify compiler.
2004-07-21 Tony Mountifield <tony@softins.co.uk>
* etharp.c: Removed spurious semicolon and added missing end-of-comment.
* ethernetif.c Updated low_level_output() to match prototype for
netif->linkoutput and changed low_level_input() similarly for consistency.
* api_msg.c: Changed recv_raw() from int to u8_t, to match prototype
of raw_recv() in raw.h and so avoid compiler error.
* sockets.c: Added trivial (int) cast to keep compiler happier.
* ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros.
(STABLE-1_0_0)
++ Changes:
2004-07-05 Leon Woestenberg <leon.woestenberg@gmx.net>
* sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure
your cc.h file defines this either 1 or 0. If non-defined,
defaults to 1.
* .c: Added <string.h> and <errno.h> includes where used.
* etharp.c: Made some array indices unsigned.
2004-06-27 Leon Woestenberg <leon.woestenberg@gmx.net>
* netif.*: Added netif_set_up()/down().
* dhcp.c: Changes to restart program flow.
2004-05-07 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.c: In find_entry(), instead of a list traversal per candidate, do a
single-pass lookup for different candidates. Should exploit locality.
2004-04-29 Leon Woestenberg <leon.woestenberg@gmx.net>
* tcp*.c: Cleaned up source comment documentation for Doxygen processing.
* opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC.
* etharp.c: update_arp_entry() only adds new ARP entries when adviced to by
the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option.
++ Bug fixes:
* some debug formatters and casts fixed.
* numereous fixes in PPP.
2004-04-27 Leon Woestenberg <leon.woestenberg@gmx.net>
* etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution
suggested by Timmy Brolin. Fix for 32-bit processors that cannot access
non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix
is to prefix the 14-bit Ethernet headers with two padding bytes.
2004-04-23 Leon Woestenberg <leon.woestenberg@gmx.net>
* ip_addr.c: Fix in the ip_addr_isbroadcast() check.
* etharp.c: Fixed the case where the packet that initiates the ARP request
is not queued, and gets lost. Fixed the case where the packets destination
address is already known; we now always queue the packet and perform an ARP
request.
(STABLE-0_7_0)
++ Bug fixes:
* Fixed TCP bug for SYN_SENT to ESTABLISHED state transition.
* Fixed TCP bug in dequeueing of FIN from out of order segment queue.
* Fixed two possible NULL references in rare cases.
(STABLE-0_6_6)
++ Bug fixes:
* Fixed DHCP which did not include the IP address in DECLINE messages.
++ Changes:
* etharp.c has been hauled over a bit.
(STABLE-0_6_5)
++ Bug fixes:
* 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:

View File

@@ -6,7 +6,7 @@ in lwIP development.
2 How to contribute to lwIP
Here is a short list of suggestions to anybody working with lwIP and
trying to contribute bugreports, fixes, enhancements, platform ports etc.
trying to contribute bug reports, fixes, enhancements, platform ports etc.
First of all as you may already know lwIP is a volunteer project so feedback
to fixes or questions might often come late. Hopefully the bug and patch tracking
features of Savannah help us not lose users' input.
@@ -14,19 +14,20 @@ features of Savannah help us not lose users' input.
2.1 Source code style:
1. do not use tabs.
2. identation is two spaces per level.
2. indentation is two spaces per level (i.e. per tab).
3. end debug messages with a trailing newline (\n).
4. one space between keyword and opening bracket.
5. no space between function and opening bracket.
6. one space and no newline before opening curly braces of a block.
7. spaces surrounding assignment and comparisons.
8. use current source code style as further reference.
7. closing curly brace on a single line.
8. spaces surrounding assignment and comparisons.
9. use current source code style as further reference.
2.2 Source code documentation style:
1. JavaDoc compliant and Doxygen compatible.
2. Function documentation above functions in .c files, not .h files.
(This forces you to synchronize documentation and behaviour.)
(This forces you to synchronize documentation and implementation.)
3. Use current documentation style as further reference.
2.3 Bug reports and patches:
@@ -55,9 +56,7 @@ features of Savannah help us not lose users' input.
2.4 Platform porters:
1. If you've ported lwIP to a platform (an OS, a uC/processor or a combination of these) and you think it
could benefit others[1] you might want to post an url to a tarball or zip from which it can be imported
to the contrib CVS module. Then you get CVS access and have to maintain your port :)
[1] - lwIP CVS should not be just a place to keep your port so you don't have to set up your own CVS :)
Especially welcome are ports to common enough OS/hardware that others can have access too.
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
you think it could benefit others[1] you might want discuss this on the mailing list. You
can also ask for CVS access to submit and maintain your port in the contrib CVS module.

View File

@@ -1,20 +1,21 @@
Raw TCP/IP interface for lwIP 0.5
Raw TCP/IP interface for lwIP
Author: Adam Dunkels
Authors: Adam Dunkels, Leon Woestenberg
lwIP provides two Application Program's Interfaces (APIs) for programs
to use for communication with the TCP/IP code: the sequential API
(often just called "the API") and the raw TCP/IP interface. This
document is intended as a description of the latter. For lwIP versions
lower than 0.5, this API was not documented.
to use for communication with the TCP/IP code:
* low-level "core" / "callback" or "raw" API.
* higher-level "sequential" API.
The sequential API provides a way for ordinary, sequential, programs
to use the lwIP stack. It is quite similar to the BSD socket API. The
model of execution is based on the open-read-write-close
model of execution is based on the blocking open-read-write-close
paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
code and the application program must reside in different execution
contexts (threads).
** The remainder of this document discusses the "raw" API. **
The raw TCP/IP interface allows the application program to integrate
better with the TCP/IP code. Program execution is event based by
having callback functions being called from within the TCP/IP
@@ -34,7 +35,6 @@ Both APIs can be used simultaneously by different application
programs. In fact, the sequential API is implemented as an application
program using the raw TCP/IP interface.
--- Callbacks
Program execution is driven by callbacks. Each callback is an ordinary
@@ -272,6 +272,11 @@ level of complexity of UDP, the interface is significantly simpler.
Sets the remote end of the pcb. This function does not generate any
network traffic, but only set the remote address of the pcb.
- err_t udp_disconnect(struct udp_pcb *pcb)
Remove the remote end of the pcb. This function does not generate
any network traffic, but only removes the remote address of the pcb.
- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
Sends the pbuf p. The pbuf is not deallocated.

View File

@@ -2,51 +2,99 @@ Daily Use Guide for using Savannah for lwIP
Table of Contents:
1 - Anonymous CVS checkouts and updates (to be elaborated)
1 - Obtaining lwIP from the CVS repository
2 - Committers/developers CVS access using SSH (to be written)
3 - Merging from DEVEL branch to main trunk (stable branch)
4 - How to release lwIP
1 Anonymous CVS checkouts and updates
-------------------------------------
Obtain lwIP from the STABLE tree (on the CVS main trunk)
1 Obtaining lwIP from the CVS repository
----------------------------------------
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip
To perform an anonymous CVS checkout of the main trunk (this is where
bug fixes and incremental enhancements occur), do this:
Or, obtain a specific release as follows:
export CVS_RSH=ssh
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_6_3 -d lwip-0.6.3 lwip
(If SSH asks about authenticity of the host, you can check the key
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
Or, obtain a development branch as follows:
Or, obtain a stable branch (updated with bug fixes only) as follows:
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_7 -d lwip-0.7 lwip
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-devel lwip
Or, obtain a specific (fixed) release as follows:
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_7_0 -d lwip-0.7.0 lwip
Or, obtain a development branch (considered unstable!) as follows:
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-DEVEL lwip
3 Merging from DEVEL branch to main trunk (stable branch)
---------------------------------------------------------
3 Committers/developers CVS access using SSH
--------------------------------------------
Merging from DEVEL to main requires that the DEVEL branch
has a tag indicating the previous merger. This tag is
called 'merged_from_DEVEL_to_main'.
The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption.
As such, CVS commits to the server occur through a SSH tunnel for project members.
To create a SSH2 key pair in UNIX-like environments, do this:
ssh-keygen -t dsa
Under Windows, a recommended SSH client is "PuTTY", freely available with good
documentation and a graphic user interface. Use its key generator.
Now paste the id_dsa.pub contents into your Savannah account public key list. Wait
a while so that Savannah can update its configuration (This can take minutes).
Try to login using SSH:
ssh -v your_login@subversions.gnu.org
If it tells you:
Authenticating with public key "your_key_name"...
Server refused to allocate pty
then you could login; Savannah refuses to give you a shell - which is OK, as we
are allowed to use SSH for CVS only. Now, you should be able to do this:
export CVS_RSH=ssh
cvs -d:ext:your_login@subversions.gnu.org:/cvsroot/lwip checkout lwip
after which you can edit your local files with bug fixes or new features and
commit them. Make sure you know what you are doing when using CVS to make
changes on the repository. If in doubt, ask on the lwip-members mailing list.
3 Merging from DEVEL branch to main trunk (stable)
--------------------------------------------------
Merging is a delicate process in CVS and requires the
following disciplined steps in order to prevent conflicts
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 OF THE
MERGE BRANCH (REPLACING EXISTING TAGS WITH THE SAME NAME).
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
Now move the tag in the DEVEL branch to this merge point,
so we can use this for future merges.
(This will apply the changes between 'merged_from_DEVEL_to_main'
and 'DEVEL' to your work set of files)
cvs -z4 rtag -F -r DEVEL merged_from_DEVEL_to_main lwip
We can now commit the merge result.
cvs commit -R -m "Merged from DEVEL to main."
If this worked out OK, we now move the tag in the DEVEL branch
to this merge point, so we can use this point for future merges:
cvs rtag -F -r DEVEL merged_from_DEVEL_to_main lwip
4 How to release lwIP
---------------------
@@ -58,49 +106,25 @@ Login CVS using pserver authentication, then export a clean copy of the
tagged tree. Export is similar to a checkout, except that the CVS metadata
is not created locally.
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
export CVS_RSH=ssh
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip export -r STABLE-0_6_3 -d lwip-0.6.3 lwip
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 cjvf lwip-0.6.3.tar.bz2 lwip-0.6.3
zip -r lwip-0.6.3.zip lwip-0.6.3
First, make a local release directory to work in, I use "lwip-releases":
Now, sign the archives with a detached GPG binary signature as follows:
mkdir lwip-releases
cd lwip-releases
gpg -b lwip-0.6.3.tar.gz
gpg -b lwip-0.6.3.tar.bz2
gpg -b lwip-0.6.3.zip
Now, make a new release by creating a new directory for it (these are
Savannah conventions so that it shows up in the Files list real nice):
Upload these files using anonymous FTP:
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
mkdir stable.pkg
cd stable.pkg
mkdir 0.6.3
cd 0.6.3
We can now copy the tar archive we made earlier into the release directory:
cp /../../../lwip-0.6.3.tar.gz .
Finally, synchronize this directory upwards to Savannah:
rsync -n -e "ssh -1" -t -u -v -r . likewise@savannah.nongnu.org:/upload/lwip
This does a "dry run": no files are modified! After you have confirmed that
this is what you intended to do, remove "-n" and actually synchronize for
real. The release should now be available here:
http://savannah.nongnu.org/files/?group=lwip
---
Explanation of rsync options used:
-t: preserve file timestamps
-u: do not overwrite existing files, unless they are older
-v: be verbose (long format file attributes)
-r: recurse into directories
-n: dry-run, do not modify anything.
---
ncftp>mput *0.6.3.*
Additionally, you may post a news item on Savannah, like this:

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -32,6 +32,9 @@
*
*/
#include <string.h>
#include <errno.h>
#include "lwip/opt.h"
#include "lwip/api.h"
#include "lwip/arch.h"
@@ -99,7 +102,7 @@ static int err_to_errno_table[11] = {
set_errno(sk->err); \
} while (0)
/*-----------------------------------------------------------------------------------*/
static struct lwip_socket *
get_socket(int s)
{
@@ -121,7 +124,7 @@ get_socket(int s)
return sock;
}
/*-----------------------------------------------------------------------------------*/
static int
alloc_socket(struct netconn *newconn)
{
@@ -150,7 +153,7 @@ alloc_socket(struct netconn *newconn)
sys_sem_signal(socksem);
return -1;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
@@ -164,6 +167,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -197,16 +201,14 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
newconn->socket = newsock;
sys_sem_signal(socksem);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port));
#endif
sock_set_errno(sock, 0);
return newsock;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
{
@@ -217,17 +219,16 @@ lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
local_port = ((struct sockaddr_in *)name)->sin_port;
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port)));
#endif
err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
@@ -241,7 +242,7 @@ lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_close(int s)
{
@@ -257,6 +258,7 @@ lwip_close(int s)
sock = get_socket(s);
if (!sock) {
sys_sem_signal(socksem);
set_errno(EBADF);
return -1;
}
@@ -271,7 +273,7 @@ lwip_close(int s)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
{
@@ -280,6 +282,7 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -293,11 +296,9 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
remote_port = ((struct sockaddr_in *)name)->sin_port;
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
#endif
err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
}
@@ -312,7 +313,7 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_listen(int s, int backlog)
{
@@ -322,6 +323,7 @@ lwip_listen(int s, int backlog)
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -336,7 +338,7 @@ lwip_listen(int s, int backlog)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
struct sockaddr *from, socklen_t *fromlen)
@@ -351,6 +353,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -411,13 +414,11 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
memcpy(from, &sin, *fromlen);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
#endif
} else {
#if SOCKETS_DEBUG > 0
#if SOCKETS_DEBUG
addr = netbuf_fromaddr(buf);
port = netbuf_fromport(buf);
@@ -444,19 +445,19 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
sock_set_errno(sock, 0);
return copylen;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_read(int s, void *mem, int len)
{
return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
}
/*-----------------------------------------------------------------------------------*/
int
lwip_recv(int s, void *mem, int len, unsigned int flags)
{
return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
}
/*-----------------------------------------------------------------------------------*/
int
lwip_send(int s, void *data, int size, unsigned int flags)
{
@@ -468,11 +469,15 @@ lwip_send(int s, void *data, int size, unsigned int flags)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
switch (netconn_type(sock->conn)) {
case NETCONN_RAW:
case NETCONN_UDP:
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
/* create a buffer */
buf = netbuf_new();
@@ -509,7 +514,7 @@ lwip_send(int s, void *data, int size, unsigned int flags)
sock_set_errno(sock, 0);
return size;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_sendto(int s, void *data, int size, unsigned int flags,
struct sockaddr *to, socklen_t tolen)
@@ -521,6 +526,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -530,11 +536,9 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
remote_port = ((struct sockaddr_in *)to)->sin_port;
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags));
ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));
#endif
netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
@@ -548,7 +552,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
netconn_disconnect(sock->conn);
return ret;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_socket(int domain, int type, int protocol)
{
@@ -557,6 +561,10 @@ lwip_socket(int domain, int type, int protocol)
/* create a netconn */
switch (type) {
case SOCK_RAW:
conn = netconn_new_with_proto_and_callback(NETCONN_RAW, protocol, event_callback);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
break;
case SOCK_DGRAM:
conn = netconn_new_with_callback(NETCONN_UDP, event_callback);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
@@ -589,14 +597,14 @@ lwip_socket(int domain, int type, int protocol)
set_errno(0);
return i;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_write(int s, void *data, int size)
{
return lwip_send(s, data, size, 0);
}
/*-----------------------------------------------------------------------------------*/
static int
lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
{
@@ -643,7 +651,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
}
/*-----------------------------------------------------------------------------------*/
int
lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
struct timeval *timeout)
@@ -723,7 +731,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
/* Wait forever */
msectimeout = 0;
else
msectimeout = ((timeout->tv_sec * 1000) + (timeout->tv_usec /1000));
msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
@@ -789,7 +797,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
return nready;
}
/*-----------------------------------------------------------------------------------*/
static void
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
{
@@ -878,7 +886,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
}
/*-----------------------------------------------------------------------------------*/
int lwip_shutdown(int s, int how)
@@ -895,6 +903,7 @@ int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -905,11 +914,9 @@ int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
/* get the IP address and port of the remote host */
netconn_peer(sock->conn, &naddr, &sin.sin_port);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
#endif
sin.sin_port = htons(sin.sin_port);
sin.sin_addr.s_addr = naddr.addr;
@@ -930,6 +937,7 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@@ -940,11 +948,9 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
/* get the IP address and port of the remote host */
netconn_addr(sock->conn, &naddr, &sin.sin_port);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
#endif
sin.sin_port = htons(sin.sin_port);
sin.sin_addr.s_addr = naddr->addr;
@@ -959,32 +965,190 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)
{
int err = ENOSYS;
int err = 0;
struct lwip_socket *sock = get_socket(s);
if (!sock) {
if(!sock) {
set_errno(EBADF);
return -1;
}
if (level == SOL_SOCKET) {
switch (optname) {
if( NULL == optval || NULL == optlen ) {
sock_set_errno( sock, EFAULT );
return -1;
}
/* Do length and type checks for the various options first, to keep it readable. */
switch( level ) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch(optname) {
case SO_ACCEPTCONN:
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_ERROR:
if (!optval || !optlen || (*optlen != sizeof(int))) {
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINLINE: */
/* UNIMPL case SO_RCVBUF: */
/* UNIMPL case SO_SNDBUF: */
/* UNIMPL case SO_RCVLOWAT: */
/* UNIMPL case SO_SNDLOWAT: */
#if SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
case SO_TYPE:
/* UNIMPL case SO_USELOOPBACK: */
if( *optlen < sizeof(int) ) {
err = EINVAL;
break;
}
*(int *)optval = sock->err;
sock->err = 0;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
err = 0;
break;
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch(optname) {
/* UNIMPL case IP_HDRINCL: */
/* UNIMPL case IP_RCVDSTADDR: */
/* UNIMPL case IP_RCVIF: */
case IP_TTL:
case IP_TOS:
if( *optlen < sizeof(int) ) {
err = EINVAL;
}
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
if( *optlen < sizeof(int) ) {
err = EINVAL;
break;
}
} else {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
/* If this is no TCP socket, ignore any options. */
if ( sock->conn->type != NETCONN_TCP ) return 0;
switch( optname ) {
case TCP_NODELAY:
case TCP_KEEPALIVE:
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* UNDEFINED LEVEL */
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
err = ENOPROTOOPT;
} /* switch */
if( 0 != err ) {
sock_set_errno(sock, err);
return -1;
}
/* Now do the actual option processing */
switch(level) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch( optname ) {
/* The option flags */
case SO_ACCEPTCONN:
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINCLUDE: */
#if 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 = (int)sock->conn->pcb.tcp->keepalive;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
break;
} /* switch */
break;
}
sock_set_errno(sock, err);
return err ? -1 : 0;
}
@@ -992,27 +1156,165 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
{
struct lwip_socket *sock = get_socket(s);
int err = ENOSYS;
int err = 0;
if (!sock) {
if(!sock) {
set_errno(EBADF);
return -1;
}
if (level == SOL_SOCKET) {
switch (optname) {
case SO_REUSEADDR:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, ..)\n", s));
/* XXX just pretend we support this for now */
err = 0;
if( NULL == optval ) {
sock_set_errno( sock, EFAULT );
return -1;
}
/* Do length and type checks for the various options first, to keep it readable. */
switch( level ) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch(optname) {
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINLINE: */
/* UNIMPL case SO_RCVBUF: */
/* UNIMPL case SO_SNDBUF: */
/* UNIMPL case SO_RCVLOWAT: */
/* UNIMPL case SO_SNDLOWAT: */
#if SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
/* UNIMPL case SO_USELOOPBACK: */
if( optlen < sizeof(int) ) {
err = EINVAL;
}
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch(optname) {
/* UNIMPL case IP_HDRINCL: */
/* UNIMPL case IP_RCVDSTADDR: */
/* UNIMPL case IP_RCVIF: */
case IP_TTL:
case IP_TOS:
if( optlen < sizeof(int) ) {
err = EINVAL;
}
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
if( optlen < sizeof(int) ) {
err = EINVAL;
break;
}
} else {
/* If this is no TCP socket, ignore any options. */
if ( sock->conn->type != NETCONN_TCP ) return 0;
switch( optname ) {
case TCP_NODELAY:
case TCP_KEEPALIVE:
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* UNDEFINED LEVEL */
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
err = ENOPROTOOPT;
} /* switch */
if( 0 != err ) {
sock_set_errno(sock, err);
return -1;
}
/* Now do the actual option processing */
switch(level) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch(optname) {
/* The option flags */
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINCLUDE: */
#if 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) -> %lu\n", s, sock->conn->pcb.tcp->keepalive));
break;
} /* switch */
break;
} /* switch */
sock_set_errno(sock, err);
return err ? -1 : 0;
}
@@ -1021,7 +1323,8 @@ int lwip_ioctl(int s, long cmd, void *argp)
{
struct lwip_socket *sock = get_socket(s);
if (!sock) {
if(!sock) {
set_errno(EBADF);
return -1;
}
@@ -1035,7 +1338,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
*((u16_t*)argp) = sock->conn->recv_avail;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
sock_set_errno(sock, 0);
sock_set_errno(sock, 0);
return 0;
case FIONBIO:
@@ -1044,7 +1347,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
else
sock->flags &= ~O_NONBLOCK;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
sock_set_errno(sock, 0);
sock_set_errno(sock, 0);
return 0;
default:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -46,34 +46,41 @@
static void (* tcpip_init_done)(void *arg) = NULL;
static void *tcpip_init_done_arg;
static sys_mbox_t mbox;
#if LWIP_TCP
static int tcpip_tcp_timer_active = 0;
/*-----------------------------------------------------------------------------------*/
static void
tcpip_tcp_timer(void *arg)
{
(void)arg;
/* call TCP timer handler */
tcp_tmr();
/* timer still needed? */
if (tcp_active_pcbs || tcp_tw_pcbs) {
/* restart timer */
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
} else {
tcpip_tcp_timer_active = 0;
/* disable timer */
tcpip_tcp_timer_active = 0;
}
}
#if !NO_SYS
void
tcp_timer_needed(void)
{
/* timer is off but needed again? */
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
tcpip_tcp_timer_active = 1;
/* enable and start timer */
tcpip_tcp_timer_active = 1;
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
}
}
#endif /* !NO_SYS */
#endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/
static void
tcpip_thread(void *arg)
{
@@ -110,16 +117,16 @@ tcpip_thread(void *arg)
default:
break;
}
memp_freep(MEMP_TCPIP_MSG, msg);
memp_free(MEMP_TCPIP_MSG, msg);
}
}
/*-----------------------------------------------------------------------------------*/
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG);
msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) {
pbuf_free(p);
return ERR_MEM;
@@ -131,13 +138,13 @@ tcpip_input(struct pbuf *p, struct netif *inp)
sys_mbox_post(mbox, msg);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
err_t
tcpip_callback(void (*f)(void *ctx), void *ctx)
{
struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG);
msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) {
return ERR_MEM;
}
@@ -148,12 +155,12 @@ tcpip_callback(void (*f)(void *ctx), void *ctx)
sys_mbox_post(mbox, msg);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
tcpip_apimsg(struct api_msg *apimsg)
{
struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG);
msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) {
memp_free(MEMP_API_MSG, apimsg);
return;
@@ -162,7 +169,7 @@ tcpip_apimsg(struct api_msg *apimsg)
msg->msg.apimsg = apimsg;
sys_mbox_post(mbox, msg);
}
/*-----------------------------------------------------------------------------------*/
void
tcpip_init(void (* initfunc)(void *), void *arg)
{
@@ -171,7 +178,7 @@ tcpip_init(void (* initfunc)(void *), void *arg)
mbox = sys_mbox_new();
sys_thread_new(tcpip_thread, NULL, TCPIP_THREAD_PRIO);
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -6,8 +6,8 @@
/*
*
* Copyright (c) 2001-2003 Leon Woestenberg <leon.woestenberg@gmx.net>
* Copyright (c) 2001-2003 Axon Digital Design B.V., The Netherlands.
* Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
* Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -67,20 +67,26 @@
* to remove the DHCP client.
*
*/
#include <string.h>
#include "lwip/stats.h"
#include "lwip/mem.h"
#include "lwip/udp.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/inet.h"
#include "lwip/ip_addr.h"
#include "netif/etharp.h"
#include "lwip/sys.h"
#include "lwip/opt.h"
#include "lwip/dhcp.h"
#if LWIP_DHCP /* don't build if not configured for use in lwipopt.h */
/** global transaction identifier, must be
* unique for each DHCP request. */
* unique for each DHCP request. We simply increment, starting
* with this value (easy to match with a packet analyzer) */
static u32_t xid = 0xABCD0000;
/** DHCP client state machine functions */
@@ -94,7 +100,6 @@ static void dhcp_check(struct netif *netif);
static void dhcp_bind(struct netif *netif);
static err_t dhcp_decline(struct netif *netif);
static err_t dhcp_rebind(struct netif *netif);
static err_t dhcp_release(struct netif *netif);
static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state);
/** receive, unfold, parse and free incoming messages */
@@ -192,6 +197,7 @@ static void dhcp_handle_offer(struct netif *netif)
/* remember offered address */
ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08lx\n", dhcp->offered_ip_addr.addr));
dhcp_select(netif);
}
}
@@ -228,10 +234,11 @@ static err_t dhcp_select(struct netif *netif)
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
dhcp_option_trailer(dhcp);
/* shrink the pbuf to the actual content length */
@@ -290,18 +297,20 @@ void dhcp_coarse_tmr()
/**
* DHCP transaction timeout handling
*
* A DHCP server is expected to respond within a
* short period of time.
* A DHCP server is expected to respond within a short period of time.
* This timer checks whether an outstanding DHCP request is timed out.
*
*/
void dhcp_fine_tmr()
{
struct netif *netif = netif_list;
/* loop through clients */
/* loop through netif's */
while (netif != NULL) {
/* only act on DHCP configured interfaces */
if (netif->dhcp != NULL) {
/* timer is active (non zero), and triggers (zeroes) now */
/* timer is active (non zero), and is about to trigger now */
if (netif->dhcp->request_timeout-- == 1) {
/* { netif->dhcp->request_timeout == 0 } */
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
/* this clients' request timeout triggered */
dhcp_timeout(netif);
@@ -380,8 +389,8 @@ static void dhcp_t1_timeout(struct netif *netif)
struct dhcp *dhcp = netif->dhcp;
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_t1_timeout()\n"));
if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
/* just retry to renew */
/* note that the rebind timer will eventually time-out if renew does not work */
/* just retry to renew - note that the rebind timer (t2) will
* eventually time-out if renew tries fail. */
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
dhcp_renew(netif);
}
@@ -403,7 +412,6 @@ static void dhcp_t2_timeout(struct netif *netif)
}
/**
* Extract options from the server ACK message.
*
* @param netif the netif under DHCP control
*/
@@ -477,6 +485,19 @@ static void dhcp_handle_ack(struct netif *netif)
if (option_ptr != NULL) {
dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
}
/* DNS servers */
option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_DNS_SERVER);
if (option_ptr != NULL) {
u8_t n;
dhcp->dns_count = dhcp_get_option_byte(&option_ptr[1]);
/* limit to at most DHCP_MAX_DNS DNS servers */
if (dhcp->dns_count > DHCP_MAX_DNS) dhcp->dns_count = DHCP_MAX_DNS;
for (n = 0; n < dhcp->dns_count; n++)
{
dhcp->offered_dns_addr[n].addr = htonl(dhcp_get_option_long(&option_ptr[2+(n<<2)]));
}
}
}
/**
@@ -499,39 +520,43 @@ err_t dhcp_start(struct netif *netif)
LWIP_ASSERT("netif != NULL", netif != NULL);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
netif->flags &= ~NETIF_FLAG_DHCP;
/* no DHCP client attached yet? */
if (dhcp == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
dhcp = mem_malloc(sizeof(struct dhcp));
if (dhcp == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
netif->flags &= ~NETIF_FLAG_DHCP;
return ERR_MEM;
}
/* clear data structure */
memset(dhcp, 0, sizeof(struct dhcp));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp"));
dhcp->pcb = udp_new();
if (dhcp->pcb == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
mem_free((void *)dhcp);
dhcp = NULL;
netif->flags &= ~NETIF_FLAG_DHCP;
return ERR_MEM;
}
/* store this dhcp client in the netif */
netif->dhcp = dhcp;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): created new udp pcb\n"));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp"));
/* already has DHCP client attached */
} else {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n"));
}
/* clear data structure */
memset(dhcp, 0, sizeof(struct dhcp));
/* allocate UDP PCB */
dhcp->pcb = udp_new();
if (dhcp->pcb == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
mem_free((void *)dhcp);
netif->dhcp = dhcp = NULL;
return ERR_MEM;
}
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
/* (re)start the DHCP negotiation */
result = dhcp_discover(netif);
if (result != ERR_OK) {
/* free resources allocated above */
dhcp_stop(netif);
return ERR_MEM;
}
netif->flags |= NETIF_FLAG_DHCP;
return result;
}
@@ -646,13 +671,18 @@ static err_t dhcp_decline(struct netif *netif)
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
dhcp_option_short(dhcp, 576);
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
dhcp_option_trailer(dhcp);
/* resize pbuf to reflect true size of options */
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
udp_send(dhcp->pcb, dhcp->p_out);
/* @todo: should we really connect here? we are performing sendto() */
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
/* per section 4.4.4, broadcast DECLINE messages */
udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
} else {
@@ -689,10 +719,11 @@ static err_t dhcp_discover(struct netif *netif)
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
dhcp_option_short(dhcp, 576);
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
dhcp_option_trailer(dhcp);
@@ -702,15 +733,9 @@ static err_t dhcp_discover(struct netif *netif)
/* set receive callback function with netif as user data */
udp_recv(dhcp->pcb, dhcp_recv, netif);
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: send()ing\n"));
udp_send(dhcp->pcb, dhcp->p_out);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: bind()ing\n"));
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: connect()ing\n"));
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover: SELECTING\n"));
@@ -782,6 +807,8 @@ static void dhcp_bind(struct netif *netif)
netif_set_netmask(netif, &sn_mask);
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08lx\n", gw_addr.addr));
netif_set_gw(netif, &gw_addr);
/* bring the interface up */
netif_set_up(netif);
/* netif is now bound to DHCP leased address */
dhcp_set_state(dhcp, DHCP_BOUND);
}
@@ -877,10 +904,11 @@ static err_t dhcp_rebind(struct netif *netif)
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
/* set remote IP association to any DHCP server */
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
udp_send(dhcp->pcb, dhcp->p_out);
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
/* broadcast to server */
udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind: REBINDING\n"));
} else {
@@ -898,7 +926,7 @@ static err_t dhcp_rebind(struct netif *netif)
*
* @param netif network interface which must release its lease
*/
static err_t dhcp_release(struct netif *netif)
err_t dhcp_release(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
err_t result;
@@ -907,8 +935,13 @@ static err_t dhcp_release(struct netif *netif)
/* idle DHCP client */
dhcp_set_state(dhcp, DHCP_OFF);
/* clean old DHCP offer */
dhcp->server_ip_addr.addr = 0;
dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0;
dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0;
dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
dhcp->dns_count = 0;
/* create and initialize the DHCP message header */
result = dhcp_create_request(netif);
if (result == ERR_OK) {
@@ -930,11 +963,14 @@ static err_t dhcp_release(struct netif *netif)
dhcp->tries++;
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %u msecs\n", msecs));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %u msecs\n", msecs));
/* bring the interface down */
netif_set_down(netif);
/* remove IP address from interface */
netif_set_ipaddr(netif, IP_ADDR_ANY);
netif_set_gw(netif, IP_ADDR_ANY);
netif_set_netmask(netif, IP_ADDR_ANY);
/* TODO: netif_down(netif); */
return result;
}
@@ -1239,10 +1275,10 @@ static err_t dhcp_create_request(struct netif *netif)
dhcp->msg_out->xid = htonl(dhcp->xid);
dhcp->msg_out->secs = 0;
dhcp->msg_out->flags = 0;
dhcp->msg_out->ciaddr = netif->ip_addr.addr;
dhcp->msg_out->yiaddr = 0;
dhcp->msg_out->siaddr = 0;
dhcp->msg_out->giaddr = 0;
dhcp->msg_out->ciaddr.addr = netif->ip_addr.addr;
dhcp->msg_out->yiaddr.addr = 0;
dhcp->msg_out->siaddr.addr = 0;
dhcp->msg_out->giaddr.addr = 0;
for (i = 0; i < DHCP_CHADDR_LEN; i++) {
/* copy netif hardware address, pad with zeroes */
dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
@@ -1414,3 +1450,5 @@ static u32_t dhcp_get_option_long(u8_t *ptr)
LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%lu\n", value));
return value;
}
#endif /* LWIP_DHCP */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -30,14 +30,14 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* inet.c
*
* Functions common to all TCP/IP modules, such as the Internet checksum and the
* byte order functions.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -46,10 +46,21 @@
#include "lwip/def.h"
#include "lwip/inet.h"
#include "lwip/sys.h"
/*-----------------------------------------------------------------------------------*/
/* This is a reference implementation of the checksum algorithm
- it may not work on all architectures, and all processors, particularly
if they have issues with alignment and 16 bit access.
- in this case you will need to port it to your architecture and
#define LWIP_CHKSUM <your_checksum_routine>
in your sys_arch.h
*/
#ifndef LWIP_CHKSUM
#define LWIP_CHKSUM lwip_standard_chksum
static u16_t
lwip_chksum(void *dataptr, int len)
lwip_standard_chksum(void *dataptr, int len)
{
u32_t acc;
@@ -75,12 +86,13 @@ lwip_chksum(void *dataptr, int len)
return (u16_t)acc;
}
/*-----------------------------------------------------------------------------------*/
#endif
/* inet_chksum_pseudo:
*
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
*/
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pseudo(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest,
@@ -96,7 +108,7 @@ inet_chksum_pseudo(struct pbuf *p,
for(q = p; q != NULL; q = q->next) {
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
(void *)q, (void *)q->next));
acc += lwip_chksum(q->payload, q->len);
acc += LWIP_CHKSUM(q->payload, q->len);
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%lx \n", acc));*/
while (acc >> 16) {
acc = (acc & 0xffffUL) + (acc >> 16);
@@ -122,27 +134,27 @@ inet_chksum_pseudo(struct pbuf *p,
acc = (acc & 0xffffUL) + (acc >> 16);
}
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
return ~(acc & 0xffffUL);
return (u16_t)~(acc & 0xffffUL);
}
/*-----------------------------------------------------------------------------------*/
/* inet_chksum:
*
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
* and ICMP.
*/
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum(void *dataptr, u16_t len)
{
u32_t acc;
acc = lwip_chksum(dataptr, len);
acc = LWIP_CHKSUM(dataptr, len);
while (acc >> 16) {
acc = (acc & 0xffff) + (acc >> 16);
}
return ~(acc & 0xffff);
return (u16_t)~(acc & 0xffff);
}
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pbuf(struct pbuf *p)
{
@@ -153,7 +165,7 @@ inet_chksum_pbuf(struct pbuf *p)
acc = 0;
swapped = 0;
for(q = p; q != NULL; q = q->next) {
acc += lwip_chksum(q->payload, q->len);
acc += LWIP_CHKSUM(q->payload, q->len);
while (acc >> 16) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
@@ -166,10 +178,20 @@ inet_chksum_pbuf(struct pbuf *p)
if (swapped) {
acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
}
return ~(acc & 0xffffUL);
return (u16_t)~(acc & 0xffffUL);
}
/*-----------------------------------------------------------------------------------*/
/* Here for now until needed in other places in lwIP */
#ifndef isascii
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
#define isascii(c) in_range(c, 0x20, 0x7f)
#define isdigit(c) in_range(c, '0', '9')
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
#define islower(c) in_range(c, 'a', 'z')
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
#endif
/*
* Ascii internet address interpretation routine.
* The value returned is in network order.
@@ -222,12 +244,12 @@ inet_chksum_pbuf(struct pbuf *p)
base = 8;
}
for (;;) {
if (isascii(c) && isdigit(c)) {
val = (val * base) + (c - '0');
if (isdigit(c)) {
val = (val * base) + (int)(c - '0');
c = *++cp;
} else if (base == 16 && isascii(c) && isxdigit(c)) {
} else if (base == 16 && isxdigit(c)) {
val = (val << 4) |
(c + 10 - (islower(c) ? 'a' : 'A'));
(int)(c + 10 - (islower(c) ? 'a' : 'A'));
c = *++cp;
} else
break;
@@ -290,18 +312,19 @@ inet_chksum_pbuf(struct pbuf *p)
/* Convert numeric IP address into decimal dotted ASCII representation.
* returns ptr to static buffer; not reentrant!
*/
u8_t *inet_ntoa(u32_t addr)
char *inet_ntoa(struct in_addr addr)
{
static u8_t str[16];
u8_t inv[3];
u8_t *rp;
static char str[16];
u32_t s_addr = addr.s_addr;
char inv[3];
char *rp;
u8_t *ap;
u8_t rem;
u8_t n;
u8_t i;
rp = str;
ap = (u8_t *)&addr;
ap = (u8_t *)&s_addr;
for(n = 0; n < 4; n++) {
i = 0;
do {
@@ -318,24 +341,24 @@ u8_t *inet_ntoa(u32_t addr)
return str;
}
/*-----------------------------------------------------------------------------------*/
#ifndef BYTE_ORDER
#error BYTE_ORDER is not defined
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
/*-----------------------------------------------------------------------------------*/
u16_t
htons(u16_t n)
{
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
}
/*-----------------------------------------------------------------------------------*/
u16_t
ntohs(u16_t n)
{
return htons(n);
}
/*-----------------------------------------------------------------------------------*/
u32_t
htonl(u32_t n)
{
@@ -344,11 +367,11 @@ htonl(u32_t n)
((n & 0xff0000) >> 8) |
((n & 0xff000000) >> 24);
}
/*-----------------------------------------------------------------------------------*/
u32_t
ntohl(u32_t n)
{
return htonl(n);
}
/*-----------------------------------------------------------------------------------*/
#endif /* BYTE_ORDER == LITTLE_ENDIAN */

View File

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

View File

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

View File

@@ -1,5 +1,12 @@
/* @file
*
* This is the IP layer implementation for incoming and outgoing IP traffic.
*
* @see ip_frag.c
*
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -30,18 +37,8 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* ip.c
*
* This is the code for the IP layer.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/ip.h"
@@ -49,6 +46,7 @@
#include "lwip/inet.h"
#include "lwip/netif.h"
#include "lwip/icmp.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
@@ -61,75 +59,24 @@
# include "lwip/dhcp.h"
#endif /* LWIP_DHCP */
/*-----------------------------------------------------------------------------------*/
/* ip_init:
*
/**
* Initializes the IP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_init(void)
{
/* no initializations as of yet */
}
/*-----------------------------------------------------------------------------------*/
/* ip_lookup:
*
* An experimental feature that will be changed in future versions. Do
* not depend on it yet...
*/
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
u8_t
ip_lookup(void *header, struct netif *inp)
{
struct ip_hdr *iphdr;
iphdr = header;
/* not IP v4? */
if (IPH_V(iphdr) != 4) {
return 0;
}
/* Immediately accept/decline packets that are fragments or has
options. */
#if IP_REASSEMBLY == 0
/* if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
return 0;
}*/
#endif /* IP_REASSEMBLY == 0 */
#if IP_OPTIONS == 0
if (IPH_HL(iphdr) != 5) {
return 0;
}
#endif /* IP_OPTIONS == 0 */
switch (IPH_PROTO(iphdr)) {
#if LWIP_UDP > 0
case IP_PROTO_UDP:
return udp_lookup(iphdr, inp);
#endif /* LWIP_UDP */
#if LWIP_TCP > 0
case IP_PROTO_TCP:
return 1;
#endif /* LWIP_TCP */
case IP_PROTO_ICMP:
return 1;
default:
return 0;
}
}
#endif /* LWIP_DEBUG */
/*-----------------------------------------------------------------------------------*/
/* ip_route:
*
/**
* Finds the appropriate network interface for a given IP address. It
* searches the list of network interfaces linearly. A match is found
* if the masked IP address of the network interface equals the masked
* IP address given to the function.
*/
/*-----------------------------------------------------------------------------------*/
struct netif *
ip_route(struct ip_addr *dest)
{
@@ -138,7 +85,7 @@ ip_route(struct ip_addr *dest)
/* iterate through netifs */
for(netif = netif_list; netif != NULL; netif = netif->next) {
/* network mask matches? */
if (ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
/* return netif on which to forward IP packet */
return netif;
}
@@ -147,15 +94,14 @@ ip_route(struct ip_addr *dest)
return netif_default;
}
#if IP_FORWARD
/*-----------------------------------------------------------------------------------*/
/* ip_forward:
*
/**
* Forwards an IP packet. It finds an appropriate route for the
* packet, decrements the TTL value of the packet, adjusts the
* checksum and outputs the packet on the appropriate interface.
*/
/*-----------------------------------------------------------------------------------*/
static void
static struct netif *
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
{
struct netif *netif;
@@ -167,14 +113,14 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%lx found\n",
iphdr->dest.addr));
snmp_inc_ipnoroutes();
return;
return (struct netif *)NULL;
}
/* Do not forward packets onto the same network interface on which
they arrived. */
* they arrived. */
if (netif == inp) {
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
snmp_inc_ipnoroutes();
return;
return (struct netif *)NULL;
}
/* decrement TTL */
@@ -186,7 +132,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
icmp_time_exceeded(p, ICMP_TE_TTL);
snmp_inc_icmpouttimeexcds();
}
return;
return (struct netif *)NULL;
}
/* Incrementally update the IP checksum. */
@@ -199,20 +145,18 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
iphdr->dest.addr));
#ifdef IP_STATS
++lwip_stats.ip.fw;
++lwip_stats.ip.xmit;
#endif /* IP_STATS */
IP_STATS_INC(ip.fw);
IP_STATS_INC(ip.xmit);
snmp_inc_ipforwdatagrams();
PERF_STOP("ip_forward");
/* transmit pbuf on chosen interface */
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
return netif;
}
#endif /* IP_FORWARD */
/*-----------------------------------------------------------------------------------*/
/* ip_input:
*
/**
* This function is called by the network interface device driver when
* an IP packet is received. The function does the basic checks of the
* IP header such as packet size being at least larger than the header
@@ -220,31 +164,28 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
* forwarded (using ip_forward). The IP checksum is always checked.
*
* Finally, the packet is sent to the upper layer protocol input function.
*
*
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_input(struct pbuf *p, struct netif *inp) {
static struct ip_hdr *iphdr;
static struct netif *netif;
static u16_t iphdrlen;
struct ip_hdr *iphdr;
struct netif *netif;
u16_t iphdrlen;
#ifdef IP_STATS
++lwip_stats.ip.recv;
#endif /* IP_STATS */
IP_STATS_INC(ip.recv);
snmp_inc_ipinreceives();
/* identify the IP header */
iphdr = p->payload;
if (IPH_V(iphdr) != 4) {
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %u\n", IPH_V(iphdr)));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.err;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.err);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
@@ -259,64 +200,58 @@ ip_input(struct pbuf *p, struct netif *inp) {
iphdrlen, p->len));
/* free (drop) packet pbufs */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.lenerr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.lenerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipindiscards();
return ERR_OK;
}
/* verify checksum */
#if CHECKSUM_CHECK_IP
if (inet_chksum(iphdr, iphdrlen) != 0) {
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.chkerr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.chkerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipindiscards();
return ERR_OK;
}
#endif
/* Trim pbuf. This should have been done at the netif layer,
but we'll do it anyway just to be sure that its done. */
* but we'll do it anyway just to be sure that its done. */
pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
/* is this packet for us? */
for(netif = netif_list; netif != NULL; netif = netif->next) {
/* match packet against an interface, i.e. is this packet for us? */
for (netif = netif_list; netif != NULL; netif = netif->next) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%lx netif->ip_addr 0x%lx (0x%lx, 0x%lx, 0x%lx)\n",
iphdr->dest.addr, netif->ip_addr.addr,
iphdr->dest.addr & netif->netmask.addr,
netif->ip_addr.addr & netif->netmask.addr,
iphdr->dest.addr & ~(netif->netmask.addr)));
iphdr->dest.addr, netif->ip_addr.addr,
iphdr->dest.addr & netif->netmask.addr,
netif->ip_addr.addr & netif->netmask.addr,
iphdr->dest.addr & ~(netif->netmask.addr)));
/* interface configured? */
if (!ip_addr_isany(&(netif->ip_addr)))
/* interface is up and configured? */
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
{
/* unicast to this interface address? */
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
/* or broadcast matching this interface network address? */
(ip_addr_isbroadcast(&(iphdr->dest), &(netif->netmask)) &&
ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) ||
/* or restricted broadcast? */
ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
netif->name[0], netif->name[1]));
/* break out of for loop */
break;
/* or broadcast on this interface network address? */
ip_addr_isbroadcast(&(iphdr->dest), netif)) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
netif->name[0], netif->name[1]));
/* break out of for loop */
break;
}
}
}
#if LWIP_DHCP
/* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
According to RFC 1542 section 3.1.1, referred by RFC 2131). */
* using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
* According to RFC 1542 section 3.1.1, referred by RFC 2131).
*/
if (netif == NULL) {
/* remote port is DHCP server? */
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
@@ -329,13 +264,13 @@ ip_input(struct pbuf *p, struct netif *inp) {
}
}
#endif /* LWIP_DHCP */
/* packet not for us? */
/* packet not for us? */
if (netif == NULL) {
/* packet not for us, route or discard */
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
#if IP_FORWARD
/* non-broadcast packet? */
if (!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask))) {
if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
/* try to forward IP packet on (other) interfaces */
ip_forward(p, iphdr, inp);
}
@@ -347,59 +282,59 @@ ip_input(struct pbuf *p, struct netif *inp) {
pbuf_free(p);
return ERR_OK;
}
#if IP_REASSEMBLY
/* packet consists of multiple fragments? */
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04x tot_len=%u len=%u MF=%u offset=%u), calling ip_reass()\n",
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
/* reassemble the packet*/
p = ip_reass(p);
/* packet not fully reassembled yet? */
if (p == NULL) {
return ERR_OK;
}
iphdr = p->payload;
}
#else /* IP_REASSEMBLY */
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
ntohs(IPH_OFFSET(iphdr))));
#ifdef IP_STATS
++lwip_stats.ip.opterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
ntohs(IPH_OFFSET(iphdr))));
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
#endif /* IP_REASSEMBLY */
}
#if IP_OPTIONS == 0
#if IP_OPTIONS == 0 /* no support for IP options in the IP header? */
if (iphdrlen > IP_HLEN) {
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.opterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
#endif /* IP_OPTIONS == 0 */
/* send to upper layers */
#if IP_DEBUG
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
ip_debug_print(p);
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
#endif /* IP_DEBUG */
#if LWIP_RAW
/* raw input did not eat the packet? */
if (raw_input(p, inp) == 0) {
#endif /* LWIP_RAW */
switch (IPH_PROTO(iphdr)) {
#if LWIP_UDP > 0
#if LWIP_UDP
case IP_PROTO_UDP:
case IP_PROTO_UDPLITE:
snmp_inc_ipindelivers();
udp_input(p, inp);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP > 0
#if LWIP_TCP
case IP_PROTO_TCP:
snmp_inc_ipindelivers();
tcp_input(p, inp);
@@ -411,8 +346,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
break;
default:
/* send ICMP destination protocol unreachable unless is was a broadcast */
if (!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) &&
!ip_addr_ismulticast(&(iphdr->dest))) {
if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
!ip_addr_ismulticast(&(iphdr->dest))) {
p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PROTO);
}
@@ -420,32 +355,30 @@ ip_input(struct pbuf *p, struct netif *inp) {
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
#ifdef IP_STATS
++lwip_stats.ip.proterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.proterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
}
#if LWIP_RAW
} /* LWIP_RAW */
#endif
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* ip_output_if:
*
/**
* Sends an IP packet on a network interface. This function constructs
* the IP header and calculates the IP header checksum. If the source
* IP address is NULL, the IP address of the outgoing network
* interface is filled in as source address.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl,
ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t tos,
u8_t proto, struct netif *netif)
{
static struct ip_hdr *iphdr;
static u16_t ip_id = 0;
struct ip_hdr *iphdr;
u16_t ip_id = 0;
snmp_inc_ipoutrequests();
@@ -453,9 +386,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
if (pbuf_header(p, IP_HLEN)) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
#ifdef IP_STATS
++lwip_stats.ip.err;
#endif /* IP_STATS */
IP_STATS_INC(ip.err);
snmp_inc_ipoutdiscards();
return ERR_BUF;
}
@@ -467,7 +398,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
ip_addr_set(&(iphdr->dest), dest);
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
IPH_LEN_SET(iphdr, htons(p->tot_len));
IPH_OFFSET_SET(iphdr, htons(IP_DF));
IPH_ID_SET(iphdr, htons(ip_id));
@@ -480,7 +411,9 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
}
IPH_CHKSUM_SET(iphdr, 0);
#if CHECKSUM_GEN_IP
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
#endif
} else {
iphdr = p->payload;
dest = &(iphdr->dest);
@@ -492,44 +425,38 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
return ip_frag(p,netif,dest);
#endif
#ifdef IP_STATS
lwip_stats.ip.xmit++;
#endif /* IP_STATS */
IP_STATS_INC(ip.xmit);
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
return netif->output(netif, p, dest);
}
/*-----------------------------------------------------------------------------------*/
/* ip_output:
*
/**
* Simple interface to ip_output_if. It finds the outgoing network
* interface and calls upon ip_output_if to do the actual work.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto)
u8_t ttl, u8_t tos, u8_t proto)
{
struct netif *netif;
if ((netif = ip_route(dest)) == NULL) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr));
#ifdef IP_STATS
++lwip_stats.ip.rterr;
#endif /* IP_STATS */
IP_STATS_INC(ip.rterr);
snmp_inc_ipoutdiscards();
return ERR_RTE;
}
return ip_output_if (p, src, dest, ttl, proto, netif);
return ip_output_if(p, src, dest, ttl, tos, proto, netif);
}
/*-----------------------------------------------------------------------------------*/
#if IP_DEBUG
void
ip_debug_print(struct pbuf *p)
@@ -559,21 +486,21 @@ ip_debug_print(struct pbuf *p)
IPH_PROTO(iphdr),
ntohs(IPH_CHKSUM(iphdr))));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (src)\n",
ntohl(iphdr->src.addr) >> 24 & 0xff,
ntohl(iphdr->src.addr) >> 16 & 0xff,
ntohl(iphdr->src.addr) >> 8 & 0xff,
ntohl(iphdr->src.addr) & 0xff));
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | %3u | %3u | (src)\n",
ip4_addr1(&iphdr->src),
ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src),
ip4_addr4(&iphdr->src)));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (dest)\n",
ntohl(iphdr->dest.addr) >> 24 & 0xff,
ntohl(iphdr->dest.addr) >> 16 & 0xff,
ntohl(iphdr->dest.addr) >> 8 & 0xff,
ntohl(iphdr->dest.addr) & 0xff));
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | %3u | %3u | (dest)\n",
ip4_addr1(&iphdr->dest),
ip4_addr2(&iphdr->dest),
ip4_addr3(&iphdr->dest),
ip4_addr4(&iphdr->dest)));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -32,7 +32,41 @@
#include "lwip/ip_addr.h"
#include "lwip/inet.h"
#include "lwip/netif.h"
/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
const struct ip_addr ip_addr_any = { 0x00000000UL };
const struct ip_addr ip_addr_broadcast = { 0xffffffffUL };
/* Determine if an address is a broadcast address on a network interface
*
* @param addr address to be checked
* @param netif the network interface against which the address is checked
* @return returns non-zero if the address is a broadcast address
*
*/
u8_t ip_addr_isbroadcast(struct ip_addr *addr, struct netif *netif)
{
/* all ones (broadcast) or all zeroes (old skool broadcast) */
if ((addr->addr == ip_addr_broadcast.addr) ||
(addr->addr == ip_addr_any.addr))
return 1;
/* no broadcast support on this network interface? */
else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0)
/* the given address cannot be a broadcast address
* nor can we check against any broadcast addresses */
return 0;
/* address matches network interface address exactly? => no broadcast */
else if (addr->addr == netif->ip_addr.addr)
return 0;
/* on the same (sub) network... */
else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask))
/* ...and host identifier bits are all ones? =>... */
&& ((addr->addr & ~netif->netmask.addr) ==
(ip_addr_broadcast.addr & ~netif->netmask.addr)))
/* => network broadcast address */
return 1;
else
return 0;
}

View File

@@ -1,5 +1,11 @@
/* @file
*
* This is the IP packet segmentation and reassembly implementation.
*
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -31,14 +37,6 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* ip_frag.c
*
* This is the code for IP segmentation and reassembly
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/ip.h"
@@ -109,9 +107,7 @@ ip_reass(struct pbuf *p)
u16_t offset, len;
u16_t i;
#ifdef IP_STATS
++lwip_stats.ip_frag.recv;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.recv);
iphdr = (struct ip_hdr *) ip_reassbuf;
fraghdr = (struct ip_hdr *) p->payload;
@@ -135,9 +131,7 @@ ip_reass(struct pbuf *p)
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n"));
#ifdef IP_STATS
++lwip_stats.ip_frag.cachehit;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.cachehit);
/* Find out the offset in the reassembly buffer where we should
copy the fragment. */
len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
@@ -249,19 +243,15 @@ ip_reass(struct pbuf *p)
variable. */
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: memcpy from %p (%d) to %p, %d bytes\n",
&ip_reassbuf[i], i, q->payload,
(void *)&ip_reassbuf[i], i, q->payload,
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
memcpy(q->payload, &ip_reassbuf[i],
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
i += q->len;
}
#ifdef IP_STATS
++lwip_stats.ip_frag.fw;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.fw);
} else {
#ifdef IP_STATS
++lwip_stats.ip_frag.memerr;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.memerr);
}
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
return p;
@@ -269,9 +259,7 @@ ip_reass(struct pbuf *p)
}
nullreturn:
#ifdef IP_STATS
++lwip_stats.ip_frag.drop;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.drop);
pbuf_free(p);
return NULL;
}
@@ -304,7 +292,6 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
rambuf->tot_len = rambuf->len = mtu;
rambuf->payload = MEM_ALIGN((void *)buf);
/* Copy the IP header in it */
iphdr = rambuf->payload;
memcpy(iphdr, p->payload, IP_HLEN);
@@ -347,9 +334,7 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
pbuf_chain(header, rambuf);
netif->output(netif, header, dest);
#ifdef IP_STATS
++lwip_stats.ip_frag.xmit;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.xmit);
pbuf_free(header);
left -= cop;

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -31,13 +31,13 @@
*/
/*-----------------------------------------------------------------------------------*/
/* ip.c
*
* This is the code for the IP layer for IPv6.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@@ -53,45 +53,45 @@
#include "lwip/stats.h"
#include "arch/perf.h"
/*-----------------------------------------------------------------------------------*/
/* ip_init:
*
* Initializes the IP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_init(void)
{
}
/*-----------------------------------------------------------------------------------*/
/* ip_route:
*
* Finds the appropriate network interface for a given IP address. It searches the
* list of network interfaces linearly. A match is found if the masked IP address of
* the network interface equals the masked IP address given to the function.
*/
/*-----------------------------------------------------------------------------------*/
struct netif *
ip_route(struct ip_addr *dest)
{
struct netif *netif;
for(netif = netif_list; netif != NULL; netif = netif->next) {
if (ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
return netif;
}
}
return netif_default;
}
/*-----------------------------------------------------------------------------------*/
/* ip_forward:
*
* Forwards an IP packet. It finds an appropriate route for the packet, decrements
* the TTL value of the packet, adjusts the checksum and outputs the packet on the
* appropriate interface.
*/
/*-----------------------------------------------------------------------------------*/
static void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
{
@@ -142,7 +142,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
}
/*-----------------------------------------------------------------------------------*/
/* ip_input:
*
* This function is called by the network interface device driver when an IP packet is
@@ -152,7 +152,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
*
* Finally, the packet is sent to the upper layer protocol input function.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_input(struct pbuf *p, struct netif *inp) {
struct ip_hdr *iphdr;
@@ -249,14 +249,14 @@ ip_input(struct pbuf *p, struct netif *inp) {
PERF_STOP("ip_input");
}
/*-----------------------------------------------------------------------------------*/
/* ip_output_if:
*
* Sends an IP packet on a network interface. This function constructs the IP header
* and calculates the IP header checksum. If the source IP address is NULL,
* the IP address of the outgoing network interface is filled in as source address.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl,
@@ -311,13 +311,13 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
PERF_STOP("ip_output_if");
return netif->output(netif, p, dest);
}
/*-----------------------------------------------------------------------------------*/
/* ip_output:
*
* Simple interface to ip_output_if. It finds the outgoing network interface and
* calls upon ip_output_if to do the actual work.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto)
@@ -333,7 +333,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
return ip_output_if (p, src, dest, ttl, proto, netif);
}
/*-----------------------------------------------------------------------------------*/
#if IP_DEBUG
void
ip_debug_print(struct pbuf *p)
@@ -383,4 +383,4 @@ ip_debug_print(struct pbuf *p)
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/

View File

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

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -36,6 +36,7 @@
*
*/
#include <string.h>
#include "lwip/arch.h"
#include "lwip/opt.h"
@@ -54,6 +55,8 @@ struct mem {
u16_t used;
#elif MEM_ALIGNMENT == 4
u32_t used;
#elif MEM_ALIGNMENT == 8
u64_t used;
#else
#error "unhandled MEM_ALIGNMENT size"
#endif /* MEM_ALIGNMENT */
@@ -127,7 +130,7 @@ mem_init(void)
lfree = (struct mem *)ram;
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.avail = MEM_SIZE;
#endif /* MEM_STATS */
}
@@ -148,7 +151,7 @@ mem_free(void *rmem)
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
#ifdef MEM_STATS
#if MEM_STATS
++lwip_stats.mem.err;
#endif /* MEM_STATS */
sys_sem_signal(mem_sem);
@@ -164,7 +167,7 @@ mem_free(void *rmem)
lfree = mem;
}
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
#endif /* MEM_STATS */
@@ -183,7 +186,7 @@ mem_reallocm(void *rmem, mem_size_t newsize)
mem_free(rmem);
return nmem;
}
/*-----------------------------------------------------------------------------------*/
void *
mem_realloc(void *rmem, mem_size_t newsize)
{
@@ -215,7 +218,7 @@ mem_realloc(void *rmem, mem_size_t newsize)
ptr = (u8_t *)mem - ram;
size = mem->next - ptr - SIZEOF_STRUCT_MEM;
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.used -= (size - newsize);
#endif /* MEM_STATS */
@@ -273,7 +276,7 @@ mem_malloc(mem_size_t size)
mem2->used = 0;
mem->used = 1;
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
/* if (lwip_stats.mem.max < lwip_stats.mem.used) {
lwip_stats.mem.max = lwip_stats.mem.used;
@@ -292,14 +295,14 @@ mem_malloc(mem_size_t size)
}
sys_sem_signal(mem_sem);
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
(u32_t)mem + SIZEOF_STRUCT_MEM + size <= (u32_t)ram_end);
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
(unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
}
}
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size));
#ifdef MEM_STATS
#if MEM_STATS
++lwip_stats.mem.err;
#endif /* MEM_STATS */
sys_sem_signal(mem_sem);

View File

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

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -39,44 +39,36 @@
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/netif.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/tcp.h"
struct netif *netif_list = NULL;
struct netif *netif_default = NULL;
/**
* Add a network interface to the list of lwIP netifs.
*
* @param netif a pre-allocated netif structure
* @param ipaddr IP address for the new netif
* @param netmask network mask for the new netif
* @param gw default gateway IP address for the new netif
* @param state opaque data passed to the new netif
* @param init callback function that initializes the interface
* @param input callback function that...
* @param input callback function that is called to pass
* ingress packets up in the protocol layer stack.
*
* @return netif, or NULL if failed.
*/
struct netif *
netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
struct ip_addr *gw,
void *state,
err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif))
{
struct netif *netif;
static int netifnum = 0;
/* allocate netif structure */
netif = mem_malloc(sizeof(struct netif));
if (netif == NULL) {
LWIP_DEBUGF(NETIF_DEBUG, ("netif_add(): out of memory for netif\n"));
return NULL;
}
#if LWIP_DHCP
/* netif not under DHCP control by default */
netif->dhcp = NULL;
@@ -90,14 +82,12 @@ netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
/* call user specified initialization function for netif */
if (init(netif) != ERR_OK) {
mem_free(netif);
return NULL;
}
/* add this netif to the list */
netif->next = netif_list;
netif_list = netif;
#if NETIF_DEBUG
LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
netif->name[0], netif->name[1]));
ip_addr_debug_print(NETIF_DEBUG, ipaddr);
@@ -106,7 +96,6 @@ netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
ip_addr_debug_print(NETIF_DEBUG, gw);
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
#endif /* NETIF_DEBUG */
return netif;
}
@@ -144,7 +133,6 @@ void netif_remove(struct netif * netif)
/* reset default netif */
netif_default = NULL;
LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
mem_free( netif );
}
struct netif *
@@ -170,7 +158,7 @@ netif_find(char *name)
LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
return NULL;
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
{
@@ -183,7 +171,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
/* address is actually being changed? */
if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
{
extern struct tcp_pcb *tcp_active_pcbs;
/* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n"));
pcb = tcp_active_pcbs;
while (pcb != NULL) {
@@ -191,57 +179,64 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
/* this connection must be aborted */
struct tcp_pcb *next = pcb->next;
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting pcb %p\n", (void *)pcb));
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
tcp_abort(pcb);
pcb = next;
} else {
pcb = pcb->next;
}
}
for (lpcb = tcp_listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
/* PCB bound to current local interface address? */
if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {
/* The PCB is listening to the old ipaddr and
* is set to listen to the new one instead
* TODO: how do we know it is _listening_? */
* is set to listen to the new one instead */
ip_addr_set(&(lpcb->local_ip), ipaddr);
}
}
}
#endif
ip_addr_set(&(netif->ip_addr), ipaddr);
#if 0 /* only allowed for Ethernet interfaces TODO: how can we check? */
/** For Ethernet network interfaces, we would like to send a
* "gratuitous ARP"; this is an ARP packet sent by a node in order
* to spontaneously cause other nodes to update an entry in their
* ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6.
*/
etharp_query(netif, ipaddr, NULL);
#endif
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %u.%u.%u.%u\n",
netif->name[0], netif->name[1],
(unsigned int)(ntohl(netif->ip_addr.addr) >> 24 & 0xff),
(unsigned int)(ntohl(netif->ip_addr.addr) >> 16 & 0xff),
(unsigned int)(ntohl(netif->ip_addr.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->ip_addr.addr) & 0xff)));
ip4_addr1(&netif->ip_addr),
ip4_addr2(&netif->ip_addr),
ip4_addr3(&netif->ip_addr),
ip4_addr4(&netif->ip_addr)));
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_gw(struct netif *netif, struct ip_addr *gw)
{
ip_addr_set(&(netif->gw), gw);
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %u.%u.%u.%u\n",
netif->name[0], netif->name[1],
(unsigned int)(ntohl(netif->gw.addr) >> 24 & 0xff),
(unsigned int)(ntohl(netif->gw.addr) >> 16 & 0xff),
(unsigned int)(ntohl(netif->gw.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->gw.addr) & 0xff)));
netif->name[0], netif->name[1],
ip4_addr1(&netif->gw),
ip4_addr2(&netif->gw),
ip4_addr3(&netif->gw),
ip4_addr4(&netif->gw)));
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
{
ip_addr_set(&(netif->netmask), netmask);
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %u.%u.%u.%u\n",
netif->name[0], netif->name[1],
(unsigned int)(ntohl(netif->netmask.addr) >> 24 & 0xff),
(unsigned int)(ntohl(netif->netmask.addr) >> 16 & 0xff),
(unsigned int)(ntohl(netif->netmask.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->netmask.addr) & 0xff)));
netif->name[0], netif->name[1],
ip4_addr1(&netif->netmask),
ip4_addr2(&netif->netmask),
ip4_addr3(&netif->netmask),
ip4_addr4(&netif->netmask)));
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_default(struct netif *netif)
{
@@ -249,10 +244,45 @@ netif_set_default(struct netif *netif)
LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
}
/*-----------------------------------------------------------------------------------*/
/**
* Bring an interface up, available for processing
* traffic.
*
* @note: Enabling DHCP on a down interface will make it come
* up once configured.
*
* @see dhcp_start()
*/
void netif_set_up(struct netif *netif)
{
netif->flags |= NETIF_FLAG_UP;
}
/**
* Ask if an interface is up
*/
u8_t netif_is_up(struct netif *netif)
{
return (netif->flags & NETIF_FLAG_UP)?1:0;
}
/**
* Bring an interface down, disabling any traffic processing.
*
* @note: Enabling DHCP on a down interface will make it come
* up once configured.
*
* @see dhcp_start()
*/
void netif_set_down(struct netif *netif)
{
netif->flags &= ~NETIF_FLAG_UP;
}
void
netif_init(void)
{
netif_list = netif_default = NULL;
}
/*-----------------------------------------------------------------------------------*/

View File

@@ -11,12 +11,15 @@
* list. This is called a "pbuf chain".
*
* Multiple packets may be queued, also using this singly linked list.
* This is called a "packet queue". So, a packet queue consists of one
* or more pbuf chains, each of which consist of one or more pbufs.
* This is called a "packet queue".
*
* So, a packet queue consists of one or more pbuf chains, each of
* which consist of one or more pbufs. Currently, queues are only
* supported in a limited section of lwIP, this is the etharp queueing
* code. Outside of this section no packet queues are supported yet.
*
* The differences between a pbuf chain and a packet queue are very
* subtle. Currently, queues are only supported in a limited section
* of lwIP, this is the etharp queueing code. Outside of this section
* no packet queues are supported as of yet.
* precise but subtle.
*
* The last pbuf of a packet has a ->tot_len field that equals the
* ->len field. It can be found by traversing the list. If the last
@@ -28,7 +31,7 @@
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -100,9 +103,9 @@ pbuf_init(void)
u16_t i;
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", (mem_ptr_t)pbuf_pool % MEM_ALIGNMENT == 0);
#ifdef PBUF_STATS
#if PBUF_STATS
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
#endif /* PBUF_STATS */
@@ -113,6 +116,7 @@ pbuf_init(void)
p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));
p->flags = PBUF_FLAG_POOL;
q = p;
p = p->next;
}
@@ -143,7 +147,7 @@ pbuf_pool_alloc(void)
/* Next, check the actual pbuf pool, but if the pool is locked, we
pretend to be out of buffers and return NULL. */
if (pbuf_pool_free_lock) {
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
return NULL;
@@ -156,7 +160,7 @@ pbuf_pool_alloc(void)
pbuf_pool = p->next;
}
#if !SYS_LIGHTWEIGHT_PROT
#ifdef PBUF_STATS
#if PBUF_STATS
} else {
++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
@@ -164,7 +168,7 @@ pbuf_pool_alloc(void)
pbuf_pool_alloc_lock = 0;
#endif /* SYS_LIGHTWEIGHT_PROT */
#ifdef PBUF_STATS
#if PBUF_STATS
if (p != NULL) {
++lwip_stats.pbuf.used;
if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) {
@@ -179,7 +183,7 @@ pbuf_pool_alloc(void)
/**
* Allocates a pbuf.
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
*
* The actual memory allocated for the pbuf is determined by the
* layer at which the pbuf is allocated and the requested size
@@ -243,7 +247,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
p = pbuf_pool_alloc();
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
if (p == NULL) {
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */
return NULL;
@@ -253,13 +257,11 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
/* make the payload pointer point 'offset' bytes into pbuf data memory */
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
((u32_t)p->payload % MEM_ALIGNMENT) == 0);
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
/* the total length of the pbuf chain is the requested size */
p->tot_len = length;
/* set the length of the first pbuf in the chain */
p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length;
/* set pbuf type */
p->flags = PBUF_FLAG_POOL;
/* set reference count (needed here in case we fail) */
p->ref = 1;
@@ -274,7 +276,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
q = pbuf_pool_alloc();
if (q == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */
/* free chain so far allocated */
@@ -289,10 +291,9 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
q->tot_len = rem_len;
/* this pbuf length is pool size, unless smaller sized tail */
q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
q->flags = PBUF_FLAG_POOL;
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
((u32_t)q->payload % MEM_ALIGNMENT) == 0);
((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
q->ref = 1;
/* calculate remaining length to be allocated */
rem_len -= q->len;
@@ -300,12 +301,12 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
r = q;
}
/* end of chain */
//r->next = NULL;
/*r->next = NULL;*/
break;
case PBUF_RAM:
/* If pbuf is to be allocated in RAM, allocate memory for it. */
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + length + offset));
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + offset) + MEM_ALIGN_SIZE(length));
if (p == NULL) {
return NULL;
}
@@ -316,14 +317,14 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
p->flags = PBUF_FLAG_RAM;
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
((u32_t)p->payload % MEM_ALIGNMENT) == 0);
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
break;
/* pbuf references existing (static constant) ROM payload? */
/* pbuf references existing (non-volatile static constant) ROM payload? */
case PBUF_ROM:
/* pbuf references existing (externally allocated) RAM payload? */
case PBUF_REF:
/* only allocate memory for the pbuf structure */
p = memp_mallocp(MEMP_PBUF);
p = memp_malloc(MEMP_PBUF);
if (p == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", flag == PBUF_ROM?"ROM":"REF"));
return NULL;
@@ -345,7 +346,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
}
#ifdef PBUF_STATS
#if PBUF_STATS
#define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
#else /* PBUF_STATS */
#define DEC_PBUF_STATS
@@ -412,7 +413,7 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
/* first, step over any pbufs that should remain in the chain */
rem_len = new_len;
q = p;
/* this pbuf should be kept? */
/* should this pbuf be kept? */
while (rem_len > q->len) {
/* decrease remaining length by pbuf length */
rem_len -= q->len;
@@ -452,83 +453,93 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
*
* The ->payload, ->tot_len and ->len fields are adjusted.
*
* @param hdr_size Number of bytes to increment header size which
* @param hdr_size_inc Number of bytes to increment header size which
* increases the size of the pbuf. New space is on the front.
* (Using a negative value decreases the header size.)
* If hdr_size_inc is 0, this function does nothing and returns succesful.
*
* PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
* the call will fail. A check is made that the increase in header size does
* not move the payload pointer in front of the start of the buffer.
* @return 1 on failure, 0 on success.
* @return non-zero on failure, zero on success.
*
* @note May not be called on a packet queue.
*/
u8_t
pbuf_header(struct pbuf *p, s16_t header_size)
pbuf_header(struct pbuf *p, s16_t header_size_increment)
{
void *payload;
LWIP_ASSERT("p != NULL", p != NULL);
if ((header_size_increment == 0) || (p == NULL)) return 0;
/* remember current payload pointer */
payload = p->payload;
/* pbuf types containing payloads? */
if (p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL) {
/* set new payload pointer */
p->payload = (u8_t *)p->payload - header_size;
p->payload = (u8_t *)p->payload - header_size_increment;
/* boundary check fails? */
if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p\n",
(u8_t *)p->payload,
(u8_t *)p + sizeof(struct pbuf)) );\
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
(void *)p->payload,
(void *)(p + 1)));\
/* restore old payload pointer */
p->payload = payload;
/* bail out unsuccesfully */
return 1;
}
/* pbuf types refering to payloads? */
/* pbuf types refering to external payloads? */
} else if (p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_ROM) {
/* hide a header in the payload? */
if ((header_size < 0) && (header_size - p->len <= 0)) {
if ((header_size_increment < 0) && (header_size_increment - p->len <= 0)) {
/* increase payload pointer */
p->payload = (u8_t *)p->payload - header_size;
p->payload = (u8_t *)p->payload - header_size_increment;
} else {
/* cannot expand payload to front (yet!)
* bail out unsuccesfully */
return 1;
}
}
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", (void *)payload, (void *)p->payload, header_size) );
/* modify pbuf length fields */
p->len += header_size;
p->tot_len += header_size;
p->len += header_size_increment;
p->tot_len += header_size_increment;
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n",
(void *)payload, (void *)p->payload, header_size_increment));
return 0;
}
/**
* Free a pbuf (chain) from usage, de-allocate non-used head of chain.
* Dereference a pbuf chain or queue and deallocate any no-longer-used
* pbufs at the head of this chain or queue.
*
* Decrements the pbuf reference count. If it reaches
* zero, the pbuf is deallocated.
* Decrements the pbuf reference count. If it reaches zero, the pbuf is
* deallocated.
*
* For a pbuf chain, this is repeated for each pbuf in the chain, until
* a non-zero reference count is encountered, or the end of the chain is
* reached.
* For a pbuf chain, this is repeated for each pbuf in the chain,
* up to the first pbuf which has a non-zero reference count after
* decrementing. So, when all reference counts are one, the whole
* chain is free'd.
*
* @param pbuf pbuf (chain) to be freed from one user.
* @param pbuf The pbuf (chain) to be dereferenced.
*
* @return the number of unreferenced pbufs that were de-allocated
* @return the number of pbufs that were de-allocated
* from the head of the chain.
*
* @note May not be called on a packet queue.
* @note MUST NOT be called on a packet queue (Not verified to work yet).
* @note the reference counter of a pbuf equals the number of pointers
* that refer to the pbuf (or into the pbuf).
*
* @internal examples:
*
* Assuming existing chains a->b->c with the following reference
* counts, calling pbuf_free(a) results in:
*
* 1->2->3 becomes ...1->3
* 3->3->3 becomes 2->3->3
* 1->1->2 becomes ....->1
* 1->1->2 becomes ......1
* 2->1->1 becomes 1->1->1
* 1->1->1 becomes .......
*
@@ -540,6 +551,8 @@ pbuf_free(struct pbuf *p)
u8_t count;
SYS_ARCH_DECL_PROTECT(old_level);
LWIP_ASSERT("p != NULL", p != NULL);
/* if assertions are disabled, proceed with debug output */
if (p == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
return 0;
@@ -574,9 +587,9 @@ pbuf_free(struct pbuf *p)
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
PBUF_POOL_FREE(p);
/* a ROM or RAM referencing pbuf */
/* is this a ROM or RAM referencing pbuf? */
} else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
memp_freep(MEMP_PBUF, p);
memp_free(MEMP_PBUF, p);
/* p->flags == PBUF_FLAG_RAM */
} else {
mem_free(p);
@@ -588,7 +601,7 @@ pbuf_free(struct pbuf *p)
/* (and so the remaining pbufs in chain as well) */
} else {
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, (unsigned int)p->ref));
/* stop walking through chain */
/* stop walking through the chain */
p = NULL;
}
}
@@ -619,7 +632,6 @@ pbuf_clen(struct pbuf *p)
}
/**
*
* Increment the reference count of the pbuf.
*
* @param p pbuf to increase reference counter of
@@ -638,12 +650,51 @@ pbuf_ref(struct pbuf *p)
}
/**
*
* Chain two pbufs (or pbuf chains) together. They must belong to the same packet.
*
* Concatenate two pbufs (each may be a pbuf chain) and take over
* the caller's reference of the tail pbuf.
*
* @note The caller MAY NOT reference the tail pbuf afterwards.
* Use pbuf_chain() for that purpose.
*
* @see pbuf_chain()
*/
void
pbuf_cat(struct pbuf *h, struct pbuf *t)
{
struct pbuf *p;
LWIP_ASSERT("h != NULL (programmer violates API)", h != NULL);
LWIP_ASSERT("t != NULL (programmer violates API)", t != NULL);
if ((h == NULL) || (t == NULL)) return;
/* proceed to last pbuf of chain */
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);
LWIP_ASSERT("p->next == NULL", p->next == NULL);
/* add total length of second chain to last pbuf total of first chain */
p->tot_len += t->tot_len;
/* chain last pbuf of head (p) with first of tail (t) */
p->next = t;
/* p->next now references t, but the caller will drop its reference to t,
* so netto there is no change to the reference count of t.
*/
}
/**
* Chain two pbufs (or pbuf chains) together.
*
* The caller MUST call pbuf_free(t) once it has stopped
* using it. Use pbuf_cat() instead if you no longer use t.
*
* @param h head pbuf (chain)
* @param t tail pbuf (chain)
* @note May not be called on a packet queue.
* @note The pbufs MUST belong to the same packet.
* @note MAY NOT be called on a packet queue.
*
* The ->tot_len fields of all pbufs of the head chain are adjusted.
* The ->next field of the last pbuf of the head chain is adjusted.
@@ -653,32 +704,14 @@ pbuf_ref(struct pbuf *p)
void
pbuf_chain(struct pbuf *h, struct pbuf *t)
{
struct pbuf *p;
LWIP_ASSERT("h != NULL", h != NULL);
LWIP_ASSERT("t != NULL", t != NULL);
if (t == NULL)
return;
/* proceed to last pbuf of chain */
for (p = h; p->next != NULL; p = p->next) {
/* add total length of second chain to all totals of first chain */
p->tot_len += t->tot_len;
}
/* p is last pbuf of first h chain */
LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
/* add total length of second chain to last pbuf total of first chain */
p->tot_len += t->tot_len;
/* chain last pbuf of h chain (p) with first of tail (t) */
p->next = t;
/* t is now referenced to one more time */
pbuf_cat(h, t);
/* t is now referenced by h */
pbuf_ref(t);
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)p, (void *)t));
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
}
/* For packet queueing. Note that queued packets must be dequeued first
* before calling any pbuf functions. */
/* For packet queueing. Note that queued packets MUST be dequeued first
* using pbuf_dequeue() before calling other pbuf_() functions. */
#if ARP_QUEUEING
/**
* Add a packet to the end of a queue.
@@ -686,15 +719,22 @@ pbuf_chain(struct pbuf *h, struct pbuf *t)
* @param q pointer to first packet on the queue
* @param n packet to be queued
*
* Both packets MUST be given, and must be different.
*/
void
pbuf_queue(struct pbuf *p, struct pbuf *n)
{
LWIP_ASSERT("p != NULL", p != NULL);
LWIP_ASSERT("n != NULL", n != NULL);
if ((p == NULL) || (n == NULL))
#if PBUF_DEBUG /* remember head of queue */
struct pbuf *q = p;
#endif
/* programmer stupidity checks */
LWIP_ASSERT("p == NULL in pbuf_queue: this indicates a programmer error\n", p != NULL);
LWIP_ASSERT("n == NULL in pbuf_queue: this indicates a programmer error\n", n != NULL);
LWIP_ASSERT("p == n in pbuf_queue: this indicates a programmer error\n", p != n);
if ((p == NULL) || (n == NULL) || (p == n)){
LWIP_DEBUGF(PBUF_DEBUG | DBG_HALT | 3, ("pbuf_queue: programmer argument error\n"))
return;
}
/* iterate through all packets on queue */
while (p->next != NULL) {
@@ -702,25 +742,39 @@ pbuf_queue(struct pbuf *p, struct pbuf *n)
#if PBUF_DEBUG
/* iterate through all pbufs in packet */
while (p->tot_len != p->len) {
/* make sure invariant condition holds */
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
/* make sure each packet is complete */
LWIP_ASSERT("p->next != NULL", p->next != NULL);
p = p->next;
/* { p->tot_len == p->len => p is last pbuf of a packet } */
}
#endif
/* now p->tot_len == p->len */
/* { p is last pbuf of a packet } */
/* proceed to next packet on queue */
p = p->next;
#endif
/* proceed to next pbuf */
if (p->next != NULL) p = p->next;
}
/* chain last pbuf of h chain (p) with first of tail (t) */
/* { p->tot_len == p->len and p->next == NULL } ==>
* { p is last pbuf of last packet on queue } */
/* chain last pbuf of queue with n */
p->next = n;
/* t is now referenced to one more time */
/* n is now referenced to by the (packet p in the) queue */
pbuf_ref(n);
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_queue: referencing queued packet %p\n", (void *)n));
#if PBUF_DEBUG
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2,
("pbuf_queue: newly queued packet %p sits after packet %p in queue %p\n",
(void *)n, (void *)p, (void *)q));
#endif
}
/**
* Remove a packet from the head of a queue.
*
* The caller MUST reference the remainder of the queue (as returned). The
* caller MUST NOT call pbuf_ref() as it implicitly takes over the reference
* from p.
*
* @param p pointer to first packet on the queue which will be dequeued.
* @return first packet on the remaining queue (NULL if no further packets).
*
@@ -731,19 +785,28 @@ pbuf_dequeue(struct pbuf *p)
struct pbuf *q;
LWIP_ASSERT("p != NULL", p != NULL);
/* iterate through all pbufs in packet */
/* iterate through all pbufs in packet p */
while (p->tot_len != p->len) {
/* make sure invariant condition holds */
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
/* make sure each packet is complete */
LWIP_ASSERT("p->next != NULL", p->next != NULL);
p = p->next;
}
/* remember next packet on queue */
/* { p->tot_len == p->len } => p is the last pbuf of the first packet */
/* remember next packet on queue in q */
q = p->next;
/* dequeue p from queue */
/* dequeue packet p from queue */
p->next = NULL;
/* q is now referenced to one less time */
pbuf_free(q);
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: dereferencing remaining queue %p\n", (void *)q));
/* any next packet on queue? */
if (q != NULL) {
/* although q is no longer referenced by p, it MUST be referenced by
* the caller, who is maintaining this packet queue. So, we do not call
* pbuf_free(q) here, resulting in an implicit pbuf_ref(q) for the caller. */
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: first remaining packet on queue is %p\n", (void *)q));
} else {
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: no further packets on queue\n"));
}
return q;
}
#endif
@@ -761,10 +824,10 @@ pbuf_dequeue(struct pbuf *p)
*
* @note You MUST explicitly use p = pbuf_take(p);
* The pbuf you give as argument, may have been replaced
* by pbuf_take()!
* by a (differently located) copy through pbuf_take()!
*
* @note Any replaced pbufs will be freed through pbuf_free().
* This may 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
*
@@ -789,7 +852,9 @@ pbuf_take(struct pbuf *p)
/* PBUF_POOL buffers are faster if we can use them */
if (p->len <= PBUF_POOL_BUFSIZE) {
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
if (q == NULL) LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
if (q == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
}
} else {
/* no replacement pbuf yet */
q = NULL;
@@ -798,7 +863,9 @@ pbuf_take(struct pbuf *p)
/* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
if (q == NULL) {
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);
if (q == NULL) LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));
if (q == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));
}
}
/* replacement pbuf could be allocated? */
if (q != NULL)
@@ -881,35 +948,13 @@ pbuf_dechain(struct pbuf *p)
/* q is no longer referenced by p, free it */
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
tail_gone = pbuf_free(q);
if (tail_gone > 0) LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
if (tail_gone > 0) {
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
}
/* return remaining tail or NULL if deallocated */
}
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
return (tail_gone > 0? NULL: q);
}
/* 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

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

@@ -0,0 +1,326 @@
/**
* @file
*
* Implementation of raw protocol PCBs for low-level handling of
* different types of protocols besides (or overriding) those
* already available in lwIP.
*
*/
/*
* Copyright (c) 2001-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>
*
*/
#include <string.h>
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/memp.h"
#include "lwip/inet.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/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 if so, pass it to a user-provided receive callback function.
*
* Given an incoming IP datagram (as a chain of pbufs) this function
* finds a corresponding RAW PCB and calls the corresponding receive
* callback function.
*
* @param pbuf pbuf to be demultiplexed to a RAW PCB.
* @param netif network interface on which the datagram was received.
* @Return - 1 if the packet has been eaten by a RAW PCB receive
* callback function. The caller MAY NOT not reference the
* packet any longer, and MAY NOT call pbuf_free().
* @return - 0 if packet is not eaten (pbuf is still referenced by the
* caller).
*
*/
u8_t
raw_input(struct pbuf *p, struct netif *inp)
{
struct raw_pcb *pcb;
struct ip_hdr *iphdr;
int proto;
u8_t eaten = 0;
iphdr = p->payload;
proto = IPH_PROTO(iphdr);
pcb = raw_pcbs;
/* loop through all raw pcbs until the packet is eaten by one */
/* this allows multiple pcbs to match against the packet by design */
while ((eaten == 0) && (pcb != NULL)) {
if (pcb->protocol == proto) {
/* receive callback function available? */
if (pcb->recv != NULL) {
/* the receive callback function did not eat the packet? */
if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0)
{
/* receive function ate the packet */
p = NULL;
eaten = 1;
}
}
/* no receive callback function was set for this raw PCB */
/* drop the packet */
}
pcb = pcb->next;
}
return eaten;
}
/**
* 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 IP address 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_sendto() 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_sendto()
*/
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 for received packets that match the
* raw PCB's protocol and binding.
*
* The callback function MUST either
* - eat the packet by calling pbuf_free() and returning non-zero. The
* packet will not be passed to other raw PCBs or other protocol layers.
* - not free the packet, and return zero. The packet will be matched
* against further PCBs and/or forwarded to another protocol layers.
*
* @return non-zero if the packet was free()d, zero if the packet remains
* available for others.
*/
void
raw_recv(struct raw_pcb *pcb,
u8_t (* 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 inconsistent with the receive callback where
* you actually get the IP headers), you can only specify the IP payload here.
* It requires some more changes in lwIP. (there will be a raw_send() function
* then.)
*
* @param pcb the raw pcb which to send
* @param p the IP payload to send
* @param ipaddr the destination address of the IP packet
*
*/
err_t
raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
{
err_t err;
struct netif *netif;
struct ip_addr *src_ip;
struct pbuf *q; /* q will be sent down the stack */
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_sendto\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_sendto: could not allocate header\n"));
return ERR_MEM;
}
/* chain header q in front of given pbuf p */
pbuf_chain(q, p);
/* { first pbuf q points to header pbuf } */
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: 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_sendto: No route to 0x%lx\n", ipaddr->addr));
#if RAW_STATS
/* ++lwip_stats.raw.rterr;*/
#endif /* RAW_STATS */
/* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) {
pbuf_free(q);
}
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 IP packet
*
*/
err_t
raw_send(struct raw_pcb *pcb, struct pbuf *p)
{
return raw_sendto(pcb, p, &pcb->remote_ip);
}
/**
* Remove an RAW PCB.
*
* @param pcb RAW PCB to be removed. The PCB is removed from the list of
* RAW PCB's and the data structure is freed from memory.
*
* @see raw_new()
*/
void
raw_remove(struct raw_pcb *pcb)
{
struct raw_pcb *pcb2;
/* pcb to be removed is first in list? */
if (raw_pcbs == pcb) {
/* make list start at 2nd pcb */
raw_pcbs = raw_pcbs->next;
/* pcb not 1st in list */
} else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
/* find pcb in raw_pcbs list */
if (pcb2->next != NULL && pcb2->next == pcb) {
/* remove pcb from list */
pcb2->next = pcb->next;
}
}
memp_free(MEMP_RAW_PCB, pcb);
}
/**
* Create a RAW PCB.
*
* @return The RAW PCB which was created. NULL if the PCB data structure
* could not be allocated.
*
* @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP)
*
* @see raw_remove()
*/
struct raw_pcb *
raw_new(u16_t proto) {
struct raw_pcb *pcb;
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_new\n"));
pcb = memp_malloc(MEMP_RAW_PCB);
/* could allocate RAW PCB? */
if (pcb != NULL) {
/* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct raw_pcb));
pcb->protocol = proto;
pcb->ttl = RAW_TTL;
pcb->next = raw_pcbs;
raw_pcbs = pcb;
}
return pcb;
}
#endif /* LWIP_RAW */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -30,6 +30,7 @@
*
*/
#include <string.h>
#include "lwip/opt.h"
@@ -41,11 +42,74 @@
#if LWIP_STATS
struct stats_ lwip_stats;
/*-----------------------------------------------------------------------------------*/
void
stats_init(void)
{
memset(&lwip_stats, 0, sizeof(struct stats_));
}
#if LWIP_STATS_DISPLAY
void
stats_display_proto(struct stats_proto *proto, char *name)
{
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
LWIP_PLATFORM_DIAG(("xmit: %d\n\t", proto->xmit));
LWIP_PLATFORM_DIAG(("rexmit: %d\n\t", proto->rexmit));
LWIP_PLATFORM_DIAG(("recv: %d\n\t", proto->recv));
LWIP_PLATFORM_DIAG(("fw: %d\n\t", proto->fw));
LWIP_PLATFORM_DIAG(("drop: %d\n\t", proto->drop));
LWIP_PLATFORM_DIAG(("chkerr: %d\n\t", proto->chkerr));
LWIP_PLATFORM_DIAG(("lenerr: %d\n\t", proto->lenerr));
LWIP_PLATFORM_DIAG(("memerr: %d\n\t", proto->memerr));
LWIP_PLATFORM_DIAG(("rterr: %d\n\t", proto->rterr));
LWIP_PLATFORM_DIAG(("proterr: %d\n\t", proto->proterr));
LWIP_PLATFORM_DIAG(("opterr: %d\n\t", proto->opterr));
LWIP_PLATFORM_DIAG(("err: %d\n\t", proto->err));
LWIP_PLATFORM_DIAG(("cachehit: %d\n", proto->cachehit));
}
void
stats_display_pbuf(struct stats_pbuf *pbuf)
{
LWIP_PLATFORM_DIAG(("\nPBUF\n\t"));
LWIP_PLATFORM_DIAG(("avail: %d\n\t", pbuf->avail));
LWIP_PLATFORM_DIAG(("used: %d\n\t", pbuf->used));
LWIP_PLATFORM_DIAG(("max: %d\n\t", pbuf->max));
LWIP_PLATFORM_DIAG(("err: %d\n\t", pbuf->err));
LWIP_PLATFORM_DIAG(("alloc_locked: %d\n\t", pbuf->alloc_locked));
LWIP_PLATFORM_DIAG(("refresh_locked: %d\n", pbuf->refresh_locked));
}
void
stats_display_mem(struct stats_mem *mem, char *name)
{
LWIP_PLATFORM_DIAG(("\n MEM %s\n\t", name));
LWIP_PLATFORM_DIAG(("avail: %d\n\t", mem->avail));
LWIP_PLATFORM_DIAG(("used: %d\n\t", mem->used));
LWIP_PLATFORM_DIAG(("max: %d\n\t", mem->max));
LWIP_PLATFORM_DIAG(("err: %d\n", mem->err));
}
void
stats_display(void)
{
int i;
char * memp_names[] = {"PBUF", "RAW_PCB", "UDP_PCB", "TCP_PCB", "TCP_PCB_LISTEN",
"TCP_SEG", "NETBUF", "NETCONN", "API_MSG", "TCP_MSG", "TIMEOUT"};
stats_display_proto(&lwip_stats.link, "LINK");
stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG");
stats_display_proto(&lwip_stats.ip, "IP");
stats_display_proto(&lwip_stats.icmp, "ICMP");
stats_display_proto(&lwip_stats.udp, "UDP");
stats_display_proto(&lwip_stats.tcp, "TCP");
stats_display_pbuf(&lwip_stats.pbuf);
stats_display_mem(&lwip_stats.mem, "HEAP");
for (i = 0; i < MEMP_MAX; i++) {
stats_display_mem(&lwip_stats.memp[i], memp_names[i]);
}
}
#endif /* LWIP_STATS_DISPLAY */
#endif /* LWIP_STATS */
/*-----------------------------------------------------------------------------------*/

View File

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

View File

@@ -2,10 +2,15 @@
* @file
*
* Transmission Control Protocol for IP
*
* This file contains common functions for the TCP implementation, such as functinos
* for manipulating the data structures and the TCP timer functions. TCP functions
* related to input and output is found in tcp_in.c and tcp_out.c respectively.
*
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -36,16 +41,7 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* tcp.c
*
* This file contains common functions for the TCP implementation, such as functinos
* for manipulating the data structures and the TCP timer functions. TCP functions
* related to input and output is found in tcp_input.c and tcp_output.c respectively.
*
*/
/*-----------------------------------------------------------------------------------*/
#include <string.h>
#include "lwip/opt.h"
#include "lwip/def.h"
@@ -62,30 +58,28 @@ const u8_t tcp_backoff[13] =
{ 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
/* The TCP PCB lists. */
struct tcp_pcb_listen *tcp_listen_pcbs; /* List of all TCP PCBs in LISTEN state. */
struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
state in which they accept or send
data. */
struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
/** List of all TCP PCBs in LISTEN state */
union tcp_listen_pcbs_t tcp_listen_pcbs;
/** List of all TCP PCBs that are in a state in which
* they accept or send data. */
struct tcp_pcb *tcp_active_pcbs;
/** List of all TCP PCBs in TIME-WAIT state */
struct tcp_pcb *tcp_tw_pcbs;
struct tcp_pcb *tcp_tmp_pcb;
static u8_t tcp_timer;
static u16_t tcp_new_port(void);
/*-----------------------------------------------------------------------------------*/
/*
* tcp_init():
*
/**
* Initializes the TCP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_init(void)
{
/* Clear globals. */
tcp_listen_pcbs = NULL;
tcp_listen_pcbs.listen_pcbs = NULL;
tcp_active_pcbs = NULL;
tcp_tw_pcbs = NULL;
tcp_tmp_pcb = NULL;
@@ -95,41 +89,28 @@ tcp_init(void)
tcp_timer = 0;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_tmr():
*
/**
* Called periodically to dispatch TCP timers.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_tmr(void)
{
++tcp_timer;
if (tcp_timer == 10) {
tcp_timer = 0;
}
if (tcp_timer & 1) {
/* Call tcp_fasttmr() every 200 ms, i.e., every other timer
tcp_tmr() is called. */
tcp_fasttmr();
}
if (tcp_timer == 0 || tcp_timer == 5) {
/* Call tcp_slowtmr() every 500 ms, i.e., every fifth timer
/* Call tcp_fasttmr() every 250 ms */
tcp_fasttmr();
if (++tcp_timer & 1) {
/* Call tcp_tmr() every 500 ms, i.e., every other timer
tcp_tmr() is called. */
tcp_slowtmr();
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_close():
*
/**
* Closes the connection held by the PCB.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_close(struct tcp_pcb *pcb)
{
@@ -141,9 +122,21 @@ tcp_close(struct tcp_pcb *pcb)
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
#endif /* TCP_DEBUG */
switch (pcb->state) {
case CLOSED:
/* Closing a pcb in the CLOSED state might seem erroneous,
* however, it is in this state once allocated and as yet unused
* and the user needs some way to free it should the need arise.
* Calling tcp_close() with a pcb that has already been closed, (i.e. twice)
* or for a pcb that has been used and then entered the CLOSED state
* is erroneous, but this should never happen as the pcb has in those cases
* been freed, and so any remaining handles are bogus. */
err = ERR_OK;
memp_free(MEMP_TCP_PCB, pcb);
pcb = NULL;
break;
case LISTEN:
err = ERR_OK;
tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs, pcb);
tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb);
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
pcb = NULL;
break;
@@ -154,11 +147,6 @@ tcp_close(struct tcp_pcb *pcb)
pcb = NULL;
break;
case SYN_RCVD:
err = tcp_send_ctrl(pcb, TCP_FIN);
if (err == ERR_OK) {
pcb->state = FIN_WAIT_1;
}
break;
case ESTABLISHED:
err = tcp_send_ctrl(pcb, TCP_FIN);
if (err == ERR_OK) {
@@ -183,16 +171,13 @@ tcp_close(struct tcp_pcb *pcb)
}
return err;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_abort()
*
/**
* Aborts a connection by sending a RST to the remote host and deletes
* the local protocol control block. This is done when a connection is
* killed because of shortage of memory.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_abort(struct tcp_pcb *pcb)
{
@@ -240,27 +225,28 @@ tcp_abort(struct tcp_pcb *pcb)
tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_bind():
*
/**
* Binds the connection to a local portnumber and IP address. If the
* IP address is not given (i.e., ipaddr == NULL), the IP address of
* the outgoing network interface is used instead.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct tcp_pcb *cpcb;
#if SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
if (port == 0) {
port = tcp_new_port();
}
#if SO_REUSE == 0
/* Check if the address already is in use. */
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs;
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
cpcb != NULL; cpcb = cpcb->next) {
if (cpcb->local_port == port) {
if (ip_addr_isany(&(cpcb->local_ip)) ||
@@ -280,6 +266,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.pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
}
}
}
}
/* Search through list of PCB's in a state in which they can accept or send data. Same decription as for
PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */
for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
}
}
}
}
/* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port}
can be rebound. The same applies when SOF_REUSEPORT is set.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n"));
return ERR_USE;
}
else if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
}
}
}
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
{IP, port} can't be reused. */
if(!reuse_port_all_set) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n"));
return ERR_USE;
}
#endif /* SO_REUSE */
if (!ip_addr_isany(ipaddr)) {
pcb->local_ip = *ipaddr;
}
@@ -298,17 +380,14 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
return ERR_ABRT;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_listen():
*
/**
* Set the state of the connection to be LISTEN, which means that it
* is able to accept incoming connections. The protocol control block
* is reallocated in order to consume less memory. Setting the
* connection to LISTEN is an irreversible process.
*
*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_listen(struct tcp_pcb *pcb)
{
@@ -325,47 +404,66 @@ tcp_listen(struct tcp_pcb *pcb)
lpcb->callback_arg = pcb->callback_arg;
lpcb->local_port = pcb->local_port;
lpcb->state = LISTEN;
lpcb->so_options = pcb->so_options;
lpcb->so_options |= SOF_ACCEPTCONN;
lpcb->ttl = pcb->ttl;
lpcb->tos = pcb->tos;
ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
memp_free(MEMP_TCP_PCB, pcb);
#if LWIP_CALLBACK_API
lpcb->accept = tcp_accept_null;
#endif /* LWIP_CALLBACK_API */
TCP_REG(&tcp_listen_pcbs, lpcb);
TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb);
return (struct tcp_pcb *)lpcb;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_recved():
*
/**
* This function should be called by the application when it has
* processed the data. The purpose is to advertise a larger window
* when the data has been processed.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_recved(struct tcp_pcb *pcb, u16_t len)
{
pcb->rcv_wnd += len;
if (pcb->rcv_wnd > TCP_WND) {
if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
pcb->rcv_wnd = TCP_WND;
} else {
pcb->rcv_wnd += len;
}
if (!(pcb->flags & TF_ACK_DELAY) &&
!(pcb->flags & TF_ACK_NOW)) {
/*
* We send an ACK here (if one is not already pending, hence
* the above tests) as tcp_recved() implies that the application
* has processed some data, and so we can open the receiver's
* window to allow more to be transmitted. This could result in
* two ACKs being sent for each received packet in some limited cases
* (where the application is only receiving data, and is slow to
* process it) but it is necessary to guarantee that the sender can
* continue to transmit.
*/
tcp_ack(pcb);
}
else if (pcb->flags & TF_ACK_DELAY && pcb->rcv_wnd >= TCP_WND/2) {
/* If we can send a window update such that there is a full
* segment available in the window, do so now. This is sort of
* nagle-like in its goals, and tries to hit a compromise between
* sending acks each time the window is updated, and only sending
* window updates when a timer expires. The "threshold" used
* above (currently TCP_WND/2) can be tuned to be more or less
* aggressive */
tcp_ack_now(pcb);
}
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n",
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_new_port():
*
/**
* A nastly hack featuring 'goto' statements that allocates a
* new TCP local port.
*/
/*-----------------------------------------------------------------------------------*/
static u16_t
tcp_new_port(void)
{
@@ -391,22 +489,19 @@ tcp_new_port(void)
goto again;
}
}
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs; pcb != NULL; pcb = pcb->next) {
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->local_port == port) {
goto again;
}
}
return port;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_connect():
*
/**
* Connects to another host. The function given as the "connected"
* argument will be called when the connection has been established.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
@@ -453,15 +548,12 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
}
return ret;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_slowtmr():
*
/**
* Called every 500 ms and implements the retransmission timer and the timer that
* removes PCBs that have been in TIME-WAIT for enough time. It also increments
* various timers such as the inactivity timer in each PCB.
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_slowtmr(void)
{
@@ -477,7 +569,9 @@ tcp_slowtmr(void)
/* Steps through all of the active PCBs. */
prev = NULL;
pcb = tcp_active_pcbs;
if (pcb == NULL) LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
if (pcb == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
}
while (pcb != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));
LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED);
@@ -506,7 +600,6 @@ tcp_slowtmr(void)
if (pcb->state != SYN_SENT) {
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
}
tcp_rexmit(pcb);
/* Reduce congestion window and ssthresh. */
eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
pcb->ssthresh = eff_wnd >> 1;
@@ -516,7 +609,10 @@ tcp_slowtmr(void)
pcb->cwnd = pcb->mss;
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n",
pcb->cwnd, pcb->ssthresh));
}
/* The following needs to be called AFTER cwnd is set to one mss - STJ */
tcp_rexmit_rto(pcb);
}
}
/* Check if this PCB has stayed too long in FIN-WAIT-2 */
if (pcb->state == FIN_WAIT_2) {
@@ -527,6 +623,21 @@ tcp_slowtmr(void)
}
}
/* Check if KEEPALIVE should be sent */
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
tcp_abort(pcb);
}
else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + pcb->keep_cnt * TCP_KEEPINTVL) / TCP_SLOW_INTERVAL) {
tcp_keepalive(pcb);
pcb->keep_cnt++;
}
}
/* If this PCB has queued out of sequence data, but has been
inactive for too long, will drop the data (it will eventually
be retransmitted). */
@@ -622,13 +733,10 @@ tcp_slowtmr(void)
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_fasttmr():
*
* Is called every TCP_FINE_TIMEOUT (100 ms) and sends delayed ACKs.
/**
* Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_fasttmr(void)
{
@@ -643,75 +751,60 @@ tcp_fasttmr(void)
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_segs_free():
*
/**
* Deallocates a list of TCP segments (tcp_seg structures).
*
*/
/*-----------------------------------------------------------------------------------*/
u8_t
tcp_segs_free(struct tcp_seg *seg)
{
u8_t count = 0;
struct tcp_seg *next;
again:
if (seg != NULL) {
while (seg != NULL) {
next = seg->next;
count += tcp_seg_free(seg);
seg = next;
goto again;
}
return count;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_seg_free():
*
/**
* Frees a TCP segment.
*
*/
/*-----------------------------------------------------------------------------------*/
u8_t
tcp_seg_free(struct tcp_seg *seg)
{
u8_t count = 0;
if (seg != NULL) {
if (seg->p == NULL) {
memp_free(MEMP_TCP_SEG, seg);
} else {
if (seg->p != NULL) {
count = pbuf_free(seg->p);
#if TCP_DEBUG
seg->p = NULL;
#endif /* TCP_DEBUG */
memp_free(MEMP_TCP_SEG, seg);
}
memp_free(MEMP_TCP_SEG, seg);
}
return count;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_setprio():
*
/**
* Sets the priority of a connection.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
{
pcb->prio = prio;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_seg_copy():
*
#if TCP_QUEUE_OOSEQ
/**
* Returns a copy of the given TCP segment.
*
*/
/*-----------------------------------------------------------------------------------*/
struct tcp_seg *
tcp_seg_copy(struct tcp_seg *seg)
{
@@ -725,7 +818,8 @@ tcp_seg_copy(struct tcp_seg *seg)
pbuf_ref(cseg->p);
return cseg;
}
/*-----------------------------------------------------------------------------------*/
#endif
#if LWIP_CALLBACK_API
static err_t
tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
@@ -739,7 +833,7 @@ tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
return ERR_OK;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
static void
tcp_kill_prio(u8_t prio)
{
@@ -764,13 +858,13 @@ tcp_kill_prio(u8_t prio)
}
}
if (inactive != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB 0x%p (%ld)\n",
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%ld)\n",
(void *)inactive, inactivity));
tcp_abort(inactive);
}
}
/*-----------------------------------------------------------------------------------*/
static void
tcp_kill_timewait(void)
{
@@ -786,14 +880,14 @@ tcp_kill_timewait(void)
}
}
if (inactive != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB 0x%p (%ld)\n",
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%ld)\n",
(void *)inactive, inactivity));
tcp_abort(inactive);
}
}
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_alloc(u8_t prio)
{
@@ -817,6 +911,8 @@ tcp_alloc(u8_t prio)
pcb->snd_buf = TCP_SND_BUF;
pcb->snd_queuelen = 0;
pcb->rcv_wnd = TCP_WND;
pcb->tos = 0;
pcb->ttl = TCP_TTL;
pcb->mss = TCP_MSS;
pcb->rto = 3000 / TCP_SLOW_INTERVAL;
pcb->sa = 0;
@@ -836,24 +932,29 @@ tcp_alloc(u8_t prio)
#if LWIP_CALLBACK_API
pcb->recv = tcp_recv_null;
#endif /* LWIP_CALLBACK_API */
/* Init KEEPALIVE timer */
pcb->keepalive = TCP_KEEPDEFAULT;
pcb->keep_cnt = 0;
}
return pcb;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_new():
*
/**
* Creates a new TCP protocol control block but doesn't place it on
* any of the TCP PCB lists.
*
* @internal: Maybe there should be a idle TCP PCB list where these
* PCBs are put on. We can then implement port reservation using
* tcp_bind(). Currently, we lack this (BSD socket type of) feature.
*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_new(void)
{
return tcp_alloc(TCP_PRIO_NORMAL);
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_arg():
*
@@ -861,73 +962,71 @@ tcp_new(void)
* functions.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_arg(struct tcp_pcb *pcb, void *arg)
{
pcb->callback_arg = arg;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_recv():
*
#if LWIP_CALLBACK_API
/**
* Used to specify the function that should be called when a TCP
* connection receives data.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_recv(struct tcp_pcb *pcb,
err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
{
pcb->recv = recv;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_sent():
*
/**
* Used to specify the function that should be called when TCP data
* has been successfully delivered to the remote host.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_sent(struct tcp_pcb *pcb,
err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
{
pcb->sent = sent;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_err():
*
/**
* Used to specify the function that should be called when a fatal error
* has occured on the connection.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_err(struct tcp_pcb *pcb,
void (* errf)(void *arg, err_t err))
{
pcb->errf = errf;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_poll():
/**
* 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 */
/**
* Used to specify the function that should be called periodically
* from TCP. The interval is specified in terms of the TCP coarse
* timer interval, which is called twice a second.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_poll(struct tcp_pcb *pcb,
err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
@@ -937,31 +1036,11 @@ tcp_poll(struct tcp_pcb *pcb,
#endif /* LWIP_CALLBACK_API */
pcb->pollinterval = interval;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_accept():
*
* Used for specifying the function that should be called when a
* LISTENing connection has been connected to another host.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_accept(struct tcp_pcb *pcb,
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
{
((struct tcp_pcb_listen *)pcb)->accept = accept;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_pcb_purge():
*
/**
* Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_pcb_purge(struct tcp_pcb *pcb)
{
@@ -971,7 +1050,6 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
#if TCP_DEBUG
if (pcb->unsent != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));
}
@@ -982,28 +1060,20 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
if (pcb->ooseq != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
}
#endif
#endif /* TCP_DEBUG */
tcp_segs_free(pcb->unsent);
#if TCP_QUEUE_OOSEQ
tcp_segs_free(pcb->ooseq);
pcb->ooseq = NULL;
#endif /* TCP_QUEUE_OOSEQ */
tcp_segs_free(pcb->unsent);
tcp_segs_free(pcb->unacked);
pcb->unacked = pcb->unsent =
#if TCP_QUEUE_OOSEQ
pcb->ooseq =
#endif /* TCP_QUEUE_OOSEQ */
NULL;
pcb->unacked = pcb->unsent = NULL;
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_pcb_remove():
*
/**
* Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
{
@@ -1022,14 +1092,11 @@ tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_next_iss():
*
/**
* Calculates a new initial sequence number for new connections.
*
*/
/*-----------------------------------------------------------------------------------*/
u32_t
tcp_next_iss(void)
{
@@ -1038,31 +1105,31 @@ tcp_next_iss(void)
iss += tcp_ticks; /* XXX */
return iss;
}
/*-----------------------------------------------------------------------------------*/
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
void
tcp_debug_print(struct tcp_hdr *tcphdr)
{
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %04x | %04x | (src port, dest port)\n",
tcphdr->src, tcphdr->dest));
LWIP_DEBUGF(TCP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
ntohs(tcphdr->src), ntohs(tcphdr->dest)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %08lu | (seq no)\n",
tcphdr->seqno));
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (seq no)\n",
ntohl(tcphdr->seqno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %08lu | (ack no)\n",
tcphdr->ackno));
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (ack no)\n",
ntohl(tcphdr->ackno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u| %5u | (offset, flags (",
TCPH_OFFSET(tcphdr),
TCPH_FLAGS(tcphdr) >> 4 & 1,
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u%u| %5u | (hdrlen, flags (",
TCPH_HDRLEN(tcphdr),
TCPH_FLAGS(tcphdr) >> 5 & 1,
TCPH_FLAGS(tcphdr) >> 4 & 1,
TCPH_FLAGS(tcphdr) >> 3 & 1,
TCPH_FLAGS(tcphdr) >> 2 & 1,
TCPH_FLAGS(tcphdr) >> 1 & 1,
TCPH_FLAGS(tcphdr) & 1,
tcphdr->wnd));
ntohs(tcphdr->wnd)));
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
@@ -1070,7 +1137,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_state(enum tcp_state s)
{
@@ -1111,7 +1178,7 @@ tcp_debug_print_state(enum tcp_state s)
break;
}
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_flags(u8_t flags)
{
@@ -1133,8 +1200,14 @@ tcp_debug_print_flags(u8_t flags)
if (flags & TCP_URG) {
LWIP_DEBUGF(TCP_DEBUG, ("URG "));
}
if (flags & TCP_ECE) {
LWIP_DEBUGF(TCP_DEBUG, ("ECE "));
}
if (flags & TCP_CWR) {
LWIP_DEBUGF(TCP_DEBUG, ("CWR "));
}
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_pcbs(void)
{
@@ -1147,7 +1220,7 @@ tcp_debug_print_pcbs(void)
tcp_debug_print_state(pcb->state);
}
LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs; pcb != NULL; pcb = pcb->next) {
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",
pcb->local_port, pcb->remote_port,
pcb->snd_nxt, pcb->rcv_nxt));
@@ -1161,7 +1234,7 @@ tcp_debug_print_pcbs(void)
tcp_debug_print_state(pcb->state);
}
}
/*-----------------------------------------------------------------------------------*/
int
tcp_pcbs_sane(void)
{
@@ -1178,7 +1251,7 @@ tcp_pcbs_sane(void)
}
#endif /* TCP_DEBUG */
#endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@@ -2,9 +2,13 @@
* @file
*
* Transmission Control Protocol, outgoing traffic
*
* The output functions of TCP.
*
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -35,15 +39,6 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* tcp_output.c
*
* The output functions of TCP.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/def.h"
#include "lwip/opt.h"
@@ -51,6 +46,7 @@
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/inet.h"
@@ -63,24 +59,36 @@
/* Forward declarations.*/
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
/*-----------------------------------------------------------------------------------*/
err_t
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
{
/* no data, no length, flags, copy=1, no optdata, no optdatalen */
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
}
/*-----------------------------------------------------------------------------------*/
/**
* Write data for sending (but does not send it immediately).
*
* It waits in the expectation of more data being sent soon (as
* it can send them more efficiently by combining them together).
* To prompt the system to send data now, call tcp_output() after
* calling tcp_write().
*
* @arg pcb Protocol control block of the TCP connection to enqueue data for.
*
* @see tcp_write()
*/
err_t
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
{
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb,
arg, len, (unsigned int)copy));
if (pcb->state == SYN_SENT ||
pcb->state == SYN_RCVD ||
pcb->state == ESTABLISHED ||
pcb->state == CLOSE_WAIT) {
/* connection is in valid state for data transmission? */
if (pcb->state == ESTABLISHED ||
pcb->state == CLOSE_WAIT ||
pcb->state == SYN_SENT ||
pcb->state == SYN_RCVD) {
if (len > 0) {
return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
}
@@ -90,11 +98,25 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
return ERR_CONN;
}
}
/*-----------------------------------------------------------------------------------*/
/**
* Enqueue either data or TCP options (but not both) for tranmission
*
*
*
* @arg pcb Protocol control block for the TCP connection to enqueue data for.
* @arg arg Pointer to the data to be enqueued for sending.
* @arg len Data length in bytes
* @arg flags
* @arg copy 1 if data must be copied, 0 if data is non-volatile and can be
* referenced.
* @arg optdata
* @arg optlen
*/
err_t
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
u8_t flags, u8_t copy,
u8_t *optdata, u8_t optlen)
u8_t flags, u8_t copy,
u8_t *optdata, u8_t optlen)
{
struct pbuf *p;
struct tcp_seg *seg, *useg, *queue;
@@ -105,39 +127,43 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%u)\n",
(void *)pcb, arg, len, (unsigned int)flags, (unsigned int)copy));
left = len;
ptr = arg;
LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
len == 0 || optlen == 0);
LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
arg == NULL || optdata == NULL);
/* fail on too much data */
if (len > pcb->snd_buf) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%u > snd_buf=%u)\n", len, pcb->snd_buf));
return ERR_MEM;
}
left = len;
ptr = arg;
/* seqno will be the sequence number of the first segment enqueued
* by the call to this function. */
seqno = pcb->snd_lbb;
queue = NULL;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %u\n", (unsigned int)pcb->snd_queuelen));
/* Check if the queue length exceeds the configured maximum queue
* length. If so, we return an error. */
/* If total number of pbufs on the unsent/unacked queues exceeds the
* configured maximum, return an error */
queuelen = pcb->snd_queuelen;
if (queuelen >= TCP_SND_QUEUELEN) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %u (max %u)\n", queuelen, TCP_SND_QUEUELEN));
goto memerr;
}
if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL);
if (queuelen != 0) {
LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
pcb->unacked != NULL || pcb->unsent != NULL);
} else {
LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
pcb->unacked == NULL && pcb->unsent == NULL);
}
seg = NULL;
seglen = 0;
/* First, break up the data into segments and tuck them together in
* the local "queue" variable. */
useg = queue = seg = NULL;
seglen = 0;
while (queue == NULL || left > 0) {
/* The segment length should be the MSS if the data to be enqueued
@@ -153,19 +179,25 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
seg->next = NULL;
seg->p = NULL;
/* first segment of to-be-queued data? */
if (queue == NULL) {
queue = seg;
}
/* subsequent segments of to-be-queued data */
else {
/* Attach the segment to the end of the queued segments. */
for (useg = queue; useg->next != NULL; useg = useg->next);
/* Attach the segment to the end of the queued segments */
LWIP_ASSERT("useg != NULL", useg != NULL);
useg->next = seg;
}
/* remember last segment of to-be-queued data for next iteration */
useg = seg;
/* If copy is set, memory should be allocated
* and data copied into pbuf, otherwise data comes from
* ROM or other static memory, and need not be copied. If
* optdata is != NULL, we have options instead of data. */
/* options? */
if (optdata != NULL) {
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
goto memerr;
@@ -173,6 +205,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
++queuelen;
seg->dataptr = seg->p->payload;
}
/* copy from volatile memory? */
else if (copy) {
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %u\n", seglen));
@@ -186,8 +219,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
}
/* do not copy data */
else {
/* first, allocate a pbuf for holding the data.
/* First, allocate a pbuf for holding the data.
* since the referenced data is available at least until it is sent out on the
* link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
* instead of PBUF_REF here.
@@ -197,6 +229,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
goto memerr;
}
++queuelen;
/* reference the non-volatile payload data */
p->payload = ptr;
seg->dataptr = ptr;
@@ -210,9 +243,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
}
++queuelen;
/* Chain the headers and data pbufs together. */
pbuf_chain(seg->p, p);
pbuf_free(p);
/* Concatenate the headers and data pbufs together. */
pbuf_cat(seg->p/*header*/, p/*data*/);
p = NULL;
}
@@ -224,19 +256,11 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
}
seg->len = seglen;
#if 0 /* Was commented out. TODO: can someone say why this is here? */
if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
++seg->len;
}
#endif
/* Build TCP header. */
/* build TCP header */
if (pbuf_header(seg->p, TCP_HLEN)) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
#ifdef TCP_STATS
++lwip_stats.tcp.err;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.err);
goto memerr;
}
seg->tcphdr = seg->p->payload;
@@ -249,10 +273,10 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* Copy the options into the header, if they are present. */
if (optdata == NULL) {
TCPH_OFFSET_SET(seg->tcphdr, 5 << 4);
TCPH_HDRLEN_SET(seg->tcphdr, 5);
}
else {
TCPH_OFFSET_SET(seg->tcphdr, (5 + optlen / 4) << 4);
TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
/* Copy options into data portion of segment.
Options can thus only be sent in non data carrying
segments such as SYN|ACK. */
@@ -268,7 +292,6 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
ptr = (void *)((char *)ptr + seglen);
}
/* Now that the data to be enqueued has been broken up into TCP
segments in the queue variable, we add them to the end of the
pcb->unsent queue. */
@@ -278,6 +301,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
else {
for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
}
/* { useg is last segment on the unsent queue, NULL if list is empty } */
/* If there is room in the last pbuf on the unsent queue,
chain the first pbuf on the queue together with that. */
@@ -285,28 +309,27 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
TCP_TCPLEN(useg) != 0 &&
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
!(flags & (TCP_SYN | TCP_FIN)) &&
/* fit within max seg size */
useg->len + queue->len <= pcb->mss) {
/* Remove TCP header from first segment. */
/* Remove TCP header from first segment of our to-be-queued list */
pbuf_header(queue->p, -TCP_HLEN);
pbuf_chain(useg->p, queue->p);
/* Free buffer which was merged. Note that the previous pbuf_chain call
* will have incremented the ref count, so here the ref count will still
* be 1 for the 1 pointer still being used on this buffer. */
pbuf_free(queue->p);
pbuf_cat(useg->p, queue->p);
useg->len += queue->len;
useg->next = queue->next;
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining, new len %u\n", useg->len));
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %u\n", useg->len));
if (seg == queue) {
seg = NULL;
}
memp_free(MEMP_TCP_SEG, queue);
}
else {
/* empty list */
if (useg == NULL) {
/* initialize list with this segment */
pcb->unsent = queue;
}
/* enqueue segment */
else {
useg->next = queue;
}
@@ -316,25 +339,23 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
}
pcb->snd_lbb += len;
pcb->snd_buf -= len;
/* update number of segments on the queues */
pcb->snd_queuelen = queuelen;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen));
if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL);
LWIP_ASSERT("tcp_enqueue: valid queue length",
pcb->unacked != NULL || pcb->unsent != NULL);
}
/* Set the PSH flag in the last segment that we enqueued, but only
if the segment has data (indicated by seglen > 0). */
if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_PSH);
TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
}
return ERR_OK;
memerr:
#ifdef TCP_STATS
++lwip_stats.tcp.memerr;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.memerr);
if (queue != NULL) {
tcp_segs_free(queue);
@@ -342,12 +363,11 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL);
}
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
return ERR_MEM;
}
/*-----------------------------------------------------------------------------------*/
/* find out what we can send and send it */
err_t
tcp_output(struct tcp_pcb *pcb)
@@ -370,25 +390,31 @@ tcp_output(struct tcp_pcb *pcb)
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
seg = pcb->unsent;
/* If the TF_ACK_NOW flag is set, we check if there is data that is
to be sent. If data is to be sent out, we'll just piggyback our
acknowledgement with the outgoing segment. If no data will be
sent (either because the ->unsent queue is empty or because the
window doesn't allow it) we'll have to construct an empty ACK
segment and send it. */
/* 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 and no data will be sent (either
* because the ->unsent queue is empty or because the window does
* not allow it), construct an empty ACK segment and send it.
*
* If data is to be sent, we will just piggyback the ACK (see below).
*/
if (pcb->flags & TF_ACK_NOW &&
(seg == NULL ||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if (p == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
return ERR_BUF;
}
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %lu\n", pcb->rcv_nxt));
/* remove ACK flags from the PCB, as we send an empty ACK now */
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
tcphdr = p->payload;
tcphdr->src = htons(pcb->local_port);
@@ -398,13 +424,14 @@ tcp_output(struct tcp_pcb *pcb)
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_OFFSET_SET(tcphdr, 5 << 4);
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
IP_PROTO_TCP, p->tot_len);
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
#endif
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
pbuf_free(p);
@@ -428,7 +455,7 @@ tcp_output(struct tcp_pcb *pcb)
ntohl(seg->tcphdr->seqno), pcb->lastack));
}
#endif /* TCP_CWND_DEBUG */
/* data available and window allows it to be sent? */
while (seg != NULL &&
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
#if TCP_CWND_DEBUG
@@ -443,7 +470,7 @@ tcp_output(struct tcp_pcb *pcb)
pcb->unsent = seg->next;
if (pcb->state != SYN_SENT) {
TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_ACK);
TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
}
@@ -455,14 +482,26 @@ tcp_output(struct tcp_pcb *pcb)
/* put segment on unacknowledged list if length > 0 */
if (TCP_TCPLEN(seg) > 0) {
seg->next = NULL;
/* unacked list is empty? */
if (pcb->unacked == NULL) {
pcb->unacked = seg;
useg = seg;
/* unacked list is not empty? */
} else {
for (useg = pcb->unacked; useg->next != NULL; useg = useg->next);
useg->next = seg;
/* In the case of fast retransmit, the packet should not go to the tail
* of the unacked queue, but rather at the head. We need to check for
* this case. -STJ Jul 27, 2004 */
if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
/* add segment to head of unacked list */
seg->next = pcb->unacked;
pcb->unacked = seg;
} else {
/* add segment to tail of unacked list */
useg->next = seg;
useg = useg->next;
}
}
/* do not queue empty segments on the unacked list */
} else {
tcp_seg_free(seg);
}
@@ -470,7 +509,10 @@ tcp_output(struct tcp_pcb *pcb)
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/**
* Actually send a TCP segment over IP
*/
static void
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
{
@@ -519,18 +561,18 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
seg->p->payload = seg->tcphdr;
seg->tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
&(pcb->local_ip),
&(pcb->remote_ip),
IP_PROTO_TCP, seg->p->tot_len);
#ifdef TCP_STATS
++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */
#endif
TCP_STATS_INC(tcp.xmit);
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
}
/*-----------------------------------------------------------------------------------*/
void
tcp_rst(u32_t seqno, u32_t ackno,
struct ip_addr *local_ip, struct ip_addr *remote_ip,
@@ -552,20 +594,50 @@ tcp_rst(u32_t seqno, u32_t ackno,
TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
tcphdr->wnd = htons(TCP_WND);
tcphdr->urgp = 0;
TCPH_OFFSET_SET(tcphdr, 5 << 4);
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
IP_PROTO_TCP, p->tot_len);
#ifdef TCP_STATS
++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */
ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP);
#endif
TCP_STATS_INC(tcp.xmit);
/* Send output with hardcoded TTL since we have no access to the pcb */
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
}
/*-----------------------------------------------------------------------------------*/
/* requeue all unacked segments for retransmission */
void
tcp_rexmit_rto(struct tcp_pcb *pcb)
{
struct tcp_seg *seg;
if (pcb->unacked == NULL) {
return;
}
/* Move all unacked segments to the head of the unsent queue */
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
/* concatenate unsent queue after unacked queue */
seg->next = pcb->unsent;
/* unsent queue is the concatenated queue (of unacked, unsent) */
pcb->unsent = pcb->unacked;
/* unacked queue is now empty */
pcb->unacked = NULL;
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
/* increment number of retransmissions */
++pcb->nrtx;
/* Don't take any RTT measurements after retransmitting. */
pcb->rttest = 0;
/* Do the actual retransmission */
tcp_output(pcb);
}
void
tcp_rexmit(struct tcp_pcb *pcb)
{
@@ -575,14 +647,11 @@ tcp_rexmit(struct tcp_pcb *pcb)
return;
}
/* Move all unacked segments to the unsent queue. */
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
seg->next = pcb->unsent;
/* Move the first unacked segment to the unsent queue */
seg = pcb->unacked->next;
pcb->unacked->next = pcb->unsent;
pcb->unsent = pcb->unacked;
pcb->unacked = NULL;
pcb->unacked = seg;
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
@@ -595,6 +664,50 @@ tcp_rexmit(struct tcp_pcb *pcb)
tcp_output(pcb);
}
void
tcp_keepalive(struct tcp_pcb *pcb)
{
struct pbuf *p;
struct tcp_hdr *tcphdr;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %lu pcb->tmr %lu pcb->keep_cnt %u\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;
#if CHECKSUM_GEN_TCP
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
#endif
TCP_STATS_INC(tcp.xmit);
/* Send output to IP */
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
}
#endif /* LWIP_TCP */

View File

@@ -4,7 +4,7 @@
*
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -35,22 +35,24 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* udp.c
*
* The code for the User Datagram Protocol UDP.
*
*/
/*-----------------------------------------------------------------------------------*/
#include <string.h>
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/memp.h"
#include "lwip/inet.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/udp.h"
#include "lwip/icmp.h"
#include "lwip/ip_addr.h"
#include "lwip/stats.h"
@@ -64,87 +66,13 @@ struct udp_pcb *udp_pcbs = NULL;
static struct udp_pcb *pcb_cache = NULL;
#if UDP_DEBUG
int udp_debug_print(struct udp_hdr *udphdr);
#endif /* UDP_DEBUG */
/*-----------------------------------------------------------------------------------*/
void
udp_init(void)
{
udp_pcbs = pcb_cache = NULL;
}
/*-----------------------------------------------------------------------------------*/
/* udp_lookup:
*
* An experimental feature that will be changed in future versions. Do
* not depend on it yet...
*/
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
u8_t
udp_lookup(struct ip_hdr *iphdr, struct netif *inp)
{
struct udp_pcb *pcb;
struct udp_hdr *udphdr;
u16_t src, dest;
PERF_START;
(void)inp;
udphdr = (struct udp_hdr *)(u8_t *)iphdr + IPH_HL(iphdr) * 4;
src = ntohs(udphdr->src);
dest = ntohs(udphdr->dest);
pcb = pcb_cache;
if (pcb != NULL &&
pcb->remote_port == src &&
pcb->local_port == dest &&
(ip_addr_isany(&pcb->remote_ip) ||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
return 1;
}
else {
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->remote_port == src &&
pcb->local_port == dest &&
(ip_addr_isany(&pcb->remote_ip) ||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
pcb_cache = pcb;
break;
}
}
if (pcb == NULL) {
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->remote_port == 0 &&
pcb->local_port == dest &&
(ip_addr_isany(&pcb->remote_ip) ||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
break;
}
}
}
}
PERF_STOP("udp_lookup");
if (pcb != NULL) {
return 1;
}
else {
return 1;
}
}
#endif /* LWIP_DEBUG */
/**
* Process an incoming UDP datagram.
*
@@ -163,21 +91,24 @@ udp_input(struct pbuf *p, struct netif *inp)
struct ip_hdr *iphdr;
u16_t src, dest;
#if SO_REUSE
struct udp_pcb *pcb_temp;
int reuse = 0;
int reuse_port_1 = 0;
int reuse_port_2 = 0;
#endif /* SO_REUSE */
PERF_START;
#ifdef UDP_STATS
++lwip_stats.udp.recv;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.recv);
iphdr = p->payload;
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
/* drop short packets */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
#ifdef UDP_STATS
++lwip_stats.udp.lenerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.lenerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
@@ -190,9 +121,7 @@ udp_input(struct pbuf *p, struct netif *inp)
src = ntohs(udphdr->src);
dest = ntohs(udphdr->dest);
#if UDP_DEBUG
udp_debug_print(udphdr);
#endif /* UDP_DEBUG */
/* print the UDP source and destination */
LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n",
@@ -200,8 +129,18 @@ udp_input(struct pbuf *p, struct netif *inp)
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
#if SO_REUSE
pcb_temp = udp_pcbs;
again_1:
/* Iterate through the UDP pcb list for a fully matching pcb */
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
for (pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
/* Iterate through the UDP pcb list for a fully matching pcb */
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
/* print the PCB local and remote address */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
@@ -221,6 +160,27 @@ udp_input(struct pbuf *p, struct netif *inp)
(ip_addr_isany(&pcb->local_ip) ||
/* PCB local IP address matches UDP destination IP address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
#if SO_REUSE
if (pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port_1 = 1;
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if (reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
break;
}
}
@@ -228,7 +188,16 @@ udp_input(struct pbuf *p, struct netif *inp)
if (pcb == NULL) {
/* Iterate through the UDP PCB list for a pcb that matches
the local address. */
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#if SO_REUSE
pcb_temp = udp_pcbs;
again_2:
for (pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
@@ -242,7 +211,28 @@ udp_input(struct pbuf *p, struct netif *inp)
(ip_addr_isany(&pcb->local_ip) ||
/* ...matching interface address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
break;
#if SO_REUSE
if (pcb->so_options & SOF_REUSEPORT) {
if (reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port_2 = 1;
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if (reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
break;
}
}
}
@@ -258,56 +248,80 @@ udp_input(struct pbuf *p, struct netif *inp)
if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
#endif /* IPv4 */
/* Do the UDP Lite checksum */
#if CHECKSUM_CHECK_UDP
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
(struct ip_addr *)&(iphdr->dest),
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
#ifdef UDP_STATS
++lwip_stats.udp.chkerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
}
#endif
} else {
#if CHECKSUM_CHECK_UDP
if (udphdr->chksum != 0) {
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
(struct ip_addr *)&(iphdr->dest),
IP_PROTO_UDP, p->tot_len) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n"));
#ifdef UDP_STATS
++lwip_stats.udp.chkerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
}
}
#endif
}
pbuf_header(p, -UDP_HLEN);
if (pcb != NULL) {
snmp_inc_udpindatagrams();
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
#if SO_REUSE
/* First socket should receive now */
if(reuse_port_1 || reuse_port_2) {
/* We want to search on next socket after receiving */
pcb_temp = pcb->next;
if(reuse_port_1) {
/* We are searching connected sockets */
reuse_port_1 = 0;
reuse_port_2 = 0;
goto again_1;
} else {
/* We are searching unconnected sockets */
reuse_port_1 = 0;
reuse_port_2 = 0;
goto again_2;
}
}
#endif /* SO_REUSE */
} else {
#if SO_REUSE
if(reuse) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
pbuf_free(p);
goto end;
}
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
/* No match was found, send ICMP destination port unreachable unless
destination address was broadcast/multicast. */
destination address was broadcast/multicast. */
if (!ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) &&
!ip_addr_ismulticast(&iphdr->dest)) {
if (!ip_addr_isbroadcast(&iphdr->dest, inp) &&
!ip_addr_ismulticast(&iphdr->dest)) {
/* adjust pbuf pointer */
p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PORT);
}
#ifdef UDP_STATS
++lwip_stats.udp.proterr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.proterr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpnoports();
pbuf_free(p);
}
@@ -318,6 +332,47 @@ udp_input(struct pbuf *p, struct netif *inp)
PERF_STOP("udp_input");
}
/**
* Send data to a specified address using UDP.
*
* @param pcb UDP PCB used to send the data.
* @param pbuf chain of pbuf's to be sent.
* @param dst_ip Destination IP address.
* @param dst_port Destination UDP port.
*
* If the PCB already has a remote address association, it will
* be restored after the data is sent.
*
* @return lwIP error code.
* - ERR_OK. Successful. No error occured.
* - ERR_MEM. Out of memory.
* - ERR_RTE. Could not find route to destination address.
*
* @see udp_disconnect() udp_send()
*/
err_t
udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
struct ip_addr *dst_ip, u16_t dst_port)
{
err_t err;
/* temporary space for current PCB remote address */
struct ip_addr pcb_remote_ip;
u16_t pcb_remote_port;
/* remember current remote peer address of PCB */
pcb_remote_ip.addr = pcb->remote_ip.addr;
pcb_remote_port = pcb->remote_port;
/* copy packet destination address to PCB remote peer address */
pcb->remote_ip.addr = dst_ip->addr;
pcb->remote_port = dst_port;
/* send to the packet destination address */
err = udp_send(pcb, p);
/* restore PCB remote peer address */
pcb->remote_ip.addr = pcb_remote_ip.addr;
pcb->remote_port = pcb_remote_port;
return err;
}
/**
* Send data using UDP.
*
@@ -327,10 +382,9 @@ udp_input(struct pbuf *p, struct netif *inp)
* @return lwIP error code.
* - ERR_OK. Successful. No error occured.
* - ERR_MEM. Out of memory.
* - ERR_USE. The specified ipaddr and port are already bound to by
* another UDP PCB.
* - ERR_RTE. Could not find route to destination address.
*
* @see udp_disconnect()
* @see udp_disconnect() udp_sendto()
*/
err_t
udp_send(struct udp_pcb *pcb, struct pbuf *p)
@@ -355,7 +409,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* not enough space to add an UDP header to first pbuf in given p chain? */
if (pbuf_header(p, UDP_HLEN)) {
/* allocate header in new pbuf */
/* allocate header in a seperate new pbuf */
q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
/* new header pbuf could not be allocated? */
if (q == NULL) {
@@ -367,25 +421,27 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* { first pbuf q points to header pbuf } */
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
/* adding a header within p succeeded */
} else {
} else {
/* first pbuf q equals given pbuf */
q = p;
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
}
/* { q now represents the packet to be sent } */
udphdr = q->payload;
udphdr->src = htons(pcb->local_port);
udphdr->dest = htons(pcb->remote_port);
udphdr->chksum = 0x0000;
/* in UDP, 0 checksum means 'no checksum' */
udphdr->chksum = 0x0000;
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
/* find the outgoing network interface for this packet */
netif = ip_route(&(pcb->remote_ip));
/* no outgoing network interface could be found? */
if (netif == NULL) {
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr));
#ifdef UDP_STATS
++lwip_stats.udp.rterr;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/* using IP_ANY_ADDR? */
/* PCB local address is IP_ANY_ADDR? */
if (ip_addr_isany(&pcb->local_ip)) {
/* use outgoing network interface IP address as source address */
src_ip = &(netif->ip_addr);
@@ -402,38 +458,47 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* set UDP message length in UDP header */
udphdr->len = htons(pcb->chksum_len);
/* calculate checksum */
#if CHECKSUM_GEN_UDP
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip),
IP_PROTO_UDP, pcb->chksum_len);
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
#else
udphdr->chksum = 0x0000;
#endif
/* output to IP */
err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDPLITE, netif);
snmp_inc_udpoutdatagrams();
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
err = ip_output_if (q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
/* UDP */
} else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len));
udphdr->len = htons(q->tot_len);
/* calculate checksum */
#if CHECKSUM_GEN_UDP
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &pcb->remote_ip, IP_PROTO_UDP, q->tot_len);
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
}
#else
udphdr->chksum = 0x0000;
#endif
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04x\n", udphdr->chksum));
snmp_inc_udpoutdatagrams();
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
/* output to IP */
err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDP, netif);
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
}
/* TODO: must this be increased even if error occured? */
snmp_inc_udpoutdatagrams();
/* did we chain a header earlier? */
/* did we chain a seperate header pbuf earlier? */
if (q != p) {
/* free the header */
pbuf_free(q);
/* free the header pbuf */
pbuf_free(q); q = NULL;
/* { p is still referenced by the caller, and will live on } */
}
#ifdef UDP_STATS
++lwip_stats.udp.xmit;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.xmit);
return err;
}
@@ -457,9 +522,13 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
u8_t rebind;
#if SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
ip_addr_debug_print(UDP_DEBUG, ipaddr);
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port));
rebind = 0;
/* Check for double bind and rebind of the same pcb */
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
@@ -470,11 +539,13 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
/* pcb already in list, just rebind */
rebind = 1;
}
#if SO_REUSE == 0
/* this code does not allow upper layer to share a UDP port for
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
combine with implementation of UDP PCB flags. Leon Woestenberg. */
#if 0
#ifdef LWIP_UDP_TODO
/* port matches that of PCB in list? */
else if ((ipcb->local_port == port) &&
/* IP address matches, or one is IP_ADDR_ANY? */
@@ -486,8 +557,52 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
return ERR_USE;
}
#endif
#else /* SO_REUSE */
/* Search through list of PCB's.
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
But no two PCB's bound to same local port and same local address is valid.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
else if (ipcb->local_port == port) {
if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
}
}
#endif /* SO_REUSE */
}
/* bind local address */
#if SO_REUSE
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
{IP, port} can't be reused. */
if(!reuse_port_all_set) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n"));
return ERR_USE;
}
#endif /* SO_REUSE */
ip_addr_set(&pcb->local_ip, ipaddr);
/* no port specified? */
if (port == 0) {
@@ -552,16 +667,14 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
pcb->remote_port = port;
pcb->flags |= UDP_FLAGS_CONNECTED;
/** TODO: this functionality belongs in upper layers */
#if 0
#ifdef LWIP_UDP_TODO
/* Nail down local IP for netconn_addr()/getsockname() */
if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
struct netif *netif;
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
#ifdef UDP_STATS
++lwip_stats.udp.rterr;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/** TODO: this will bind the udp pcb locally, to the interface which
@@ -594,9 +707,13 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
void
udp_disconnect(struct udp_pcb *pcb)
{
/* reset remote address association */
ip_addr_set(&pcb->remote_ip, IP_ADDR_ANY);
pcb->remote_port = 0;
/* mark PCB as unconnected */
pcb->flags &= ~UDP_FLAGS_CONNECTED;
}
/*-----------------------------------------------------------------------------------*/
void
udp_recv(struct udp_pcb *pcb,
void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
@@ -649,10 +766,13 @@ udp_new(void) {
if (pcb != NULL) {
/* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct udp_pcb));
pcb->ttl = UDP_TTL;
}
return pcb;
}
/*-----------------------------------------------------------------------------------*/
#if UDP_DEBUG
int
udp_debug_print(struct udp_hdr *udphdr)
@@ -668,7 +788,7 @@ udp_debug_print(struct udp_hdr *udphdr)
return 0;
}
#endif /* UDP_DEBUG */
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_UDP */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -37,6 +37,7 @@
#include "lwip/opt.h"
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#define ICMP_ER 0 /* echo reply */

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -34,6 +34,40 @@
#include "lwip/arch.h"
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip_addr {
PACK_STRUCT_FIELD(u32_t addr);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip_addr2 {
PACK_STRUCT_FIELD(u16_t addrw[2]);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
/* For compatibility with BSD code */
struct in_addr {
u32_t s_addr;
};
struct netif;
extern const struct ip_addr ip_addr_any;
extern const struct ip_addr ip_addr_broadcast;
/** IP_ADDR_ can be used as a fixed IP address
* for the wildcard and the broadcast address
*/
@@ -76,33 +110,22 @@
#define IN_LOOPBACKNET 127 /* official! */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip_addr {
PACK_STRUCT_FIELD(u32_t addr);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
/* For compatibility with BSD code */
struct in_addr {
u32_t s_addr;
};
extern const struct ip_addr ip_addr_any;
extern const struct ip_addr ip_addr_broadcast;
#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = htonl(((u32_t)(a & 0xff) << 24) | ((u32_t)(b & 0xff) << 16) | \
((u32_t)(c & 0xff) << 8) | (u32_t)(d & 0xff))
#define ip_addr_set(dest, src) (dest)->addr = \
((src) == NULL? 0:\
((struct ip_addr *)src)->addr)
#define ip_addr_maskcmp(addr1, addr2, mask) (((addr1)->addr & \
(src)->addr)
/**
* Determine if two address are on the same network.
*
* @arg addr1 IP address 1
* @arg addr2 IP address 2
* @arg mask network identifier mask
* @return !0 if the network identifiers of both address match
*/
#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \
(mask)->addr) == \
((addr2)->addr & \
(mask)->addr))
@@ -110,10 +133,7 @@ extern const struct ip_addr ip_addr_broadcast;
#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0)
#define ip_addr_isbroadcast(addr1, mask) (((((addr1)->addr) & ~((mask)->addr)) == \
(0xffffffff & ~((mask)->addr))) || \
((addr1)->addr == 0xffffffff) || \
((addr1)->addr == 0x00000000))
u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -45,7 +45,7 @@ struct ip_addr {
(ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \
(ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0)
int ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
int ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
struct ip_addr *mask);
int ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2);
void ip_addr_set(struct ip_addr *dest, struct ip_addr *src);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -43,6 +43,10 @@ struct dhcp
struct ip_addr offered_sn_mask;
struct ip_addr offered_gw_addr;
struct ip_addr offered_bc_addr;
#define DHCP_MAX_DNS 2
u32_t dns_count; /* actual number of DNS servers obtained */
struct ip_addr offered_dns_addr[DHCP_MAX_DNS]; /* DNS server addresses */
u32_t offered_t0_lease; /* lease period (in seconds) */
u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */
@@ -70,10 +74,10 @@ struct dhcp_msg
PACK_STRUCT_FIELD(u32_t xid);
PACK_STRUCT_FIELD(u16_t secs);
PACK_STRUCT_FIELD(u16_t flags);
PACK_STRUCT_FIELD(u32_t ciaddr);
PACK_STRUCT_FIELD(u32_t yiaddr);
PACK_STRUCT_FIELD(u32_t siaddr);
PACK_STRUCT_FIELD(u32_t giaddr);
PACK_STRUCT_FIELD(struct ip_addr ciaddr);
PACK_STRUCT_FIELD(struct ip_addr yiaddr);
PACK_STRUCT_FIELD(struct ip_addr siaddr);
PACK_STRUCT_FIELD(struct ip_addr giaddr);
#define DHCP_CHADDR_LEN 16U
PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]);
#define DHCP_SNAME_LEN 64U
@@ -82,8 +86,12 @@ struct dhcp_msg
PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]);
PACK_STRUCT_FIELD(u32_t cookie);
#define DHCP_MIN_OPTIONS_LEN 68U
/** make sure user does not configure this too small */
#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
# undef DHCP_OPTIONS_LEN
#endif
/** allow this to be configured in lwipopts.h, but not too small */
#if ((!defined(DHCP_OPTIONS_LEN)) || (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
#if (!defined(DHCP_OPTIONS_LEN))
/** set this to be sufficient for your options in outgoing DHCP msgs */
# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN
#endif
@@ -96,11 +104,13 @@ PACK_STRUCT_END
/** start DHCP configuration */
err_t dhcp_start(struct netif *netif);
/** enforce early lease renewal (not needed normally)*/
err_t dhcp_renew(struct netif *netif);
/** release the DHCP lease, usually called before dhcp_stop()*/
err_t dhcp_release(struct netif *netif);
/** stop DHCP configuration */
void dhcp_stop(struct netif *netif);
/** enforce lease renewal */
err_t dhcp_renew(struct netif *netif);
/** inform server of our IP address */
/** inform server of our manual IP address */
void dhcp_inform(struct netif *netif);
/** if enabled, check whether the offered IP address is not in use, using ARP */
@@ -174,7 +184,8 @@ void dhcp_fine_tmr(void);
/** BootP options */
#define DHCP_OPTION_PAD 0
#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */
#define DHCP_OPTION_ROUTER 3
#define DHCP_OPTION_ROUTER 3
#define DHCP_OPTION_DNS_SERVER 6
#define DHCP_OPTION_HOSTNAME 12
#define DHCP_OPTION_IP_TTL 23
#define DHCP_OPTION_MTU 26
@@ -191,10 +202,10 @@ void dhcp_fine_tmr(void);
#define DHCP_OPTION_MESSAGE_TYPE_LEN 1
#define DHCP_OPTION_SERVER_ID 54 /* RFC 2131 9.7, server IP address */
#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2131 9.8, requested option types */
#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */
#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */
#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2131 9.10, message size accepted >= 576 */
#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */
#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2
#define DHCP_OPTION_T1 58 /* T1 renewal time */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -59,6 +59,7 @@ typedef s8_t err_t;
#define ERR_USE -10 /* Address in use. */
#define ERR_IF -11 /* Low-level netif error */
#define ERR_ISCONN -12 /* Already connected. */
#ifdef LWIP_DEBUG

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -40,7 +40,9 @@
#include "lwip/inet.h"
#include "lwip/pbuf.h"
#include "lwip/dhcp.h"
#if LWIP_DHCP
# include "lwip/dhcp.h"
#endif
/** must be the maximum of all used hardware address lengths
across all types of interfaces in use */
@@ -50,7 +52,8 @@
/** whether the network interface is 'up'. this is
* a software flag used to control whether this network
* interface is enabled and processes traffic */
* interface is enabled and processes traffic.
*/
#define NETIF_FLAG_UP 0x1U
/** if set, the netif has broadcast capability */
#define NETIF_FLAG_BROADCAST 0x2U
@@ -59,35 +62,36 @@
/** if set, the interface is configured using DHCP */
#define NETIF_FLAG_DHCP 0x08U
/** if set, the interface has an active link
* (set by the interface) */
* (set by the network interface driver) */
#define NETIF_FLAG_LINK_UP 0x10U
/** generic data structure used for all lwIP network interfaces */
/** Generic data structure used for all lwIP network interfaces.
* The following fields should be filled in by the initialization
* function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
struct netif {
/** pointer to next in linked list */
struct netif *next;
/** The following fields should be filled in by the
initialization function for the device driver. */
/** IP address configuration in network byte order */
struct ip_addr ip_addr;
struct ip_addr netmask;
struct ip_addr gw;
/** This function is called by the network device driver
to pass a packet up the TCP/IP stack. */
* to pass a packet up the TCP/IP stack. */
err_t (* input)(struct pbuf *p, struct netif *inp);
/** This function is called by the IP module when it wants
to send a packet on the interface. This function typically
first resolves the hardware address, then sends the packet. */
* to send a packet on the interface. This function typically
* first resolves the hardware address, then sends the packet. */
err_t (* output)(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr);
/** This function is called by the ARP module when it wants
to send a packet on the interface. This function outputs
the pbuf as-is on the link medium. */
* to send a packet on the interface. This function outputs
* the pbuf as-is on the link medium. */
err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
/** This field can be set by the device driver and could point
to state information for the device. */
* to state information for the device. */
void *state;
#if LWIP_DHCP
/** the DHCP client state information for this netif */
@@ -99,12 +103,14 @@ struct netif {
unsigned char hwaddr[NETIF_MAX_HWADDR_LEN];
/** maximum transfer unit (in bytes) */
u16_t mtu;
/** flags (see NETIF_FLAG_ above) */
u8_t flags;
/** link type */
u8_t link_type;
/** descriptive abbreviation */
char name[2];
/** number of this interface */
u8_t num;
/** NETIF_FLAG_* */
u8_t flags;
};
/** The list of network interfaces. */
@@ -115,7 +121,7 @@ extern struct netif *netif_default;
/* netif_init() must be called first. */
void netif_init(void);
struct netif *netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
struct netif *netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
struct ip_addr *gw,
void *state,
err_t (* init)(struct netif *netif),
@@ -137,5 +143,8 @@ void netif_set_default(struct netif *netif);
void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr);
void netif_set_netmask(struct netif *netif, struct ip_addr *netmast);
void netif_set_gw(struct netif *netif, struct ip_addr *gw);
void netif_set_up(struct netif *netif);
void netif_set_down(struct netif *netif);
u8_t netif_is_up(struct netif *netif);
#endif /* __LWIP_NETIF_H__ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -32,9 +32,9 @@
#ifndef __LWIP_OPT_H__
#define __LWIP_OPT_H__
#include "lwip/debug.h"
/* Include user defined options first */
#include "lwipopts.h"
#include "lwip/debug.h"
/* Define default values for unconfigured parameters. */
@@ -67,6 +67,10 @@ a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE 1600
#endif
#ifndef MEMP_SANITY_CHECK
#define MEMP_SANITY_CHECK 0
#endif
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high. */
@@ -74,6 +78,11 @@ a lot of data that needs to be copied, this should be set high. */
#define MEMP_NUM_PBUF 16
#endif
/* Number of raw connection PCBs */
#ifndef MEMP_NUM_RAW_PCB
#define MEMP_NUM_RAW_PCB 4
#endif
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#ifndef MEMP_NUM_UDP_PCB
@@ -137,10 +146,10 @@ a lot of data that needs to be copied, this should be set high. */
#endif
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
link level header. */
link level header. Defaults to 14 for Ethernet. */
#ifndef PBUF_LINK_HLEN
#define PBUF_LINK_HLEN 0
#define PBUF_LINK_HLEN 14
#endif
@@ -154,26 +163,28 @@ a lot of data that needs to be copied, this should be set high. */
/**
* If enabled, outgoing packets are queued during hardware address
* resolution. The etharp.c implementation queues 1 packet only.
* resolution.
*
* This feature has not stabilized yet. Single-packet queueing is
* believed to be stable, multi-packet queueing is believed to
* clash with the TCP segment queueing.
*
* As multi-packet-queueing is currently disabled, enabling this
* _should_ work, but we need your testing feedback on lwip-users.
*
*/
#ifndef ARP_QUEUEING
#define ARP_QUEUEING 1
#endif
/** If enabled, the first packet queued will not be overwritten by
* later packets. If disabled, later packets overwrite early packets
* in the queue. Default is disabled, which is recommended.
*/
#ifndef ARP_QUEUE_FIRST
#define ARP_QUEUE_FIRST 0
/* This option is deprecated */
#ifdef ETHARP_QUEUE_FIRST
#error ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h.
#endif
/**
* If defined to 1, cache entries are updated or added for every kind of ARP traffic
* or broadcast IP traffic. Recommended for routers.
* If defined to 0, only existing cache entries are updated. Entries are added when
* lwIP is sending to them. Recommended for embedded devices.
*/
#ifndef ETHARP_ALWAYS_INSERT
#define ETHARP_ALWAYS_INSERT 1
/* This option is removed to comply with the ARP standard */
#ifdef ETHARP_ALWAYS_INSERT
#error ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h.
#endif
/* ---------- IP options ---------- */
@@ -211,6 +222,16 @@ a lot of data that needs to be copied, this should be set high. */
#define ICMP_TTL 255
#endif
/* ---------- RAW options ---------- */
#ifndef LWIP_RAW
#define LWIP_RAW 1
#endif
#ifndef RAW_TTL
#define RAW_TTL 255
#endif
/* ---------- DHCP options ---------- */
#ifndef LWIP_DHCP
@@ -288,8 +309,10 @@ a lot of data that needs to be copied, this should be set high. */
#define TCP_SNDLOWAT TCP_SND_BUF/2
#endif
/* Support loop interface (127.0.0.1) */
#ifndef LWIP_HAVE_LOOPIF
#define LWIP_HAVE_LOOPIF 1
#endif
#ifndef LWIP_EVENT_API
#define LWIP_EVENT_API 0
@@ -320,6 +343,14 @@ a lot of data that needs to be copied, this should be set high. */
#define DEFAULT_THREAD_PRIO 1
#endif
/* ---------- Socket Options ---------- */
/* Enable SO_REUSEADDR and SO_REUSEPORT options */
#ifndef SO_REUSE
# define SO_REUSE 0
#endif
/* ---------- Statistics options ---------- */
#ifndef LWIP_STATS
#define LWIP_STATS 1
@@ -327,15 +358,68 @@ a lot of data that needs to be copied, this should be set high. */
#if LWIP_STATS
#define LINK_STATS
#define IP_STATS
#define ICMP_STATS
#define UDP_STATS
#define TCP_STATS
#define MEM_STATS
#define MEMP_STATS
#define PBUF_STATS
#define SYS_STATS
#ifndef LWIP_STATS_DISPLAY
#define LWIP_STATS_DISPLAY 0
#endif
#ifndef LINK_STATS
#define LINK_STATS 1
#endif
#ifndef IP_STATS
#define IP_STATS 1
#endif
#ifndef IPFRAG_STATS
#define IPFRAG_STATS 1
#endif
#ifndef ICMP_STATS
#define ICMP_STATS 1
#endif
#ifndef UDP_STATS
#define UDP_STATS 1
#endif
#ifndef TCP_STATS
#define TCP_STATS 1
#endif
#ifndef MEM_STATS
#define MEM_STATS 1
#endif
#ifndef MEMP_STATS
#define MEMP_STATS 1
#endif
#ifndef PBUF_STATS
#define PBUF_STATS 1
#endif
#ifndef SYS_STATS
#define SYS_STATS 1
#endif
#ifndef RAW_STATS
#define RAW_STATS 0
#endif
#else
#define LINK_STATS 0
#define IP_STATS 0
#define IPFRAG_STATS 0
#define ICMP_STATS 0
#define UDP_STATS 0
#define TCP_STATS 0
#define MEM_STATS 0
#define MEMP_STATS 0
#define PBUF_STATS 0
#define SYS_STATS 0
#define RAW_STATS 0
#define LWIP_STATS_DISPLAY 0
#endif /* LWIP_STATS */
@@ -426,6 +510,31 @@ a lot of data that needs to be copied, this should be set high. */
#endif /* PPP_SUPPORT */
/* checksum options - set to zero for hardware checksum support */
#ifndef CHECKSUM_GEN_IP
#define CHECKSUM_GEN_IP 1
#endif
#ifndef CHECKSUM_GEN_UDP
#define CHECKSUM_GEN_UDP 1
#endif
#ifndef CHECKSUM_GEN_TCP
#define CHECKSUM_GEN_TCP 1
#endif
#ifndef CHECKSUM_CHECK_IP
#define CHECKSUM_CHECK_IP 1
#endif
#ifndef CHECKSUM_CHECK_UDP
#define CHECKSUM_CHECK_UDP 1
#endif
#ifndef CHECKSUM_CHECK_TCP
#define CHECKSUM_CHECK_TCP 1
#endif
/* Debugging options all default to off */
@@ -433,10 +542,6 @@ a lot of data that needs to be copied, this should be set high. */
#define DBG_TYPES_ON 0
#endif
#ifndef DEMO_DEBUG
#define DEMO_DEBUG DBG_OFF
#endif
#ifndef ETHARP_DEBUG
#define ETHARP_DEBUG DBG_OFF
#endif
@@ -477,6 +582,10 @@ a lot of data that needs to be copied, this should be set high. */
#define IP_REASS_DEBUG DBG_OFF
#endif
#ifndef RAW_DEBUG
#define RAW_DEBUG DBG_OFF
#endif
#ifndef MEM_DEBUG
#define MEM_DEBUG DBG_OFF
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -29,7 +29,7 @@
* Author: Adam Dunkels <adam@sics.se>
*
*/
/*-----------------------------------------------------------------------------------*/
#ifndef __LWIP_PBUF_H__
#define __LWIP_PBUF_H__
@@ -53,8 +53,8 @@ typedef enum {
PBUF_POOL
} pbuf_flag;
/* Definitions for the pbuf flag field (these are not the flags that
are passed to pbuf_alloc()). */
/* Definitions for the pbuf flag field. These are NOT the flags that
* are passed to pbuf_alloc(). */
#define PBUF_FLAG_RAM 0x00U /* Flags that pbuf data is stored in RAM */
#define PBUF_FLAG_ROM 0x01U /* Flags that pbuf data is stored in ROM */
#define PBUF_FLAG_POOL 0x02U /* Flags that the pbuf comes from the pbuf pool */
@@ -79,10 +79,10 @@ struct pbuf {
*/
u16_t tot_len;
/* length of this buffer */
/** length of this buffer */
u16_t len;
/* flags telling the type of pbuf */
/** flags telling the type of pbuf, see PBUF_FLAG_ */
u16_t flags;
/**
@@ -94,11 +94,6 @@ struct pbuf {
};
/* pbuf_init():
Initializes the pbuf module. The num parameter determines how many
pbufs that should be allocated to the pbuf pool, and the size
parameter specifies the size of the data allocated to those. */
void pbuf_init(void);
struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag);
@@ -108,8 +103,11 @@ void pbuf_ref(struct pbuf *p);
void pbuf_ref_chain(struct pbuf *p);
u8_t pbuf_free(struct pbuf *p);
u8_t pbuf_clen(struct pbuf *p);
void pbuf_cat(struct pbuf *h, struct pbuf *t);
void pbuf_chain(struct pbuf *h, struct pbuf *t);
struct pbuf *pbuf_take(struct pbuf *f);
struct pbuf *pbuf_dechain(struct pbuf *p);
void pbuf_queue(struct pbuf *p, struct pbuf *n);
struct pbuf * pbuf_dequeue(struct pbuf *p);
#endif /* __LWIP_PBUF_H__ */

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;
u8_t (* 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,
u8_t (* recv)(void *arg, struct raw_pcb *pcb,
struct pbuf *p,
struct ip_addr *addr),
void *recv_arg);
err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr);
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
/* The following functions are the lower layer interface to RAW. */
u8_t raw_input (struct pbuf *p, struct netif *inp);
void raw_init (void);
#endif /* __LWIP_RAW_H__ */

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -40,8 +40,6 @@
#include "lwip/ip.h"
#include "lwip/icmp.h"
#include "lwip/sys.h"
#include "lwip/err.h"
struct tcp_pcb;
@@ -53,7 +51,7 @@ void tcp_init (void); /* Must be called first to
initialize TCP. */
void tcp_tmr (void); /* Must be called every
TCP_TMR_INTERVAL
ms. (Typically 100 ms). */
ms. (Typically 250 ms). */
/* Application program's interface: */
struct tcp_pcb * tcp_new (void);
struct tcp_pcb * tcp_alloc (u8_t prio);
@@ -107,6 +105,7 @@ void tcp_input (struct pbuf *p, struct netif *inp);
/* Used within the TCP code only: */
err_t tcp_output (struct tcp_pcb *pcb);
void tcp_rexmit (struct tcp_pcb *pcb);
void tcp_rexmit_rto (struct tcp_pcb *pcb);
@@ -114,31 +113,37 @@ void tcp_rexmit (struct tcp_pcb *pcb);
#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
/* is b<=a<=c? */
#if 0 /* see bug #10548 */
#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
#endif
#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
#define TCP_FIN 0x01U
#define TCP_SYN 0x02U
#define TCP_RST 0x04U
#define TCP_PSH 0x08U
#define TCP_ACK 0x10U
#define TCP_URG 0x20U
#define TCP_ECE 0x40U
#define TCP_CWR 0x80U
#define TCP_FIN 0x01
#define TCP_SYN 0x02
#define TCP_RST 0x04
#define TCP_PSH 0x08
#define TCP_ACK 0x10
#define TCP_URG 0x20
#define TCP_FLAGS 0x3f
#define TCP_FLAGS 0x3fU
/* Length of the TCP header, excluding options. */
#define TCP_HLEN 20
#ifndef TCP_TMR_INTERVAL
#define TCP_TMR_INTERVAL 100 /* The TCP timer interval in
#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in
milliseconds. */
#endif /* TCP_TMR_INTERVAL */
#ifndef TCP_FAST_INTERVAL
#define TCP_FAST_INTERVAL 200 /* the fine grained timeout in
#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in
milliseconds */
#endif /* TCP_FAST_INTERVAL */
#ifndef TCP_SLOW_INTERVAL
#define TCP_SLOW_INTERVAL 500 /* the coarse grained timeout in
#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in
milliseconds */
#endif /* TCP_SLOW_INTERVAL */
@@ -149,6 +154,19 @@ void tcp_rexmit (struct tcp_pcb *pcb);
#define TCP_MSL 60000 /* The maximum segment lifetime in microseconds */
/*
* User-settable options (used with setsockopt).
*/
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keepalive miliseconds */
/* Keepalive values */
#define TCP_KEEPDEFAULT 7200000 /* KEEPALIVE timer in miliseconds */
#define TCP_KEEPINTVL 75000 /* Time between KEEPALIVE probes in miliseconds */
#define TCP_KEEPCNT 9 /* Counter for KEEPALIVE probes */
#define TCP_MAXIDLE TCP_KEEPCNT * TCP_KEEPINTVL /* Maximum KEEPALIVE probe time */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
@@ -158,7 +176,7 @@ struct tcp_hdr {
PACK_STRUCT_FIELD(u16_t dest);
PACK_STRUCT_FIELD(u32_t seqno);
PACK_STRUCT_FIELD(u32_t ackno);
PACK_STRUCT_FIELD(u16_t _offset_flags);
PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
PACK_STRUCT_FIELD(u16_t wnd);
PACK_STRUCT_FIELD(u16_t chksum);
PACK_STRUCT_FIELD(u16_t urgp);
@@ -168,11 +186,15 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
#define TCPH_OFFSET(hdr) (ntohs((hdr)->_offset_flags) >> 8)
#define TCPH_FLAGS(hdr) (ntohs((hdr)->_offset_flags) & 0xff)
#define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
#define TCPH_OFFSET_SET(hdr, offset) (hdr)->_offset_flags = htons(((offset) << 8) | TCPH_FLAGS(hdr))
#define TCPH_FLAGS_SET(hdr, flags) (hdr)->_offset_flags = htons((TCPH_OFFSET(hdr) << 8) | (flags))
#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons((ntohs((phdr)->_hdrlen_rsvd_flags) & ~TCP_FLAGS) | (flags))
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (flags))
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & TCP_FIN || \
TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0))
@@ -191,21 +213,29 @@ enum tcp_state {
TIME_WAIT = 10
};
/* the TCP protocol control block */
struct tcp_pcb {
struct tcp_pcb *next; /* for the linked list */
/** common PCB members */
IP_PCB;
/** protocol specific PCB members */
struct tcp_pcb *next; /* for the linked list */
enum tcp_state state; /* TCP state */
u8_t prio;
void *callback_arg;
struct ip_addr local_ip;
u16_t local_port;
enum tcp_state state; /* TCP state */
struct ip_addr remote_ip;
u16_t remote_port;
/* receiver varables */
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 variables */
u32_t rcv_nxt; /* next seqno expected */
u16_t rcv_wnd; /* receiver window */
@@ -217,19 +247,11 @@ struct tcp_pcb {
u16_t rtime;
u16_t mss; /* maximum segment size */
u8_t flags;
#define TF_ACK_DELAY 0x01U /* Delayed ACK. */
#define TF_ACK_NOW 0x02U /* Immediate ACK. */
#define TF_INFR 0x04U /* In fast recovery. */
#define TF_RESET 0x08U /* Connection was reset. */
#define TF_CLOSED 0x10U /* Connection was sucessfully closed. */
#define TF_GOT_FIN 0x20U /* Connection was closed by the remote end. */
/* RTT estimation variables. */
u16_t rttest; /* RTT estimate in 500ms ticks */
/* RTT (round trip time) estimation variables */
u32_t rttest; /* RTT estimate in 500ms ticks */
u32_t rtseq; /* sequence number being timed */
s16_t sa, sv;
s16_t sa, sv; /* @todo document this */
u16_t rto; /* retransmission time-out */
u8_t nrtx; /* number of retransmissions */
@@ -282,21 +304,32 @@ struct tcp_pcb {
/* Function to be called whenever a fatal error occurs. */
void (* errf)(void *arg, err_t err);
#endif /* LWIP_CALLBACK_API */
/* idle time before KEEPALIVE is sent */
u32_t keepalive;
/* KEEPALIVE counter */
u8_t keep_cnt;
};
struct tcp_pcb_listen {
/* Common members of all PCB types */
IP_PCB;
/* Protocol specific PCB members */
struct tcp_pcb_listen *next; /* for the linked list */
u8_t prio;
void *callback_arg;
struct ip_addr local_ip;
u16_t local_port;
/* Even if state is obviously LISTEN this is here for
* field compatibility with tpc_pcb to which it is cast sometimes
* Until a cleaner solution emerges this is here.FIXME
*/
enum tcp_state state; /* TCP state */
u8_t prio;
void *callback_arg;
u16_t local_port;
#if LWIP_CALLBACK_API
/* Function to call when a listener has been connected. */
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
@@ -342,7 +375,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
#define TCP_EVENT_RECV(pcb,p,err,ret) \
if((pcb)->recv != NULL) \
{ ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
pbuf_free(p); }
if (p) pbuf_free(p); }
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
if((pcb)->connected != NULL) \
(ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
@@ -354,7 +387,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
(errf)((arg),(err))
#endif /* LWIP_EVENT_API */
/* This structure is used to repressent TCP segments when queued. */
/* This structure represents a TCP segment on the unsent and unacked queues */
struct tcp_seg {
struct tcp_seg *next; /* used when putting segements on a queue */
struct pbuf *p; /* buffer containing data + TCP header */
@@ -396,6 +429,8 @@ void tcp_rst(u32_t seqno, u32_t ackno,
u32_t tcp_next_iss(void);
void tcp_keepalive(struct tcp_pcb *pcb);
extern struct tcp_pcb *tcp_input_pcb;
extern u32_t tcp_ticks;
@@ -406,7 +441,11 @@ void tcp_debug_print_state(enum tcp_state s);
void tcp_debug_print_pcbs(void);
int tcp_pcbs_sane(void);
#else
#define tcp_pcbs_sane() 1
# define tcp_debug_print(tcphdr)
# define tcp_debug_print_flags(flags)
# define tcp_debug_print_state(s)
# define tcp_debug_print_pcbs()
# define tcp_pcbs_sane() 1
#endif /* TCP_DEBUG */
#if NO_SYS
@@ -416,7 +455,11 @@ void tcp_timer_needed(void);
#endif
/* The TCP PCB lists. */
extern struct tcp_pcb_listen *tcp_listen_pcbs; /* List of all TCP PCBs in LISTEN state. */
union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
struct tcp_pcb_listen *listen_pcbs;
struct tcp_pcb *pcbs;
};
extern union tcp_listen_pcbs_t tcp_listen_pcbs;
extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
state in which they accept or send
data. */

View File

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

View File

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

View File

@@ -1,5 +1,7 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
* Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -33,6 +35,10 @@
#ifndef __NETIF_ETHARP_H__
#define __NETIF_ETHARP_H__
#ifndef ETH_PAD_SIZE
#define ETH_PAD_SIZE 0
#endif
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
@@ -46,15 +52,30 @@ struct eth_addr {
PACK_STRUCT_FIELD(u8_t addr[6]);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct eth_hdr {
#if ETH_PAD_SIZE
PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
#endif
PACK_STRUCT_FIELD(struct eth_addr dest);
PACK_STRUCT_FIELD(struct eth_addr src);
PACK_STRUCT_FIELD(u16_t type);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
/** the ARP message */
struct etharp_hdr {
@@ -64,35 +85,42 @@ struct etharp_hdr {
PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
PACK_STRUCT_FIELD(u16_t opcode);
PACK_STRUCT_FIELD(struct eth_addr shwaddr);
PACK_STRUCT_FIELD(struct ip_addr sipaddr);
PACK_STRUCT_FIELD(struct ip_addr2 sipaddr);
PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
PACK_STRUCT_FIELD(struct ip_addr dipaddr);
PACK_STRUCT_FIELD(struct ip_addr2 dipaddr);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
PACK_STRUCT_BEGIN
struct ethip_hdr {
PACK_STRUCT_FIELD(struct eth_hdr eth);
PACK_STRUCT_FIELD(struct ip_hdr ip);
};
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#define ARP_TMR_INTERVAL 10000
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ethip_hdr {
PACK_STRUCT_FIELD(struct eth_hdr eth);
PACK_STRUCT_FIELD(struct ip_hdr ip);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
/** 5 seconds period */
#define ARP_TMR_INTERVAL 5000
#define ETHTYPE_ARP 0x0806
#define ETHTYPE_IP 0x0800
void etharp_init(void);
void etharp_tmr(void);
struct pbuf *etharp_ip_input(struct netif *netif, struct pbuf *p);
struct pbuf *etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
void etharp_ip_input(struct netif *netif, struct pbuf *p);
void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
struct pbuf *p);
struct pbuf *etharp_output(struct netif *netif, struct ip_addr *ipaddr,
err_t etharp_output(struct netif *netif, struct ip_addr *ipaddr,
struct pbuf *q);
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q);
err_t etharp_request(struct netif *netif, struct ip_addr *ipaddr);
#endif /* __NETIF_ARP_H__ */

View File

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

View File

@@ -1,17 +1,18 @@
This directory contains generic network interface device drivers that
don't contain any hardware or architecture specific code. The files
do not contain any hardware or architecture specific code. The files
are:
etharp.c
Implements the ARP (Address Resolution Protocol) over
Ethernet. The code in this file should be used together with
Ethernet device drivers.
Ethernet device drivers. Note that this module has been
largely made Ethernet independent so you should be able to
adapt this for other link layers (such as Firewire).
ethernetif.c
An example of how an Ethernet device driver could look. This
file can be used as a "skeleton" for developing new Ethernet
network device drivers. It uses the etharp.c ARP code.
!!!THIS FILE IS NOT IN SYNC WITH CURRENT CODE !!!!
loopif.c
An example network interface that shows how a "loopback"

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -35,8 +35,6 @@
* drivers for lwIP. Add code to the low_level functions and do a
* search-and-replace for the word "ethernetif" to replace it with
* something that better describes your network interface.
*
* THIS CODE NEEDS TO BE FIXED - IT IS NOT In SYNC WITH CURRENT ETHARP API
*/
#include "lwip/opt.h"
@@ -44,12 +42,13 @@
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include <lwip/stats.h>
#include "netif/arp.h"
#include "netif/etharp.h"
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 't'
#define IFNAME1 'n'
struct ethernetif {
struct eth_addr *ethaddr;
@@ -63,13 +62,10 @@ static void ethernetif_input(struct netif *netif);
static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr);
/*-----------------------------------------------------------------------------------*/
static void
low_level_init(struct netif *netif)
{
struct ethernetif *ethernetif;
ethernetif = netif->state;
struct ethernetif *ethernetif = netif->state;
/* set MAC hardware address length */
netif->hwaddr_len = 6;
@@ -77,7 +73,7 @@ low_level_init(struct netif *netif)
/* set MAC hardware address */
netif->hwaddr[0] = ;
...
netif->hwaddr[6] = ;
netif->hwaddr[5] = ;
/* maximum transfer unit */
netif->mtu = 1500;
@@ -87,7 +83,7 @@ low_level_init(struct netif *netif)
/* Do whatever else is needed to initialize interface. */
}
/*-----------------------------------------------------------------------------------*/
/*
* low_level_output():
*
@@ -96,15 +92,19 @@ low_level_init(struct netif *netif)
* might be chained.
*
*/
/*-----------------------------------------------------------------------------------*/
static err_t
low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
low_level_output(struct netif *netif, struct pbuf *p)
{
struct ethernetif *ethernetif = netif->state;
struct pbuf *q;
initiate transfer();
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
for(q = p; q != NULL; q = q->next) {
/* Send the data from the pbuf to the interface, one pbuf at a
time. The size of the data in each pbuf is kept in the ->len
@@ -113,14 +113,18 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
}
signal that packet should be sent();
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.xmit++;
#endif /* LINK_STATS */
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* low_level_input():
*
@@ -128,10 +132,11 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
* packet from the interface into the pbuf.
*
*/
/*-----------------------------------------------------------------------------------*/
static struct pbuf *
low_level_input(struct ethernetif *ethernetif)
low_level_input(struct netif *netif)
{
struct ethernetif *ethernetif = netif->state;
struct pbuf *p, *q;
u16_t len;
@@ -139,25 +144,39 @@ low_level_input(struct ethernetif *ethernetif)
variable. */
len = ;
#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p != NULL) {
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
/* We iterate over the pbuf chain until we have read the entire
packet into the pbuf. */
* packet into the pbuf. */
for(q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the chain. The
available data in the pbuf is given by the q->len
variable. */
* available data in the pbuf is given by the q->len
* variable. */
read data into(q->payload, q->len);
}
acknowledge that packet has been read();
#ifdef LINK_STATS
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
#if LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
} else {
drop packet();
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif /* LINK_STATS */
@@ -165,106 +184,26 @@ low_level_input(struct ethernetif *ethernetif)
return p;
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_output():
*
* This function is called by the TCP/IP stack when an IP packet
* should be sent. It calls the function called low_level_output() to
* do the actuall transmission of the packet.
* do the actual transmission of the packet.
*
*/
/*-----------------------------------------------------------------------------------*/
static err_t
ethernetif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr)
{
struct ethernetif *ethernetif;
struct pbuf *q;
struct eth_hdr *ethhdr;
struct eth_addr *dest, mcastaddr;
struct ip_addr *queryaddr;
err_t err;
u8_t i;
ethernetif = netif->state;
/* Make room for Ethernet header. */
if (pbuf_header(p, 14) != 0) {
/* The pbuf_header() call shouldn't fail, but we allocate an extra
pbuf just in case. */
q = pbuf_alloc(PBUF_LINK, 14, PBUF_RAM);
if (q == NULL) {
#ifdef LINK_STATS
lwip_stats.link.drop++;
lwip_stats.link.memerr++;
#endif /* LINK_STATS */
return ERR_MEM;
}
pbuf_chain(q, p);
p = q;
}
/* Construct Ethernet header. Start with looking up deciding which
MAC address to use as a destination address. Broadcasts and
multicasts are special, all other addresses are looked up in the
ARP table. */
queryaddr = ipaddr;
if (ip_addr_isany(ipaddr) ||
ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
dest = (struct eth_addr *)&ethbroadcast;
} else if (ip_addr_ismulticast(ipaddr)) {
/* Hash IP multicast address to MAC address. */
mcastaddr.addr[0] = 0x01;
mcastaddr.addr[1] = 0x0;
mcastaddr.addr[2] = 0x5e;
mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
mcastaddr.addr[4] = ip4_addr3(ipaddr);
mcastaddr.addr[5] = ip4_addr4(ipaddr);
dest = &mcastaddr;
} else {
if (ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
/* Use destination IP address if the destination is on the same
subnet as we are. */
queryaddr = ipaddr;
} else {
/* Otherwise we use the default router as the address to send
the Ethernet frame to. */
queryaddr = &(netif->gw);
}
dest = arp_lookup(queryaddr);
}
/* If the arp_lookup() didn't find an address, we send out an ARP
query for the IP address. */
if (dest == NULL) {
q = arp_query(netif, ethernetif->ethaddr, queryaddr);
if (q != NULL) {
err = low_level_output(ethernetif, q);
pbuf_free(q);
return err;
}
#ifdef LINK_STATS
lwip_stats.link.drop++;
lwip_stats.link.memerr++;
#endif /* LINK_STATS */
return ERR_MEM;
}
ethhdr = p->payload;
for(i = 0; i < 6; i++) {
ethhdr->dest.addr[i] = dest->addr[i];
ethhdr->src.addr[i] = ethernetif->ethaddr->addr[i];
}
ethhdr->type = htons(ETHTYPE_IP);
return low_level_output(ethernetif, p);
/* resolve hardware address, then send (or queue) packet */
return etharp_output(netif, ipaddr, p);
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_input():
*
@@ -274,7 +213,7 @@ ethernetif_output(struct netif *netif, struct pbuf *p,
* interface.
*
*/
/*-----------------------------------------------------------------------------------*/
static void
ethernetif_input(struct netif *netif)
{
@@ -282,46 +221,50 @@ ethernetif_input(struct netif *netif)
struct eth_hdr *ethhdr;
struct pbuf *p;
ethernetif = netif->state;
p = low_level_input(ethernetif);
/* move received packet into a new pbuf */
p = low_level_input(netif);
/* no packet could be read, silently ignore this */
if (p == NULL) return;
/* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload;
if (p != NULL) {
#ifdef LINK_STATS
lwip_stats.link.recv++;
#if LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
ethhdr = p->payload;
ethhdr = p->payload;
switch (htons(ethhdr->type)) {
case ETHTYPE_IP:
arp_ip_input(netif, p);
pbuf_header(p, -14);
netif->input(p, netif);
break;
switch (htons(ethhdr->type)) {
/* IP packet? */
case ETHTYPE_IP:
/* update ARP table */
etharp_ip_input(netif, p);
/* skip Ethernet header */
pbuf_header(p, -sizeof(struct eth_hdr));
/* pass to network layer */
netif->input(p, netif);
break;
case ETHTYPE_ARP:
p = arp_arp_input(netif, ethernetif->ethaddr, p);
if (p != NULL) {
low_level_output(ethernetif, p);
pbuf_free(p);
}
/* pass p to ARP module */
etharp_arp_input(netif, ethernetif->ethaddr, p);
break;
default:
pbuf_free(p);
p = NULL;
break;
}
}
}
/*-----------------------------------------------------------------------------------*/
static void
arp_timer(void *arg)
{
arp_tmr();
etharp_tmr();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_init():
*
@@ -330,13 +273,20 @@ arp_timer(void *arg)
* actual setup of the hardware.
*
*/
/*-----------------------------------------------------------------------------------*/
void
err_t
ethernetif_init(struct netif *netif)
{
struct ethernetif *ethernetif;
ethernetif = mem_malloc(sizeof(struct ethernetif));
if (ethernetif == NULL)
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
return ERR_MEM;
}
netif->state = ethernetif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
@@ -346,8 +296,11 @@ ethernetif_init(struct netif *netif)
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
low_level_init(netif);
arp_init();
etharp_init();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/

View File

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

View File

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

View File

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

View File

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

View File

@@ -49,6 +49,8 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <string.h>
#include "ppp.h"
#if PPP_SUPPORT > 0
#include "auth.h"
@@ -178,6 +180,20 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
/*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/
/*
* Non-standard inet_ntoa left here for compat with original ppp
* sources. Assumes u32_t instead of struct in_addr.
*/
char * _inet_ntoa(u32_t n)
{
struct in_addr ia;
ia.s_addr = n;
return inet_ntoa(ia);
}
#define inet_ntoa _inet_ntoa
/*
* ipcp_init - Initialize IPCP.
*/
@@ -1192,12 +1208,12 @@ static void ipcp_up(fsm *f)
ho->hisaddr = wo->hisaddr;
if (ho->hisaddr == 0) {
ppp_trace(LOG_ERR, "Could not determine remote IP address\n");
IPCPDEBUG((LOG_ERR, "Could not determine remote IP address\n"));
ipcp_close(f->unit, "Could not determine remote IP address");
return;
}
if (go->ouraddr == 0) {
ppp_trace(LOG_ERR, "Could not determine local IP address\n");
IPCPDEBUG((LOG_ERR, "Could not determine local IP address\n"));
ipcp_close(f->unit, "Could not determine local IP address");
return;
}
@@ -1210,8 +1226,8 @@ static void ipcp_up(fsm *f)
* Check that the peer is allowed to use the IP address it wants.
*/
if (!auth_ip_addr(f->unit, ho->hisaddr)) {
ppp_trace(LOG_ERR, "Peer is not authorized to use remote address %s\n",
inet_ntoa(ho->hisaddr));
IPCPDEBUG((LOG_ERR, "Peer is not authorized to use remote address %s\n",
inet_ntoa(ho->hisaddr)));
ipcp_close(f->unit, "Unauthorized remote IP address");
return;
}

View File

@@ -49,6 +49,9 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <string.h>
#include "ppp.h"
#if PPP_SUPPORT > 0
#include "fsm.h"

View File

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

View File

@@ -78,6 +78,9 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <string.h>
#include "ppp.h"
#if PPP_SUPPORT > 0
#include "randm.h"
@@ -153,7 +156,7 @@ typedef struct PPPControl_s {
struct vjcompress vjComp; /* Van Jabobsen compression header. */
#endif
struct netif *netif;
struct netif netif;
struct ppp_addrs addrs;
@@ -290,13 +293,12 @@ void pppInit(void)
memset(&ppp_settings, 0, sizeof(ppp_settings));
ppp_settings.usepeerdns = 1;
ppp_settings.refuse_chap = (CHAP_SUPPORT == 0);
pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL);
magicInit();
for (i = 0; i < NUM_PPP; i++) {
pppControl[i].openFlag = 0;
pppControl[i].netif = NULL;
subnetMask = htonl(0xffffff00);
@@ -307,25 +309,69 @@ void pppInit(void)
(*protp->init)(i);
}
#ifdef LINK_STATS
#if LINK_STATS
/* Clear the statistics. */
memset(&lwip_stats.link, 0, sizeof(lwip_stats.link));
#endif
}
void pppSetAuth(const char *user, const char *passwd)
void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
{
if(user) {
strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0';
} else
ppp_settings.user[0] = '\0';
switch(authType) {
case PPPAUTHTYPE_NONE:
default:
#ifdef LWIP_PPP_STRICT_PAP_REJECT
ppp_settings.refuse_pap = 1;
#else
/* some providers request pap and accept an empty login/pw */
ppp_settings.refuse_pap = 0;
#endif
ppp_settings.refuse_chap = 1;
break;
case PPPAUTHTYPE_ANY:
/* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
* RFC 1994 says:
*
* In practice, within or associated with each PPP server, there is a
* database which associates "user" names with authentication
* information ("secrets"). It is not anticipated that a particular
* named user would be authenticated by multiple methods. This would
* make the user vulnerable to attacks which negotiate the least secure
* method from among a set (such as PAP rather than CHAP). If the same
* secret was used, PAP would reveal the secret to be used later with
* CHAP.
*
* Instead, for each user name there should be an indication of exactly
* one method used to authenticate that user name. If a user needs to
* make use of different authentication methods under different
* circumstances, then distinct user names SHOULD be employed, each of
* which identifies exactly one authentication method.
*
*/
ppp_settings.refuse_pap = 0;
ppp_settings.refuse_chap = 0;
break;
case PPPAUTHTYPE_PAP:
ppp_settings.refuse_pap = 0;
ppp_settings.refuse_chap = 1;
break;
case PPPAUTHTYPE_CHAP:
ppp_settings.refuse_pap = 1;
ppp_settings.refuse_chap = 0;
break;
}
if(passwd) {
strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1);
ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0';
} else
ppp_settings.passwd[0] = '\0';
if(user) {
strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0';
} else
ppp_settings.user[0] = '\0';
if(passwd) {
strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1);
ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0';
} else
ppp_settings.passwd[0] = '\0';
}
/* Open a new PPP connection using the given I/O device.
@@ -438,7 +484,7 @@ static void nPut(PPPControl *pc, struct pbuf *nb)
if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
PPPDEBUG((LOG_WARNING,
"PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.err++;
#endif /* LINK_STATS */
pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
@@ -447,7 +493,7 @@ static void nPut(PPPControl *pc, struct pbuf *nb)
}
pbuf_free(nb);
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.xmit++;
#endif /* LINK_STATS */
}
@@ -471,7 +517,7 @@ static struct pbuf *pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
if (tb) {
nb->next = tb;
}
#ifdef LINK_STATS
#if LINK_STATS
else {
lwip_stats.link.memerr++;
}
@@ -493,14 +539,14 @@ static struct pbuf *pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
/* Send a packet on the given connection. */
static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
{
int pd = (int)netif->state;
u_short protocol = PPP_IP;
int pd = (int)netif->state;
u_short protocol = PPP_IP;
PPPControl *pc = &pppControl[pd];
u_int fcsOut = PPP_INITFCS;
struct pbuf *headMB = NULL, *tailMB = NULL, *p;
u_char c;
(void)ipaddr;
(void)ipaddr;
/* Validate parameters. */
/* We let any protocol value go through - it can't hurt us
@@ -508,7 +554,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n",
pd, protocol, pb));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.opterr++;
lwip_stats.link.drop++;
#endif
@@ -518,7 +564,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
/* Check that the link is up. */
if (lcp_phase[pd] == PHASE_DEAD) {
PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.rterr++;
lwip_stats.link.drop++;
#endif
@@ -529,7 +575,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) {
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif /* LINK_STATS */
@@ -556,7 +602,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
break;
default:
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.proterr++;
lwip_stats.link.drop++;
#endif
@@ -618,7 +664,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
"pppifOutput[%d]: Alloc err - dropping proto=%d\n",
pd, protocol));
pbuf_free(headMB);
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif
@@ -707,7 +753,7 @@ int pppWrite(int pd, const u_char *s, int n)
struct pbuf *headMB = NULL, *tailMB;
headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) {
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.proterr++;
#endif /* LINK_STATS */
@@ -747,7 +793,7 @@ int pppWrite(int pd, const u_char *s, int n)
"pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
/* "pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
pbuf_free(headMB);
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.proterr++;
#endif /* LINK_STATS */
@@ -959,12 +1005,10 @@ int sifup(int pd)
st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else {
if(pc->netif)
netif_remove(pc->netif);
pc->netif = netif_add(&pc->addrs.our_ipaddr, &pc->addrs.netmask, &pc->addrs.his_ipaddr, (void *)pd, pppifNetifInit, ip_input);
if(pc->netif) {
pc->if_up = 1;
pc->errCode = PPPERR_NONE;
netif_remove(&pc->netif);
if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, &pc->addrs.his_ipaddr, (void *)pd, pppifNetifInit, ip_input)) {
pc->if_up = 1;
pc->errCode = PPPERR_NONE;
PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
if(pc->linkStatusCB)
@@ -1002,12 +1046,10 @@ int sifdown(int pd)
PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
} else {
pc->if_up = 0;
if(pc->netif)
netif_remove(pc->netif);
pc->netif = NULL;
PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
if(pc->linkStatusCB)
pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
netif_remove(&pc->netif);
PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
if(pc->linkStatusCB)
pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
}
return st;
}
@@ -1082,7 +1124,7 @@ int sifdefaultroute(int pd, u32_t l, u32_t g)
st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else {
netif_set_default(pc->netif);
netif_set_default(&pc->netif);
}
/* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */
@@ -1194,7 +1236,7 @@ static void pppMain(void *arg)
pppInProc(pd, p->payload, c);
} else {
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
sys_msleep(250); /* give other tasks a chance to run */
sys_msleep(1); /* give other tasks a chance to run */
}
}
}
@@ -1254,7 +1296,7 @@ static void pppInput(void *arg)
pbuf_header(nb, -(int)sizeof(struct pppInputHeader));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
@@ -1280,7 +1322,7 @@ static void pppInput(void *arg)
* pass the result to IP.
*/
if (vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) {
pppControl[pd].netif->input(nb, pppControl[pd].netif);
pppControl[pd].netif.input(nb, &pppControl[pd].netif);
return;
}
/* Something's wrong so drop it. */
@@ -1298,7 +1340,7 @@ static void pppInput(void *arg)
* the packet to IP.
*/
if (vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) {
pppControl[pd].netif->input(nb, pppControl[pd].netif);
pppControl[pd].netif.input(nb, &pppControl[pd].netif);
return;
}
/* Something's wrong so drop it. */
@@ -1312,7 +1354,7 @@ static void pppInput(void *arg)
break;
case PPP_IP: /* Internet Protocol */
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;
default:
{
@@ -1344,7 +1386,7 @@ static void pppInput(void *arg)
}
drop:
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.drop++;
#endif
@@ -1374,7 +1416,7 @@ static void pppDrop(PPPControl *pc)
vj_uncompress_err(&pc->vjComp);
#endif
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.drop++;
#endif /* LINK_STATS */
}
@@ -1412,7 +1454,7 @@ static void pppInProc(int pd, u_char *s, int l)
PPPDEBUG((LOG_WARNING,
"pppInProc[%d]: Dropping incomplete packet %d\n",
pd, pc->inState));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.lenerr++;
#endif
pppDrop(pc);
@@ -1422,7 +1464,7 @@ static void pppInProc(int pd, u_char *s, int l)
PPPDEBUG((LOG_INFO,
"pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n",
pd, pc->inFCS, pc->inProtocol));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.chkerr++;
#endif
pppDrop(pc);
@@ -1436,14 +1478,12 @@ static void pppInProc(int pd, u_char *s, int l)
pc->inTail->tot_len = pc->inTail->len;
if (pc->inTail != pc->inHead) {
pbuf_chain(pc->inHead, pc->inTail);
pbuf_free(pc->inTail);
pbuf_cat(pc->inHead, pc->inTail);
}
} else {
pc->inTail->tot_len = pc->inTail->len;
if (pc->inTail != pc->inHead) {
pbuf_chain(pc->inHead, pc->inTail);
pbuf_free(pc->inTail);
pbuf_cat(pc->inHead, pc->inTail);
}
pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2);
@@ -1454,7 +1494,7 @@ static void pppInProc(int pd, u_char *s, int l)
PPPDEBUG((LOG_ERR,
"pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd));
pbuf_free(pc->inHead);
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.drop++;
#endif
}
@@ -1539,8 +1579,7 @@ static void pppInProc(int pd, u_char *s, int l)
if(pc->inTail) {
pc->inTail->tot_len = pc->inTail->len;
if (pc->inTail != pc->inHead) {
pbuf_chain(pc->inHead, pc->inTail);
pbuf_free(pc->inTail);
pbuf_cat(pc->inHead, pc->inTail);
}
}
/* If we haven't started a packet, we need a packet header. */
@@ -1550,7 +1589,7 @@ static void pppInProc(int pd, u_char *s, int l)
* higher layers deal with it. Continue processing
* the received pbuf chain in case a new packet starts. */
PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
#endif /* LINK_STATS */
pppDrop(pc);

View File

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

View File

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

View File

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

View File

@@ -28,14 +28,15 @@
* for a 16 bit processor.
*/
#include <string.h>
#include "ppp.h"
#include "vj.h"
#include "pppdebug.h"
#if VJ_SUPPORT > 0
#ifdef LINK_STATS
#if LINK_STATS
#define INCR(counter) ++comp->stats.counter
#else
#define INCR(counter)
@@ -611,8 +612,7 @@ int vj_uncompress_tcp(
*nb = NULL;
goto bad;
}
pbuf_chain(np, n0);
pbuf_free(n0);
pbuf_cat(np, n0);
n0 = np;
}
LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen);

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, Swedish Institute of Computer Science.
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -115,9 +115,7 @@ slipif_input( struct netif * netif )
/* Received whole packet. */
pbuf_realloc(q, recved);
#ifdef LINK_STATS
++lwip_stats.link.recv;
#endif /* LINK_STATS */
LINK_STATS_INC(link.recv);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
return q;
@@ -141,16 +139,13 @@ slipif_input( struct netif * netif )
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
#ifdef LINK_STATS
if (p == NULL) {
++lwip_stats.link.drop;
LINK_STATS_INC(link.drop);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
}
#endif /* LINK_STATS */
if (q != NULL) {
pbuf_chain(q, p);
pbuf_free(p);
pbuf_cat(q, p);
} else {
q = p;
}
@@ -204,6 +199,7 @@ slipif_init(struct netif *netif)
netif->name[1] = 'l';
netif->output = slipif_output;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_POINTTOPOINT;
netif->state = sio_open(netif->num);
if (!netif->state)