提交 b9290bce 编写于 作者: B bernard.xiong

update lwip to 1.3.1

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@37 bbd45198-f89e-11dd-88c7-29a3b14d5316
上级 1ae9da27
......@@ -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 Frdric 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 Frdric 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, Frdric 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, Frdric 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 Frdric 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)
......
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;
}
......
此差异已折叠。
......@@ -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)
......
#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 */
u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif));
addr += netif->autoip->tried_llipaddr;
addr = AUTOIP_NET | (addr & 0xffff);
/* Now, 169.254.0.0 <= addr <= 169.254.255.255 */
if (RandomIPAddr->addr>0xA9FEFEFF) {
RandomIPAddr->addr = (0xA9FE0100 + (RandomIPAddr->addr-0xA9FEFEFF));
if (addr < AUTOIP_RANGE_START) {
addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
}
if (RandomIPAddr->addr<0xA9FE0100) {
RandomIPAddr->addr = (0xA9FEFEFF - (0xA9FE0100-RandomIPAddr->addr));
if (addr > AUTOIP_RANGE_END) {
addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
}
RandomIPAddr->addr = htonl(RandomIPAddr->addr);
LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
(addr <= AUTOIP_RANGE_END));
IPAddr->addr = htonl(addr);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
("autoip_create_rand_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n",
(u16_t)(netif->autoip->tried_llipaddr), (u32_t)(RandomIPAddr->addr)));
("autoip_create_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n",
(u16_t)(netif->autoip->tried_llipaddr), (u32_t)(IPAddr->addr)));
}
/**
......@@ -258,7 +279,7 @@ autoip_start(struct netif *netif)
autoip->lastconflict = 0;
}
autoip_create_rand_addr(netif, &(autoip->llipaddr));
autoip_create_addr(netif, &(autoip->llipaddr));
autoip->tried_llipaddr++;
autoip->state = AUTOIP_STATE_PROBING;
autoip->sent_num = 0;
......@@ -395,8 +416,8 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
* structure packing (not using structure copy which breaks strict-aliasing rules).
*/
MEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
MEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
......
......@@ -53,9 +53,18 @@
#include <string.h>
/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
* used to modify and send a response packet (and to 1 if this is not the case,
* e.g. when link header is stripped of when receiving) */
#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
/* The amount of data from the original packet to return in a dest-unreachable */
#define ICMP_DEST_UNREACH_DATASIZE 8
static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
/**
* Processes ICMP input packets, called from ip_input().
*
......@@ -94,13 +103,30 @@ icmp_input(struct pbuf *p, struct netif *inp)
#endif /* LWIP_DEBUG */
switch (type) {
case ICMP_ECHO:
/* broadcast or multicast destination address? */
if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
ICMP_STATS_INC(icmp.err);
pbuf_free(p);
return;
#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
{
int accepted = 1;
#if !LWIP_MULTICAST_PING
/* multicast destination address? */
if (ip_addr_ismulticast(&iphdr->dest)) {
accepted = 0;
}
#endif /* LWIP_MULTICAST_PING */
#if !LWIP_BROADCAST_PING
/* broadcast destination address? */
if (ip_addr_isbroadcast(&iphdr->dest, inp)) {
accepted = 0;
}
#endif /* LWIP_BROADCAST_PING */
/* broadcast or multicast destination address not acceptd? */
if (!accepted) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
ICMP_STATS_INC(icmp.err);
pbuf_free(p);
return;
}
}
#endif /* !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
......@@ -113,6 +139,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
snmp_inc_icmpinerrors();
return;
}
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) {
/* p is not big enough to contain link headers
* allocate a new one and copy p into it
......@@ -153,6 +180,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
goto memerr;
}
}
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
/* At this point, all checks are OK. */
/* We generate an answer by switching the dest and src ip addresses,
* setting the icmp type to ECHO_RESPONSE and updating the checksum. */
......@@ -205,11 +233,13 @@ lenerr:
ICMP_STATS_INC(icmp.lenerr);
snmp_inc_icmpinerrors();
return;
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
memerr:
pbuf_free(p);
ICMP_STATS_INC(icmp.err);
snmp_inc_icmpinerrors();
return;
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
}
/**
......@@ -224,40 +254,7 @@ memerr:
void
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
{
struct pbuf *q;
struct ip_hdr *iphdr;
struct icmp_dur_hdr *idur;
/* ICMP header + IP header + 8 bytes of data */
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
PBUF_RAM);
if (q == NULL) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n"));
return;
}
LWIP_ASSERT("check that first pbuf can hold icmp message",
(q->len >= (sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
iphdr = p->payload;
idur = q->payload;
ICMPH_TYPE_SET(idur, ICMP_DUR);
ICMPH_CODE_SET(idur, t);
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_dur_hdr), p->payload,
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
/* calculate checksum */
idur->chksum = 0;
idur->chksum = inet_chksum(idur, q->len);
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpoutdestunreachs();
ip_output(q, NULL, &(iphdr->src), ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q);
icmp_send_response(p, ICMP_DUR, t);
}
#if IP_FORWARD || IP_REASSEMBLY
......@@ -270,20 +267,37 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
*/
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
{
icmp_send_response(p, ICMP_TE, t);
}
#endif /* IP_FORWARD || IP_REASSEMBLY */
/**
* Send an icmp packet in response to an incoming packet.
*
* @param p the input packet for which the 'unreachable' should be sent,
* p->payload pointing to the IP header
* @param type Type of the ICMP header
* @param code Code of the ICMP header
*/
static void
icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
{
struct pbuf *q;
struct ip_hdr *iphdr;
struct icmp_te_hdr *tehdr;
/* we can use the echo header here */
struct icmp_echo_hdr *icmphdr;
/* ICMP header + IP header + 8 bytes of data */
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
PBUF_RAM);
if (q == NULL) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
return;
}
LWIP_ASSERT("check that first pbuf can hold icmp message",
(q->len >= (sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
(q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
iphdr = p->payload;
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
......@@ -292,17 +306,19 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
tehdr = q->payload;
ICMPH_TYPE_SET(tehdr, ICMP_TE);
ICMPH_CODE_SET(tehdr, t);
icmphdr = q->payload;
icmphdr->type = type;
icmphdr->code = code;
icmphdr->id = 0;
icmphdr->seqno = 0;
/* copy fields from original packet */
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_dur_hdr), (u8_t *)p->payload,
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
/* calculate checksum */
tehdr->chksum = 0;
tehdr->chksum = inet_chksum(tehdr, q->len);
icmphdr->chksum = 0;
icmphdr->chksum = inet_chksum(icmphdr, q->len);
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
......@@ -312,6 +328,4 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
pbuf_free(q);
}
#endif /* IP_FORWARD */
#endif /* LWIP_ICMP */
......@@ -128,7 +128,7 @@ igmp_dump_group_list()
while (group != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state)));
ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
LWIP_DEBUGF(IGMP_DEBUG, (" on if %x\n", (int) group->interface));
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->interface));
group = group->next;
}
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
......@@ -147,7 +147,7 @@ igmp_start(struct netif *netif)
{
struct igmp_group* group;
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %x\n", (int) netif));
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", netif));
group = igmp_lookup_group(netif, &allsystems);
......@@ -159,7 +159,7 @@ igmp_start(struct netif *netif)
if (netif->igmp_mac_filter != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD "));
ip_addr_debug_print(IGMP_DEBUG, &allsystems);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif));
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
netif->igmp_mac_filter( netif, &allsystems, IGMP_ADD_MAC_FILTER);
}
......@@ -198,7 +198,7 @@ igmp_stop(struct netif *netif)
if (netif->igmp_mac_filter != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL "));
ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif));
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER);
}
/* free group */
......@@ -223,7 +223,7 @@ igmp_report_groups( struct netif *netif)
{
struct igmp_group *group = igmp_group_list;
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %x\n", (int) netif));
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif));
while (group != NULL) {
if (group->interface == netif) {
......@@ -295,7 +295,7 @@ igmp_lookup_group(struct netif *ifp, struct ip_addr *addr)
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));
ip_addr_debug_print(IGMP_DEBUG, addr);
LWIP_DEBUGF(IGMP_DEBUG, (" on if %x\n", (int) ifp));
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", ifp));
return group;
}
......@@ -361,7 +361,7 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
ip_addr_debug_print(IGMP_DEBUG, &(iphdr->src));
LWIP_DEBUGF(IGMP_DEBUG, (" to address "));
ip_addr_debug_print(IGMP_DEBUG, &(iphdr->dest));
LWIP_DEBUGF(IGMP_DEBUG, (" on if %x\n", (int) inp));
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp));
/* Now calculate and check the checksum */
igmp = (struct igmp_msg *)p->payload;
......@@ -439,7 +439,8 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
break;
}
default: {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %x in state %x on group %x on if %x\n", (int) igmp->igmp_msgtype, (int) group->group_state, (int) &group, (int) group->interface));
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n",
igmp->igmp_msgtype, group->group_state, &group, group->interface));
break;
}
}
......@@ -488,7 +489,7 @@ igmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
if ((group->use==0) && (netif->igmp_mac_filter != NULL)) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD "));
ip_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif));
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER);
}
......@@ -563,7 +564,7 @@ igmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
if (netif->igmp_mac_filter != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL "));
ip_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif));
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER);
}
......@@ -624,7 +625,7 @@ igmp_timeout(struct igmp_group *group)
if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address "));
ip_addr_debug_print(IGMP_DEBUG, &(group->group_address));
LWIP_DEBUGF(IGMP_DEBUG, (" on if %x\n", (int) group->interface));
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->interface));
igmp_send(group, IGMP_V2_MEMB_REPORT);
}
......@@ -666,7 +667,8 @@ igmp_stop_timer(struct igmp_group *group)
void
igmp_delaying_member( struct igmp_group *group, u8_t maxresp)
{
if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && (maxresp > group->timer))) {
if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) ||
((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && (maxresp > group->timer))) {
igmp_start_timer(group, (maxresp)/2);
group->group_state = IGMP_GROUP_DELAYING_MEMBER;
}
......@@ -695,64 +697,11 @@ err_t
igmp_ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto, struct netif *netif)
{
static u16_t ip_id = 0;
struct ip_hdr * iphdr = NULL;
u16_t * ra = NULL;
/* First write in the "router alert" */
if (pbuf_header(p, ROUTER_ALERTLEN)) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_ip_output_if: not enough room for IP header in pbuf\n"));
return ERR_BUF;
}
/* This is the "router alert" option */
ra = p->payload;
u16_t ra[2];
ra[0] = htons (ROUTER_ALERT);
ra[1] = 0x0000; /* Router shall examine packet */
/* now the normal ip header */
if (pbuf_header(p, IP_HLEN)) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_ip_output_if: not enough room for IP header in pbuf\n"));
return ERR_BUF;
}
iphdr = p->payload;
/* Should the IP header be generated or is it already included in p? */
if (dest != IP_HDRINCL) {
/** @todo should be shared with ip.c - ip_output_if */
IPH_TTL_SET(iphdr, ttl);
IPH_PROTO_SET(iphdr, proto);
ip_addr_set(&(iphdr->dest), dest);
IPH_VHLTOS_SET(iphdr, 4, ((IP_HLEN + ROUTER_ALERTLEN) / 4), 0/*tos*/);
IPH_LEN_SET(iphdr, htons(p->tot_len));
IPH_OFFSET_SET(iphdr, 0);
IPH_ID_SET(iphdr, htons(ip_id));
++ip_id;
if (ip_addr_isany(src)) {
ip_addr_set(&(iphdr->src), &(netif->ip_addr));
} else {
ip_addr_set(&(iphdr->src), src);
}
IPH_CHKSUM_SET(iphdr, 0);
#if CHECKSUM_GEN_IP
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, (IP_HLEN + ROUTER_ALERTLEN)));
#endif
} else {
dest = &(iphdr->dest);
}
#if IP_DEBUG
ip_debug_print(p);
#endif
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_ip_output_if: sending to if %x\n", (int) netif));
return netif->output(netif, p, dest);
return ip_output_if_opt(p, src, dest, ttl, 0, proto, netif, ra, ROUTER_ALERTLEN);
}
/**
......@@ -796,10 +745,10 @@ igmp_send(struct igmp_group *group, u8_t type)
igmp->igmp_checksum = 0;
igmp->igmp_checksum = inet_chksum( igmp, IGMP_MINLEN);
igmp_ip_output_if( p, &src, dest, IGMP_TTL, IP_PROTO_IGMP, group->interface);
igmp_ip_output_if(p, &src, dest, IGMP_TTL, IP_PROTO_IGMP, group->interface);
}
pbuf_free (p);
pbuf_free(p);
} else {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n"));
}
......
......@@ -83,7 +83,8 @@ int
inet_aton(const char *cp, struct in_addr *addr)
{
u32_t val;
int base, n, c;
u8_t base;
char c;
u32_t parts[4];
u32_t *pp = parts;
......@@ -133,14 +134,13 @@ inet_aton(const char *cp, struct in_addr *addr)
/*
* Check for trailing characters.
*/
if (c != '\0' && (!isprint(c) || !isspace(c)))
if (c != '\0' && !isspace(c))
return (0);
/*
* Concoct the address according to
* the number of parts specified.
*/
n = pp - parts + 1;
switch (n) {
switch (pp - parts + 1) {
case 0:
return (0); /* initial nondigit */
......
......@@ -41,7 +41,7 @@
#include "lwip/inet_chksum.h"
#include "lwip/inet.h"
#include <string.h>
#include <stddef.h>
/* These are some reference implementations of the checksum algorithm, with the
* aim of being simple, correct and fully portable. Checksumming is the
......@@ -65,6 +65,18 @@
# define LWIP_CHKSUM_ALGORITHM 0
#endif
/** Like the name says... */
#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)
/* little endian and PLATFORM_BYTESWAP defined */
#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w)
#else
/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */
#define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8)
#endif
/** Split an u32_t in two u16_ts and add them up */
#define FOLD_U32T(u) ((u >> 16) + (u & 0x0000ffffUL))
#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
/**
* lwip checksum
......@@ -86,8 +98,7 @@ lwip_standard_chksum(void *dataptr, u16_t len)
acc = 0;
/* dataptr may be at odd or even addresses */
octetptr = (u8_t*)dataptr;
while (len > 1)
{
while (len > 1) {
/* declare first octet as most significant
thus assume network order, ignoring host order */
src = (*octetptr) << 8;
......@@ -98,15 +109,14 @@ lwip_standard_chksum(void *dataptr, u16_t len)
acc += src;
len -= 2;
}
if (len > 0)
{
if (len > 0) {
/* accumulate remaining octet */
src = (*octetptr) << 8;
acc += src;
}
/* add deferred carry bits */
acc = (acc >> 16) + (acc & 0x0000ffffUL);
if ((acc & 0xffff0000) != 0) {
if ((acc & 0xffff0000UL) != 0) {
acc = (acc >> 16) + (acc & 0x0000ffffUL);
}
/* This maybe a little confusing: reorder sum using htons()
......@@ -154,19 +164,22 @@ lwip_standard_chksum(void *dataptr, int len)
}
/* Consume left-over byte, if any */
if (len > 0)
if (len > 0) {
((u8_t *)&t)[0] = *(u8_t *)ps;;
}
/* Add end bytes */
sum += t;
/* Fold 32-bit sum to 16 bits */
while ((sum >> 16) != 0)
sum = (sum & 0xffff) + (sum >> 16);
/* Fold 32-bit sum to 16 bits
calling this twice is propably faster than if statements... */
sum = FOLD_U32T(sum);
sum = FOLD_U32T(sum);
/* Swap if alignment was odd */
if (odd)
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
if (odd) {
sum = SWAP_BYTES_IN_WORD(sum);
}
return sum;
}
......@@ -211,18 +224,20 @@ lwip_standard_chksum(void *dataptr, int len)
while (len > 7) {
tmp = sum + *pl++; /* ping */
if (tmp < sum)
if (tmp < sum) {
tmp++; /* add back carry */
}
sum = tmp + *pl++; /* pong */
if (sum < tmp)
if (sum < tmp) {
sum++; /* add back carry */
}
len -= 8;
}
/* make room in upper bits */
sum = (sum >> 16) + (sum & 0xffff);
sum = FOLD_U32T(sum);
ps = (u16_t *)pl;
......@@ -233,16 +248,20 @@ lwip_standard_chksum(void *dataptr, int len)
}
/* dangling tail byte remaining? */
if (len > 0) /* include odd byte */
if (len > 0) { /* include odd byte */
((u8_t *)&t)[0] = *(u8_t *)ps;
}
sum += t; /* add end bytes */
while ((sum >> 16) != 0) /* combine halves */
sum = (sum >> 16) + (sum & 0xffff);
/* Fold 32-bit sum to 16 bits
calling this twice is propably faster than if statements... */
sum = FOLD_U32T(sum);
sum = FOLD_U32T(sum);
if (odd)
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
if (odd) {
sum = SWAP_BYTES_IN_WORD(sum);
}
return sum;
}
......@@ -277,18 +296,18 @@ inet_chksum_pseudo(struct pbuf *p,
(void *)q, (void *)q->next));
acc += LWIP_CHKSUM(q->payload, q->len);
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
while ((acc >> 16) != 0) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
/* just executing this next line is probably faster that the if statement needed
to check whether we really need to execute it, and does no harm */
acc = FOLD_U32T(acc);
if (q->len % 2 != 0) {
swapped = 1 - swapped;
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
acc = SWAP_BYTES_IN_WORD(acc);
}
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
}
if (swapped) {
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
acc = SWAP_BYTES_IN_WORD(acc);
}
acc += (src->addr & 0xffffUL);
acc += ((src->addr >> 16) & 0xffffUL);
......@@ -297,9 +316,10 @@ inet_chksum_pseudo(struct pbuf *p,
acc += (u32_t)htons((u16_t)proto);
acc += (u32_t)htons(proto_len);
while ((acc >> 16) != 0) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
/* Fold 32-bit sum to 16 bits
calling this twice is propably faster than if statements... */
acc = FOLD_U32T(acc);
acc = FOLD_U32T(acc);
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
return (u16_t)~(acc & 0xffffUL);
}
......@@ -316,6 +336,8 @@ inet_chksum_pseudo(struct pbuf *p,
* @param proto_len length of the ip data part (used for checksum of pseudo header)
* @return checksum (as u16_t) to be saved directly in the protocol header
*/
/* Currently only used by UDPLITE, although this could change in the future. */
#if LWIP_UDPLITE
u16_t
inet_chksum_pseudo_partial(struct pbuf *p,
struct ip_addr *src, struct ip_addr *dest,
......@@ -340,18 +362,17 @@ inet_chksum_pseudo_partial(struct pbuf *p,
chksum_len -= chklen;
LWIP_ASSERT("delete me", chksum_len < 0x7fff);
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
while ((acc >> 16) != 0) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
/* fold the upper bit down */
acc = FOLD_U32T(acc);
if (q->len % 2 != 0) {
swapped = 1 - swapped;
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
acc = SWAP_BYTES_IN_WORD(acc);
}
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
}
if (swapped) {
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
acc = SWAP_BYTES_IN_WORD(acc);
}
acc += (src->addr & 0xffffUL);
acc += ((src->addr >> 16) & 0xffffUL);
......@@ -360,12 +381,14 @@ inet_chksum_pseudo_partial(struct pbuf *p,
acc += (u32_t)htons((u16_t)proto);
acc += (u32_t)htons(proto_len);
while ((acc >> 16) != 0) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
/* Fold 32-bit sum to 16 bits
calling this twice is propably faster than if statements... */
acc = FOLD_U32T(acc);
acc = FOLD_U32T(acc);
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
return (u16_t)~(acc & 0xffffUL);
}
#endif /* LWIP_UDPLITE */
/* inet_chksum:
*
......@@ -380,13 +403,7 @@ inet_chksum_pseudo_partial(struct pbuf *p,
u16_t
inet_chksum(void *dataptr, u16_t len)
{
u32_t acc;
acc = LWIP_CHKSUM(dataptr, len);
while ((acc >> 16) != 0) {
acc = (acc & 0xffff) + (acc >> 16);
}
return (u16_t)~(acc & 0xffff);
return ~LWIP_CHKSUM(dataptr, len);
}
/**
......@@ -407,17 +424,15 @@ inet_chksum_pbuf(struct pbuf *p)
swapped = 0;
for(q = p; q != NULL; q = q->next) {
acc += LWIP_CHKSUM(q->payload, q->len);
while ((acc >> 16) != 0) {
acc = (acc & 0xffffUL) + (acc >> 16);
}
acc = FOLD_U32T(acc);
if (q->len % 2 != 0) {
swapped = 1 - swapped;
acc = (acc & 0x00ffUL << 8) | (acc & 0xff00UL >> 8);
acc = SWAP_BYTES_IN_WORD(acc);
}
}
if (swapped) {
acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
acc = SWAP_BYTES_IN_WORD(acc);
}
return (u16_t)~(acc & 0xffffUL);
}
......@@ -56,6 +56,47 @@
#include "lwip/stats.h"
#include "arch/perf.h"
#include <string.h>
/**
* The interface that provided the packet for the current callback
* invocation.
*/
static struct netif *current_netif;
/**
* Header of the input packet currently being processed.
*/
static const struct ip_hdr *current_header;
/**
* Get the interface that received the current packet.
*
* This function must only be called from a receive callback (udp_recv,
* raw_recv, tcp_accept). It will return NULL otherwise.
*
* @param pcb Pointer to the pcb receiving a packet.
*/
struct netif *
ip_current_netif(void)
{
return current_netif;
}
/**
* Get the IP header of the current packet.
*
* This function must only be called from a receive callback (udp_recv,
* raw_recv, tcp_accept). It will return NULL otherwise.
*
* @param pcb Pointer to the pcb receiving a packet.
*/
const struct ip_hdr *
ip_current_header(void)
{
return current_header;
}
/**
* Finds the appropriate network interface for a given IP address. It
* searches the list of network interfaces linearly. A match is found
......@@ -388,6 +429,9 @@ ip_input(struct pbuf *p, struct netif *inp)
ip_debug_print(p);
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
current_netif = inp;
current_header = iphdr;
#if LWIP_RAW
/* raw input did not eat the packet? */
if (raw_input(p, inp) == 0)
......@@ -440,6 +484,9 @@ ip_input(struct pbuf *p, struct netif *inp)
}
}
current_netif = NULL;
current_header = NULL;
return ERR_OK;
}
......@@ -473,6 +520,21 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t tos,
u8_t proto, struct netif *netif)
{
#if IP_OPTIONS_SEND
return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0);
}
/**
* Same as ip_output_if() but with the possibility to include IP options:
*
* @ param ip_options pointer to the IP options, copied into the IP header
* @ param optlen length of ip_options
*/
err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
u16_t optlen)
{
#endif /* IP_OPTIONS_SEND */
struct ip_hdr *iphdr;
static u16_t ip_id = 0;
......@@ -480,6 +542,27 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
/* Should the IP header be generated or is it already included in p? */
if (dest != IP_HDRINCL) {
u16_t ip_hlen = IP_HLEN;
#if IP_OPTIONS_SEND
u16_t optlen_aligned = 0;
if (optlen != 0) {
/* round up to a multiple of 4 */
optlen_aligned = ((optlen + 3) & ~3);
ip_hlen += optlen_aligned;
/* First write in the IP options */
if (pbuf_header(p, optlen_aligned)) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output_if_opt: not enough room for IP options in pbuf\n"));
IP_STATS_INC(ip.err);
snmp_inc_ipoutdiscards();
return ERR_BUF;
}
MEMCPY(p->payload, ip_options, optlen);
if (optlen < optlen_aligned) {
/* zero the remaining bytes */
memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
}
}
#endif /* IP_OPTIONS_SEND */
/* generate IP header */
if (pbuf_header(p, IP_HLEN)) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
......@@ -498,7 +581,7 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
ip_addr_set(&(iphdr->dest), dest);
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos);
IPH_LEN_SET(iphdr, htons(p->tot_len));
IPH_OFFSET_SET(iphdr, 0);
IPH_ID_SET(iphdr, htons(ip_id));
......@@ -512,7 +595,7 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
IPH_CHKSUM_SET(iphdr, 0);
#if CHECKSUM_GEN_IP
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
#endif
} else {
/* IP header already included in p */
......@@ -531,9 +614,19 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
ip_debug_print(p);
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
if (ip_addr_cmp(dest, &netif->ip_addr)) {
/* Packet to self, enqueue it for loopback */
LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
return netif_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);
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);
/* 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 */
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 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->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));
}
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 == 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_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;
}
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 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));
}
#if MEMP_STATS
void
stats_display(void)
stats_display_memp(struct stats_mem *mem, int index)
{
#if MEMP_STATS
s16_t i;
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
if(index < MEMP_MAX) {
stats_display_mem(mem, memp_names[index]);
}
}
#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++) {
stats_display_mem(&lwip_stats.memp[i], memp_names[i]);
MEMP_STATS_DISPLAY(i);
}
#endif
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;
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -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
}
......
此差异已折叠。
......@@ -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 */
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -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
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册