update lwip to 1.3.1
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@37 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
parent
1ae9da2752
commit
b9290bcef4
|
@ -19,8 +19,375 @@ HISTORY
|
|||
|
||||
++ New features:
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
|
||||
(STABLE-1.3.1)
|
||||
|
||||
++ New features:
|
||||
|
||||
2009-05-10 Simon Goldschmidt
|
||||
* opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option
|
||||
LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only
|
||||
one pbuf to help MACs that don't support scatter-gather DMA.
|
||||
|
||||
2009-05-09 Simon Goldschmidt
|
||||
* icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming
|
||||
ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||
|
||||
2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen
|
||||
* ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive
|
||||
extended info about the currently received packet.
|
||||
|
||||
2009-04-27 Simon Goldschmidt
|
||||
* sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1
|
||||
|
||||
2009-04-25 Simon Goldschmidt
|
||||
* mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next
|
||||
bigger malloc pool if one is empty (only usable with MEM_USE_POOLS).
|
||||
|
||||
2009-04-21 Simon Goldschmidt
|
||||
* dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static
|
||||
hosts table. New configuration options DNS_LOCAL_HOSTLIST and
|
||||
DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined
|
||||
as an external function for lookup.
|
||||
|
||||
2009-04-15 Simon Goldschmidt
|
||||
* dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique
|
||||
|
||||
2009-03-31 Kieran Mansley
|
||||
* tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for
|
||||
TCP timestamp options, off by default. Rework tcp_enqueue() to
|
||||
take option flags rather than specified option data
|
||||
|
||||
2009-02-18 Simon Goldschmidt
|
||||
* cc.h: Added printf formatter for size_t: SZT_F
|
||||
|
||||
2009-02-16 Simon Goldschmidt (patch by Rishi Khan)
|
||||
* icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast
|
||||
pings
|
||||
|
||||
2009-02-12 Simon Goldschmidt
|
||||
* init.h: Added LWIP_VERSION to get the current version of the stack
|
||||
|
||||
2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler)
|
||||
* opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead
|
||||
of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc
|
||||
is otherwise used)
|
||||
|
||||
2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach)
|
||||
* ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial()
|
||||
is only used by UDPLITE at present, so conditionalise it.
|
||||
|
||||
2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli)
|
||||
* autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP
|
||||
"seed" address. This should reduce AUTOIP conflicts if
|
||||
LWIP_AUTOIP_CREATE_SEED_ADDR is overridden.
|
||||
|
||||
2008-10-02 Jonathan Larmour and Rishi Khan
|
||||
* sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking
|
||||
socket.
|
||||
|
||||
2008-06-30 Simon Goldschmidt
|
||||
* mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from
|
||||
interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows
|
||||
mem_free to run between mem_malloc iterations. Added illegal counter for
|
||||
mem stats.
|
||||
|
||||
2008-06-27 Simon Goldschmidt
|
||||
* stats.h/.c, some other files: patch #6483: stats module improvement:
|
||||
Added defines to display each module's statistic individually, added stats
|
||||
defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter.
|
||||
|
||||
2008-06-17 Simon Goldschmidt
|
||||
* err.h: patch #6459: Made err_t overridable to use a more efficient type
|
||||
(define LWIP_ERR_T in cc.h)
|
||||
|
||||
2008-06-17 Simon Goldschmidt
|
||||
* slipif.c: patch #6480: Added a configuration option for slipif for symmetry
|
||||
to loopif
|
||||
|
||||
2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli)
|
||||
* netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly
|
||||
modified version of patch # 6370: Moved loopif code to netif.c so that
|
||||
loopback traffic is supported on all netifs (all local IPs).
|
||||
Added option to limit loopback packets for each netifs.
|
||||
|
||||
|
||||
++ Bugfixes:
|
||||
2009-08-12 Kieran Mansley
|
||||
* tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when
|
||||
out of window or out of order properly
|
||||
|
||||
2009-08-12 Kieran Mansley
|
||||
* tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1
|
||||
|
||||
2009-07-28 Simon Goldschmidt
|
||||
* mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s
|
||||
|
||||
2009-07-27 Kieran Mansley
|
||||
* api.h api_msg.h netdb.h sockets.h: add missing #include directives
|
||||
|
||||
2009-07-09 Kieran Mansley
|
||||
* api_msg.c, sockets.c, api.h: BUG23240 use signed counters for
|
||||
recv_avail and don't increment counters until message successfully
|
||||
sent to mbox
|
||||
|
||||
2009-06-25 Kieran Mansley
|
||||
* api_msg.c api.h: BUG26722: initialise netconn write variables
|
||||
in netconn_alloc
|
||||
|
||||
2009-06-25 Kieran Mansley
|
||||
* tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set
|
||||
|
||||
2009-06-25 Kieran Mansley
|
||||
* tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct
|
||||
simultaneous close behaviour, and make snd_nxt have the same meaning
|
||||
as in the RFCs.
|
||||
|
||||
2009-05-12 Simon Goldschmidt
|
||||
* etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on
|
||||
arp_table / uses etharp_query" by adding etharp_gratuitous()
|
||||
|
||||
2009-05-12 Simon Goldschmidt
|
||||
* ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options
|
||||
to the IP header (used by igmp_ip_output_if)
|
||||
|
||||
2009-05-06 Simon Goldschmidt
|
||||
* inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if
|
||||
defined) for SWAP_BYTES_IN_WORD to speed up checksumming.
|
||||
|
||||
2009-05-05 Simon Goldschmidt
|
||||
* sockets.c: bug #26405: Prematurely released semaphore causes lwip_select()
|
||||
to crash
|
||||
|
||||
2009-05-04 Simon Goldschmidt
|
||||
* init.c: snmp was not initialized in lwip_init()
|
||||
|
||||
2009-05-04 Frédéric Bernon
|
||||
* dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled.
|
||||
|
||||
2009-05-03 Simon Goldschmidt
|
||||
* tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full
|
||||
(and unsent->next == NULL)
|
||||
|
||||
2009-05-02 Simon Goldschmidt
|
||||
* tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after
|
||||
1.3.0 in CVS only) - fixes compilation of ppp_oe.c
|
||||
|
||||
2009-05-02 Simon Goldschmidt
|
||||
* msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields
|
||||
|
||||
2009-05-01 Simon Goldschmidt
|
||||
* pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets
|
||||
|
||||
2009-05-01 Simon Goldschmidt
|
||||
* ppp.c: bug #24228: Memory corruption with PPP and DHCP
|
||||
|
||||
2009-04-29 Frédéric Bernon
|
||||
* raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the
|
||||
SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception
|
||||
of broadcast packets even when this option wasn't set. Port maintainers
|
||||
which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h.
|
||||
If you want this option also filter broadcast on recv operations, you also
|
||||
have to set IP_SOF_BROADCAST_RECV=1 in opt.h.
|
||||
|
||||
2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen
|
||||
* dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and
|
||||
DHCP/AUTOIP cooperation
|
||||
|
||||
2009-04-25 Simon Goldschmidt, Oleg Tyshev
|
||||
* tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd
|
||||
Fixed by sorting the unsent and unacked queues (segments are inserted at the
|
||||
right place in tcp_output and tcp_rexmit).
|
||||
|
||||
2009-04-25 Simon Goldschmidt
|
||||
* memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation
|
||||
when debugging": memp_sizes contained the wrong sizes (including sanity
|
||||
regions); memp pools for MEM_USE_POOLS were too small
|
||||
|
||||
2009-04-24 Simon Goldschmidt, Frédéric Bernon
|
||||
* inet.c: patch #6765: Fix a small problem with the last changes (incorrect
|
||||
behavior, with with ip address string not ended by a '\0', a space or a
|
||||
end of line)
|
||||
|
||||
2009-04-19 Simon Goldschmidt
|
||||
* rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails,
|
||||
pcb->err is called, not pcb->connected (with an error code).
|
||||
|
||||
2009-04-19 Simon Goldschmidt
|
||||
* tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with
|
||||
no-copy-tcpwrite": deallocate option data, only concat segments with same flags
|
||||
|
||||
2009-04-19 Simon Goldschmidt
|
||||
* tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated
|
||||
in the header pbuf, not the data pbuf)
|
||||
|
||||
2009-04-18 Simon Goldschmidt
|
||||
* api_msg.c: fixed bug #25695: Segmentation fault in do_writemore()
|
||||
|
||||
2009-04-15 Simon Goldschmidt
|
||||
* sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp
|
||||
|
||||
2009-04-15 Simon Goldschmidt
|
||||
* dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in
|
||||
|
||||
2009-04-15 Simon Goldschmidt
|
||||
* ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function
|
||||
ip_hinted_output() (for smaller code mainly)
|
||||
|
||||
2009-04-15 Simon Goldschmidt
|
||||
* inet.c: patch #6765: Supporting new line characters in inet_aton()
|
||||
|
||||
2009-04-15 Simon Goldschmidt
|
||||
* dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option;
|
||||
Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu
|
||||
is big enough in dhcp_start
|
||||
|
||||
2009-04-15 Simon Goldschmidt
|
||||
* netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak
|
||||
|
||||
2009-04-15 Simon Goldschmidt
|
||||
* sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY
|
||||
|
||||
2009-04-15 Simon Goldschmidt
|
||||
* sockets.c: bug #26121: set_errno can be overridden
|
||||
|
||||
2009-04-09 Kieran Mansley (patch from Luca Ceresoli <lucaceresoli>)
|
||||
* init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when
|
||||
LWIP_TCP==0
|
||||
|
||||
2009-04-09 Kieran Mansley (patch from Roy Lee <roylee17>)
|
||||
* tcp.h: Patch#6802 Add do-while-clauses to those function like
|
||||
macros in tcp.h
|
||||
|
||||
2009-03-31 Kieran Mansley
|
||||
* tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window
|
||||
updates are calculated and sent (BUG20515)
|
||||
|
||||
* tcp_in.c: cope with SYN packets received during established states,
|
||||
and retransmission of initial SYN.
|
||||
|
||||
* tcp_out.c: set push bit correctly when tcp segments are merged
|
||||
|
||||
2009-03-27 Kieran Mansley
|
||||
* tcp_out.c set window correctly on probes (correcting change made
|
||||
yesterday)
|
||||
|
||||
2009-03-26 Kieran Mansley
|
||||
* tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping
|
||||
connections where no reset required (bug #25622)
|
||||
|
||||
* tcp_out.c: set TCP_ACK flag on keepalive and zero window probes
|
||||
(bug #20779)
|
||||
|
||||
2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach)
|
||||
* ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be
|
||||
too small depending on MEM_ALIGNMENT
|
||||
|
||||
2009-02-16 Simon Goldschmidt
|
||||
* sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard;
|
||||
converted size argument of netconn_write to 'size_t'
|
||||
|
||||
2009-02-16 Simon Goldschmidt
|
||||
* tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host
|
||||
by moving accept callback function pointer to TCP_PCB_COMMON
|
||||
|
||||
2009-02-12 Simon Goldschmidt
|
||||
* dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size"
|
||||
option)
|
||||
|
||||
2009-02-11 Simon Goldschmidt
|
||||
* dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start)
|
||||
|
||||
2009-02-11 Simon Goldschmidt
|
||||
* opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize:
|
||||
RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv())
|
||||
|
||||
2009-02-10 Simon Goldschmidt
|
||||
* tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD:
|
||||
Accepts_pending is decrease on a corresponding listen pcb when a connection
|
||||
in state SYN_RCVD is close.
|
||||
|
||||
2009-01-28 Jonathan Larmour
|
||||
* pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run
|
||||
out of pool pbufs.
|
||||
|
||||
2008-12-19 Simon Goldschmidt
|
||||
* many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2
|
||||
|
||||
2008-12-10 Tamas Somogyi, Frédéric Bernon
|
||||
* sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and
|
||||
port uses deleted netbuf.
|
||||
|
||||
2008-10-18 Simon Goldschmidt
|
||||
* tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length
|
||||
in tcp_parseopt
|
||||
|
||||
2008-10-15 Simon Goldschmidt
|
||||
* ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers
|
||||
by packing the struct ip_reass_helper.
|
||||
|
||||
2008-10-03 David Woodhouse, Jonathan Larmour
|
||||
* etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address.
|
||||
|
||||
2008-10-02 Jonathan Larmour
|
||||
* dns.c: Hard-code structure sizes, to avoid issues on some compilers where
|
||||
padding is included.
|
||||
|
||||
2008-09-30 Jonathan Larmour
|
||||
* sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an
|
||||
assertion check that addrlen isn't NULL.
|
||||
|
||||
2008-09-30 Jonathan Larmour
|
||||
* tcp.c: Fix bug #24227, wrong error message in tcp_bind.
|
||||
|
||||
2008-08-26 Simon Goldschmidt
|
||||
* inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and
|
||||
inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h
|
||||
|
||||
2008-08-14 Simon Goldschmidt
|
||||
* api_msg.c: fixed bug #23847: do_close_internal references freed memory (when
|
||||
tcp_close returns != ERR_OK)
|
||||
|
||||
2008-07-08 Frédéric Bernon
|
||||
* stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters
|
||||
in macros, mainly if MEM_STATS=0 and MEMP_STATS=0).
|
||||
|
||||
2008-06-24 Jonathan Larmour
|
||||
* tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused
|
||||
if tcp_seg_copy fails.
|
||||
|
||||
2008-06-17 Simon Goldschmidt
|
||||
* inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations)
|
||||
and created defines for swapping bytes and folding u32 to u16.
|
||||
|
||||
2008-05-30 Kieran Mansley
|
||||
* tcp_in.c Remove redundant "if" statement, and use real rcv_wnd
|
||||
rather than rcv_ann_wnd when deciding if packets are in-window.
|
||||
Contributed by <arasmussen@consultant.datasys.swri.edu>
|
||||
|
||||
2008-05-30 Kieran Mansley
|
||||
* mem.h: Fix BUG#23254. Change macro definition of mem_* to allow
|
||||
passing as function pointers when MEM_LIBC_MALLOC is defined.
|
||||
|
||||
2008-05-09 Jonathan Larmour
|
||||
* err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to
|
||||
stop it being treated as a fatal error.
|
||||
|
||||
2008-04-15 Simon Goldschmidt
|
||||
* dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP
|
||||
(flag now cleared)
|
||||
|
||||
2008-03-27 Simon Goldschmidt
|
||||
* mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free
|
||||
from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1
|
||||
in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs
|
||||
or heap memory from interrupt context
|
||||
|
||||
2008-03-26 Simon Goldschmidt
|
||||
* tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote
|
||||
host sent a zero mss as TCP option.
|
||||
|
||||
|
||||
(STABLE-1.3.0)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
savannah.txt - How to obtain the current development source code.
|
||||
contrib.txt - How to contribute to lwIP as a developer.
|
||||
rawapi.txt - The documentation for the core API of lwIP.
|
||||
Also provides an overview about the other APIs and multithreading.
|
||||
snmp_agent.txt - The documentation for the lwIP SNMP agent.
|
||||
sys_arch.txt - The documentation for a system abstraction layer of lwIP.
|
||||
|
|
|
@ -2,10 +2,11 @@ Raw TCP/IP interface for lwIP
|
|||
|
||||
Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons
|
||||
|
||||
lwIP provides two Application Program's Interfaces (APIs) for programs
|
||||
lwIP provides three Application Program's Interfaces (APIs) for programs
|
||||
to use for communication with the TCP/IP code:
|
||||
* low-level "core" / "callback" or "raw" API.
|
||||
* higher-level "sequential" API.
|
||||
* BSD-style socket 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
|
||||
|
@ -14,6 +15,45 @@ 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 socket API is a compatibility API for existing applications,
|
||||
currently it is built on top of the sequential API. It is meant to
|
||||
provide all functions needed to run socket API applications running
|
||||
on other platforms (e.g. unix / windows etc.). However, due to limitations
|
||||
in the specification of this API, there might be incompatibilities
|
||||
that require small modifications of existing programs.
|
||||
|
||||
** Threading
|
||||
|
||||
lwIP started targeting single-threaded environments. When adding multi-
|
||||
threading support, instead of making the core thread-safe, another
|
||||
approach was chosen: there is one main thread running the lwIP core
|
||||
(also known as the "tcpip_thread"). The raw API may only be used from
|
||||
this thread! Application threads using the sequential- or socket API
|
||||
communicate with this main thread through message passing.
|
||||
|
||||
As such, the list of functions that may be called from
|
||||
other threads or an ISR is very limited! Only functions
|
||||
from these API header files are thread-safe:
|
||||
- api.h
|
||||
- netbuf.h
|
||||
- netdb.h
|
||||
- netifapi.h
|
||||
- sockets.h
|
||||
- sys.h
|
||||
|
||||
Additionaly, memory (de-)allocation functions may be
|
||||
called from multiple threads (not ISR!) with NO_SYS=0
|
||||
since they are protected by SYS_LIGHTWEIGHT_PROT and/or
|
||||
semaphores.
|
||||
|
||||
Only since 1.3.0, if SYS_LIGHTWEIGHT_PROT is set to 1
|
||||
and LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1,
|
||||
pbuf_free() may also be called from another thread or
|
||||
an ISR (since only then, mem_free - for PBUF_RAM - may
|
||||
be called from an ISR: otherwise, the HEAP is only
|
||||
protected by semaphores).
|
||||
|
||||
|
||||
** The remainder of this document discusses the "raw" API. **
|
||||
|
||||
The raw TCP/IP interface allows the application program to integrate
|
||||
|
@ -128,8 +168,9 @@ incoming connections or be explicitly connected to another host.
|
|||
function specified as the fourth argument (the "connected" argument)
|
||||
when the connection is established. If the connection could not be
|
||||
properly established, either because the other host refused the
|
||||
connection or because the other host didn't answer, the "connected"
|
||||
function will be called with an the "err" argument set accordingly.
|
||||
connection or because the other host didn't answer, the "err"
|
||||
callback function of this pcb (registered with tcp_err, see below)
|
||||
will be called.
|
||||
|
||||
The tcp_connect() function can return ERR_MEM if no memory is
|
||||
available for enqueueing the SYN segment. If the SYN indeed was
|
||||
|
|
|
@ -195,6 +195,8 @@ cc.h - Architecture environment, some compiler specific, some
|
|||
Platform specific diagnostic output -
|
||||
LWIP_PLATFORM_DIAG(x) - non-fatal, print a message.
|
||||
LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution.
|
||||
Portability defines for printf formatters:
|
||||
U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F
|
||||
|
||||
"lightweight" synchronization mechanisms -
|
||||
SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable.
|
||||
|
|
|
@ -119,19 +119,6 @@ netconn_delete(struct netconn *conn)
|
|||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of a netconn (as enum netconn_type).
|
||||
*
|
||||
* @param conn the netconn of which to get the type
|
||||
* @return the netconn_type of conn
|
||||
*/
|
||||
enum netconn_type
|
||||
netconn_type(struct netconn *conn)
|
||||
{
|
||||
LWIP_ERROR("netconn_type: invalid conn", (conn != NULL), return NETCONN_INVALID;);
|
||||
return conn->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the local or remote IP address and port of a netconn.
|
||||
* For RAW netconns, this returns the protocol instead of a port!
|
||||
|
@ -439,7 +426,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
|
|||
|
||||
LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
|
||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
|
||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
|
||||
msg.function = do_send;
|
||||
msg.msg.conn = conn;
|
||||
msg.msg.msg.b = buf;
|
||||
|
@ -459,7 +446,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
|
|||
* @return ERR_OK if data was sent, any other err_t on error
|
||||
*/
|
||||
err_t
|
||||
netconn_write(struct netconn *conn, const void *dataptr, int size, u8_t apiflags)
|
||||
netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apiflags)
|
||||
{
|
||||
struct api_msg msg;
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
#include "lwip/igmp.h"
|
||||
#include "lwip/dns.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* forward declarations */
|
||||
#if LWIP_TCP
|
||||
static err_t do_writemore(struct netconn *conn);
|
||||
|
@ -108,11 +110,13 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
|||
buf->addr = &(((struct ip_hdr*)(q->payload))->src);
|
||||
buf->port = pcb->protocol;
|
||||
|
||||
SYS_ARCH_INC(conn->recv_avail, q->tot_len);
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len);
|
||||
if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
|
||||
netbuf_delete(buf);
|
||||
return 0;
|
||||
} else {
|
||||
SYS_ARCH_INC(conn->recv_avail, q->tot_len);
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,12 +170,13 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
|||
buf->port = port;
|
||||
}
|
||||
|
||||
SYS_ARCH_INC(conn->recv_avail, p->tot_len);
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
|
||||
if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
|
||||
netbuf_delete(buf);
|
||||
return;
|
||||
} else {
|
||||
SYS_ARCH_INC(conn->recv_avail, p->tot_len);
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_UDP */
|
||||
|
@ -206,10 +211,12 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
|||
} else {
|
||||
len = 0;
|
||||
}
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
||||
|
||||
if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) {
|
||||
return ERR_MEM;
|
||||
} else {
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
|
@ -365,8 +372,6 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
|||
newconn->pcb.tcp = newpcb;
|
||||
setup_tcp(newconn);
|
||||
newconn->err = err;
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
|
||||
|
||||
if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) {
|
||||
/* When returning != ERR_OK, the connection is aborted in tcp_process(),
|
||||
|
@ -374,7 +379,11 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
|||
newconn->pcb.tcp = NULL;
|
||||
netconn_free(newconn);
|
||||
return ERR_MEM;
|
||||
} else {
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* LWIP_TCP */
|
||||
|
@ -528,11 +537,18 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
|
|||
conn->socket = -1;
|
||||
conn->callback = callback;
|
||||
conn->recv_avail = 0;
|
||||
#if LWIP_TCP
|
||||
conn->write_msg = NULL;
|
||||
conn->write_offset = 0;
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
conn->write_delayed = 0;
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||
#endif /* LWIP_TCP */
|
||||
#if LWIP_SO_RCVTIMEO
|
||||
conn->recv_timeout = 0;
|
||||
#endif /* LWIP_SO_RCVTIMEO */
|
||||
#if LWIP_SO_RCVBUF
|
||||
conn->recv_bufsize = INT_MAX;
|
||||
conn->recv_bufsize = RECV_BUFSIZE_DEFAULT;
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
return conn;
|
||||
}
|
||||
|
@ -598,11 +614,16 @@ do_close_internal(struct netconn *conn)
|
|||
LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
|
||||
|
||||
/* Set back some callback pointers */
|
||||
tcp_arg(conn->pcb.tcp, NULL);
|
||||
if (conn->pcb.tcp->state == LISTEN) {
|
||||
tcp_arg(conn->pcb.tcp, NULL);
|
||||
tcp_accept(conn->pcb.tcp, NULL);
|
||||
} else {
|
||||
tcp_recv(conn->pcb.tcp, NULL);
|
||||
tcp_accept(conn->pcb.tcp, NULL);
|
||||
/* some callbacks have to be reset if tcp_close is not successful */
|
||||
tcp_sent(conn->pcb.tcp, NULL);
|
||||
tcp_poll(conn->pcb.tcp, NULL, 4);
|
||||
tcp_err(conn->pcb.tcp, NULL);
|
||||
}
|
||||
/* Try to close the connection */
|
||||
err = tcp_close(conn->pcb.tcp);
|
||||
|
@ -610,11 +631,6 @@ do_close_internal(struct netconn *conn)
|
|||
/* Closing succeeded */
|
||||
conn->state = NETCONN_NONE;
|
||||
/* Set back some callback pointers as conn is going away */
|
||||
tcp_err(conn->pcb.tcp, NULL);
|
||||
tcp_poll(conn->pcb.tcp, NULL, 4);
|
||||
tcp_sent(conn->pcb.tcp, NULL);
|
||||
tcp_recv(conn->pcb.tcp, NULL);
|
||||
tcp_arg(conn->pcb.tcp, NULL);
|
||||
conn->pcb.tcp = NULL;
|
||||
conn->err = ERR_OK;
|
||||
/* Trigger select() in socket layer. This send should something else so the
|
||||
|
@ -623,6 +639,14 @@ do_close_internal(struct netconn *conn)
|
|||
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
|
||||
/* wake up the application task */
|
||||
sys_sem_signal(conn->op_completed);
|
||||
} else {
|
||||
/* Closing failed, restore some of the callbacks */
|
||||
/* Closing of listen pcb will never fail! */
|
||||
LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN));
|
||||
tcp_sent(conn->pcb.tcp, sent_tcp);
|
||||
tcp_poll(conn->pcb.tcp, poll_tcp, 4);
|
||||
tcp_err(conn->pcb.tcp, err_tcp);
|
||||
tcp_arg(conn->pcb.tcp, conn);
|
||||
}
|
||||
/* If closing didn't succeed, we get called again either
|
||||
from poll_tcp or from sent_tcp */
|
||||
|
@ -894,7 +918,7 @@ do_send(struct api_msg_msg *msg)
|
|||
}
|
||||
|
||||
/**
|
||||
* Recv some data from a RAW or UDP pcb contained in a netconn
|
||||
* Indicate data has been received from a TCP pcb contained in a netconn
|
||||
* Called from netconn_recv
|
||||
*
|
||||
* @param msg the api_msg_msg pointing to the connection
|
||||
|
@ -940,17 +964,19 @@ do_writemore(struct netconn *conn)
|
|||
void *dataptr;
|
||||
u16_t len, available;
|
||||
u8_t write_finished = 0;
|
||||
size_t diff;
|
||||
|
||||
LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE));
|
||||
|
||||
dataptr = (u8_t*)conn->write_msg->msg.w.dataptr + conn->write_offset;
|
||||
if ((conn->write_msg->msg.w.len - conn->write_offset > 0xffff)) { /* max_u16_t */
|
||||
diff = conn->write_msg->msg.w.len - conn->write_offset;
|
||||
if (diff > 0xffffUL) { /* max_u16_t */
|
||||
len = 0xffff;
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
conn->write_delayed = 1;
|
||||
#endif
|
||||
} else {
|
||||
len = conn->write_msg->msg.w.len - conn->write_offset;
|
||||
len = (u16_t)diff;
|
||||
}
|
||||
available = tcp_sndbuf(conn->pcb.tcp);
|
||||
if (available < len) {
|
||||
|
@ -970,6 +996,8 @@ do_writemore(struct netconn *conn)
|
|||
write_finished = 1;
|
||||
conn->write_msg = NULL;
|
||||
conn->write_offset = 0;
|
||||
/* API_EVENT might call tcp_tmr, so reset conn->state now */
|
||||
conn->state = NETCONN_NONE;
|
||||
}
|
||||
err = tcp_output_nagle(conn->pcb.tcp);
|
||||
conn->err = err;
|
||||
|
@ -1027,6 +1055,8 @@ do_write(struct api_msg_msg *msg)
|
|||
#if LWIP_TCP
|
||||
msg->conn->state = NETCONN_WRITE;
|
||||
/* set all the variables used by do_writemore */
|
||||
LWIP_ASSERT("already writing", msg->conn->write_msg == NULL &&
|
||||
msg->conn->write_offset == 0);
|
||||
msg->conn->write_msg = msg;
|
||||
msg->conn->write_offset = 0;
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
|
|
|
@ -44,17 +44,17 @@ static const char *err_strerr[] = {
|
|||
"Ok.", /* ERR_OK 0 */
|
||||
"Out of memory error.", /* ERR_MEM -1 */
|
||||
"Buffer error.", /* ERR_BUF -2 */
|
||||
"Routing problem.", /* ERR_RTE -3 */
|
||||
"Connection aborted.", /* ERR_ABRT -4 */
|
||||
"Connection reset.", /* ERR_RST -5 */
|
||||
"Connection closed.", /* ERR_CLSD -6 */
|
||||
"Not connected.", /* ERR_CONN -7 */
|
||||
"Illegal value.", /* ERR_VAL -8 */
|
||||
"Illegal argument.", /* ERR_ARG -9 */
|
||||
"Address in use.", /* ERR_USE -10 */
|
||||
"Low-level netif error.", /* ERR_IF -11 */
|
||||
"Already connected.", /* ERR_ISCONN -12 */
|
||||
"Timeout.", /* ERR_TIMEOUT -13 */
|
||||
"Timeout.", /* ERR_TIMEOUT -3 */
|
||||
"Routing problem.", /* ERR_RTE -4 */
|
||||
"Connection aborted.", /* ERR_ABRT -5 */
|
||||
"Connection reset.", /* ERR_RST -6 */
|
||||
"Connection closed.", /* ERR_CLSD -7 */
|
||||
"Not connected.", /* ERR_CONN -8 */
|
||||
"Illegal value.", /* ERR_VAL -9 */
|
||||
"Illegal argument.", /* ERR_ARG -10 */
|
||||
"Address in use.", /* ERR_USE -11 */
|
||||
"Low-level netif error.", /* ERR_IF -12 */
|
||||
"Already connected.", /* ERR_ISCONN -13 */
|
||||
"Operation in progress." /* ERR_INPROGRESS -14 */
|
||||
};
|
||||
|
||||
|
|
|
@ -158,14 +158,14 @@ netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
|
|||
* Chain one netbuf to another (@see pbuf_chain)
|
||||
*
|
||||
* @param head the first netbuf
|
||||
* @param tail netbuf to chain after head
|
||||
* @param tail netbuf to chain after head, freed by this function, may not be reference after returning
|
||||
*/
|
||||
void
|
||||
netbuf_chain(struct netbuf *head, struct netbuf *tail)
|
||||
{
|
||||
LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;);
|
||||
LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
|
||||
pbuf_chain(head->p, tail->p);
|
||||
pbuf_cat(head->p, tail->p);
|
||||
head->ptr = head->p;
|
||||
memp_free(MEMP_NETBUF, tail);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/api.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** helper struct for gethostbyname_r to access the char* buffer */
|
||||
struct gethostbyname_r_helper {
|
||||
struct ip_addr *addrs;
|
||||
|
@ -107,23 +110,23 @@ lwip_gethostbyname(const char *name)
|
|||
|
||||
#if DNS_DEBUG
|
||||
/* dump hostent */
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == 0x%08lX\n",(u32_t)(s_hostent.h_aliases)));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", s_hostent.h_aliases));
|
||||
if (s_hostent.h_aliases != NULL) {
|
||||
u8_t idx;
|
||||
for ( idx=0; s_hostent.h_aliases[idx]; idx++) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == 0x%08lX\n", idx, s_hostent.h_aliases[idx]));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %p\n", idx, s_hostent.h_aliases[idx]));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx]));
|
||||
}
|
||||
}
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %lu\n", (u32_t)(s_hostent.h_addrtype)));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %lu\n", (u32_t)(s_hostent.h_length)));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == 0x%08lX\n", s_hostent.h_addr_list));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", s_hostent.h_addr_list));
|
||||
if (s_hostent.h_addr_list != NULL) {
|
||||
u8_t idx;
|
||||
for ( idx=0; s_hostent.h_addr_list[idx]; idx++) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == 0x%08lX\n", idx, s_hostent.h_addr_list[idx]));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, inet_ntoa(*((struct in_addr*)(s_hostent.h_addr_list[idx])))));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx]));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, inet_ntoa(*((struct in_addr*)(s_hostent.h_addr_list[idx])))));
|
||||
}
|
||||
}
|
||||
#endif /* DNS_DEBUG */
|
||||
|
@ -326,7 +329,8 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
|||
if (nodename != NULL) {
|
||||
/* copy nodename to canonname if specified */
|
||||
size_t namelen = strlen(nodename);
|
||||
ai->ai_canonname = mem_malloc(namelen + 1);
|
||||
LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
|
||||
ai->ai_canonname = mem_malloc((mem_size_t)(namelen + 1));
|
||||
if (ai->ai_canonname == NULL) {
|
||||
goto memerr;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ struct lwip_socket {
|
|||
u16_t lastoffset;
|
||||
/** number of times data was received, set by event_callback(),
|
||||
tested by the receive and select functions */
|
||||
u16_t rcvevent;
|
||||
s16_t rcvevent;
|
||||
/** number of times data was received, set by event_callback(),
|
||||
tested by select */
|
||||
u16_t sendevent;
|
||||
|
@ -128,17 +128,17 @@ static const int err_to_errno_table[] = {
|
|||
0, /* ERR_OK 0 No error, everything OK. */
|
||||
ENOMEM, /* ERR_MEM -1 Out of memory error. */
|
||||
ENOBUFS, /* ERR_BUF -2 Buffer error. */
|
||||
EHOSTUNREACH, /* ERR_RTE -3 Routing problem. */
|
||||
ECONNABORTED, /* ERR_ABRT -4 Connection aborted. */
|
||||
ECONNRESET, /* ERR_RST -5 Connection reset. */
|
||||
ESHUTDOWN, /* ERR_CLSD -6 Connection closed. */
|
||||
ENOTCONN, /* ERR_CONN -7 Not connected. */
|
||||
EINVAL, /* ERR_VAL -8 Illegal value. */
|
||||
EIO, /* ERR_ARG -9 Illegal argument. */
|
||||
EADDRINUSE, /* ERR_USE -10 Address in use. */
|
||||
-1, /* ERR_IF -11 Low-level netif error */
|
||||
-1, /* ERR_ISCONN -12 Already connected. */
|
||||
ETIMEDOUT, /* ERR_TIMEOUT -13 Timeout */
|
||||
ETIMEDOUT, /* ERR_TIMEOUT -3 Timeout */
|
||||
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
|
||||
ECONNABORTED, /* ERR_ABRT -5 Connection aborted. */
|
||||
ECONNRESET, /* ERR_RST -6 Connection reset. */
|
||||
ESHUTDOWN, /* ERR_CLSD -7 Connection closed. */
|
||||
ENOTCONN, /* ERR_CONN -8 Not connected. */
|
||||
EINVAL, /* ERR_VAL -9 Illegal value. */
|
||||
EIO, /* ERR_ARG -10 Illegal argument. */
|
||||
EADDRINUSE, /* ERR_USE -11 Address in use. */
|
||||
-1, /* ERR_IF -12 Low-level netif error */
|
||||
-1, /* ERR_ISCONN -13 Already connected. */
|
||||
EINPROGRESS /* ERR_INPROGRESS -14 Operation in progress */
|
||||
};
|
||||
|
||||
|
@ -150,7 +150,9 @@ static const int err_to_errno_table[] = {
|
|||
err_to_errno_table[-(err)] : EIO)
|
||||
|
||||
#ifdef ERRNO
|
||||
#ifndef set_errno
|
||||
#define set_errno(err) errno = (err)
|
||||
#endif
|
||||
#else
|
||||
#define set_errno(err)
|
||||
#endif
|
||||
|
@ -258,6 +260,12 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
|||
if (!sock)
|
||||
return -1;
|
||||
|
||||
if ((sock->flags & O_NONBLOCK) && (sock->rcvevent <= 0)) {
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
|
||||
sock_set_errno(sock, EWOULDBLOCK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
newconn = netconn_accept(sock->conn);
|
||||
if (!newconn) {
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) failed, err=%d\n", s, sock->conn->err));
|
||||
|
@ -273,16 +281,22 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
|||
return -1;
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
sin.sin_addr.s_addr = naddr.addr;
|
||||
/* Note that POSIX only requires us to check addr is non-NULL. addrlen must
|
||||
* not be NULL if addr is valid.
|
||||
*/
|
||||
if (NULL != addr) {
|
||||
LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
sin.sin_addr.s_addr = naddr.addr;
|
||||
|
||||
if (*addrlen > sizeof(sin))
|
||||
*addrlen = sizeof(sin);
|
||||
if (*addrlen > sizeof(sin))
|
||||
*addrlen = sizeof(sin);
|
||||
|
||||
SMEMCPY(addr, &sin, *addrlen);
|
||||
MEMCPY(addr, &sin, *addrlen);
|
||||
}
|
||||
|
||||
newsock = alloc_socket(newconn);
|
||||
if (newsock == -1) {
|
||||
|
@ -307,14 +321,14 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
|||
|
||||
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));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
|
||||
|
||||
sock_set_errno(sock, 0);
|
||||
return newsock;
|
||||
}
|
||||
|
||||
int
|
||||
lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
|
||||
lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
|
||||
{
|
||||
struct lwip_socket *sock;
|
||||
struct ip_addr local_addr;
|
||||
|
@ -326,15 +340,15 @@ lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
|
|||
return -1;
|
||||
|
||||
LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
|
||||
((((struct sockaddr_in *)name)->sin_family) == AF_INET)),
|
||||
((((const struct sockaddr_in *)name)->sin_family) == AF_INET)),
|
||||
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
||||
|
||||
local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
|
||||
local_port = ((struct sockaddr_in *)name)->sin_port;
|
||||
local_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr;
|
||||
local_port = ((const struct sockaddr_in *)name)->sin_port;
|
||||
|
||||
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)));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port)));
|
||||
|
||||
err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
|
||||
|
||||
|
@ -386,22 +400,22 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
|
|||
return -1;
|
||||
|
||||
LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
|
||||
((((struct sockaddr_in *)name)->sin_family) == AF_INET)),
|
||||
((((const struct sockaddr_in *)name)->sin_family) == AF_INET)),
|
||||
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
||||
|
||||
if (((struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
|
||||
if (((const struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
|
||||
err = netconn_disconnect(sock->conn);
|
||||
} else {
|
||||
struct ip_addr remote_addr;
|
||||
u16_t remote_port;
|
||||
|
||||
remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
|
||||
remote_port = ((struct sockaddr_in *)name)->sin_port;
|
||||
remote_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr;
|
||||
remote_port = ((const struct sockaddr_in *)name)->sin_port;
|
||||
|
||||
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)));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port)));
|
||||
|
||||
err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
|
||||
}
|
||||
|
@ -458,7 +472,7 @@ lwip_listen(int s, int backlog)
|
|||
}
|
||||
|
||||
int
|
||||
lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
||||
lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen)
|
||||
{
|
||||
struct lwip_socket *sock;
|
||||
|
@ -468,7 +482,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
|||
u16_t port;
|
||||
u8_t done = 0;
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
|
||||
sock = get_socket(s);
|
||||
if (!sock)
|
||||
return -1;
|
||||
|
@ -480,7 +494,13 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
|||
buf = sock->lastdata;
|
||||
} else {
|
||||
/* If this is non-blocking call, then check first */
|
||||
if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && !sock->rcvevent) {
|
||||
if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) &&
|
||||
(sock->rcvevent <= 0)) {
|
||||
if (off > 0) {
|
||||
/* already received data, return that */
|
||||
sock_set_errno(sock, 0);
|
||||
return off;
|
||||
}
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
|
||||
sock_set_errno(sock, EWOULDBLOCK);
|
||||
return -1;
|
||||
|
@ -492,22 +512,29 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
|||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv netbuf=%p\n", (void*)buf));
|
||||
|
||||
if (!buf) {
|
||||
if (off > 0) {
|
||||
/* already received data, return that */
|
||||
sock_set_errno(sock, 0);
|
||||
return off;
|
||||
}
|
||||
/* We should really do some error checking here. */
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
|
||||
sock_set_errno(sock, (((sock->conn->pcb.ip!=NULL) && (sock->conn->err==ERR_OK))?ETIMEDOUT:err_to_errno(sock->conn->err)));
|
||||
sock_set_errno(sock, (((sock->conn->pcb.ip != NULL) && (sock->conn->err == ERR_OK))
|
||||
? ETIMEDOUT : err_to_errno(sock->conn->err)));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
buflen = netbuf_len(buf);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%d len=%d off=%d sock->lastoffset=%d\n", buflen, len, off, sock->lastoffset));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%"U16_F" sock->lastoffset=%"U16_F"\n",
|
||||
buflen, len, off, sock->lastoffset));
|
||||
|
||||
buflen -= sock->lastoffset;
|
||||
|
||||
if (len > buflen) {
|
||||
copylen = buflen;
|
||||
} else {
|
||||
copylen = len;
|
||||
copylen = (u16_t)len;
|
||||
}
|
||||
|
||||
/* copy the contents of the received buffer into
|
||||
|
@ -517,20 +544,71 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
|||
off += copylen;
|
||||
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
|
||||
len -= copylen;
|
||||
if ( (len <= 0) || (buf->p->flags & PBUF_FLAG_PUSH) || !sock->rcvevent) {
|
||||
if ( (len <= 0) ||
|
||||
(buf->p->flags & PBUF_FLAG_PUSH) ||
|
||||
(sock->rcvevent <= 0) ||
|
||||
((flags & MSG_PEEK)!=0)) {
|
||||
done = 1;
|
||||
}
|
||||
} else {
|
||||
done = 1;
|
||||
}
|
||||
|
||||
/* Check to see from where the data was.*/
|
||||
if (done) {
|
||||
if (from && fromlen) {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
|
||||
netconn_getaddr(sock->conn, addr, &port, 0);
|
||||
} else {
|
||||
addr = netbuf_fromaddr(buf);
|
||||
port = netbuf_fromport(buf);
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
sin.sin_addr.s_addr = addr->addr;
|
||||
|
||||
if (*fromlen > sizeof(sin)) {
|
||||
*fromlen = sizeof(sin);
|
||||
}
|
||||
|
||||
MEMCPY(from, &sin, *fromlen);
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, addr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off));
|
||||
} else {
|
||||
#if SOCKETS_DEBUG
|
||||
struct sockaddr_in sin;
|
||||
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
|
||||
netconn_getaddr(sock->conn, addr, &port, 0);
|
||||
} else {
|
||||
addr = netbuf_fromaddr(buf);
|
||||
port = netbuf_fromport(buf);
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, addr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off));
|
||||
#endif /* SOCKETS_DEBUG */
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't peek the incoming message... */
|
||||
if ((flags & MSG_PEEK)==0) {
|
||||
/* If this is a TCP socket, check if there is data left in the
|
||||
buffer. If so, it should be saved in the sock structure for next
|
||||
time around. */
|
||||
if ((sock->conn->type == NETCONN_TCP) && (buflen - copylen > 0)) {
|
||||
if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
|
||||
sock->lastdata = buf;
|
||||
sock->lastoffset += copylen;
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", (void*)buf));
|
||||
|
@ -540,85 +618,39 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
|||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", (void*)buf));
|
||||
netbuf_delete(buf);
|
||||
}
|
||||
} else {
|
||||
done = 1;
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
/* Check to see from where the data was.*/
|
||||
if (from && fromlen) {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
|
||||
netconn_getaddr(sock->conn, addr, &port, 0);
|
||||
} else {
|
||||
addr = netbuf_fromaddr(buf);
|
||||
port = netbuf_fromport(buf);
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
sin.sin_addr.s_addr = addr->addr;
|
||||
|
||||
if (*fromlen > sizeof(sin))
|
||||
*fromlen = sizeof(sin);
|
||||
|
||||
SMEMCPY(from, &sin, *fromlen);
|
||||
|
||||
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, off));
|
||||
} else {
|
||||
#if SOCKETS_DEBUG
|
||||
struct sockaddr_in sin;
|
||||
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
|
||||
netconn_getaddr(sock->conn, addr, &port, 0);
|
||||
} else {
|
||||
addr = netbuf_fromaddr(buf);
|
||||
port = netbuf_fromport(buf);
|
||||
}
|
||||
|
||||
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, off));
|
||||
#endif /* SOCKETS_DEBUG */
|
||||
}
|
||||
|
||||
sock_set_errno(sock, 0);
|
||||
return off;
|
||||
}
|
||||
|
||||
int
|
||||
lwip_read(int s, void *mem, int len)
|
||||
lwip_read(int s, void *mem, size_t len)
|
||||
{
|
||||
return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
lwip_recv(int s, void *mem, int len, unsigned int flags)
|
||||
lwip_recv(int s, void *mem, size_t len, int flags)
|
||||
{
|
||||
return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
lwip_send(int s, const void *data, int size, unsigned int flags)
|
||||
lwip_send(int s, const void *data, size_t size, int flags)
|
||||
{
|
||||
struct lwip_socket *sock;
|
||||
err_t err;
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n",
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
|
||||
s, data, size, flags));
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock)
|
||||
return -1;
|
||||
|
||||
if (sock->conn->type!=NETCONN_TCP) {
|
||||
if (sock->conn->type != NETCONN_TCP) {
|
||||
#if (LWIP_UDP || LWIP_RAW)
|
||||
return lwip_sendto(s, data, size, flags, NULL, 0);
|
||||
#else
|
||||
|
@ -629,18 +661,19 @@ lwip_send(int s, const void *data, int size, unsigned int flags)
|
|||
|
||||
err = netconn_write(sock->conn, data, size, NETCONN_COPY | ((flags & MSG_MORE)?NETCONN_MORE:0));
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%d\n", s, err, size));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%"SZT_F"\n", s, err, size));
|
||||
sock_set_errno(sock, err_to_errno(err));
|
||||
return (err==ERR_OK?size:-1);
|
||||
return (err == ERR_OK ? (int)size : -1);
|
||||
}
|
||||
|
||||
int
|
||||
lwip_sendto(int s, const void *data, int size, unsigned int flags,
|
||||
struct sockaddr *to, socklen_t tolen)
|
||||
lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
const struct sockaddr *to, socklen_t tolen)
|
||||
{
|
||||
struct lwip_socket *sock;
|
||||
struct ip_addr remote_addr;
|
||||
int err;
|
||||
err_t err;
|
||||
u16_t short_size;
|
||||
#if !LWIP_TCPIP_CORE_LOCKING
|
||||
struct netbuf buf;
|
||||
u16_t remote_port;
|
||||
|
@ -650,7 +683,7 @@ lwip_sendto(int s, const void *data, int size, unsigned int flags,
|
|||
if (!sock)
|
||||
return -1;
|
||||
|
||||
if (sock->conn->type==NETCONN_TCP) {
|
||||
if (sock->conn->type == NETCONN_TCP) {
|
||||
#if LWIP_TCP
|
||||
return lwip_send(s, data, size, flags);
|
||||
#else
|
||||
|
@ -659,11 +692,11 @@ lwip_sendto(int s, const void *data, int size, unsigned int flags,
|
|||
#endif /* LWIP_TCP */
|
||||
}
|
||||
|
||||
LWIP_ASSERT("lwip_sendto: size must fit in u16_t",
|
||||
((size >= 0) && (size <= 0xffff)));
|
||||
LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
|
||||
short_size = (u16_t)size;
|
||||
LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
|
||||
((tolen == sizeof(struct sockaddr_in)) &&
|
||||
((((struct sockaddr_in *)to)->sin_family) == AF_INET))),
|
||||
((((const struct sockaddr_in *)to)->sin_family) == AF_INET))),
|
||||
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
|
||||
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
|
@ -675,15 +708,15 @@ lwip_sendto(int s, const void *data, int size, unsigned int flags,
|
|||
err = ERR_MEM;
|
||||
} else {
|
||||
p->payload = (void*)data;
|
||||
p->len = p->tot_len = size;
|
||||
p->len = p->tot_len = short_size;
|
||||
|
||||
remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
|
||||
remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
|
||||
|
||||
LOCK_TCPIP_CORE();
|
||||
if (sock->conn->type==NETCONN_RAW) {
|
||||
err = sock->conn->err = raw_sendto(sock->conn->pcb.raw, p, &remote_addr);
|
||||
} else {
|
||||
err = sock->conn->err = udp_sendto(sock->conn->pcb.udp, p, &remote_addr, ntohs(((struct sockaddr_in *)to)->sin_port));
|
||||
err = sock->conn->err = udp_sendto(sock->conn->pcb.udp, p, &remote_addr, ntohs(((const struct sockaddr_in *)to)->sin_port));
|
||||
}
|
||||
UNLOCK_TCPIP_CORE();
|
||||
|
||||
|
@ -694,8 +727,8 @@ lwip_sendto(int s, const void *data, int size, unsigned int flags,
|
|||
/* initialize a buffer */
|
||||
buf.p = buf.ptr = NULL;
|
||||
if (to) {
|
||||
remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
|
||||
remote_port = ntohs(((struct sockaddr_in *)to)->sin_port);
|
||||
remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
|
||||
remote_port = ntohs(((const struct sockaddr_in *)to)->sin_port);
|
||||
buf.addr = &remote_addr;
|
||||
buf.port = remote_port;
|
||||
} else {
|
||||
|
@ -705,24 +738,32 @@ lwip_sendto(int s, const void *data, int size, unsigned int flags,
|
|||
buf.port = 0;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=",
|
||||
s, data, size, flags));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%d"U16_F", flags=0x%x to=",
|
||||
s, data, short_size, flags));
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", remote_port));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
|
||||
|
||||
/* make the buffer point to the data that should be sent */
|
||||
if ((err = netbuf_ref(&buf, data, size)) == ERR_OK) {
|
||||
#if LWIP_NETIF_TX_SINGLE_PBUF
|
||||
/* Allocate a new netbuf and copy the data into it. */
|
||||
if (netbuf_alloc(&buf, short_size) == NULL) {
|
||||
err = ERR_MEM;
|
||||
} else {
|
||||
err = netbuf_take(&buf, data, short_size);
|
||||
}
|
||||
#else /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
err = netbuf_ref(&buf, data, short_size);
|
||||
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
if (err == ERR_OK) {
|
||||
/* send the data */
|
||||
err = netconn_send(sock->conn, &buf);
|
||||
}
|
||||
|
||||
/* deallocated the buffer */
|
||||
if (buf.p != NULL) {
|
||||
pbuf_free(buf.p);
|
||||
}
|
||||
netbuf_free(&buf);
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||
sock_set_errno(sock, err_to_errno(err));
|
||||
return (err==ERR_OK?size:-1);
|
||||
return (err == ERR_OK ? short_size : -1);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -778,7 +819,7 @@ lwip_socket(int domain, int type, int protocol)
|
|||
}
|
||||
|
||||
int
|
||||
lwip_write(int s, const void *data, int size)
|
||||
lwip_write(int s, const void *data, size_t size)
|
||||
{
|
||||
return lwip_send(s, data, size, 0);
|
||||
}
|
||||
|
@ -815,7 +856,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
|
|||
if (FD_ISSET(i, readset)) {
|
||||
/* See if netconn of this socket is ready for read */
|
||||
p_sock = get_socket(i);
|
||||
if (p_sock && (p_sock->lastdata || p_sock->rcvevent)) {
|
||||
if (p_sock && (p_sock->lastdata || (p_sock->rcvevent > 0))) {
|
||||
FD_SET(i, &lreadset);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
|
||||
nready++;
|
||||
|
@ -855,7 +896,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
|||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n",
|
||||
maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
|
||||
timeout ? timeout->tv_sec : -1L, timeout ? timeout->tv_usec : -1L));
|
||||
timeout ? (long)timeout->tv_sec : (long)-1,
|
||||
timeout ? (long)timeout->tv_usec : (long)-1));
|
||||
|
||||
select_cb.next = 0;
|
||||
select_cb.readset = readset;
|
||||
|
@ -924,14 +966,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
|||
msectimeout = 1;
|
||||
}
|
||||
|
||||
if (msectimeout > 0 && sys_arch_timeouts() == NULL){
|
||||
/* it's not a lwip thread, use os semaphore with timeout to handle it */
|
||||
i = sys_arch_sem_wait(select_cb.sem, msectimeout);
|
||||
}
|
||||
else {
|
||||
/* it's a lwip thread, use os semaphore with timeout to handle it */
|
||||
i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
|
||||
}
|
||||
i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
|
||||
|
||||
/* Take us off the list */
|
||||
sys_sem_wait(selectsem);
|
||||
|
@ -1069,7 +1104,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
|
|||
if (scb->sem_signalled == 0) {
|
||||
/* Test this select call for our socket */
|
||||
if (scb->readset && FD_ISSET(s, scb->readset))
|
||||
if (sock->rcvevent)
|
||||
if (sock->rcvevent > 0)
|
||||
break;
|
||||
if (scb->writeset && FD_ISSET(s, scb->writeset))
|
||||
if (sock->sendevent)
|
||||
|
@ -1078,8 +1113,8 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
|
|||
}
|
||||
if (scb) {
|
||||
scb->sem_signalled = 1;
|
||||
sys_sem_signal(selectsem);
|
||||
sys_sem_signal(scb->sem);
|
||||
sys_sem_signal(selectsem);
|
||||
} else {
|
||||
sys_sem_signal(selectsem);
|
||||
break;
|
||||
|
@ -1119,7 +1154,7 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
|
|||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
|
||||
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
|
||||
|
||||
sin.sin_port = htons(sin.sin_port);
|
||||
sin.sin_addr.s_addr = naddr.addr;
|
||||
|
@ -1127,7 +1162,7 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
|
|||
if (*namelen > sizeof(sin))
|
||||
*namelen = sizeof(sin);
|
||||
|
||||
SMEMCPY(name, &sin, *namelen);
|
||||
MEMCPY(name, &sin, *namelen);
|
||||
sock_set_errno(sock, 0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1444,7 +1479,7 @@ lwip_getsockopt_internal(void *arg)
|
|||
break;
|
||||
case IP_MULTICAST_IF:
|
||||
((struct in_addr*) optval)->s_addr = sock->conn->pcb.udp->multicast_ip.addr;
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%x\n",
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
|
||||
s, *(u32_t *)optval));
|
||||
break;
|
||||
#endif /* LWIP_IGMP */
|
||||
|
@ -1777,12 +1812,12 @@ lwip_setsockopt_internal(void *arg)
|
|||
switch (optname) {
|
||||
case IP_TTL:
|
||||
sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n",
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
|
||||
s, sock->conn->pcb.ip->ttl));
|
||||
break;
|
||||
case IP_TOS:
|
||||
sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n",
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
|
||||
s, sock->conn->pcb.ip->tos));
|
||||
break;
|
||||
#if LWIP_IGMP
|
||||
|
@ -1826,24 +1861,24 @@ lwip_setsockopt_internal(void *arg)
|
|||
break;
|
||||
case TCP_KEEPALIVE:
|
||||
sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %lu\n",
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n",
|
||||
s, sock->conn->pcb.tcp->keep_idle));
|
||||
break;
|
||||
|
||||
#if LWIP_TCP_KEEPALIVE
|
||||
case TCP_KEEPIDLE:
|
||||
sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %lu\n",
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n",
|
||||
s, sock->conn->pcb.tcp->keep_idle));
|
||||
break;
|
||||
case TCP_KEEPINTVL:
|
||||
sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %lu\n",
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n",
|
||||
s, sock->conn->pcb.tcp->keep_intvl));
|
||||
break;
|
||||
case TCP_KEEPCNT:
|
||||
sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %lu\n",
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n",
|
||||
s, sock->conn->pcb.tcp->keep_cnt));
|
||||
break;
|
||||
#endif /* LWIP_TCP_KEEPALIVE */
|
||||
|
@ -1887,6 +1922,7 @@ lwip_ioctl(int s, long cmd, void *argp)
|
|||
{
|
||||
struct lwip_socket *sock = get_socket(s);
|
||||
u16_t buflen = 0;
|
||||
s16_t recv_avail;
|
||||
|
||||
if (!sock)
|
||||
return -1;
|
||||
|
@ -1898,7 +1934,10 @@ lwip_ioctl(int s, long cmd, void *argp)
|
|||
return -1;
|
||||
}
|
||||
|
||||
SYS_ARCH_GET(sock->conn->recv_avail, *((u16_t*)argp));
|
||||
SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
|
||||
if (recv_avail < 0)
|
||||
recv_avail = 0;
|
||||
*((u16_t*)argp) = (u16_t)recv_avail;
|
||||
|
||||
/* Check if there is data left from the last recv operation. /maq 041215 */
|
||||
if (sock->lastdata) {
|
||||
|
@ -1908,7 +1947,7 @@ lwip_ioctl(int s, long cmd, void *argp)
|
|||
*((u16_t*)argp) += buflen;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
|
||||
sock_set_errno(sock, 0);
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -297,11 +297,12 @@ tcpip_thread(void *arg)
|
|||
|
||||
case TCPIP_MSG_TIMEOUT:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
|
||||
|
||||
if(msg->msg.tmo.msecs != 0xffffffff)
|
||||
sys_timeout (msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
|
||||
else
|
||||
sys_untimeout (msg->msg.tmo.h, msg->msg.tmo.arg);
|
||||
sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
|
||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
||||
break;
|
||||
case TCPIP_MSG_UNTIMEOUT:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
|
||||
sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
|
||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
||||
break;
|
||||
|
||||
|
@ -379,6 +380,14 @@ tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block)
|
|||
return ERR_VAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* call sys_timeout in tcpip_thread
|
||||
*
|
||||
* @param msec time in miliseconds for timeout
|
||||
* @param h function to be called on timeout
|
||||
* @param arg argument to pass to timeout function h
|
||||
* @return ERR_MEM on memory error, ERR_OK otherwise
|
||||
*/
|
||||
err_t
|
||||
tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
||||
{
|
||||
|
@ -400,6 +409,34 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
|||
return ERR_VAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* call sys_untimeout in tcpip_thread
|
||||
*
|
||||
* @param msec time in miliseconds for timeout
|
||||
* @param h function to be called on timeout
|
||||
* @param arg argument to pass to timeout function h
|
||||
* @return ERR_MEM on memory error, ERR_OK otherwise
|
||||
*/
|
||||
err_t
|
||||
tcpip_untimeout(sys_timeout_handler h, void *arg)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
|
||||
if (mbox != SYS_MBOX_NULL) {
|
||||
msg = memp_malloc(MEMP_TCPIP_MSG_API);
|
||||
if (msg == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
msg->type = TCPIP_MSG_UNTIMEOUT;
|
||||
msg->msg.tmo.h = h;
|
||||
msg->msg.tmo.arg = arg;
|
||||
sys_mbox_post(mbox, msg);
|
||||
return ERR_OK;
|
||||
}
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
#if LWIP_NETCONN
|
||||
/**
|
||||
* Call the lower part of a netconn_* function
|
||||
|
@ -518,4 +555,42 @@ tcpip_init(void (* initfunc)(void *), void *arg)
|
|||
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple callback function used with tcpip_callback to free a pbuf
|
||||
* (pbuf_free has a wrong signature for tcpip_callback)
|
||||
*
|
||||
* @param p The pbuf (chain) to be dereferenced.
|
||||
*/
|
||||
static void
|
||||
pbuf_free_int(void *p)
|
||||
{
|
||||
struct pbuf *q = p;
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple wrapper function that allows you to free a pbuf from interrupt context.
|
||||
*
|
||||
* @param p The pbuf (chain) to be dereferenced.
|
||||
* @return ERR_OK if callback could be enqueued, an err_t if not
|
||||
*/
|
||||
err_t
|
||||
pbuf_free_callback(struct pbuf *p)
|
||||
{
|
||||
return tcpip_callback_with_block(pbuf_free_int, p, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple wrapper function that allows you to free heap memory from
|
||||
* interrupt context.
|
||||
*
|
||||
* @param m the heap memory to free
|
||||
* @return ERR_OK if callback could be enqueued, an err_t if not
|
||||
*/
|
||||
err_t
|
||||
mem_free_callback(void *m)
|
||||
{
|
||||
return tcpip_callback_with_block(mem_free, m, 0);
|
||||
}
|
||||
|
||||
#endif /* !NO_SYS */
|
||||
|
|
|
@ -77,8 +77,9 @@ typedef rt_uint32_t mem_ptr_t;
|
|||
#define PACK_STRUCT_END
|
||||
#endif
|
||||
|
||||
void sys_arch_assert(const char* file, int line);
|
||||
#define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0)
|
||||
#define LWIP_PLATFORM_ASSERT(x) {RT_ASSERT(x);}
|
||||
#define LWIP_PLATFORM_ASSERT(x) { rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__); }
|
||||
|
||||
#define SYS_ARCH_DECL_PROTECT(x)
|
||||
#define SYS_ARCH_PROTECT(x)
|
||||
|
|
|
@ -1,137 +0,0 @@
|
|||
#include "lwip/opt.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
#if (NO_SYS == 0)
|
||||
/* don't build if not configured for use in lwipopts.h */
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
/* RT-Thread kernel object */
|
||||
#define rt_list_entry(node, type, member) \
|
||||
((type *)((char *)(node) - (unsigned long)(&((type *)0)->member)))
|
||||
extern struct rt_object_information rt_object_container[];
|
||||
|
||||
/**
|
||||
* Wait (forever) for a message to arrive in an mbox.
|
||||
* While waiting, timeouts (for this thread) are processed.
|
||||
*
|
||||
* @param mbox the mbox to fetch the message from
|
||||
* @param msg the place to store the message
|
||||
*/
|
||||
void
|
||||
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
|
||||
{
|
||||
rt_mb_recv(mbox, (rt_uint32_t *)msg, RT_WAITING_FOREVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait (forever) for a semaphore to become available.
|
||||
* While waiting, timeouts (for this thread) are processed.
|
||||
*
|
||||
* @param sem semaphore to wait for
|
||||
*/
|
||||
void
|
||||
sys_sem_wait(sys_sem_t sem)
|
||||
{
|
||||
rt_sem_take(sem, RT_WAITING_FOREVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a one-shot timer (aka timeout). Timeouts are processed in the
|
||||
* following cases:
|
||||
* - while waiting for a message using sys_mbox_fetch()
|
||||
* - while waiting for a semaphore using sys_sem_wait() or sys_sem_wait_timeout()
|
||||
* - while sleeping using the inbuilt sys_msleep()
|
||||
*
|
||||
* @param msecs time in milliseconds after that the timer should expire
|
||||
* @param h callback function to call when msecs have elapsed
|
||||
* @param arg argument to pass to the callback function
|
||||
*/
|
||||
void
|
||||
sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
||||
{
|
||||
rt_timer_t timer;
|
||||
static int counter = 0;
|
||||
char tname[RT_NAME_MAX];
|
||||
|
||||
rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_TIMER_NAME, counter);
|
||||
counter ++;
|
||||
|
||||
/* create timer and start it */
|
||||
timer = rt_timer_create(tname, h, arg, msecs, RT_TIMER_FLAG_ONE_SHOT);
|
||||
rt_timer_start(timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through timeout list (for this task only) and remove the first matching
|
||||
* entry, even though the timeout has not triggered yet.
|
||||
*
|
||||
* @note This function only works as expected if there is only one timeout
|
||||
* calling 'h' in the list of timeouts.
|
||||
*
|
||||
* @param h callback function that would be called by the timeout
|
||||
* @param arg callback argument that would be passed to h
|
||||
*/
|
||||
void
|
||||
sys_untimeout(sys_timeout_handler h, void *arg)
|
||||
{
|
||||
rt_base_t level;
|
||||
struct rt_list_node *list, *node;
|
||||
struct rt_timer *timer = RT_NULL;
|
||||
|
||||
/* lock interrupt */
|
||||
level = rt_hw_interrupt_disable();
|
||||
|
||||
/* find related timer */
|
||||
list = &rt_object_container[RT_Object_Class_Timer].object_list;
|
||||
for (node = list->next; node != list; node = node->next)
|
||||
{
|
||||
timer = (struct rt_timer*)(rt_list_entry(node, struct rt_object, list));
|
||||
if (timer->timeout_func == h && timer->parameter == arg)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
/* remove this timer */
|
||||
if (timer != RT_NULL)
|
||||
rt_timer_delete(timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a semaphore with timeout (specified in ms)
|
||||
*
|
||||
* @param sem semaphore to wait
|
||||
* @param timeout timeout in ms (0: wait forever)
|
||||
* @return 0 on timeout, 1 otherwise
|
||||
*/
|
||||
int
|
||||
sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
|
||||
{
|
||||
rt_err_t err;
|
||||
|
||||
if (timeout == 0) err = rt_sem_take(sem, RT_WAITING_FOREVER);
|
||||
else err = rt_sem_take(sem, timeout);
|
||||
|
||||
if (err != RT_EOK) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep for some ms. Timeouts are processed while sleeping.
|
||||
*
|
||||
* @param ms number of milliseconds to sleep
|
||||
*/
|
||||
void
|
||||
sys_msleep(u32_t ms)
|
||||
{
|
||||
rt_thread_delay(ms);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -83,7 +83,10 @@ u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
|
|||
{
|
||||
rt_err_t ret;
|
||||
s32_t t;
|
||||
u32_t tick;
|
||||
|
||||
/* get the begin tick */
|
||||
tick = rt_tick_get();
|
||||
#ifdef LWIP_DEBUG
|
||||
{
|
||||
struct rt_thread *thread;
|
||||
|
@ -108,7 +111,14 @@ u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
|
|||
if (ret == -RT_ETIMEOUT) return SYS_ARCH_TIMEOUT;
|
||||
else if (ret == RT_EOK) ret = 1;
|
||||
|
||||
return ret;
|
||||
/* get elapse msecond */
|
||||
tick = rt_tick_get() - tick;
|
||||
|
||||
/* convert tick to msecond */
|
||||
tick = tick * (1000/RT_TICK_PER_SECOND);
|
||||
if (tick == 0) tick = 1;
|
||||
|
||||
return tick;
|
||||
}
|
||||
|
||||
sys_mbox_t sys_mbox_new(int size)
|
||||
|
@ -187,6 +197,10 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
|
|||
{
|
||||
rt_err_t ret;
|
||||
s32_t t;
|
||||
u32_t tick;
|
||||
|
||||
/* get the begin tick */
|
||||
tick = rt_tick_get();
|
||||
|
||||
if(timeout == 0)
|
||||
t = RT_WAITING_FOREVER;
|
||||
|
@ -212,7 +226,14 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
|
|||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
/* get elapse msecond */
|
||||
tick = rt_tick_get() - tick;
|
||||
|
||||
/* convert tick to msecond */
|
||||
tick = tick * (1000/RT_TICK_PER_SECOND);
|
||||
if (tick == 0) tick = 1;
|
||||
|
||||
return tick;
|
||||
}
|
||||
|
||||
u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg)
|
||||
|
@ -290,3 +311,9 @@ void sys_arch_unprotect(sys_prot_t pval)
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
void sys_arch_assert(const char* file, int line)
|
||||
{
|
||||
rt_kprintf("Assertion: %d in %s\n", line, file);
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
|
|
|
@ -86,10 +86,19 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
/** global transaction identifier, must be
|
||||
* unique for each DHCP request. We simply increment, starting
|
||||
* with this value (easy to match with a packet analyzer) */
|
||||
static u32_t xid = 0xABCD0000;
|
||||
/** Default for DHCP_GLOBAL_XID is 0xABCD0000
|
||||
* This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g.
|
||||
* #define DHCP_GLOBAL_XID_HEADER "stdlib.h"
|
||||
* #define DHCP_GLOBAL_XID rand()
|
||||
*/
|
||||
#ifdef DHCP_GLOBAL_XID_HEADER
|
||||
#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */
|
||||
#endif
|
||||
|
||||
/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU
|
||||
* MTU is checked to be big enough in dhcp_start */
|
||||
#define DHCP_MAX_MSG_LEN(netif) (netif->mtu)
|
||||
#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576
|
||||
|
||||
/* DHCP client state machine functions */
|
||||
static void dhcp_handle_ack(struct netif *netif);
|
||||
|
@ -183,6 +192,7 @@ dhcp_check(struct netif *netif)
|
|||
u16_t msecs;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
|
||||
(s16_t)netif->name[1]));
|
||||
dhcp_set_state(dhcp, DHCP_CHECKING);
|
||||
/* create an ARP query for the offered IP address, expecting that no host
|
||||
responds, as the IP address should not be in use. */
|
||||
result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
|
||||
|
@ -193,7 +203,6 @@ dhcp_check(struct netif *netif)
|
|||
msecs = 500;
|
||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
|
||||
dhcp_set_state(dhcp, DHCP_CHECKING);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -239,6 +248,7 @@ dhcp_select(struct netif *netif)
|
|||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
dhcp_set_state(dhcp, DHCP_REQUESTING);
|
||||
|
||||
/* create and initialize the DHCP message header */
|
||||
result = dhcp_create_request(netif);
|
||||
|
@ -247,7 +257,7 @@ dhcp_select(struct netif *netif)
|
|||
dhcp_option_byte(dhcp, DHCP_REQUEST);
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
|
||||
dhcp_option_short(dhcp, 576);
|
||||
dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
|
||||
|
||||
/* MUST request the offered IP address */
|
||||
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
|
||||
|
@ -264,7 +274,7 @@ dhcp_select(struct netif *netif)
|
|||
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
p = (const char*)netif->hostname;
|
||||
if (p!=NULL) {
|
||||
if (p != NULL) {
|
||||
dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p));
|
||||
while (*p) {
|
||||
dhcp_option_byte(dhcp, *p++);
|
||||
|
@ -284,12 +294,11 @@ dhcp_select(struct netif *netif)
|
|||
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
dhcp_delete_request(netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
|
||||
dhcp_set_state(dhcp, DHCP_REQUESTING);
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_select: could not allocate DHCP request\n"));
|
||||
}
|
||||
dhcp->tries++;
|
||||
msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000;
|
||||
msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
|
||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs));
|
||||
return result;
|
||||
|
@ -539,8 +548,6 @@ dhcp_handle_ack(struct netif *netif)
|
|||
dhcp->offered_dns_addr[n].addr = htonl(dhcp_get_option_long(&option_ptr[2 + n * 4]));
|
||||
#if LWIP_DNS
|
||||
dns_setserver( n, (struct ip_addr *)(&(dhcp->offered_dns_addr[n].addr)));
|
||||
/* added by Puxiang Xiong */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_ack(): DNS server: 0x%08"X32_F"\n", dhcp->offered_dns_addr[n].addr));
|
||||
#endif /* LWIP_DNS */
|
||||
}
|
||||
#if LWIP_DNS
|
||||
|
@ -570,8 +577,16 @@ dhcp_start(struct netif *netif)
|
|||
LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
|
||||
dhcp = netif->dhcp;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
/* Remove the flag that says this netif is handled by DHCP,
|
||||
it is set when we succeeded starting. */
|
||||
netif->flags &= ~NETIF_FLAG_DHCP;
|
||||
|
||||
/* check MTU of the netif */
|
||||
if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
/* no DHCP client attached yet? */
|
||||
if (dhcp == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
|
||||
|
@ -586,6 +601,12 @@ dhcp_start(struct netif *netif)
|
|||
/* already has DHCP client attached */
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n"));
|
||||
if (dhcp->pcb != NULL) {
|
||||
udp_remove(dhcp->pcb);
|
||||
}
|
||||
if (dhcp->p != NULL) {
|
||||
pbuf_free(dhcp->p);
|
||||
}
|
||||
}
|
||||
|
||||
/* clear data structure */
|
||||
|
@ -598,6 +619,9 @@ dhcp_start(struct netif *netif)
|
|||
netif->dhcp = dhcp = NULL;
|
||||
return ERR_MEM;
|
||||
}
|
||||
#if IP_SOF_BROADCAST
|
||||
dhcp->pcb->so_options|=SOF_BROADCAST;
|
||||
#endif /* IP_SOF_BROADCAST */
|
||||
/* set up local and remote port for the pcb */
|
||||
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
|
@ -611,6 +635,7 @@ dhcp_start(struct netif *netif)
|
|||
dhcp_stop(netif);
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* Set the flag that says this netif is handled by DHCP. */
|
||||
netif->flags |= NETIF_FLAG_DHCP;
|
||||
return result;
|
||||
}
|
||||
|
@ -653,13 +678,15 @@ dhcp_inform(struct netif *netif)
|
|||
dhcp_option_byte(dhcp, DHCP_INFORM);
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
|
||||
/* TODO: use netif->mtu ?! */
|
||||
dhcp_option_short(dhcp, 576);
|
||||
dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
|
||||
|
||||
dhcp_option_trailer(dhcp);
|
||||
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
#if IP_SOF_BROADCAST
|
||||
dhcp->pcb->so_options|=SOF_BROADCAST;
|
||||
#endif /* IP_SOF_BROADCAST */
|
||||
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||
udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
|
||||
|
@ -670,14 +697,12 @@ dhcp_inform(struct netif *netif)
|
|||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_inform: could not allocate DHCP request\n"));
|
||||
}
|
||||
|
||||
if (dhcp != NULL) {
|
||||
if (dhcp->pcb != NULL) {
|
||||
udp_remove(dhcp->pcb);
|
||||
}
|
||||
dhcp->pcb = NULL;
|
||||
mem_free((void *)dhcp);
|
||||
netif->dhcp = old_dhcp;
|
||||
if (dhcp->pcb != NULL) {
|
||||
udp_remove(dhcp->pcb);
|
||||
}
|
||||
dhcp->pcb = NULL;
|
||||
mem_free((void *)dhcp);
|
||||
netif->dhcp = old_dhcp;
|
||||
}
|
||||
|
||||
#if DHCP_DOES_ARP_CHECK
|
||||
|
@ -727,9 +752,6 @@ dhcp_decline(struct netif *netif)
|
|||
dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
|
||||
dhcp_option_byte(dhcp, DHCP_DECLINE);
|
||||
|
||||
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));
|
||||
|
||||
|
@ -768,6 +790,7 @@ dhcp_discover(struct netif *netif)
|
|||
u16_t msecs;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_discover()\n"));
|
||||
ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
|
||||
dhcp_set_state(dhcp, DHCP_SELECTING);
|
||||
/* create and initialize the DHCP message header */
|
||||
result = dhcp_create_request(netif);
|
||||
if (result == ERR_OK) {
|
||||
|
@ -776,7 +799,7 @@ dhcp_discover(struct netif *netif)
|
|||
dhcp_option_byte(dhcp, DHCP_DISCOVER);
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
|
||||
dhcp_option_short(dhcp, 576);
|
||||
dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
|
||||
dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
|
||||
|
@ -795,19 +818,17 @@ dhcp_discover(struct netif *netif)
|
|||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
|
||||
dhcp_delete_request(netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
|
||||
dhcp_set_state(dhcp, DHCP_SELECTING);
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_discover: could not allocate DHCP request\n"));
|
||||
}
|
||||
dhcp->tries++;
|
||||
#if LWIP_DHCP_AUTOIP_COOP
|
||||
/* that means we waited 57 seconds */
|
||||
if(dhcp->tries >= 9 && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) {
|
||||
if(dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) {
|
||||
dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON;
|
||||
autoip_start(netif);
|
||||
}
|
||||
#endif /* LWIP_DHCP_AUTOIP_COOP */
|
||||
msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
|
||||
msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
|
||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
|
||||
return result;
|
||||
|
@ -883,6 +904,13 @@ dhcp_bind(struct netif *netif)
|
|||
gw_addr.addr |= htonl(0x00000001);
|
||||
}
|
||||
|
||||
#if LWIP_DHCP_AUTOIP_COOP
|
||||
if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
|
||||
autoip_stop(netif);
|
||||
dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
|
||||
}
|
||||
#endif /* LWIP_DHCP_AUTOIP_COOP */
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
|
||||
netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", sn_mask.addr));
|
||||
|
@ -906,6 +934,9 @@ dhcp_renew(struct netif *netif)
|
|||
struct dhcp *dhcp = netif->dhcp;
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
const char *p;
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_renew()\n"));
|
||||
dhcp_set_state(dhcp, DHCP_RENEWING);
|
||||
|
||||
|
@ -917,8 +948,17 @@ dhcp_renew(struct netif *netif)
|
|||
dhcp_option_byte(dhcp, DHCP_REQUEST);
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
|
||||
/* TODO: use netif->mtu in some way */
|
||||
dhcp_option_short(dhcp, 576);
|
||||
dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
|
||||
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
p = (const char*)netif->hostname;
|
||||
if (p != NULL) {
|
||||
dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p));
|
||||
while (*p) {
|
||||
dhcp_option_byte(dhcp, *p++);
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
|
||||
#if 0
|
||||
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
|
||||
|
@ -961,6 +1001,9 @@ dhcp_rebind(struct netif *netif)
|
|||
struct dhcp *dhcp = netif->dhcp;
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
const char *p;
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n"));
|
||||
dhcp_set_state(dhcp, DHCP_REBINDING);
|
||||
|
||||
|
@ -972,7 +1015,17 @@ dhcp_rebind(struct netif *netif)
|
|||
dhcp_option_byte(dhcp, DHCP_REQUEST);
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
|
||||
dhcp_option_short(dhcp, 576);
|
||||
dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
|
||||
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
p = (const char*)netif->hostname;
|
||||
if (p != NULL) {
|
||||
dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p));
|
||||
while (*p) {
|
||||
dhcp_option_byte(dhcp, *p++);
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
|
||||
#if 0
|
||||
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
|
||||
|
@ -1065,10 +1118,19 @@ dhcp_stop(struct netif *netif)
|
|||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
|
||||
/* Remove the flag that says this netif is handled by DHCP. */
|
||||
netif->flags &= ~NETIF_FLAG_DHCP;
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_stop()\n"));
|
||||
/* netif is DHCP configured? */
|
||||
if (dhcp != NULL) {
|
||||
#if LWIP_DHCP_AUTOIP_COOP
|
||||
if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
|
||||
autoip_stop(netif);
|
||||
dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
|
||||
}
|
||||
#endif /* LWIP_DHCP_AUTOIP_COOP */
|
||||
|
||||
if (dhcp->pcb != NULL) {
|
||||
udp_remove(dhcp->pcb);
|
||||
dhcp->pcb = NULL;
|
||||
|
@ -1305,6 +1367,7 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
|
|||
dhcp_handle_offer(netif);
|
||||
}
|
||||
free_pbuf_and_return:
|
||||
dhcp_free_reply(dhcp);
|
||||
pbuf_free(p);
|
||||
dhcp->p = NULL;
|
||||
}
|
||||
|
@ -1319,6 +1382,20 @@ dhcp_create_request(struct netif *netif)
|
|||
{
|
||||
struct dhcp *dhcp;
|
||||
u16_t i;
|
||||
#ifndef DHCP_GLOBAL_XID
|
||||
/** default global transaction identifier starting value (easy to match
|
||||
* with a packet analyser). We simply increment for each new request.
|
||||
* Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one
|
||||
* at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */
|
||||
static u32_t xid = 0xABCD0000;
|
||||
#else
|
||||
static u32_t xid;
|
||||
static u8_t xid_initialised = 0;
|
||||
if (!xid_initialised) {
|
||||
xid = DHCP_GLOBAL_XID;
|
||||
xid_initialised = !xid_initialised;
|
||||
}
|
||||
#endif
|
||||
LWIP_ERROR("dhcp_create_request: netif != NULL", (netif != NULL), return ERR_ARG;);
|
||||
dhcp = netif->dhcp;
|
||||
LWIP_ERROR("dhcp_create_request: dhcp != NULL", (dhcp != NULL), return ERR_VAL;);
|
||||
|
@ -1332,9 +1409,12 @@ dhcp_create_request(struct netif *netif)
|
|||
LWIP_ASSERT("dhcp_create_request: check that first pbuf can hold struct dhcp_msg",
|
||||
(dhcp->p_out->len >= sizeof(struct dhcp_msg)));
|
||||
|
||||
/* give unique transaction identifier to this request */
|
||||
dhcp->xid = xid++;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("transaction id xid++(%"X32_F") dhcp->xid(%"U32_F")\n",xid,dhcp->xid));
|
||||
/* reuse transaction identifier in retransmissions */
|
||||
if (dhcp->tries==0)
|
||||
xid++;
|
||||
dhcp->xid = xid;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
|
||||
("transaction id xid(%"X32_F")\n", xid));
|
||||
|
||||
dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
|
||||
|
||||
|
@ -1347,7 +1427,10 @@ dhcp_create_request(struct netif *netif)
|
|||
dhcp->msg_out->xid = htonl(dhcp->xid);
|
||||
dhcp->msg_out->secs = 0;
|
||||
dhcp->msg_out->flags = 0;
|
||||
dhcp->msg_out->ciaddr.addr = netif->ip_addr.addr;
|
||||
dhcp->msg_out->ciaddr.addr = 0;
|
||||
if (dhcp->state==DHCP_BOUND || dhcp->state==DHCP_RENEWING || dhcp->state==DHCP_REBINDING) {
|
||||
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;
|
||||
|
|
|
@ -127,18 +127,19 @@
|
|||
PACK_STRUCT_BEGIN
|
||||
/** DNS message header */
|
||||
struct dns_hdr {
|
||||
u16_t id;
|
||||
u8_t flags1;
|
||||
u8_t flags2;
|
||||
u16_t numquestions;
|
||||
u16_t numanswers;
|
||||
u16_t numauthrr;
|
||||
u16_t numextrarr;
|
||||
PACK_STRUCT_FIELD(u16_t id);
|
||||
PACK_STRUCT_FIELD(u8_t flags1);
|
||||
PACK_STRUCT_FIELD(u8_t flags2);
|
||||
PACK_STRUCT_FIELD(u16_t numquestions);
|
||||
PACK_STRUCT_FIELD(u16_t numanswers);
|
||||
PACK_STRUCT_FIELD(u16_t numauthrr);
|
||||
PACK_STRUCT_FIELD(u16_t numextrarr);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
#define SIZEOF_DNS_HDR 12
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
|
@ -148,13 +149,14 @@ PACK_STRUCT_BEGIN
|
|||
struct dns_query {
|
||||
/* DNS query record starts with either a domain name or a pointer
|
||||
to a name already present somewhere in the packet. */
|
||||
u16_t type;
|
||||
u16_t class;
|
||||
PACK_STRUCT_FIELD(u16_t type);
|
||||
PACK_STRUCT_FIELD(u16_t class);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
#define SIZEOF_DNS_QUERY 4
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
|
@ -164,15 +166,16 @@ PACK_STRUCT_BEGIN
|
|||
struct dns_answer {
|
||||
/* DNS answer record starts with either a domain name or a pointer
|
||||
to a name already present somewhere in the packet. */
|
||||
u16_t type;
|
||||
u16_t class;
|
||||
u32_t ttl;
|
||||
u16_t len;
|
||||
PACK_STRUCT_FIELD(u16_t type);
|
||||
PACK_STRUCT_FIELD(u16_t class);
|
||||
PACK_STRUCT_FIELD(u32_t ttl);
|
||||
PACK_STRUCT_FIELD(u16_t len);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
#define SIZEOF_DNS_ANSWER 10
|
||||
|
||||
/** DNS table entry */
|
||||
struct dns_table_entry {
|
||||
|
@ -190,6 +193,40 @@ struct dns_table_entry {
|
|||
void *arg;
|
||||
};
|
||||
|
||||
#if DNS_LOCAL_HOSTLIST
|
||||
/** struct used for local host-list */
|
||||
struct local_hostlist_entry {
|
||||
/** static hostname */
|
||||
const char *name;
|
||||
/** static host address in network byteorder */
|
||||
u32_t addr;
|
||||
struct local_hostlist_entry *next;
|
||||
};
|
||||
|
||||
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
/** Local host-list. For hostnames in this list, no
|
||||
* external name resolution is performed */
|
||||
static struct local_hostlist_entry *local_hostlist_dynamic;
|
||||
#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
|
||||
/** Defining this allows the local_hostlist_static to be placed in a different
|
||||
* linker section (e.g. FLASH) */
|
||||
#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
|
||||
#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
|
||||
#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */
|
||||
/** Defining this allows the local_hostlist_static to be placed in a different
|
||||
* linker section (e.g. FLASH) */
|
||||
#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
|
||||
#define DNS_LOCAL_HOSTLIST_STORAGE_POST
|
||||
#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */
|
||||
DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
|
||||
DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
|
||||
|
||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
|
||||
static void dns_init_local();
|
||||
#endif /* DNS_LOCAL_HOSTLIST */
|
||||
|
||||
|
||||
/* forward declarations */
|
||||
static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
|
||||
|
@ -241,6 +278,9 @@ dns_init()
|
|||
dns_setserver(0, &dnsserver);
|
||||
}
|
||||
}
|
||||
#if DNS_LOCAL_HOSTLIST
|
||||
dns_init_local();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -288,6 +328,119 @@ dns_tmr(void)
|
|||
}
|
||||
}
|
||||
|
||||
#if DNS_LOCAL_HOSTLIST
|
||||
static void
|
||||
dns_init_local()
|
||||
{
|
||||
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
|
||||
int i;
|
||||
struct local_hostlist_entry *entry;
|
||||
/* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
|
||||
struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
|
||||
for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
|
||||
entry = mem_malloc(sizeof(struct local_hostlist_entry));
|
||||
LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
|
||||
if (entry != NULL) {
|
||||
struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
|
||||
entry->name = init_entry->name;
|
||||
entry->addr = init_entry->addr;
|
||||
entry->next = local_hostlist_dynamic;
|
||||
local_hostlist_dynamic = entry;
|
||||
}
|
||||
}
|
||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the local host-list for a hostname.
|
||||
*
|
||||
* @param hostname Hostname to look for in the local host-list
|
||||
* @return The first IP address for the hostname in the local host-list or
|
||||
* INADDR_NONE if not found.
|
||||
*/
|
||||
static u32_t
|
||||
dns_lookup_local(const char *hostname)
|
||||
{
|
||||
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
struct local_hostlist_entry *entry = local_hostlist_dynamic;
|
||||
while(entry != NULL) {
|
||||
if(strcmp(entry->name, hostname) == 0) {
|
||||
return entry->addr;
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
int i;
|
||||
for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
|
||||
if(strcmp(local_hostlist_static[i].name, hostname) == 0) {
|
||||
return local_hostlist_static[i].addr;
|
||||
}
|
||||
}
|
||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
return INADDR_NONE;
|
||||
}
|
||||
|
||||
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
/** Remove all entries from the local host-list for a specific hostname
|
||||
* and/or IP addess
|
||||
*
|
||||
* @param hostname hostname for which entries shall be removed from the local
|
||||
* host-list
|
||||
* @param addr address for which entries shall be removed from the local host-list
|
||||
* @return the number of removed entries
|
||||
*/
|
||||
int
|
||||
dns_local_removehost(const char *hostname, const struct ip_addr *addr)
|
||||
{
|
||||
int removed = 0;
|
||||
struct local_hostlist_entry *entry = local_hostlist_dynamic;
|
||||
struct local_hostlist_entry *last_entry = NULL;
|
||||
while (entry != NULL) {
|
||||
if (((hostname == NULL) || !strcmp(entry->name, hostname)) &&
|
||||
((addr == NULL) || (entry->addr == addr->addr))) {
|
||||
struct local_hostlist_entry *free_entry;
|
||||
if (last_entry != NULL) {
|
||||
last_entry->next = entry->next;
|
||||
} else {
|
||||
local_hostlist_dynamic = entry->next;
|
||||
}
|
||||
free_entry = entry;
|
||||
entry = entry->next;
|
||||
mem_free(free_entry);
|
||||
removed++;
|
||||
} else {
|
||||
last_entry = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a hostname/IP address pair to the local host-list.
|
||||
* Duplicates are not checked.
|
||||
*
|
||||
* @param hostname hostname of the new entry
|
||||
* @param addr IP address of the new entry
|
||||
* @return ERR_OK if succeeded or ERR_MEM on memory error
|
||||
*/
|
||||
err_t
|
||||
dns_local_addhost(const char *hostname, const struct ip_addr *addr)
|
||||
{
|
||||
struct local_hostlist_entry *entry;
|
||||
entry = mem_malloc(sizeof(struct local_hostlist_entry));
|
||||
if (entry == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
entry->name = hostname;
|
||||
entry->addr = addr->addr;
|
||||
entry->next = local_hostlist_dynamic;
|
||||
local_hostlist_dynamic = entry;
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/
|
||||
#endif /* DNS_LOCAL_HOSTLIST */
|
||||
|
||||
/**
|
||||
* Look up a hostname in the array of known hostnames.
|
||||
*
|
||||
|
@ -298,13 +451,26 @@ dns_tmr(void)
|
|||
*
|
||||
* @param name the hostname to look up
|
||||
* @return the hostname's IP address, as u32_t (instead of struct ip_addr to
|
||||
* better check for failure: != 0) or 0 if the hostname was not found
|
||||
* in the cached dns_table.
|
||||
* better check for failure: != INADDR_NONE) or INADDR_NONE if the hostname
|
||||
* was not found in the cached dns_table.
|
||||
*/
|
||||
static u32_t
|
||||
dns_lookup(const char *name)
|
||||
{
|
||||
u8_t i;
|
||||
#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
|
||||
u32_t addr;
|
||||
#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
|
||||
#if DNS_LOCAL_HOSTLIST
|
||||
if ((addr = dns_lookup_local(name)) != INADDR_NONE) {
|
||||
return addr;
|
||||
}
|
||||
#endif /* DNS_LOCAL_HOSTLIST */
|
||||
#ifdef DNS_LOOKUP_LOCAL_EXTERN
|
||||
if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != INADDR_NONE) {
|
||||
return addr;
|
||||
}
|
||||
#endif /* DNS_LOOKUP_LOCAL_EXTERN */
|
||||
|
||||
/* Walk through name list, return entry if found. If not, return NULL. */
|
||||
for (i = 0; i < DNS_TABLE_SIZE; ++i) {
|
||||
|
@ -317,7 +483,7 @@ dns_lookup(const char *name)
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return INADDR_NONE;
|
||||
}
|
||||
|
||||
#if DNS_DOES_NAME_CHECK
|
||||
|
@ -415,17 +581,17 @@ dns_send(u8_t numdns, const char* name, u8_t id)
|
|||
LWIP_ASSERT("dns server has no IP address set", dns_servers[numdns].addr != 0);
|
||||
|
||||
/* if here, we have either a new query or a retry on a previous query to process */
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dns_hdr) + DNS_MAX_NAME_LENGTH +
|
||||
sizeof(struct dns_query), PBUF_RAM);
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
|
||||
SIZEOF_DNS_QUERY, PBUF_RAM);
|
||||
if (p != NULL) {
|
||||
LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
|
||||
/* fill dns header */
|
||||
hdr = (struct dns_hdr*)p->payload;
|
||||
memset(hdr, 0, sizeof(struct dns_hdr));
|
||||
memset(hdr, 0, SIZEOF_DNS_HDR);
|
||||
hdr->id = htons(id);
|
||||
hdr->flags1 = DNS_FLAG1_RD;
|
||||
hdr->numquestions = htons(1);
|
||||
query = (char*)hdr + sizeof(struct dns_hdr);
|
||||
query = (char*)hdr + SIZEOF_DNS_HDR;
|
||||
pHostname = name;
|
||||
--pHostname;
|
||||
|
||||
|
@ -446,10 +612,10 @@ dns_send(u8_t numdns, const char* name, u8_t id)
|
|||
/* fill dns query */
|
||||
qry.type = htons(DNS_RRTYPE_A);
|
||||
qry.class = htons(DNS_RRCLASS_IN);
|
||||
MEMCPY( query, &qry, sizeof(struct dns_query));
|
||||
MEMCPY( query, &qry, SIZEOF_DNS_QUERY);
|
||||
|
||||
/* resize pbuf to the exact dns query */
|
||||
pbuf_realloc(p, (query + sizeof(struct dns_query)) - ((char*)(p->payload)));
|
||||
pbuf_realloc(p, (query + SIZEOF_DNS_QUERY) - ((char*)(p->payload)));
|
||||
|
||||
/* connect to the server for faster receiving */
|
||||
udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
|
||||
|
@ -591,7 +757,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
|
|||
}
|
||||
|
||||
/* is the dns message big enough ? */
|
||||
if (p->tot_len < (sizeof(struct dns_hdr) + sizeof(struct dns_query) + sizeof(struct dns_answer))) {
|
||||
if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
|
||||
/* free pbuf and return */
|
||||
goto memerr1;
|
||||
|
@ -632,7 +798,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
|
|||
|
||||
#if DNS_DOES_NAME_CHECK
|
||||
/* Check if the name in the "question" part match with the name in the entry. */
|
||||
if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + sizeof(struct dns_hdr)) != 0) {
|
||||
if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name));
|
||||
/* call callback to indicate error, clean up memory and return */
|
||||
goto responseerr;
|
||||
|
@ -640,14 +806,14 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
|
|||
#endif /* DNS_DOES_NAME_CHECK */
|
||||
|
||||
/* Skip the name in the "question" part */
|
||||
pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + sizeof(struct dns_hdr)) + sizeof(struct dns_query);
|
||||
pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
|
||||
|
||||
while(nanswers > 0) {
|
||||
/* skip answer resource record's host name */
|
||||
pHostname = (char *) dns_parse_name((unsigned char *)pHostname);
|
||||
|
||||
/* Check for IP address type and Internet class. Others are discarded. */
|
||||
MEMCPY(&ans, pHostname, sizeof(struct dns_answer));
|
||||
MEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
|
||||
if((ntohs(ans.type) == DNS_RRTYPE_A) && (ntohs(ans.class) == DNS_RRCLASS_IN) && (ntohs(ans.len) == sizeof(struct ip_addr)) ) {
|
||||
/* read the answer resource record's TTL, and maximize it if needed */
|
||||
pEntry->ttl = ntohl(ans.ttl);
|
||||
|
@ -655,7 +821,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
|
|||
pEntry->ttl = DNS_MAX_TTL;
|
||||
}
|
||||
/* read the IP address after answer resource record's header */
|
||||
MEMCPY( &(pEntry->ipaddr), (pHostname+sizeof(struct dns_answer)), sizeof(struct ip_addr));
|
||||
MEMCPY( &(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(struct ip_addr));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
|
||||
ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("\n"));
|
||||
|
@ -666,7 +832,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
|
|||
/* deallocate memory and return */
|
||||
goto memerr2;
|
||||
} else {
|
||||
pHostname = pHostname + sizeof(struct dns_answer) + htons(ans.len);
|
||||
pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
|
||||
}
|
||||
--nanswers;
|
||||
}
|
||||
|
@ -803,7 +969,7 @@ dns_gethostbyname(const char *hostname, struct ip_addr *addr, dns_found_callback
|
|||
/* host name already in octet notation? set ip addr and return ERR_OK
|
||||
* already have this address cached? */
|
||||
if (((addr->addr = inet_addr(hostname)) != INADDR_NONE) ||
|
||||
((addr->addr = dns_lookup(hostname)) != 0)) {
|
||||
((addr->addr = dns_lookup(hostname)) != INADDR_NONE)) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "lwip/raw.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/snmp_msg.h"
|
||||
#include "lwip/autoip.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/dns.h"
|
||||
|
@ -61,6 +62,9 @@
|
|||
#ifndef BYTE_ORDER
|
||||
#error "BYTE_ORDER is not defined, you have to define it in your cc.h"
|
||||
#endif
|
||||
#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
|
||||
#error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_ARP && ARP_QUEUEING)
|
||||
#error "If you want to use ARP Queueing, you have to define LWIP_ARP=1 in your lwipopts.h"
|
||||
#endif
|
||||
|
@ -155,6 +159,15 @@
|
|||
#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS)
|
||||
#error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h"
|
||||
#endif
|
||||
#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT)
|
||||
#error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
|
||||
#endif
|
||||
#if (TCP_QUEUE_OOSEQ && !LWIP_TCP)
|
||||
#error "TCP_QUEUE_OOSEQ requires LWIP_TCP"
|
||||
#endif
|
||||
#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
|
||||
#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
|
||||
#endif
|
||||
|
||||
|
||||
/* Compile-time checks for deprecated options.
|
||||
|
@ -241,6 +254,9 @@ lwip_init(void)
|
|||
#if LWIP_TCP
|
||||
tcp_init();
|
||||
#endif /* LWIP_TCP */
|
||||
#if LWIP_SNMP
|
||||
snmp_init();
|
||||
#endif /* LWIP_SNMP */
|
||||
#if LWIP_AUTOIP
|
||||
autoip_init();
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
|
|
@ -76,7 +76,15 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Pseudo random macro based on netif informations.
|
||||
/* 169.254.0.0 */
|
||||
#define AUTOIP_NET 0xA9FE0000
|
||||
/* 169.254.1.0 */
|
||||
#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100)
|
||||
/* 169.254.254.255 */
|
||||
#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF)
|
||||
|
||||
|
||||
/** Pseudo random macro based on netif informations.
|
||||
* You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */
|
||||
#ifndef LWIP_AUTOIP_RAND
|
||||
#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \
|
||||
|
@ -86,11 +94,21 @@
|
|||
(netif->autoip?netif->autoip->tried_llipaddr:0))
|
||||
#endif /* LWIP_AUTOIP_RAND */
|
||||
|
||||
/**
|
||||
* Macro that generates the initial IP address to be tried by AUTOIP.
|
||||
* If you want to override this, define it to something else in lwipopts.h.
|
||||
*/
|
||||
#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
|
||||
#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
|
||||
(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
|
||||
((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
|
||||
#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
|
||||
|
||||
/* static functions */
|
||||
static void autoip_handle_arp_conflict(struct netif *netif);
|
||||
|
||||
/* creates random LL IP-Address for a network interface */
|
||||
static void autoip_create_rand_addr(struct netif *netif, struct ip_addr *RandomIPAddr);
|
||||
/* creates a pseudo random LL IP-Address for a network interface */
|
||||
static void autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr);
|
||||
|
||||
/* sends an ARP announce */
|
||||
static err_t autoip_arp_announce(struct netif *netif);
|
||||
|
@ -144,30 +162,33 @@ autoip_handle_arp_conflict(struct netif *netif)
|
|||
* Create an IP-Address out of range 169.254.1.0 to 169.254.254.255
|
||||
*
|
||||
* @param netif network interface on which create the IP-Address
|
||||
* @param RandomIPAddr ip address to initialize
|
||||
* @param IPAddr ip address to initialize
|
||||
*/
|
||||
static void
|
||||
autoip_create_rand_addr(struct netif *netif, struct ip_addr *RandomIPAddr)
|
||||
autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr)
|
||||
{
|
||||
/* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
|
||||
* compliant to RFC 3927 Section 2.1
|
||||
* We have 254 * 256 possibilities
|
||||
*/
|
||||
* We have 254 * 256 possibilities */
|
||||
|
||||
RandomIPAddr->addr = (0xA9FE0100 + ((u32_t)(((u8_t)(netif->hwaddr[4])) |
|
||||
((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)) + netif->autoip->tried_llipaddr);
|
||||
u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif));
|
||||
addr += netif->autoip->tried_llipaddr;
|
||||
addr = AUTOIP_NET | (addr & 0xffff);
|
||||
/* Now, 169.254.0.0 <= addr <= 169.254.255.255 */
|
||||
|
||||
if (RandomIPAddr->addr>0xA9FEFEFF) {
|
||||
RandomIPAddr->addr = (0xA9FE0100 + (RandomIPAddr->addr-0xA9FEFEFF));
|
||||
if (addr < AUTOIP_RANGE_START) {
|
||||
addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
|
||||
}
|
||||
if (RandomIPAddr->addr<0xA9FE0100) {
|
||||
RandomIPAddr->addr = (0xA9FEFEFF - (0xA9FE0100-RandomIPAddr->addr));
|
||||
if (addr > AUTOIP_RANGE_END) {
|
||||
addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
|
||||
}
|
||||
RandomIPAddr->addr = htonl(RandomIPAddr->addr);
|
||||
LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
|
||||
(addr <= AUTOIP_RANGE_END));
|
||||
IPAddr->addr = htonl(addr);
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
|
||||
("autoip_create_rand_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n",
|
||||
(u16_t)(netif->autoip->tried_llipaddr), (u32_t)(RandomIPAddr->addr)));
|
||||
("autoip_create_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n",
|
||||
(u16_t)(netif->autoip->tried_llipaddr), (u32_t)(IPAddr->addr)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -258,7 +279,7 @@ autoip_start(struct netif *netif)
|
|||
autoip->lastconflict = 0;
|
||||
}
|
||||
|
||||
autoip_create_rand_addr(netif, &(autoip->llipaddr));
|
||||
autoip_create_addr(netif, &(autoip->llipaddr));
|
||||
autoip->tried_llipaddr++;
|
||||
autoip->state = AUTOIP_STATE_PROBING;
|
||||
autoip->sent_num = 0;
|
||||
|
@ -395,8 +416,8 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
|||
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
|
||||
* structure packing (not using structure copy which breaks strict-aliasing rules).
|
||||
*/
|
||||
MEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
|
||||
MEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
|
||||
SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
|
||||
SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
|
||||
|
||||
if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
|
||||
((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
|
||||
|
|
|
@ -53,9 +53,18 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
|
||||
* used to modify and send a response packet (and to 1 if this is not the case,
|
||||
* e.g. when link header is stripped of when receiving) */
|
||||
#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||
#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
|
||||
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
||||
|
||||
/* The amount of data from the original packet to return in a dest-unreachable */
|
||||
#define ICMP_DEST_UNREACH_DATASIZE 8
|
||||
|
||||
static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
|
||||
|
||||
/**
|
||||
* Processes ICMP input packets, called from ip_input().
|
||||
*
|
||||
|
@ -94,13 +103,30 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||
#endif /* LWIP_DEBUG */
|
||||
switch (type) {
|
||||
case ICMP_ECHO:
|
||||
/* broadcast or multicast destination address? */
|
||||
if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
|
||||
ICMP_STATS_INC(icmp.err);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
|
||||
{
|
||||
int accepted = 1;
|
||||
#if !LWIP_MULTICAST_PING
|
||||
/* multicast destination address? */
|
||||
if (ip_addr_ismulticast(&iphdr->dest)) {
|
||||
accepted = 0;
|
||||
}
|
||||
#endif /* LWIP_MULTICAST_PING */
|
||||
#if !LWIP_BROADCAST_PING
|
||||
/* broadcast destination address? */
|
||||
if (ip_addr_isbroadcast(&iphdr->dest, inp)) {
|
||||
accepted = 0;
|
||||
}
|
||||
#endif /* LWIP_BROADCAST_PING */
|
||||
/* broadcast or multicast destination address not acceptd? */
|
||||
if (!accepted) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
|
||||
ICMP_STATS_INC(icmp.err);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
|
||||
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
|
||||
|
@ -113,6 +139,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||
snmp_inc_icmpinerrors();
|
||||
return;
|
||||
}
|
||||
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||
if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) {
|
||||
/* p is not big enough to contain link headers
|
||||
* allocate a new one and copy p into it
|
||||
|
@ -153,6 +180,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||
goto memerr;
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
||||
/* At this point, all checks are OK. */
|
||||
/* We generate an answer by switching the dest and src ip addresses,
|
||||
* setting the icmp type to ECHO_RESPONSE and updating the checksum. */
|
||||
|
@ -205,11 +233,13 @@ lenerr:
|
|||
ICMP_STATS_INC(icmp.lenerr);
|
||||
snmp_inc_icmpinerrors();
|
||||
return;
|
||||
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||
memerr:
|
||||
pbuf_free(p);
|
||||
ICMP_STATS_INC(icmp.err);
|
||||
snmp_inc_icmpinerrors();
|
||||
return;
|
||||
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -224,40 +254,7 @@ memerr:
|
|||
void
|
||||
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_dur_hdr *idur;
|
||||
|
||||
/* ICMP header + IP header + 8 bytes of data */
|
||||
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
|
||||
PBUF_RAM);
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n"));
|
||||
return;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
||||
(q->len >= (sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
idur = q->payload;
|
||||
ICMPH_TYPE_SET(idur, ICMP_DUR);
|
||||
ICMPH_CODE_SET(idur, t);
|
||||
|
||||
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_dur_hdr), p->payload,
|
||||
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
|
||||
|
||||
/* calculate checksum */
|
||||
idur->chksum = 0;
|
||||
idur->chksum = inet_chksum(idur, q->len);
|
||||
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, 0, IP_PROTO_ICMP);
|
||||
pbuf_free(q);
|
||||
icmp_send_response(p, ICMP_DUR, t);
|
||||
}
|
||||
|
||||
#if IP_FORWARD || IP_REASSEMBLY
|
||||
|
@ -270,20 +267,37 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
|||
*/
|
||||
void
|
||||
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
||||
{
|
||||
icmp_send_response(p, ICMP_TE, t);
|
||||
}
|
||||
|
||||
#endif /* IP_FORWARD || IP_REASSEMBLY */
|
||||
|
||||
/**
|
||||
* Send an icmp packet in response to an incoming packet.
|
||||
*
|
||||
* @param p the input packet for which the 'unreachable' should be sent,
|
||||
* p->payload pointing to the IP header
|
||||
* @param type Type of the ICMP header
|
||||
* @param code Code of the ICMP header
|
||||
*/
|
||||
static void
|
||||
icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_te_hdr *tehdr;
|
||||
/* we can use the echo header here */
|
||||
struct icmp_echo_hdr *icmphdr;
|
||||
|
||||
/* ICMP header + IP header + 8 bytes of data */
|
||||
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
|
||||
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
|
||||
PBUF_RAM);
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
|
||||
return;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
||||
(q->len >= (sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
|
||||
(q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
|
||||
|
||||
iphdr = p->payload;
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
|
||||
|
@ -292,17 +306,19 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
|||
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
|
||||
|
||||
tehdr = q->payload;
|
||||
ICMPH_TYPE_SET(tehdr, ICMP_TE);
|
||||
ICMPH_CODE_SET(tehdr, t);
|
||||
icmphdr = q->payload;
|
||||
icmphdr->type = type;
|
||||
icmphdr->code = code;
|
||||
icmphdr->id = 0;
|
||||
icmphdr->seqno = 0;
|
||||
|
||||
/* copy fields from original packet */
|
||||
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_dur_hdr), (u8_t *)p->payload,
|
||||
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
|
||||
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
|
||||
|
||||
/* calculate checksum */
|
||||
tehdr->chksum = 0;
|
||||
tehdr->chksum = inet_chksum(tehdr, q->len);
|
||||
icmphdr->chksum = 0;
|
||||
icmphdr->chksum = inet_chksum(icmphdr, q->len);
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
/* increase number of messages attempted to send */
|
||||
snmp_inc_icmpoutmsgs();
|
||||
|
@ -312,6 +328,4 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
|||
pbuf_free(q);
|
||||
}
|
||||
|
||||
#endif /* IP_FORWARD */
|
||||
|
||||
#endif /* LWIP_ICMP */
|
||||
|
|
|
@ -128,7 +128,7 @@ igmp_dump_group_list()
|
|||
while (group != NULL) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state)));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %x\n", (int) group->interface));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->interface));
|
||||
group = group->next;
|
||||
}
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
|
||||
|
@ -147,7 +147,7 @@ igmp_start(struct netif *netif)
|
|||
{
|
||||
struct igmp_group* group;
|
||||
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %x\n", (int) netif));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", netif));
|
||||
|
||||
group = igmp_lookup_group(netif, &allsystems);
|
||||
|
||||
|
@ -159,7 +159,7 @@ igmp_start(struct netif *netif)
|
|||
if (netif->igmp_mac_filter != NULL) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD "));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &allsystems);
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
|
||||
netif->igmp_mac_filter( netif, &allsystems, IGMP_ADD_MAC_FILTER);
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,7 @@ igmp_stop(struct netif *netif)
|
|||
if (netif->igmp_mac_filter != NULL) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL "));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
|
||||
netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER);
|
||||
}
|
||||
/* free group */
|
||||
|
@ -223,7 +223,7 @@ igmp_report_groups( struct netif *netif)
|
|||
{
|
||||
struct igmp_group *group = igmp_group_list;
|
||||
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %x\n", (int) netif));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif));
|
||||
|
||||
while (group != NULL) {
|
||||
if (group->interface == netif) {
|
||||
|
@ -295,7 +295,7 @@ igmp_lookup_group(struct netif *ifp, struct ip_addr *addr)
|
|||
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));
|
||||
ip_addr_debug_print(IGMP_DEBUG, addr);
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %x\n", (int) ifp));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", ifp));
|
||||
|
||||
return group;
|
||||
}
|
||||
|
@ -361,7 +361,7 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
|
|||
ip_addr_debug_print(IGMP_DEBUG, &(iphdr->src));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" to address "));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &(iphdr->dest));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %x\n", (int) inp));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp));
|
||||
|
||||
/* Now calculate and check the checksum */
|
||||
igmp = (struct igmp_msg *)p->payload;
|
||||
|
@ -439,7 +439,8 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %x in state %x on group %x on if %x\n", (int) igmp->igmp_msgtype, (int) group->group_state, (int) &group, (int) group->interface));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n",
|
||||
igmp->igmp_msgtype, group->group_state, &group, group->interface));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -488,7 +489,7 @@ igmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
|
|||
if ((group->use==0) && (netif->igmp_mac_filter != NULL)) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD "));
|
||||
ip_addr_debug_print(IGMP_DEBUG, groupaddr);
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
|
||||
netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER);
|
||||
}
|
||||
|
||||
|
@ -563,7 +564,7 @@ igmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
|
|||
if (netif->igmp_mac_filter != NULL) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL "));
|
||||
ip_addr_debug_print(IGMP_DEBUG, groupaddr);
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
|
||||
netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER);
|
||||
}
|
||||
|
||||
|
@ -624,7 +625,7 @@ igmp_timeout(struct igmp_group *group)
|
|||
if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address "));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &(group->group_address));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %x\n", (int) group->interface));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->interface));
|
||||
|
||||
igmp_send(group, IGMP_V2_MEMB_REPORT);
|
||||
}
|
||||
|
@ -666,7 +667,8 @@ igmp_stop_timer(struct igmp_group *group)
|
|||
void
|
||||
igmp_delaying_member( struct igmp_group *group, u8_t maxresp)
|
||||
{
|
||||
if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && (maxresp > group->timer))) {
|
||||
if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) ||
|
||||
((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && (maxresp > group->timer))) {
|
||||
igmp_start_timer(group, (maxresp)/2);
|
||||
group->group_state = IGMP_GROUP_DELAYING_MEMBER;
|
||||
}
|
||||
|
@ -695,64 +697,11 @@ err_t
|
|||
igmp_ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t proto, struct netif *netif)
|
||||
{
|
||||
static u16_t ip_id = 0;
|
||||
struct ip_hdr * iphdr = NULL;
|
||||
u16_t * ra = NULL;
|
||||
|
||||
/* First write in the "router alert" */
|
||||
if (pbuf_header(p, ROUTER_ALERTLEN)) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_ip_output_if: not enough room for IP header in pbuf\n"));
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
/* This is the "router alert" option */
|
||||
ra = p->payload;
|
||||
u16_t ra[2];
|
||||
ra[0] = htons (ROUTER_ALERT);
|
||||
ra[1] = 0x0000; /* Router shall examine packet */
|
||||
|
||||
/* now the normal ip header */
|
||||
if (pbuf_header(p, IP_HLEN)) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_ip_output_if: not enough room for IP header in pbuf\n"));
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
/* Should the IP header be generated or is it already included in p? */
|
||||
if (dest != IP_HDRINCL) {
|
||||
/** @todo should be shared with ip.c - ip_output_if */
|
||||
IPH_TTL_SET(iphdr, ttl);
|
||||
IPH_PROTO_SET(iphdr, proto);
|
||||
|
||||
ip_addr_set(&(iphdr->dest), dest);
|
||||
|
||||
IPH_VHLTOS_SET(iphdr, 4, ((IP_HLEN + ROUTER_ALERTLEN) / 4), 0/*tos*/);
|
||||
IPH_LEN_SET(iphdr, htons(p->tot_len));
|
||||
IPH_OFFSET_SET(iphdr, 0);
|
||||
IPH_ID_SET(iphdr, htons(ip_id));
|
||||
++ip_id;
|
||||
|
||||
if (ip_addr_isany(src)) {
|
||||
ip_addr_set(&(iphdr->src), &(netif->ip_addr));
|
||||
} else {
|
||||
ip_addr_set(&(iphdr->src), src);
|
||||
}
|
||||
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
#if CHECKSUM_GEN_IP
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, (IP_HLEN + ROUTER_ALERTLEN)));
|
||||
#endif
|
||||
} else {
|
||||
dest = &(iphdr->dest);
|
||||
}
|
||||
|
||||
#if IP_DEBUG
|
||||
ip_debug_print(p);
|
||||
#endif
|
||||
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_ip_output_if: sending to if %x\n", (int) netif));
|
||||
|
||||
return netif->output(netif, p, dest);
|
||||
return ip_output_if_opt(p, src, dest, ttl, 0, proto, netif, ra, ROUTER_ALERTLEN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -796,10 +745,10 @@ igmp_send(struct igmp_group *group, u8_t type)
|
|||
igmp->igmp_checksum = 0;
|
||||
igmp->igmp_checksum = inet_chksum( igmp, IGMP_MINLEN);
|
||||
|
||||
igmp_ip_output_if( p, &src, dest, IGMP_TTL, IP_PROTO_IGMP, group->interface);
|
||||
igmp_ip_output_if(p, &src, dest, IGMP_TTL, IP_PROTO_IGMP, group->interface);
|
||||
}
|
||||
|
||||
pbuf_free (p);
|
||||
pbuf_free(p);
|
||||
} else {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n"));
|
||||
}
|
||||
|
|
|
@ -83,7 +83,8 @@ int
|
|||
inet_aton(const char *cp, struct in_addr *addr)
|
||||
{
|
||||
u32_t val;
|
||||
int base, n, c;
|
||||
u8_t base;
|
||||
char c;
|
||||
u32_t parts[4];
|
||||
u32_t *pp = parts;
|
||||
|
||||
|
@ -133,14 +134,13 @@ inet_aton(const char *cp, struct in_addr *addr)
|
|||
/*
|
||||
* Check for trailing characters.
|
||||
*/
|
||||
if (c != '\0' && (!isprint(c) || !isspace(c)))
|
||||
if (c != '\0' && !isspace(c))
|
||||
return (0);
|
||||
/*
|
||||
* Concoct the address according to
|
||||
* the number of parts specified.
|
||||
*/
|
||||
n = pp - parts + 1;
|
||||
switch (n) {
|
||||
switch (pp - parts + 1) {
|
||||
|
||||
case 0:
|
||||
return (0); /* initial nondigit */
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/inet.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* These are some reference implementations of the checksum algorithm, with the
|
||||
* aim of being simple, correct and fully portable. Checksumming is the
|
||||
|
@ -65,6 +65,18 @@
|
|||
# define LWIP_CHKSUM_ALGORITHM 0
|
||||
#endif
|
||||
|
||||
/** Like the name says... */
|
||||
#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
/* little endian and PLATFORM_BYTESWAP defined */
|
||||
#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w)
|
||||
#else
|
||||
/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */
|
||||
#define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8)
|
||||
#endif
|
||||
|
||||
/** Split an u32_t in two u16_ts and add them up */
|
||||
#define FOLD_U32T(u) ((u >> 16) + (u & 0x0000ffffUL))
|
||||
|
||||
#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
|
||||
/**
|
||||
* lwip checksum
|
||||
|
@ -86,8 +98,7 @@ lwip_standard_chksum(void *dataptr, u16_t len)
|
|||
acc = 0;
|
||||
/* dataptr may be at odd or even addresses */
|
||||
octetptr = (u8_t*)dataptr;
|
||||
while (len > 1)
|
||||
{
|
||||
while (len > 1) {
|
||||
/* declare first octet as most significant
|
||||
thus assume network order, ignoring host order */
|
||||
src = (*octetptr) << 8;
|
||||
|
@ -98,15 +109,14 @@ lwip_standard_chksum(void *dataptr, u16_t len)
|
|||
acc += src;
|
||||
len -= 2;
|
||||
}
|
||||
if (len > 0)
|
||||
{
|
||||
if (len > 0) {
|
||||
/* accumulate remaining octet */
|
||||
src = (*octetptr) << 8;
|
||||
acc += src;
|
||||
}
|
||||
/* add deferred carry bits */
|
||||
acc = (acc >> 16) + (acc & 0x0000ffffUL);
|
||||
if ((acc & 0xffff0000) != 0) {
|
||||
if ((acc & 0xffff0000UL) != 0) {
|
||||
acc = (acc >> 16) + (acc & 0x0000ffffUL);
|
||||
}
|
||||
/* This maybe a little confusing: reorder sum using htons()
|
||||
|
@ -154,19 +164,22 @@ lwip_standard_chksum(void *dataptr, int len)
|
|||
}
|
||||
|
||||
/* Consume left-over byte, if any */
|
||||
if (len > 0)
|
||||
if (len > 0) {
|
||||
((u8_t *)&t)[0] = *(u8_t *)ps;;
|
||||
}
|
||||
|
||||
/* Add end bytes */
|
||||
sum += t;
|
||||
|
||||
/* Fold 32-bit sum to 16 bits */
|
||||
while ((sum >> 16) != 0)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
sum = FOLD_U32T(sum);
|
||||
sum = FOLD_U32T(sum);
|
||||
|
||||
/* Swap if alignment was odd */
|
||||
if (odd)
|
||||
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
|
||||
if (odd) {
|
||||
sum = SWAP_BYTES_IN_WORD(sum);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
@ -211,18 +224,20 @@ lwip_standard_chksum(void *dataptr, int len)
|
|||
|
||||
while (len > 7) {
|
||||
tmp = sum + *pl++; /* ping */
|
||||
if (tmp < sum)
|
||||
if (tmp < sum) {
|
||||
tmp++; /* add back carry */
|
||||
}
|
||||
|
||||
sum = tmp + *pl++; /* pong */
|
||||
if (sum < tmp)
|
||||
if (sum < tmp) {
|
||||
sum++; /* add back carry */
|
||||
}
|
||||
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
/* make room in upper bits */
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum = FOLD_U32T(sum);
|
||||
|
||||
ps = (u16_t *)pl;
|
||||
|
||||
|
@ -233,16 +248,20 @@ lwip_standard_chksum(void *dataptr, int len)
|
|||
}
|
||||
|
||||
/* dangling tail byte remaining? */
|
||||
if (len > 0) /* include odd byte */
|
||||
if (len > 0) { /* include odd byte */
|
||||
((u8_t *)&t)[0] = *(u8_t *)ps;
|
||||
}
|
||||
|
||||
sum += t; /* add end bytes */
|
||||
|
||||
while ((sum >> 16) != 0) /* combine halves */
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
sum = FOLD_U32T(sum);
|
||||
sum = FOLD_U32T(sum);
|
||||
|
||||
if (odd)
|
||||
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
|
||||
if (odd) {
|
||||
sum = SWAP_BYTES_IN_WORD(sum);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
@ -277,18 +296,18 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||
(void *)q, (void *)q->next));
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||
while ((acc >> 16) != 0) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
/* just executing this next line is probably faster that the if statement needed
|
||||
to check whether we really need to execute it, and does no harm */
|
||||
acc = FOLD_U32T(acc);
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
acc += (src->addr & 0xffffUL);
|
||||
acc += ((src->addr >> 16) & 0xffffUL);
|
||||
|
@ -297,9 +316,10 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
while ((acc >> 16) != 0) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
acc = FOLD_U32T(acc);
|
||||
acc = FOLD_U32T(acc);
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
@ -316,6 +336,8 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||
* @param proto_len length of the ip data part (used for checksum of pseudo header)
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
/* Currently only used by UDPLITE, although this could change in the future. */
|
||||
#if LWIP_UDPLITE
|
||||
u16_t
|
||||
inet_chksum_pseudo_partial(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
|
@ -340,18 +362,17 @@ inet_chksum_pseudo_partial(struct pbuf *p,
|
|||
chksum_len -= chklen;
|
||||
LWIP_ASSERT("delete me", chksum_len < 0x7fff);
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||
while ((acc >> 16) != 0) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
/* fold the upper bit down */
|
||||
acc = FOLD_U32T(acc);
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
acc += (src->addr & 0xffffUL);
|
||||
acc += ((src->addr >> 16) & 0xffffUL);
|
||||
|
@ -360,12 +381,14 @@ inet_chksum_pseudo_partial(struct pbuf *p,
|
|||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
while ((acc >> 16) != 0) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
acc = FOLD_U32T(acc);
|
||||
acc = FOLD_U32T(acc);
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
#endif /* LWIP_UDPLITE */
|
||||
|
||||
/* inet_chksum:
|
||||
*
|
||||
|
@ -380,13 +403,7 @@ inet_chksum_pseudo_partial(struct pbuf *p,
|
|||
u16_t
|
||||
inet_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc;
|
||||
|
||||
acc = LWIP_CHKSUM(dataptr, len);
|
||||
while ((acc >> 16) != 0) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
return (u16_t)~(acc & 0xffff);
|
||||
return ~LWIP_CHKSUM(dataptr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -407,17 +424,15 @@ inet_chksum_pbuf(struct pbuf *p)
|
|||
swapped = 0;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
while ((acc >> 16) != 0) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
acc = FOLD_U32T(acc);
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = (acc & 0x00ffUL << 8) | (acc & 0xff00UL >> 8);
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,47 @@
|
|||
#include "lwip/stats.h"
|
||||
#include "arch/perf.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* The interface that provided the packet for the current callback
|
||||
* invocation.
|
||||
*/
|
||||
static struct netif *current_netif;
|
||||
|
||||
/**
|
||||
* Header of the input packet currently being processed.
|
||||
*/
|
||||
static const struct ip_hdr *current_header;
|
||||
|
||||
/**
|
||||
* Get the interface that received the current packet.
|
||||
*
|
||||
* This function must only be called from a receive callback (udp_recv,
|
||||
* raw_recv, tcp_accept). It will return NULL otherwise.
|
||||
*
|
||||
* @param pcb Pointer to the pcb receiving a packet.
|
||||
*/
|
||||
struct netif *
|
||||
ip_current_netif(void)
|
||||
{
|
||||
return current_netif;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IP header of the current packet.
|
||||
*
|
||||
* This function must only be called from a receive callback (udp_recv,
|
||||
* raw_recv, tcp_accept). It will return NULL otherwise.
|
||||
*
|
||||
* @param pcb Pointer to the pcb receiving a packet.
|
||||
*/
|
||||
const struct ip_hdr *
|
||||
ip_current_header(void)
|
||||
{
|
||||
return current_header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the appropriate network interface for a given IP address. It
|
||||
* searches the list of network interfaces linearly. A match is found
|
||||
|
@ -388,6 +429,9 @@ ip_input(struct pbuf *p, struct netif *inp)
|
|||
ip_debug_print(p);
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
|
||||
|
||||
current_netif = inp;
|
||||
current_header = iphdr;
|
||||
|
||||
#if LWIP_RAW
|
||||
/* raw input did not eat the packet? */
|
||||
if (raw_input(p, inp) == 0)
|
||||
|
@ -440,6 +484,9 @@ ip_input(struct pbuf *p, struct netif *inp)
|
|||
}
|
||||
}
|
||||
|
||||
current_netif = NULL;
|
||||
current_header = NULL;
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
@ -473,6 +520,21 @@ 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)
|
||||
{
|
||||
#if IP_OPTIONS_SEND
|
||||
return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as ip_output_if() but with the possibility to include IP options:
|
||||
*
|
||||
* @ param ip_options pointer to the IP options, copied into the IP header
|
||||
* @ param optlen length of ip_options
|
||||
*/
|
||||
err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
||||
u16_t optlen)
|
||||
{
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
struct ip_hdr *iphdr;
|
||||
static u16_t ip_id = 0;
|
||||
|
||||
|
@ -480,6 +542,27 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||
|
||||
/* Should the IP header be generated or is it already included in p? */
|
||||
if (dest != IP_HDRINCL) {
|
||||
u16_t ip_hlen = IP_HLEN;
|
||||
#if IP_OPTIONS_SEND
|
||||
u16_t optlen_aligned = 0;
|
||||
if (optlen != 0) {
|
||||
/* round up to a multiple of 4 */
|
||||
optlen_aligned = ((optlen + 3) & ~3);
|
||||
ip_hlen += optlen_aligned;
|
||||
/* First write in the IP options */
|
||||
if (pbuf_header(p, optlen_aligned)) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output_if_opt: not enough room for IP options in pbuf\n"));
|
||||
IP_STATS_INC(ip.err);
|
||||
snmp_inc_ipoutdiscards();
|
||||
return ERR_BUF;
|
||||
}
|
||||
MEMCPY(p->payload, ip_options, optlen);
|
||||
if (optlen < optlen_aligned) {
|
||||
/* zero the remaining bytes */
|
||||
memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
|
||||
}
|
||||
}
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
/* generate IP header */
|
||||
if (pbuf_header(p, IP_HLEN)) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
|
||||
|
@ -498,7 +581,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, tos);
|
||||
IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos);
|
||||
IPH_LEN_SET(iphdr, htons(p->tot_len));
|
||||
IPH_OFFSET_SET(iphdr, 0);
|
||||
IPH_ID_SET(iphdr, htons(ip_id));
|
||||
|
@ -512,7 +595,7 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
#if CHECKSUM_GEN_IP
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
|
||||
#endif
|
||||
} else {
|
||||
/* IP header already included in p */
|
||||
|
@ -531,9 +614,19 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
|
||||
ip_debug_print(p);
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
||||
#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
|
||||
if (ip_addr_cmp(dest, &netif->ip_addr)) {
|
||||
/* Packet to self, enqueue it for loopback */
|
||||
LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
|
||||
|
||||
return netif->output(netif, p, dest);
|
||||
return netif_loop_output(netif, p, dest);
|
||||
} else
|
||||
#endif /* (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) */
|
||||
{
|
||||
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
||||
|
||||
return netif->output(netif, p, dest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -560,12 +653,54 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||
struct netif *netif;
|
||||
|
||||
if ((netif = ip_route(dest)) == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
|
||||
IP_STATS_INC(ip.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
return ip_output_if(p, src, dest, ttl, tos, proto, netif);
|
||||
}
|
||||
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
|
||||
* before calling ip_output_if.
|
||||
*
|
||||
* @param p the packet to send (p->payload points to the data, e.g. next
|
||||
protocol header; if dest == IP_HDRINCL, p already includes an IP
|
||||
header and p->payload points to that IP header)
|
||||
* @param src the source IP address to send from (if src == IP_ADDR_ANY, the
|
||||
* IP address of the netif used to send is used as source address)
|
||||
* @param dest the destination IP address to send the packet to
|
||||
* @param ttl the TTL value to be set in the IP header
|
||||
* @param tos the TOS value to be set in the IP header
|
||||
* @param proto the PROTOCOL to be set in the IP header
|
||||
* @param addr_hint address hint pointer set to netif->addr_hint before
|
||||
* calling ip_output_if()
|
||||
*
|
||||
* @return ERR_RTE if no route is found
|
||||
* see ip_output_if() for more return values
|
||||
*/
|
||||
err_t
|
||||
ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)
|
||||
{
|
||||
struct netif *netif;
|
||||
err_t err;
|
||||
|
||||
if ((netif = ip_route(dest)) == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
|
||||
IP_STATS_INC(ip.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
netif->addr_hint = addr_hint;
|
||||
err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
|
||||
netif->addr_hint = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
|
||||
#if IP_DEBUG
|
||||
/* Print an IP header by using LWIP_DEBUGF
|
||||
* @param p an IP packet, p->payload pointing to the IP header
|
||||
|
|
|
@ -81,12 +81,21 @@
|
|||
/** This is a helper struct which holds the starting
|
||||
* offset and the ending offset of this fragment to
|
||||
* easily chain the fragments.
|
||||
* It has to be packed since it has to fit inside the IP header.
|
||||
*/
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip_reass_helper {
|
||||
struct pbuf *next_pbuf;
|
||||
u16_t start;
|
||||
u16_t end;
|
||||
};
|
||||
PACK_STRUCT_FIELD(struct pbuf *next_pbuf);
|
||||
PACK_STRUCT_FIELD(u16_t start);
|
||||
PACK_STRUCT_FIELD(u16_t end);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \
|
||||
(ip_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \
|
||||
|
@ -599,7 +608,7 @@ nullreturn:
|
|||
|
||||
#if IP_FRAG
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU)];
|
||||
static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)];
|
||||
#endif /* IP_FRAG_USES_STATIC_BUF */
|
||||
|
||||
/**
|
||||
|
|
|
@ -327,6 +327,28 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||
return ip_output_if (p, src, dest, ttl, proto, netif);
|
||||
}
|
||||
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
err_t
|
||||
ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)
|
||||
{
|
||||
struct netif *netif;
|
||||
err_t err;
|
||||
|
||||
if ((netif = ip_route(dest)) == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
|
||||
IP_STATS_INC(ip.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
netif->addr_hint = addr_hint;
|
||||
err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
|
||||
netif->addr_hint = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
|
||||
#if IP_DEBUG
|
||||
void
|
||||
ip_debug_print(struct pbuf *p)
|
||||
|
|
|
@ -67,14 +67,6 @@
|
|||
#if MEM_USE_POOLS
|
||||
/* lwIP head implemented with different sized pools */
|
||||
|
||||
/**
|
||||
* This structure is used to save the pool one element came from.
|
||||
*/
|
||||
struct mem_helper
|
||||
{
|
||||
memp_t poolnr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocate memory: determine the smallest pool that is big enough
|
||||
* to contain an element of 'size' and get an element from that pool.
|
||||
|
@ -85,13 +77,17 @@ struct mem_helper
|
|||
void *
|
||||
mem_malloc(mem_size_t size)
|
||||
{
|
||||
struct mem_helper *element;
|
||||
struct memp_malloc_helper *element;
|
||||
memp_t poolnr;
|
||||
mem_size_t required_size = size + sizeof(struct memp_malloc_helper);
|
||||
|
||||
for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr++) {
|
||||
#if MEM_USE_POOLS_TRY_BIGGER_POOL
|
||||
again:
|
||||
#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
|
||||
/* is this pool big enough to hold an element of the required size
|
||||
plus a struct mem_helper that saves the pool this element came from? */
|
||||
if ((size + sizeof(struct mem_helper)) <= memp_sizes[poolnr]) {
|
||||
plus a struct memp_malloc_helper that saves the pool this element came from? */
|
||||
if (required_size <= memp_sizes[poolnr]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -99,17 +95,23 @@ mem_malloc(mem_size_t size)
|
|||
LWIP_ASSERT("mem_malloc(): no pool is that big!", 0);
|
||||
return NULL;
|
||||
}
|
||||
element = (struct mem_helper*)memp_malloc(poolnr);
|
||||
element = (struct memp_malloc_helper*)memp_malloc(poolnr);
|
||||
if (element == NULL) {
|
||||
/* No need to DEBUGF or ASSERT: This error is already
|
||||
taken care of in memp.c */
|
||||
/** @todo: we could try a bigger pool if this one is empty! */
|
||||
#if MEM_USE_POOLS_TRY_BIGGER_POOL
|
||||
/** Try a bigger pool if this one is empty! */
|
||||
if (poolnr < MEMP_POOL_LAST) {
|
||||
poolnr++;
|
||||
goto again;
|
||||
}
|
||||
#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* save the pool number this element came from */
|
||||
element->poolnr = poolnr;
|
||||
/* and return a pointer to the memory directly after the struct mem_helper */
|
||||
/* and return a pointer to the memory directly after the struct memp_malloc_helper */
|
||||
element++;
|
||||
|
||||
return element;
|
||||
|
@ -125,12 +127,12 @@ mem_malloc(mem_size_t size)
|
|||
void
|
||||
mem_free(void *rmem)
|
||||
{
|
||||
struct mem_helper *hmem = (struct mem_helper*)rmem;
|
||||
struct memp_malloc_helper *hmem = (struct memp_malloc_helper*)rmem;
|
||||
|
||||
LWIP_ASSERT("rmem != NULL", (rmem != NULL));
|
||||
LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
|
||||
|
||||
/* get the original struct mem_helper */
|
||||
/* get the original struct memp_malloc_helper */
|
||||
hmem--;
|
||||
|
||||
LWIP_ASSERT("hmem != NULL", (hmem != NULL));
|
||||
|
@ -177,9 +179,36 @@ static u8_t *ram;
|
|||
static struct mem *ram_end;
|
||||
/** pointer to the lowest free block, this is used for faster search */
|
||||
static struct mem *lfree;
|
||||
|
||||
/** concurrent access protection */
|
||||
static sys_sem_t mem_sem;
|
||||
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
|
||||
static volatile u8_t mem_free_count;
|
||||
|
||||
/* Allow mem_free from other (e.g. interrupt) context */
|
||||
#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free)
|
||||
#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free)
|
||||
#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free)
|
||||
#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc)
|
||||
#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc)
|
||||
#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc)
|
||||
|
||||
#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
|
||||
/* Protect the heap only by using a semaphore */
|
||||
#define LWIP_MEM_FREE_DECL_PROTECT()
|
||||
#define LWIP_MEM_FREE_PROTECT() sys_arch_sem_wait(mem_sem, 0)
|
||||
#define LWIP_MEM_FREE_UNPROTECT() sys_sem_signal(mem_sem)
|
||||
/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
|
||||
#define LWIP_MEM_ALLOC_DECL_PROTECT()
|
||||
#define LWIP_MEM_ALLOC_PROTECT()
|
||||
#define LWIP_MEM_ALLOC_UNPROTECT()
|
||||
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
|
||||
|
||||
/**
|
||||
* "Plug holes" by combining adjacent empty struct mems.
|
||||
* After this function is through, there should not exist
|
||||
|
@ -255,9 +284,7 @@ mem_init(void)
|
|||
/* initialize the lowest-free pointer to the start of the heap */
|
||||
lfree = (struct mem *)ram;
|
||||
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.avail = MEM_SIZE_ALIGNED;
|
||||
#endif /* MEM_STATS */
|
||||
MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -270,6 +297,7 @@ void
|
|||
mem_free(void *rmem)
|
||||
{
|
||||
struct mem *mem;
|
||||
LWIP_MEM_FREE_DECL_PROTECT();
|
||||
|
||||
if (rmem == NULL) {
|
||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | 2, ("mem_free(p == NULL) was called.\n"));
|
||||
|
@ -277,20 +305,20 @@ mem_free(void *rmem)
|
|||
}
|
||||
LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
|
||||
|
||||
/* protect the heap from concurrent access */
|
||||
sys_arch_sem_wait(mem_sem, 0);
|
||||
|
||||
LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
|
||||
(u8_t *)rmem < (u8_t *)ram_end);
|
||||
|
||||
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
|
||||
#if MEM_STATS
|
||||
++lwip_stats.mem.err;
|
||||
#endif /* MEM_STATS */
|
||||
sys_sem_signal(mem_sem);
|
||||
/* protect mem stats from concurrent access */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
MEM_STATS_INC(illegal);
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
return;
|
||||
}
|
||||
/* protect the heap from concurrent access */
|
||||
LWIP_MEM_FREE_PROTECT();
|
||||
/* Get the corresponding struct mem ... */
|
||||
mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
|
||||
/* ... which has to be in a used state ... */
|
||||
|
@ -303,13 +331,14 @@ mem_free(void *rmem)
|
|||
lfree = mem;
|
||||
}
|
||||
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
|
||||
#endif /* MEM_STATS */
|
||||
MEM_STATS_DEC_USED(used, mem->next - ((u8_t *)mem - ram));
|
||||
|
||||
/* finally, see if prev or next are free also */
|
||||
plug_holes(mem);
|
||||
sys_sem_signal(mem_sem);
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
mem_free_count = 1;
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
LWIP_MEM_FREE_UNPROTECT();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -321,6 +350,8 @@ mem_free(void *rmem)
|
|||
* @param newsize required size after shrinking (needs to be smaller than or
|
||||
* equal to the previous size)
|
||||
* @return for compatibility reasons: is always == rmem, at the moment
|
||||
* or NULL if newsize is > old size, in which case rmem is NOT touched
|
||||
* or freed!
|
||||
*/
|
||||
void *
|
||||
mem_realloc(void *rmem, mem_size_t newsize)
|
||||
|
@ -328,6 +359,8 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
|||
mem_size_t size;
|
||||
mem_size_t ptr, ptr2;
|
||||
struct mem *mem, *mem2;
|
||||
/* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */
|
||||
LWIP_MEM_FREE_DECL_PROTECT();
|
||||
|
||||
/* Expand the size of the allocated memory region so that we can
|
||||
adjust for alignment. */
|
||||
|
@ -346,7 +379,12 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
|||
(u8_t *)rmem < (u8_t *)ram_end);
|
||||
|
||||
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
|
||||
/* protect mem stats from concurrent access */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
MEM_STATS_INC(illegal);
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
return rmem;
|
||||
}
|
||||
/* Get the corresponding struct mem ... */
|
||||
|
@ -366,11 +404,9 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
|||
}
|
||||
|
||||
/* protect the heap from concurrent access */
|
||||
sys_arch_sem_wait(mem_sem, 0);
|
||||
LWIP_MEM_FREE_PROTECT();
|
||||
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.used -= (size - newsize);
|
||||
#endif /* MEM_STATS */
|
||||
MEM_STATS_DEC_USED(used, (size - newsize));
|
||||
|
||||
mem2 = (struct mem *)&ram[mem->next];
|
||||
if(mem2->used == 0) {
|
||||
|
@ -426,7 +462,10 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
|||
-> don't do anyhting.
|
||||
-> the remaining space stays unused since it is too small
|
||||
} */
|
||||
sys_sem_signal(mem_sem);
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
mem_free_count = 1;
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
LWIP_MEM_FREE_UNPROTECT();
|
||||
return rmem;
|
||||
}
|
||||
|
||||
|
@ -444,6 +483,10 @@ mem_malloc(mem_size_t size)
|
|||
{
|
||||
mem_size_t ptr, ptr2;
|
||||
struct mem *mem, *mem2;
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
u8_t local_mem_free_count = 0;
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
LWIP_MEM_ALLOC_DECL_PROTECT();
|
||||
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
|
@ -464,88 +507,101 @@ mem_malloc(mem_size_t size)
|
|||
|
||||
/* protect the heap from concurrent access */
|
||||
sys_arch_sem_wait(mem_sem, 0);
|
||||
LWIP_MEM_ALLOC_PROTECT();
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
/* run as long as a mem_free disturbed mem_malloc */
|
||||
do {
|
||||
local_mem_free_count = 0;
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
|
||||
/* Scan through the heap searching for a free block that is big enough,
|
||||
* beginning with the lowest free block.
|
||||
*/
|
||||
for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
|
||||
ptr = ((struct mem *)&ram[ptr])->next) {
|
||||
mem = (struct mem *)&ram[ptr];
|
||||
|
||||
if ((!mem->used) &&
|
||||
(mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
|
||||
/* mem is not used and at least perfect fit is possible:
|
||||
* mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
|
||||
|
||||
if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
|
||||
/* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
|
||||
* at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
|
||||
* -> split large block, create empty remainder,
|
||||
* remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
|
||||
* mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
|
||||
* struct mem would fit in but no data between mem2 and mem2->next
|
||||
* @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
|
||||
* region that couldn't hold data, but when mem->next gets freed,
|
||||
* the 2 regions would be combined, resulting in more free memory
|
||||
*/
|
||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
|
||||
/* create mem2 struct */
|
||||
mem2 = (struct mem *)&ram[ptr2];
|
||||
mem2->used = 0;
|
||||
mem2->next = mem->next;
|
||||
mem2->prev = ptr;
|
||||
/* and insert it between mem and mem->next */
|
||||
mem->next = ptr2;
|
||||
mem->used = 1;
|
||||
|
||||
if (mem2->next != MEM_SIZE_ALIGNED) {
|
||||
((struct mem *)&ram[mem2->next])->prev = ptr2;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
#endif /* MEM_STATS */
|
||||
} else {
|
||||
/* (a mem2 struct does no fit into the user data space of mem and mem->next will always
|
||||
* be used at this point: if not we have 2 unused structs in a row, plug_holes should have
|
||||
* take care of this).
|
||||
* -> near fit or excact fit: do not split, no mem2 creation
|
||||
* also can't move mem->next directly behind mem, since mem->next
|
||||
* will always be used at this point!
|
||||
*/
|
||||
mem->used = 1;
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.used += mem->next - ((u8_t *)mem - ram);
|
||||
if (lwip_stats.mem.max < lwip_stats.mem.used) {
|
||||
lwip_stats.mem.max = lwip_stats.mem.used;
|
||||
}
|
||||
#endif /* MEM_STATS */
|
||||
/* Scan through the heap searching for a free block that is big enough,
|
||||
* beginning with the lowest free block.
|
||||
*/
|
||||
for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
|
||||
ptr = ((struct mem *)&ram[ptr])->next) {
|
||||
mem = (struct mem *)&ram[ptr];
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
mem_free_count = 0;
|
||||
LWIP_MEM_ALLOC_UNPROTECT();
|
||||
/* allow mem_free to run */
|
||||
LWIP_MEM_ALLOC_PROTECT();
|
||||
if (mem_free_count != 0) {
|
||||
local_mem_free_count = mem_free_count;
|
||||
}
|
||||
mem_free_count = 0;
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
|
||||
if (mem == lfree) {
|
||||
/* Find next free block after mem and update lowest free pointer */
|
||||
while (lfree->used && lfree != ram_end) {
|
||||
lfree = (struct mem *)&ram[lfree->next];
|
||||
if ((!mem->used) &&
|
||||
(mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
|
||||
/* mem is not used and at least perfect fit is possible:
|
||||
* mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
|
||||
|
||||
if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
|
||||
/* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
|
||||
* at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
|
||||
* -> split large block, create empty remainder,
|
||||
* remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
|
||||
* mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
|
||||
* struct mem would fit in but no data between mem2 and mem2->next
|
||||
* @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
|
||||
* region that couldn't hold data, but when mem->next gets freed,
|
||||
* the 2 regions would be combined, resulting in more free memory
|
||||
*/
|
||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
|
||||
/* create mem2 struct */
|
||||
mem2 = (struct mem *)&ram[ptr2];
|
||||
mem2->used = 0;
|
||||
mem2->next = mem->next;
|
||||
mem2->prev = ptr;
|
||||
/* and insert it between mem and mem->next */
|
||||
mem->next = ptr2;
|
||||
mem->used = 1;
|
||||
|
||||
if (mem2->next != MEM_SIZE_ALIGNED) {
|
||||
((struct mem *)&ram[mem2->next])->prev = ptr2;
|
||||
}
|
||||
MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
|
||||
} else {
|
||||
/* (a mem2 struct does no fit into the user data space of mem and mem->next will always
|
||||
* be used at this point: if not we have 2 unused structs in a row, plug_holes should have
|
||||
* take care of this).
|
||||
* -> near fit or excact fit: do not split, no mem2 creation
|
||||
* also can't move mem->next directly behind mem, since mem->next
|
||||
* will always be used at this point!
|
||||
*/
|
||||
mem->used = 1;
|
||||
MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram));
|
||||
}
|
||||
LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
|
||||
}
|
||||
sys_sem_signal(mem_sem);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
|
||||
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
|
||||
(unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
|
||||
LWIP_ASSERT("mem_malloc: sanity check alignment",
|
||||
(((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
|
||||
|
||||
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
|
||||
if (mem == lfree) {
|
||||
/* Find next free block after mem and update lowest free pointer */
|
||||
while (lfree->used && lfree != ram_end) {
|
||||
LWIP_MEM_ALLOC_UNPROTECT();
|
||||
/* prevent high interrupt latency... */
|
||||
LWIP_MEM_ALLOC_PROTECT();
|
||||
lfree = (struct mem *)&ram[lfree->next];
|
||||
}
|
||||
LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
|
||||
}
|
||||
LWIP_MEM_ALLOC_UNPROTECT();
|
||||
sys_sem_signal(mem_sem);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
|
||||
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
|
||||
((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
|
||||
LWIP_ASSERT("mem_malloc: sanity check alignment",
|
||||
(((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
|
||||
|
||||
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
/* if we got interrupted by a mem_free, try again */
|
||||
} while(local_mem_free_count != 0);
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
|
||||
#if MEM_STATS
|
||||
++lwip_stats.mem.err;
|
||||
#endif /* MEM_STATS */
|
||||
MEM_STATS_INC(err);
|
||||
LWIP_MEM_ALLOC_UNPROTECT();
|
||||
sys_sem_signal(mem_sem);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
struct memp {
|
||||
struct memp *next;
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
|
@ -109,15 +111,23 @@ struct memp {
|
|||
* Elements form a linked list. */
|
||||
static struct memp *memp_tab[MEMP_MAX];
|
||||
|
||||
#else /* MEMP_MEM_MALLOC */
|
||||
|
||||
#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x))
|
||||
|
||||
#endif /* MEMP_MEM_MALLOC */
|
||||
|
||||
/** This array holds the element sizes of each pool. */
|
||||
#if !MEM_USE_POOLS
|
||||
#if !MEM_USE_POOLS && !MEMP_MEM_MALLOC
|
||||
static
|
||||
#endif
|
||||
const u16_t memp_sizes[MEMP_MAX] = {
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_ALIGN_SIZE(size),
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size),
|
||||
#include "lwip/memp_std.h"
|
||||
};
|
||||
|
||||
#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
/** This array holds the number of elements in each pool. */
|
||||
static const u16_t memp_num[MEMP_MAX] = {
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) (num),
|
||||
|
@ -183,7 +193,7 @@ memp_overflow_check_element(struct memp *p, u16_t memp_size)
|
|||
}
|
||||
#endif
|
||||
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
||||
m = (u8_t*)p + MEMP_SIZE + memp_size - MEMP_SANITY_REGION_AFTER_ALIGNED;
|
||||
m = (u8_t*)p + MEMP_SIZE + memp_size;
|
||||
for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
|
||||
if (m[k] != 0xcd) {
|
||||
LWIP_ASSERT("detected memp overflow!", 0);
|
||||
|
@ -208,7 +218,7 @@ memp_overflow_check_all(void)
|
|||
p = p;
|
||||
for (j = 0; j < memp_num[i]; ++j) {
|
||||
memp_overflow_check_element(p, memp_sizes[i]);
|
||||
p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i]);
|
||||
p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -232,10 +242,10 @@ memp_overflow_init(void)
|
|||
memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED);
|
||||
#endif
|
||||
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
||||
m = (u8_t*)p + MEMP_SIZE + memp_sizes[i] - MEMP_SANITY_REGION_AFTER_ALIGNED;
|
||||
m = (u8_t*)p + MEMP_SIZE + memp_sizes[i];
|
||||
memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED);
|
||||
#endif
|
||||
p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i]);
|
||||
p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -252,13 +262,12 @@ memp_init(void)
|
|||
struct memp *memp;
|
||||
u16_t i, j;
|
||||
|
||||
#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;
|
||||
lwip_stats.memp[i].avail = memp_num[i];
|
||||
MEMP_STATS_AVAIL(used, i, 0);
|
||||
MEMP_STATS_AVAIL(max, i, 0);
|
||||
MEMP_STATS_AVAIL(err, i, 0);
|
||||
MEMP_STATS_AVAIL(avail, i, memp_num[i]);
|
||||
}
|
||||
#endif /* MEMP_STATS */
|
||||
|
||||
memp = LWIP_MEM_ALIGN(memp_memory);
|
||||
/* for every pool: */
|
||||
|
@ -268,7 +277,11 @@ memp_init(void)
|
|||
for (j = 0; j < memp_num[i]; ++j) {
|
||||
memp->next = memp_tab[i];
|
||||
memp_tab[i] = memp;
|
||||
memp = (struct memp *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i]);
|
||||
memp = (struct memp *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i]
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
+ MEMP_SANITY_REGION_AFTER_ALIGNED
|
||||
#endif
|
||||
);
|
||||
}
|
||||
}
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
|
@ -315,20 +328,13 @@ memp_malloc_fn(memp_t type, const char* file, const int line)
|
|||
memp->file = file;
|
||||
memp->line = line;
|
||||
#endif /* MEMP_OVERFLOW_CHECK */
|
||||
#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 */
|
||||
MEMP_STATS_INC_USED(used, type);
|
||||
LWIP_ASSERT("memp_malloc: memp properly aligned",
|
||||
((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
|
||||
memp = (struct memp*)((u8_t*)memp + MEMP_SIZE);
|
||||
} else {
|
||||
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
|
||||
#if MEMP_STATS
|
||||
++lwip_stats.memp[type].err;
|
||||
#endif /* MEMP_STATS */
|
||||
MEMP_STATS_INC(err, type);
|
||||
}
|
||||
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
|
@ -365,9 +371,7 @@ memp_free(memp_t type, void *mem)
|
|||
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
||||
#endif /* MEMP_OVERFLOW_CHECK */
|
||||
|
||||
#if MEMP_STATS
|
||||
lwip_stats.memp[type].used--;
|
||||
#endif /* MEMP_STATS */
|
||||
MEMP_STATS_DEC(used, type);
|
||||
|
||||
memp->next = memp_tab[type];
|
||||
memp_tab[type] = memp;
|
||||
|
@ -378,3 +382,5 @@ memp_free(memp_t type, void *mem)
|
|||
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
}
|
||||
|
||||
#endif /* MEMP_MEM_MALLOC */
|
||||
|
|
|
@ -45,6 +45,12 @@
|
|||
#include "lwip/snmp.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "netif/etharp.h"
|
||||
#if ENABLE_LOOPBACK
|
||||
#include "lwip/sys.h"
|
||||
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
#include "lwip/tcpip.h"
|
||||
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
|
||||
#if LWIP_NETIF_STATUS_CALLBACK
|
||||
#define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }
|
||||
|
@ -106,6 +112,10 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
|||
#if LWIP_IGMP
|
||||
netif->igmp_mac_filter = NULL;
|
||||
#endif /* LWIP_IGMP */
|
||||
#if ENABLE_LOOPBACK
|
||||
netif->loop_first = NULL;
|
||||
netif->loop_last = NULL;
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
|
||||
/* remember netif specific state information data */
|
||||
netif->state = state;
|
||||
|
@ -114,6 +124,9 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
|||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
|
||||
netif->loop_cnt_current = 0;
|
||||
#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
|
||||
|
||||
netif_set_addr(netif, ipaddr, netmask, gw);
|
||||
|
||||
|
@ -388,13 +401,9 @@ void netif_set_up(struct netif *netif)
|
|||
NETIF_STATUS_CALLBACK(netif);
|
||||
|
||||
#if LWIP_ARP
|
||||
/** 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.
|
||||
*/
|
||||
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
|
||||
if (netif->flags & NETIF_FLAG_ETHARP) {
|
||||
etharp_query(netif, &(netif->ip_addr), NULL);
|
||||
etharp_gratuitous(netif);
|
||||
}
|
||||
#endif /* LWIP_ARP */
|
||||
|
||||
|
@ -451,13 +460,9 @@ void netif_set_link_up(struct netif *netif )
|
|||
netif->flags |= NETIF_FLAG_LINK_UP;
|
||||
|
||||
#if LWIP_ARP
|
||||
/** 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.
|
||||
*/
|
||||
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
|
||||
if (netif->flags & NETIF_FLAG_ETHARP) {
|
||||
etharp_query(netif, &(netif->ip_addr), NULL);
|
||||
etharp_gratuitous(netif);
|
||||
}
|
||||
#endif /* LWIP_ARP */
|
||||
|
||||
|
@ -493,7 +498,158 @@ u8_t netif_is_link_up(struct netif *netif)
|
|||
*/
|
||||
void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif ))
|
||||
{
|
||||
if ( netif )
|
||||
netif->link_callback = link_callback;
|
||||
if (netif) {
|
||||
netif->link_callback = link_callback;
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_NETIF_LINK_CALLBACK */
|
||||
|
||||
#if ENABLE_LOOPBACK
|
||||
/**
|
||||
* Send an IP packet to be received on the same netif (loopif-like).
|
||||
* The pbuf is simply copied and handed back to netif->input.
|
||||
* In multithreaded mode, this is done directly since netif->input must put
|
||||
* the packet on a queue.
|
||||
* In callback mode, the packet is put on an internal queue and is fed to
|
||||
* netif->input by netif_poll().
|
||||
*
|
||||
* @param netif the lwip network interface structure
|
||||
* @param p the (IP) packet to 'send'
|
||||
* @param ipaddr the ip address to send the packet to (not used)
|
||||
* @return ERR_OK if the packet has been sent
|
||||
* ERR_MEM if the pbuf used to copy the packet couldn't be allocated
|
||||
*/
|
||||
err_t
|
||||
netif_loop_output(struct netif *netif, struct pbuf *p,
|
||||
struct ip_addr *ipaddr)
|
||||
{
|
||||
struct pbuf *r;
|
||||
err_t err;
|
||||
struct pbuf *last;
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
u8_t clen = 0;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
LWIP_UNUSED_ARG(ipaddr);
|
||||
|
||||
/* Allocate a new pbuf */
|
||||
r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
|
||||
if (r == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
clen = pbuf_clen(r);
|
||||
/* check for overflow or too many pbuf on queue */
|
||||
if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
|
||||
((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
|
||||
pbuf_free(r);
|
||||
r = NULL;
|
||||
return ERR_MEM;
|
||||
}
|
||||
netif->loop_cnt_current += clen;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
|
||||
/* Copy the whole pbuf queue p into the single pbuf r */
|
||||
if ((err = pbuf_copy(r, p)) != ERR_OK) {
|
||||
pbuf_free(r);
|
||||
r = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Put the packet on a linked list which gets emptied through calling
|
||||
netif_poll(). */
|
||||
|
||||
/* let last point to the last pbuf in chain r */
|
||||
for (last = r; last->next != NULL; last = last->next);
|
||||
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
if(netif->loop_first != NULL) {
|
||||
LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
|
||||
netif->loop_last->next = r;
|
||||
netif->loop_last = last;
|
||||
} else {
|
||||
netif->loop_first = r;
|
||||
netif->loop_last = last;
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
||||
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
/* For multithreading environment, schedule a call to netif_poll */
|
||||
tcpip_callback((void (*)(void *))(netif_poll), netif);
|
||||
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call netif_poll() in the main loop of your application. This is to prevent
|
||||
* reentering non-reentrant functions like tcp_input(). Packets passed to
|
||||
* netif_loop_output() are put on a list that is passed to netif->input() by
|
||||
* netif_poll().
|
||||
*/
|
||||
void
|
||||
netif_poll(struct netif *netif)
|
||||
{
|
||||
struct pbuf *in;
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
|
||||
do {
|
||||
/* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
in = netif->loop_first;
|
||||
if(in != NULL) {
|
||||
struct pbuf *in_end = in;
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
u8_t clen = pbuf_clen(in);
|
||||
/* adjust the number of pbufs on queue */
|
||||
LWIP_ASSERT("netif->loop_cnt_current underflow",
|
||||
((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
|
||||
netif->loop_cnt_current -= clen;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
while(in_end->len != in_end->tot_len) {
|
||||
LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
|
||||
in_end = in_end->next;
|
||||
}
|
||||
/* 'in_end' now points to the last pbuf from 'in' */
|
||||
if(in_end == netif->loop_last) {
|
||||
/* this was the last pbuf in the list */
|
||||
netif->loop_first = netif->loop_last = NULL;
|
||||
} else {
|
||||
/* pop the pbuf off the list */
|
||||
netif->loop_first = in_end->next;
|
||||
LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
|
||||
}
|
||||
/* De-queue the pbuf from its successors on the 'loop_' list. */
|
||||
in_end->next = NULL;
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
||||
if(in != NULL) {
|
||||
/* loopback packets are always IP packets! */
|
||||
if(ip_input(in, netif) != ERR_OK) {
|
||||
pbuf_free(in);
|
||||
}
|
||||
/* Don't reference the packet any more! */
|
||||
in = NULL;
|
||||
}
|
||||
/* go on while there is a packet on the list */
|
||||
} while(netif->loop_first != NULL);
|
||||
}
|
||||
|
||||
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
/**
|
||||
* Calls netif_poll() for every netif on the netif_list.
|
||||
*/
|
||||
void
|
||||
netif_poll_all(void)
|
||||
{
|
||||
struct netif *netif = netif_list;
|
||||
/* loop through netifs */
|
||||
while (netif != NULL) {
|
||||
netif_poll(netif);
|
||||
/* proceed to next network interface */
|
||||
netif = netif->next;
|
||||
}
|
||||
}
|
||||
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
|
|
|
@ -70,6 +70,9 @@
|
|||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "arch/perf.h"
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
#include "lwip/tcp.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -78,6 +81,42 @@
|
|||
aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
|
||||
#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
|
||||
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
#define ALLOC_POOL_PBUF(p) do { (p) = alloc_pool_pbuf(); } while (0)
|
||||
#else
|
||||
#define ALLOC_POOL_PBUF(p) do { (p) = memp_malloc(MEMP_PBUF_POOL); } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
/**
|
||||
* Attempt to reclaim some memory from queued out-of-sequence TCP segments
|
||||
* if we run out of pool pbufs. It's better to give priority to new packets
|
||||
* if we're running out.
|
||||
*
|
||||
* @return the allocated pbuf.
|
||||
*/
|
||||
static struct pbuf *
|
||||
alloc_pool_pbuf(void)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
struct pbuf *p;
|
||||
|
||||
retry:
|
||||
p = memp_malloc(MEMP_PBUF_POOL);
|
||||
if (NULL == p) {
|
||||
for (pcb=tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
|
||||
if (NULL != pcb->ooseq) {
|
||||
tcp_segs_free(pcb->ooseq);
|
||||
pcb->ooseq = NULL;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
||||
/**
|
||||
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
|
||||
*
|
||||
|
@ -142,7 +181,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
|||
switch (type) {
|
||||
case PBUF_POOL:
|
||||
/* allocate head of pbuf chain into p */
|
||||
p = memp_malloc(MEMP_PBUF_POOL);
|
||||
ALLOC_POOL_PBUF(p);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
|
@ -161,6 +200,8 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
|||
LWIP_ASSERT("check p->payload + p->len does not overflow pbuf",
|
||||
((u8_t*)p->payload + p->len <=
|
||||
(u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED));
|
||||
LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT",
|
||||
(PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 );
|
||||
/* set reference count (needed here in case we fail) */
|
||||
p->ref = 1;
|
||||
|
||||
|
@ -172,7 +213,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
|||
rem_len = length - p->len;
|
||||
/* any remaining pbufs to be allocated? */
|
||||
while (rem_len > 0) {
|
||||
q = memp_malloc(MEMP_PBUF_POOL);
|
||||
ALLOC_POOL_PBUF(q);
|
||||
if (q == NULL) {
|
||||
/* free chain so far allocated */
|
||||
pbuf_free(p);
|
||||
|
@ -272,6 +313,7 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
|
|||
u16_t rem_len; /* remaining length */
|
||||
s32_t grow;
|
||||
|
||||
LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL);
|
||||
LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL ||
|
||||
p->type == PBUF_ROM ||
|
||||
p->type == PBUF_RAM ||
|
||||
|
@ -299,6 +341,7 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
|
|||
q->tot_len += (u16_t)grow;
|
||||
/* proceed to next pbuf in chain */
|
||||
q = q->next;
|
||||
LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL);
|
||||
}
|
||||
/* we have now reached the new last pbuf (in q) */
|
||||
/* rem_len == desired length for pbuf q */
|
||||
|
@ -667,8 +710,8 @@ pbuf_dechain(struct pbuf *p)
|
|||
*
|
||||
* @note Only one packet is copied, no packet queue!
|
||||
*
|
||||
* @param p_to pbuf source of the copy
|
||||
* @param p_from pbuf destination of the copy
|
||||
* @param p_to pbuf destination of the copy
|
||||
* @param p_from pbuf source of the copy
|
||||
*
|
||||
* @return ERR_OK if pbuf was copied
|
||||
* ERR_ARG if one of the pbufs is NULL or p_to is not big
|
||||
|
@ -735,8 +778,10 @@ pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
|
|||
*
|
||||
* @param buf the pbuf from which to copy data
|
||||
* @param dataptr the application supplied buffer
|
||||
* @param len length of data to copy (dataptr must be big enough)
|
||||
* @param len length of data to copy (dataptr must be big enough). No more
|
||||
* than buf->tot_len will be copied, irrespective of len
|
||||
* @param offset offset into the packet buffer from where to begin copying len bytes
|
||||
* @return the number of bytes copied, or 0 on failure
|
||||
*/
|
||||
u16_t
|
||||
pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
||||
|
@ -746,8 +791,8 @@ pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
|||
u16_t buf_copy_len;
|
||||
u16_t copied_total = 0;
|
||||
|
||||
LWIP_ERROR("netbuf_copy_partial: invalid buf", (buf != NULL), return 0;);
|
||||
LWIP_ERROR("netbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);
|
||||
LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;);
|
||||
LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);
|
||||
|
||||
left = 0;
|
||||
|
||||
|
@ -775,3 +820,76 @@ pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
|||
}
|
||||
return copied_total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy application supplied data into a pbuf.
|
||||
* This function can only be used to copy the equivalent of buf->tot_len data.
|
||||
*
|
||||
* @param buf pbuf to fill with data
|
||||
* @param dataptr application supplied data buffer
|
||||
* @param len length of the application supplied data buffer
|
||||
*
|
||||
* @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough
|
||||
*/
|
||||
err_t
|
||||
pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
|
||||
{
|
||||
struct pbuf *p;
|
||||
u16_t buf_copy_len;
|
||||
u16_t total_copy_len = len;
|
||||
u16_t copied_total = 0;
|
||||
|
||||
LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;);
|
||||
LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;);
|
||||
|
||||
if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) {
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
|
||||
for(p = buf; total_copy_len != 0; p = p->next) {
|
||||
LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL);
|
||||
buf_copy_len = total_copy_len;
|
||||
if (buf_copy_len > p->len) {
|
||||
/* this pbuf cannot hold all remaining data */
|
||||
buf_copy_len = p->len;
|
||||
}
|
||||
/* copy the necessary parts of the buffer */
|
||||
MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len);
|
||||
total_copy_len -= buf_copy_len;
|
||||
copied_total += buf_copy_len;
|
||||
}
|
||||
LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single pbuf out of a queue of pbufs.
|
||||
*
|
||||
* @remark: The source pbuf 'p' is not freed by this function because that can
|
||||
* be illegal in some places!
|
||||
*
|
||||
* @param p the source pbuf
|
||||
* @param layer pbuf_layer of the new pbuf
|
||||
*
|
||||
* @return a new, single pbuf (p->next is NULL)
|
||||
* or the old pbuf if allocation fails
|
||||
*/
|
||||
struct pbuf*
|
||||
pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
|
||||
{
|
||||
struct pbuf *q;
|
||||
err_t err;
|
||||
if (p->next == NULL) {
|
||||
return p;
|
||||
}
|
||||
q = pbuf_alloc(layer, p->tot_len, PBUF_RAM);
|
||||
if (q == NULL) {
|
||||
/* @todo: what do we do now? */
|
||||
return p;
|
||||
}
|
||||
err = pbuf_copy(q, p);
|
||||
LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
|
||||
pbuf_free(p);
|
||||
return q;
|
||||
}
|
||||
|
|
|
@ -93,24 +93,29 @@ raw_input(struct pbuf *p, struct netif *inp)
|
|||
/* 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;
|
||||
if (prev != NULL) {
|
||||
/* move the pcb to the front of raw_pcbs so that is
|
||||
found faster next time */
|
||||
prev->next = pcb->next;
|
||||
pcb->next = raw_pcbs;
|
||||
raw_pcbs = pcb;
|
||||
#if IP_SOF_BROADCAST_RECV
|
||||
/* broadcast filter? */
|
||||
if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(&(iphdr->dest), inp))
|
||||
#endif /* IP_SOF_BROADCAST_RECV */
|
||||
{
|
||||
/* receive callback function available? */
|
||||
if (pcb->recv != NULL) {
|
||||
/* the receive callback function did not eat the packet? */
|
||||
if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0) {
|
||||
/* receive function ate the packet */
|
||||
p = NULL;
|
||||
eaten = 1;
|
||||
if (prev != NULL) {
|
||||
/* move the pcb to the front of raw_pcbs so that is
|
||||
found faster next time */
|
||||
prev->next = pcb->next;
|
||||
pcb->next = raw_pcbs;
|
||||
raw_pcbs = pcb;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* no receive callback function was set for this raw PCB */
|
||||
}
|
||||
/* no receive callback function was set for this raw PCB */
|
||||
/* drop the packet */
|
||||
}
|
||||
prev = pcb;
|
||||
|
@ -238,6 +243,18 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
|||
return ERR_RTE;
|
||||
}
|
||||
|
||||
#if IP_SOF_BROADCAST
|
||||
/* broadcast filter? */
|
||||
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif) ) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
}
|
||||
return ERR_VAL;
|
||||
}
|
||||
#endif /* IP_SOF_BROADCAST */
|
||||
|
||||
if (ip_addr_isany(&pcb->local_ip)) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
src_ip = &(netif->ip_addr);
|
||||
|
|
|
@ -2205,10 +2205,10 @@ system_get_value(struct obj_def *od, u16_t len, void *value)
|
|||
switch (id)
|
||||
{
|
||||
case 1: /* sysDescr */
|
||||
ocstrncpy(value,sysdescr_ptr,len);
|
||||
ocstrncpy(value,sysdescr_ptr, len);
|
||||
break;
|
||||
case 2: /* sysObjectID */
|
||||
objectidncpy((s32_t*)value,(s32_t*)sysobjid.id,len / sizeof(s32_t));
|
||||
objectidncpy((s32_t*)value, (s32_t*)sysobjid.id, (u8_t)(len / sizeof(s32_t)));
|
||||
break;
|
||||
case 3: /* sysUpTime */
|
||||
{
|
||||
|
@ -2606,7 +2606,7 @@ ifentry_get_value(struct obj_def *od, u16_t len, void *value)
|
|||
}
|
||||
break;
|
||||
case 22: /* ifSpecific */
|
||||
objectidncpy((s32_t*)value,(s32_t*)ifspecific.id,len / sizeof(s32_t));
|
||||
objectidncpy((s32_t*)value, (s32_t*)ifspecific.id, (u8_t)(len / sizeof(s32_t)));
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
@ -3342,7 +3342,7 @@ ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value)
|
|||
}
|
||||
break;
|
||||
case 13: /* ipRouteInfo */
|
||||
objectidncpy((s32_t*)value,(s32_t*)iprouteinfo.id,len / sizeof(s32_t));
|
||||
objectidncpy((s32_t*)value, (s32_t*)iprouteinfo.id, (u8_t)(len / sizeof(s32_t)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -589,9 +589,10 @@ snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
|||
{
|
||||
struct mib_external_node *en;
|
||||
|
||||
/** set_value_a() @todo: use reply value?? */
|
||||
/** set_value_a() */
|
||||
en = msg_ps->ext_mib_node;
|
||||
en->set_value_a(request_id, &msg_ps->ext_object_def, 0, NULL);
|
||||
en->set_value_a(request_id, &msg_ps->ext_object_def,
|
||||
msg_ps->vb_ptr->value_len, msg_ps->vb_ptr->value);
|
||||
|
||||
/** @todo use set_value_pc() if toobig */
|
||||
msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;
|
||||
|
@ -1145,7 +1146,7 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_
|
|||
derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
|
||||
if ((derr != ERR_OK) ||
|
||||
(type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)) ||
|
||||
(len <= 0) || (len > vb_len))
|
||||
(len == 0) || (len > vb_len))
|
||||
{
|
||||
snmp_inc_snmpinasnparseerrs();
|
||||
/* free varbinds (if available) */
|
||||
|
|
|
@ -54,7 +54,6 @@ stats_display_proto(struct stats_proto *proto, char *name)
|
|||
{
|
||||
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
||||
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit));
|
||||
LWIP_PLATFORM_DIAG(("rexmit: %"STAT_COUNTER_F"\n\t", proto->rexmit));
|
||||
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv));
|
||||
LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw));
|
||||
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop));
|
||||
|
@ -68,6 +67,7 @@ stats_display_proto(struct stats_proto *proto, char *name)
|
|||
LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit));
|
||||
}
|
||||
|
||||
#if IGMP_STATS
|
||||
void
|
||||
stats_display_igmp(struct stats_igmp *igmp)
|
||||
{
|
||||
|
@ -82,7 +82,9 @@ stats_display_igmp(struct stats_igmp *igmp)
|
|||
LWIP_PLATFORM_DIAG(("report_rxed: %"STAT_COUNTER_F"\n\t", igmp->report_rxed));
|
||||
LWIP_PLATFORM_DIAG(("group_query_rxed: %"STAT_COUNTER_F"\n", igmp->group_query_rxed));
|
||||
}
|
||||
#endif /* IGMP_STATS */
|
||||
|
||||
#if MEM_STATS || MEMP_STATS
|
||||
void
|
||||
stats_display_mem(struct stats_mem *mem, char *name)
|
||||
{
|
||||
|
@ -93,48 +95,53 @@ stats_display_mem(struct stats_mem *mem, char *name)
|
|||
LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err));
|
||||
}
|
||||
|
||||
void
|
||||
stats_display(void)
|
||||
{
|
||||
#if MEMP_STATS
|
||||
s16_t i;
|
||||
void
|
||||
stats_display_memp(struct stats_mem *mem, int index)
|
||||
{
|
||||
char * memp_names[] = {
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) desc,
|
||||
#include "lwip/memp_std.h"
|
||||
};
|
||||
#endif
|
||||
#if LINK_STATS
|
||||
stats_display_proto(&lwip_stats.link, "LINK");
|
||||
#endif
|
||||
#if ETHARP_STATS
|
||||
stats_display_proto(&lwip_stats.etharp, "ETHARP");
|
||||
#endif
|
||||
#if IPFRAG_STATS
|
||||
stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG");
|
||||
#endif
|
||||
#if IP_STATS
|
||||
stats_display_proto(&lwip_stats.ip, "IP");
|
||||
#endif
|
||||
#if ICMP_STATS
|
||||
stats_display_proto(&lwip_stats.icmp, "ICMP");
|
||||
#endif
|
||||
#if IGMP_STATS
|
||||
stats_display_igmp(&lwip_stats.igmp);
|
||||
#endif
|
||||
#if UDP_STATS
|
||||
stats_display_proto(&lwip_stats.udp, "UDP");
|
||||
#endif
|
||||
#if TCP_STATS
|
||||
stats_display_proto(&lwip_stats.tcp, "TCP");
|
||||
#endif
|
||||
#if MEM_STATS
|
||||
stats_display_mem(&lwip_stats.mem, "HEAP");
|
||||
#endif
|
||||
#if MEMP_STATS
|
||||
for (i = 0; i < MEMP_MAX; i++) {
|
||||
stats_display_mem(&lwip_stats.memp[i], memp_names[i]);
|
||||
if(index < MEMP_MAX) {
|
||||
stats_display_mem(mem, memp_names[index]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* MEMP_STATS */
|
||||
#endif /* MEM_STATS || MEMP_STATS */
|
||||
|
||||
#if SYS_STATS
|
||||
void
|
||||
stats_display_sys(struct stats_sys *sys)
|
||||
{
|
||||
LWIP_PLATFORM_DIAG(("\nSYS\n\t"));
|
||||
LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used));
|
||||
LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max));
|
||||
LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err));
|
||||
LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used));
|
||||
LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max));
|
||||
LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err));
|
||||
}
|
||||
#endif /* SYS_STATS */
|
||||
|
||||
void
|
||||
stats_display(void)
|
||||
{
|
||||
s16_t i;
|
||||
|
||||
LINK_STATS_DISPLAY();
|
||||
ETHARP_STATS_DISPLAY();
|
||||
IPFRAG_STATS_DISPLAY();
|
||||
IP_STATS_DISPLAY();
|
||||
IGMP_STATS_DISPLAY();
|
||||
ICMP_STATS_DISPLAY();
|
||||
UDP_STATS_DISPLAY();
|
||||
TCP_STATS_DISPLAY();
|
||||
MEM_STATS_DISPLAY();
|
||||
for (i = 0; i < MEMP_MAX; i++) {
|
||||
MEMP_STATS_DISPLAY(i);
|
||||
}
|
||||
SYS_STATS_DISPLAY();
|
||||
}
|
||||
#endif /* LWIP_STATS_DISPLAY */
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ struct sswt_cb
|
|||
void
|
||||
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
|
||||
{
|
||||
u32_t time;
|
||||
u32_t time_needed;
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *tmptimeout;
|
||||
sys_timeout_handler h;
|
||||
|
@ -76,18 +76,18 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
|
|||
|
||||
if (!timeouts || !timeouts->next) {
|
||||
UNLOCK_TCPIP_CORE();
|
||||
time = sys_arch_mbox_fetch(mbox, msg, 0);
|
||||
time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
|
||||
LOCK_TCPIP_CORE();
|
||||
} else {
|
||||
if (timeouts->next->time > 0) {
|
||||
UNLOCK_TCPIP_CORE();
|
||||
time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
|
||||
time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
|
||||
LOCK_TCPIP_CORE();
|
||||
} else {
|
||||
time = SYS_ARCH_TIMEOUT;
|
||||
time_needed = SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
if (time == SYS_ARCH_TIMEOUT) {
|
||||
if (time_needed == SYS_ARCH_TIMEOUT) {
|
||||
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
|
||||
could be fetched. We should now call the timeout handler and
|
||||
deallocate the memory allocated for the timeout. */
|
||||
|
@ -107,8 +107,8 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
|
|||
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
|
||||
occured. The time variable is set to the number of
|
||||
milliseconds we waited for the message. */
|
||||
if (time < timeouts->next->time) {
|
||||
timeouts->next->time -= time;
|
||||
if (time_needed < timeouts->next->time) {
|
||||
timeouts->next->time -= time_needed;
|
||||
} else {
|
||||
timeouts->next->time = 0;
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
|
|||
void
|
||||
sys_sem_wait(sys_sem_t sem)
|
||||
{
|
||||
u32_t time;
|
||||
u32_t time_needed;
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *tmptimeout;
|
||||
sys_timeout_handler h;
|
||||
|
@ -139,12 +139,12 @@ sys_sem_wait(sys_sem_t sem)
|
|||
sys_arch_sem_wait(sem, 0);
|
||||
} else {
|
||||
if (timeouts->next->time > 0) {
|
||||
time = sys_arch_sem_wait(sem, timeouts->next->time);
|
||||
time_needed = sys_arch_sem_wait(sem, timeouts->next->time);
|
||||
} else {
|
||||
time = SYS_ARCH_TIMEOUT;
|
||||
time_needed = SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
if (time == SYS_ARCH_TIMEOUT) {
|
||||
if (time_needed == SYS_ARCH_TIMEOUT) {
|
||||
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
|
||||
could be fetched. We should now call the timeout handler and
|
||||
deallocate the memory allocated for the timeout. */
|
||||
|
@ -164,8 +164,8 @@ sys_sem_wait(sys_sem_t sem)
|
|||
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
|
||||
occured. The time variable is set to the number of
|
||||
milliseconds we waited for the message. */
|
||||
if (time < timeouts->next->time) {
|
||||
timeouts->next->time -= time;
|
||||
if (time_needed < timeouts->next->time) {
|
||||
timeouts->next->time -= time_needed;
|
||||
} else {
|
||||
timeouts->next->time = 0;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "lwip/memp.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/debug.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -186,14 +187,15 @@ tcp_close(struct tcp_pcb *pcb)
|
|||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Abandons a connection and optionally sends a RST to the remote
|
||||
* host. Deletes the local protocol control block. This is done when
|
||||
* a connection is killed because of shortage of memory.
|
||||
*
|
||||
* @param pcb the tcp_pcb to abort
|
||||
* @param reset boolean to indicate whether a reset should be sent
|
||||
*/
|
||||
void
|
||||
tcp_abort(struct tcp_pcb *pcb)
|
||||
tcp_abandon(struct tcp_pcb *pcb, int reset)
|
||||
{
|
||||
u32_t seqno, ackno;
|
||||
u16_t remote_port, local_port;
|
||||
|
@ -235,8 +237,10 @@ tcp_abort(struct tcp_pcb *pcb)
|
|||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abort: sending RST\n"));
|
||||
tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
|
||||
if (reset) {
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
|
||||
tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,7 +262,7 @@ tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||
{
|
||||
struct tcp_pcb *cpcb;
|
||||
|
||||
LWIP_ERROR("tcp_connect: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
|
||||
LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
|
||||
|
||||
if (port == 0) {
|
||||
port = tcp_new_port();
|
||||
|
@ -380,6 +384,33 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
|||
return (struct tcp_pcb *)lpcb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state that tracks the available window space to advertise.
|
||||
*
|
||||
* Returns how much extra window would be advertised if we sent an
|
||||
* update now.
|
||||
*/
|
||||
u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb)
|
||||
{
|
||||
u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd;
|
||||
|
||||
if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + pcb->mss)) {
|
||||
/* we can advertise more window */
|
||||
pcb->rcv_ann_wnd = pcb->rcv_wnd;
|
||||
return new_right_edge - pcb->rcv_ann_right_edge;
|
||||
} else {
|
||||
if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) {
|
||||
/* Can happen due to other end sending out of advertised window,
|
||||
* but within actual available (but not yet advertised) window */
|
||||
pcb->rcv_ann_wnd = 0;
|
||||
} else {
|
||||
/* keep the right edge of window constant */
|
||||
pcb->rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function should be called by the application when it has
|
||||
* processed the data. The purpose is to advertise a larger window
|
||||
|
@ -391,40 +422,23 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
|
|||
void
|
||||
tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
||||
{
|
||||
if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
|
||||
pcb->rcv_wnd = TCP_WND;
|
||||
pcb->rcv_ann_wnd = TCP_WND;
|
||||
} else {
|
||||
pcb->rcv_wnd += len;
|
||||
if (pcb->rcv_wnd >= pcb->mss) {
|
||||
pcb->rcv_ann_wnd = pcb->rcv_wnd;
|
||||
}
|
||||
}
|
||||
int wnd_inflation;
|
||||
|
||||
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 */
|
||||
LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n",
|
||||
len <= 0xffff - pcb->rcv_wnd );
|
||||
|
||||
pcb->rcv_wnd += len;
|
||||
if (pcb->rcv_wnd > TCP_WND)
|
||||
pcb->rcv_wnd = TCP_WND;
|
||||
|
||||
wnd_inflation = tcp_update_rcv_ann_wnd(pcb);
|
||||
|
||||
/* If the change in the right edge of window is significant (default
|
||||
* watermark is TCP_WND/2), then send an explicit update now.
|
||||
* Otherwise wait for a packet to be sent in the normal course of
|
||||
* events (or more window to be available later) */
|
||||
if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD)
|
||||
tcp_ack_now(pcb);
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n",
|
||||
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
|
||||
|
@ -485,7 +499,6 @@ 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))
|
||||
{
|
||||
u32_t optdata;
|
||||
err_t ret;
|
||||
u32_t iss;
|
||||
|
||||
|
@ -508,8 +521,10 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
|
|||
pcb->snd_lbb = iss - 1;
|
||||
pcb->rcv_wnd = TCP_WND;
|
||||
pcb->rcv_ann_wnd = TCP_WND;
|
||||
pcb->rcv_ann_right_edge = pcb->rcv_nxt;
|
||||
pcb->snd_wnd = TCP_WND;
|
||||
/* The send MSS is updated when an MSS option is received. */
|
||||
/* As initial send MSS, we use TCP_MSS but limit it to 536.
|
||||
The send MSS is updated when an MSS option is received. */
|
||||
pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
|
||||
|
@ -525,10 +540,11 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
|
|||
|
||||
snmp_inc_tcpactiveopens();
|
||||
|
||||
/* Build an MSS option */
|
||||
optdata = TCP_BUILD_MSS_OPTION();
|
||||
|
||||
ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, (u8_t *)&optdata, 4);
|
||||
ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, TF_SEG_OPTS_MSS
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
| TF_SEG_OPTS_TS
|
||||
#endif
|
||||
);
|
||||
if (ret == ERR_OK) {
|
||||
tcp_output(pcb);
|
||||
}
|
||||
|
@ -991,7 +1007,8 @@ tcp_alloc(u8_t prio)
|
|||
pcb->rcv_ann_wnd = TCP_WND;
|
||||
pcb->tos = 0;
|
||||
pcb->ttl = TCP_TTL;
|
||||
/* The send MSS is updated when an MSS option is received. */
|
||||
/* As initial send MSS, we use TCP_MSS but limit it to 536.
|
||||
The send MSS is updated when an MSS option is received. */
|
||||
pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
|
||||
pcb->rto = 3000 / TCP_SLOW_INTERVAL;
|
||||
pcb->sa = 0;
|
||||
|
@ -1001,7 +1018,6 @@ tcp_alloc(u8_t prio)
|
|||
iss = tcp_next_iss();
|
||||
pcb->snd_wl2 = iss;
|
||||
pcb->snd_nxt = iss;
|
||||
pcb->snd_max = iss;
|
||||
pcb->lastack = iss;
|
||||
pcb->snd_lbb = iss;
|
||||
pcb->tmr = tcp_ticks;
|
||||
|
@ -1112,7 +1128,7 @@ 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;
|
||||
pcb->accept = accept;
|
||||
}
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
|
@ -1148,6 +1164,27 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
|
|||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
|
||||
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
if (pcb->state == SYN_RCVD) {
|
||||
/* Need to find the corresponding listen_pcb and decrease its accepts_pending */
|
||||
struct tcp_pcb_listen *lpcb;
|
||||
LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL",
|
||||
tcp_listen_pcbs.listen_pcbs != NULL);
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
if ((lpcb->local_port == pcb->local_port) &&
|
||||
(ip_addr_isany(&lpcb->local_ip) ||
|
||||
ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) {
|
||||
/* port and address of the listen pcb match the timed-out pcb */
|
||||
LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
|
||||
lpcb->accepts_pending > 0);
|
||||
lpcb->accepts_pending--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
|
||||
|
||||
if (pcb->refused_data != NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n"));
|
||||
pbuf_free(pcb->refused_data);
|
||||
|
@ -1242,7 +1279,9 @@ tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr)
|
|||
mss_s = outif->mtu - IP_HLEN - TCP_HLEN;
|
||||
/* RFC 1122, chap 4.2.2.6:
|
||||
* Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
|
||||
* but we only send options with SYN and that is never filled with data! */
|
||||
* We correct for TCP options in tcp_enqueue(), and don't support
|
||||
* IP options
|
||||
*/
|
||||
sendmss = LWIP_MIN(sendmss, mss_s);
|
||||
}
|
||||
return sendmss;
|
||||
|
@ -1364,6 +1403,7 @@ tcp_debug_print_flags(u8_t flags)
|
|||
if (flags & TCP_CWR) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("CWR "));
|
||||
}
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -169,8 +169,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||
ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
|
||||
tcphdr->wnd = ntohs(tcphdr->wnd);
|
||||
|
||||
flags = TCPH_FLAGS(tcphdr) & TCP_FLAGS;
|
||||
tcplen = p->tot_len + ((flags & TCP_FIN || flags & TCP_SYN)? 1: 0);
|
||||
flags = TCPH_FLAGS(tcphdr);
|
||||
tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
|
||||
|
||||
/* Demultiplex an incoming segment. First, we check if it is destined
|
||||
for an active connection. */
|
||||
|
@ -393,7 +393,7 @@ static err_t
|
|||
tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
{
|
||||
struct tcp_pcb *npcb;
|
||||
u32_t optdata;
|
||||
err_t rc;
|
||||
|
||||
/* In the LISTEN state, we check for incoming SYN segments,
|
||||
creates a new PCB, and responds with a SYN|ACK. */
|
||||
|
@ -408,6 +408,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
if (pcb->accepts_pending >= pcb->backlog) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
|
||||
return ERR_ABRT;
|
||||
}
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
|
@ -430,6 +431,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||
npcb->remote_port = tcphdr->src;
|
||||
npcb->state = SYN_RCVD;
|
||||
npcb->rcv_nxt = seqno + 1;
|
||||
npcb->rcv_ann_right_edge = npcb->rcv_nxt;
|
||||
npcb->snd_wnd = tcphdr->wnd;
|
||||
npcb->ssthresh = npcb->snd_wnd;
|
||||
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
|
||||
|
@ -451,10 +453,17 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||
|
||||
snmp_inc_tcppassiveopens();
|
||||
|
||||
/* Build an MSS option. */
|
||||
optdata = TCP_BUILD_MSS_OPTION();
|
||||
/* Send a SYN|ACK together with the MSS option. */
|
||||
tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4);
|
||||
rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
/* and maybe include the TIMESTAMP option */
|
||||
| (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0)
|
||||
#endif
|
||||
);
|
||||
if (rc != ERR_OK) {
|
||||
tcp_abandon(npcb, 0);
|
||||
return rc;
|
||||
}
|
||||
return tcp_output(npcb);
|
||||
}
|
||||
return ERR_OK;
|
||||
|
@ -498,7 +507,6 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
struct tcp_seg *rseg;
|
||||
u8_t acceptable = 0;
|
||||
err_t err;
|
||||
u8_t accepted_inseq;
|
||||
|
||||
err = ERR_OK;
|
||||
|
||||
|
@ -511,7 +519,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
}
|
||||
} else {
|
||||
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
|
||||
pcb->rcv_nxt+pcb->rcv_ann_wnd)) {
|
||||
pcb->rcv_nxt+pcb->rcv_wnd)) {
|
||||
acceptable = 1;
|
||||
}
|
||||
}
|
||||
|
@ -519,7 +527,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
if (acceptable) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
|
||||
LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
|
||||
recv_flags = TF_RESET;
|
||||
recv_flags |= TF_RESET;
|
||||
pcb->flags &= ~TF_ACK_DELAY;
|
||||
return ERR_RST;
|
||||
} else {
|
||||
|
@ -531,10 +539,18 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
}
|
||||
}
|
||||
|
||||
if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
|
||||
/* Cope with new connection attempt after remote end crashed */
|
||||
tcp_ack_now(pcb);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* Update the PCB (in)activity timer. */
|
||||
pcb->tmr = tcp_ticks;
|
||||
pcb->keep_cnt_sent = 0;
|
||||
|
||||
tcp_parseopt(pcb);
|
||||
|
||||
/* Do different things depending on the TCP state. */
|
||||
switch (pcb->state) {
|
||||
case SYN_SENT:
|
||||
|
@ -545,14 +561,12 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
&& ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
|
||||
pcb->snd_buf++;
|
||||
pcb->rcv_nxt = seqno + 1;
|
||||
pcb->rcv_ann_right_edge = pcb->rcv_nxt;
|
||||
pcb->lastack = ackno;
|
||||
pcb->snd_wnd = tcphdr->wnd;
|
||||
pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
|
||||
pcb->state = ESTABLISHED;
|
||||
|
||||
/* Parse any options in the SYNACK before using pcb->mss since that
|
||||
* can be changed by the received options! */
|
||||
tcp_parseopt(pcb);
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
@ -592,8 +606,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
}
|
||||
break;
|
||||
case SYN_RCVD:
|
||||
if (flags & TCP_ACK &&
|
||||
!(flags & TCP_RST)) {
|
||||
if (flags & TCP_ACK) {
|
||||
/* expected ACK number? */
|
||||
if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
|
||||
u16_t old_cwnd;
|
||||
|
@ -613,11 +626,11 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
old_cwnd = pcb->cwnd;
|
||||
/* If there was any data contained within this ACK,
|
||||
* we'd better pass it on to the application as well. */
|
||||
accepted_inseq = tcp_receive(pcb);
|
||||
tcp_receive(pcb);
|
||||
|
||||
pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
|
||||
|
||||
if ((flags & TCP_FIN) && accepted_inseq) {
|
||||
if (recv_flags & TF_GOT_FIN) {
|
||||
tcp_ack_now(pcb);
|
||||
pcb->state = CLOSE_WAIT;
|
||||
}
|
||||
|
@ -628,21 +641,24 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
} else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
|
||||
/* Looks like another copy of the SYN - retransmit our SYN-ACK */
|
||||
tcp_rexmit(pcb);
|
||||
}
|
||||
break;
|
||||
case CLOSE_WAIT:
|
||||
/* FALLTHROUGH */
|
||||
case ESTABLISHED:
|
||||
accepted_inseq = tcp_receive(pcb);
|
||||
if ((flags & TCP_FIN) && accepted_inseq) { /* passive close */
|
||||
tcp_receive(pcb);
|
||||
if (recv_flags & TF_GOT_FIN) { /* passive close */
|
||||
tcp_ack_now(pcb);
|
||||
pcb->state = CLOSE_WAIT;
|
||||
}
|
||||
break;
|
||||
case FIN_WAIT_1:
|
||||
tcp_receive(pcb);
|
||||
if (flags & TCP_FIN) {
|
||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||
if (recv_flags & TF_GOT_FIN) {
|
||||
if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
|
||||
LWIP_DEBUGF(TCP_DEBUG,
|
||||
("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
tcp_ack_now(pcb);
|
||||
|
@ -654,13 +670,13 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
tcp_ack_now(pcb);
|
||||
pcb->state = CLOSING;
|
||||
}
|
||||
} else if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||
} else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
|
||||
pcb->state = FIN_WAIT_2;
|
||||
}
|
||||
break;
|
||||
case FIN_WAIT_2:
|
||||
tcp_receive(pcb);
|
||||
if (flags & TCP_FIN) {
|
||||
if (recv_flags & TF_GOT_FIN) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
tcp_ack_now(pcb);
|
||||
tcp_pcb_purge(pcb);
|
||||
|
@ -673,7 +689,6 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
tcp_receive(pcb);
|
||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
tcp_ack_now(pcb);
|
||||
tcp_pcb_purge(pcb);
|
||||
TCP_RMV(&tcp_active_pcbs, pcb);
|
||||
pcb->state = TIME_WAIT;
|
||||
|
@ -685,7 +700,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
/* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
|
||||
recv_flags = TF_CLOSED;
|
||||
recv_flags |= TF_CLOSED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -723,7 +738,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
u8_t accepted_inseq = 0;
|
||||
|
||||
if (flags & TCP_ACK) {
|
||||
right_wnd_edge = pcb->snd_wnd + pcb->snd_wl1;
|
||||
right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
|
||||
|
||||
/* Update window. */
|
||||
if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
|
||||
|
@ -739,8 +754,10 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
#if TCP_WND_DEBUG
|
||||
} else {
|
||||
if (pcb->snd_wnd != tcphdr->wnd) {
|
||||
LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: no window update lastack %"U32_F" snd_max %"U32_F" ackno %"U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
|
||||
pcb->lastack, pcb->snd_max, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
|
||||
LWIP_DEBUGF(TCP_WND_DEBUG,
|
||||
("tcp_receive: no window update lastack %"U32_F" ackno %"
|
||||
U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
|
||||
pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
|
||||
}
|
||||
#endif /* TCP_WND_DEBUG */
|
||||
}
|
||||
|
@ -748,7 +765,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
if (pcb->lastack == ackno) {
|
||||
pcb->acked = 0;
|
||||
|
||||
if (pcb->snd_wl1 + pcb->snd_wnd == right_wnd_edge){
|
||||
if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
|
||||
++pcb->dupacks;
|
||||
if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
|
||||
if (!(pcb->flags & TF_INFR)) {
|
||||
|
@ -785,9 +802,9 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
}
|
||||
} else {
|
||||
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %"U32_F" %"U32_F"\n",
|
||||
pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
|
||||
pcb->snd_wl2 + pcb->snd_wnd, right_wnd_edge));
|
||||
}
|
||||
} else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){
|
||||
} else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
|
||||
/* We come here when the ACK acknowledges new data. */
|
||||
|
||||
/* Reset the "IN Fast Retransmit" flag, since we are no longer
|
||||
|
@ -881,10 +898,8 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
->unsent list after a retransmission, so these segments may
|
||||
in fact have been sent once. */
|
||||
while (pcb->unsent != NULL &&
|
||||
/*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) &&
|
||||
TCP_SEQ_LEQ(ackno, pcb->snd_max)*/
|
||||
TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_max)
|
||||
) {
|
||||
TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
|
||||
ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
|
||||
TCP_TCPLEN(pcb->unsent)));
|
||||
|
@ -900,10 +915,6 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
LWIP_ASSERT("tcp_receive: valid queue length",
|
||||
pcb->unacked != NULL || pcb->unsent != NULL);
|
||||
}
|
||||
|
||||
if (pcb->unsent != NULL) {
|
||||
pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);
|
||||
}
|
||||
}
|
||||
/* End of ACK for new data processing. */
|
||||
|
||||
|
@ -1038,53 +1049,81 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
and below rcv_nxt + rcv_wnd) in order to be further
|
||||
processed. */
|
||||
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
|
||||
pcb->rcv_nxt + pcb->rcv_ann_wnd - 1)){
|
||||
pcb->rcv_nxt + pcb->rcv_wnd - 1)){
|
||||
if (pcb->rcv_nxt == seqno) {
|
||||
accepted_inseq = 1;
|
||||
/* The incoming segment is the next in sequence. We check if
|
||||
we have to trim the end of the segment and update rcv_nxt
|
||||
and pass the data to the application. */
|
||||
tcplen = TCP_TCPLEN(&inseg);
|
||||
|
||||
if (tcplen > pcb->rcv_wnd) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
||||
("tcp_receive: other end overran receive window"
|
||||
"seqno %"U32_F" len %"U32_F" right edge %"U32_F"\n",
|
||||
seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
|
||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
|
||||
/* Must remove the FIN from the header as we're trimming
|
||||
* that byte of sequence-space from the packet */
|
||||
TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
|
||||
}
|
||||
/* Adjust length of segment to fit in the window. */
|
||||
inseg.len = pcb->rcv_wnd;
|
||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
|
||||
inseg.len -= 1;
|
||||
}
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
tcplen = TCP_TCPLEN(&inseg);
|
||||
LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
|
||||
(seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
|
||||
}
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
if (pcb->ooseq != NULL &&
|
||||
TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) {
|
||||
if (pcb->ooseq->len > 0) {
|
||||
/* We have to trim the second edge of the incoming
|
||||
segment. */
|
||||
inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
} else {
|
||||
/* does the ooseq segment contain only flags that are in inseg also? */
|
||||
if ((TCPH_FLAGS(inseg.tcphdr) & (TCP_FIN|TCP_SYN)) ==
|
||||
(TCPH_FLAGS(pcb->ooseq->tcphdr) & (TCP_FIN|TCP_SYN))) {
|
||||
if (pcb->ooseq != NULL) {
|
||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
||||
("tcp_receive: received in-order FIN, binning ooseq queue\n"));
|
||||
/* Received in-order FIN means anything that was received
|
||||
* out of order must now have been received in-order, so
|
||||
* bin the ooseq queue */
|
||||
while (pcb->ooseq != NULL) {
|
||||
struct tcp_seg *old_ooseq = pcb->ooseq;
|
||||
pcb->ooseq = pcb->ooseq->next;
|
||||
memp_free(MEMP_TCP_SEG, old_ooseq);
|
||||
}
|
||||
} else if (TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + tcplen)) {
|
||||
if (pcb->ooseq->len > 0) {
|
||||
/* We have to trim the second edge of the incoming segment. */
|
||||
LWIP_ASSERT("tcp_receive: trimmed segment would have zero length\n",
|
||||
TCP_SEQ_GT(pcb->ooseq->tcphdr->seqno, seqno));
|
||||
/* FIN in inseg already handled by dropping whole ooseq queue */
|
||||
inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
|
||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
|
||||
inseg.len -= 1;
|
||||
}
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
tcplen = TCP_TCPLEN(&inseg);
|
||||
LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
|
||||
(seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
|
||||
} else {
|
||||
/* does the ooseq segment contain only flags that are in inseg also? */
|
||||
if ((TCPH_FLAGS(inseg.tcphdr) & (TCP_FIN|TCP_SYN)) ==
|
||||
(TCPH_FLAGS(pcb->ooseq->tcphdr) & (TCP_FIN|TCP_SYN))) {
|
||||
struct tcp_seg *old_ooseq = pcb->ooseq;
|
||||
pcb->ooseq = pcb->ooseq->next;
|
||||
memp_free(MEMP_TCP_SEG, old_ooseq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
||||
tcplen = TCP_TCPLEN(&inseg);
|
||||
|
||||
/* First received FIN will be ACKed +1, on any successive (duplicate)
|
||||
* FINs we are already in CLOSE_WAIT and have already done +1.
|
||||
*/
|
||||
if (pcb->state != CLOSE_WAIT) {
|
||||
pcb->rcv_nxt += tcplen;
|
||||
}
|
||||
pcb->rcv_nxt = seqno + tcplen;
|
||||
|
||||
/* Update the receiver's (our) window. */
|
||||
if (pcb->rcv_wnd < tcplen) {
|
||||
pcb->rcv_wnd = 0;
|
||||
} else {
|
||||
pcb->rcv_wnd -= tcplen;
|
||||
}
|
||||
LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
|
||||
pcb->rcv_wnd -= tcplen;
|
||||
|
||||
if (pcb->rcv_ann_wnd < tcplen) {
|
||||
pcb->rcv_ann_wnd = 0;
|
||||
} else {
|
||||
pcb->rcv_ann_wnd -= tcplen;
|
||||
}
|
||||
tcp_update_rcv_ann_wnd(pcb);
|
||||
|
||||
/* If there is data in the segment, we make preparations to
|
||||
pass this up to the application. The ->recv_data variable
|
||||
|
@ -1104,7 +1143,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
}
|
||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
|
||||
recv_flags = TF_GOT_FIN;
|
||||
recv_flags |= TF_GOT_FIN;
|
||||
}
|
||||
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
|
@ -1117,16 +1156,11 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
seqno = pcb->ooseq->tcphdr->seqno;
|
||||
|
||||
pcb->rcv_nxt += TCP_TCPLEN(cseg);
|
||||
if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) {
|
||||
pcb->rcv_wnd = 0;
|
||||
} else {
|
||||
pcb->rcv_wnd -= TCP_TCPLEN(cseg);
|
||||
}
|
||||
if (pcb->rcv_ann_wnd < TCP_TCPLEN(cseg)) {
|
||||
pcb->rcv_ann_wnd = 0;
|
||||
} else {
|
||||
pcb->rcv_ann_wnd -= TCP_TCPLEN(cseg);
|
||||
}
|
||||
LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
|
||||
pcb->rcv_wnd >= TCP_TCPLEN(cseg));
|
||||
pcb->rcv_wnd -= TCP_TCPLEN(cseg);
|
||||
|
||||
tcp_update_rcv_ann_wnd(pcb);
|
||||
|
||||
if (cseg->p->tot_len > 0) {
|
||||
/* Chain this pbuf onto the pbuf that we will pass to
|
||||
|
@ -1140,7 +1174,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
}
|
||||
if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
|
||||
recv_flags = TF_GOT_FIN;
|
||||
recv_flags |= TF_GOT_FIN;
|
||||
if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
|
||||
pcb->state = CLOSE_WAIT;
|
||||
}
|
||||
|
@ -1195,14 +1229,14 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
} else {
|
||||
pcb->ooseq = cseg;
|
||||
}
|
||||
}
|
||||
tcp_seg_free(next);
|
||||
if (cseg->next != NULL) {
|
||||
next = cseg->next;
|
||||
if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
|
||||
/* We need to trim the incoming segment. */
|
||||
cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
|
||||
pbuf_realloc(cseg->p, cseg->len);
|
||||
tcp_seg_free(next);
|
||||
if (cseg->next != NULL) {
|
||||
next = cseg->next;
|
||||
if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
|
||||
/* We need to trim the incoming segment. */
|
||||
cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
|
||||
pbuf_realloc(cseg->p, cseg->len);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1282,10 +1316,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
|
||||
}
|
||||
} else {
|
||||
if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
|
||||
pcb->rcv_nxt + pcb->rcv_ann_wnd-1)){
|
||||
tcp_ack_now(pcb);
|
||||
}
|
||||
tcp_ack_now(pcb);
|
||||
}
|
||||
} else {
|
||||
/* Segments with length 0 is taken care of here. Segments that
|
||||
|
@ -1300,8 +1331,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
}
|
||||
|
||||
/**
|
||||
* Parses the options contained in the incoming segment. (Code taken
|
||||
* from uIP with only small changes.)
|
||||
* Parses the options contained in the incoming segment.
|
||||
*
|
||||
* Called from tcp_listen_input() and tcp_process().
|
||||
* Currently, only the MSS option is supported!
|
||||
|
@ -1311,35 +1341,72 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||
static void
|
||||
tcp_parseopt(struct tcp_pcb *pcb)
|
||||
{
|
||||
u8_t c;
|
||||
u8_t *opts, opt;
|
||||
u16_t c, max_c;
|
||||
u16_t mss;
|
||||
u8_t *opts, opt;
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
u32_t tsval;
|
||||
#endif
|
||||
|
||||
opts = (u8_t *)tcphdr + TCP_HLEN;
|
||||
|
||||
/* Parse the TCP MSS option, if present. */
|
||||
if(TCPH_HDRLEN(tcphdr) > 0x5) {
|
||||
for(c = 0; c < (TCPH_HDRLEN(tcphdr) - 5) << 2 ;) {
|
||||
max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
|
||||
for (c = 0; c < max_c; ) {
|
||||
opt = opts[c];
|
||||
if (opt == 0x00) {
|
||||
switch (opt) {
|
||||
case 0x00:
|
||||
/* End of options. */
|
||||
break;
|
||||
} else if (opt == 0x01) {
|
||||
++c;
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
|
||||
return;
|
||||
case 0x01:
|
||||
/* NOP option. */
|
||||
} else if (opt == 0x02 &&
|
||||
opts[c + 1] == 0x04) {
|
||||
++c;
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
|
||||
break;
|
||||
case 0x02:
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
|
||||
if (opts[c + 1] != 0x04 || c + 0x04 > max_c) {
|
||||
/* Bad length */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
|
||||
return;
|
||||
}
|
||||
/* An MSS option with the right option length. */
|
||||
mss = (opts[c + 2] << 8) | opts[c + 3];
|
||||
pcb->mss = mss > TCP_MSS? TCP_MSS: mss;
|
||||
|
||||
/* And we are done processing options. */
|
||||
/* Limit the mss to the configured TCP_MSS and prevent division by zero */
|
||||
pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
|
||||
/* Advance to next option */
|
||||
c += 0x04;
|
||||
break;
|
||||
} else {
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
case 0x08:
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
|
||||
if (opts[c + 1] != 0x0A || c + 0x0A > max_c) {
|
||||
/* Bad length */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
|
||||
return;
|
||||
}
|
||||
/* TCP timestamp option with valid length */
|
||||
tsval = (opts[c+2]) | (opts[c+3] << 8) |
|
||||
(opts[c+4] << 16) | (opts[c+5] << 24);
|
||||
if (flags & TCP_SYN) {
|
||||
pcb->ts_recent = ntohl(tsval);
|
||||
pcb->flags |= TF_TIMESTAMP;
|
||||
} else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
|
||||
pcb->ts_recent = ntohl(tsval);
|
||||
}
|
||||
/* Advance to next option */
|
||||
c += 0x0A;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
|
||||
if (opts[c + 1] == 0) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
|
||||
/* If the length field is zero, the options are malformed
|
||||
and we don't process them further. */
|
||||
break;
|
||||
return;
|
||||
}
|
||||
/* All other options have a length field, so that we easily
|
||||
can skip past them. */
|
||||
|
|
|
@ -59,6 +59,27 @@
|
|||
/* Forward declarations.*/
|
||||
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
|
||||
|
||||
static struct tcp_hdr *
|
||||
tcp_output_set_header(struct tcp_pcb *pcb, struct pbuf *p, int optlen,
|
||||
u32_t seqno_be /* already in network byte order */)
|
||||
{
|
||||
struct tcp_hdr *tcphdr = p->payload;
|
||||
tcphdr->src = htons(pcb->local_port);
|
||||
tcphdr->dest = htons(pcb->remote_port);
|
||||
tcphdr->seqno = seqno_be;
|
||||
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
|
||||
tcphdr->wnd = htons(pcb->rcv_ann_wnd);
|
||||
tcphdr->urgp = 0;
|
||||
TCPH_HDRLEN_SET(tcphdr, (5 + optlen / 4));
|
||||
tcphdr->chksum = 0;
|
||||
|
||||
/* If we're sending a packet, update the announced right window edge */
|
||||
pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
|
||||
|
||||
return tcphdr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by tcp_close() to send a segment including flags but not data.
|
||||
*
|
||||
|
@ -69,8 +90,8 @@ 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, TCP_WRITE_FLAG_COPY, NULL, 0);
|
||||
/* no data, no length, flags, copy=1, no optdata */
|
||||
return tcp_enqueue(pcb, NULL, 0, flags, TCP_WRITE_FLAG_COPY, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -102,7 +123,12 @@ tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
|
|||
pcb->state == SYN_SENT ||
|
||||
pcb->state == SYN_RCVD) {
|
||||
if (len > 0) {
|
||||
return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, NULL, 0);
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
return tcp_enqueue(pcb, (void *)data, len, 0, apiflags,
|
||||
pcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0);
|
||||
#else
|
||||
return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 0);
|
||||
#endif
|
||||
}
|
||||
return ERR_OK;
|
||||
} else {
|
||||
|
@ -112,7 +138,7 @@ tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
|
|||
}
|
||||
|
||||
/**
|
||||
* Enqueue either data or TCP options (but not both) for tranmission
|
||||
* Enqueue data and/or TCP options for transmission
|
||||
*
|
||||
* Called by tcp_connect(), tcp_listen_input(), tcp_send_ctrl() and tcp_write().
|
||||
*
|
||||
|
@ -123,13 +149,11 @@ tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
|
|||
* @param apiflags combination of following flags :
|
||||
* - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
|
||||
* - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
|
||||
* @param optdata
|
||||
* @param optlen
|
||||
* @param optflags options to include in segment later on (see definition of struct tcp_seg)
|
||||
*/
|
||||
err_t
|
||||
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
u8_t flags, u8_t apiflags,
|
||||
u8_t *optdata, u8_t optlen)
|
||||
u8_t flags, u8_t apiflags, u8_t optflags)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_seg *seg, *useg, *queue;
|
||||
|
@ -137,13 +161,17 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||
u16_t left, seglen;
|
||||
void *ptr;
|
||||
u16_t queuelen;
|
||||
u8_t optlen;
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
|
||||
("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", apiflags=%"U16_F")\n",
|
||||
(void *)pcb, arg, len, (u16_t)flags, (u16_t)apiflags));
|
||||
LWIP_ERROR("tcp_enqueue: packet needs payload, options, or SYN/FIN (programmer violates API)",
|
||||
((len != 0) || (optflags != 0) || ((flags & (TCP_SYN | TCP_FIN)) != 0)),
|
||||
return ERR_ARG;);
|
||||
LWIP_ERROR("tcp_enqueue: len != 0 || arg == NULL (programmer violates API)",
|
||||
((len != 0) || (arg == NULL)), return ERR_ARG;);
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", apiflags=%"U16_F")\n",
|
||||
(void *)pcb, arg, len, (u16_t)flags, (u16_t)apiflags));
|
||||
LWIP_ERROR("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
|
||||
((len == 0) || (optlen == 0)), return ERR_ARG;);
|
||||
LWIP_ERROR("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
|
||||
((arg == NULL) || (optdata == NULL)), return ERR_ARG;);
|
||||
/* fail on too much data */
|
||||
if (len > pcb->snd_buf) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
|
||||
|
@ -153,6 +181,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||
left = len;
|
||||
ptr = arg;
|
||||
|
||||
optlen = LWIP_TCP_OPT_LENGTH(optflags);
|
||||
|
||||
/* seqno will be the sequence number of the first segment enqueued
|
||||
* by the call to this function. */
|
||||
seqno = pcb->snd_lbb;
|
||||
|
@ -182,15 +212,14 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||
useg = queue = seg = NULL;
|
||||
seglen = 0;
|
||||
while (queue == NULL || left > 0) {
|
||||
|
||||
/* The segment length should be the MSS if the data to be enqueued
|
||||
* is larger than the MSS. */
|
||||
seglen = left > pcb->mss? pcb->mss: left;
|
||||
/* The segment length (including options) should be at most the MSS */
|
||||
seglen = left > (pcb->mss - optlen) ? (pcb->mss - optlen) : left;
|
||||
|
||||
/* Allocate memory for tcp_seg, and fill in fields. */
|
||||
seg = memp_malloc(MEMP_TCP_SEG);
|
||||
if (seg == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
|
||||
("tcp_enqueue: could not allocate memory for tcp_seg\n"));
|
||||
goto memerr;
|
||||
}
|
||||
seg->next = NULL;
|
||||
|
@ -211,62 +240,54 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||
|
||||
/* 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;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold optlen",
|
||||
(seg->p->len >= optlen));
|
||||
queuelen += pbuf_clen(seg->p);
|
||||
seg->dataptr = seg->p->payload;
|
||||
}
|
||||
/* copy from volatile memory? */
|
||||
else if (apiflags & TCP_WRITE_FLAG_COPY) {
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
|
||||
* ROM or other static memory, and need not be copied. */
|
||||
if (apiflags & TCP_WRITE_FLAG_COPY) {
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
|
||||
("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
|
||||
goto memerr;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold the complete seglen",
|
||||
(seg->p->len >= seglen));
|
||||
(seg->p->len >= seglen + optlen));
|
||||
queuelen += pbuf_clen(seg->p);
|
||||
if (arg != NULL) {
|
||||
MEMCPY(seg->p->payload, ptr, seglen);
|
||||
MEMCPY((char *)seg->p->payload + optlen, ptr, seglen);
|
||||
}
|
||||
seg->dataptr = seg->p->payload;
|
||||
}
|
||||
/* do not copy data */
|
||||
else {
|
||||
/* 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.
|
||||
*/
|
||||
if ((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
|
||||
goto memerr;
|
||||
}
|
||||
++queuelen;
|
||||
/* reference the non-volatile payload data */
|
||||
p->payload = ptr;
|
||||
seg->dataptr = ptr;
|
||||
|
||||
/* Second, allocate a pbuf for the headers. */
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
|
||||
/* If allocation fails, we have to deallocate the data pbuf as
|
||||
* well. */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
|
||||
/* First, allocate a pbuf for the headers. */
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
|
||||
("tcp_enqueue: could not allocate memory for header pbuf\n"));
|
||||
goto memerr;
|
||||
}
|
||||
queuelen += pbuf_clen(seg->p);
|
||||
|
||||
/* Concatenate the headers and data pbufs together. */
|
||||
pbuf_cat(seg->p/*header*/, p/*data*/);
|
||||
p = NULL;
|
||||
/* Second, 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.
|
||||
*/
|
||||
if (left > 0) {
|
||||
if ((p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
|
||||
/* If allocation fails, we have to deallocate the header pbuf as well. */
|
||||
pbuf_free(seg->p);
|
||||
seg->p = NULL;
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
|
||||
("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
|
||||
goto memerr;
|
||||
}
|
||||
++queuelen;
|
||||
/* reference the non-volatile payload data */
|
||||
p->payload = ptr;
|
||||
seg->dataptr = ptr;
|
||||
|
||||
/* Concatenate the headers and data pbufs together. */
|
||||
pbuf_cat(seg->p/*header*/, p/*data*/);
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now that there are more segments queued, we check again if the
|
||||
|
@ -292,17 +313,10 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||
TCPH_FLAGS_SET(seg->tcphdr, flags);
|
||||
/* don't fill in tcphdr->ackno and tcphdr->wnd until later */
|
||||
|
||||
/* Copy the options into the header, if they are present. */
|
||||
if (optdata == NULL) {
|
||||
TCPH_HDRLEN_SET(seg->tcphdr, 5);
|
||||
}
|
||||
else {
|
||||
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. */
|
||||
SMEMCPY(seg->dataptr, optdata, optlen);
|
||||
}
|
||||
seg->flags = optflags;
|
||||
|
||||
/* Set the length of the header */
|
||||
TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
|
||||
ntohl(seg->tcphdr->seqno),
|
||||
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
|
||||
|
@ -331,21 +345,33 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
|
||||
!(flags & (TCP_SYN | TCP_FIN)) &&
|
||||
/* fit within max seg size */
|
||||
useg->len + queue->len <= pcb->mss) {
|
||||
(useg->len + queue->len <= pcb->mss) &&
|
||||
/* only concatenate segments with the same options */
|
||||
(useg->flags == queue->flags)) {
|
||||
/* Remove TCP header from first segment of our to-be-queued list */
|
||||
if(pbuf_header(queue->p, -TCP_HLEN)) {
|
||||
if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) {
|
||||
/* Can we cope with this failing? Just assert for now */
|
||||
LWIP_ASSERT("pbuf_header failed\n", 0);
|
||||
TCP_STATS_INC(tcp.err);
|
||||
goto memerr;
|
||||
}
|
||||
if (queue->p->len == 0) {
|
||||
/* free the first (header-only) pbuf if it is now empty (contained only headers) */
|
||||
struct pbuf *old_q = queue->p;
|
||||
queue->p = queue->p->next;
|
||||
old_q->next = NULL;
|
||||
queuelen--;
|
||||
pbuf_free(old_q);
|
||||
}
|
||||
LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
|
||||
pbuf_cat(useg->p, queue->p);
|
||||
useg->len += queue->len;
|
||||
useg->next = queue->next;
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
|
||||
if (seg == queue) {
|
||||
seg = NULL;
|
||||
seg = useg;
|
||||
seglen = useg->len;
|
||||
}
|
||||
memp_free(MEMP_TCP_SEG, queue);
|
||||
}
|
||||
|
@ -400,6 +426,24 @@ memerr:
|
|||
return ERR_MEM;
|
||||
}
|
||||
|
||||
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
/* Build a timestamp option (12 bytes long) at the specified options pointer)
|
||||
*
|
||||
* @param pcb tcp_pcb
|
||||
* @param opts option pointer where to store the timestamp option
|
||||
*/
|
||||
static void
|
||||
tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
|
||||
{
|
||||
/* Pad with two NOP options to make everything nicely aligned */
|
||||
opts[0] = htonl(0x0101080A);
|
||||
opts[1] = htonl(sys_now());
|
||||
opts[2] = htonl(pcb->ts_recent);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Find out what we can send and send it
|
||||
*
|
||||
|
@ -413,10 +457,11 @@ tcp_output(struct tcp_pcb *pcb)
|
|||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
struct tcp_seg *seg, *useg;
|
||||
u32_t wnd;
|
||||
u32_t wnd, snd_nxt;
|
||||
#if TCP_CWND_DEBUG
|
||||
s16_t i = 0;
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
u8_t optlen = 0;
|
||||
|
||||
/* First, check if we are invoked by the TCP input processing
|
||||
code. If so, we do not output anything. Instead, we rely on the
|
||||
|
@ -445,41 +490,37 @@ tcp_output(struct tcp_pcb *pcb)
|
|||
if (pcb->flags & TF_ACK_NOW &&
|
||||
(seg == NULL ||
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
if (pcb->flags & TF_TIMESTAMP)
|
||||
optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
|
||||
#endif
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
||||
return ERR_BUF;
|
||||
}
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
|
||||
("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
|
||||
/* remove ACK flags from the PCB, as we send an empty ACK now */
|
||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||
|
||||
tcphdr = p->payload;
|
||||
tcphdr->src = htons(pcb->local_port);
|
||||
tcphdr->dest = htons(pcb->remote_port);
|
||||
tcphdr->seqno = htonl(pcb->snd_nxt);
|
||||
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
|
||||
tcphdr->wnd = htons(pcb->rcv_ann_wnd);
|
||||
tcphdr->urgp = 0;
|
||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||
tcphdr = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
|
||||
|
||||
/* NB. MSS option is only sent on SYNs, so ignore it here */
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
pcb->ts_lastacksent = pcb->rcv_nxt;
|
||||
|
||||
if (pcb->flags & TF_TIMESTAMP)
|
||||
tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
|
||||
#endif
|
||||
|
||||
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
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
{
|
||||
struct netif *netif;
|
||||
netif = ip_route(&pcb->remote_ip);
|
||||
if(netif != NULL){
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
ip_output_if(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl,
|
||||
pcb->tos, IP_PROTO_TCP, netif);
|
||||
netif->addr_hint = NULL;
|
||||
}
|
||||
}
|
||||
ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
|
@ -543,9 +584,9 @@ tcp_output(struct tcp_pcb *pcb)
|
|||
}
|
||||
|
||||
tcp_output_segment(seg, pcb);
|
||||
pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
|
||||
if (TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) {
|
||||
pcb->snd_max = pcb->snd_nxt;
|
||||
snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
|
||||
if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
|
||||
pcb->snd_nxt = snd_nxt;
|
||||
}
|
||||
/* put segment on unacknowledged list if length > 0 */
|
||||
if (TCP_TCPLEN(seg) > 0) {
|
||||
|
@ -557,12 +598,17 @@ tcp_output(struct tcp_pcb *pcb)
|
|||
/* unacked list is not empty? */
|
||||
} else {
|
||||
/* In the case of fast retransmit, the packet should not go to the tail
|
||||
* of the unacked queue, but rather at the head. We need to check for
|
||||
* of the unacked queue, but rather somewhere before it. 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;
|
||||
/* add segment to before tail of unacked list, keeping the list sorted */
|
||||
struct tcp_seg **cur_seg = &(pcb->unacked);
|
||||
while (*cur_seg &&
|
||||
TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
|
||||
cur_seg = &((*cur_seg)->next );
|
||||
}
|
||||
seg->next = (*cur_seg);
|
||||
(*cur_seg) = seg;
|
||||
} else {
|
||||
/* add segment to tail of unacked list */
|
||||
useg->next = seg;
|
||||
|
@ -598,6 +644,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||
{
|
||||
u16_t len;
|
||||
struct netif *netif;
|
||||
u32_t *opts;
|
||||
|
||||
/** @bug Exclude retransmitted segments from this count. */
|
||||
snmp_inc_tcpoutsegs();
|
||||
|
@ -609,6 +656,24 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||
/* advertise our receive window size in this TCP segment */
|
||||
seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
|
||||
|
||||
pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
|
||||
|
||||
/* Add any requested options. NB MSS option is only set on SYN
|
||||
packets, so ignore it here */
|
||||
opts = (u32_t *)(seg->tcphdr + 1);
|
||||
if (seg->flags & TF_SEG_OPTS_MSS) {
|
||||
TCP_BUILD_MSS_OPTION(*opts);
|
||||
opts += 1;
|
||||
}
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
pcb->ts_lastacksent = pcb->rcv_nxt;
|
||||
|
||||
if (seg->flags & TF_SEG_OPTS_TS) {
|
||||
tcp_build_timestamp_option(pcb, opts);
|
||||
opts += 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we don't have a local IP address, we get one by
|
||||
calling ip_route(). */
|
||||
if (ip_addr_isany(&(pcb->local_ip))) {
|
||||
|
@ -650,16 +715,8 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
{
|
||||
struct netif *netif;
|
||||
netif = ip_route(&pcb->remote_ip);
|
||||
if(netif != NULL){
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
ip_output_if(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl,
|
||||
pcb->tos, IP_PROTO_TCP, netif);
|
||||
netif->addr_hint = NULL;
|
||||
}
|
||||
}
|
||||
ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
|
@ -749,7 +806,6 @@ tcp_rexmit_rto(struct tcp_pcb *pcb)
|
|||
/* unacked queue is now empty */
|
||||
pcb->unacked = NULL;
|
||||
|
||||
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||
/* increment number of retransmissions */
|
||||
++pcb->nrtx;
|
||||
|
||||
|
@ -771,18 +827,24 @@ void
|
|||
tcp_rexmit(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct tcp_seg *seg;
|
||||
struct tcp_seg **cur_seg;
|
||||
|
||||
if (pcb->unacked == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Move the first unacked segment to the unsent queue */
|
||||
seg = pcb->unacked->next;
|
||||
pcb->unacked->next = pcb->unsent;
|
||||
pcb->unsent = pcb->unacked;
|
||||
pcb->unacked = seg;
|
||||
/* Keep the unsent queue sorted. */
|
||||
seg = pcb->unacked;
|
||||
pcb->unacked = seg->next;
|
||||
|
||||
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||
cur_seg = &(pcb->unsent);
|
||||
while (*cur_seg &&
|
||||
TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
|
||||
cur_seg = &((*cur_seg)->next );
|
||||
}
|
||||
seg->next = *cur_seg;
|
||||
*cur_seg = seg;
|
||||
|
||||
++pcb->nrtx;
|
||||
|
||||
|
@ -825,17 +887,8 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||
LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
|
||||
(p->len >= sizeof(struct tcp_hdr)));
|
||||
|
||||
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);
|
||||
TCPH_FLAGS_SET(tcphdr, 0);
|
||||
tcphdr->wnd = htons(pcb->rcv_ann_wnd);
|
||||
tcphdr->urgp = 0;
|
||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||
tcphdr = tcp_output_set_header(pcb, p, 0, htonl(pcb->snd_nxt - 1));
|
||||
|
||||
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);
|
||||
|
@ -844,16 +897,8 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||
|
||||
/* Send output to IP */
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
{
|
||||
struct netif *netif;
|
||||
netif = ip_route(&pcb->remote_ip);
|
||||
if(netif != NULL){
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
ip_output_if(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl,
|
||||
0, IP_PROTO_TCP, netif);
|
||||
netif->addr_hint = NULL;
|
||||
}
|
||||
}
|
||||
ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
|
||||
&(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
|
@ -908,20 +953,11 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
|||
LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
|
||||
(p->len >= sizeof(struct tcp_hdr)));
|
||||
|
||||
tcphdr = p->payload;
|
||||
tcphdr->src = htons(pcb->local_port);
|
||||
tcphdr->dest = htons(pcb->remote_port);
|
||||
tcphdr->seqno = seg->tcphdr->seqno;
|
||||
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||
TCPH_FLAGS_SET(tcphdr, 0);
|
||||
tcphdr->wnd = htons(pcb->rcv_ann_wnd);
|
||||
tcphdr->urgp = 0;
|
||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||
tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno);
|
||||
|
||||
/* Copy in one byte from the head of the unacked queue */
|
||||
*((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
|
||||
|
||||
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);
|
||||
|
@ -930,16 +966,8 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
|||
|
||||
/* Send output to IP */
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
{
|
||||
struct netif *netif;
|
||||
netif = ip_route(&pcb->remote_ip);
|
||||
if(netif != NULL){
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
ip_output_if(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl,
|
||||
0, IP_PROTO_TCP, netif);
|
||||
netif->addr_hint = NULL;
|
||||
}
|
||||
}
|
||||
ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
|
||||
&(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
|
|
|
@ -90,6 +90,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||
struct ip_hdr *iphdr;
|
||||
u16_t src, dest;
|
||||
u8_t local_match;
|
||||
u8_t broadcast;
|
||||
|
||||
PERF_START;
|
||||
|
||||
|
@ -112,6 +113,9 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||
|
||||
udphdr = (struct udp_hdr *)p->payload;
|
||||
|
||||
/* is broadcast packet ? */
|
||||
broadcast = ip_addr_isbroadcast(&(iphdr->dest), inp);
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
|
||||
|
||||
/* convert src and dest ports to host byte order */
|
||||
|
@ -169,12 +173,16 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||
|
||||
/* compare PCB local addr+port to UDP destination addr+port */
|
||||
if ((pcb->local_port == dest) &&
|
||||
(ip_addr_isany(&pcb->local_ip) ||
|
||||
((!broadcast && ip_addr_isany(&pcb->local_ip)) ||
|
||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)) ||
|
||||
#if LWIP_IGMP
|
||||
ip_addr_ismulticast(&(iphdr->dest)) ||
|
||||
#endif /* LWIP_IGMP */
|
||||
ip_addr_isbroadcast(&(iphdr->dest), inp))) {
|
||||
#if IP_SOF_BROADCAST_RECV
|
||||
(broadcast && (pcb->so_options & SOF_BROADCAST)))) {
|
||||
#else /* IP_SOF_BROADCAST_RECV */
|
||||
(broadcast))) {
|
||||
#endif /* IP_SOF_BROADCAST_RECV */
|
||||
local_match = 1;
|
||||
if ((uncon_pcb == NULL) &&
|
||||
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
|
||||
|
@ -286,7 +294,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||
#if LWIP_ICMP
|
||||
/* No match was found, send ICMP destination port unreachable unless
|
||||
destination address was broadcast/multicast. */
|
||||
if (!ip_addr_isbroadcast(&iphdr->dest, inp) &&
|
||||
if (!broadcast &&
|
||||
!ip_addr_ismulticast(&iphdr->dest)) {
|
||||
/* move payload pointer back to ip header */
|
||||
pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN);
|
||||
|
@ -400,6 +408,14 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
|||
err_t err;
|
||||
struct pbuf *q; /* q will be sent down the stack */
|
||||
|
||||
#if IP_SOF_BROADCAST
|
||||
/* broadcast filter? */
|
||||
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
return ERR_VAL;
|
||||
}
|
||||
#endif /* IP_SOF_BROADCAST */
|
||||
|
||||
/* if the PCB is not yet bound to a port, bind it here */
|
||||
if (pcb->local_port == 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 2, ("udp_send: not yet bound to a port, binding now\n"));
|
||||
|
@ -635,9 +651,9 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
|
||||
(u16_t)((ntohl(pcb->local_ip.addr) >> 24) & 0xff),
|
||||
(u16_t)((ntohl(pcb->local_ip.addr) >> 16) & 0xff),
|
||||
(u16_t)((ntohl(pcb->local_ip.addr) >> 8) & 0xff),
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
|
||||
return ERR_OK;
|
||||
}
|
||||
|
@ -693,9 +709,9 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||
#endif
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
|
||||
(u16_t)((ntohl(pcb->remote_ip.addr) >> 24) & 0xff),
|
||||
(u16_t)((ntohl(pcb->remote_ip.addr) >> 16) & 0xff),
|
||||
(u16_t)((ntohl(pcb->remote_ip.addr) >> 8) & 0xff),
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
|
||||
|
||||
/* Insert UDP PCB into the list of active UDP PCBs. */
|
||||
|
|
|
@ -78,39 +78,30 @@ void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
|
|||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
/** This is the standard ICMP header only that the u32_t data
|
||||
* is splitted to two u16_t like ICMP echo needs it.
|
||||
* This header is also used for other ICMP types that do not
|
||||
* use the data part.
|
||||
*/
|
||||
PACK_STRUCT_BEGIN
|
||||
struct icmp_echo_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u16_t id);
|
||||
PACK_STRUCT_FIELD(u16_t seqno);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
|
||||
PACK_STRUCT_BEGIN
|
||||
struct icmp_dur_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u32_t unused);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
|
||||
PACK_STRUCT_BEGIN
|
||||
struct icmp_te_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u32_t unused);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define ICMPH_TYPE(hdr) (ntohs((hdr)->_type_code) >> 8)
|
||||
#define ICMPH_CODE(hdr) (ntohs((hdr)->_type_code) & 0xff)
|
||||
#define ICMPH_TYPE(hdr) ((hdr)->type)
|
||||
#define ICMPH_CODE(hdr) ((hdr)->code)
|
||||
|
||||
#define ICMPH_TYPE_SET(hdr, type) ((hdr)->_type_code = htons(ICMPH_CODE(hdr) | ((type) << 8)))
|
||||
#define ICMPH_CODE_SET(hdr, code) ((hdr)->_type_code = htons((code) | (ICMPH_TYPE(hdr) << 8)))
|
||||
/** Combines type and code to an u16_t */
|
||||
#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t))
|
||||
#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -34,12 +34,20 @@
|
|||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For compatibility with BSD code */
|
||||
struct in_addr {
|
||||
u32_t s_addr;
|
||||
};
|
||||
|
||||
#define INADDR_NONE ((u32_t)0xffffffffUL) /* 255.255.255.255 */
|
||||
#define INADDR_LOOPBACK ((u32_t)0x7f000001UL) /* 127.0.0.1 */
|
||||
#define INADDR_ANY ((u32_t)0x00000000UL) /* 0.0.0.0 */
|
||||
#define INADDR_BROADCAST ((u32_t)0xffffffffUL) /* 255.255.255.255 */
|
||||
|
||||
u32_t inet_addr(const char *cp);
|
||||
int inet_aton(const char *cp, struct in_addr *addr);
|
||||
char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */
|
||||
|
|
|
@ -46,9 +46,11 @@ u16_t inet_chksum_pbuf(struct pbuf *p);
|
|||
u16_t inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u16_t proto_len);
|
||||
#if LWIP_UDPLITE
|
||||
u16_t inet_chksum_pseudo_partial(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u16_t proto_len, u16_t chksum_len);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -38,19 +38,14 @@
|
|||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ip_init() /* Compatibility define, not init needed. */
|
||||
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 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 tos, u8_t proto,
|
||||
struct netif *netif);
|
||||
/** Currently, the function ip_output_if_opt() is only used with IGMP */
|
||||
#define IP_OPTIONS_SEND LWIP_IGMP
|
||||
|
||||
#define IP_HLEN 20
|
||||
|
||||
|
@ -103,7 +98,7 @@ struct ip_pcb {
|
|||
#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_BROADCAST (u16_t)0x0020U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
|
||||
#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 */
|
||||
|
@ -158,6 +153,25 @@ PACK_STRUCT_END
|
|||
#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8)))
|
||||
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
|
||||
|
||||
#define ip_init() /* Compatibility define, not init needed. */
|
||||
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 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 tos, u8_t proto,
|
||||
struct netif *netif);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
err_t ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||
#if IP_OPTIONS_SEND
|
||||
err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
||||
u16_t optlen);
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
struct netif *ip_current_netif(void);
|
||||
const struct ip_hdr *ip_current_header(void);
|
||||
#if IP_DEBUG
|
||||
void ip_debug_print(struct pbuf *p);
|
||||
#else
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -66,11 +68,6 @@ PACK_STRUCT_END
|
|||
# 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;
|
||||
|
@ -82,9 +79,6 @@ extern const struct ip_addr ip_addr_broadcast;
|
|||
#define IP_ADDR_ANY ((struct ip_addr *)&ip_addr_any)
|
||||
#define IP_ADDR_BROADCAST ((struct ip_addr *)&ip_addr_broadcast)
|
||||
|
||||
#define INADDR_NONE ((u32_t)0xffffffffUL) /* 255.255.255.255 */
|
||||
#define INADDR_LOOPBACK ((u32_t)0x7f000001UL) /* 127.0.0.1 */
|
||||
|
||||
/* Definitions of the bits in an Internet address integer.
|
||||
|
||||
On subnets, host and network parts are found according to
|
||||
|
@ -150,11 +144,15 @@ u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
|
|||
#define ip_addr_islinklocal(addr1) (((addr1)->addr & ntohl(0xffff0000UL)) == ntohl(0xa9fe0000UL))
|
||||
|
||||
#define ip_addr_debug_print(debug, ipaddr) \
|
||||
LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
|
||||
ipaddr ? (u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff : 0, \
|
||||
ipaddr ? (u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff : 0, \
|
||||
ipaddr ? (u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff : 0, \
|
||||
ipaddr ? (u16_t)ntohl((ipaddr)->addr) & 0xff : 0))
|
||||
LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
|
||||
ipaddr != NULL ? \
|
||||
(u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff : 0, \
|
||||
ipaddr != NULL ? \
|
||||
(u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff : 0, \
|
||||
ipaddr != NULL ? \
|
||||
(u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff : 0, \
|
||||
ipaddr != NULL ? \
|
||||
(u16_t)ntohl((ipaddr)->addr) & 0xff : 0))
|
||||
|
||||
/* These are cast to u16_t, with the intent that they are often arguments
|
||||
* to printf using the U16_F format from cc.h. */
|
||||
|
|
|
@ -114,6 +114,9 @@ err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||
u8_t ttl, u8_t proto,
|
||||
struct netif *netif);
|
||||
|
||||
#define ip_current_netif() NULL
|
||||
#define ip_current_header() NULL
|
||||
|
||||
#if IP_DEBUG
|
||||
void ip_debug_print(struct pbuf *p);
|
||||
#endif /* IP_DEBUG */
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
||||
#include "lwip/netbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
@ -137,19 +139,21 @@ struct netconn {
|
|||
/** maximum amount of bytes queued in recvmbox */
|
||||
int recv_bufsize;
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
u16_t recv_avail;
|
||||
s16_t recv_avail;
|
||||
#if LWIP_TCP
|
||||
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
|
||||
this temporarily stores the message. */
|
||||
struct api_msg_msg *write_msg;
|
||||
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
|
||||
this temporarily stores how much is already sent. */
|
||||
int write_offset;
|
||||
size_t write_offset;
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
|
||||
this temporarily stores whether to wake up the original application task
|
||||
if data couldn't be sent in the first try. */
|
||||
u8_t write_delayed;
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||
#endif /* LWIP_TCP */
|
||||
/** A callback function that is informed about events for this netconn */
|
||||
netconn_callback callback;
|
||||
};
|
||||
|
@ -166,7 +170,8 @@ struct
|
|||
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto,
|
||||
netconn_callback callback);
|
||||
err_t netconn_delete (struct netconn *conn);
|
||||
enum netconn_type netconn_type (struct netconn *conn);
|
||||
/** Get the type of a netconn (as enum netconn_type). */
|
||||
#define netconn_type(conn) (conn->type)
|
||||
|
||||
err_t netconn_getaddr (struct netconn *conn,
|
||||
struct ip_addr *addr,
|
||||
|
@ -191,7 +196,7 @@ err_t netconn_sendto (struct netconn *conn,
|
|||
err_t netconn_send (struct netconn *conn,
|
||||
struct netbuf *buf);
|
||||
err_t netconn_write (struct netconn *conn,
|
||||
const void *dataptr, int size,
|
||||
const void *dataptr, size_t size,
|
||||
u8_t apiflags);
|
||||
err_t netconn_close (struct netconn *conn);
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
|
@ -78,7 +80,7 @@ struct api_msg_msg {
|
|||
/** used for do_write */
|
||||
struct {
|
||||
const void *dataptr;
|
||||
int len;
|
||||
size_t len;
|
||||
u8_t apiflags;
|
||||
} w;
|
||||
/** used ofr do_recv */
|
||||
|
|
|
@ -42,6 +42,11 @@
|
|||
|
||||
#include "arch/cc.h"
|
||||
|
||||
/** Temporary: define format string for size_t if not defined in cc.h */
|
||||
#ifndef SZT_F
|
||||
#define SZT_F U32_F
|
||||
#endif /* SZT_F */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -194,13 +199,7 @@ extern "C" {
|
|||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_PROVIDE_ERRNO */
|
||||
|
||||
/*yi.qiu@2008.09.08, Newlib does not provide following errno*/
|
||||
#define ENSROK 0 /* DNS server returned answer with no data */
|
||||
#define ENSRNODATA 160 /* DNS server returned answer with no data */
|
||||
#define ENSRFORMERR 161 /* DNS server claims query was misformatted */
|
||||
|
@ -221,6 +220,12 @@ extern int errno;
|
|||
#define ENSRQUERYDOMAINTOOLONG 176 /* Domain name is too long */
|
||||
#define ENSRCNAMELOOP 177 /* Domain name is too long */
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_PROVIDE_ERRNO */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -61,26 +61,28 @@
|
|||
#define LWIP_DBG_HALT 0x08U
|
||||
|
||||
#ifndef LWIP_NOASSERT
|
||||
#define LWIP_ASSERT(x,y) do { if(!(y)) LWIP_PLATFORM_ASSERT(x); } while(0)
|
||||
#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \
|
||||
LWIP_PLATFORM_ASSERT(message); } while(0)
|
||||
#else /* LWIP_NOASSERT */
|
||||
#define LWIP_ASSERT(x,y)
|
||||
#define LWIP_ASSERT(message, assertion)
|
||||
#endif /* LWIP_NOASSERT */
|
||||
|
||||
/** print "m" message only if "e" is true, and execute "h" expression */
|
||||
/** if "expression" isn't true, then print "message" and execute "handler" expression */
|
||||
#ifndef LWIP_ERROR
|
||||
#define LWIP_ERROR(m,e,h) do { if (!(e)) { LWIP_PLATFORM_ASSERT(m); h;}} while(0)
|
||||
#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
|
||||
LWIP_PLATFORM_ASSERT(message); handler;}} while(0)
|
||||
#endif /* LWIP_ERROR */
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
/** print debug message only if debug message type is enabled...
|
||||
* AND is of correct type AND is at least LWIP_DBG_LEVEL
|
||||
*/
|
||||
#define LWIP_DEBUGF(debug,x) do { \
|
||||
#define LWIP_DEBUGF(debug, message) do { \
|
||||
if ( \
|
||||
((debug) & LWIP_DBG_ON) && \
|
||||
((debug) & LWIP_DBG_TYPES_ON) && \
|
||||
((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \
|
||||
LWIP_PLATFORM_DIAG(x); \
|
||||
LWIP_PLATFORM_DIAG(message); \
|
||||
if ((debug) & LWIP_DBG_HALT) { \
|
||||
while(1); \
|
||||
} \
|
||||
|
@ -88,7 +90,7 @@
|
|||
} while(0)
|
||||
|
||||
#else /* LWIP_DEBUG */
|
||||
#define LWIP_DEBUGF(debug,x)
|
||||
#define LWIP_DEBUGF(debug, message)
|
||||
#endif /* LWIP_DEBUG */
|
||||
|
||||
#endif /* __LWIP_DEBUG_H__ */
|
||||
|
|
|
@ -18,7 +18,7 @@ extern "C" {
|
|||
/** period (in seconds) of the application calling dhcp_coarse_tmr() */
|
||||
#define DHCP_COARSE_TIMER_SECS 60
|
||||
/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */
|
||||
#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS*1000)
|
||||
#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL)
|
||||
/** period (in milliseconds) of the application calling dhcp_fine_tmr() */
|
||||
#define DHCP_FINE_TIMER_MSECS 500
|
||||
|
||||
|
|
|
@ -87,6 +87,11 @@ struct ip_addr dns_getserver(u8_t numdns);
|
|||
err_t dns_gethostbyname(const char *hostname, struct ip_addr *addr,
|
||||
dns_found_callback found, void *callback_arg);
|
||||
|
||||
#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
int dns_local_removehost(const char *hostname, const struct ip_addr *addr);
|
||||
err_t dns_local_addhost(const char *hostname, const struct ip_addr *addr);
|
||||
#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
|
||||
#endif /* LWIP_DNS */
|
||||
|
||||
#endif /* __LWIP_DNS_H__ */
|
||||
|
|
|
@ -33,37 +33,43 @@
|
|||
#define __LWIP_ERR_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef s8_t err_t;
|
||||
/** Define LWIP_ERR_T in cc.h if you want to use
|
||||
* a different type for your platform (must be signed). */
|
||||
#ifdef LWIP_ERR_T
|
||||
typedef LWIP_ERR_T err_t;
|
||||
#else /* LWIP_ERR_T */
|
||||
typedef s8_t err_t;
|
||||
#endif /* LWIP_ERR_T*/
|
||||
|
||||
/* Definitions for error constants. */
|
||||
|
||||
#define ERR_OK 0 /* No error, everything OK. */
|
||||
#define ERR_MEM -1 /* Out of memory error. */
|
||||
#define ERR_BUF -2 /* Buffer error. */
|
||||
#define ERR_RTE -3 /* Routing problem. */
|
||||
#define ERR_TIMEOUT -3 /* Timeout. */
|
||||
#define ERR_RTE -4 /* Routing problem. */
|
||||
|
||||
#define ERR_IS_FATAL(e) ((e) < ERR_RTE)
|
||||
|
||||
#define ERR_ABRT -4 /* Connection aborted. */
|
||||
#define ERR_RST -5 /* Connection reset. */
|
||||
#define ERR_CLSD -6 /* Connection closed. */
|
||||
#define ERR_CONN -7 /* Not connected. */
|
||||
#define ERR_ABRT -5 /* Connection aborted. */
|
||||
#define ERR_RST -6 /* Connection reset. */
|
||||
#define ERR_CLSD -7 /* Connection closed. */
|
||||
#define ERR_CONN -8 /* Not connected. */
|
||||
|
||||
#define ERR_VAL -8 /* Illegal value. */
|
||||
#define ERR_VAL -9 /* Illegal value. */
|
||||
|
||||
#define ERR_ARG -9 /* Illegal argument. */
|
||||
#define ERR_ARG -10 /* Illegal argument. */
|
||||
|
||||
#define ERR_USE -10 /* Address in use. */
|
||||
#define ERR_USE -11 /* Address in use. */
|
||||
|
||||
#define ERR_IF -11 /* Low-level netif error */
|
||||
#define ERR_ISCONN -12 /* Already connected. */
|
||||
|
||||
#define ERR_TIMEOUT -13 /* Timeout. */
|
||||
#define ERR_IF -12 /* Low-level netif error */
|
||||
#define ERR_ISCONN -13 /* Already connected. */
|
||||
|
||||
#define ERR_INPROGRESS -14 /* Operation in progress */
|
||||
|
||||
|
|
|
@ -38,6 +38,30 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** X.x.x: Major version of the stack */
|
||||
#define LWIP_VERSION_MAJOR 1U
|
||||
/** x.X.x: Minor version of the stack */
|
||||
#define LWIP_VERSION_MINOR 3U
|
||||
/** x.x.X: Revision of the stack */
|
||||
#define LWIP_VERSION_REVISION 1U
|
||||
/** For release candidates, this is set to 1..254
|
||||
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
|
||||
* For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
||||
#define LWIP_VERSION_RC 255U
|
||||
|
||||
/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */
|
||||
#define LWIP_RC_RELEASE 255U
|
||||
/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for CVS versions */
|
||||
#define LWIP_RC_DEVELOPMENT 0U
|
||||
|
||||
#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE)
|
||||
#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT)
|
||||
#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT))
|
||||
|
||||
/** Provides the version of the stack */
|
||||
#define LWIP_VERSION (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 | \
|
||||
LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC)
|
||||
|
||||
/* Modules initialization */
|
||||
void lwip_init(void);
|
||||
|
||||
|
|
|
@ -50,16 +50,20 @@ typedef size_t mem_size_t;
|
|||
* allow these defines to be overridden.
|
||||
*/
|
||||
#ifndef mem_free
|
||||
#define mem_free(x) free(x)
|
||||
#define mem_free free
|
||||
#endif
|
||||
#ifndef mem_malloc
|
||||
#define mem_malloc(x) malloc(x)
|
||||
#define mem_malloc malloc
|
||||
#endif
|
||||
#ifndef mem_calloc
|
||||
#define mem_calloc(x, y) calloc(x, y)
|
||||
#define mem_calloc calloc
|
||||
#endif
|
||||
#ifndef mem_realloc
|
||||
#define mem_realloc(x, size) (x)
|
||||
static void *mem_realloc(void *mem, mem_size_t size)
|
||||
{
|
||||
LWIP_UNUSED_ARG(size);
|
||||
return mem;
|
||||
}
|
||||
#endif
|
||||
#else /* MEM_LIBC_MALLOC */
|
||||
|
||||
|
|
|
@ -73,8 +73,28 @@ typedef enum {
|
|||
We use this helper type and these defines so we can avoid using const memp_t values */
|
||||
#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST)
|
||||
#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST)
|
||||
#endif /* MEM_USE_POOLS */
|
||||
|
||||
#if MEMP_MEM_MALLOC || MEM_USE_POOLS
|
||||
extern const u16_t memp_sizes[MEMP_MAX];
|
||||
#endif /* MEMP_MEM_MALLOC || MEM_USE_POOLS */
|
||||
|
||||
#if MEMP_MEM_MALLOC
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
#define memp_init()
|
||||
#define memp_malloc(type) mem_malloc(memp_sizes[type])
|
||||
#define memp_free(type, mem) mem_free(mem)
|
||||
|
||||
#else /* MEMP_MEM_MALLOC */
|
||||
|
||||
#if MEM_USE_POOLS
|
||||
/** This structure is used to save the pool one element came from. */
|
||||
struct memp_malloc_helper
|
||||
{
|
||||
memp_t poolnr;
|
||||
};
|
||||
#endif /* MEM_USE_POOLS */
|
||||
|
||||
void memp_init(void);
|
||||
|
@ -87,6 +107,8 @@ void *memp_malloc(memp_t type);
|
|||
#endif
|
||||
void memp_free(memp_t type, void *mem);
|
||||
|
||||
#endif /* MEMP_MEM_MALLOC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -10,8 +10,9 @@
|
|||
* above, then will declare #2 & #3 to be just standard mempools.
|
||||
*/
|
||||
#ifndef LWIP_MALLOC_MEMPOOL
|
||||
/* This treats "malloc pools" just like any other pool */
|
||||
#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, size, "MALLOC_"#size)
|
||||
/* This treats "malloc pools" just like any other pool.
|
||||
The pools are a little bigger to provide 'size' as the amount of user data. */
|
||||
#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + sizeof(struct memp_malloc_helper)), "MALLOC_"#size)
|
||||
#define LWIP_MALLOC_MEMPOOL_START
|
||||
#define LWIP_MALLOC_MEMPOOL_END
|
||||
#endif /* LWIP_MALLOC_MEMPOOL */
|
||||
|
|
|
@ -65,6 +65,7 @@ void netbuf_first (struct netbuf *buf);
|
|||
#define netbuf_copy_partial(buf, dataptr, len, offset) \
|
||||
pbuf_copy_partial((buf)->p, (dataptr), (len), (offset))
|
||||
#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
|
||||
#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len)
|
||||
#define netbuf_len(buf) ((buf)->p->tot_len)
|
||||
#define netbuf_fromaddr(buf) ((buf)->addr)
|
||||
#define netbuf_fromport(buf) ((buf)->port)
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#if LWIP_DNS && LWIP_SOCKET
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
/* some rarely used options */
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
|
@ -165,6 +167,14 @@ struct netif {
|
|||
#if LWIP_NETIF_HWADDRHINT
|
||||
u8_t *addr_hint;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||
#if ENABLE_LOOPBACK
|
||||
/* List of packets to be queued for ourselves. */
|
||||
struct pbuf *loop_first;
|
||||
struct pbuf *loop_last;
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
u16_t loop_cnt_current;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
};
|
||||
|
||||
#if LWIP_SNMP
|
||||
|
@ -242,4 +252,12 @@ void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct
|
|||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LOOPBACK
|
||||
err_t netif_loop_output(struct netif *netif, struct pbuf *p, struct ip_addr *dest_ip);
|
||||
void netif_poll(struct netif *netif);
|
||||
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
void netif_poll_all(void);
|
||||
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
|
||||
#endif /* __LWIP_NETIF_H__ */
|
||||
|
|
|
@ -98,6 +98,15 @@
|
|||
#define MEM_LIBC_MALLOC 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator.
|
||||
* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution
|
||||
* speed and usage from interrupts!
|
||||
*/
|
||||
#ifndef MEMP_MEM_MALLOC
|
||||
#define MEMP_MEM_MALLOC 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEM_ALIGNMENT: should be set to the alignment of the CPU
|
||||
* 4 byte alignment -> #define MEM_ALIGNMENT 4
|
||||
|
@ -139,12 +148,21 @@
|
|||
/**
|
||||
* MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set
|
||||
* of memory pools of various sizes. When mem_malloc is called, an element of
|
||||
* the smallest pool that can provide the lenght needed is returned.
|
||||
* the smallest pool that can provide the length needed is returned.
|
||||
* To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled.
|
||||
*/
|
||||
#ifndef MEM_USE_POOLS
|
||||
#define MEM_USE_POOLS 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next
|
||||
* bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more
|
||||
* reliable. */
|
||||
#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL
|
||||
#define MEM_USE_POOLS_TRY_BIGGER_POOL 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h
|
||||
* that defines additional pools beyond the "standard" ones required
|
||||
|
@ -155,6 +173,27 @@
|
|||
#define MEMP_USE_CUSTOM_POOLS 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from
|
||||
* interrupt context (or another context that doesn't allow waiting for a
|
||||
* semaphore).
|
||||
* If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT,
|
||||
* while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs
|
||||
* with each loop so that mem_free can run.
|
||||
*
|
||||
* ATTENTION: As you can see from the above description, this leads to dis-/
|
||||
* enabling interrupts often, which can be slow! Also, on low memory, mem_malloc
|
||||
* can need longer.
|
||||
*
|
||||
* If you don't want that, at least for NO_SYS=0, you can still use the following
|
||||
* functions to enqueue a deallocation call which then runs in the tcpip_thread
|
||||
* context:
|
||||
* - pbuf_free_callback(p);
|
||||
* - mem_free_callback(m);
|
||||
*/
|
||||
#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
------------------------------------------------
|
||||
|
@ -411,6 +450,23 @@
|
|||
#define IP_DEFAULT_TTL 255
|
||||
#endif
|
||||
|
||||
/**
|
||||
* IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast
|
||||
* filter per pcb on udp and raw send operations. To enable broadcast filter
|
||||
* on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1.
|
||||
*/
|
||||
#ifndef IP_SOF_BROADCAST
|
||||
#define IP_SOF_BROADCAST 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast
|
||||
* filter on recv operations.
|
||||
*/
|
||||
#ifndef IP_SOF_BROADCAST_RECV
|
||||
#define IP_SOF_BROADCAST_RECV 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
----------------------------------
|
||||
---------- ICMP options ----------
|
||||
|
@ -431,6 +487,20 @@
|
|||
#define ICMP_TTL (IP_DEFAULT_TTL)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only)
|
||||
*/
|
||||
#ifndef LWIP_BROADCAST_PING
|
||||
#define LWIP_BROADCAST_PING 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only)
|
||||
*/
|
||||
#ifndef LWIP_MULTICAST_PING
|
||||
#define LWIP_MULTICAST_PING 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
---------------------------------
|
||||
---------- RAW options ----------
|
||||
|
@ -489,6 +559,17 @@
|
|||
#define LWIP_DHCP_AUTOIP_COOP 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes
|
||||
* that should be sent before falling back on AUTOIP. This can be set
|
||||
* as low as 1 to get an AutoIP address very quickly, but you should
|
||||
* be prepared to handle a changing IP address when DHCP overrides
|
||||
* AutoIP.
|
||||
*/
|
||||
#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES
|
||||
#define LWIP_DHCP_AUTOIP_COOP_TRIES 9
|
||||
#endif
|
||||
|
||||
/*
|
||||
----------------------------------
|
||||
---------- SNMP options ----------
|
||||
|
@ -591,6 +672,26 @@
|
|||
#define DNS_MSG_SIZE 512
|
||||
#endif
|
||||
|
||||
/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled,
|
||||
* you have to define
|
||||
* #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}}
|
||||
* (an array of structs name/address, where address is an u32_t in network
|
||||
* byte order).
|
||||
*
|
||||
* Instead, you can also use an external function:
|
||||
* #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name)
|
||||
* that returns the IP address or INADDR_NONE if not found.
|
||||
*/
|
||||
#ifndef DNS_LOCAL_HOSTLIST
|
||||
#define DNS_LOCAL_HOSTLIST 0
|
||||
#endif /* DNS_LOCAL_HOSTLIST */
|
||||
|
||||
/** If this is turned on, the local host-list can be dynamically changed
|
||||
* at runtime. */
|
||||
#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0
|
||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
|
||||
/*
|
||||
---------------------------------
|
||||
---------- UDP options ----------
|
||||
|
@ -637,7 +738,8 @@
|
|||
#endif
|
||||
|
||||
/**
|
||||
* TCP_WND: The size of a TCP window.
|
||||
* TCP_WND: The size of a TCP window. This must be at least
|
||||
* (2 * TCP_MSS) for things to work well
|
||||
*/
|
||||
#ifndef TCP_WND
|
||||
#define TCP_WND 2048
|
||||
|
@ -662,7 +764,7 @@
|
|||
* Define to 0 if your device is low on memory.
|
||||
*/
|
||||
#ifndef TCP_QUEUE_OOSEQ
|
||||
#define TCP_QUEUE_OOSEQ 1
|
||||
#define TCP_QUEUE_OOSEQ (LWIP_TCP)
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -729,6 +831,21 @@
|
|||
#define TCP_DEFAULT_LISTEN_BACKLOG 0xff
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option.
|
||||
*/
|
||||
#ifndef LWIP_TCP_TIMESTAMPS
|
||||
#define LWIP_TCP_TIMESTAMPS 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an
|
||||
* explicit window update
|
||||
*/
|
||||
#ifndef TCP_WND_UPDATE_THRESHOLD
|
||||
#define TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1.
|
||||
* LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all
|
||||
|
@ -815,6 +932,52 @@
|
|||
#define LWIP_NETIF_HWADDRHINT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP
|
||||
* address equal to the netif IP address, looping them back up the stack.
|
||||
*/
|
||||
#ifndef LWIP_NETIF_LOOPBACK
|
||||
#define LWIP_NETIF_LOOPBACK 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback
|
||||
* sending for each netif (0 = disabled)
|
||||
*/
|
||||
#ifndef LWIP_LOOPBACK_MAX_PBUFS
|
||||
#define LWIP_LOOPBACK_MAX_PBUFS 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in
|
||||
* the system, as netifs must change how they behave depending on this setting
|
||||
* for the LWIP_NETIF_LOOPBACK option to work.
|
||||
* Setting this is needed to avoid reentering non-reentrant functions like
|
||||
* tcp_input().
|
||||
* LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a
|
||||
* multithreaded environment like tcpip.c. In this case, netif->input()
|
||||
* is called directly.
|
||||
* LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
|
||||
* The packets are put on a list and netif_poll() must be called in
|
||||
* the main application loop.
|
||||
*/
|
||||
#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data
|
||||
* to be sent into one single pbuf. This is for compatibility with DMA-enabled
|
||||
* MACs that do not support scatter-gather.
|
||||
* Beware that this might involve CPU-memcpy before transmitting that would not
|
||||
* be needed without this flag! Use this only if you need to!
|
||||
*
|
||||
* @todo: TCP and IP-frag do not work with this, yet:
|
||||
*/
|
||||
#ifndef LWIP_NETIF_TX_SINGLE_PBUF
|
||||
#define LWIP_NETIF_TX_SINGLE_PBUF 0
|
||||
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
|
||||
/*
|
||||
------------------------------------
|
||||
---------- LOOPIF options ----------
|
||||
|
@ -827,20 +990,16 @@
|
|||
#define LWIP_HAVE_LOOPIF 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
------------------------------------
|
||||
---------- SLIPIF options ----------
|
||||
------------------------------------
|
||||
*/
|
||||
/**
|
||||
* LWIP_LOOPIF_MULTITHREADING: Indicates whether threading is enabled in
|
||||
* the system, as LOOPIF must change how it behaves depending on this setting.
|
||||
* Setting this is needed to avoid reentering non-reentrant functions like
|
||||
* tcp_input().
|
||||
* LWIP_LOOPIF_MULTITHREADING==1: Indicates that the user is using a
|
||||
* multithreaded environment like tcpip.c. In this case, netif->input()
|
||||
* is called directly.
|
||||
* LWIP_LOOPIF_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
|
||||
* The packets are put on a list and loopif_poll() must be called in
|
||||
* the main application loop.
|
||||
* LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c
|
||||
*/
|
||||
#ifndef LWIP_LOOPIF_MULTITHREADING
|
||||
#define LWIP_LOOPIF_MULTITHREADING 1
|
||||
#ifndef LWIP_HAVE_SLIPIF
|
||||
#define LWIP_HAVE_SLIPIF 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -1039,7 +1198,7 @@
|
|||
* names (read, write & close). (only used if you use sockets.c)
|
||||
*/
|
||||
#ifndef LWIP_POSIX_SOCKETS_IO_NAMES
|
||||
#define LWIP_POSIX_SOCKETS_IO_NAMES 0
|
||||
#define LWIP_POSIX_SOCKETS_IO_NAMES 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -1065,6 +1224,13 @@
|
|||
#define LWIP_SO_RCVBUF 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize.
|
||||
*/
|
||||
#ifndef RECV_BUFSIZE_DEFAULT
|
||||
#define RECV_BUFSIZE_DEFAULT INT_MAX
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SO_REUSE==1: Enable SO_REUSEADDR and SO_REUSEPORT options. DO NOT USE!
|
||||
*/
|
||||
|
|
|
@ -110,6 +110,8 @@ void pbuf_chain(struct pbuf *head, struct pbuf *tail);
|
|||
struct pbuf *pbuf_dechain(struct pbuf *p);
|
||||
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from);
|
||||
u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
|
||||
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
|
||||
struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -32,16 +32,24 @@
|
|||
* It needs to be implemented by those platforms which need SLIP or PPP
|
||||
*/
|
||||
|
||||
#ifndef __SIO_H__
|
||||
#define __SIO_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* If you want to define sio_fd_t elsewhere or differently,
|
||||
define this in your cc.h file. */
|
||||
#ifndef __sio_fd_t_defined
|
||||
typedef void * sio_fd_t;
|
||||
#endif
|
||||
|
||||
/* The following functions can be defined to something else in your cc.h file
|
||||
or be implemented in your custom sio.c file. */
|
||||
|
||||
#ifndef sio_open
|
||||
sio_fd_t sio_open(u8_t);
|
||||
#endif
|
||||
|
@ -69,3 +77,5 @@ void sio_read_abort(sio_fd_t);
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SIO_H__ */
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include "lwip/pbuf.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#if LWIP_SNMP
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -94,4 +96,6 @@ err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw);
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_SNMP */
|
||||
|
||||
#endif /* __LWIP_SNMP_ASN1_H__ */
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#include "lwip/snmp.h"
|
||||
#include "lwip/snmp_structs.h"
|
||||
|
||||
#if LWIP_SNMP
|
||||
|
||||
#if SNMP_PRIVATE_MIB
|
||||
#include "private_mib.h"
|
||||
#endif
|
||||
|
@ -304,4 +306,6 @@ void snmp_authfail_trap(void);
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_SNMP */
|
||||
|
||||
#endif /* __LWIP_SNMP_MSG_H__ */
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/inet.h"
|
||||
|
||||
|
@ -69,13 +71,6 @@ struct sockaddr {
|
|||
#define SOCK_DGRAM 2
|
||||
#define SOCK_RAW 3
|
||||
|
||||
/*
|
||||
* Maximum queue length specifiable by listen(2).
|
||||
*/
|
||||
#ifndef SOMAXCONN
|
||||
#define SOMAXCONN 128
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Option flags per-socket. These must match the SOF_ flags in ip.h!
|
||||
*/
|
||||
|
@ -84,7 +79,7 @@ struct sockaddr {
|
|||
#define SO_REUSEADDR 0x0004 /* Unimplemented: allow local address reuse */
|
||||
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
|
||||
#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */
|
||||
#define SO_BROADCAST 0x0020 /* Unimplemented: permit sending of broadcast msgs */
|
||||
#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
|
||||
#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */
|
||||
#define SO_LINGER 0x0080 /* linger on close if data present */
|
||||
#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */
|
||||
|
@ -131,9 +126,6 @@ struct linger {
|
|||
#define IPPROTO_UDP 17
|
||||
#define IPPROTO_UDPLITE 136
|
||||
|
||||
#define INADDR_ANY 0
|
||||
#define INADDR_BROADCAST 0xffffffff
|
||||
|
||||
/* Flags we can use with send and recv. */
|
||||
#define MSG_PEEK 0x01 /* Peeks at an incoming message */
|
||||
#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */
|
||||
|
@ -184,7 +176,22 @@ typedef struct ip_mreq {
|
|||
} ip_mreq;
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
/* Unimplemented for now... */
|
||||
/*
|
||||
* The Type of Service provides an indication of the abstract
|
||||
* parameters of the quality of service desired. These parameters are
|
||||
* to be used to guide the selection of the actual service parameters
|
||||
* when transmitting a datagram through a particular network. Several
|
||||
* networks offer service precedence, which somehow treats high
|
||||
* precedence traffic as more important than other traffic (generally
|
||||
* by accepting only traffic above a certain precedence at time of high
|
||||
* load). The major choice is a three way tradeoff between low-delay,
|
||||
* high-reliability, and high-throughput.
|
||||
* The use of the Delay, Throughput, and Reliability indications may
|
||||
* increase the cost (in some sense) of the service. In many networks
|
||||
* better performance for one of these parameters is coupled with worse
|
||||
* performance on another. Except for very unusual cases at most two
|
||||
* of these three indications should be set.
|
||||
*/
|
||||
#define IPTOS_TOS_MASK 0x1E
|
||||
#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
|
||||
#define IPTOS_LOWDELAY 0x10
|
||||
|
@ -194,7 +201,13 @@ typedef struct ip_mreq {
|
|||
#define IPTOS_MINCOST IPTOS_LOWCOST
|
||||
|
||||
/*
|
||||
* Definitions for IP precedence (also in ip_tos) (Unimplemented)
|
||||
* The Network Control precedence designation is intended to be used
|
||||
* within a network only. The actual use and control of that
|
||||
* designation is up to each network. The Internetwork Control
|
||||
* designation is intended for use by gateway control originators only.
|
||||
* If the actual use of these precedence designations is of concern to
|
||||
* a particular network, it is the responsibility of that network to
|
||||
* control the access to, and use of, those precedence designations.
|
||||
*/
|
||||
#define IPTOS_PREC_MASK 0xe0
|
||||
#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK)
|
||||
|
@ -286,7 +299,7 @@ struct timeval {
|
|||
void lwip_socket_init(void);
|
||||
|
||||
int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int lwip_bind(int s, struct sockaddr *name, socklen_t namelen);
|
||||
int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen);
|
||||
int lwip_shutdown(int s, int how);
|
||||
int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen);
|
||||
|
@ -295,15 +308,15 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
|
|||
int lwip_close(int s);
|
||||
int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen);
|
||||
int lwip_listen(int s, int backlog);
|
||||
int lwip_recv(int s, void *mem, int len, unsigned int flags);
|
||||
int lwip_read(int s, void *mem, int len);
|
||||
int lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
||||
int lwip_recv(int s, void *mem, size_t len, int flags);
|
||||
int lwip_read(int s, void *mem, size_t len);
|
||||
int lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen);
|
||||
int lwip_send(int s, const void *dataptr, int size, unsigned int flags);
|
||||
int lwip_sendto(int s, const void *dataptr, int size, unsigned int flags,
|
||||
struct sockaddr *to, socklen_t tolen);
|
||||
int lwip_send(int s, const void *dataptr, size_t size, int flags);
|
||||
int lwip_sendto(int s, const void *dataptr, size_t size, int flags,
|
||||
const struct sockaddr *to, socklen_t tolen);
|
||||
int lwip_socket(int domain, int type, int protocol);
|
||||
int lwip_write(int s, const void *dataptr, int size);
|
||||
int lwip_write(int s, const void *dataptr, size_t size);
|
||||
int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
struct timeval *timeout);
|
||||
int lwip_ioctl(int s, long cmd, void *argp);
|
||||
|
|
|
@ -57,7 +57,6 @@ extern "C" {
|
|||
|
||||
struct stats_proto {
|
||||
STAT_COUNTER xmit; /* Transmitted packets. */
|
||||
STAT_COUNTER rexmit; /* Retransmitted packets. */
|
||||
STAT_COUNTER recv; /* Received packets. */
|
||||
STAT_COUNTER fw; /* Forwarded packets. */
|
||||
STAT_COUNTER drop; /* Dropped packets. */
|
||||
|
@ -87,7 +86,8 @@ struct stats_mem {
|
|||
mem_size_t avail;
|
||||
mem_size_t used;
|
||||
mem_size_t max;
|
||||
mem_size_t err;
|
||||
STAT_COUNTER err;
|
||||
STAT_COUNTER illegal;
|
||||
};
|
||||
|
||||
struct stats_syselem {
|
||||
|
@ -142,64 +142,138 @@ extern struct stats_ lwip_stats;
|
|||
#define stats_init() /* Compatibility define, not init needed. */
|
||||
|
||||
#define STATS_INC(x) ++lwip_stats.x
|
||||
#define STATS_DEC(x) --lwip_stats.x
|
||||
#else
|
||||
#define stats_init()
|
||||
#define STATS_INC(x)
|
||||
#define STATS_DEC(x)
|
||||
#endif /* LWIP_STATS */
|
||||
|
||||
#if TCP_STATS
|
||||
#define TCP_STATS_INC(x) STATS_INC(x)
|
||||
#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP")
|
||||
#else
|
||||
#define TCP_STATS_INC(x)
|
||||
#define TCP_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if UDP_STATS
|
||||
#define UDP_STATS_INC(x) STATS_INC(x)
|
||||
#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP")
|
||||
#else
|
||||
#define UDP_STATS_INC(x)
|
||||
#define UDP_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if ICMP_STATS
|
||||
#define ICMP_STATS_INC(x) STATS_INC(x)
|
||||
#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP")
|
||||
#else
|
||||
#define ICMP_STATS_INC(x)
|
||||
#define ICMP_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if IGMP_STATS
|
||||
#define IGMP_STATS_INC(x) STATS_INC(x)
|
||||
#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp)
|
||||
#else
|
||||
#define IGMP_STATS_INC(x)
|
||||
#define IGMP_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if IP_STATS
|
||||
#define IP_STATS_INC(x) STATS_INC(x)
|
||||
#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP")
|
||||
#else
|
||||
#define IP_STATS_INC(x)
|
||||
#define IP_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if IPFRAG_STATS
|
||||
#define IPFRAG_STATS_INC(x) STATS_INC(x)
|
||||
#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG")
|
||||
#else
|
||||
#define IPFRAG_STATS_INC(x)
|
||||
#define IPFRAG_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if ETHARP_STATS
|
||||
#define ETHARP_STATS_INC(x) STATS_INC(x)
|
||||
#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP")
|
||||
#else
|
||||
#define ETHARP_STATS_INC(x)
|
||||
#define ETHARP_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if LINK_STATS
|
||||
#define LINK_STATS_INC(x) STATS_INC(x)
|
||||
#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK")
|
||||
#else
|
||||
#define LINK_STATS_INC(x)
|
||||
#define LINK_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if MEM_STATS
|
||||
#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
|
||||
#define MEM_STATS_INC(x) STATS_INC(mem.x)
|
||||
#define MEM_STATS_INC_USED(x, y) do { lwip_stats.mem.used += y; \
|
||||
if (lwip_stats.mem.max < lwip_stats.mem.used) { \
|
||||
lwip_stats.mem.max = lwip_stats.mem.used; \
|
||||
} \
|
||||
} while(0)
|
||||
#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y
|
||||
#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP")
|
||||
#else
|
||||
#define MEM_STATS_AVAIL(x, y)
|
||||
#define MEM_STATS_INC(x)
|
||||
#define MEM_STATS_INC_USED(x, y)
|
||||
#define MEM_STATS_DEC_USED(x, y)
|
||||
#define MEM_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
#if MEMP_STATS
|
||||
#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y
|
||||
#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x)
|
||||
#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x)
|
||||
#define MEMP_STATS_INC_USED(x, i) do { ++lwip_stats.memp[i].used; \
|
||||
if (lwip_stats.memp[i].max < lwip_stats.memp[i].used) { \
|
||||
lwip_stats.memp[i].max = lwip_stats.memp[i].used; \
|
||||
} \
|
||||
} while(0)
|
||||
#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i)
|
||||
#else
|
||||
#define MEMP_STATS_AVAIL(x, i, y)
|
||||
#define MEMP_STATS_INC(x, i)
|
||||
#define MEMP_STATS_DEC(x, i)
|
||||
#define MEMP_STATS_INC_USED(x, i)
|
||||
#define MEMP_STATS_DISPLAY(i)
|
||||
#endif
|
||||
|
||||
#if SYS_STATS
|
||||
#define SYS_STATS_INC(x) STATS_INC(sys.x)
|
||||
#define SYS_STATS_DEC(x) STATS_DEC(sys.x)
|
||||
#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys)
|
||||
#else
|
||||
#define SYS_STATS_INC(x)
|
||||
#define SYS_STATS_DEC(x)
|
||||
#define SYS_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
/* Display of statistics */
|
||||
#if LWIP_STATS_DISPLAY
|
||||
void stats_display(void);
|
||||
void stats_display_proto(struct stats_proto *proto, char *name);
|
||||
void stats_display_igmp(struct stats_igmp *igmp);
|
||||
void stats_display_mem(struct stats_mem *mem, char *name);
|
||||
void stats_display_memp(struct stats_mem *mem, int index);
|
||||
void stats_display_sys(struct stats_sys *sys);
|
||||
#else
|
||||
#define stats_display()
|
||||
#define stats_display_proto(proto, name)
|
||||
#define stats_display_igmp(igmp)
|
||||
#define stats_display_mem(mem, name)
|
||||
#define stats_display_memp(mem, index)
|
||||
#define stats_display_sys(sys)
|
||||
#endif /* LWIP_STATS_DISPLAY */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -44,7 +44,6 @@ extern "C" {
|
|||
definitions of the sys_ functions. */
|
||||
typedef u8_t sys_sem_t;
|
||||
typedef u8_t sys_mbox_t;
|
||||
typedef u8_t sys_prot_t;
|
||||
struct sys_timeo {u8_t dummy;};
|
||||
|
||||
#define sys_init()
|
||||
|
@ -139,13 +138,11 @@ void sys_mbox_fetch(sys_mbox_t mbox, void **msg);
|
|||
/* Thread functions. */
|
||||
sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio);
|
||||
|
||||
/* The following functions are used only in Unix code, and
|
||||
can be omitted when porting the stack. */
|
||||
/* Returns the current time in microseconds. */
|
||||
unsigned long sys_now(void);
|
||||
|
||||
#endif /* NO_SYS */
|
||||
|
||||
/** Returns the current time in milliseconds. */
|
||||
u32_t sys_now(void);
|
||||
|
||||
/* Critical Region Protection */
|
||||
/* These functions must be implemented in the sys_arch.c file.
|
||||
In some implementations they can provide a more light-weight protection
|
||||
|
|
|
@ -96,7 +96,8 @@ err_t tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
|||
struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
|
||||
#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
|
||||
|
||||
void tcp_abort (struct tcp_pcb *pcb);
|
||||
void tcp_abandon (struct tcp_pcb *pcb, int reset);
|
||||
#define tcp_abort(pcb) tcp_abandon((pcb), 1)
|
||||
err_t tcp_close (struct tcp_pcb *pcb);
|
||||
|
||||
/* Flags for "apiflags" parameter in tcp_write and tcp_enqueue */
|
||||
|
@ -124,26 +125,24 @@ void tcp_input (struct pbuf *p, struct netif *inp);
|
|||
err_t tcp_output (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit_rto (struct tcp_pcb *pcb);
|
||||
u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
|
||||
|
||||
/**
|
||||
* This is the Nagle algorithm: inhibit the sending of new TCP
|
||||
* segments when new outgoing data arrives from the user if any
|
||||
* previously transmitted data on the connection remains
|
||||
* unacknowledged.
|
||||
* This is the Nagle algorithm: try to combine user data to send as few TCP
|
||||
* segments as possible. Only send if
|
||||
* - no previously transmitted data on the connection remains unacknowledged or
|
||||
* - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or
|
||||
* - the only unsent segment is at least pcb->mss bytes long (or there is more
|
||||
* than one unsent segment - with lwIP, this can happen although unsent->len < mss)
|
||||
*/
|
||||
#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
|
||||
((tpcb)->flags & TF_NODELAY) || \
|
||||
(((tpcb)->unsent != NULL) && ((tpcb)->unsent->next != NULL))) ? \
|
||||
1 : 0)
|
||||
(((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
|
||||
((tpcb)->unsent->len >= (tpcb)->mss))) \
|
||||
) ? 1 : 0)
|
||||
#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK)
|
||||
|
||||
|
||||
/** This returns a TCP header option for MSS in an u32_t */
|
||||
#define TCP_BUILD_MSS_OPTION() htonl(((u32_t)2 << 24) | \
|
||||
((u32_t)4 << 16) | \
|
||||
(((u32_t)TCP_MSS / 256) << 8) | \
|
||||
(TCP_MSS & 255))
|
||||
|
||||
#define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0)
|
||||
#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
|
||||
#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
|
||||
|
@ -185,7 +184,7 @@ void tcp_rexmit_rto (struct tcp_pcb *pcb);
|
|||
#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */
|
||||
|
||||
#ifndef TCP_MSL
|
||||
#define TCP_MSL 60000U /* The maximum segment lifetime in milliseconds */
|
||||
#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */
|
||||
#endif
|
||||
|
||||
/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */
|
||||
|
@ -258,6 +257,20 @@ enum tcp_state {
|
|||
#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */
|
||||
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
|
||||
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
/* Function to call when a listener has been connected.
|
||||
* @param arg user-supplied argument (tcp_pcb.callback_arg)
|
||||
* @param pcb a new tcp_pcb that now is connected
|
||||
* @param err an error argument (TODO: that is current always ERR_OK?)
|
||||
* @return ERR_OK: accept the new connection,
|
||||
* any other err_t abortsthe new connection
|
||||
*/
|
||||
#define DEF_ACCEPT_CALLBACK err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
#else /* LWIP_CALLBACK_API */
|
||||
#define DEF_ACCEPT_CALLBACK
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
/**
|
||||
* members common to struct tcp_pcb and struct tcp_listen_pcb
|
||||
*/
|
||||
|
@ -267,7 +280,10 @@ enum tcp_state {
|
|||
u8_t prio; \
|
||||
void *callback_arg; \
|
||||
/* ports are in host byte order */ \
|
||||
u16_t local_port
|
||||
u16_t local_port; \
|
||||
/* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \
|
||||
DEF_ACCEPT_CALLBACK
|
||||
|
||||
|
||||
/* the TCP protocol control block */
|
||||
struct tcp_pcb {
|
||||
|
@ -280,19 +296,21 @@ struct tcp_pcb {
|
|||
u16_t remote_port;
|
||||
|
||||
u8_t flags;
|
||||
#define TF_ACK_DELAY (u8_t)0x01U /* Delayed ACK. */
|
||||
#define TF_ACK_NOW (u8_t)0x02U /* Immediate ACK. */
|
||||
#define TF_INFR (u8_t)0x04U /* In fast recovery. */
|
||||
#define TF_FIN (u8_t)0x20U /* Connection was closed locally (FIN segment enqueued). */
|
||||
#define TF_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */
|
||||
#define TF_NAGLEMEMERR (u8_t)0x80U /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */
|
||||
#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_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */
|
||||
#define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */
|
||||
#define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */
|
||||
#define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */
|
||||
|
||||
/* the rest of the fields are in host byte order
|
||||
as we have to do some math with them */
|
||||
/* receiver variables */
|
||||
u32_t rcv_nxt; /* next seqno expected */
|
||||
u16_t rcv_wnd; /* receiver window */
|
||||
u16_t rcv_ann_wnd; /* announced receive window */
|
||||
u16_t rcv_wnd; /* receiver window available */
|
||||
u16_t rcv_ann_wnd; /* receiver window to announce */
|
||||
u32_t rcv_ann_right_edge; /* announced right edge of window */
|
||||
|
||||
/* Timers */
|
||||
u32_t tmr;
|
||||
|
@ -320,12 +338,11 @@ struct tcp_pcb {
|
|||
u16_t ssthresh;
|
||||
|
||||
/* sender variables */
|
||||
u32_t snd_nxt, /* next seqno to be sent */
|
||||
snd_max; /* Highest seqno sent. */
|
||||
u32_t snd_nxt; /* next new seqno to be sent */
|
||||
u16_t snd_wnd; /* sender window */
|
||||
u32_t snd_wl1, snd_wl2, /* Sequence and acknowledgement numbers of last
|
||||
u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last
|
||||
window update. */
|
||||
snd_lbb; /* Sequence number of next byte to be buffered. */
|
||||
u32_t snd_lbb; /* Sequence number of next byte to be buffered. */
|
||||
|
||||
u16_t acked;
|
||||
|
||||
|
@ -369,15 +386,6 @@ struct tcp_pcb {
|
|||
*/
|
||||
err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err);
|
||||
|
||||
/* Function to call when a listener has been connected.
|
||||
* @param arg user-supplied argument (tcp_pcb.callback_arg)
|
||||
* @param pcb a new tcp_pcb that now is connected
|
||||
* @param err an error argument (TODO: that is current always ERR_OK?)
|
||||
* @return ERR_OK: accept the new connection,
|
||||
* any other err_t abortsthe new connection
|
||||
*/
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
|
||||
|
||||
/* Function which is called periodically.
|
||||
* The period can be adjusted in multiples of the TCP slow timer interval
|
||||
* by changing tcp_pcb.polltmr.
|
||||
|
@ -398,6 +406,11 @@ struct tcp_pcb {
|
|||
void (* errf)(void *arg, err_t err);
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
u32_t ts_lastacksent;
|
||||
u32_t ts_recent;
|
||||
#endif /* LWIP_TCP_TIMESTAMPS */
|
||||
|
||||
/* idle time before KEEPALIVE is sent */
|
||||
u32_t keep_idle;
|
||||
#if LWIP_TCP_KEEPALIVE
|
||||
|
@ -420,16 +433,6 @@ struct tcp_pcb_listen {
|
|||
/* Protocol specific PCB members */
|
||||
TCP_PCB_COMMON(struct tcp_pcb_listen);
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
/* Function to call when a listener has been connected.
|
||||
* @param arg user-supplied argument (tcp_pcb.callback_arg)
|
||||
* @param pcb a new tcp_pcb that now is connected
|
||||
* @param err an error argument (TODO: that is current always ERR_OK?)
|
||||
* @return ERR_OK: accept the new connection,
|
||||
* any other err_t abortsthe new connection
|
||||
*/
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
u8_t backlog;
|
||||
u8_t accepts_pending;
|
||||
|
@ -466,26 +469,52 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
|
|||
#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
|
||||
LWIP_EVENT_ERR, NULL, 0, (err))
|
||||
#else /* LWIP_EVENT_API */
|
||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) \
|
||||
if((pcb)->accept != NULL) \
|
||||
(ret = (pcb)->accept((pcb)->callback_arg,(pcb),(err)))
|
||||
#define TCP_EVENT_SENT(pcb,space,ret) \
|
||||
if((pcb)->sent != NULL) \
|
||||
(ret = (pcb)->sent((pcb)->callback_arg,(pcb),(space)))
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) \
|
||||
if((pcb)->recv != NULL) \
|
||||
{ ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
|
||||
ret = ERR_OK; \
|
||||
if (p) pbuf_free(p); }
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
|
||||
if((pcb)->connected != NULL) \
|
||||
(ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
|
||||
#define TCP_EVENT_POLL(pcb,ret) \
|
||||
if((pcb)->poll != NULL) \
|
||||
(ret = (pcb)->poll((pcb)->callback_arg,(pcb)))
|
||||
#define TCP_EVENT_ERR(errf,arg,err) \
|
||||
if((errf) != NULL) \
|
||||
(errf)((arg),(err))
|
||||
|
||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) \
|
||||
do { \
|
||||
if((pcb)->accept != NULL) \
|
||||
(ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_SENT(pcb,space,ret) \
|
||||
do { \
|
||||
if((pcb)->sent != NULL) \
|
||||
(ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) \
|
||||
do { \
|
||||
if((pcb)->recv != NULL) { \
|
||||
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \
|
||||
} else { \
|
||||
(ret) = ERR_OK; \
|
||||
if (p != NULL) \
|
||||
pbuf_free(p); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
|
||||
do { \
|
||||
if((pcb)->connected != NULL) \
|
||||
(ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_POLL(pcb,ret) \
|
||||
do { \
|
||||
if((pcb)->poll != NULL) \
|
||||
(ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_ERR(errf,arg,err) \
|
||||
do { \
|
||||
if((errf) != NULL) \
|
||||
(errf)((arg),(err)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* LWIP_EVENT_API */
|
||||
|
||||
/* This structure represents a TCP segment on the unsent and unacked queues */
|
||||
|
@ -494,9 +523,22 @@ struct tcp_seg {
|
|||
struct pbuf *p; /* buffer containing data + TCP header */
|
||||
void *dataptr; /* pointer to the TCP data in the pbuf */
|
||||
u16_t len; /* the TCP length of this segment */
|
||||
u8_t flags;
|
||||
#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */
|
||||
#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */
|
||||
struct tcp_hdr *tcphdr; /* the TCP header */
|
||||
};
|
||||
|
||||
#define LWIP_TCP_OPT_LENGTH(flags) \
|
||||
(flags & TF_SEG_OPTS_MSS ? 4 : 0) + \
|
||||
(flags & TF_SEG_OPTS_TS ? 12 : 0)
|
||||
|
||||
/** This returns a TCP header option for MSS in an u32_t */
|
||||
#define TCP_BUILD_MSS_OPTION(x) (x) = htonl(((u32_t)2 << 24) | \
|
||||
((u32_t)4 << 16) | \
|
||||
(((u32_t)TCP_MSS / 256) << 8) | \
|
||||
(TCP_MSS & 255))
|
||||
|
||||
/* Internal functions and global variables: */
|
||||
struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
|
||||
void tcp_pcb_purge(struct tcp_pcb *pcb);
|
||||
|
@ -506,21 +548,27 @@ u8_t tcp_segs_free(struct tcp_seg *seg);
|
|||
u8_t tcp_seg_free(struct tcp_seg *seg);
|
||||
struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
|
||||
|
||||
#define tcp_ack(pcb) if((pcb)->flags & TF_ACK_DELAY) { \
|
||||
(pcb)->flags &= ~TF_ACK_DELAY; \
|
||||
(pcb)->flags |= TF_ACK_NOW; \
|
||||
tcp_output(pcb); \
|
||||
} else { \
|
||||
(pcb)->flags |= TF_ACK_DELAY; \
|
||||
}
|
||||
#define tcp_ack(pcb) \
|
||||
do { \
|
||||
if((pcb)->flags & TF_ACK_DELAY) { \
|
||||
(pcb)->flags &= ~TF_ACK_DELAY; \
|
||||
(pcb)->flags |= TF_ACK_NOW; \
|
||||
tcp_output(pcb); \
|
||||
} \
|
||||
else { \
|
||||
(pcb)->flags |= TF_ACK_DELAY; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define tcp_ack_now(pcb) (pcb)->flags |= TF_ACK_NOW; \
|
||||
tcp_output(pcb)
|
||||
#define tcp_ack_now(pcb) \
|
||||
do { \
|
||||
(pcb)->flags |= TF_ACK_NOW; \
|
||||
tcp_output(pcb); \
|
||||
} while (0)
|
||||
|
||||
err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags);
|
||||
err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len,
|
||||
u8_t flags, u8_t apiflags,
|
||||
u8_t *optdata, u8_t optlen);
|
||||
u8_t flags, u8_t apiflags, u8_t optflags);
|
||||
|
||||
void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
|
||||
|
||||
|
@ -614,22 +662,32 @@ extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
|
|||
} while(0)
|
||||
|
||||
#else /* LWIP_DEBUG */
|
||||
#define TCP_REG(pcbs, npcb) do { \
|
||||
npcb->next = *pcbs; \
|
||||
*(pcbs) = npcb; \
|
||||
tcp_timer_needed(); \
|
||||
} while(0)
|
||||
#define TCP_RMV(pcbs, npcb) do { \
|
||||
if(*(pcbs) == npcb) { \
|
||||
(*(pcbs)) = (*pcbs)->next; \
|
||||
} else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
|
||||
tcp_tmp_pcb->next = npcb->next; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
npcb->next = NULL; \
|
||||
} while(0)
|
||||
|
||||
#define TCP_REG(pcbs, npcb) \
|
||||
do { \
|
||||
npcb->next = *pcbs; \
|
||||
*(pcbs) = npcb; \
|
||||
tcp_timer_needed(); \
|
||||
} while (0)
|
||||
|
||||
#define TCP_RMV(pcbs, npcb) \
|
||||
do { \
|
||||
if(*(pcbs) == npcb) { \
|
||||
(*(pcbs)) = (*pcbs)->next; \
|
||||
} \
|
||||
else { \
|
||||
for(tcp_tmp_pcb = *pcbs; \
|
||||
tcp_tmp_pcb != NULL; \
|
||||
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
|
||||
tcp_tmp_pcb->next = npcb->next; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
npcb->next = NULL; \
|
||||
} while(0)
|
||||
|
||||
#endif /* LWIP_DEBUG */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "lwip/pbuf.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -83,10 +84,14 @@ err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg);
|
|||
#endif /* LWIP_NETIF_API */
|
||||
|
||||
err_t tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block);
|
||||
#define tcpip_callback(f,ctx) tcpip_callback_with_block(f,ctx,1)
|
||||
#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1)
|
||||
|
||||
/* free pbufs or heap memory from another context without blocking */
|
||||
err_t pbuf_free_callback(struct pbuf *p);
|
||||
err_t mem_free_callback(void *m);
|
||||
|
||||
err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
|
||||
#define tcpip_untimeout(h, arg) tcpip_timeout(0xffffffff, h, arg)
|
||||
err_t tcpip_untimeout(sys_timeout_handler h, void *arg);
|
||||
|
||||
enum tcpip_msg_type {
|
||||
#if LWIP_NETCONN
|
||||
|
@ -97,7 +102,8 @@ enum tcpip_msg_type {
|
|||
TCPIP_MSG_NETIFAPI,
|
||||
#endif /* LWIP_NETIF_API */
|
||||
TCPIP_MSG_CALLBACK,
|
||||
TCPIP_MSG_TIMEOUT
|
||||
TCPIP_MSG_TIMEOUT,
|
||||
TCPIP_MSG_UNTIMEOUT
|
||||
};
|
||||
|
||||
struct tcpip_msg {
|
||||
|
|
|
@ -151,6 +151,11 @@ void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
|
|||
err_t etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr);
|
||||
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);
|
||||
/** For Ethernet network interfaces, we might want to send "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. */
|
||||
#define etharp_gratuitous(netif) etharp_request((netif), &(netif)->ip_addr)
|
||||
|
||||
err_t ethernet_input(struct pbuf *p, struct netif *netif);
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#ifndef __NETIF_LOOPIF_H__
|
||||
#define __NETIF_LOOPIF_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/err.h"
|
||||
|
||||
|
@ -39,9 +40,9 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !LWIP_LOOPIF_MULTITHREADING
|
||||
void loopif_poll(struct netif *netif);
|
||||
#endif
|
||||
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
#define loopif_poll netif_poll
|
||||
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
|
||||
err_t loopif_init(struct netif *netif);
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
*
|
||||
* This implementation complies with RFC 826 (Ethernet ARP). It supports
|
||||
* Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6
|
||||
* if an interface calls etharp_query(our_netif, its_ip_addr, NULL) upon
|
||||
* address change.
|
||||
* if an interface calls etharp_gratuitous(our_netif) upon address change.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -353,7 +352,7 @@ find_entry(struct ip_addr *ipaddr, u8_t flags)
|
|||
* 1) empty entry
|
||||
* 2) oldest stable entry
|
||||
* 3) oldest pending entry without queued packets
|
||||
* 4) oldest pending entry without queued packets
|
||||
* 4) oldest pending entry with queued packets
|
||||
*
|
||||
* { ETHARP_TRY_HARD is set at this point }
|
||||
*/
|
||||
|
@ -705,7 +704,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||
hdr->opcode = htons(ARP_REPLY);
|
||||
|
||||
hdr->dipaddr = hdr->sipaddr;
|
||||
hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr;
|
||||
SMEMCPY(&hdr->sipaddr, &netif->ip_addr, sizeof(hdr->sipaddr));
|
||||
|
||||
LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
|
||||
(netif->hwaddr_len == ETHARP_HWADDR_LEN));
|
||||
|
@ -1041,7 +1040,7 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
|
|||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
/* allocate a pbuf for the outgoing ARP request packet */
|
||||
p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(struct etharp_hdr), PBUF_RAM);
|
||||
/* could allocate a pbuf for an ARP request? */
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 2, ("etharp_raw: could not allocate pbuf for ARP request.\n"));
|
||||
|
@ -1130,6 +1129,13 @@ ethernet_input(struct pbuf *p, struct netif *netif)
|
|||
|
||||
/* points to packet payload, which starts with an Ethernet header */
|
||||
ethhdr = p->payload;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
|
||||
("ethernet_input: dest:%02x:%02x:%02x:%02x:%02x:%02x, src:%02x:%02x:%02x:%02x:%02x:%02x, type:%2hx\n",
|
||||
(unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
|
||||
(unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
|
||||
(unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
|
||||
(unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
|
||||
(unsigned)htons(ethhdr->type)));
|
||||
|
||||
switch (htons(ethhdr->type)) {
|
||||
/* IP packet? */
|
||||
|
@ -1165,6 +1171,8 @@ ethernet_input(struct pbuf *p, struct netif *netif)
|
|||
#endif /* PPPOE_SUPPORT */
|
||||
|
||||
default:
|
||||
ETHARP_STATS_INC(etharp.proterr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
pbuf_free(p);
|
||||
p = NULL;
|
||||
break;
|
||||
|
|
|
@ -40,149 +40,8 @@
|
|||
#if LWIP_HAVE_LOOPIF
|
||||
|
||||
#include "netif/loopif.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if !LWIP_LOOPIF_MULTITHREADING
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/mem.h"
|
||||
|
||||
/* helper struct for the linked list of pbufs */
|
||||
struct loopif_private {
|
||||
struct pbuf *first;
|
||||
struct pbuf *last;
|
||||
};
|
||||
|
||||
/**
|
||||
* Call loopif_poll() in the main loop of your application. This is to prevent
|
||||
* reentering non-reentrant functions like tcp_input(). Packets passed to
|
||||
* loopif_output() are put on a list that is passed to netif->input() by
|
||||
* loopif_poll().
|
||||
*
|
||||
* @param netif the lwip network interface structure for this loopif
|
||||
*/
|
||||
void
|
||||
loopif_poll(struct netif *netif)
|
||||
{
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
struct pbuf *in, *in_end;
|
||||
struct loopif_private *priv = (struct loopif_private*)netif->state;
|
||||
|
||||
LWIP_ERROR("priv != NULL", (priv != NULL), return;);
|
||||
|
||||
do {
|
||||
/* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
in = priv->first;
|
||||
if(in) {
|
||||
in_end = in;
|
||||
while(in_end->len != in_end->tot_len) {
|
||||
LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
|
||||
in_end = in_end->next;
|
||||
}
|
||||
/* 'in_end' now points to the last pbuf from 'in' */
|
||||
if(in_end == priv->last) {
|
||||
/* this was the last pbuf in the list */
|
||||
priv->first = priv->last = NULL;
|
||||
} else {
|
||||
/* pop the pbuf off the list */
|
||||
priv->first = in_end->next;
|
||||
LWIP_ASSERT("should not be null since first != last!", priv->first != NULL);
|
||||
}
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
||||
if(in != NULL) {
|
||||
if(in_end->next != NULL) {
|
||||
/* De-queue the pbuf from its successors on the 'priv' list. */
|
||||
in_end->next = NULL;
|
||||
}
|
||||
if(netif->input(in, netif) != ERR_OK) {
|
||||
pbuf_free(in);
|
||||
}
|
||||
/* Don't reference the packet any more! */
|
||||
in = NULL;
|
||||
in_end = NULL;
|
||||
}
|
||||
/* go on while there is a packet on the list */
|
||||
} while(priv->first != NULL);
|
||||
}
|
||||
#endif /* LWIP_LOOPIF_MULTITHREADING */
|
||||
|
||||
/**
|
||||
* Send an IP packet over the loopback interface.
|
||||
* The pbuf is simply copied and handed back to netif->input.
|
||||
* In multithreaded mode, this is done directly since netif->input must put
|
||||
* the packet on a queue.
|
||||
* In callback mode, the packet is put on an internal queue and is fed to
|
||||
* netif->input by loopif_poll().
|
||||
*
|
||||
* @param netif the lwip network interface structure for this loopif
|
||||
* @param p the (IP) packet to 'send'
|
||||
* @param ipaddr the ip address to send the packet to (not used for loopif)
|
||||
* @return ERR_OK if the packet has been sent
|
||||
* ERR_MEM if the pbuf used to copy the packet couldn't be allocated
|
||||
*/
|
||||
static err_t
|
||||
loopif_output(struct netif *netif, struct pbuf *p,
|
||||
struct ip_addr *ipaddr)
|
||||
{
|
||||
#if !LWIP_LOOPIF_MULTITHREADING
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
struct loopif_private *priv;
|
||||
struct pbuf *last;
|
||||
#endif /* LWIP_LOOPIF_MULTITHREADING */
|
||||
struct pbuf *r;
|
||||
err_t err;
|
||||
|
||||
LWIP_UNUSED_ARG(ipaddr);
|
||||
|
||||
/* Allocate a new pbuf */
|
||||
r = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
|
||||
if (r == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
/* Copy the whole pbuf queue p into the single pbuf r */
|
||||
if ((err = pbuf_copy(r, p)) != ERR_OK) {
|
||||
pbuf_free(r);
|
||||
r = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
#if LWIP_LOOPIF_MULTITHREADING
|
||||
/* Multithreading environment, netif->input() is supposed to put the packet
|
||||
into a mailbox, so we can safely call it here without risking to re-enter
|
||||
functions that are not reentrant (TCP!!!) */
|
||||
if(netif->input(r, netif) != ERR_OK) {
|
||||
pbuf_free(r);
|
||||
r = NULL;
|
||||
}
|
||||
#else /* LWIP_LOOPIF_MULTITHREADING */
|
||||
/* Raw API without threads: put the packet on a linked list which gets emptied
|
||||
through calling loopif_poll(). */
|
||||
priv = (struct loopif_private*)netif->state;
|
||||
|
||||
/* let last point to the last pbuf in chain r */
|
||||
for (last = r; last->next != NULL; last = last->next);
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
if(priv->first != NULL) {
|
||||
LWIP_ASSERT("if first != NULL, last must also be != NULL", priv->last != NULL);
|
||||
priv->last->next = r;
|
||||
priv->last = last;
|
||||
} else {
|
||||
priv->first = r;
|
||||
priv->last = last;
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
#endif /* LWIP_LOOPIF_MULTITHREADING */
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a lwip network interface structure for a loopback interface
|
||||
*
|
||||
|
@ -193,16 +52,6 @@ loopif_output(struct netif *netif, struct pbuf *p,
|
|||
err_t
|
||||
loopif_init(struct netif *netif)
|
||||
{
|
||||
#if !LWIP_LOOPIF_MULTITHREADING
|
||||
struct loopif_private *priv;
|
||||
|
||||
priv = (struct loopif_private*)mem_malloc(sizeof(struct loopif_private));
|
||||
if(priv == NULL)
|
||||
return ERR_MEM;
|
||||
priv->first = priv->last = NULL;
|
||||
netif->state = priv;
|
||||
#endif /* LWIP_LOOPIF_MULTITHREADING */
|
||||
|
||||
/* initialize the snmp variables and counters inside the struct netif
|
||||
* ifSpeed: no assumption can be made!
|
||||
*/
|
||||
|
@ -210,7 +59,7 @@ loopif_init(struct netif *netif)
|
|||
|
||||
netif->name[0] = 'l';
|
||||
netif->name[1] = 'o';
|
||||
netif->output = loopif_output;
|
||||
netif->output = netif_loop_output;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -518,16 +518,18 @@ upap_rauthnak(upap_state *u, u_char *inp, int id, int len)
|
|||
*/
|
||||
if (len < sizeof (u_char)) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
|
||||
return;
|
||||
} else {
|
||||
GETCHAR(msglen, inp);
|
||||
if(msglen > 0) {
|
||||
len -= sizeof (u_char);
|
||||
if (len < msglen) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
msg = (char *) inp;
|
||||
PRINTMSG(msg, msglen);
|
||||
}
|
||||
}
|
||||
GETCHAR(msglen, inp);
|
||||
len -= sizeof (u_char);
|
||||
if (len < msglen) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
msg = (char *) inp;
|
||||
PRINTMSG(msg, msglen);
|
||||
|
||||
u->us_clientstate = UPAPCS_BADAUTH;
|
||||
|
||||
|
|
|
@ -1056,7 +1056,7 @@ pppWriteOverEthernet(int pd, const u_char *s, int n)
|
|||
|
||||
pc->lastXMit = sys_jiffies();
|
||||
|
||||
SMEMCPY(pb->payload, s, n);
|
||||
MEMCPY(pb->payload, s, n);
|
||||
|
||||
if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
|
||||
LINK_STATS_INC(link.err);
|
||||
|
@ -1339,10 +1339,6 @@ sifup(int pd)
|
|||
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)) {
|
||||
netif_set_up(&pc->netif);
|
||||
#if LWIP_DHCP
|
||||
/* ugly workaround for storing a reference to the ppp related info*/
|
||||
pc->netif.dhcp = (struct dhcp *) &pc->addrs;
|
||||
#endif /* LWIP_DHCP */
|
||||
pc->if_up = 1;
|
||||
pc->errCode = PPPERR_NONE;
|
||||
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
|
||||
#include "netif/slipif.h"
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_HAVE_SLIPIF
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
|
@ -273,3 +276,4 @@ slipif_init(struct netif *netif)
|
|||
sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop, netif, SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* LWIP_HAVE_SLIPIF */
|
||||
|
|
Loading…
Reference in New Issue