mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-02-07 01:22:37 +08:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
|
||||
@@ -76,9 +76,10 @@ typedef rt_uint32_t mem_ptr_t;
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#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);
|
||||
@@ -152,14 +161,14 @@ static void
|
||||
dhcp_handle_nak(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
|
||||
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
/* Set the interface down since the address must no longer be used, as per RFC2131 */
|
||||
netif_set_down(netif);
|
||||
/* remove IP address from interface */
|
||||
netif_set_ipaddr(netif, IP_ADDR_ANY);
|
||||
netif_set_gw(netif, IP_ADDR_ANY);
|
||||
netif_set_netmask(netif, IP_ADDR_ANY);
|
||||
netif_set_netmask(netif, IP_ADDR_ANY);
|
||||
/* Change to a defined state */
|
||||
dhcp_set_state(dhcp, DHCP_BACKING_OFF);
|
||||
/* We can immediately restart discovery */
|
||||
@@ -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;
|
||||
@@ -330,7 +339,7 @@ dhcp_coarse_tmr()
|
||||
*
|
||||
* A DHCP server is expected to respond within a short period of time.
|
||||
* This timer checks whether an outstanding DHCP request is timed out.
|
||||
*
|
||||
*
|
||||
*/
|
||||
void
|
||||
dhcp_fine_tmr()
|
||||
@@ -340,7 +349,7 @@ dhcp_fine_tmr()
|
||||
while (netif != NULL) {
|
||||
/* only act on DHCP configured interfaces */
|
||||
if (netif->dhcp != NULL) {
|
||||
/* timer is active (non zero), and is about to trigger now */
|
||||
/* timer is active (non zero), and is about to trigger now */
|
||||
if (netif->dhcp->request_timeout > 1) {
|
||||
netif->dhcp->request_timeout--;
|
||||
}
|
||||
@@ -526,7 +535,7 @@ dhcp_handle_ack(struct netif *netif)
|
||||
if (option_ptr != NULL) {
|
||||
dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
|
||||
}
|
||||
|
||||
|
||||
/* DNS servers */
|
||||
option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_DNS_SERVER);
|
||||
if (option_ptr != NULL) {
|
||||
@@ -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,8 +601,14 @@ 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 */
|
||||
memset(dhcp, 0, sizeof(struct dhcp));
|
||||
/* allocate UDP PCB */
|
||||
@@ -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);
|
||||
@@ -1022,7 +1075,7 @@ dhcp_release(struct netif *netif)
|
||||
dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0;
|
||||
dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
|
||||
dhcp->dns_count = 0;
|
||||
|
||||
|
||||
/* create and initialize the DHCP message header */
|
||||
result = dhcp_create_request(netif);
|
||||
if (result == ERR_OK) {
|
||||
@@ -1050,7 +1103,7 @@ dhcp_release(struct netif *netif)
|
||||
netif_set_ipaddr(netif, IP_ADDR_ANY);
|
||||
netif_set_gw(netif, IP_ADDR_ANY);
|
||||
netif_set_netmask(netif, IP_ADDR_ANY);
|
||||
|
||||
|
||||
/* TODO: netif_down(netif); */
|
||||
return result;
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
RandomIPAddr->addr = (0xA9FE0100 + ((u32_t)(((u8_t)(netif->hwaddr[4])) |
|
||||
((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)) + netif->autoip->tried_llipaddr);
|
||||
* We have 254 * 256 possibilities */
|
||||
|
||||
if (RandomIPAddr->addr>0xA9FEFEFF) {
|
||||
RandomIPAddr->addr = (0xA9FE0100 + (RandomIPAddr->addr-0xA9FEFEFF));
|
||||
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 (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
|
||||
@@ -308,27 +321,20 @@ memp_malloc_fn(memp_t type, const char* file, const int line)
|
||||
|
||||
memp = memp_tab[type];
|
||||
|
||||
if (memp != NULL) {
|
||||
memp_tab[type] = memp->next;
|
||||
if (memp != NULL) {
|
||||
memp_tab[type] = memp->next;
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
memp->next = NULL;
|
||||
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;
|
||||
@@ -228,7 +233,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((netif = ip_route(ipaddr)) == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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,16 +173,20 @@ 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) ||
|
||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)) ||
|
||||
((!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)) {
|
||||
/* the first unconnected matching PCB */
|
||||
/* the first unconnected matching PCB */
|
||||
uncon_pcb = pcb;
|
||||
}
|
||||
}
|
||||
@@ -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"));
|
||||
@@ -496,7 +512,7 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
@@ -519,7 +535,7 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
@@ -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__ */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user