summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2012-05-29 10:31:38 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2012-05-29 10:31:38 -0700
commitd493d0416f038f80d73b897e317e6d2c251c1775 (patch)
tree6a1f4aa39149c6093ec4ab7c8a93dd1252d7ec4e
parentc135aeebe08d857548a3a56b6fc3a0125ec8972c (diff)
parent930e929b202ed292077fb14981e5c6bd4c55651e (diff)
downloadsyslinux-d493d0416f038f80d73b897e317e6d2c251c1775.tar.gz
Merge remote-tracking branch 'genec/lwip-1.4.0-test-2' into lwip
-rw-r--r--core/fs/pxe/tcp.c4
-rw-r--r--core/fs/pxe/tftp.c9
-rw-r--r--core/lwip/CHANGELOG657
-rw-r--r--core/lwip/UPGRADING144
-rw-r--r--core/lwip/doc/rawapi.txt31
-rw-r--r--core/lwip/doc/snmp_agent.txt4
-rw-r--r--core/lwip/doc/sys_arch.txt12
-rw-r--r--core/lwip/src/api/api_lib.c476
-rw-r--r--core/lwip/src/api/api_msg.c930
-rw-r--r--core/lwip/src/api/err.c23
-rw-r--r--core/lwip/src/api/netbuf.c13
-rw-r--r--core/lwip/src/api/netdb.c38
-rw-r--r--core/lwip/src/api/netifapi.c32
-rw-r--r--core/lwip/src/api/sockets.c1132
-rw-r--r--core/lwip/src/api/tcpip.c313
-rw-r--r--core/lwip/src/arch/sys_arch.c98
-rw-r--r--core/lwip/src/core/def.c108
-rw-r--r--core/lwip/src/core/dhcp.c955
-rw-r--r--core/lwip/src/core/dns.c228
-rw-r--r--core/lwip/src/core/init.c62
-rw-r--r--core/lwip/src/core/ipv4/autoip.c93
-rw-r--r--core/lwip/src/core/ipv4/icmp.c38
-rw-r--r--core/lwip/src/core/ipv4/igmp.c198
-rw-r--r--core/lwip/src/core/ipv4/inet.c236
-rw-r--r--core/lwip/src/core/ipv4/inet_chksum.c84
-rw-r--r--core/lwip/src/core/ipv4/ip.c280
-rw-r--r--core/lwip/src/core/ipv4/ip_addr.c262
-rw-r--r--core/lwip/src/core/ipv4/ip_frag.c115
-rw-r--r--core/lwip/src/core/mem.c101
-rw-r--r--core/lwip/src/core/memp.c123
-rw-r--r--core/lwip/src/core/netif.c305
-rw-r--r--core/lwip/src/core/pbuf.c273
-rw-r--r--core/lwip/src/core/raw.c41
-rw-r--r--core/lwip/src/core/snmp/asn1_dec.c32
-rw-r--r--core/lwip/src/core/snmp/asn1_enc.c56
-rw-r--r--core/lwip/src/core/snmp/mib2.c608
-rw-r--r--core/lwip/src/core/snmp/mib_structs.c47
-rw-r--r--core/lwip/src/core/snmp/msg_in.c263
-rw-r--r--core/lwip/src/core/snmp/msg_out.c44
-rw-r--r--core/lwip/src/core/stats.c55
-rw-r--r--core/lwip/src/core/sys.c306
-rw-r--r--core/lwip/src/core/tcp.c524
-rw-r--r--core/lwip/src/core/tcp_in.c245
-rw-r--r--core/lwip/src/core/tcp_out.c1066
-rw-r--r--core/lwip/src/core/timers.c483
-rw-r--r--core/lwip/src/core/udp.c253
-rw-r--r--core/lwip/src/include/arch/sys_arch.h7
-rw-r--r--core/lwip/src/include/ipv4/lwip/autoip.h5
-rw-r--r--core/lwip/src/include/ipv4/lwip/icmp.h28
-rw-r--r--core/lwip/src/include/ipv4/lwip/igmp.h100
-rw-r--r--core/lwip/src/include/ipv4/lwip/inet.h108
-rw-r--r--core/lwip/src/include/ipv4/lwip/inet_chksum.h38
-rw-r--r--core/lwip/src/include/ipv4/lwip/ip.h75
-rw-r--r--core/lwip/src/include/ipv4/lwip/ip_addr.h191
-rw-r--r--core/lwip/src/include/ipv4/lwip/ip_frag.h14
-rw-r--r--core/lwip/src/include/lwip/api.h160
-rw-r--r--core/lwip/src/include/lwip/api_msg.h26
-rw-r--r--core/lwip/src/include/lwip/arch.h295
-rw-r--r--core/lwip/src/include/lwip/def.h82
-rw-r--r--core/lwip/src/include/lwip/dhcp.h156
-rw-r--r--core/lwip/src/include/lwip/dns.h51
-rw-r--r--core/lwip/src/include/lwip/err.h28
-rw-r--r--core/lwip/src/include/lwip/init.h4
-rw-r--r--core/lwip/src/include/lwip/mem.h35
-rw-r--r--core/lwip/src/include/lwip/memp_std.h26
-rw-r--r--core/lwip/src/include/lwip/netbuf.h33
-rw-r--r--core/lwip/src/include/lwip/netdb.h13
-rw-r--r--core/lwip/src/include/lwip/netif.h174
-rw-r--r--core/lwip/src/include/lwip/netifapi.h37
-rw-r--r--core/lwip/src/include/lwip/opt.h253
-rw-r--r--core/lwip/src/include/lwip/pbuf.h48
-rw-r--r--core/lwip/src/include/lwip/raw.h47
-rw-r--r--core/lwip/src/include/lwip/snmp.h11
-rw-r--r--core/lwip/src/include/lwip/snmp_asn1.h16
-rw-r--r--core/lwip/src/include/lwip/snmp_msg.h10
-rw-r--r--core/lwip/src/include/lwip/snmp_structs.h38
-rw-r--r--core/lwip/src/include/lwip/sockets.h27
-rw-r--r--core/lwip/src/include/lwip/stats.h51
-rw-r--r--core/lwip/src/include/lwip/sys.h206
-rw-r--r--core/lwip/src/include/lwip/tcp.h610
-rw-r--r--core/lwip/src/include/lwip/tcp_impl.h471
-rw-r--r--core/lwip/src/include/lwip/tcpip.h40
-rw-r--r--core/lwip/src/include/lwip/timers.h (renamed from core/lwip/src/include/netif/loopif.h)61
-rw-r--r--core/lwip/src/include/lwip/udp.h94
-rw-r--r--core/lwip/src/include/lwipopts.h4
-rw-r--r--core/lwip/src/include/netif/etharp.h81
-rw-r--r--core/lwip/src/include/netif/ppp_oe.h101
-rw-r--r--core/lwip/src/netif/etharp.c898
-rw-r--r--core/lwip/src/netif/loopif.c66
-rw-r--r--core/lwip/src/netif/ppp/auth.c946
-rw-r--r--core/lwip/src/netif/ppp/auth.h2
-rw-r--r--core/lwip/src/netif/ppp/chap.c255
-rw-r--r--core/lwip/src/netif/ppp/chap.h64
-rw-r--r--core/lwip/src/netif/ppp/chpms.c95
-rw-r--r--core/lwip/src/netif/ppp/fsm.c380
-rw-r--r--core/lwip/src/netif/ppp/fsm.h60
-rw-r--r--core/lwip/src/netif/ppp/ipcp.c206
-rw-r--r--core/lwip/src/netif/ppp/ipcp.h24
-rw-r--r--core/lwip/src/netif/ppp/lcp.c325
-rw-r--r--core/lwip/src/netif/ppp/lcp.h20
-rw-r--r--core/lwip/src/netif/ppp/magic.c4
-rw-r--r--core/lwip/src/netif/ppp/magic.h6
-rw-r--r--core/lwip/src/netif/ppp/md5.c4
-rw-r--r--core/lwip/src/netif/ppp/pap.c210
-rw-r--r--core/lwip/src/netif/ppp/pap.h49
-rw-r--r--core/lwip/src/netif/ppp/ppp.c809
-rw-r--r--core/lwip/src/netif/ppp/ppp.h48
-rw-r--r--core/lwip/src/netif/ppp/ppp_oe.c323
-rw-r--r--core/lwip/src/netif/ppp/pppdebug.h55
-rw-r--r--core/lwip/src/netif/ppp/randm.c4
-rw-r--r--core/lwip/src/netif/ppp/vj.c182
-rw-r--r--core/lwip/src/netif/ppp/vj.h7
-rw-r--r--core/lwip/src/netif/ppp/vjbsdhdr.h75
-rw-r--r--core/lwip/src/netif/slipif.c2
114 files changed, 12485 insertions, 7889 deletions
diff --git a/core/fs/pxe/tcp.c b/core/fs/pxe/tcp.c
index daff4d70..ec7679e7 100644
--- a/core/fs/pxe/tcp.c
+++ b/core/fs/pxe/tcp.c
@@ -51,8 +51,8 @@ void tcp_fill_buffer(struct inode *inode)
}
/* If needed get a new netbuf */
if (!socket->buf) {
- socket->buf = netconn_recv(socket->conn);
- if (!socket->buf) {
+ err = netconn_recv(socket->conn, &(socket->buf));
+ if (!socket->buf || err) {
socket->tftp_goteof = 1;
if (inode->size == -1)
inode->size = socket->tftp_filepos;
diff --git a/core/fs/pxe/tftp.c b/core/fs/pxe/tftp.c
index 429e8ffe..f6ea2974 100644
--- a/core/fs/pxe/tftp.c
+++ b/core/fs/pxe/tftp.c
@@ -138,6 +138,7 @@ static void tftp_get_packet(struct inode *inode)
struct netbuf *nbuf;
u16_t nbuf_len;
struct pxe_pvt_inode *socket = PVT(inode);
+ err_t err;
/*
* Start by ACKing the previous packet; this should cause
@@ -151,8 +152,8 @@ static void tftp_get_packet(struct inode *inode)
ack_packet(inode, socket->tftp_lastpkt);
while (timeout) {
- nbuf = netconn_recv(socket->conn);
- if (!nbuf) {
+ err = netconn_recv(socket->conn, &nbuf);
+ if (!nbuf || err) {
jiffies_t now = jiffies();
if (now-oldtime >= timeout) {
@@ -318,8 +319,8 @@ sendreq:
wait_pkt:
netconn_disconnect(socket->conn);
for (;;) {
- nbuf = netconn_recv(socket->conn);
- if (!nbuf) {
+ err = netconn_recv(socket->conn, &nbuf);
+ if (!nbuf || err) {
jiffies_t now = jiffies();
if (now - oldtime >= timeout)
goto sendreq;
diff --git a/core/lwip/CHANGELOG b/core/lwip/CHANGELOG
index 860d1c47..6e27a66b 100644
--- a/core/lwip/CHANGELOG
+++ b/core/lwip/CHANGELOG
@@ -1,27 +1,658 @@
-FUTURE
-
- * TODO: The lwIP source code makes some invalid assumptions on processor
- word-length, storage sizes and alignment. See the mailing lists for
- problems with exoteric (/DSP) architectures showing these problems.
- We still have to fix some of these issues neatly.
-
- * TODO: the PPP code is broken in a few ways. There are namespace
- collisions on BSD systems and many assumptions on word-length
- (sizeof(int)). In ppp.c an assumption is made on the availability of
- a thread subsystem. Either PPP needs to be moved to contrib/ports/???
- or rearranged to be more generic.
-
HISTORY
(CVS HEAD)
* [Enter new changes just after this line - do not remove this line]
+ ++ New features:
+
+
+ ++ Bugfixes:
+
+
+
+
+(STABLE-1.4.0)
+
++ New features:
+ 2011-03-27: Simon Goldschmidt
+ * tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and
+ calculate it in tcp_zero_window_probe (the only place where it was used).
+
+ 2010-11-21: Simon Goldschmidt
+ * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif
+ (fixes bug #31525).
+
+ 2010-07-12: Simon Goldschmidt (patch by Stephane Lesage)
+ * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for
+ IP_MULTICAST_LOOP at socket- and raw-API level.
+
+ 2010-06-16: Simon Goldschmidt
+ * ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow
+ link-layer-addressed UDP traffic to be received while a netif is down (just
+ like DHCP during configuration)
+
+ 2010-05-22: Simon Goldschmidt
+ * many many files: bug #27352: removed packing from ip_addr_t, the packed
+ version is now only used in protocol headers. Added global storage for
+ current src/dest IP address while in input functions.
+
+ 2010-05-16: Simon Goldschmidt
+ * def.h: task #10391: Add preprocessor-macros for compile-time htonl
+ calculation (and use them throughout the stack where applicable)
+
+ 2010-05-16: Simon Goldschmidt
+ * opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool
+ instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h)
+
+ 2010-05-16: Simon Goldschmidt
+ * opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own
+ MEMP pool instead of the heap
+
+ 2010-05-13: Simon Goldschmidt
+ * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added
+ new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast
+ packets to more than one pcb.
+
+ 2010-05-02: Simon Goldschmidt
+ * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending
+ UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1
+
+ 2010-04-30: Simon Goldschmidt
+ * udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that
+ take a precalculated checksum, added pbuf_fill_chksum() to copy data
+ into a pbuf and at the same time calculating the checksum for that data
+
+ 2010-04-29: Simon Goldschmidt
+ * ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying
+ 2-byte-aligned IP addresses and MAC addresses
+
+ 2010-04-28: Patch by Bill Auerbach
+ * ip.c: Inline generating IP checksum to save a function call
+
+ 2010-04-14: Simon Goldschmidt
+ * tcpip.h/.c, timers.c: Added an overridable define to get informed when the
+ tcpip_thread processes messages or timeouts to implement a watchdog.
+
+ 2010-03-28: Simon Goldschmidt
+ * ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing
+ fragment if LWIP_NETIF_TX_SINGLE_PBUF==1
+
+ 2010-03-27: Simon Goldschmidt
+ * etharp.c: Speedup TX by moving code from find_entry to etharp_output/
+ etharp_query to prevent unnecessary function calls (inspired by
+ patch #7135).
+
+ 2010-03-20: Simon Goldschmidt
+ * opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code
+ since the linker cannot do this automatically to save space.
+
+ 2010-03-20: Simon Goldschmidt
+ * opt.h, etharp.c/.h: Added support for static ARP table entries
+
+ 2010-03-14: Simon Goldschmidt
+ * tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum
+ when creating TCP segments, not when (re-)transmitting them.
+
+ 2010-03-07: Simon Goldschmidt
+ * sockets.c: bug #28775 (select/event_callback: only check select_cb_list
+ on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code.
+ This should speed up receiving data on sockets as the select code in
+ event_callback is only executed when select is waiting.
+
+ 2010-03-06: Simon Goldschmidt
+ * tcp_out.c: task #7013 (Create option to have all packets delivered to
+ netif->output in one piece): Always copy to try to create single pbufs
+ in tcp_write.
+
+ 2010-03-06: Simon Goldschmidt
+ * api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv
+ by not allocating a netbuf): added function netconn_recv_tcp_pbuf()
+ for tcp netconns to receive pbufs, not netbufs; use that function
+ for tcp sockets.
+
+ 2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt
+ * opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040:
+ Work on tcp_enqueue: Don't waste memory when chaining segments,
+ added option TCP_OVERSIZE to prevent creating many small pbufs when
+ calling tcp_write with many small blocks of data. Instead, pbufs are
+ allocated larger than needed and the space is used for later calls to
+ tcp_write.
+
+ 2010-02-21: Simon Goldschmidt
+ * stats.c/.h: Added const char* name to mem- and memp-stats for easier
+ debugging.
+
+ 2010-02-21: Simon Goldschmidt
+ * tcp.h (and usages), added tcp_impl.h: Splitted API and internal
+ implementation of tcp to make API usage cleare to application programmers
+
+ 2010-02-14: Simon Goldschmidt/Stephane Lesage
+ * ip_addr.h: Improved some defines working on ip addresses, added faster
+ macro to copy addresses that cannot be NULL
+
+ 2010-02-13: Simon Goldschmidt
+ * api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non-
+ blocking send operation)
+
+ 2010-02-12: Simon Goldschmidt
+ * sockets.c/.h: Added a minimal version of posix fctl() to have a
+ standardised way to set O_NONBLOCK for nonblocking sockets.
+
+ 2010-02-12: Simon Goldschmidt
+ * dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated
+ memory): added autoip_set_struct() and dhcp_set_struct() to let autoip
+ and dhcp work with user-allocated structs instead of callin mem_malloc
+
+ 2010-02-12: Simon Goldschmidt/Jeff Barber
+ * tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has
+ SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT
+
+ 2010-02-12: Simon Goldschmidt
+ * sys layer: task #10139 (Prefer statically allocated memory): converted
+ mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t;
+ converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
+ task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX
+ to let sys.h use binary semaphores instead of mutexes - as before)
+
+ 2010-02-09: Simon Goldschmidt (Simon Kallweit)
+ * timers.c/.h: Added function sys_restart_timeouts() from patch #7085
+ (Restart system timeout handling)
+
+ 2010-02-09: Simon Goldschmidt
+ * netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into
+ netif.c) - loopif does not have to be created by the port any more,
+ just define LWIP_HAVE_LOOPIF to 1.
+
+ 2010-02-08: Simon Goldschmidt
+ * inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa
+ inet_ntoa_r/ipaddr_ntoa_r
+
+ 2010-02-08: Simon Goldschmidt
+ * netif.h: Added netif_s/get_igmp_mac_filter() macros
+
+ 2010-02-05: Simon Goldschmidt
+ * netif.h: Added function-like macros to get/set the hostname on a netif
+
+ 2010-02-04: Simon Goldschmidt
+ * nearly every file: Replaced struct ip_addr by typedef ip_addr_t to
+ make changing the actual implementation behind the typedef easier.
+
+ 2010-02-01: Simon Goldschmidt
+ * opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool
+ for allocating memory when getaddrinfo() is called.
+
+ 2010-01-31: Simon Goldschmidt
+ * dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse
+ them once instead of parsing for every option. This also removes
+ the need for mem_malloc from dhcp_recv and makes it possible to
+ correctly retrieve the BOOTP file.
+
+ 2010-01-30: simon Goldschmidt
+ * sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect
+ the sockets array.
+
+ 2010-01-29: Simon Goldschmidt (patch by Laura Garrett)
+ * api.h, api_msg.c, sockets.c: Added except set support in select
+ (patch #6860)
+
+ 2010-01-29: Simon Goldschmidt (patch by Laura Garrett)
+ * api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c:
+ Add non-blocking support for connect (partly from patch #6860),
+ plus many cleanups in socket & netconn API.
+
+ 2010-01-27: Simon Goldschmidt
+ * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding
+ to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605
+
+ 2010-01-26: Simon Goldschmidt
+ * snmp: Use memp pools for snmp instead of the heap; added 4 new pools.
+
+ 2010-01-14: Simon Goldschmidt
+ * ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback
+ by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback()
+
+ 2010-01-13: Simon Goldschmidt
+ * mem.c: The heap now may be moved to user-defined memory by defining
+ LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address
+ (patch #6966 and bug #26133)
+
+ 2010-01-10: Simon Goldschmidt (Bill Auerbach)
+ * opt.h, memp.c: patch #6822 (Add option to place memory pools in
+ separate arrays)
+
+ 2010-01-10: Simon Goldschmidt
+ * init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define
+ LWIP_RAND() for lwip-wide randomization (to be defined in cc.h)
+
+ 2009-12-31: Simon Goldschmidt
+ * tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h
+ added timers.c/.h: Separated timer implementation from semaphore/mbox
+ implementation, moved timer implementation to timers.c/.h, timers are
+ now only called from tcpip_thread or by explicitly checking them.
+ (TASK#7235)
+
+ 2009-12-27: Simon Goldschmidt
+ * opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option
+ LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE)
+
++ Bugfixes:
+ 2011-04-20: Simon Goldschmidt
+ * sys_arch.txt: sys_arch_timeouts() is not needed any more.
+
+ 2011-04-13: Simon Goldschmidt
+ * tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by
+ using ports in the IANA private/dynamic range (49152 through 65535).
+
+ 2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl:
+ * etharp.h/.c: Fixed broken VLAN support.
+
+ 2011-03-27: Simon Goldschmidt
+ * tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp
+ pcbs) by checking if the pcb was bound (local_port != 0).
+
+ 2011-03-27: Simon Goldschmidt
+ * ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice)
+
+ 2011-03-27: Simon Goldschmidt
+ * sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and
+ raw pcbs with LWIP_TCPIP_CORE_LOCKING==1.
+
+ 2011-03-27: Simon Goldschmidt
+ * tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route
+ is present never times out) by starting retransmission timer before checking
+ route.
+
+ 2011-03-22: Simon Goldschmidt
+ * ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only
+ calling sio_read_abort() if the file descriptor is valid.
+
+ 2011-03-14: Simon Goldschmidt
+ * err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect
+ more than once can render a socket useless) since it mainly involves changing
+ "FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal.
+
+ 2011-03-13: Simon Goldschmidt
+ * sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing
+ err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN:
+ use EALRADY instead of -1
+
+ 2011-03-13: Simon Goldschmidt
+ * api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the
+ connection has been aborted by err_tcp (since this is not a normal closing
+ procedure).
+
+ 2011-03-13: Simon Goldschmidt
+ * tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind
+ with pcb->state != CLOSED
+
+ 2011-02-17: Simon Goldschmidt
+ * rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in
+ documentation
+
+ 2011-02-17: Simon Goldschmidt
+ * many files: Added missing U/UL modifiers to fix 16-bit-arch portability.
+
+ 2011-01-24: Simon Goldschmidt
+ * sockets.c: Fixed bug #31741: lwip_select seems to have threading problems
+
+ 2010-12-02: Simon Goldschmidt
+ * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal.
+
+ 2010-11-23: Simon Goldschmidt
+ * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for
+ LWIP_SO_RCVBUF and ioctl/FIONREAD.
+
+ 2010-11-23: Simon Goldschmidt
+ * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at
+ least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet.
+
+ 2010-11-23: Simon Goldschmidt
+ * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after
+ refusing 'refused_data' again.
+
+ 2010-11-22: Simon Goldschmidt
+ * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS
+ after a successful nonblocking connection.
+
+ 2010-11-22: Simon Goldschmidt
+ * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr
+ must be sent link-local
+
+ 2010-11-22: Simon Goldschmidt
+ * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for
+ LWIP_TIMERS==0
+
+ 2010-11-20: Simon Goldschmidt
+ * sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number
+
+ 2010-11-20: Simon Goldschmidt
+ * sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to
+ resemble other stacks.
+
+ 2010-11-20: Simon Goldschmidt
+ * dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else
+ no-copy TCP writes will never succeed.
+
+ 2010-11-20: Simon Goldschmidt
+ * dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does
+ not match documentation: return ERR_ARG instead of ERR_VAL if not
+ initialized or wrong argument.
+
+ 2010-10-20: Simon Goldschmidt
+ * sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16
+
+ 2010-10-05: Simon Goldschmidt
+ * dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when
+ replugging the network cable after an AutoIP address was assigned.
+
+ 2010-08-10: Simon Goldschmidt
+ * tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs
+
+ 2010-08-03: Simon Goldschmidt
+ * udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625)
+
+ 2010-08-01: Simon Goldschmidt (patch by Greg Renda)
+ * ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big
+ endian architectures)
+
+ 2010-07-28: Simon Goldschmidt
+ * api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP
+ disabled.
+
+ 2010-07-27: Simon Goldschmidt
+ * tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no
+ harm but never did anything
+
+ 2010-07-21: Simon Goldschmidt
+ * ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not
+ add IP options)
+
+ 2010-07-16: Kieran Mansley
+ * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator
+
+ 2010-07-10: Simon Goldschmidt
+ * ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options
+
+ 2010-06-30: Simon Goldschmidt
+ * api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in
+ netconn_delete)
+
+ 2010-06-28: Kieran Mansley
+ * timers.c remove unportable printing of C function pointers
+
+ 2010-06-24: Simon Goldschmidt
+ * init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag
+ NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading
+
+ 2010-06-24: Simon Goldschmidt
+ * api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly
+ implemented shutdown at socket level.
+
+ 2010-06-21: Simon Goldschmidt
+ * pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has
+ problems with zero-copy DMA MACs) by adding custom pbufs and implementing
+ custom pbufs that reference other (original) pbufs. Additionally set
+ IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side.
+
+ 2010-06-15: Simon Goldschmidt
+ * dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses
+
+ 2010-06-14: Simon Goldschmidt
+ * autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses
+
+ 2010-06-12: Simon Goldschmidt
+ * dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop
+ state
+
+ 2010-05-17: Simon Goldschmidt
+ * netdb.c: Correctly NULL-terminate h_addr_list
+
+ 2010-05-16: Simon Goldschmidt
+ * def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent
+ "symbol already defined" i.e. when linking to winsock
+
+ 2010-05-05: Simon Goldschmidt
+ * def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may
+ overflow)
+
+ 2010-04-21: Simon Goldschmidt
+ * api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening
+ connection)
+
+ 2010-03-28: Luca Ceresoli
+ * ip_addr.c/.h: patch #7143: Add a few missing const qualifiers
+
+ 2010-03-27: Luca Ceresoli
+ * mib2.c: patch #7130: remove meaningless const qualifiers
+
+ 2010-03-26: Simon Goldschmidt
+ * tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too
+
+ 2010-03-26: Simon Goldschmidt
+ * various files: Fixed compiling with different options disabled (TCP/UDP),
+ triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled
+
+ 2010-03-25: Simon Goldschmidt
+ * sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly
+
+ 2010-03-25: Simon Goldschmidt
+ * tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side
+ overrunning our rcv_wnd in ooseq case.
+
+ 2010-03-22: Simon Goldschmidt
+ * tcp.c: tcp_listen() did not copy the pcb's prio.
+
+ 2010-03-19: Simon Goldschmidt
+ * snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set
+
+ 2010-03-14: Simon Goldschmidt
+ * opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports
+ where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h
+ and basing PBUF_LINK_HLEN on it.
+
+ 2010-03-08: Simon Goldschmidt
+ * netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections
+ when assiging routable address): when checking incoming packets and
+ aborting existing connection on address change, filter out link-local
+ addresses.
+
+ 2010-03-06: Simon Goldschmidt
+ * sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING
+
+ 2010-03-06: Simon Goldschmidt
+ * ipv4/ip.c: Don't try to forward link-local addresses
+
+ 2010-03-06: Simon Goldschmidt
+ * etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal-
+ addresses to gw
+
+ 2010-03-05: Simon Goldschmidt
+ * dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type
+ and state.
+
+ 2010-03-05: Simon Goldschmidt
+ * api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split
+ into multiple calls to tcp_write.
+
+ 2010-02-21: Simon Goldschmidt
+ * opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep
+ the implementation of DNS_USES_STATIC_BUF==1)
+
+ 2010-02-20: Simon Goldschmidt
+ * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement
+ close() vs. shutdown(). Now the application does not get any more
+ recv callbacks after calling tcp_close(). Added tcp_shutdown().
+
+ 2010-02-19: Simon Goldschmidt
+ * mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent
+ confusion with realloc()
+
+ 2010-02-15: Simon Goldschmidt/Stephane Lesage
+ * netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK
+ (fixes bug #28899)
+
+ 2010-02-14: Simon Goldschmidt
+ * netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with
+ LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and
+ admin-status of a netif are up
+
+ 2010-02-14: Simon Goldschmidt
+ * opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet
+ reception and is not really necessary
+
+ 2010-02-14: Simon Goldschmidt
+ * etharp.c/.h: Fixed ARP input processing: only add a new entry if a
+ request was directed as us (RFC 826, Packet Reception), otherwise
+ only update existing entries; internalized some functions
+
+ 2010-02-14: Simon Goldschmidt
+ * netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be
+ disabled on netif used for PPPoE) by adding a new netif flag
+ (NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet
+ device but prevents usage of ARP (so that ethernet_input can be used
+ for PPPoE).
+
+ 2010-02-12: Simon Goldschmidt
+ * netif.c: netif_set_link_up/down: only do something if the link state
+ actually changes
+
+ 2010-02-12: Simon Goldschmidt/Stephane Lesage
+ * api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking
+ connect)
+
+ 2010-02-12: Simon Goldschmidt
+ * mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h)
+
+ 2010-02-09: Simon Goldschmidt
+ * api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110
+ (recv() makes receive window update for data that wasn't received by
+ application)
+
+ 2010-02-09: Simon Goldschmidt/Stephane Lesage
+ * sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out
+ or any netconn_recv() error)
+
+ 2010-02-09: Simon Goldschmidt
+ * ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets)
+
+ 2010-02-09: Simon Goldschmidt
+ * netif.c: For loopback packets, adjust the stats- and snmp-counters
+ for the loopback netif.
+
+ 2010-02-08: Simon Goldschmidt
+ * igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity
+ since they are not used anywhere else.
+
+ 2010-02-08: Simon Goldschmidt (Stéphane Lesage)
+ * igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats
+ (patch from bug #28798)
+
+ 2010-02-08: Simon Goldschmidt (Stéphane Lesage)
+ * igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and
+ another bug when LWIP_RAND() returns zero.
+
+ 2010-02-04: Simon Goldschmidt
+ * nearly every file: Use macros defined in ip_addr.h (some of them new)
+ to work with IP addresses (preparation for bug #27352 - Change ip_addr
+ from struct to typedef (u32_t) - and better code).
+
+ 2010-01-31: Simon Goldschmidt
+ * netif.c: Don't call the link-callback from netif_set_up/down() since
+ this invalidly retriggers DHCP.
+
+ 2010-01-29: Simon Goldschmidt
+ * ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the
+ portability file inet.h and its contents from the stack: moved htonX-
+ functions to def.h (and the new def.c - they are not ipv4 dependent),
+ let inet.h depend on ip_addr.h and not the other way round.
+ This fixes bug #28732.
+
+ 2010-01-28: Kieran Mansley
+ * tcp.c: Ensure ssthresh >= 2*MSS
+
+ 2010-01-27: Simon Goldschmidt
+ * tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv
+ callback can lead to accessing unallocated memory. As a consequence,
+ ERR_ABRT means the application has called tcp_abort()!
+
+ 2010-01-25: Simon Goldschmidt
+ * snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY
+ not implemented in SNMP): write-only or not-accessible are still
+ returned by getnext (though not by get)
+
+ 2010-01-24: Simon Goldschmidt
+ * snmp: Renamed the private mib node from 'private' to 'mib_private' to
+ not use reserved C/C++ keywords
+
+ 2010-01-23: Simon Goldschmidt
+ * sockets.c: Fixed bug #28716: select() returns 0 after waiting for less
+ than 1 ms
+
+ 2010-01-21: Simon Goldschmidt
+ * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called
+ if tcp_enqueue fails) both in raw- and netconn-API
+
+ 2010-01-19: Simon Goldschmidt
+ * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp
+
+ 2010-01-18: Iordan Neshev/Simon Goldschmidt
+ * src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some
+ bugfix backports from 2.4.x.
+
+ 2010-01-18: Simon Goldschmidt
+ * mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong
+
+ 2010-01-17: Simon Goldschmidt
+ * api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c):
+ task #10102: "netconn: clean up conn->err threading issues" by adding
+ error return value to struct api_msg_msg
+
+ 2010-01-17: Simon Goldschmidt
+ * api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept()
+ to return err_t (bugs #27709 and #28087)
+
+ 2010-01-14: Simon Goldschmidt
+ * ...: Use typedef for function prototypes throughout the stack.
+
+ 2010-01-13: Simon Goldschmidt
+ * api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive
+ window = 0) by correctly draining recvmbox/acceptmbox
+
+ 2010-01-11: Simon Goldschmidt
+ * pap.c: Fixed bug #13315 (PPP PAP authentication can result in
+ erroneous callbacks) by copying the code from recent pppd
+
+ 2010-01-10: Simon Goldschmidt
+ * raw.c: Fixed bug #28506 (raw_bind should filter received packets)
+
+ 2010-01-10: Simon Goldschmidt
+ * tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)())
+
+ 2010-01-08: Simon Goldschmidt
+ * sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535)
+
+ 2010-01-08: Simon Goldschmidt
+ * dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string
+ passed to dns_local_addhost() might be volatile
+
+ 2010-01-07: Simon Goldschmidt
+ * timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too
+
+ 2010-01-06: Simon Goldschmidt
+ * netdb.h: Fixed bug #28496: missing include guards in netdb.h
+
+ 2009-12-31: Simon Goldschmidt
+ * many ppp files: Reorganised PPP source code from ucip structure to pppd
+ structure to easily compare our code against the pppd code (around v2.3.1)
+
+ 2009-12-27: Simon Goldschmidt
+ * tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted
+ unit test
+
(STABLE-1.3.2)
diff --git a/core/lwip/UPGRADING b/core/lwip/UPGRADING
new file mode 100644
index 00000000..6501107a
--- /dev/null
+++ b/core/lwip/UPGRADING
@@ -0,0 +1,144 @@
+This file lists major changes between release versions that require
+ports or applications to be changed. Use it to update a port or an
+application written for an older version of lwIP to correctly work
+with newer versions.
+
+
+(CVS HEAD)
+
+ * [Enter new changes just after this line - do not remove this line]
+
+ ++ Application changes:
+
+ * Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for
+ compatibility to old applications, but will be removed in the future).
+
+ * Renamed mem_realloc() to mem_trim() to prevent confusion with realloc()
+
+ +++ Raw API:
+ * Changed the semantics of tcp_close() (since it was rather a
+ shutdown before): Now the application does *NOT* get any calls to the recv
+ callback (aside from NULL/closed) after calling tcp_close()
+
+ * When calling tcp_abort() from a raw API TCP callback function,
+ make sure you return ERR_ABRT to prevent accessing unallocated memory.
+ (ERR_ABRT now means the applicaiton has called tcp_abort!)
+
+ +++ Netconn API:
+ * Changed netconn_receive() and netconn_accept() to return
+ err_t, not a pointer to new data/netconn.
+
+ +++ Socket API:
+ * LWIP_SO_RCVTIMEO: when accept() or recv() time out, they
+ now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT.
+
+ * Added a minimal version of posix fctl() to have a
+ standardised way to set O_NONBLOCK for nonblocking sockets.
+
+ +++ all APIs:
+ * correctly implemented SO(F)_REUSEADDR
+
+ ++ Port changes
+
+ +++ new files:
+
+ * Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h:
+
+ * Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains
+ the actual application programmer's API
+
+ * Separated timer implementation from sys.h/.c, moved to timers.h/.c;
+ Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you
+ still want to use your own timer implementation for NO_SYS==0 (as before).
+
+ +++ sys layer:
+
+ * Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/
+ sys_sem_t;
+
+ * Converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
+
+ * Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use
+ binary semaphores instead of mutexes - as before)
+
+ +++ new options:
+
+ * Don't waste memory when chaining segments, added option TCP_OVERSIZE to
+ prevent creating many small pbufs when calling tcp_write with many small
+ blocks of data. Instead, pbufs are allocated larger than needed and the
+ space is used for later calls to tcp_write.
+
+ * Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs
+ in tcp_write/udp_send.
+
+ * Added an additional option LWIP_ETHERNET to support ethernet without ARP
+ (necessary for pure PPPoE)
+
+ * Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may
+ be used to place these pools into user-defined memory by using external
+ declaration.
+
+ * Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT
+
+ +++ new pools:
+
+ * Netdb uses a memp pool for allocating memory when getaddrinfo() is called,
+ so MEMP_NUM_NETDB has to be set accordingly.
+
+ * DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so
+ MEMP_NUM_LOCALHOSTLIST has to be set accordingly.
+
+ * Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have
+ to be set accordingly.
+
+ * PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES
+ has to be set accordingly
+
+ * Integrated loopif into netif.c - loopif does not have to be created by the
+ port any more, just define LWIP_HAVE_LOOPIF to 1.
+
+ * Added define LWIP_RAND() for lwip-wide randomization (needs to be defined
+ in cc.h, e.g. used by igmp)
+
+ * Added printf-formatter X8_F to printf u8_t as hex
+
+ * The heap now may be moved to user-defined memory by defining
+ LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address
+
+ * added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work
+ with user-allocated structs instead of calling mem_malloc
+
+ * Added const char* name to mem- and memp-stats for easier debugging.
+
+ * Calculate the TCP/UDP checksum while copying to only fetch data once:
+ Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
+
+ * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
+ more than one pcb.
+
+ * Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned
+ off any more, if this is set to 0, only one packet (the most recent one) is
+ queued (like demanded by RFC 1122).
+
+
+ ++ Major bugfixes/improvements
+
+ * Implemented tcp_shutdown() to only shut down one end of a connection
+ * Implemented shutdown() at socket- and netconn-level
+ * Added errorset support to select() + improved select speed overhead
+ * Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x)
+ * Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1
+ * Use macros defined in ip_addr.h to work with IP addresses
+ * Implemented many nonblocking socket/netconn functions
+ * Fixed ARP input processing: only add a new entry if a request was directed as us
+ * mem_realloc() to mem_trim() to prevent confusion with realloc()
+ * Some improvements for AutoIP (don't route/forward link-local addresses, don't break
+ existing connections when assigning a routable address)
+ * Correctly handle remote side overrunning our rcv_wnd in ooseq case
+ * Removed packing from ip_addr_t, the packed version is now only used in protocol headers
+ * Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0
+ * Added support for static ARP table entries
+
+(STABLE-1.3.2)
+
+ * initial version of this file
diff --git a/core/lwip/doc/rawapi.txt b/core/lwip/doc/rawapi.txt
index 25fdc2e8..c727da99 100644
--- a/core/lwip/doc/rawapi.txt
+++ b/core/lwip/doc/rawapi.txt
@@ -251,8 +251,9 @@ if a call to tcp_write() has failed because memory wasn't available,
the application may use the polling functionality to call tcp_write()
again when the connection has been idle for a while.
-- void tcp_poll(struct tcp_pcb *pcb, u8_t interval,
- err_t (* poll)(void *arg, struct tcp_pcb *tpcb))
+- void tcp_poll(struct tcp_pcb *pcb,
+ err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
+ u8_t interval)
Specifies the polling interval and the callback function that should
be called to poll the application. The interval is specified in
@@ -278,6 +279,11 @@ again when the connection has been idle for a while.
Aborts the connection by sending a RST (reset) segment to the remote
host. The pcb is deallocated. This function never fails.
+ ATTENTION: When calling this from one of the TCP callbacks, make
+ sure you always return ERR_ABRT (and never return ERR_ABRT otherwise
+ or you will risk accessing deallocated memory or memory leaks!
+
+
If a connection is aborted because of an error, the application is
alerted of this event by the err callback. Errors that might abort a
connection are when there is a shortage of memory. The callback
@@ -476,3 +482,24 @@ to match your application and network.
For a production release it is recommended to set LWIP_STATS to 0.
Note that speed performance isn't influenced much by simply setting
high values to the memory options.
+
+For more optimization hints take a look at the lwIP wiki.
+
+--- Zero-copy MACs
+
+To achieve zero-copy on transmit, the data passed to the raw API must
+remain unchanged until sent. Because the send- (or write-)functions return
+when the packets have been enqueued for sending, data must be kept stable
+after that, too.
+
+This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions
+must *not* be reused by the application unless their ref-count is 1.
+
+For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too,
+but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while
+PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change).
+
+Also, data passed to tcp_write without the copy-flag must not be changed!
+
+Therefore, be careful which type of PBUF you use and if you copy TCP data
+or not!
diff --git a/core/lwip/doc/snmp_agent.txt b/core/lwip/doc/snmp_agent.txt
index 9b58616a..2653230f 100644
--- a/core/lwip/doc/snmp_agent.txt
+++ b/core/lwip/doc/snmp_agent.txt
@@ -46,7 +46,7 @@ Loading additional MIBs
Large SNMP message support
The packet decoding and encoding routines are designed
- to use pbuf-chains. Larger payloads then the minimum
+ to use pbuf-chains. Larger payloads than the minimum
SNMP requirement of 484 octets are supported if the
PBUF_POOL_SIZE and IP_REASS_BUFSIZE are set to match your
local requirement.
@@ -170,7 +170,7 @@ resembles the "auto-completion" operation)
The middle part is usually located in ROM (const)
to preserve precious RAM on small microcontrollers.
-However RAM location is possible for an dynamically
+However RAM location is possible for a dynamically
changing private tree.
The index part is handled by functions which in
diff --git a/core/lwip/doc/sys_arch.txt b/core/lwip/doc/sys_arch.txt
index cac4c626..4eb93078 100644
--- a/core/lwip/doc/sys_arch.txt
+++ b/core/lwip/doc/sys_arch.txt
@@ -123,18 +123,6 @@ The following functions must be implemented by the sys_arch:
sys_arch_mbox_fetch(mbox,msg,1)
although this would introduce unnecessary delays.
-- struct sys_timeouts *sys_arch_timeouts(void)
-
- Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
- each thread has a list of timeouts which is repressented as a linked
- list of sys_timeout structures. The sys_timeouts structure holds a
- pointer to a linked list of timeouts. This function is called by
- the lwIP timeout scheduler and must not return a NULL value.
-
- In a single thread sys_arch implementation, this function will
- simply return a pointer to a global sys_timeouts variable stored in
- the sys_arch module.
-
If threads are supported by the underlying operating system and if
such functionality is needed in lwIP, the following function will have
to be implemented as well:
diff --git a/core/lwip/src/api/api_lib.c b/core/lwip/src/api/api_lib.c
index 195a9a52..b1a9e525 100644
--- a/core/lwip/src/api/api_lib.c
+++ b/core/lwip/src/api/api_lib.c
@@ -71,19 +71,19 @@ netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_cal
struct api_msg msg;
conn = netconn_alloc(t, callback);
- if (conn != NULL ) {
+ if (conn != NULL) {
msg.function = do_newconn;
msg.msg.msg.n.proto = proto;
msg.msg.conn = conn;
- TCPIP_APIMSG(&msg);
-
- if (conn->err != ERR_OK) {
+ if (TCPIP_APIMSG(&msg) != ERR_OK) {
LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
- LWIP_ASSERT("conn has no op_completed", conn->op_completed != SYS_SEM_NULL);
- LWIP_ASSERT("conn has no recvmbox", conn->recvmbox != SYS_MBOX_NULL);
- LWIP_ASSERT("conn->acceptmbox shouldn't exist", conn->acceptmbox == SYS_MBOX_NULL);
- sys_sem_free(conn->op_completed);
- sys_mbox_free(conn->recvmbox);
+ LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
+ LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
+#if LWIP_TCP
+ LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
+#endif /* LWIP_TCP */
+ sys_sem_free(&conn->op_completed);
+ sys_mbox_free(&conn->recvmbox);
memp_free(MEMP_NETCONN, conn);
return NULL;
}
@@ -113,9 +113,10 @@ netconn_delete(struct netconn *conn)
msg.msg.conn = conn;
tcpip_apimsg(&msg);
- conn->pcb.tcp = NULL;
netconn_free(conn);
+ /* don't care for return value of do_delconn since it only calls void functions */
+
return ERR_OK;
}
@@ -131,9 +132,10 @@ netconn_delete(struct netconn *conn)
* ERR_OK if the information was retrieved
*/
err_t
-netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t local)
+netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
{
struct api_msg msg;
+ err_t err;
LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
@@ -144,9 +146,10 @@ netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t lo
msg.msg.msg.ad.ipaddr = addr;
msg.msg.msg.ad.port = port;
msg.msg.msg.ad.local = local;
- TCPIP_APIMSG(&msg);
+ err = TCPIP_APIMSG(&msg);
- return conn->err;
+ NETCONN_SET_SAFE_ERR(conn, err);
+ return err;
}
/**
@@ -160,9 +163,10 @@ netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t lo
* @return ERR_OK if bound, any other err_t on failure
*/
err_t
-netconn_bind(struct netconn *conn, struct ip_addr *addr, u16_t port)
+netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port)
{
struct api_msg msg;
+ err_t err;
LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
@@ -170,8 +174,10 @@ netconn_bind(struct netconn *conn, struct ip_addr *addr, u16_t port)
msg.msg.conn = conn;
msg.msg.msg.bc.ipaddr = addr;
msg.msg.msg.bc.port = port;
- TCPIP_APIMSG(&msg);
- return conn->err;
+ err = TCPIP_APIMSG(&msg);
+
+ NETCONN_SET_SAFE_ERR(conn, err);
+ return err;
}
/**
@@ -183,9 +189,10 @@ netconn_bind(struct netconn *conn, struct ip_addr *addr, u16_t port)
* @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise
*/
err_t
-netconn_connect(struct netconn *conn, struct ip_addr *addr, u16_t port)
+netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port)
{
struct api_msg msg;
+ err_t err;
LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
@@ -194,8 +201,10 @@ netconn_connect(struct netconn *conn, struct ip_addr *addr, u16_t port)
msg.msg.msg.bc.ipaddr = addr;
msg.msg.msg.bc.port = port;
/* This is the only function which need to not block tcpip_thread */
- tcpip_apimsg(&msg);
- return conn->err;
+ err = tcpip_apimsg(&msg);
+
+ NETCONN_SET_SAFE_ERR(conn, err);
+ return err;
}
/**
@@ -208,13 +217,16 @@ err_t
netconn_disconnect(struct netconn *conn)
{
struct api_msg msg;
+ err_t err;
LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
msg.function = do_disconnect;
msg.msg.conn = conn;
- TCPIP_APIMSG(&msg);
- return conn->err;
+ err = TCPIP_APIMSG(&msg);
+
+ NETCONN_SET_SAFE_ERR(conn, err);
+ return err;
}
/**
@@ -228,7 +240,9 @@ netconn_disconnect(struct netconn *conn)
err_t
netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
{
+#if LWIP_TCP
struct api_msg msg;
+ err_t err;
/* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
LWIP_UNUSED_ARG(backlog);
@@ -240,156 +254,276 @@ netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
#if TCP_LISTEN_BACKLOG
msg.msg.msg.lb.backlog = backlog;
#endif /* TCP_LISTEN_BACKLOG */
- TCPIP_APIMSG(&msg);
- return conn->err;
+ err = TCPIP_APIMSG(&msg);
+
+ NETCONN_SET_SAFE_ERR(conn, err);
+ return err;
+#else /* LWIP_TCP */
+ LWIP_UNUSED_ARG(conn);
+ LWIP_UNUSED_ARG(backlog);
+ return ERR_ARG;
+#endif /* LWIP_TCP */
}
/**
* Accept a new connection on a TCP listening netconn.
*
* @param conn the TCP listen netconn
- * @return the newly accepted netconn or NULL on timeout
+ * @param new_conn pointer where the new connection is stored
+ * @return ERR_OK if a new connection has been received or an error
+ * code otherwise
*/
-struct netconn *
-netconn_accept(struct netconn *conn)
+err_t
+netconn_accept(struct netconn *conn, struct netconn **new_conn)
{
+#if LWIP_TCP
struct netconn *newconn;
+ err_t err;
+#if TCP_LISTEN_BACKLOG
+ struct api_msg msg;
+#endif /* TCP_LISTEN_BACKLOG */
+
+ LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;);
+ *new_conn = NULL;
+ LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
+ LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;);
- LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return NULL;);
- LWIP_ERROR("netconn_accept: invalid acceptmbox", (conn->acceptmbox != SYS_MBOX_NULL), return NULL;);
+ err = conn->last_err;
+ if (ERR_IS_FATAL(err)) {
+ /* don't recv on fatal errors: this might block the application task
+ waiting on acceptmbox forever! */
+ return err;
+ }
#if LWIP_SO_RCVTIMEO
- if (sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
- newconn = NULL;
- } else
+ if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
+ NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
+ return ERR_TIMEOUT;
+ }
#else
- sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, 0);
+ sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0);
#endif /* LWIP_SO_RCVTIMEO*/
- {
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
+ /* Register event with callback */
+ API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
+ if (newconn == NULL) {
+ /* connection has been aborted */
+ NETCONN_SET_SAFE_ERR(conn, ERR_ABRT);
+ return ERR_ABRT;
+ }
#if TCP_LISTEN_BACKLOG
- if (newconn != NULL) {
- /* Let the stack know that we have accepted the connection. */
- struct api_msg msg;
- msg.function = do_recv;
- msg.msg.conn = conn;
- TCPIP_APIMSG(&msg);
- }
+ /* Let the stack know that we have accepted the connection. */
+ msg.function = do_recv;
+ msg.msg.conn = conn;
+ /* don't care for the return value of do_recv */
+ TCPIP_APIMSG(&msg);
#endif /* TCP_LISTEN_BACKLOG */
- }
- return newconn;
+ *new_conn = newconn;
+ /* don't set conn->last_err: it's only ERR_OK, anyway */
+ return ERR_OK;
+#else /* LWIP_TCP */
+ LWIP_UNUSED_ARG(conn);
+ LWIP_UNUSED_ARG(new_conn);
+ return ERR_ARG;
+#endif /* LWIP_TCP */
}
/**
- * Receive data (in form of a netbuf containing a packet buffer) from a netconn
+ * Receive data: actual implementation that doesn't care whether pbuf or netbuf
+ * is received
*
* @param conn the netconn from which to receive data
- * @return a new netbuf containing received data or NULL on memory error or timeout
+ * @param new_buf pointer where a new pbuf/netbuf is stored when received data
+ * @return ERR_OK if data has been received, an error code otherwise (timeout,
+ * memory error or another error)
*/
-struct netbuf *
-netconn_recv(struct netconn *conn)
+static err_t
+netconn_recv_data(struct netconn *conn, void **new_buf)
{
- struct api_msg msg;
- struct netbuf *buf = NULL;
- struct pbuf *p;
+ void *buf = NULL;
u16_t len;
+ err_t err;
+#if LWIP_TCP
+ struct api_msg msg;
+#endif /* LWIP_TCP */
- LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return NULL;);
-
- if (conn->recvmbox == SYS_MBOX_NULL) {
- /* @todo: should calling netconn_recv on a TCP listen conn be fatal (ERR_CONN)?? */
- /* TCP listen conns don't have a recvmbox! */
- conn->err = ERR_CONN;
- return NULL;
+ LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
+ *new_buf = NULL;
+ LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
+ LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
+
+ err = conn->last_err;
+ if (ERR_IS_FATAL(err)) {
+ /* don't recv on fatal errors: this might block the application task
+ waiting on recvmbox forever! */
+ /* @todo: this does not allow us to fetch data that has been put into recvmbox
+ before the fatal error occurred - is that a problem? */
+ return err;
}
- if (ERR_IS_FATAL(conn->err)) {
- return NULL;
+#if LWIP_SO_RCVTIMEO
+ if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
+ NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
+ return ERR_TIMEOUT;
}
+#else
+ sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
+#endif /* LWIP_SO_RCVTIMEO*/
- if (conn->type == NETCONN_TCP) {
#if LWIP_TCP
- if (conn->state == NETCONN_LISTEN) {
- /* @todo: should calling netconn_recv on a TCP listen conn be fatal?? */
- conn->err = ERR_CONN;
- return NULL;
+ if (conn->type == NETCONN_TCP) {
+ if (!netconn_get_noautorecved(conn) || (buf == NULL)) {
+ /* Let the stack know that we have taken the data. */
+ /* TODO: Speedup: Don't block and wait for the answer here
+ (to prevent multiple thread-switches). */
+ msg.function = do_recv;
+ msg.msg.conn = conn;
+ if (buf != NULL) {
+ msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len;
+ } else {
+ msg.msg.msg.r.len = 1;
+ }
+ /* don't care for the return value of do_recv */
+ TCPIP_APIMSG(&msg);
}
- buf = memp_malloc(MEMP_NETBUF);
-
+ /* If we are closed, we indicate that we no longer wish to use the socket */
if (buf == NULL) {
- conn->err = ERR_MEM;
- return NULL;
+ API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
+ /* Avoid to lose any previous error code */
+ NETCONN_SET_SAFE_ERR(conn, ERR_CLSD);
+ return ERR_CLSD;
}
+ len = ((struct pbuf *)buf)->tot_len;
+ }
+#endif /* LWIP_TCP */
+#if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
+ else
+#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
+#if (LWIP_UDP || LWIP_RAW)
+ {
+ LWIP_ASSERT("buf != NULL", buf != NULL);
+ len = netbuf_len((struct netbuf *)buf);
+ }
+#endif /* (LWIP_UDP || LWIP_RAW) */
-#if LWIP_SO_RCVTIMEO
- if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) {
- memp_free(MEMP_NETBUF, buf);
- conn->err = ERR_TIMEOUT;
- return NULL;
- }
-#else
- sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, 0);
-#endif /* LWIP_SO_RCVTIMEO*/
+#if LWIP_SO_RCVBUF
+ SYS_ARCH_DEC(conn->recv_avail, len);
+#endif /* LWIP_SO_RCVBUF */
+ /* Register event with callback */
+ API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
- if (p != NULL) {
- len = p->tot_len;
- SYS_ARCH_DEC(conn->recv_avail, len);
- } else {
- len = 0;
- }
+ LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
+ *new_buf = buf;
+ /* don't set conn->last_err: it's only ERR_OK, anyway */
+ return ERR_OK;
+}
- /* If we are closed, we indicate that we no longer wish to use the socket */
- if (p == NULL) {
+/**
+ * Receive data (in form of a pbuf) from a TCP netconn
+ *
+ * @param conn the netconn from which to receive data
+ * @param new_buf pointer where a new pbuf is stored when received data
+ * @return ERR_OK if data has been received, an error code otherwise (timeout,
+ * memory error or another error)
+ * ERR_ARG if conn is not a TCP netconn
+ */
+err_t
+netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
+{
+ LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
+ netconn_type(conn) == NETCONN_TCP, return ERR_ARG;);
+
+ return netconn_recv_data(conn, (void **)new_buf);
+}
+
+/**
+ * Receive data (in form of a netbuf containing a packet buffer) from a netconn
+ *
+ * @param conn the netconn from which to receive data
+ * @param new_buf pointer where a new netbuf is stored when received data
+ * @return ERR_OK if data has been received, an error code otherwise (timeout,
+ * memory error or another error)
+ */
+err_t
+netconn_recv(struct netconn *conn, struct netbuf **new_buf)
+{
+#if LWIP_TCP
+ struct netbuf *buf = NULL;
+ err_t err;
+#endif /* LWIP_TCP */
+
+ LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
+ *new_buf = NULL;
+ LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
+ LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
+
+#if LWIP_TCP
+ if (conn->type == NETCONN_TCP) {
+ struct pbuf *p = NULL;
+ /* This is not a listening netconn, since recvmbox is set */
+
+ buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
+ if (buf == NULL) {
+ NETCONN_SET_SAFE_ERR(conn, ERR_MEM);
+ return ERR_MEM;
+ }
+
+ err = netconn_recv_data(conn, (void **)&p);
+ if (err != ERR_OK) {
memp_free(MEMP_NETBUF, buf);
- /* Avoid to lose any previous error code */
- if (conn->err == ERR_OK) {
- conn->err = ERR_CLSD;
- }
- return NULL;
+ return err;
}
+ LWIP_ASSERT("p != NULL", p != NULL);
buf->p = p;
buf->ptr = p;
buf->port = 0;
- buf->addr = NULL;
+ ip_addr_set_any(&buf->addr);
+ *new_buf = buf;
+ /* don't set conn->last_err: it's only ERR_OK, anyway */
+ return ERR_OK;
+ } else
+#endif /* LWIP_TCP */
+ {
+#if (LWIP_UDP || LWIP_RAW)
+ return netconn_recv_data(conn, (void **)new_buf);
+#endif /* (LWIP_UDP || LWIP_RAW) */
+ }
+}
+/**
+ * TCP: update the receive window: by calling this, the application
+ * tells the stack that it has processed data and is able to accept
+ * new data.
+ * ATTENTION: use with care, this is mainly used for sockets!
+ * Can only be used when calling netconn_set_noautorecved(conn, 1) before.
+ *
+ * @param conn the netconn for which to update the receive window
+ * @param length amount of data processed (ATTENTION: this must be accurate!)
+ */
+void
+netconn_recved(struct netconn *conn, u32_t length)
+{
+#if LWIP_TCP
+ if ((conn != NULL) && (conn->type == NETCONN_TCP) &&
+ (netconn_get_noautorecved(conn))) {
+ struct api_msg msg;
/* Let the stack know that we have taken the data. */
+ /* TODO: Speedup: Don't block and wait for the answer here
+ (to prevent multiple thread-switches). */
msg.function = do_recv;
msg.msg.conn = conn;
- if (buf != NULL) {
- msg.msg.msg.r.len = buf->p->tot_len;
- } else {
- msg.msg.msg.r.len = 1;
- }
+ msg.msg.msg.r.len = length;
+ /* don't care for the return value of do_recv */
TCPIP_APIMSG(&msg);
-#endif /* LWIP_TCP */
- } else {
-#if (LWIP_UDP || LWIP_RAW)
-#if LWIP_SO_RCVTIMEO
- if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&buf, conn->recv_timeout)==SYS_ARCH_TIMEOUT) {
- buf = NULL;
- }
-#else
- sys_arch_mbox_fetch(conn->recvmbox, (void *)&buf, 0);
-#endif /* LWIP_SO_RCVTIMEO*/
- if (buf!=NULL) {
- SYS_ARCH_DEC(conn->recv_avail, buf->p->tot_len);
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
- }
-#endif /* (LWIP_UDP || LWIP_RAW) */
}
-
- LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err));
-
- return buf;
+#else /* LWIP_TCP */
+ LWIP_UNUSED_ARG(conn);
+ LWIP_UNUSED_ARG(length);
+#endif /* LWIP_TCP */
}
/**
@@ -403,10 +537,10 @@ netconn_recv(struct netconn *conn)
* @return ERR_OK if data was sent, any other err_t on error
*/
err_t
-netconn_sendto(struct netconn *conn, struct netbuf *buf, struct ip_addr *addr, u16_t port)
+netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port)
{
if (buf != NULL) {
- buf->addr = addr;
+ ip_addr_set(&buf->addr, addr);
buf->port = port;
return netconn_send(conn, buf);
}
@@ -424,6 +558,7 @@ err_t
netconn_send(struct netconn *conn, struct netbuf *buf)
{
struct api_msg msg;
+ err_t err;
LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
@@ -431,8 +566,10 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
msg.function = do_send;
msg.msg.conn = conn;
msg.msg.msg.b = buf;
- TCPIP_APIMSG(&msg);
- return conn->err;
+ err = TCPIP_APIMSG(&msg);
+
+ NETCONN_SET_SAFE_ERR(conn, err);
+ return err;
}
/**
@@ -442,18 +579,25 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
* @param dataptr pointer to the application buffer that contains the data to send
* @param size size of the application data to send
* @param apiflags combination of following flags :
- * - NETCONN_COPY (0x01) data will be copied into memory belonging to the stack
- * - NETCONN_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent
+ * - NETCONN_COPY: data will be copied into memory belonging to the stack
+ * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent
+ * - NETCONN_DONTBLOCK: only write the data if all dat can be written at once
* @return ERR_OK if data was sent, any other err_t on error
*/
err_t
netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apiflags)
{
struct api_msg msg;
+ err_t err;
LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;);
+ if (size == 0) {
+ return ERR_OK;
+ }
+ /* @todo: for non-blocking write, check if 'size' would ever fit into
+ snd_queue or snd_buf */
msg.function = do_write;
msg.msg.conn = conn;
msg.msg.msg.w.dataptr = dataptr;
@@ -462,27 +606,62 @@ netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apifl
/* For locking the core: this _can_ be delayed on low memory/low send buffer,
but if it is, this is done inside api_msg.c:do_write(), so we can use the
non-blocking version here. */
- TCPIP_APIMSG(&msg);
- return conn->err;
+ err = TCPIP_APIMSG(&msg);
+
+ NETCONN_SET_SAFE_ERR(conn, err);
+ return err;
}
/**
- * Close a TCP netconn (doesn't delete it).
+ * Close ot shutdown a TCP netconn (doesn't delete it).
*
- * @param conn the TCP netconn to close
+ * @param conn the TCP netconn to close or shutdown
+ * @param how fully close or only shutdown one side?
* @return ERR_OK if the netconn was closed, any other err_t on error
*/
-err_t
-netconn_close(struct netconn *conn)
+static err_t
+netconn_close_shutdown(struct netconn *conn, u8_t how)
{
struct api_msg msg;
+ err_t err;
LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;);
msg.function = do_close;
msg.msg.conn = conn;
- tcpip_apimsg(&msg);
- return conn->err;
+ /* shutting down both ends is the same as closing */
+ msg.msg.msg.sd.shut = how;
+ /* because of the LWIP_TCPIP_CORE_LOCKING implementation of do_close,
+ don't use TCPIP_APIMSG here */
+ err = tcpip_apimsg(&msg);
+
+ NETCONN_SET_SAFE_ERR(conn, err);
+ return err;
+}
+
+/**
+ * Close a TCP netconn (doesn't delete it).
+ *
+ * @param conn the TCP netconn to close
+ * @return ERR_OK if the netconn was closed, any other err_t on error
+ */
+err_t
+netconn_close(struct netconn *conn)
+{
+ /* shutting down both ends is the same as closing */
+ return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR);
+}
+
+/**
+ * Shut down one or both sides of a TCP netconn (doesn't delete it).
+ *
+ * @param conn the TCP netconn to shut down
+ * @return ERR_OK if the netconn was closed, any other err_t on error
+ */
+err_t
+netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
+{
+ return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
}
#if LWIP_IGMP
@@ -491,28 +670,31 @@ netconn_close(struct netconn *conn)
*
* @param conn the UDP netconn for which to change multicast addresses
* @param multiaddr IP address of the multicast group to join or leave
- * @param interface the IP address of the network interface on which to send
+ * @param netif_addr the IP address of the network interface on which to send
* the igmp message
* @param join_or_leave flag whether to send a join- or leave-message
* @return ERR_OK if the action was taken, any err_t on error
*/
err_t
netconn_join_leave_group(struct netconn *conn,
- struct ip_addr *multiaddr,
- struct ip_addr *interface,
+ ip_addr_t *multiaddr,
+ ip_addr_t *netif_addr,
enum netconn_igmp join_or_leave)
{
struct api_msg msg;
+ err_t err;
LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;);
msg.function = do_join_leave_group;
msg.msg.conn = conn;
msg.msg.msg.jl.multiaddr = multiaddr;
- msg.msg.msg.jl.interface = interface;
+ msg.msg.msg.jl.netif_addr = netif_addr;
msg.msg.msg.jl.join_or_leave = join_or_leave;
- TCPIP_APIMSG(&msg);
- return conn->err;
+ err = TCPIP_APIMSG(&msg);
+
+ NETCONN_SET_SAFE_ERR(conn, err);
+ return err;
}
#endif /* LWIP_IGMP */
@@ -521,14 +703,14 @@ netconn_join_leave_group(struct netconn *conn,
* Execute a DNS query, only one IP address is returned
*
* @param name a string representation of the DNS host name to query
- * @param addr a preallocated struct ip_addr where to store the resolved IP address
+ * @param addr a preallocated ip_addr_t where to store the resolved IP address
* @return ERR_OK: resolving succeeded
* ERR_MEM: memory error, try again later
* ERR_ARG: dns client not initialized or invalid hostname
* ERR_VAL: dns server response was invalid
*/
err_t
-netconn_gethostbyname(const char *name, struct ip_addr *addr)
+netconn_gethostbyname(const char *name, ip_addr_t *addr)
{
struct dns_api_msg msg;
err_t err;
@@ -537,19 +719,19 @@ netconn_gethostbyname(const char *name, struct ip_addr *addr)
LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
- sem = sys_sem_new(0);
- if (sem == SYS_SEM_NULL) {
- return ERR_MEM;
+ err = sys_sem_new(&sem, 0);
+ if (err != ERR_OK) {
+ return err;
}
msg.name = name;
msg.addr = addr;
msg.err = &err;
- msg.sem = sem;
+ msg.sem = &sem;
tcpip_callback(do_gethostbyname, &msg);
- sys_sem_wait(sem);
- sys_sem_free(sem);
+ sys_sem_wait(&sem);
+ sys_sem_free(&sem);
return err;
}
diff --git a/core/lwip/src/api/api_msg.c b/core/lwip/src/api/api_msg.c
index 46c9abf2..448f96dd 100644
--- a/core/lwip/src/api/api_msg.c
+++ b/core/lwip/src/api/api_msg.c
@@ -54,6 +54,12 @@
#include <string.h>
+#define SET_NONBLOCKING_CONNECT(conn, val) do { if(val) { \
+ (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \
+} else { \
+ (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0)
+#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0)
+
/* forward declarations */
#if LWIP_TCP
static err_t do_writemore(struct netconn *conn);
@@ -70,24 +76,22 @@ static void do_close_internal(struct netconn *conn);
*/
static u8_t
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
- struct ip_addr *addr)
+ ip_addr_t *addr)
{
struct pbuf *q;
struct netbuf *buf;
struct netconn *conn;
-#if LWIP_SO_RCVBUF
- int recv_avail;
-#endif /* LWIP_SO_RCVBUF */
LWIP_UNUSED_ARG(addr);
- conn = arg;
+ conn = (struct netconn *)arg;
+ if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) {
#if LWIP_SO_RCVBUF
- SYS_ARCH_GET(conn->recv_avail, recv_avail);
- if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL) &&
- ((recv_avail + (int)(p->tot_len)) <= conn->recv_bufsize)) {
-#else /* LWIP_SO_RCVBUF */
- if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL)) {
+ int recv_avail;
+ SYS_ARCH_GET(conn->recv_avail, recv_avail);
+ if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) {
+ return 0;
+ }
#endif /* LWIP_SO_RCVBUF */
/* copy the whole packet into new pbufs */
q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
@@ -98,8 +102,9 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
}
}
- if(q != NULL) {
- buf = memp_malloc(MEMP_NETBUF);
+ if (q != NULL) {
+ u16_t len;
+ buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
if (buf == NULL) {
pbuf_free(q);
return 0;
@@ -107,16 +112,19 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
buf->p = q;
buf->ptr = q;
- buf->addr = &(((struct ip_hdr*)(q->payload))->src);
+ ip_addr_copy(buf->addr, *ip_current_src_addr());
buf->port = pcb->protocol;
- if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
+ len = 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);
+#if LWIP_SO_RCVBUF
+ SYS_ARCH_INC(conn->recv_avail, len);
+#endif /* LWIP_SO_RCVBUF */
/* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len);
+ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
}
}
}
@@ -134,10 +142,11 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
*/
static void
recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
- struct ip_addr *addr, u16_t port)
+ ip_addr_t *addr, u16_t port)
{
struct netbuf *buf;
struct netconn *conn;
+ u16_t len;
#if LWIP_SO_RCVBUF
int recv_avail;
#endif /* LWIP_SO_RCVBUF */
@@ -145,47 +154,53 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
LWIP_UNUSED_ARG(pcb); /* only used for asserts... */
LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
- conn = arg;
+ conn = (struct netconn *)arg;
LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
#if LWIP_SO_RCVBUF
SYS_ARCH_GET(conn->recv_avail, recv_avail);
- if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL) ||
+ if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) ||
((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
#else /* LWIP_SO_RCVBUF */
- if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) {
+ if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) {
#endif /* LWIP_SO_RCVBUF */
pbuf_free(p);
return;
}
- buf = memp_malloc(MEMP_NETBUF);
+ buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
if (buf == NULL) {
pbuf_free(p);
return;
} else {
buf->p = p;
buf->ptr = p;
- buf->addr = addr;
+ ip_addr_set(&buf->addr, addr);
buf->port = port;
#if LWIP_NETBUF_RECVINFO
{
const struct ip_hdr* iphdr = ip_current_header();
/* get the UDP header - always in the first pbuf, ensured by udp_input */
const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr));
- buf->toaddr = (struct ip_addr*)&iphdr->dest;
- buf->toport = udphdr->dest;
+#if LWIP_CHECKSUM_ON_COPY
+ buf->flags = NETBUF_FLAG_DESTADDR;
+#endif /* LWIP_CHECKSUM_ON_COPY */
+ ip_addr_set(&buf->toaddr, ip_current_dest_addr());
+ buf->toport_chksum = udphdr->dest;
}
#endif /* LWIP_NETBUF_RECVINFO */
}
- if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
+ len = 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);
+#if LWIP_SO_RCVBUF
+ SYS_ARCH_INC(conn->recv_avail, len);
+#endif /* LWIP_SO_RCVBUF */
/* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
+ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
}
}
#endif /* LWIP_UDP */
@@ -206,24 +221,40 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
LWIP_UNUSED_ARG(pcb);
LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL);
LWIP_ASSERT("recv_tcp must have an argument", arg != NULL);
- conn = arg;
+ conn = (struct netconn *)arg;
LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);
- if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) {
+ if (conn == NULL) {
return ERR_VAL;
}
+ if (!sys_mbox_valid(&conn->recvmbox)) {
+ /* recvmbox already deleted */
+ if (p != NULL) {
+ tcp_recved(pcb, p->tot_len);
+ pbuf_free(p);
+ }
+ return ERR_OK;
+ }
+ /* Unlike for UDP or RAW pcbs, don't check for available space
+ using recv_avail since that could break the connection
+ (data is already ACKed) */
+
+ /* don't overwrite fatal errors! */
+ NETCONN_SET_SAFE_ERR(conn, err);
- conn->err = err;
if (p != NULL) {
len = p->tot_len;
- SYS_ARCH_INC(conn->recv_avail, len);
} else {
len = 0;
}
- if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) {
+ if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) {
+ /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */
return ERR_MEM;
} else {
+#if LWIP_SO_RCVBUF
+ SYS_ARCH_INC(conn->recv_avail, len);
+#endif /* LWIP_SO_RCVBUF */
/* Register event with callback */
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
}
@@ -245,7 +276,7 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
static err_t
poll_tcp(void *arg, struct tcp_pcb *pcb)
{
- struct netconn *conn = arg;
+ struct netconn *conn = (struct netconn *)arg;
LWIP_UNUSED_ARG(pcb);
LWIP_ASSERT("conn != NULL", (conn != NULL));
@@ -255,6 +286,18 @@ poll_tcp(void *arg, struct tcp_pcb *pcb)
} else if (conn->state == NETCONN_CLOSE) {
do_close_internal(conn);
}
+ /* @todo: implement connect timeout here? */
+
+ /* Did a nonblocking write fail before? Then check available write-space. */
+ if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) {
+ /* If the queued byte- or pbuf-count drops below the configured low-water limit,
+ let select mark this pcb as writable again. */
+ if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
+ (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
+ conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
+ API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
+ }
+ }
return ERR_OK;
}
@@ -269,20 +312,23 @@ poll_tcp(void *arg, struct tcp_pcb *pcb)
static err_t
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
{
- struct netconn *conn = arg;
+ struct netconn *conn = (struct netconn *)arg;
LWIP_UNUSED_ARG(pcb);
LWIP_ASSERT("conn != NULL", (conn != NULL));
if (conn->state == NETCONN_WRITE) {
- LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL);
do_writemore(conn);
} else if (conn->state == NETCONN_CLOSE) {
do_close_internal(conn);
}
if (conn) {
- if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)) {
+ /* If the queued byte- or pbuf-count drops below the configured low-water limit,
+ let select mark this pcb as writable again. */
+ if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
+ (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
+ conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
}
}
@@ -301,33 +347,59 @@ static void
err_tcp(void *arg, err_t err)
{
struct netconn *conn;
+ enum netconn_state old_state;
+ SYS_ARCH_DECL_PROTECT(lev);
- conn = arg;
+ conn = (struct netconn *)arg;
LWIP_ASSERT("conn != NULL", (conn != NULL));
conn->pcb.tcp = NULL;
- conn->err = err;
- if (conn->recvmbox != SYS_MBOX_NULL) {
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
- sys_mbox_post(conn->recvmbox, NULL);
- }
- if (conn->op_completed != SYS_SEM_NULL && conn->state == NETCONN_CONNECT) {
- conn->state = NETCONN_NONE;
- sys_sem_signal(conn->op_completed);
+ /* no check since this is always fatal! */
+ SYS_ARCH_PROTECT(lev);
+ conn->last_err = err;
+ SYS_ARCH_UNPROTECT(lev);
+
+ /* reset conn->state now before waking up other threads */
+ old_state = conn->state;
+ conn->state = NETCONN_NONE;
+
+ /* Notify the user layer about a connection error. Used to signal
+ select. */
+ API_EVENT(conn, NETCONN_EVT_ERROR, 0);
+ /* Try to release selects pending on 'read' or 'write', too.
+ They will get an error if they actually try to read or write. */
+ API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
+ API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
+
+ /* pass NULL-message to recvmbox to wake up pending recv */
+ if (sys_mbox_valid(&conn->recvmbox)) {
+ /* use trypost to prevent deadlock */
+ sys_mbox_trypost(&conn->recvmbox, NULL);
}
- if (conn->acceptmbox != SYS_MBOX_NULL) {
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
- sys_mbox_post(conn->acceptmbox, NULL);
+ /* pass NULL-message to acceptmbox to wake up pending accept */
+ if (sys_mbox_valid(&conn->acceptmbox)) {
+ /* use trypost to preven deadlock */
+ sys_mbox_trypost(&conn->acceptmbox, NULL);
}
- if ((conn->state == NETCONN_WRITE) || (conn->state == NETCONN_CLOSE)) {
+
+ if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) ||
+ (old_state == NETCONN_CONNECT)) {
/* calling do_writemore/do_close_internal is not necessary
since the pcb has already been deleted! */
- conn->state = NETCONN_NONE;
- /* wake up the waiting task */
- sys_sem_signal(conn->op_completed);
+ int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn);
+ SET_NONBLOCKING_CONNECT(conn, 0);
+
+ if (!was_nonblocking_connect) {
+ /* set error return code */
+ LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
+ conn->current_msg->err = err;
+ conn->current_msg = NULL;
+ /* wake up the waiting task */
+ sys_sem_signal(&conn->op_completed);
+ }
+ } else {
+ LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL);
}
}
@@ -360,17 +432,14 @@ static err_t
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
{
struct netconn *newconn;
- struct netconn *conn;
+ struct netconn *conn = (struct netconn *)arg;
-#if API_MSG_DEBUG
-#if TCP_DEBUG
- tcp_debug_print_state(newpcb->state);
-#endif /* TCP_DEBUG */
-#endif /* API_MSG_DEBUG */
- conn = (struct netconn *)arg;
+ LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));
- LWIP_ERROR("accept_function: invalid conn->acceptmbox",
- conn->acceptmbox != SYS_MBOX_NULL, return ERR_VAL;);
+ if (!sys_mbox_valid(&conn->acceptmbox)) {
+ LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n"));
+ return ERR_VAL;
+ }
/* We have to set the callback here even though
* the new socket is unknown. conn->socket is marked as -1. */
@@ -380,12 +449,17 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
}
newconn->pcb.tcp = newpcb;
setup_tcp(newconn);
- newconn->err = err;
+ /* no protection: when creating the pcb, the netconn is not yet known
+ to the application thread */
+ newconn->last_err = err;
- if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) {
- /* When returning != ERR_OK, the connection is aborted in tcp_process(),
+ if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) {
+ /* When returning != ERR_OK, the pcb is aborted in tcp_process(),
so do nothing here! */
newconn->pcb.tcp = NULL;
+ /* no need to drain since we know the recvmbox is empty. */
+ sys_mbox_free(&newconn->recvmbox);
+ sys_mbox_set_invalid(&newconn->recvmbox);
netconn_free(newconn);
return ERR_MEM;
} else {
@@ -404,60 +478,56 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
* @param msg the api_msg_msg describing the connection type
* @return msg->conn->err, but the return value is currently ignored
*/
-static err_t
+static void
pcb_new(struct api_msg_msg *msg)
{
- msg->conn->err = ERR_OK;
-
- LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
+ LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
- /* Allocate a PCB for this connection */
- switch(NETCONNTYPE_GROUP(msg->conn->type)) {
+ /* Allocate a PCB for this connection */
+ switch(NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
- case NETCONN_RAW:
- msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
- if(msg->conn->pcb.raw == NULL) {
- msg->conn->err = ERR_MEM;
- break;
- }
- raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
- break;
+ case NETCONN_RAW:
+ msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
+ if(msg->conn->pcb.raw == NULL) {
+ msg->err = ERR_MEM;
+ break;
+ }
+ raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
+ break;
#endif /* LWIP_RAW */
#if LWIP_UDP
- case NETCONN_UDP:
- msg->conn->pcb.udp = udp_new();
- if(msg->conn->pcb.udp == NULL) {
- msg->conn->err = ERR_MEM;
- break;
- }
+ case NETCONN_UDP:
+ msg->conn->pcb.udp = udp_new();
+ if(msg->conn->pcb.udp == NULL) {
+ msg->err = ERR_MEM;
+ break;
+ }
#if LWIP_UDPLITE
- if (msg->conn->type==NETCONN_UDPLITE) {
- udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
- }
+ if (msg->conn->type==NETCONN_UDPLITE) {
+ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
+ }
#endif /* LWIP_UDPLITE */
- if (msg->conn->type==NETCONN_UDPNOCHKSUM) {
- udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
- }
- udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
- break;
+ if (msg->conn->type==NETCONN_UDPNOCHKSUM) {
+ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
+ }
+ udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
+ break;
#endif /* LWIP_UDP */
#if LWIP_TCP
- case NETCONN_TCP:
- msg->conn->pcb.tcp = tcp_new();
- if(msg->conn->pcb.tcp == NULL) {
- msg->conn->err = ERR_MEM;
- break;
- }
- setup_tcp(msg->conn);
- break;
+ case NETCONN_TCP:
+ msg->conn->pcb.tcp = tcp_new();
+ if(msg->conn->pcb.tcp == NULL) {
+ msg->err = ERR_MEM;
+ break;
+ }
+ setup_tcp(msg->conn);
+ break;
#endif /* LWIP_TCP */
- default:
- /* Unsupported netconn type, e.g. protocol disabled */
- msg->conn->err = ERR_VAL;
- break;
- }
-
- return msg->conn->err;
+ default:
+ /* Unsupported netconn type, e.g. protocol disabled */
+ msg->err = ERR_VAL;
+ break;
+ }
}
/**
@@ -469,14 +539,15 @@ pcb_new(struct api_msg_msg *msg)
void
do_newconn(struct api_msg_msg *msg)
{
- if(msg->conn->pcb.tcp == NULL) {
- pcb_new(msg);
- }
- /* Else? This "new" connection already has a PCB allocated. */
- /* Is this an error condition? Should it be deleted? */
- /* We currently just are happy and return. */
-
- TCPIP_APIMSG_ACK(msg);
+ msg->err = ERR_OK;
+ if(msg->conn->pcb.tcp == NULL) {
+ pcb_new(msg);
+ }
+ /* Else? This "new" connection already has a PCB allocated. */
+ /* Is this an error condition? Should it be deleted? */
+ /* We currently just are happy and return. */
+
+ TCPIP_APIMSG_ACK(msg);
}
/**
@@ -495,12 +566,12 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
struct netconn *conn;
int size;
- conn = memp_malloc(MEMP_NETCONN);
+ conn = (struct netconn *)memp_malloc(MEMP_NETCONN);
if (conn == NULL) {
return NULL;
}
- conn->err = ERR_OK;
+ conn->last_err = ERR_OK;
conn->type = t;
conn->pcb.tcp = NULL;
@@ -530,35 +601,37 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
}
#endif
- if ((conn->op_completed = sys_sem_new(0)) == SYS_SEM_NULL) {
+ if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) {
memp_free(MEMP_NETCONN, conn);
return NULL;
}
- if ((conn->recvmbox = sys_mbox_new(size)) == SYS_MBOX_NULL) {
- sys_sem_free(conn->op_completed);
+ if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) {
+ sys_sem_free(&conn->op_completed);
memp_free(MEMP_NETCONN, conn);
return NULL;
}
- conn->acceptmbox = SYS_MBOX_NULL;
+#if LWIP_TCP
+ sys_mbox_set_invalid(&conn->acceptmbox);
+#endif
conn->state = NETCONN_NONE;
+#if LWIP_SOCKET
/* initialize socket to -1 since 0 is a valid socket */
conn->socket = -1;
+#endif /* LWIP_SOCKET */
conn->callback = callback;
- conn->recv_avail = 0;
#if LWIP_TCP
- conn->write_msg = NULL;
+ conn->current_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 = RECV_BUFSIZE_DEFAULT;
+ conn->recv_avail = 0;
#endif /* LWIP_SO_RCVBUF */
+ conn->flags = 0;
return conn;
}
@@ -571,37 +644,83 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
void
netconn_free(struct netconn *conn)
{
- void *mem;
LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL);
+ LWIP_ASSERT("recvmbox must be deallocated before calling this function",
+ !sys_mbox_valid(&conn->recvmbox));
+#if LWIP_TCP
+ LWIP_ASSERT("acceptmbox must be deallocated before calling this function",
+ !sys_mbox_valid(&conn->acceptmbox));
+#endif /* LWIP_TCP */
+
+ sys_sem_free(&conn->op_completed);
+ sys_sem_set_invalid(&conn->op_completed);
+
+ memp_free(MEMP_NETCONN, conn);
+}
- /* Drain the recvmbox. */
- if (conn->recvmbox != SYS_MBOX_NULL) {
- while (sys_mbox_tryfetch(conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {
+/**
+ * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in
+ * these mboxes
+ *
+ * @param conn the netconn to free
+ * @bytes_drained bytes drained from recvmbox
+ * @accepts_drained pending connections drained from acceptmbox
+ */
+static void
+netconn_drain(struct netconn *conn)
+{
+ void *mem;
+#if LWIP_TCP
+ struct pbuf *p;
+#endif /* LWIP_TCP */
+
+ /* This runs in tcpip_thread, so we don't need to lock against rx packets */
+
+ /* Delete and drain the recvmbox. */
+ if (sys_mbox_valid(&conn->recvmbox)) {
+ while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {
+#if LWIP_TCP
if (conn->type == NETCONN_TCP) {
if(mem != NULL) {
- pbuf_free((struct pbuf *)mem);
+ p = (struct pbuf*)mem;
+ /* pcb might be set to NULL already by err_tcp() */
+ if (conn->pcb.tcp != NULL) {
+ tcp_recved(conn->pcb.tcp, p->tot_len);
+ }
+ pbuf_free(p);
}
- } else {
+ } else
+#endif /* LWIP_TCP */
+ {
netbuf_delete((struct netbuf *)mem);
}
}
- sys_mbox_free(conn->recvmbox);
- conn->recvmbox = SYS_MBOX_NULL;
+ sys_mbox_free(&conn->recvmbox);
+ sys_mbox_set_invalid(&conn->recvmbox);
}
- /* Drain the acceptmbox. */
- if (conn->acceptmbox != SYS_MBOX_NULL) {
- while (sys_mbox_tryfetch(conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) {
- netconn_delete((struct netconn *)mem);
+ /* Delete and drain the acceptmbox. */
+#if LWIP_TCP
+ if (sys_mbox_valid(&conn->acceptmbox)) {
+ while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) {
+ struct netconn *newconn = (struct netconn *)mem;
+ /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */
+ /* pcb might be set to NULL already by err_tcp() */
+ if (conn->pcb.tcp != NULL) {
+ tcp_accepted(conn->pcb.tcp);
+ }
+ /* drain recvmbox */
+ netconn_drain(newconn);
+ if (newconn->pcb.tcp != NULL) {
+ tcp_abort(newconn->pcb.tcp);
+ newconn->pcb.tcp = NULL;
+ }
+ netconn_free(newconn);
}
- sys_mbox_free(conn->acceptmbox);
- conn->acceptmbox = SYS_MBOX_NULL;
+ sys_mbox_free(&conn->acceptmbox);
+ sys_mbox_set_invalid(&conn->acceptmbox);
}
-
- sys_sem_free(conn->op_completed);
- conn->op_completed = SYS_SEM_NULL;
-
- memp_free(MEMP_NETCONN, conn);
+#endif /* LWIP_TCP */
}
#if LWIP_TCP
@@ -616,38 +735,66 @@ static void
do_close_internal(struct netconn *conn)
{
err_t err;
+ u8_t shut, shut_rx, shut_tx, close;
LWIP_ASSERT("invalid conn", (conn != NULL));
LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP));
LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));
LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
+ LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
+
+ shut = conn->current_msg->msg.sd.shut;
+ shut_rx = shut & NETCONN_SHUT_RD;
+ shut_tx = shut & NETCONN_SHUT_WR;
+ /* shutting down both ends is the same as closing */
+ close = shut == NETCONN_SHUT_RDWR;
/* Set back some callback pointers */
- tcp_arg(conn->pcb.tcp, NULL);
+ if (close) {
+ tcp_arg(conn->pcb.tcp, NULL);
+ }
if (conn->pcb.tcp->state == LISTEN) {
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);
+ if (shut_rx) {
+ tcp_recv(conn->pcb.tcp, NULL);
+ tcp_accept(conn->pcb.tcp, NULL);
+ }
+ if (shut_tx) {
+ tcp_sent(conn->pcb.tcp, NULL);
+ }
+ if (close) {
+ tcp_poll(conn->pcb.tcp, NULL, 4);
+ tcp_err(conn->pcb.tcp, NULL);
+ }
}
/* Try to close the connection */
- err = tcp_close(conn->pcb.tcp);
+ if (shut == NETCONN_SHUT_RDWR) {
+ err = tcp_close(conn->pcb.tcp);
+ } else {
+ err = tcp_shutdown(conn->pcb.tcp, shut & NETCONN_SHUT_RD, shut & NETCONN_SHUT_WR);
+ }
if (err == ERR_OK) {
/* Closing succeeded */
+ conn->current_msg->err = ERR_OK;
+ conn->current_msg = NULL;
conn->state = NETCONN_NONE;
/* Set back some callback pointers as conn is going away */
conn->pcb.tcp = NULL;
- conn->err = ERR_OK;
- /* Trigger select() in socket layer. This send should something else so the
- errorfd is set, not the read and write fd! */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
- API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
+ /* Trigger select() in socket layer. Make sure everybody notices activity
+ on the connection, error first! */
+ if (close) {
+ API_EVENT(conn, NETCONN_EVT_ERROR, 0);
+ }
+ if (shut_rx) {
+ API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
+ }
+ if (shut_tx) {
+ API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
+ }
/* wake up the application task */
- sys_sem_signal(conn->op_completed);
+ sys_sem_signal(&conn->op_completed);
} else {
/* Closing failed, restore some of the callbacks */
/* Closing of listen pcb will never fail! */
@@ -656,6 +803,7 @@ do_close_internal(struct netconn *conn)
tcp_poll(conn->pcb.tcp, poll_tcp, 4);
tcp_err(conn->pcb.tcp, err_tcp);
tcp_arg(conn->pcb.tcp, conn);
+ /* don't restore recv callback: we don't want to receive any more data */
}
/* If closing didn't succeed, we get called again either
from poll_tcp or from sent_tcp */
@@ -671,40 +819,59 @@ do_close_internal(struct netconn *conn)
void
do_delconn(struct api_msg_msg *msg)
{
- if (msg->conn->pcb.tcp != NULL) {
- switch (NETCONNTYPE_GROUP(msg->conn->type)) {
+ /* @todo TCP: abort running write/connect? */
+ if ((msg->conn->state != NETCONN_NONE) &&
+ (msg->conn->state != NETCONN_LISTEN) &&
+ (msg->conn->state != NETCONN_CONNECT)) {
+ /* this only happens for TCP netconns */
+ LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP);
+ msg->err = ERR_INPROGRESS;
+ } else {
+ LWIP_ASSERT("blocking connect in progress",
+ (msg->conn->state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn));
+ /* Drain and delete mboxes */
+ netconn_drain(msg->conn);
+
+ if (msg->conn->pcb.tcp != NULL) {
+
+ switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
- case NETCONN_RAW:
- raw_remove(msg->conn->pcb.raw);
- break;
+ case NETCONN_RAW:
+ raw_remove(msg->conn->pcb.raw);
+ break;
#endif /* LWIP_RAW */
#if LWIP_UDP
- case NETCONN_UDP:
- msg->conn->pcb.udp->recv_arg = NULL;
- udp_remove(msg->conn->pcb.udp);
- break;
+ case NETCONN_UDP:
+ msg->conn->pcb.udp->recv_arg = NULL;
+ udp_remove(msg->conn->pcb.udp);
+ break;
#endif /* LWIP_UDP */
#if LWIP_TCP
- case NETCONN_TCP:
- msg->conn->state = NETCONN_CLOSE;
- do_close_internal(msg->conn);
- /* API_EVENT is called inside do_close_internal, before releasing
- the application thread, so we can return at this point! */
- return;
+ case NETCONN_TCP:
+ LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
+ msg->conn->write_offset == 0);
+ msg->conn->state = NETCONN_CLOSE;
+ msg->msg.sd.shut = NETCONN_SHUT_RDWR;
+ msg->conn->current_msg = msg;
+ do_close_internal(msg->conn);
+ /* API_EVENT is called inside do_close_internal, before releasing
+ the application thread, so we can return at this point! */
+ return;
#endif /* LWIP_TCP */
- default:
- break;
+ default:
+ break;
+ }
+ msg->conn->pcb.tcp = NULL;
}
- }
- /* tcp netconns don't come here! */
-
- /* Trigger select() in socket layer. This send should something else so the
- errorfd is set, not the read and write fd! */
- API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0);
- API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
+ /* tcp netconns don't come here! */
- if (msg->conn->op_completed != SYS_SEM_NULL) {
- sys_sem_signal(msg->conn->op_completed);
+ /* @todo: this lets select make the socket readable and writable,
+ which is wrong! errfd instead? */
+ API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0);
+ API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
+ }
+ if (sys_sem_valid(&msg->conn->op_completed)) {
+ sys_sem_signal(&msg->conn->op_completed);
}
}
@@ -718,30 +885,30 @@ do_delconn(struct api_msg_msg *msg)
void
do_bind(struct api_msg_msg *msg)
{
- if (!ERR_IS_FATAL(msg->conn->err)) {
+ if (ERR_IS_FATAL(msg->conn->last_err)) {
+ msg->err = msg->conn->last_err;
+ } else {
+ msg->err = ERR_VAL;
if (msg->conn->pcb.tcp != NULL) {
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
case NETCONN_RAW:
- msg->conn->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
+ msg->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
break;
#endif /* LWIP_RAW */
#if LWIP_UDP
case NETCONN_UDP:
- msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
+ msg->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
- msg->conn->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port);
+ msg->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port);
break;
#endif /* LWIP_TCP */
default:
break;
}
- } else {
- /* msg->conn->pcb is NULL */
- msg->conn->err = ERR_VAL;
}
}
TCPIP_APIMSG_ACK(msg);
@@ -758,21 +925,38 @@ static err_t
do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct netconn *conn;
+ int was_blocking;
LWIP_UNUSED_ARG(pcb);
- conn = arg;
+ conn = (struct netconn *)arg;
if (conn == NULL) {
return ERR_VAL;
}
- conn->err = err;
+ LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT);
+ LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect",
+ (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn));
+
+ if (conn->current_msg != NULL) {
+ conn->current_msg->err = err;
+ }
if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) {
setup_tcp(conn);
}
+ was_blocking = !IN_NONBLOCKING_CONNECT(conn);
+ SET_NONBLOCKING_CONNECT(conn, 0);
+ conn->current_msg = NULL;
conn->state = NETCONN_NONE;
- sys_sem_signal(conn->op_completed);
+ if (!was_blocking) {
+ NETCONN_SET_SAFE_ERR(conn, ERR_OK);
+ }
+ API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
+
+ if (was_blocking) {
+ sys_sem_signal(&conn->op_completed);
+ }
return ERR_OK;
}
#endif /* LWIP_TCP */
@@ -788,38 +972,51 @@ void
do_connect(struct api_msg_msg *msg)
{
if (msg->conn->pcb.tcp == NULL) {
- sys_sem_signal(msg->conn->op_completed);
- return;
- }
-
- switch (NETCONNTYPE_GROUP(msg->conn->type)) {
+ /* This may happen when calling netconn_connect() a second time */
+ msg->err = ERR_CLSD;
+ } else {
+ switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
case NETCONN_RAW:
- msg->conn->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
- sys_sem_signal(msg->conn->op_completed);
+ msg->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
break;
#endif /* LWIP_RAW */
#if LWIP_UDP
case NETCONN_UDP:
- msg->conn->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
- sys_sem_signal(msg->conn->op_completed);
+ msg->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
- msg->conn->state = NETCONN_CONNECT;
- setup_tcp(msg->conn);
- msg->conn->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,
- do_connected);
- /* sys_sem_signal() is called from do_connected (or err_tcp()),
- * when the connection is established! */
+ /* Prevent connect while doing any other action. */
+ if (msg->conn->state != NETCONN_NONE) {
+ msg->err = ERR_ISCONN;
+ } else {
+ setup_tcp(msg->conn);
+ msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr,
+ msg->msg.bc.port, do_connected);
+ if (msg->err == ERR_OK) {
+ u8_t non_blocking = netconn_is_nonblocking(msg->conn);
+ msg->conn->state = NETCONN_CONNECT;
+ SET_NONBLOCKING_CONNECT(msg->conn, non_blocking);
+ if (non_blocking) {
+ msg->err = ERR_INPROGRESS;
+ } else {
+ msg->conn->current_msg = msg;
+ /* sys_sem_signal() is called from do_connected (or err_tcp()),
+ * when the connection is established! */
+ return;
+ }
+ }
+ }
break;
#endif /* LWIP_TCP */
default:
- LWIP_ERROR("Invalid netconn type", 0, do{ msg->conn->err = ERR_VAL;
- sys_sem_signal(msg->conn->op_completed); }while(0));
+ LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0));
break;
+ }
}
+ sys_sem_signal(&msg->conn->op_completed);
}
/**
@@ -835,11 +1032,16 @@ do_disconnect(struct api_msg_msg *msg)
#if LWIP_UDP
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
udp_disconnect(msg->conn->pcb.udp);
- }
+ msg->err = ERR_OK;
+ } else
#endif /* LWIP_UDP */
+ {
+ msg->err = ERR_VAL;
+ }
TCPIP_APIMSG_ACK(msg);
}
+#if LWIP_TCP
/**
* Set a TCP pcb contained in a netconn into listen mode
* Called from netconn_listen.
@@ -849,46 +1051,50 @@ do_disconnect(struct api_msg_msg *msg)
void
do_listen(struct api_msg_msg *msg)
{
-#if LWIP_TCP
- if (!ERR_IS_FATAL(msg->conn->err)) {
+ if (ERR_IS_FATAL(msg->conn->last_err)) {
+ msg->err = msg->conn->last_err;
+ } else {
+ msg->err = ERR_CONN;
if (msg->conn->pcb.tcp != NULL) {
if (msg->conn->type == NETCONN_TCP) {
- if (msg->conn->pcb.tcp->state == CLOSED) {
+ if (msg->conn->state == NETCONN_NONE) {
#if TCP_LISTEN_BACKLOG
struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
#else /* TCP_LISTEN_BACKLOG */
struct tcp_pcb* lpcb = tcp_listen(msg->conn->pcb.tcp);
#endif /* TCP_LISTEN_BACKLOG */
if (lpcb == NULL) {
- msg->conn->err = ERR_MEM;
+ /* in this case, the old pcb is still allocated */
+ msg->err = ERR_MEM;
} else {
/* delete the recvmbox and allocate the acceptmbox */
- if (msg->conn->recvmbox != SYS_MBOX_NULL) {
+ if (sys_mbox_valid(&msg->conn->recvmbox)) {
/** @todo: should we drain the recvmbox here? */
- sys_mbox_free(msg->conn->recvmbox);
- msg->conn->recvmbox = SYS_MBOX_NULL;
+ sys_mbox_free(&msg->conn->recvmbox);
+ sys_mbox_set_invalid(&msg->conn->recvmbox);
}
- if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
- if ((msg->conn->acceptmbox = sys_mbox_new(DEFAULT_ACCEPTMBOX_SIZE)) == SYS_MBOX_NULL) {
- msg->conn->err = ERR_MEM;
- }
+ msg->err = ERR_OK;
+ if (!sys_mbox_valid(&msg->conn->acceptmbox)) {
+ msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE);
}
- if (msg->conn->err == ERR_OK) {
+ if (msg->err == ERR_OK) {
msg->conn->state = NETCONN_LISTEN;
msg->conn->pcb.tcp = lpcb;
tcp_arg(msg->conn->pcb.tcp, msg->conn);
tcp_accept(msg->conn->pcb.tcp, accept_function);
+ } else {
+ /* since the old pcb is already deallocated, free lpcb now */
+ tcp_close(lpcb);
+ msg->conn->pcb.tcp = NULL;
}
}
- } else {
- msg->conn->err = ERR_CONN;
}
}
}
}
-#endif /* LWIP_TCP */
TCPIP_APIMSG_ACK(msg);
}
+#endif /* LWIP_TCP */
/**
* Send some data on a RAW or UDP pcb contained in a netconn
@@ -899,25 +1105,39 @@ do_listen(struct api_msg_msg *msg)
void
do_send(struct api_msg_msg *msg)
{
- if (!ERR_IS_FATAL(msg->conn->err)) {
+ if (ERR_IS_FATAL(msg->conn->last_err)) {
+ msg->err = msg->conn->last_err;
+ } else {
+ msg->err = ERR_CONN;
if (msg->conn->pcb.tcp != NULL) {
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
case NETCONN_RAW:
- if (msg->msg.b->addr == NULL) {
- msg->conn->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
+ if (ip_addr_isany(&msg->msg.b->addr)) {
+ msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
} else {
- msg->conn->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, msg->msg.b->addr);
+ msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr);
}
break;
#endif
#if LWIP_UDP
case NETCONN_UDP:
- if (msg->msg.b->addr == NULL) {
- msg->conn->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
+#if LWIP_CHECKSUM_ON_COPY
+ if (ip_addr_isany(&msg->msg.b->addr)) {
+ msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p,
+ msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
} else {
- msg->conn->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, msg->msg.b->addr, msg->msg.b->port);
+ msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p,
+ &msg->msg.b->addr, msg->msg.b->port,
+ msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
}
+#else /* LWIP_CHECKSUM_ON_COPY */
+ if (ip_addr_isany(&msg->msg.b->addr)) {
+ msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
+ } else {
+ msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port);
+ }
+#endif /* LWIP_CHECKSUM_ON_COPY */
break;
#endif /* LWIP_UDP */
default:
@@ -928,6 +1148,7 @@ do_send(struct api_msg_msg *msg)
TCPIP_APIMSG_ACK(msg);
}
+#if LWIP_TCP
/**
* Indicate data has been received from a TCP pcb contained in a netconn
* Called from netconn_recv
@@ -937,26 +1158,27 @@ do_send(struct api_msg_msg *msg)
void
do_recv(struct api_msg_msg *msg)
{
-#if LWIP_TCP
- if (!ERR_IS_FATAL(msg->conn->err)) {
- if (msg->conn->pcb.tcp != NULL) {
- if (msg->conn->type == NETCONN_TCP) {
+ msg->err = ERR_OK;
+ if (msg->conn->pcb.tcp != NULL) {
+ if (msg->conn->type == NETCONN_TCP) {
#if TCP_LISTEN_BACKLOG
- if (msg->conn->pcb.tcp->state == LISTEN) {
- tcp_accepted(msg->conn->pcb.tcp);
- } else
+ if (msg->conn->pcb.tcp->state == LISTEN) {
+ tcp_accepted(msg->conn->pcb.tcp);
+ } else
#endif /* TCP_LISTEN_BACKLOG */
- {
- tcp_recved(msg->conn->pcb.tcp, msg->msg.r.len);
- }
+ {
+ u32_t remaining = msg->msg.r.len;
+ do {
+ u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining;
+ tcp_recved(msg->conn->pcb.tcp, recved);
+ remaining -= recved;
+ }while(remaining != 0);
}
}
}
-#endif /* LWIP_TCP */
TCPIP_APIMSG_ACK(msg);
}
-#if LWIP_TCP
/**
* See if more data needs to be written from a previous call to netconn_write.
* Called initially from do_write. If the first call can't send all data
@@ -971,21 +1193,30 @@ do_recv(struct api_msg_msg *msg)
static err_t
do_writemore(struct netconn *conn)
{
- err_t err;
+ err_t err = ERR_OK;
void *dataptr;
u16_t len, available;
u8_t write_finished = 0;
size_t diff;
+ u8_t dontblock = netconn_is_nonblocking(conn) ||
+ (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK);
+ u8_t apiflags = conn->current_msg->msg.w.apiflags;
+ LWIP_ASSERT("conn != NULL", conn != NULL);
LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE));
+ LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
+ LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL);
+ LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len",
+ conn->write_offset < conn->current_msg->msg.w.len);
- dataptr = (u8_t*)conn->write_msg->msg.w.dataptr + conn->write_offset;
- diff = conn->write_msg->msg.w.len - conn->write_offset;
+ dataptr = (u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset;
+ diff = conn->current_msg->msg.w.len - conn->write_offset;
if (diff > 0xffffUL) { /* max_u16_t */
len = 0xffff;
#if LWIP_TCPIP_CORE_LOCKING
- conn->write_delayed = 1;
+ conn->flags |= NETCONN_FLAG_WRITE_DELAYED;
#endif
+ apiflags |= TCP_WRITE_FLAG_MORE;
} else {
len = (u16_t)diff;
}
@@ -994,54 +1225,74 @@ do_writemore(struct netconn *conn)
/* don't try to write more than sendbuf */
len = available;
#if LWIP_TCPIP_CORE_LOCKING
- conn->write_delayed = 1;
+ conn->flags |= NETCONN_FLAG_WRITE_DELAYED;
#endif
+ apiflags |= TCP_WRITE_FLAG_MORE;
+ }
+ if (dontblock && (len < conn->current_msg->msg.w.len)) {
+ /* failed to send all data at once -> nonblocking write not possible */
+ err = ERR_MEM;
}
-
- err = tcp_write(conn->pcb.tcp, dataptr, len, conn->write_msg->msg.w.apiflags);
- LWIP_ASSERT("do_writemore: invalid length!", ((conn->write_offset + len) <= conn->write_msg->msg.w.len));
if (err == ERR_OK) {
- conn->write_offset += len;
- if (conn->write_offset == conn->write_msg->msg.w.len) {
- /* everything was written */
- 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;
- if ((err == ERR_OK) && (tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT)) {
+ LWIP_ASSERT("do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len));
+ err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags);
+ }
+ if (dontblock && (err == ERR_MEM)) {
+ /* nonblocking write failed */
+ write_finished = 1;
+ err = ERR_WOULDBLOCK;
+ /* let poll_tcp check writable space to mark the pcb
+ writable again */
+ conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE;
+ /* let select mark this pcb as non-writable. */
+ API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
+ } else {
+ /* if OK or memory error, check available space */
+ if (((err == ERR_OK) || (err == ERR_MEM)) &&
+ ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) ||
+ (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT))) {
+ /* The queued byte- or pbuf-count exceeds the configured low-water limit,
+ let select mark this pcb as non-writable. */
API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
}
- } else if (err == ERR_MEM) {
- /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
- we do NOT return to the application thread, since ERR_MEM is
- only a temporary error! */
- /* tcp_enqueue returned ERR_MEM, try tcp_output anyway */
- err = tcp_output(conn->pcb.tcp);
-
-#if LWIP_TCPIP_CORE_LOCKING
- conn->write_delayed = 1;
-#endif
- } else {
- /* On errors != ERR_MEM, we don't try writing any more but return
- the error to the application thread. */
- conn->err = err;
- write_finished = 1;
+ if (err == ERR_OK) {
+ conn->write_offset += len;
+ if (conn->write_offset == conn->current_msg->msg.w.len) {
+ /* everything was written */
+ write_finished = 1;
+ conn->write_offset = 0;
+ }
+ tcp_output(conn->pcb.tcp);
+ } else if (err == ERR_MEM) {
+ /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
+ we do NOT return to the application thread, since ERR_MEM is
+ only a temporary error! */
+
+ /* tcp_write returned ERR_MEM, try tcp_output anyway */
+ tcp_output(conn->pcb.tcp);
+
+ #if LWIP_TCPIP_CORE_LOCKING
+ conn->flags |= NETCONN_FLAG_WRITE_DELAYED;
+ #endif
+ } else {
+ /* On errors != ERR_MEM, we don't try writing any more but return
+ the error to the application thread. */
+ write_finished = 1;
+ }
}
if (write_finished) {
/* everything was written: set back connection state
and back to application task */
+ conn->current_msg->err = err;
+ conn->current_msg = NULL;
conn->state = NETCONN_NONE;
#if LWIP_TCPIP_CORE_LOCKING
- if (conn->write_delayed != 0)
+ if ((conn->flags & NETCONN_FLAG_WRITE_DELAYED) != 0)
#endif
{
- sys_sem_signal(conn->op_completed);
+ sys_sem_signal(&conn->op_completed);
}
}
#if LWIP_TCPIP_CORE_LOCKING
@@ -1061,33 +1312,46 @@ do_writemore(struct netconn *conn)
void
do_write(struct api_msg_msg *msg)
{
- if (!ERR_IS_FATAL(msg->conn->err)) {
- if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
+ if (ERR_IS_FATAL(msg->conn->last_err)) {
+ msg->err = msg->conn->last_err;
+ } else {
+ if (msg->conn->type == NETCONN_TCP) {
#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 (msg->conn->state != NETCONN_NONE) {
+ /* netconn is connecting, closing or in blocking write */
+ msg->err = ERR_INPROGRESS;
+ } else if (msg->conn->pcb.tcp != NULL) {
+ msg->conn->state = NETCONN_WRITE;
+ /* set all the variables used by do_writemore */
+ LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
+ msg->conn->write_offset == 0);
+ LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0);
+ msg->conn->current_msg = msg;
+ msg->conn->write_offset = 0;
#if LWIP_TCPIP_CORE_LOCKING
- msg->conn->write_delayed = 0;
- if (do_writemore(msg->conn) != ERR_OK) {
- LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE);
- UNLOCK_TCPIP_CORE();
- sys_arch_sem_wait(msg->conn->op_completed, 0);
- LOCK_TCPIP_CORE();
- LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
+ msg->conn->flags &= ~NETCONN_FLAG_WRITE_DELAYED;
+ if (do_writemore(msg->conn) != ERR_OK) {
+ LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE);
+ UNLOCK_TCPIP_CORE();
+ sys_arch_sem_wait(&msg->conn->op_completed, 0);
+ LOCK_TCPIP_CORE();
+ LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
+ }
+#else /* LWIP_TCPIP_CORE_LOCKING */
+ do_writemore(msg->conn);
+#endif /* LWIP_TCPIP_CORE_LOCKING */
+ /* for both cases: if do_writemore was called, don't ACK the APIMSG
+ since do_writemore ACKs it! */
+ return;
+ } else {
+ msg->err = ERR_CONN;
}
-#else
- do_writemore(msg->conn);
-#endif
- /* for both cases: if do_writemore was called, don't ACK the APIMSG! */
- return;
+#else /* LWIP_TCP */
+ msg->err = ERR_VAL;
#endif /* LWIP_TCP */
#if (LWIP_UDP || LWIP_RAW)
} else {
- msg->conn->err = ERR_VAL;
+ msg->err = ERR_VAL;
#endif /* (LWIP_UDP || LWIP_RAW) */
}
}
@@ -1104,8 +1368,10 @@ void
do_getaddr(struct api_msg_msg *msg)
{
if (msg->conn->pcb.ip != NULL) {
- *(msg->msg.ad.ipaddr) = (msg->msg.ad.local?msg->conn->pcb.ip->local_ip:msg->conn->pcb.ip->remote_ip);
-
+ *(msg->msg.ad.ipaddr) = (msg->msg.ad.local ? msg->conn->pcb.ip->local_ip :
+ msg->conn->pcb.ip->remote_ip);
+
+ msg->err = ERR_OK;
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
case NETCONN_RAW:
@@ -1113,7 +1379,7 @@ do_getaddr(struct api_msg_msg *msg)
*(msg->msg.ad.port) = msg->conn->pcb.raw->protocol;
} else {
/* return an error as connecting is only a helper for upper layers */
- msg->conn->err = ERR_CONN;
+ msg->err = ERR_CONN;
}
break;
#endif /* LWIP_RAW */
@@ -1123,7 +1389,7 @@ do_getaddr(struct api_msg_msg *msg)
*(msg->msg.ad.port) = msg->conn->pcb.udp->local_port;
} else {
if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) {
- msg->conn->err = ERR_CONN;
+ msg->err = ERR_CONN;
} else {
*(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port;
}
@@ -1135,9 +1401,12 @@ do_getaddr(struct api_msg_msg *msg)
*(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port);
break;
#endif /* LWIP_TCP */
+ default:
+ LWIP_ASSERT("invalid netconn_type", 0);
+ break;
}
} else {
- msg->conn->err = ERR_CONN;
+ msg->err = ERR_CONN;
}
TCPIP_APIMSG_ACK(msg);
}
@@ -1152,16 +1421,34 @@ void
do_close(struct api_msg_msg *msg)
{
#if LWIP_TCP
- if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
+ /* @todo: abort running write/connect? */
+ if ((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN)) {
+ /* this only happens for TCP netconns */
+ LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP);
+ msg->err = ERR_INPROGRESS;
+ } else if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
+ if ((msg->msg.sd.shut != NETCONN_SHUT_RDWR) && (msg->conn->state == NETCONN_LISTEN)) {
+ /* LISTEN doesn't support half shutdown */
+ msg->err = ERR_CONN;
+ } else {
+ if (msg->msg.sd.shut & NETCONN_SHUT_RD) {
+ /* Drain and delete mboxes */
+ netconn_drain(msg->conn);
+ }
+ LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
+ msg->conn->write_offset == 0);
msg->conn->state = NETCONN_CLOSE;
+ msg->conn->current_msg = msg;
do_close_internal(msg->conn);
/* for tcp netconns, do_close_internal ACKs the message */
+ return;
+ }
} else
#endif /* LWIP_TCP */
{
- msg->conn->err = ERR_VAL;
- sys_sem_signal(msg->conn->op_completed);
+ msg->err = ERR_VAL;
}
+ sys_sem_signal(&msg->conn->op_completed);
}
#if LWIP_IGMP
@@ -1174,21 +1461,25 @@ do_close(struct api_msg_msg *msg)
void
do_join_leave_group(struct api_msg_msg *msg)
{
- if (!ERR_IS_FATAL(msg->conn->err)) {
+ if (ERR_IS_FATAL(msg->conn->last_err)) {
+ msg->err = msg->conn->last_err;
+ } else {
if (msg->conn->pcb.tcp != NULL) {
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
#if LWIP_UDP
if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
- msg->conn->err = igmp_joingroup(msg->msg.jl.interface, msg->msg.jl.multiaddr);
+ msg->err = igmp_joingroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
} else {
- msg->conn->err = igmp_leavegroup(msg->msg.jl.interface, msg->msg.jl.multiaddr);
+ msg->err = igmp_leavegroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
}
#endif /* LWIP_UDP */
#if (LWIP_TCP || LWIP_RAW)
} else {
- msg->conn->err = ERR_VAL;
+ msg->err = ERR_VAL;
#endif /* (LWIP_TCP || LWIP_RAW) */
}
+ } else {
+ msg->err = ERR_CONN;
}
}
TCPIP_APIMSG_ACK(msg);
@@ -1202,11 +1493,12 @@ do_join_leave_group(struct api_msg_msg *msg)
* signaling the semaphore.
*/
static void
-do_dns_found(const char *name, struct ip_addr *ipaddr, void *arg)
+do_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
{
struct dns_api_msg *msg = (struct dns_api_msg*)arg;
LWIP_ASSERT("DNS response for wrong host name", strcmp(msg->name, name) == 0);
+ LWIP_UNUSED_ARG(name);
if (ipaddr == NULL) {
/* timeout or memory error */
diff --git a/core/lwip/src/api/err.c b/core/lwip/src/api/err.c
index a90cb98c..92fa8b7d 100644
--- a/core/lwip/src/api/err.c
+++ b/core/lwip/src/api/err.c
@@ -44,18 +44,19 @@ static const char *err_strerr[] = {
"Ok.", /* ERR_OK 0 */
"Out of memory error.", /* ERR_MEM -1 */
"Buffer error.", /* ERR_BUF -2 */
- "Timeout.", /* ERR_TIMEOUT -3 */
+ "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 */
+ "Operation in progress.", /* ERR_INPROGRESS -5 */
+ "Illegal value.", /* ERR_VAL -6 */
+ "Operation would block.", /* ERR_WOULDBLOCK -7 */
+ "Address in use.", /* ERR_USE -8 */
+ "Already connected.", /* ERR_ISCONN -9 */
+ "Connection aborted.", /* ERR_ABRT -10 */
+ "Connection reset.", /* ERR_RST -11 */
+ "Connection closed.", /* ERR_CLSD -12 */
+ "Not connected.", /* ERR_CONN -13 */
+ "Illegal argument.", /* ERR_ARG -14 */
+ "Low-level netif error.", /* ERR_IF -15 */
};
/**
diff --git a/core/lwip/src/api/netbuf.c b/core/lwip/src/api/netbuf.c
index 57efc4f9..9390c9ee 100644
--- a/core/lwip/src/api/netbuf.c
+++ b/core/lwip/src/api/netbuf.c
@@ -57,16 +57,21 @@ netbuf *netbuf_new(void)
{
struct netbuf *buf;
- buf = memp_malloc(MEMP_NETBUF);
+ buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
if (buf != NULL) {
buf->p = NULL;
buf->ptr = NULL;
- buf->addr = NULL;
+ ip_addr_set_any(&buf->addr);
buf->port = 0;
+#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
+#if LWIP_CHECKSUM_ON_COPY
+ buf->flags = 0;
+#endif /* LWIP_CHECKSUM_ON_COPY */
+ buf->toport_chksum = 0;
#if LWIP_NETBUF_RECVINFO
- buf->toaddr = NULL;
- buf->toport = 0;
+ ip_addr_set_any(&buf->toaddr);
#endif /* LWIP_NETBUF_RECVINFO */
+#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
return buf;
} else {
return NULL;
diff --git a/core/lwip/src/api/netdb.c b/core/lwip/src/api/netdb.c
index 69a331be..a7e4e06b 100644
--- a/core/lwip/src/api/netdb.c
+++ b/core/lwip/src/api/netdb.c
@@ -39,16 +39,18 @@
#include "lwip/err.h"
#include "lwip/mem.h"
+#include "lwip/memp.h"
#include "lwip/ip_addr.h"
#include "lwip/api.h"
+#include "lwip/dns.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;
- struct ip_addr addr;
+ ip_addr_t *addrs;
+ ip_addr_t addr;
char *aliases;
};
@@ -83,13 +85,13 @@ struct hostent*
lwip_gethostbyname(const char *name)
{
err_t err;
- struct ip_addr addr;
+ ip_addr_t addr;
/* buffer variables for lwip_gethostbyname() */
HOSTENT_STORAGE struct hostent s_hostent;
HOSTENT_STORAGE char *s_aliases;
- HOSTENT_STORAGE struct ip_addr s_hostent_addr;
- HOSTENT_STORAGE struct ip_addr *s_phostent_addr;
+ HOSTENT_STORAGE ip_addr_t s_hostent_addr;
+ HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2];
/* query host IP address */
err = netconn_gethostbyname(name, &addr);
@@ -101,11 +103,12 @@ lwip_gethostbyname(const char *name)
/* fill hostent */
s_hostent_addr = addr;
- s_phostent_addr = &s_hostent_addr;
+ s_phostent_addr[0] = &s_hostent_addr;
+ s_phostent_addr[1] = NULL;
s_hostent.h_name = (char*)name;
s_hostent.h_aliases = &s_aliases;
s_hostent.h_addrtype = AF_INET;
- s_hostent.h_length = sizeof(struct ip_addr);
+ s_hostent.h_length = sizeof(ip_addr_t);
s_hostent.h_addr_list = (char**)&s_phostent_addr;
#if DNS_DEBUG
@@ -126,7 +129,7 @@ lwip_gethostbyname(const char *name)
u8_t idx;
for ( idx=0; s_hostent.h_addr_list[idx]; 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, ip_ntoa(s_hostent.h_addr_list[idx])));
+ LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ip_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx])));
}
}
#endif /* DNS_DEBUG */
@@ -211,7 +214,7 @@ lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
ret->h_name = (char*)hostname;
ret->h_aliases = &(h->aliases);
ret->h_addrtype = AF_INET;
- ret->h_length = sizeof(struct ip_addr);
+ ret->h_length = sizeof(ip_addr_t);
ret->h_addr_list = (char**)&(h->addrs);
/* set result != NULL */
@@ -235,7 +238,7 @@ lwip_freeaddrinfo(struct addrinfo *ai)
while (ai != NULL) {
next = ai->ai_next;
- mem_free(ai);
+ memp_free(MEMP_NETDB, ai);
ai = next;
}
}
@@ -264,7 +267,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
const struct addrinfo *hints, struct addrinfo **res)
{
err_t err;
- struct ip_addr addr;
+ ip_addr_t addr;
struct addrinfo *ai;
struct sockaddr_in *sa = NULL;
int port_nr = 0;
@@ -296,7 +299,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
}
} else {
/* service location specified, use loopback address */
- addr.addr = htonl(INADDR_LOOPBACK);
+ ip_addr_set_loopback(&addr);
}
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_in);
@@ -305,17 +308,20 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
total_size += namelen + 1;
}
- ai = mem_malloc(total_size);
+ /* If this fails, please report to lwip-devel! :-) */
+ LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!",
+ total_size <= NETDB_ELEM_SIZE);
+ ai = (struct addrinfo *)memp_malloc(MEMP_NETDB);
if (ai == NULL) {
goto memerr;
}
memset(ai, 0, total_size);
sa = (struct sockaddr_in*)((u8_t*)ai + sizeof(struct addrinfo));
/* set up sockaddr */
- sa->sin_addr.s_addr = addr.addr;
+ inet_addr_from_ipaddr(&sa->sin_addr, &addr);
sa->sin_family = AF_INET;
sa->sin_len = sizeof(struct sockaddr_in);
- sa->sin_port = htons(port_nr);
+ sa->sin_port = htons((u16_t)port_nr);
/* set up addrinfo */
ai->ai_family = AF_INET;
@@ -338,7 +344,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
return 0;
memerr:
if (ai != NULL) {
- mem_free(ai);
+ memp_free(MEMP_NETDB, ai);
}
return EAI_MEMORY;
}
diff --git a/core/lwip/src/api/netifapi.c b/core/lwip/src/api/netifapi.c
index 57089864..43e47203 100644
--- a/core/lwip/src/api/netifapi.c
+++ b/core/lwip/src/api/netifapi.c
@@ -42,7 +42,7 @@
* Call netif_add() inside the tcpip_thread context.
*/
void
-do_netifapi_netif_add( struct netifapi_msg_msg *msg)
+do_netifapi_netif_add(struct netifapi_msg_msg *msg)
{
if (!netif_add( msg->netif,
msg->msg.add.ipaddr,
@@ -62,7 +62,7 @@ do_netifapi_netif_add( struct netifapi_msg_msg *msg)
* Call netif_set_addr() inside the tcpip_thread context.
*/
void
-do_netifapi_netif_set_addr( struct netifapi_msg_msg *msg)
+do_netifapi_netif_set_addr(struct netifapi_msg_msg *msg)
{
netif_set_addr( msg->netif,
msg->msg.add.ipaddr,
@@ -77,11 +77,10 @@ do_netifapi_netif_set_addr( struct netifapi_msg_msg *msg)
* tcpip_thread context.
*/
void
-do_netifapi_netif_common( struct netifapi_msg_msg *msg)
+do_netifapi_netif_common(struct netifapi_msg_msg *msg)
{
- if (msg->msg.common.errtfunc!=NULL) {
- msg->err =
- msg->msg.common.errtfunc(msg->netif);
+ if (msg->msg.common.errtfunc != NULL) {
+ msg->err = msg->msg.common.errtfunc(msg->netif);
} else {
msg->err = ERR_OK;
msg->msg.common.voidfunc(msg->netif);
@@ -97,12 +96,12 @@ do_netifapi_netif_common( struct netifapi_msg_msg *msg)
*/
err_t
netifapi_netif_add(struct netif *netif,
- struct ip_addr *ipaddr,
- struct ip_addr *netmask,
- struct ip_addr *gw,
+ ip_addr_t *ipaddr,
+ ip_addr_t *netmask,
+ ip_addr_t *gw,
void *state,
- err_t (* init)(struct netif *netif),
- err_t (* input)(struct pbuf *p, struct netif *netif))
+ netif_init_fn init,
+ netif_input_fn input)
{
struct netifapi_msg msg;
msg.function = do_netifapi_netif_add;
@@ -125,9 +124,9 @@ netifapi_netif_add(struct netif *netif,
*/
err_t
netifapi_netif_set_addr(struct netif *netif,
- struct ip_addr *ipaddr,
- struct ip_addr *netmask,
- struct ip_addr *gw)
+ ip_addr_t *ipaddr,
+ ip_addr_t *netmask,
+ ip_addr_t *gw)
{
struct netifapi_msg msg;
msg.function = do_netifapi_netif_set_addr;
@@ -146,9 +145,8 @@ netifapi_netif_set_addr(struct netif *netif,
* @note use only for functions where there is only "netif" parameter.
*/
err_t
-netifapi_netif_common( struct netif *netif,
- void (* voidfunc)(struct netif *netif),
- err_t (* errtfunc)(struct netif *netif) )
+netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
+ netifapi_errt_fn errtfunc)
{
struct netifapi_msg msg;
msg.function = do_netifapi_netif_common;
diff --git a/core/lwip/src/api/sockets.c b/core/lwip/src/api/sockets.c
index 340c6dcf..e36012ce 100644
--- a/core/lwip/src/api/sockets.c
+++ b/core/lwip/src/api/sockets.c
@@ -51,35 +51,43 @@
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/tcpip.h"
+#include "lwip/pbuf.h"
+#if LWIP_CHECKSUM_ON_COPY
+#include "lwip/inet_chksum.h"
+#endif
#include <string.h>
#define NUM_SOCKETS MEMP_NUM_NETCONN
/** Contains all internal pointers and states used for a socket */
-struct lwip_socket {
+struct lwip_sock {
/** sockets currently are built on netconns, each socket has one netconn */
struct netconn *conn;
/** data that was left from the previous read */
- struct netbuf *lastdata;
+ void *lastdata;
/** offset in the data that was left from the previous read */
u16_t lastoffset;
/** number of times data was received, set by event_callback(),
tested by the receive and select functions */
s16_t rcvevent;
- /** number of times data was received, set by event_callback(),
+ /** number of times data was ACKed (free send buffer), set by event_callback(),
tested by select */
u16_t sendevent;
- /** socket flags (currently, only used for O_NONBLOCK) */
- u16_t flags;
+ /** error happened for this socket, set by event_callback(), tested by select */
+ u16_t errevent;
/** last error that occurred on this socket */
int err;
+ /** counter of how many threads are waiting for this socket using select */
+ int select_waiting;
};
/** Description for a task waiting in select */
struct lwip_select_cb {
/** Pointer to the next waiting task */
struct lwip_select_cb *next;
+ /** Pointer to the previous waiting task */
+ struct lwip_select_cb *prev;
/** readset passed to select */
fd_set *readset;
/** writeset passed to select */
@@ -96,9 +104,11 @@ struct lwip_select_cb {
* functions running in tcpip_thread context (only a void* is allowed) */
struct lwip_setgetsockopt_data {
/** socket struct for which to change options */
- struct lwip_socket *sock;
+ struct lwip_sock *sock;
+#ifdef LWIP_DEBUG
/** socket index for which to change options */
int s;
+#endif /* LWIP_DEBUG */
/** level of the option to process */
int level;
/** name of the option to process */
@@ -113,14 +123,12 @@ struct lwip_setgetsockopt_data {
};
/** The global array of available sockets */
-static struct lwip_socket sockets[NUM_SOCKETS];
+static struct lwip_sock sockets[NUM_SOCKETS];
/** The global list of tasks waiting for select */
static struct lwip_select_cb *select_cb_list;
-
-/** Semaphore protecting the sockets array */
-static sys_sem_t socksem;
-/** Semaphore protecting select_cb_list */
-static sys_sem_t selectsem;
+/** This counter is increased from lwip_select when the list is chagned
+ and checked in event_callback to see if it has changed. */
+static volatile int select_cb_ctr;
/** Table to quickly map an lwIP error (err_t) to a socket error
* by using -err as an index */
@@ -128,18 +136,19 @@ static const int err_to_errno_table[] = {
0, /* ERR_OK 0 No error, everything OK. */
ENOMEM, /* ERR_MEM -1 Out of memory error. */
ENOBUFS, /* ERR_BUF -2 Buffer error. */
- ETIMEDOUT, /* ERR_TIMEOUT -3 Timeout */
+ EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
- ECONNABORTED, /* ERR_ABRT -5 Connection aborted. */
- ECONNRESET, /* ERR_RST -6 Connection reset. */
- ESHUTDOWN, /* ERR_CLSD -7 Connection closed. */
- ENOTCONN, /* ERR_CONN -8 Not connected. */
- EINVAL, /* ERR_VAL -9 Illegal value. */
- EIO, /* ERR_ARG -10 Illegal argument. */
- EADDRINUSE, /* ERR_USE -11 Address in use. */
- -1, /* ERR_IF -12 Low-level netif error */
- -1, /* ERR_ISCONN -13 Already connected. */
- EINPROGRESS /* ERR_INPROGRESS -14 Operation in progress */
+ EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
+ EINVAL, /* ERR_VAL -6 Illegal value. */
+ EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
+ EADDRINUSE, /* ERR_USE -8 Address in use. */
+ EALREADY, /* ERR_ISCONN -9 Already connected. */
+ ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
+ ECONNRESET, /* ERR_RST -11 Connection reset. */
+ ENOTCONN, /* ERR_CLSD -12 Connection closed. */
+ ENOTCONN, /* ERR_CONN -13 Not connected. */
+ EIO, /* ERR_ARG -14 Illegal argument. */
+ -1, /* ERR_IF -15 Low-level netif error */
};
#define ERR_TO_ERRNO_TABLE_SIZE \
@@ -153,9 +162,9 @@ static const int err_to_errno_table[] = {
#ifndef set_errno
#define set_errno(err) errno = (err)
#endif
-#else
+#else /* ERRNO */
#define set_errno(err)
-#endif
+#endif /* ERRNO */
#define sock_set_errno(sk, e) do { \
sk->err = (e); \
@@ -174,20 +183,18 @@ static void lwip_setsockopt_internal(void *arg);
void
lwip_socket_init(void)
{
- socksem = sys_sem_new(1);
- selectsem = sys_sem_new(1);
}
/**
* Map a externally used socket index to the internal socket representation.
*
* @param s externally used socket index
- * @return struct lwip_socket for the socket or NULL if not found
+ * @return struct lwip_sock for the socket or NULL if not found
*/
-static struct lwip_socket *
+static struct lwip_sock *
get_socket(int s)
{
- struct lwip_socket *sock;
+ struct lwip_sock *sock;
if ((s < 0) || (s >= NUM_SOCKETS)) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
@@ -207,37 +214,94 @@ get_socket(int s)
}
/**
+ * Same as get_socket but doesn't set errno
+ *
+ * @param s externally used socket index
+ * @return struct lwip_sock for the socket or NULL if not found
+ */
+static struct lwip_sock *
+tryget_socket(int s)
+{
+ if ((s < 0) || (s >= NUM_SOCKETS)) {
+ return NULL;
+ }
+ if (!sockets[s].conn) {
+ return NULL;
+ }
+ return &sockets[s];
+}
+
+/**
* Allocate a new socket for a given netconn.
*
* @param newconn the netconn for which to allocate a socket
+ * @param accepted 1 if socket has been created by accept(),
+ * 0 if socket has been created by socket()
* @return the index of the new socket; -1 on error
*/
static int
-alloc_socket(struct netconn *newconn)
+alloc_socket(struct netconn *newconn, int accepted)
{
int i;
-
- /* Protect socket array */
- sys_sem_wait(socksem);
+ SYS_ARCH_DECL_PROTECT(lev);
/* allocate a new socket identifier */
for (i = 0; i < NUM_SOCKETS; ++i) {
+ /* Protect socket array */
+ SYS_ARCH_PROTECT(lev);
if (!sockets[i].conn) {
sockets[i].conn = newconn;
+ /* The socket is not yet known to anyone, so no need to protect
+ after having marked it as used. */
+ SYS_ARCH_UNPROTECT(lev);
sockets[i].lastdata = NULL;
sockets[i].lastoffset = 0;
sockets[i].rcvevent = 0;
- sockets[i].sendevent = 1; /* TCP send buf is empty */
- sockets[i].flags = 0;
+ /* TCP sendbuf is empty, but the socket is not yet writable until connected
+ * (unless it has been created by accept()). */
+ sockets[i].sendevent = (newconn->type == NETCONN_TCP ? (accepted != 0) : 1);
+ sockets[i].errevent = 0;
sockets[i].err = 0;
- sys_sem_signal(socksem);
+ sockets[i].select_waiting = 0;
return i;
}
+ SYS_ARCH_UNPROTECT(lev);
}
- sys_sem_signal(socksem);
return -1;
}
+/** Free a socket. The socket's netconn must have been
+ * delete before!
+ *
+ * @param sock the socket to free
+ * @param is_tcp != 0 for TCP sockets, used to free lastdata
+ */
+static void
+free_socket(struct lwip_sock *sock, int is_tcp)
+{
+ void *lastdata;
+ SYS_ARCH_DECL_PROTECT(lev);
+
+ lastdata = sock->lastdata;
+ sock->lastdata = NULL;
+ sock->lastoffset = 0;
+ sock->err = 0;
+
+ /* Protect socket array */
+ SYS_ARCH_PROTECT(lev);
+ sock->conn = NULL;
+ SYS_ARCH_UNPROTECT(lev);
+ /* don't use 'sock' after this line, as another task might have allocated it */
+
+ if (lastdata != NULL) {
+ if (is_tcp) {
+ pbuf_free((struct pbuf *)lastdata);
+ } else {
+ netbuf_delete((struct netbuf *)lastdata);
+ }
+ }
+}
+
/* Below this, the well-known socket functions are implemented.
* Use google.com or opengroup.org to get a good description :-)
*
@@ -247,35 +311,42 @@ alloc_socket(struct netconn *newconn)
int
lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
- struct lwip_socket *sock, *nsock;
+ struct lwip_sock *sock, *nsock;
struct netconn *newconn;
- struct ip_addr naddr;
+ ip_addr_t naddr;
u16_t port;
int newsock;
struct sockaddr_in sin;
err_t err;
+ SYS_ARCH_DECL_PROTECT(lev);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
sock = get_socket(s);
- if (!sock)
+ if (!sock) {
return -1;
+ }
- if ((sock->flags & O_NONBLOCK) && (sock->rcvevent <= 0)) {
+ if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
sock_set_errno(sock, EWOULDBLOCK);
return -1;
}
- newconn = netconn_accept(sock->conn);
- if (!newconn) {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) failed, err=%d\n", s, sock->conn->err));
- sock_set_errno(sock, err_to_errno(sock->conn->err));
+ /* wait for a new connection */
+ err = netconn_accept(sock->conn, &newconn);
+ if (err != ERR_OK) {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err));
+ sock_set_errno(sock, err_to_errno(err));
return -1;
}
+ LWIP_ASSERT("newconn != NULL", newconn != NULL);
+ /* Prevent automatic window updates, we do this on our own! */
+ netconn_set_noautorecved(newconn, 1);
/* get the IP address and port of the remote host */
err = netconn_peer(newconn, &naddr, &port);
if (err != ERR_OK) {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
netconn_delete(newconn);
sock_set_errno(sock, err_to_errno(err));
return -1;
@@ -290,7 +361,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
- sin.sin_addr.s_addr = naddr.addr;
+ inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
if (*addrlen > sizeof(sin))
*addrlen = sizeof(sin);
@@ -298,26 +369,25 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
MEMCPY(addr, &sin, *addrlen);
}
- newsock = alloc_socket(newconn);
+ newsock = alloc_socket(newconn, 1);
if (newsock == -1) {
netconn_delete(newconn);
sock_set_errno(sock, ENFILE);
return -1;
}
LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS));
- newconn->callback = event_callback;
+ LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback);
nsock = &sockets[newsock];
- LWIP_ASSERT("invalid socket pointer", nsock != NULL);
- sys_sem_wait(socksem);
/* See event_callback: If data comes in right away after an accept, even
* though the server task might not have created a new socket yet.
* In that case, newconn->socket is counted down (newconn->socket--),
* so nsock->rcvevent is >= 1 here!
*/
- nsock->rcvevent += -1 - newconn->socket;
+ SYS_ARCH_PROTECT(lev);
+ nsock->rcvevent += (s16_t)(-1 - newconn->socket);
newconn->socket = newsock;
- sys_sem_signal(socksem);
+ SYS_ARCH_UNPROTECT(lev);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
@@ -330,21 +400,25 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
int
lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
{
- struct lwip_socket *sock;
- struct ip_addr local_addr;
+ struct lwip_sock *sock;
+ ip_addr_t local_addr;
u16_t local_port;
err_t err;
+ const struct sockaddr_in *name_in;
sock = get_socket(s);
- if (!sock)
+ if (!sock) {
return -1;
+ }
+ /* check size, familiy and alignment of 'name' */
LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
- ((((const struct sockaddr_in *)name)->sin_family) == AF_INET)),
+ ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
+ name_in = (const struct sockaddr_in *)(void*)name;
- local_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr;
- local_port = ((const struct sockaddr_in *)name)->sin_port;
+ inet_addr_to_ipaddr(&local_addr, &name_in->sin_addr);
+ local_port = name_in->sin_port;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
@@ -366,7 +440,8 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
int
lwip_close(int s)
{
- struct lwip_socket *sock;
+ struct lwip_sock *sock;
+ int is_tcp = 0;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
@@ -375,43 +450,46 @@ lwip_close(int s)
return -1;
}
+ if(sock->conn != NULL) {
+ is_tcp = netconn_type(sock->conn) == NETCONN_TCP;
+ } else {
+ LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
+ }
+
netconn_delete(sock->conn);
- sys_sem_wait(socksem);
- if (sock->lastdata) {
- netbuf_delete(sock->lastdata);
- }
- sock->lastdata = NULL;
- sock->lastoffset = 0;
- sock->conn = NULL;
- sock_set_errno(sock, 0);
- sys_sem_signal(socksem);
+ free_socket(sock, is_tcp);
+ set_errno(0);
return 0;
}
int
lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
{
- struct lwip_socket *sock;
+ struct lwip_sock *sock;
err_t err;
+ const struct sockaddr_in *name_in;
sock = get_socket(s);
- if (!sock)
+ if (!sock) {
return -1;
+ }
+ /* check size, familiy and alignment of 'name' */
LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
- ((((const struct sockaddr_in *)name)->sin_family) == AF_INET)),
+ ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
+ name_in = (const struct sockaddr_in *)(void*)name;
- if (((const struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
+ if (name_in->sin_family == AF_UNSPEC) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
err = netconn_disconnect(sock->conn);
} else {
- struct ip_addr remote_addr;
+ ip_addr_t remote_addr;
u16_t remote_port;
- remote_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr;
- remote_port = ((const struct sockaddr_in *)name)->sin_port;
+ inet_addr_to_ipaddr(&remote_addr, &name_in->sin_addr);
+ remote_port = name_in->sin_port;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
@@ -436,30 +514,26 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
* The socket may not have been used for another connection previously.
*
* @param s the socket to set to listening mode
- * @param backlog (ATTENTION: need TCP_LISTEN_BACKLOG=1)
+ * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1)
* @return 0 on success, non-zero on failure
*/
int
lwip_listen(int s, int backlog)
{
- struct lwip_socket *sock;
+ struct lwip_sock *sock;
err_t err;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
sock = get_socket(s);
- if (!sock)
+ if (!sock) {
return -1;
+ }
/* limit the "backlog" parameter to fit in an u8_t */
- if (backlog < 0) {
- backlog = 0;
- }
- if (backlog > 0xff) {
- backlog = 0xff;
- }
+ backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff);
- err = netconn_listen_with_backlog(sock->conn, backlog);
+ err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog);
if (err != ERR_OK) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
@@ -475,28 +549,34 @@ int
lwip_recvfrom(int s, void *mem, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen)
{
- struct lwip_socket *sock;
- struct netbuf *buf;
- u16_t buflen, copylen, off = 0;
- struct ip_addr *addr;
- u16_t port;
- u8_t done = 0;
+ struct lwip_sock *sock;
+ void *buf = NULL;
+ struct pbuf *p;
+ u16_t buflen, copylen;
+ int off = 0;
+ ip_addr_t *addr;
+ u16_t port;
+ u8_t done = 0;
+ err_t err;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
sock = get_socket(s);
- if (!sock)
+ if (!sock) {
return -1;
+ }
do {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", (void*)sock->lastdata));
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata));
/* Check if there is data left from the last recv operation. */
if (sock->lastdata) {
buf = sock->lastdata;
} else {
/* If this is non-blocking call, then check first */
- if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) &&
+ if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&
(sock->rcvevent <= 0)) {
if (off > 0) {
+ /* update receive window */
+ netconn_recved(sock->conn, (u32_t)off);
/* already received data, return that */
sock_set_errno(sock, 0);
return off;
@@ -507,26 +587,44 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
}
/* No data was left from the previous operation, so we try to get
- some from the network. */
- sock->lastdata = buf = netconn_recv(sock->conn);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv netbuf=%p\n", (void*)buf));
+ some from the network. */
+ if (netconn_type(sock->conn) == NETCONN_TCP) {
+ err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
+ } else {
+ err = netconn_recv(sock->conn, (struct netbuf **)&buf);
+ }
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n",
+ err, buf));
- if (!buf) {
+ if (err != ERR_OK) {
if (off > 0) {
+ /* update receive window */
+ netconn_recved(sock->conn, (u32_t)off);
/* already received data, return that */
sock_set_errno(sock, 0);
return off;
}
/* We should really do some error checking here. */
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
- sock_set_errno(sock, (((sock->conn->pcb.ip != NULL) && (sock->conn->err == ERR_OK))
- ? ETIMEDOUT : err_to_errno(sock->conn->err)));
- return 0;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n",
+ s, lwip_strerr(err)));
+ sock_set_errno(sock, err_to_errno(err));
+ if (err == ERR_CLSD) {
+ return 0;
+ } else {
+ return -1;
+ }
}
+ LWIP_ASSERT("buf != NULL", buf != NULL);
+ sock->lastdata = buf;
}
- buflen = netbuf_len(buf);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%"U16_F" sock->lastoffset=%"U16_F"\n",
+ if (netconn_type(sock->conn) == NETCONN_TCP) {
+ p = (struct pbuf *)buf;
+ } else {
+ p = ((struct netbuf *)buf)->p;
+ }
+ buflen = p->tot_len;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n",
buflen, len, off, sock->lastoffset));
buflen -= sock->lastoffset;
@@ -539,7 +637,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
/* copy the contents of the received buffer into
the supplied memory pointer mem */
- netbuf_copy_partial(buf, (u8_t*)mem + off, copylen, sock->lastoffset);
+ pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset);
off += copylen;
@@ -547,7 +645,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
len -= copylen;
if ( (len <= 0) ||
- (buf->p->flags & PBUF_FLAG_PUSH) ||
+ (p->flags & PBUF_FLAG_PUSH) ||
(sock->rcvevent <= 0) ||
((flags & MSG_PEEK)!=0)) {
done = 1;
@@ -558,22 +656,23 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
/* Check to see from where the data was.*/
if (done) {
+ ip_addr_t fromaddr;
if (from && fromlen) {
struct sockaddr_in sin;
if (netconn_type(sock->conn) == NETCONN_TCP) {
- addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
+ addr = &fromaddr;
netconn_getaddr(sock->conn, addr, &port, 0);
} else {
- addr = netbuf_fromaddr(buf);
- port = netbuf_fromport(buf);
+ addr = netbuf_fromaddr((struct netbuf *)buf);
+ port = netbuf_fromport((struct netbuf *)buf);
}
memset(&sin, 0, sizeof(sin));
sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
- sin.sin_addr.s_addr = addr->addr;
+ inet_addr_from_ipaddr(&sin.sin_addr, addr);
if (*fromlen > sizeof(sin)) {
*fromlen = sizeof(sin);
@@ -583,44 +682,50 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, addr);
- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off));
+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
} else {
- #if SOCKETS_DEBUG
- struct sockaddr_in sin;
-
+#if SOCKETS_DEBUG
if (netconn_type(sock->conn) == NETCONN_TCP) {
- addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
+ addr = &fromaddr;
netconn_getaddr(sock->conn, addr, &port, 0);
} else {
- addr = netbuf_fromaddr(buf);
- port = netbuf_fromport(buf);
+ addr = netbuf_fromaddr((struct netbuf *)buf);
+ port = netbuf_fromport((struct netbuf *)buf);
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, addr);
- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off));
- #endif /* SOCKETS_DEBUG */
+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
+#endif /* SOCKETS_DEBUG */
}
}
/* If we don't peek the incoming message... */
- if ((flags & MSG_PEEK)==0) {
+ if ((flags & MSG_PEEK) == 0) {
/* If this is a TCP socket, check if there is data left in the
buffer. If so, it should be saved in the sock structure for next
time around. */
if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
sock->lastdata = buf;
sock->lastoffset += copylen;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", (void*)buf));
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
} else {
sock->lastdata = NULL;
sock->lastoffset = 0;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", (void*)buf));
- netbuf_delete(buf);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
+ if (netconn_type(sock->conn) == NETCONN_TCP) {
+ pbuf_free((struct pbuf *)buf);
+ } else {
+ netbuf_delete((struct netbuf *)buf);
+ }
}
}
} while (!done);
+ if (off > 0) {
+ /* update receive window */
+ netconn_recved(sock->conn, (u32_t)off);
+ }
sock_set_errno(sock, 0);
return off;
}
@@ -640,26 +745,39 @@ lwip_recv(int s, void *mem, size_t len, int flags)
int
lwip_send(int s, const void *data, size_t size, int flags)
{
- struct lwip_socket *sock;
+ struct lwip_sock *sock;
err_t err;
+ u8_t write_flags;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
s, data, size, flags));
sock = get_socket(s);
- if (!sock)
+ if (!sock) {
return -1;
+ }
if (sock->conn->type != NETCONN_TCP) {
#if (LWIP_UDP || LWIP_RAW)
return lwip_sendto(s, data, size, flags, NULL, 0);
-#else
+#else /* (LWIP_UDP || LWIP_RAW) */
sock_set_errno(sock, err_to_errno(ERR_ARG));
return -1;
#endif /* (LWIP_UDP || LWIP_RAW) */
}
- err = netconn_write(sock->conn, data, size, NETCONN_COPY | ((flags & MSG_MORE)?NETCONN_MORE:0));
+ if ((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) {
+ if ((size > TCP_SND_BUF) || ((size / TCP_MSS) > TCP_SND_QUEUELEN)) {
+ /* too much data to ever send nonblocking! */
+ sock_set_errno(sock, EMSGSIZE);
+ return -1;
+ }
+ }
+
+ write_flags = NETCONN_COPY |
+ ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
+ ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
+ err = netconn_write(sock->conn, data, size, write_flags);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%"SZT_F"\n", s, err, size));
sock_set_errno(sock, err_to_errno(err));
@@ -670,77 +788,115 @@ int
lwip_sendto(int s, const void *data, size_t size, int flags,
const struct sockaddr *to, socklen_t tolen)
{
- struct lwip_socket *sock;
- struct ip_addr remote_addr;
+ struct lwip_sock *sock;
err_t err;
u16_t short_size;
+ const struct sockaddr_in *to_in;
+ u16_t remote_port;
#if !LWIP_TCPIP_CORE_LOCKING
struct netbuf buf;
- u16_t remote_port;
#endif
sock = get_socket(s);
- if (!sock)
+ if (!sock) {
return -1;
+ }
if (sock->conn->type == NETCONN_TCP) {
#if LWIP_TCP
return lwip_send(s, data, size, flags);
-#else
+#else /* LWIP_TCP */
+ LWIP_UNUSED_ARG(flags);
sock_set_errno(sock, err_to_errno(ERR_ARG));
return -1;
#endif /* LWIP_TCP */
}
+ /* @todo: split into multiple sendto's? */
LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
short_size = (u16_t)size;
LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
((tolen == sizeof(struct sockaddr_in)) &&
- ((((const struct sockaddr_in *)to)->sin_family) == AF_INET))),
+ ((to->sa_family) == AF_INET) && ((((mem_ptr_t)to) % 4) == 0))),
sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
+ to_in = (const struct sockaddr_in *)(void*)to;
#if LWIP_TCPIP_CORE_LOCKING
/* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */
- { struct pbuf* p;
-
- p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
- if (p == NULL) {
- err = ERR_MEM;
- } else {
+ {
+ struct pbuf* p;
+ ip_addr_t *remote_addr;
+
+#if LWIP_NETIF_TX_SINGLE_PBUF
+ p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM);
+ if (p != NULL) {
+#if LWIP_CHECKSUM_ON_COPY
+ u16_t chksum = 0;
+ if (sock->conn->type != NETCONN_RAW) {
+ chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size);
+ } else
+#endif /* LWIP_CHECKSUM_ON_COPY */
+ MEMCPY(p->payload, data, size);
+#else /* LWIP_NETIF_TX_SINGLE_PBUF */
+ p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_REF);
+ if (p != NULL) {
p->payload = (void*)data;
- p->len = p->tot_len = short_size;
-
- remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
-
+#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
+
+ if (to_in != NULL) {
+ inet_addr_to_ipaddr_p(remote_addr, &to_in->sin_addr);
+ remote_port = ntohs(to_in->sin_port);
+ } else {
+ remote_addr = &sock->conn->pcb.raw->remote_ip;
+ if (sock->conn->type == NETCONN_RAW) {
+ remote_port = 0;
+ } else {
+ remote_port = sock->conn->pcb.udp->remote_port;
+ }
+ }
+
LOCK_TCPIP_CORE();
- if (sock->conn->type==NETCONN_RAW) {
- err = sock->conn->err = raw_sendto(sock->conn->pcb.raw, p, &remote_addr);
+ if (sock->conn->type == NETCONN_RAW) {
+ err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr);
} else {
- err = sock->conn->err = udp_sendto(sock->conn->pcb.udp, p, &remote_addr, ntohs(((const struct sockaddr_in *)to)->sin_port));
+#if LWIP_UDP
+#if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF
+ err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p,
+ remote_addr, remote_port, 1, chksum);
+#else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
+ err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p,
+ remote_addr, remote_port);
+#endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
+#else /* LWIP_UDP */
+ err = ERR_ARG;
+#endif /* LWIP_UDP */
}
UNLOCK_TCPIP_CORE();
pbuf_free(p);
+ } else {
+ err = ERR_MEM;
}
}
-#else
+#else /* LWIP_TCPIP_CORE_LOCKING */
/* initialize a buffer */
buf.p = buf.ptr = NULL;
+#if LWIP_CHECKSUM_ON_COPY
+ buf.flags = 0;
+#endif /* LWIP_CHECKSUM_ON_COPY */
if (to) {
- remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
- remote_port = ntohs(((const struct sockaddr_in *)to)->sin_port);
- buf.addr = &remote_addr;
- buf.port = remote_port;
+ inet_addr_to_ipaddr(&buf.addr, &to_in->sin_addr);
+ remote_port = ntohs(to_in->sin_port);
+ netbuf_fromport(&buf) = remote_port;
} else {
- remote_addr.addr = 0;
- remote_port = 0;
- buf.addr = NULL;
- buf.port = 0;
+ remote_port = 0;
+ ip_addr_set_any(&buf.addr);
+ netbuf_fromport(&buf) = 0;
}
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%d"U16_F", flags=0x%x to=",
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=",
s, data, short_size, flags));
- ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
+ ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
/* make the buffer point to the data that should be sent */
@@ -749,7 +905,16 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
if (netbuf_alloc(&buf, short_size) == NULL) {
err = ERR_MEM;
} else {
- err = netbuf_take(&buf, data, short_size);
+#if LWIP_CHECKSUM_ON_COPY
+ if (sock->conn->type != NETCONN_RAW) {
+ u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
+ netbuf_set_chksum(&buf, chksum);
+ err = ERR_OK;
+ } else
+#endif /* LWIP_CHECKSUM_ON_COPY */
+ {
+ err = netbuf_take(&buf, data, short_size);
+ }
}
#else /* LWIP_NETIF_TX_SINGLE_PBUF */
err = netbuf_ref(&buf, data, short_size);
@@ -791,6 +956,10 @@ lwip_socket(int domain, int type, int protocol)
conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
+ if (conn != NULL) {
+ /* Prevent automatic window updates, we do this on our own! */
+ netconn_set_noautorecved(conn, 1);
+ }
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
@@ -805,7 +974,7 @@ lwip_socket(int domain, int type, int protocol)
return -1;
}
- i = alloc_socket(conn);
+ i = alloc_socket(conn, 0);
if (i == -1) {
netconn_delete(conn);
@@ -832,200 +1001,228 @@ lwip_write(int s, const void *data, size_t size)
* exceptset is not used for now!!!
*
* @param maxfdp1 the highest socket index in the sets
- * @param readset in: set of sockets to check for read events;
- * out: set of sockets that had read events
- * @param writeset in: set of sockets to check for write events;
- * out: set of sockets that had write events
- * @param exceptset not yet implemented
- * @return number of sockets that had events (read+write)
+ * @param readset_in: set of sockets to check for read events
+ * @param writeset_in: set of sockets to check for write events
+ * @param exceptset_in: set of sockets to check for error events
+ * @param readset_out: set of sockets that had read events
+ * @param writeset_out: set of sockets that had write events
+ * @param exceptset_out: set os sockets that had error events
+ * @return number of sockets that had events (read/write/exception) (>= 0)
*/
static int
-lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
+lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in,
+ fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out)
{
int i, nready = 0;
fd_set lreadset, lwriteset, lexceptset;
- struct lwip_socket *p_sock;
-
+ struct lwip_sock *sock;
+ SYS_ARCH_DECL_PROTECT(lev);
+
FD_ZERO(&lreadset);
FD_ZERO(&lwriteset);
FD_ZERO(&lexceptset);
-
+
/* Go through each socket in each list to count number of sockets which
- currently match */
+ currently match */
for(i = 0; i < maxfdp1; i++) {
- if (FD_ISSET(i, readset)) {
- /* See if netconn of this socket is ready for read */
- p_sock = get_socket(i);
- if (p_sock && (p_sock->lastdata || (p_sock->rcvevent > 0))) {
- FD_SET(i, &lreadset);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
- nready++;
- }
+ void* lastdata = NULL;
+ s16_t rcvevent = 0;
+ u16_t sendevent = 0;
+ u16_t errevent = 0;
+ /* First get the socket's status (protected)... */
+ SYS_ARCH_PROTECT(lev);
+ sock = tryget_socket(i);
+ if (sock != NULL) {
+ lastdata = sock->lastdata;
+ rcvevent = sock->rcvevent;
+ sendevent = sock->sendevent;
+ errevent = sock->errevent;
}
- if (FD_ISSET(i, writeset)) {
- /* See if netconn of this socket is ready for write */
- p_sock = get_socket(i);
- if (p_sock && p_sock->sendevent) {
- FD_SET(i, &lwriteset);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
- nready++;
- }
+ SYS_ARCH_UNPROTECT(lev);
+ /* ... then examine it: */
+ /* See if netconn of this socket is ready for read */
+ if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) {
+ FD_SET(i, &lreadset);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
+ nready++;
+ }
+ /* See if netconn of this socket is ready for write */
+ if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) {
+ FD_SET(i, &lwriteset);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
+ nready++;
+ }
+ /* See if netconn of this socket had an error */
+ if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) {
+ FD_SET(i, &lexceptset);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i));
+ nready++;
}
}
- *readset = lreadset;
- *writeset = lwriteset;
- FD_ZERO(exceptset);
-
+ /* copy local sets to the ones provided as arguments */
+ *readset_out = lreadset;
+ *writeset_out = lwriteset;
+ *exceptset_out = lexceptset;
+
+ LWIP_ASSERT("nready >= 0", nready >= 0);
return nready;
}
-
/**
* Processing exceptset is not yet implemented.
*/
int
lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
- struct timeval *timeout)
+ struct timeval *timeout)
{
- int i;
+ u32_t waitres = 0;
int nready;
fd_set lreadset, lwriteset, lexceptset;
u32_t msectimeout;
struct lwip_select_cb select_cb;
- struct lwip_select_cb *p_selcb;
+ err_t err;
+ int i;
+ SYS_ARCH_DECL_PROTECT(lev);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n",
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n",
maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
- timeout ? (long)timeout->tv_sec : (long)-1,
- timeout ? (long)timeout->tv_usec : (long)-1));
-
- select_cb.next = 0;
- select_cb.readset = readset;
- select_cb.writeset = writeset;
- select_cb.exceptset = exceptset;
- select_cb.sem_signalled = 0;
-
- /* Protect ourselves searching through the list */
- sys_sem_wait(selectsem);
-
- if (readset)
- lreadset = *readset;
- else
- FD_ZERO(&lreadset);
- if (writeset)
- lwriteset = *writeset;
- else
- FD_ZERO(&lwriteset);
- if (exceptset)
- lexceptset = *exceptset;
- else
- FD_ZERO(&lexceptset);
+ timeout ? (s32_t)timeout->tv_sec : (s32_t)-1,
+ timeout ? (s32_t)timeout->tv_usec : (s32_t)-1));
/* Go through each socket in each list to count number of sockets which
currently match */
- nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
+ nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
/* If we don't have any current events, then suspend if we are supposed to */
if (!nready) {
if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
- sys_sem_signal(selectsem);
- if (readset)
- FD_ZERO(readset);
- if (writeset)
- FD_ZERO(writeset);
- if (exceptset)
- FD_ZERO(exceptset);
-
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
- set_errno(0);
-
- return 0;
+ /* This is OK as the local fdsets are empty and nready is zero,
+ or we would have returned earlier. */
+ goto return_copy_fdsets;
}
-
- /* add our semaphore to list */
- /* We don't actually need any dynamic memory. Our entry on the
- * list is only valid while we are in this function, so it's ok
- * to use local variables */
-
- select_cb.sem = sys_sem_new(0);
- /* Note that we are still protected */
+
+ /* None ready: add our semaphore to list:
+ We don't actually need any dynamic memory. Our entry on the
+ list is only valid while we are in this function, so it's ok
+ to use local variables. */
+
+ select_cb.next = NULL;
+ select_cb.prev = NULL;
+ select_cb.readset = readset;
+ select_cb.writeset = writeset;
+ select_cb.exceptset = exceptset;
+ select_cb.sem_signalled = 0;
+ err = sys_sem_new(&select_cb.sem, 0);
+ if (err != ERR_OK) {
+ /* failed to create semaphore */
+ set_errno(ENOMEM);
+ return -1;
+ }
+
+ /* Protect the select_cb_list */
+ SYS_ARCH_PROTECT(lev);
+
/* Put this select_cb on top of list */
select_cb.next = select_cb_list;
+ if (select_cb_list != NULL) {
+ select_cb_list->prev = &select_cb;
+ }
select_cb_list = &select_cb;
-
+ /* Increasing this counter tells even_callback that the list has changed. */
+ select_cb_ctr++;
+
/* Now we can safely unprotect */
- sys_sem_signal(selectsem);
-
- /* Now just wait to be woken */
- if (timeout == 0)
- /* Wait forever */
- msectimeout = 0;
- else {
- msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
- if(msectimeout == 0)
- msectimeout = 1;
+ SYS_ARCH_UNPROTECT(lev);
+
+ /* Increase select_waiting for each socket we are interested in */
+ for(i = 0; i < maxfdp1; i++) {
+ if ((readset && FD_ISSET(i, readset)) ||
+ (writeset && FD_ISSET(i, writeset)) ||
+ (exceptset && FD_ISSET(i, exceptset))) {
+ struct lwip_sock *sock = tryget_socket(i);
+ LWIP_ASSERT("sock != NULL", sock != NULL);
+ SYS_ARCH_PROTECT(lev);
+ sock->select_waiting++;
+ LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
+ SYS_ARCH_UNPROTECT(lev);
+ }
}
-
- i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
-
- /* Take us off the list */
- sys_sem_wait(selectsem);
- if (select_cb_list == &select_cb)
- select_cb_list = select_cb.next;
- else
- for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next) {
- if (p_selcb->next == &select_cb) {
- p_selcb->next = select_cb.next;
- break;
+
+ /* Call lwip_selscan again: there could have been events between
+ the last scan (whithout us on the list) and putting us on the list! */
+ nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
+ if (!nready) {
+ /* Still none ready, just wait to be woken */
+ if (timeout == 0) {
+ /* Wait forever */
+ msectimeout = 0;
+ } else {
+ msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
+ if (msectimeout == 0) {
+ /* Wait 1ms at least (0 means wait forever) */
+ msectimeout = 1;
}
}
-
- sys_sem_signal(selectsem);
-
- sys_sem_free(select_cb.sem);
- if (i == 0) {
+
+ waitres = sys_arch_sem_wait(&select_cb.sem, msectimeout);
+ }
+ /* Increase select_waiting for each socket we are interested in */
+ for(i = 0; i < maxfdp1; i++) {
+ if ((readset && FD_ISSET(i, readset)) ||
+ (writeset && FD_ISSET(i, writeset)) ||
+ (exceptset && FD_ISSET(i, exceptset))) {
+ struct lwip_sock *sock = tryget_socket(i);
+ LWIP_ASSERT("sock != NULL", sock != NULL);
+ SYS_ARCH_PROTECT(lev);
+ sock->select_waiting--;
+ LWIP_ASSERT("sock->select_waiting >= 0", sock->select_waiting >= 0);
+ SYS_ARCH_UNPROTECT(lev);
+ }
+ }
+ /* Take us off the list */
+ SYS_ARCH_PROTECT(lev);
+ if (select_cb.next != NULL) {
+ select_cb.next->prev = select_cb.prev;
+ }
+ if (select_cb_list == &select_cb) {
+ LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL);
+ select_cb_list = select_cb.next;
+ } else {
+ LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
+ select_cb.prev->next = select_cb.next;
+ }
+ /* Increasing this counter tells even_callback that the list has changed. */
+ select_cb_ctr++;
+ SYS_ARCH_UNPROTECT(lev);
+
+ sys_sem_free(&select_cb.sem);
+ if (waitres == SYS_ARCH_TIMEOUT) {
/* Timeout */
- if (readset)
- FD_ZERO(readset);
- if (writeset)
- FD_ZERO(writeset);
- if (exceptset)
- FD_ZERO(exceptset);
-
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
- set_errno(0);
-
- return 0;
+ /* This is OK as the local fdsets are empty and nready is zero,
+ or we would have returned earlier. */
+ goto return_copy_fdsets;
}
-
- if (readset)
- lreadset = *readset;
- else
- FD_ZERO(&lreadset);
- if (writeset)
- lwriteset = *writeset;
- else
- FD_ZERO(&lwriteset);
- if (exceptset)
- lexceptset = *exceptset;
- else
- FD_ZERO(&lexceptset);
-
+
/* See what's set */
- nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
- } else
- sys_sem_signal(selectsem);
-
- if (readset)
+ nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
+ }
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
+return_copy_fdsets:
+ set_errno(0);
+ if (readset) {
*readset = lreadset;
- if (writeset)
+ }
+ if (writeset) {
*writeset = lwriteset;
- if (exceptset)
+ }
+ if (exceptset) {
*exceptset = lexceptset;
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
- set_errno(0);
-
+ }
+
+
return nready;
}
@@ -1037,8 +1234,10 @@ static void
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
{
int s;
- struct lwip_socket *sock;
+ struct lwip_sock *sock;
struct lwip_select_cb *scb;
+ int last_select_cb_ctr;
+ SYS_ARCH_DECL_PROTECT(lev);
LWIP_UNUSED_ARG(len);
@@ -1051,16 +1250,16 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
* Just count down (or up) if that's the case and we
* will use the data later. Note that only receive events
* can happen before the new socket is set up. */
- sys_sem_wait(socksem);
+ SYS_ARCH_PROTECT(lev);
if (conn->socket < 0) {
if (evt == NETCONN_EVT_RCVPLUS) {
conn->socket--;
}
- sys_sem_signal(socksem);
+ SYS_ARCH_UNPROTECT(lev);
return;
}
s = conn->socket;
- sys_sem_signal(socksem);
+ SYS_ARCH_UNPROTECT(lev);
}
sock = get_socket(s);
@@ -1071,7 +1270,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
return;
}
- sys_sem_wait(selectsem);
+ SYS_ARCH_PROTECT(lev);
/* Set event as required */
switch (evt) {
case NETCONN_EVT_RCVPLUS:
@@ -1086,41 +1285,65 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
case NETCONN_EVT_SENDMINUS:
sock->sendevent = 0;
break;
+ case NETCONN_EVT_ERROR:
+ sock->errevent = 1;
+ break;
default:
LWIP_ASSERT("unknown event", 0);
break;
}
- sys_sem_signal(selectsem);
+
+ if (sock->select_waiting == 0) {
+ /* noone is waiting for this socket, no need to check select_cb_list */
+ SYS_ARCH_UNPROTECT(lev);
+ return;
+ }
/* Now decide if anyone is waiting for this socket */
- /* NOTE: This code is written this way to protect the select link list
- but to avoid a deadlock situation by releasing socksem before
- signalling for the select. This means we need to go through the list
- multiple times ONLY IF a select was actually waiting. We go through
- the list the number of waiting select calls + 1. This list is
- expected to be small. */
- while (1) {
- sys_sem_wait(selectsem);
- for (scb = select_cb_list; scb; scb = scb->next) {
- if (scb->sem_signalled == 0) {
- /* Test this select call for our socket */
- if (scb->readset && FD_ISSET(s, scb->readset))
- if (sock->rcvevent > 0)
- break;
- if (scb->writeset && FD_ISSET(s, scb->writeset))
- if (sock->sendevent)
- break;
+ /* NOTE: This code goes through the select_cb_list list multiple times
+ ONLY IF a select was actually waiting. We go through the list the number
+ of waiting select calls + 1. This list is expected to be small. */
+
+ /* At this point, SYS_ARCH is still protected! */
+again:
+ for (scb = select_cb_list; scb != NULL; scb = scb->next) {
+ if (scb->sem_signalled == 0) {
+ /* semaphore not signalled yet */
+ int do_signal = 0;
+ /* Test this select call for our socket */
+ if (sock->rcvevent > 0) {
+ if (scb->readset && FD_ISSET(s, scb->readset)) {
+ do_signal = 1;
+ }
+ }
+ if (sock->sendevent != 0) {
+ if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
+ do_signal = 1;
+ }
+ }
+ if (sock->errevent != 0) {
+ if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
+ do_signal = 1;
+ }
+ }
+ if (do_signal) {
+ scb->sem_signalled = 1;
+ /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might
+ lead to the select thread taking itself off the list, invalidagin the semaphore. */
+ sys_sem_signal(&scb->sem);
}
}
- if (scb) {
- scb->sem_signalled = 1;
- sys_sem_signal(scb->sem);
- sys_sem_signal(selectsem);
- } else {
- sys_sem_signal(selectsem);
- break;
+ /* unlock interrupts with each step */
+ last_select_cb_ctr = select_cb_ctr;
+ SYS_ARCH_UNPROTECT(lev);
+ /* this makes sure interrupt protection time is short */
+ SYS_ARCH_PROTECT(lev);
+ if (last_select_cb_ctr != select_cb_ctr) {
+ /* someone has changed select_cb_list, restart at the beginning */
+ goto again;
}
}
+ SYS_ARCH_UNPROTECT(lev);
}
/**
@@ -1130,21 +1353,55 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
int
lwip_shutdown(int s, int how)
{
- LWIP_UNUSED_ARG(how);
+ struct lwip_sock *sock;
+ err_t err;
+ u8_t shut_rx = 0, shut_tx = 0;
+
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
- return lwip_close(s); /* XXX temporary hack until proper implementation */
+
+ sock = get_socket(s);
+ if (!sock) {
+ return -1;
+ }
+
+ if (sock->conn != NULL) {
+ if (netconn_type(sock->conn) != NETCONN_TCP) {
+ sock_set_errno(sock, EOPNOTSUPP);
+ return EOPNOTSUPP;
+ }
+ } else {
+ sock_set_errno(sock, ENOTCONN);
+ return ENOTCONN;
+ }
+
+ if (how == SHUT_RD) {
+ shut_rx = 1;
+ } else if (how == SHUT_WR) {
+ shut_tx = 1;
+ } else if(how == SHUT_RDWR) {
+ shut_rx = 1;
+ shut_tx = 1;
+ } else {
+ sock_set_errno(sock, EINVAL);
+ return EINVAL;
+ }
+ err = netconn_shutdown(sock->conn, shut_rx, shut_tx);
+
+ sock_set_errno(sock, err_to_errno(err));
+ return (err == ERR_OK ? 0 : -1);
}
static int
lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
{
- struct lwip_socket *sock;
+ struct lwip_sock *sock;
struct sockaddr_in sin;
- struct ip_addr naddr;
+ ip_addr_t naddr;
sock = get_socket(s);
- if (!sock)
+ if (!sock) {
return -1;
+ }
memset(&sin, 0, sizeof(sin));
sin.sin_len = sizeof(sin);
@@ -1158,10 +1415,11 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
sin.sin_port = htons(sin.sin_port);
- sin.sin_addr.s_addr = naddr.addr;
+ inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
- if (*namelen > sizeof(sin))
+ if (*namelen > sizeof(sin)) {
*namelen = sizeof(sin);
+ }
MEMCPY(name, &sin, *namelen);
sock_set_errno(sock, 0);
@@ -1184,11 +1442,12 @@ int
lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
{
err_t err = ERR_OK;
- struct lwip_socket *sock = get_socket(s);
+ struct lwip_sock *sock = get_socket(s);
struct lwip_setgetsockopt_data data;
- if (!sock)
+ if (!sock) {
return -1;
+ }
if ((NULL == optval) || (NULL == optlen)) {
sock_set_errno(sock, EFAULT);
@@ -1274,6 +1533,14 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
err = EINVAL;
}
break;
+ case IP_MULTICAST_LOOP:
+ if (*optlen < sizeof(u8_t)) {
+ err = EINVAL;
+ }
+ if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
+ err = EAFNOSUPPORT;
+ }
+ break;
#endif /* LWIP_IGMP */
default:
@@ -1321,8 +1588,9 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
}
/* If this is no UDP lite socket, ignore any options. */
- if (sock->conn->type != NETCONN_UDPLITE)
+ if (sock->conn->type != NETCONN_UDPLITE) {
return 0;
+ }
switch (optname) {
case UDPLITE_SEND_CSCOV:
@@ -1351,13 +1619,16 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
/* Now do the actual option processing */
data.sock = sock;
+#ifdef LWIP_DEBUG
+ data.s = s;
+#endif /* LWIP_DEBUG */
data.level = level;
data.optname = optname;
data.optval = optval;
data.optlen = optlen;
data.err = err;
tcpip_callback(lwip_getsockopt_internal, &data);
- sys_arch_sem_wait(sock->conn->op_completed, 0);
+ sys_arch_sem_wait(&sock->conn->op_completed, 0);
/* maybe lwip_getsockopt_internal has changed err */
err = data.err;
@@ -1368,7 +1639,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
static void
lwip_getsockopt_internal(void *arg)
{
- struct lwip_socket *sock;
+ struct lwip_sock *sock;
#ifdef LWIP_DEBUG
int s;
#endif /* LWIP_DEBUG */
@@ -1388,7 +1659,7 @@ lwip_getsockopt_internal(void *arg)
optval = data->optval;
switch (level) {
-
+
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch (optname) {
@@ -1432,8 +1703,9 @@ lwip_getsockopt_internal(void *arg)
break;
case SO_ERROR:
- if (sock->err == 0) {
- sock_set_errno(sock, err_to_errno(sock->conn->err));
+ /* only overwrite ERR_OK or tempoary errors */
+ if ((sock->err == 0) || (sock->err == EINPROGRESS)) {
+ sock_set_errno(sock, err_to_errno(sock->conn->last_err));
}
*(int *)optval = sock->err;
sock->err = 0;
@@ -1443,12 +1715,12 @@ lwip_getsockopt_internal(void *arg)
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO:
- *(int *)optval = sock->conn->recv_timeout;
+ *(int *)optval = netconn_get_recvtimeout(sock->conn);
break;
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
case SO_RCVBUF:
- *(int *)optval = sock->conn->recv_bufsize;
+ *(int *)optval = netconn_get_recvbufsize(sock->conn);
break;
#endif /* LWIP_SO_RCVBUF */
#if LWIP_UDP
@@ -1456,6 +1728,9 @@ lwip_getsockopt_internal(void *arg)
*(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
break;
#endif /* LWIP_UDP*/
+ default:
+ LWIP_ASSERT("unhandled optname", 0);
+ break;
} /* switch (optname) */
break;
@@ -1479,11 +1754,23 @@ lwip_getsockopt_internal(void *arg)
s, *(int *)optval));
break;
case IP_MULTICAST_IF:
- ((struct in_addr*) optval)->s_addr = sock->conn->pcb.udp->multicast_ip.addr;
+ inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
s, *(u32_t *)optval));
break;
+ case IP_MULTICAST_LOOP:
+ if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
+ *(u8_t*)optval = 1;
+ } else {
+ *(u8_t*)optval = 0;
+ }
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n",
+ s, *(int *)optval));
+ break;
#endif /* LWIP_IGMP */
+ default:
+ LWIP_ASSERT("unhandled optname", 0);
+ break;
} /* switch (optname) */
break;
@@ -1519,7 +1806,9 @@ lwip_getsockopt_internal(void *arg)
s, *(int *)optval));
break;
#endif /* LWIP_TCP_KEEPALIVE */
-
+ default:
+ LWIP_ASSERT("unhandled optname", 0);
+ break;
} /* switch (optname) */
break;
#endif /* LWIP_TCP */
@@ -1537,22 +1826,29 @@ lwip_getsockopt_internal(void *arg)
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
s, (*(int*)optval)) );
break;
+ default:
+ LWIP_ASSERT("unhandled optname", 0);
+ break;
} /* switch (optname) */
break;
#endif /* LWIP_UDP */
+ default:
+ LWIP_ASSERT("unhandled level", 0);
+ break;
} /* switch (level) */
- sys_sem_signal(sock->conn->op_completed);
+ sys_sem_signal(&sock->conn->op_completed);
}
int
lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
{
- struct lwip_socket *sock = get_socket(s);
- int err = ERR_OK;
+ struct lwip_sock *sock = get_socket(s);
+ err_t err = ERR_OK;
struct lwip_setgetsockopt_data data;
- if (!sock)
+ if (!sock) {
return -1;
+ }
if (NULL == optval) {
sock_set_errno(sock, EFAULT);
@@ -1639,6 +1935,14 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
err = EAFNOSUPPORT;
}
break;
+ case IP_MULTICAST_LOOP:
+ if (optlen < sizeof(u8_t)) {
+ err = EINVAL;
+ }
+ if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
+ err = EAFNOSUPPORT;
+ }
+ break;
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
if (optlen < sizeof(struct ip_mreq)) {
@@ -1725,13 +2029,16 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
/* Now do the actual option processing */
data.sock = sock;
+#ifdef LWIP_DEBUG
+ data.s = s;
+#endif /* LWIP_DEBUG */
data.level = level;
data.optname = optname;
data.optval = (void*)optval;
data.optlen = &optlen;
data.err = err;
tcpip_callback(lwip_setsockopt_internal, &data);
- sys_arch_sem_wait(sock->conn->op_completed, 0);
+ sys_arch_sem_wait(&sock->conn->op_completed, 0);
/* maybe lwip_setsockopt_internal has changed err */
err = data.err;
@@ -1742,7 +2049,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
static void
lwip_setsockopt_internal(void *arg)
{
- struct lwip_socket *sock;
+ struct lwip_sock *sock;
#ifdef LWIP_DEBUG
int s;
#endif /* LWIP_DEBUG */
@@ -1788,12 +2095,12 @@ lwip_setsockopt_internal(void *arg)
break;
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO:
- sock->conn->recv_timeout = ( *(int*)optval );
+ netconn_set_recvtimeout(sock->conn, *(int*)optval);
break;
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
case SO_RCVBUF:
- sock->conn->recv_bufsize = ( *(int*)optval );
+ netconn_set_recvbufsize(sock->conn, *(int*)optval);
break;
#endif /* LWIP_SO_RCVBUF */
#if LWIP_UDP
@@ -1805,6 +2112,9 @@ lwip_setsockopt_internal(void *arg)
}
break;
#endif /* LWIP_UDP */
+ default:
+ LWIP_ASSERT("unhandled optname", 0);
+ break;
} /* switch (optname) */
break;
@@ -1826,17 +2136,28 @@ lwip_setsockopt_internal(void *arg)
sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval);
break;
case IP_MULTICAST_IF:
- sock->conn->pcb.udp->multicast_ip.addr = ((struct in_addr*) optval)->s_addr;
+ inet_addr_to_ipaddr(&sock->conn->pcb.udp->multicast_ip, (struct in_addr*)optval);
+ break;
+ case IP_MULTICAST_LOOP:
+ if (*(u8_t*)optval) {
+ udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
+ } else {
+ udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
+ }
break;
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
{
/* If this is a TCP or a RAW socket, ignore these options. */
struct ip_mreq *imr = (struct ip_mreq *)optval;
+ ip_addr_t if_addr;
+ ip_addr_t multi_addr;
+ inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
+ inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
if(optname == IP_ADD_MEMBERSHIP){
- data->err = igmp_joingroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
+ data->err = igmp_joingroup(&if_addr, &multi_addr);
} else {
- data->err = igmp_leavegroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
+ data->err = igmp_leavegroup(&if_addr, &multi_addr);
}
if(data->err != ERR_OK) {
data->err = EADDRNOTAVAIL;
@@ -1844,6 +2165,9 @@ lwip_setsockopt_internal(void *arg)
}
break;
#endif /* LWIP_IGMP */
+ default:
+ LWIP_ASSERT("unhandled optname", 0);
+ break;
} /* switch (optname) */
break;
@@ -1883,7 +2207,9 @@ lwip_setsockopt_internal(void *arg)
s, sock->conn->pcb.tcp->keep_cnt));
break;
#endif /* LWIP_TCP_KEEPALIVE */
-
+ default:
+ LWIP_ASSERT("unhandled optname", 0);
+ break;
} /* switch (optname) */
break;
#endif /* LWIP_TCP*/
@@ -1892,43 +2218,54 @@ lwip_setsockopt_internal(void *arg)
case IPPROTO_UDPLITE:
switch (optname) {
case UDPLITE_SEND_CSCOV:
- if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
+ if ((*(int*)optval != 0) && ((*(int*)optval < 8)) || (*(int*)optval > 0xffff)) {
/* don't allow illegal values! */
sock->conn->pcb.udp->chksum_len_tx = 8;
} else {
- sock->conn->pcb.udp->chksum_len_tx = *(int*)optval;
+ sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(int*)optval;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
s, (*(int*)optval)) );
break;
case UDPLITE_RECV_CSCOV:
- if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
+ if ((*(int*)optval != 0) && ((*(int*)optval < 8)) || (*(int*)optval > 0xffff)) {
/* don't allow illegal values! */
sock->conn->pcb.udp->chksum_len_rx = 8;
} else {
- sock->conn->pcb.udp->chksum_len_rx = *(int*)optval;
+ sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(int*)optval;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
s, (*(int*)optval)) );
break;
+ default:
+ LWIP_ASSERT("unhandled optname", 0);
+ break;
} /* switch (optname) */
break;
#endif /* LWIP_UDP */
+ default:
+ LWIP_ASSERT("unhandled level", 0);
+ break;
} /* switch (level) */
- sys_sem_signal(sock->conn->op_completed);
+ sys_sem_signal(&sock->conn->op_completed);
}
int
lwip_ioctl(int s, long cmd, void *argp)
{
- struct lwip_socket *sock = get_socket(s);
+ struct lwip_sock *sock = get_socket(s);
+ u8_t val;
+#if LWIP_SO_RCVBUF
u16_t buflen = 0;
s16_t recv_avail;
+#endif /* LWIP_SO_RCVBUF */
- if (!sock)
+ if (!sock) {
return -1;
+ }
switch (cmd) {
+#if LWIP_SO_RCVBUF
case FIONREAD:
if (!argp) {
sock_set_errno(sock, EINVAL);
@@ -1936,13 +2273,18 @@ lwip_ioctl(int s, long cmd, void *argp)
}
SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
- if (recv_avail < 0)
+ if (recv_avail < 0) {
recv_avail = 0;
+ }
*((u16_t*)argp) = (u16_t)recv_avail;
/* Check if there is data left from the last recv operation. /maq 041215 */
if (sock->lastdata) {
- buflen = netbuf_len(sock->lastdata);
+ struct pbuf *p = (struct pbuf *)sock->lastdata;
+ if (netconn_type(sock->conn) != NETCONN_TCP) {
+ p = ((struct netbuf *)p)->p;
+ }
+ buflen = p->tot_len;
buflen -= sock->lastoffset;
*((u16_t*)argp) += buflen;
@@ -1951,13 +2293,15 @@ lwip_ioctl(int s, long cmd, void *argp)
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
sock_set_errno(sock, 0);
return 0;
+#endif /* LWIP_SO_RCVBUF */
case FIONBIO:
- if (argp && *(u32_t*)argp)
- sock->flags |= O_NONBLOCK;
- else
- sock->flags &= ~O_NONBLOCK;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
+ val = 0;
+ if (argp && *(u32_t*)argp) {
+ val = 1;
+ }
+ netconn_set_nonblocking(sock->conn, val);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val));
sock_set_errno(sock, 0);
return 0;
@@ -1968,4 +2312,36 @@ lwip_ioctl(int s, long cmd, void *argp)
} /* switch (cmd) */
}
+/** A minimal implementation of fcntl.
+ * Currently only the commands F_GETFL and F_SETFL are implemented.
+ * Only the flag O_NONBLOCK is implemented.
+ */
+int
+lwip_fcntl(int s, int cmd, int val)
+{
+ struct lwip_sock *sock = get_socket(s);
+ int ret = -1;
+
+ if (!sock || !sock->conn) {
+ return -1;
+ }
+
+ switch (cmd) {
+ case F_GETFL:
+ ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0;
+ break;
+ case F_SETFL:
+ if ((val & ~O_NONBLOCK) == 0) {
+ /* only O_NONBLOCK, all other bits are zero */
+ netconn_set_nonblocking(sock->conn, val & O_NONBLOCK);
+ ret = 0;
+ }
+ break;
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val));
+ break;
+ }
+ return ret;
+}
+
#endif /* LWIP_SOCKET */
diff --git a/core/lwip/src/api/tcpip.c b/core/lwip/src/api/tcpip.c
index 9c0ba5b6..857e7d9b 100644
--- a/core/lwip/src/api/tcpip.c
+++ b/core/lwip/src/api/tcpip.c
@@ -42,183 +42,23 @@
#include "lwip/sys.h"
#include "lwip/memp.h"
+#include "lwip/mem.h"
#include "lwip/pbuf.h"
-#include "lwip/ip_frag.h"
-#include "lwip/tcp.h"
-#include "lwip/autoip.h"
-#include "lwip/dhcp.h"
-#include "lwip/igmp.h"
-#include "lwip/dns.h"
#include "lwip/tcpip.h"
#include "lwip/init.h"
#include "netif/etharp.h"
#include "netif/ppp_oe.h"
/* global variables */
-static void (* tcpip_init_done)(void *arg);
+static tcpip_init_done_fn tcpip_init_done;
static void *tcpip_init_done_arg;
-static sys_mbox_t mbox = SYS_MBOX_NULL;
+static sys_mbox_t mbox;
#if LWIP_TCPIP_CORE_LOCKING
/** The global semaphore to lock the stack. */
-sys_sem_t lock_tcpip_core;
+sys_mutex_t lock_tcpip_core;
#endif /* LWIP_TCPIP_CORE_LOCKING */
-#if LWIP_TCP
-/* global variable that shows if the tcp timer is currently scheduled or not */
-static int tcpip_tcp_timer_active;
-
-/**
- * Timer callback function that calls tcp_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-tcpip_tcp_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
-
- /* call TCP timer handler */
- tcp_tmr();
- /* timer still needed? */
- if (tcp_active_pcbs || tcp_tw_pcbs) {
- /* restart timer */
- sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
- } else {
- /* disable timer */
- tcpip_tcp_timer_active = 0;
- }
-}
-
-#if !NO_SYS
-/**
- * Called from TCP_REG when registering a new PCB:
- * the reason is to have the TCP timer only running when
- * there are active (or time-wait) PCBs.
- */
-void
-tcp_timer_needed(void)
-{
- /* timer is off but needed again? */
- if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
- /* enable and start timer */
- tcpip_tcp_timer_active = 1;
- sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
- }
-}
-#endif /* !NO_SYS */
-#endif /* LWIP_TCP */
-
-#if IP_REASSEMBLY
-/**
- * Timer callback function that calls ip_reass_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-ip_reass_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
- ip_reass_tmr();
- sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
-}
-#endif /* IP_REASSEMBLY */
-
-#if LWIP_ARP
-/**
- * Timer callback function that calls etharp_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-arp_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: etharp_tmr()\n"));
- etharp_tmr();
- undiarp_tmr();
- sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
-}
-#endif /* LWIP_ARP */
-
-#if LWIP_DHCP
-/**
- * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-dhcp_timer_coarse(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
- dhcp_coarse_tmr();
- sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
-}
-
-/**
- * Timer callback function that calls dhcp_fine_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-dhcp_timer_fine(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
- dhcp_fine_tmr();
- sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
-}
-#endif /* LWIP_DHCP */
-
-#if LWIP_AUTOIP
-/**
- * Timer callback function that calls autoip_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-autoip_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: autoip_tmr()\n"));
- autoip_tmr();
- sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
-}
-#endif /* LWIP_AUTOIP */
-
-#if LWIP_IGMP
-/**
- * Timer callback function that calls igmp_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-igmp_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: igmp_tmr()\n"));
- igmp_tmr();
- sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
-}
-#endif /* LWIP_IGMP */
-
-#if LWIP_DNS
-/**
- * Timer callback function that calls dns_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-dns_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dns_tmr()\n"));
- dns_tmr();
- sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
-}
-#endif /* LWIP_DNS */
/**
* The main lwIP thread. This thread has exclusive access to lwIP core functions
@@ -236,33 +76,17 @@ tcpip_thread(void *arg)
struct tcpip_msg *msg;
LWIP_UNUSED_ARG(arg);
-#if IP_REASSEMBLY
- sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
-#endif /* IP_REASSEMBLY */
-#if LWIP_ARP
- sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
-#endif /* LWIP_ARP */
-#if LWIP_DHCP
- sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
- sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
-#endif /* LWIP_DHCP */
-#if LWIP_AUTOIP
- sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
-#endif /* LWIP_AUTOIP */
-#if LWIP_IGMP
- sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
-#endif /* LWIP_IGMP */
-#if LWIP_DNS
- sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
-#endif /* LWIP_DNS */
-
if (tcpip_init_done != NULL) {
tcpip_init_done(tcpip_init_done_arg);
}
LOCK_TCPIP_CORE();
while (1) { /* MAIN Loop */
- sys_mbox_fetch(mbox, (void *)&msg);
+ UNLOCK_TCPIP_CORE();
+ LWIP_TCPIP_THREAD_ALIVE();
+ /* wait for a message, timeouts are processed while waiting */
+ sys_timeouts_mbox_fetch(&mbox, (void **)&msg);
+ LOCK_TCPIP_CORE();
switch (msg->type) {
#if LWIP_NETCONN
case TCPIP_MSG_API:
@@ -271,17 +95,20 @@ tcpip_thread(void *arg)
break;
#endif /* LWIP_NETCONN */
+#if !LWIP_TCPIP_CORE_LOCKING_INPUT
case TCPIP_MSG_INPKT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
-#if LWIP_ARP
- if (msg->msg.inp.netif->flags & NETIF_FLAG_ETHARP) {
+#if LWIP_ETHERNET
+ if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
} else
-#endif /* LWIP_ARP */
- { ip_input(msg->msg.inp.p, msg->msg.inp.netif);
+#endif /* LWIP_ETHERNET */
+ {
+ ip_input(msg->msg.inp.p, msg->msg.inp.netif);
}
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
break;
+#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
#if LWIP_NETIF_API
case TCPIP_MSG_NETIFAPI:
@@ -292,10 +119,11 @@ tcpip_thread(void *arg)
case TCPIP_MSG_CALLBACK:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
- msg->msg.cb.f(msg->msg.cb.ctx);
+ msg->msg.cb.function(msg->msg.cb.ctx);
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
+#if LWIP_TCPIP_TIMEOUT
case TCPIP_MSG_TIMEOUT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
@@ -306,8 +134,11 @@ tcpip_thread(void *arg)
sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
+#endif /* LWIP_TCPIP_TIMEOUT */
default:
+ LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
+ LWIP_ASSERT("tcpip_thread: invalid message", 0);
break;
}
}
@@ -317,16 +148,32 @@ tcpip_thread(void *arg)
* Pass a received packet to tcpip_thread for input processing
*
* @param p the received packet, p->payload pointing to the Ethernet header or
- * to an IP header (if netif doesn't got NETIF_FLAG_ETHARP flag)
+ * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
+ * NETIF_FLAG_ETHERNET flags)
* @param inp the network interface on which the packet was received
*/
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
+#if LWIP_TCPIP_CORE_LOCKING_INPUT
+ err_t ret;
+ LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp));
+ LOCK_TCPIP_CORE();
+#if LWIP_ETHERNET
+ if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
+ ret = ethernet_input(p, inp);
+ } else
+#endif /* LWIP_ETHERNET */
+ {
+ ret = ip_input(p, inp);
+ }
+ UNLOCK_TCPIP_CORE();
+ return ret;
+#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
struct tcpip_msg *msg;
- if (mbox != SYS_MBOX_NULL) {
- msg = memp_malloc(MEMP_TCPIP_MSG_INPKT);
+ if (sys_mbox_valid(&mbox)) {
+ msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
if (msg == NULL) {
return ERR_MEM;
}
@@ -334,13 +181,14 @@ tcpip_input(struct pbuf *p, struct netif *inp)
msg->type = TCPIP_MSG_INPKT;
msg->msg.inp.p = p;
msg->msg.inp.netif = inp;
- if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
+ if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
return ERR_MEM;
}
return ERR_OK;
}
return ERR_VAL;
+#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
}
/**
@@ -355,23 +203,23 @@ tcpip_input(struct pbuf *p, struct netif *inp)
* @return ERR_OK if the function was called, another err_t if not
*/
err_t
-tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block)
+tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
{
struct tcpip_msg *msg;
- if (mbox != SYS_MBOX_NULL) {
- msg = memp_malloc(MEMP_TCPIP_MSG_API);
+ if (sys_mbox_valid(&mbox)) {
+ msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_CALLBACK;
- msg->msg.cb.f = f;
+ msg->msg.cb.function = function;
msg->msg.cb.ctx = ctx;
if (block) {
- sys_mbox_post(mbox, msg);
+ sys_mbox_post(&mbox, msg);
} else {
- if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
+ if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
memp_free(MEMP_TCPIP_MSG_API, msg);
return ERR_MEM;
}
@@ -381,10 +229,11 @@ tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block)
return ERR_VAL;
}
+#if LWIP_TCPIP_TIMEOUT
/**
* call sys_timeout in tcpip_thread
*
- * @param msec time in miliseconds for timeout
+ * @param msec time in milliseconds 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
@@ -394,8 +243,8 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{
struct tcpip_msg *msg;
- if (mbox != SYS_MBOX_NULL) {
- msg = memp_malloc(MEMP_TCPIP_MSG_API);
+ if (sys_mbox_valid(&mbox)) {
+ msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
@@ -404,7 +253,7 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
msg->msg.tmo.msecs = msecs;
msg->msg.tmo.h = h;
msg->msg.tmo.arg = arg;
- sys_mbox_post(mbox, msg);
+ sys_mbox_post(&mbox, msg);
return ERR_OK;
}
return ERR_VAL;
@@ -413,7 +262,7 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
/**
* call sys_untimeout in tcpip_thread
*
- * @param msec time in miliseconds for timeout
+ * @param msec time in milliseconds 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
@@ -423,8 +272,8 @@ 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 (sys_mbox_valid(&mbox)) {
+ msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
@@ -432,11 +281,12 @@ tcpip_untimeout(sys_timeout_handler h, void *arg)
msg->type = TCPIP_MSG_UNTIMEOUT;
msg->msg.tmo.h = h;
msg->msg.tmo.arg = arg;
- sys_mbox_post(mbox, msg);
+ sys_mbox_post(&mbox, msg);
return ERR_OK;
}
return ERR_VAL;
}
+#endif /* LWIP_TCPIP_TIMEOUT */
#if LWIP_NETCONN
/**
@@ -451,13 +301,17 @@ err_t
tcpip_apimsg(struct api_msg *apimsg)
{
struct tcpip_msg msg;
+#ifdef LWIP_DEBUG
+ /* catch functions that don't set err */
+ apimsg->msg.err = ERR_VAL;
+#endif
- if (mbox != SYS_MBOX_NULL) {
+ if (sys_mbox_valid(&mbox)) {
msg.type = TCPIP_MSG_API;
msg.msg.apimsg = apimsg;
- sys_mbox_post(mbox, &msg);
- sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0);
- return ERR_OK;
+ sys_mbox_post(&mbox, &msg);
+ sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0);
+ return apimsg->msg.err;
}
return ERR_VAL;
}
@@ -474,10 +328,15 @@ tcpip_apimsg(struct api_msg *apimsg)
err_t
tcpip_apimsg_lock(struct api_msg *apimsg)
{
+#ifdef LWIP_DEBUG
+ /* catch functions that don't set err */
+ apimsg->msg.err = ERR_VAL;
+#endif
+
LOCK_TCPIP_CORE();
apimsg->function(&(apimsg->msg));
UNLOCK_TCPIP_CORE();
- return ERR_OK;
+ return apimsg->msg.err;
}
#endif /* LWIP_TCPIP_CORE_LOCKING */
@@ -497,18 +356,18 @@ tcpip_netifapi(struct netifapi_msg* netifapimsg)
{
struct tcpip_msg msg;
- if (mbox != SYS_MBOX_NULL) {
- netifapimsg->msg.sem = sys_sem_new(0);
- if (netifapimsg->msg.sem == SYS_SEM_NULL) {
- netifapimsg->msg.err = ERR_MEM;
- return netifapimsg->msg.err;
+ if (sys_mbox_valid(&mbox)) {
+ err_t err = sys_sem_new(&netifapimsg->msg.sem, 0);
+ if (err != ERR_OK) {
+ netifapimsg->msg.err = err;
+ return err;
}
msg.type = TCPIP_MSG_NETIFAPI;
msg.msg.netifapimsg = netifapimsg;
- sys_mbox_post(mbox, &msg);
- sys_sem_wait(netifapimsg->msg.sem);
- sys_sem_free(netifapimsg->msg.sem);
+ sys_mbox_post(&mbox, &msg);
+ sys_sem_wait(&netifapimsg->msg.sem);
+ sys_sem_free(&netifapimsg->msg.sem);
return netifapimsg->msg.err;
}
return ERR_VAL;
@@ -542,15 +401,19 @@ tcpip_netifapi_lock(struct netifapi_msg* netifapimsg)
* @param arg argument to pass to initfunc
*/
void
-tcpip_init(void (* initfunc)(void *), void *arg)
+tcpip_init(tcpip_init_done_fn initfunc, void *arg)
{
lwip_init();
tcpip_init_done = initfunc;
tcpip_init_done_arg = arg;
- mbox = sys_mbox_new(TCPIP_MBOX_SIZE);
+ if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
+ LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
+ }
#if LWIP_TCPIP_CORE_LOCKING
- lock_tcpip_core = sys_sem_new(1);
+ if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
+ LWIP_ASSERT("failed to create lock_tcpip_core", 0);
+ }
#endif /* LWIP_TCPIP_CORE_LOCKING */
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
@@ -565,7 +428,7 @@ tcpip_init(void (* initfunc)(void *), void *arg)
static void
pbuf_free_int(void *p)
{
- struct pbuf *q = p;
+ struct pbuf *q = (struct pbuf *)p;
pbuf_free(q);
}
diff --git a/core/lwip/src/arch/sys_arch.c b/core/lwip/src/arch/sys_arch.c
index 65be3874..5f8437e8 100644
--- a/core/lwip/src/arch/sys_arch.c
+++ b/core/lwip/src/arch/sys_arch.c
@@ -8,77 +8,119 @@ void sys_init(void)
{
}
-sys_sem_t sys_sem_new(u8_t count)
+err_t sys_sem_new(sys_sem_t *sem, u8_t count)
{
- sys_sem_t sem = malloc(sizeof(struct semaphore));
if (!sem)
- return NULL;
+ return EINVAL;
+ *sem = malloc(sizeof(struct semaphore));
+ if (!*sem)
+ return ENOMEM;
- sem_init(sem, count);
- return sem;
+ sem_init(*sem, count);
+ return 0;
}
-void sys_sem_free(sys_sem_t sem)
+void sys_sem_free(sys_sem_t *sem)
{
- free(sem);
+ if (!!sem && !!*sem) {
+ sys_sem_set_invalid(sem);
+ free(*sem);
+ }
}
-u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
+void sys_sem_set_invalid(sys_sem_t *sem)
+{
+ if (!sem || !*sem)
+ return;
+ sem_set_invalid(*sem);
+}
+
+
+int sys_sem_valid(sys_sem_t *sem)
+{
+ if (!sem || !*sem)
+ return 0;
+ return sem_is_valid(*sem);
+}
+
+u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
{
mstime_t rv;
- rv = sem_down(sem, timeout);
+ if (!!sem)
+ return SYS_ARCH_TIMEOUT;
+ rv = sem_down(*sem, timeout);
if (rv == (mstime_t)-1)
return SYS_ARCH_TIMEOUT;
else
return rv;
}
-sys_mbox_t sys_mbox_new(int size)
+err_t sys_mbox_new(sys_mbox_t *mbox, int size)
{
- struct mailbox *mbox;
-
- mbox = malloc(MBOX_BYTES(size));
if (!mbox)
- return NULL;
+ return EINVAL;
+ *mbox = malloc(MBOX_BYTES(size));
+ if (!(*mbox))
+ return ENOMEM;
- mbox_init(mbox, size);
- return mbox;
+ mbox_init(*mbox, size);
+ return 0;
}
-void sys_mbox_free(sys_mbox_t mbox)
+void sys_mbox_free(sys_mbox_t *mbox)
{
- free(mbox);
+ if (!!mbox && !!*mbox)
+ free(*mbox);
}
-void sys_mbox_post(sys_mbox_t mbox, void *msg)
+void sys_mbox_post(sys_mbox_t *mbox, void *msg)
{
- mbox_post(mbox, msg, 0);
+ if (!!mbox)
+ mbox_post(*mbox, msg, 0);
}
-err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg)
+err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
{
- return mbox_post(mbox, msg, -1);
+ if (!mbox)
+ return EINVAL;
+ return mbox_post(*mbox, msg, -1);
}
-u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
+u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
{
mstime_t rv;
- rv = mbox_fetch(mbox, msg, timeout);
+ if (!mbox)
+ return SYS_MBOX_EMPTY;
+ rv = mbox_fetch(*mbox, msg, timeout);
if (rv == (mstime_t)-1)
return SYS_ARCH_TIMEOUT;
else
return rv;
}
-u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg)
+u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
+{
+ if (!mbox)
+ return SYS_MBOX_EMPTY;
+ return mbox_fetch(*mbox, msg, -1);
+}
+
+void sys_mbox_set_invalid(sys_mbox_t *mbox)
{
- return mbox_fetch(mbox, msg, -1);
+ if (!!mbox)
+ mbox_set_invalid(*mbox);
}
-sys_thread_t sys_thread_new(char *name, void (*thread)(void *),
- void *arg, int stacksize, int prio)
+int sys_mbox_valid(sys_mbox_t *mbox)
+{
+ return ((!!mbox) && mbox_is_valid(*mbox));
+}
+
+
+sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread,
+ void *arg, int stacksize, int prio)
{
return start_thread(name, stacksize, prio, thread, arg);
}
diff --git a/core/lwip/src/core/def.c b/core/lwip/src/core/def.c
new file mode 100644
index 00000000..352b5524
--- /dev/null
+++ b/core/lwip/src/core/def.c
@@ -0,0 +1,108 @@
+/**
+ * @file
+ * Common functions used throughout the stack.
+ *
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+
+#include "lwip/opt.h"
+#include "lwip/def.h"
+
+/**
+ * These are reference implementations of the byte swapping functions.
+ * Again with the aim of being simple, correct and fully portable.
+ * Byte swapping is the second thing you would want to optimize. You will
+ * need to port it to your architecture and in your cc.h:
+ *
+ * #define LWIP_PLATFORM_BYTESWAP 1
+ * #define LWIP_PLATFORM_HTONS(x) <your_htons>
+ * #define LWIP_PLATFORM_HTONL(x) <your_htonl>
+ *
+ * Note ntohs() and ntohl() are merely references to the htonx counterparts.
+ */
+
+#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
+
+/**
+ * Convert an u16_t from host- to network byte order.
+ *
+ * @param n u16_t in host byte order
+ * @return n in network byte order
+ */
+u16_t
+lwip_htons(u16_t n)
+{
+ return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
+}
+
+/**
+ * Convert an u16_t from network- to host byte order.
+ *
+ * @param n u16_t in network byte order
+ * @return n in host byte order
+ */
+u16_t
+lwip_ntohs(u16_t n)
+{
+ return lwip_htons(n);
+}
+
+/**
+ * Convert an u32_t from host- to network byte order.
+ *
+ * @param n u32_t in host byte order
+ * @return n in network byte order
+ */
+u32_t
+lwip_htonl(u32_t n)
+{
+ return ((n & 0xff) << 24) |
+ ((n & 0xff00) << 8) |
+ ((n & 0xff0000UL) >> 8) |
+ ((n & 0xff000000UL) >> 24);
+}
+
+/**
+ * Convert an u32_t from network- to host byte order.
+ *
+ * @param n u32_t in network byte order
+ * @return n in host byte order
+ */
+u32_t
+lwip_ntohl(u32_t n)
+{
+ return lwip_htonl(n);
+}
+
+#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */
diff --git a/core/lwip/src/core/dhcp.c b/core/lwip/src/core/dhcp.c
index 82068bfd..81b4be27 100644
--- a/core/lwip/src/core/dhcp.c
+++ b/core/lwip/src/core/dhcp.c
@@ -43,8 +43,6 @@
* with RFC 2131 and RFC 2132.
*
* TODO:
- * - Proper parsing of DHCP messages exploiting file/sname field overloading.
- * - Add JavaDoc style documentation (API, internals).
* - Support for interfaces other than Ethernet (SLIP, PPP, ...)
*
* Please coordinate changes and requests with Leon Woestenberg
@@ -77,7 +75,7 @@
#include "lwip/udp.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
-#include "lwip/inet.h"
+#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/dhcp.h"
#include "lwip/autoip.h"
@@ -104,16 +102,43 @@
#define REBOOT_TRIES 2
-/* DHCP client state machine functions */
-static void dhcp_handle_ack(struct netif *netif);
-static void dhcp_handle_nak(struct netif *netif);
-static void dhcp_handle_offer(struct netif *netif);
+/** Option handling: options are parsed in dhcp_parse_reply
+ * and saved in an array where other functions can load them from.
+ * This might be moved into the struct dhcp (not necessarily since
+ * lwIP is single-threaded and the array is only used while in recv
+ * callback). */
+#define DHCP_OPTION_IDX_OVERLOAD 0
+#define DHCP_OPTION_IDX_MSG_TYPE 1
+#define DHCP_OPTION_IDX_SERVER_ID 2
+#define DHCP_OPTION_IDX_LEASE_TIME 3
+#define DHCP_OPTION_IDX_T1 4
+#define DHCP_OPTION_IDX_T2 5
+#define DHCP_OPTION_IDX_SUBNET_MASK 6
+#define DHCP_OPTION_IDX_ROUTER 7
+#define DHCP_OPTION_IDX_DNS_SERVER 8
+#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
+
+/** Holds the decoded option values, only valid while in dhcp_recv.
+ @todo: move this into struct dhcp? */
+u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX];
+/** Holds a flag which option was received and is contained in dhcp_rx_options_val,
+ only valid while in dhcp_recv.
+ @todo: move this into struct dhcp? */
+u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
+
+#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0)
+#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1)
+#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0)
+#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given)))
+#define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx])
+#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val))
+
+/* DHCP client state machine functions */
static err_t dhcp_discover(struct netif *netif);
static err_t dhcp_select(struct netif *netif);
static void dhcp_bind(struct netif *netif);
#if DHCP_DOES_ARP_CHECK
-static void dhcp_check(struct netif *netif);
static err_t dhcp_decline(struct netif *netif);
#endif /* DHCP_DOES_ARP_CHECK */
static err_t dhcp_rebind(struct netif *netif);
@@ -121,15 +146,7 @@ static err_t dhcp_reboot(struct netif *netif);
static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
/* receive, unfold, parse and free incoming messages */
-static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
-static err_t dhcp_unfold_reply(struct dhcp *dhcp, struct pbuf *p);
-static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type);
-static u8_t dhcp_get_option_byte(u8_t *ptr);
-#if 0
-static u16_t dhcp_get_option_short(u8_t *ptr);
-#endif
-static u32_t dhcp_get_option_long(u8_t *ptr);
-static void dhcp_free_reply(struct dhcp *dhcp);
+static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
/* set the DHCP timers */
static void dhcp_timeout(struct netif *netif);
@@ -137,10 +154,10 @@ static void dhcp_t1_timeout(struct netif *netif);
static void dhcp_t2_timeout(struct netif *netif);
/* build outgoing messages */
-/* create a DHCP request, fill in common headers */
-static err_t dhcp_create_request(struct netif *netif);
+/* create a DHCP message, fill in common headers */
+static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type);
/* free a DHCP request */
-static void dhcp_delete_request(struct netif *netif);
+static void dhcp_delete_msg(struct dhcp *dhcp);
/* add a DHCP option (type, then length in bytes) */
static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len);
/* add option values */
@@ -221,18 +238,22 @@ static void
dhcp_handle_offer(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
- /* obtain the server address */
- u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
- if (option_ptr != NULL) {
- dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", dhcp->server_ip_addr.addr));
+ /* obtain the server address */
+ if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) {
+ ip4_addr_set_u32(&dhcp->server_ip_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID)));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n",
+ ip4_addr_get_u32(&dhcp->server_ip_addr)));
/* remember offered address */
- ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
+ ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr);
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n",
+ ip4_addr_get_u32(&dhcp->offered_ip_addr)));
dhcp_select(netif);
+ } else {
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
+ ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif));
}
}
@@ -250,28 +271,22 @@ dhcp_select(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, ("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);
+ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
if (result == ERR_OK) {
- dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
- dhcp_option_byte(dhcp, DHCP_REQUEST);
-
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
/* MUST request the offered IP address */
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
- dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
+ dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
- dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
+ dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->server_ip_addr)));
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
@@ -280,11 +295,15 @@ dhcp_select(struct netif *netif)
dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
#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++);
+ if (netif->hostname != NULL) {
+ const char *p = (const char*)netif->hostname;
+ u8_t namelen = (u8_t)strlen(p);
+ if (namelen > 0) {
+ LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255);
+ dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen);
+ while (*p) {
+ dhcp_option_byte(dhcp, *p++);
+ }
}
}
#endif /* LWIP_NETIF_HOSTNAME */
@@ -295,7 +314,7 @@ dhcp_select(struct netif *netif)
/* send broadcast to any DHCP server */
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
- dhcp_delete_request(netif);
+ dhcp_delete_msg(dhcp);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
} else {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n"));
@@ -309,7 +328,6 @@ dhcp_select(struct netif *netif)
/**
* The DHCP timer that checks for lease renewal/rebind timeouts.
- *
*/
void
dhcp_coarse_tmr()
@@ -342,7 +360,6 @@ 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()
@@ -360,7 +377,7 @@ dhcp_fine_tmr()
netif->dhcp->request_timeout--;
/* { netif->dhcp->request_timeout == 0 } */
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
- /* this clients' request timeout triggered */
+ /* this client's request timeout triggered */
dhcp_timeout(netif);
}
}
@@ -445,10 +462,14 @@ dhcp_t1_timeout(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
- if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
+ if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) ||
+ (dhcp->state == DHCP_RENEWING)) {
/* just retry to renew - note that the rebind timer (t2) will
* eventually time-out if renew tries fail. */
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("dhcp_t1_timeout(): must renew\n"));
+ /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
+ DHCP_RENEWING, not DHCP_BOUND */
dhcp_renew(netif);
}
}
@@ -463,9 +484,13 @@ dhcp_t2_timeout(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n"));
- if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
+ if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) ||
+ (dhcp->state == DHCP_RENEWING)) {
/* just retry to rebind */
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout(): must rebind\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("dhcp_t2_timeout(): must rebind\n"));
+ /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
+ DHCP_REBINDING, not DHCP_BOUND */
dhcp_rebind(netif);
}
}
@@ -479,91 +504,108 @@ static void
dhcp_handle_ack(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
- u8_t *option_ptr;
+#if LWIP_DNS
+ u8_t n;
+#endif /* LWIP_DNS */
+
/* clear options we might not get from the ACK */
- dhcp->offered_sn_mask.addr = 0;
- dhcp->offered_gw_addr.addr = 0;
- dhcp->offered_bc_addr.addr = 0;
+ ip_addr_set_zero(&dhcp->offered_sn_mask);
+ ip_addr_set_zero(&dhcp->offered_gw_addr);
+#if LWIP_DHCP_BOOTP_FILE
+ ip_addr_set_zero(&dhcp->offered_si_addr);
+#endif /* LWIP_DHCP_BOOTP_FILE */
/* lease time given? */
- option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_LEASE_TIME);
- if (option_ptr != NULL) {
+ if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) {
/* remember offered lease time */
- dhcp->offered_t0_lease = dhcp_get_option_long(option_ptr + 2);
+ dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME);
}
/* renewal period given? */
- option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T1);
- if (option_ptr != NULL) {
+ if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) {
/* remember given renewal period */
- dhcp->offered_t1_renew = dhcp_get_option_long(option_ptr + 2);
+ dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1);
} else {
/* calculate safe periods for renewal */
dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
}
/* renewal period given? */
- option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T2);
- if (option_ptr != NULL) {
+ if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) {
/* remember given rebind period */
- dhcp->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2);
+ dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2);
} else {
/* calculate safe periods for rebinding */
dhcp->offered_t2_rebind = dhcp->offered_t0_lease;
}
/* (y)our internet address */
- ip_addr_set(&dhcp->offered_ip_addr, &dhcp->msg_in->yiaddr);
+ ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr);
-/**
- * Patch #1308
- * TODO: we must check if the file field is not overloaded by DHCP options!
- */
-#if 0
- /* boot server address */
- ip_addr_set(&dhcp->offered_si_addr, &dhcp->msg_in->siaddr);
- /* boot file name */
- if (dhcp->msg_in->file[0]) {
- dhcp->boot_file_name = mem_malloc(strlen(dhcp->msg_in->file) + 1);
- strcpy(dhcp->boot_file_name, dhcp->msg_in->file);
- }
-#endif
+#if LWIP_DHCP_BOOTP_FILE
+ /* copy boot server address,
+ boot file name copied in dhcp_parse_reply if not overloaded */
+ ip_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr);
+#endif /* LWIP_DHCP_BOOTP_FILE */
- /* subnet mask */
- option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SUBNET_MASK);
/* subnet mask given? */
- if (option_ptr != NULL) {
- dhcp->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
+ if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) {
+ /* remember given subnet mask */
+ ip4_addr_set_u32(&dhcp->offered_sn_mask, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)));
+ dhcp->subnet_mask_given = 1;
+ } else {
+ dhcp->subnet_mask_given = 0;
}
/* gateway router */
- option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_ROUTER);
- if (option_ptr != NULL) {
- dhcp->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
- }
-
- /* broadcast address */
- option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_BROADCAST);
- if (option_ptr != NULL) {
- dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
+ if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) {
+ ip4_addr_set_u32(&dhcp->offered_gw_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER)));
}
- /* DNS servers */
- option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_DNS_SERVER);
- if (option_ptr != NULL) {
- u8_t n;
- dhcp->dns_count = dhcp_get_option_byte(&option_ptr[1]) / (u32_t)sizeof(struct ip_addr);
- /* limit to at most DHCP_MAX_DNS DNS servers */
- if (dhcp->dns_count > DHCP_MAX_DNS)
- dhcp->dns_count = DHCP_MAX_DNS;
- for (n = 0; n < dhcp->dns_count; n++) {
- dhcp->offered_dns_addr[n].addr = htonl(dhcp_get_option_long(&option_ptr[2 + n * 4]));
#if LWIP_DNS
- dns_setserver( n, (struct ip_addr *)(&(dhcp->offered_dns_addr[n].addr)));
-#endif /* LWIP_DNS */
- }
-#if LWIP_DNS
- dns_setserver( n, (struct ip_addr *)(&ip_addr_any));
+ /* DNS servers */
+ n = 0;
+ while(dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n) && (n < DNS_MAX_SERVERS)) {
+ ip_addr_t dns_addr;
+ ip4_addr_set_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
+ dns_setserver(n, &dns_addr);
+ n++;
+ }
#endif /* LWIP_DNS */
+}
+
+/** Set a statically allocated struct dhcp to work with.
+ * Using this prevents dhcp_start to allocate it using mem_malloc.
+ *
+ * @param netif the netif for which to set the struct dhcp
+ * @param dhcp (uninitialised) dhcp struct allocated by the application
+ */
+void
+dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
+{
+ LWIP_ASSERT("netif != NULL", netif != NULL);
+ LWIP_ASSERT("dhcp != NULL", dhcp != NULL);
+ LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL);
+
+ /* clear data structure */
+ memset(dhcp, 0, sizeof(struct dhcp));
+ /* dhcp_set_state(&dhcp, DHCP_OFF); */
+ netif->dhcp = dhcp;
+}
+
+/** Removes a struct dhcp from a netif.
+ *
+ * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the
+ * struct dhcp since the memory is passed back to the heap.
+ *
+ * @param netif the netif from which to remove the struct dhcp
+ */
+void dhcp_cleanup(struct netif *netif)
+{
+ LWIP_ASSERT("netif != NULL", netif != NULL);
+
+ if (netif->dhcp != NULL) {
+ mem_free(netif->dhcp);
+ netif->dhcp = NULL;
}
}
@@ -592,6 +634,12 @@ dhcp_start(struct netif *netif)
it is set when we succeeded starting. */
netif->flags &= ~NETIF_FLAG_DHCP;
+ /* check hwtype of the netif */
+ if ((netif->flags & NETIF_FLAG_ETHARP) == 0) {
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): No ETHARP netif\n"));
+ return ERR_ARG;
+ }
+
/* 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"));
@@ -601,7 +649,7 @@ dhcp_start(struct netif *netif)
/* no DHCP client attached yet? */
if (dhcp == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
- dhcp = mem_malloc(sizeof(struct dhcp));
+ dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
if (dhcp == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
return ERR_MEM;
@@ -616,23 +664,19 @@ dhcp_start(struct netif *netif)
udp_remove(dhcp->pcb);
}
LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL);
- LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
- dhcp->options_in == NULL && dhcp->options_in_len == 0);
+ LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL );
}
/* clear data structure */
memset(dhcp, 0, sizeof(struct dhcp));
+ /* dhcp_set_state(&dhcp, DHCP_OFF); */
/* allocate UDP PCB */
dhcp->pcb = udp_new();
if (dhcp->pcb == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
- mem_free((void *)dhcp);
- netif->dhcp = dhcp = NULL;
return ERR_MEM;
}
-#if IP_SOF_BROADCAST
- dhcp->pcb->so_options|=SOF_BROADCAST;
-#endif /* IP_SOF_BROADCAST */
+ dhcp->pcb->so_options |= 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);
@@ -663,54 +707,50 @@ dhcp_start(struct netif *netif)
void
dhcp_inform(struct netif *netif)
{
- struct dhcp *dhcp, *old_dhcp;
+ struct dhcp dhcp;
err_t result = ERR_OK;
- dhcp = mem_malloc(sizeof(struct dhcp));
- if (dhcp == NULL) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not allocate dhcp\n"));
- return;
- }
- memset(dhcp, 0, sizeof(struct dhcp));
+ struct udp_pcb *pcb;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): allocated dhcp\n"));
- dhcp->pcb = udp_new();
- if (dhcp->pcb == NULL) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb"));
- goto free_dhcp_and_return;
+ LWIP_ERROR("netif != NULL", (netif != NULL), return;);
+
+ memset(&dhcp, 0, sizeof(struct dhcp));
+ dhcp_set_state(&dhcp, DHCP_INFORM);
+
+ if ((netif->dhcp != NULL) && (netif->dhcp->pcb != NULL)) {
+ /* re-use existing pcb */
+ pcb = netif->dhcp->pcb;
+ } else {
+ pcb = udp_new();
+ if (pcb == NULL) {
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb"));
+ return;
+ }
+ dhcp.pcb = pcb;
+ dhcp.pcb->so_options |= SOF_BROADCAST;
+ udp_bind(dhcp.pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
}
- old_dhcp = netif->dhcp;
- netif->dhcp = dhcp;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
/* create and initialize the DHCP message header */
- result = dhcp_create_request(netif);
+ result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM);
if (result == ERR_OK) {
+ dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
+ dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif));
- dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
- dhcp_option_byte(dhcp, DHCP_INFORM);
-
- dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
- dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
-
- dhcp_option_trailer(dhcp);
+ dhcp_option_trailer(&dhcp);
- pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
+ pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len);
-#if IP_SOF_BROADCAST
- dhcp->pcb->so_options|=SOF_BROADCAST;
-#endif /* IP_SOF_BROADCAST */
- udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
- udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
- dhcp_delete_request(netif);
+ udp_sendto_if(pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
+ dhcp_delete_msg(&dhcp);
} else {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n"));
}
- udp_remove(dhcp->pcb);
- dhcp->pcb = NULL;
- netif->dhcp = old_dhcp;
-free_dhcp_and_return:
- mem_free((void *)dhcp);
+ if (dhcp.pcb != NULL) {
+ /* otherwise, the existing pcb was used */
+ udp_remove(dhcp.pcb);
+ }
}
/** Handle a possible change in the network configuration.
@@ -738,6 +778,12 @@ dhcp_network_changed(struct netif *netif)
break;
default:
dhcp->tries = 0;
+#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 */
dhcp_discover(netif);
break;
}
@@ -750,13 +796,14 @@ dhcp_network_changed(struct netif *netif)
* @param netif the network interface on which the reply was received
* @param addr The IP address we received a reply from
*/
-void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
+void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr)
{
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n"));
/* is a DHCP client doing an ARP check? */
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", addr->addr));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n",
+ ip4_addr_get_u32(addr)));
/* did a host respond with the address we
were offered by the DHCP server? */
if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
@@ -786,13 +833,10 @@ dhcp_decline(struct netif *netif)
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n"));
dhcp_set_state(dhcp, DHCP_BACKING_OFF);
/* create and initialize the DHCP message header */
- result = dhcp_create_request(netif);
+ result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE);
if (result == ERR_OK) {
- dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
- dhcp_option_byte(dhcp, DHCP_DECLINE);
-
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
- dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
+ dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
dhcp_option_trailer(dhcp);
/* resize pbuf to reflect true size of options */
@@ -800,7 +844,7 @@ dhcp_decline(struct netif *netif)
/* per section 4.4.4, broadcast DECLINE messages */
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
- dhcp_delete_request(netif);
+ dhcp_delete_msg(dhcp);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
} else {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
@@ -812,7 +856,7 @@ dhcp_decline(struct netif *netif)
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
return result;
}
-#endif
+#endif /* DHCP_DOES_ARP_CHECK */
/**
@@ -827,14 +871,12 @@ dhcp_discover(struct netif *netif)
err_t result = ERR_OK;
u16_t msecs;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n"));
- ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
+ ip_addr_set_any(&dhcp->offered_ip_addr);
dhcp_set_state(dhcp, DHCP_SELECTING);
/* create and initialize the DHCP message header */
- result = dhcp_create_request(netif);
+ result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER);
if (result == ERR_OK) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n"));
- dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
- dhcp_option_byte(dhcp, DHCP_DISCOVER);
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
@@ -853,7 +895,7 @@ dhcp_discover(struct netif *netif)
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
- dhcp_delete_request(netif);
+ dhcp_delete_msg(dhcp);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
} else {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n"));
@@ -882,7 +924,7 @@ dhcp_bind(struct netif *netif)
{
u32_t timeout;
struct dhcp *dhcp;
- struct ip_addr sn_mask, gw_addr;
+ ip_addr_t sn_mask, gw_addr;
LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
dhcp = netif->dhcp;
LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;);
@@ -915,30 +957,29 @@ dhcp_bind(struct netif *netif)
}
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
}
- /* copy offered network mask */
- ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
- /* subnet mask not given? */
- /* TODO: this is not a valid check. what if the network mask is 0? */
- if (sn_mask.addr == 0) {
- /* choose a safe subnet mask given the network class */
- u8_t first_octet = ip4_addr1(&sn_mask);
+ if (dhcp->subnet_mask_given) {
+ /* copy offered network mask */
+ ip_addr_copy(sn_mask, dhcp->offered_sn_mask);
+ } else {
+ /* subnet mask not given, choose a safe subnet mask given the network class */
+ u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr);
if (first_octet <= 127) {
- sn_mask.addr = htonl(0xff000000);
+ ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL));
} else if (first_octet >= 192) {
- sn_mask.addr = htonl(0xffffff00);
+ ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL));
} else {
- sn_mask.addr = htonl(0xffff0000);
+ ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL));
}
}
- ip_addr_set(&gw_addr, &dhcp->offered_gw_addr);
+ ip_addr_copy(gw_addr, dhcp->offered_gw_addr);
/* gateway address not given? */
- if (gw_addr.addr == 0) {
+ if (ip_addr_isany(&gw_addr)) {
/* copy network address */
- gw_addr.addr = (dhcp->offered_ip_addr.addr & sn_mask.addr);
+ ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask);
/* use first host address on network as gateway */
- gw_addr.addr |= htonl(0x00000001);
+ ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL));
}
#if LWIP_DHCP_AUTOIP_COOP
@@ -948,11 +989,14 @@ dhcp_bind(struct netif *netif)
}
#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));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n",
+ ip4_addr_get_u32(&dhcp->offered_ip_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));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n",
+ ip4_addr_get_u32(&sn_mask)));
netif_set_netmask(netif, &sn_mask);
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", gw_addr.addr));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n",
+ ip4_addr_get_u32(&gw_addr)));
netif_set_gw(netif, &gw_addr);
/* bring the interface up */
netif_set_up(netif);
@@ -971,28 +1015,25 @@ 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, ("dhcp_renew()\n"));
dhcp_set_state(dhcp, DHCP_RENEWING);
/* create and initialize the DHCP message header */
- result = dhcp_create_request(netif);
+ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
if (result == ERR_OK) {
-
- dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
- dhcp_option_byte(dhcp, DHCP_REQUEST);
-
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
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++);
+ if (netif->hostname != NULL) {
+ const char *p = (const char*)netif->hostname;
+ u8_t namelen = (u8_t)strlen(p);
+ if (namelen > 0) {
+ LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255);
+ dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen);
+ while (*p) {
+ dhcp_option_byte(dhcp, *p++);
+ }
}
}
#endif /* LWIP_NETIF_HOSTNAME */
@@ -1012,7 +1053,7 @@ dhcp_renew(struct netif *netif)
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
- dhcp_delete_request(netif);
+ dhcp_delete_msg(dhcp);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
} else {
@@ -1037,28 +1078,25 @@ 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);
/* create and initialize the DHCP message header */
- result = dhcp_create_request(netif);
+ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
if (result == ERR_OK) {
-
- dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
- dhcp_option_byte(dhcp, DHCP_REQUEST);
-
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
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++);
+ if (netif->hostname != NULL) {
+ const char *p = (const char*)netif->hostname;
+ u8_t namelen = (u8_t)strlen(p);
+ if (namelen > 0) {
+ LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255);
+ dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen);
+ while (*p) {
+ dhcp_option_byte(dhcp, *p++);
+ }
}
}
#endif /* LWIP_NETIF_HOSTNAME */
@@ -1077,7 +1115,7 @@ dhcp_rebind(struct netif *netif)
/* broadcast to server */
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
- dhcp_delete_request(netif);
+ dhcp_delete_msg(dhcp);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
} else {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n"));
@@ -1104,17 +1142,13 @@ dhcp_reboot(struct netif *netif)
dhcp_set_state(dhcp, DHCP_REBOOTING);
/* create and initialize the DHCP message header */
- result = dhcp_create_request(netif);
+ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
if (result == ERR_OK) {
-
- dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
- 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(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
- dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
+ dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
dhcp_option_trailer(dhcp);
@@ -1122,7 +1156,7 @@ dhcp_reboot(struct netif *netif)
/* broadcast to server */
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
- dhcp_delete_request(netif);
+ dhcp_delete_msg(dhcp);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n"));
} else {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n"));
@@ -1151,24 +1185,24 @@ dhcp_release(struct netif *netif)
/* idle DHCP client */
dhcp_set_state(dhcp, DHCP_OFF);
/* clean old DHCP offer */
- dhcp->server_ip_addr.addr = 0;
- dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0;
- dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0;
+ ip_addr_set_zero(&dhcp->server_ip_addr);
+ ip_addr_set_zero(&dhcp->offered_ip_addr);
+ ip_addr_set_zero(&dhcp->offered_sn_mask);
+ ip_addr_set_zero(&dhcp->offered_gw_addr);
+#if LWIP_DHCP_BOOTP_FILE
+ ip_addr_set_zero(&dhcp->offered_si_addr);
+#endif /* LWIP_DHCP_BOOTP_FILE */
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);
+ result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE);
if (result == ERR_OK) {
- dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
- dhcp_option_byte(dhcp, DHCP_RELEASE);
-
dhcp_option_trailer(dhcp);
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
- dhcp_delete_request(netif);
+ dhcp_delete_msg(dhcp);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
} else {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
@@ -1184,7 +1218,6 @@ dhcp_release(struct netif *netif)
netif_set_gw(netif, IP_ADDR_ANY);
netif_set_netmask(netif, IP_ADDR_ANY);
- /* TODO: netif_down(netif); */
return result;
}
@@ -1196,8 +1229,9 @@ dhcp_release(struct netif *netif)
void
dhcp_stop(struct netif *netif)
{
- struct dhcp *dhcp = netif->dhcp;
+ struct dhcp *dhcp;
LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
+ dhcp = netif->dhcp;
/* Remove the flag that says this netif is handled by DHCP. */
netif->flags &= ~NETIF_FLAG_DHCP;
@@ -1205,20 +1239,18 @@ dhcp_stop(struct netif *netif)
/* 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;
- }
+ 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;
}
- LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
- dhcp->options_in == NULL && dhcp->options_in_len == 0);
- mem_free((void *)dhcp);
- netif->dhcp = NULL;
+ LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
+ dhcp_set_state(dhcp, DHCP_OFF);
}
}
@@ -1226,8 +1258,6 @@ dhcp_stop(struct netif *netif)
* Set the DHCP state of a DHCP client.
*
* If the state changed, reset the number of tries.
- *
- * TODO: we might also want to reset the timeout here?
*/
static void
dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
@@ -1235,6 +1265,7 @@ dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
if (new_state != dhcp->state) {
dhcp->state = new_state;
dhcp->tries = 0;
+ dhcp->request_timeout = 0;
}
}
@@ -1290,84 +1321,208 @@ dhcp_option_long(struct dhcp *dhcp, u32_t value)
*
*/
static err_t
-dhcp_unfold_reply(struct dhcp *dhcp, struct pbuf *p)
+dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p)
{
- u16_t ret;
- LWIP_ERROR("dhcp != NULL", (dhcp != NULL), return ERR_ARG;);
- /* free any left-overs from previous unfolds */
- dhcp_free_reply(dhcp);
- /* options present? */
- if (p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)) {
- dhcp->options_in_len = p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
- dhcp->options_in = mem_malloc(dhcp->options_in_len);
- if (dhcp->options_in == NULL) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
- ("dhcp_unfold_reply(): could not allocate dhcp->options\n"));
- dhcp->options_in_len = 0;
- return ERR_MEM;
+ u8_t *options;
+ u16_t offset;
+ u16_t offset_max;
+ u16_t options_idx;
+ u16_t options_idx_max;
+ struct pbuf *q;
+ int parse_file_as_options = 0;
+ int parse_sname_as_options = 0;
+
+ /* clear received options */
+ dhcp_clear_all_options(dhcp);
+ /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */
+ if (p->len < DHCP_SNAME_OFS) {
+ return ERR_BUF;
+ }
+ dhcp->msg_in = (struct dhcp_msg *)p->payload;
+#if LWIP_DHCP_BOOTP_FILE
+ /* clear boot file name */
+ dhcp->boot_file_name[0] = 0;
+#endif /* LWIP_DHCP_BOOTP_FILE */
+
+ /* parse options */
+
+ /* start with options field */
+ options_idx = DHCP_OPTIONS_OFS;
+ /* parse options to the end of the received packet */
+ options_idx_max = p->tot_len;
+again:
+ q = p;
+ while((q != NULL) && (options_idx >= q->len)) {
+ options_idx -= q->len;
+ options_idx_max -= q->len;
+ q = q->next;
+ }
+ if (q == NULL) {
+ return ERR_BUF;
+ }
+ offset = options_idx;
+ offset_max = options_idx_max;
+ options = (u8_t*)q->payload;
+ /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
+ while((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) {
+ u8_t op = options[offset];
+ u8_t len;
+ u8_t decode_len = 0;
+ int decode_idx = -1;
+ u16_t val_offset = offset + 2;
+ /* len byte might be in the next pbuf */
+ if (offset + 1 < q->len) {
+ len = options[offset + 1];
+ } else {
+ len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0);
}
- }
- dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
- if (dhcp->msg_in == NULL) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
- ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n"));
- if (dhcp->options_in != NULL) {
- mem_free(dhcp->options_in);
- dhcp->options_in = NULL;
- dhcp->options_in_len = 0;
+ /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
+ decode_len = len;
+ switch(op) {
+ /* case(DHCP_OPTION_END): handled above */
+ case(DHCP_OPTION_PAD):
+ /* special option: no len encoded */
+ decode_len = len = 0;
+ /* will be increased below */
+ offset--;
+ break;
+ case(DHCP_OPTION_SUBNET_MASK):
+ LWIP_ASSERT("len == 4", len == 4);
+ decode_idx = DHCP_OPTION_IDX_SUBNET_MASK;
+ break;
+ case(DHCP_OPTION_ROUTER):
+ decode_len = 4; /* only copy the first given router */
+ LWIP_ASSERT("len >= decode_len", len >= decode_len);
+ decode_idx = DHCP_OPTION_IDX_ROUTER;
+ break;
+ case(DHCP_OPTION_DNS_SERVER):
+ /* special case: there might be more than one server */
+ LWIP_ASSERT("len % 4 == 0", len % 4 == 0);
+ /* limit number of DNS servers */
+ decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS);
+ LWIP_ASSERT("len >= decode_len", len >= decode_len);
+ decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
+ break;
+ case(DHCP_OPTION_LEASE_TIME):
+ LWIP_ASSERT("len == 4", len == 4);
+ decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
+ break;
+ case(DHCP_OPTION_OVERLOAD):
+ LWIP_ASSERT("len == 1", len == 1);
+ decode_idx = DHCP_OPTION_IDX_OVERLOAD;
+ break;
+ case(DHCP_OPTION_MESSAGE_TYPE):
+ LWIP_ASSERT("len == 1", len == 1);
+ decode_idx = DHCP_OPTION_IDX_MSG_TYPE;
+ break;
+ case(DHCP_OPTION_SERVER_ID):
+ LWIP_ASSERT("len == 4", len == 4);
+ decode_idx = DHCP_OPTION_IDX_SERVER_ID;
+ break;
+ case(DHCP_OPTION_T1):
+ LWIP_ASSERT("len == 4", len == 4);
+ decode_idx = DHCP_OPTION_IDX_T1;
+ break;
+ case(DHCP_OPTION_T2):
+ LWIP_ASSERT("len == 4", len == 4);
+ decode_idx = DHCP_OPTION_IDX_T2;
+ break;
+ default:
+ decode_len = 0;
+ LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", op));
+ break;
+ }
+ offset += len + 2;
+ if (decode_len > 0) {
+ u32_t value = 0;
+ u16_t copy_len;
+decode_next:
+ LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX);
+ LWIP_ASSERT("option already decoded", !dhcp_option_given(dhcp, decode_idx));
+ copy_len = LWIP_MIN(decode_len, 4);
+ pbuf_copy_partial(q, &value, copy_len, val_offset);
+ if (decode_len > 4) {
+ /* decode more than one u32_t */
+ LWIP_ASSERT("decode_len % 4 == 0", decode_len % 4 == 0);
+ dhcp_got_option(dhcp, decode_idx);
+ dhcp_set_option_value(dhcp, decode_idx, htonl(value));
+ decode_len -= 4;
+ val_offset += 4;
+ decode_idx++;
+ goto decode_next;
+ } else if (decode_len == 4) {
+ value = ntohl(value);
+ } else {
+ LWIP_ASSERT("invalid decode_len", decode_len == 1);
+ value = ((u8_t*)&value)[0];
+ }
+ dhcp_got_option(dhcp, decode_idx);
+ dhcp_set_option_value(dhcp, decode_idx, value);
+ }
+ if (offset >= q->len) {
+ offset -= q->len;
+ offset_max -= q->len;
+ q = q->next;
+ options = (u8_t*)q->payload;
}
- return ERR_MEM;
}
-
- /** copy the DHCP message without options */
- ret = pbuf_copy_partial(p, dhcp->msg_in, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN, 0);
- LWIP_ASSERT("ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN", ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes into dhcp->msg_in[]\n",
- sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN));
-
- if (dhcp->options_in != NULL) {
- /** copy the DHCP options */
- ret = pbuf_copy_partial(p, dhcp->options_in, dhcp->options_in_len, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
- LWIP_ASSERT("ret == dhcp->options_in_len", ret == dhcp->options_in_len);
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes to dhcp->options_in[]\n",
- dhcp->options_in_len));
+ /* is this an overloaded message? */
+ if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) {
+ u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD);
+ dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD);
+ if (overload == DHCP_OVERLOAD_FILE) {
+ parse_file_as_options = 1;
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n"));
+ } else if (overload == DHCP_OVERLOAD_SNAME) {
+ parse_sname_as_options = 1;
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n"));
+ } else if (overload == DHCP_OVERLOAD_SNAME_FILE) {
+ parse_sname_as_options = 1;
+ parse_file_as_options = 1;
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n"));
+ } else {
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload));
+ }
+#if LWIP_DHCP_BOOTP_FILE
+ if (!parse_file_as_options) {
+ /* only do this for ACK messages */
+ if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) &&
+ (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK))
+ /* copy bootp file name, don't care for sname (server hostname) */
+ pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS);
+ /* make sure the string is really NULL-terminated */
+ dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0;
+ }
+#endif /* LWIP_DHCP_BOOTP_FILE */
+ }
+ if (parse_file_as_options) {
+ /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */
+ parse_file_as_options = 0;
+ options_idx = DHCP_FILE_OFS;
+ options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN;
+ goto again;
+ } else if (parse_sname_as_options) {
+ parse_sname_as_options = 0;
+ options_idx = DHCP_SNAME_OFS;
+ options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN;
+ goto again;
}
- LWIP_UNUSED_ARG(ret);
return ERR_OK;
}
/**
- * Free the incoming DHCP message including contiguous copy of
- * its DHCP options.
- */
-static void dhcp_free_reply(struct dhcp *dhcp)
-{
- if (dhcp->msg_in != NULL) {
- mem_free((void *)dhcp->msg_in);
- dhcp->msg_in = NULL;
- }
- if (dhcp->options_in) {
- mem_free(dhcp->options_in);
- dhcp->options_in = NULL;
- dhcp->options_in_len = 0;
- }
- LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): free'd\n"));
-}
-
-/**
* If an incoming DHCP message is in response to us, then trigger the state machine
*/
-static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
+static void
+dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
{
struct netif *netif = (struct netif *)arg;
struct dhcp *dhcp = netif->dhcp;
struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
- u8_t *options_ptr;
u8_t msg_type;
u8_t i;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
- (u16_t)(ntohl(addr->addr) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff),
- (u16_t)(ntohl(addr->addr) >> 8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port));
+ ip4_addr1_16(addr), ip4_addr2_16(addr), ip4_addr3_16(addr), ip4_addr4_16(addr), port));
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
/* prevent warnings about unused arguments */
@@ -1375,11 +1530,10 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
LWIP_UNUSED_ARG(addr);
LWIP_UNUSED_ARG(port);
- LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
- dhcp->options_in == NULL && dhcp->options_in_len == 0);
+ LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
if (p->len < DHCP_MIN_REPLY_LEN) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message too short\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n"));
goto free_pbuf_and_return;
}
@@ -1403,7 +1557,7 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
goto free_pbuf_and_return;
}
/* option fields could be unfold? */
- if (dhcp_unfold_reply(dhcp, p) != ERR_OK) {
+ if (dhcp_parse_reply(dhcp, p) != ERR_OK) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
("problem unfolding DHCP message - too short on memory?\n"));
goto free_pbuf_and_return;
@@ -1411,21 +1565,19 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
/* obtain pointer to DHCP message type */
- options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE);
- if (options_ptr == NULL) {
+ if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
goto free_pbuf_and_return;
}
/* read DHCP message type */
- msg_type = dhcp_get_option_byte(options_ptr + 2);
+ msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE);
/* message type is DHCP ACK? */
if (msg_type == DHCP_ACK) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n"));
/* in requesting state? */
if (dhcp->state == DHCP_REQUESTING) {
dhcp_handle_ack(netif);
- dhcp->request_timeout = 0;
#if DHCP_DOES_ARP_CHECK
/* check if the acknowledged lease address is already in use */
dhcp_check(netif);
@@ -1436,7 +1588,6 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
}
/* already bound to the given lease address? */
else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) {
- dhcp->request_timeout = 0;
dhcp_bind(netif);
}
}
@@ -1445,7 +1596,6 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) ||
(dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n"));
- dhcp->request_timeout = 0;
dhcp_handle_nak(netif);
}
/* received a DHCP_OFFER in DHCP_SELECTING state? */
@@ -1456,7 +1606,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);
+ dhcp->msg_in = NULL;
pbuf_free(p);
}
@@ -1464,11 +1614,12 @@ free_pbuf_and_return:
* Create a DHCP request, fill in common headers
*
* @param netif the netif under DHCP control
+ * @param dhcp dhcp control struct
+ * @param message_type message type of the request
*/
static err_t
-dhcp_create_request(struct netif *netif)
+dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
{
- struct dhcp *dhcp;
u16_t i;
#ifndef DHCP_GLOBAL_XID
/** default global transaction identifier starting value (easy to match
@@ -1484,23 +1635,23 @@ dhcp_create_request(struct netif *netif)
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;);
- LWIP_ASSERT("dhcp_create_request: dhcp->p_out == NULL", dhcp->p_out == NULL);
- LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
+ LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;);
+ LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;);
+ LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL);
+ LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
if (dhcp->p_out == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
- ("dhcp_create_request(): could not allocate pbuf\n"));
+ ("dhcp_create_msg(): could not allocate pbuf\n"));
return ERR_MEM;
}
- LWIP_ASSERT("dhcp_create_request: check that first pbuf can hold struct dhcp_msg",
+ LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg",
(dhcp->p_out->len >= sizeof(struct dhcp_msg)));
/* reuse transaction identifier in retransmissions */
- if (dhcp->tries==0)
+ if (dhcp->tries == 0) {
xid++;
+ }
dhcp->xid = xid;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
("transaction id xid(%"X32_F")\n", xid));
@@ -1510,19 +1661,23 @@ dhcp_create_request(struct netif *netif)
dhcp->msg_out->op = DHCP_BOOTREQUEST;
/* TODO: make link layer independent */
dhcp->msg_out->htype = DHCP_HTYPE_ETH;
- /* TODO: make link layer independent */
- dhcp->msg_out->hlen = DHCP_HLEN_ETH;
+ dhcp->msg_out->hlen = netif->hwaddr_len;
dhcp->msg_out->hops = 0;
dhcp->msg_out->xid = htonl(dhcp->xid);
dhcp->msg_out->secs = 0;
+ /* we don't need the broadcast flag since we can receive unicast traffic
+ before being fully configured! */
dhcp->msg_out->flags = 0;
- 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;
+ ip_addr_set_zero(&dhcp->msg_out->ciaddr);
+ /* set ciaddr to netif->ip_addr based on message_type and state */
+ if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) ||
+ ((message_type == DHCP_REQUEST) && /* DHCP_BOUND not used for sending! */
+ ((dhcp->state==DHCP_RENEWING) || dhcp->state==DHCP_REBINDING))) {
+ ip_addr_copy(dhcp->msg_out->ciaddr, netif->ip_addr);
+ }
+ ip_addr_set_zero(&dhcp->msg_out->yiaddr);
+ ip_addr_set_zero(&dhcp->msg_out->siaddr);
+ ip_addr_set_zero(&dhcp->msg_out->giaddr);
for (i = 0; i < DHCP_CHADDR_LEN; i++) {
/* copy netif hardware address, pad with zeroes */
dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
@@ -1533,29 +1688,29 @@ dhcp_create_request(struct netif *netif)
for (i = 0; i < DHCP_FILE_LEN; i++) {
dhcp->msg_out->file[i] = 0;
}
- dhcp->msg_out->cookie = htonl(0x63825363UL);
+ dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
dhcp->options_out_len = 0;
/* fill options field with an incrementing array (for debugging purposes) */
for (i = 0; i < DHCP_OPTIONS_LEN; i++) {
dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */
}
+ /* Add option MESSAGE_TYPE */
+ dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
+ dhcp_option_byte(dhcp, message_type);
return ERR_OK;
}
/**
* Free previously allocated memory used to send a DHCP request.
*
- * @param netif the netif under DHCP control
+ * @param dhcp the dhcp struct to free the request from
*/
static void
-dhcp_delete_request(struct netif *netif)
+dhcp_delete_msg(struct dhcp *dhcp)
{
- struct dhcp *dhcp;
- LWIP_ERROR("dhcp_delete_request: netif != NULL", (netif != NULL), return;);
- dhcp = netif->dhcp;
- LWIP_ERROR("dhcp_delete_request: dhcp != NULL", (dhcp != NULL), return;);
- LWIP_ASSERT("dhcp_delete_request: dhcp->p_out != NULL", dhcp->p_out != NULL);
- LWIP_ASSERT("dhcp_delete_request: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
+ LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;);
+ LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL);
+ LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
if (dhcp->p_out != NULL) {
pbuf_free(dhcp->p_out);
}
@@ -1587,136 +1742,4 @@ dhcp_option_trailer(struct dhcp *dhcp)
}
}
-/**
- * Find the offset of a DHCP option inside the DHCP message.
- *
- * @param dhcp DHCP client
- * @param option_type
- *
- * @return a byte offset into the UDP message where the option was found, or
- * zero if the given option was not found.
- */
-static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
-{
- u8_t overload = DHCP_OVERLOAD_NONE;
-
- /* options available? */
- if ((dhcp->options_in != NULL) && (dhcp->options_in_len > 0)) {
- /* start with options field */
- u8_t *options = (u8_t *)dhcp->options_in;
- u16_t offset = 0;
- /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
- while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
- /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
- /* are the sname and/or file field overloaded with options? */
- if (options[offset] == DHCP_OPTION_OVERLOAD) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded message detected\n"));
- /* skip option type and length */
- offset += 2;
- overload = options[offset++];
- }
- /* requested option found */
- else if (options[offset] == option_type) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("option found at offset %"U16_F" in options\n", offset));
- return &options[offset];
- /* skip option */
- } else {
- LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", options[offset]));
- /* skip option type */
- offset++;
- /* skip option length, and then length bytes */
- offset += 1 + options[offset];
- }
- }
- /* is this an overloaded message? */
- if (overload != DHCP_OVERLOAD_NONE) {
- u16_t field_len;
- if (overload == DHCP_OVERLOAD_FILE) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n"));
- options = (u8_t *)&dhcp->msg_in->file;
- field_len = DHCP_FILE_LEN;
- } else if (overload == DHCP_OVERLOAD_SNAME) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n"));
- options = (u8_t *)&dhcp->msg_in->sname;
- field_len = DHCP_SNAME_LEN;
- /* TODO: check if else if () is necessary */
- } else {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n"));
- options = (u8_t *)&dhcp->msg_in->sname;
- field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;
- }
- offset = 0;
-
- /* at least 1 byte to read and no end marker */
- while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
- if (options[offset] == option_type) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("option found at offset=%"U16_F"\n", offset));
- return &options[offset];
- /* skip option */
- } else {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("skipping option %"U16_F"\n", options[offset]));
- /* skip option type */
- offset++;
- offset += 1 + options[offset];
- }
- }
- }
- }
- return NULL;
-}
-
-/**
- * Return the byte of DHCP option data.
- *
- * @param client DHCP client.
- * @param ptr pointer obtained by dhcp_get_option_ptr().
- *
- * @return byte value at the given address.
- */
-static u8_t
-dhcp_get_option_byte(u8_t *ptr)
-{
- LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%"U16_F"\n", (u16_t)(*ptr)));
- return *ptr;
-}
-
-#if 0 /* currently unused */
-/**
- * Return the 16-bit value of DHCP option data.
- *
- * @param client DHCP client.
- * @param ptr pointer obtained by dhcp_get_option_ptr().
- *
- * @return byte value at the given address.
- */
-static u16_t
-dhcp_get_option_short(u8_t *ptr)
-{
- u16_t value;
- value = *ptr++ << 8;
- value |= *ptr;
- LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%"U16_F"\n", value));
- return value;
-}
-#endif
-
-/**
- * Return the 32-bit value of DHCP option data.
- *
- * @param client DHCP client.
- * @param ptr pointer obtained by dhcp_get_option_ptr().
- *
- * @return byte value at the given address.
- */
-static u32_t dhcp_get_option_long(u8_t *ptr)
-{
- u32_t value;
- value = (u32_t)(*ptr++) << 24;
- value |= (u32_t)(*ptr++) << 16;
- value |= (u32_t)(*ptr++) << 8;
- value |= (u32_t)(*ptr++);
- LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%"U32_F"\n", value));
- return value;
-}
-
#endif /* LWIP_DHCP */
diff --git a/core/lwip/src/core/dns.c b/core/lwip/src/core/dns.c
index 4021d1dd..ca807c14 100644
--- a/core/lwip/src/core/dns.c
+++ b/core/lwip/src/core/dns.c
@@ -78,13 +78,14 @@
#include "lwip/udp.h"
#include "lwip/mem.h"
+#include "lwip/memp.h"
#include "lwip/dns.h"
#include <string.h>
/** DNS server IP address */
#ifndef DNS_SERVER_ADDRESS
-#define DNS_SERVER_ADDRESS inet_addr("208.67.222.222") /* resolver1.opendns.com */
+#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */
#endif
/** DNS server port address */
@@ -141,40 +142,26 @@ PACK_STRUCT_END
#endif
#define SIZEOF_DNS_HDR 12
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-/** DNS query message structure */
+/** DNS query message structure.
+ No packing needed: only used locally on the stack. */
struct dns_query {
/* DNS query record starts with either a domain name or a pointer
to a name already present somewhere in the packet. */
- 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
+ u16_t type;
+ u16_t cls;
+};
#define SIZEOF_DNS_QUERY 4
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-/** DNS answer message structure */
+/** DNS answer message structure.
+ No packing needed: only used locally on the stack. */
struct dns_answer {
/* DNS answer record starts with either a domain name or a pointer
to a name already present somewhere in the packet. */
- 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
+ u16_t type;
+ u16_t cls;
+ u32_t ttl;
+ u16_t len;
+};
#define SIZEOF_DNS_ANSWER 10
/** DNS table entry */
@@ -187,21 +174,13 @@ struct dns_table_entry {
u8_t err;
u32_t ttl;
char name[DNS_MAX_NAME_LENGTH];
- struct ip_addr ipaddr;
+ ip_addr_t ipaddr;
/* pointer to callback on DNS query done */
dns_found_callback found;
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
@@ -229,7 +208,7 @@ static void dns_init_local();
/* forward declarations */
-static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
+static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
static void dns_check_entries(void);
/*-----------------------------------------------------------------------------
@@ -240,11 +219,10 @@ static void dns_check_entries(void);
static struct udp_pcb *dns_pcb;
static u8_t dns_seqno;
static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
-static struct ip_addr dns_servers[DNS_MAX_SERVERS];
-
-#if (DNS_USES_STATIC_BUF == 1)
-static u8_t dns_payload[DNS_MSG_SIZE];
-#endif /* (DNS_USES_STATIC_BUF == 1) */
+static ip_addr_t dns_servers[DNS_MAX_SERVERS];
+/** Contiguous buffer for processing responses */
+static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)];
+static u8_t* dns_payload;
/**
* Initialize the resolver: set up the UDP pcb and configure the default server
@@ -253,10 +231,12 @@ static u8_t dns_payload[DNS_MSG_SIZE];
void
dns_init()
{
- struct ip_addr dnsserver;
+ ip_addr_t dnsserver;
+
+ dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer);
/* initialize default DNS server address */
- dnsserver.addr = DNS_SERVER_ADDRESS;
+ DNS_SERVER_ADDRESS(&dnsserver);
LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
@@ -290,7 +270,7 @@ dns_init()
* @param dnsserver IP address of the DNS server to set
*/
void
-dns_setserver(u8_t numdns, struct ip_addr *dnsserver)
+dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
{
/*
* hpa: the lwip code has the dnsserver->addr != 0 test, but that would
@@ -298,7 +278,7 @@ dns_setserver(u8_t numdns, struct ip_addr *dnsserver)
* DNS server...
*/
if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) &&
- (dnsserver != NULL) /* && (dnsserver->addr !=0) */) {
+ (dnsserver != NULL) /* && !ip_addr_isany(dnsserver) */) {
dns_servers[numdns] = (*dnsserver);
}
}
@@ -310,7 +290,7 @@ dns_setserver(u8_t numdns, struct ip_addr *dnsserver)
* @return IP address of the indexed DNS server or "ip_addr_any" if the DNS
* server has not been configured.
*/
-struct ip_addr
+ip_addr_t
dns_getserver(u8_t numdns)
{
if (numdns < DNS_MAX_SERVERS) {
@@ -342,12 +322,18 @@ dns_init_local()
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;
+ size_t namelen;
for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
- entry = mem_malloc(sizeof(struct local_hostlist_entry));
+ struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
+ LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
+ namelen = strlen(init_entry->name);
+ LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
+ entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
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->name = (char*)entry + sizeof(struct local_hostlist_entry);
+ MEMCPY((char*)entry->name, init_entry->name, namelen);
+ ((char*)entry->name)[namelen] = 0;
entry->addr = init_entry->addr;
entry->next = local_hostlist_dynamic;
local_hostlist_dynamic = entry;
@@ -361,7 +347,7 @@ dns_init_local()
*
* @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.
+ * IPADDR_NONE if not found.
*/
static u32_t
dns_lookup_local(const char *hostname)
@@ -370,7 +356,7 @@ dns_lookup_local(const char *hostname)
struct local_hostlist_entry *entry = local_hostlist_dynamic;
while(entry != NULL) {
if(strcmp(entry->name, hostname) == 0) {
- return entry->addr;
+ return ip4_addr_get_u32(&entry->addr);
}
entry = entry->next;
}
@@ -378,11 +364,11 @@ dns_lookup_local(const char *hostname)
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;
+ return ip4_addr_get_u32(&local_hostlist_static[i].addr);
}
}
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
- return INADDR_NONE;
+ return IPADDR_NONE;
}
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
@@ -395,14 +381,14 @@ dns_lookup_local(const char *hostname)
* @return the number of removed entries
*/
int
-dns_local_removehost(const char *hostname, const struct ip_addr *addr)
+dns_local_removehost(const char *hostname, const ip_addr_t *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))) {
+ ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
struct local_hostlist_entry *free_entry;
if (last_entry != NULL) {
last_entry->next = entry->next;
@@ -411,7 +397,7 @@ dns_local_removehost(const char *hostname, const struct ip_addr *addr)
}
free_entry = entry;
entry = entry->next;
- mem_free(free_entry);
+ memp_free(MEMP_LOCALHOSTLIST, free_entry);
removed++;
} else {
last_entry = entry;
@@ -430,15 +416,21 @@ dns_local_removehost(const char *hostname, const struct ip_addr *addr)
* @return ERR_OK if succeeded or ERR_MEM on memory error
*/
err_t
-dns_local_addhost(const char *hostname, const struct ip_addr *addr)
+dns_local_addhost(const char *hostname, const ip_addr_t *addr)
{
struct local_hostlist_entry *entry;
- entry = mem_malloc(sizeof(struct local_hostlist_entry));
+ size_t namelen;
+ LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
+ namelen = strlen(hostname);
+ LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
+ entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
if (entry == NULL) {
return ERR_MEM;
}
- entry->name = hostname;
- entry->addr = addr->addr;
+ entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
+ MEMCPY((char*)entry->name, hostname, namelen);
+ ((char*)entry->name)[namelen] = 0;
+ ip_addr_copy(entry->addr, *addr);
entry->next = local_hostlist_dynamic;
local_hostlist_dynamic = entry;
return ERR_OK;
@@ -455,8 +447,8 @@ dns_local_addhost(const char *hostname, const struct ip_addr *addr)
* for a hostname.
*
* @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: != INADDR_NONE) or INADDR_NONE if the hostname
+ * @return the hostname's IP address, as u32_t (instead of ip_addr_t to
+ * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname
* was not found in the cached dns_table.
*/
static u32_t
@@ -467,12 +459,12 @@ dns_lookup(const char *name)
u32_t addr;
#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
#if DNS_LOCAL_HOSTLIST
- if ((addr = dns_lookup_local(name)) != INADDR_NONE) {
+ if ((addr = dns_lookup_local(name)) != IPADDR_NONE) {
return addr;
}
#endif /* DNS_LOCAL_HOSTLIST */
#ifdef DNS_LOOKUP_LOCAL_EXTERN
- if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != INADDR_NONE) {
+ if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) {
return addr;
}
#endif /* DNS_LOOKUP_LOCAL_EXTERN */
@@ -484,11 +476,11 @@ dns_lookup(const char *name)
LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
LWIP_DEBUGF(DNS_DEBUG, ("\n"));
- return dns_table[i].ipaddr.addr;
+ return ip4_addr_get_u32(&dns_table[i].ipaddr);
}
}
- return INADDR_NONE;
+ return IPADDR_NONE;
}
#if DNS_DOES_NAME_CHECK
@@ -583,7 +575,7 @@ dns_send(u8_t numdns, const char* name, u8_t id)
LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
(u16_t)(numdns), name));
LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
- LWIP_ASSERT("dns server has no IP address set", dns_servers[numdns].addr != 0);
+ LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns]));
/* if here, we have either a new query or a retry on a previous query to process */
p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
@@ -595,7 +587,7 @@ dns_send(u8_t numdns, const char* name, u8_t id)
memset(hdr, 0, SIZEOF_DNS_HDR);
hdr->id = htons(id);
hdr->flags1 = DNS_FLAG1_RD;
- hdr->numquestions = htons(1);
+ hdr->numquestions = PP_HTONS(1);
query = (char*)hdr + SIZEOF_DNS_HDR;
pHostname = name;
--pHostname;
@@ -615,12 +607,12 @@ dns_send(u8_t numdns, const char* name, u8_t id)
*query++='\0';
/* fill dns query */
- qry.type = htons(DNS_RRTYPE_A);
- qry.class = htons(DNS_RRCLASS_IN);
- MEMCPY( query, &qry, SIZEOF_DNS_QUERY);
+ qry.type = PP_HTONS(DNS_RRTYPE_A);
+ qry.cls = PP_HTONS(DNS_RRCLASS_IN);
+ SMEMCPY(query, &qry, SIZEOF_DNS_QUERY);
/* resize pbuf to the exact dns query */
- pbuf_realloc(p, (query + SIZEOF_DNS_QUERY) - ((char*)(p->payload)));
+ pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))));
/* connect to the server for faster receiving */
udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
@@ -648,6 +640,7 @@ dns_send(u8_t numdns, const char* name, u8_t id)
static void
dns_check_entry(u8_t i)
{
+ err_t err;
struct dns_table_entry *pEntry = &dns_table[i];
LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
@@ -662,14 +655,18 @@ dns_check_entry(u8_t i)
pEntry->retries = 0;
/* send DNS packet for this entry */
- dns_send(pEntry->numdns, pEntry->name, i);
+ err = dns_send(pEntry->numdns, pEntry->name, i);
+ if (err != ERR_OK) {
+ LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ ("dns_send returned error: %s\n", lwip_strerr(err)));
+ }
break;
}
case DNS_STATE_ASKING: {
if (--pEntry->tmr == 0) {
if (++pEntry->retries == DNS_MAX_RETRIES) {
- if ((pEntry->numdns+1<DNS_MAX_SERVERS) && (dns_servers[pEntry->numdns+1].addr!=0)) {
+ if ((pEntry->numdns+1<DNS_MAX_SERVERS) && !ip_addr_isany(&dns_servers[pEntry->numdns+1])) {
/* change of server */
pEntry->numdns++;
pEntry->tmr = 1;
@@ -691,7 +688,11 @@ dns_check_entry(u8_t i)
pEntry->tmr = pEntry->retries;
/* send DNS packet for this entry */
- dns_send(pEntry->numdns, pEntry->name, i);
+ err = dns_send(pEntry->numdns, pEntry->name, i);
+ if (err != ERR_OK) {
+ LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ ("dns_send returned error: %s\n", lwip_strerr(err)));
+ }
}
break;
}
@@ -734,20 +735,14 @@ dns_check_entries(void)
* @params see udp.h
*/
static void
-dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
+dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
{
- u8_t i;
+ u16_t i;
char *pHostname;
struct dns_hdr *hdr;
struct dns_answer ans;
struct dns_table_entry *pEntry;
- u8_t nquestions, nanswers;
-#if (DNS_USES_STATIC_BUF == 0)
- u8_t dns_payload[DNS_MSG_SIZE];
-#endif /* (DNS_USES_STATIC_BUF == 0) */
-#if (DNS_USES_STATIC_BUF == 2)
- u8_t* dns_payload;
-#endif /* (DNS_USES_STATIC_BUF == 2) */
+ u16_t nquestions, nanswers;
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(pcb);
@@ -758,24 +753,15 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
if (p->tot_len > DNS_MSG_SIZE) {
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
/* free pbuf and return */
- goto memerr1;
+ goto memerr;
}
/* is the dns message big enough ? */
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;
- }
-
-#if (DNS_USES_STATIC_BUF == 2)
- dns_payload = mem_malloc(p->tot_len);
- if (dns_payload == NULL) {
- LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: mem_malloc error\n"));
- /* free pbuf and return */
- goto memerr1;
+ goto memerr;
}
-#endif /* (DNS_USES_STATIC_BUF == 2) */
/* copy dns payload inside static buffer for processing */
if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) {
@@ -813,20 +799,21 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
/* Skip the name in the "question" part */
pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
- while(nanswers > 0) {
+ 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_DNS_ANSWER);
- if((ntohs(ans.type) == DNS_RRTYPE_A) && (ntohs(ans.class) == DNS_RRCLASS_IN) && (ntohs(ans.len) == sizeof(struct ip_addr)) ) {
+ SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
+ if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) &&
+ (ans.len == PP_HTONS(sizeof(ip_addr_t))) ) {
/* read the answer resource record's TTL, and maximize it if needed */
pEntry->ttl = ntohl(ans.ttl);
if (pEntry->ttl > DNS_MAX_TTL) {
pEntry->ttl = DNS_MAX_TTL;
}
/* read the IP address after answer resource record's header */
- MEMCPY( &(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(struct ip_addr));
+ SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t));
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
LWIP_DEBUGF(DNS_DEBUG, ("\n"));
@@ -835,7 +822,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
(*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
}
/* deallocate memory and return */
- goto memerr2;
+ goto memerr;
} else {
pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
}
@@ -849,7 +836,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
}
/* deallocate memory and return */
- goto memerr2;
+ goto memerr;
responseerr:
/* ERROR: call specified callback function with NULL as name to indicate an error */
@@ -860,13 +847,7 @@ responseerr:
pEntry->state = DNS_STATE_UNUSED;
pEntry->found = NULL;
-memerr2:
-#if (DNS_USES_STATIC_BUF == 2)
- /* free dns buffer */
- mem_free(dns_payload);
-#endif /* (DNS_USES_STATIC_BUF == 2) */
-
-memerr1:
+memerr:
/* free pbuf */
pbuf_free(p);
return;
@@ -886,6 +867,7 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
u8_t i;
u8_t lseq, lseqi;
struct dns_table_entry *pEntry = NULL;
+ size_t namelen;
/* search an unused entry, or the oldest one */
lseq = lseqi = 0;
@@ -925,7 +907,9 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
pEntry->seqno = dns_seqno++;
pEntry->found = found;
pEntry->arg = callback_arg;
- strcpy(pEntry->name, name);
+ namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1);
+ MEMCPY(pEntry->name, name, namelen);
+ pEntry->name[namelen] = 0;
/* force to send query without waiting timer */
dns_check_entry(i);
@@ -943,9 +927,10 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
* name is already in the local names table.
* - ERR_INPROGRESS enqueue a request to be sent to the DNS server
* for resolution if no errors are present.
+ * - ERR_ARG: dns client not initialized or invalid hostname
*
* @param hostname the hostname that is to be queried
- * @param addr pointer to a struct ip_addr where to store the address if it is already
+ * @param addr pointer to a ip_addr_t where to store the address if it is already
* cached in the dns_table (only valid if ERR_OK is returned!)
* @param found a callback function to be called on success, failure or timeout (only if
* ERR_INPROGRESS is returned!)
@@ -953,28 +938,33 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
* @return a err_t return code.
*/
err_t
-dns_gethostbyname(const char *hostname, struct ip_addr *addr, dns_found_callback found,
+dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
void *callback_arg)
{
+ u32_t ipaddr;
/* not initialized or no valid server yet, or invalid addr pointer
* or invalid hostname or invalid hostname length */
if ((dns_pcb == NULL) || (addr == NULL) ||
(!hostname) || (!hostname[0]) ||
(strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
- return ERR_VAL;
+ return ERR_ARG;
}
#if LWIP_HAVE_LOOPIF
- if (strcmp(hostname,"localhost")==0) {
- addr->addr = htonl(INADDR_LOOPBACK);
+ if (strcmp(hostname, "localhost")==0) {
+ ip_addr_set_loopback(addr);
return ERR_OK;
}
#endif /* LWIP_HAVE_LOOPIF */
- /* 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)) != INADDR_NONE)) {
+ /* host name already in octet notation? set ip addr and return ERR_OK */
+ ipaddr = ipaddr_addr(hostname);
+ if (ipaddr == IPADDR_NONE) {
+ /* already have this address cached? */
+ ipaddr = dns_lookup(hostname);
+ }
+ if (ipaddr != IPADDR_NONE) {
+ ip4_addr_set_u32(addr, ipaddr);
return ERR_OK;
}
diff --git a/core/lwip/src/core/init.c b/core/lwip/src/core/init.c
index 775010ac..36038350 100644
--- a/core/lwip/src/core/init.c
+++ b/core/lwip/src/core/init.c
@@ -49,11 +49,12 @@
#include "lwip/ip.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
-#include "lwip/tcp.h"
+#include "lwip/tcp_impl.h"
#include "lwip/snmp_msg.h"
#include "lwip/autoip.h"
#include "lwip/igmp.h"
#include "lwip/dns.h"
+#include "lwip/timers.h"
#include "netif/etharp.h"
/* Compile-time sanity checks for configuration errors.
@@ -80,12 +81,12 @@
#if (!LWIP_UDP && LWIP_IGMP)
#error "If you want to use IGMP, you have to define LWIP_UDP=1 in your lwipopts.h"
#endif
+#if (!LWIP_UDP && LWIP_SNMP)
+ #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h"
+#endif
#if (!LWIP_UDP && LWIP_DNS)
#error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
#endif
-#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
- #error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h"
-#endif
#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
#error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
#endif
@@ -104,6 +105,9 @@
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
#endif
+#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
+ #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
+#endif
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
#endif
@@ -113,9 +117,6 @@
#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
#error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
#endif
-#if (PPP_SUPPORT && (NO_SYS==1))
- #error "If you want to use PPP, you have to define NO_SYS=0 in your lwipopts.h"
-#endif
#if (LWIP_NETIF_API && (NO_SYS==1))
#error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
#endif
@@ -147,7 +148,7 @@
#error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
#endif
/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
-#if ((NO_SYS==0) && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT)))
+#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT))
#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
#endif
#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
@@ -171,6 +172,21 @@
#if PPP_SUPPORT && !PPPOS_SUPPORT & !PPPOE_SUPPORT
#error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on"
#endif
+#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
+ #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
+#endif
+#if LWIP_IGMP && !defined(LWIP_RAND)
+ #error "When using IGMP, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value"
+#endif
+#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
+ #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
+#endif
+#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE
+ #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets"
+#endif
+#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF
+ #error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues"
+#endif
/* Compile-time checks for deprecated options.
@@ -193,11 +209,6 @@
#ifdef ETHARP_ALWAYS_INSERT
#error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
#endif
-#if SO_REUSE
-/* I removed the lot since this was an ugly hack. It broke the raw-API.
- It also came with many ugly goto's, Christiaan Simons. */
- #error "SO_REUSE currently unavailable, this was a hack"
-#endif
#ifdef LWIP_DEBUG
static void
@@ -215,13 +226,28 @@ lwip_sanity_check(void)
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly\n"));
if (TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF/TCP_MSS)))
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work\n"));
- if (TCP_SNDLOWAT > TCP_SND_BUF)
- LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than or equal to TCP_SND_BUF.\n"));
+ if (TCP_SNDLOWAT >= TCP_SND_BUF)
+ LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF.\n"));
+ if (TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN)
+ LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN.\n"));
if (TCP_WND > (PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE))
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE\n"));
if (TCP_WND < TCP_MSS)
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is smaller than MSS\n"));
#endif /* LWIP_TCP */
+#if LWIP_SOCKET
+ /* Check that the SO_* socket options and SOF_* lwIP-internal flags match */
+ if (SO_ACCEPTCONN != SOF_ACCEPTCONN)
+ LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: SO_ACCEPTCONN != SOF_ACCEPTCONN\n"));
+ if (SO_REUSEADDR != SOF_REUSEADDR)
+ LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: SO_REUSEADDR != SOF_REUSEADDR\n"));
+ if (SO_KEEPALIVE != SOF_KEEPALIVE)
+ LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: SO_KEEPALIVE != SOF_KEEPALIVE\n"));
+ if (SO_BROADCAST != SOF_BROADCAST)
+ LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: SO_BROADCAST != SOF_BROADCAST\n"));
+ if (SO_LINGER != SOF_LINGER)
+ LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: SO_LINGER != SOF_LINGER\n"));
+#endif /* LWIP_SOCKET */
}
#else /* LWIP_DEBUG */
#define lwip_sanity_check()
@@ -238,7 +264,9 @@ lwip_init(void)
/* Modules initialization */
stats_init();
+#if !NO_SYS
sys_init();
+#endif /* !NO_SYS */
lwip_mem_init();
memp_init();
pbuf_init();
@@ -271,4 +299,8 @@ lwip_init(void)
#if LWIP_DNS
dns_init();
#endif /* LWIP_DNS */
+
+#if LWIP_TIMERS
+ sys_timeouts_init();
+#endif /* LWIP_TIMERS */
}
diff --git a/core/lwip/src/core/ipv4/autoip.c b/core/lwip/src/core/ipv4/autoip.c
index 7aa7cea5..92bb4591 100644
--- a/core/lwip/src/core/ipv4/autoip.c
+++ b/core/lwip/src/core/ipv4/autoip.c
@@ -108,7 +108,7 @@
static void autoip_handle_arp_conflict(struct netif *netif);
/* creates a pseudo random LL IP-Address for a network interface */
-static void autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr);
+static void autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr);
/* sends an ARP probe */
static err_t autoip_arp_probe(struct netif *netif);
@@ -131,6 +131,36 @@ autoip_init(void)
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_init()\n"));
}
+/** Set a statically allocated struct autoip to work with.
+ * Using this prevents autoip_start to allocate it using mem_malloc.
+ *
+ * @param netif the netif for which to set the struct autoip
+ * @param dhcp (uninitialised) dhcp struct allocated by the application
+ */
+void
+autoip_set_struct(struct netif *netif, struct autoip *autoip)
+{
+ LWIP_ASSERT("netif != NULL", netif != NULL);
+ LWIP_ASSERT("autoip != NULL", autoip != NULL);
+ LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL);
+
+ /* clear data structure */
+ memset(autoip, 0, sizeof(struct autoip));
+ /* autoip->state = AUTOIP_STATE_OFF; */
+ netif->autoip = autoip;
+}
+
+/** Restart AutoIP client and check the next address (conflict detected)
+ *
+ * @param netif The netif under AutoIP control
+ */
+static void
+autoip_restart(struct netif *netif)
+{
+ netif->autoip->tried_llipaddr++;
+ autoip_start(netif);
+}
+
/**
* Handle a IP address conflict after an ARP conflict detection
*/
@@ -149,7 +179,7 @@ autoip_handle_arp_conflict(struct netif *netif)
("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
/* TODO: close all TCP sessions */
- autoip_start(netif);
+ autoip_restart(netif);
} else {
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
@@ -160,7 +190,7 @@ autoip_handle_arp_conflict(struct netif *netif)
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_handle_arp_conflict(): we do not defend, retreating\n"));
/* TODO: close all TCP sessions */
- autoip_start(netif);
+ autoip_restart(netif);
}
}
@@ -171,7 +201,7 @@ autoip_handle_arp_conflict(struct netif *netif)
* @param ipaddr ip address to initialize
*/
static void
-autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr)
+autoip_create_addr(struct netif *netif, ip_addr_t *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
@@ -190,11 +220,12 @@ autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr)
}
LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
(addr <= AUTOIP_RANGE_END));
- ipaddr->addr = htonl(addr);
+ ip4_addr_set_u32(ipaddr, htonl(addr));
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
- ("autoip_create_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n",
- (u16_t)(netif->autoip->tried_llipaddr), (u32_t)(ipaddr->addr)));
+ ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr),
+ ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
}
/**
@@ -232,11 +263,13 @@ static err_t
autoip_bind(struct netif *netif)
{
struct autoip *autoip = netif->autoip;
- struct ip_addr sn_mask, gw_addr;
+ ip_addr_t sn_mask, gw_addr;
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
- ("autoip_bind(netif=%p) %c%c%"U16_F" 0x%08"X32_F"\n",
- (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, autoip->llipaddr.addr));
+ ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num,
+ ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
+ ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
IP4_ADDR(&sn_mask, 255, 255, 0, 0);
IP4_ADDR(&gw_addr, 0, 0, 0, 0);
@@ -269,9 +302,9 @@ autoip_start(struct netif *netif)
/* Set IP-Address, Netmask and Gateway to 0 to make sure that
* ARP Packets are formed correctly
*/
- netif->ip_addr.addr = 0;
- netif->netmask.addr = 0;
- netif->gw.addr = 0;
+ ip_addr_set_zero(&netif->ip_addr);
+ ip_addr_set_zero(&netif->netmask);
+ ip_addr_set_zero(&netif->gw);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
@@ -280,13 +313,13 @@ autoip_start(struct netif *netif)
/* no AutoIP client attached yet? */
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
("autoip_start(): starting new AUTOIP client\n"));
- autoip = mem_malloc(sizeof(struct autoip));
+ autoip = (struct autoip *)mem_malloc(sizeof(struct autoip));
if(autoip == NULL) {
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
("autoip_start(): could not allocate autoip\n"));
return ERR_MEM;
}
- memset( autoip, 0, sizeof(struct autoip));
+ memset(autoip, 0, sizeof(struct autoip));
/* store this AutoIP client in the netif */
netif->autoip = autoip;
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
@@ -294,12 +327,11 @@ autoip_start(struct netif *netif)
autoip->state = AUTOIP_STATE_OFF;
autoip->ttw = 0;
autoip->sent_num = 0;
- memset(&autoip->llipaddr, 0, sizeof(struct ip_addr));
+ ip_addr_set_zero(&autoip->llipaddr);
autoip->lastconflict = 0;
}
autoip_create_addr(netif, &(autoip->llipaddr));
- autoip->tried_llipaddr++;
autoip_start_probing(netif);
return result;
@@ -312,6 +344,10 @@ autoip_start_probing(struct netif *netif)
autoip->state = AUTOIP_STATE_PROBING;
autoip->sent_num = 0;
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
+ ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
/* time to wait to first probe, this is randomly
* choosen out of 0 to PROBE_WAIT seconds.
@@ -385,6 +421,10 @@ autoip_tmr()
netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
netif->autoip->sent_num = 0;
netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
+ ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
} else {
autoip_arp_probe(netif);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
@@ -422,6 +462,10 @@ autoip_tmr()
netif->autoip->state = AUTOIP_STATE_BOUND;
netif->autoip->sent_num = 0;
netif->autoip->ttw = 0;
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
+ ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
}
}
break;
@@ -448,20 +492,15 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
* when probing ip.dst == llipaddr && hw.src != netif->hwaddr
* we have a conflict and must solve it
*/
- struct ip_addr sipaddr, dipaddr;
+ ip_addr_t sipaddr, dipaddr;
struct eth_addr netifaddr;
- netifaddr.addr[0] = netif->hwaddr[0];
- netifaddr.addr[1] = netif->hwaddr[1];
- netifaddr.addr[2] = netif->hwaddr[2];
- netifaddr.addr[3] = netif->hwaddr[3];
- netifaddr.addr[4] = netif->hwaddr[4];
- netifaddr.addr[5] = netif->hwaddr[5];
+ ETHADDR16_COPY(netifaddr.addr, netif->hwaddr);
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
* structure packing (not using structure copy which breaks strict-aliasing rules).
*/
- SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
- SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
+ IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
+ IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
@@ -477,7 +516,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
!eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
("autoip_arp_reply(): Probe Conflict detected\n"));
- autoip_start(netif);
+ autoip_restart(netif);
}
} else {
/* RFC 3927 Section 2.5:
diff --git a/core/lwip/src/core/ipv4/icmp.c b/core/lwip/src/core/ipv4/icmp.c
index b97a587a..32902a52 100644
--- a/core/lwip/src/core/ipv4/icmp.c
+++ b/core/lwip/src/core/ipv4/icmp.c
@@ -44,7 +44,6 @@
#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
#include "lwip/icmp.h"
-#include "lwip/inet.h"
#include "lwip/inet_chksum.h"
#include "lwip/ip.h"
#include "lwip/def.h"
@@ -83,14 +82,13 @@ icmp_input(struct pbuf *p, struct netif *inp)
#endif /* LWIP_DEBUG */
struct icmp_echo_hdr *iecho;
struct ip_hdr *iphdr;
- struct ip_addr tmpaddr;
s16_t hlen;
ICMP_STATS_INC(icmp.recv);
snmp_inc_icmpinmsgs();
- iphdr = p->payload;
+ iphdr = (struct ip_hdr *)p->payload;
hlen = IPH_HL(iphdr) * 4;
if (pbuf_header(p, -hlen) || (p->tot_len < sizeof(u16_t)*2)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
@@ -102,19 +100,23 @@ icmp_input(struct pbuf *p, struct netif *inp)
code = *(((u8_t *)p->payload)+1);
#endif /* LWIP_DEBUG */
switch (type) {
+ case ICMP_ER:
+ /* This is OK, echo reply might have been parsed by a raw PCB
+ (as obviously, an echo request has been sent, too). */
+ break;
case ICMP_ECHO:
#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
{
int accepted = 1;
#if !LWIP_MULTICAST_PING
/* multicast destination address? */
- if (ip_addr_ismulticast(&iphdr->dest)) {
+ if (ip_addr_ismulticast(&current_iphdr_dest)) {
accepted = 0;
}
#endif /* LWIP_MULTICAST_PING */
#if !LWIP_BROADCAST_PING
/* broadcast destination address? */
- if (ip_addr_isbroadcast(&iphdr->dest, inp)) {
+ if (ip_addr_isbroadcast(&current_iphdr_dest, inp)) {
accepted = 0;
}
#endif /* LWIP_BROADCAST_PING */
@@ -163,7 +165,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0);
goto memerr;
}
- iphdr = r->payload;
+ iphdr = (struct ip_hdr *)r->payload;
/* switch r->payload back to icmp header */
if (pbuf_header(r, -hlen)) {
LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0);
@@ -184,16 +186,15 @@ icmp_input(struct pbuf *p, struct netif *inp)
/* 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. */
- iecho = p->payload;
- tmpaddr.addr = iphdr->src.addr;
- iphdr->src.addr = iphdr->dest.addr;
- iphdr->dest.addr = tmpaddr.addr;
+ iecho = (struct icmp_echo_hdr *)p->payload;
+ ip_addr_copy(iphdr->src, *ip_current_dest_addr());
+ ip_addr_copy(iphdr->dest, *ip_current_src_addr());
ICMPH_TYPE_SET(iecho, ICMP_ER);
/* adjust the checksum */
- if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {
- iecho->chksum += htons(ICMP_ECHO << 8) + 1;
+ if (iecho->chksum >= PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
+ iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
} else {
- iecho->chksum += htons(ICMP_ECHO << 8);
+ iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
}
/* Set the correct TTL and recalculate the header checksum. */
@@ -213,7 +214,8 @@ icmp_input(struct pbuf *p, struct netif *inp)
LWIP_ASSERT("Can't move over header in packet", 0);
} else {
err_t ret;
- ret = ip_output_if(p, &(iphdr->src), IP_HDRINCL,
+ /* send an ICMP packet, src addr is the dest addr of the curren packet */
+ ret = ip_output_if(p, ip_current_dest_addr(), IP_HDRINCL,
ICMP_TTL, 0, IP_PROTO_ICMP, inp);
if (ret != ERR_OK) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret));
@@ -288,6 +290,7 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
struct ip_hdr *iphdr;
/* we can use the echo header here */
struct icmp_echo_hdr *icmphdr;
+ ip_addr_t iphdr_src;
/* ICMP header + IP header + 8 bytes of data */
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
@@ -299,14 +302,14 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
LWIP_ASSERT("check that first pbuf can hold icmp message",
(q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
- iphdr = p->payload;
+ iphdr = (struct ip_hdr *)p->payload;
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
- icmphdr = q->payload;
+ icmphdr = (struct icmp_echo_hdr *)q->payload;
icmphdr->type = type;
icmphdr->code = code;
icmphdr->id = 0;
@@ -324,7 +327,8 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpouttimeexcds();
- ip_output(q, NULL, &(iphdr->src), ICMP_TTL, 0, IP_PROTO_ICMP);
+ ip_addr_copy(iphdr_src, iphdr->src);
+ ip_output(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q);
}
diff --git a/core/lwip/src/core/ipv4/igmp.c b/core/lwip/src/core/ipv4/igmp.c
index 7c07bc46..4e4405e1 100644
--- a/core/lwip/src/core/ipv4/igmp.c
+++ b/core/lwip/src/core/ipv4/igmp.c
@@ -86,7 +86,6 @@ Steve Reynolds
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/ip.h"
-#include "lwip/inet.h"
#include "lwip/inet_chksum.h"
#include "lwip/netif.h"
#include "lwip/icmp.h"
@@ -96,13 +95,60 @@ Steve Reynolds
#include "string.h"
-/*-----------------------------------------------------------------------------
- * Globales
- *----------------------------------------------------------------------------*/
+/*
+ * IGMP constants
+ */
+#define IGMP_TTL 1
+#define IGMP_MINLEN 8
+#define ROUTER_ALERT 0x9404U
+#define ROUTER_ALERTLEN 4
+
+/*
+ * IGMP message types, including version number.
+ */
+#define IGMP_MEMB_QUERY 0x11 /* Membership query */
+#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */
+#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */
+#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */
+
+/* Group membership states */
+#define IGMP_GROUP_NON_MEMBER 0
+#define IGMP_GROUP_DELAYING_MEMBER 1
+#define IGMP_GROUP_IDLE_MEMBER 2
+
+/**
+ * IGMP packet format.
+ */
+#ifdef PACK_STRUCT_USE_INCLUDES
+# include "arch/bpstruct.h"
+#endif
+PACK_STRUCT_BEGIN
+struct igmp_msg {
+ PACK_STRUCT_FIELD(u8_t igmp_msgtype);
+ PACK_STRUCT_FIELD(u8_t igmp_maxresp);
+ PACK_STRUCT_FIELD(u16_t igmp_checksum);
+ PACK_STRUCT_FIELD(ip_addr_p_t igmp_group_address);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+#ifdef PACK_STRUCT_USE_INCLUDES
+# include "arch/epstruct.h"
+#endif
+
+
+static struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr);
+static err_t igmp_remove_group(struct igmp_group *group);
+static void igmp_timeout( struct igmp_group *group);
+static void igmp_start_timer(struct igmp_group *group, u8_t max_time);
+static void igmp_stop_timer(struct igmp_group *group);
+static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp);
+static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif);
+static void igmp_send(struct igmp_group *group, u8_t type);
+
static struct igmp_group* igmp_group_list;
-static struct ip_addr allsystems;
-static struct ip_addr allrouters;
+static ip_addr_t allsystems;
+static ip_addr_t allrouters;
+
/**
* Initialize the IGMP module
@@ -128,7 +174,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 %p\n", group->interface));
+ LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif));
group = group->next;
}
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
@@ -160,7 +206,7 @@ igmp_start(struct netif *netif)
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD "));
ip_addr_debug_print(IGMP_DEBUG, &allsystems);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
- netif->igmp_mac_filter( netif, &allsystems, IGMP_ADD_MAC_FILTER);
+ netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER);
}
return ERR_OK;
@@ -185,7 +231,7 @@ igmp_stop(struct netif *netif)
while (group != NULL) {
next = group->next;
/* is it a group joined on this interface? */
- if (group->interface == netif) {
+ if (group->netif == netif) {
/* is it the first group of the list? */
if (group == igmp_group_list) {
igmp_group_list = next;
@@ -219,15 +265,15 @@ igmp_stop(struct netif *netif)
* @param netif network interface on which report IGMP memberships
*/
void
-igmp_report_groups( struct netif *netif)
+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 %p\n", netif));
while (group != NULL) {
- if (group->interface == netif) {
- igmp_delaying_member( group, IGMP_JOIN_DELAYING_MEMBER_TMR);
+ if (group->netif == netif) {
+ igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
}
group = group->next;
}
@@ -242,12 +288,12 @@ igmp_report_groups( struct netif *netif)
* NULL if the group wasn't found.
*/
struct igmp_group *
-igmp_lookfor_group(struct netif *ifp, struct ip_addr *addr)
+igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr)
{
struct igmp_group *group = igmp_group_list;
while (group != NULL) {
- if ((group->interface == ifp) && (ip_addr_cmp(&(group->group_address), addr))) {
+ if ((group->netif == ifp) && (ip_addr_cmp(&(group->group_address), addr))) {
return group;
}
group = group->next;
@@ -268,7 +314,7 @@ igmp_lookfor_group(struct netif *ifp, struct ip_addr *addr)
* NULL on memory error.
*/
struct igmp_group *
-igmp_lookup_group(struct netif *ifp, struct ip_addr *addr)
+igmp_lookup_group(struct netif *ifp, ip_addr_t *addr)
{
struct igmp_group *group = igmp_group_list;
@@ -280,9 +326,9 @@ igmp_lookup_group(struct netif *ifp, struct ip_addr *addr)
}
/* Group doesn't exist yet, create a new one */
- group = memp_malloc(MEMP_IGMP_GROUP);
+ group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP);
if (group != NULL) {
- group->interface = ifp;
+ group->netif = ifp;
ip_addr_set(&(group->group_address), addr);
group->timer = 0; /* Not running */
group->group_state = IGMP_GROUP_NON_MEMBER;
@@ -306,7 +352,7 @@ igmp_lookup_group(struct netif *ifp, struct ip_addr *addr)
* @param group the group to remove from the global igmp_group_list
* @return ERR_OK if group was removed from the list, an err_t otherwise
*/
-err_t
+static err_t
igmp_remove_group(struct igmp_group *group)
{
err_t err = ERR_OK;
@@ -341,15 +387,17 @@ igmp_remove_group(struct igmp_group *group)
* @param dest destination ip address of the igmp packet
*/
void
-igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
+igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)
{
struct ip_hdr * iphdr;
struct igmp_msg* igmp;
struct igmp_group* group;
struct igmp_group* groupref;
+ IGMP_STATS_INC(igmp.recv);
+
/* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */
- iphdr = p->payload;
+ iphdr = (struct ip_hdr *)p->payload;
if (pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4)) || (p->len < IGMP_MINLEN)) {
pbuf_free(p);
IGMP_STATS_INC(igmp.lenerr);
@@ -373,11 +421,12 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
}
/* Packet is ok so find an existing group */
- group = igmp_lookfor_group(inp, dest); /* use the incoming IP address! */
+ group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */
/* If group can be found or create... */
if (!group) {
pbuf_free(p);
+ IGMP_STATS_INC(igmp.drop);
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n"));
return;
}
@@ -386,50 +435,56 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
switch (igmp->igmp_msgtype) {
case IGMP_MEMB_QUERY: {
/* IGMP_MEMB_QUERY to the "all systems" address ? */
- if ((ip_addr_cmp(dest, &allsystems)) && (igmp->igmp_group_address.addr == 0)) {
+ if ((ip_addr_cmp(dest, &allsystems)) && ip_addr_isany(&igmp->igmp_group_address)) {
/* THIS IS THE GENERAL QUERY */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
if (igmp->igmp_maxresp == 0) {
- IGMP_STATS_INC(igmp.v1_rxed);
+ IGMP_STATS_INC(igmp.rx_v1);
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n"));
igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR;
+ } else {
+ IGMP_STATS_INC(igmp.rx_general);
}
- IGMP_STATS_INC(igmp.group_query_rxed);
groupref = igmp_group_list;
while (groupref) {
/* Do not send messages on the all systems group address! */
- if ((groupref->interface == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) {
- igmp_delaying_member( groupref, igmp->igmp_maxresp);
+ if ((groupref->netif == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) {
+ igmp_delaying_member(groupref, igmp->igmp_maxresp);
}
groupref = groupref->next;
}
} else {
/* IGMP_MEMB_QUERY to a specific group ? */
- if (group->group_address.addr != 0) {
+ if (!ip_addr_isany(&igmp->igmp_group_address)) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group "));
- ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
- if (ip_addr_cmp (dest, &allsystems)) {
+ ip_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address);
+ if (ip_addr_cmp(dest, &allsystems)) {
+ ip_addr_t groupaddr;
LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
- /* we first need to re-lookfor the group since we used dest last time */
- group = igmp_lookfor_group(inp, &igmp->igmp_group_address);
+ /* we first need to re-look for the group since we used dest last time */
+ ip_addr_copy(groupaddr, igmp->igmp_group_address);
+ group = igmp_lookfor_group(inp, &groupaddr);
} else {
LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
}
if (group != NULL) {
- IGMP_STATS_INC(igmp.unicast_query);
- igmp_delaying_member( group, igmp->igmp_maxresp);
+ IGMP_STATS_INC(igmp.rx_group);
+ igmp_delaying_member(group, igmp->igmp_maxresp);
+ } else {
+ IGMP_STATS_INC(igmp.drop);
}
+ } else {
+ IGMP_STATS_INC(igmp.proterr);
}
}
break;
}
case IGMP_V2_MEMB_REPORT: {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n"));
-
- IGMP_STATS_INC(igmp.report_rxed);
+ IGMP_STATS_INC(igmp.rx_report);
if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
/* This is on a specific group we have already looked up */
group->timer = 0; /* stopped */
@@ -440,7 +495,8 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
}
default: {
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));
+ igmp->igmp_msgtype, group->group_state, &group, group->netif));
+ IGMP_STATS_INC(igmp.proterr);
break;
}
}
@@ -457,7 +513,7 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
* @return ERR_OK if group was joined on the netif(s), an err_t otherwise
*/
err_t
-igmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
+igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)
{
err_t err = ERR_VAL; /* no matching interface */
struct igmp_group *group;
@@ -493,7 +549,7 @@ igmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER);
}
- IGMP_STATS_INC(igmp.join_sent);
+ IGMP_STATS_INC(igmp.tx_join);
igmp_send(group, IGMP_V2_MEMB_REPORT);
igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
@@ -527,7 +583,7 @@ igmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
* @return ERR_OK if group was left on the netif(s), an err_t otherwise
*/
err_t
-igmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
+igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)
{
err_t err = ERR_VAL; /* no matching interface */
struct igmp_group *group;
@@ -556,7 +612,7 @@ igmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
/* If we are the last reporter for this group */
if (group->last_reporter_flag) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n"));
- IGMP_STATS_INC(igmp.leave_sent);
+ IGMP_STATS_INC(igmp.tx_leave);
igmp_send(group, IGMP_LEAVE_GROUP);
}
@@ -602,8 +658,8 @@ igmp_tmr(void)
struct igmp_group *group = igmp_group_list;
while (group != NULL) {
- if (group->timer != 0) {
- group->timer -= 1;
+ if (group->timer > 0) {
+ group->timer--;
if (group->timer == 0) {
igmp_timeout(group);
}
@@ -618,15 +674,16 @@ igmp_tmr(void)
*
* @param group an igmp_group for which a timeout is reached
*/
-void
+static void
igmp_timeout(struct igmp_group *group)
{
/* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this 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 %p\n", group->interface));
+ LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif));
+ IGMP_STATS_INC(igmp.tx_report);
igmp_send(group, IGMP_V2_MEMB_REPORT);
}
}
@@ -638,13 +695,15 @@ igmp_timeout(struct igmp_group *group)
* @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with
* every call to igmp_tmr())
*/
-void
+static void
igmp_start_timer(struct igmp_group *group, u8_t max_time)
{
- /**
- * @todo Important !! this should be random 0 -> max_time. Find out how to do this
- */
- group->timer = max_time;
+ /* ensure the input value is > 0 */
+ if (max_time == 0) {
+ max_time = 1;
+ }
+ /* ensure the random value is > 0 */
+ group->timer = (LWIP_RAND() % (max_time - 1)) + 1;
}
/**
@@ -652,7 +711,7 @@ igmp_start_timer(struct igmp_group *group, u8_t max_time)
*
* @param group the igmp_group for which to stop the timer
*/
-void
+static void
igmp_stop_timer(struct igmp_group *group)
{
group->timer = 0;
@@ -664,12 +723,13 @@ igmp_stop_timer(struct igmp_group *group)
* @param group the igmp_group for which "delaying" membership report
* @param maxresp query delay
*/
-void
-igmp_delaying_member( struct igmp_group *group, u8_t maxresp)
+static 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))) {
- igmp_start_timer(group, (maxresp)/2);
+ ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) &&
+ ((group->timer == 0) || (maxresp < group->timer)))) {
+ igmp_start_timer(group, maxresp);
group->group_state = IGMP_GROUP_DELAYING_MEMBER;
}
}
@@ -693,15 +753,15 @@ igmp_delaying_member( struct igmp_group *group, u8_t maxresp)
* ERR_BUF if p doesn't have enough space for IP/LINK headers
* returns errors returned by netif->output
*/
-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 err_t
+igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif)
{
/* This is the "router alert" option */
u16_t ra[2];
- ra[0] = htons (ROUTER_ALERT);
+ ra[0] = PP_HTONS(ROUTER_ALERT);
ra[1] = 0x0000; /* Router shall examine packet */
- return ip_output_if_opt(p, src, dest, ttl, 0, proto, netif, ra, ROUTER_ALERTLEN);
+ IGMP_STATS_INC(igmp.xmit);
+ return ip_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN);
}
/**
@@ -710,32 +770,31 @@ igmp_ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
* @param group the group to which to send the packet
* @param type the type of igmp packet to send
*/
-void
+static void
igmp_send(struct igmp_group *group, u8_t type)
{
struct pbuf* p = NULL;
struct igmp_msg* igmp = NULL;
- struct ip_addr src = {0};
- struct ip_addr* dest = NULL;
+ ip_addr_t src = *IP_ADDR_ANY;
+ ip_addr_t* dest = NULL;
/* IP header + "router alert" option + IGMP header */
p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM);
if (p) {
- igmp = p->payload;
+ igmp = (struct igmp_msg *)p->payload;
LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg",
(p->len >= sizeof(struct igmp_msg)));
- ip_addr_set(&src, &((group->interface)->ip_addr));
+ ip_addr_copy(src, group->netif->ip_addr);
if (type == IGMP_V2_MEMB_REPORT) {
dest = &(group->group_address);
- IGMP_STATS_INC(igmp.report_sent);
- ip_addr_set(&(igmp->igmp_group_address), &(group->group_address));
+ ip_addr_copy(igmp->igmp_group_address, group->group_address);
group->last_reporter_flag = 1; /* Remember we were the last to report */
} else {
if (type == IGMP_LEAVE_GROUP) {
dest = &allrouters;
- ip_addr_set(&(igmp->igmp_group_address), &(group->group_address));
+ ip_addr_copy(igmp->igmp_group_address, group->group_address);
}
}
@@ -743,14 +802,15 @@ igmp_send(struct igmp_group *group, u8_t type)
igmp->igmp_msgtype = type;
igmp->igmp_maxresp = 0;
igmp->igmp_checksum = 0;
- igmp->igmp_checksum = inet_chksum( igmp, IGMP_MINLEN);
+ 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, group->netif);
}
pbuf_free(p);
} else {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n"));
+ IGMP_STATS_INC(igmp.memerr);
}
}
diff --git a/core/lwip/src/core/ipv4/inet.c b/core/lwip/src/core/ipv4/inet.c
index 69baf1d5..e283a576 100644
--- a/core/lwip/src/core/ipv4/inet.c
+++ b/core/lwip/src/core/ipv4/inet.c
@@ -40,239 +40,3 @@
#include "lwip/inet.h"
-/* Here for now until needed in other places in lwIP */
-#ifndef isprint
-#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
-#define isprint(c) in_range(c, 0x20, 0x7f)
-#define isdigit(c) in_range(c, '0', '9')
-#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
-#define islower(c) in_range(c, 'a', 'z')
-#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
-#endif
-
-/**
- * Ascii internet address interpretation routine.
- * The value returned is in network order.
- *
- * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
- * @return ip address in network order
- */
-u32_t
-inet_addr(const char *cp)
-{
- struct in_addr val;
-
- if (inet_aton(cp, &val)) {
- return (val.s_addr);
- }
- return (INADDR_NONE);
-}
-
-/**
- * Check whether "cp" is a valid ascii representation
- * of an Internet address and convert to a binary address.
- * Returns 1 if the address is valid, 0 if not.
- * This replaces inet_addr, the return value from which
- * cannot distinguish between failure and a local broadcast address.
- *
- * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
- * @param addr pointer to which to save the ip address in network order
- * @return 1 if cp could be converted to addr, 0 on failure
- */
-int
-inet_aton(const char *cp, struct in_addr *addr)
-{
- u32_t val;
- u8_t base;
- char c;
- u32_t parts[4];
- u32_t *pp = parts;
-
- c = *cp;
- for (;;) {
- /*
- * Collect number up to ``.''.
- * Values are specified as for C:
- * 0x=hex, 0=octal, 1-9=decimal.
- */
- if (!isdigit(c))
- return (0);
- val = 0;
- base = 10;
- if (c == '0') {
- c = *++cp;
- if (c == 'x' || c == 'X') {
- base = 16;
- c = *++cp;
- } else
- base = 8;
- }
- for (;;) {
- if (isdigit(c)) {
- val = (val * base) + (int)(c - '0');
- c = *++cp;
- } else if (base == 16 && isxdigit(c)) {
- val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
- c = *++cp;
- } else
- break;
- }
- if (c == '.') {
- /*
- * Internet format:
- * a.b.c.d
- * a.b.c (with c treated as 16 bits)
- * a.b (with b treated as 24 bits)
- */
- if (pp >= parts + 3)
- return (0);
- *pp++ = val;
- c = *++cp;
- } else
- break;
- }
- /*
- * Check for trailing characters.
- */
- if (c != '\0' && !isspace(c))
- return (0);
- /*
- * Concoct the address according to
- * the number of parts specified.
- */
- switch (pp - parts + 1) {
-
- case 0:
- return (0); /* initial nondigit */
-
- case 1: /* a -- 32 bits */
- break;
-
- case 2: /* a.b -- 8.24 bits */
- if (val > 0xffffffUL)
- return (0);
- val |= parts[0] << 24;
- break;
-
- case 3: /* a.b.c -- 8.8.16 bits */
- if (val > 0xffff)
- return (0);
- val |= (parts[0] << 24) | (parts[1] << 16);
- break;
-
- case 4: /* a.b.c.d -- 8.8.8.8 bits */
- if (val > 0xff)
- return (0);
- val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
- break;
- }
- if (addr)
- addr->s_addr = htonl(val);
- return (1);
-}
-
-/**
- * Convert numeric IP address into decimal dotted ASCII representation.
- * returns ptr to static buffer; not reentrant!
- *
- * @param addr ip address in network order to convert
- * @return pointer to a global static (!) buffer that holds the ASCII
- * represenation of addr
- */
-char *
-inet_ntoa(struct in_addr addr)
-{
- static char str[16];
- u32_t s_addr = addr.s_addr;
- char inv[3];
- char *rp;
- u8_t *ap;
- u8_t rem;
- u8_t n;
- u8_t i;
-
- rp = str;
- ap = (u8_t *)&s_addr;
- for(n = 0; n < 4; n++) {
- i = 0;
- do {
- rem = *ap % (u8_t)10;
- *ap /= (u8_t)10;
- inv[i++] = '0' + rem;
- } while(*ap);
- while(i--)
- *rp++ = inv[i];
- *rp++ = '.';
- ap++;
- }
- *--rp = 0;
- return str;
-}
-
-/**
- * These are reference implementations of the byte swapping functions.
- * Again with the aim of being simple, correct and fully portable.
- * Byte swapping is the second thing you would want to optimize. You will
- * need to port it to your architecture and in your cc.h:
- *
- * #define LWIP_PLATFORM_BYTESWAP 1
- * #define LWIP_PLATFORM_HTONS(x) <your_htons>
- * #define LWIP_PLATFORM_HTONL(x) <your_htonl>
- *
- * Note ntohs() and ntohl() are merely references to the htonx counterparts.
- */
-
-#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
-
-/**
- * Convert an u16_t from host- to network byte order.
- *
- * @param n u16_t in host byte order
- * @return n in network byte order
- */
-u16_t
-htons(u16_t n)
-{
- return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
-}
-
-/**
- * Convert an u16_t from network- to host byte order.
- *
- * @param n u16_t in network byte order
- * @return n in host byte order
- */
-u16_t
-ntohs(u16_t n)
-{
- return htons(n);
-}
-
-/**
- * Convert an u32_t from host- to network byte order.
- *
- * @param n u32_t in host byte order
- * @return n in network byte order
- */
-u32_t
-htonl(u32_t n)
-{
- return ((n & 0xff) << 24) |
- ((n & 0xff00) << 8) |
- ((n & 0xff0000UL) >> 8) |
- ((n & 0xff000000UL) >> 24);
-}
-
-/**
- * Convert an u32_t from network- to host byte order.
- *
- * @param n u32_t in network byte order
- * @return n in host byte order
- */
-u32_t
-ntohl(u32_t n)
-{
- return htonl(n);
-}
-
-#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */
diff --git a/core/lwip/src/core/ipv4/inet_chksum.c b/core/lwip/src/core/ipv4/inet_chksum.c
index 185881ef..960252f6 100644
--- a/core/lwip/src/core/ipv4/inet_chksum.c
+++ b/core/lwip/src/core/ipv4/inet_chksum.c
@@ -39,9 +39,10 @@
#include "lwip/opt.h"
#include "lwip/inet_chksum.h"
-#include "lwip/inet.h"
+#include "lwip/def.h"
#include <stddef.h>
+#include <string.h>
/* These are some reference implementations of the checksum algorithm, with the
* aim of being simple, correct and fully portable. Checksumming is the
@@ -57,7 +58,7 @@
#ifndef LWIP_CHKSUM
# define LWIP_CHKSUM lwip_standard_chksum
# ifndef LWIP_CHKSUM_ALGORITHM
-# define LWIP_CHKSUM_ALGORITHM 1
+# define LWIP_CHKSUM_ALGORITHM 2
# endif
#endif
/* If none set: */
@@ -65,18 +66,6 @@
# 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
@@ -145,10 +134,10 @@ lwip_standard_chksum(void *dataptr, u16_t len)
static u16_t
lwip_standard_chksum(void *dataptr, int len)
{
- u8_t *pb = dataptr;
+ u8_t *pb = (u8_t *)dataptr;
u16_t *ps, t = 0;
u32_t sum = 0;
- int odd = ((u32_t)pb & 1);
+ int odd = ((mem_ptr_t)pb & 1);
/* Get aligned to u16_t */
if (odd && len > 0) {
@@ -157,7 +146,7 @@ lwip_standard_chksum(void *dataptr, int len)
}
/* Add the bulk of the data */
- ps = (u16_t *)pb;
+ ps = (u16_t *)(void *)pb;
while (len > 1) {
sum += *ps++;
len -= 2;
@@ -165,7 +154,7 @@ lwip_standard_chksum(void *dataptr, int len)
/* Consume left-over byte, if any */
if (len > 0) {
- ((u8_t *)&t)[0] = *(u8_t *)ps;;
+ ((u8_t *)&t)[0] = *(u8_t *)ps;
}
/* Add end bytes */
@@ -181,7 +170,7 @@ lwip_standard_chksum(void *dataptr, int len)
sum = SWAP_BYTES_IN_WORD(sum);
}
- return sum;
+ return (u16_t)sum;
}
#endif
@@ -201,12 +190,12 @@ lwip_standard_chksum(void *dataptr, int len)
static u16_t
lwip_standard_chksum(void *dataptr, int len)
{
- u8_t *pb = dataptr;
+ u8_t *pb = (u8_t *)dataptr;
u16_t *ps, t = 0;
u32_t *pl;
u32_t sum = 0, tmp;
/* starts at odd byte address? */
- int odd = ((u32_t)pb & 1);
+ int odd = ((mem_ptr_t)pb & 1);
if (odd && len > 0) {
((u8_t *)&t)[1] = *pb++;
@@ -215,7 +204,7 @@ lwip_standard_chksum(void *dataptr, int len)
ps = (u16_t *)pb;
- if (((u32_t)ps & 3) && len > 1) {
+ if (((mem_ptr_t)ps & 3) && len > 1) {
sum += *ps++;
len -= 2;
}
@@ -263,7 +252,7 @@ lwip_standard_chksum(void *dataptr, int len)
sum = SWAP_BYTES_IN_WORD(sum);
}
- return sum;
+ return (u16_t)sum;
}
#endif
@@ -281,10 +270,11 @@ lwip_standard_chksum(void *dataptr, int len)
*/
u16_t
inet_chksum_pseudo(struct pbuf *p,
- struct ip_addr *src, struct ip_addr *dest,
+ ip_addr_t *src, ip_addr_t *dest,
u8_t proto, u16_t proto_len)
{
u32_t acc;
+ u32_t addr;
struct pbuf *q;
u8_t swapped;
@@ -309,10 +299,12 @@ inet_chksum_pseudo(struct pbuf *p,
if (swapped) {
acc = SWAP_BYTES_IN_WORD(acc);
}
- acc += (src->addr & 0xffffUL);
- acc += ((src->addr >> 16) & 0xffffUL);
- acc += (dest->addr & 0xffffUL);
- acc += ((dest->addr >> 16) & 0xffffUL);
+ addr = ip4_addr_get_u32(src);
+ acc += (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
+ addr = ip4_addr_get_u32(dest);
+ acc += (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
acc += (u32_t)htons((u16_t)proto);
acc += (u32_t)htons(proto_len);
@@ -336,14 +328,13 @@ 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,
+ ip_addr_t *src, ip_addr_t *dest,
u8_t proto, u16_t proto_len, u16_t chksum_len)
{
u32_t acc;
+ u32_t addr;
struct pbuf *q;
u8_t swapped;
u16_t chklen;
@@ -374,10 +365,12 @@ inet_chksum_pseudo_partial(struct pbuf *p,
if (swapped) {
acc = SWAP_BYTES_IN_WORD(acc);
}
- acc += (src->addr & 0xffffUL);
- acc += ((src->addr >> 16) & 0xffffUL);
- acc += (dest->addr & 0xffffUL);
- acc += ((dest->addr >> 16) & 0xffffUL);
+ addr = ip4_addr_get_u32(src);
+ acc += (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
+ addr = ip4_addr_get_u32(dest);
+ acc += (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
acc += (u32_t)htons((u16_t)proto);
acc += (u32_t)htons(proto_len);
@@ -388,7 +381,6 @@ inet_chksum_pseudo_partial(struct pbuf *p,
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:
*
@@ -436,3 +428,23 @@ inet_chksum_pbuf(struct pbuf *p)
}
return (u16_t)~(acc & 0xffffUL);
}
+
+/* These are some implementations for LWIP_CHKSUM_COPY, which copies data
+ * like MEMCPY but generates a checksum at the same time. Since this is a
+ * performance-sensitive function, you might want to create your own version
+ * in assembly targeted at your hardware by defining it in lwipopts.h:
+ * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len)
+ */
+
+#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */
+/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM.
+ * For architectures with big caches, data might still be in cache when
+ * generating the checksum after copying.
+ */
+u16_t
+lwip_chksum_copy(void *dst, const void *src, u16_t len)
+{
+ MEMCPY(dst, src, len);
+ return LWIP_CHKSUM(dst, len);
+}
+#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */
diff --git a/core/lwip/src/core/ipv4/ip.c b/core/lwip/src/core/ipv4/ip.c
index b1e98f33..6f248716 100644
--- a/core/lwip/src/core/ipv4/ip.c
+++ b/core/lwip/src/core/ipv4/ip.c
@@ -43,21 +43,56 @@
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/ip_frag.h"
-#include "lwip/inet.h"
#include "lwip/inet_chksum.h"
#include "lwip/netif.h"
#include "lwip/icmp.h"
#include "lwip/igmp.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
-#include "lwip/tcp.h"
+#include "lwip/tcp_impl.h"
#include "lwip/snmp.h"
#include "lwip/dhcp.h"
+#include "lwip/autoip.h"
#include "lwip/stats.h"
#include "arch/perf.h"
#include <string.h>
+/** Set this to 0 in the rare case of wanting to call an extra function to
+ * generate the IP checksum (in contrast to calculating it on-the-fly). */
+#ifndef LWIP_INLINE_IP_CHKSUM
+#define LWIP_INLINE_IP_CHKSUM 1
+#endif
+#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP
+#define CHECKSUM_GEN_IP_INLINE 1
+#else
+#define CHECKSUM_GEN_IP_INLINE 0
+#endif
+
+#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT)
+#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1
+
+/** Some defines for DHCP to let link-layer-addressed packets through while the
+ * netif is down.
+ * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT
+ * to return 1 if the port is accepted and 0 if the port is not accepted.
+ */
+#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT)
+/* accept DHCP client port and custom port */
+#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \
+ || (LWIP_IP_ACCEPT_UDP_PORT(port)))
+#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
+/* accept custom port only */
+#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(dst_port))
+#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
+/* accept DHCP client port only */
+#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT))
+#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
+
+#else /* LWIP_DHCP */
+#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0
+#endif /* LWIP_DHCP */
+
/**
* The interface that provided the packet for the current callback
* invocation.
@@ -68,6 +103,13 @@ struct netif *current_netif;
* Header of the input packet currently being processed.
*/
const struct ip_hdr *current_header;
+/** Source IP address of current_header */
+ip_addr_t current_iphdr_src;
+/** Destination IP address of current_header */
+ip_addr_t current_iphdr_dest;
+
+/** The IP header ID of the next outgoing IP packet */
+static u16_t ip_id;
/**
* Finds the appropriate network interface for a given IP address. It
@@ -79,7 +121,7 @@ const struct ip_hdr *current_header;
* @return the netif on which to send to reach dest
*/
struct netif *
-ip_route(struct ip_addr *dest)
+ip_route(ip_addr_t *dest)
{
struct netif *netif;
@@ -94,7 +136,8 @@ ip_route(struct ip_addr *dest)
}
}
if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to 0x%"X32_F"\n", dest->addr));
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
IP_STATS_INC(ip.rterr);
snmp_inc_ipoutnoroutes();
return NULL;
@@ -112,28 +155,35 @@ ip_route(struct ip_addr *dest)
* @param p the packet to forward (p->payload points to IP header)
* @param iphdr the IP header of the input packet
* @param inp the netif on which this packet was received
- * @return the netif on which the packet was sent (NULL if it wasn't sent)
*/
-static struct netif *
+static void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
{
struct netif *netif;
PERF_START;
+
+ /* RFC3927 2.7: do not forward link-local addresses */
+ if (ip_addr_islinklocal(&current_iphdr_dest)) {
+ LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
+ ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
+ goto return_noroute;
+ }
+
/* Find network interface where to forward this IP packet to. */
- netif = ip_route((struct ip_addr *)&(iphdr->dest));
+ netif = ip_route(&current_iphdr_dest);
if (netif == NULL) {
- LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n",
- iphdr->dest.addr));
- snmp_inc_ipoutnoroutes();
- return (struct netif *)NULL;
+ LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n",
+ ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
+ ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
+ goto return_noroute;
}
/* Do not forward packets onto the same network interface on which
* they arrived. */
if (netif == inp) {
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
- snmp_inc_ipoutnoroutes();
- return (struct netif *)NULL;
+ goto return_noroute;
}
/* decrement TTL */
@@ -147,18 +197,19 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
icmp_time_exceeded(p, ICMP_TE_TTL);
}
#endif /* LWIP_ICMP */
- return (struct netif *)NULL;
+ return;
}
/* Incrementally update the IP checksum. */
- if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
- IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
+ if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) {
+ IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1);
} else {
- IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
+ IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100));
}
- LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
- iphdr->dest.addr));
+ LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
+ ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
IP_STATS_INC(ip.fw);
IP_STATS_INC(ip.xmit);
@@ -166,8 +217,10 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
PERF_STOP("ip_forward");
/* transmit pbuf on chosen interface */
- netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
- return netif;
+ netif->output(netif, p, &current_iphdr_dest);
+ return;
+return_noroute:
+ snmp_inc_ipoutnoroutes();
}
#endif /* IP_FORWARD */
@@ -192,15 +245,15 @@ ip_input(struct pbuf *p, struct netif *inp)
struct netif *netif;
u16_t iphdr_hlen;
u16_t iphdr_len;
-#if LWIP_DHCP
+#if IP_ACCEPT_LINK_LAYER_ADDRESSING
int check_ip_src=1;
-#endif /* LWIP_DHCP */
+#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
IP_STATS_INC(ip.recv);
snmp_inc_ipinreceives();
/* identify the IP header */
- iphdr = p->payload;
+ iphdr = (struct ip_hdr *)p->payload;
if (IPH_V(iphdr) != 4) {
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
ip_debug_print(p);
@@ -257,10 +310,14 @@ ip_input(struct pbuf *p, struct netif *inp)
* but we'll do it anyway just to be sure that its done. */
pbuf_realloc(p, iphdr_len);
+ /* copy IP addresses to aligned ip_addr_t */
+ ip_addr_copy(current_iphdr_dest, iphdr->dest);
+ ip_addr_copy(current_iphdr_src, iphdr->src);
+
/* match packet against an interface, i.e. is this packet for us? */
#if LWIP_IGMP
- if (ip_addr_ismulticast(&(iphdr->dest))) {
- if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &(iphdr->dest)))) {
+ if (ip_addr_ismulticast(&current_iphdr_dest)) {
+ if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &current_iphdr_dest))) {
netif = inp;
} else {
netif = NULL;
@@ -275,22 +332,33 @@ ip_input(struct pbuf *p, struct netif *inp)
netif = inp;
do {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
- iphdr->dest.addr, netif->ip_addr.addr,
- iphdr->dest.addr & netif->netmask.addr,
- netif->ip_addr.addr & netif->netmask.addr,
- iphdr->dest.addr & ~(netif->netmask.addr)));
+ ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr),
+ ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask),
+ ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask),
+ ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask)));
/* interface is up and configured? */
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
/* unicast to this interface address? */
- if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
+ if (ip_addr_cmp(&current_iphdr_dest, &(netif->ip_addr)) ||
/* or broadcast on this interface network address? */
- ip_addr_isbroadcast(&(iphdr->dest), netif)) {
+ ip_addr_isbroadcast(&current_iphdr_dest, netif)) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
netif->name[0], netif->name[1]));
/* break out of for loop */
break;
}
+#if LWIP_AUTOIP
+ /* connections to link-local addresses must persist after changing
+ the netif's address (RFC3927 ch. 1.9) */
+ if ((netif->autoip != NULL) &&
+ ip_addr_cmp(&current_iphdr_dest, &(netif->autoip->llipaddr))) {
+ LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n",
+ netif->name[0], netif->name[1]));
+ /* break out of for loop */
+ break;
+ }
+#endif /* LWIP_AUTOIP */
}
if (first) {
first = 0;
@@ -304,32 +372,38 @@ ip_input(struct pbuf *p, struct netif *inp)
} while(netif != NULL);
}
-#if LWIP_DHCP
+#if IP_ACCEPT_LINK_LAYER_ADDRESSING
/* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
* using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
* According to RFC 1542 section 3.1.1, referred by RFC 2131).
+ *
+ * If you want to accept private broadcast communication while a netif is down,
+ * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.:
+ *
+ * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345))
*/
if (netif == NULL) {
/* remote port is DHCP server? */
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
+ struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen);
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
- ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest)));
- if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) {
+ ntohs(udphdr->dest)));
+ if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) {
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n"));
netif = inp;
check_ip_src = 0;
}
}
}
-#endif /* LWIP_DHCP */
+#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
/* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
-#if LWIP_DHCP
+#if IP_ACCEPT_LINK_LAYER_ADDRESSING
/* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
- if (check_ip_src && (iphdr->src.addr != 0))
-#endif /* LWIP_DHCP */
- { if ((ip_addr_isbroadcast(&(iphdr->src), inp)) ||
- (ip_addr_ismulticast(&(iphdr->src)))) {
+ if (check_ip_src && !ip_addr_isany(&current_iphdr_src))
+#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
+ { if ((ip_addr_isbroadcast(&current_iphdr_src, inp)) ||
+ (ip_addr_ismulticast(&current_iphdr_src))) {
/* packet source is not valid */
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
/* free (drop) packet pbufs */
@@ -347,7 +421,7 @@ ip_input(struct pbuf *p, struct netif *inp)
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
#if IP_FORWARD
/* non-broadcast packet? */
- if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
+ if (!ip_addr_isbroadcast(&current_iphdr_dest, inp)) {
/* try to forward IP packet on (other) interfaces */
ip_forward(p, iphdr, inp);
} else
@@ -360,17 +434,17 @@ ip_input(struct pbuf *p, struct netif *inp)
return ERR_OK;
}
/* packet consists of multiple fragments? */
- if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
+ if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
- ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
+ ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
/* reassemble the packet*/
p = ip_reass(p);
/* packet not fully reassembled yet? */
if (p == NULL) {
return ERR_OK;
}
- iphdr = p->payload;
+ iphdr = (struct ip_hdr *)p->payload;
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
@@ -387,7 +461,7 @@ ip_input(struct pbuf *p, struct netif *inp)
#if LWIP_IGMP
/* there is an extra "router alert" option in IGMP messages which we allow for but do not police */
- if((iphdr_hlen > IP_HLEN && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
+ if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
#else
if (iphdr_hlen > IP_HLEN) {
#endif /* LWIP_IGMP */
@@ -439,14 +513,14 @@ ip_input(struct pbuf *p, struct netif *inp)
#endif /* LWIP_ICMP */
#if LWIP_IGMP
case IP_PROTO_IGMP:
- igmp_input(p,inp,&(iphdr->dest));
+ igmp_input(p, inp, &current_iphdr_dest);
break;
#endif /* LWIP_IGMP */
default:
#if LWIP_ICMP
/* send ICMP destination protocol unreachable unless is was a broadcast */
- if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
- !ip_addr_ismulticast(&(iphdr->dest))) {
+ if (!ip_addr_isbroadcast(&current_iphdr_dest, inp) &&
+ !ip_addr_ismulticast(&current_iphdr_dest)) {
p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PROTO);
}
@@ -463,6 +537,8 @@ ip_input(struct pbuf *p, struct netif *inp)
current_netif = NULL;
current_header = NULL;
+ ip_addr_set_any(&current_iphdr_src);
+ ip_addr_set_any(&current_iphdr_dest);
return ERR_OK;
}
@@ -493,7 +569,7 @@ ip_input(struct pbuf *p, struct netif *inp)
* unique identifiers independent of destination"
*/
err_t
-ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
u8_t ttl, u8_t tos,
u8_t proto, struct netif *netif)
{
@@ -507,13 +583,20 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
* @ 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,
+err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *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;
+ ip_addr_t dest_addr;
+#if CHECKSUM_GEN_IP_INLINE
+ u32_t chk_sum = 0;
+#endif /* CHECKSUM_GEN_IP_INLINE */
+
+ /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
+ gets altered as the packet is passed down the stack */
+ LWIP_ASSERT("p->ref == 1", p->ref == 1);
snmp_inc_ipoutrequests();
@@ -523,6 +606,9 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
#if IP_OPTIONS_SEND
u16_t optlen_aligned = 0;
if (optlen != 0) {
+#if CHECKSUM_GEN_IP_INLINE
+ int i;
+#endif /* CHECKSUM_GEN_IP_INLINE */
/* round up to a multiple of 4 */
optlen_aligned = ((optlen + 3) & ~3);
ip_hlen += optlen_aligned;
@@ -538,6 +624,11 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
/* zero the remaining bytes */
memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
}
+#if CHECKSUM_GEN_IP_INLINE
+ for (i = 0; i < optlen_aligned/2; i++) {
+ chk_sum += ((u16_t*)p->payload)[i];
+ }
+#endif /* CHECKSUM_GEN_IP_INLINE */
}
#endif /* IP_OPTIONS_SEND */
/* generate IP header */
@@ -549,35 +640,63 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
return ERR_BUF;
}
- iphdr = p->payload;
+ iphdr = (struct ip_hdr *)p->payload;
LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",
(p->len >= sizeof(struct ip_hdr)));
IPH_TTL_SET(iphdr, ttl);
IPH_PROTO_SET(iphdr, proto);
+#if CHECKSUM_GEN_IP_INLINE
+ chk_sum += LWIP_MAKE_U16(proto, ttl);
+#endif /* CHECKSUM_GEN_IP_INLINE */
- ip_addr_set(&(iphdr->dest), dest);
+ /* dest cannot be NULL here */
+ ip_addr_copy(iphdr->dest, *dest);
+#if CHECKSUM_GEN_IP_INLINE
+ chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF;
+ chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16;
+#endif /* CHECKSUM_GEN_IP_INLINE */
IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos);
+#if CHECKSUM_GEN_IP_INLINE
+ chk_sum += iphdr->_v_hl_tos;
+#endif /* CHECKSUM_GEN_IP_INLINE */
IPH_LEN_SET(iphdr, htons(p->tot_len));
+#if CHECKSUM_GEN_IP_INLINE
+ chk_sum += iphdr->_len;
+#endif /* CHECKSUM_GEN_IP_INLINE */
IPH_OFFSET_SET(iphdr, 0);
IPH_ID_SET(iphdr, htons(ip_id));
+#if CHECKSUM_GEN_IP_INLINE
+ chk_sum += iphdr->_id;
+#endif /* CHECKSUM_GEN_IP_INLINE */
++ip_id;
if (ip_addr_isany(src)) {
- ip_addr_set(&(iphdr->src), &(netif->ip_addr));
+ ip_addr_copy(iphdr->src, netif->ip_addr);
} else {
- ip_addr_set(&(iphdr->src), src);
+ /* src cannot be NULL here */
+ ip_addr_copy(iphdr->src, *src);
}
+#if CHECKSUM_GEN_IP_INLINE
+ chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF;
+ chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16;
+ chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
+ chk_sum = (chk_sum >> 16) + chk_sum;
+ chk_sum = ~chk_sum;
+ iphdr->_chksum = chk_sum; /* network order */
+#else /* CHECKSUM_GEN_IP_INLINE */
IPH_CHKSUM_SET(iphdr, 0);
#if CHECKSUM_GEN_IP
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
#endif
+#endif /* CHECKSUM_GEN_IP_INLINE */
} else {
/* IP header already included in p */
- iphdr = p->payload;
- dest = &(iphdr->dest);
+ iphdr = (struct ip_hdr *)p->payload;
+ ip_addr_copy(dest_addr, iphdr->dest);
+ dest = &dest_addr;
}
IP_STATS_INC(ip.xmit);
@@ -591,13 +710,18 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
return netif_loop_output(netif, p, dest);
}
+#if LWIP_IGMP
+ if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
+ netif_loop_output(netif, p, dest);
+ }
+#endif /* LWIP_IGMP */
#endif /* ENABLE_LOOPBACK */
#if IP_FRAG
/* don't fragment if interface has mtu set to 0 [loopif] */
if (netif->mtu && (p->tot_len > netif->mtu)) {
- return ip_frag(p,netif,dest);
+ return ip_frag(p, netif, dest);
}
-#endif
+#endif /* IP_FRAG */
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
return netif->output(netif, p, dest);
@@ -621,13 +745,18 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
* see ip_output_if() for more return values
*/
err_t
-ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
u8_t ttl, u8_t tos, u8_t proto)
{
struct netif *netif;
+ /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
+ gets altered as the packet is passed down the stack */
+ LWIP_ASSERT("p->ref == 1", p->ref == 1);
+
if ((netif = ip_route(dest)) == NULL) {
- LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
+ LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
IP_STATS_INC(ip.rterr);
return ERR_RTE;
}
@@ -655,14 +784,19 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
* see ip_output_if() for more return values
*/
err_t
-ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)
{
struct netif *netif;
err_t err;
+ /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
+ gets altered as the packet is passed down the stack */
+ LWIP_ASSERT("p->ref == 1", p->ref == 1);
+
if ((netif = ip_route(dest)) == NULL) {
- LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
+ LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
IP_STATS_INC(ip.rterr);
return ERR_RTE;
}
@@ -682,7 +816,7 @@ ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
void
ip_debug_print(struct pbuf *p)
{
- struct ip_hdr *iphdr = p->payload;
+ struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
u8_t *payload;
payload = (u8_t *)iphdr + IP_HLEN;
@@ -708,16 +842,16 @@ ip_debug_print(struct pbuf *p)
ntohs(IPH_CHKSUM(iphdr))));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
- ip4_addr1(&iphdr->src),
- ip4_addr2(&iphdr->src),
- ip4_addr3(&iphdr->src),
- ip4_addr4(&iphdr->src)));
+ ip4_addr1_16(&iphdr->src),
+ ip4_addr2_16(&iphdr->src),
+ ip4_addr3_16(&iphdr->src),
+ ip4_addr4_16(&iphdr->src)));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
- ip4_addr1(&iphdr->dest),
- ip4_addr2(&iphdr->dest),
- ip4_addr3(&iphdr->dest),
- ip4_addr4(&iphdr->dest)));
+ ip4_addr1_16(&iphdr->dest),
+ ip4_addr2_16(&iphdr->dest),
+ ip4_addr3_16(&iphdr->dest),
+ ip4_addr4_16(&iphdr->dest)));
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */
diff --git a/core/lwip/src/core/ipv4/ip_addr.c b/core/lwip/src/core/ipv4/ip_addr.c
index 94bf4678..8f633ff2 100644
--- a/core/lwip/src/core/ipv4/ip_addr.c
+++ b/core/lwip/src/core/ipv4/ip_addr.c
@@ -38,15 +38,11 @@
#include "lwip/opt.h"
#include "lwip/ip_addr.h"
-#include "lwip/inet.h"
#include "lwip/netif.h"
-#define IP_ADDR_ANY_VALUE 0x00000000UL
-#define IP_ADDR_BROADCAST_VALUE 0xffffffffUL
-
/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
-const struct ip_addr ip_addr_any = { IP_ADDR_ANY_VALUE };
-const struct ip_addr ip_addr_broadcast = { IP_ADDR_BROADCAST_VALUE };
+const ip_addr_t ip_addr_any = { IPADDR_ANY };
+const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST };
/**
* Determine if an address is a broadcast address on a network interface
@@ -55,30 +51,262 @@ const struct ip_addr ip_addr_broadcast = { IP_ADDR_BROADCAST_VALUE };
* @param netif the network interface against which the address is checked
* @return returns non-zero if the address is a broadcast address
*/
-u8_t ip_addr_isbroadcast(struct ip_addr *addr, struct netif *netif)
+u8_t
+ip4_addr_isbroadcast(u32_t addr, const struct netif *netif)
{
- u32_t addr2test;
+ ip_addr_t ipaddr;
+ ip4_addr_set_u32(&ipaddr, addr);
- addr2test = addr->addr;
/* all ones (broadcast) or all zeroes (old skool broadcast) */
- if ((~addr2test == IP_ADDR_ANY_VALUE) ||
- (addr2test == IP_ADDR_ANY_VALUE))
+ if ((~addr == IPADDR_ANY) ||
+ (addr == IPADDR_ANY)) {
return 1;
/* no broadcast support on this network interface? */
- else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0)
+ } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) {
/* the given address cannot be a broadcast address
* nor can we check against any broadcast addresses */
return 0;
/* address matches network interface address exactly? => no broadcast */
- else if (addr2test == netif->ip_addr.addr)
+ } else if (addr == ip4_addr_get_u32(&netif->ip_addr)) {
return 0;
/* on the same (sub) network... */
- else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask))
+ } else if (ip_addr_netcmp(&ipaddr, &(netif->ip_addr), &(netif->netmask))
/* ...and host identifier bits are all ones? =>... */
- && ((addr2test & ~netif->netmask.addr) ==
- (IP_ADDR_BROADCAST_VALUE & ~netif->netmask.addr)))
+ && ((addr & ~ip4_addr_get_u32(&netif->netmask)) ==
+ (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) {
/* => network broadcast address */
return 1;
- else
+ } else {
return 0;
+ }
+}
+
+/** Checks if a netmask is valid (starting with ones, then only zeros)
+ *
+ * @param netmask the IPv4 netmask to check (in network byte order!)
+ * @return 1 if the netmask is valid, 0 if it is not
+ */
+u8_t
+ip4_addr_netmask_valid(u32_t netmask)
+{
+ u32_t mask;
+ u32_t nm_hostorder = lwip_htonl(netmask);
+
+ /* first, check for the first zero */
+ for (mask = 1UL << 31 ; mask != 0; mask >>= 1) {
+ if ((nm_hostorder & mask) == 0) {
+ break;
+ }
+ }
+ /* then check that there is no one */
+ for (; mask != 0; mask >>= 1) {
+ if ((nm_hostorder & mask) != 0) {
+ /* there is a one after the first zero -> invalid */
+ return 0;
+ }
+ }
+ /* no one after the first zero -> valid */
+ return 1;
+}
+
+/* Here for now until needed in other places in lwIP */
+#ifndef isprint
+#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
+#define isprint(c) in_range(c, 0x20, 0x7f)
+#define isdigit(c) in_range(c, '0', '9')
+#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
+#define islower(c) in_range(c, 'a', 'z')
+#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
+#endif
+
+/**
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ *
+ * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
+ * @return ip address in network order
+ */
+u32_t
+ipaddr_addr(const char *cp)
+{
+ ip_addr_t val;
+
+ if (ipaddr_aton(cp, &val)) {
+ return ip4_addr_get_u32(&val);
+ }
+ return (IPADDR_NONE);
+}
+
+/**
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ *
+ * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
+ * @param addr pointer to which to save the ip address in network order
+ * @return 1 if cp could be converted to addr, 0 on failure
+ */
+int
+ipaddr_aton(const char *cp, ip_addr_t *addr)
+{
+ u32_t val;
+ u8_t base;
+ char c;
+ u32_t parts[4];
+ u32_t *pp = parts;
+
+ c = *cp;
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, 1-9=decimal.
+ */
+ if (!isdigit(c))
+ return (0);
+ val = 0;
+ base = 10;
+ if (c == '0') {
+ c = *++cp;
+ if (c == 'x' || c == 'X') {
+ base = 16;
+ c = *++cp;
+ } else
+ base = 8;
+ }
+ for (;;) {
+ if (isdigit(c)) {
+ val = (val * base) + (int)(c - '0');
+ c = *++cp;
+ } else if (base == 16 && isxdigit(c)) {
+ val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
+ c = *++cp;
+ } else
+ break;
+ }
+ if (c == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3) {
+ return (0);
+ }
+ *pp++ = val;
+ c = *++cp;
+ } else
+ break;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (c != '\0' && !isspace(c)) {
+ return (0);
+ }
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ switch (pp - parts + 1) {
+
+ case 0:
+ return (0); /* initial nondigit */
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffffUL) {
+ return (0);
+ }
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff) {
+ return (0);
+ }
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff) {
+ return (0);
+ }
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ default:
+ LWIP_ASSERT("unhandled", 0);
+ break;
+ }
+ if (addr) {
+ ip4_addr_set_u32(addr, htonl(val));
+ }
+ return (1);
+}
+
+/**
+ * Convert numeric IP address into decimal dotted ASCII representation.
+ * returns ptr to static buffer; not reentrant!
+ *
+ * @param addr ip address in network order to convert
+ * @return pointer to a global static (!) buffer that holds the ASCII
+ * represenation of addr
+ */
+char *
+ipaddr_ntoa(const ip_addr_t *addr)
+{
+ static char str[16];
+ return ipaddr_ntoa_r(addr, str, 16);
+}
+
+/**
+ * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
+ *
+ * @param addr ip address in network order to convert
+ * @param buf target buffer where the string is stored
+ * @param buflen length of buf
+ * @return either pointer to buf which now holds the ASCII
+ * representation of addr or NULL if buf was too small
+ */
+char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen)
+{
+ u32_t s_addr;
+ char inv[3];
+ char *rp;
+ u8_t *ap;
+ u8_t rem;
+ u8_t n;
+ u8_t i;
+ int len = 0;
+
+ s_addr = ip4_addr_get_u32(addr);
+
+ rp = buf;
+ ap = (u8_t *)&s_addr;
+ for(n = 0; n < 4; n++) {
+ i = 0;
+ do {
+ rem = *ap % (u8_t)10;
+ *ap /= (u8_t)10;
+ inv[i++] = '0' + rem;
+ } while(*ap);
+ while(i--) {
+ if (len++ >= buflen) {
+ return NULL;
+ }
+ *rp++ = inv[i];
+ }
+ if (len++ >= buflen) {
+ return NULL;
+ }
+ *rp++ = '.';
+ ap++;
+ }
+ *--rp = 0;
+ return buf;
}
diff --git a/core/lwip/src/core/ipv4/ip_frag.c b/core/lwip/src/core/ipv4/ip_frag.c
index 1939d831..8d184345 100644
--- a/core/lwip/src/core/ipv4/ip_frag.c
+++ b/core/lwip/src/core/ipv4/ip_frag.c
@@ -40,8 +40,7 @@
#include "lwip/opt.h"
#include "lwip/ip_frag.h"
-#include "lwip/ip.h"
-#include "lwip/inet.h"
+#include "lwip/def.h"
#include "lwip/inet_chksum.h"
#include "lwip/netif.h"
#include "lwip/snmp.h"
@@ -81,7 +80,10 @@
/** 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.
+ * It has the same packing requirements as the IP header, since it replaces
+ * the IP header in memory in incoming fragments (after copying it) to keep
+ * track of the various fragments. (-> If the IP header doesn't need packing,
+ * this struct doesn't need packing, too.)
*/
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
@@ -155,7 +157,8 @@ ip_reass_tmr(void)
static int
ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
{
- int pbufs_freed = 0;
+ u16_t pbufs_freed = 0;
+ u8_t clen;
struct pbuf *p;
struct ip_reass_helper *iprh;
@@ -175,7 +178,9 @@ ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *p
/* Then, copy the original header into it. */
SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN);
icmp_time_exceeded(p, ICMP_TE_FRAG);
- pbufs_freed += pbuf_clen(p);
+ clen = pbuf_clen(p);
+ LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
+ pbufs_freed += clen;
pbuf_free(p);
}
#endif /* LWIP_ICMP */
@@ -189,8 +194,10 @@ ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *p
pcur = p;
/* get the next pointer before freeing */
p = iprh->next_pbuf;
- pbufs_freed += pbuf_clen(pcur);
- pbuf_free(pcur);
+ clen = pbuf_clen(pcur);
+ LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
+ pbufs_freed += clen;
+ pbuf_free(pcur);
}
/* Then, unchain the struct ip_reassdata from the list and free it. */
ip_reass_dequeue_datagram(ipr, prev);
@@ -263,11 +270,11 @@ ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen)
{
struct ip_reassdata* ipr;
/* No matching previous fragment found, allocate a new reassdata struct */
- ipr = memp_malloc(MEMP_REASSDATA);
+ ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
if (ipr == NULL) {
#if IP_REASS_FREE_OLDEST
if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) {
- ipr = memp_malloc(MEMP_REASSDATA);
+ ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
}
if (ipr == NULL)
#endif /* IP_REASS_FREE_OLDEST */
@@ -548,7 +555,7 @@ ip_reass(struct pbuf *p)
* to an existing one */
/* check for 'no more fragments', and update queue entry*/
- if ((ntohs(IPH_OFFSET(fraghdr)) & IP_MF) == 0) {
+ if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) {
ipr->flags |= IP_REASS_FLAG_LASTFRAG;
ipr->datagram_len = offset + len;
LWIP_DEBUGF(IP_REASS_DEBUG,
@@ -609,6 +616,38 @@ nullreturn:
#if IP_FRAG
#if IP_FRAG_USES_STATIC_BUF
static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)];
+#else /* IP_FRAG_USES_STATIC_BUF */
+
+#if !LWIP_NETIF_TX_SINGLE_PBUF
+/** Allocate a new struct pbuf_custom_ref */
+static struct pbuf_custom_ref*
+ip_frag_alloc_pbuf_custom_ref(void)
+{
+ return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF);
+}
+
+/** Free a struct pbuf_custom_ref */
+static void
+ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p)
+{
+ LWIP_ASSERT("p != NULL", p != NULL);
+ memp_free(MEMP_FRAG_PBUF, p);
+}
+
+/** Free-callback function to free a 'struct pbuf_custom_ref', called by
+ * pbuf_free. */
+static void
+ipfrag_free_pbuf_custom(struct pbuf *p)
+{
+ struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p;
+ LWIP_ASSERT("pcr != NULL", pcr != NULL);
+ LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p);
+ if (pcr->original != NULL) {
+ pbuf_free(pcr->original);
+ }
+ ip_frag_free_pbuf_custom_ref(pcr);
+}
+#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */
#endif /* IP_FRAG_USES_STATIC_BUF */
/**
@@ -625,13 +664,15 @@ static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)];
* @return ERR_OK if sent successfully, err_t otherwise
*/
err_t
-ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
+ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest)
{
struct pbuf *rambuf;
#if IP_FRAG_USES_STATIC_BUF
struct pbuf *header;
#else
+#if !LWIP_NETIF_TX_SINGLE_PBUF
struct pbuf *newpbuf;
+#endif
struct ip_hdr *original_iphdr;
#endif
struct ip_hdr *iphdr;
@@ -642,7 +683,7 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
u16_t last;
u16_t poff = IP_HLEN;
u16_t tmp;
-#if !IP_FRAG_USES_STATIC_BUF
+#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
u16_t newpbuflen = 0;
u16_t left_to_copy;
#endif
@@ -662,10 +703,10 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
rambuf->payload = LWIP_MEM_ALIGN((void *)buf);
/* Copy the IP header in it */
- iphdr = rambuf->payload;
+ iphdr = (struct ip_hdr *)rambuf->payload;
SMEMCPY(iphdr, p->payload, IP_HLEN);
#else /* IP_FRAG_USES_STATIC_BUF */
- original_iphdr = p->payload;
+ original_iphdr = (struct ip_hdr *)p->payload;
iphdr = original_iphdr;
#endif /* IP_FRAG_USES_STATIC_BUF */
@@ -683,8 +724,9 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
/* Set new offset and MF flag */
tmp = omf | (IP_OFFMASK & (ofo));
- if (!last)
+ if (!last) {
tmp = tmp | IP_MF;
+ }
/* Fill this fragment */
cop = last ? left : nfb * 8;
@@ -692,6 +734,23 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
#if IP_FRAG_USES_STATIC_BUF
poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff);
#else /* IP_FRAG_USES_STATIC_BUF */
+#if LWIP_NETIF_TX_SINGLE_PBUF
+ rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM);
+ if (rambuf == NULL) {
+ return ERR_MEM;
+ }
+ LWIP_ASSERT("this needs a pbuf in one piece!",
+ (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL));
+ poff += pbuf_copy_partial(p, rambuf->payload, cop, poff);
+ /* make room for the IP header */
+ if(pbuf_header(rambuf, IP_HLEN)) {
+ pbuf_free(rambuf);
+ return ERR_MEM;
+ }
+ /* fill in the IP header */
+ SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
+ iphdr = rambuf->payload;
+#else /* LWIP_NETIF_TX_SINGLE_PBUF */
/* When not using a static buffer, create a chain of pbufs.
* The first will be a PBUF_RAM holding the link and IP header.
* The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
@@ -704,7 +763,7 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
LWIP_ASSERT("this needs a pbuf in one piece!",
(p->len >= (IP_HLEN)));
SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
- iphdr = rambuf->payload;
+ iphdr = (struct ip_hdr *)rambuf->payload;
/* Can just adjust p directly for needed offset. */
p->payload = (u8_t *)p->payload + poff;
@@ -712,29 +771,40 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
left_to_copy = cop;
while (left_to_copy) {
+ struct pbuf_custom_ref *pcr;
newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len;
/* Is this pbuf already empty? */
if (!newpbuflen) {
p = p->next;
continue;
}
- newpbuf = pbuf_alloc(PBUF_RAW, 0, PBUF_REF);
- if (newpbuf == NULL) {
+ pcr = ip_frag_alloc_pbuf_custom_ref();
+ if (pcr == NULL) {
pbuf_free(rambuf);
return ERR_MEM;
}
/* Mirror this pbuf, although we might not need all of it. */
- newpbuf->payload = p->payload;
- newpbuf->len = newpbuf->tot_len = newpbuflen;
+ newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen);
+ if (newpbuf == NULL) {
+ ip_frag_free_pbuf_custom_ref(pcr);
+ pbuf_free(rambuf);
+ return ERR_MEM;
+ }
+ pbuf_ref(p);
+ pcr->original = p;
+ pcr->pc.custom_free_function = ipfrag_free_pbuf_custom;
+
/* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain
* so that it is removed when pbuf_dechain is later called on rambuf.
*/
pbuf_cat(rambuf, newpbuf);
left_to_copy -= newpbuflen;
- if (left_to_copy)
+ if (left_to_copy) {
p = p->next;
+ }
}
poff = newpbuflen;
+#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
#endif /* IP_FRAG_USES_STATIC_BUF */
/* Correct header */
@@ -744,8 +814,9 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
#if IP_FRAG_USES_STATIC_BUF
- if (last)
+ if (last) {
pbuf_realloc(rambuf, left + IP_HLEN);
+ }
/* This part is ugly: we alloc a RAM based pbuf for
* the link level header for each chunk and then
diff --git a/core/lwip/src/core/mem.c b/core/lwip/src/core/mem.c
index 83c97536..2934e5a9 100644
--- a/core/lwip/src/core/mem.c
+++ b/core/lwip/src/core/mem.c
@@ -61,6 +61,7 @@
#include "lwip/mem.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
+#include "lwip/err.h"
#include <string.h>
@@ -81,7 +82,7 @@ mem_malloc(mem_size_t size)
memp_t poolnr;
mem_size_t required_size = size + sizeof(struct memp_malloc_helper);
- for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr++) {
+ for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) {
#if MEM_USE_POOLS_TRY_BIGGER_POOL
again:
#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
@@ -154,7 +155,7 @@ mem_free(void *rmem)
struct mem {
/** index (-> ram[next]) of the next struct */
mem_size_t next;
- /** index (-> ram[next]) of the next struct */
+ /** index (-> ram[prev]) of the previous struct */
mem_size_t prev;
/** 1: this area is used; 0: this area is unused */
u8_t used;
@@ -171,8 +172,16 @@ struct mem {
#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
+/** If you want to relocate the heap to external memory, simply define
+ * LWIP_RAM_HEAP_POINTER as a void-pointer to that location.
+ * If so, make sure the memory at that location is big enough (see below on
+ * how that space is calculated). */
+#ifndef LWIP_RAM_HEAP_POINTER
/** the heap. we need one struct mem at the end and some room for alignment */
-static u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
+u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
+#define LWIP_RAM_HEAP_POINTER ram_heap
+#endif /* LWIP_RAM_HEAP_POINTER */
+
/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */
static u8_t *ram;
/** the last entry, always unused! */
@@ -181,7 +190,7 @@ static struct mem *ram_end;
static struct mem *lfree;
/** concurrent access protection */
-static sys_sem_t mem_sem;
+static sys_mutex_t mem_mutex;
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
@@ -199,8 +208,8 @@ static volatile u8_t mem_free_count;
/* 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)
+#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex)
+#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex)
/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
#define LWIP_MEM_ALLOC_DECL_PROTECT()
#define LWIP_MEM_ALLOC_PROTECT()
@@ -215,7 +224,7 @@ static volatile u8_t mem_free_count;
* one empty struct mem pointing to another empty struct mem.
*
* @param mem this points to a struct mem which just has been freed
- * @internal this function is only called by mem_free() and mem_realloc()
+ * @internal this function is only called by mem_free() and mem_trim()
*
* This assumes access to the heap is protected by the calling function
* already.
@@ -233,25 +242,25 @@ plug_holes(struct mem *mem)
/* plug hole forward */
LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED);
- nmem = (struct mem *)&ram[mem->next];
+ nmem = (struct mem *)(void *)&ram[mem->next];
if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
/* if mem->next is unused and not end of ram, combine mem and mem->next */
if (lfree == nmem) {
lfree = mem;
}
mem->next = nmem->next;
- ((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;
+ ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram);
}
/* plug hole backward */
- pmem = (struct mem *)&ram[mem->prev];
+ pmem = (struct mem *)(void *)&ram[mem->prev];
if (pmem != mem && pmem->used == 0) {
/* if mem->prev is unused, combine mem and mem->prev */
if (lfree == mem) {
lfree = pmem;
}
pmem->next = mem->next;
- ((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;
+ ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram);
}
}
@@ -267,24 +276,26 @@ lwip_mem_init(void)
(SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0);
/* align the heap */
- ram = LWIP_MEM_ALIGN(ram_heap);
+ ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER);
/* initialize the start of the heap */
- mem = (struct mem *)ram;
+ mem = (struct mem *)(void *)ram;
mem->next = MEM_SIZE_ALIGNED;
mem->prev = 0;
mem->used = 0;
/* initialize the end of the heap */
- ram_end = (struct mem *)&ram[MEM_SIZE_ALIGNED];
+ ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED];
ram_end->used = 1;
ram_end->next = MEM_SIZE_ALIGNED;
ram_end->prev = MEM_SIZE_ALIGNED;
- mem_sem = sys_sem_new(1);
-
/* initialize the lowest-free pointer to the start of the heap */
- lfree = (struct mem *)ram;
+ lfree = (struct mem *)(void *)ram;
MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
+
+ if(sys_mutex_new(&mem_mutex) != ERR_OK) {
+ LWIP_ASSERT("failed to create mem_mutex", 0);
+ }
}
/**
@@ -320,7 +331,7 @@ mem_free(void *rmem)
/* protect the heap from concurrent access */
LWIP_MEM_FREE_PROTECT();
/* Get the corresponding struct mem ... */
- mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
+ mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
/* ... which has to be in a used state ... */
LWIP_ASSERT("mem_free: mem->used", mem->used);
/* ... and is now unused. */
@@ -331,7 +342,7 @@ mem_free(void *rmem)
lfree = mem;
}
- MEM_STATS_DEC_USED(used, mem->next - ((u8_t *)mem - ram));
+ MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram)));
/* finally, see if prev or next are free also */
plug_holes(mem);
@@ -342,9 +353,7 @@ mem_free(void *rmem)
}
/**
- * In contrast to its name, mem_realloc can only shrink memory, not expand it.
- * Since the only use (for now) is in pbuf_realloc (which also can only shrink),
- * this shouldn't be a problem!
+ * Shrink memory returned by mem_malloc().
*
* @param rmem pointer to memory allocated by mem_malloc the is to be shrinked
* @param newsize required size after shrinking (needs to be smaller than or
@@ -354,7 +363,7 @@ mem_free(void *rmem)
* or freed!
*/
void *
-mem_realloc(void *rmem, mem_size_t newsize)
+mem_trim(void *rmem, mem_size_t newsize)
{
mem_size_t size;
mem_size_t ptr, ptr2;
@@ -375,12 +384,12 @@ mem_realloc(void *rmem, mem_size_t newsize)
return NULL;
}
- LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
+ LWIP_ASSERT("mem_trim: 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 | LWIP_DBG_LEVEL_SEVERE, ("mem_realloc: illegal memory\n"));
+ LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n"));
/* protect mem stats from concurrent access */
SYS_ARCH_PROTECT(lev);
MEM_STATS_INC(illegal);
@@ -388,12 +397,12 @@ mem_realloc(void *rmem, mem_size_t newsize)
return rmem;
}
/* Get the corresponding struct mem ... */
- mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
+ mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
/* ... and its offset pointer */
- ptr = (u8_t *)mem - ram;
+ ptr = (mem_size_t)((u8_t *)mem - ram);
size = mem->next - ptr - SIZEOF_STRUCT_MEM;
- LWIP_ASSERT("mem_realloc can only shrink memory", newsize <= size);
+ LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size);
if (newsize > size) {
/* not supported */
return NULL;
@@ -406,9 +415,7 @@ mem_realloc(void *rmem, mem_size_t newsize)
/* protect the heap from concurrent access */
LWIP_MEM_FREE_PROTECT();
- MEM_STATS_DEC_USED(used, (size - newsize));
-
- mem2 = (struct mem *)&ram[mem->next];
+ mem2 = (struct mem *)(void *)&ram[mem->next];
if(mem2->used == 0) {
/* The next struct is unused, we can simply move it at little */
mem_size_t next;
@@ -417,9 +424,9 @@ mem_realloc(void *rmem, mem_size_t newsize)
/* create new struct mem which is moved directly after the shrinked mem */
ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
if (lfree == mem2) {
- lfree = (struct mem *)&ram[ptr2];
+ lfree = (struct mem *)(void *)&ram[ptr2];
}
- mem2 = (struct mem *)&ram[ptr2];
+ mem2 = (struct mem *)(void *)&ram[ptr2];
mem2->used = 0;
/* restore the next pointer */
mem2->next = next;
@@ -431,8 +438,9 @@ mem_realloc(void *rmem, mem_size_t newsize)
* let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not
* the end of the heap */
if (mem2->next != MEM_SIZE_ALIGNED) {
- ((struct mem *)&ram[mem2->next])->prev = ptr2;
+ ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
}
+ MEM_STATS_DEC_USED(used, (size - newsize));
/* no need to plug holes, we've already done that */
} else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {
/* Next struct is used but there's room for another struct mem with
@@ -443,7 +451,7 @@ mem_realloc(void *rmem, mem_size_t newsize)
* 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 + newsize;
- mem2 = (struct mem *)&ram[ptr2];
+ mem2 = (struct mem *)(void *)&ram[ptr2];
if (mem2 < lfree) {
lfree = mem2;
}
@@ -452,8 +460,9 @@ mem_realloc(void *rmem, mem_size_t newsize)
mem2->prev = ptr;
mem->next = ptr2;
if (mem2->next != MEM_SIZE_ALIGNED) {
- ((struct mem *)&ram[mem2->next])->prev = ptr2;
+ ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
}
+ MEM_STATS_DEC_USED(used, (size - newsize));
/* the original mem->next is used, so no need to plug holes! */
}
/* else {
@@ -506,7 +515,7 @@ mem_malloc(mem_size_t size)
}
/* protect the heap from concurrent access */
- sys_arch_sem_wait(mem_sem, 0);
+ sys_mutex_lock(&mem_mutex);
LWIP_MEM_ALLOC_PROTECT();
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
/* run as long as a mem_free disturbed mem_malloc */
@@ -517,9 +526,9 @@ mem_malloc(mem_size_t size)
/* 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];
+ for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size;
+ ptr = ((struct mem *)(void *)&ram[ptr])->next) {
+ mem = (struct mem *)(void *)&ram[ptr];
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
mem_free_count = 0;
LWIP_MEM_ALLOC_UNPROTECT();
@@ -549,7 +558,7 @@ mem_malloc(mem_size_t size)
*/
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
/* create mem2 struct */
- mem2 = (struct mem *)&ram[ptr2];
+ mem2 = (struct mem *)(void *)&ram[ptr2];
mem2->used = 0;
mem2->next = mem->next;
mem2->prev = ptr;
@@ -558,7 +567,7 @@ mem_malloc(mem_size_t size)
mem->used = 1;
if (mem2->next != MEM_SIZE_ALIGNED) {
- ((struct mem *)&ram[mem2->next])->prev = ptr2;
+ ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
}
MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
} else {
@@ -570,7 +579,7 @@ mem_malloc(mem_size_t size)
* will always be used at this point!
*/
mem->used = 1;
- MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram));
+ MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram));
}
if (mem == lfree) {
@@ -579,12 +588,12 @@ mem_malloc(mem_size_t size)
LWIP_MEM_ALLOC_UNPROTECT();
/* prevent high interrupt latency... */
LWIP_MEM_ALLOC_PROTECT();
- lfree = (struct mem *)&ram[lfree->next];
+ lfree = (struct mem *)(void *)&ram[lfree->next];
}
LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
}
LWIP_MEM_ALLOC_UNPROTECT();
- sys_sem_signal(mem_sem);
+ sys_mutex_unlock(&mem_mutex);
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.",
@@ -602,7 +611,7 @@ mem_malloc(mem_size_t size)
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
MEM_STATS_INC(err);
LWIP_MEM_ALLOC_UNPROTECT();
- sys_sem_signal(mem_sem);
+ sys_mutex_unlock(&mem_mutex);
return NULL;
}
diff --git a/core/lwip/src/core/memp.c b/core/lwip/src/core/memp.c
index dea18154..4da879a5 100644
--- a/core/lwip/src/core/memp.c
+++ b/core/lwip/src/core/memp.c
@@ -44,15 +44,20 @@
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/raw.h"
-#include "lwip/tcp.h"
+#include "lwip/tcp_impl.h"
#include "lwip/igmp.h"
#include "lwip/api.h"
#include "lwip/api_msg.h"
#include "lwip/tcpip.h"
#include "lwip/sys.h"
+#include "lwip/timers.h"
#include "lwip/stats.h"
#include "netif/etharp.h"
#include "lwip/ip_frag.h"
+#include "lwip/snmp_structs.h"
+#include "lwip/snmp_msg.h"
+#include "lwip/dns.h"
+#include "netif/ppp_oe.h"
#include <string.h>
@@ -142,12 +147,33 @@ static const char *memp_desc[MEMP_MAX] = {
};
#endif /* LWIP_DEBUG */
-/** This is the actual memory used by the pools. */
+#if MEMP_SEPARATE_POOLS
+
+/** This creates each memory pool. These are named memp_memory_XXX_base (where
+ * XXX is the name of the pool defined in memp_std.h).
+ * To relocate a pool, declare it as extern in cc.h. Example for GCC:
+ * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_UDP_PCB_base[];
+ */
+#define LWIP_MEMPOOL(name,num,size,desc) u8_t memp_memory_ ## name ## _base \
+ [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))];
+#include "lwip/memp_std.h"
+
+/** This array holds the base of each memory pool. */
+static u8_t *const memp_bases[] = {
+#define LWIP_MEMPOOL(name,num,size,desc) memp_memory_ ## name ## _base,
+#include "lwip/memp_std.h"
+};
+
+#else /* MEMP_SEPARATE_POOLS */
+
+/** This is the actual memory used by the pools (all pools in one big block). */
static u8_t memp_memory[MEM_ALIGNMENT - 1
#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) )
#include "lwip/memp_std.h"
];
+#endif /* MEMP_SEPARATE_POOLS */
+
#if MEMP_SANITY_CHECK
/**
* Check that memp-lists don't form a circle
@@ -172,31 +198,74 @@ memp_sanity(void)
}
#endif /* MEMP_SANITY_CHECK*/
#if MEMP_OVERFLOW_CHECK
+#if defined(LWIP_DEBUG) && MEMP_STATS
+static const char * memp_overflow_names[] = {
+#define LWIP_MEMPOOL(name,num,size,desc) "/"desc,
+#include "lwip/memp_std.h"
+ };
+#endif
+
/**
* Check if a memp element was victim of an overflow
* (e.g. the restricted area after it has been altered)
*
* @param p the memp element to check
- * @param memp_size the element size of the pool p comes from
+ * @param memp_type the pool p comes from
*/
static void
-memp_overflow_check_element(struct memp *p, u16_t memp_size)
+memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type)
{
u16_t k;
u8_t *m;
-#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
- m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
- for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) {
+#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
+ m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type];
+ for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
if (m[k] != 0xcd) {
- LWIP_ASSERT("detected memp underflow!", 0);
+ char errstr[128] = "detected memp overflow in pool ";
+ char digit[] = "0";
+ if(memp_type >= 10) {
+ digit[0] = '0' + (memp_type/10);
+ strcat(errstr, digit);
+ }
+ digit[0] = '0' + (memp_type%10);
+ strcat(errstr, digit);
+#if defined(LWIP_DEBUG) && MEMP_STATS
+ strcat(errstr, memp_overflow_names[memp_type]);
+#endif
+ LWIP_ASSERT(errstr, 0);
}
}
#endif
-#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
- m = (u8_t*)p + MEMP_SIZE + memp_size;
- for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
+}
+
+/**
+ * Check if a memp element was victim of an underflow
+ * (e.g. the restricted area before it has been altered)
+ *
+ * @param p the memp element to check
+ * @param memp_type the pool p comes from
+ */
+static void
+memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type)
+{
+ u16_t k;
+ u8_t *m;
+#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
+ m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
+ for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) {
if (m[k] != 0xcd) {
- LWIP_ASSERT("detected memp overflow!", 0);
+ char errstr[128] = "detected memp underflow in pool ";
+ char digit[] = "0";
+ if(memp_type >= 10) {
+ digit[0] = '0' + (memp_type/10);
+ strcat(errstr, digit);
+ }
+ digit[0] = '0' + (memp_type%10);
+ strcat(errstr, digit);
+#if defined(LWIP_DEBUG) && MEMP_STATS
+ strcat(errstr, memp_overflow_names[memp_type]);
+#endif
+ LWIP_ASSERT(errstr, 0);
}
}
#endif
@@ -213,11 +282,19 @@ memp_overflow_check_all(void)
u16_t i, j;
struct memp *p;
- p = LWIP_MEM_ALIGN(memp_memory);
+ p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
+ for (i = 0; i < MEMP_MAX; ++i) {
+ p = p;
+ for (j = 0; j < memp_num[i]; ++j) {
+ memp_overflow_check_element_overflow(p, i);
+ p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
+ }
+ }
+ p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
for (i = 0; i < MEMP_MAX; ++i) {
p = p;
for (j = 0; j < memp_num[i]; ++j) {
- memp_overflow_check_element(p, memp_sizes[i]);
+ memp_overflow_check_element_underflow(p, i);
p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
}
}
@@ -233,7 +310,7 @@ memp_overflow_init(void)
struct memp *p;
u8_t *m;
- p = LWIP_MEM_ALIGN(memp_memory);
+ p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
for (i = 0; i < MEMP_MAX; ++i) {
p = p;
for (j = 0; j < memp_num[i]; ++j) {
@@ -269,15 +346,20 @@ memp_init(void)
MEMP_STATS_AVAIL(avail, i, memp_num[i]);
}
- memp = LWIP_MEM_ALIGN(memp_memory);
+#if !MEMP_SEPARATE_POOLS
+ memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
+#endif /* !MEMP_SEPARATE_POOLS */
/* for every pool: */
for (i = 0; i < MEMP_MAX; ++i) {
memp_tab[i] = NULL;
+#if MEMP_SEPARATE_POOLS
+ memp = (struct memp*)memp_bases[i];
+#endif /* MEMP_SEPARATE_POOLS */
/* create a linked list of memp elements */
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 *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i]
#if MEMP_OVERFLOW_CHECK
+ MEMP_SANITY_REGION_AFTER_ALIGNED
#endif
@@ -331,7 +413,7 @@ memp_malloc_fn(memp_t type, const char* file, const int line)
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);
+ memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE);
} else {
LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
MEMP_STATS_INC(err, type);
@@ -360,14 +442,15 @@ memp_free(memp_t type, void *mem)
LWIP_ASSERT("memp_free: mem properly aligned",
((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);
- memp = (struct memp *)((u8_t*)mem - MEMP_SIZE);
+ memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE);
SYS_ARCH_PROTECT(old_level);
#if MEMP_OVERFLOW_CHECK
#if MEMP_OVERFLOW_CHECK >= 2
memp_overflow_check_all();
#else
- memp_overflow_check_element(memp, memp_sizes[type]);
+ memp_overflow_check_element_overflow(memp, type);
+ memp_overflow_check_element_underflow(memp, type);
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
#endif /* MEMP_OVERFLOW_CHECK */
diff --git a/core/lwip/src/core/netif.c b/core/lwip/src/core/netif.c
index b52cd02a..f190b1f2 100644
--- a/core/lwip/src/core/netif.c
+++ b/core/lwip/src/core/netif.c
@@ -41,10 +41,11 @@
#include "lwip/def.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
-#include "lwip/tcp.h"
+#include "lwip/tcp_impl.h"
#include "lwip/snmp.h"
#include "lwip/igmp.h"
#include "netif/etharp.h"
+#include "lwip/stats.h"
#if ENABLE_LOOPBACK
#include "lwip/sys.h"
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
@@ -60,20 +61,64 @@
#endif /* LWIP_DHCP */
#if LWIP_NETIF_STATUS_CALLBACK
-#define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }
+#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0)
#else
-#define NETIF_STATUS_CALLBACK(n) { /* NOP */ }
+#define NETIF_STATUS_CALLBACK(n)
#endif /* LWIP_NETIF_STATUS_CALLBACK */
#if LWIP_NETIF_LINK_CALLBACK
-#define NETIF_LINK_CALLBACK(n) { if (n->link_callback) (n->link_callback)(n); }
+#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0)
#else
-#define NETIF_LINK_CALLBACK(n) { /* NOP */ }
+#define NETIF_LINK_CALLBACK(n)
#endif /* LWIP_NETIF_LINK_CALLBACK */
struct netif *netif_list;
struct netif *netif_default;
+#if LWIP_HAVE_LOOPIF
+static struct netif loop_netif;
+
+/**
+ * Initialize a lwip network interface structure for a loopback interface
+ *
+ * @param netif the lwip network interface structure for this loopif
+ * @return ERR_OK if the loopif is initialized
+ * ERR_MEM if private data couldn't be allocated
+ */
+static err_t
+netif_loopif_init(struct netif *netif)
+{
+ /* initialize the snmp variables and counters inside the struct netif
+ * ifSpeed: no assumption can be made!
+ */
+ NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0);
+
+ netif->name[0] = 'l';
+ netif->name[1] = 'o';
+ netif->output = netif_loop_output;
+ return ERR_OK;
+}
+#endif /* LWIP_HAVE_LOOPIF */
+
+void
+netif_init(void)
+{
+#if LWIP_HAVE_LOOPIF
+ ip_addr_t loop_ipaddr, loop_netmask, loop_gw;
+ IP4_ADDR(&loop_gw, 127,0,0,1);
+ IP4_ADDR(&loop_ipaddr, 127,0,0,1);
+ IP4_ADDR(&loop_netmask, 255,0,0,0);
+
+#if NO_SYS
+ netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input);
+#else /* NO_SYS */
+ netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input);
+#endif /* NO_SYS */
+ netif_set_up(&loop_netif);
+
+#endif /* LWIP_HAVE_LOOPIF */
+}
+
/**
* Add a network interface to the list of lwIP netifs.
*
@@ -89,18 +134,17 @@ struct netif *netif_default;
* @return netif, or NULL if failed.
*/
struct netif *
-netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
- struct ip_addr *gw,
- void *state,
- err_t (* init)(struct netif *netif),
- err_t (* input)(struct pbuf *p, struct netif *netif))
+netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
+ ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
{
static u8_t netifnum = 0;
+ LWIP_ASSERT("No init function given", init != NULL);
+
/* reset new interface configuration state */
- netif->ip_addr.addr = 0;
- netif->netmask.addr = 0;
- netif->gw.addr = 0;
+ ip_addr_set_zero(&netif->ip_addr);
+ ip_addr_set_zero(&netif->netmask);
+ ip_addr_set_zero(&netif->gw);
netif->flags = 0;
#if LWIP_DHCP
/* netif not under DHCP control by default */
@@ -150,7 +194,7 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
#if LWIP_IGMP
/* start IGMP processing */
if (netif->flags & NETIF_FLAG_IGMP) {
- igmp_start( netif);
+ igmp_start(netif);
}
#endif /* LWIP_IGMP */
@@ -175,8 +219,8 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
* @param gw the new default gateway
*/
void
-netif_set_addr(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
- struct ip_addr *gw)
+netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
+ ip_addr_t *gw)
{
netif_set_ipaddr(netif, ipaddr);
netif_set_netmask(netif, netmask);
@@ -188,41 +232,47 @@ netif_set_addr(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netm
*
* @param netif the network interface to remove
*/
-void netif_remove(struct netif * netif)
+void
+netif_remove(struct netif *netif)
{
- if ( netif == NULL ) return;
+ if (netif == NULL) {
+ return;
+ }
#if LWIP_IGMP
/* stop IGMP processing */
if (netif->flags & NETIF_FLAG_IGMP) {
- igmp_stop( netif);
+ igmp_stop(netif);
}
#endif /* LWIP_IGMP */
+ if (netif_is_up(netif)) {
+ /* set netif down before removing (call callback function) */
+ netif_set_down(netif);
+ }
snmp_delete_ipaddridx_tree(netif);
/* is it the first netif? */
if (netif_list == netif) {
netif_list = netif->next;
- snmp_dec_iflist();
- }
- else {
+ } else {
/* look for netif further down the list */
struct netif * tmpNetif;
for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) {
if (tmpNetif->next == netif) {
tmpNetif->next = netif->next;
- snmp_dec_iflist();
break;
}
}
if (tmpNetif == NULL)
return; /* we didn't find any netif today */
}
+ snmp_dec_iflist();
/* this netif is default? */
- if (netif_default == netif)
+ if (netif_default == netif) {
/* reset default netif */
netif_set_default(NULL);
+ }
LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
}
@@ -266,7 +316,7 @@ netif_find(char *name)
* default gateway
*/
void
-netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
+netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)
{
/* TODO: Handling of obsolete pcbs */
/* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */
@@ -275,14 +325,18 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
struct tcp_pcb_listen *lpcb;
/* address is actually being changed? */
- if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
- {
+ if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) {
/* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
pcb = tcp_active_pcbs;
while (pcb != NULL) {
/* PCB bound to current local interface address? */
- if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
+ if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))
+#if LWIP_AUTOIP
+ /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */
+ && !ip_addr_islinklocal(&(pcb->local_ip))
+#endif /* LWIP_AUTOIP */
+ ) {
/* this connection must be aborted */
struct tcp_pcb *next = pcb->next;
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
@@ -312,10 +366,10 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
- ip4_addr1(&netif->ip_addr),
- ip4_addr2(&netif->ip_addr),
- ip4_addr3(&netif->ip_addr),
- ip4_addr4(&netif->ip_addr)));
+ ip4_addr1_16(&netif->ip_addr),
+ ip4_addr2_16(&netif->ip_addr),
+ ip4_addr3_16(&netif->ip_addr),
+ ip4_addr4_16(&netif->ip_addr)));
}
/**
@@ -327,15 +381,15 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
* @note call netif_set_addr() if you also want to change ip address and netmask
*/
void
-netif_set_gw(struct netif *netif, struct ip_addr *gw)
+netif_set_gw(struct netif *netif, ip_addr_t *gw)
{
ip_addr_set(&(netif->gw), gw);
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
- ip4_addr1(&netif->gw),
- ip4_addr2(&netif->gw),
- ip4_addr3(&netif->gw),
- ip4_addr4(&netif->gw)));
+ ip4_addr1_16(&netif->gw),
+ ip4_addr2_16(&netif->gw),
+ ip4_addr3_16(&netif->gw),
+ ip4_addr4_16(&netif->gw)));
}
/**
@@ -348,7 +402,7 @@ netif_set_gw(struct netif *netif, struct ip_addr *gw)
* default gateway
*/
void
-netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
+netif_set_netmask(struct netif *netif, ip_addr_t *netmask)
{
snmp_delete_iprteidx_tree(0, netif);
/* set new netmask to netif */
@@ -356,10 +410,10 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
snmp_insert_iprteidx_tree(0, netif);
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
- ip4_addr1(&netif->netmask),
- ip4_addr2(&netif->netmask),
- ip4_addr3(&netif->netmask),
- ip4_addr4(&netif->netmask)));
+ ip4_addr1_16(&netif->netmask),
+ ip4_addr2_16(&netif->netmask),
+ ip4_addr3_16(&netif->netmask),
+ ip4_addr4_16(&netif->netmask)));
}
/**
@@ -371,13 +425,10 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
void
netif_set_default(struct netif *netif)
{
- if (netif == NULL)
- {
+ if (netif == NULL) {
/* remove default route */
snmp_delete_iprteidx_tree(1, netif);
- }
- else
- {
+ } else {
/* install default route */
snmp_insert_iprteidx_tree(1, netif);
}
@@ -397,29 +448,30 @@ netif_set_default(struct netif *netif)
*/
void netif_set_up(struct netif *netif)
{
- if ( !(netif->flags & NETIF_FLAG_UP )) {
+ if (!(netif->flags & NETIF_FLAG_UP)) {
netif->flags |= NETIF_FLAG_UP;
#if LWIP_SNMP
snmp_get_sysuptime(&netif->ts);
#endif /* LWIP_SNMP */
- NETIF_LINK_CALLBACK(netif);
NETIF_STATUS_CALLBACK(netif);
+ if (netif->flags & NETIF_FLAG_LINK_UP) {
#if LWIP_ARP
- /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
- if (netif->flags & NETIF_FLAG_ETHARP) {
- etharp_gratuitous(netif);
- }
+ /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
+ if (netif->flags & (NETIF_FLAG_ETHARP)) {
+ etharp_gratuitous(netif);
+ }
#endif /* LWIP_ARP */
#if LWIP_IGMP
- /* resend IGMP memberships */
- if (netif->flags & NETIF_FLAG_IGMP) {
- igmp_report_groups( netif);
- }
+ /* resend IGMP memberships */
+ if (netif->flags & NETIF_FLAG_IGMP) {
+ igmp_report_groups( netif);
+ }
#endif /* LWIP_IGMP */
+ }
}
}
@@ -433,73 +485,65 @@ void netif_set_up(struct netif *netif)
*/
void netif_set_down(struct netif *netif)
{
- if ( netif->flags & NETIF_FLAG_UP )
- {
- netif->flags &= ~NETIF_FLAG_UP;
+ if (netif->flags & NETIF_FLAG_UP) {
+ netif->flags &= ~NETIF_FLAG_UP;
#if LWIP_SNMP
- snmp_get_sysuptime(&netif->ts);
+ snmp_get_sysuptime(&netif->ts);
#endif
-
- NETIF_LINK_CALLBACK(netif);
- NETIF_STATUS_CALLBACK(netif);
- }
-}
-/**
- * Ask if an interface is up
- */
-u8_t netif_is_up(struct netif *netif)
-{
- return (netif->flags & NETIF_FLAG_UP)?1:0;
+ NETIF_STATUS_CALLBACK(netif);
+ }
}
#if LWIP_NETIF_STATUS_CALLBACK
/**
* Set callback to be called when interface is brought up/down
*/
-void netif_set_status_callback(struct netif *netif, void (* status_callback)(struct netif *netif ))
+void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)
{
- if ( netif )
- netif->status_callback = status_callback;
+ if (netif) {
+ netif->status_callback = status_callback;
+ }
}
#endif /* LWIP_NETIF_STATUS_CALLBACK */
-#if LWIP_NETIF_LINK_CALLBACK
/**
* Called by a driver when its link goes up
*/
void netif_set_link_up(struct netif *netif )
{
- netif->flags |= NETIF_FLAG_LINK_UP;
+ if (!(netif->flags & NETIF_FLAG_LINK_UP)) {
+ netif->flags |= NETIF_FLAG_LINK_UP;
#if LWIP_DHCP
- if (netif->dhcp) {
- dhcp_network_changed(netif);
- }
+ if (netif->dhcp) {
+ dhcp_network_changed(netif);
+ }
#endif /* LWIP_DHCP */
#if LWIP_AUTOIP
- if (netif->autoip) {
- autoip_network_changed(netif);
- }
+ if (netif->autoip) {
+ autoip_network_changed(netif);
+ }
#endif /* LWIP_AUTOIP */
- if (netif->flags & NETIF_FLAG_UP) {
+ if (netif->flags & NETIF_FLAG_UP) {
#if LWIP_ARP
- /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
- if (netif->flags & NETIF_FLAG_ETHARP) {
- etharp_gratuitous(netif);
- }
+ /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
+ if (netif->flags & NETIF_FLAG_ETHARP) {
+ etharp_gratuitous(netif);
+ }
#endif /* LWIP_ARP */
#if LWIP_IGMP
- /* resend IGMP memberships */
- if (netif->flags & NETIF_FLAG_IGMP) {
- igmp_report_groups( netif);
- }
+ /* resend IGMP memberships */
+ if (netif->flags & NETIF_FLAG_IGMP) {
+ igmp_report_groups( netif);
+ }
#endif /* LWIP_IGMP */
+ }
+ NETIF_LINK_CALLBACK(netif);
}
- NETIF_LINK_CALLBACK(netif);
}
/**
@@ -507,22 +551,17 @@ void netif_set_link_up(struct netif *netif )
*/
void netif_set_link_down(struct netif *netif )
{
- netif->flags &= ~NETIF_FLAG_LINK_UP;
- NETIF_LINK_CALLBACK(netif);
-}
-
-/**
- * Ask if a link is up
- */
-u8_t netif_is_link_up(struct netif *netif)
-{
- return (netif->flags & NETIF_FLAG_LINK_UP) ? 1 : 0;
+ if (netif->flags & NETIF_FLAG_LINK_UP) {
+ netif->flags &= ~NETIF_FLAG_LINK_UP;
+ NETIF_LINK_CALLBACK(netif);
+ }
}
+#if LWIP_NETIF_LINK_CALLBACK
/**
* Set callback to be called when link is brought up/down
*/
-void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif ))
+void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)
{
if (netif) {
netif->link_callback = link_callback;
@@ -547,7 +586,7 @@ void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct
*/
err_t
netif_loop_output(struct netif *netif, struct pbuf *p,
- struct ip_addr *ipaddr)
+ ip_addr_t *ipaddr)
{
struct pbuf *r;
err_t err;
@@ -555,22 +594,36 @@ netif_loop_output(struct netif *netif, struct pbuf *p,
#if LWIP_LOOPBACK_MAX_PBUFS
u8_t clen = 0;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
+ /* If we have a loopif, SNMP counters are adjusted for it,
+ * if not they are adjusted for 'netif'. */
+#if LWIP_SNMP
+#if LWIP_HAVE_LOOPIF
+ struct netif *stats_if = &loop_netif;
+#else /* LWIP_HAVE_LOOPIF */
+ struct netif *stats_if = netif;
+#endif /* LWIP_HAVE_LOOPIF */
+#endif /* LWIP_SNMP */
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) {
+ LINK_STATS_INC(link.memerr);
+ LINK_STATS_INC(link.drop);
+ snmp_inc_ifoutdiscards(stats_if);
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) > LWIP_LOOPBACK_MAX_PBUFS)) {
+ pbuf_free(r);
+ LINK_STATS_INC(link.memerr);
+ LINK_STATS_INC(link.drop);
+ snmp_inc_ifoutdiscards(stats_if);
+ return ERR_MEM;
}
netif->loop_cnt_current += clen;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
@@ -578,7 +631,9 @@ netif_loop_output(struct netif *netif, struct pbuf *p,
/* Copy the whole pbuf queue p into the single pbuf r */
if ((err = pbuf_copy(r, p)) != ERR_OK) {
pbuf_free(r);
- r = NULL;
+ LINK_STATS_INC(link.memerr);
+ LINK_STATS_INC(link.drop);
+ snmp_inc_ifoutdiscards(stats_if);
return err;
}
@@ -599,9 +654,13 @@ netif_loop_output(struct netif *netif, struct pbuf *p,
}
SYS_ARCH_UNPROTECT(lev);
+ LINK_STATS_INC(link.xmit);
+ snmp_add_ifoutoctets(stats_if, p->tot_len);
+ snmp_inc_ifoutucastpkts(stats_if);
+
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
/* For multithreading environment, schedule a call to netif_poll */
- tcpip_callback((void (*)(void *))(netif_poll), netif);
+ tcpip_callback((tcpip_callback_fn)netif_poll, netif);
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
return ERR_OK;
@@ -617,13 +676,22 @@ void
netif_poll(struct netif *netif)
{
struct pbuf *in;
+ /* If we have a loopif, SNMP counters are adjusted for it,
+ * if not they are adjusted for 'netif'. */
+#if LWIP_SNMP
+#if LWIP_HAVE_LOOPIF
+ struct netif *stats_if = &loop_netif;
+#else /* LWIP_HAVE_LOOPIF */
+ struct netif *stats_if = netif;
+#endif /* LWIP_HAVE_LOOPIF */
+#endif /* LWIP_SNMP */
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) {
+ if (in != NULL) {
struct pbuf *in_end = in;
#if LWIP_LOOPBACK_MAX_PBUFS
u8_t clen = pbuf_clen(in);
@@ -632,12 +700,12 @@ netif_poll(struct netif *netif)
((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) {
+ 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) {
+ if (in_end == netif->loop_last) {
/* this was the last pbuf in the list */
netif->loop_first = netif->loop_last = NULL;
} else {
@@ -650,16 +718,19 @@ netif_poll(struct netif *netif)
}
SYS_ARCH_UNPROTECT(lev);
- if(in != NULL) {
+ if (in != NULL) {
+ LINK_STATS_INC(link.recv);
+ snmp_add_ifinoctets(stats_if, in->tot_len);
+ snmp_inc_ifinucastpkts(stats_if);
/* loopback packets are always IP packets! */
- if(ip_input(in, netif) != ERR_OK) {
+ 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);
+ } while (netif->loop_first != NULL);
}
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
diff --git a/core/lwip/src/core/pbuf.c b/core/lwip/src/core/pbuf.c
index 11cc2e67..dd9ff64e 100644
--- a/core/lwip/src/core/pbuf.c
+++ b/core/lwip/src/core/pbuf.c
@@ -71,7 +71,10 @@
#include "lwip/sys.h"
#include "arch/perf.h"
#if TCP_QUEUE_OOSEQ
-#include "lwip/tcp.h"
+#include "lwip/tcp_impl.h"
+#endif
+#if LWIP_CHECKSUM_ON_COPY
+#include "lwip/inet_chksum.h"
#endif
#include <string.h>
@@ -81,9 +84,9 @@
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 || NO_SYS
+#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS
#define PBUF_POOL_IS_EMPTY()
-#else /* !TCP_QUEUE_OOSEQ || NO_SYS */
+#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS */
/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
#ifndef PBUF_POOL_FREE_OOSEQ
#define PBUF_POOL_FREE_OOSEQ 1
@@ -145,7 +148,7 @@ pbuf_pool_is_empty(void)
}
}
#endif /* PBUF_POOL_FREE_OOSEQ */
-#endif /* !TCP_QUEUE_OOSEQ || NO_SYS */
+#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS */
/**
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
@@ -211,7 +214,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);
+ p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
if (p == NULL) {
PBUF_POOL_IS_EMPTY();
@@ -244,7 +247,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);
+ q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
if (q == NULL) {
PBUF_POOL_IS_EMPTY();
/* free chain so far allocated */
@@ -298,7 +301,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
/* pbuf references existing (externally allocated) RAM payload? */
case PBUF_REF:
/* only allocate memory for the pbuf structure */
- p = memp_malloc(MEMP_PBUF);
+ p = (struct pbuf *)memp_malloc(MEMP_PBUF);
if (p == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n",
@@ -323,6 +326,67 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
return p;
}
+#if LWIP_SUPPORT_CUSTOM_PBUF
+/** Initialize a custom pbuf (already allocated).
+ *
+ * @param layer flag to define header size
+ * @param length size of the pbuf's payload
+ * @param type type of the pbuf (only used to treat the pbuf accordingly, as
+ * this function allocates no memory)
+ * @param p pointer to the custom pbuf to initialize (already allocated)
+ * @param payload_mem pointer to the buffer that is used for payload and headers,
+ * must be at least big enough to hold 'length' plus the header size,
+ * may be NULL if set later
+ * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least
+ * big enough to hold 'length' plus the header size
+ */
+struct pbuf*
+pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p,
+ void *payload_mem, u16_t payload_mem_len)
+{
+ u16_t offset;
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length));
+
+ /* determine header offset */
+ offset = 0;
+ switch (l) {
+ case PBUF_TRANSPORT:
+ /* add room for transport (often TCP) layer header */
+ offset += PBUF_TRANSPORT_HLEN;
+ /* FALLTHROUGH */
+ case PBUF_IP:
+ /* add room for IP layer header */
+ offset += PBUF_IP_HLEN;
+ /* FALLTHROUGH */
+ case PBUF_LINK:
+ /* add room for link layer header */
+ offset += PBUF_LINK_HLEN;
+ break;
+ case PBUF_RAW:
+ break;
+ default:
+ LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0);
+ return NULL;
+ }
+
+ if (LWIP_MEM_ALIGN_SIZE(offset) + length < payload_mem_len) {
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length));
+ return NULL;
+ }
+
+ p->pbuf.next = NULL;
+ if (payload_mem != NULL) {
+ p->pbuf.payload = LWIP_MEM_ALIGN((void *)((u8_t *)payload_mem + offset));
+ } else {
+ p->pbuf.payload = NULL;
+ }
+ p->pbuf.flags = PBUF_FLAG_IS_CUSTOM;
+ p->pbuf.len = p->pbuf.tot_len = length;
+ p->pbuf.type = type;
+ p->pbuf.ref = 1;
+ return &p->pbuf;
+}
+#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
/**
* Shrink a pbuf chain to a desired length.
@@ -383,8 +447,8 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
/* (other types merely adjust their length fields */
if ((q->type == PBUF_RAM) && (rem_len != q->len)) {
/* reallocate and adjust the length of the pbuf that will be split */
- q = mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rem_len);
- LWIP_ASSERT("mem_realloc give q == NULL", q != NULL);
+ q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len);
+ LWIP_ASSERT("mem_trim returned q == NULL", q != NULL);
}
/* adjust length fields for new last pbuf */
q->len = rem_len;
@@ -428,8 +492,9 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
u16_t increment_magnitude;
LWIP_ASSERT("p != NULL", p != NULL);
- if ((header_size_increment == 0) || (p == NULL))
+ if ((header_size_increment == 0) || (p == NULL)) {
return 0;
+ }
if (header_size_increment < 0){
increment_magnitude = -header_size_increment;
@@ -478,8 +543,7 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
* bail out unsuccesfully */
return 1;
}
- }
- else {
+ } else {
/* Unknown type */
LWIP_ASSERT("bad pbuf type", 0);
return 1;
@@ -570,15 +634,25 @@ pbuf_free(struct pbuf *p)
q = p->next;
LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p));
type = p->type;
- /* is this a pbuf from the pool? */
- if (type == PBUF_POOL) {
- memp_free(MEMP_PBUF_POOL, p);
- /* is this a ROM or RAM referencing pbuf? */
- } else if (type == PBUF_ROM || type == PBUF_REF) {
- memp_free(MEMP_PBUF, p);
- /* type == PBUF_RAM */
- } else {
- mem_free(p);
+#if LWIP_SUPPORT_CUSTOM_PBUF
+ /* is this a custom pbuf? */
+ if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) {
+ struct pbuf_custom *pc = (struct pbuf_custom*)p;
+ LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL);
+ pc->custom_free_function(p);
+ } else
+#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
+ {
+ /* is this a pbuf from the pool? */
+ if (type == PBUF_POOL) {
+ memp_free(MEMP_PBUF_POOL, p);
+ /* is this a ROM or RAM referencing pbuf? */
+ } else if (type == PBUF_ROM || type == PBUF_REF) {
+ memp_free(MEMP_PBUF, p);
+ /* type == PBUF_RAM */
+ } else {
+ mem_free(p);
+ }
}
count++;
/* proceed to next pbuf */
@@ -900,8 +974,8 @@ pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
/**
* 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!
+ * @remark: Either the source pbuf 'p' is freed by this function or the original
+ * pbuf 'p' is returned, therefore the caller has to check the result!
*
* @param p the source pbuf
* @param layer pbuf_layer of the new pbuf
@@ -927,3 +1001,156 @@ pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
pbuf_free(p);
return q;
}
+
+#if LWIP_CHECKSUM_ON_COPY
+/**
+ * Copies data into a single pbuf (*not* into a pbuf queue!) and updates
+ * the checksum while copying
+ *
+ * @param p the pbuf to copy data into
+ * @param start_offset offset of p->payload where to copy the data to
+ * @param dataptr data to copy into the pbuf
+ * @param len length of data to copy into the pbuf
+ * @param chksum pointer to the checksum which is updated
+ * @return ERR_OK if successful, another error if the data does not fit
+ * within the (first) pbuf (no pbuf queues!)
+ */
+err_t
+pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
+ u16_t len, u16_t *chksum)
+{
+ u32_t acc;
+ u16_t copy_chksum;
+ char *dst_ptr;
+ LWIP_ASSERT("p != NULL", p != NULL);
+ LWIP_ASSERT("dataptr != NULL", dataptr != NULL);
+ LWIP_ASSERT("chksum != NULL", chksum != NULL);
+ LWIP_ASSERT("len != 0", len != 0);
+
+ if ((start_offset >= p->len) || (start_offset + len > p->len)) {
+ return ERR_ARG;
+ }
+
+ dst_ptr = ((char*)p->payload) + start_offset;
+ copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len);
+ if ((start_offset & 1) != 0) {
+ copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum);
+ }
+ acc = *chksum;
+ acc += copy_chksum;
+ *chksum = FOLD_U32T(acc);
+ return ERR_OK;
+}
+#endif /* LWIP_CHECKSUM_ON_COPY */
+
+ /** Get one byte from the specified position in a pbuf
+ * WARNING: returns zero for offset >= p->tot_len
+ *
+ * @param p pbuf to parse
+ * @param offset offset into p of the byte to return
+ * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len
+ */
+u8_t
+pbuf_get_at(struct pbuf* p, u16_t offset)
+{
+ u16_t copy_from = offset;
+ struct pbuf* q = p;
+
+ /* get the correct pbuf */
+ while ((q != NULL) && (q->len <= copy_from)) {
+ copy_from -= q->len;
+ q = q->next;
+ }
+ /* return requested data if pbuf is OK */
+ if ((q != NULL) && (q->len > copy_from)) {
+ return ((u8_t*)q->payload)[copy_from];
+ }
+ return 0;
+}
+
+/** Compare pbuf contents at specified offset with memory s2, both of length n
+ *
+ * @param p pbuf to compare
+ * @param offset offset into p at wich to start comparing
+ * @param s2 buffer to compare
+ * @param n length of buffer to compare
+ * @return zero if equal, nonzero otherwise
+ * (0xffff if p is too short, diffoffset+1 otherwise)
+ */
+u16_t
+pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n)
+{
+ u16_t start = offset;
+ struct pbuf* q = p;
+
+ /* get the correct pbuf */
+ while ((q != NULL) && (q->len <= start)) {
+ start -= q->len;
+ q = q->next;
+ }
+ /* return requested data if pbuf is OK */
+ if ((q != NULL) && (q->len > start)) {
+ u16_t i;
+ for(i = 0; i < n; i++) {
+ u8_t a = pbuf_get_at(q, start + i);
+ u8_t b = ((u8_t*)s2)[i];
+ if (a != b) {
+ return i+1;
+ }
+ }
+ return 0;
+ }
+ return 0xffff;
+}
+
+/** Find occurrence of mem (with length mem_len) in pbuf p, starting at offset
+ * start_offset.
+ *
+ * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as
+ * return value 'not found'
+ * @param mem search for the contents of this buffer
+ * @param mem_len length of 'mem'
+ * @param start_offset offset into p at which to start searching
+ * @return 0xFFFF if substr was not found in p or the index where it was found
+ */
+u16_t
+pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)
+{
+ u16_t i;
+ u16_t max = p->tot_len - mem_len;
+ if (p->tot_len >= mem_len + start_offset) {
+ for(i = start_offset; i <= max; ) {
+ u16_t plus = pbuf_memcmp(p, i, mem, mem_len);
+ if (plus == 0) {
+ return i;
+ } else {
+ i += plus;
+ }
+ }
+ }
+ return 0xFFFF;
+}
+
+/** Find occurrence of substr with length substr_len in pbuf p, start at offset
+ * start_offset
+ * WARNING: in contrast to strstr(), this one does not stop at the first \0 in
+ * the pbuf/source string!
+ *
+ * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as
+ * return value 'not found'
+ * @param substr string to search for in p, maximum length is 0xFFFE
+ * @return 0xFFFF if substr was not found in p or the index where it was found
+ */
+u16_t
+pbuf_strstr(struct pbuf* p, const char* substr)
+{
+ size_t substr_len;
+ if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) {
+ return 0xFFFF;
+ }
+ substr_len = strlen(substr);
+ if (substr_len >= 0xFFFF) {
+ return 0xFFFF;
+ }
+ return pbuf_memfind(p, substr, (u16_t)substr_len, 0);
+}
diff --git a/core/lwip/src/core/raw.c b/core/lwip/src/core/raw.c
index 2f105fe6..9fcb1003 100644
--- a/core/lwip/src/core/raw.c
+++ b/core/lwip/src/core/raw.c
@@ -44,12 +44,10 @@
#include "lwip/def.h"
#include "lwip/memp.h"
-#include "lwip/inet.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/raw.h"
#include "lwip/stats.h"
-#include "lwip/snmp.h"
#include "arch/perf.h"
#include <string.h>
@@ -84,7 +82,7 @@ raw_input(struct pbuf *p, struct netif *inp)
LWIP_UNUSED_ARG(inp);
- iphdr = p->payload;
+ iphdr = (struct ip_hdr *)p->payload;
proto = IPH_PROTO(iphdr);
prev = NULL;
@@ -92,16 +90,18 @@ raw_input(struct pbuf *p, struct netif *inp)
/* loop through all raw pcbs until the packet is eaten by one */
/* this allows multiple pcbs to match against the packet by design */
while ((eaten == 0) && (pcb != NULL)) {
- if (pcb->protocol == proto) {
+ if ((pcb->protocol == proto) &&
+ (ip_addr_isany(&pcb->local_ip) ||
+ ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest))) {
#if IP_SOF_BROADCAST_RECV
/* broadcast filter? */
- if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(&(iphdr->dest), inp))
+ if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(&current_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) {
+ if (pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()) != 0) {
/* receive function ate the packet */
p = NULL;
eaten = 1;
@@ -139,7 +139,7 @@ raw_input(struct pbuf *p, struct netif *inp)
* @see raw_disconnect()
*/
err_t
-raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
+raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
{
ip_addr_set(&pcb->local_ip, ipaddr);
return ERR_OK;
@@ -159,7 +159,7 @@ raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
* @see raw_disconnect() and raw_sendto()
*/
err_t
-raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
+raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr)
{
ip_addr_set(&pcb->remote_ip, ipaddr);
return ERR_OK;
@@ -180,10 +180,7 @@ raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
* available for others.
*/
void
-raw_recv(struct raw_pcb *pcb,
- u8_t (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
- struct ip_addr *addr),
- void *recv_arg)
+raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
{
/* remember recv() callback and user data */
pcb->recv = recv;
@@ -203,11 +200,11 @@ raw_recv(struct raw_pcb *pcb,
*
*/
err_t
-raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
+raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
{
err_t err;
struct netif *netif;
- struct ip_addr *src_ip;
+ ip_addr_t *src_ip;
struct pbuf *q; /* q will be sent down the stack */
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
@@ -221,8 +218,10 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
return ERR_MEM;
}
- /* chain header q in front of given pbuf p */
- pbuf_chain(q, p);
+ if (p->tot_len != 0) {
+ /* chain header q in front of given pbuf p */
+ pbuf_chain(q, p);
+ }
/* { first pbuf q points to header pbuf } */
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
} else {
@@ -235,7 +234,8 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
}
if ((netif = ip_route(ipaddr)) == NULL) {
- LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
/* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) {
pbuf_free(q);
@@ -245,7 +245,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
#if IP_SOF_BROADCAST
/* broadcast filter? */
- if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif) ) {
+ if (((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif)) {
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
/* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) {
@@ -332,12 +332,13 @@ raw_remove(struct raw_pcb *pcb)
* @see raw_remove()
*/
struct raw_pcb *
-raw_new(u8_t proto) {
+raw_new(u8_t proto)
+{
struct raw_pcb *pcb;
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n"));
- pcb = memp_malloc(MEMP_RAW_PCB);
+ pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB);
/* could allocate RAW PCB? */
if (pcb != NULL) {
/* initialize PCB to all zeroes */
diff --git a/core/lwip/src/core/snmp/asn1_dec.c b/core/lwip/src/core/snmp/asn1_dec.c
index 650fb403..1d565820 100644
--- a/core/lwip/src/core/snmp/asn1_dec.c
+++ b/core/lwip/src/core/snmp/asn1_dec.c
@@ -61,7 +61,7 @@ snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type)
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
*type = *msg_ptr;
return ERR_OK;
@@ -94,7 +94,7 @@ snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
if (*msg_ptr < 0x80)
@@ -125,7 +125,7 @@ snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -160,7 +160,7 @@ snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
}
else
{
@@ -186,7 +186,7 @@ snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -249,7 +249,7 @@ snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value)
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
if ((len > 0) && (len < 6))
{
@@ -273,7 +273,7 @@ snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -295,7 +295,7 @@ snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -349,7 +349,7 @@ snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value)
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
if ((len > 0) && (len < 5))
{
@@ -386,7 +386,7 @@ snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -439,7 +439,7 @@ snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid)
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
oid->len = 0;
@@ -493,7 +493,7 @@ snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -519,7 +519,7 @@ snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -551,7 +551,7 @@ snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -607,7 +607,7 @@ snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
if (raw_len >= len)
{
@@ -623,7 +623,7 @@ snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
diff --git a/core/lwip/src/core/snmp/asn1_enc.c b/core/lwip/src/core/snmp/asn1_enc.c
index 77af6b4b..64dfc5f6 100644
--- a/core/lwip/src/core/snmp/asn1_enc.c
+++ b/core/lwip/src/core/snmp/asn1_enc.c
@@ -190,7 +190,7 @@ snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type)
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
*msg_ptr = type;
return ERR_OK;
@@ -222,12 +222,12 @@ snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
if (length < 0x80)
{
- *msg_ptr = length;
+ *msg_ptr = (u8_t)length;
return ERR_OK;
}
else if (length < 0x100)
@@ -239,14 +239,14 @@ snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
}
else
{
/* next octet in same pbuf */
msg_ptr++;
}
- *msg_ptr = length;
+ *msg_ptr = (u8_t)length;
return ERR_OK;
}
else
@@ -265,7 +265,7 @@ snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -276,12 +276,12 @@ snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
if (i == 0)
{
/* least significant length octet */
- *msg_ptr = length;
+ *msg_ptr = (u8_t)length;
}
else
{
/* most significant length octet */
- *msg_ptr = length >> 8;
+ *msg_ptr = (u8_t)(length >> 8);
}
}
return ERR_OK;
@@ -305,7 +305,7 @@ snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
* @see snmp_asn1_enc_u32t_cnt()
*/
err_t
-snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
+snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value)
{
u16_t plen, base;
u8_t *msg_ptr;
@@ -317,7 +317,7 @@ snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
if (octets_needed == 5)
@@ -331,7 +331,7 @@ snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -343,14 +343,14 @@ snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
while (octets_needed > 1)
{
octets_needed--;
- *msg_ptr = value >> (octets_needed << 3);
+ *msg_ptr = (u8_t)(value >> (octets_needed << 3));
ofs += 1;
if (ofs >= plen)
{
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -360,7 +360,7 @@ snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
}
}
/* (only) one least significant octet */
- *msg_ptr = value;
+ *msg_ptr = (u8_t)value;
return ERR_OK;
}
p = p->next;
@@ -381,7 +381,7 @@ snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
* @see snmp_asn1_enc_s32t_cnt()
*/
err_t
-snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value)
+snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value)
{
u16_t plen, base;
u8_t *msg_ptr;
@@ -393,20 +393,20 @@ snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value)
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
while (octets_needed > 1)
{
octets_needed--;
- *msg_ptr = value >> (octets_needed << 3);
+ *msg_ptr = (u8_t)(value >> (octets_needed << 3));
ofs += 1;
if (ofs >= plen)
{
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -416,7 +416,7 @@ snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value)
}
}
/* (only) one least significant octet */
- *msg_ptr = value;
+ *msg_ptr = (u8_t)value;
return ERR_OK;
}
p = p->next;
@@ -447,7 +447,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
if (ident_len > 1)
@@ -460,7 +460,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
else
{
/* calculate prefix */
- *msg_ptr = (ident[0] * 40) + ident[1];
+ *msg_ptr = (u8_t)((ident[0] * 40) + ident[1]);
}
ofs += 1;
if (ofs >= plen)
@@ -468,7 +468,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -498,7 +498,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
{
u8_t code;
- code = sub_id >> shift;
+ code = (u8_t)(sub_id >> shift);
if ((code != 0) || (tail != 0))
{
tail = 1;
@@ -509,7 +509,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -529,7 +529,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
@@ -559,7 +559,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode
*/
err_t
-snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw)
+snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw)
{
u16_t plen, base;
u8_t *msg_ptr;
@@ -571,7 +571,7 @@ snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw)
plen += p->len;
if (ofs < plen)
{
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
msg_ptr += ofs - base;
while (raw_len > 1)
@@ -586,7 +586,7 @@ snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw)
/* next octet in next pbuf */
p = p->next;
if (p == NULL) { return ERR_ARG; }
- msg_ptr = p->payload;
+ msg_ptr = (u8_t*)p->payload;
plen += p->len;
}
else
diff --git a/core/lwip/src/core/snmp/mib2.c b/core/lwip/src/core/snmp/mib2.c
index bc5830d6..29decd30 100644
--- a/core/lwip/src/core/snmp/mib2.c
+++ b/core/lwip/src/core/snmp/mib2.c
@@ -43,10 +43,12 @@
#include "lwip/netif.h"
#include "lwip/ip.h"
#include "lwip/ip_frag.h"
-#include "lwip/tcp.h"
+#include "lwip/mem.h"
+#include "lwip/tcp_impl.h"
#include "lwip/udp.h"
#include "lwip/snmp_asn1.h"
#include "lwip/snmp_structs.h"
+#include "lwip/sys.h"
#include "netif/etharp.h"
/**
@@ -131,20 +133,20 @@ const s32_t snmp_ids[28] = {
17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30
};
struct mib_node* const snmp_nodes[28] = {
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
- (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+ (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar
};
const struct mib_array_node snmp = {
&noleafs_get_object_def,
@@ -176,7 +178,7 @@ struct mib_list_rootnode udp_root = {
};
const s32_t udpentry_ids[2] = { 1, 2 };
struct mib_node* const udpentry_nodes[2] = {
- (struct mib_node* const)&udp_root, (struct mib_node* const)&udp_root,
+ (struct mib_node*)&udp_root, (struct mib_node*)&udp_root,
};
const struct mib_array_node udpentry = {
&noleafs_get_object_def,
@@ -190,7 +192,7 @@ const struct mib_array_node udpentry = {
};
s32_t udptable_id = 1;
-struct mib_node* udptable_node = (struct mib_node* const)&udpentry;
+struct mib_node* udptable_node = (struct mib_node*)&udpentry;
struct mib_ram_array_node udptable = {
&noleafs_get_object_def,
&noleafs_get_value,
@@ -212,9 +214,9 @@ const mib_scalar_node udp_scalar = {
};
const s32_t udp_ids[5] = { 1, 2, 3, 4, 5 };
struct mib_node* const udp_nodes[5] = {
- (struct mib_node* const)&udp_scalar, (struct mib_node* const)&udp_scalar,
- (struct mib_node* const)&udp_scalar, (struct mib_node* const)&udp_scalar,
- (struct mib_node* const)&udptable
+ (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar,
+ (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar,
+ (struct mib_node*)&udptable
};
const struct mib_array_node udp = {
&noleafs_get_object_def,
@@ -244,9 +246,9 @@ struct mib_list_rootnode tcpconntree_root = {
};
const s32_t tcpconnentry_ids[5] = { 1, 2, 3, 4, 5 };
struct mib_node* const tcpconnentry_nodes[5] = {
- (struct mib_node* const)&tcpconntree_root, (struct mib_node* const)&tcpconntree_root,
- (struct mib_node* const)&tcpconntree_root, (struct mib_node* const)&tcpconntree_root,
- (struct mib_node* const)&tcpconntree_root
+ (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root,
+ (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root,
+ (struct mib_node*)&tcpconntree_root
};
const struct mib_array_node tcpconnentry = {
&noleafs_get_object_def,
@@ -260,7 +262,7 @@ const struct mib_array_node tcpconnentry = {
};
s32_t tcpconntable_id = 1;
-struct mib_node* tcpconntable_node = (struct mib_node* const)&tcpconnentry;
+struct mib_node* tcpconntable_node = (struct mib_node*)&tcpconnentry;
struct mib_ram_array_node tcpconntable = {
&noleafs_get_object_def,
&noleafs_get_value,
@@ -284,14 +286,14 @@ const mib_scalar_node tcp_scalar = {
};
const s32_t tcp_ids[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
struct mib_node* const tcp_nodes[15] = {
- (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
- (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
- (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
- (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
- (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
- (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
- (struct mib_node* const)&tcpconntable, (struct mib_node* const)&tcp_scalar,
- (struct mib_node* const)&tcp_scalar
+ (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+ (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+ (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+ (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+ (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+ (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+ (struct mib_node*)&tcpconntable, (struct mib_node*)&tcp_scalar,
+ (struct mib_node*)&tcp_scalar
};
const struct mib_array_node tcp = {
&noleafs_get_object_def,
@@ -316,19 +318,19 @@ const mib_scalar_node icmp_scalar = {
};
const s32_t icmp_ids[26] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 };
struct mib_node* const icmp_nodes[26] = {
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
- (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+ (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar
};
const struct mib_array_node icmp = {
&noleafs_get_object_def,
@@ -355,8 +357,8 @@ struct mib_list_rootnode ipntomtree_root = {
};
const s32_t ipntomentry_ids[4] = { 1, 2, 3, 4 };
struct mib_node* const ipntomentry_nodes[4] = {
- (struct mib_node* const)&ipntomtree_root, (struct mib_node* const)&ipntomtree_root,
- (struct mib_node* const)&ipntomtree_root, (struct mib_node* const)&ipntomtree_root
+ (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root,
+ (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root
};
const struct mib_array_node ipntomentry = {
&noleafs_get_object_def,
@@ -370,7 +372,7 @@ const struct mib_array_node ipntomentry = {
};
s32_t ipntomtable_id = 1;
-struct mib_node* ipntomtable_node = (struct mib_node* const)&ipntomentry;
+struct mib_node* ipntomtable_node = (struct mib_node*)&ipntomentry;
struct mib_ram_array_node ipntomtable = {
&noleafs_get_object_def,
&noleafs_get_value,
@@ -396,13 +398,13 @@ struct mib_list_rootnode iprtetree_root = {
};
const s32_t iprteentry_ids[13] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
struct mib_node* const iprteentry_nodes[13] = {
- (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
- (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
- (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
- (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
- (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
- (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
- (struct mib_node* const)&iprtetree_root
+ (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+ (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+ (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+ (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+ (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+ (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+ (struct mib_node*)&iprtetree_root
};
const struct mib_array_node iprteentry = {
&noleafs_get_object_def,
@@ -416,7 +418,7 @@ const struct mib_array_node iprteentry = {
};
s32_t iprtetable_id = 1;
-struct mib_node* iprtetable_node = (struct mib_node* const)&iprteentry;
+struct mib_node* iprtetable_node = (struct mib_node*)&iprteentry;
struct mib_ram_array_node iprtetable = {
&noleafs_get_object_def,
&noleafs_get_value,
@@ -442,11 +444,11 @@ struct mib_list_rootnode ipaddrtree_root = {
};
const s32_t ipaddrentry_ids[5] = { 1, 2, 3, 4, 5 };
struct mib_node* const ipaddrentry_nodes[5] = {
- (struct mib_node* const)&ipaddrtree_root,
- (struct mib_node* const)&ipaddrtree_root,
- (struct mib_node* const)&ipaddrtree_root,
- (struct mib_node* const)&ipaddrtree_root,
- (struct mib_node* const)&ipaddrtree_root
+ (struct mib_node*)&ipaddrtree_root,
+ (struct mib_node*)&ipaddrtree_root,
+ (struct mib_node*)&ipaddrtree_root,
+ (struct mib_node*)&ipaddrtree_root,
+ (struct mib_node*)&ipaddrtree_root
};
const struct mib_array_node ipaddrentry = {
&noleafs_get_object_def,
@@ -460,7 +462,7 @@ const struct mib_array_node ipaddrentry = {
};
s32_t ipaddrtable_id = 1;
-struct mib_node* ipaddrtable_node = (struct mib_node* const)&ipaddrentry;
+struct mib_node* ipaddrtable_node = (struct mib_node*)&ipaddrentry;
struct mib_ram_array_node ipaddrtable = {
&noleafs_get_object_def,
&noleafs_get_value,
@@ -483,18 +485,18 @@ const mib_scalar_node ip_scalar = {
};
const s32_t ip_ids[23] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
struct mib_node* const ip_nodes[23] = {
- (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
- (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
- (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
- (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
- (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
- (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
- (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
- (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
- (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
- (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ipaddrtable,
- (struct mib_node* const)&iprtetable, (struct mib_node* const)&ipntomtable,
- (struct mib_node* const)&ip_scalar
+ (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+ (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+ (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+ (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+ (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+ (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+ (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+ (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+ (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+ (struct mib_node*)&ip_scalar, (struct mib_node*)&ipaddrtable,
+ (struct mib_node*)&iprtetable, (struct mib_node*)&ipntomtable,
+ (struct mib_node*)&ip_scalar
};
const struct mib_array_node mib2_ip = {
&noleafs_get_object_def,
@@ -521,9 +523,9 @@ struct mib_list_rootnode arptree_root = {
};
const s32_t atentry_ids[3] = { 1, 2, 3 };
struct mib_node* const atentry_nodes[3] = {
- (struct mib_node* const)&arptree_root,
- (struct mib_node* const)&arptree_root,
- (struct mib_node* const)&arptree_root
+ (struct mib_node*)&arptree_root,
+ (struct mib_node*)&arptree_root,
+ (struct mib_node*)&arptree_root
};
const struct mib_array_node atentry = {
&noleafs_get_object_def,
@@ -537,7 +539,7 @@ const struct mib_array_node atentry = {
};
const s32_t attable_id = 1;
-struct mib_node* const attable_node = (struct mib_node* const)&atentry;
+struct mib_node* const attable_node = (struct mib_node*)&atentry;
const struct mib_array_node attable = {
&noleafs_get_object_def,
&noleafs_get_value,
@@ -551,7 +553,7 @@ const struct mib_array_node attable = {
/* at .1.3.6.1.2.1.3 */
s32_t at_id = 1;
-struct mib_node* mib2_at_node = (struct mib_node* const)&attable;
+struct mib_node* mib2_at_node = (struct mib_node*)&attable;
struct mib_ram_array_node at = {
&noleafs_get_object_def,
&noleafs_get_value,
@@ -582,17 +584,17 @@ struct mib_list_rootnode iflist_root = {
};
const s32_t ifentry_ids[22] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 };
struct mib_node* const ifentry_nodes[22] = {
- (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
- (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
- (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
- (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
- (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
- (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
- (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
- (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
- (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
- (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
- (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root
+ (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+ (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+ (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+ (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+ (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+ (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+ (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+ (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+ (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+ (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+ (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root
};
const struct mib_array_node ifentry = {
&noleafs_get_object_def,
@@ -606,7 +608,7 @@ const struct mib_array_node ifentry = {
};
s32_t iftable_id = 1;
-struct mib_node* iftable_node = (struct mib_node* const)&ifentry;
+struct mib_node* iftable_node = (struct mib_node*)&ifentry;
struct mib_ram_array_node iftable = {
&noleafs_get_object_def,
&noleafs_get_value,
@@ -629,7 +631,7 @@ const mib_scalar_node interfaces_scalar = {
};
const s32_t interfaces_ids[2] = { 1, 2 };
struct mib_node* const interfaces_nodes[2] = {
- (struct mib_node* const)&interfaces_scalar, (struct mib_node* const)&iftable
+ (struct mib_node*)&interfaces_scalar, (struct mib_node*)&iftable
};
const struct mib_array_node interfaces = {
&noleafs_get_object_def,
@@ -655,10 +657,10 @@ const mib_scalar_node sys_tem_scalar = {
};
const s32_t sys_tem_ids[7] = { 1, 2, 3, 4, 5, 6, 7 };
struct mib_node* const sys_tem_nodes[7] = {
- (struct mib_node* const)&sys_tem_scalar, (struct mib_node* const)&sys_tem_scalar,
- (struct mib_node* const)&sys_tem_scalar, (struct mib_node* const)&sys_tem_scalar,
- (struct mib_node* const)&sys_tem_scalar, (struct mib_node* const)&sys_tem_scalar,
- (struct mib_node* const)&sys_tem_scalar
+ (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar,
+ (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar,
+ (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar,
+ (struct mib_node*)&sys_tem_scalar
};
/* work around name issue with 'sys_tem', some compiler(s?) seem to reserve 'system' */
const struct mib_array_node sys_tem = {
@@ -692,16 +694,16 @@ const s32_t mib2_ids[MIB2_GROUPS] =
11
};
struct mib_node* const mib2_nodes[MIB2_GROUPS] = {
- (struct mib_node* const)&sys_tem,
- (struct mib_node* const)&interfaces,
- (struct mib_node* const)&at,
- (struct mib_node* const)&mib2_ip,
- (struct mib_node* const)&icmp,
+ (struct mib_node*)&sys_tem,
+ (struct mib_node*)&interfaces,
+ (struct mib_node*)&at,
+ (struct mib_node*)&mib2_ip,
+ (struct mib_node*)&icmp,
#if LWIP_TCP
- (struct mib_node* const)&tcp,
+ (struct mib_node*)&tcp,
#endif
- (struct mib_node* const)&udp,
- (struct mib_node* const)&snmp
+ (struct mib_node*)&udp,
+ (struct mib_node*)&snmp
};
const struct mib_array_node mib2 = {
@@ -717,7 +719,7 @@ const struct mib_array_node mib2 = {
/* mgmt .1.3.6.1.2 */
const s32_t mgmt_ids[1] = { 1 };
-struct mib_node* const mgmt_nodes[1] = { (struct mib_node* const)&mib2 };
+struct mib_node* const mgmt_nodes[1] = { (struct mib_node*)&mib2 };
const struct mib_array_node mgmt = {
&noleafs_get_object_def,
&noleafs_get_value,
@@ -731,8 +733,10 @@ const struct mib_array_node mgmt = {
/* internet .1.3.6.1 */
#if SNMP_PRIVATE_MIB
+/* When using a private MIB, you have to create a file 'private_mib.h' that contains
+ * a 'struct mib_array_node mib_private' which contains your MIB. */
s32_t internet_ids[2] = { 2, 4 };
-struct mib_node* const internet_nodes[2] = { (struct mib_node* const)&mgmt, (struct mib_node* const)&private };
+struct mib_node* const internet_nodes[2] = { (struct mib_node*)&mgmt, (struct mib_node*)&mib_private };
const struct mib_array_node internet = {
&noleafs_get_object_def,
&noleafs_get_value,
@@ -745,7 +749,7 @@ const struct mib_array_node internet = {
};
#else
const s32_t internet_ids[1] = { 2 };
-struct mib_node* const internet_nodes[1] = { (struct mib_node* const)&mgmt };
+struct mib_node* const internet_nodes[1] = { (struct mib_node*)&mgmt };
const struct mib_array_node internet = {
&noleafs_get_object_def,
&noleafs_get_value,
@@ -898,11 +902,11 @@ static u32_t snmpinpkts = 0,
* @param src points to source
* @param n number of octets to copy.
*/
-void ocstrncpy(u8_t *dst, u8_t *src, u8_t n)
+static void ocstrncpy(u8_t *dst, u8_t *src, u16_t n)
{
- while (n > 0)
- {
- n--;
+ u16_t i = n;
+ while (i > 0) {
+ i--;
*dst++ = *src++;
}
}
@@ -916,9 +920,9 @@ void ocstrncpy(u8_t *dst, u8_t *src, u8_t n)
*/
void objectidncpy(s32_t *dst, s32_t *src, u8_t n)
{
- while(n > 0)
- {
- n--;
+ u8_t i = n;
+ while(i > 0) {
+ i--;
*dst++ = *src++;
}
}
@@ -1082,18 +1086,16 @@ void snmp_dec_iflist(void)
* Inserts ARP table indexes (.xIfIndex.xNetAddress)
* into arp table index trees (both atTable and ipNetToMediaTable).
*/
-void snmp_insert_arpidx_tree(struct netif *ni, struct ip_addr *ip)
+void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip)
{
struct mib_list_rootnode *at_rn;
struct mib_list_node *at_node;
- struct ip_addr hip;
s32_t arpidx[5];
u8_t level, tree;
LWIP_ASSERT("ni != NULL", ni != NULL);
snmp_netiftoifindex(ni, &arpidx[0]);
- hip.addr = ntohl(ip->addr);
- snmp_iptooid(&hip, &arpidx[1]);
+ snmp_iptooid(ip, &arpidx[1]);
for (tree = 0; tree < 2; tree++)
{
@@ -1156,17 +1158,15 @@ void snmp_insert_arpidx_tree(struct netif *ni, struct ip_addr *ip)
* Removes ARP table indexes (.xIfIndex.xNetAddress)
* from arp table index trees.
*/
-void snmp_delete_arpidx_tree(struct netif *ni, struct ip_addr *ip)
+void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip)
{
struct mib_list_rootnode *at_rn, *next, *del_rn[5];
struct mib_list_node *at_n, *del_n[5];
- struct ip_addr hip;
s32_t arpidx[5];
u8_t fc, tree, level, del_cnt;
snmp_netiftoifindex(ni, &arpidx[0]);
- hip.addr = ntohl(ip->addr);
- snmp_iptooid(&hip, &arpidx[1]);
+ snmp_iptooid(ip, &arpidx[1]);
for (tree = 0; tree < 2; tree++)
{
@@ -1319,13 +1319,11 @@ void snmp_insert_ipaddridx_tree(struct netif *ni)
{
struct mib_list_rootnode *ipa_rn;
struct mib_list_node *ipa_node;
- struct ip_addr ip;
s32_t ipaddridx[4];
u8_t level;
LWIP_ASSERT("ni != NULL", ni != NULL);
- ip.addr = ntohl(ni->ip_addr.addr);
- snmp_iptooid(&ip, &ipaddridx[0]);
+ snmp_iptooid(&ni->ip_addr, &ipaddridx[0]);
level = 0;
ipa_rn = &ipaddrtree_root;
@@ -1375,13 +1373,11 @@ void snmp_delete_ipaddridx_tree(struct netif *ni)
{
struct mib_list_rootnode *ipa_rn, *next, *del_rn[4];
struct mib_list_node *ipa_n, *del_n[4];
- struct ip_addr ip;
s32_t ipaddridx[4];
u8_t fc, level, del_cnt;
LWIP_ASSERT("ni != NULL", ni != NULL);
- ip.addr = ntohl(ni->ip_addr.addr);
- snmp_iptooid(&ip, &ipaddridx[0]);
+ snmp_iptooid(&ni->ip_addr, &ipaddridx[0]);
/* mark nodes for deletion */
level = 0;
@@ -1443,20 +1439,22 @@ void snmp_delete_ipaddridx_tree(struct netif *ni)
void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni)
{
u8_t insert = 0;
- struct ip_addr dst;
+ ip_addr_t dst;
if (dflt != 0)
{
/* the default route 0.0.0.0 */
- dst.addr = 0;
+ ip_addr_set_any(&dst);
insert = 1;
}
else
{
/* route to the network address */
- dst.addr = ntohl(ni->ip_addr.addr & ni->netmask.addr);
+ ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask);
/* exclude 0.0.0.0 network (reserved for default rte) */
- if (dst.addr != 0) insert = 1;
+ if (!ip_addr_isany(&dst)) {
+ insert = 1;
+ }
}
if (insert)
{
@@ -1517,23 +1515,25 @@ void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni)
*/
void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni)
{
- u8_t delete = 0;
- struct ip_addr dst;
+ u8_t del = 0;
+ ip_addr_t dst;
if (dflt != 0)
{
/* the default route 0.0.0.0 */
- dst.addr = 0;
- delete = 1;
+ ip_addr_set_any(&dst);
+ del = 1;
}
else
{
/* route to the network address */
- dst.addr = ntohl(ni->ip_addr.addr & ni->netmask.addr);
+ ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask);
/* exclude 0.0.0.0 network (reserved for default rte) */
- if (dst.addr != 0) delete = 1;
+ if (!ip_addr_isany(&dst)) {
+ del = 1;
+ }
}
- if (delete)
+ if (del)
{
struct mib_list_rootnode *iprte_rn, *next, *del_rn[4];
struct mib_list_node *iprte_n, *del_n[4];
@@ -1793,13 +1793,11 @@ void snmp_insert_udpidx_tree(struct udp_pcb *pcb)
{
struct mib_list_rootnode *udp_rn;
struct mib_list_node *udp_node;
- struct ip_addr ip;
s32_t udpidx[5];
u8_t level;
LWIP_ASSERT("pcb != NULL", pcb != NULL);
- ip.addr = ntohl(pcb->local_ip.addr);
- snmp_iptooid(&ip, &udpidx[0]);
+ snmp_iptooid(&pcb->local_ip, &udpidx[0]);
udpidx[4] = pcb->local_port;
udp_rn = &udp_root;
@@ -1845,29 +1843,28 @@ void snmp_insert_udpidx_tree(struct udp_pcb *pcb)
*/
void snmp_delete_udpidx_tree(struct udp_pcb *pcb)
{
+ struct udp_pcb *npcb;
struct mib_list_rootnode *udp_rn, *next, *del_rn[5];
struct mib_list_node *udp_n, *del_n[5];
- struct ip_addr ip;
s32_t udpidx[5];
u8_t bindings, fc, level, del_cnt;
LWIP_ASSERT("pcb != NULL", pcb != NULL);
- ip.addr = ntohl(pcb->local_ip.addr);
- snmp_iptooid(&ip, &udpidx[0]);
+ snmp_iptooid(&pcb->local_ip, &udpidx[0]);
udpidx[4] = pcb->local_port;
/* count PCBs for a given binding
(e.g. when reusing ports or for temp output PCBs) */
bindings = 0;
- pcb = udp_pcbs;
- while ((pcb != NULL))
+ npcb = udp_pcbs;
+ while ((npcb != NULL))
{
- if ((pcb->local_ip.addr == ip.addr) &&
- (pcb->local_port == udpidx[4]))
+ if (ip_addr_cmp(&npcb->local_ip, &pcb->local_ip) &&
+ (npcb->local_port == udpidx[4]))
{
bindings++;
}
- pcb = pcb->next;
+ npcb = npcb->next;
}
if (bindings == 1)
{
@@ -2129,7 +2126,8 @@ system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
od->id_inst_len = ident_len;
od->id_inst_ptr = ident;
- id = ident[0];
+ LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
+ id = (u8_t)ident[0];
LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def system.%"U16_F".0\n",(u16_t)id));
switch (id)
{
@@ -2201,32 +2199,33 @@ system_get_value(struct obj_def *od, u16_t len, void *value)
{
u8_t id;
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* sysDescr */
- ocstrncpy(value,sysdescr_ptr, len);
+ ocstrncpy((u8_t*)value, sysdescr_ptr, len);
break;
case 2: /* sysObjectID */
objectidncpy((s32_t*)value, (s32_t*)sysobjid.id, (u8_t)(len / sizeof(s32_t)));
break;
case 3: /* sysUpTime */
{
- snmp_get_sysuptime(value);
+ snmp_get_sysuptime((u32_t*)value);
}
break;
case 4: /* sysContact */
- ocstrncpy(value,syscontact_ptr,len);
+ ocstrncpy((u8_t*)value, syscontact_ptr, len);
break;
case 5: /* sysName */
- ocstrncpy(value,sysname_ptr,len);
+ ocstrncpy((u8_t*)value, sysname_ptr, len);
break;
case 6: /* sysLocation */
- ocstrncpy(value,syslocation_ptr,len);
+ ocstrncpy((u8_t*)value, syslocation_ptr, len);
break;
case 7: /* sysServices */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
*sint_ptr = sysservices;
}
break;
@@ -2240,7 +2239,8 @@ system_set_test(struct obj_def *od, u16_t len, void *value)
LWIP_UNUSED_ARG(value);
set_ok = 0;
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 4: /* sysContact */
@@ -2273,20 +2273,22 @@ system_set_value(struct obj_def *od, u16_t len, void *value)
{
u8_t id;
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid len", len <= 0xff);
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 4: /* sysContact */
- ocstrncpy(syscontact_ptr,value,len);
- *syscontact_len_ptr = len;
+ ocstrncpy(syscontact_ptr, (u8_t*)value, len);
+ *syscontact_len_ptr = (u8_t)len;
break;
case 5: /* sysName */
- ocstrncpy(sysname_ptr,value,len);
- *sysname_len_ptr = len;
+ ocstrncpy(sysname_ptr, (u8_t*)value, len);
+ *sysname_len_ptr = (u8_t)len;
break;
case 6: /* sysLocation */
- ocstrncpy(syslocation_ptr,value,len);
- *syslocation_len_ptr = len;
+ ocstrncpy(syslocation_ptr, (u8_t*)value, len);
+ *syslocation_len_ptr = (u8_t)len;
break;
};
}
@@ -2335,7 +2337,7 @@ interfaces_get_value(struct obj_def *od, u16_t len, void *value)
LWIP_UNUSED_ARG(len);
if (od->id_inst_ptr[0] == 1)
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
*sint_ptr = iflist_root.count;
}
}
@@ -2360,7 +2362,8 @@ ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
od->id_inst_len = ident_len;
od->id_inst_ptr = ident;
- id = ident[0];
+ LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
+ id = (u8_t)ident[0];
LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ifentry.%"U16_F"\n",(u16_t)id));
switch (id)
{
@@ -2461,43 +2464,43 @@ ifentry_get_value(struct obj_def *od, u16_t len, void *value)
u8_t id;
snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* ifIndex */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
*sint_ptr = od->id_inst_ptr[1];
}
break;
case 2: /* ifDescr */
- ocstrncpy(value,(u8_t*)netif->name,len);
+ ocstrncpy((u8_t*)value, (u8_t*)netif->name, len);
break;
case 3: /* ifType */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
*sint_ptr = netif->link_type;
}
break;
case 4: /* ifMtu */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
*sint_ptr = netif->mtu;
}
break;
case 5: /* ifSpeed */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = netif->link_speed;
}
break;
case 6: /* ifPhysAddress */
- ocstrncpy(value,netif->hwaddr,len);
+ ocstrncpy((u8_t*)value, netif->hwaddr, len);
break;
case 7: /* ifAdminStatus */
-#if LWIP_NETIF_LINK_CALLBACK
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
if (netif_is_up(netif))
{
if (netif_is_link_up(netif))
@@ -2515,10 +2518,9 @@ ifentry_get_value(struct obj_def *od, u16_t len, void *value)
}
}
break;
-#endif
case 8: /* ifOperStatus */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
if (netif_is_up(netif))
{
*sint_ptr = 1;
@@ -2531,31 +2533,31 @@ ifentry_get_value(struct obj_def *od, u16_t len, void *value)
break;
case 9: /* ifLastChange */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = netif->ts;
}
break;
case 10: /* ifInOctets */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = netif->ifinoctets;
}
break;
case 11: /* ifInUcastPkts */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = netif->ifinucastpkts;
}
break;
case 12: /* ifInNUcastPkts */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = netif->ifinnucastpkts;
}
break;
case 13: /* ifInDiscarts */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = netif->ifindiscards;
}
break;
@@ -2563,45 +2565,45 @@ ifentry_get_value(struct obj_def *od, u16_t len, void *value)
case 15: /* ifInUnkownProtos */
/** @todo add these counters! */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = 0;
}
break;
case 16: /* ifOutOctets */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = netif->ifoutoctets;
}
break;
case 17: /* ifOutUcastPkts */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = netif->ifoutucastpkts;
}
break;
case 18: /* ifOutNUcastPkts */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = netif->ifoutnucastpkts;
}
break;
case 19: /* ifOutDiscarts */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = netif->ifoutdiscards;
}
break;
case 20: /* ifOutErrors */
/** @todo add this counter! */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = 0;
}
break;
case 21: /* ifOutQLen */
/** @todo figure out if this must be 0 (no queue) or 1? */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = 0;
}
break;
@@ -2613,19 +2615,20 @@ ifentry_get_value(struct obj_def *od, u16_t len, void *value)
#if !SNMP_SAFE_REQUESTS
static u8_t
-ifentry_set_test (struct obj_def *od, u16_t len, void *value)
+ifentry_set_test(struct obj_def *od, u16_t len, void *value)
{
struct netif *netif;
u8_t id, set_ok;
+ LWIP_UNUSED_ARG(len);
set_ok = 0;
snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
- id = od->id_inst_ptr[0];
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 7: /* ifAdminStatus */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
if (*sint_ptr == 1 || *sint_ptr == 2)
set_ok = 1;
}
@@ -2635,18 +2638,19 @@ ifentry_set_test (struct obj_def *od, u16_t len, void *value)
}
static void
-ifentry_set_value (struct obj_def *od, u16_t len, void *value)
+ifentry_set_value(struct obj_def *od, u16_t len, void *value)
{
struct netif *netif;
u8_t id;
+ LWIP_UNUSED_ARG(len);
snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
- id = od->id_inst_ptr[0];
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 7: /* ifAdminStatus */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
if (*sint_ptr == 1)
{
netif_set_up(netif);
@@ -2719,9 +2723,9 @@ atentry_get_value(struct obj_def *od, u16_t len, void *value)
#if LWIP_ARP
u8_t id;
struct eth_addr* ethaddr_ret;
- struct ip_addr* ipaddr_ret;
+ ip_addr_t* ipaddr_ret;
#endif /* LWIP_ARP */
- struct ip_addr ip;
+ ip_addr_t ip;
struct netif *netif;
LWIP_UNUSED_ARG(len);
@@ -2729,30 +2733,30 @@ atentry_get_value(struct obj_def *od, u16_t len, void *value)
snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
snmp_oidtoip(&od->id_inst_ptr[2], &ip);
- ip.addr = htonl(ip.addr);
#if LWIP_ARP /** @todo implement a netif_find_addr */
if (etharp_find_addr(netif, &ip, &ethaddr_ret, &ipaddr_ret) > -1)
{
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* atIfIndex */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
*sint_ptr = od->id_inst_ptr[1];
}
break;
case 2: /* atPhysAddress */
{
- struct eth_addr *dst = value;
+ struct eth_addr *dst = (struct eth_addr*)value;
*dst = *ethaddr_ret;
}
break;
case 3: /* atNetAddress */
{
- struct ip_addr *dst = value;
+ ip_addr_t *dst = (ip_addr_t*)value;
*dst = *ipaddr_ret;
}
@@ -2775,7 +2779,8 @@ ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
od->id_inst_len = ident_len;
od->id_inst_ptr = ident;
- id = ident[0];
+ LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
+ id = (u8_t)ident[0];
LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ip.%"U16_F".0\n",(u16_t)id));
switch (id)
{
@@ -2833,12 +2838,13 @@ ip_get_value(struct obj_def *od, u16_t len, void *value)
u8_t id;
LWIP_UNUSED_ARG(len);
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* ipForwarding */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
#if IP_FORWARD
/* forwarding */
*sint_ptr = 1;
@@ -2850,73 +2856,73 @@ ip_get_value(struct obj_def *od, u16_t len, void *value)
break;
case 2: /* ipDefaultTTL */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
*sint_ptr = IP_DEFAULT_TTL;
}
break;
case 3: /* ipInReceives */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipinreceives;
}
break;
case 4: /* ipInHdrErrors */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipinhdrerrors;
}
break;
case 5: /* ipInAddrErrors */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipinaddrerrors;
}
break;
case 6: /* ipForwDatagrams */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipforwdatagrams;
}
break;
case 7: /* ipInUnknownProtos */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipinunknownprotos;
}
break;
case 8: /* ipInDiscards */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipindiscards;
}
break;
case 9: /* ipInDelivers */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipindelivers;
}
break;
case 10: /* ipOutRequests */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipoutrequests;
}
break;
case 11: /* ipOutDiscards */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipoutdiscards;
}
break;
case 12: /* ipOutNoRoutes */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipoutnoroutes;
}
break;
case 13: /* ipReasmTimeout */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
#if IP_REASSEMBLY
*sint_ptr = IP_REASS_MAXAGE;
#else
@@ -2926,44 +2932,44 @@ ip_get_value(struct obj_def *od, u16_t len, void *value)
break;
case 14: /* ipReasmReqds */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipreasmreqds;
}
break;
case 15: /* ipReasmOKs */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipreasmoks;
}
break;
case 16: /* ipReasmFails */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipreasmfails;
}
break;
case 17: /* ipFragOKs */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipfragoks;
}
break;
case 18: /* ipFragFails */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipfragfails;
}
break;
case 19: /* ipFragCreates */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = ipfragcreates;
}
break;
case 23: /* ipRoutingDiscards */
/** @todo can lwIP discard routes at all?? hardwire this to 0?? */
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
*uint_ptr = iproutingdiscards;
}
break;
@@ -2984,11 +2990,12 @@ static u8_t
ip_set_test(struct obj_def *od, u16_t len, void *value)
{
u8_t id, set_ok;
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
LWIP_UNUSED_ARG(len);
set_ok = 0;
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* ipForwarding */
@@ -3027,7 +3034,8 @@ ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
od->id_inst_len = ident_len;
od->id_inst_ptr = ident;
- id = ident[0];
+ LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
+ id = (u8_t)ident[0];
switch (id)
{
case 1: /* ipAdEntAddr */
@@ -3063,12 +3071,11 @@ ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value)
{
u8_t id;
u16_t ifidx;
- struct ip_addr ip;
+ ip_addr_t ip;
struct netif *netif = netif_list;
LWIP_UNUSED_ARG(len);
snmp_oidtoip(&od->id_inst_ptr[1], &ip);
- ip.addr = htonl(ip.addr);
ifidx = 0;
while ((netif != NULL) && !ip_addr_cmp(&ip, &netif->ip_addr))
{
@@ -3078,39 +3085,40 @@ ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value)
if (netif != NULL)
{
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* ipAdEntAddr */
{
- struct ip_addr *dst = value;
+ ip_addr_t *dst = (ip_addr_t*)value;
*dst = netif->ip_addr;
}
break;
case 2: /* ipAdEntIfIndex */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
*sint_ptr = ifidx + 1;
}
break;
case 3: /* ipAdEntNetMask */
{
- struct ip_addr *dst = value;
+ ip_addr_t *dst = (ip_addr_t*)value;
*dst = netif->netmask;
}
break;
case 4: /* ipAdEntBcastAddr */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
/* lwIP oddity, there's no broadcast
address in the netif we can rely on */
- *sint_ptr = ip_addr_broadcast.addr & 1;
+ *sint_ptr = IPADDR_BROADCAST & 1;
}
break;
case 5: /* ipAdEntReasmMaxSize */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
#if IP_REASSEMBLY
/* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs,
* but only if receiving one fragmented packet at a time.
@@ -3148,7 +3156,8 @@ ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
od->id_inst_len = ident_len;
od->id_inst_ptr = ident;
- id = ident[0];
+ LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
+ id = (u8_t)ident[0];
switch (id)
{
case 1: /* ipRouteDest */
@@ -3202,15 +3211,14 @@ static void
ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value)
{
struct netif *netif;
- struct ip_addr dest;
+ ip_addr_t dest;
s32_t *ident;
u8_t id;
ident = od->id_inst_ptr;
snmp_oidtoip(&ident[1], &dest);
- dest.addr = htonl(dest.addr);
- if (dest.addr == 0)
+ if (ip_addr_isany(&dest))
{
/* ip_route() uses default netif for default route */
netif = netif_default;
@@ -3227,37 +3235,38 @@ ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value)
}
if (netif != NULL)
{
- id = ident[0];
+ LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
+ id = (u8_t)ident[0];
switch (id)
{
case 1: /* ipRouteDest */
{
- struct ip_addr *dst = value;
+ ip_addr_t *dst = (ip_addr_t*)value;
- if (dest.addr == 0)
+ if (ip_addr_isany(&dest))
{
/* default rte has 0.0.0.0 dest */
- dst->addr = 0;
+ ip_addr_set_zero(dst);
}
else
{
/* netifs have netaddress dest */
- dst->addr = netif->ip_addr.addr & netif->netmask.addr;
+ ip_addr_get_network(dst, &netif->ip_addr, &netif->netmask);
}
}
break;
case 2: /* ipRouteIfIndex */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
snmp_netiftoifindex(netif, sint_ptr);
}
break;
case 3: /* ipRouteMetric1 */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
- if (dest.addr == 0)
+ if (ip_addr_isany(&dest))
{
/* default rte has metric 1 */
*sint_ptr = 1;
@@ -3274,16 +3283,16 @@ ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value)
case 6: /* ipRouteMetric4 */
case 12: /* ipRouteMetric5 */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
/* not used */
*sint_ptr = -1;
}
break;
case 7: /* ipRouteNextHop */
{
- struct ip_addr *dst = value;
+ ip_addr_t *dst = (ip_addr_t*)value;
- if (dest.addr == 0)
+ if (ip_addr_isany(&dest))
{
/* default rte: gateway */
*dst = netif->gw;
@@ -3297,9 +3306,9 @@ ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value)
break;
case 8: /* ipRouteType */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
- if (dest.addr == 0)
+ if (ip_addr_isany(&dest))
{
/* default rte is indirect */
*sint_ptr = 4;
@@ -3313,14 +3322,14 @@ ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value)
break;
case 9: /* ipRouteProto */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
/* locally defined routes */
*sint_ptr = 2;
}
break;
case 10: /* ipRouteAge */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
/** @todo (sysuptime - timestamp last change) / 100
@see snmp_insert_iprteidx_tree() */
*sint_ptr = 0;
@@ -3328,12 +3337,12 @@ ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value)
break;
case 11: /* ipRouteMask */
{
- struct ip_addr *dst = value;
+ ip_addr_t *dst = (ip_addr_t*)value;
- if (dest.addr == 0)
+ if (ip_addr_isany(&dest))
{
/* default rte use 0.0.0.0 mask */
- dst->addr = 0;
+ ip_addr_set_zero(dst);
}
else
{
@@ -3363,7 +3372,8 @@ ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
od->id_inst_len = ident_len;
od->id_inst_ptr = ident;
- id = ident[0];
+ LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
+ id = (u8_t)ident[0];
switch (id)
{
case 1: /* ipNetToMediaIfIndex */
@@ -3404,9 +3414,9 @@ ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value)
#if LWIP_ARP
u8_t id;
struct eth_addr* ethaddr_ret;
- struct ip_addr* ipaddr_ret;
+ ip_addr_t* ipaddr_ret;
#endif /* LWIP_ARP */
- struct ip_addr ip;
+ ip_addr_t ip;
struct netif *netif;
LWIP_UNUSED_ARG(len);
@@ -3414,37 +3424,37 @@ ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value)
snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
snmp_oidtoip(&od->id_inst_ptr[2], &ip);
- ip.addr = htonl(ip.addr);
#if LWIP_ARP /** @todo implement a netif_find_addr */
if (etharp_find_addr(netif, &ip, &ethaddr_ret, &ipaddr_ret) > -1)
{
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* ipNetToMediaIfIndex */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
*sint_ptr = od->id_inst_ptr[1];
}
break;
case 2: /* ipNetToMediaPhysAddress */
{
- struct eth_addr *dst = value;
+ struct eth_addr *dst = (struct eth_addr*)value;
*dst = *ethaddr_ret;
}
break;
case 3: /* ipNetToMediaNetAddress */
{
- struct ip_addr *dst = value;
+ ip_addr_t *dst = (ip_addr_t*)value;
*dst = *ipaddr_ret;
}
break;
case 4: /* ipNetToMediaType */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
/* dynamic (?) */
*sint_ptr = 3;
}
@@ -3481,11 +3491,12 @@ icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
static void
icmp_get_value(struct obj_def *od, u16_t len, void *value)
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
u8_t id;
LWIP_UNUSED_ARG(len);
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* icmpInMsgs */
@@ -3584,7 +3595,8 @@ tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
od->id_inst_len = ident_len;
od->id_inst_ptr = ident;
- id = ident[0];
+ LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
+ id = (u8_t)ident[0];
LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id));
switch (id)
@@ -3634,12 +3646,13 @@ tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
static void
tcp_get_value(struct obj_def *od, u16_t len, void *value)
{
- u32_t *uint_ptr = value;
- s32_t *sint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
+ s32_t *sint_ptr = (s32_t*)value;
u8_t id;
LWIP_UNUSED_ARG(len);
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* tcpRtoAlgorithm, vanj(4) */
@@ -3759,16 +3772,14 @@ tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
static void
tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value)
{
- struct ip_addr lip, rip;
+ ip_addr_t lip, rip;
u16_t lport, rport;
s32_t *ident;
ident = od->id_inst_ptr;
snmp_oidtoip(&ident[1], &lip);
- lip.addr = htonl(lip.addr);
lport = ident[5];
snmp_oidtoip(&ident[6], &rip);
- rip.addr = htonl(rip.addr);
rport = ident[10];
/** @todo find matching PCB */
@@ -3803,11 +3814,12 @@ udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
static void
udp_get_value(struct obj_def *od, u16_t len, void *value)
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
u8_t id;
LWIP_UNUSED_ARG(len);
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* udpInDatagrams */
@@ -3869,17 +3881,17 @@ udpentry_get_value(struct obj_def *od, u16_t len, void *value)
{
u8_t id;
struct udp_pcb *pcb;
- struct ip_addr ip;
+ ip_addr_t ip;
u16_t port;
LWIP_UNUSED_ARG(len);
snmp_oidtoip(&od->id_inst_ptr[1], &ip);
- ip.addr = htonl(ip.addr);
- port = od->id_inst_ptr[5];
+ LWIP_ASSERT("invalid port", (od->id_inst_ptr[5] >= 0) && (od->id_inst_ptr[5] <= 0xffff));
+ port = (u16_t)od->id_inst_ptr[5];
pcb = udp_pcbs;
while ((pcb != NULL) &&
- !((pcb->local_ip.addr == ip.addr) &&
+ !(ip_addr_cmp(&pcb->local_ip, &ip) &&
(pcb->local_port == port)))
{
pcb = pcb->next;
@@ -3887,18 +3899,19 @@ udpentry_get_value(struct obj_def *od, u16_t len, void *value)
if (pcb != NULL)
{
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* udpLocalAddress */
{
- struct ip_addr *dst = value;
+ ip_addr_t *dst = (ip_addr_t*)value;
*dst = pcb->local_ip;
}
break;
case 2: /* udpLocalPort */
{
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
*sint_ptr = pcb->local_port;
}
break;
@@ -3919,7 +3932,8 @@ snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
od->id_inst_len = ident_len;
od->id_inst_ptr = ident;
- id = ident[0];
+ LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
+ id = (u8_t)ident[0];
switch (id)
{
case 1: /* snmpInPkts */
@@ -3976,11 +3990,12 @@ snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
static void
snmp_get_value(struct obj_def *od, u16_t len, void *value)
{
- u32_t *uint_ptr = value;
+ u32_t *uint_ptr = (u32_t*)value;
u8_t id;
LWIP_UNUSED_ARG(len);
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
switch (id)
{
case 1: /* snmpInPkts */
@@ -4084,11 +4099,12 @@ snmp_set_test(struct obj_def *od, u16_t len, void *value)
LWIP_UNUSED_ARG(len);
set_ok = 0;
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
if (id == 30)
{
/* snmpEnableAuthenTraps */
- s32_t *sint_ptr = value;
+ s32_t *sint_ptr = (s32_t*)value;
if (snmpenableauthentraps_ptr != &snmpenableauthentraps_default)
{
@@ -4116,12 +4132,14 @@ snmp_set_value(struct obj_def *od, u16_t len, void *value)
u8_t id;
LWIP_UNUSED_ARG(len);
- id = od->id_inst_ptr[0];
+ LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
+ id = (u8_t)od->id_inst_ptr[0];
if (id == 30)
{
/* snmpEnableAuthenTraps */
- s32_t *sint_ptr = value;
- *snmpenableauthentraps_ptr = *sint_ptr;
+ /* @todo @fixme: which kind of pointer is 'value'? s32_t or u8_t??? */
+ u8_t *ptr = (u8_t*)value;
+ *snmpenableauthentraps_ptr = *ptr;
}
}
diff --git a/core/lwip/src/core/snmp/mib_structs.c b/core/lwip/src/core/snmp/mib_structs.c
index 39a29496..2f185cb4 100644
--- a/core/lwip/src/core/snmp/mib_structs.c
+++ b/core/lwip/src/core/snmp/mib_structs.c
@@ -37,7 +37,8 @@
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
#include "lwip/snmp_structs.h"
-#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/netif.h"
/** .iso.org.dod.internet address prefix, @see snmp_iso_*() */
const s32_t prefix[4] = {1, 3, 6, 1};
@@ -94,7 +95,7 @@ void
snmp_ifindextonetif(s32_t ifindex, struct netif **netif)
{
struct netif *nif = netif_list;
- u16_t i, ifidx;
+ s32_t i, ifidx;
ifidx = ifindex - 1;
i = 0;
@@ -132,18 +133,9 @@ snmp_netiftoifindex(struct netif *netif, s32_t *ifidx)
* @param ip points to output struct
*/
void
-snmp_oidtoip(s32_t *ident, struct ip_addr *ip)
+snmp_oidtoip(s32_t *ident, ip_addr_t *ip)
{
- u32_t ipa;
-
- ipa = ident[0];
- ipa <<= 8;
- ipa |= ident[1];
- ipa <<= 8;
- ipa |= ident[2];
- ipa <<= 8;
- ipa |= ident[3];
- ip->addr = ipa;
+ IP4_ADDR(ip, ident[0], ident[1], ident[2], ident[3]);
}
/**
@@ -152,15 +144,12 @@ snmp_oidtoip(s32_t *ident, struct ip_addr *ip)
* @param ident points to s32_t ident[4] output
*/
void
-snmp_iptooid(struct ip_addr *ip, s32_t *ident)
+snmp_iptooid(ip_addr_t *ip, s32_t *ident)
{
- u32_t ipa;
-
- ipa = ip->addr;
- ident[0] = (ipa >> 24) & 0xff;
- ident[1] = (ipa >> 16) & 0xff;
- ident[2] = (ipa >> 8) & 0xff;
- ident[3] = ipa & 0xff;
+ ident[0] = ip4_addr1(ip);
+ ident[1] = ip4_addr2(ip);
+ ident[2] = ip4_addr3(ip);
+ ident[3] = ip4_addr4(ip);
}
struct mib_list_node *
@@ -168,7 +157,7 @@ snmp_mib_ln_alloc(s32_t id)
{
struct mib_list_node *ln;
- ln = (struct mib_list_node *)mem_malloc(sizeof(struct mib_list_node));
+ ln = (struct mib_list_node *)memp_malloc(MEMP_SNMP_NODE);
if (ln != NULL)
{
ln->prev = NULL;
@@ -182,7 +171,7 @@ snmp_mib_ln_alloc(s32_t id)
void
snmp_mib_ln_free(struct mib_list_node *ln)
{
- mem_free(ln);
+ memp_free(MEMP_SNMP_NODE, ln);
}
struct mib_list_rootnode *
@@ -190,7 +179,7 @@ snmp_mib_lrn_alloc(void)
{
struct mib_list_rootnode *lrn;
- lrn = (struct mib_list_rootnode*)mem_malloc(sizeof(struct mib_list_rootnode));
+ lrn = (struct mib_list_rootnode*)memp_malloc(MEMP_SNMP_ROOTNODE);
if (lrn != NULL)
{
lrn->get_object_def = noleafs_get_object_def;
@@ -209,7 +198,7 @@ snmp_mib_lrn_alloc(void)
void
snmp_mib_lrn_free(struct mib_list_rootnode *lrn)
{
- mem_free(lrn);
+ memp_free(MEMP_SNMP_ROOTNODE, lrn);
}
/**
@@ -456,7 +445,7 @@ snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n)
* @param node points to the root of the tree ('.internet')
* @param ident_len the length of the supplied object identifier
* @param ident points to the array of sub identifiers
- * @param np points to the found object instance (rerurn)
+ * @param np points to the found object instance (return)
* @return pointer to the requested parent (!) node if success, NULL otherwise
*/
struct mib_node *
@@ -753,7 +742,8 @@ snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snm
LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n"));
/* non-leaf, store right child ptr and id */
- j = i + 1;
+ LWIP_ASSERT("i < 0xff", i < 0xff);
+ j = (u8_t)i + 1;
while ((j < an->maxlength) && (empty_table(an->nptr[j])))
{
j++;
@@ -995,7 +985,8 @@ snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snm
LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n"));
/* non-leaf, store right child ptr and id */
- j = i + 1;
+ LWIP_ASSERT("i < 0xff", i < 0xff);
+ j = (u8_t)i + 1;
if (j < len)
{
/* right node is the current external node */
diff --git a/core/lwip/src/core/snmp/msg_in.c b/core/lwip/src/core/snmp/msg_in.c
index d0c3c753..2dfb55b2 100644
--- a/core/lwip/src/core/snmp/msg_in.c
+++ b/core/lwip/src/core/snmp/msg_in.c
@@ -36,14 +36,14 @@
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
-#include "lwip/ip_addr.h"
-#include "lwip/mem.h"
-#include "lwip/udp.h"
-#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/snmp_asn1.h"
#include "lwip/snmp_msg.h"
#include "lwip/snmp_structs.h"
+#include "lwip/ip_addr.h"
+#include "lwip/memp.h"
+#include "lwip/udp.h"
+#include "lwip/stats.h"
#include <string.h>
@@ -58,7 +58,7 @@ struct snmp_msg_pstat msg_input_list[SNMP_CONCURRENT_REQUESTS];
/* UDP Protocol Control Block */
struct udp_pcb *snmp1_pcb;
-static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
+static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
static err_t snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat);
static err_t snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat);
@@ -88,6 +88,15 @@ snmp_init(void)
msg_ps++;
}
trap_msg.pcb = snmp1_pcb;
+
+#ifdef SNMP_PRIVATE_MIB_INIT
+ /* If defined, rhis must be a function-like define to initialize the
+ * private MIB after the stack has been initialized.
+ * The private MIB can also be initialized in tcpip_callback (or after
+ * the stack is initialized), this define is only for convenience. */
+ SNMP_PRIVATE_MIB_INIT();
+#endif /* SNMP_PRIVATE_MIB_INIT */
+
/* The coldstart trap will only be output
if our outgoing interface is up & configured */
snmp_coldstart_trap();
@@ -150,7 +159,8 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
/* translate answer into a known lifeform */
en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);
- if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
+ if ((msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) &&
+ (msg_ps->ext_object_def.access & MIB_ACCESS_READ))
{
msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE;
en->get_value_q(request_id, &msg_ps->ext_object_def);
@@ -171,7 +181,7 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
en = msg_ps->ext_mib_node;
/* allocate output varbind */
- vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind));
+ vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
LWIP_ASSERT("vb != NULL",vb != NULL);
if (vb != NULL)
{
@@ -186,10 +196,12 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
msg_ps->vb_ptr->ident_len = 0;
vb->value_type = msg_ps->ext_object_def.asn_type;
- vb->value_len = msg_ps->ext_object_def.v_len;
+ LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff);
+ vb->value_len = (u8_t)msg_ps->ext_object_def.v_len;
if (vb->value_len > 0)
{
- vb->value = mem_malloc(vb->value_len);
+ LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE);
+ vb->value = memp_malloc(MEMP_SNMP_VALUE);
LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
if (vb->value != NULL)
{
@@ -205,7 +217,7 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no variable space\n"));
msg_ps->vb_ptr->ident = vb->ident;
msg_ps->vb_ptr->ident_len = vb->ident_len;
- mem_free(vb);
+ memp_free(MEMP_SNMP_VARBIND, vb);
snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
}
}
@@ -268,7 +280,8 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
mn->get_object_def(np.ident_len, np.ident, &object_def);
- if (object_def.instance != MIB_OBJECT_NONE)
+ if ((object_def.instance != MIB_OBJECT_NONE) &&
+ (object_def.access & MIB_ACCESS_READ))
{
mn = mn;
}
@@ -283,7 +296,7 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;
/* allocate output varbind */
- vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind));
+ vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
LWIP_ASSERT("vb != NULL",vb != NULL);
if (vb != NULL)
{
@@ -298,10 +311,13 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
msg_ps->vb_ptr->ident_len = 0;
vb->value_type = object_def.asn_type;
- vb->value_len = object_def.v_len;
+ LWIP_ASSERT("invalid length", object_def.v_len <= 0xff);
+ vb->value_len = (u8_t)object_def.v_len;
if (vb->value_len > 0)
{
- vb->value = mem_malloc(vb->value_len);
+ LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low",
+ vb->value_len <= SNMP_MAX_VALUE_SIZE);
+ vb->value = memp_malloc(MEMP_SNMP_VALUE);
LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
if (vb->value != NULL)
{
@@ -315,7 +331,7 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate variable space\n"));
msg_ps->vb_ptr->ident = vb->ident;
msg_ps->vb_ptr->ident_len = vb->ident_len;
- mem_free(vb);
+ memp_free(MEMP_SNMP_VARBIND, vb);
snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
}
}
@@ -394,9 +410,10 @@ snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
/* get_value() answer */
en = msg_ps->ext_mib_node;
+ LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff);
vb = snmp_varbind_alloc(&msg_ps->ext_oid,
msg_ps->ext_object_def.asn_type,
- msg_ps->ext_object_def.v_len);
+ (u8_t)msg_ps->ext_object_def.v_len);
if (vb != NULL)
{
en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value);
@@ -468,7 +485,8 @@ snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
mn->get_object_def(1, &oid.id[oid.len - 1], &object_def);
- vb = snmp_varbind_alloc(&oid, object_def.asn_type, object_def.v_len);
+ LWIP_ASSERT("invalid length", object_def.v_len <= 0xff);
+ vb = snmp_varbind_alloc(&oid, object_def.asn_type, (u8_t)object_def.v_len);
if (vb != NULL)
{
msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;
@@ -538,7 +556,7 @@ snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
/* set_test() answer*/
en = msg_ps->ext_mib_node;
- if (msg_ps->ext_object_def.access == MIB_OBJECT_READ_WRITE)
+ if (msg_ps->ext_object_def.access & MIB_ACCESS_WRITE)
{
if ((msg_ps->ext_object_def.asn_type == msg_ps->vb_ptr->value_type) &&
(en->set_test_a(request_id,&msg_ps->ext_object_def,
@@ -653,7 +671,7 @@ snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
{
msg_ps->state = SNMP_MSG_INTERNAL_SET_TEST;
- if (object_def.access == MIB_OBJECT_READ_WRITE)
+ if (object_def.access & MIB_ACCESS_WRITE)
{
if ((object_def.asn_type == msg_ps->vb_ptr->value_type) &&
(mn->set_test(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0))
@@ -788,123 +806,85 @@ snmp_msg_event(u8_t request_id)
/* lwIP UDP receive callback function */
static void
-snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
+snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
{
- struct udp_hdr *udphdr;
+ struct snmp_msg_pstat *msg_ps;
+ u8_t req_idx;
+ err_t err_ret;
+ u16_t payload_len = p->tot_len;
+ u16_t payload_ofs = 0;
+ u16_t varbind_ofs = 0;
/* suppress unused argument warning */
LWIP_UNUSED_ARG(arg);
- /* peek in the UDP header (goto IP payload) */
- if(pbuf_header(p, UDP_HLEN)){
- LWIP_ASSERT("Can't move to UDP header", 0);
+
+ /* traverse input message process list, look for SNMP_MSG_EMPTY */
+ msg_ps = &msg_input_list[0];
+ req_idx = 0;
+ while ((req_idx < SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY))
+ {
+ req_idx++;
+ msg_ps++;
+ }
+ if (req_idx == SNMP_CONCURRENT_REQUESTS)
+ {
+ /* exceeding number of concurrent requests */
pbuf_free(p);
return;
}
- udphdr = p->payload;
- /* check if datagram is really directed at us (including broadcast requests) */
- if ((pcb == snmp1_pcb) && (ntohs(udphdr->dest) == SNMP_IN_PORT))
+ /* accepting request */
+ snmp_inc_snmpinpkts();
+ /* record used 'protocol control block' */
+ msg_ps->pcb = pcb;
+ /* source address (network order) */
+ msg_ps->sip = *addr;
+ /* source port (host order (lwIP oddity)) */
+ msg_ps->sp = port;
+
+ /* check total length, version, community, pdu type */
+ err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps);
+ /* Only accept requests and requests without error (be robust) */
+ /* Reject response and trap headers or error requests as input! */
+ if ((err_ret != ERR_OK) ||
+ ((msg_ps->rt != SNMP_ASN1_PDU_GET_REQ) &&
+ (msg_ps->rt != SNMP_ASN1_PDU_GET_NEXT_REQ) &&
+ (msg_ps->rt != SNMP_ASN1_PDU_SET_REQ)) ||
+ ((msg_ps->error_status != SNMP_ES_NOERROR) ||
+ (msg_ps->error_index != 0)) )
{
- struct snmp_msg_pstat *msg_ps;
- u8_t req_idx;
-
- /* traverse input message process list, look for SNMP_MSG_EMPTY */
- msg_ps = &msg_input_list[0];
- req_idx = 0;
- while ((req_idx<SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY))
- {
- req_idx++;
- msg_ps++;
- }
- if (req_idx != SNMP_CONCURRENT_REQUESTS)
- {
- err_t err_ret;
- u16_t payload_len;
- u16_t payload_ofs;
- u16_t varbind_ofs = 0;
-
- /* accepting request */
- snmp_inc_snmpinpkts();
- /* record used 'protocol control block' */
- msg_ps->pcb = pcb;
- /* source address (network order) */
- msg_ps->sip = *addr;
- /* source port (host order (lwIP oddity)) */
- msg_ps->sp = port;
- /* read UDP payload length from UDP header */
- payload_len = ntohs(udphdr->len) - UDP_HLEN;
-
- /* adjust to UDP payload */
- payload_ofs = UDP_HLEN;
-
- /* check total length, version, community, pdu type */
- err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps);
- if (((msg_ps->rt == SNMP_ASN1_PDU_GET_REQ) ||
- (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ) ||
- (msg_ps->rt == SNMP_ASN1_PDU_SET_REQ)) &&
- ((msg_ps->error_status == SNMP_ES_NOERROR) &&
- (msg_ps->error_index == 0)) )
- {
- /* Only accept requests and requests without error (be robust) */
- err_ret = err_ret;
- }
- else
- {
- /* Reject response and trap headers or error requests as input! */
- err_ret = ERR_ARG;
- }
- if (err_ret == ERR_OK)
- {
- LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community));
-
- /* Builds a list of variable bindings. Copy the varbinds from the pbuf
- chain to glue them when these are divided over two or more pbuf's. */
- err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps);
- if ((err_ret == ERR_OK) && (msg_ps->invb.count > 0))
- {
- /* we've decoded the incoming message, release input msg now */
- pbuf_free(p);
-
- msg_ps->error_status = SNMP_ES_NOERROR;
- msg_ps->error_index = 0;
- /* find object for each variable binding */
- msg_ps->state = SNMP_MSG_SEARCH_OBJ;
- /* first variable binding from list to inspect */
- msg_ps->vb_idx = 0;
-
- LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count));
-
- /* handle input event and as much objects as possible in one go */
- snmp_msg_event(req_idx);
- }
- else
- {
- /* varbind-list decode failed, or varbind list empty.
- drop request silently, do not return error!
- (errors are only returned for a specific varbind failure) */
- pbuf_free(p);
- LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n"));
- }
- }
- else
- {
- /* header check failed
- drop request silently, do not return error! */
- pbuf_free(p);
- LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n"));
- }
- }
- else
- {
- /* exceeding number of concurrent requests */
- pbuf_free(p);
- }
+ /* header check failed drop request silently, do not return error! */
+ pbuf_free(p);
+ LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n"));
+ return;
}
- else
+ LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community));
+
+ /* Builds a list of variable bindings. Copy the varbinds from the pbuf
+ chain to glue them when these are divided over two or more pbuf's. */
+ err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps);
+ /* we've decoded the incoming message, release input msg now */
+ pbuf_free(p);
+ if ((err_ret != ERR_OK) || (msg_ps->invb.count == 0))
{
- /* datagram not for us */
- pbuf_free(p);
+ /* varbind-list decode failed, or varbind list empty.
+ drop request silently, do not return error!
+ (errors are only returned for a specific varbind failure) */
+ LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n"));
+ return;
}
+
+ msg_ps->error_status = SNMP_ES_NOERROR;
+ msg_ps->error_index = 0;
+ /* find object for each variable binding */
+ msg_ps->state = SNMP_MSG_SEARCH_OBJ;
+ /* first variable binding from list to inspect */
+ msg_ps->vb_idx = 0;
+
+ LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count));
+
+ /* handle input event and as much objects as possible in one go */
+ snmp_msg_event(req_idx);
}
/**
@@ -978,7 +958,7 @@ snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret,
/* add zero terminator */
len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN));
m_stat->community[len] = 0;
- m_stat->com_strlen = len;
+ m_stat->com_strlen = (u8_t)len;
if (strncmp(snmp_publiccommunity, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0)
{
/** @todo: move this if we need to check more names */
@@ -1195,7 +1175,7 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_
vb = snmp_varbind_alloc(&oid, type, sizeof(s32_t));
if (vb != NULL)
{
- s32_t *vptr = vb->value;
+ s32_t *vptr = (s32_t*)vb->value;
derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, vptr);
snmp_varbind_tail_add(&m_stat->invb, vb);
@@ -1211,7 +1191,7 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_
vb = snmp_varbind_alloc(&oid, type, sizeof(u32_t));
if (vb != NULL)
{
- u32_t *vptr = vb->value;
+ u32_t *vptr = (u32_t*)vb->value;
derr = snmp_asn1_dec_u32t(p, ofs + 1 + len_octets, len, vptr);
snmp_varbind_tail_add(&m_stat->invb, vb);
@@ -1223,10 +1203,11 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_
break;
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):
- vb = snmp_varbind_alloc(&oid, type, len);
+ LWIP_ASSERT("invalid length", len <= 0xff);
+ vb = snmp_varbind_alloc(&oid, type, (u8_t)len);
if (vb != NULL)
{
- derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, vb->value);
+ derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value);
snmp_varbind_tail_add(&m_stat->invb, vb);
}
else
@@ -1254,7 +1235,7 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_
if (vb != NULL)
{
u8_t i = oid_value.len;
- s32_t *vptr = vb->value;
+ s32_t *vptr = (s32_t*)vb->value;
while(i > 0)
{
@@ -1277,7 +1258,7 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_
vb = snmp_varbind_alloc(&oid, type, 4);
if (vb != NULL)
{
- derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, vb->value);
+ derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value);
snmp_varbind_tail_add(&m_stat->invb, vb);
}
else
@@ -1323,7 +1304,7 @@ snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
{
struct snmp_varbind *vb;
- vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind));
+ vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
LWIP_ASSERT("vb != NULL",vb != NULL);
if (vb != NULL)
{
@@ -1335,12 +1316,13 @@ snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
vb->ident_len = i;
if (i > 0)
{
+ LWIP_ASSERT("SNMP_MAX_TREE_DEPTH is configured too low", i <= SNMP_MAX_TREE_DEPTH);
/* allocate array of s32_t for our object identifier */
- vb->ident = (s32_t*)mem_malloc(sizeof(s32_t) * i);
+ vb->ident = (s32_t*)memp_malloc(MEMP_SNMP_VALUE);
LWIP_ASSERT("vb->ident != NULL",vb->ident != NULL);
if (vb->ident == NULL)
{
- mem_free(vb);
+ memp_free(MEMP_SNMP_VARBIND, vb);
return NULL;
}
while(i > 0)
@@ -1358,16 +1340,17 @@ snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
vb->value_len = len;
if (len > 0)
{
+ LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE);
/* allocate raw bytes for our object value */
- vb->value = mem_malloc(len);
+ vb->value = memp_malloc(MEMP_SNMP_VALUE);
LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
if (vb->value == NULL)
{
if (vb->ident != NULL)
{
- mem_free(vb->ident);
+ memp_free(MEMP_SNMP_VALUE, vb->ident);
}
- mem_free(vb);
+ memp_free(MEMP_SNMP_VARBIND, vb);
return NULL;
}
}
@@ -1385,13 +1368,13 @@ snmp_varbind_free(struct snmp_varbind *vb)
{
if (vb->value != NULL )
{
- mem_free(vb->value);
+ memp_free(MEMP_SNMP_VALUE, vb->value);
}
if (vb->ident != NULL )
{
- mem_free(vb->ident);
+ memp_free(MEMP_SNMP_VALUE, vb->ident);
}
- mem_free(vb);
+ memp_free(MEMP_SNMP_VARBIND, vb);
}
void
diff --git a/core/lwip/src/core/snmp/msg_out.c b/core/lwip/src/core/snmp/msg_out.c
index b705aaca..4778bee6 100644
--- a/core/lwip/src/core/snmp/msg_out.c
+++ b/core/lwip/src/core/snmp/msg_out.c
@@ -55,7 +55,7 @@
struct snmp_trap_dst
{
/* destination IP address in network order */
- struct ip_addr dip;
+ ip_addr_t dip;
/* set to 0 when disabled, >0 when enabled */
u8_t enable;
};
@@ -92,11 +92,11 @@ snmp_trap_dst_enable(u8_t dst_idx, u8_t enable)
* @param dst IPv4 address in host order.
*/
void
-snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst)
+snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst)
{
if (dst_idx < SNMP_TRAP_DESTINATIONS)
{
- trap_dst[dst_idx].dip.addr = htonl(dst->addr);
+ ip_addr_set(&trap_dst[dst_idx].dip, dst);
}
}
@@ -221,23 +221,24 @@ snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap)
{
struct snmp_trap_dst *td;
struct netif *dst_if;
- struct ip_addr dst_ip;
+ ip_addr_t dst_ip;
struct pbuf *p;
u16_t i,tot_len;
for (i=0, td = &trap_dst[0]; i<SNMP_TRAP_DESTINATIONS; i++, td++)
{
- if ((td->enable != 0) && (td->dip.addr != 0))
+ if ((td->enable != 0) && !ip_addr_isany(&td->dip))
{
/* network order trap destination */
- trap_msg.dip.addr = td->dip.addr;
+ ip_addr_copy(trap_msg.dip, td->dip);
/* lookup current source address for this dst */
dst_if = ip_route(&td->dip);
- dst_ip.addr = ntohl(dst_if->ip_addr.addr);
- trap_msg.sip_raw[0] = dst_ip.addr >> 24;
- trap_msg.sip_raw[1] = dst_ip.addr >> 16;
- trap_msg.sip_raw[2] = dst_ip.addr >> 8;
- trap_msg.sip_raw[3] = dst_ip.addr;
+ ip_addr_copy(dst_ip, dst_if->ip_addr);
+ /* @todo: what about IPv6? */
+ trap_msg.sip_raw[0] = ip4_addr1(&dst_ip);
+ trap_msg.sip_raw[1] = ip4_addr2(&dst_ip);
+ trap_msg.sip_raw[2] = ip4_addr3(&dst_ip);
+ trap_msg.sip_raw[3] = ip4_addr4(&dst_ip);
trap_msg.gen_trap = generic_trap;
trap_msg.spc_trap = specific_trap;
if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC)
@@ -269,11 +270,8 @@ snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap)
snmp_inc_snmpouttraps();
snmp_inc_snmpoutpkts();
- /** connect to the TRAP destination */
- udp_connect(trap_msg.pcb, &trap_msg.dip, SNMP_TRAP_PORT);
- udp_send(trap_msg.pcb, p);
- /** disassociate remote address and port with this pcb */
- udp_disconnect(trap_msg.pcb);
+ /** send to the TRAP destination */
+ udp_sendto(trap_msg.pcb, p, &trap_msg.dip, SNMP_TRAP_PORT);
pbuf_free(p);
}
@@ -435,13 +433,13 @@ snmp_varbind_list_sum(struct snmp_varbind_root *root)
switch (vb->value_type)
{
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):
- sint_ptr = vb->value;
+ sint_ptr = (s32_t*)vb->value;
snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen);
break;
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):
- uint_ptr = vb->value;
+ uint_ptr = (u32_t*)vb->value;
snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen);
break;
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
@@ -451,7 +449,7 @@ snmp_varbind_list_sum(struct snmp_varbind_root *root)
vb->vlen = vb->value_len;
break;
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):
- sint_ptr = vb->value;
+ sint_ptr = (s32_t*)vb->value;
snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen);
break;
default:
@@ -649,25 +647,25 @@ snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs)
switch (vb->value_type)
{
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):
- sint_ptr = vb->value;
+ sint_ptr = (s32_t*)vb->value;
snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr);
break;
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):
- uint_ptr = vb->value;
+ uint_ptr = (u32_t*)vb->value;
snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr);
break;
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR):
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):
- raw_ptr = vb->value;
+ raw_ptr = (u8_t*)vb->value;
snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr);
break;
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL):
break;
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):
- sint_ptr = vb->value;
+ sint_ptr = (s32_t*)vb->value;
snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr);
break;
default:
diff --git a/core/lwip/src/core/stats.c b/core/lwip/src/core/stats.c
index a036d83b..69f97d41 100644
--- a/core/lwip/src/core/stats.c
+++ b/core/lwip/src/core/stats.c
@@ -48,6 +48,25 @@
struct stats_ lwip_stats;
+void stats_init(void)
+{
+#ifdef LWIP_DEBUG
+#if MEMP_STATS
+ const char * memp_names[] = {
+#define LWIP_MEMPOOL(name,num,size,desc) desc,
+#include "lwip/memp_std.h"
+ };
+ int i;
+ for (i = 0; i < MEMP_MAX; i++) {
+ lwip_stats.memp[i].name = memp_names[i];
+ }
+#endif /* MEMP_STATS */
+#if MEM_STATS
+ lwip_stats.mem.name = "MEM";
+#endif /* MEM_STATS */
+#endif /* LWIP_DEBUG */
+}
+
#if LWIP_STATS_DISPLAY
void
stats_display_proto(struct stats_proto *proto, char *name)
@@ -72,15 +91,20 @@ void
stats_display_igmp(struct stats_igmp *igmp)
{
LWIP_PLATFORM_DIAG(("\nIGMP\n\t"));
- LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr));
+ LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit));
+ LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv));
+ LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop));
LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr));
- LWIP_PLATFORM_DIAG(("v1_rxed: %"STAT_COUNTER_F"\n\t", igmp->v1_rxed));
- LWIP_PLATFORM_DIAG(("join_sent: %"STAT_COUNTER_F"\n\t", igmp->join_sent));
- LWIP_PLATFORM_DIAG(("leave_sent: %"STAT_COUNTER_F"\n\t", igmp->leave_sent));
- LWIP_PLATFORM_DIAG(("unicast_query: %"STAT_COUNTER_F"\n\t", igmp->unicast_query));
- LWIP_PLATFORM_DIAG(("report_sent: %"STAT_COUNTER_F"\n\t", igmp->report_sent));
- 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));
+ LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr));
+ LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr));
+ LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr));
+ LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1));
+ LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n", igmp->rx_group));
+ LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n", igmp->rx_general));
+ LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report));
+ LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join));
+ LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave));
+ LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report));
}
#endif /* IGMP_STATS */
@@ -115,12 +139,15 @@ 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));
+ 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(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used));
+ LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max));
+ LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.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 */
diff --git a/core/lwip/src/core/sys.c b/core/lwip/src/core/sys.c
index cb5e86a7..d3a77deb 100644
--- a/core/lwip/src/core/sys.c
+++ b/core/lwip/src/core/sys.c
@@ -38,309 +38,29 @@
#include "lwip/opt.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"
-
-/**
- * Struct used for sys_sem_wait_timeout() to tell wether the time
- * has run out or the semaphore has really become available.
- */
-struct sswt_cb
-{
- s16_t timeflag;
- sys_sem_t *psem;
-};
-
-/**
- * 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)
-{
- u32_t time_needed;
- struct sys_timeouts *timeouts;
- struct sys_timeo *tmptimeout;
- sys_timeout_handler h;
- void *arg;
-
- again:
- timeouts = sys_arch_timeouts();
-
- if (!timeouts || !timeouts->next) {
- UNLOCK_TCPIP_CORE();
- time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
- LOCK_TCPIP_CORE();
- } else {
- if (timeouts->next->time > 0) {
- UNLOCK_TCPIP_CORE();
- time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
- LOCK_TCPIP_CORE();
- } else {
- time_needed = 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. */
- tmptimeout = timeouts->next;
- timeouts->next = tmptimeout->next;
- h = tmptimeout->h;
- arg = tmptimeout->arg;
- memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
- if (h != NULL) {
- LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", *(void**)&h, arg));
- h(arg);
- }
-
- /* We try again to fetch a message from the mbox. */
- goto again;
- } else {
- /* 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_needed < timeouts->next->time) {
- timeouts->next->time -= time_needed;
- } else {
- timeouts->next->time = 0;
- }
- }
- }
-}
-
-/**
- * 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)
-{
- u32_t time_needed;
- struct sys_timeouts *timeouts;
- struct sys_timeo *tmptimeout;
- sys_timeout_handler h;
- void *arg;
-
- again:
-
- timeouts = sys_arch_timeouts();
-
- if (!timeouts || !timeouts->next) {
- sys_arch_sem_wait(sem, 0);
- } else {
- if (timeouts->next->time > 0) {
- time_needed = sys_arch_sem_wait(sem, timeouts->next->time);
- } else {
- time_needed = 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. */
- tmptimeout = timeouts->next;
- timeouts->next = tmptimeout->next;
- h = tmptimeout->h;
- arg = tmptimeout->arg;
- memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
- if (h != NULL) {
- LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", *(void**)&h, (void *)arg));
- h(arg);
- }
-
- /* We try again to fetch a message from the mbox. */
- goto again;
- } else {
- /* 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_needed < timeouts->next->time) {
- timeouts->next->time -= time_needed;
- } else {
- timeouts->next->time = 0;
- }
- }
- }
-}
-
-/**
- * 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)
-{
- struct sys_timeouts *timeouts;
- struct sys_timeo *timeout, *t;
-
- timeout = memp_malloc(MEMP_SYS_TIMEOUT);
- if (timeout == NULL) {
- LWIP_ASSERT("sys_timeout: timeout != NULL", timeout != NULL);
- return;
- }
- timeout->next = NULL;
- timeout->h = h;
- timeout->arg = arg;
- timeout->time = msecs;
-
- timeouts = sys_arch_timeouts();
- LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n",
- (void *)timeout, msecs, *(void**)&h, (void *)arg));
+/* Most of the functions defined in sys.h must be implemented in the
+ * architecture-dependent file sys_arch.c */
- if (timeouts == NULL) {
- LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
- return;
- }
-
- if (timeouts->next == NULL) {
- timeouts->next = timeout;
- return;
- }
-
- if (timeouts->next->time > msecs) {
- timeouts->next->time -= msecs;
- timeout->next = timeouts->next;
- timeouts->next = timeout;
- } else {
- for(t = timeouts->next; t != NULL; t = t->next) {
- timeout->time -= t->time;
- if (t->next == NULL || t->next->time > timeout->time) {
- if (t->next != NULL) {
- t->next->time -= timeout->time;
- }
- timeout->next = t->next;
- t->next = timeout;
- break;
- }
- }
- }
-}
-
-/**
- * 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)
-{
- struct sys_timeouts *timeouts;
- struct sys_timeo *prev_t, *t;
-
- timeouts = sys_arch_timeouts();
-
- if (timeouts == NULL) {
- LWIP_ASSERT("sys_untimeout: timeouts != NULL", timeouts != NULL);
- return;
- }
- if (timeouts->next == NULL) {
- return;
- }
-
- for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
- if ((t->h == h) && (t->arg == arg)) {
- /* We have a match */
- /* Unlink from previous in list */
- if (prev_t == NULL) {
- timeouts->next = t->next;
- } else {
- prev_t->next = t->next;
- }
- /* If not the last one, add time of this one back to next */
- if (t->next != NULL) {
- t->next->time += t->time;
- }
- memp_free(MEMP_SYS_TIMEOUT, t);
- return;
- }
- }
- return;
-}
+#if !NO_SYS
/**
- * Timeout handler function for sys_sem_wait_timeout()
- *
- * @param arg struct sswt_cb* used to signal a semaphore and end waiting.
- */
-static void
-sswt_handler(void *arg)
-{
- struct sswt_cb *sswt_cb = (struct sswt_cb *) arg;
-
- /* Timeout. Set flag to TRUE and signal semaphore */
- sswt_cb->timeflag = 1;
- sys_sem_signal(*(sswt_cb->psem));
-}
-
-/**
- * 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)
-{
- struct sswt_cb sswt_cb;
-
- sswt_cb.psem = &sem;
- sswt_cb.timeflag = 0;
-
- /* If timeout is zero, then just wait forever */
- if (timeout > 0) {
- /* Create a timer and pass it the address of our flag */
- sys_timeout(timeout, sswt_handler, &sswt_cb);
- }
- sys_sem_wait(sem);
- /* Was it a timeout? */
- if (sswt_cb.timeflag) {
- /* timeout */
- return 0;
- } else {
- /* Not a timeout. Remove timeout entry */
- sys_untimeout(sswt_handler, &sswt_cb);
- return 1;
- }
-}
-
-/**
- * Sleep for some ms. Timeouts are processed while sleeping.
+ * Sleep for some ms. Timeouts are NOT processed while sleeping.
*
* @param ms number of milliseconds to sleep
*/
void
sys_msleep(u32_t ms)
{
- sys_sem_t delaysem = sys_sem_new(0);
-
- sys_sem_wait_timeout(delaysem, ms);
-
- sys_sem_free(delaysem);
+ if (ms > 0) {
+ sys_sem_t delaysem;
+ err_t err = sys_sem_new(&delaysem, 0);
+ if (err == ERR_OK) {
+ sys_arch_sem_wait(&delaysem, ms);
+ sys_sem_free(&delaysem);
+ }
+ }
}
-
-#endif /* NO_SYS */
+#endif /* !NO_SYS */
diff --git a/core/lwip/src/core/tcp.c b/core/lwip/src/core/tcp.c
index 29cdf185..c629bc4e 100644
--- a/core/lwip/src/core/tcp.c
+++ b/core/lwip/src/core/tcp.c
@@ -49,12 +49,13 @@
#include "lwip/memp.h"
#include "lwip/snmp.h"
#include "lwip/tcp.h"
+#include "lwip/tcp_impl.h"
#include "lwip/debug.h"
#include "lwip/stats.h"
#include <string.h>
-const char *tcp_state_str[] = {
+const char * const tcp_state_str[] = {
"CLOSED",
"LISTEN",
"SYN_SENT",
@@ -78,17 +79,25 @@ const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 };
/* The TCP PCB lists. */
/** List of all TCP PCBs bound but not yet (connected || listening) */
-struct tcp_pcb *tcp_bound_pcbs;
+struct tcp_pcb *tcp_bound_pcbs;
/** List of all TCP PCBs in LISTEN state */
union tcp_listen_pcbs_t tcp_listen_pcbs;
/** List of all TCP PCBs that are in a state in which
* they accept or send data. */
-struct tcp_pcb *tcp_active_pcbs;
+struct tcp_pcb *tcp_active_pcbs;
/** List of all TCP PCBs in TIME-WAIT state */
struct tcp_pcb *tcp_tw_pcbs;
+#define NUM_TCP_PCB_LISTS 4
+#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3
+/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */
+struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs,
+ &tcp_active_pcbs, &tcp_tw_pcbs};
+
+/** Only used for temporary storage. */
struct tcp_pcb *tcp_tmp_pcb;
+/** Timer counter to handle calling slow-timer from tcp_tmr() */
static u8_t tcp_timer;
static u16_t tcp_new_port(void);
@@ -110,7 +119,9 @@ tcp_tmr(void)
}
/**
- * Closes the connection held by the PCB.
+ * Closes the TX side of a connection held by the PCB.
+ * For tcp_close(), a RST is sent if the application didn't receive all data
+ * (tcp_recved() not called for all data passed to recv callback).
*
* Listening pcbs are freed and may not be referenced any more.
* Connection pcbs are freed if not yet connected and may not be referenced
@@ -123,15 +134,34 @@ tcp_tmr(void)
* @return ERR_OK if connection has been closed
* another err_t if closing failed and pcb is not freed
*/
-err_t
-tcp_close(struct tcp_pcb *pcb)
+static err_t
+tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
{
err_t err;
-#if TCP_DEBUG
- LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in "));
- tcp_debug_print_state(pcb->state);
-#endif /* TCP_DEBUG */
+ if (rst_on_unacked_data && (pcb->state != LISTEN)) {
+ if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND)) {
+ /* Not all data received by application, send RST to tell the remote
+ side about this. */
+ LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED);
+
+ /* don't call tcp_abort here: we must not deallocate the pcb since
+ that might not be expected when calling tcp_close */
+ tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
+ pcb->local_port, pcb->remote_port);
+
+ tcp_pcb_purge(pcb);
+
+ /* TODO: to which state do we move now? */
+
+ /* move to TIME_WAIT since we close actively */
+ TCP_RMV(&tcp_active_pcbs, pcb);
+ pcb->state = TIME_WAIT;
+ TCP_REG(&tcp_tw_pcbs, pcb);
+
+ return ERR_OK;
+ }
+ }
switch (pcb->state) {
case CLOSED:
@@ -143,13 +173,15 @@ tcp_close(struct tcp_pcb *pcb)
* is erroneous, but this should never happen as the pcb has in those cases
* been freed, and so any remaining handles are bogus. */
err = ERR_OK;
- TCP_RMV(&tcp_bound_pcbs, pcb);
+ if (pcb->local_port != 0) {
+ TCP_RMV(&tcp_bound_pcbs, pcb);
+ }
memp_free(MEMP_TCP_PCB, pcb);
pcb = NULL;
break;
case LISTEN:
err = ERR_OK;
- tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb);
+ tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb);
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
pcb = NULL;
break;
@@ -161,21 +193,21 @@ tcp_close(struct tcp_pcb *pcb)
snmp_inc_tcpattemptfails();
break;
case SYN_RCVD:
- err = tcp_send_ctrl(pcb, TCP_FIN);
+ err = tcp_send_fin(pcb);
if (err == ERR_OK) {
snmp_inc_tcpattemptfails();
pcb->state = FIN_WAIT_1;
}
break;
case ESTABLISHED:
- err = tcp_send_ctrl(pcb, TCP_FIN);
+ err = tcp_send_fin(pcb);
if (err == ERR_OK) {
snmp_inc_tcpestabresets();
pcb->state = FIN_WAIT_1;
}
break;
case CLOSE_WAIT:
- err = tcp_send_ctrl(pcb, TCP_FIN);
+ err = tcp_send_fin(pcb);
if (err == ERR_OK) {
snmp_inc_tcpestabresets();
pcb->state = LAST_ACK;
@@ -195,13 +227,86 @@ tcp_close(struct tcp_pcb *pcb)
returns (unsent data is sent from tcp timer functions, also), we don't care
for the return value of tcp_output for now. */
/* @todo: When implementing SO_LINGER, this must be changed somehow:
- If SOF_LINGER is set, the data should be sent when tcp_close returns. */
+ If SOF_LINGER is set, the data should be sent and acked before close returns.
+ This can only be valid for sequential APIs, not for the raw API. */
tcp_output(pcb);
}
return err;
}
/**
+ * Closes the connection held by the PCB.
+ *
+ * Listening pcbs are freed and may not be referenced any more.
+ * Connection pcbs are freed if not yet connected and may not be referenced
+ * any more. If a connection is established (at least SYN received or in
+ * a closing state), the connection is closed, and put in a closing state.
+ * The pcb is then automatically freed in tcp_slowtmr(). It is therefore
+ * unsafe to reference it (unless an error is returned).
+ *
+ * @param pcb the tcp_pcb to close
+ * @return ERR_OK if connection has been closed
+ * another err_t if closing failed and pcb is not freed
+ */
+err_t
+tcp_close(struct tcp_pcb *pcb)
+{
+#if TCP_DEBUG
+ LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in "));
+ tcp_debug_print_state(pcb->state);
+#endif /* TCP_DEBUG */
+
+ if (pcb->state != LISTEN) {
+ /* Set a flag not to receive any more data... */
+ pcb->flags |= TF_RXCLOSED;
+ }
+ /* ... and close */
+ return tcp_close_shutdown(pcb, 1);
+}
+
+/**
+ * Causes all or part of a full-duplex connection of this PCB to be shut down.
+ * This doesn't deallocate the PCB!
+ *
+ * @param pcb PCB to shutdown
+ * @param shut_rx shut down receive side if this is != 0
+ * @param shut_tx shut down send side if this is != 0
+ * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down)
+ * another err_t on error.
+ */
+err_t
+tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx)
+{
+ if (pcb->state == LISTEN) {
+ return ERR_CONN;
+ }
+ if (shut_rx) {
+ /* shut down the receive side: free buffered data... */
+ if (pcb->refused_data != NULL) {
+ pbuf_free(pcb->refused_data);
+ pcb->refused_data = NULL;
+ }
+ /* ... and set a flag not to receive any more data */
+ pcb->flags |= TF_RXCLOSED;
+ }
+ if (shut_tx) {
+ /* This can't happen twice since if it succeeds, the pcb's state is changed.
+ Only close in these states as the others directly deallocate the PCB */
+ switch (pcb->state) {
+ case SYN_RCVD:
+ case ESTABLISHED:
+ case CLOSE_WAIT:
+ return tcp_close_shutdown(pcb, 0);
+ default:
+ /* don't shut down other states */
+ break;
+ }
+ }
+ /* @todo: return another err_t if not in correct state or already shut? */
+ return ERR_OK;
+}
+
+/**
* Abandons a connection and optionally sends a RST to the remote
* host. Deletes the local protocol control block. This is done when
* a connection is killed because of shortage of memory.
@@ -214,13 +319,15 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
{
u32_t seqno, ackno;
u16_t remote_port, local_port;
- struct ip_addr remote_ip, local_ip;
+ ip_addr_t remote_ip, local_ip;
#if LWIP_CALLBACK_API
- void (* errf)(void *arg, err_t err);
+ tcp_err_fn errf;
#endif /* LWIP_CALLBACK_API */
void *errf_arg;
-
+ /* pcb->state LISTEN not allowed here */
+ LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs",
+ pcb->state != LISTEN);
/* Figure out on which TCP PCB list we are, and remove us. If we
are in an active state, call the receive function associated with
the PCB with a NULL argument, and send an RST to the remote end. */
@@ -230,8 +337,8 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
} else {
seqno = pcb->snd_nxt;
ackno = pcb->rcv_nxt;
- ip_addr_set(&local_ip, &(pcb->local_ip));
- ip_addr_set(&remote_ip, &(pcb->remote_ip));
+ ip_addr_copy(local_ip, pcb->local_ip);
+ ip_addr_copy(remote_ip, pcb->remote_ip);
local_port = pcb->local_port;
remote_port = pcb->remote_port;
#if LWIP_CALLBACK_API
@@ -260,6 +367,22 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
}
/**
+ * Aborts the connection by sending a RST (reset) segment to the remote
+ * host. The pcb is deallocated. This function never fails.
+ *
+ * ATTENTION: When calling this from one of the TCP callbacks, make
+ * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise
+ * or you will risk accessing deallocated memory or memory leaks!
+ *
+ * @param pcb the tcp pcb to abort
+ */
+void
+tcp_abort(struct tcp_pcb *pcb)
+{
+ tcp_abandon(pcb, 1);
+}
+
+/**
* Binds the connection to a local portnumber and IP address. If the
* IP address is not given (i.e., ipaddr == NULL), the IP address of
* the outgoing network interface is used instead.
@@ -270,57 +393,51 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
* to any local address
* @param port the local port to bind to
* @return ERR_USE if the port is already in use
+ * ERR_VAL if bind failed because the PCB is not in a valid state
* ERR_OK if bound
*/
err_t
-tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
+tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
{
+ int i;
+ int max_pcb_list = NUM_TCP_PCB_LISTS;
struct tcp_pcb *cpcb;
- LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
+ LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL);
+
+#if SO_REUSE
+ /* Unless the REUSEADDR flag is set,
+ we have to check the pcbs in TIME-WAIT state, also.
+ We do not dump TIME_WAIT pcb's; they can still be matched by incoming
+ packets using both local and remote IP addresses and ports to distinguish.
+ */
+ if ((pcb->so_options & SOF_REUSEADDR) != 0) {
+ max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT;
+ }
+#endif /* SO_REUSE */
if (port == 0) {
port = tcp_new_port();
}
- /* Check if the address already is in use. */
- /* Check the listen pcbs. */
- for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
- cpcb != NULL; cpcb = cpcb->next) {
- if (cpcb->local_port == port) {
- if (ip_addr_isany(&(cpcb->local_ip)) ||
- ip_addr_isany(ipaddr) ||
- ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
- return ERR_USE;
- }
- }
- }
- /* Check the connected pcbs. */
- for(cpcb = tcp_active_pcbs;
- cpcb != NULL; cpcb = cpcb->next) {
- if (cpcb->local_port == port) {
- if (ip_addr_isany(&(cpcb->local_ip)) ||
- ip_addr_isany(ipaddr) ||
- ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
- return ERR_USE;
- }
- }
- }
- /* Check the bound, not yet connected pcbs. */
- for(cpcb = tcp_bound_pcbs; cpcb != NULL; cpcb = cpcb->next) {
- if (cpcb->local_port == port) {
- if (ip_addr_isany(&(cpcb->local_ip)) ||
- ip_addr_isany(ipaddr) ||
- ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
- return ERR_USE;
- }
- }
- }
- /* @todo: until SO_REUSEADDR is implemented (see task #6995 on savannah),
- * we have to check the pcbs in TIME-WAIT state, also: */
- for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
- if (cpcb->local_port == port) {
- if (ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
- return ERR_USE;
+
+ /* Check if the address already is in use (on all lists) */
+ for (i = 0; i < max_pcb_list; i++) {
+ for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
+ if (cpcb->local_port == port) {
+#if SO_REUSE
+ /* Omit checking for the same port if both pcbs have REUSEADDR set.
+ For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in
+ tcp_connect. */
+ if (((pcb->so_options & SOF_REUSEADDR) == 0) ||
+ ((cpcb->so_options & SOF_REUSEADDR) == 0))
+#endif /* SO_REUSE */
+ {
+ if (ip_addr_isany(&(cpcb->local_ip)) ||
+ ip_addr_isany(ipaddr) ||
+ ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
+ return ERR_USE;
+ }
+ }
}
}
}
@@ -374,19 +491,37 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
if (pcb->state == LISTEN) {
return pcb;
}
- lpcb = memp_malloc(MEMP_TCP_PCB_LISTEN);
+#if SO_REUSE
+ if ((pcb->so_options & SOF_REUSEADDR) != 0) {
+ /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage
+ is declared (listen-/connection-pcb), we have to make sure now that
+ this port is only used once for every local IP. */
+ for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
+ if (lpcb->local_port == pcb->local_port) {
+ if (ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) {
+ /* this address/port is already used */
+ return NULL;
+ }
+ }
+ }
+ }
+#endif /* SO_REUSE */
+ lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN);
if (lpcb == NULL) {
return NULL;
}
lpcb->callback_arg = pcb->callback_arg;
lpcb->local_port = pcb->local_port;
lpcb->state = LISTEN;
+ lpcb->prio = pcb->prio;
lpcb->so_options = pcb->so_options;
lpcb->so_options |= SOF_ACCEPTCONN;
lpcb->ttl = pcb->ttl;
lpcb->tos = pcb->tos;
- ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
- TCP_RMV(&tcp_bound_pcbs, pcb);
+ ip_addr_copy(lpcb->local_ip, pcb->local_ip);
+ if (pcb->local_port != 0) {
+ TCP_RMV(&tcp_bound_pcbs, pcb);
+ }
memp_free(MEMP_TCP_PCB, pcb);
#if LWIP_CALLBACK_API
lpcb->accept = tcp_accept_null;
@@ -395,7 +530,7 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
lpcb->accepts_pending = 0;
lpcb->backlog = (backlog ? backlog : 1);
#endif /* TCP_LISTEN_BACKLOG */
- TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb);
+ TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb);
return (struct tcp_pcb *)lpcb;
}
@@ -420,7 +555,9 @@ u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb)
pcb->rcv_ann_wnd = 0;
} else {
/* keep the right edge of window constant */
- pcb->rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt;
+ u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt;
+ LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff);
+ pcb->rcv_ann_wnd = (u16_t)new_rcv_ann_wnd;
}
return 0;
}
@@ -443,17 +580,20 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
len <= 0xffff - pcb->rcv_wnd );
pcb->rcv_wnd += len;
- if (pcb->rcv_wnd > TCP_WND)
+ if (pcb->rcv_wnd > TCP_WND) {
pcb->rcv_wnd = TCP_WND;
+ }
wnd_inflation = tcp_update_rcv_ann_wnd(pcb);
/* If the change in the right edge of window is significant (default
- * watermark is TCP_WND/2), then send an explicit update now.
+ * watermark is TCP_WND/4), then send an explicit update now.
* Otherwise wait for a packet to be sent in the normal course of
* events (or more window to be available later) */
- if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD)
+ if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) {
tcp_ack_now(pcb);
+ tcp_output(pcb);
+ }
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n",
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
@@ -468,31 +608,26 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
static u16_t
tcp_new_port(void)
{
+ int i;
struct tcp_pcb *pcb;
#ifndef TCP_LOCAL_PORT_RANGE_START
-#define TCP_LOCAL_PORT_RANGE_START 4096
-#define TCP_LOCAL_PORT_RANGE_END 0x7fff
+/* From http://www.iana.org/assignments/port-numbers:
+ "The Dynamic and/or Private Ports are those from 49152 through 65535" */
+#define TCP_LOCAL_PORT_RANGE_START 0xc000
+#define TCP_LOCAL_PORT_RANGE_END 0xffff
#endif
static u16_t port = TCP_LOCAL_PORT_RANGE_START;
again:
- if (++port > TCP_LOCAL_PORT_RANGE_END) {
+ if (port++ >= TCP_LOCAL_PORT_RANGE_END) {
port = TCP_LOCAL_PORT_RANGE_START;
}
-
- for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
- if (pcb->local_port == port) {
- goto again;
- }
- }
- for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
- if (pcb->local_port == port) {
- goto again;
- }
- }
- for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
- if (pcb->local_port == port) {
- goto again;
+ /* Check all PCB lists. */
+ for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
+ for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
+ if (pcb->local_port == port) {
+ goto again;
+ }
}
}
return port;
@@ -511,13 +646,14 @@ tcp_new_port(void)
* other err_t values if connect request couldn't be sent
*/
err_t
-tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
- err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
+tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
+ tcp_connected_fn connected)
{
err_t ret;
u32_t iss;
+ u16_t old_local_port;
- LWIP_ERROR("tcp_connect: can only connected from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
+ LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
if (ipaddr != NULL) {
@@ -526,9 +662,44 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
return ERR_VAL;
}
pcb->remote_port = port;
+
+ /* check if we have a route to the remote host */
+ if (ip_addr_isany(&(pcb->local_ip))) {
+ /* no local IP address set, yet. */
+ struct netif *netif = ip_route(&(pcb->remote_ip));
+ if (netif == NULL) {
+ /* Don't even try to send a SYN packet if we have no route
+ since that will fail. */
+ return ERR_RTE;
+ }
+ /* Use the netif's IP address as local address. */
+ ip_addr_copy(pcb->local_ip, netif->ip_addr);
+ }
+
+ old_local_port = pcb->local_port;
if (pcb->local_port == 0) {
pcb->local_port = tcp_new_port();
}
+#if SO_REUSE
+ if ((pcb->so_options & SOF_REUSEADDR) != 0) {
+ /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure
+ now that the 5-tuple is unique. */
+ struct tcp_pcb *cpcb;
+ int i;
+ /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */
+ for (i = 2; i < NUM_TCP_PCB_LISTS; i++) {
+ for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
+ if ((cpcb->local_port == pcb->local_port) &&
+ (cpcb->remote_port == port) &&
+ ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) &&
+ ip_addr_cmp(&cpcb->remote_ip, ipaddr)) {
+ /* linux returns EISCONN here, but ERR_USE should be OK for us */
+ return ERR_USE;
+ }
+ }
+ }
+ }
+#endif /* SO_REUSE */
iss = tcp_next_iss();
pcb->rcv_nxt = 0;
pcb->snd_nxt = iss;
@@ -546,25 +717,27 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
pcb->cwnd = 1;
pcb->ssthresh = pcb->mss * 10;
- pcb->state = SYN_SENT;
-#if LWIP_CALLBACK_API
+#if LWIP_CALLBACK_API
pcb->connected = connected;
+#else /* LWIP_CALLBACK_API */
+ LWIP_UNUSED_ARG(connected);
#endif /* LWIP_CALLBACK_API */
- TCP_RMV(&tcp_bound_pcbs, pcb);
- TCP_REG(&tcp_active_pcbs, pcb);
- snmp_inc_tcpactiveopens();
-
- ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, TF_SEG_OPTS_MSS
-#if LWIP_TCP_TIMESTAMPS
- | TF_SEG_OPTS_TS
-#endif
- );
- if (ret == ERR_OK) {
+ /* Send a SYN together with the MSS option. */
+ ret = tcp_enqueue_flags(pcb, TCP_SYN);
+ if (ret == ERR_OK) {
+ /* SYN segment was enqueued, changed the pcbs state now */
+ pcb->state = SYN_SENT;
+ if (old_local_port != 0) {
+ TCP_RMV(&tcp_bound_pcbs, pcb);
+ }
+ TCP_REG(&tcp_active_pcbs, pcb);
+ snmp_inc_tcpactiveopens();
+
tcp_output(pcb);
}
return ret;
-}
+}
/**
* Called every 500 ms and implements the retransmission timer and the timer that
@@ -576,7 +749,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
void
tcp_slowtmr(void)
{
- struct tcp_pcb *pcb, *pcb2, *prev;
+ struct tcp_pcb *pcb, *prev;
u16_t eff_wnd;
u8_t pcb_remove; /* flag if a PCB should be removed */
u8_t pcb_reset; /* flag if a RST should be sent when removing */
@@ -643,8 +816,8 @@ tcp_slowtmr(void)
/* Reduce congestion window and ssthresh. */
eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
pcb->ssthresh = eff_wnd >> 1;
- if (pcb->ssthresh < pcb->mss) {
- pcb->ssthresh = pcb->mss * 2;
+ if (pcb->ssthresh < (pcb->mss << 1)) {
+ pcb->ssthresh = (pcb->mss << 1);
}
pcb->cwnd = pcb->mss;
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F
@@ -667,21 +840,21 @@ tcp_slowtmr(void)
}
/* Check if KEEPALIVE should be sent */
- if((pcb->so_options & SOF_KEEPALIVE) &&
- ((pcb->state == ESTABLISHED) ||
+ if((pcb->so_options & SOF_KEEPALIVE) &&
+ ((pcb->state == ESTABLISHED) ||
(pcb->state == CLOSE_WAIT))) {
#if LWIP_TCP_KEEPALIVE
- if((u32_t)(tcp_ticks - pcb->tmr) >
+ if((u32_t)(tcp_ticks - pcb->tmr) >
(pcb->keep_idle + (pcb->keep_cnt*pcb->keep_intvl))
/ TCP_SLOW_INTERVAL)
#else
- if((u32_t)(tcp_ticks - pcb->tmr) >
+ if((u32_t)(tcp_ticks - pcb->tmr) >
(pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)
#endif /* LWIP_TCP_KEEPALIVE */
{
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
- ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
- ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
+ ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
+ ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
++pcb_remove;
++pcb_reset;
@@ -704,7 +877,7 @@ tcp_slowtmr(void)
/* If this PCB has queued out of sequence data, but has been
inactive for too long, will drop the data (it will eventually
be retransmitted). */
-#if TCP_QUEUE_OOSEQ
+#if TCP_QUEUE_OOSEQ
if (pcb->ooseq != NULL &&
(u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) {
tcp_segs_free(pcb->ooseq);
@@ -732,7 +905,8 @@ tcp_slowtmr(void)
/* If the PCB should be removed, do it. */
if (pcb_remove) {
- tcp_pcb_purge(pcb);
+ struct tcp_pcb *pcb2;
+ tcp_pcb_purge(pcb);
/* Remove PCB from tcp_active_pcbs list. */
if (prev != NULL) {
LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
@@ -749,30 +923,31 @@ tcp_slowtmr(void)
pcb->local_port, pcb->remote_port);
}
- pcb2 = pcb->next;
- memp_free(MEMP_TCP_PCB, pcb);
- pcb = pcb2;
+ pcb2 = pcb;
+ pcb = pcb->next;
+ memp_free(MEMP_TCP_PCB, pcb2);
} else {
+ /* get the 'next' element now and work with 'prev' below (in case of abort) */
+ prev = pcb;
+ pcb = pcb->next;
/* We check if we should poll the connection. */
- ++pcb->polltmr;
- if (pcb->polltmr >= pcb->pollinterval) {
- pcb->polltmr = 0;
+ ++prev->polltmr;
+ if (prev->polltmr >= prev->pollinterval) {
+ prev->polltmr = 0;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n"));
- TCP_EVENT_POLL(pcb, err);
+ TCP_EVENT_POLL(prev, err);
+ /* if err == ERR_ABRT, 'prev' is already deallocated */
if (err == ERR_OK) {
- tcp_output(pcb);
+ tcp_output(prev);
}
}
-
- prev = pcb;
- pcb = pcb->next;
}
}
/* Steps through all of the TIME-WAIT PCBs. */
- prev = NULL;
+ prev = NULL;
pcb = tcp_tw_pcbs;
while (pcb != NULL) {
LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
@@ -787,7 +962,8 @@ tcp_slowtmr(void)
/* If the PCB should be removed, do it. */
if (pcb_remove) {
- tcp_pcb_purge(pcb);
+ struct tcp_pcb *pcb2;
+ tcp_pcb_purge(pcb);
/* Remove PCB from tcp_tw_pcbs list. */
if (prev != NULL) {
LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
@@ -797,9 +973,9 @@ tcp_slowtmr(void)
LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
tcp_tw_pcbs = pcb->next;
}
- pcb2 = pcb->next;
- memp_free(MEMP_TCP_PCB, pcb);
- pcb = pcb2;
+ pcb2 = pcb;
+ pcb = pcb->next;
+ memp_free(MEMP_TCP_PCB, pcb2);
} else {
prev = pcb;
pcb = pcb->next;
@@ -816,9 +992,10 @@ tcp_slowtmr(void)
void
tcp_fasttmr(void)
{
- struct tcp_pcb *pcb;
+ struct tcp_pcb *pcb = tcp_active_pcbs;
- for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+ while(pcb != NULL) {
+ struct tcp_pcb *next = pcb->next;
/* If there is data which was previously "refused" by upper layer */
if (pcb->refused_data != NULL) {
/* Notify again application with data previously received. */
@@ -827,15 +1004,21 @@ tcp_fasttmr(void)
TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
if (err == ERR_OK) {
pcb->refused_data = NULL;
+ } else if (err == ERR_ABRT) {
+ /* if err == ERR_ABRT, 'pcb' is already deallocated */
+ pcb = NULL;
}
}
- /* send delayed ACKs */
- if (pcb->flags & TF_ACK_DELAY) {
+ /* send delayed ACKs */
+ if (pcb && (pcb->flags & TF_ACK_DELAY)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
tcp_ack_now(pcb);
+ tcp_output(pcb);
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
}
+
+ pcb = next;
}
}
@@ -843,42 +1026,34 @@ tcp_fasttmr(void)
* Deallocates a list of TCP segments (tcp_seg structures).
*
* @param seg tcp_seg list of TCP segments to free
- * @return the number of pbufs that were deallocated
*/
-u8_t
+void
tcp_segs_free(struct tcp_seg *seg)
{
- u8_t count = 0;
- struct tcp_seg *next;
while (seg != NULL) {
- next = seg->next;
- count += tcp_seg_free(seg);
+ struct tcp_seg *next = seg->next;
+ tcp_seg_free(seg);
seg = next;
}
- return count;
}
/**
* Frees a TCP segment (tcp_seg structure).
*
* @param seg single tcp_seg to free
- * @return the number of pbufs that were deallocated
*/
-u8_t
+void
tcp_seg_free(struct tcp_seg *seg)
{
- u8_t count = 0;
-
if (seg != NULL) {
if (seg->p != NULL) {
- count = pbuf_free(seg->p);
+ pbuf_free(seg->p);
#if TCP_DEBUG
seg->p = NULL;
#endif /* TCP_DEBUG */
}
memp_free(MEMP_TCP_SEG, seg);
}
- return count;
}
/**
@@ -892,8 +1067,8 @@ tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
{
pcb->prio = prio;
}
-#if TCP_QUEUE_OOSEQ
+#if TCP_QUEUE_OOSEQ
/**
* Returns a copy of the given TCP segment.
* The pbuf and data are not copied, only the pointers
@@ -906,7 +1081,7 @@ tcp_seg_copy(struct tcp_seg *seg)
{
struct tcp_seg *cseg;
- cseg = memp_malloc(MEMP_TCP_SEG);
+ cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG);
if (cseg == NULL) {
return NULL;
}
@@ -914,7 +1089,7 @@ tcp_seg_copy(struct tcp_seg *seg)
pbuf_ref(cseg->p);
return cseg;
}
-#endif
+#endif /* TCP_QUEUE_OOSEQ */
#if LWIP_CALLBACK_API
/**
@@ -966,7 +1141,7 @@ tcp_kill_prio(u8_t prio)
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",
(void *)inactive, inactivity));
tcp_abort(inactive);
- }
+ }
}
/**
@@ -992,7 +1167,7 @@ tcp_kill_timewait(void)
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n",
(void *)inactive, inactivity));
tcp_abort(inactive);
- }
+ }
}
/**
@@ -1007,19 +1182,19 @@ tcp_alloc(u8_t prio)
struct tcp_pcb *pcb;
u32_t iss;
- pcb = memp_malloc(MEMP_TCP_PCB);
+ pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
if (pcb == NULL) {
/* Try killing oldest connection in TIME-WAIT. */
LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n"));
tcp_kill_timewait();
/* Try to allocate a tcp_pcb again. */
- pcb = memp_malloc(MEMP_TCP_PCB);
+ pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
if (pcb == NULL) {
/* Try killing active connections with lower priority than the new one. */
LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio));
tcp_kill_prio(prio);
/* Try to allocate a tcp_pcb again. */
- pcb = memp_malloc(MEMP_TCP_PCB);
+ pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
if (pcb != NULL) {
/* adjust err stats: memp_malloc failed twice before */
MEMP_STATS_DEC(err, MEMP_TCP_PCB);
@@ -1032,7 +1207,7 @@ tcp_alloc(u8_t prio)
}
if (pcb != NULL) {
memset(pcb, 0, sizeof(struct tcp_pcb));
- pcb->prio = TCP_PRIO_NORMAL;
+ pcb->prio = prio;
pcb->snd_buf = TCP_SND_BUF;
pcb->snd_queuelen = 0;
pcb->rcv_wnd = TCP_WND;
@@ -1113,8 +1288,7 @@ tcp_arg(struct tcp_pcb *pcb, void *arg)
* @param recv callback function to call for this pcb when data is received
*/
void
-tcp_recv(struct tcp_pcb *pcb,
- err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
+tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv)
{
pcb->recv = recv;
}
@@ -1127,8 +1301,7 @@ tcp_recv(struct tcp_pcb *pcb,
* @param sent callback function to call for this pcb when data is successfully sent
*/
void
-tcp_sent(struct tcp_pcb *pcb,
- err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
+tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent)
{
pcb->sent = sent;
}
@@ -1138,14 +1311,13 @@ tcp_sent(struct tcp_pcb *pcb,
* has occured on the connection.
*
* @param pcb tcp_pcb to set the err callback
- * @param errf callback function to call for this pcb when a fatal error
+ * @param err callback function to call for this pcb when a fatal error
* has occured on the connection
*/
void
-tcp_err(struct tcp_pcb *pcb,
- void (* errf)(void *arg, err_t err))
+tcp_err(struct tcp_pcb *pcb, tcp_err_fn err)
{
- pcb->errf = errf;
+ pcb->errf = err;
}
/**
@@ -1157,8 +1329,7 @@ tcp_err(struct tcp_pcb *pcb,
* connection has been connected to another host
*/
void
-tcp_accept(struct tcp_pcb *pcb,
- err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
+tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept)
{
pcb->accept = accept;
}
@@ -1172,11 +1343,12 @@ tcp_accept(struct tcp_pcb *pcb,
*
*/
void
-tcp_poll(struct tcp_pcb *pcb,
- err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
+tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval)
{
#if LWIP_CALLBACK_API
pcb->poll = poll;
+#else /* LWIP_CALLBACK_API */
+ LWIP_UNUSED_ARG(poll);
#endif /* LWIP_CALLBACK_API */
pcb->pollinterval = interval;
}
@@ -1228,21 +1400,24 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
if (pcb->unacked != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n"));
}
-#if TCP_QUEUE_OOSEQ /* LW */
+#if TCP_QUEUE_OOSEQ
if (pcb->ooseq != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
}
+ tcp_segs_free(pcb->ooseq);
+ pcb->ooseq = NULL;
+#endif /* TCP_QUEUE_OOSEQ */
/* Stop the retransmission timer as it will expect data on unacked
queue if it fires */
pcb->rtime = -1;
- tcp_segs_free(pcb->ooseq);
- pcb->ooseq = NULL;
-#endif /* TCP_QUEUE_OOSEQ */
tcp_segs_free(pcb->unsent);
tcp_segs_free(pcb->unacked);
pcb->unacked = pcb->unsent = NULL;
+#if TCP_OVERSIZE
+ pcb->unsent_oversize = 0;
+#endif /* TCP_OVERSIZE */
}
}
@@ -1301,7 +1476,7 @@ tcp_next_iss(void)
* calculating the minimum of TCP_MSS and that netif's mtu (if set).
*/
u16_t
-tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr)
+tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr)
{
u16_t mss_s;
struct netif *outif;
@@ -1311,8 +1486,7 @@ tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr)
mss_s = outif->mtu - IP_HLEN - TCP_HLEN;
/* RFC 1122, chap 4.2.2.6:
* Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
- * We correct for TCP options in tcp_enqueue(), and don't support
- * IP options
+ * We correct for TCP options in tcp_write(), and don't support IP options.
*/
sendmss = LWIP_MIN(sendmss, mss_s);
}
diff --git a/core/lwip/src/core/tcp_in.c b/core/lwip/src/core/tcp_in.c
index 51e87759..90952648 100644
--- a/core/lwip/src/core/tcp_in.c
+++ b/core/lwip/src/core/tcp_in.c
@@ -45,13 +45,12 @@
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
-#include "lwip/tcp.h"
+#include "lwip/tcp_impl.h"
#include "lwip/def.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
-#include "lwip/inet.h"
#include "lwip/inet_chksum.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
@@ -94,6 +93,10 @@ tcp_input(struct pbuf *p, struct netif *inp)
{
struct tcp_pcb *pcb, *prev;
struct tcp_pcb_listen *lpcb;
+#if SO_REUSE
+ struct tcp_pcb *lpcb_prev = NULL;
+ struct tcp_pcb_listen *lpcb_any = NULL;
+#endif /* SO_REUSE */
u8_t hdrlen;
err_t err;
@@ -102,7 +105,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
TCP_STATS_INC(tcp.recv);
snmp_inc_tcpinsegs();
- iphdr = p->payload;
+ iphdr = (struct ip_hdr *)p->payload;
tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
#if TCP_INPUT_DEBUG
@@ -121,8 +124,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
}
/* Don't even process incoming broadcasts/multicasts. */
- if (ip_addr_isbroadcast(&(iphdr->dest), inp) ||
- ip_addr_ismulticast(&(iphdr->dest))) {
+ if (ip_addr_isbroadcast(&current_iphdr_dest, inp) ||
+ ip_addr_ismulticast(&current_iphdr_dest)) {
TCP_STATS_INC(tcp.proterr);
TCP_STATS_INC(tcp.drop);
snmp_inc_tcpinerrs();
@@ -132,11 +135,10 @@ tcp_input(struct pbuf *p, struct netif *inp)
#if CHECKSUM_CHECK_TCP
/* Verify TCP checksum. */
- if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
- (struct ip_addr *)&(iphdr->dest),
+ if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
IP_PROTO_TCP, p->tot_len) != 0) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
- inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest),
+ inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
IP_PROTO_TCP, p->tot_len)));
#if TCP_DEBUG
tcp_debug_print(tcphdr);
@@ -183,8 +185,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
if (pcb->remote_port == tcphdr->src &&
pcb->local_port == tcphdr->dest &&
- ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
- ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
+ ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src) &&
+ ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest)) {
/* Move this PCB to the front of the list so that subsequent
lookups will be faster (we exploit locality in TCP segment
@@ -208,8 +210,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
if (pcb->remote_port == tcphdr->src &&
pcb->local_port == tcphdr->dest &&
- ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
- ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
+ ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src) &&
+ ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest)) {
/* We don't really care enough to move this PCB to the front
of the list since we are not very likely to receive that
many segments for connections in TIME-WAIT. */
@@ -220,31 +222,55 @@ tcp_input(struct pbuf *p, struct netif *inp)
}
}
- /* Finally, if we still did not get a match, we check all PCBs that
- are LISTENing for incoming connections. */
+ /* Finally, if we still did not get a match, we check all PCBs that
+ are LISTENing for incoming connections. */
prev = NULL;
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
- if ((ip_addr_isany(&(lpcb->local_ip)) ||
- ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
- lpcb->local_port == tcphdr->dest) {
- /* Move this PCB to the front of the list so that subsequent
- lookups will be faster (we exploit locality in TCP segment
- arrivals). */
- if (prev != NULL) {
- ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
- /* our successor is the remainder of the listening list */
- lpcb->next = tcp_listen_pcbs.listen_pcbs;
- /* put this listening pcb at the head of the listening list */
- tcp_listen_pcbs.listen_pcbs = lpcb;
+ if (lpcb->local_port == tcphdr->dest) {
+#if SO_REUSE
+ if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest)) {
+ /* found an exact match */
+ break;
+ } else if(ip_addr_isany(&(lpcb->local_ip))) {
+ /* found an ANY-match */
+ lpcb_any = lpcb;
+ lpcb_prev = prev;
}
-
- LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
- tcp_listen_input(lpcb);
- pbuf_free(p);
- return;
+#else /* SO_REUSE */
+ if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest) ||
+ ip_addr_isany(&(lpcb->local_ip))) {
+ /* found a match */
+ break;
+ }
+#endif /* SO_REUSE */
}
prev = (struct tcp_pcb *)lpcb;
}
+#if SO_REUSE
+ /* first try specific local IP */
+ if (lpcb == NULL) {
+ /* only pass to ANY if no specific local IP has been found */
+ lpcb = lpcb_any;
+ prev = lpcb_prev;
+ }
+#endif /* SO_REUSE */
+ if (lpcb != NULL) {
+ /* Move this PCB to the front of the list so that subsequent
+ lookups will be faster (we exploit locality in TCP segment
+ arrivals). */
+ if (prev != NULL) {
+ ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
+ /* our successor is the remainder of the listening list */
+ lpcb->next = tcp_listen_pcbs.listen_pcbs;
+ /* put this listening pcb at the head of the listening list */
+ tcp_listen_pcbs.listen_pcbs = lpcb;
+ }
+
+ LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
+ tcp_listen_input(lpcb);
+ pbuf_free(p);
+ return;
+ }
}
#if TCP_INPUT_DEBUG
@@ -265,7 +291,6 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Set up a tcp_seg structure. */
inseg.next = NULL;
inseg.len = p->tot_len;
- inseg.dataptr = p->payload;
inseg.p = p;
inseg.tcphdr = tcphdr;
@@ -279,8 +304,10 @@ tcp_input(struct pbuf *p, struct netif *inp)
TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
if (err == ERR_OK) {
pcb->refused_data = NULL;
- } else {
- /* drop incoming packets, because pcb is "full" */
+ } else if ((err == ERR_ABRT) || (tcplen > 0)) {
+ /* if err == ERR_ABRT, 'pcb' is already deallocated */
+ /* Drop incoming packets because pcb is "full" (only if the incoming
+ segment contains data). */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
TCP_STATS_INC(tcp.drop);
snmp_inc_tcpinerrs();
@@ -313,15 +340,29 @@ tcp_input(struct pbuf *p, struct netif *inp)
now. */
if (pcb->acked > 0) {
TCP_EVENT_SENT(pcb, pcb->acked, err);
+ if (err == ERR_ABRT) {
+ goto aborted;
+ }
}
-
+
if (recv_data != NULL) {
- if(flags & TCP_PSH) {
+ LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
+ if (pcb->flags & TF_RXCLOSED) {
+ /* received data although already closed -> abort (send RST) to
+ notify the remote host that not all data has been processed */
+ pbuf_free(recv_data);
+ tcp_abort(pcb);
+ goto aborted;
+ }
+ if (flags & TCP_PSH) {
recv_data->flags |= PBUF_FLAG_PUSH;
}
/* Notify application that data has been received. */
TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
+ if (err == ERR_ABRT) {
+ goto aborted;
+ }
/* If the upper layer can't receive this data, store it */
if (err != ERR_OK) {
@@ -333,7 +374,15 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* If a FIN segment was received, we call the callback
function with a NULL buffer to indicate EOF. */
if (recv_flags & TF_GOT_FIN) {
- TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
+ /* correct rcv_wnd as the application won't call tcp_recved()
+ for the FIN's seqno */
+ if (pcb->rcv_wnd != TCP_WND) {
+ pcb->rcv_wnd++;
+ }
+ TCP_EVENT_CLOSED(pcb, err);
+ if (err == ERR_ABRT) {
+ goto aborted;
+ }
}
tcp_input_pcb = NULL;
@@ -346,8 +395,11 @@ tcp_input(struct pbuf *p, struct netif *inp)
#endif /* TCP_INPUT_DEBUG */
}
}
+ /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()).
+ Below this line, 'pcb' may not be dereferenced! */
+aborted:
tcp_input_pcb = NULL;
-
+ recv_data = NULL;
/* give up our reference to inseg.p */
if (inseg.p != NULL)
@@ -364,7 +416,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
TCP_STATS_INC(tcp.proterr);
TCP_STATS_INC(tcp.drop);
tcp_rst(ackno, seqno + tcplen,
- &(iphdr->dest), &(iphdr->src),
+ ip_current_dest_addr(), ip_current_src_addr(),
tcphdr->dest, tcphdr->src);
}
pbuf_free(p);
@@ -399,7 +451,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
RST. */
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
tcp_rst(ackno + 1, seqno + tcplen,
- &(iphdr->dest), &(iphdr->src),
+ ip_current_dest_addr(), ip_current_src_addr(),
tcphdr->dest, tcphdr->src);
} else if (flags & TCP_SYN) {
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
@@ -422,9 +474,9 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
pcb->accepts_pending++;
#endif /* TCP_LISTEN_BACKLOG */
/* Set up the new PCB. */
- ip_addr_set(&(npcb->local_ip), &(iphdr->dest));
+ ip_addr_copy(npcb->local_ip, current_iphdr_dest);
npcb->local_port = pcb->local_port;
- ip_addr_set(&(npcb->remote_ip), &(iphdr->src));
+ ip_addr_copy(npcb->remote_ip, current_iphdr_src);
npcb->remote_port = tcphdr->src;
npcb->state = SYN_RCVD;
npcb->rcv_nxt = seqno + 1;
@@ -437,7 +489,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
npcb->accept = pcb->accept;
#endif /* LWIP_CALLBACK_API */
/* inherit socket options */
- npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
+ npcb->so_options = pcb->so_options & SOF_INHERITED;
/* Register the new PCB so that we can begin receiving segments
for it. */
TCP_REG(&tcp_active_pcbs, npcb);
@@ -451,12 +503,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
snmp_inc_tcppassiveopens();
/* Send a SYN|ACK together with the MSS option. */
- rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS
-#if LWIP_TCP_TIMESTAMPS
- /* and maybe include the TIMESTAMP option */
- | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0)
-#endif
- );
+ rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
if (rc != ERR_OK) {
tcp_abandon(npcb, 0);
return rc;
@@ -492,7 +539,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
should be sent in reply */
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
/* If the SYN is in the window it is an error, send a reset */
- tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
+ tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
tcphdr->dest, tcphdr->src);
return ERR_OK;
}
@@ -565,8 +612,10 @@ tcp_process(struct tcp_pcb *pcb)
return ERR_OK;
}
- /* Update the PCB (in)activity timer. */
- pcb->tmr = tcp_ticks;
+ if ((pcb->flags & TF_RXCLOSED) == 0) {
+ /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
+ pcb->tmr = tcp_ticks;
+ }
pcb->keep_cnt_sent = 0;
tcp_parseopt(pcb);
@@ -616,12 +665,15 @@ tcp_process(struct tcp_pcb *pcb)
/* Call the user specified function to call when sucessfully
* connected. */
TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
+ if (err == ERR_ABRT) {
+ return ERR_ABRT;
+ }
tcp_ack_now(pcb);
}
/* received ACK? possibly a half-open connection */
else if (flags & TCP_ACK) {
/* send a RST to bring the other side in a non-synchronized state. */
- tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
+ tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
tcphdr->dest, tcphdr->src);
}
break;
@@ -640,7 +692,10 @@ tcp_process(struct tcp_pcb *pcb)
if (err != ERR_OK) {
/* If the accept function returns with an error, we abort
* the connection. */
- tcp_abort(pcb);
+ /* Already aborted? */
+ if (err != ERR_ABRT) {
+ tcp_abort(pcb);
+ }
return ERR_ABRT;
}
old_cwnd = pcb->cwnd;
@@ -659,11 +714,9 @@ tcp_process(struct tcp_pcb *pcb)
tcp_ack_now(pcb);
pcb->state = CLOSE_WAIT;
}
- }
- /* incorrect ACK number */
- else {
- /* send RST */
- tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
+ } else {
+ /* incorrect ACK number, send RST */
+ tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
tcphdr->dest, tcphdr->src);
}
} else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
@@ -758,7 +811,7 @@ tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
(next->tcphdr->seqno + next->len))) {
/* cseg with FIN already processed */
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
- TCPH_FLAGS_SET(cseg->tcphdr, TCPH_FLAGS(cseg->tcphdr) | TCP_FIN);
+ TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN);
}
old_seg = next;
next = next->next;
@@ -773,7 +826,7 @@ tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
}
cseg->next = next;
}
-#endif
+#endif /* TCP_QUEUE_OOSEQ */
/**
* Called by tcp_process. Checks if the given segment is an ACK for outstanding
@@ -793,7 +846,7 @@ tcp_receive(struct tcp_pcb *pcb)
struct tcp_seg *next;
#if TCP_QUEUE_OOSEQ
struct tcp_seg *prev, *cseg;
-#endif
+#endif /* TCP_QUEUE_OOSEQ */
struct pbuf *p;
s32_t off;
s16_t m;
@@ -1113,9 +1166,6 @@ tcp_receive(struct tcp_pcb *pcb)
LWIP_ASSERT("pbuf_header failed", 0);
}
}
- /* KJM following line changed to use p->payload rather than inseg->p->payload
- to fix bug #9076 */
- inseg.dataptr = p->payload;
inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
}
@@ -1143,7 +1193,7 @@ tcp_receive(struct tcp_pcb *pcb)
if (tcplen > pcb->rcv_wnd) {
LWIP_DEBUGF(TCP_INPUT_DEBUG,
("tcp_receive: other end overran receive window"
- "seqno %"U32_F" len %"U32_F" right edge %"U32_F"\n",
+ "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
/* Must remove the FIN from the header as we're trimming
@@ -1161,60 +1211,53 @@ tcp_receive(struct tcp_pcb *pcb)
(seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
}
#if TCP_QUEUE_OOSEQ
+ /* Received in-sequence data, adjust ooseq data if:
+ - FIN has been received or
+ - inseq overlaps with ooseq */
if (pcb->ooseq != NULL) {
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG,
("tcp_receive: received in-order FIN, binning ooseq queue\n"));
/* Received in-order FIN means anything that was received
* out of order must now have been received in-order, so
- * bin the ooseq queue
- * rcv_nxt
- * . |--ooseq--|
- * .==seg============|FIN
- */
+ * bin the ooseq queue */
while (pcb->ooseq != NULL) {
struct tcp_seg *old_ooseq = pcb->ooseq;
pcb->ooseq = pcb->ooseq->next;
tcp_seg_free(old_ooseq);
- }
- }
+ }
+ }
else {
- struct tcp_seg* next = pcb->ooseq;
- struct tcp_seg *old_seg;
- /* rcv_nxt
- * . |--ooseq--|
- * .==seg============|
- */
+ next = pcb->ooseq;
+ /* Remove all segments on ooseq that are covered by inseg already.
+ * FIN is copied from ooseq to inseg if present. */
while (next &&
TCP_SEQ_GEQ(seqno + tcplen,
next->tcphdr->seqno + next->len)) {
- /* inseg doesn't have FIN (already processed) */
+ /* inseg cannot have FIN here (already processed above) */
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
(TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
- TCPH_FLAGS_SET(inseg.tcphdr,
- TCPH_FLAGS(inseg.tcphdr) | TCP_FIN);
+ TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
tcplen = TCP_TCPLEN(&inseg);
}
- old_seg = next;
+ prev = next;
next = next->next;
- tcp_seg_free(old_seg);
+ tcp_seg_free(prev);
}
- /* rcv_nxt
- * . |--ooseq--|
- * .==seg============|
- */
+ /* Now trim right side of inseg if it overlaps with the first
+ * segment on ooseq */
if (next &&
TCP_SEQ_GT(seqno + tcplen,
next->tcphdr->seqno)) {
- /* FIN in inseg already handled by dropping whole ooseq queue */
- inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
+ /* inseg cannot have FIN here (already processed above) */
+ inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
inseg.len -= 1;
}
pbuf_realloc(inseg.p, inseg.len);
tcplen = TCP_TCPLEN(&inseg);
LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
- (seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
+ (seqno + tcplen) == next->tcphdr->seqno);
}
pcb->ooseq = next;
}
@@ -1252,7 +1295,7 @@ tcp_receive(struct tcp_pcb *pcb)
#if TCP_QUEUE_OOSEQ
/* We now check if we have segments on the ->ooseq queue that
- is now in sequence. */
+ are now in sequence. */
while (pcb->ooseq != NULL &&
pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
@@ -1392,6 +1435,24 @@ tcp_receive(struct tcp_pcb *pcb)
next->len = (u16_t)(seqno - next->tcphdr->seqno);
pbuf_realloc(next->p, next->len);
}
+ /* check if the remote side overruns our receive window */
+ if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) {
+ LWIP_DEBUGF(TCP_INPUT_DEBUG,
+ ("tcp_receive: other end overran receive window"
+ "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
+ seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
+ if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
+ /* Must remove the FIN from the header as we're trimming
+ * that byte of sequence-space from the packet */
+ TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN);
+ }
+ /* Adjust length of segment to fit in the window. */
+ next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno;
+ pbuf_realloc(next->next->p, next->next->len);
+ tcplen = TCP_TCPLEN(next->next);
+ LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
+ (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
+ }
}
break;
}
diff --git a/core/lwip/src/core/tcp_out.c b/core/lwip/src/core/tcp_out.c
index ddada420..86e09195 100644
--- a/core/lwip/src/core/tcp_out.c
+++ b/core/lwip/src/core/tcp_out.c
@@ -42,382 +42,643 @@
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
-#include "lwip/tcp.h"
+#include "lwip/tcp_impl.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
-#include "lwip/inet.h"
#include "lwip/inet_chksum.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include <string.h>
+/* Define some copy-macros for checksum-on-copy so that the code looks
+ nicer by preventing too many ifdef's. */
+#if TCP_CHECKSUM_ON_COPY
+#define TCP_DATA_COPY(dst, src, len, seg) do { \
+ tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \
+ len, &seg->chksum, &seg->chksum_swapped); \
+ seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0)
+#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \
+ tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped);
+#else /* TCP_CHECKSUM_ON_COPY*/
+#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len)
+#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len)
+#endif /* TCP_CHECKSUM_ON_COPY*/
+
+/** Define this to 1 for an extra check that the output checksum is valid
+ * (usefule when the checksum is generated by the application, not the stack) */
+#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK
+#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0
+#endif
+
/* Forward declarations.*/
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
-static struct tcp_hdr *
-tcp_output_set_header(struct tcp_pcb *pcb, struct pbuf *p, int optlen,
+/** Allocate a pbuf and create a tcphdr at p->payload, used for output
+ * functions other than the default tcp_output -> tcp_output_segment
+ * (e.g. tcp_send_empty_ack, etc.)
+ *
+ * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr)
+ * @param optlen length of header-options
+ * @param datalen length of tcp data to reserve in pbuf
+ * @param seqno_be seqno in network byte order (big-endian)
+ * @return pbuf with p->payload being the tcp_hdr
+ */
+static struct pbuf *
+tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen,
u32_t seqno_be /* already in network byte order */)
{
- struct tcp_hdr *tcphdr = p->payload;
- tcphdr->src = htons(pcb->local_port);
- tcphdr->dest = htons(pcb->remote_port);
- tcphdr->seqno = seqno_be;
- tcphdr->ackno = htonl(pcb->rcv_nxt);
- TCPH_FLAGS_SET(tcphdr, TCP_ACK);
- tcphdr->wnd = htons(pcb->rcv_ann_wnd);
- tcphdr->urgp = 0;
- TCPH_HDRLEN_SET(tcphdr, (5 + optlen / 4));
- tcphdr->chksum = 0;
-
- /* If we're sending a packet, update the announced right window edge */
- pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
-
- return tcphdr;
+ struct tcp_hdr *tcphdr;
+ struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM);
+ if (p != NULL) {
+ LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
+ (p->len >= TCP_HLEN + optlen));
+ tcphdr = (struct tcp_hdr *)p->payload;
+ tcphdr->src = htons(pcb->local_port);
+ tcphdr->dest = htons(pcb->remote_port);
+ tcphdr->seqno = seqno_be;
+ tcphdr->ackno = htonl(pcb->rcv_nxt);
+ TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK);
+ tcphdr->wnd = htons(pcb->rcv_ann_wnd);
+ tcphdr->chksum = 0;
+ tcphdr->urgp = 0;
+
+ /* If we're sending a packet, update the announced right window edge */
+ pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
+ }
+ return p;
}
/**
- * Called by tcp_close() to send a segment including flags but not data.
+ * Called by tcp_close() to send a segment including FIN flag but not data.
*
* @param pcb the tcp_pcb over which to send a segment
- * @param flags the flags to set in the segment header
* @return ERR_OK if sent, another err_t otherwise
*/
err_t
-tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
+tcp_send_fin(struct tcp_pcb *pcb)
{
+ /* first, try to add the fin to the last unsent segment */
+ if (pcb->unsent != NULL) {
+ struct tcp_seg *last_unsent;
+ for (last_unsent = pcb->unsent; last_unsent->next != NULL;
+ last_unsent = last_unsent->next);
+
+ if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) {
+ /* no SYN/FIN/RST flag in the header, we can add the FIN flag */
+ TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN);
+ return ERR_OK;
+ }
+ }
/* no data, no length, flags, copy=1, no optdata */
- return tcp_enqueue(pcb, NULL, 0, flags, TCP_WRITE_FLAG_COPY, 0);
+ return tcp_enqueue_flags(pcb, TCP_FIN);
}
/**
- * Write data for sending (but does not send it immediately).
+ * Create a TCP segment with prefilled header.
*
- * It waits in the expectation of more data being sent soon (as
- * it can send them more efficiently by combining them together).
- * To prompt the system to send data now, call tcp_output() after
- * calling tcp_write().
- *
- * @param pcb Protocol control block of the TCP connection to enqueue data for.
- * @param data pointer to the data to send
- * @param len length (in bytes) of the data to send
- * @param apiflags combination of following flags :
- * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
- * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
- * @return ERR_OK if enqueued, another err_t on error
- *
- * @see tcp_write()
+ * Called by tcp_write and tcp_enqueue_flags.
+ *
+ * @param pcb Protocol control block for the TCP connection.
+ * @param p pbuf that is used to hold the TCP header.
+ * @param flags TCP flags for header.
+ * @param seqno TCP sequence number of this packet
+ * @param optflags options to include in TCP header
+ * @return a new tcp_seg pointing to p, or NULL.
+ * The TCP header is filled in except ackno and wnd.
+ * p is freed on failure.
*/
-err_t
-tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
+static struct tcp_seg *
+tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags)
{
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", (void *)pcb,
- data, len, (u16_t)apiflags));
- /* connection is in valid state for data transmission? */
- if (pcb->state == ESTABLISHED ||
- pcb->state == CLOSE_WAIT ||
- pcb->state == SYN_SENT ||
- pcb->state == SYN_RCVD) {
- if (len > 0) {
-#if LWIP_TCP_TIMESTAMPS
- return tcp_enqueue(pcb, (void *)data, len, 0, apiflags,
- pcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0);
-#else
- return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 0);
-#endif
- }
- return ERR_OK;
- } else {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
- return ERR_CONN;
+ struct tcp_seg *seg;
+ u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
+
+ if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no memory.\n"));
+ pbuf_free(p);
+ return NULL;
}
-}
+ seg->flags = optflags;
+ seg->next = NULL;
+ seg->p = p;
+ seg->len = p->tot_len - optlen;
+#if TCP_OVERSIZE_DBGCHECK
+ seg->oversize_left = 0;
+#endif /* TCP_OVERSIZE_DBGCHECK */
+#if TCP_CHECKSUM_ON_COPY
+ seg->chksum = 0;
+ seg->chksum_swapped = 0;
+ /* check optflags */
+ LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED",
+ (optflags & TF_SEG_DATA_CHECKSUMMED) == 0);
+#endif /* TCP_CHECKSUM_ON_COPY */
+
+ /* build TCP header */
+ if (pbuf_header(p, TCP_HLEN)) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no room for TCP header in pbuf.\n"));
+ TCP_STATS_INC(tcp.err);
+ tcp_seg_free(seg);
+ return NULL;
+ }
+ seg->tcphdr = (struct tcp_hdr *)seg->p->payload;
+ seg->tcphdr->src = htons(pcb->local_port);
+ seg->tcphdr->dest = htons(pcb->remote_port);
+ seg->tcphdr->seqno = htonl(seqno);
+ /* ackno is set in tcp_output */
+ TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags);
+ /* wnd and chksum are set in tcp_output */
+ seg->tcphdr->urgp = 0;
+ return seg;
+}
/**
- * Enqueue data and/or TCP options for transmission
+ * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end.
*
- * Called by tcp_connect(), tcp_listen_input(), tcp_send_ctrl() and tcp_write().
+ * This function is like pbuf_alloc(layer, length, PBUF_RAM) except
+ * there may be extra bytes available at the end.
*
- * @param pcb Protocol control block for the TCP connection to enqueue data for.
- * @param arg Pointer to the data to be enqueued for sending.
- * @param len Data length in bytes
- * @param flags tcp header flags to set in the outgoing segment
- * @param apiflags combination of following flags :
- * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
- * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
- * @param optflags options to include in segment later on (see definition of struct tcp_seg)
+ * @param layer flag to define header size.
+ * @param length size of the pbuf's payload.
+ * @param max_length maximum usable size of payload+oversize.
+ * @param oversize pointer to a u16_t that will receive the number of usable tail bytes.
+ * @param pcb The TCP connection that willo enqueue the pbuf.
+ * @param apiflags API flags given to tcp_write.
+ * @param first_seg true when this pbuf will be used in the first enqueued segment.
+ * @param
*/
-err_t
-tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
- u8_t flags, u8_t apiflags, u8_t optflags)
+#if TCP_OVERSIZE
+static struct pbuf *
+tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length,
+ u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags,
+ u8_t first_seg)
{
struct pbuf *p;
- struct tcp_seg *seg, *useg, *queue;
- u32_t seqno;
- u16_t left, seglen;
- void *ptr;
- u16_t queuelen;
- u8_t optlen;
+ u16_t alloc = length;
+
+#if LWIP_NETIF_TX_SINGLE_PBUF
+ LWIP_UNUSED_ARG(max_length);
+ LWIP_UNUSED_ARG(pcb);
+ LWIP_UNUSED_ARG(apiflags);
+ LWIP_UNUSED_ARG(first_seg);
+ /* always create MSS-sized pbufs */
+ alloc = TCP_MSS;
+#else /* LWIP_NETIF_TX_SINGLE_PBUF */
+ if (length < max_length) {
+ /* Should we allocate an oversized pbuf, or just the minimum
+ * length required? If tcp_write is going to be called again
+ * before this segment is transmitted, we want the oversized
+ * buffer. If the segment will be transmitted immediately, we can
+ * save memory by allocating only length. We use a simple
+ * heuristic based on the following information:
+ *
+ * Did the user set TCP_WRITE_FLAG_MORE?
+ *
+ * Will the Nagle algorithm defer transmission of this segment?
+ */
+ if ((apiflags & TCP_WRITE_FLAG_MORE) ||
+ (!(pcb->flags & TF_NODELAY) &&
+ (!first_seg ||
+ pcb->unsent != NULL ||
+ pcb->unacked != NULL))) {
+ alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(length + TCP_OVERSIZE));
+ }
+ }
+#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
+ p = pbuf_alloc(layer, alloc, PBUF_RAM);
+ if (p == NULL) {
+ return NULL;
+ }
+ LWIP_ASSERT("need unchained pbuf", p->next == NULL);
+ *oversize = p->len - length;
+ /* trim p->len to the currently used size */
+ p->len = p->tot_len = length;
+ return p;
+}
+#else /* TCP_OVERSIZE */
+#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM)
+#endif /* TCP_OVERSIZE */
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
- ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", apiflags=%"U16_F")\n",
- (void *)pcb, arg, len, (u16_t)flags, (u16_t)apiflags));
- LWIP_ERROR("tcp_enqueue: packet needs payload, options, or SYN/FIN (programmer violates API)",
- ((len != 0) || (optflags != 0) || ((flags & (TCP_SYN | TCP_FIN)) != 0)),
- return ERR_ARG;);
- LWIP_ERROR("tcp_enqueue: len != 0 || arg == NULL (programmer violates API)",
- ((len != 0) || (arg == NULL)), return ERR_ARG;);
+#if TCP_CHECKSUM_ON_COPY
+/** Add a checksum of newly added data to the segment */
+static void
+tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum,
+ u8_t *seg_chksum_swapped)
+{
+ u32_t helper;
+ /* add chksum to old chksum and fold to u16_t */
+ helper = chksum + *seg_chksum;
+ chksum = FOLD_U32T(helper);
+ if ((len & 1) != 0) {
+ *seg_chksum_swapped = 1 - *seg_chksum_swapped;
+ chksum = SWAP_BYTES_IN_WORD(chksum);
+ }
+ *seg_chksum = chksum;
+}
+#endif /* TCP_CHECKSUM_ON_COPY */
+
+/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen).
+ *
+ * @param pcb the tcp pcb to check for
+ * @param len length of data to send (checked agains snd_buf)
+ * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise
+ */
+static err_t
+tcp_write_checks(struct tcp_pcb *pcb, u16_t len)
+{
+ /* connection is in invalid state for data transmission? */
+ if ((pcb->state != ESTABLISHED) &&
+ (pcb->state != CLOSE_WAIT) &&
+ (pcb->state != SYN_SENT) &&
+ (pcb->state != SYN_RCVD)) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
+ return ERR_CONN;
+ } else if (len == 0) {
+ return ERR_OK;
+ }
/* fail on too much data */
if (len > pcb->snd_buf) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
- ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n",
+ len, pcb->snd_buf));
pcb->flags |= TF_NAGLEMEMERR;
return ERR_MEM;
}
- left = len;
- ptr = arg;
- optlen = LWIP_TCP_OPT_LENGTH(optflags);
-
- /* seqno will be the sequence number of the first segment enqueued
- * by the call to this function. */
- seqno = pcb->snd_lbb;
-
- LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
+ LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
/* If total number of pbufs on the unsent/unacked queues exceeds the
* configured maximum, return an error */
- queuelen = pcb->snd_queuelen;
/* check for configured max queuelen and possible overflow */
- if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
- ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
+ if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n",
+ pcb->snd_queuelen, TCP_SND_QUEUELEN));
TCP_STATS_INC(tcp.memerr);
pcb->flags |= TF_NAGLEMEMERR;
return ERR_MEM;
}
- if (queuelen != 0) {
- LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
+ if (pcb->snd_queuelen != 0) {
+ LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty",
pcb->unacked != NULL || pcb->unsent != NULL);
} else {
- LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
+ LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty",
pcb->unacked == NULL && pcb->unsent == NULL);
}
+ return ERR_OK;
+}
- /* First, break up the data into segments and tuck them together in
- * the local "queue" variable. */
- useg = queue = seg = NULL;
- seglen = 0;
- while (queue == NULL || left > 0) {
- /* The segment length (including options) should be at most the MSS */
- seglen = left > (pcb->mss - optlen) ? (pcb->mss - optlen) : left;
-
- /* Allocate memory for tcp_seg, and fill in fields. */
- seg = memp_malloc(MEMP_TCP_SEG);
- if (seg == NULL) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
- ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
- goto memerr;
- }
- seg->next = NULL;
- seg->p = NULL;
+/**
+ * Write data for sending (but does not send it immediately).
+ *
+ * It waits in the expectation of more data being sent soon (as
+ * it can send them more efficiently by combining them together).
+ * To prompt the system to send data now, call tcp_output() after
+ * calling tcp_write().
+ *
+ * @param pcb Protocol control block for the TCP connection to enqueue data for.
+ * @param arg Pointer to the data to be enqueued for sending.
+ * @param len Data length in bytes
+ * @param apiflags combination of following flags :
+ * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
+ * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
+ * @return ERR_OK if enqueued, another err_t on error
+ */
+err_t
+tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
+{
+ struct pbuf *concat_p = NULL;
+ struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL;
+ u16_t pos = 0; /* position in 'arg' data */
+ u16_t queuelen;
+ u8_t optlen = 0;
+ u8_t optflags = 0;
+#if TCP_OVERSIZE
+ u16_t oversize = 0;
+ u16_t oversize_used = 0;
+#endif /* TCP_OVERSIZE */
+#if TCP_CHECKSUM_ON_COPY
+ u16_t concat_chksum = 0;
+ u8_t concat_chksum_swapped = 0;
+ u16_t concat_chksummed = 0;
+#endif /* TCP_CHECKSUM_ON_COPY */
+ err_t err;
+
+#if LWIP_NETIF_TX_SINGLE_PBUF
+ /* Always copy to try to create single pbufs for TX */
+ apiflags |= TCP_WRITE_FLAG_COPY;
+#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
+
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n",
+ (void *)pcb, arg, len, (u16_t)apiflags));
+ LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)",
+ arg != NULL, return ERR_ARG;);
+
+ err = tcp_write_checks(pcb, len);
+ if (err != ERR_OK) {
+ return err;
+ }
+ queuelen = pcb->snd_queuelen;
- /* first segment of to-be-queued data? */
- if (queue == NULL) {
- queue = seg;
+#if LWIP_TCP_TIMESTAMPS
+ if ((pcb->flags & TF_TIMESTAMP)) {
+ optflags = TF_SEG_OPTS_TS;
+ optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
+ }
+#endif /* LWIP_TCP_TIMESTAMPS */
+
+
+ /*
+ * TCP segmentation is done in three phases with increasing complexity:
+ *
+ * 1. Copy data directly into an oversized pbuf.
+ * 2. Chain a new pbuf to the end of pcb->unsent.
+ * 3. Create new segments.
+ *
+ * We may run out of memory at any point. In that case we must
+ * return ERR_MEM and not change anything in pcb. Therefore, all
+ * changes are recorded in local variables and committed at the end
+ * of the function. Some pcb fields are maintained in local copies:
+ *
+ * queuelen = pcb->snd_queuelen
+ * oversize = pcb->unsent_oversize
+ *
+ * These variables are set consistently by the phases:
+ *
+ * seg points to the last segment tampered with.
+ *
+ * pos records progress as data is segmented.
+ */
+
+ /* Find the tail of the unsent queue. */
+ if (pcb->unsent != NULL) {
+ u16_t space;
+ u16_t unsent_optlen;
+
+ /* @todo: this could be sped up by keeping last_unsent in the pcb */
+ for (last_unsent = pcb->unsent; last_unsent->next != NULL;
+ last_unsent = last_unsent->next);
+
+ /* Usable space at the end of the last unsent segment */
+ unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags);
+ space = pcb->mss - (last_unsent->len + unsent_optlen);
+
+ /*
+ * Phase 1: Copy data directly into an oversized pbuf.
+ *
+ * The number of bytes copied is recorded in the oversize_used
+ * variable. The actual copying is done at the bottom of the
+ * function.
+ */
+#if TCP_OVERSIZE
+#if TCP_OVERSIZE_DBGCHECK
+ /* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */
+ LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)",
+ pcb->unsent_oversize == last_unsent->oversize_left);
+#endif /* TCP_OVERSIZE_DBGCHECK */
+ oversize = pcb->unsent_oversize;
+ if (oversize > 0) {
+ LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space);
+ seg = last_unsent;
+ oversize_used = oversize < len ? oversize : len;
+ pos += oversize_used;
+ oversize -= oversize_used;
+ space -= oversize_used;
}
- /* subsequent segments of to-be-queued data */
- else {
- /* Attach the segment to the end of the queued segments */
- LWIP_ASSERT("useg != NULL", useg != NULL);
- useg->next = seg;
+ /* now we are either finished or oversize is zero */
+ LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len));
+#endif /* TCP_OVERSIZE */
+
+ /*
+ * Phase 2: Chain a new pbuf to the end of pcb->unsent.
+ *
+ * We don't extend segments containing SYN/FIN flags or options
+ * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at
+ * the end.
+ */
+ if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
+ u16_t seglen = space < len - pos ? space : len - pos;
+ seg = last_unsent;
+
+ /* Create a pbuf with a copy or reference to seglen bytes. We
+ * can use PBUF_RAW here since the data appears in the middle of
+ * a segment. A header will never be prepended. */
+ if (apiflags & TCP_WRITE_FLAG_COPY) {
+ /* Data is copied */
+ if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
+ ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n",
+ seglen));
+ goto memerr;
+ }
+#if TCP_OVERSIZE_DBGCHECK
+ last_unsent->oversize_left = oversize;
+#endif /* TCP_OVERSIZE_DBGCHECK */
+ TCP_DATA_COPY2(concat_p->payload, (u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
+#if TCP_CHECKSUM_ON_COPY
+ concat_chksummed += seglen;
+#endif /* TCP_CHECKSUM_ON_COPY */
+ } else {
+ /* Data is not copied */
+ if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
+ ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
+ goto memerr;
+ }
+#if TCP_CHECKSUM_ON_COPY
+ /* calculate the checksum of nocopy-data */
+ tcp_seg_add_chksum(~inet_chksum((u8_t*)arg + pos, seglen), seglen,
+ &concat_chksum, &concat_chksum_swapped);
+ concat_chksummed += seglen;
+#endif /* TCP_CHECKSUM_ON_COPY */
+ /* reference the non-volatile payload data */
+ concat_p->payload = (u8_t*)arg + pos;
+ }
+
+ pos += seglen;
+ queuelen += pbuf_clen(concat_p);
}
- /* remember last segment of to-be-queued data for next iteration */
- useg = seg;
+ } else {
+#if TCP_OVERSIZE
+ LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)",
+ pcb->unsent_oversize == 0);
+#endif /* TCP_OVERSIZE */
+ }
+
+ /*
+ * Phase 3: Create new segments.
+ *
+ * The new segments are chained together in the local 'queue'
+ * variable, ready to be appended to pcb->unsent.
+ */
+ while (pos < len) {
+ struct pbuf *p;
+ u16_t left = len - pos;
+ u16_t max_len = pcb->mss - optlen;
+ u16_t seglen = left > max_len ? max_len : left;
+#if TCP_CHECKSUM_ON_COPY
+ u16_t chksum = 0;
+ u8_t chksum_swapped = 0;
+#endif /* TCP_CHECKSUM_ON_COPY */
- /* If copy is set, memory should be allocated
- * and data copied into pbuf, otherwise data comes from
- * ROM or other static memory, and need not be copied. */
if (apiflags & TCP_WRITE_FLAG_COPY) {
- if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
- ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
+ /* If copy is set, memory should be allocated and data copied
+ * into pbuf */
+ if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, pcb->mss, &oversize, pcb, apiflags, queue == NULL)) == NULL) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
goto memerr;
}
- LWIP_ASSERT("check that first pbuf can hold the complete seglen",
- (seg->p->len >= seglen + optlen));
- queuelen += pbuf_clen(seg->p);
- if (arg != NULL) {
- MEMCPY((char *)seg->p->payload + optlen, ptr, seglen);
- }
- seg->dataptr = seg->p->payload;
- }
- /* do not copy data */
- else {
- /* First, allocate a pbuf for the headers. */
- if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
- ("tcp_enqueue: could not allocate memory for header pbuf\n"));
+ LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen",
+ (p->len >= seglen));
+ TCP_DATA_COPY2((char *)p->payload + optlen, (u8_t*)arg + pos, seglen, &chksum, &chksum_swapped);
+ } else {
+ /* Copy is not set: First allocate a pbuf for holding the data.
+ * Since the referenced data is available at least until it is
+ * sent out on the link (as it has to be ACKed by the remote
+ * party) we can safely use PBUF_ROM instead of PBUF_REF here.
+ */
+ struct pbuf *p2;
+#if TCP_OVERSIZE
+ LWIP_ASSERT("oversize == 0", oversize == 0);
+#endif /* TCP_OVERSIZE */
+ if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
goto memerr;
}
- queuelen += pbuf_clen(seg->p);
-
- /* Second, allocate a pbuf for holding the data.
- * since the referenced data is available at least until it is sent out on the
- * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
- * instead of PBUF_REF here.
- */
- if (left > 0) {
- if ((p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
- /* If allocation fails, we have to deallocate the header pbuf as well. */
- pbuf_free(seg->p);
- seg->p = NULL;
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
- ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
- goto memerr;
- }
- ++queuelen;
- /* reference the non-volatile payload data */
- p->payload = ptr;
- seg->dataptr = ptr;
-
- /* Concatenate the headers and data pbufs together. */
- pbuf_cat(seg->p/*header*/, p/*data*/);
- p = NULL;
+#if TCP_CHECKSUM_ON_COPY
+ /* calculate the checksum of nocopy-data */
+ chksum = ~inet_chksum((u8_t*)arg + pos, seglen);
+#endif /* TCP_CHECKSUM_ON_COPY */
+ /* reference the non-volatile payload data */
+ p2->payload = (u8_t*)arg + pos;
+
+ /* Second, allocate a pbuf for the headers. */
+ if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
+ /* If allocation fails, we have to deallocate the data pbuf as
+ * well. */
+ pbuf_free(p2);
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for header pbuf\n"));
+ goto memerr;
}
+ /* Concatenate the headers and data pbufs together. */
+ pbuf_cat(p/*header*/, p2/*data*/);
}
+ queuelen += pbuf_clen(p);
+
/* Now that there are more segments queued, we check again if the
- length of the queue exceeds the configured maximum or overflows. */
+ * length of the queue exceeds the configured maximum or
+ * overflows. */
if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
- ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
+ pbuf_free(p);
goto memerr;
}
- seg->len = seglen;
-
- /* build TCP header */
- if (pbuf_header(seg->p, TCP_HLEN)) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
- TCP_STATS_INC(tcp.err);
+ if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) {
goto memerr;
}
- seg->tcphdr = seg->p->payload;
- seg->tcphdr->src = htons(pcb->local_port);
- seg->tcphdr->dest = htons(pcb->remote_port);
- seg->tcphdr->seqno = htonl(seqno);
- seg->tcphdr->urgp = 0;
- TCPH_FLAGS_SET(seg->tcphdr, flags);
- /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
-
- seg->flags = optflags;
-
- /* Set the length of the header */
- TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
+#if TCP_OVERSIZE_DBGCHECK
+ seg->oversize_left = oversize;
+#endif /* TCP_OVERSIZE_DBGCHECK */
+#if TCP_CHECKSUM_ON_COPY
+ seg->chksum = chksum;
+ seg->chksum_swapped = chksum_swapped;
+ seg->flags |= TF_SEG_DATA_CHECKSUMMED;
+#endif /* TCP_CHECKSUM_ON_COPY */
+
+ /* first segment of to-be-queued data? */
+ if (queue == NULL) {
+ queue = seg;
+ } else {
+ /* Attach the segment to the end of the queued segments */
+ LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL);
+ prev_seg->next = seg;
+ }
+ /* remember last segment of to-be-queued data for next iteration */
+ prev_seg = seg;
+
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n",
ntohl(seg->tcphdr->seqno),
- ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
- (u16_t)flags));
+ ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
- left -= seglen;
- seqno += seglen;
- ptr = (void *)((u8_t *)ptr + seglen);
+ pos += seglen;
}
- /* Now that the data to be enqueued has been broken up into TCP
- segments in the queue variable, we add them to the end of the
- pcb->unsent queue. */
- if (pcb->unsent == NULL) {
- useg = NULL;
- }
- else {
- for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
- }
- /* { useg is last segment on the unsent queue, NULL if list is empty } */
-
- /* If there is room in the last pbuf on the unsent queue,
- chain the first pbuf on the queue together with that. */
- if (useg != NULL &&
- TCP_TCPLEN(useg) != 0 &&
- !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
- (!(flags & (TCP_SYN | TCP_FIN)) || (flags == TCP_FIN)) &&
- /* fit within max seg size */
- (useg->len + queue->len <= pcb->mss) &&
- /* only concatenate segments with the same options */
- (useg->flags == queue->flags) &&
- /* segments are consecutive */
- (ntohl(useg->tcphdr->seqno) + useg->len == ntohl(queue->tcphdr->seqno)) ) {
- /* Remove TCP header from first segment of our to-be-queued list */
- if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) {
- /* Can we cope with this failing? Just assert for now */
- LWIP_ASSERT("pbuf_header failed\n", 0);
- TCP_STATS_INC(tcp.err);
- goto memerr;
- }
- if (queue->p->len == 0) {
- /* free the first (header-only) pbuf if it is now empty (contained only headers) */
- struct pbuf *old_q = queue->p;
- queue->p = queue->p->next;
- old_q->next = NULL;
- queuelen--;
- pbuf_free(old_q);
- }
- if (flags & TCP_FIN) {
- /* the new segment contains only FIN, no data -> put the FIN into the last segment */
- LWIP_ASSERT("FIN enqueued together with data", queue->p == NULL && queue->len == 0);
- TCPH_SET_FLAG(useg->tcphdr, TCP_FIN);
- } else {
- LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
- pbuf_cat(useg->p, queue->p);
- useg->len += queue->len;
- useg->next = queue->next;
- }
+ /*
+ * All three segmentation phases were successful. We can commit the
+ * transaction.
+ */
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
- if (seg == queue) {
- seg = useg;
- seglen = useg->len;
+ /*
+ * Phase 1: If data has been added to the preallocated tail of
+ * last_unsent, we update the length fields of the pbuf chain.
+ */
+#if TCP_OVERSIZE
+ if (oversize_used > 0) {
+ struct pbuf *p;
+ /* Bump tot_len of whole chain, len of tail */
+ for (p = last_unsent->p; p; p = p->next) {
+ p->tot_len += oversize_used;
+ if (p->next == NULL) {
+ TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent);
+ p->len += oversize_used;
+ }
}
- memp_free(MEMP_TCP_SEG, queue);
+ last_unsent->len += oversize_used;
+#if TCP_OVERSIZE_DBGCHECK
+ last_unsent->oversize_left -= oversize_used;
+#endif /* TCP_OVERSIZE_DBGCHECK */
}
- else {
- /* empty list */
- if (useg == NULL) {
- /* initialize list with this segment */
- pcb->unsent = queue;
- }
- /* enqueue segment */
- else {
- useg->next = queue;
+ pcb->unsent_oversize = oversize;
+#endif /* TCP_OVERSIZE */
+
+ /*
+ * Phase 2: concat_p can be concatenated onto last_unsent->p
+ */
+ if (concat_p != NULL) {
+ LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty",
+ (last_unsent != NULL));
+ pbuf_cat(last_unsent->p, concat_p);
+ last_unsent->len += concat_p->tot_len;
+#if TCP_CHECKSUM_ON_COPY
+ if (concat_chksummed) {
+ tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
+ &last_unsent->chksum_swapped);
+ last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
}
+#endif /* TCP_CHECKSUM_ON_COPY */
}
- if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
- ++len;
- }
- if (flags & TCP_FIN) {
- pcb->flags |= TF_FIN;
+
+ /*
+ * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that
+ * is harmless
+ */
+ if (last_unsent == NULL) {
+ pcb->unsent = queue;
+ } else {
+ last_unsent->next = queue;
}
- pcb->snd_lbb += len;
+ /*
+ * Finally update the pcb state.
+ */
+ pcb->snd_lbb += len;
pcb->snd_buf -= len;
-
- /* update number of segments on the queues */
pcb->snd_queuelen = queuelen;
- LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
+
+ LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n",
+ pcb->snd_queuelen));
if (pcb->snd_queuelen != 0) {
- LWIP_ASSERT("tcp_enqueue: valid queue length",
- pcb->unacked != NULL || pcb->unsent != NULL);
+ LWIP_ASSERT("tcp_write: valid queue length",
+ pcb->unacked != NULL || pcb->unsent != NULL);
}
- /* Set the PSH flag in the last segment that we enqueued, but only
- if the segment has data (indicated by seglen > 0). */
- if (seg != NULL && seglen > 0 && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
+ /* Set the PSH flag in the last segment that we enqueued. */
+ if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
}
@@ -426,17 +687,130 @@ memerr:
pcb->flags |= TF_NAGLEMEMERR;
TCP_STATS_INC(tcp.memerr);
+ if (concat_p != NULL) {
+ pbuf_free(concat_p);
+ }
if (queue != NULL) {
tcp_segs_free(queue);
}
if (pcb->snd_queuelen != 0) {
- LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
+ LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL);
}
- LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
+ LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
return ERR_MEM;
}
+/**
+ * Enqueue TCP options for transmission.
+ *
+ * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl().
+ *
+ * @param pcb Protocol control block for the TCP connection.
+ * @param flags TCP header flags to set in the outgoing segment.
+ * @param optdata pointer to TCP options, or NULL.
+ * @param optlen length of TCP options in bytes.
+ */
+err_t
+tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
+{
+ struct pbuf *p;
+ struct tcp_seg *seg;
+ u8_t optflags = 0;
+ u8_t optlen = 0;
+
+ LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
+
+ LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)",
+ (flags & (TCP_SYN | TCP_FIN)) != 0);
+
+ /* check for configured max queuelen and possible overflow */
+ if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n",
+ pcb->snd_queuelen, TCP_SND_QUEUELEN));
+ TCP_STATS_INC(tcp.memerr);
+ pcb->flags |= TF_NAGLEMEMERR;
+ return ERR_MEM;
+ }
+
+ if (flags & TCP_SYN) {
+ optflags = TF_SEG_OPTS_MSS;
+ }
+#if LWIP_TCP_TIMESTAMPS
+ if ((pcb->flags & TF_TIMESTAMP)) {
+ optflags |= TF_SEG_OPTS_TS;
+ }
+#endif /* LWIP_TCP_TIMESTAMPS */
+ optlen = LWIP_TCP_OPT_LENGTH(optflags);
+
+ /* tcp_enqueue_flags is always called with either SYN or FIN in flags.
+ * We need one available snd_buf byte to do that.
+ * This means we can't send FIN while snd_buf==0. A better fix would be to
+ * not include SYN and FIN sequence numbers in the snd_buf count. */
+ if (pcb->snd_buf == 0) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: no send buffer available\n"));
+ TCP_STATS_INC(tcp.memerr);
+ return ERR_MEM;
+ }
+
+ /* Allocate pbuf with room for TCP header + options */
+ if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
+ pcb->flags |= TF_NAGLEMEMERR;
+ TCP_STATS_INC(tcp.memerr);
+ return ERR_MEM;
+ }
+ LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen",
+ (p->len >= optlen));
+
+ /* Allocate memory for tcp_seg, and fill in fields. */
+ if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) {
+ pcb->flags |= TF_NAGLEMEMERR;
+ TCP_STATS_INC(tcp.memerr);
+ return ERR_MEM;
+ }
+ LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0);
+ LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0);
+
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE,
+ ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
+ ntohl(seg->tcphdr->seqno),
+ ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
+ (u16_t)flags));
+
+ /* Now append seg to pcb->unsent queue */
+ if (pcb->unsent == NULL) {
+ pcb->unsent = seg;
+ } else {
+ struct tcp_seg *useg;
+ for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
+ useg->next = seg;
+ }
+#if TCP_OVERSIZE
+ /* The new unsent tail has no space */
+ pcb->unsent_oversize = 0;
+#endif /* TCP_OVERSIZE */
+
+ /* SYN and FIN bump the sequence number */
+ if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
+ pcb->snd_lbb++;
+ /* optlen does not influence snd_buf */
+ pcb->snd_buf--;
+ }
+ if (flags & TCP_FIN) {
+ pcb->flags |= TF_FIN;
+ }
+
+ /* update number of segments on the queues */
+ pcb->snd_queuelen += pbuf_clen(seg->p);
+ LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
+ if (pcb->snd_queuelen != 0) {
+ LWIP_ASSERT("tcp_enqueue_flags: invalid queue length",
+ pcb->unacked != NULL || pcb->unsent != NULL);
+ }
+
+ return ERR_OK;
+}
+
#if LWIP_TCP_TIMESTAMPS
/* Build a timestamp option (12 bytes long) at the specified options pointer)
@@ -448,7 +822,7 @@ static void
tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
{
/* Pad with two NOP options to make everything nicely aligned */
- opts[0] = htonl(0x0101080A);
+ opts[0] = PP_HTONL(0x0101080A);
opts[1] = htonl(sys_now());
opts[2] = htonl(pcb->ts_recent);
}
@@ -470,18 +844,18 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
}
#endif
- p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
+
+ p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt));
if (p == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
return ERR_BUF;
}
+ tcphdr = (struct tcp_hdr *)p->payload;
LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
/* remove ACK flags from the PCB, as we send an empty ACK now */
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
- tcphdr = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
-
/* NB. MSS option is only sent on SYNs, so ignore it here */
#if LWIP_TCP_TIMESTAMPS
pcb->ts_lastacksent = pcb->rcv_nxt;
@@ -581,10 +955,10 @@ tcp_output(struct tcp_pcb *pcb)
(TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
/* Stop sending if the nagle algorithm would prevent it
* Don't stop:
- * - if tcp_enqueue had a memory error before (prevent delayed ACK timeout) or
+ * - if tcp_write had a memory error before (prevent delayed ACK timeout) or
* - if FIN was already enqueued for this PCB (SYN is always alone in a segment -
* either seg->next != NULL or pcb->unacked == NULL;
- * RST is no sent using tcp_enqueue/tcp_output.
+ * RST is no sent using tcp_write/tcp_output.
*/
if((tcp_do_output_nagle(pcb) == 0) &&
((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){
@@ -623,7 +997,7 @@ tcp_output(struct tcp_pcb *pcb)
/* In the case of fast retransmit, the packet should not go to the tail
* of the unacked queue, but rather somewhere before it. We need to check for
* this case. -STJ Jul 27, 2004 */
- if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
+ if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) {
/* add segment to before tail of unacked list, keeping the list sorted */
struct tcp_seg **cur_seg = &(pcb->unacked);
while (*cur_seg &&
@@ -644,6 +1018,12 @@ tcp_output(struct tcp_pcb *pcb)
}
seg = pcb->unsent;
}
+#if TCP_OVERSIZE
+ if (pcb->unsent == NULL) {
+ /* last unsent has been removed, reset unsent_oversize */
+ pcb->unsent_oversize = 0;
+ }
+#endif /* TCP_OVERSIZE */
if (seg != NULL && pcb->persist_backoff == 0 &&
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
@@ -683,7 +1063,8 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
/* Add any requested options. NB MSS option is only set on SYN
packets, so ignore it here */
- opts = (u32_t *)(seg->tcphdr + 1);
+ LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0);
+ opts = (u32_t *)(void *)(seg->tcphdr + 1);
if (seg->flags & TF_SEG_OPTS_MSS) {
TCP_BUILD_MSS_OPTION(*opts);
opts += 1;
@@ -697,6 +1078,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
}
#endif
+ /* Set retransmission timer running if it is not currently enabled
+ This must be set before checking the route. */
+ if (pcb->rtime == -1) {
+ pcb->rtime = 0;
+ }
+
/* If we don't have a local IP address, we get one by
calling ip_route(). */
if (ip_addr_isany(&(pcb->local_ip))) {
@@ -704,13 +1091,9 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
if (netif == NULL) {
return;
}
- ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
+ ip_addr_copy(pcb->local_ip, netif->ip_addr);
}
- /* Set retransmission timer running if it is not currently enabled */
- if(pcb->rtime == -1)
- pcb->rtime = 0;
-
if (pcb->rttest == 0) {
pcb->rttest = tcp_ticks;
pcb->rtseq = ntohl(seg->tcphdr->seqno);
@@ -730,11 +1113,45 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
seg->tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP
- seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
- &(pcb->local_ip),
+#if TCP_CHECKSUM_ON_COPY
+ {
+ u32_t acc;
+#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
+ u16_t chksum_slow = inet_chksum_pseudo(seg->p, &(pcb->local_ip),
+ &(pcb->remote_ip),
+ IP_PROTO_TCP, seg->p->tot_len);
+#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
+ if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
+ LWIP_ASSERT("data included but not checksummed",
+ seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4));
+ }
+
+ /* rebuild TCP header checksum (TCP header changes for retransmissions!) */
+ acc = inet_chksum_pseudo_partial(seg->p, &(pcb->local_ip),
&(pcb->remote_ip),
- IP_PROTO_TCP, seg->p->tot_len);
-#endif
+ IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4);
+ /* add payload checksum */
+ if (seg->chksum_swapped) {
+ seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum);
+ seg->chksum_swapped = 0;
+ }
+ acc += (u16_t)~(seg->chksum);
+ seg->tcphdr->chksum = FOLD_U32T(acc);
+#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
+ if (chksum_slow != seg->tcphdr->chksum) {
+ LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n",
+ seg->tcphdr->chksum, chksum_slow));
+ seg->tcphdr->chksum = chksum_slow;
+ }
+#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
+ }
+#else /* TCP_CHECKSUM_ON_COPY */
+ seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip),
+ &(pcb->remote_ip),
+ IP_PROTO_TCP, seg->p->tot_len);
+#endif /* TCP_CHECKSUM_ON_COPY */
+#endif /* CHECKSUM_GEN_TCP */
TCP_STATS_INC(tcp.xmit);
#if LWIP_NETIF_HWADDRHINT
@@ -768,7 +1185,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
*/
void
tcp_rst(u32_t seqno, u32_t ackno,
- struct ip_addr *local_ip, struct ip_addr *remote_ip,
+ ip_addr_t *local_ip, ip_addr_t *remote_ip,
u16_t local_port, u16_t remote_port)
{
struct pbuf *p;
@@ -781,17 +1198,16 @@ tcp_rst(u32_t seqno, u32_t ackno,
LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
(p->len >= sizeof(struct tcp_hdr)));
- tcphdr = p->payload;
+ tcphdr = (struct tcp_hdr *)p->payload;
tcphdr->src = htons(local_port);
tcphdr->dest = htons(remote_port);
tcphdr->seqno = htonl(seqno);
tcphdr->ackno = htonl(ackno);
- TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
- tcphdr->wnd = htons(TCP_WND);
+ TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
+ tcphdr->wnd = PP_HTONS(TCP_WND);
+ tcphdr->chksum = 0;
tcphdr->urgp = 0;
- TCPH_HDRLEN_SET(tcphdr, 5);
- tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
IP_PROTO_TCP, p->tot_len);
@@ -900,10 +1316,11 @@ tcp_rexmit_fast(struct tcp_pcb *pcb)
/* Set ssthresh to half of the minimum of the current
* cwnd and the advertised window */
- if (pcb->cwnd > pcb->snd_wnd)
+ if (pcb->cwnd > pcb->snd_wnd) {
pcb->ssthresh = pcb->snd_wnd / 2;
- else
+ } else {
pcb->ssthresh = pcb->cwnd / 2;
+ }
/* The minimum value for ssthresh should be 2 MSS */
if (pcb->ssthresh < 2*pcb->mss) {
@@ -935,23 +1352,19 @@ tcp_keepalive(struct tcp_pcb *pcb)
struct tcp_hdr *tcphdr;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
- ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
+ ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
+ ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
- p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
-
+ p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1));
if(p == NULL) {
LWIP_DEBUGF(TCP_DEBUG,
("tcp_keepalive: could not allocate memory for pbuf\n"));
return;
}
- LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
- (p->len >= sizeof(struct tcp_hdr)));
-
- tcphdr = tcp_output_set_header(pcb, p, 0, htonl(pcb->snd_nxt - 1));
+ tcphdr = (struct tcp_hdr *)p->payload;
#if CHECKSUM_GEN_TCP
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
@@ -994,8 +1407,8 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
LWIP_DEBUGF(TCP_DEBUG,
("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
- ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
- ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
+ ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
+ ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
LWIP_DEBUGF(TCP_DEBUG,
("tcp_zero_window_probe: tcp_ticks %"U32_F
@@ -1004,31 +1417,32 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
seg = pcb->unacked;
- if(seg == NULL)
+ if(seg == NULL) {
seg = pcb->unsent;
-
- if(seg == NULL)
+ }
+ if(seg == NULL) {
return;
+ }
is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
- len = is_fin ? TCP_HLEN : TCP_HLEN + 1;
+ /* we want to send one seqno: either FIN or data (no options) */
+ len = is_fin ? 0 : 1;
- p = pbuf_alloc(PBUF_IP, len, PBUF_RAM);
+ p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
if(p == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
return;
}
- LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
- (p->len >= sizeof(struct tcp_hdr)));
-
- tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno);
+ tcphdr = (struct tcp_hdr *)p->payload;
if (is_fin) {
/* FIN segment, no data */
TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
} else {
/* Data segment, copy in one byte from the head of the unacked queue */
- *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
+ struct tcp_hdr *thdr = (struct tcp_hdr *)seg->p->payload;
+ char *d = ((char *)p->payload + TCP_HLEN);
+ pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4);
}
#if CHECKSUM_GEN_TCP
diff --git a/core/lwip/src/core/timers.c b/core/lwip/src/core/timers.c
new file mode 100644
index 00000000..4e94f0d1
--- /dev/null
+++ b/core/lwip/src/core/timers.c
@@ -0,0 +1,483 @@
+/**
+ * @file
+ * Stack-internal timers implementation.
+ * This file includes timer callbacks for stack-internal timers as well as
+ * functions to set up or stop timers and check for expired timers.
+ *
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ * Simon Goldschmidt
+ *
+ */
+
+#include "lwip/opt.h"
+
+#include "lwip/timers.h"
+#include "lwip/tcp_impl.h"
+
+#if LWIP_TIMERS
+
+#include "lwip/def.h"
+#include "lwip/memp.h"
+#include "lwip/tcpip.h"
+
+#include "lwip/ip_frag.h"
+#include "netif/etharp.h"
+#include "lwip/dhcp.h"
+#include "lwip/autoip.h"
+#include "lwip/igmp.h"
+#include "lwip/dns.h"
+
+
+/** The one and only timeout list */
+static struct sys_timeo *next_timeout;
+#if NO_SYS
+static u32_t timeouts_last_time;
+#endif /* NO_SYS */
+
+#if LWIP_TCP
+/** global variable that shows if the tcp timer is currently scheduled or not */
+static int tcpip_tcp_timer_active;
+
+/**
+ * Timer callback function that calls tcp_tmr() and reschedules itself.
+ *
+ * @param arg unused argument
+ */
+static void
+tcpip_tcp_timer(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+
+ /* call TCP timer handler */
+ tcp_tmr();
+ /* timer still needed? */
+ if (tcp_active_pcbs || tcp_tw_pcbs) {
+ /* restart timer */
+ sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
+ } else {
+ /* disable timer */
+ tcpip_tcp_timer_active = 0;
+ }
+}
+
+/**
+ * Called from TCP_REG when registering a new PCB:
+ * the reason is to have the TCP timer only running when
+ * there are active (or time-wait) PCBs.
+ */
+void
+tcp_timer_needed(void)
+{
+ /* timer is off but needed again? */
+ if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
+ /* enable and start timer */
+ tcpip_tcp_timer_active = 1;
+ sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
+ }
+}
+#endif /* LWIP_TCP */
+
+#if IP_REASSEMBLY
+/**
+ * Timer callback function that calls ip_reass_tmr() and reschedules itself.
+ *
+ * @param arg unused argument
+ */
+static void
+ip_reass_timer(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+ LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n"));
+ ip_reass_tmr();
+ sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
+}
+#endif /* IP_REASSEMBLY */
+
+#if LWIP_ARP
+/**
+ * Timer callback function that calls etharp_tmr() and reschedules itself.
+ *
+ * @param arg unused argument
+ */
+static void
+arp_timer(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+ LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n"));
+ etharp_tmr();
+ undiarp_tmr();
+ sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
+}
+#endif /* LWIP_ARP */
+
+#if LWIP_DHCP
+/**
+ * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself.
+ *
+ * @param arg unused argument
+ */
+static void
+dhcp_timer_coarse(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+ LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
+ dhcp_coarse_tmr();
+ sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
+}
+
+/**
+ * Timer callback function that calls dhcp_fine_tmr() and reschedules itself.
+ *
+ * @param arg unused argument
+ */
+static void
+dhcp_timer_fine(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+ LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
+ dhcp_fine_tmr();
+ sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
+}
+#endif /* LWIP_DHCP */
+
+#if LWIP_AUTOIP
+/**
+ * Timer callback function that calls autoip_tmr() and reschedules itself.
+ *
+ * @param arg unused argument
+ */
+static void
+autoip_timer(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+ LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n"));
+ autoip_tmr();
+ sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
+}
+#endif /* LWIP_AUTOIP */
+
+#if LWIP_IGMP
+/**
+ * Timer callback function that calls igmp_tmr() and reschedules itself.
+ *
+ * @param arg unused argument
+ */
+static void
+igmp_timer(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+ LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n"));
+ igmp_tmr();
+ sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
+}
+#endif /* LWIP_IGMP */
+
+#if LWIP_DNS
+/**
+ * Timer callback function that calls dns_tmr() and reschedules itself.
+ *
+ * @param arg unused argument
+ */
+static void
+dns_timer(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+ LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n"));
+ dns_tmr();
+ sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
+}
+#endif /* LWIP_DNS */
+
+/** Initialize this module */
+void sys_timeouts_init(void)
+{
+#if IP_REASSEMBLY
+ sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
+#endif /* IP_REASSEMBLY */
+#if LWIP_ARP
+ sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
+#endif /* LWIP_ARP */
+#if LWIP_DHCP
+ sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
+ sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
+#endif /* LWIP_DHCP */
+#if LWIP_AUTOIP
+ sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
+#endif /* LWIP_AUTOIP */
+#if LWIP_IGMP
+ sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
+#endif /* LWIP_IGMP */
+#if LWIP_DNS
+ sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
+#endif /* LWIP_DNS */
+
+#if NO_SYS
+ /* Initialise timestamp for sys_check_timeouts */
+ timeouts_last_time = sys_now();
+#endif
+}
+
+/**
+ * Create a one-shot timer (aka timeout). Timeouts are processed in the
+ * following cases:
+ * - while waiting for a message using sys_timeouts_mbox_fetch()
+ * - by calling sys_check_timeouts() (NO_SYS==1 only)
+ *
+ * @param msecs time in milliseconds after that the timer should expire
+ * @param handler callback function to call when msecs have elapsed
+ * @param arg argument to pass to the callback function
+ */
+#if LWIP_DEBUG_TIMERNAMES
+void
+sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name)
+#else /* LWIP_DEBUG_TIMERNAMES */
+void
+sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
+#endif /* LWIP_DEBUG_TIMERNAMES */
+{
+ struct sys_timeo *timeout, *t;
+
+ timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
+ if (timeout == NULL) {
+ LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
+ return;
+ }
+ timeout->next = NULL;
+ timeout->h = handler;
+ timeout->arg = arg;
+ timeout->time = msecs;
+#if LWIP_DEBUG_TIMERNAMES
+ timeout->handler_name = handler_name;
+ LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n",
+ (void *)timeout, msecs, handler_name, (void *)arg));
+#endif /* LWIP_DEBUG_TIMERNAMES */
+
+ if (next_timeout == NULL) {
+ next_timeout = timeout;
+ return;
+ }
+
+ if (next_timeout->time > msecs) {
+ next_timeout->time -= msecs;
+ timeout->next = next_timeout;
+ next_timeout = timeout;
+ } else {
+ for(t = next_timeout; t != NULL; t = t->next) {
+ timeout->time -= t->time;
+ if (t->next == NULL || t->next->time > timeout->time) {
+ if (t->next != NULL) {
+ t->next->time -= timeout->time;
+ }
+ timeout->next = t->next;
+ t->next = timeout;
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * 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 'handler' in the list of timeouts.
+ *
+ * @param handler callback function that would be called by the timeout
+ * @param arg callback argument that would be passed to handler
+*/
+void
+sys_untimeout(sys_timeout_handler handler, void *arg)
+{
+ struct sys_timeo *prev_t, *t;
+
+ if (next_timeout == NULL) {
+ return;
+ }
+
+ for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
+ if ((t->h == handler) && (t->arg == arg)) {
+ /* We have a match */
+ /* Unlink from previous in list */
+ if (prev_t == NULL) {
+ next_timeout = t->next;
+ } else {
+ prev_t->next = t->next;
+ }
+ /* If not the last one, add time of this one back to next */
+ if (t->next != NULL) {
+ t->next->time += t->time;
+ }
+ memp_free(MEMP_SYS_TIMEOUT, t);
+ return;
+ }
+ }
+ return;
+}
+
+#if NO_SYS
+
+/** Handle timeouts for NO_SYS==1 (i.e. without using
+ * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout
+ * handler functions when timeouts expire.
+ *
+ * Must be called periodically from your main loop.
+ */
+void
+sys_check_timeouts(void)
+{
+ struct sys_timeo *tmptimeout;
+ u32_t diff;
+ sys_timeout_handler handler;
+ void *arg;
+ int had_one;
+ u32_t now;
+
+ now = sys_now();
+ if (next_timeout) {
+ /* this cares for wraparounds */
+ diff = LWIP_U32_DIFF(now, timeouts_last_time);
+ do
+ {
+ had_one = 0;
+ tmptimeout = next_timeout;
+ if (tmptimeout->time <= diff) {
+ /* timeout has expired */
+ had_one = 1;
+ timeouts_last_time = now;
+ diff -= tmptimeout->time;
+ next_timeout = tmptimeout->next;
+ handler = tmptimeout->h;
+ arg = tmptimeout->arg;
+#if LWIP_DEBUG_TIMERNAMES
+ if (handler != NULL) {
+ LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n",
+ tmptimeout->handler_name, arg));
+ }
+#endif /* LWIP_DEBUG_TIMERNAMES */
+ memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
+ if (handler != NULL) {
+ handler(arg);
+ }
+ }
+ /* repeat until all expired timers have been called */
+ }while(had_one);
+ }
+}
+
+/** Set back the timestamp of the last call to sys_check_timeouts()
+ * This is necessary if sys_check_timeouts() hasn't been called for a long
+ * time (e.g. while saving energy) to prevent all timer functions of that
+ * period being called.
+ */
+void
+sys_restart_timeouts(void)
+{
+ timeouts_last_time = sys_now();
+}
+
+#else /* NO_SYS */
+
+/**
+ * Wait (forever) for a message to arrive in an mbox.
+ * While waiting, timeouts are processed.
+ *
+ * @param mbox the mbox to fetch the message from
+ * @param msg the place to store the message
+ */
+void
+sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
+{
+ u32_t time_needed;
+ struct sys_timeo *tmptimeout;
+ sys_timeout_handler handler;
+ void *arg;
+
+ again:
+ if (!next_timeout) {
+ time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
+ } else {
+ if (next_timeout->time > 0) {
+ time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time);
+ } else {
+ time_needed = 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. */
+ tmptimeout = next_timeout;
+ next_timeout = tmptimeout->next;
+ handler = tmptimeout->h;
+ arg = tmptimeout->arg;
+#if LWIP_DEBUG_TIMERNAMES
+ if (handler != NULL) {
+ LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n",
+ tmptimeout->handler_name, arg));
+ }
+#endif /* LWIP_DEBUG_TIMERNAMES */
+ memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
+ if (handler != NULL) {
+ /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the
+ timeout handler function. */
+ LOCK_TCPIP_CORE();
+ handler(arg);
+ UNLOCK_TCPIP_CORE();
+ }
+ LWIP_TCPIP_THREAD_ALIVE();
+
+ /* We try again to fetch a message from the mbox. */
+ goto again;
+ } else {
+ /* 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_needed < next_timeout->time) {
+ next_timeout->time -= time_needed;
+ } else {
+ next_timeout->time = 0;
+ }
+ }
+ }
+}
+
+#endif /* NO_SYS */
+
+#else /* LWIP_TIMERS */
+/* Satisfy the TCP code which calls this function */
+void
+tcp_timer_needed(void)
+{
+}
+#endif /* LWIP_TIMERS */
diff --git a/core/lwip/src/core/udp.c b/core/lwip/src/core/udp.c
index 96dab41b..4596ba2b 100644
--- a/core/lwip/src/core/udp.c
+++ b/core/lwip/src/core/udp.c
@@ -53,7 +53,6 @@
#include "lwip/udp.h"
#include "lwip/def.h"
#include "lwip/memp.h"
-#include "lwip/inet.h"
#include "lwip/inet_chksum.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
@@ -96,7 +95,7 @@ udp_input(struct pbuf *p, struct netif *inp)
UDP_STATS_INC(udp.recv);
- iphdr = p->payload;
+ iphdr = (struct ip_hdr *)p->payload;
/* Check minimum length (IP header + UDP header)
* and move payload pointer to UDP header */
@@ -114,7 +113,7 @@ udp_input(struct pbuf *p, struct netif *inp)
udphdr = (struct udp_hdr *)p->payload;
/* is broadcast packet ? */
- broadcast = ip_addr_isbroadcast(&(iphdr->dest), inp);
+ broadcast = ip_addr_isbroadcast(&current_iphdr_dest, inp);
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
@@ -128,10 +127,10 @@ udp_input(struct pbuf *p, struct netif *inp)
LWIP_DEBUGF(UDP_DEBUG,
("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- "
"(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
- ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest),
- ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
- ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
- ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
+ ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest),
+ ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest), ntohs(udphdr->dest),
+ ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src),
+ ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src), ntohs(udphdr->src)));
#if LWIP_DHCP
pcb = NULL;
@@ -145,7 +144,7 @@ udp_input(struct pbuf *p, struct netif *inp)
(- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY!
- inp->dhcp->pcb->remote == ANY or iphdr->src */
if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) ||
- ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), &(iphdr->src)))) {
+ ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), &current_iphdr_src))) {
pcb = inp->dhcp->pcb;
}
}
@@ -166,17 +165,17 @@ udp_input(struct pbuf *p, struct netif *inp)
LWIP_DEBUGF(UDP_DEBUG,
("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- "
"(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
- ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
- ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
- ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
- ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
+ ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
+ ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), pcb->local_port,
+ ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
+ ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip), pcb->remote_port));
/* compare PCB local addr+port to UDP destination addr+port */
if ((pcb->local_port == dest) &&
((!broadcast && ip_addr_isany(&pcb->local_ip)) ||
- ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)) ||
+ ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest) ||
#if LWIP_IGMP
- ip_addr_ismulticast(&(iphdr->dest)) ||
+ ip_addr_ismulticast(&current_iphdr_dest) ||
#endif /* LWIP_IGMP */
#if IP_SOF_BROADCAST_RECV
(broadcast && (pcb->so_options & SOF_BROADCAST)))) {
@@ -194,7 +193,7 @@ udp_input(struct pbuf *p, struct netif *inp)
if ((local_match != 0) &&
(pcb->remote_port == src) &&
(ip_addr_isany(&pcb->remote_ip) ||
- ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)))) {
+ ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src))) {
/* the first fully matching PCB */
if (prev != NULL) {
/* move the pcb to the front of udp_pcbs so that is
@@ -216,7 +215,7 @@ udp_input(struct pbuf *p, struct netif *inp)
}
/* Check checksum if this is a match or if it was directed at us. */
- if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &iphdr->dest)) {
+ if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &current_iphdr_dest)) {
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n"));
#if LWIP_UDPLITE
if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
@@ -238,8 +237,7 @@ udp_input(struct pbuf *p, struct netif *inp)
goto end;
}
}
- if (inet_chksum_pseudo_partial(p, (struct ip_addr *)&(iphdr->src),
- (struct ip_addr *)&(iphdr->dest),
+ if (inet_chksum_pseudo_partial(p, &current_iphdr_src, &current_iphdr_dest,
IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
@@ -255,8 +253,7 @@ udp_input(struct pbuf *p, struct netif *inp)
{
#if CHECKSUM_CHECK_UDP
if (udphdr->chksum != 0) {
- if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
- (struct ip_addr *)&(iphdr->dest),
+ if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
IP_PROTO_UDP, p->tot_len) != 0) {
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("udp_input: UDP datagram discarded due to failing checksum\n"));
@@ -279,10 +276,58 @@ udp_input(struct pbuf *p, struct netif *inp)
}
if (pcb != NULL) {
snmp_inc_udpindatagrams();
+#if SO_REUSE && SO_REUSE_RXTOALL
+ if ((broadcast || ip_addr_ismulticast(&current_iphdr_dest)) &&
+ ((pcb->so_options & SOF_REUSEADDR) != 0)) {
+ /* pass broadcast- or multicast packets to all multicast pcbs
+ if SOF_REUSEADDR is set on the first match */
+ struct udp_pcb *mpcb;
+ u8_t p_header_changed = 0;
+ for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) {
+ if (mpcb != pcb) {
+ /* compare PCB local addr+port to UDP destination addr+port */
+ if ((mpcb->local_port == dest) &&
+ ((!broadcast && ip_addr_isany(&mpcb->local_ip)) ||
+ ip_addr_cmp(&(mpcb->local_ip), &current_iphdr_dest) ||
+#if LWIP_IGMP
+ ip_addr_ismulticast(&current_iphdr_dest) ||
+#endif /* LWIP_IGMP */
+#if IP_SOF_BROADCAST_RECV
+ (broadcast && (mpcb->so_options & SOF_BROADCAST)))) {
+#else /* IP_SOF_BROADCAST_RECV */
+ (broadcast))) {
+#endif /* IP_SOF_BROADCAST_RECV */
+ /* pass a copy of the packet to all local matches */
+ if (mpcb->recv != NULL) {
+ struct pbuf *q;
+ /* for that, move payload to IP header again */
+ if (p_header_changed == 0) {
+ pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
+ p_header_changed = 1;
+ }
+ q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
+ if (q != NULL) {
+ err_t err = pbuf_copy(q, p);
+ if (err == ERR_OK) {
+ /* move payload to UDP data */
+ pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
+ mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (p_header_changed) {
+ /* and move payload to UDP data again */
+ pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
+ }
+ }
+#endif /* SO_REUSE && SO_REUSE_RXTOALL */
/* callback */
if (pcb->recv != NULL) {
/* now the recv function is responsible for freeing p */
- pcb->recv(pcb->recv_arg, pcb, p, &iphdr->src, src);
+ pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
} else {
/* no recv function registered? then we have to free the pbuf! */
pbuf_free(p);
@@ -295,7 +340,7 @@ udp_input(struct pbuf *p, struct netif *inp)
/* No match was found, send ICMP destination port unreachable unless
destination address was broadcast/multicast. */
if (!broadcast &&
- !ip_addr_ismulticast(&iphdr->dest)) {
+ !ip_addr_ismulticast(&current_iphdr_dest)) {
/* move payload pointer back to ip header */
pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN);
LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr));
@@ -339,6 +384,19 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port);
}
+#if LWIP_CHECKSUM_ON_COPY
+/** Same as udp_send() but with checksum
+ */
+err_t
+udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
+ u8_t have_chksum, u16_t chksum)
+{
+ /* send to the packet using remote ip and port stored in the pcb */
+ return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port,
+ have_chksum, chksum);
+}
+#endif /* LWIP_CHECKSUM_ON_COPY */
+
/**
* Send data to a specified address using UDP.
*
@@ -358,8 +416,18 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
*/
err_t
udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
- struct ip_addr *dst_ip, u16_t dst_port)
+ ip_addr_t *dst_ip, u16_t dst_port)
+{
+#if LWIP_CHECKSUM_ON_COPY
+ return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0);
+}
+
+/** Same as udp_sendto(), but with checksum */
+err_t
+udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
+ u16_t dst_port, u8_t have_chksum, u16_t chksum)
{
+#endif /* LWIP_CHECKSUM_ON_COPY */
struct netif *netif;
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
@@ -373,11 +441,16 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
/* no outgoing network interface could be found? */
if (netif == NULL) {
- LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to 0x%"X32_F"\n", dst_ip->addr));
+ LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(dst_ip), ip4_addr2_16(dst_ip), ip4_addr3_16(dst_ip), ip4_addr4_16(dst_ip)));
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
+#if LWIP_CHECKSUM_ON_COPY
+ return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum);
+#else /* LWIP_CHECKSUM_ON_COPY */
return udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
+#endif /* LWIP_CHECKSUM_ON_COPY */
}
/**
@@ -401,10 +474,21 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
*/
err_t
udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
- struct ip_addr *dst_ip, u16_t dst_port, struct netif *netif)
+ ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif)
{
+#if LWIP_CHECKSUM_ON_COPY
+ return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0);
+}
+
+/** Same as udp_sendto_if(), but with checksum */
+err_t
+udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
+ u16_t dst_port, struct netif *netif, u8_t have_chksum,
+ u16_t chksum)
+{
+#endif /* LWIP_CHECKSUM_ON_COPY */
struct udp_hdr *udphdr;
- struct ip_addr *src_ip;
+ ip_addr_t *src_ip;
err_t err;
struct pbuf *q; /* q will be sent down the stack */
@@ -436,8 +520,10 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n"));
return ERR_MEM;
}
- /* chain header q in front of given pbuf p */
- pbuf_chain(q, p);
+ if (p->tot_len != 0) {
+ /* chain header q in front of given pbuf p (only if p contains data) */
+ pbuf_chain(q, p);
+ }
/* first pbuf q points to header pbuf */
LWIP_DEBUGF(UDP_DEBUG,
("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
@@ -450,12 +536,20 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
LWIP_ASSERT("check that first pbuf can hold struct udp_hdr",
(q->len >= sizeof(struct udp_hdr)));
/* q now represents the packet to be sent */
- udphdr = q->payload;
+ udphdr = (struct udp_hdr *)q->payload;
udphdr->src = htons(pcb->local_port);
udphdr->dest = htons(dst_port);
/* in UDP, 0 checksum means 'no checksum' */
udphdr->chksum = 0x0000;
+ /* Multicast Loop? */
+#if LWIP_IGMP
+ if (ip_addr_ismulticast(dst_ip) && ((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0)) {
+ q->flags |= PBUF_FLAG_MCASTLOOP;
+ }
+#endif /* LWIP_IGMP */
+
+
/* PCB local address is IP_ANY_ADDR? */
if (ip_addr_isany(&pcb->local_ip)) {
/* use outgoing network interface IP address as source address */
@@ -503,11 +597,23 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
/* calculate checksum */
#if CHECKSUM_GEN_UDP
udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
- IP_PROTO_UDPLITE, q->tot_len, chklen);
+ IP_PROTO_UDPLITE, q->tot_len,
+#if !LWIP_CHECKSUM_ON_COPY
+ chklen);
+#else /* !LWIP_CHECKSUM_ON_COPY */
+ (have_chksum ? UDP_HLEN : chklen));
+ if (have_chksum) {
+ u32_t acc;
+ acc = udphdr->chksum + (u16_t)~(chksum);
+ udphdr->chksum = FOLD_U32T(acc);
+ }
+#endif /* !LWIP_CHECKSUM_ON_COPY */
+
/* chksum zero must become 0xffff, as zero means 'no checksum' */
- if (udphdr->chksum == 0x0000)
+ if (udphdr->chksum == 0x0000) {
udphdr->chksum = 0xffff;
-#endif /* CHECKSUM_CHECK_UDP */
+ }
+#endif /* CHECKSUM_GEN_UDP */
/* output to IP */
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
#if LWIP_NETIF_HWADDRHINT
@@ -525,11 +631,27 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
/* calculate checksum */
#if CHECKSUM_GEN_UDP
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
- udphdr->chksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
+ u16_t udpchksum;
+#if LWIP_CHECKSUM_ON_COPY
+ if (have_chksum) {
+ u32_t acc;
+ udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP,
+ q->tot_len, UDP_HLEN);
+ acc = udpchksum + (u16_t)~(chksum);
+ udpchksum = FOLD_U32T(acc);
+ } else
+#endif /* LWIP_CHECKSUM_ON_COPY */
+ {
+ udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
+ }
+
/* chksum zero must become 0xffff, as zero means 'no checksum' */
- if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
+ if (udpchksum == 0x0000) {
+ udpchksum = 0xffff;
+ }
+ udphdr->chksum = udpchksum;
}
-#endif /* CHECKSUM_CHECK_UDP */
+#endif /* CHECKSUM_GEN_UDP */
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
/* output to IP */
@@ -576,7 +698,7 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
* @see udp_disconnect()
*/
err_t
-udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
+udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
u8_t rebind;
@@ -596,13 +718,16 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
rebind = 1;
}
- /* this code does not allow upper layer to share a UDP port for
- listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
- SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
- combine with implementation of UDP PCB flags. Leon Woestenberg. */
-#ifdef LWIP_UDP_TODO
- /* port matches that of PCB in list? */
- else
+ /* By default, we don't allow to bind to a port that any other udp
+ PCB is alread bound to, unless *all* PCBs with that port have tha
+ REUSEADDR flag set. */
+#if SO_REUSE
+ else if (((pcb->so_options & SOF_REUSEADDR) == 0) &&
+ ((ipcb->so_options & SOF_REUSEADDR) == 0)) {
+#else /* SO_REUSE */
+ /* port matches that of PCB in list and REUSEADDR not set -> reject */
+ else {
+#endif /* SO_REUSE */
if ((ipcb->local_port == port) &&
/* IP address matches, or one is IP_ADDR_ANY? */
(ip_addr_isany(&(ipcb->local_ip)) ||
@@ -613,7 +738,7 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
return ERR_USE;
}
-#endif
+ }
}
ip_addr_set(&pcb->local_ip, ipaddr);
@@ -621,8 +746,10 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
/* no port specified? */
if (port == 0) {
#ifndef UDP_LOCAL_PORT_RANGE_START
-#define UDP_LOCAL_PORT_RANGE_START 4096
-#define UDP_LOCAL_PORT_RANGE_END 0x7fff
+/* From http://www.iana.org/assignments/port-numbers:
+ "The Dynamic and/or Private Ports are those from 49152 through 65535" */
+#define UDP_LOCAL_PORT_RANGE_START 0xc000
+#define UDP_LOCAL_PORT_RANGE_END 0xffff
#endif
port = UDP_LOCAL_PORT_RANGE_START;
ipcb = udp_pcbs;
@@ -632,9 +759,10 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
port++;
/* restart scanning all udp pcbs */
ipcb = udp_pcbs;
- } else
+ } else {
/* go on with next udp pcb */
ipcb = ipcb->next;
+ }
}
if (ipcb != NULL) {
/* no more ports available in local range */
@@ -652,10 +780,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) & 0xff), pcb->local_port));
+ ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
+ ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
+ pcb->local_port));
return ERR_OK;
}
/**
@@ -676,14 +803,15 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
* @see udp_disconnect()
*/
err_t
-udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
+udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
if (pcb->local_port == 0) {
err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
- if (err != ERR_OK)
+ if (err != ERR_OK) {
return err;
+ }
}
ip_addr_set(&pcb->remote_ip, ipaddr);
@@ -710,10 +838,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) & 0xff), pcb->remote_port));
+ ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
+ ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
+ pcb->local_port));
/* Insert UDP PCB into the list of active UDP PCBs. */
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
@@ -737,7 +864,7 @@ void
udp_disconnect(struct udp_pcb *pcb)
{
/* reset remote address association */
- ip_addr_set(&pcb->remote_ip, IP_ADDR_ANY);
+ ip_addr_set_any(&pcb->remote_ip);
pcb->remote_port = 0;
/* mark PCB as unconnected */
pcb->flags &= ~UDP_FLAGS_CONNECTED;
@@ -753,10 +880,7 @@ udp_disconnect(struct udp_pcb *pcb)
* @param recv_arg additional argument to pass to the callback function
*/
void
-udp_recv(struct udp_pcb *pcb,
- void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
- struct ip_addr *addr, u16_t port),
- void *recv_arg)
+udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
{
/* remember recv() callback and user data */
pcb->recv = recv;
@@ -782,7 +906,7 @@ udp_remove(struct udp_pcb *pcb)
/* make list start at 2nd pcb */
udp_pcbs = udp_pcbs->next;
/* pcb not 1st in list */
- } else
+ } else {
for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
/* find pcb in udp_pcbs list */
if (pcb2->next != NULL && pcb2->next == pcb) {
@@ -790,6 +914,7 @@ udp_remove(struct udp_pcb *pcb)
pcb2->next = pcb->next;
}
}
+ }
memp_free(MEMP_UDP_PCB, pcb);
}
@@ -805,7 +930,7 @@ struct udp_pcb *
udp_new(void)
{
struct udp_pcb *pcb;
- pcb = memp_malloc(MEMP_UDP_PCB);
+ pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB);
/* could allocate UDP PCB? */
if (pcb != NULL) {
/* UDP Lite: by initializing to all zeroes, chksum_len is set to 0
diff --git a/core/lwip/src/include/arch/sys_arch.h b/core/lwip/src/include/arch/sys_arch.h
index 89126208..732a19c4 100644
--- a/core/lwip/src/include/arch/sys_arch.h
+++ b/core/lwip/src/include/arch/sys_arch.h
@@ -10,7 +10,12 @@ typedef struct semaphore *sys_sem_t;
typedef struct mailbox *sys_mbox_t;
typedef struct thread *sys_thread_t;
-#define sys_sem_signal(x) sem_up(x)
+static inline void sys_sem_signal(sys_sem_t *sem)
+{
+ if (!!sem)
+ sem_up(*sem);
+}
+
#define sys_now ms_timer
#define SYS_MBOX_NULL NULL
diff --git a/core/lwip/src/include/ipv4/lwip/autoip.h b/core/lwip/src/include/ipv4/lwip/autoip.h
index f2621658..23c264a1 100644
--- a/core/lwip/src/include/ipv4/lwip/autoip.h
+++ b/core/lwip/src/include/ipv4/lwip/autoip.h
@@ -80,7 +80,7 @@ extern "C" {
struct autoip
{
- struct ip_addr llipaddr; /* the currently selected, probed, announced or used LL IP-Address */
+ ip_addr_t llipaddr; /* the currently selected, probed, announced or used LL IP-Address */
u8_t state; /* current AutoIP state machine state */
u8_t sent_num; /* sent number of probes or announces, dependent on state */
u16_t ttw; /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */
@@ -92,6 +92,9 @@ struct autoip
/** Init srand, has to be called before entering mainloop */
void autoip_init(void);
+/** Set a struct autoip allocated by the application to work with */
+void autoip_set_struct(struct netif *netif, struct autoip *autoip);
+
/** Start AutoIP client */
err_t autoip_start(struct netif *netif);
diff --git a/core/lwip/src/include/ipv4/lwip/icmp.h b/core/lwip/src/include/ipv4/lwip/icmp.h
index c73961c9..d47a7d8a 100644
--- a/core/lwip/src/include/ipv4/lwip/icmp.h
+++ b/core/lwip/src/include/ipv4/lwip/icmp.h
@@ -41,29 +41,29 @@
extern "C" {
#endif
-#define ICMP_ER 0 /* echo reply */
-#define ICMP_DUR 3 /* destination unreachable */
-#define ICMP_SQ 4 /* source quench */
-#define ICMP_RD 5 /* redirect */
+#define ICMP_ER 0 /* echo reply */
+#define ICMP_DUR 3 /* destination unreachable */
+#define ICMP_SQ 4 /* source quench */
+#define ICMP_RD 5 /* redirect */
#define ICMP_ECHO 8 /* echo */
-#define ICMP_TE 11 /* time exceeded */
-#define ICMP_PP 12 /* parameter problem */
-#define ICMP_TS 13 /* timestamp */
+#define ICMP_TE 11 /* time exceeded */
+#define ICMP_PP 12 /* parameter problem */
+#define ICMP_TS 13 /* timestamp */
#define ICMP_TSR 14 /* timestamp reply */
#define ICMP_IRQ 15 /* information request */
-#define ICMP_IR 16 /* information reply */
+#define ICMP_IR 16 /* information reply */
enum icmp_dur_type {
- ICMP_DUR_NET = 0, /* net unreachable */
- ICMP_DUR_HOST = 1, /* host unreachable */
+ ICMP_DUR_NET = 0, /* net unreachable */
+ ICMP_DUR_HOST = 1, /* host unreachable */
ICMP_DUR_PROTO = 2, /* protocol unreachable */
- ICMP_DUR_PORT = 3, /* port unreachable */
- ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
- ICMP_DUR_SR = 5 /* source route failed */
+ ICMP_DUR_PORT = 3, /* port unreachable */
+ ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
+ ICMP_DUR_SR = 5 /* source route failed */
};
enum icmp_te_type {
- ICMP_TE_TTL = 0, /* time to live exceeded in transit */
+ ICMP_TE_TTL = 0, /* time to live exceeded in transit */
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
};
diff --git a/core/lwip/src/include/ipv4/lwip/igmp.h b/core/lwip/src/include/ipv4/lwip/igmp.h
index 59c933f3..8aabac24 100644
--- a/core/lwip/src/include/ipv4/lwip/igmp.h
+++ b/core/lwip/src/include/ipv4/lwip/igmp.h
@@ -46,57 +46,20 @@
extern "C" {
#endif
-/*
- * IGMP constants
- */
-#define IP_PROTO_IGMP 2
-#define IGMP_TTL 1
-#define IGMP_MINLEN 8
-#define ROUTER_ALERT 0x9404
-#define ROUTER_ALERTLEN 4
-
-/*
- * IGMP message types, including version number.
- */
-#define IGMP_MEMB_QUERY 0x11 /* Membership query */
-#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */
-#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */
-#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */
/* IGMP timer */
#define IGMP_TMR_INTERVAL 100 /* Milliseconds */
#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL)
#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL)
-/* MAC Filter Actions */
+/* MAC Filter Actions, these are passed to a netif's
+ * igmp_mac_filter callback function. */
#define IGMP_DEL_MAC_FILTER 0
#define IGMP_ADD_MAC_FILTER 1
-/* Group membership states */
-#define IGMP_GROUP_NON_MEMBER 0
-#define IGMP_GROUP_DELAYING_MEMBER 1
-#define IGMP_GROUP_IDLE_MEMBER 2
-
-/*
- * IGMP packet format.
- */
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-struct igmp_msg {
- PACK_STRUCT_FIELD(u8_t igmp_msgtype);
- PACK_STRUCT_FIELD(u8_t igmp_maxresp);
- PACK_STRUCT_FIELD(u16_t igmp_checksum);
- PACK_STRUCT_FIELD(struct ip_addr igmp_group_address);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/epstruct.h"
-#endif
-/*
- * now a group structure - there is
+/**
+ * igmp group structure - there is
* a list of groups for each interface
* these should really be linked from the interface, but
* if we keep them separate we will not affect the lwip original code
@@ -106,53 +69,34 @@ PACK_STRUCT_END
* will not run the state machine as it is used to kick off reports
* from all the other groups
*/
-
struct igmp_group {
+ /** next link */
struct igmp_group *next;
- struct netif *interface;
- struct ip_addr group_address;
- u8_t last_reporter_flag; /* signifies we were the last person to report */
+ /** interface on which the group is active */
+ struct netif *netif;
+ /** multicast address */
+ ip_addr_t group_address;
+ /** signifies we were the last person to report */
+ u8_t last_reporter_flag;
+ /** current state of the group */
u8_t group_state;
+ /** timer for reporting, negative is OFF */
u16_t timer;
- u8_t use; /* counter of simultaneous uses */
+ /** counter of simultaneous uses */
+ u8_t use;
};
-
/* Prototypes */
void igmp_init(void);
-
-err_t igmp_start( struct netif *netif);
-
-err_t igmp_stop( struct netif *netif);
-
-void igmp_report_groups( struct netif *netif);
-
-struct igmp_group *igmp_lookfor_group( struct netif *ifp, struct ip_addr *addr);
-
-struct igmp_group *igmp_lookup_group( struct netif *ifp, struct ip_addr *addr);
-
-err_t igmp_remove_group( struct igmp_group *group);
-
-void igmp_input( struct pbuf *p, struct netif *inp, struct ip_addr *dest);
-
-err_t igmp_joingroup( struct ip_addr *ifaddr, struct ip_addr *groupaddr);
-
-err_t igmp_leavegroup( struct ip_addr *ifaddr, struct ip_addr *groupaddr);
-
+err_t igmp_start(struct netif *netif);
+err_t igmp_stop(struct netif *netif);
+void igmp_report_groups(struct netif *netif);
+struct igmp_group *igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr);
+void igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest);
+err_t igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr);
+err_t igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr);
void igmp_tmr(void);
-void igmp_timeout( struct igmp_group *group);
-
-void igmp_start_timer( struct igmp_group *group, u8_t max_time);
-
-void igmp_stop_timer( struct igmp_group *group);
-
-void igmp_delaying_member( struct igmp_group *group, u8_t maxresp);
-
-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);
-
-void igmp_send( struct igmp_group *group, u8_t type);
-
#ifdef __cplusplus
}
#endif
diff --git a/core/lwip/src/include/ipv4/lwip/inet.h b/core/lwip/src/include/ipv4/lwip/inet.h
index 7e801308..0513c740 100644
--- a/core/lwip/src/include/ipv4/lwip/inet.h
+++ b/core/lwip/src/include/ipv4/lwip/inet.h
@@ -33,66 +33,70 @@
#define __LWIP_INET_H__
#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "lwip/ip_addr.h"
#ifdef __cplusplus
extern "C" {
#endif
-/* For compatibility with BSD code */
+/** For compatibility with BSD code */
#include <netinet/in.h>
-#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! */
-
-#ifdef htons
-#undef htons
-#endif /* htons */
-#ifdef htonl
-#undef htonl
-#endif /* htonl */
-#ifdef ntohs
-#undef ntohs
-#endif /* ntohs */
-#ifdef ntohl
-#undef ntohl
-#endif /* ntohl */
-
-#ifndef LWIP_PLATFORM_BYTESWAP
-#define LWIP_PLATFORM_BYTESWAP 0
-#endif
+/** 255.255.255.255 */
+#define INADDR_NONE IPADDR_NONE
+/** 127.0.0.1 */
+#define INADDR_LOOPBACK IPADDR_LOOPBACK
+/** 0.0.0.0 */
+#define INADDR_ANY IPADDR_ANY
+/** 255.255.255.255 */
+#define INADDR_BROADCAST IPADDR_BROADCAST
+
+/* Definitions of the bits in an Internet address integer.
+
+ On subnets, host and network parts are found according to
+ the subnet mask, not these masks. */
+#define IN_CLASSA(a) IP_CLASSA(a)
+#define IN_CLASSA_NET IP_CLASSA_NET
+#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT
+#define IN_CLASSA_HOST IP_CLASSA_HOST
+#define IN_CLASSA_MAX IP_CLASSA_MAX
+
+#define IN_CLASSB(b) IP_CLASSB(b)
+#define IN_CLASSB_NET IP_CLASSB_NET
+#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT
+#define IN_CLASSB_HOST IP_CLASSB_HOST
+#define IN_CLASSB_MAX IP_CLASSB_MAX
+
+#define IN_CLASSC(c) IP_CLASSC(c)
+#define IN_CLASSC_NET IP_CLASSC_NET
+#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT
+#define IN_CLASSC_HOST IP_CLASSC_HOST
+#define IN_CLASSC_MAX IP_CLASSC_MAX
+
+#define IN_CLASSD(d) IP_CLASSD(d)
+#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */
+#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */
+#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */
+#define IN_CLASSD_MAX IP_CLASSD_MAX
+
+#define IN_MULTICAST(a) IP_MULTICAST(a)
+
+#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a)
+#define IN_BADCLASS(a) IP_BADCLASS(a)
+
+#define IN_LOOPBACKNET IP_LOOPBACKNET
+
+#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr))
+#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr))
+/* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */
+#define inet_addr_to_ipaddr_p(target_ipaddr_p, source_inaddr) ((target_ipaddr_p) = (ip_addr_t*)&((source_inaddr)->s_addr))
-#if BYTE_ORDER == BIG_ENDIAN
-#define htons(x) (x)
-#define ntohs(x) (x)
-#define htonl(x) (x)
-#define ntohl(x) (x)
-#else /* BYTE_ORDER != BIG_ENDIAN */
-#ifdef LWIP_PREFIX_BYTEORDER_FUNCS
-/* workaround for naming collisions on some platforms */
-#define htons lwip_htons
-#define ntohs lwip_ntohs
-#define htonl lwip_htonl
-#define ntohl lwip_ntohl
-#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */
-#if LWIP_PLATFORM_BYTESWAP
-#define htons(x) LWIP_PLATFORM_HTONS(x)
-#define ntohs(x) LWIP_PLATFORM_HTONS(x)
-#define htonl(x) LWIP_PLATFORM_HTONL(x)
-#define ntohl(x) LWIP_PLATFORM_HTONL(x)
-#else /* LWIP_PLATFORM_BYTESWAP */
-u16_t htons(u16_t x);
-u16_t ntohs(u16_t x);
-u32_t htonl(u32_t x);
-u32_t ntohl(u32_t x);
-#endif /* LWIP_PLATFORM_BYTESWAP */
-
-#endif /* BYTE_ORDER == BIG_ENDIAN */
+/* directly map this to the lwip internal functions */
+#define inet_addr(cp) ipaddr_addr(cp)
+#define inet_aton(cp, addr) ipaddr_aton(cp, (ip_addr_t*)addr)
+#define inet_ntoa(addr) ipaddr_ntoa((ip_addr_t*)&(addr))
+#define inet_ntoa_r(addr, buf, buflen) ipaddr_ntoa_r((ip_addr_t*)&(addr), buf, buflen)
#ifdef __cplusplus
}
diff --git a/core/lwip/src/include/ipv4/lwip/inet_chksum.h b/core/lwip/src/include/ipv4/lwip/inet_chksum.h
index 5cae59cb..79a2d90f 100644
--- a/core/lwip/src/include/ipv4/lwip/inet_chksum.h
+++ b/core/lwip/src/include/ipv4/lwip/inet_chksum.h
@@ -37,6 +37,35 @@
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
+/** Swap the bytes in an u16_t: much like htons() for little-endian */
+#ifndef SWAP_BYTES_IN_WORD
+#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 /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) */
+/* 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 /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)*/
+#endif /* SWAP_BYTES_IN_WORD */
+
+/** Split an u32_t in two u16_ts and add them up */
+#ifndef FOLD_U32T
+#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL))
+#endif
+
+#if LWIP_CHECKSUM_ON_COPY
+/** Function-like macro: same as MEMCPY but returns the checksum of copied data
+ as u16_t */
+#ifndef LWIP_CHKSUM_COPY
+#define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len)
+#ifndef LWIP_CHKSUM_COPY_ALGORITHM
+#define LWIP_CHKSUM_COPY_ALGORITHM 1
+#endif /* LWIP_CHKSUM_COPY_ALGORITHM */
+#endif /* LWIP_CHKSUM_COPY */
+#else /* LWIP_CHECKSUM_ON_COPY */
+#define LWIP_CHKSUM_COPY_ALGORITHM 0
+#endif /* LWIP_CHECKSUM_ON_COPY */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -44,13 +73,14 @@ extern "C" {
u16_t inet_chksum(void *dataptr, u16_t len);
u16_t inet_chksum_pbuf(struct pbuf *p);
u16_t inet_chksum_pseudo(struct pbuf *p,
- struct ip_addr *src, struct ip_addr *dest,
+ ip_addr_t *src, ip_addr_t *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,
+ ip_addr_t *src, ip_addr_t *dest,
u8_t proto, u16_t proto_len, u16_t chksum_len);
-#endif
+#if LWIP_CHKSUM_COPY_ALGORITHM
+u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len);
+#endif /* LWIP_CHKSUM_COPY_ALGORITHM */
#ifdef __cplusplus
}
diff --git a/core/lwip/src/include/ipv4/lwip/ip.h b/core/lwip/src/include/ipv4/lwip/ip.h
index fd84f304..74f501d1 100644
--- a/core/lwip/src/include/ipv4/lwip/ip.h
+++ b/core/lwip/src/include/ipv4/lwip/ip.h
@@ -50,6 +50,7 @@ extern "C" {
#define IP_HLEN 20
#define IP_PROTO_ICMP 1
+#define IP_PROTO_IGMP 2
#define IP_PROTO_UDP 17
#define IP_PROTO_UDPLITE 136
#define IP_PROTO_TCP 6
@@ -74,10 +75,10 @@ extern "C" {
having to change all PCB structs. */
#define IP_PCB \
/* ip addresses in network byte order */ \
- struct ip_addr local_ip; \
- struct ip_addr remote_ip; \
+ ip_addr_t local_ip; \
+ ip_addr_t remote_ip; \
/* Socket options */ \
- u16_t so_options; \
+ u8_t so_options; \
/* Type Of Service */ \
u8_t tos; \
/* Time To Live */ \
@@ -93,16 +94,19 @@ struct ip_pcb {
/*
* Option flags per-socket. These are the same like SO_XXX.
*/
-#define SOF_DEBUG (u16_t)0x0001U /* turn on debugging info recording */
-#define SOF_ACCEPTCONN (u16_t)0x0002U /* socket has had listen() */
-#define SOF_REUSEADDR (u16_t)0x0004U /* allow local address reuse */
-#define SOF_KEEPALIVE (u16_t)0x0008U /* keep connections alive */
-#define SOF_DONTROUTE (u16_t)0x0010U /* just use interface addresses */
-#define SOF_BROADCAST (u16_t)0x0020U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
-#define SOF_USELOOPBACK (u16_t)0x0040U /* bypass hardware when possible */
-#define SOF_LINGER (u16_t)0x0080U /* linger on close if data present */
-#define SOF_OOBINLINE (u16_t)0x0100U /* leave received OOB data in line */
-#define SOF_REUSEPORT (u16_t)0x0200U /* allow local address & port reuse */
+/*#define SOF_DEBUG (u8_t)0x01U Unimplemented: turn on debugging info recording */
+#define SOF_ACCEPTCONN (u8_t)0x02U /* socket has had listen() */
+#define SOF_REUSEADDR (u8_t)0x04U /* allow local address reuse */
+#define SOF_KEEPALIVE (u8_t)0x08U /* keep connections alive */
+/*#define SOF_DONTROUTE (u8_t)0x10U Unimplemented: just use interface addresses */
+#define SOF_BROADCAST (u8_t)0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
+/*#define SOF_USELOOPBACK (u8_t)0x40U Unimplemented: bypass hardware when possible */
+#define SOF_LINGER (u8_t)0x80U /* linger on close if data present */
+/*#define SOF_OOBINLINE (u16_t)0x0100U Unimplemented: leave received OOB data in line */
+/*#define SOF_REUSEPORT (u16_t)0x0200U Unimplemented: allow local address & port reuse */
+
+/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */
+#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE|SOF_LINGER/*|SOF_DEBUG|SOF_DONTROUTE|SOF_OOBINLINE*/)
#ifdef PACK_STRUCT_USE_INCLUDES
@@ -118,17 +122,19 @@ struct ip_hdr {
PACK_STRUCT_FIELD(u16_t _id);
/* fragment offset field */
PACK_STRUCT_FIELD(u16_t _offset);
-#define IP_RF 0x8000 /* reserved fragment flag */
-#define IP_DF 0x4000 /* dont fragment flag */
-#define IP_MF 0x2000 /* more fragments flag */
-#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
- /* time to live / protocol*/
- PACK_STRUCT_FIELD(u16_t _ttl_proto);
+#define IP_RF 0x8000U /* reserved fragment flag */
+#define IP_DF 0x4000U /* dont fragment flag */
+#define IP_MF 0x2000U /* more fragments flag */
+#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */
+ /* time to live */
+ PACK_STRUCT_FIELD(u8_t _ttl);
+ /* protocol*/
+ PACK_STRUCT_FIELD(u8_t _proto);
/* checksum */
PACK_STRUCT_FIELD(u16_t _chksum);
/* source and destination IP addresses */
- PACK_STRUCT_FIELD(struct ip_addr src);
- PACK_STRUCT_FIELD(struct ip_addr dest);
+ PACK_STRUCT_FIELD(ip_addr_p_t src);
+ PACK_STRUCT_FIELD(ip_addr_p_t dest);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
@@ -141,37 +147,41 @@ PACK_STRUCT_END
#define IPH_LEN(hdr) ((hdr)->_len)
#define IPH_ID(hdr) ((hdr)->_id)
#define IPH_OFFSET(hdr) ((hdr)->_offset)
-#define IPH_TTL(hdr) (ntohs((hdr)->_ttl_proto) >> 8)
-#define IPH_PROTO(hdr) (ntohs((hdr)->_ttl_proto) & 0xff)
+#define IPH_TTL(hdr) ((hdr)->_ttl)
+#define IPH_PROTO(hdr) ((hdr)->_proto)
#define IPH_CHKSUM(hdr) ((hdr)->_chksum)
#define IPH_VHLTOS_SET(hdr, v, hl, tos) (hdr)->_v_hl_tos = (htons(((v) << 12) | ((hl) << 8) | (tos)))
#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len)
#define IPH_ID_SET(hdr, id) (hdr)->_id = (id)
#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off)
-#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl_proto = (htons(IPH_PROTO(hdr) | ((u16_t)(ttl) << 8)))
-#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8)))
+#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl)
+#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto)
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
/** The interface that provided the packet for the current callback invocation. */
extern struct netif *current_netif;
/** Header of the input packet currently being processed. */
extern const struct ip_hdr *current_header;
+/** Source IP address of current_header */
+extern ip_addr_t current_iphdr_src;
+/** Destination IP address of current_header */
+extern ip_addr_t current_iphdr_dest;
#define ip_init() /* Compatibility define, not init needed. */
-struct netif *ip_route(struct ip_addr *dest);
+struct netif *ip_route(ip_addr_t *dest);
err_t ip_input(struct pbuf *p, struct netif *inp);
-err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
u8_t ttl, u8_t tos, u8_t proto);
-err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+err_t ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
u8_t ttl, u8_t tos, u8_t proto,
struct netif *netif);
#if LWIP_NETIF_HWADDRHINT
-err_t ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint);
#endif /* LWIP_NETIF_HWADDRHINT */
#if IP_OPTIONS_SEND
-err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
+err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
u16_t optlen);
#endif /* IP_OPTIONS_SEND */
@@ -183,6 +193,11 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
* This function must only be called from a receive callback (udp_recv,
* raw_recv, tcp_accept). It will return NULL otherwise. */
#define ip_current_header() (current_header)
+/** Source IP address of current_header */
+#define ip_current_src_addr() (&current_iphdr_src)
+/** Destination IP address of current_header */
+#define ip_current_dest_addr() (&current_iphdr_dest)
+
#if IP_DEBUG
void ip_debug_print(struct pbuf *p);
#else
diff --git a/core/lwip/src/include/ipv4/lwip/ip_addr.h b/core/lwip/src/include/ipv4/lwip/ip_addr.h
index 298e6576..77f84e02 100644
--- a/core/lwip/src/include/ipv4/lwip/ip_addr.h
+++ b/core/lwip/src/include/ipv4/lwip/ip_addr.h
@@ -33,18 +33,25 @@
#define __LWIP_IP_ADDR_H__
#include "lwip/opt.h"
-
-#include "lwip/inet.h"
+#include "lwip/def.h"
#ifdef __cplusplus
extern "C" {
#endif
+/* This is the aligned version of ip_addr_t,
+ used as local variable, on the stack, etc. */
+struct ip_addr {
+ u32_t addr;
+};
+
+/* This is the packed version of ip_addr_t,
+ used in network headers that are itself packed */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
-struct ip_addr {
+struct ip_addr_packed {
PACK_STRUCT_FIELD(u32_t addr);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
@@ -52,6 +59,11 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
+/** ip_addr_t uses a struct for convenience only, so that the same defines can
+ * operate both on ip_addr_t as well as on ip_addr_p_t. */
+typedef struct ip_addr ip_addr_t;
+typedef struct ip_addr_packed ip_addr_p_t;
+
/*
* struct ipaddr2 is used in the definition of the ARP packet format in
* order to support compilers that don't have structure packing.
@@ -68,59 +80,109 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
+/* Forward declaration to not include netif.h */
struct netif;
-extern const struct ip_addr ip_addr_any;
-extern const struct ip_addr ip_addr_broadcast;
+extern const ip_addr_t ip_addr_any;
+extern const ip_addr_t ip_addr_broadcast;
/** IP_ADDR_ can be used as a fixed IP address
* for the wildcard and the broadcast address
*/
-#define IP_ADDR_ANY ((struct ip_addr *)&ip_addr_any)
-#define IP_ADDR_BROADCAST ((struct ip_addr *)&ip_addr_broadcast)
+#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any)
+#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast)
+
+/** 255.255.255.255 */
+#define IPADDR_NONE ((u32_t)0xffffffffUL)
+/** 127.0.0.1 */
+#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL)
+/** 0.0.0.0 */
+#define IPADDR_ANY ((u32_t)0x00000000UL)
+/** 255.255.255.255 */
+#define IPADDR_BROADCAST ((u32_t)0xffffffffUL)
/* Definitions of the bits in an Internet address integer.
On subnets, host and network parts are found according to
the subnet mask, not these masks. */
+#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0)
+#define IP_CLASSA_NET 0xff000000
+#define IP_CLASSA_NSHIFT 24
+#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET)
+#define IP_CLASSA_MAX 128
-#define IN_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0)
-#define IN_CLASSA_NET 0xff000000
-#define IN_CLASSA_NSHIFT 24
-#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
-#define IN_CLASSA_MAX 128
+#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL)
+#define IP_CLASSB_NET 0xffff0000
+#define IP_CLASSB_NSHIFT 16
+#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET)
+#define IP_CLASSB_MAX 65536
-#define IN_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL)
-#define IN_CLASSB_NET 0xffff0000
-#define IN_CLASSB_NSHIFT 16
-#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
-#define IN_CLASSB_MAX 65536
+#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL)
+#define IP_CLASSC_NET 0xffffff00
+#define IP_CLASSC_NSHIFT 8
+#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET)
-#define IN_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL)
-#define IN_CLASSC_NET 0xffffff00
-#define IN_CLASSC_NSHIFT 8
-#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
+#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL)
+#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */
+#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */
+#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */
+#define IP_MULTICAST(a) IP_CLASSD(a)
-#define IN_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL)
-#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */
-#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */
-#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */
-#define IN_MULTICAST(a) IN_CLASSD(a)
+#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
+#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
-#define IN_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
-#define IN_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
+#define IP_LOOPBACKNET 127 /* official! */
-#define IN_LOOPBACKNET 127 /* official! */
+#if BYTE_ORDER == BIG_ENDIAN
+/** Set an IP address given by the four byte-parts */
+#define IP4_ADDR(ipaddr, a,b,c,d) \
+ (ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \
+ ((u32_t)((b) & 0xff) << 16) | \
+ ((u32_t)((c) & 0xff) << 8) | \
+ (u32_t)((d) & 0xff)
+#else
+/** Set an IP address given by the four byte-parts.
+ Little-endian version that prevents the use of htonl. */
#define IP4_ADDR(ipaddr, a,b,c,d) \
- (ipaddr)->addr = htonl(((u32_t)((a) & 0xff) << 24) | \
- ((u32_t)((b) & 0xff) << 16) | \
- ((u32_t)((c) & 0xff) << 8) | \
- (u32_t)((d) & 0xff))
-
-#define ip_addr_set(dest, src) (dest)->addr = \
- ((src) == NULL? 0:\
- (src)->addr)
+ (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \
+ ((u32_t)((c) & 0xff) << 16) | \
+ ((u32_t)((b) & 0xff) << 8) | \
+ (u32_t)((a) & 0xff)
+#endif
+
+/** MEMCPY-like copying of IP addresses where addresses are known to be
+ * 16-bit-aligned if the port is correctly configured (so a port could define
+ * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */
+#ifndef IPADDR2_COPY
+#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip_addr_t))
+#endif
+
+/** Copy IP address - faster than ip_addr_set: no NULL check */
+#define ip_addr_copy(dest, src) ((dest).addr = (src).addr)
+/** Safely copy one IP address to another (src may be NULL) */
+#define ip_addr_set(dest, src) ((dest)->addr = \
+ ((src) == NULL ? 0 : \
+ (src)->addr))
+/** Set complete address to zero */
+#define ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0)
+/** Set address to IPADDR_ANY (no need for htonl()) */
+#define ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY)
+/** Set address to loopback address */
+#define ip_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK))
+/** Safely copy one IP address to another and change byte order
+ * from host- to network-order. */
+#define ip_addr_set_hton(dest, src) ((dest)->addr = \
+ ((src) == NULL ? 0:\
+ htonl((src)->addr)))
+/** IPv4 only: set the IP address given as an u32_t */
+#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32))
+/** IPv4 only: get the IP address as an u32_t */
+#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr)
+
+/** Get the network address by combining host address with netmask */
+#define ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr))
+
/**
* Determine if two address are on the same network.
*
@@ -135,36 +197,45 @@ extern const struct ip_addr ip_addr_broadcast;
(mask)->addr))
#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr)
-#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0)
+#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == IPADDR_ANY)
-u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
+#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif))
+u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif);
-#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000UL)) == ntohl(0xe0000000UL))
+#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr)
+u8_t ip4_addr_netmask_valid(u32_t netmask);
-#define ip_addr_islinklocal(addr1) (((addr1)->addr & ntohl(0xffff0000UL)) == ntohl(0xa9fe0000UL))
+#define ip_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL))
-#define ip_addr_debug_print(debug, ipaddr) \
- LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
- ipaddr != NULL ? \
- (u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff : 0, \
- ipaddr != NULL ? \
- (u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff : 0, \
- ipaddr != NULL ? \
- (u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff : 0, \
- ipaddr != NULL ? \
- (u16_t)ntohl((ipaddr)->addr) & 0xff : 0))
+#define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL))
+#define ip_addr_debug_print(debug, ipaddr) \
+ LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
+ ipaddr != NULL ? ip4_addr1_16(ipaddr) : 0, \
+ ipaddr != NULL ? ip4_addr2_16(ipaddr) : 0, \
+ ipaddr != NULL ? ip4_addr3_16(ipaddr) : 0, \
+ ipaddr != NULL ? ip4_addr4_16(ipaddr) : 0))
+
+/* Get one byte from the 4-byte address */
+#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0])
+#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1])
+#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2])
+#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3])
/* These are cast to u16_t, with the intent that they are often arguments
* to printf using the U16_F format from cc.h. */
-#define ip4_addr1(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff)
-#define ip4_addr2(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff)
-#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
-#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff)
-
-/**
- * Same as inet_ntoa() but takes a struct ip_addr*
- */
-#define ip_ntoa(addr) ((addr != NULL) ? inet_ntoa(*((struct in_addr*)(addr))) : "NULL")
+#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr))
+#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr))
+#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr))
+#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr))
+
+/** For backwards compatibility */
+#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr)
+
+u32_t ipaddr_addr(const char *cp);
+int ipaddr_aton(const char *cp, ip_addr_t *addr);
+/** returns ptr to static buffer; not reentrant! */
+char *ipaddr_ntoa(const ip_addr_t *addr);
+char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen);
#ifdef __cplusplus
}
diff --git a/core/lwip/src/include/ipv4/lwip/ip_frag.h b/core/lwip/src/include/ipv4/lwip/ip_frag.h
index 380e604d..77b5eb1e 100644
--- a/core/lwip/src/include/ipv4/lwip/ip_frag.h
+++ b/core/lwip/src/include/ipv4/lwip/ip_frag.h
@@ -66,7 +66,19 @@ struct pbuf * ip_reass(struct pbuf *p);
#endif /* IP_REASSEMBLY */
#if IP_FRAG
-err_t ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest);
+#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
+/** A custom pbuf that holds a reference to another pbuf, which is freed
+ * when this custom pbuf is freed. This is used to create a custom PBUF_REF
+ * that points into the original pbuf. */
+struct pbuf_custom_ref {
+ /** 'base class' */
+ struct pbuf_custom pc;
+ /** pointer to the original pbuf that is referenced */
+ struct pbuf *original;
+};
+#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
+
+err_t ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest);
#endif /* IP_FRAG */
#ifdef __cplusplus
diff --git a/core/lwip/src/include/lwip/api.h b/core/lwip/src/include/lwip/api.h
index f6b1f743..91b9e5d2 100644
--- a/core/lwip/src/include/lwip/api.h
+++ b/core/lwip/src/include/lwip/api.h
@@ -51,16 +51,35 @@ extern "C" {
* the same byte order as in the corresponding pcb.
*/
-/* Flags for netconn_write */
-#define NETCONN_NOFLAG 0x00
-#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */
-#define NETCONN_COPY 0x01
-#define NETCONN_MORE 0x02
+/* Flags for netconn_write (u8_t) */
+#define NETCONN_NOFLAG 0x00
+#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */
+#define NETCONN_COPY 0x01
+#define NETCONN_MORE 0x02
+#define NETCONN_DONTBLOCK 0x04
+
+/* Flags for struct netconn.flags (u8_t) */
+/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
+ this temporarily stores whether to wake up the original application task
+ if data couldn't be sent in the first try. */
+#define NETCONN_FLAG_WRITE_DELAYED 0x01
+/** Should this netconn avoid blocking? */
+#define NETCONN_FLAG_NON_BLOCKING 0x02
+/** Was the last connect action a non-blocking one? */
+#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04
+/** If this is set, a TCP netconn must call netconn_recved() to update
+ the TCP receive window (done automatically if not set). */
+#define NETCONN_FLAG_NO_AUTO_RECVED 0x08
+/** If a nonblocking write has been rejected before, poll_tcp needs to
+ check if the netconn is writable again */
+#define NETCONN_FLAG_CHECK_WRITESPACE 0x10
+
/* Helpers to process several netconn_types by the same code */
#define NETCONNTYPE_GROUP(t) (t&0xF0)
#define NETCONNTYPE_DATAGRAM(t) (t&0xE0)
+/** Protocol family and type of the netconn */
enum netconn_type {
NETCONN_INVALID = 0,
/* NETCONN_TCP Group */
@@ -73,6 +92,8 @@ enum netconn_type {
NETCONN_RAW = 0x40
};
+/** Current state of the netconn. Non-TCP netconns are always
+ * in state NETCONN_NONE! */
enum netconn_state {
NETCONN_NONE,
NETCONN_WRITE,
@@ -81,14 +102,17 @@ enum netconn_state {
NETCONN_CLOSE
};
+/** Use to inform the callback function about changes */
enum netconn_evt {
NETCONN_EVT_RCVPLUS,
NETCONN_EVT_RCVMINUS,
NETCONN_EVT_SENDPLUS,
- NETCONN_EVT_SENDMINUS
+ NETCONN_EVT_SENDMINUS,
+ NETCONN_EVT_ERROR
};
#if LWIP_IGMP
+/** Used for netconn_join_leave_group() */
enum netconn_igmp {
NETCONN_JOIN,
NETCONN_LEAVE
@@ -101,6 +125,7 @@ struct tcp_pcb;
struct udp_pcb;
struct raw_pcb;
struct netconn;
+struct api_msg_msg;
/** A callback prototype to inform about events for a netconn */
typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len);
@@ -119,99 +144,136 @@ struct netconn {
struct raw_pcb *raw;
} pcb;
/** the last error this netconn had */
- err_t err;
+ err_t last_err;
/** sem that is used to synchroneously execute functions in the core context */
sys_sem_t op_completed;
/** mbox where received packets are stored until they are fetched
by the netconn application thread (can grow quite big) */
sys_mbox_t recvmbox;
+#if LWIP_TCP
/** mbox where new connections are stored until processed
by the application thread */
sys_mbox_t acceptmbox;
+#endif /* LWIP_TCP */
/** only used for socket layer */
+#if LWIP_SOCKET
int socket;
+#endif /* LWIP_SOCKET */
#if LWIP_SO_RCVTIMEO
/** timeout to wait for new data to be received
(or connections to arrive for listening netconns) */
int recv_timeout;
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
- /** maximum amount of bytes queued in recvmbox */
+ /** maximum amount of bytes queued in recvmbox
+ not used for TCP: adjust TCP_WND instead! */
int recv_bufsize;
-#endif /* LWIP_SO_RCVBUF */
+ /** number of bytes currently in recvmbox to be received,
+ tested against recv_bufsize to limit bytes on recvmbox
+ for UDP and RAW, used for FIONREAD */
s16_t recv_avail;
+#endif /* LWIP_SO_RCVBUF */
+ /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */
+ u8_t flags;
#if LWIP_TCP
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
- this temporarily stores the message. */
- struct api_msg_msg *write_msg;
- /** TCP: when data passed to netconn_write doesn't fit into the send buffer,
this temporarily stores how much is already sent. */
size_t write_offset;
-#if LWIP_TCPIP_CORE_LOCKING
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
- this temporarily stores whether to wake up the original application task
- if data couldn't be sent in the first try. */
- u8_t write_delayed;
-#endif /* LWIP_TCPIP_CORE_LOCKING */
+ this temporarily stores the message.
+ Also used during connect and close. */
+ struct api_msg_msg *current_msg;
#endif /* LWIP_TCP */
/** A callback function that is informed about events for this netconn */
netconn_callback callback;
};
-/* Register an Network connection event */
+/** Register an Network connection event */
#define API_EVENT(c,e,l) if (c->callback) { \
(*c->callback)(c, e, l); \
}
+/** Set conn->last_err to err but don't overwrite fatal errors */
+#define NETCONN_SET_SAFE_ERR(conn, err) do { \
+ SYS_ARCH_DECL_PROTECT(lev); \
+ SYS_ARCH_PROTECT(lev); \
+ if (!ERR_IS_FATAL((conn)->last_err)) { \
+ (conn)->last_err = err; \
+ } \
+ SYS_ARCH_UNPROTECT(lev); \
+} while(0);
+
/* Network connection functions: */
#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL)
#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c)
struct
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto,
- netconn_callback callback);
-err_t netconn_delete (struct netconn *conn);
+ netconn_callback callback);
+err_t netconn_delete(struct netconn *conn);
/** Get the type of a netconn (as enum netconn_type). */
#define netconn_type(conn) (conn->type)
-err_t netconn_getaddr (struct netconn *conn,
- struct ip_addr *addr,
- u16_t *port,
- u8_t local);
+err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr,
+ u16_t *port, u8_t local);
#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0)
#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1)
-err_t netconn_bind (struct netconn *conn,
- struct ip_addr *addr,
- u16_t port);
-err_t netconn_connect (struct netconn *conn,
- struct ip_addr *addr,
- u16_t port);
-err_t netconn_disconnect (struct netconn *conn);
-err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog);
+err_t netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port);
+err_t netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port);
+err_t netconn_disconnect (struct netconn *conn);
+err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog);
#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG)
-struct netconn * netconn_accept (struct netconn *conn);
-struct netbuf * netconn_recv (struct netconn *conn);
-err_t netconn_sendto (struct netconn *conn,
- struct netbuf *buf, struct ip_addr *addr, u16_t port);
-err_t netconn_send (struct netconn *conn,
- struct netbuf *buf);
-err_t netconn_write (struct netconn *conn,
- const void *dataptr, size_t size,
- u8_t apiflags);
-err_t netconn_close (struct netconn *conn);
+err_t netconn_accept(struct netconn *conn, struct netconn **new_conn);
+err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf);
+err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf);
+void netconn_recved(struct netconn *conn, u32_t length);
+err_t netconn_sendto(struct netconn *conn, struct netbuf *buf,
+ ip_addr_t *addr, u16_t port);
+err_t netconn_send(struct netconn *conn, struct netbuf *buf);
+err_t netconn_write(struct netconn *conn, const void *dataptr, size_t size,
+ u8_t apiflags);
+err_t netconn_close(struct netconn *conn);
+err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx);
#if LWIP_IGMP
-err_t netconn_join_leave_group (struct netconn *conn,
- struct ip_addr *multiaddr,
- struct ip_addr *interface,
- enum netconn_igmp join_or_leave);
+err_t netconn_join_leave_group(struct netconn *conn, ip_addr_t *multiaddr,
+ ip_addr_t *netif_addr, enum netconn_igmp join_or_leave);
#endif /* LWIP_IGMP */
#if LWIP_DNS
-err_t netconn_gethostbyname(const char *name, struct ip_addr *addr);
+err_t netconn_gethostbyname(const char *name, ip_addr_t *addr);
#endif /* LWIP_DNS */
-#define netconn_err(conn) ((conn)->err)
-#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
+#define netconn_err(conn) ((conn)->last_err)
+#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
+
+/** Set the blocking status of netconn calls (@todo: write/send is missing) */
+#define netconn_set_nonblocking(conn, val) do { if(val) { \
+ (conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \
+} else { \
+ (conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0)
+/** Get the blocking status of netconn calls (@todo: write/send is missing) */
+#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0)
+
+/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */
+#define netconn_set_noautorecved(conn, val) do { if(val) { \
+ (conn)->flags |= NETCONN_FLAG_NO_AUTO_RECVED; \
+} else { \
+ (conn)->flags &= ~ NETCONN_FLAG_NO_AUTO_RECVED; }} while(0)
+/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */
+#define netconn_get_noautorecved(conn) (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0)
+
+#if LWIP_SO_RCVTIMEO
+/** Set the receive timeout in milliseconds */
+#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout))
+/** Get the receive timeout in milliseconds */
+#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout)
+#endif /* LWIP_SO_RCVTIMEO */
+#if LWIP_SO_RCVBUF
+/** Set the receive buffer in bytes */
+#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize))
+/** Get the receive buffer in bytes */
+#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize)
+#endif /* LWIP_SO_RCVBUF*/
#ifdef __cplusplus
}
diff --git a/core/lwip/src/include/lwip/api_msg.h b/core/lwip/src/include/lwip/api_msg.h
index d3b04568..f99d8c3b 100644
--- a/core/lwip/src/include/lwip/api_msg.h
+++ b/core/lwip/src/include/lwip/api_msg.h
@@ -48,6 +48,11 @@
extern "C" {
#endif
+/* For the netconn API, these values are use as a bitmask! */
+#define NETCONN_SHUT_RD 1
+#define NETCONN_SHUT_WR 2
+#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR)
+
/* IP addresses and port numbers are expected to be in
* the same byte order as in the corresponding pcb.
*/
@@ -58,6 +63,8 @@ struct api_msg_msg {
/** The netconn which to process - always needed: it includes the semaphore
which is used to block the application thread until the function finished. */
struct netconn *conn;
+ /** The return value of the function executed in tcpip_thread. */
+ err_t err;
/** Depending on the executed function, one of these union members is used */
union {
/** used for do_send */
@@ -68,12 +75,12 @@ struct api_msg_msg {
} n;
/** used for do_bind and do_connect */
struct {
- struct ip_addr *ipaddr;
+ ip_addr_t *ipaddr;
u16_t port;
} bc;
/** used for do_getaddr */
struct {
- struct ip_addr *ipaddr;
+ ip_addr_t *ipaddr;
u16_t *port;
u8_t local;
} ad;
@@ -85,13 +92,17 @@ struct api_msg_msg {
} w;
/** used for do_recv */
struct {
- u16_t len;
+ u32_t len;
} r;
+ /** used for do_close (/shutdown) */
+ struct {
+ u8_t shut;
+ } sd;
#if LWIP_IGMP
/** used for do_join_leave_group */
struct {
- struct ip_addr *multiaddr;
- struct ip_addr *interface;
+ ip_addr_t *multiaddr;
+ ip_addr_t *netif_addr;
enum netconn_igmp join_or_leave;
} jl;
#endif /* LWIP_IGMP */
@@ -122,10 +133,10 @@ struct dns_api_msg {
/** Hostname to query or dotted IP address string */
const char *name;
/** Rhe resolved address is stored here */
- struct ip_addr *addr;
+ ip_addr_t *addr;
/** This semaphore is posted when the name is resolved, the application thread
should wait on it. */
- sys_sem_t sem;
+ sys_sem_t *sem;
/** Errors are given back here */
err_t *err;
};
@@ -142,6 +153,7 @@ void do_recv ( struct api_msg_msg *msg);
void do_write ( struct api_msg_msg *msg);
void do_getaddr ( struct api_msg_msg *msg);
void do_close ( struct api_msg_msg *msg);
+void do_shutdown ( struct api_msg_msg *msg);
#if LWIP_IGMP
void do_join_leave_group( struct api_msg_msg *msg);
#endif /* LWIP_IGMP */
diff --git a/core/lwip/src/include/lwip/arch.h b/core/lwip/src/include/lwip/arch.h
index 3a5a0e4f..524af6be 100644
--- a/core/lwip/src/include/lwip/arch.h
+++ b/core/lwip/src/include/lwip/arch.h
@@ -46,6 +46,11 @@
#ifndef SZT_F
#define SZT_F U32_F
#endif /* SZT_F */
+/** Temporary upgrade helper: define format string for u8_t as hex if not
+ defined in cc.h */
+#ifndef X8_F
+#define X8_F "02x"
+#endif /* X8_F */
#ifdef __cplusplus
extern "C" {
@@ -71,154 +76,154 @@ extern "C" {
#ifdef LWIP_PROVIDE_ERRNO
-#define EPERM 1 /* Operation not permitted */
-#define ENOENT 2 /* No such file or directory */
-#define ESRCH 3 /* No such process */
-#define EINTR 4 /* Interrupted system call */
-#define EIO 5 /* I/O error */
-#define ENXIO 6 /* No such device or address */
-#define E2BIG 7 /* Arg list too long */
-#define ENOEXEC 8 /* Exec format error */
-#define EBADF 9 /* Bad file number */
-#define ECHILD 10 /* No child processes */
-#define EAGAIN 11 /* Try again */
-#define ENOMEM 12 /* Out of memory */
-#define EACCES 13 /* Permission denied */
-#define EFAULT 14 /* Bad address */
-#define ENOTBLK 15 /* Block device required */
-#define EBUSY 16 /* Device or resource busy */
-#define EEXIST 17 /* File exists */
-#define EXDEV 18 /* Cross-device link */
-#define ENODEV 19 /* No such device */
-#define ENOTDIR 20 /* Not a directory */
-#define EISDIR 21 /* Is a directory */
-#define EINVAL 22 /* Invalid argument */
-#define ENFILE 23 /* File table overflow */
-#define EMFILE 24 /* Too many open files */
-#define ENOTTY 25 /* Not a typewriter */
-#define ETXTBSY 26 /* Text file busy */
-#define EFBIG 27 /* File too large */
-#define ENOSPC 28 /* No space left on device */
-#define ESPIPE 29 /* Illegal seek */
-#define EROFS 30 /* Read-only file system */
-#define EMLINK 31 /* Too many links */
-#define EPIPE 32 /* Broken pipe */
-#define EDOM 33 /* Math argument out of domain of func */
-#define ERANGE 34 /* Math result not representable */
-#define EDEADLK 35 /* Resource deadlock would occur */
-#define ENAMETOOLONG 36 /* File name too long */
-#define ENOLCK 37 /* No record locks available */
-#define ENOSYS 38 /* Function not implemented */
-#define ENOTEMPTY 39 /* Directory not empty */
-#define ELOOP 40 /* Too many symbolic links encountered */
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* I/O error */
+#define ENXIO 6 /* No such device or address */
+#define E2BIG 7 /* Arg list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file number */
+#define ECHILD 10 /* No child processes */
+#define EAGAIN 11 /* Try again */
+#define ENOMEM 12 /* Out of memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device or resource busy */
+#define EEXIST 17 /* File exists */
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* No such device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* File table overflow */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Not a typewriter */
+#define ETXTBSY 26 /* Text file busy */
+#define EFBIG 27 /* File too large */
+#define ENOSPC 28 /* No space left on device */
+#define ESPIPE 29 /* Illegal seek */
+#define EROFS 30 /* Read-only file system */
+#define EMLINK 31 /* Too many links */
+#define EPIPE 32 /* Broken pipe */
+#define EDOM 33 /* Math argument out of domain of func */
+#define ERANGE 34 /* Math result not representable */
+#define EDEADLK 35 /* Resource deadlock would occur */
+#define ENAMETOOLONG 36 /* File name too long */
+#define ENOLCK 37 /* No record locks available */
+#define ENOSYS 38 /* Function not implemented */
+#define ENOTEMPTY 39 /* Directory not empty */
+#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
-#define ENOMSG 42 /* No message of desired type */
-#define EIDRM 43 /* Identifier removed */
-#define ECHRNG 44 /* Channel number out of range */
-#define EL2NSYNC 45 /* Level 2 not synchronized */
-#define EL3HLT 46 /* Level 3 halted */
-#define EL3RST 47 /* Level 3 reset */
-#define ELNRNG 48 /* Link number out of range */
-#define EUNATCH 49 /* Protocol driver not attached */
-#define ENOCSI 50 /* No CSI structure available */
-#define EL2HLT 51 /* Level 2 halted */
-#define EBADE 52 /* Invalid exchange */
-#define EBADR 53 /* Invalid request descriptor */
-#define EXFULL 54 /* Exchange full */
-#define ENOANO 55 /* No anode */
-#define EBADRQC 56 /* Invalid request code */
-#define EBADSLT 57 /* Invalid slot */
-
-#define EDEADLOCK EDEADLK
-
-#define EBFONT 59 /* Bad font file format */
-#define ENOSTR 60 /* Device not a stream */
-#define ENODATA 61 /* No data available */
-#define ETIME 62 /* Timer expired */
-#define ENOSR 63 /* Out of streams resources */
-#define ENONET 64 /* Machine is not on the network */
-#define ENOPKG 65 /* Package not installed */
-#define EREMOTE 66 /* Object is remote */
-#define ENOLINK 67 /* Link has been severed */
-#define EADV 68 /* Advertise error */
-#define ESRMNT 69 /* Srmount error */
-#define ECOMM 70 /* Communication error on send */
-#define EPROTO 71 /* Protocol error */
-#define EMULTIHOP 72 /* Multihop attempted */
-#define EDOTDOT 73 /* RFS specific error */
-#define EBADMSG 74 /* Not a data message */
-#define EOVERFLOW 75 /* Value too large for defined data type */
-#define ENOTUNIQ 76 /* Name not unique on network */
-#define EBADFD 77 /* File descriptor in bad state */
-#define EREMCHG 78 /* Remote address changed */
-#define ELIBACC 79 /* Can not access a needed shared library */
-#define ELIBBAD 80 /* Accessing a corrupted shared library */
-#define ELIBSCN 81 /* .lib section in a.out corrupted */
-#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
-#define ELIBEXEC 83 /* Cannot exec a shared library directly */
-#define EILSEQ 84 /* Illegal byte sequence */
-#define ERESTART 85 /* Interrupted system call should be restarted */
-#define ESTRPIPE 86 /* Streams pipe error */
-#define EUSERS 87 /* Too many users */
-#define ENOTSOCK 88 /* Socket operation on non-socket */
-#define EDESTADDRREQ 89 /* Destination address required */
-#define EMSGSIZE 90 /* Message too long */
-#define EPROTOTYPE 91 /* Protocol wrong type for socket */
+#define ENOMSG 42 /* No message of desired type */
+#define EIDRM 43 /* Identifier removed */
+#define ECHRNG 44 /* Channel number out of range */
+#define EL2NSYNC 45 /* Level 2 not synchronized */
+#define EL3HLT 46 /* Level 3 halted */
+#define EL3RST 47 /* Level 3 reset */
+#define ELNRNG 48 /* Link number out of range */
+#define EUNATCH 49 /* Protocol driver not attached */
+#define ENOCSI 50 /* No CSI structure available */
+#define EL2HLT 51 /* Level 2 halted */
+#define EBADE 52 /* Invalid exchange */
+#define EBADR 53 /* Invalid request descriptor */
+#define EXFULL 54 /* Exchange full */
+#define ENOANO 55 /* No anode */
+#define EBADRQC 56 /* Invalid request code */
+#define EBADSLT 57 /* Invalid slot */
+
+#define EDEADLOCK EDEADLK
+
+#define EBFONT 59 /* Bad font file format */
+#define ENOSTR 60 /* Device not a stream */
+#define ENODATA 61 /* No data available */
+#define ETIME 62 /* Timer expired */
+#define ENOSR 63 /* Out of streams resources */
+#define ENONET 64 /* Machine is not on the network */
+#define ENOPKG 65 /* Package not installed */
+#define EREMOTE 66 /* Object is remote */
+#define ENOLINK 67 /* Link has been severed */
+#define EADV 68 /* Advertise error */
+#define ESRMNT 69 /* Srmount error */
+#define ECOMM 70 /* Communication error on send */
+#define EPROTO 71 /* Protocol error */
+#define EMULTIHOP 72 /* Multihop attempted */
+#define EDOTDOT 73 /* RFS specific error */
+#define EBADMSG 74 /* Not a data message */
+#define EOVERFLOW 75 /* Value too large for defined data type */
+#define ENOTUNIQ 76 /* Name not unique on network */
+#define EBADFD 77 /* File descriptor in bad state */
+#define EREMCHG 78 /* Remote address changed */
+#define ELIBACC 79 /* Can not access a needed shared library */
+#define ELIBBAD 80 /* Accessing a corrupted shared library */
+#define ELIBSCN 81 /* .lib section in a.out corrupted */
+#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
+#define ELIBEXEC 83 /* Cannot exec a shared library directly */
+#define EILSEQ 84 /* Illegal byte sequence */
+#define ERESTART 85 /* Interrupted system call should be restarted */
+#define ESTRPIPE 86 /* Streams pipe error */
+#define EUSERS 87 /* Too many users */
+#define ENOTSOCK 88 /* Socket operation on non-socket */
+#define EDESTADDRREQ 89 /* Destination address required */
+#define EMSGSIZE 90 /* Message too long */
+#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
-#define EPROTONOSUPPORT 93 /* Protocol not supported */
-#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
-#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
-#define EPFNOSUPPORT 96 /* Protocol family not supported */
-#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
-#define EADDRINUSE 98 /* Address already in use */
-#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
-#define ENETDOWN 100 /* Network is down */
-#define ENETUNREACH 101 /* Network is unreachable */
-#define ENETRESET 102 /* Network dropped connection because of reset */
-#define ECONNABORTED 103 /* Software caused connection abort */
-#define ECONNRESET 104 /* Connection reset by peer */
-#define ENOBUFS 105 /* No buffer space available */
-#define EISCONN 106 /* Transport endpoint is already connected */
-#define ENOTCONN 107 /* Transport endpoint is not connected */
-#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
-#define ETOOMANYREFS 109 /* Too many references: cannot splice */
-#define ETIMEDOUT 110 /* Connection timed out */
-#define ECONNREFUSED 111 /* Connection refused */
-#define EHOSTDOWN 112 /* Host is down */
-#define EHOSTUNREACH 113 /* No route to host */
-#define EALREADY 114 /* Operation already in progress */
-#define EINPROGRESS 115 /* Operation now in progress */
-#define ESTALE 116 /* Stale NFS file handle */
-#define EUCLEAN 117 /* Structure needs cleaning */
-#define ENOTNAM 118 /* Not a XENIX named type file */
-#define ENAVAIL 119 /* No XENIX semaphores available */
-#define EISNAM 120 /* Is a named type file */
-#define EREMOTEIO 121 /* Remote I/O error */
-#define EDQUOT 122 /* Quota exceeded */
-
-#define ENOMEDIUM 123 /* No medium found */
-#define EMEDIUMTYPE 124 /* Wrong medium type */
-
-
-#define ENSROK 0 /* DNS server returned answer with no data */
-#define ENSRNODATA 160 /* DNS server returned answer with no data */
-#define ENSRFORMERR 161 /* DNS server claims query was misformatted */
-#define ENSRSERVFAIL 162 /* DNS server returned general failure */
-#define ENSRNOTFOUND 163 /* Domain name not found */
-#define ENSRNOTIMP 164 /* DNS server does not implement requested operation */
-#define ENSRREFUSED 165 /* DNS server refused query */
-#define ENSRBADQUERY 166 /* Misformatted DNS query */
-#define ENSRBADNAME 167 /* Misformatted domain name */
-#define ENSRBADFAMILY 168 /* Unsupported address family */
-#define ENSRBADRESP 169 /* Misformatted DNS reply */
-#define ENSRCONNREFUSED 170 /* Could not contact DNS servers */
-#define ENSRTIMEOUT 171 /* Timeout while contacting DNS servers */
-#define ENSROF 172 /* End of file */
-#define ENSRFILE 173 /* Error reading file */
-#define ENSRNOMEM 174 /* Out of memory */
-#define ENSRDESTRUCTION 175 /* Application terminated lookup */
+#define EPROTONOSUPPORT 93 /* Protocol not supported */
+#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
+#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define EPFNOSUPPORT 96 /* Protocol family not supported */
+#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
+#define EADDRINUSE 98 /* Address already in use */
+#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define ENETDOWN 100 /* Network is down */
+#define ENETUNREACH 101 /* Network is unreachable */
+#define ENETRESET 102 /* Network dropped connection because of reset */
+#define ECONNABORTED 103 /* Software caused connection abort */
+#define ECONNRESET 104 /* Connection reset by peer */
+#define ENOBUFS 105 /* No buffer space available */
+#define EISCONN 106 /* Transport endpoint is already connected */
+#define ENOTCONN 107 /* Transport endpoint is not connected */
+#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
+#define ETOOMANYREFS 109 /* Too many references: cannot splice */
+#define ETIMEDOUT 110 /* Connection timed out */
+#define ECONNREFUSED 111 /* Connection refused */
+#define EHOSTDOWN 112 /* Host is down */
+#define EHOSTUNREACH 113 /* No route to host */
+#define EALREADY 114 /* Operation already in progress */
+#define EINPROGRESS 115 /* Operation now in progress */
+#define ESTALE 116 /* Stale NFS file handle */
+#define EUCLEAN 117 /* Structure needs cleaning */
+#define ENOTNAM 118 /* Not a XENIX named type file */
+#define ENAVAIL 119 /* No XENIX semaphores available */
+#define EISNAM 120 /* Is a named type file */
+#define EREMOTEIO 121 /* Remote I/O error */
+#define EDQUOT 122 /* Quota exceeded */
+
+#define ENOMEDIUM 123 /* No medium found */
+#define EMEDIUMTYPE 124 /* Wrong medium type */
+
+
+#define ENSROK 0 /* DNS server returned answer with no data */
+#define ENSRNODATA 160 /* DNS server returned answer with no data */
+#define ENSRFORMERR 161 /* DNS server claims query was misformatted */
+#define ENSRSERVFAIL 162 /* DNS server returned general failure */
+#define ENSRNOTFOUND 163 /* Domain name not found */
+#define ENSRNOTIMP 164 /* DNS server does not implement requested operation */
+#define ENSRREFUSED 165 /* DNS server refused query */
+#define ENSRBADQUERY 166 /* Misformatted DNS query */
+#define ENSRBADNAME 167 /* Misformatted domain name */
+#define ENSRBADFAMILY 168 /* Unsupported address family */
+#define ENSRBADRESP 169 /* Misformatted DNS reply */
+#define ENSRCONNREFUSED 170 /* Could not contact DNS servers */
+#define ENSRTIMEOUT 171 /* Timeout while contacting DNS servers */
+#define ENSROF 172 /* End of file */
+#define ENSRFILE 173 /* Error reading file */
+#define ENSRNOMEM 174 /* Out of memory */
+#define ENSRDESTRUCTION 175 /* Application terminated lookup */
#define ENSRQUERYDOMAINTOOLONG 176 /* Domain name is too long */
-#define ENSRCNAMELOOP 177 /* Domain name is too long */
+#define ENSRCNAMELOOP 177 /* Domain name is too long */
#ifndef errno
extern int errno;
diff --git a/core/lwip/src/include/lwip/def.h b/core/lwip/src/include/lwip/def.h
index d2ed251d..9b6de6a8 100644
--- a/core/lwip/src/include/lwip/def.h
+++ b/core/lwip/src/include/lwip/def.h
@@ -32,8 +32,13 @@
#ifndef __LWIP_DEF_H__
#define __LWIP_DEF_H__
-/* this might define NULL already */
+/* arch.h might define NULL already */
#include "lwip/arch.h"
+#include "lwip/opt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y))
#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y))
@@ -42,6 +47,81 @@
#define NULL ((void *)0)
#endif
+/** Get the absolute difference between 2 u32_t values (correcting overflows)
+ * 'a' is expected to be 'higher' (without overflow) than 'b'. */
+#define LWIP_U32_DIFF(a, b) (((a) >= (b)) ? ((a) - (b)) : (((a) + ((b) ^ 0xFFFFFFFF) + 1)))
+
+/* Endianess-optimized shifting of two u8_t to create one u16_t */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define LWIP_MAKE_U16(a, b) ((a << 8) | b)
+#else
+#define LWIP_MAKE_U16(a, b) ((b << 8) | a)
+#endif
+
+#ifndef LWIP_PLATFORM_BYTESWAP
+#define LWIP_PLATFORM_BYTESWAP 0
+#endif
+
+#ifndef LWIP_PREFIX_BYTEORDER_FUNCS
+/* workaround for naming collisions on some platforms */
+
+#ifdef htons
+#undef htons
+#endif /* htons */
+#ifdef htonl
+#undef htonl
+#endif /* htonl */
+#ifdef ntohs
+#undef ntohs
+#endif /* ntohs */
+#ifdef ntohl
+#undef ntohl
+#endif /* ntohl */
+
+#define htons(x) lwip_htons(x)
+#define ntohs(x) lwip_ntohs(x)
+#define htonl(x) lwip_htonl(x)
+#define ntohl(x) lwip_ntohl(x)
+#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define lwip_htons(x) (x)
+#define lwip_ntohs(x) (x)
+#define lwip_htonl(x) (x)
+#define lwip_ntohl(x) (x)
+#define PP_HTONS(x) (x)
+#define PP_NTOHS(x) (x)
+#define PP_HTONL(x) (x)
+#define PP_NTOHL(x) (x)
+#else /* BYTE_ORDER != BIG_ENDIAN */
+#if LWIP_PLATFORM_BYTESWAP
+#define lwip_htons(x) LWIP_PLATFORM_HTONS(x)
+#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x)
+#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x)
+#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x)
+#else /* LWIP_PLATFORM_BYTESWAP */
+u16_t lwip_htons(u16_t x);
+u16_t lwip_ntohs(u16_t x);
+u32_t lwip_htonl(u32_t x);
+u32_t lwip_ntohl(u32_t x);
+#endif /* LWIP_PLATFORM_BYTESWAP */
+
+/* These macros should be calculated by the preprocessor and are used
+ with compile-time constants only (so that there is no little-endian
+ overhead at runtime). */
+#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
+#define PP_NTOHS(x) PP_HTONS(x)
+#define PP_HTONL(x) ((((x) & 0xff) << 24) | \
+ (((x) & 0xff00) << 8) | \
+ (((x) & 0xff0000UL) >> 8) | \
+ (((x) & 0xff000000UL) >> 24))
+#define PP_NTOHL(x) PP_HTONL(x)
+
+#endif /* BYTE_ORDER == BIG_ENDIAN */
+
+#ifdef __cplusplus
+}
+#endif
#endif /* __LWIP_DEF_H__ */
diff --git a/core/lwip/src/include/lwip/dhcp.h b/core/lwip/src/include/lwip/dhcp.h
index db37e884..32d93381 100644
--- a/core/lwip/src/include/lwip/dhcp.h
+++ b/core/lwip/src/include/lwip/dhcp.h
@@ -22,6 +22,10 @@ extern "C" {
/** period (in milliseconds) of the application calling dhcp_fine_tmr() */
#define DHCP_FINE_TIMER_MSECS 500
+#define DHCP_CHADDR_LEN 16U
+#define DHCP_SNAME_LEN 64U
+#define DHCP_FILE_LEN 128U
+
struct dhcp
{
/** transaction identifier of last sent request */
@@ -30,14 +34,14 @@ struct dhcp
struct udp_pcb *pcb;
/** incoming msg */
struct dhcp_msg *msg_in;
- /** incoming msg options */
- void *options_in;
- /** ingoing msg options length */
- u16_t options_in_len;
/** current DHCP state machine state */
u8_t state;
/** retries of current request */
u8_t tries;
+#if LWIP_DHCP_AUTOIP_COOP
+ u8_t autoip_coop_state;
+#endif
+ u8_t subnet_mask_given;
struct pbuf *p_out; /* pbuf of outcoming msg */
struct dhcp_msg *msg_out; /* outgoing msg */
@@ -45,28 +49,20 @@ struct dhcp
u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */
u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */
u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */
- struct ip_addr server_ip_addr; /* dhcp server address that offered this lease */
- struct ip_addr offered_ip_addr;
- struct ip_addr offered_sn_mask;
- struct ip_addr offered_gw_addr;
- struct ip_addr offered_bc_addr;
-#define DHCP_MAX_DNS 2
- u32_t dns_count; /* actual number of DNS servers obtained */
- struct ip_addr offered_dns_addr[DHCP_MAX_DNS]; /* DNS server addresses */
+ ip_addr_t server_ip_addr; /* dhcp server address that offered this lease */
+ ip_addr_t offered_ip_addr;
+ ip_addr_t offered_sn_mask;
+ ip_addr_t offered_gw_addr;
u32_t offered_t0_lease; /* lease period (in seconds) */
u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */
-#if LWIP_DHCP_AUTOIP_COOP
- u8_t autoip_coop_state;
-#endif
-/** Patch #1308
- * TODO: See dhcp.c "TODO"s
- */
-#if 0
- struct ip_addr offered_si_addr;
- u8_t *boot_file_name;
-#endif
+ /* @todo: LWIP_DHCP_BOOTP_FILE configuration option?
+ integrate with possible TFTP-client for booting? */
+#if LWIP_DHCP_BOOTP_FILE
+ ip_addr_t offered_si_addr;
+ char boot_file_name[DHCP_FILE_LEN];
+#endif /* LWIP_DHCP_BOOTPFILE */
};
/* MUST be compiled with "pack structs" or equivalent! */
@@ -84,15 +80,12 @@ struct dhcp_msg
PACK_STRUCT_FIELD(u32_t xid);
PACK_STRUCT_FIELD(u16_t secs);
PACK_STRUCT_FIELD(u16_t flags);
- PACK_STRUCT_FIELD(struct ip_addr ciaddr);
- PACK_STRUCT_FIELD(struct ip_addr yiaddr);
- PACK_STRUCT_FIELD(struct ip_addr siaddr);
- PACK_STRUCT_FIELD(struct ip_addr giaddr);
-#define DHCP_CHADDR_LEN 16U
+ PACK_STRUCT_FIELD(ip_addr_p_t ciaddr);
+ PACK_STRUCT_FIELD(ip_addr_p_t yiaddr);
+ PACK_STRUCT_FIELD(ip_addr_p_t siaddr);
+ PACK_STRUCT_FIELD(ip_addr_p_t giaddr);
PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]);
-#define DHCP_SNAME_LEN 64U
PACK_STRUCT_FIELD(u8_t sname[DHCP_SNAME_LEN]);
-#define DHCP_FILE_LEN 128U
PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]);
PACK_STRUCT_FIELD(u32_t cookie);
#define DHCP_MIN_OPTIONS_LEN 68U
@@ -112,6 +105,10 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
+void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
+/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */
+#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0)
+void dhcp_cleanup(struct netif *netif);
/** start DHCP configuration */
err_t dhcp_start(struct netif *netif);
/** enforce early lease renewal (not needed normally)*/
@@ -127,7 +124,7 @@ void dhcp_network_changed(struct netif *netif);
/** if enabled, check whether the offered IP address is not in use, using ARP */
#if DHCP_DOES_ARP_CHECK
-void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr);
+void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr);
#endif
/** to be called every minute */
@@ -136,66 +133,66 @@ void dhcp_coarse_tmr(void);
void dhcp_fine_tmr(void);
/** DHCP message item offsets and length */
-#define DHCP_MSG_OFS (UDP_DATA_OFS)
- #define DHCP_OP_OFS (DHCP_MSG_OFS + 0)
- #define DHCP_HTYPE_OFS (DHCP_MSG_OFS + 1)
- #define DHCP_HLEN_OFS (DHCP_MSG_OFS + 2)
- #define DHCP_HOPS_OFS (DHCP_MSG_OFS + 3)
- #define DHCP_XID_OFS (DHCP_MSG_OFS + 4)
- #define DHCP_SECS_OFS (DHCP_MSG_OFS + 8)
- #define DHCP_FLAGS_OFS (DHCP_MSG_OFS + 10)
- #define DHCP_CIADDR_OFS (DHCP_MSG_OFS + 12)
- #define DHCP_YIADDR_OFS (DHCP_MSG_OFS + 16)
- #define DHCP_SIADDR_OFS (DHCP_MSG_OFS + 20)
- #define DHCP_GIADDR_OFS (DHCP_MSG_OFS + 24)
- #define DHCP_CHADDR_OFS (DHCP_MSG_OFS + 28)
- #define DHCP_SNAME_OFS (DHCP_MSG_OFS + 44)
- #define DHCP_FILE_OFS (DHCP_MSG_OFS + 108)
-#define DHCP_MSG_LEN 236
-
-#define DHCP_COOKIE_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN)
-#define DHCP_OPTIONS_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN + 4)
-
-#define DHCP_CLIENT_PORT 68
-#define DHCP_SERVER_PORT 67
+#define DHCP_OP_OFS 0
+#define DHCP_HTYPE_OFS 1
+#define DHCP_HLEN_OFS 2
+#define DHCP_HOPS_OFS 3
+#define DHCP_XID_OFS 4
+#define DHCP_SECS_OFS 8
+#define DHCP_FLAGS_OFS 10
+#define DHCP_CIADDR_OFS 12
+#define DHCP_YIADDR_OFS 16
+#define DHCP_SIADDR_OFS 20
+#define DHCP_GIADDR_OFS 24
+#define DHCP_CHADDR_OFS 28
+#define DHCP_SNAME_OFS 44
+#define DHCP_FILE_OFS 108
+#define DHCP_MSG_LEN 236
+
+#define DHCP_COOKIE_OFS DHCP_MSG_LEN
+#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4)
+
+#define DHCP_CLIENT_PORT 68
+#define DHCP_SERVER_PORT 67
/** DHCP client states */
-#define DHCP_REQUESTING 1
-#define DHCP_INIT 2
-#define DHCP_REBOOTING 3
-#define DHCP_REBINDING 4
-#define DHCP_RENEWING 5
-#define DHCP_SELECTING 6
-#define DHCP_INFORMING 7
-#define DHCP_CHECKING 8
-#define DHCP_PERMANENT 9
-#define DHCP_BOUND 10
+#define DHCP_OFF 0
+#define DHCP_REQUESTING 1
+#define DHCP_INIT 2
+#define DHCP_REBOOTING 3
+#define DHCP_REBINDING 4
+#define DHCP_RENEWING 5
+#define DHCP_SELECTING 6
+#define DHCP_INFORMING 7
+#define DHCP_CHECKING 8
+#define DHCP_PERMANENT 9
+#define DHCP_BOUND 10
/** not yet implemented #define DHCP_RELEASING 11 */
-#define DHCP_BACKING_OFF 12
-#define DHCP_OFF 13
+#define DHCP_BACKING_OFF 12
/** AUTOIP cooperatation flags */
-#define DHCP_AUTOIP_COOP_STATE_OFF 0
-#define DHCP_AUTOIP_COOP_STATE_ON 1
+#define DHCP_AUTOIP_COOP_STATE_OFF 0
+#define DHCP_AUTOIP_COOP_STATE_ON 1
-#define DHCP_BOOTREQUEST 1
-#define DHCP_BOOTREPLY 2
+#define DHCP_BOOTREQUEST 1
+#define DHCP_BOOTREPLY 2
+/** DHCP message types */
#define DHCP_DISCOVER 1
-#define DHCP_OFFER 2
-#define DHCP_REQUEST 3
-#define DHCP_DECLINE 4
-#define DHCP_ACK 5
-#define DHCP_NAK 6
-#define DHCP_RELEASE 7
-#define DHCP_INFORM 8
-
+#define DHCP_OFFER 2
+#define DHCP_REQUEST 3
+#define DHCP_DECLINE 4
+#define DHCP_ACK 5
+#define DHCP_NAK 6
+#define DHCP_RELEASE 7
+#define DHCP_INFORM 8
+
+/** DHCP hardware type, currently only ethernet is supported */
#define DHCP_HTYPE_ETH 1
-#define DHCP_HLEN_ETH 6
+#define DHCP_MAGIC_COOKIE 0x63825363UL
-#define DHCP_BROADCAST_FLAG 15
-#define DHCP_BROADCAST_MASK (1 << DHCP_FLAG_BROADCAST)
+/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */
/** BootP options */
#define DHCP_OPTION_PAD 0
@@ -217,7 +214,6 @@ void dhcp_fine_tmr(void);
#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */
#define DHCP_OPTION_MESSAGE_TYPE_LEN 1
-
#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */
#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */
diff --git a/core/lwip/src/include/lwip/dns.h b/core/lwip/src/include/lwip/dns.h
index e5f4b7a3..6c7d9b07 100644
--- a/core/lwip/src/include/lwip/dns.h
+++ b/core/lwip/src/include/lwip/dns.h
@@ -38,6 +38,10 @@
#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/** DNS timer period */
#define DNS_TMR_INTERVAL 1000
@@ -66,32 +70,55 @@
#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */
#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */
+/* The size used for the next line is rather a hack, but it prevents including socket.h in all files
+ that include memp.h, and that would possibly break portability (since socket.h defines some types
+ and constants possibly already define by the OS).
+ Calculation rule:
+ sizeof(struct addrinfo) + sizeof(struct sockaddr_in) + DNS_MAX_NAME_LENGTH + 1 byte zero-termination */
+#define NETDB_ELEM_SIZE (32 + 16 + DNS_MAX_NAME_LENGTH + 1)
+
+#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 */
+ ip_addr_t addr;
+ struct local_hostlist_entry *next;
+};
+#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN
+#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH
+#endif
+#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1))
+#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+#endif /* DNS_LOCAL_HOSTLIST */
+
/** Callback which is invoked when a hostname is found.
* A function of this type must be implemented by the application using the DNS resolver.
* @param name pointer to the name that was looked up.
- * @param ipaddr pointer to a struct ip_addr containing the IP address of the hostname,
+ * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname,
* or NULL if the name could not be found (or on any other error).
* @param callback_arg a user-specified callback argument passed to dns_gethostbyname
*/
-typedef void (*dns_found_callback)(const char *name, struct ip_addr *ipaddr, void *callback_arg);
-
+typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg);
void dns_init(void);
-
void dns_tmr(void);
-
-void dns_setserver(u8_t numdns, struct ip_addr *dnsserver);
-
-struct ip_addr dns_getserver(u8_t numdns);
-
-err_t dns_gethostbyname(const char *hostname, struct ip_addr *addr,
+void dns_setserver(u8_t numdns, ip_addr_t *dnsserver);
+ip_addr_t dns_getserver(u8_t numdns);
+err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr,
dns_found_callback found, void *callback_arg);
#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-int dns_local_removehost(const char *hostname, const struct ip_addr *addr);
-err_t dns_local_addhost(const char *hostname, const struct ip_addr *addr);
+int dns_local_removehost(const char *hostname, const ip_addr_t *addr);
+err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr);
#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+#ifdef __cplusplus
+}
+#endif
+
#endif /* LWIP_DNS */
#endif /* __LWIP_DNS_H__ */
diff --git a/core/lwip/src/include/lwip/err.h b/core/lwip/src/include/lwip/err.h
index 69676445..ac907729 100644
--- a/core/lwip/src/include/lwip/err.h
+++ b/core/lwip/src/include/lwip/err.h
@@ -44,7 +44,7 @@ extern "C" {
#ifdef LWIP_ERR_T
typedef LWIP_ERR_T err_t;
#else /* LWIP_ERR_T */
- typedef s8_t err_t;
+typedef s8_t err_t;
#endif /* LWIP_ERR_T*/
/* Definitions for error constants. */
@@ -54,24 +54,22 @@ typedef LWIP_ERR_T err_t;
#define ERR_BUF -2 /* Buffer error. */
#define ERR_TIMEOUT -3 /* Timeout. */
#define ERR_RTE -4 /* Routing problem. */
+#define ERR_INPROGRESS -5 /* Operation in progress */
+#define ERR_VAL -6 /* Illegal value. */
+#define ERR_WOULDBLOCK -7 /* Operation would block. */
+#define ERR_USE -8 /* Address in use. */
+#define ERR_ISCONN -9 /* Already connected. */
-#define ERR_IS_FATAL(e) ((e) < ERR_RTE)
+#define ERR_IS_FATAL(e) ((e) < ERR_ISCONN)
-#define ERR_ABRT -5 /* Connection aborted. */
-#define ERR_RST -6 /* Connection reset. */
-#define ERR_CLSD -7 /* Connection closed. */
-#define ERR_CONN -8 /* Not connected. */
+#define ERR_ABRT -10 /* Connection aborted. */
+#define ERR_RST -11 /* Connection reset. */
+#define ERR_CLSD -12 /* Connection closed. */
+#define ERR_CONN -13 /* Not connected. */
-#define ERR_VAL -9 /* Illegal value. */
+#define ERR_ARG -14 /* Illegal argument. */
-#define ERR_ARG -10 /* Illegal argument. */
-
-#define ERR_USE -11 /* Address in use. */
-
-#define ERR_IF -12 /* Low-level netif error */
-#define ERR_ISCONN -13 /* Already connected. */
-
-#define ERR_INPROGRESS -14 /* Operation in progress */
+#define ERR_IF -15 /* Low-level netif error */
#ifdef LWIP_DEBUG
diff --git a/core/lwip/src/include/lwip/init.h b/core/lwip/src/include/lwip/init.h
index c1455f5a..77dcdfc7 100644
--- a/core/lwip/src/include/lwip/init.h
+++ b/core/lwip/src/include/lwip/init.h
@@ -41,9 +41,9 @@ extern "C" {
/** X.x.x: Major version of the stack */
#define LWIP_VERSION_MAJOR 1U
/** x.X.x: Minor version of the stack */
-#define LWIP_VERSION_MINOR 3U
+#define LWIP_VERSION_MINOR 4U
/** x.x.X: Revision of the stack */
-#define LWIP_VERSION_REVISION 2U
+#define LWIP_VERSION_REVISION 0U
/** For release candidates, this is set to 1..254
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
* For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */
diff --git a/core/lwip/src/include/lwip/mem.h b/core/lwip/src/include/lwip/mem.h
index aeac0a81..4dbf2f64 100644
--- a/core/lwip/src/include/lwip/mem.h
+++ b/core/lwip/src/include/lwip/mem.h
@@ -58,44 +58,59 @@ typedef size_t mem_size_t;
#ifndef mem_calloc
#define mem_calloc calloc
#endif
-#ifndef mem_realloc
-static inline void *mem_realloc(void *mem, mem_size_t size)
-{
- LWIP_UNUSED_ARG(size);
- return mem;
-}
+/* Since there is no C library allocation function to shrink memory without
+ moving it, define this to nothing. */
+#ifndef mem_trim
+#define mem_trim(mem, size) (mem)
#endif
#else /* MEM_LIBC_MALLOC */
/* MEM_SIZE would have to be aligned, but using 64000 here instead of
* 65535 leaves some room for alignment...
*/
-#if MEM_SIZE > 64000l
+#if MEM_SIZE > 64000L
typedef u32_t mem_size_t;
+#define MEM_SIZE_F U32_F
#else
typedef u16_t mem_size_t;
+#define MEM_SIZE_F U16_F
#endif /* MEM_SIZE > 64000 */
#if MEM_USE_POOLS
/** lwip_mem_init is not used when using pools instead of a heap */
#define lwip_mem_init()
-/** mem_realloc is not used when using pools instead of a heap:
+/** mem_trim is not used when using pools instead of a heap:
we can't free part of a pool element and don't want to copy the rest */
-#define mem_realloc(mem, size) (mem)
+#define mem_trim(mem, size) (mem)
#else /* MEM_USE_POOLS */
/* lwIP alternative malloc */
void lwip_mem_init(void);
-void *mem_realloc(void *mem, mem_size_t size);
+void *mem_trim(void *mem, mem_size_t size);
#endif /* MEM_USE_POOLS */
void *mem_malloc(mem_size_t size);
void *mem_calloc(mem_size_t count, mem_size_t size);
void mem_free(void *mem);
#endif /* MEM_LIBC_MALLOC */
+/** Calculate memory size for an aligned buffer - returns the next highest
+ * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and
+ * LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4).
+ */
#ifndef LWIP_MEM_ALIGN_SIZE
#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1))
#endif
+/** Calculate safe memory size for an aligned buffer when using an unaligned
+ * type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the
+ * start (e.g. if buffer is u8_t[] and actual data will be u32_t*)
+ */
+#ifndef LWIP_MEM_ALIGN_BUFFER
+#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1))
+#endif
+
+/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT
+ * so that ADDR % MEM_ALIGNMENT == 0
+ */
#ifndef LWIP_MEM_ALIGN
#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))
#endif
diff --git a/core/lwip/src/include/lwip/memp_std.h b/core/lwip/src/include/lwip/memp_std.h
index 34469032..6ce408fb 100644
--- a/core/lwip/src/include/lwip/memp_std.h
+++ b/core/lwip/src/include/lwip/memp_std.h
@@ -47,6 +47,9 @@ LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg),
#if IP_REASSEMBLY
LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA")
#endif /* IP_REASSEMBLY */
+#if IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
+LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF")
+#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
#if LWIP_NETCONN
LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF")
@@ -55,7 +58,9 @@ LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn),
#if NO_SYS==0
LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API")
+#if !LWIP_TCPIP_CORE_LOCKING_INPUT
LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT")
+#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
#endif /* NO_SYS==0 */
#if ARP_QUEUEING
@@ -66,10 +71,25 @@ LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_en
LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP")
#endif /* LWIP_IGMP */
-#if NO_SYS==0
+#if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */
LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT")
-#endif /* NO_SYS==0 */
-
+#endif /* LWIP_TIMERS */
+
+#if LWIP_SNMP
+LWIP_MEMPOOL(SNMP_ROOTNODE, MEMP_NUM_SNMP_ROOTNODE, sizeof(struct mib_list_rootnode), "SNMP_ROOTNODE")
+LWIP_MEMPOOL(SNMP_NODE, MEMP_NUM_SNMP_NODE, sizeof(struct mib_list_node), "SNMP_NODE")
+LWIP_MEMPOOL(SNMP_VARBIND, MEMP_NUM_SNMP_VARBIND, sizeof(struct snmp_varbind), "SNMP_VARBIND")
+LWIP_MEMPOOL(SNMP_VALUE, MEMP_NUM_SNMP_VALUE, SNMP_MAX_VALUE_SIZE, "SNMP_VALUE")
+#endif /* LWIP_SNMP */
+#if LWIP_DNS && LWIP_SOCKET
+LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB")
+#endif /* LWIP_DNS && LWIP_SOCKET */
+#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST")
+#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+#if PPP_SUPPORT && PPPOE_SUPPORT
+LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF")
+#endif /* PPP_SUPPORT && PPPOE_SUPPORT */
/*
* A list of pools of pbuf's used by LWIP.
diff --git a/core/lwip/src/include/lwip/netbuf.h b/core/lwip/src/include/lwip/netbuf.h
index 0dfb367a..7d247d71 100644
--- a/core/lwip/src/include/lwip/netbuf.h
+++ b/core/lwip/src/include/lwip/netbuf.h
@@ -40,14 +40,24 @@
extern "C" {
#endif
+/** This netbuf has dest-addr/port set */
+#define NETBUF_FLAG_DESTADDR 0x01
+/** This netbuf includes a checksum */
+#define NETBUF_FLAG_CHKSUM 0x02
+
struct netbuf {
struct pbuf *p, *ptr;
- struct ip_addr *addr;
+ ip_addr_t addr;
u16_t port;
+#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
+#if LWIP_CHECKSUM_ON_COPY
+ u8_t flags;
+#endif /* LWIP_CHECKSUM_ON_COPY */
+ u16_t toport_chksum;
#if LWIP_NETBUF_RECVINFO
- struct ip_addr *toaddr;
- u16_t toport;
+ ip_addr_t toaddr;
#endif /* LWIP_NETBUF_RECVINFO */
+#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
};
/* Network buffer functions: */
@@ -56,13 +66,12 @@ void netbuf_delete (struct netbuf *buf);
void * netbuf_alloc (struct netbuf *buf, u16_t size);
void netbuf_free (struct netbuf *buf);
err_t netbuf_ref (struct netbuf *buf,
- const void *dataptr, u16_t size);
+ const void *dataptr, u16_t size);
void netbuf_chain (struct netbuf *head,
struct netbuf *tail);
-u16_t netbuf_len (struct netbuf *buf);
err_t netbuf_data (struct netbuf *buf,
- void **dataptr, u16_t *len);
+ void **dataptr, u16_t *len);
s8_t netbuf_next (struct netbuf *buf);
void netbuf_first (struct netbuf *buf);
@@ -72,12 +81,18 @@ void netbuf_first (struct netbuf *buf);
#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len)
#define netbuf_len(buf) ((buf)->p->tot_len)
-#define netbuf_fromaddr(buf) ((buf)->addr)
+#define netbuf_fromaddr(buf) (&((buf)->addr))
+#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set((&(buf)->addr), fromaddr)
#define netbuf_fromport(buf) ((buf)->port)
#if LWIP_NETBUF_RECVINFO
-#define netbuf_destaddr(buf) ((buf)->toaddr)
-#define netbuf_destport(buf) ((buf)->toport)
+#define netbuf_destaddr(buf) (&((buf)->toaddr))
+#define netbuf_set_destaddr(buf, destaddr) ip_addr_set((&(buf)->addr), destaddr)
+#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0)
#endif /* LWIP_NETBUF_RECVINFO */
+#if LWIP_CHECKSUM_ON_COPY
+#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \
+ (buf)->toport_chksum = chksum; } while(0)
+#endif /* LWIP_CHECKSUM_ON_COPY */
#ifdef __cplusplus
}
diff --git a/core/lwip/src/include/lwip/netdb.h b/core/lwip/src/include/lwip/netdb.h
index 29c9847c..7587e2f2 100644
--- a/core/lwip/src/include/lwip/netdb.h
+++ b/core/lwip/src/include/lwip/netdb.h
@@ -26,6 +26,8 @@
* Author: Simon Goldschmidt
*
*/
+#ifndef __LWIP_NETDB_H__
+#define __LWIP_NETDB_H__
#include "lwip/opt.h"
@@ -33,8 +35,13 @@
#include <stddef.h> /* for size_t */
+#include "lwip/inet.h"
#include "lwip/sockets.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* some rarely used options */
#ifndef LWIP_DNS_API_DECLARE_H_ERRNO
#define LWIP_DNS_API_DECLARE_H_ERRNO 1
@@ -108,4 +115,10 @@ int lwip_getaddrinfo(const char *nodename,
lwip_getaddrinfo(nodname, servname, hints, res)
#endif /* LWIP_COMPAT_SOCKETS */
+#ifdef __cplusplus
+}
+#endif
+
#endif /* LWIP_DNS && LWIP_SOCKET */
+
+#endif /* __LWIP_NETDB_H__ */
diff --git a/core/lwip/src/include/lwip/netif.h b/core/lwip/src/include/lwip/netif.h
index 462d3497..8e799295 100644
--- a/core/lwip/src/include/lwip/netif.h
+++ b/core/lwip/src/include/lwip/netif.h
@@ -40,7 +40,7 @@
#include "lwip/ip_addr.h"
-#include "lwip/inet.h"
+#include "lwip/def.h"
#include "lwip/pbuf.h"
#if LWIP_DHCP
struct dhcp;
@@ -60,61 +60,108 @@ extern "C" {
across all types of interfaces in use */
#define NETIF_MAX_HWADDR_LEN 32U
-/** TODO: define the use (where, when, whom) of netif flags */
-
-/** whether the network interface is 'up'. this is
+/** Whether the network interface is 'up'. This is
* a software flag used to control whether this network
* interface is enabled and processes traffic.
+ * It is set by the startup code (for static IP configuration) or
+ * by dhcp/autoip when an address has been assigned.
*/
#define NETIF_FLAG_UP 0x01U
-/** if set, the netif has broadcast capability */
+/** If set, the netif has broadcast capability.
+ * Set by the netif driver in its init function. */
#define NETIF_FLAG_BROADCAST 0x02U
-/** if set, the netif is one end of a point-to-point connection */
+/** If set, the netif is one end of a point-to-point connection.
+ * Set by the netif driver in its init function. */
#define NETIF_FLAG_POINTTOPOINT 0x04U
-/** if set, the interface is configured using DHCP */
+/** If set, the interface is configured using DHCP.
+ * Set by the DHCP code when starting or stopping DHCP. */
#define NETIF_FLAG_DHCP 0x08U
-/** if set, the interface has an active link
- * (set by the network interface driver) */
+/** If set, the interface has an active link
+ * (set by the network interface driver).
+ * Either set by the netif driver in its init function (if the link
+ * is up at that time) or at a later point once the link comes up
+ * (if link detection is supported by the hardware). */
#define NETIF_FLAG_LINK_UP 0x10U
-/** if set, the netif is an device using ARP */
+/** If set, the netif is an ethernet device using ARP.
+ * Set by the netif driver in its init function.
+ * Used to check input packet types and use of DHCP. */
#define NETIF_FLAG_ETHARP 0x20U
-/** if set, the netif has IGMP capability */
-#define NETIF_FLAG_IGMP 0x40U
+/** If set, the netif is an ethernet device. It might not use
+ * ARP or TCP/IP if it is used for PPPoE only.
+ */
+#define NETIF_FLAG_ETHERNET 0x40U
+/** If set, the netif has IGMP capability.
+ * Set by the netif driver in its init function. */
+#define NETIF_FLAG_IGMP 0x80U
+
+/** Function prototype for netif init functions. Set up flags and output/linkoutput
+ * callback functions in this function.
+ *
+ * @param netif The netif to initialize
+ */
+typedef err_t (*netif_init_fn)(struct netif *netif);
+/** Function prototype for netif->input functions. This function is saved as 'input'
+ * callback function in the netif struct. Call it when a packet has been received.
+ *
+ * @param p The received packet, copied into a pbuf
+ * @param inp The netif which received the packet
+ */
+typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp);
+/** Function prototype for netif->output functions. Called by lwIP when a packet
+ * shall be sent. For ethernet netif, set this to 'etharp_output' and set
+ * 'linkoutput'.
+ *
+ * @param netif The netif which shall send a packet
+ * @param p The packet to send (p->payload points to IP header)
+ * @param ipaddr The IP address to which the packet shall be sent
+ */
+typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p,
+ ip_addr_t *ipaddr);
+/** Function prototype for netif->linkoutput functions. Only used for ethernet
+ * netifs. This function is called by ARP when a packet shall be sent.
+ *
+ * @param netif The netif which shall send a packet
+ * @param p The packet to send (raw ethernet packet)
+ */
+typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p);
+/** Function prototype for netif status- or link-callback functions. */
+typedef void (*netif_status_callback_fn)(struct netif *netif);
+/** Function prototype for netif igmp_mac_filter functions */
+typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif,
+ ip_addr_t *group, u8_t action);
/** Generic data structure used for all lwIP network interfaces.
* The following fields should be filled in by the initialization
* function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
-
struct netif {
/** pointer to next in linked list */
struct netif *next;
/** IP address configuration in network byte order */
- struct ip_addr ip_addr;
- struct ip_addr netmask;
- struct ip_addr gw;
+ ip_addr_t ip_addr;
+ ip_addr_t netmask;
+ ip_addr_t gw;
/** This function is called by the network device driver
* to pass a packet up the TCP/IP stack. */
- err_t (* input)(struct pbuf *p, struct netif *inp);
+ netif_input_fn input;
/** This function is called by the IP module when it wants
* to send a packet on the interface. This function typically
* first resolves the hardware address, then sends the packet. */
- err_t (* output)(struct netif *netif, struct pbuf *p,
- struct ip_addr *ipaddr);
+ netif_output_fn output;
/** This function is called by the ARP module when it wants
* to send a packet on the interface. This function outputs
* the pbuf as-is on the link medium. */
- err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
+ netif_linkoutput_fn linkoutput;
#if LWIP_NETIF_STATUS_CALLBACK
/** This function is called when the netif state is set to up or down
*/
- void (* status_callback)(struct netif *netif);
+ netif_status_callback_fn status_callback;
#endif /* LWIP_NETIF_STATUS_CALLBACK */
#if LWIP_NETIF_LINK_CALLBACK
/** This function is called when the netif link is set to up or down
*/
- void (* link_callback)(struct netif *netif);
+ netif_status_callback_fn link_callback;
#endif /* LWIP_NETIF_LINK_CALLBACK */
/** This field can be set by the device driver and could point
* to state information for the device. */
@@ -161,8 +208,9 @@ struct netif {
u32_t ifoutdiscards;
#endif /* LWIP_SNMP */
#if LWIP_IGMP
- /* This function could be called to add or delete a entry in the multicast filter table of the ethernet MAC.*/
- err_t (*igmp_mac_filter)( struct netif *netif, struct ip_addr *group, u8_t action);
+ /** This function could be called to add or delete a entry in the multicast
+ filter table of the ethernet MAC.*/
+ netif_igmp_mac_filter_fn igmp_mac_filter;
#endif /* LWIP_IGMP */
#if LWIP_NETIF_HWADDRHINT
u8_t *addr_hint;
@@ -180,18 +228,18 @@ struct netif {
#if LWIP_SNMP
#define NETIF_INIT_SNMP(netif, type, speed) \
/* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \
- netif->link_type = type; \
+ (netif)->link_type = (type); \
/* your link speed here (units: bits per second) */ \
- netif->link_speed = speed; \
- netif->ts = 0; \
- netif->ifinoctets = 0; \
- netif->ifinucastpkts = 0; \
- netif->ifinnucastpkts = 0; \
- netif->ifindiscards = 0; \
- netif->ifoutoctets = 0; \
- netif->ifoutucastpkts = 0; \
- netif->ifoutnucastpkts = 0; \
- netif->ifoutdiscards = 0
+ (netif)->link_speed = (speed); \
+ (netif)->ts = 0; \
+ (netif)->ifinoctets = 0; \
+ (netif)->ifinucastpkts = 0; \
+ (netif)->ifinnucastpkts = 0; \
+ (netif)->ifindiscards = 0; \
+ (netif)->ifoutoctets = 0; \
+ (netif)->ifoutucastpkts = 0; \
+ (netif)->ifoutnucastpkts = 0; \
+ (netif)->ifoutdiscards = 0
#else /* LWIP_SNMP */
#define NETIF_INIT_SNMP(netif, type, speed)
#endif /* LWIP_SNMP */
@@ -202,17 +250,14 @@ extern struct netif *netif_list;
/** The default network interface. */
extern struct netif *netif_default;
-#define netif_init() /* Compatibility define, not init needed. */
+void netif_init(void);
-struct netif *netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
- struct ip_addr *gw,
- void *state,
- err_t (* init)(struct netif *netif),
- err_t (* input)(struct pbuf *p, struct netif *netif));
+struct netif *netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
+ ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input);
void
-netif_set_addr(struct netif *netif,struct ip_addr *ipaddr, struct ip_addr *netmask,
- struct ip_addr *gw);
+netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
+ ip_addr_t *gw);
void netif_remove(struct netif * netif);
/* Returns a network interface given its name. The name is of the form
@@ -223,41 +268,48 @@ struct netif *netif_find(char *name);
void netif_set_default(struct netif *netif);
-void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr);
-void netif_set_netmask(struct netif *netif, struct ip_addr *netmask);
-void netif_set_gw(struct netif *netif, struct ip_addr *gw);
+void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr);
+void netif_set_netmask(struct netif *netif, ip_addr_t *netmask);
+void netif_set_gw(struct netif *netif, ip_addr_t *gw);
void netif_set_up(struct netif *netif);
void netif_set_down(struct netif *netif);
-u8_t netif_is_up(struct netif *netif);
+/** Ask if an interface is up */
+#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0)
#if LWIP_NETIF_STATUS_CALLBACK
-/*
- * Set callback to be called when interface is brought up/down
- */
-void netif_set_status_callback(struct netif *netif, void (* status_callback)(struct netif *netif));
+void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback);
#endif /* LWIP_NETIF_STATUS_CALLBACK */
-#if LWIP_NETIF_LINK_CALLBACK
void netif_set_link_up(struct netif *netif);
void netif_set_link_down(struct netif *netif);
-u8_t netif_is_link_up(struct netif *netif);
-/*
- * Set callback to be called when link is brought up/down
- */
-void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif));
+/** Ask if a link is up */
+#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0)
+
+#if LWIP_NETIF_LINK_CALLBACK
+void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback);
#endif /* LWIP_NETIF_LINK_CALLBACK */
-#ifdef __cplusplus
-}
-#endif
+#if LWIP_NETIF_HOSTNAME
+#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0)
+#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL)
+#endif /* LWIP_NETIF_HOSTNAME */
+
+#if LWIP_IGMP
+#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0)
+#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL)
+#endif /* LWIP_IGMP */
#if ENABLE_LOOPBACK
-err_t netif_loop_output(struct netif *netif, struct pbuf *p, struct ip_addr *dest_ip);
+err_t netif_loop_output(struct netif *netif, struct pbuf *p, ip_addr_t *dest_ip);
void netif_poll(struct netif *netif);
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
void netif_poll_all(void);
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
#endif /* ENABLE_LOOPBACK */
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __LWIP_NETIF_H__ */
diff --git a/core/lwip/src/include/lwip/netifapi.h b/core/lwip/src/include/lwip/netifapi.h
index 4145dd74..33318efa 100644
--- a/core/lwip/src/include/lwip/netifapi.h
+++ b/core/lwip/src/include/lwip/netifapi.h
@@ -41,6 +41,9 @@
extern "C" {
#endif
+typedef void (*netifapi_void_fn)(struct netif *netif);
+typedef err_t (*netifapi_errt_fn)(struct netif *netif);
+
struct netifapi_msg_msg {
#if !LWIP_TCPIP_CORE_LOCKING
sys_sem_t sem;
@@ -49,16 +52,16 @@ struct netifapi_msg_msg {
struct netif *netif;
union {
struct {
- struct ip_addr *ipaddr;
- struct ip_addr *netmask;
- struct ip_addr *gw;
+ ip_addr_t *ipaddr;
+ ip_addr_t *netmask;
+ ip_addr_t *gw;
void *state;
- err_t (* init) (struct netif *netif);
- err_t (* input)(struct pbuf *p, struct netif *netif);
+ netif_init_fn init;
+ netif_input_fn input;
} add;
struct {
- void (* voidfunc)(struct netif *netif);
- err_t (* errtfunc)(struct netif *netif);
+ netifapi_void_fn voidfunc;
+ netifapi_errt_fn errtfunc;
} common;
} msg;
};
@@ -71,21 +74,21 @@ struct netifapi_msg {
/* API for application */
err_t netifapi_netif_add ( struct netif *netif,
- struct ip_addr *ipaddr,
- struct ip_addr *netmask,
- struct ip_addr *gw,
+ ip_addr_t *ipaddr,
+ ip_addr_t *netmask,
+ ip_addr_t *gw,
void *state,
- err_t (* init)(struct netif *netif),
- err_t (* input)(struct pbuf *p, struct netif *netif) );
+ netif_init_fn init,
+ netif_input_fn input);
err_t netifapi_netif_set_addr ( struct netif *netif,
- struct ip_addr *ipaddr,
- struct ip_addr *netmask,
- struct ip_addr *gw );
+ ip_addr_t *ipaddr,
+ ip_addr_t *netmask,
+ ip_addr_t *gw );
err_t netifapi_netif_common ( struct netif *netif,
- void (* voidfunc)(struct netif *netif),
- err_t (* errtfunc)(struct netif *netif) );
+ netifapi_void_fn voidfunc,
+ netifapi_errt_fn errtfunc);
#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL)
#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL)
diff --git a/core/lwip/src/include/lwip/opt.h b/core/lwip/src/include/lwip/opt.h
index eb99a778..a1b87658 100644
--- a/core/lwip/src/include/lwip/opt.h
+++ b/core/lwip/src/include/lwip/opt.h
@@ -69,6 +69,14 @@
#endif
/**
+ * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1
+ * Mainly for compatibility to old versions.
+ */
+#ifndef NO_SYS_NO_TIMERS
+#define NO_SYS_NO_TIMERS 0
+#endif
+
+/**
* MEMCPY: override this if you have a faster implementation at hand than the
* one included in your C library
*/
@@ -125,6 +133,15 @@
#endif
/**
+ * MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array.
+ * This can be used to individually change the location of each pool.
+ * Default is one big array for all pools
+ */
+#ifndef MEMP_SEPARATE_POOLS
+#define MEMP_SEPARATE_POOLS 0
+#endif
+
+/**
* MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable
* amount of bytes before and after each memp element in every pool and fills
* it with a prominent default value.
@@ -251,7 +268,7 @@
#endif
/**
- * MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for
+ * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for
* reassembly (whole packets, not fragments!)
*/
#ifndef MEMP_NUM_REASSDATA
@@ -259,6 +276,17 @@
#endif
/**
+ * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent
+ * (fragments, not whole packets!).
+ * This is only used with IP_FRAG_USES_STATIC_BUF==0 and
+ * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs
+ * where the packet is not yet sent when netif->output returns.
+ */
+#ifndef MEMP_NUM_FRAG_PBUF
+#define MEMP_NUM_FRAG_PBUF 15
+#endif
+
+/**
* MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing
* packets (pbufs) that are waiting for an ARP request (to resolve
* their destination address) to finish.
@@ -321,6 +349,63 @@
#endif
/**
+ * MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree.
+ */
+#ifndef MEMP_NUM_SNMP_NODE
+#define MEMP_NUM_SNMP_NODE 50
+#endif
+
+/**
+ * MEMP_NUM_SNMP_ROOTNODE: the number of branches in the SNMP tree.
+ * Every branch has one leaf (MEMP_NUM_SNMP_NODE) at least!
+ */
+#ifndef MEMP_NUM_SNMP_ROOTNODE
+#define MEMP_NUM_SNMP_ROOTNODE 30
+#endif
+
+/**
+ * MEMP_NUM_SNMP_VARBIND: the number of concurrent requests (does not have to
+ * be changed normally) - 2 of these are used per request (1 for input,
+ * 1 for output)
+ */
+#ifndef MEMP_NUM_SNMP_VARBIND
+#define MEMP_NUM_SNMP_VARBIND 2
+#endif
+
+/**
+ * MEMP_NUM_SNMP_VALUE: the number of OID or values concurrently used
+ * (does not have to be changed normally) - 3 of these are used per request
+ * (1 for the value read and 2 for OIDs - input and output)
+ */
+#ifndef MEMP_NUM_SNMP_VALUE
+#define MEMP_NUM_SNMP_VALUE 3
+#endif
+
+/**
+ * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls
+ * (before freeing the corresponding memory using lwip_freeaddrinfo()).
+ */
+#ifndef MEMP_NUM_NETDB
+#define MEMP_NUM_NETDB 1
+#endif
+
+/**
+ * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list
+ * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1.
+ */
+#ifndef MEMP_NUM_LOCALHOSTLIST
+#define MEMP_NUM_LOCALHOSTLIST 1
+#endif
+
+/**
+ * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE
+ * interfaces (only used with PPPOE_SUPPORT==1)
+ */
+#ifndef MEMP_NUM_PPPOE_INTERFACES
+#define MEMP_NUM_PPPOE_INTERFACES 1
+#endif
+
+/**
* PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
*/
#ifndef PBUF_POOL_SIZE
@@ -347,11 +432,14 @@
#endif
/**
- * ARP_QUEUEING==1: Outgoing packets are queued during hardware address
- * resolution.
+ * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address
+ * resolution. By default, only the most recent packet is queued per IP address.
+ * This is sufficient for most protocols and mainly reduces TCP connection
+ * startup time. Set this to 1 if you know your application sends more than one
+ * packet in a row to an IP address that is not in the ARP cache.
*/
#ifndef ARP_QUEUEING
-#define ARP_QUEUEING 1
+#define ARP_QUEUEING 0
#endif
/**
@@ -361,9 +449,11 @@
* correct addresses, or as a limited approach to attempt to handle
* spoofing. If disabled, lwIP will need to make a new ARP request if
* the peer is not already in the ARP table, adding a little latency.
+ * The peer *is* in the ARP table if it requested our address before.
+ * Also notice that this slows down input processing of every IP packet!
*/
#ifndef ETHARP_TRUST_IP_MAC
-#define ETHARP_TRUST_IP_MAC 1
+#define ETHARP_TRUST_IP_MAC 0
#endif
/**
@@ -376,6 +466,30 @@
#define ETHARP_SUPPORT_VLAN 0
#endif
+/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP
+ * might be disabled
+ */
+#ifndef LWIP_ETHERNET
+#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT)
+#endif
+
+/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure
+ * alignment of payload after that header. Since the header is 14 bytes long,
+ * without this padding e.g. addresses in the IP header will not be aligned
+ * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms.
+ */
+#ifndef ETH_PAD_SIZE
+#define ETH_PAD_SIZE 0
+#endif
+
+/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table
+ * entries (using etharp_add_static_entry/etharp_remove_static_entry).
+ */
+#ifndef ETHARP_SUPPORT_STATIC_ENTRIES
+#define ETHARP_SUPPORT_STATIC_ENTRIES 0
+#endif
+
+
/*
--------------------------------
---------- IP options ----------
@@ -439,10 +553,12 @@
/**
* IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP
* fragmentation. Otherwise pbufs are allocated and reference the original
- * packet data to be fragmented.
+ * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1,
+ * new PBUF_RAM pbufs are used for fragments).
+ * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs!
*/
#ifndef IP_FRAG_USES_STATIC_BUF
-#define IP_FRAG_USES_STATIC_BUF 1
+#define IP_FRAG_USES_STATIC_BUF 0
#endif
/**
@@ -595,7 +711,8 @@
/**
* SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will
- * allow. At least one request buffer is required.
+ * allow. At least one request buffer is required.
+ * Does not have to be changed unless external MIBs answer request asynchronously
*/
#ifndef SNMP_CONCURRENT_REQUESTS
#define SNMP_CONCURRENT_REQUESTS 1
@@ -611,6 +728,8 @@
/**
* SNMP_PRIVATE_MIB:
+ * When using a private MIB, you have to create a file 'private_mib.h' that contains
+ * a 'struct mib_array_node mib_private' which contains your MIB.
*/
#ifndef SNMP_PRIVATE_MIB
#define SNMP_PRIVATE_MIB 0
@@ -625,6 +744,31 @@
#define SNMP_SAFE_REQUESTS 1
#endif
+/**
+ * The maximum length of strings used. This affects the size of
+ * MEMP_SNMP_VALUE elements.
+ */
+#ifndef SNMP_MAX_OCTET_STRING_LEN
+#define SNMP_MAX_OCTET_STRING_LEN 127
+#endif
+
+/**
+ * The maximum depth of the SNMP tree.
+ * With private MIBs enabled, this depends on your MIB!
+ * This affects the size of MEMP_SNMP_VALUE elements.
+ */
+#ifndef SNMP_MAX_TREE_DEPTH
+#define SNMP_MAX_TREE_DEPTH 15
+#endif
+
+/**
+ * The size of the MEMP_SNMP_VALUE elements, normally calculated from
+ * SNMP_MAX_OCTET_STRING_LEN and SNMP_MAX_TREE_DEPTH.
+ */
+#ifndef SNMP_MAX_VALUE_SIZE
+#define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH))
+#endif
+
/*
----------------------------------
---------- IGMP options ----------
@@ -670,13 +814,6 @@
#define DNS_DOES_NAME_CHECK 1
#endif
-/** DNS use a local buffer if DNS_USES_STATIC_BUF=0, a static one if
- DNS_USES_STATIC_BUF=1, or a dynamic one if DNS_USES_STATIC_BUF=2.
- The buffer will be of size DNS_MSG_SIZE */
-#ifndef DNS_USES_STATIC_BUF
-#define DNS_USES_STATIC_BUF 1
-#endif
-
/** DNS message max. size. Default value is RFC compliant. */
#ifndef DNS_MSG_SIZE
#define DNS_MSG_SIZE 512
@@ -820,19 +957,28 @@
* as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
*/
#ifndef TCP_SND_QUEUELEN
-#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF)/(TCP_MSS))
+#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS))
#endif
/**
- * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than or equal
- * to TCP_SND_BUF. It is the amount of space which must be available in the
- * TCP snd_buf for select to return writable.
+ * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than
+ * TCP_SND_BUF. It is the amount of space which must be available in the
+ * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT).
*/
#ifndef TCP_SNDLOWAT
#define TCP_SNDLOWAT ((TCP_SND_BUF)/2)
#endif
/**
+ * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be grater
+ * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below
+ * this number, select returns writable (combined with TCP_SNDLOWAT).
+ */
+#ifndef TCP_SNDQUEUELOWAT
+#define TCP_SNDQUEUELOWAT ((TCP_SND_QUEUELEN)/2)
+#endif
+
+/**
* TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb.
*/
#ifndef TCP_LISTEN_BACKLOG
@@ -849,6 +995,24 @@
#endif
/**
+ * TCP_OVERSIZE: The maximum number of bytes that tcp_write may
+ * allocate ahead of time in an attempt to create shorter pbuf chains
+ * for transmission. The meaningful range is 0 to TCP_MSS. Some
+ * suggested values are:
+ *
+ * 0: Disable oversized allocation. Each tcp_write() allocates a new
+ pbuf (old behaviour).
+ * 1: Allocate size-aligned pbufs with minimal excess. Use this if your
+ * scatter-gather DMA requires aligned fragments.
+ * 128: Limit the pbuf/memory overhead to 20%.
+ * TCP_MSS: Try to create unfragmented TCP packets.
+ * TCP_MSS/4: Try to create 4 fragments or less per TCP packet.
+ */
+#ifndef TCP_OVERSIZE
+#define TCP_OVERSIZE TCP_MSS
+#endif
+
+/**
* LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option.
*/
#ifndef LWIP_TCP_TIMESTAMPS
@@ -890,7 +1054,7 @@
* Ethernet.
*/
#ifndef PBUF_LINK_HLEN
-#define PBUF_LINK_HLEN 14
+#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE)
#endif
/**
@@ -1084,14 +1248,14 @@
#endif
/**
- * PPP_THREAD_NAME: The name assigned to the pppMain thread.
+ * PPP_THREAD_NAME: The name assigned to the pppInputThread.
*/
#ifndef PPP_THREAD_NAME
-#define PPP_THREAD_NAME "pppMain"
+#define PPP_THREAD_NAME "pppInputThread"
#endif
/**
- * PPP_THREAD_STACKSIZE: The stack size used by the pppMain thread.
+ * PPP_THREAD_STACKSIZE: The stack size used by the pppInputThread.
* The stack size value itself is platform-dependent, but is passed to
* sys_thread_new() when the thread is created.
*/
@@ -1100,7 +1264,7 @@
#endif
/**
- * PPP_THREAD_PRIO: The priority assigned to the pppMain thread.
+ * PPP_THREAD_PRIO: The priority assigned to the pppInputThread.
* The priority value itself is platform-dependent, but is passed to
* sys_thread_new() when the thread is created.
*/
@@ -1183,12 +1347,27 @@
#endif
/**
+ * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!)
+ * Don't use it if you're not an active lwIP project member
+ */
+#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT
+#define LWIP_TCPIP_CORE_LOCKING_INPUT 0
+#endif
+
+/**
* LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
*/
#ifndef LWIP_NETCONN
#define LWIP_NETCONN 1
#endif
+/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout tod create
+ * timers running in tcpip_thread from another thread.
+ */
+#ifndef LWIP_TCPIP_TIMEOUT
+#define LWIP_TCPIP_TIMEOUT 1
+#endif
+
/*
------------------------------------
---------- Socket options ----------
@@ -1249,12 +1428,21 @@
#endif
/**
- * SO_REUSE==1: Enable SO_REUSEADDR and SO_REUSEPORT options. DO NOT USE!
+ * SO_REUSE==1: Enable SO_REUSEADDR option.
*/
#ifndef SO_REUSE
#define SO_REUSE 0
#endif
+/**
+ * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets
+ * to all local matches if SO_REUSEADDR is turned on.
+ * WARNING: Adds a memcpy for every packet if passing to more than one pcb!
+ */
+#ifndef SO_REUSE_RXTOALL
+#define SO_REUSE_RXTOALL 0
+#endif
+
/*
----------------------------------------
---------- Statistics options ----------
@@ -1583,6 +1771,14 @@
#define CHECKSUM_CHECK_TCP 1
#endif
+/**
+ * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from
+ * application buffers to pbufs.
+ */
+#ifndef LWIP_CHECKSUM_ON_COPY
+#define LWIP_CHECKSUM_ON_COPY 0
+#endif
+
/*
---------------------------------------
---------- Debugging options ----------
@@ -1711,6 +1907,13 @@
#endif
/**
+ * TIMERS_DEBUG: Enable debugging in timers.c.
+ */
+#ifndef TIMERS_DEBUG
+#define TIMERS_DEBUG LWIP_DBG_OFF
+#endif
+
+/**
* TCP_DEBUG: Enable debugging for TCP.
*/
#ifndef TCP_DEBUG
diff --git a/core/lwip/src/include/lwip/pbuf.h b/core/lwip/src/include/lwip/pbuf.h
index 8380f65d..3b1d608b 100644
--- a/core/lwip/src/include/lwip/pbuf.h
+++ b/core/lwip/src/include/lwip/pbuf.h
@@ -40,6 +40,10 @@
extern "C" {
#endif
+/** Currently, the pbuf_custom code is only needed for one specific configuration
+ * of IP_FRAG */
+#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF)
+
#define PBUF_TRANSPORT_HLEN 20
#define PBUF_IP_HLEN 20
@@ -59,7 +63,12 @@ typedef enum {
/** indicates this packet's data should be immediately passed to the application */
-#define PBUF_FLAG_PUSH 0x01U
+#define PBUF_FLAG_PUSH 0x01U
+/** indicates this is a custom pbuf: pbuf_free and pbuf_header handle such a
+ a pbuf differently */
+#define PBUF_FLAG_IS_CUSTOM 0x02U
+/** indicates this pbuf is UDP multicast to be looped back */
+#define PBUF_FLAG_MCASTLOOP 0x04U
struct pbuf {
/** next pbuf in singly linked pbuf chain */
@@ -67,7 +76,7 @@ struct pbuf {
/** pointer to the actual data in the buffer */
void *payload;
-
+
/**
* total length of this buffer and all next buffers in chain
* belonging to the same packet.
@@ -76,9 +85,9 @@ struct pbuf {
* p->tot_len == p->len + (p->next? p->next->tot_len: 0)
*/
u16_t tot_len;
-
+
/** length of this buffer */
- u16_t len;
+ u16_t len;
/** pbuf_type as u8_t instead of enum to save space */
u8_t /*pbuf_type*/ type;
@@ -92,17 +101,33 @@ struct pbuf {
* the stack itself, or pbuf->next pointers from a chain.
*/
u16_t ref;
-
};
+#if LWIP_SUPPORT_CUSTOM_PBUF
+/** Prototype for a function to free a custom pbuf */
+typedef void (*pbuf_free_custom_fn)(struct pbuf *p);
+
+/** A custom pbuf: like a pbuf, but following a function pointer to free it. */
+struct pbuf_custom {
+ /** The actual pbuf */
+ struct pbuf pbuf;
+ /** This function is called when pbuf_free deallocates this pbuf(_custom) */
+ pbuf_free_custom_fn custom_free_function;
+};
+#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
+
/* Initializes the pbuf module. This call is empty for now, but may not be in future. */
#define pbuf_init()
-struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_type type);
+struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type);
+#if LWIP_SUPPORT_CUSTOM_PBUF
+struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type,
+ struct pbuf_custom *p, void *payload_mem,
+ u16_t payload_mem_len);
+#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
void pbuf_realloc(struct pbuf *p, u16_t size);
u8_t pbuf_header(struct pbuf *p, s16_t header_size);
void pbuf_ref(struct pbuf *p);
-void pbuf_ref_chain(struct pbuf *p);
u8_t pbuf_free(struct pbuf *p);
u8_t pbuf_clen(struct pbuf *p);
void pbuf_cat(struct pbuf *head, struct pbuf *tail);
@@ -112,6 +137,15 @@ err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from);
u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer);
+#if LWIP_CHECKSUM_ON_COPY
+err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
+ u16_t len, u16_t *chksum);
+#endif /* LWIP_CHECKSUM_ON_COPY */
+
+u8_t pbuf_get_at(struct pbuf* p, u16_t offset);
+u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n);
+u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset);
+u16_t pbuf_strstr(struct pbuf* p, const char* substr);
#ifdef __cplusplus
}
diff --git a/core/lwip/src/include/lwip/raw.h b/core/lwip/src/include/lwip/raw.h
index 20b0a11b..17d0a1c5 100644
--- a/core/lwip/src/include/lwip/raw.h
+++ b/core/lwip/src/include/lwip/raw.h
@@ -37,7 +37,7 @@
#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
#include "lwip/pbuf.h"
-#include "lwip/inet.h"
+#include "lwip/def.h"
#include "lwip/ip.h"
#include "lwip/ip_addr.h"
@@ -45,26 +45,31 @@
extern "C" {
#endif
+struct raw_pcb;
+
+/** Function prototype for raw pcb receive callback functions.
+ * @param arg user supplied argument (raw_pcb.recv_arg)
+ * @param pcb the raw_pcb which received data
+ * @param p the packet buffer that was received
+ * @param addr the remote IP address from which the packet was received
+ * @return 1 if the packet was 'eaten' (aka. deleted),
+ * 0 if the packet lives on
+ * If returning 1, the callback is responsible for freeing the pbuf
+ * if it's not used any more.
+ */
+typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
+ ip_addr_t *addr);
+
struct raw_pcb {
-/* Common members of all PCB types */
+ /* Common members of all PCB types */
IP_PCB;
struct raw_pcb *next;
u8_t protocol;
- /* receive callback function
- * @param arg user supplied argument (raw_pcb.recv_arg)
- * @param pcb the raw_pcb which received data
- * @param p the packet buffer that was received
- * @param addr the remote IP address from which the packet was received
- * @return 1 if the packet was 'eaten' (aka. deleted),
- * 0 if the packet lives on
- * If returning 1, the callback is responsible for freeing the pbuf
- * if it's not used any more.
- */
- u8_t (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
- struct ip_addr *addr);
+ /** receive callback function */
+ raw_recv_fn recv;
/* user-supplied argument for the recv callback */
void *recv_arg;
};
@@ -73,15 +78,11 @@ struct raw_pcb {
RAW code. */
struct raw_pcb * raw_new (u8_t proto);
void raw_remove (struct raw_pcb *pcb);
-err_t raw_bind (struct raw_pcb *pcb, struct ip_addr *ipaddr);
-err_t raw_connect (struct raw_pcb *pcb, struct ip_addr *ipaddr);
-
-void raw_recv (struct raw_pcb *pcb,
- u8_t (* recv)(void *arg, struct raw_pcb *pcb,
- struct pbuf *p,
- struct ip_addr *addr),
- void *recv_arg);
-err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr);
+err_t raw_bind (struct raw_pcb *pcb, ip_addr_t *ipaddr);
+err_t raw_connect (struct raw_pcb *pcb, ip_addr_t *ipaddr);
+
+void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg);
+err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr);
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
/* The following functions are the lower layer interface to RAW. */
diff --git a/core/lwip/src/include/lwip/snmp.h b/core/lwip/src/include/lwip/snmp.h
index dd03d5d7..2ed043dd 100644
--- a/core/lwip/src/include/lwip/snmp.h
+++ b/core/lwip/src/include/lwip/snmp.h
@@ -34,13 +34,16 @@
#define __LWIP_SNMP_H__
#include "lwip/opt.h"
-#include "lwip/netif.h"
-#include "lwip/udp.h"
#ifdef __cplusplus
extern "C" {
#endif
+#include "lwip/ip_addr.h"
+
+struct udp_pcb;
+struct netif;
+
/**
* @see RFC1213, "MIB-II, 6. Definitions"
*/
@@ -118,8 +121,8 @@ void snmp_inc_iflist(void);
void snmp_dec_iflist(void);
/* ARP (for atTable and ipNetToMediaTable) */
-void snmp_insert_arpidx_tree(struct netif *ni, struct ip_addr *ip);
-void snmp_delete_arpidx_tree(struct netif *ni, struct ip_addr *ip);
+void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip);
+void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip);
/* IP */
void snmp_inc_ipinreceives(void);
diff --git a/core/lwip/src/include/lwip/snmp_asn1.h b/core/lwip/src/include/lwip/snmp_asn1.h
index 8a602881..605fa3f1 100644
--- a/core/lwip/src/include/lwip/snmp_asn1.h
+++ b/core/lwip/src/include/lwip/snmp_asn1.h
@@ -46,12 +46,12 @@
extern "C" {
#endif
-#define SNMP_ASN1_UNIV (!0x80 | !0x40)
-#define SNMP_ASN1_APPLIC (!0x80 | 0x40)
-#define SNMP_ASN1_CONTXT ( 0x80 | !0x40)
+#define SNMP_ASN1_UNIV (0) /* (!0x80 | !0x40) */
+#define SNMP_ASN1_APPLIC (0x40) /* (!0x80 | 0x40) */
+#define SNMP_ASN1_CONTXT (0x80) /* ( 0x80 | !0x40) */
-#define SNMP_ASN1_CONSTR (0x20)
-#define SNMP_ASN1_PRIMIT (!0x20)
+#define SNMP_ASN1_CONSTR (0x20) /* ( 0x20) */
+#define SNMP_ASN1_PRIMIT (0) /* (!0x20) */
/* universal tags */
#define SNMP_ASN1_INTEG 2
@@ -87,10 +87,10 @@ void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed);
void snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed);
err_t snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type);
err_t snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length);
-err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value);
-err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value);
+err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value);
+err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value);
err_t snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident);
-err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw);
+err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw);
#ifdef __cplusplus
}
diff --git a/core/lwip/src/include/lwip/snmp_msg.h b/core/lwip/src/include/lwip/snmp_msg.h
index b2f69c4b..1183e3a9 100644
--- a/core/lwip/src/include/lwip/snmp_msg.h
+++ b/core/lwip/src/include/lwip/snmp_msg.h
@@ -38,10 +38,14 @@
#include "lwip/opt.h"
#include "lwip/snmp.h"
#include "lwip/snmp_structs.h"
+#include "lwip/ip_addr.h"
+#include "lwip/err.h"
#if LWIP_SNMP
#if SNMP_PRIVATE_MIB
+/* When using a private MIB, you have to create a file 'private_mib.h' that contains
+ * a 'struct mib_array_node mib_private' which contains your MIB. */
#include "private_mib.h"
#endif
@@ -219,7 +223,7 @@ struct snmp_msg_pstat
/* lwIP local port (161) binding */
struct udp_pcb *pcb;
/* source IP address */
- struct ip_addr sip;
+ ip_addr_t sip;
/* source UDP port */
u16_t sp;
/* request type */
@@ -258,7 +262,7 @@ struct snmp_msg_trap
/* lwIP local port (161) binding */
struct udp_pcb *pcb;
/* destination IP address in network order */
- struct ip_addr dip;
+ ip_addr_t dip;
/* source enterprise ID (sysObjectID) */
struct snmp_obj_id *enterprise;
@@ -286,7 +290,7 @@ extern struct snmp_msg_trap trap_msg;
/** Agent setup, start listening to port 161. */
void snmp_init(void);
void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable);
-void snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst);
+void snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst);
/** Varbind-list functions. */
struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len);
diff --git a/core/lwip/src/include/lwip/snmp_structs.h b/core/lwip/src/include/lwip/snmp_structs.h
index 9f3f8a94..0d3b46a9 100644
--- a/core/lwip/src/include/lwip/snmp_structs.h
+++ b/core/lwip/src/include/lwip/snmp_structs.h
@@ -44,6 +44,8 @@
#include "lwip/snmp.h"
#if SNMP_PRIVATE_MIB
+/* When using a private MIB, you have to create a file 'private_mib.h' that contains
+ * a 'struct mib_array_node mib_private' which contains your MIB. */
#include "private_mib.h"
#endif
@@ -56,11 +58,15 @@ extern "C" {
#define MIB_OBJECT_SCALAR 1
#define MIB_OBJECT_TAB 2
+/* MIB access types */
+#define MIB_ACCESS_READ 1
+#define MIB_ACCESS_WRITE 2
+
/* MIB object access */
-#define MIB_OBJECT_READ_ONLY 0
-#define MIB_OBJECT_READ_WRITE 1
-#define MIB_OBJECT_WRITE_ONLY 2
-#define MIB_OBJECT_NOT_ACCESSIBLE 3
+#define MIB_OBJECT_READ_ONLY MIB_ACCESS_READ
+#define MIB_OBJECT_READ_WRITE (MIB_ACCESS_READ | MIB_ACCESS_WRITE)
+#define MIB_OBJECT_WRITE_ONLY MIB_ACCESS_WRITE
+#define MIB_OBJECT_NOT_ACCESSIBLE 0
/** object definition returned by (get_object_def)() */
struct obj_def
@@ -109,9 +115,9 @@ struct mib_node
/** sets object value, only to be called when set_test() */
void (*set_value)(struct obj_def *od, u16_t len, void *value);
/** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */
- const u8_t node_type;
+ u8_t node_type;
/* array or max list length */
- const u16_t maxlength;
+ u16_t maxlength;
};
/** derived node for scalars .0 index */
@@ -122,15 +128,15 @@ typedef struct mib_node mib_scalar_node;
struct mib_array_node
{
/* inherited "base class" members */
- void (* const get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od);
- void (* const get_value)(struct obj_def *od, u16_t len, void *value);
+ void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od);
+ void (*get_value)(struct obj_def *od, u16_t len, void *value);
u8_t (*set_test)(struct obj_def *od, u16_t len, void *value);
void (*set_value)(struct obj_def *od, u16_t len, void *value);
- const u8_t node_type;
- const u16_t maxlength;
+ u8_t node_type;
+ u16_t maxlength;
- /* aditional struct members */
+ /* additional struct members */
const s32_t *objid;
struct mib_node* const *nptr;
};
@@ -174,7 +180,7 @@ struct mib_list_rootnode
u8_t node_type;
u16_t maxlength;
- /* aditional struct members */
+ /* additional struct members */
struct mib_list_node *head;
struct mib_list_node *tail;
/* counts list nodes in list */
@@ -194,8 +200,8 @@ struct mib_external_node
u8_t node_type;
u16_t maxlength;
- /* aditional struct members */
- /** points to an extenal (in memory) record of some sort of addressing
+ /* additional struct members */
+ /** points to an external (in memory) record of some sort of addressing
information, passed to and interpreted by the funtions below */
void* addr_inf;
/** tree levels under this node */
@@ -234,8 +240,8 @@ void noleafs_get_value(struct obj_def *od, u16_t len, void *value);
u8_t noleafs_set_test(struct obj_def *od, u16_t len, void *value);
void noleafs_set_value(struct obj_def *od, u16_t len, void *value);
-void snmp_oidtoip(s32_t *ident, struct ip_addr *ip);
-void snmp_iptooid(struct ip_addr *ip, s32_t *ident);
+void snmp_oidtoip(s32_t *ident, ip_addr_t *ip);
+void snmp_iptooid(ip_addr_t *ip, s32_t *ident);
void snmp_ifindextonetif(s32_t ifindex, struct netif **netif);
void snmp_netiftoifindex(struct netif *netif, s32_t *ifidx);
diff --git a/core/lwip/src/include/lwip/sockets.h b/core/lwip/src/include/lwip/sockets.h
index 7b52e151..3c8fed24 100644
--- a/core/lwip/src/include/lwip/sockets.h
+++ b/core/lwip/src/include/lwip/sockets.h
@@ -72,11 +72,11 @@ struct sockaddr {
#define SOCK_RAW 3
/*
- * Option flags per-socket. These must match the SOF_ flags in ip.h!
+ * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c)
*/
#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
-#define SO_REUSEADDR 0x0004 /* Unimplemented: allow local address reuse */
+#define SO_REUSEADDR 0x0004 /* Allow local address reuse */
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */
#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
@@ -262,9 +262,27 @@ typedef struct ip_mreq {
#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */
#endif
-/* Socket flags: */
+/* commands for fnctl */
+#ifndef F_GETFL
+#define F_GETFL 3
+#endif
+#ifndef F_SETFL
+#define F_SETFL 4
+#endif
+
+/* File status flags and file access modes for fnctl,
+ these are bits in an int. */
#ifndef O_NONBLOCK
-#define O_NONBLOCK 04000U
+#define O_NONBLOCK 1 /* nonblocking I/O */
+#endif
+#ifndef O_NDELAY
+#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */
+#endif
+
+#ifndef SHUT_RD
+ #define SHUT_RD 0
+ #define SHUT_WR 1
+ #define SHUT_RDWR 2
#endif
/* FD_SET used for lwip_select */
@@ -320,6 +338,7 @@ int lwip_write(int s, const void *dataptr, size_t size);
int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
struct timeval *timeout);
int lwip_ioctl(int s, long cmd, void *argp);
+int lwip_fcntl(int s, int cmd, int val);
#if LWIP_COMPAT_SOCKETS
#define accept(a,b,c) lwip_accept(a,b,c)
diff --git a/core/lwip/src/include/lwip/stats.h b/core/lwip/src/include/lwip/stats.h
index aa179f5c..015b7ce7 100644
--- a/core/lwip/src/include/lwip/stats.h
+++ b/core/lwip/src/include/lwip/stats.h
@@ -71,18 +71,26 @@ struct stats_proto {
};
struct stats_igmp {
- STAT_COUNTER lenerr; /* Invalid length error. */
+ STAT_COUNTER xmit; /* Transmitted packets. */
+ STAT_COUNTER recv; /* Received packets. */
+ STAT_COUNTER drop; /* Dropped packets. */
STAT_COUNTER chkerr; /* Checksum error. */
- STAT_COUNTER v1_rxed; /* */
- STAT_COUNTER join_sent; /* */
- STAT_COUNTER leave_sent; /* */
- STAT_COUNTER unicast_query; /* */
- STAT_COUNTER report_sent; /* */
- STAT_COUNTER report_rxed; /* */
- STAT_COUNTER group_query_rxed; /* */
+ STAT_COUNTER lenerr; /* Invalid length error. */
+ STAT_COUNTER memerr; /* Out of memory error. */
+ STAT_COUNTER proterr; /* Protocol error. */
+ STAT_COUNTER rx_v1; /* Received v1 frames. */
+ STAT_COUNTER rx_group; /* Received group-specific queries. */
+ STAT_COUNTER rx_general; /* Received general queries. */
+ STAT_COUNTER rx_report; /* Received reports. */
+ STAT_COUNTER tx_join; /* Sent joins. */
+ STAT_COUNTER tx_leave; /* Sent leaves. */
+ STAT_COUNTER tx_report; /* Sent reports. */
};
struct stats_mem {
+#ifdef LWIP_DEBUG
+ const char *name;
+#endif /* LWIP_DEBUG */
mem_size_t avail;
mem_size_t used;
mem_size_t max;
@@ -98,6 +106,7 @@ struct stats_syselem {
struct stats_sys {
struct stats_syselem sem;
+ struct stats_syselem mutex;
struct stats_syselem mbox;
};
@@ -139,14 +148,20 @@ struct stats_ {
extern struct stats_ lwip_stats;
-#define stats_init() /* Compatibility define, not init needed. */
+void stats_init(void);
#define STATS_INC(x) ++lwip_stats.x
#define STATS_DEC(x) --lwip_stats.x
-#else
+#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \
+ if (lwip_stats.x.max < lwip_stats.x.used) { \
+ lwip_stats.x.max = lwip_stats.x.used; \
+ } \
+ } while(0)
+#else /* LWIP_STATS */
#define stats_init()
#define STATS_INC(x)
#define STATS_DEC(x)
+#define STATS_INC_USED(x)
#endif /* LWIP_STATS */
#if TCP_STATS
@@ -216,11 +231,7 @@ extern struct stats_ lwip_stats;
#if MEM_STATS
#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
#define MEM_STATS_INC(x) STATS_INC(mem.x)
-#define MEM_STATS_INC_USED(x, y) do { lwip_stats.mem.used += y; \
- if (lwip_stats.mem.max < lwip_stats.mem.used) { \
- lwip_stats.mem.max = lwip_stats.mem.used; \
- } \
- } while(0)
+#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y)
#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y
#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP")
#else
@@ -235,11 +246,7 @@ extern struct stats_ lwip_stats;
#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y
#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x)
#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x)
-#define MEMP_STATS_INC_USED(x, i) do { ++lwip_stats.memp[i].used; \
- if (lwip_stats.memp[i].max < lwip_stats.memp[i].used) { \
- lwip_stats.memp[i].max = lwip_stats.memp[i].used; \
- } \
- } while(0)
+#define MEMP_STATS_INC_USED(x, i) STATS_INC_USED(memp[i], 1)
#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i)
#else
#define MEMP_STATS_AVAIL(x, i, y)
@@ -252,10 +259,12 @@ extern struct stats_ lwip_stats;
#if SYS_STATS
#define SYS_STATS_INC(x) STATS_INC(sys.x)
#define SYS_STATS_DEC(x) STATS_DEC(sys.x)
+#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1)
#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys)
#else
#define SYS_STATS_INC(x)
#define SYS_STATS_DEC(x)
+#define SYS_STATS_INC_USED(x)
#define SYS_STATS_DISPLAY()
#endif
@@ -267,7 +276,7 @@ void stats_display_igmp(struct stats_igmp *igmp);
void stats_display_mem(struct stats_mem *mem, char *name);
void stats_display_memp(struct stats_mem *mem, int index);
void stats_display_sys(struct stats_sys *sys);
-#else
+#else /* LWIP_STATS_DISPLAY */
#define stats_display()
#define stats_display_proto(proto, name)
#define stats_display_igmp(igmp)
diff --git a/core/lwip/src/include/lwip/sys.h b/core/lwip/src/include/lwip/sys.h
index 0cc84ddf..9f62c754 100644
--- a/core/lwip/src/include/lwip/sys.h
+++ b/core/lwip/src/include/lwip/sys.h
@@ -43,19 +43,19 @@ extern "C" {
/* For a totally minimal and standalone system, we provide null
definitions of the sys_ functions. */
typedef u8_t sys_sem_t;
+typedef u8_t sys_mutex_t;
typedef u8_t sys_mbox_t;
-struct sys_timeo {u8_t dummy;};
-#define sys_init()
-#define sys_timeout(m,h,a)
-#define sys_untimeout(m,a)
-#define sys_sem_new(c) c
+#define sys_sem_new(s, c) ERR_OK
#define sys_sem_signal(s)
#define sys_sem_wait(s)
-#define sys_sem_wait_timeout(s,t)
#define sys_arch_sem_wait(s,t)
#define sys_sem_free(s)
-#define sys_mbox_new(s) 0
+#define sys_mutex_new(mu) ERR_OK
+#define sys_mutex_lock(mu)
+#define sys_mutex_unlock(mu)
+#define sys_mutex_free(mu)
+#define sys_mbox_new(m, s) ERR_OK
#define sys_mbox_fetch(m,d)
#define sys_mbox_tryfetch(m,d)
#define sys_mbox_post(m,d)
@@ -64,12 +64,14 @@ struct sys_timeo {u8_t dummy;};
#define sys_thread_new(n,t,a,s,p)
+#define sys_msleep(t)
+
#else /* NO_SYS */
/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */
#define SYS_ARCH_TIMEOUT 0xffffffffUL
-/* sys_mbox_tryfetch returns SYS_MBOX_EMPTY if appropriate.
+/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate.
* For now we use the same magic value, but we allow this to change in future.
*/
#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT
@@ -77,70 +79,156 @@ struct sys_timeo {u8_t dummy;};
#include "lwip/err.h"
#include "arch/sys_arch.h"
-typedef void (* sys_timeout_handler)(void *arg);
-
-struct sys_timeo {
- struct sys_timeo *next;
- u32_t time;
- sys_timeout_handler h;
- void *arg;
-};
-
-struct sys_timeouts {
- struct sys_timeo *next;
-};
-
-/* sys_init() must be called before anthing else. */
-void sys_init(void);
-
-/*
- * sys_timeout():
- *
- * Schedule a timeout a specified amount of milliseconds in the
- * future. When the timeout occurs, the specified timeout handler will
- * be called. The handler will be passed the "arg" argument when
- * called.
- *
- */
-void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
-void sys_untimeout(sys_timeout_handler h, void *arg);
-struct sys_timeouts *sys_arch_timeouts(void);
-
-/* Semaphore functions. */
-sys_sem_t sys_sem_new(u8_t count);
-void sys_sem_signal(sys_sem_t sem);
-u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout);
-void sys_sem_free(sys_sem_t sem);
-void sys_sem_wait(sys_sem_t sem);
-int sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout);
+/** Function prototype for thread functions */
+typedef void (*lwip_thread_fn)(void *arg);
+
+/* Function prototypes for functions to be implemented by platform ports
+ (in sys_arch.c) */
+
+/* Mutex functions: */
+
+/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores
+ should be used instead */
+#if LWIP_COMPAT_MUTEX
+/* for old ports that don't have mutexes: define them to binary semaphores */
+#define sys_mutex_t sys_sem_t
+#define sys_mutex_new(mutex) sys_sem_new(mutex, 1)
+#define sys_mutex_lock(mutex) sys_sem_wait(mutex)
+#define sys_mutex_unlock(mutex) sys_sem_signal(mutex)
+#define sys_mutex_free(mutex) sys_sem_free(mutex)
+#define sys_mutex_valid(mutex) sys_sem_valid(mutex)
+#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex)
+
+#else /* LWIP_COMPAT_MUTEX */
+
+/** Create a new mutex
+ * @param mutex pointer to the mutex to create
+ * @return a new mutex */
+err_t sys_mutex_new(sys_mutex_t *mutex);
+/** Lock a mutex
+ * @param mutex the mutex to lock */
+void sys_mutex_lock(sys_mutex_t *mutex);
+/** Unlock a mutex
+ * @param mutex the mutex to unlock */
+void sys_mutex_unlock(sys_mutex_t *mutex);
+/** Delete a semaphore
+ * @param mutex the mutex to delete */
+void sys_mutex_free(sys_mutex_t *mutex);
+#ifndef sys_mutex_valid
+/** Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid */
+int sys_mutex_valid(sys_mutex_t *mutex);
+#endif
+#ifndef sys_mutex_set_invalid
+/** Set a mutex invalid so that sys_mutex_valid returns 0 */
+void sys_mutex_set_invalid(sys_mutex_t *mutex);
+#endif
+#endif /* LWIP_COMPAT_MUTEX */
+
+/* Semaphore functions: */
+
+/** Create a new semaphore
+ * @param sem pointer to the semaphore to create
+ * @param count initial count of the semaphore
+ * @return ERR_OK if successful, another err_t otherwise */
+err_t sys_sem_new(sys_sem_t *sem, u8_t count);
+/** Signals a semaphore
+ * @param sem the semaphore to signal */
+void sys_sem_signal(sys_sem_t *sem);
+/** Wait for a semaphore for the specified timeout
+ * @param sem the semaphore to wait for
+ * @param timeout timeout in milliseconds to wait (0 = wait forever)
+ * @return time (in milliseconds) waited for the semaphore
+ * or SYS_ARCH_TIMEOUT on timeout */
+u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout);
+/** Delete a semaphore
+ * @param sem semaphore to delete */
+void sys_sem_free(sys_sem_t *sem);
+/** Wait for a semaphore - forever/no timeout */
+#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0)
+#ifndef sys_sem_valid
+/** Check if a sempahore is valid/allocated: return 1 for valid, 0 for invalid */
+int sys_sem_valid(sys_sem_t *sem);
+#endif
+#ifndef sys_sem_set_invalid
+/** Set a semaphore invalid so that sys_sem_valid returns 0 */
+void sys_sem_set_invalid(sys_sem_t *sem);
+#endif
/* Time functions. */
#ifndef sys_msleep
void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */
#endif
-#ifndef sys_jiffies
-u32_t sys_jiffies(void); /* since power up. */
-#endif
/* Mailbox functions. */
-sys_mbox_t sys_mbox_new(int size);
-void sys_mbox_post(sys_mbox_t mbox, void *msg);
-err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg);
-u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout);
-#ifndef sys_arch_mbox_tryfetch /* Allow port to override with a macro */
-u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg);
+
+/** Create a new mbox of specified size
+ * @param mbox pointer to the mbox to create
+ * @param size (miminum) number of messages in this mbox
+ * @return ERR_OK if successful, another err_t otherwise */
+err_t sys_mbox_new(sys_mbox_t *mbox, int size);
+/** Post a message to an mbox - may not fail
+ * -> blocks if full, only used from tasks not from ISR
+ * @param mbox mbox to posts the message
+ * @param msg message to post (ATTENTION: can be NULL) */
+void sys_mbox_post(sys_mbox_t *mbox, void *msg);
+/** Try to post a message to an mbox - may fail if full or ISR
+ * @param mbox mbox to posts the message
+ * @param msg message to post (ATTENTION: can be NULL) */
+err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg);
+/** Wait for a new message to arrive in the mbox
+ * @param mbox mbox to get a message from
+ * @param msg pointer where the message is stored
+ * @param timeout maximum time (in milliseconds) to wait for a message
+ * @return time (in milliseconds) waited for a message, may be 0 if not waited
+ or SYS_ARCH_TIMEOUT on timeout
+ * The returned time has to be accurate to prevent timer jitter! */
+u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout);
+/* Allow port to override with a macro, e.g. special timout for sys_arch_mbox_fetch() */
+#ifndef sys_arch_mbox_tryfetch
+/** Wait for a new message to arrive in the mbox
+ * @param mbox mbox to get a message from
+ * @param msg pointer where the message is stored
+ * @param timeout maximum time (in milliseconds) to wait for a message
+ * @return 0 (milliseconds) if a message has been received
+ * or SYS_MBOX_EMPTY if the mailbox is empty */
+u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg);
#endif
-/* For now, we map straight to sys_arch implementation. */
+/** For now, we map straight to sys_arch implementation. */
#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg)
-void sys_mbox_free(sys_mbox_t mbox);
-void sys_mbox_fetch(sys_mbox_t mbox, void **msg);
+/** Delete an mbox
+ * @param mbox mbox to delete */
+void sys_mbox_free(sys_mbox_t *mbox);
+#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0)
+#ifndef sys_mbox_valid
+/** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */
+int sys_mbox_valid(sys_mbox_t *mbox);
+#endif
+#ifndef sys_mbox_set_invalid
+/** Set an mbox invalid so that sys_mbox_valid returns 0 */
+void sys_mbox_set_invalid(sys_mbox_t *mbox);
+#endif
-/* Thread functions. */
-sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio);
+/** The only thread function:
+ * Creates a new thread
+ * @param name human-readable name for the thread (used for debugging purposes)
+ * @param thread thread-function
+ * @param arg parameter passed to 'thread'
+ * @param stacksize stack size in bytes for the new thread (may be ignored by ports)
+ * @param prio priority of the new thread (may be ignored by ports) */
+sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio);
#endif /* NO_SYS */
-/** Returns the current time in milliseconds. */
+/* sys_init() must be called before anthing else. */
+void sys_init(void);
+
+#ifndef sys_jiffies
+/** Ticks/jiffies since power up. */
+u32_t sys_jiffies(void);
+#endif
+
+/** Returns the current time in milliseconds,
+ * may be the same as sys_jiffies or at least based on it. */
u32_t sys_now(void);
/* Critical Region Protection */
diff --git a/core/lwip/src/include/lwip/tcp.h b/core/lwip/src/include/lwip/tcp.h
index c88d25d7..07dcd10e 100644
--- a/core/lwip/src/include/lwip/tcp.h
+++ b/core/lwip/src/include/lwip/tcp.h
@@ -49,198 +49,80 @@ extern "C" {
struct tcp_pcb;
-/* Functions for interfacing with TCP: */
-
-/* Lower layer interface to TCP: */
-#define tcp_init() /* Compatibility define, not init needed. */
-void tcp_tmr (void); /* Must be called every
- TCP_TMR_INTERVAL
- ms. (Typically 250 ms). */
-/* Application program's interface: */
-struct tcp_pcb * tcp_new (void);
-struct tcp_pcb * tcp_alloc (u8_t prio);
-
-void tcp_arg (struct tcp_pcb *pcb, void *arg);
-void tcp_accept (struct tcp_pcb *pcb,
- err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
- err_t err));
-void tcp_recv (struct tcp_pcb *pcb,
- err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
- struct pbuf *p, err_t err));
-void tcp_sent (struct tcp_pcb *pcb,
- err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
- u16_t len));
-void tcp_poll (struct tcp_pcb *pcb,
- err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
- u8_t interval);
-void tcp_err (struct tcp_pcb *pcb,
- void (* err)(void *arg, err_t err));
-
-#define tcp_mss(pcb) ((pcb)->mss)
-#define tcp_sndbuf(pcb) ((pcb)->snd_buf)
-#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY)
-#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY)
-#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0)
-
-#if TCP_LISTEN_BACKLOG
-#define tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--)
-#else /* TCP_LISTEN_BACKLOG */
-#define tcp_accepted(pcb)
-#endif /* TCP_LISTEN_BACKLOG */
-
-void tcp_recved (struct tcp_pcb *pcb, u16_t len);
-err_t tcp_bind (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
- u16_t port);
-err_t tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
- u16_t port, err_t (* connected)(void *arg,
- struct tcp_pcb *tpcb,
- err_t err));
-
-struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
-#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
-
-void tcp_abandon (struct tcp_pcb *pcb, int reset);
-#define tcp_abort(pcb) tcp_abandon((pcb), 1)
-err_t tcp_close (struct tcp_pcb *pcb);
-
-/* Flags for "apiflags" parameter in tcp_write and tcp_enqueue */
-#define TCP_WRITE_FLAG_COPY 0x01
-#define TCP_WRITE_FLAG_MORE 0x02
-
-err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
- u8_t apiflags);
-
-void tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
-
-#define TCP_PRIO_MIN 1
-#define TCP_PRIO_NORMAL 64
-#define TCP_PRIO_MAX 127
-
-/* It is also possible to call these two functions at the right
- intervals (instead of calling tcp_tmr()). */
-void tcp_slowtmr (void);
-void tcp_fasttmr (void);
-
-
-/* Only used by IP to pass a TCP segment to TCP: */
-void tcp_input (struct pbuf *p, struct netif *inp);
-/* Used within the TCP code only: */
-err_t tcp_send_empty_ack(struct tcp_pcb *pcb);
-err_t tcp_output (struct tcp_pcb *pcb);
-void tcp_rexmit (struct tcp_pcb *pcb);
-void tcp_rexmit_rto (struct tcp_pcb *pcb);
-void tcp_rexmit_fast (struct tcp_pcb *pcb);
-u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
-
-/**
- * This is the Nagle algorithm: try to combine user data to send as few TCP
- * segments as possible. Only send if
- * - no previously transmitted data on the connection remains unacknowledged or
- * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or
- * - the only unsent segment is at least pcb->mss bytes long (or there is more
- * than one unsent segment - with lwIP, this can happen although unsent->len < mss)
- * - or if we are in fast-retransmit (TF_INFR)
+/** Function prototype for tcp accept callback functions. Called when a new
+ * connection can be accepted on a listening pcb.
+ *
+ * @param arg Additional argument to pass to the callback function (@see tcp_arg())
+ * @param newpcb The new connection pcb
+ * @param err An error code if there has been an error accepting.
+ * Only return ERR_ABRT if you have called tcp_abort from within the
+ * callback function!
*/
-#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
- ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \
- (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
- ((tpcb)->unsent->len >= (tpcb)->mss))) \
- ) ? 1 : 0)
-#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK)
-
-
-#define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0)
-#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
-#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
-#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
-/* is b<=a<=c? */
-#if 0 /* see bug #10548 */
-#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
-#endif
-#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
-#define TCP_FIN 0x01U
-#define TCP_SYN 0x02U
-#define TCP_RST 0x04U
-#define TCP_PSH 0x08U
-#define TCP_ACK 0x10U
-#define TCP_URG 0x20U
-#define TCP_ECE 0x40U
-#define TCP_CWR 0x80U
-
-#define TCP_FLAGS 0x3fU
-
-/* Length of the TCP header, excluding options. */
-#define TCP_HLEN 20
+typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err);
-#ifndef TCP_TMR_INTERVAL
-#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */
-#endif /* TCP_TMR_INTERVAL */
-
-#ifndef TCP_FAST_INTERVAL
-#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */
-#endif /* TCP_FAST_INTERVAL */
-
-#ifndef TCP_SLOW_INTERVAL
-#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */
-#endif /* TCP_SLOW_INTERVAL */
-
-#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */
-#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */
-
-#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */
-
-#ifndef TCP_MSL
-#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */
-#endif
-
-/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */
-#ifndef TCP_KEEPIDLE_DEFAULT
-#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */
-#endif
-
-#ifndef TCP_KEEPINTVL_DEFAULT
-#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */
-#endif
-
-#ifndef TCP_KEEPCNT_DEFAULT
-#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */
-#endif
-
-#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */
+/** Function prototype for tcp receive callback functions. Called when data has
+ * been received.
+ *
+ * @param arg Additional argument to pass to the callback function (@see tcp_arg())
+ * @param tpcb The connection pcb which received data
+ * @param p The received data (or NULL when the connection has been closed!)
+ * @param err An error code if there has been an error receiving
+ * Only return ERR_ABRT if you have called tcp_abort from within the
+ * callback function!
+ */
+typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb,
+ struct pbuf *p, err_t err);
-/* Fields are (of course) in network byte order.
- * Some fields are converted to host byte order in tcp_input().
+/** Function prototype for tcp sent callback functions. Called when sent data has
+ * been acknowledged by the remote side. Use it to free corresponding resources.
+ * This also means that the pcb has now space available to send new data.
+ *
+ * @param arg Additional argument to pass to the callback function (@see tcp_arg())
+ * @param tpcb The connection pcb for which data has been acknowledged
+ * @param len The amount of bytes acknowledged
+ * @return ERR_OK: try to send some data by calling tcp_output
+ * Only return ERR_ABRT if you have called tcp_abort from within the
+ * callback function!
*/
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-struct tcp_hdr {
- PACK_STRUCT_FIELD(u16_t src);
- PACK_STRUCT_FIELD(u16_t dest);
- PACK_STRUCT_FIELD(u32_t seqno);
- PACK_STRUCT_FIELD(u32_t ackno);
- PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
- PACK_STRUCT_FIELD(u16_t wnd);
- PACK_STRUCT_FIELD(u16_t chksum);
- PACK_STRUCT_FIELD(u16_t urgp);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/epstruct.h"
-#endif
+typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb,
+ u16_t len);
-#define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
-#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
-#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
+/** Function prototype for tcp poll callback functions. Called periodically as
+ * specified by @see tcp_poll.
+ *
+ * @param arg Additional argument to pass to the callback function (@see tcp_arg())
+ * @param tpcb tcp pcb
+ * @return ERR_OK: try to send some data by calling tcp_output
+ * Only return ERR_ABRT if you have called tcp_abort from within the
+ * callback function!
+ */
+typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb);
-#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
-#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
-#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & htons((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
-#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
-#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
+/** Function prototype for tcp error callback functions. Called when the pcb
+ * receives a RST or is unexpectedly closed for any other reason.
+ *
+ * @note The corresponding pcb is already freed when this callback is called!
+ *
+ * @param arg Additional argument to pass to the callback function (@see tcp_arg())
+ * @param err Error code to indicate why the pcb has been closed
+ * ERR_ABRT: aborted through tcp_abort or by a TCP timer
+ * ERR_RST: the connection was reset by the remote host
+ */
+typedef void (*tcp_err_fn)(void *arg, err_t err);
-#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
+/** Function prototype for tcp connected callback functions. Called when a pcb
+ * is connected to the remote side after initiating a connection attempt by
+ * calling tcp_connect().
+ *
+ * @param arg Additional argument to pass to the callback function (@see tcp_arg())
+ * @param tpcb The connection pcb which is connected
+ * @param err An unused error code, always ERR_OK currently ;-) TODO!
+ * Only return ERR_ABRT if you have called tcp_abort from within the
+ * callback function!
+ *
+ * @note When a connection attempt fails, the error callback is currently called!
+ */
+typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err);
enum tcp_state {
CLOSED = 0,
@@ -256,13 +138,6 @@ enum tcp_state {
TIME_WAIT = 10
};
-/** Flags used on input processing, not on pcb->flags
-*/
-#define TF_RESET (u8_t)0x08U /* Connection was reset. */
-#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */
-#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
-
-
#if LWIP_CALLBACK_API
/* Function to call when a listener has been connected.
* @param arg user-supplied argument (tcp_pcb.callback_arg)
@@ -271,7 +146,7 @@ enum tcp_state {
* @return ERR_OK: accept the new connection,
* any other err_t abortsthe new connection
*/
-#define DEF_ACCEPT_CALLBACK err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)
+#define DEF_ACCEPT_CALLBACK tcp_accept_fn accept;
#else /* LWIP_CALLBACK_API */
#define DEF_ACCEPT_CALLBACK
#endif /* LWIP_CALLBACK_API */
@@ -284,10 +159,10 @@ enum tcp_state {
enum tcp_state state; /* TCP state */ \
u8_t prio; \
void *callback_arg; \
- /* ports are in host byte order */ \
- u16_t local_port; \
/* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \
- DEF_ACCEPT_CALLBACK
+ DEF_ACCEPT_CALLBACK \
+ /* ports are in host byte order */ \
+ u16_t local_port
/* the TCP protocol control block */
@@ -305,6 +180,7 @@ struct tcp_pcb {
#define TF_ACK_NOW ((u8_t)0x02U) /* Immediate ACK. */
#define TF_INFR ((u8_t)0x04U) /* In fast recovery. */
#define TF_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */
+#define TF_RXCLOSED ((u8_t)0x10U) /* rx closed by tcp_shutdown */
#define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */
#define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */
#define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */
@@ -352,10 +228,14 @@ struct tcp_pcb {
u16_t acked;
u16_t snd_buf; /* Available buffer space for sending (in bytes). */
-#define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3)
+#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3)
u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
-
-
+
+#if TCP_OVERSIZE
+ /* Extra bytes available at the end of the last pbuf in unsent. */
+ u16_t unsent_oversize;
+#endif /* TCP_OVERSIZE */
+
/* These are ordered by sequence number: */
struct tcp_seg *unsent; /* Unsent (queued) segments. */
struct tcp_seg *unacked; /* Sent but unacknowledged segments. */
@@ -366,49 +246,16 @@ struct tcp_pcb {
struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */
#if LWIP_CALLBACK_API
- /* Function to be called when more send buffer space is available.
- * @param arg user-supplied argument (tcp_pcb.callback_arg)
- * @param pcb the tcp_pcb which has send buffer space available
- * @param space the amount of bytes available
- * @return ERR_OK: try to send some data by calling tcp_output
- */
- err_t (* sent)(void *arg, struct tcp_pcb *pcb, u16_t space);
-
- /* Function to be called when (in-sequence) data has arrived.
- * @param arg user-supplied argument (tcp_pcb.callback_arg)
- * @param pcb the tcp_pcb for which data has arrived
- * @param p the packet buffer which arrived
- * @param err an error argument (TODO: that is current always ERR_OK?)
- * @return ERR_OK: try to send some data by calling tcp_output
- */
- err_t (* recv)(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
-
- /* Function to be called when a connection has been set up.
- * @param arg user-supplied argument (tcp_pcb.callback_arg)
- * @param pcb the tcp_pcb that now is connected
- * @param err an error argument (TODO: that is current always ERR_OK?)
- * @return value is currently ignored
- */
- err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err);
-
- /* Function which is called periodically.
- * The period can be adjusted in multiples of the TCP slow timer interval
- * by changing tcp_pcb.polltmr.
- * @param arg user-supplied argument (tcp_pcb.callback_arg)
- * @param pcb the tcp_pcb to poll for
- * @return ERR_OK: try to send some data by calling tcp_output
- */
- err_t (* poll)(void *arg, struct tcp_pcb *pcb);
-
- /* Function to be called whenever a fatal error occurs.
- * There is no pcb parameter since most of the times, the pcb is
- * already deallocated (or there is no pcb) when this function is called.
- * @param arg user-supplied argument (tcp_pcb.callback_arg)
- * @param err an indication why the error callback is called:
- * ERR_ABRT: aborted through tcp_abort or by a TCP timer
- * ERR_RST: the connection was reset by the remote host
- */
- void (* errf)(void *arg, err_t err);
+ /* Function to be called when more send buffer space is available. */
+ tcp_sent_fn sent;
+ /* Function to be called when (in-sequence) data has arrived. */
+ tcp_recv_fn recv;
+ /* Function to be called when a connection has been set up. */
+ tcp_connected_fn connected;
+ /* Function which is called periodically. */
+ tcp_poll_fn poll;
+ /* Function to be called whenever a fatal error occurs. */
+ tcp_err_fn errf;
#endif /* LWIP_CALLBACK_API */
#if LWIP_TCP_TIMESTAMPS
@@ -461,242 +308,65 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
u16_t size,
err_t err);
-#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
- LWIP_EVENT_ACCEPT, NULL, 0, err)
-#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
- LWIP_EVENT_SENT, NULL, space, ERR_OK)
-#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
- LWIP_EVENT_RECV, (p), 0, (err))
-#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
- LWIP_EVENT_CONNECTED, NULL, 0, (err))
-#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
- LWIP_EVENT_POLL, NULL, 0, ERR_OK)
-#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
- LWIP_EVENT_ERR, NULL, 0, (err))
-#else /* LWIP_EVENT_API */
-
-#define TCP_EVENT_ACCEPT(pcb,err,ret) \
- do { \
- if((pcb)->accept != NULL) \
- (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \
- else (ret) = ERR_OK; \
- } while (0)
-
-#define TCP_EVENT_SENT(pcb,space,ret) \
- do { \
- if((pcb)->sent != NULL) \
- (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \
- else (ret) = ERR_OK; \
- } while (0)
-
-#define TCP_EVENT_RECV(pcb,p,err,ret) \
- do { \
- if((pcb)->recv != NULL) { \
- (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \
- } else { \
- (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \
- } \
- } while (0)
-
-#define TCP_EVENT_CONNECTED(pcb,err,ret) \
- do { \
- if((pcb)->connected != NULL) \
- (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \
- else (ret) = ERR_OK; \
- } while (0)
-
-#define TCP_EVENT_POLL(pcb,ret) \
- do { \
- if((pcb)->poll != NULL) \
- (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \
- else (ret) = ERR_OK; \
- } while (0)
-
-#define TCP_EVENT_ERR(errf,arg,err) \
- do { \
- if((errf) != NULL) \
- (errf)((arg),(err)); \
- } while (0)
-
#endif /* LWIP_EVENT_API */
-/* This structure represents a TCP segment on the unsent and unacked queues */
-struct tcp_seg {
- struct tcp_seg *next; /* used when putting segements on a queue */
- struct pbuf *p; /* buffer containing data + TCP header */
- void *dataptr; /* pointer to the TCP data in the pbuf */
- u16_t len; /* the TCP length of this segment */
- u8_t flags;
-#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */
-#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */
- struct tcp_hdr *tcphdr; /* the TCP header */
-};
+/* Application program's interface: */
+struct tcp_pcb * tcp_new (void);
-#define LWIP_TCP_OPT_LENGTH(flags) \
- (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \
- (flags & TF_SEG_OPTS_TS ? 12 : 0)
-
-/** This returns a TCP header option for MSS in an u32_t */
-#define TCP_BUILD_MSS_OPTION(x) (x) = htonl(((u32_t)2 << 24) | \
- ((u32_t)4 << 16) | \
- (((u32_t)TCP_MSS / 256) << 8) | \
- (TCP_MSS & 255))
-
-/* Internal functions and global variables: */
-struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
-void tcp_pcb_purge(struct tcp_pcb *pcb);
-void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
-
-u8_t tcp_segs_free(struct tcp_seg *seg);
-u8_t tcp_seg_free(struct tcp_seg *seg);
-struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
-
-#define tcp_ack(pcb) \
- do { \
- if((pcb)->flags & TF_ACK_DELAY) { \
- (pcb)->flags &= ~TF_ACK_DELAY; \
- (pcb)->flags |= TF_ACK_NOW; \
- tcp_output(pcb); \
- } \
- else { \
- (pcb)->flags |= TF_ACK_DELAY; \
- } \
- } while (0)
-
-#define tcp_ack_now(pcb) \
- do { \
- (pcb)->flags |= TF_ACK_NOW; \
- tcp_output(pcb); \
- } while (0)
-
-err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags);
-err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len,
- u8_t flags, u8_t apiflags, u8_t optflags);
-
-void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
-
-void tcp_rst(u32_t seqno, u32_t ackno,
- struct ip_addr *local_ip, struct ip_addr *remote_ip,
- u16_t local_port, u16_t remote_port);
-
-u32_t tcp_next_iss(void);
-
-void tcp_keepalive(struct tcp_pcb *pcb);
-void tcp_zero_window_probe(struct tcp_pcb *pcb);
-
-#if TCP_CALCULATE_EFF_SEND_MSS
-u16_t tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr);
-#endif /* TCP_CALCULATE_EFF_SEND_MSS */
+void tcp_arg (struct tcp_pcb *pcb, void *arg);
+void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept);
+void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv);
+void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent);
+void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval);
+void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err);
+
+#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss)
+#define tcp_sndbuf(pcb) ((pcb)->snd_buf)
+#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen)
+#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY)
+#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY)
+#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0)
-#if LWIP_CALLBACK_API
-err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
-#endif /* LWIP_CALLBACK_API */
+#if TCP_LISTEN_BACKLOG
+#define tcp_accepted(pcb) do { \
+ LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", pcb->state == LISTEN); \
+ (((struct tcp_pcb_listen *)(pcb))->accepts_pending--); } while(0)
+#else /* TCP_LISTEN_BACKLOG */
+#define tcp_accepted(pcb) LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", \
+ pcb->state == LISTEN)
+#endif /* TCP_LISTEN_BACKLOG */
+
+void tcp_recved (struct tcp_pcb *pcb, u16_t len);
+err_t tcp_bind (struct tcp_pcb *pcb, ip_addr_t *ipaddr,
+ u16_t port);
+err_t tcp_connect (struct tcp_pcb *pcb, ip_addr_t *ipaddr,
+ u16_t port, tcp_connected_fn connected);
+
+struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
+#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
+
+void tcp_abort (struct tcp_pcb *pcb);
+err_t tcp_close (struct tcp_pcb *pcb);
+err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx);
+
+/* Flags for "apiflags" parameter in tcp_write */
+#define TCP_WRITE_FLAG_COPY 0x01
+#define TCP_WRITE_FLAG_MORE 0x02
+
+err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
+ u8_t apiflags);
+
+void tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
+
+#define TCP_PRIO_MIN 1
+#define TCP_PRIO_NORMAL 64
+#define TCP_PRIO_MAX 127
+
+err_t tcp_output (struct tcp_pcb *pcb);
-extern struct tcp_pcb *tcp_input_pcb;
-extern u32_t tcp_ticks;
const char* tcp_debug_state_str(enum tcp_state s);
-#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
-void tcp_debug_print(struct tcp_hdr *tcphdr);
-void tcp_debug_print_flags(u8_t flags);
-void tcp_debug_print_state(enum tcp_state s);
-void tcp_debug_print_pcbs(void);
-s16_t tcp_pcbs_sane(void);
-#else
-# define tcp_debug_print(tcphdr)
-# define tcp_debug_print_flags(flags)
-# define tcp_debug_print_state(s)
-# define tcp_debug_print_pcbs()
-# define tcp_pcbs_sane() 1
-#endif /* TCP_DEBUG */
-
-#if NO_SYS
-#define tcp_timer_needed()
-#else
-void tcp_timer_needed(void);
-#endif
-/* The TCP PCB lists. */
-union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
- struct tcp_pcb_listen *listen_pcbs;
- struct tcp_pcb *pcbs;
-};
-extern union tcp_listen_pcbs_t tcp_listen_pcbs;
-extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
- state in which they accept or send
- data. */
-extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
-
-extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
-
-/* Axioms about the above lists:
- 1) Every TCP PCB that is not CLOSED is in one of the lists.
- 2) A PCB is only in one of the lists.
- 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state.
- 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state.
-*/
-
-/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
- with a PCB list or removes a PCB from a list, respectively. */
-#if 0
-#define TCP_REG(pcbs, npcb) do {\
- LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \
- for(tcp_tmp_pcb = *pcbs; \
- tcp_tmp_pcb != NULL; \
- tcp_tmp_pcb = tcp_tmp_pcb->next) { \
- LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \
- } \
- LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \
- npcb->next = *pcbs; \
- LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \
- *(pcbs) = npcb; \
- LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
- tcp_timer_needed(); \
- } while(0)
-#define TCP_RMV(pcbs, npcb) do { \
- LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \
- LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \
- if(*pcbs == npcb) { \
- *pcbs = (*pcbs)->next; \
- } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
- if(tcp_tmp_pcb->next == npcb) { \
- tcp_tmp_pcb->next = npcb->next; \
- break; \
- } \
- } \
- npcb->next = NULL; \
- LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
- LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \
- } while(0)
-
-#else /* LWIP_DEBUG */
-
-#define TCP_REG(pcbs, npcb) \
- do { \
- npcb->next = *pcbs; \
- *(pcbs) = npcb; \
- tcp_timer_needed(); \
- } while (0)
-
-#define TCP_RMV(pcbs, npcb) \
- do { \
- if(*(pcbs) == npcb) { \
- (*(pcbs)) = (*pcbs)->next; \
- } \
- else { \
- for(tcp_tmp_pcb = *pcbs; \
- tcp_tmp_pcb != NULL; \
- tcp_tmp_pcb = tcp_tmp_pcb->next) { \
- if(tcp_tmp_pcb->next == npcb) { \
- tcp_tmp_pcb->next = npcb->next; \
- break; \
- } \
- } \
- } \
- npcb->next = NULL; \
- } while(0)
-
-#endif /* LWIP_DEBUG */
#ifdef __cplusplus
}
diff --git a/core/lwip/src/include/lwip/tcp_impl.h b/core/lwip/src/include/lwip/tcp_impl.h
new file mode 100644
index 00000000..b4feec0d
--- /dev/null
+++ b/core/lwip/src/include/lwip/tcp_impl.h
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __LWIP_TCP_IMPL_H__
+#define __LWIP_TCP_IMPL_H__
+
+#include "lwip/opt.h"
+
+#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
+
+#include "lwip/tcp.h"
+#include "lwip/sys.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "lwip/ip.h"
+#include "lwip/icmp.h"
+#include "lwip/err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Functions for interfacing with TCP: */
+
+/* Lower layer interface to TCP: */
+#define tcp_init() /* Compatibility define, no init needed. */
+void tcp_tmr (void); /* Must be called every
+ TCP_TMR_INTERVAL
+ ms. (Typically 250 ms). */
+/* It is also possible to call these two functions at the right
+ intervals (instead of calling tcp_tmr()). */
+void tcp_slowtmr (void);
+void tcp_fasttmr (void);
+
+
+/* Only used by IP to pass a TCP segment to TCP: */
+void tcp_input (struct pbuf *p, struct netif *inp);
+/* Used within the TCP code only: */
+struct tcp_pcb * tcp_alloc (u8_t prio);
+void tcp_abandon (struct tcp_pcb *pcb, int reset);
+err_t tcp_send_empty_ack(struct tcp_pcb *pcb);
+void tcp_rexmit (struct tcp_pcb *pcb);
+void tcp_rexmit_rto (struct tcp_pcb *pcb);
+void tcp_rexmit_fast (struct tcp_pcb *pcb);
+u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
+
+/**
+ * This is the Nagle algorithm: try to combine user data to send as few TCP
+ * segments as possible. Only send if
+ * - no previously transmitted data on the connection remains unacknowledged or
+ * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or
+ * - the only unsent segment is at least pcb->mss bytes long (or there is more
+ * than one unsent segment - with lwIP, this can happen although unsent->len < mss)
+ * - or if we are in fast-retransmit (TF_INFR)
+ */
+#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
+ ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \
+ (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
+ ((tpcb)->unsent->len >= (tpcb)->mss))) \
+ ) ? 1 : 0)
+#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK)
+
+
+#define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0)
+#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
+#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
+#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
+/* is b<=a<=c? */
+#if 0 /* see bug #10548 */
+#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
+#endif
+#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
+#define TCP_FIN 0x01U
+#define TCP_SYN 0x02U
+#define TCP_RST 0x04U
+#define TCP_PSH 0x08U
+#define TCP_ACK 0x10U
+#define TCP_URG 0x20U
+#define TCP_ECE 0x40U
+#define TCP_CWR 0x80U
+
+#define TCP_FLAGS 0x3fU
+
+/* Length of the TCP header, excluding options. */
+#define TCP_HLEN 20
+
+#ifndef TCP_TMR_INTERVAL
+#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */
+#endif /* TCP_TMR_INTERVAL */
+
+#ifndef TCP_FAST_INTERVAL
+#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */
+#endif /* TCP_FAST_INTERVAL */
+
+#ifndef TCP_SLOW_INTERVAL
+#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */
+#endif /* TCP_SLOW_INTERVAL */
+
+#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */
+#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */
+
+#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */
+
+#ifndef TCP_MSL
+#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */
+#endif
+
+/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */
+#ifndef TCP_KEEPIDLE_DEFAULT
+#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */
+#endif
+
+#ifndef TCP_KEEPINTVL_DEFAULT
+#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */
+#endif
+
+#ifndef TCP_KEEPCNT_DEFAULT
+#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */
+#endif
+
+#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */
+
+/* Fields are (of course) in network byte order.
+ * Some fields are converted to host byte order in tcp_input().
+ */
+#ifdef PACK_STRUCT_USE_INCLUDES
+# include "arch/bpstruct.h"
+#endif
+PACK_STRUCT_BEGIN
+struct tcp_hdr {
+ PACK_STRUCT_FIELD(u16_t src);
+ PACK_STRUCT_FIELD(u16_t dest);
+ PACK_STRUCT_FIELD(u32_t seqno);
+ PACK_STRUCT_FIELD(u32_t ackno);
+ PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
+ PACK_STRUCT_FIELD(u16_t wnd);
+ PACK_STRUCT_FIELD(u16_t chksum);
+ PACK_STRUCT_FIELD(u16_t urgp);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+#ifdef PACK_STRUCT_USE_INCLUDES
+# include "arch/epstruct.h"
+#endif
+
+#define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
+#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
+#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
+
+#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
+#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
+#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
+#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags))
+
+#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
+#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
+
+#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
+
+/** Flags used on input processing, not on pcb->flags
+*/
+#define TF_RESET (u8_t)0x08U /* Connection was reset. */
+#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */
+#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
+
+
+#if LWIP_EVENT_API
+
+#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+ LWIP_EVENT_ACCEPT, NULL, 0, err)
+#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+ LWIP_EVENT_SENT, NULL, space, ERR_OK)
+#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+ LWIP_EVENT_RECV, (p), 0, (err))
+#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+ LWIP_EVENT_RECV, NULL, 0, ERR_OK)
+#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+ LWIP_EVENT_CONNECTED, NULL, 0, (err))
+#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+ LWIP_EVENT_POLL, NULL, 0, ERR_OK)
+#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
+ LWIP_EVENT_ERR, NULL, 0, (err))
+
+#else /* LWIP_EVENT_API */
+
+#define TCP_EVENT_ACCEPT(pcb,err,ret) \
+ do { \
+ if((pcb)->accept != NULL) \
+ (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \
+ else (ret) = ERR_ARG; \
+ } while (0)
+
+#define TCP_EVENT_SENT(pcb,space,ret) \
+ do { \
+ if((pcb)->sent != NULL) \
+ (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \
+ else (ret) = ERR_OK; \
+ } while (0)
+
+#define TCP_EVENT_RECV(pcb,p,err,ret) \
+ do { \
+ if((pcb)->recv != NULL) { \
+ (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\
+ } else { \
+ (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \
+ } \
+ } while (0)
+
+#define TCP_EVENT_CLOSED(pcb,ret) \
+ do { \
+ if(((pcb)->recv != NULL)) { \
+ (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\
+ } else { \
+ (ret) = ERR_OK; \
+ } \
+ } while (0)
+
+#define TCP_EVENT_CONNECTED(pcb,err,ret) \
+ do { \
+ if((pcb)->connected != NULL) \
+ (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \
+ else (ret) = ERR_OK; \
+ } while (0)
+
+#define TCP_EVENT_POLL(pcb,ret) \
+ do { \
+ if((pcb)->poll != NULL) \
+ (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \
+ else (ret) = ERR_OK; \
+ } while (0)
+
+#define TCP_EVENT_ERR(errf,arg,err) \
+ do { \
+ if((errf) != NULL) \
+ (errf)((arg),(err)); \
+ } while (0)
+
+#endif /* LWIP_EVENT_API */
+
+/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */
+#if TCP_OVERSIZE && defined(LWIP_DEBUG)
+#define TCP_OVERSIZE_DBGCHECK 1
+#else
+#define TCP_OVERSIZE_DBGCHECK 0
+#endif
+
+/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */
+#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP)
+
+/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */
+struct tcp_seg {
+ struct tcp_seg *next; /* used when putting segements on a queue */
+ struct pbuf *p; /* buffer containing data + TCP header */
+ u16_t len; /* the TCP length of this segment */
+#if TCP_OVERSIZE_DBGCHECK
+ u16_t oversize_left; /* Extra bytes available at the end of the last
+ pbuf in unsent (used for asserting vs.
+ tcp_pcb.unsent_oversized only) */
+#endif /* TCP_OVERSIZE_DBGCHECK */
+#if TCP_CHECKSUM_ON_COPY
+ u16_t chksum;
+ u8_t chksum_swapped;
+#endif /* TCP_CHECKSUM_ON_COPY */
+ u8_t flags;
+#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */
+#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */
+#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is
+ checksummed into 'chksum' */
+ struct tcp_hdr *tcphdr; /* the TCP header */
+};
+
+#define LWIP_TCP_OPT_LENGTH(flags) \
+ (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \
+ (flags & TF_SEG_OPTS_TS ? 12 : 0)
+
+/** This returns a TCP header option for MSS in an u32_t */
+#define TCP_BUILD_MSS_OPTION(x) (x) = PP_HTONL(((u32_t)2 << 24) | \
+ ((u32_t)4 << 16) | \
+ (((u32_t)TCP_MSS / 256) << 8) | \
+ (TCP_MSS & 255))
+
+/* Global variables: */
+extern struct tcp_pcb *tcp_input_pcb;
+extern u32_t tcp_ticks;
+
+/* The TCP PCB lists. */
+union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
+ struct tcp_pcb_listen *listen_pcbs;
+ struct tcp_pcb *pcbs;
+};
+extern struct tcp_pcb *tcp_bound_pcbs;
+extern union tcp_listen_pcbs_t tcp_listen_pcbs;
+extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
+ state in which they accept or send
+ data. */
+extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
+
+extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
+
+/* Axioms about the above lists:
+ 1) Every TCP PCB that is not CLOSED is in one of the lists.
+ 2) A PCB is only in one of the lists.
+ 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state.
+ 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state.
+*/
+/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
+ with a PCB list or removes a PCB from a list, respectively. */
+#ifndef TCP_DEBUG_PCB_LISTS
+#define TCP_DEBUG_PCB_LISTS 0
+#endif
+#if TCP_DEBUG_PCB_LISTS
+#define TCP_REG(pcbs, npcb) do {\
+ LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \
+ for(tcp_tmp_pcb = *(pcbs); \
+ tcp_tmp_pcb != NULL; \
+ tcp_tmp_pcb = tcp_tmp_pcb->next) { \
+ LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \
+ } \
+ LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \
+ (npcb)->next = *(pcbs); \
+ LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \
+ *(pcbs) = (npcb); \
+ LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
+ tcp_timer_needed(); \
+ } while(0)
+#define TCP_RMV(pcbs, npcb) do { \
+ LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \
+ LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \
+ if(*(pcbs) == (npcb)) { \
+ *(pcbs) = (*pcbs)->next; \
+ } else for(tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
+ if(tcp_tmp_pcb->next == (npcb)) { \
+ tcp_tmp_pcb->next = (npcb)->next; \
+ break; \
+ } \
+ } \
+ (npcb)->next = NULL; \
+ LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
+ LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \
+ } while(0)
+
+#else /* LWIP_DEBUG */
+
+#define TCP_REG(pcbs, npcb) \
+ do { \
+ (npcb)->next = *pcbs; \
+ *(pcbs) = (npcb); \
+ tcp_timer_needed(); \
+ } while (0)
+
+#define TCP_RMV(pcbs, npcb) \
+ do { \
+ if(*(pcbs) == (npcb)) { \
+ (*(pcbs)) = (*pcbs)->next; \
+ } \
+ else { \
+ for(tcp_tmp_pcb = *pcbs; \
+ tcp_tmp_pcb != NULL; \
+ tcp_tmp_pcb = tcp_tmp_pcb->next) { \
+ if(tcp_tmp_pcb->next == (npcb)) { \
+ tcp_tmp_pcb->next = (npcb)->next; \
+ break; \
+ } \
+ } \
+ } \
+ (npcb)->next = NULL; \
+ } while(0)
+
+#endif /* LWIP_DEBUG */
+
+
+/* Internal functions: */
+struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
+void tcp_pcb_purge(struct tcp_pcb *pcb);
+void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
+
+void tcp_segs_free(struct tcp_seg *seg);
+void tcp_seg_free(struct tcp_seg *seg);
+struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
+
+#define tcp_ack(pcb) \
+ do { \
+ if((pcb)->flags & TF_ACK_DELAY) { \
+ (pcb)->flags &= ~TF_ACK_DELAY; \
+ (pcb)->flags |= TF_ACK_NOW; \
+ } \
+ else { \
+ (pcb)->flags |= TF_ACK_DELAY; \
+ } \
+ } while (0)
+
+#define tcp_ack_now(pcb) \
+ do { \
+ (pcb)->flags |= TF_ACK_NOW; \
+ } while (0)
+
+err_t tcp_send_fin(struct tcp_pcb *pcb);
+err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags);
+
+void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
+
+void tcp_rst(u32_t seqno, u32_t ackno,
+ ip_addr_t *local_ip, ip_addr_t *remote_ip,
+ u16_t local_port, u16_t remote_port);
+
+u32_t tcp_next_iss(void);
+
+void tcp_keepalive(struct tcp_pcb *pcb);
+void tcp_zero_window_probe(struct tcp_pcb *pcb);
+
+#if TCP_CALCULATE_EFF_SEND_MSS
+u16_t tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr);
+#endif /* TCP_CALCULATE_EFF_SEND_MSS */
+
+#if LWIP_CALLBACK_API
+err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
+#endif /* LWIP_CALLBACK_API */
+
+#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
+void tcp_debug_print(struct tcp_hdr *tcphdr);
+void tcp_debug_print_flags(u8_t flags);
+void tcp_debug_print_state(enum tcp_state s);
+void tcp_debug_print_pcbs(void);
+s16_t tcp_pcbs_sane(void);
+#else
+# define tcp_debug_print(tcphdr)
+# define tcp_debug_print_flags(flags)
+# define tcp_debug_print_state(s)
+# define tcp_debug_print_pcbs()
+# define tcp_pcbs_sane() 1
+#endif /* TCP_DEBUG */
+
+/** External function (implemented in timers.c), called when TCP detects
+ * that a timer is needed (i.e. active- or time-wait-pcb found). */
+void tcp_timer_needed(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LWIP_TCP */
+
+#endif /* __LWIP_TCP_H__ */
diff --git a/core/lwip/src/include/lwip/tcpip.h b/core/lwip/src/include/lwip/tcpip.h
index 75393ee9..995ba8ad 100644
--- a/core/lwip/src/include/lwip/tcpip.h
+++ b/core/lwip/src/include/lwip/tcpip.h
@@ -41,31 +41,43 @@
#include "lwip/pbuf.h"
#include "lwip/api.h"
#include "lwip/sys.h"
+#include "lwip/timers.h"
#include "lwip/netif.h"
#ifdef __cplusplus
extern "C" {
#endif
+/** Define this to something that triggers a watchdog. This is called from
+ * tcpip_thread after processing a message. */
+#ifndef LWIP_TCPIP_THREAD_ALIVE
+#define LWIP_TCPIP_THREAD_ALIVE()
+#endif
+
#if LWIP_TCPIP_CORE_LOCKING
/** The global semaphore to lock the stack. */
-extern sys_sem_t lock_tcpip_core;
-#define LOCK_TCPIP_CORE() sys_sem_wait(lock_tcpip_core)
-#define UNLOCK_TCPIP_CORE() sys_sem_signal(lock_tcpip_core)
+extern sys_mutex_t lock_tcpip_core;
+#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core)
+#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core)
#define TCPIP_APIMSG(m) tcpip_apimsg_lock(m)
#define TCPIP_APIMSG_ACK(m)
#define TCPIP_NETIFAPI(m) tcpip_netifapi_lock(m)
#define TCPIP_NETIFAPI_ACK(m)
-#else
+#else /* LWIP_TCPIP_CORE_LOCKING */
#define LOCK_TCPIP_CORE()
#define UNLOCK_TCPIP_CORE()
#define TCPIP_APIMSG(m) tcpip_apimsg(m)
-#define TCPIP_APIMSG_ACK(m) sys_sem_signal(m->conn->op_completed)
+#define TCPIP_APIMSG_ACK(m) sys_sem_signal(&m->conn->op_completed)
#define TCPIP_NETIFAPI(m) tcpip_netifapi(m)
-#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(m->sem)
+#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(&m->sem)
#endif /* LWIP_TCPIP_CORE_LOCKING */
-void tcpip_init(void (* tcpip_init_done)(void *), void *arg);
+/** Function prototype for the init_done function passed to tcpip_init */
+typedef void (*tcpip_init_done_fn)(void *arg);
+/** Function prototype for functions passed to tcpip_callback() */
+typedef void (*tcpip_callback_fn)(void *ctx);
+
+void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg);
#if LWIP_NETCONN
err_t tcpip_apimsg(struct api_msg *apimsg);
@@ -83,15 +95,17 @@ err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg);
#endif /* LWIP_TCPIP_CORE_LOCKING */
#endif /* LWIP_NETIF_API */
-err_t tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block);
+err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block);
#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1)
/* free pbufs or heap memory from another context without blocking */
err_t pbuf_free_callback(struct pbuf *p);
err_t mem_free_callback(void *m);
+#if LWIP_TCPIP_TIMEOUT
err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
err_t tcpip_untimeout(sys_timeout_handler h, void *arg);
+#endif /* LWIP_TCPIP_TIMEOUT */
enum tcpip_msg_type {
#if LWIP_NETCONN
@@ -101,9 +115,11 @@ enum tcpip_msg_type {
#if LWIP_NETIF_API
TCPIP_MSG_NETIFAPI,
#endif /* LWIP_NETIF_API */
- TCPIP_MSG_CALLBACK,
+#if LWIP_TCPIP_TIMEOUT
TCPIP_MSG_TIMEOUT,
- TCPIP_MSG_UNTIMEOUT
+ TCPIP_MSG_UNTIMEOUT,
+#endif /* LWIP_TCPIP_TIMEOUT */
+ TCPIP_MSG_CALLBACK
};
struct tcpip_msg {
@@ -121,14 +137,16 @@ struct tcpip_msg {
struct netif *netif;
} inp;
struct {
- void (*f)(void *ctx);
+ tcpip_callback_fn function;
void *ctx;
} cb;
+#if LWIP_TCPIP_TIMEOUT
struct {
u32_t msecs;
sys_timeout_handler h;
void *arg;
} tmo;
+#endif /* LWIP_TCPIP_TIMEOUT */
} msg;
};
diff --git a/core/lwip/src/include/netif/loopif.h b/core/lwip/src/include/lwip/timers.h
index 304af4b3..fb92b4b4 100644
--- a/core/lwip/src/include/netif/loopif.h
+++ b/core/lwip/src/include/lwip/timers.h
@@ -27,27 +27,72 @@
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
+ * Simon Goldschmidt
*
*/
-#ifndef __NETIF_LOOPIF_H__
-#define __NETIF_LOOPIF_H__
+#ifndef __LWIP_TIMERS_H__
+#define __LWIP_TIMERS_H__
#include "lwip/opt.h"
-#include "lwip/netif.h"
+
+/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */
+#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS))
+
+#if LWIP_TIMERS
+
#include "lwip/err.h"
+#include "lwip/sys.h"
#ifdef __cplusplus
extern "C" {
#endif
-#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
-#define loopif_poll netif_poll
-#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
+#ifndef LWIP_DEBUG_TIMERNAMES
+#ifdef LWIP_DEBUG
+#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG
+#else /* LWIP_DEBUG */
+#define LWIP_DEBUG_TIMERNAMES 0
+#endif /* LWIP_DEBUG*/
+#endif
+
+/** Function prototype for a timeout callback function. Register such a function
+ * using sys_timeout().
+ *
+ * @param arg Additional argument to pass to the function - set up by sys_timeout()
+ */
+typedef void (* sys_timeout_handler)(void *arg);
+
+struct sys_timeo {
+ struct sys_timeo *next;
+ u32_t time;
+ sys_timeout_handler h;
+ void *arg;
+#if LWIP_DEBUG_TIMERNAMES
+ const char* handler_name;
+#endif /* LWIP_DEBUG_TIMERNAMES */
+};
+
+void sys_timeouts_init(void);
+
+#if LWIP_DEBUG_TIMERNAMES
+void sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name);
+#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler)
+#else /* LWIP_DEBUG_TIMERNAMES */
+void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg);
+#endif /* LWIP_DEBUG_TIMERNAMES */
+
+void sys_untimeout(sys_timeout_handler handler, void *arg);
+#if NO_SYS
+void sys_check_timeouts(void);
+void sys_restart_timeouts(void);
+#else /* NO_SYS */
+void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg);
+#endif /* NO_SYS */
-err_t loopif_init(struct netif *netif);
#ifdef __cplusplus
}
#endif
-#endif /* __NETIF_LOOPIF_H__ */
+#endif /* LWIP_TIMERS */
+#endif /* __LWIP_TIMERS_H__ */
diff --git a/core/lwip/src/include/lwip/udp.h b/core/lwip/src/include/lwip/udp.h
index 08d1817b..c98c1b3e 100644
--- a/core/lwip/src/include/lwip/udp.h
+++ b/core/lwip/src/include/lwip/udp.h
@@ -63,9 +63,30 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
-#define UDP_FLAGS_NOCHKSUM 0x01U
-#define UDP_FLAGS_UDPLITE 0x02U
-#define UDP_FLAGS_CONNECTED 0x04U
+#define UDP_FLAGS_NOCHKSUM 0x01U
+#define UDP_FLAGS_UDPLITE 0x02U
+#define UDP_FLAGS_CONNECTED 0x04U
+#define UDP_FLAGS_MULTICAST_LOOP 0x08U
+
+struct udp_pcb;
+
+/** Function prototype for udp pcb receive callback functions
+ * addr and port are in same byte order as in the pcb
+ * The callback is responsible for freeing the pbuf
+ * if it's not used any more.
+ *
+ * ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf
+ * makes 'addr' invalid, too.
+ *
+ * @param arg user supplied argument (udp_pcb.recv_arg)
+ * @param pcb the udp_pcb which received data
+ * @param p the packet buffer that was received
+ * @param addr the remote IP address from which the packet was received
+ * @param port the remote port from which the packet was received
+ */
+typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
+ ip_addr_t *addr, u16_t port);
+
struct udp_pcb {
/* Common members of all PCB types */
@@ -76,36 +97,22 @@ struct udp_pcb {
struct udp_pcb *next;
u8_t flags;
- /* ports are in host byte order */
+ /** ports are in host byte order */
u16_t local_port, remote_port;
#if LWIP_IGMP
- /* outgoing network interface for multicast packets */
- struct ip_addr multicast_ip;
+ /** outgoing network interface for multicast packets */
+ ip_addr_t multicast_ip;
#endif /* LWIP_IGMP */
#if LWIP_UDPLITE
- /* used for UDP_LITE only */
+ /** used for UDP_LITE only */
u16_t chksum_len_rx, chksum_len_tx;
#endif /* LWIP_UDPLITE */
- /* receive callback function
- * addr and port are in same byte order as in the pcb
- * The callback is responsible for freeing the pbuf
- * if it's not used any more.
- *
- * ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf
- * makes 'addr' invalid, too.
- *
- * @param arg user supplied argument (udp_pcb.recv_arg)
- * @param pcb the udp_pcb which received data
- * @param p the packet buffer that was received
- * @param addr the remote IP address from which the packet was received
- * @param port the remote port from which the packet was received
- */
- void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
- struct ip_addr *addr, u16_t port);
- /* user-supplied argument for the recv callback */
+ /** receive callback function */
+ udp_recv_fn recv;
+ /** user-supplied argument for the recv callback */
void *recv_arg;
};
/* udp_pcbs export for exernal reference (e.g. SNMP agent) */
@@ -115,22 +122,33 @@ extern struct udp_pcb *udp_pcbs;
UDP code. */
struct udp_pcb * udp_new (void);
void udp_remove (struct udp_pcb *pcb);
-err_t udp_bind (struct udp_pcb *pcb, struct ip_addr *ipaddr,
- u16_t port);
-err_t udp_connect (struct udp_pcb *pcb, struct ip_addr *ipaddr,
- u16_t port);
-void udp_disconnect (struct udp_pcb *pcb);
-void udp_recv (struct udp_pcb *pcb,
- void (* recv)(void *arg, struct udp_pcb *upcb,
- struct pbuf *p,
- struct ip_addr *addr,
- u16_t port),
- void *recv_arg);
-err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port, struct netif *netif);
-err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port);
+err_t udp_bind (struct udp_pcb *pcb, ip_addr_t *ipaddr,
+ u16_t port);
+err_t udp_connect (struct udp_pcb *pcb, ip_addr_t *ipaddr,
+ u16_t port);
+void udp_disconnect (struct udp_pcb *pcb);
+void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv,
+ void *recv_arg);
+err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p,
+ ip_addr_t *dst_ip, u16_t dst_port,
+ struct netif *netif);
+err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p,
+ ip_addr_t *dst_ip, u16_t dst_port);
err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);
-#define udp_flags(pcb) ((pcb)->flags)
+#if LWIP_CHECKSUM_ON_COPY
+err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p,
+ ip_addr_t *dst_ip, u16_t dst_port,
+ struct netif *netif, u8_t have_chksum,
+ u16_t chksum);
+err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p,
+ ip_addr_t *dst_ip, u16_t dst_port,
+ u8_t have_chksum, u16_t chksum);
+err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
+ u8_t have_chksum, u16_t chksum);
+#endif /* LWIP_CHECKSUM_ON_COPY */
+
+#define udp_flags(pcb) ((pcb)->flags)
#define udp_setflags(pcb, f) ((pcb)->flags = (f))
/* The following functions are the lower layer interface to UDP. */
diff --git a/core/lwip/src/include/lwipopts.h b/core/lwip/src/include/lwipopts.h
index 2f0ba032..e0d39b89 100644
--- a/core/lwip/src/include/lwipopts.h
+++ b/core/lwip/src/include/lwipopts.h
@@ -2,6 +2,7 @@
#define __LWIPOPTS_H__
#include <byteswap.h>
+#include <netinet/in.h>
#define SYS_LIGHTWEIGHT_PROT 1
#define LWIP_NETIF_API 1
@@ -65,5 +66,8 @@
#define LWIP_PLATFORM_HTONS(x) bswap_16(x)
#define LWIP_PLATFORM_HTONL(x) bswap_32(x)
+#define LWIP_PREFIX_BYTEORDER_FUNCS 0
+#define LWIP_COMPAT_MUTEX 1
+
void undiarp_tmr(void);
#endif /* __LWIPOPTS_H__ */
diff --git a/core/lwip/src/include/netif/etharp.h b/core/lwip/src/include/netif/etharp.h
index 72b8d79f..691575fa 100644
--- a/core/lwip/src/include/netif/etharp.h
+++ b/core/lwip/src/include/netif/etharp.h
@@ -37,7 +37,7 @@
#include "lwip/opt.h"
-#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
+#if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
@@ -48,10 +48,6 @@
extern "C" {
#endif
-#ifndef ETH_PAD_SIZE
-#define ETH_PAD_SIZE 0
-#endif
-
#ifndef ETHARP_HWADDR_LEN
#define ETHARP_HWADDR_LEN 6
#endif
@@ -72,6 +68,7 @@ PACK_STRUCT_END
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
+/** Ethernet header */
struct eth_hdr {
#if ETH_PAD_SIZE
PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
@@ -93,9 +90,12 @@ PACK_STRUCT_END
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
+/** VLAN header inserted between ethernet header and payload
+ * if 'type' in ethernet header is ETHTYPE_VLAN.
+ * See IEEE802.Q */
struct eth_vlan_hdr {
- PACK_STRUCT_FIELD(u16_t tpid);
PACK_STRUCT_FIELD(u16_t prio_vid);
+ PACK_STRUCT_FIELD(u16_t tpid);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
@@ -111,11 +111,12 @@ PACK_STRUCT_END
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
-/** the ARP message */
+/** the ARP message, see RFC 826 ("Packet format") */
struct etharp_hdr {
PACK_STRUCT_FIELD(u16_t hwtype);
PACK_STRUCT_FIELD(u16_t proto);
- PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
+ PACK_STRUCT_FIELD(u8_t hwlen);
+ PACK_STRUCT_FIELD(u8_t protolen);
PACK_STRUCT_FIELD(u16_t opcode);
PACK_STRUCT_FIELD(struct eth_addr shwaddr);
PACK_STRUCT_FIELD(struct ip_addr2 sipaddr);
@@ -133,16 +134,40 @@ PACK_STRUCT_END
/** 5 seconds period */
#define ARP_TMR_INTERVAL 5000
-#define ETHTYPE_ARP 0x0806
-#define ETHTYPE_IP 0x0800
-#define ETHTYPE_VLAN 0x8100
-#define ETHTYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */
-#define ETHTYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */
+#define ETHTYPE_ARP 0x0806U
+#define ETHTYPE_IP 0x0800U
+#define ETHTYPE_VLAN 0x8100U
+#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */
+#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */
+
+/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables
+ * or known to be 32-bit aligned within the protocol header. */
+#ifndef ETHADDR32_COPY
+#define ETHADDR32_COPY(src, dst) SMEMCPY(src, dst, ETHARP_HWADDR_LEN)
+#endif
+
+/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local
+ * variables and known to be 16-bit aligned within the protocol header. */
+#ifndef ETHADDR16_COPY
+#define ETHADDR16_COPY(src, dst) SMEMCPY(src, dst, ETHARP_HWADDR_LEN)
+#endif
+
+#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
/** ARP message types (opcodes) */
#define ARP_REQUEST 1
#define ARP_REPLY 2
+/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type)
+ * to a filter function that returns the correct netif when using multiple
+ * netifs on one hardware interface where the netif's low-level receive
+ * routine cannot decide for the correct netif (e.g. when mapping multiple
+ * IP addresses to one hardware interface).
+ */
+#ifndef LWIP_ARP_FILTER_NETIF
+#define LWIP_ARP_FILTER_NETIF 0
+#endif
+
#if ARP_QUEUEING
/** struct for queueing outgoing packets for unknown address
* defined here to be accessed by memp.h
@@ -155,38 +180,42 @@ struct etharp_q_entry {
#define etharp_init() /* Compatibility define, not init needed. */
void etharp_tmr(void);
-s8_t etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
- struct eth_addr **eth_ret, struct ip_addr **ip_ret);
-void etharp_ip_input(struct netif *netif, struct pbuf *p);
-void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
- struct pbuf *p);
-err_t etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr);
-err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q);
-err_t etharp_request(struct netif *netif, struct ip_addr *ipaddr);
+s8_t etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr,
+ struct eth_addr **eth_ret, ip_addr_t **ip_ret);
+err_t etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr);
+err_t etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q);
+err_t etharp_request(struct netif *netif, ip_addr_t *ipaddr);
/** For Ethernet network interfaces, we might want to send "gratuitous ARP";
* this is an ARP packet sent by a node in order to spontaneously cause other
* nodes to update an entry in their ARP cache.
* From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */
#define etharp_gratuitous(netif) etharp_request((netif), &(netif)->ip_addr)
-err_t ethernet_input(struct pbuf *p, struct netif *netif);
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+err_t etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr);
+err_t etharp_remove_static_entry(ip_addr_t *ipaddr);
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
#if LWIP_AUTOIP
err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
const struct eth_addr *ethdst_addr,
- const struct eth_addr *hwsrc_addr, const struct ip_addr *ipsrc_addr,
- const struct eth_addr *hwdst_addr, const struct ip_addr *ipdst_addr,
+ const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr,
+ const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr,
const u16_t opcode);
#endif /* LWIP_AUTOIP */
+#endif /* LWIP_ARP */
+
+err_t ethernet_input(struct pbuf *p, struct netif *netif);
+
#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETHARP_HWADDR_LEN) == 0)
extern const struct eth_addr ethbroadcast, ethzero;
+#endif /* LWIP_ARP || LWIP_ETHERNET */
+
#ifdef __cplusplus
}
#endif
-#endif /* LWIP_ARP */
-
#endif /* __NETIF_ARP_H__ */
diff --git a/core/lwip/src/include/netif/ppp_oe.h b/core/lwip/src/include/netif/ppp_oe.h
index 3aa55aec..e1cdfa51 100644
--- a/core/lwip/src/include/netif/ppp_oe.h
+++ b/core/lwip/src/include/netif/ppp_oe.h
@@ -74,15 +74,17 @@
#if PPPOE_SUPPORT > 0
+#include "netif/etharp.h"
+
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct pppoehdr {
- PACK_STRUCT_FIELD(u8_t vertype);
- PACK_STRUCT_FIELD(u8_t code);
- PACK_STRUCT_FIELD(u16_t session);
- PACK_STRUCT_FIELD(u16_t plen);
+ PACK_STRUCT_FIELD(u8_t vertype);
+ PACK_STRUCT_FIELD(u8_t code);
+ PACK_STRUCT_FIELD(u16_t session);
+ PACK_STRUCT_FIELD(u16_t plen);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
@@ -94,8 +96,8 @@ PACK_STRUCT_END
#endif
PACK_STRUCT_BEGIN
struct pppoetag {
- PACK_STRUCT_FIELD(u16_t tag);
- PACK_STRUCT_FIELD(u16_t len);
+ PACK_STRUCT_FIELD(u16_t tag);
+ PACK_STRUCT_FIELD(u16_t len);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
@@ -103,45 +105,71 @@ PACK_STRUCT_END
#endif
-#define PPPOE_STATE_INITIAL 0
-#define PPPOE_STATE_PADI_SENT 1
-#define PPPOE_STATE_PADR_SENT 2
-#define PPPOE_STATE_SESSION 3
-#define PPPOE_STATE_CLOSING 4
+#define PPPOE_STATE_INITIAL 0
+#define PPPOE_STATE_PADI_SENT 1
+#define PPPOE_STATE_PADR_SENT 2
+#define PPPOE_STATE_SESSION 3
+#define PPPOE_STATE_CLOSING 4
/* passive */
-#define PPPOE_STATE_PADO_SENT 1
-
-#define PPPOE_HEADERLEN sizeof(struct pppoehdr)
-#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */
-
-#define PPPOE_TAG_EOL 0x0000 /* end of list */
-#define PPPOE_TAG_SNAME 0x0101 /* service name */
-#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */
-#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */
-#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */
-#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */
-#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */
-#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */
-#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */
-#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */
-
-#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */
-#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */
-#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */
-#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */
-#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */
+#define PPPOE_STATE_PADO_SENT 1
+
+#define PPPOE_HEADERLEN sizeof(struct pppoehdr)
+#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */
+
+#define PPPOE_TAG_EOL 0x0000 /* end of list */
+#define PPPOE_TAG_SNAME 0x0101 /* service name */
+#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */
+#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */
+#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */
+#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */
+#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */
+#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */
+#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */
+#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */
+
+#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */
+#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */
+#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */
+#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */
+#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */
#ifndef ETHERMTU
#define ETHERMTU 1500
#endif
/* two byte PPP protocol discriminator, then IP data */
-#define PPPOE_MAXMTU (ETHERMTU-PPPOE_HEADERLEN-2)
+#define PPPOE_MAXMTU (ETHERMTU-PPPOE_HEADERLEN-2)
+
+#ifndef PPPOE_MAX_AC_COOKIE_LEN
+#define PPPOE_MAX_AC_COOKIE_LEN 64
+#endif
-struct pppoe_softc;
+struct pppoe_softc {
+ struct pppoe_softc *next;
+ struct netif *sc_ethif; /* ethernet interface we are using */
+ int sc_pd; /* ppp unit number */
+ void (*sc_linkStatusCB)(int pd, int up);
+
+ int sc_state; /* discovery phase or session connected */
+ struct eth_addr sc_dest; /* hardware address of concentrator */
+ u16_t sc_session; /* PPPoE session id */
+
+#ifdef PPPOE_TODO
+ char *sc_service_name; /* if != NULL: requested name of service */
+ char *sc_concentrator_name; /* if != NULL: requested concentrator id */
+#endif /* PPPOE_TODO */
+ u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */
+ size_t sc_ac_cookie_len; /* length of cookie data */
+#ifdef PPPOE_SERVER
+ u8_t *sc_hunique; /* content of host unique we must echo back */
+ size_t sc_hunique_len; /* length of host unique */
+#endif
+ int sc_padi_retried; /* number of PADI retries already done */
+ int sc_padr_retried; /* number of PADR retries already done */
+};
-void pppoe_init(void);
+#define pppoe_init() /* compatibility define, no initialization needed */
err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr);
err_t pppoe_destroy(struct netif *ifp);
@@ -154,7 +182,8 @@ void pppoe_data_input(struct netif *netif, struct pbuf *p);
err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb);
-extern int pppoe_hdrlen;
+/** used in ppp.c */
+#define PPPOE_HDRLEN (sizeof(struct eth_hdr) + PPPOE_HEADERLEN)
#endif /* PPPOE_SUPPORT */
diff --git a/core/lwip/src/netif/etharp.c b/core/lwip/src/netif/etharp.c
index 8f6872fa..b60dadd0 100644
--- a/core/lwip/src/netif/etharp.c
+++ b/core/lwip/src/netif/etharp.c
@@ -45,9 +45,10 @@
#include "lwip/opt.h"
-#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
+#if LWIP_ARP || LWIP_ETHERNET
-#include "lwip/inet.h"
+#include "lwip/ip_addr.h"
+#include "lwip/def.h"
#include "lwip/ip.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
@@ -61,6 +62,11 @@
#include <string.h>
+const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
+const struct eth_addr ethzero = {{0,0,0,0,0,0}};
+
+#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
+
/** the time an ARP entry stays valid after its last update,
* for ARP_TMR_INTERVAL = 5000, this is
* (240 * 5) seconds = 20 minutes.
@@ -77,12 +83,6 @@
#define HWTYPE_ETHERNET 1
-#define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8)
-#define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff)
-
-#define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8))
-#define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8))
-
enum etharp_state {
ETHARP_STATE_EMPTY = 0,
ETHARP_STATE_PENDING,
@@ -91,45 +91,49 @@ enum etharp_state {
struct etharp_entry {
#if ARP_QUEUEING
- /**
- * Pointer to queue of pending outgoing packets on this ARP entry.
- */
+ /** Pointer to queue of pending outgoing packets on this ARP entry. */
struct etharp_q_entry *q;
-#endif
- struct ip_addr ipaddr;
+#else /* ARP_QUEUEING */
+ /** Pointer to a single pending outgoing packet on this ARP entry. */
+ struct pbuf *q;
+#endif /* ARP_QUEUEING */
+ ip_addr_t ipaddr;
struct eth_addr ethaddr;
- enum etharp_state state;
- u8_t ctime;
+#if LWIP_SNMP
struct netif *netif;
+#endif /* LWIP_SNMP */
+ u8_t state;
+ u8_t ctime;
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+ u8_t static_entry;
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
};
-const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
-const struct eth_addr ethzero = {{0,0,0,0,0,0}};
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
+
#if !LWIP_NETIF_HWADDRHINT
static u8_t etharp_cached_entry;
-#endif
+#endif /* !LWIP_NETIF_HWADDRHINT */
-/**
- * Try hard to create a new entry - we want the IP address to appear in
- * the cache (even if this means removing an active entry or so). */
-#define ETHARP_TRY_HARD 1
-#define ETHARP_FIND_ONLY 2
+/** Try hard to create a new entry - we want the IP address to appear in
+ the cache (even if this means removing an active entry or so). */
+#define ETHARP_FLAG_TRY_HARD 1
+#define ETHARP_FLAG_FIND_ONLY 2
+#define ETHARP_FLAG_STATIC_ENTRY 4
#if LWIP_NETIF_HWADDRHINT
-#define NETIF_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \
+#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \
*((netif)->addr_hint) = (hint);
-static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif);
#else /* LWIP_NETIF_HWADDRHINT */
-static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags);
+#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint))
#endif /* LWIP_NETIF_HWADDRHINT */
-static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
+static err_t update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags);
/* Some checks, instead of etharp_init(): */
#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
- #error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h"
+ #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h"
#endif
@@ -153,12 +157,46 @@ free_etharp_q(struct etharp_q_entry *q)
memp_free(MEMP_ARP_QUEUE, r);
}
}
-#endif
+#else /* ARP_QUEUEING */
+
+/** Compatibility define: free the queued pbuf */
+#define free_etharp_q(q) pbuf_free(q)
+
+#endif /* ARP_QUEUEING */
+
+/** Clean up ARP table entries */
+static void
+free_entry(int i)
+{
+ /* remove from SNMP ARP index tree */
+ snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
+ /* and empty packet queue */
+ if (arp_table[i].q != NULL) {
+ /* remove all queued packets */
+ LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
+ free_etharp_q(arp_table[i].q);
+ arp_table[i].q = NULL;
+ }
+ /* recycle entry for re-use */
+ arp_table[i].state = ETHARP_STATE_EMPTY;
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+ arp_table[i].static_entry = 0;
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+#ifdef LWIP_DEBUG
+ /* for debugging, clean out the complete entry */
+ arp_table[i].ctime = 0;
+#if LWIP_SNMP
+ arp_table[i].netif = NULL;
+#endif /* LWIP_SNMP */
+ ip_addr_set_zero(&arp_table[i].ipaddr);
+ arp_table[i].ethaddr = ethzero;
+#endif /* LWIP_DEBUG */
+}
/**
* Clears expired entries in the ARP table.
*
- * This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds),
+ * This function should be called every ETHARP_TMR_INTERVAL milliseconds (5 seconds),
* in order to expire entries in the ARP table.
*/
void
@@ -169,35 +207,29 @@ etharp_tmr(void)
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
/* remove expired entries from the ARP table */
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
- arp_table[i].ctime++;
- if (((arp_table[i].state == ETHARP_STATE_STABLE) &&
- (arp_table[i].ctime >= ARP_MAXAGE)) ||
- ((arp_table[i].state == ETHARP_STATE_PENDING) &&
- (arp_table[i].ctime >= ARP_MAXPENDING))) {
- /* pending or stable entry has become old! */
- LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
- arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
- /* clean up entries that have just been expired */
- /* remove from SNMP ARP index tree */
- snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
-#if ARP_QUEUEING
- /* and empty packet queue */
- if (arp_table[i].q != NULL) {
- /* remove all queued packets */
- LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
- free_etharp_q(arp_table[i].q);
- arp_table[i].q = NULL;
+ u8_t state = arp_table[i].state;
+ if (state != ETHARP_STATE_EMPTY
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+ && (arp_table[i].static_entry == 0)
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+ ) {
+ arp_table[i].ctime++;
+ if ((arp_table[i].ctime >= ARP_MAXAGE) ||
+ ((arp_table[i].state == ETHARP_STATE_PENDING) &&
+ (arp_table[i].ctime >= ARP_MAXPENDING))) {
+ /* pending or stable entry has become old! */
+ LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
+ arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
+ /* clean up entries that have just been expired */
+ free_entry(i);
}
-#endif
- /* recycle entry for re-use */
- arp_table[i].state = ETHARP_STATE_EMPTY;
- }
#if ARP_QUEUEING
- /* still pending entry? (not expired) */
- if (arp_table[i].state == ETHARP_STATE_PENDING) {
+ /* still pending entry? (not expired) */
+ if (arp_table[i].state == ETHARP_STATE_PENDING) {
/* resend an ARP query here? */
+ }
+#endif /* ARP_QUEUEING */
}
-#endif
}
}
@@ -212,62 +244,26 @@ etharp_tmr(void)
* If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.
*
* In all cases, attempt to create new entries from an empty entry. If no
- * empty entries are available and ETHARP_TRY_HARD flag is set, recycle
+ * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle
* old entries. Heuristic choose the least important entry for recycling.
*
* @param ipaddr IP address to find in ARP cache, or to add if not found.
- * @param flags
- * - ETHARP_TRY_HARD: Try hard to create a entry by allowing recycling of
- * active (stable or pending) entries.
+ * @param flags @see definition of ETHARP_FLAG_*
+ * @param netif netif related to this address (used for NETIF_HWADDRHINT)
*
* @return The ARP entry index that matched or is created, ERR_MEM if no
* entry is found or could be recycled.
*/
static s8_t
-#if LWIP_NETIF_HWADDRHINT
-find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif)
-#else /* LWIP_NETIF_HWADDRHINT */
-find_entry(struct ip_addr *ipaddr, u8_t flags)
-#endif /* LWIP_NETIF_HWADDRHINT */
+find_entry(ip_addr_t *ipaddr, u8_t flags)
{
s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
s8_t empty = ARP_TABLE_SIZE;
u8_t i = 0, age_pending = 0, age_stable = 0;
-#if ARP_QUEUEING
/* oldest entry with packets on queue */
s8_t old_queue = ARP_TABLE_SIZE;
/* its age */
u8_t age_queue = 0;
-#endif
-
- /* First, test if the last call to this function asked for the
- * same address. If so, we're really fast! */
- if (ipaddr) {
- /* ipaddr to search for was given */
-#if LWIP_NETIF_HWADDRHINT
- if ((netif != NULL) && (netif->addr_hint != NULL)) {
- /* per-pcb cached entry was given */
- u8_t per_pcb_cache = *(netif->addr_hint);
- if ((per_pcb_cache < ARP_TABLE_SIZE) && arp_table[per_pcb_cache].state == ETHARP_STATE_STABLE) {
- /* the per-pcb-cached entry is stable */
- if (ip_addr_cmp(ipaddr, &arp_table[per_pcb_cache].ipaddr)) {
- /* per-pcb cached entry was the right one! */
- ETHARP_STATS_INC(etharp.cachehit);
- return per_pcb_cache;
- }
- }
- }
-#else /* #if LWIP_NETIF_HWADDRHINT */
- if (arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) {
- /* the cached entry is stable */
- if (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr)) {
- /* cached entry was the right one! */
- ETHARP_STATS_INC(etharp.cachehit);
- return etharp_cached_entry;
- }
- }
-#endif /* #if LWIP_NETIF_HWADDRHINT */
- }
/**
* a) do a search through the cache, remember candidates
@@ -285,65 +281,59 @@ find_entry(struct ip_addr *ipaddr, u8_t flags)
*/
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
+ u8_t state = arp_table[i].state;
/* no empty entry found yet and now we do find one? */
- if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) {
+ if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) {
LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i));
/* remember first empty entry */
empty = i;
- }
- /* pending entry? */
- else if (arp_table[i].state == ETHARP_STATE_PENDING) {
+ } else if (state != ETHARP_STATE_EMPTY) {
+ LWIP_ASSERT("state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE",
+ state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE);
/* if given, does IP address match IP address in ARP entry? */
if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i));
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching entry %"U16_F"\n", (u16_t)i));
/* found exact IP address match, simply bail out */
-#if LWIP_NETIF_HWADDRHINT
- NETIF_SET_HINT(netif, i);
-#else /* #if LWIP_NETIF_HWADDRHINT */
- etharp_cached_entry = i;
-#endif /* #if LWIP_NETIF_HWADDRHINT */
return i;
-#if ARP_QUEUEING
- /* pending with queued packets? */
- } else if (arp_table[i].q != NULL) {
- if (arp_table[i].ctime >= age_queue) {
- old_queue = i;
- age_queue = arp_table[i].ctime;
+ }
+ /* pending entry? */
+ if (state == ETHARP_STATE_PENDING) {
+ /* pending with queued packets? */
+ if (arp_table[i].q != NULL) {
+ if (arp_table[i].ctime >= age_queue) {
+ old_queue = i;
+ age_queue = arp_table[i].ctime;
+ }
+ } else
+ /* pending without queued packets? */
+ {
+ if (arp_table[i].ctime >= age_pending) {
+ old_pending = i;
+ age_pending = arp_table[i].ctime;
+ }
}
-#endif
- /* pending without queued packets? */
- } else {
- if (arp_table[i].ctime >= age_pending) {
- old_pending = i;
- age_pending = arp_table[i].ctime;
+ /* stable entry? */
+ } else if (state == ETHARP_STATE_STABLE) {
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+ /* don't record old_stable for static entries since they never expire */
+ if (arp_table[i].static_entry == 0)
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+ {
+ /* remember entry with oldest stable entry in oldest, its age in maxtime */
+ if (arp_table[i].ctime >= age_stable) {
+ old_stable = i;
+ age_stable = arp_table[i].ctime;
+ }
}
- }
- }
- /* stable entry? */
- else if (arp_table[i].state == ETHARP_STATE_STABLE) {
- /* if given, does IP address match IP address in ARP entry? */
- if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i));
- /* found exact IP address match, simply bail out */
-#if LWIP_NETIF_HWADDRHINT
- NETIF_SET_HINT(netif, i);
-#else /* #if LWIP_NETIF_HWADDRHINT */
- etharp_cached_entry = i;
-#endif /* #if LWIP_NETIF_HWADDRHINT */
- return i;
- /* remember entry with oldest stable entry in oldest, its age in maxtime */
- } else if (arp_table[i].ctime >= age_stable) {
- old_stable = i;
- age_stable = arp_table[i].ctime;
}
}
}
/* { we have no match } => try to create a new entry */
- /* no empty entry found and not allowed to recycle? */
- if (((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0))
- /* or don't create new entry, only search? */
- || ((flags & ETHARP_FIND_ONLY) != 0)) {
+ /* don't create new entry, only search? */
+ if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
+ /* or no empty entry found and not allowed to recycle? */
+ ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty entry found and not allowed to recycle\n"));
return (s8_t)ERR_MEM;
}
@@ -354,63 +344,55 @@ find_entry(struct ip_addr *ipaddr, u8_t flags)
* 3) oldest pending entry without queued packets
* 4) oldest pending entry with queued packets
*
- * { ETHARP_TRY_HARD is set at this point }
+ * { ETHARP_FLAG_TRY_HARD is set at this point }
*/
/* 1) empty entry available? */
if (empty < ARP_TABLE_SIZE) {
i = empty;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
- }
- /* 2) found recyclable stable entry? */
- else if (old_stable < ARP_TABLE_SIZE) {
- /* recycle oldest stable*/
- i = old_stable;
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
-#if ARP_QUEUEING
- /* no queued packets should exist on stable entries */
- LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
-#endif
- /* 3) found recyclable pending entry without queued packets? */
- } else if (old_pending < ARP_TABLE_SIZE) {
- /* recycle oldest pending */
- i = old_pending;
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
-#if ARP_QUEUEING
- /* 4) found recyclable pending entry with queued packets? */
- } else if (old_queue < ARP_TABLE_SIZE) {
- /* recycle oldest pending */
- i = old_queue;
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
- free_etharp_q(arp_table[i].q);
- arp_table[i].q = NULL;
-#endif
- /* no empty or recyclable entries found */
} else {
- return (s8_t)ERR_MEM;
+ /* 2) found recyclable stable entry? */
+ if (old_stable < ARP_TABLE_SIZE) {
+ /* recycle oldest stable*/
+ i = old_stable;
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
+ /* no queued packets should exist on stable entries */
+ LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
+ /* 3) found recyclable pending entry without queued packets? */
+ } else if (old_pending < ARP_TABLE_SIZE) {
+ /* recycle oldest pending */
+ i = old_pending;
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
+ /* 4) found recyclable pending entry with queued packets? */
+ } else if (old_queue < ARP_TABLE_SIZE) {
+ /* recycle oldest pending (queued packets are free in free_entry) */
+ i = old_queue;
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
+ /* no empty or recyclable entries found */
+ } else {
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty or recyclable entries found\n"));
+ return (s8_t)ERR_MEM;
+ }
+
+ /* { empty or recyclable entry found } */
+ LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
+ free_entry(i);
}
- /* { empty or recyclable entry found } */
LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
-
- if (arp_table[i].state != ETHARP_STATE_EMPTY)
- {
- snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
- }
- /* recycle entry (no-op for an already empty entry) */
- arp_table[i].state = ETHARP_STATE_EMPTY;
+ LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY",
+ arp_table[i].state == ETHARP_STATE_EMPTY);
/* IP address given? */
if (ipaddr != NULL) {
/* set IP address */
- ip_addr_set(&arp_table[i].ipaddr, ipaddr);
+ ip_addr_copy(arp_table[i].ipaddr, *ipaddr);
}
arp_table[i].ctime = 0;
-#if LWIP_NETIF_HWADDRHINT
- NETIF_SET_HINT(netif, i);
-#else /* #if LWIP_NETIF_HWADDRHINT */
- etharp_cached_entry = i;
-#endif /* #if LWIP_NETIF_HWADDRHINT */
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+ arp_table[i].static_entry = 0;
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
return (err_t)i;
}
@@ -427,18 +409,13 @@ find_entry(struct ip_addr *ipaddr, u8_t flags)
static err_t
etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
{
- struct eth_hdr *ethhdr = p->payload;
- u8_t k;
+ struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
(netif->hwaddr_len == ETHARP_HWADDR_LEN));
- k = ETHARP_HWADDR_LEN;
- while(k > 0) {
- k--;
- ethhdr->dest.addr[k] = dst->addr[k];
- ethhdr->src.addr[k] = src->addr[k];
- }
- ethhdr->type = htons(ETHTYPE_IP);
+ ETHADDR32_COPY(&ethhdr->dest, dst);
+ ETHADDR16_COPY(&ethhdr->src, src);
+ ethhdr->type = PP_HTONS(ETHTYPE_IP);
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p));
/* send the packet */
return netif->linkoutput(netif, p);
@@ -450,30 +427,27 @@ etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct
* If a pending entry is resolved, any queued packets will be sent
* at this point.
*
+ * @param netif netif related to this entry (used for NETIF_ADDRHINT)
* @param ipaddr IP address of the inserted ARP entry.
* @param ethaddr Ethernet address of the inserted ARP entry.
- * @param flags Defines behaviour:
- * - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified,
- * only existing ARP entries will be updated.
+ * @param flags @see definition of ETHARP_FLAG_*
*
* @return
* - ERR_OK Succesfully updated ARP cache.
- * - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set.
+ * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set.
* - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
*
* @see pbuf_free()
*/
static err_t
-update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
+update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
{
s8_t i;
- u8_t k;
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry()\n"));
LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN);
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
- ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr),
- ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
- ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
+ ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
+ ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
+ ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
/* non-unicast address? */
if (ip_addr_isany(ipaddr) ||
ip_addr_isbroadcast(ipaddr, netif) ||
@@ -482,34 +456,36 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
return ERR_ARG;
}
/* find or create ARP entry */
-#if LWIP_NETIF_HWADDRHINT
- i = find_entry(ipaddr, flags, netif);
-#else /* LWIP_NETIF_HWADDRHINT */
i = find_entry(ipaddr, flags);
-#endif /* LWIP_NETIF_HWADDRHINT */
/* bail out if no entry could be found */
- if (i < 0)
+ if (i < 0) {
return (err_t)i;
-
+ }
+
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+ if (flags & ETHARP_FLAG_STATIC_ENTRY) {
+ /* record static type */
+ arp_table[i].static_entry = 1;
+ }
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+
/* mark it stable */
arp_table[i].state = ETHARP_STATE_STABLE;
+
+#if LWIP_SNMP
/* record network interface */
arp_table[i].netif = netif;
-
+#endif /* LWIP_SNMP */
/* insert in SNMP ARP index tree */
snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr);
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
/* update address */
- k = ETHARP_HWADDR_LEN;
- while (k > 0) {
- k--;
- arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
- }
+ ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr);
/* reset time stamp */
arp_table[i].ctime = 0;
-#if ARP_QUEUEING
/* this is where we will send out queued packets! */
+#if ARP_QUEUEING
while (arp_table[i].q != NULL) {
struct pbuf *p;
/* remember remainder of queue */
@@ -520,15 +496,78 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
p = q->p;
/* now queue entry can be freed */
memp_free(MEMP_ARP_QUEUE, q);
+#else /* ARP_QUEUEING */
+ if (arp_table[i].q != NULL) {
+ struct pbuf *p = arp_table[i].q;
+ arp_table[i].q = NULL;
+#endif /* ARP_QUEUEING */
/* send the queued IP packet */
etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);
/* free the queued IP packet */
pbuf_free(p);
}
-#endif
return ERR_OK;
}
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+/** Add a new static entry to the ARP table. If an entry exists for the
+ * specified IP address, this entry is overwritten.
+ * If packets are queued for the specified IP address, they are sent out.
+ *
+ * @param ipaddr IP address for the new static entry
+ * @param ethaddr ethernet address for the new static entry
+ * @return @see return values of etharp_add_static_entry
+ */
+err_t
+etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr)
+{
+ struct netif *netif;
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
+ ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
+ ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
+ ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
+
+ netif = ip_route(ipaddr);
+ if (netif == NULL) {
+ return ERR_RTE;
+ }
+
+ return update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
+}
+
+/** Remove a static entry from the ARP table previously added with a call to
+ * etharp_add_static_entry.
+ *
+ * @param ipaddr IP address of the static entry to remove
+ * @return ERR_OK: entry removed
+ * ERR_MEM: entry wasn't found
+ * ERR_ARG: entry wasn't a static entry but a dynamic one
+ */
+err_t
+etharp_remove_static_entry(ip_addr_t *ipaddr)
+{
+ s8_t i;
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
+
+ /* find or create ARP entry */
+ i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
+ /* bail out if no entry could be found */
+ if (i < 0) {
+ return (err_t)i;
+ }
+
+ if ((arp_table[i].state != ETHARP_STATE_STABLE) ||
+ (arp_table[i].static_entry == 0)) {
+ /* entry wasn't a static entry, cannot remove it */
+ return ERR_ARG;
+ }
+ /* entry found, free it */
+ free_entry(i);
+ return ERR_OK;
+}
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+
/**
* Finds (stable) ethernet/IP address pair from ARP table
* using interface and IP address index.
@@ -541,18 +580,17 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
* @return table index if found, -1 otherwise
*/
s8_t
-etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
- struct eth_addr **eth_ret, struct ip_addr **ip_ret)
+etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr,
+ struct eth_addr **eth_ret, ip_addr_t **ip_ret)
{
s8_t i;
+ LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL",
+ eth_ret != NULL && ip_ret != NULL);
+
LWIP_UNUSED_ARG(netif);
-#if LWIP_NETIF_HWADDRHINT
- i = find_entry(ipaddr, ETHARP_FIND_ONLY, NULL);
-#else /* LWIP_NETIF_HWADDRHINT */
- i = find_entry(ipaddr, ETHARP_FIND_ONLY);
-#endif /* LWIP_NETIF_HWADDRHINT */
+ i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) {
*eth_ret = &arp_table[i].ethaddr;
*ip_ret = &arp_table[i].ipaddr;
@@ -561,6 +599,7 @@ etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
return -1;
}
+#if ETHARP_TRUST_IP_MAC
/**
* Updates the ARP table using the given IP packet.
*
@@ -576,35 +615,39 @@ etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
*
* @see pbuf_free()
*/
-void
+static void
etharp_ip_input(struct netif *netif, struct pbuf *p)
{
struct eth_hdr *ethhdr;
struct ip_hdr *iphdr;
+ ip_addr_t iphdr_src;
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
+
/* Only insert an entry if the source IP address of the
incoming IP packet comes from a host on the local network. */
- ethhdr = p->payload;
+ ethhdr = (struct eth_hdr *)p->payload;
iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
#if ETHARP_SUPPORT_VLAN
- if (ethhdr->type == ETHTYPE_VLAN) {
+ if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
}
#endif /* ETHARP_SUPPORT_VLAN */
+ ip_addr_copy(iphdr_src, iphdr->src);
+
/* source is not on the local network? */
- if (!ip_addr_netcmp(&(iphdr->src), &(netif->ip_addr), &(netif->netmask))) {
+ if (!ip_addr_netcmp(&iphdr_src, &(netif->ip_addr), &(netif->netmask))) {
/* do nothing */
return;
}
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
- /* update ARP table */
- /* @todo We could use ETHARP_TRY_HARD if we think we are going to talk
+ /* update the source IP address in the cache, if present */
+ /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk
* back soon (for example, if the destination IP address is ours. */
- update_arp_entry(netif, &(iphdr->src), &(ethhdr->src), 0);
+ update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY);
}
-
+#endif /* ETHARP_TRUST_IP_MAC */
/**
* Responds to ARP requests to us. Upon ARP replies to us, add entry to cache
@@ -621,21 +664,20 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
*
* @see pbuf_free()
*/
-void
+static void
etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
{
struct etharp_hdr *hdr;
struct eth_hdr *ethhdr;
/* these are aligned properly, whereas the ARP header fields might not be */
- struct ip_addr sipaddr, dipaddr;
- u8_t i;
+ ip_addr_t sipaddr, dipaddr;
u8_t for_us;
#if LWIP_AUTOIP
const u8_t * ethdst_hwaddr;
#endif /* LWIP_AUTOIP */
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
-
+
/* drop short ARP packets: we have to check for p->len instead of p->tot_len here
since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
if (p->len < SIZEOF_ETHARP_PACKET) {
@@ -648,22 +690,22 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
return;
}
- ethhdr = p->payload;
+ ethhdr = (struct eth_hdr *)p->payload;
hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
#if ETHARP_SUPPORT_VLAN
- if (ethhdr->type == ETHTYPE_VLAN) {
+ if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
}
#endif /* ETHARP_SUPPORT_VLAN */
/* RFC 826 "Packet Reception": */
- if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) ||
- (hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) ||
- (hdr->proto != htons(ETHTYPE_IP)) ||
- (ethhdr->type != htons(ETHTYPE_ARP))) {
+ if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
+ (hdr->hwlen != ETHARP_HWADDR_LEN) ||
+ (hdr->protolen != sizeof(ip_addr_t)) ||
+ (hdr->proto != PP_HTONS(ETHTYPE_IP))) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
- ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
- hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), ethhdr->type));
+ ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
+ hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen));
ETHARP_STATS_INC(etharp.proterr);
ETHARP_STATS_INC(etharp.drop);
pbuf_free(p);
@@ -680,32 +722,29 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
* structure packing (not using structure copy which breaks strict-aliasing rules). */
- SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
- SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
+ IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
+ IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
/* this interface is not configured? */
- if (netif->ip_addr.addr == 0) {
+ if (ip_addr_isany(&netif->ip_addr)) {
for_us = 0;
} else {
/* ARP packet directed to us? */
- for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr));
+ for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr));
}
- /* ARP message directed to us? */
- if (for_us) {
- /* add IP address in ARP cache; assume requester wants to talk to us.
- * can result in directly sending the queued packets for this host. */
- update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);
- /* ARP message not directed to us? */
- } else {
- /* update the source IP address in the cache, if present */
- update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0);
- }
+ /* ARP message directed to us?
+ -> add IP address in ARP cache; assume requester wants to talk to us,
+ can result in directly sending the queued packets for this host.
+ ARP message not directed to us?
+ -> update the source IP address in the cache, if present */
+ update_arp_entry(netif, &sipaddr, &(hdr->shwaddr),
+ for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
/* now act on the message itself */
- switch (htons(hdr->opcode)) {
+ switch (hdr->opcode) {
/* ARP request? */
- case ARP_REQUEST:
+ case PP_HTONS(ARP_REQUEST):
/* ARP request. If it asked for our address, we send out a
* reply. In any case, we time-stamp any existing ARP entry,
* and possiby send out an IP packet that was queued on it. */
@@ -720,29 +759,26 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
that would allocate a new pbuf. */
hdr->opcode = htons(ARP_REPLY);
- hdr->dipaddr = hdr->sipaddr;
- SMEMCPY(&hdr->sipaddr, &netif->ip_addr, sizeof(hdr->sipaddr));
+ IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr);
+ IPADDR2_COPY(&hdr->sipaddr, &netif->ip_addr);
LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
(netif->hwaddr_len == ETHARP_HWADDR_LEN));
- i = ETHARP_HWADDR_LEN;
#if LWIP_AUTOIP
- /* If we are using Link-Local, ARP packets must be broadcast on the
- * link layer. (See RFC3927 Section 2.5) */
- ethdst_hwaddr = ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;
+ /* If we are using Link-Local, all ARP packets that contain a Link-Local
+ * 'sender IP address' MUST be sent using link-layer broadcast instead of
+ * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
+ ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;
#endif /* LWIP_AUTOIP */
- while(i > 0) {
- i--;
- hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
+ ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr);
#if LWIP_AUTOIP
- ethhdr->dest.addr[i] = ethdst_hwaddr[i];
+ ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);
#else /* LWIP_AUTOIP */
- ethhdr->dest.addr[i] = hdr->shwaddr.addr[i];
+ ETHADDR16_COPY(&ethhdr->dest, &hdr->shwaddr);
#endif /* LWIP_AUTOIP */
- hdr->shwaddr.addr[i] = ethaddr->addr[i];
- ethhdr->src.addr[i] = ethaddr->addr[i];
- }
+ ETHADDR16_COPY(&hdr->shwaddr, ethaddr);
+ ETHADDR16_COPY(&ethhdr->src, ethaddr);
/* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
are already correct, we tested that before */
@@ -750,7 +786,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
/* return ARP reply */
netif->linkoutput(netif, p);
/* we are not configured? */
- } else if (netif->ip_addr.addr == 0) {
+ } else if (ip_addr_isany(&netif->ip_addr)) {
/* { for_us == 0 and netif->ip_addr.addr == 0 } */
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
/* request was not directed to us */
@@ -759,7 +795,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
}
break;
- case ARP_REPLY:
+ case PP_HTONS(ARP_REPLY):
/* ARP reply. We already updated the ARP cache earlier. */
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
@@ -768,7 +804,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
* want to take a duplicate IP address on a single network.
* @todo How should we handle redundant (fail-over) interfaces? */
dhcp_arp_reply(netif, &sipaddr);
-#endif
+#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */
break;
default:
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
@@ -798,7 +834,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
* or the return type of either etharp_query() or etharp_send_ip().
*/
err_t
-etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr)
+etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
{
struct eth_addr *dest, mcastaddr;
@@ -834,17 +870,46 @@ etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr)
/* unicast destination IP address? */
} else {
/* outside local network? */
- if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
- /* interface has default gateway? */
- if (netif->gw.addr != 0) {
- /* send to hardware address of default gateway IP address */
- ipaddr = &(netif->gw);
- /* no default gateway available */
- } else {
- /* no route to destination error (default gateway missing) */
- return ERR_RTE;
+ if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) &&
+ !ip_addr_islinklocal(ipaddr)) {
+#if LWIP_AUTOIP
+ struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload +
+ sizeof(struct eth_hdr));
+ /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
+ a link-local source address must always be "directly to its destination
+ on the same physical link. The host MUST NOT send the packet to any
+ router for forwarding". */
+ if (!ip_addr_islinklocal(&iphdr->src))
+#endif /* LWIP_AUTOIP */
+ {
+ /* interface has default gateway? */
+ if (!ip_addr_isany(&netif->gw)) {
+ /* send to hardware address of default gateway IP address */
+ ipaddr = &(netif->gw);
+ /* no default gateway available */
+ } else {
+ /* no route to destination error (default gateway missing) */
+ return ERR_RTE;
+ }
+ }
+ }
+#if LWIP_NETIF_HWADDRHINT
+ if (netif->addr_hint != NULL) {
+ /* per-pcb cached entry was given */
+ u8_t etharp_cached_entry = *(netif->addr_hint);
+ if (etharp_cached_entry < ARP_TABLE_SIZE) {
+#endif /* LWIP_NETIF_HWADDRHINT */
+ if ((arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) &&
+ (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr))) {
+ /* the per-pcb-cached entry is stable and the right one! */
+ ETHARP_STATS_INC(etharp.cachehit);
+ return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr),
+ &arp_table[etharp_cached_entry].ethaddr);
+ }
+#if LWIP_NETIF_HWADDRHINT
}
}
+#endif /* LWIP_NETIF_HWADDRHINT */
/* queue on destination Ethernet address belonging to ipaddr */
return etharp_query(netif, ipaddr, q);
}
@@ -889,7 +954,7 @@ etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr)
*
*/
err_t
-etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
+etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
{
struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
err_t result = ERR_MEM;
@@ -904,11 +969,7 @@ etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
}
/* find entry in ARP cache, ask to create entry if queueing packet */
-#if LWIP_NETIF_HWADDRHINT
- i = find_entry(ipaddr, ETHARP_TRY_HARD, netif);
-#else /* LWIP_NETIF_HWADDRHINT */
- i = find_entry(ipaddr, ETHARP_TRY_HARD);
-#endif /* LWIP_NETIF_HWADDRHINT */
+ i = find_entry(ipaddr, ETHARP_FLAG_TRY_HARD);
/* could not find or create entry? */
if (i < 0) {
@@ -940,85 +1001,94 @@ etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
since this failure could be temporary, and the next packet calling
etharp_query again could lead to sending the queued packets. */
}
+ if (q == NULL) {
+ return result;
+ }
}
-
+
/* packet given? */
- if (q != NULL) {
- /* stable entry? */
- if (arp_table[i].state == ETHARP_STATE_STABLE) {
- /* we have a valid IP->Ethernet address mapping */
- /* send the packet */
- result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
- /* pending entry? (either just created or already pending */
- } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
-#if ARP_QUEUEING /* queue the given q packet */
- struct pbuf *p;
- int copy_needed = 0;
- /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
- * to copy the whole queue into a new PBUF_RAM (see bug #11400)
- * PBUF_ROMs can be left as they are, since ROM must not get changed. */
- p = q;
- while (p) {
- LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
- if(p->type != PBUF_ROM) {
- copy_needed = 1;
- break;
- }
- p = p->next;
+ LWIP_ASSERT("q != NULL", q != NULL);
+ /* stable entry? */
+ if (arp_table[i].state == ETHARP_STATE_STABLE) {
+ /* we have a valid IP->Ethernet address mapping */
+ ETHARP_SET_HINT(netif, i);
+ /* send the packet */
+ result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
+ /* pending entry? (either just created or already pending */
+ } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
+ /* entry is still pending, queue the given packet 'q' */
+ struct pbuf *p;
+ int copy_needed = 0;
+ /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
+ * to copy the whole queue into a new PBUF_RAM (see bug #11400)
+ * PBUF_ROMs can be left as they are, since ROM must not get changed. */
+ p = q;
+ while (p) {
+ LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
+ if(p->type != PBUF_ROM) {
+ copy_needed = 1;
+ break;
}
- if(copy_needed) {
- /* copy the whole packet into new pbufs */
- p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
- if(p != NULL) {
- if (pbuf_copy(p, q) != ERR_OK) {
- pbuf_free(p);
- p = NULL;
- }
+ p = p->next;
+ }
+ if(copy_needed) {
+ /* copy the whole packet into new pbufs */
+ p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
+ if(p != NULL) {
+ if (pbuf_copy(p, q) != ERR_OK) {
+ pbuf_free(p);
+ p = NULL;
}
- } else {
- /* referencing the old pbuf is enough */
- p = q;
- pbuf_ref(p);
}
- /* packet could be taken over? */
- if (p != NULL) {
- /* queue packet ... */
- struct etharp_q_entry *new_entry;
- /* allocate a new arp queue entry */
- new_entry = memp_malloc(MEMP_ARP_QUEUE);
- if (new_entry != NULL) {
- new_entry->next = 0;
- new_entry->p = p;
- if(arp_table[i].q != NULL) {
- /* queue was already existent, append the new entry to the end */
- struct etharp_q_entry *r;
- r = arp_table[i].q;
- while (r->next != NULL) {
- r = r->next;
- }
- r->next = new_entry;
- } else {
- /* queue did not exist, first item in queue */
- arp_table[i].q = new_entry;
+ } else {
+ /* referencing the old pbuf is enough */
+ p = q;
+ pbuf_ref(p);
+ }
+ /* packet could be taken over? */
+ if (p != NULL) {
+ /* queue packet ... */
+#if ARP_QUEUEING
+ struct etharp_q_entry *new_entry;
+ /* allocate a new arp queue entry */
+ new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
+ if (new_entry != NULL) {
+ new_entry->next = 0;
+ new_entry->p = p;
+ if(arp_table[i].q != NULL) {
+ /* queue was already existent, append the new entry to the end */
+ struct etharp_q_entry *r;
+ r = arp_table[i].q;
+ while (r->next != NULL) {
+ r = r->next;
}
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
- result = ERR_OK;
+ r->next = new_entry;
} else {
- /* the pool MEMP_ARP_QUEUE is empty */
- pbuf_free(p);
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
- /* { result == ERR_MEM } through initialization */
+ /* queue did not exist, first item in queue */
+ arp_table[i].q = new_entry;
}
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
+ result = ERR_OK;
} else {
- ETHARP_STATS_INC(etharp.memerr);
+ /* the pool MEMP_ARP_QUEUE is empty */
+ pbuf_free(p);
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
- /* { result == ERR_MEM } through initialization */
+ result = ERR_MEM;
}
-#else /* ARP_QUEUEING == 0 */
- /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */
- /* { result == ERR_MEM } through initialization */
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
-#endif
+#else /* ARP_QUEUEING */
+ /* always queue one packet per ARP request only, freeing a previously queued packet */
+ if (arp_table[i].q != NULL) {
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
+ pbuf_free(arp_table[i].q);
+ }
+ arp_table[i].q = p;
+ result = ERR_OK;
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
+#endif /* ARP_QUEUEING */
+ } else {
+ ETHARP_STATS_INC(etharp.memerr);
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
+ result = ERR_MEM;
}
}
return result;
@@ -1045,13 +1115,12 @@ static
err_t
etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
const struct eth_addr *ethdst_addr,
- const struct eth_addr *hwsrc_addr, const struct ip_addr *ipsrc_addr,
- const struct eth_addr *hwdst_addr, const struct ip_addr *ipdst_addr,
+ const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr,
+ const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr,
const u16_t opcode)
{
struct pbuf *p;
err_t result = ERR_OK;
- u8_t k; /* ARP entry index */
struct eth_hdr *ethhdr;
struct etharp_hdr *hdr;
#if LWIP_AUTOIP
@@ -1070,42 +1139,41 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
(p->len >= SIZEOF_ETHARP_PACKET));
- ethhdr = p->payload;
+ ethhdr = (struct eth_hdr *)p->payload;
hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
hdr->opcode = htons(opcode);
LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
(netif->hwaddr_len == ETHARP_HWADDR_LEN));
- k = ETHARP_HWADDR_LEN;
#if LWIP_AUTOIP
- /* If we are using Link-Local, ARP packets must be broadcast on the
- * link layer. (See RFC3927 Section 2.5) */
- ethdst_hwaddr = ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;
+ /* If we are using Link-Local, all ARP packets that contain a Link-Local
+ * 'sender IP address' MUST be sent using link-layer broadcast instead of
+ * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
+ ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;
#endif /* LWIP_AUTOIP */
- /* Write MAC-Addresses (combined loop for both headers) */
- while(k > 0) {
- k--;
- /* Write the ARP MAC-Addresses */
- hdr->shwaddr.addr[k] = hwsrc_addr->addr[k];
- hdr->dhwaddr.addr[k] = hwdst_addr->addr[k];
- /* Write the Ethernet MAC-Addresses */
+ /* Write the ARP MAC-Addresses */
+ ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr);
+ ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr);
+ /* Write the Ethernet MAC-Addresses */
#if LWIP_AUTOIP
- ethhdr->dest.addr[k] = ethdst_hwaddr[k];
+ ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);
#else /* LWIP_AUTOIP */
- ethhdr->dest.addr[k] = ethdst_addr->addr[k];
+ ETHADDR16_COPY(&ethhdr->dest, ethdst_addr);
#endif /* LWIP_AUTOIP */
- ethhdr->src.addr[k] = ethsrc_addr->addr[k];
- }
- hdr->sipaddr = *(struct ip_addr2 *)ipsrc_addr;
- hdr->dipaddr = *(struct ip_addr2 *)ipdst_addr;
+ ETHADDR16_COPY(&ethhdr->src, ethsrc_addr);
+ /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
+ * structure packing. */
+ IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr);
+ IPADDR2_COPY(&hdr->dipaddr, ipdst_addr);
- hdr->hwtype = htons(HWTYPE_ETHERNET);
- hdr->proto = htons(ETHTYPE_IP);
- /* set hwlen and protolen together */
- hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr));
+ hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET);
+ hdr->proto = PP_HTONS(ETHTYPE_IP);
+ /* set hwlen and protolen */
+ hdr->hwlen = ETHARP_HWADDR_LEN;
+ hdr->protolen = sizeof(ip_addr_t);
- ethhdr->type = htons(ETHTYPE_ARP);
+ ethhdr->type = PP_HTONS(ETHTYPE_ARP);
/* send ARP query */
result = netif->linkoutput(netif, p);
ETHARP_STATS_INC(etharp.xmit);
@@ -1127,13 +1195,14 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
* any other err_t on failure
*/
err_t
-etharp_request(struct netif *netif, struct ip_addr *ipaddr)
+etharp_request(struct netif *netif, ip_addr_t *ipaddr)
{
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n"));
return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
(struct eth_addr *)netif->hwaddr, &netif->ip_addr, &ethzero,
ipaddr, ARP_REQUEST);
}
+#endif /* LWIP_ARP */
/**
* Process received ethernet frames. Using this function instead of directly
@@ -1148,21 +1217,35 @@ ethernet_input(struct pbuf *p, struct netif *netif)
{
struct eth_hdr* ethhdr;
u16_t type;
+ s16_t ip_hdr_offset = SIZEOF_ETH_HDR;
+
+ if (p->len <= SIZEOF_ETH_HDR) {
+ /* a packet with only an ethernet header (or less) is not valid for us */
+ ETHARP_STATS_INC(etharp.proterr);
+ ETHARP_STATS_INC(etharp.drop);
+ goto free_and_return;
+ }
/* points to packet payload, which starts with an Ethernet header */
- ethhdr = p->payload;
+ ethhdr = (struct eth_hdr *)p->payload;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
- ("ethernet_input: dest:%02x:%02x:%02x:%02x:%02x:%02x, src:%02x:%02x:%02x:%02x:%02x:%02x, type:%2hx\n",
+ ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n",
(unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
(unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
(unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
(unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
(unsigned)htons(ethhdr->type)));
- type = htons(ethhdr->type);
+ type = ethhdr->type;
#if ETHARP_SUPPORT_VLAN
- if (type == ETHTYPE_VLAN) {
+ if (type == PP_HTONS(ETHTYPE_VLAN)) {
struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
+ if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) {
+ /* a packet with only an ethernet/vlan header (or less) is not valid for us */
+ ETHARP_STATS_INC(etharp.proterr);
+ ETHARP_STATS_INC(etharp.drop);
+ goto free_and_return;
+ }
#ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */
if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
/* silently ignore this packet: not for our VLAN */
@@ -1170,39 +1253,50 @@ ethernet_input(struct pbuf *p, struct netif *netif)
return ERR_OK;
}
#endif /* ETHARP_VLAN_CHECK */
- type = htons(vlan->tpid);
+ type = vlan->tpid;
+ ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR;
}
#endif /* ETHARP_SUPPORT_VLAN */
+#if LWIP_ARP_FILTER_NETIF
+ netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type));
+#endif /* LWIP_ARP_FILTER_NETIF*/
+
switch (type) {
+#if LWIP_ARP
/* IP packet? */
- case ETHTYPE_IP:
+ case PP_HTONS(ETHTYPE_IP):
+ if (!(netif->flags & NETIF_FLAG_ETHARP)) {
+ goto free_and_return;
+ }
#if ETHARP_TRUST_IP_MAC
/* update ARP table */
etharp_ip_input(netif, p);
#endif /* ETHARP_TRUST_IP_MAC */
/* skip Ethernet header */
- if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) {
+ if(pbuf_header(p, -ip_hdr_offset)) {
LWIP_ASSERT("Can't move over header in packet", 0);
- pbuf_free(p);
- p = NULL;
+ goto free_and_return;
} else {
/* pass to IP layer */
ip_input(p, netif);
}
break;
- case ETHTYPE_ARP:
+ case PP_HTONS(ETHTYPE_ARP):
+ if (!(netif->flags & NETIF_FLAG_ETHARP)) {
+ goto free_and_return;
+ }
/* pass p to ARP module */
etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);
break;
-
+#endif /* LWIP_ARP */
#if PPPOE_SUPPORT
- case ETHTYPE_PPPOEDISC: /* PPP Over Ethernet Discovery Stage */
+ case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */
pppoe_disc_input(netif, p);
break;
- case ETHTYPE_PPPOE: /* PPP Over Ethernet Session Stage */
+ case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */
pppoe_data_input(netif, p);
break;
#endif /* PPPOE_SUPPORT */
@@ -1210,13 +1304,15 @@ ethernet_input(struct pbuf *p, struct netif *netif)
default:
ETHARP_STATS_INC(etharp.proterr);
ETHARP_STATS_INC(etharp.drop);
- pbuf_free(p);
- p = NULL;
- break;
+ goto free_and_return;
}
/* This means the pbuf is freed or consumed,
so the caller doesn't have to free it again */
return ERR_OK;
+
+free_and_return:
+ pbuf_free(p);
+ return ERR_OK;
}
-#endif /* LWIP_ARP */
+#endif /* LWIP_ARP || LWIP_ETHERNET */
diff --git a/core/lwip/src/netif/loopif.c b/core/lwip/src/netif/loopif.c
deleted file mode 100644
index 1e1f28cf..00000000
--- a/core/lwip/src/netif/loopif.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * @file
- * Loop Interface
- *
- */
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-#include "lwip/opt.h"
-
-#if LWIP_HAVE_LOOPIF
-
-#include "netif/loopif.h"
-#include "lwip/snmp.h"
-
-/**
- * Initialize a lwip network interface structure for a loopback interface
- *
- * @param netif the lwip network interface structure for this loopif
- * @return ERR_OK if the loopif is initialized
- * ERR_MEM if private data couldn't be allocated
- */
-err_t
-loopif_init(struct netif *netif)
-{
- /* initialize the snmp variables and counters inside the struct netif
- * ifSpeed: no assumption can be made!
- */
- NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0);
-
- netif->name[0] = 'l';
- netif->name[1] = 'o';
- netif->output = netif_loop_output;
- return ERR_OK;
-}
-
-#endif /* LWIP_HAVE_LOOPIF */
diff --git a/core/lwip/src/netif/ppp/auth.c b/core/lwip/src/netif/ppp/auth.c
index cbd3eb21..c3c49d22 100644
--- a/core/lwip/src/netif/ppp/auth.c
+++ b/core/lwip/src/netif/ppp/auth.c
@@ -82,11 +82,104 @@
#include "cbcp.h"
#endif /* CBCP_SUPPORT */
+#include "lwip/inet.h"
+
#include <string.h>
-/*************************/
-/*** LOCAL DEFINITIONS ***/
-/*************************/
+#if 0 /* UNUSED */
+/* Bits in scan_authfile return value */
+#define NONWILD_SERVER 1
+#define NONWILD_CLIENT 2
+
+#define ISWILD(word) (word[0] == '*' && word[1] == 0)
+#endif /* UNUSED */
+
+#if PAP_SUPPORT || CHAP_SUPPORT
+/* The name by which the peer authenticated itself to us. */
+static char peer_authname[MAXNAMELEN];
+#endif /* PAP_SUPPORT || CHAP_SUPPORT */
+
+/* Records which authentication operations haven't completed yet. */
+static int auth_pending[NUM_PPP];
+
+/* Set if we have successfully called plogin() */
+static int logged_in;
+
+/* Set if we have run the /etc/ppp/auth-up script. */
+static int did_authup; /* @todo, we don't need this in lwip*/
+
+/* List of addresses which the peer may use. */
+static struct wordlist *addresses[NUM_PPP];
+
+#if 0 /* UNUSED */
+/* Wordlist giving addresses which the peer may use
+ without authenticating itself. */
+static struct wordlist *noauth_addrs;
+
+/* Extra options to apply, from the secrets file entry for the peer. */
+static struct wordlist *extra_options;
+#endif /* UNUSED */
+
+/* Number of network protocols which we have opened. */
+static int num_np_open;
+
+/* Number of network protocols which have come up. */
+static int num_np_up;
+
+#if PAP_SUPPORT || CHAP_SUPPORT
+/* Set if we got the contents of passwd[] from the pap-secrets file. */
+static int passwd_from_file;
+#endif /* PAP_SUPPORT || CHAP_SUPPORT */
+
+#if 0 /* UNUSED */
+/* Set if we require authentication only because we have a default route. */
+static bool default_auth;
+
+/* Hook to enable a plugin to control the idle time limit */
+int (*idle_time_hook) __P((struct ppp_idle *)) = NULL;
+
+/* Hook for a plugin to say whether we can possibly authenticate any peer */
+int (*pap_check_hook) __P((void)) = NULL;
+
+/* Hook for a plugin to check the PAP user and password */
+int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp,
+ struct wordlist **paddrs,
+ struct wordlist **popts)) = NULL;
+
+/* Hook for a plugin to know about the PAP user logout */
+void (*pap_logout_hook) __P((void)) = NULL;
+
+/* Hook for a plugin to get the PAP password for authenticating us */
+int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL;
+
+/*
+ * This is used to ensure that we don't start an auth-up/down
+ * script while one is already running.
+ */
+enum script_state {
+ s_down,
+ s_up
+};
+
+static enum script_state auth_state = s_down;
+static enum script_state auth_script_state = s_down;
+static pid_t auth_script_pid = 0;
+
+/*
+ * Option variables.
+ * lwip: some of these are present in the ppp_settings structure
+ */
+bool uselogin = 0; /* Use /etc/passwd for checking PAP */
+bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */
+bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */
+bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */
+bool usehostname = 0; /* Use hostname for our_name */
+bool auth_required = 0; /* Always require authentication from peer */
+bool allow_any_ip = 0; /* Allow peer to use any IP address */
+bool explicit_remote = 0; /* User specified explicit remote name */
+char remote_name[MAXNAMELEN]; /* Peer's name for authentication */
+
+#endif /* UNUSED */
/* Bits in auth_pending[] */
#define PAP_WITHPEER 1
@@ -94,10 +187,7 @@
#define CHAP_WITHPEER 4
#define CHAP_PEER 8
-
-/************************/
-/*** LOCAL DATA TYPES ***/
-/************************/
+/* @todo, move this somewhere */
/* Used for storing a sequence of words. Usually malloced. */
struct wordlist {
struct wordlist *next;
@@ -105,9 +195,6 @@ struct wordlist {
};
-/***********************************/
-/*** LOCAL FUNCTION DECLARATIONS ***/
-/***********************************/
extern char *crypt (const char *, const char *);
/* Prototypes for procedures local to this file. */
@@ -116,63 +203,172 @@ static void network_phase (int);
static void check_idle (void *);
static void connect_time_expired (void *);
#if 0
-static int login (char *, char *, char **, int *);
+static int plogin (char *, char *, char **, int *);
#endif
-static void logout (void);
+static void plogout (void);
static int null_login (int);
static int get_pap_passwd (int, char *, char *);
static int have_pap_secret (void);
static int have_chap_secret (char *, char *, u32_t);
static int ip_addr_check (u32_t, struct wordlist *);
+
#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */
-static void set_allowed_addrs(int unit, struct wordlist *addrs);
+static int scan_authfile (FILE *, char *, char *, char *,
+ struct wordlist **, struct wordlist **,
+ char *);
static void free_wordlist (struct wordlist *);
+static void auth_script (char *);
+static void auth_script_done (void *);
+static void set_allowed_addrs (int unit, struct wordlist *addrs);
+static int some_ip_ok (struct wordlist *);
+static int setupapfile (char **);
+static int privgroup (char **);
+static int set_noauth_addr (char **);
+static void check_access (FILE *, char *);
#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */
-#if CBCP_SUPPORT
-static void callback_phase (int);
-#endif /* CBCP_SUPPORT */
-
-/******************************/
-/*** PUBLIC DATA STRUCTURES ***/
-/******************************/
-
-
-/*****************************/
-/*** LOCAL DATA STRUCTURES ***/
-/*****************************/
-#if PAP_SUPPORT || CHAP_SUPPORT
-/* The name by which the peer authenticated itself to us. */
-static char peer_authname[MAXNAMELEN];
-#endif /* PAP_SUPPORT || CHAP_SUPPORT */
-
-/* Records which authentication operations haven't completed yet. */
-static int auth_pending[NUM_PPP];
-
-/* Set if we have successfully called login() */
-static int logged_in;
+#if 0 /* UNUSED */
+/*
+ * Authentication-related options.
+ */
+option_t auth_options[] = {
+ { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap,
+ "Require PAP authentication from peer", 1, &auth_required },
+ { "+pap", o_bool, &lcp_wantoptions[0].neg_upap,
+ "Require PAP authentication from peer", 1, &auth_required },
+ { "refuse-pap", o_bool, &refuse_pap,
+ "Don't agree to auth to peer with PAP", 1 },
+ { "-pap", o_bool, &refuse_pap,
+ "Don't allow PAP authentication with peer", 1 },
+ { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap,
+ "Require CHAP authentication from peer", 1, &auth_required },
+ { "+chap", o_bool, &lcp_wantoptions[0].neg_chap,
+ "Require CHAP authentication from peer", 1, &auth_required },
+ { "refuse-chap", o_bool, &refuse_chap,
+ "Don't agree to auth to peer with CHAP", 1 },
+ { "-chap", o_bool, &refuse_chap,
+ "Don't allow CHAP authentication with peer", 1 },
+ { "name", o_string, our_name,
+ "Set local name for authentication",
+ OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN },
+ { "user", o_string, user,
+ "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN },
+ { "usehostname", o_bool, &usehostname,
+ "Must use hostname for authentication", 1 },
+ { "remotename", o_string, remote_name,
+ "Set remote name for authentication", OPT_STATIC,
+ &explicit_remote, MAXNAMELEN },
+ { "auth", o_bool, &auth_required,
+ "Require authentication from peer", 1 },
+ { "noauth", o_bool, &auth_required,
+ "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip },
+ { "login", o_bool, &uselogin,
+ "Use system password database for PAP", 1 },
+ { "papcrypt", o_bool, &cryptpap,
+ "PAP passwords are encrypted", 1 },
+ { "+ua", o_special, (void *)setupapfile,
+ "Get PAP user and password from file" },
+ { "password", o_string, passwd,
+ "Password for authenticating us to the peer", OPT_STATIC,
+ NULL, MAXSECRETLEN },
+ { "privgroup", o_special, (void *)privgroup,
+ "Allow group members to use privileged options", OPT_PRIV },
+ { "allow-ip", o_special, (void *)set_noauth_addr,
+ "Set IP address(es) which can be used without authentication",
+ OPT_PRIV },
+ { NULL }
+};
+#endif /* UNUSED */
+#if 0 /* UNUSED */
+/*
+ * setupapfile - specifies UPAP info for authenticating with peer.
+ */
+static int
+setupapfile(char **argv)
+{
+ FILE * ufile;
+ int l;
+
+ lcp_allowoptions[0].neg_upap = 1;
+
+ /* open user info file */
+ seteuid(getuid());
+ ufile = fopen(*argv, "r");
+ seteuid(0);
+ if (ufile == NULL) {
+ option_error("unable to open user login data file %s", *argv);
+ return 0;
+ }
+ check_access(ufile, *argv);
-/* Set if we have run the /etc/ppp/auth-up script. */
-static int did_authup;
+ /* get username */
+ if (fgets(user, MAXNAMELEN - 1, ufile) == NULL
+ || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){
+ option_error("unable to read user login data file %s", *argv);
+ return 0;
+ }
+ fclose(ufile);
-/* List of addresses which the peer may use. */
-static struct wordlist *addresses[NUM_PPP];
+ /* get rid of newlines */
+ l = strlen(user);
+ if (l > 0 && user[l-1] == '\n')
+ user[l-1] = 0;
+ l = strlen(passwd);
+ if (l > 0 && passwd[l-1] == '\n')
+ passwd[l-1] = 0;
-/* Number of network protocols which we have opened. */
-static int num_np_open;
+ return (1);
+}
+#endif /* UNUSED */
-/* Number of network protocols which have come up. */
-static int num_np_up;
+#if 0 /* UNUSED */
+/*
+ * privgroup - allow members of the group to have privileged access.
+ */
+static int
+privgroup(char **argv)
+{
+ struct group *g;
+ int i;
-#if PAP_SUPPORT || CHAP_SUPPORT
-/* Set if we got the contents of passwd[] from the pap-secrets file. */
-static int passwd_from_file;
-#endif /* PAP_SUPPORT || CHAP_SUPPORT */
+ g = getgrnam(*argv);
+ if (g == 0) {
+ option_error("group %s is unknown", *argv);
+ return 0;
+ }
+ for (i = 0; i < ngroups; ++i) {
+ if (groups[i] == g->gr_gid) {
+ privileged = 1;
+ break;
+ }
+ }
+ return 1;
+}
+#endif
+#if 0 /* UNUSED */
+/*
+ * set_noauth_addr - set address(es) that can be used without authentication.
+ * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets.
+ */
+static int
+set_noauth_addr(char **argv)
+{
+ char *addr = *argv;
+ int l = strlen(addr);
+ struct wordlist *wp;
+
+ wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l + 1);
+ if (wp == NULL)
+ novm("allow-ip argument");
+ wp->word = (char *) (wp + 1);
+ wp->next = noauth_addrs;
+ BCOPY(addr, wp->word, l);
+ noauth_addrs = wp;
+ return 1;
+}
+#endif /* UNUSED */
-/***********************************/
-/*** PUBLIC FUNCTION DEFINITIONS ***/
-/***********************************/
/*
* An Open on LCP has requested a change from Dead to Establish phase.
* Do what's necessary to bring the physical layer up.
@@ -182,7 +378,7 @@ link_required(int unit)
{
LWIP_UNUSED_ARG(unit);
- AUTHDEBUG((LOG_INFO, "link_required: %d\n", unit));
+ AUTHDEBUG(LOG_INFO, ("link_required: %d\n", unit));
}
/*
@@ -192,15 +388,15 @@ link_required(int unit)
void
link_terminated(int unit)
{
- AUTHDEBUG((LOG_INFO, "link_terminated: %d\n", unit));
+ AUTHDEBUG(LOG_INFO, ("link_terminated: %d\n", unit));
if (lcp_phase[unit] == PHASE_DEAD) {
return;
}
if (logged_in) {
- logout();
+ plogout();
}
lcp_phase[unit] = PHASE_DEAD;
- AUTHDEBUG((LOG_NOTICE, "Connection terminated.\n"));
+ AUTHDEBUG(LOG_NOTICE, ("Connection terminated.\n"));
pppLinkTerminated(unit);
}
@@ -212,8 +408,9 @@ link_down(int unit)
{
int i;
struct protent *protp;
-
- AUTHDEBUG((LOG_INFO, "link_down: %d\n", unit));
+
+ AUTHDEBUG(LOG_INFO, ("link_down: %d\n", unit));
+
if (did_authup) {
/* XXX Do link down processing. */
did_authup = 0;
@@ -229,8 +426,9 @@ link_down(int unit)
(*protp->close)(unit, "LCP down");
}
}
- num_np_open = 0;
- num_np_up = 0;
+ num_np_open = 0; /* number of network protocols we have opened */
+ num_np_up = 0; /* Number of network protocols which have come up */
+
if (lcp_phase[unit] != PHASE_DEAD) {
lcp_phase[unit] = PHASE_TERMINATE;
}
@@ -253,7 +451,7 @@ link_established(int unit)
lcp_options *ho = &lcp_hisoptions[unit];
#endif /* PAP_SUPPORT || CHAP_SUPPORT */
- AUTHDEBUG((LOG_INFO, "link_established: %d\n", unit));
+ AUTHDEBUG(LOG_INFO, ("link_established: unit %d; Lowering up all protocols...\n", unit));
/*
* Tell higher-level protocols that LCP is up.
*/
@@ -269,12 +467,12 @@ link_established(int unit)
* of "" and a password of "". If that's not OK, boot it out.
*/
if (!wo->neg_upap || !null_login(unit)) {
- AUTHDEBUG((LOG_WARNING, "peer refused to authenticate\n"));
+ AUTHDEBUG(LOG_WARNING, ("peer refused to authenticate\n"));
lcp_close(unit, "peer refused to authenticate");
return;
}
}
-
+
lcp_phase[unit] = PHASE_AUTHENTICATE;
auth = 0;
#if CHAP_SUPPORT
@@ -306,7 +504,7 @@ link_established(int unit)
if (ppp_settings.passwd[0] == 0) {
passwd_from_file = 1;
if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd)) {
- AUTHDEBUG((LOG_ERR, "No secret found for PAP login\n"));
+ AUTHDEBUG(LOG_ERR, ("No secret found for PAP login\n"));
}
}
upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd);
@@ -321,6 +519,52 @@ link_established(int unit)
}
/*
+ * Proceed to the network phase.
+ */
+static void
+network_phase(int unit)
+{
+ int i;
+ struct protent *protp;
+ lcp_options *go = &lcp_gotoptions[unit];
+
+ /*
+ * If the peer had to authenticate, run the auth-up script now.
+ */
+ if ((go->neg_chap || go->neg_upap) && !did_authup) {
+ /* XXX Do setup for peer authentication. */
+ did_authup = 1;
+ }
+
+#if CBCP_SUPPORT
+ /*
+ * If we negotiated callback, do it now.
+ */
+ if (go->neg_cbcp) {
+ lcp_phase[unit] = PHASE_CALLBACK;
+ (*cbcp_protent.open)(unit);
+ return;
+ }
+#endif /* CBCP_SUPPORT */
+
+ lcp_phase[unit] = PHASE_NETWORK;
+ for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
+ if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) {
+ (*protp->open)(unit);
+ if (protp->protocol != PPP_CCP) {
+ ++num_np_open;
+ }
+ }
+ }
+
+ if (num_np_open == 0) {
+ /* nothing to do */
+ lcp_close(0, "No network protocols running");
+ }
+}
+/* @todo: add void start_networks(void) here (pppd 2.3.11) */
+
+/*
* The peer has failed to authenticate himself using `protocol'.
*/
void
@@ -328,7 +572,7 @@ auth_peer_fail(int unit, u16_t protocol)
{
LWIP_UNUSED_ARG(protocol);
- AUTHDEBUG((LOG_INFO, "auth_peer_fail: %d proto=%X\n", unit, protocol));
+ AUTHDEBUG(LOG_INFO, ("auth_peer_fail: %d proto=%X\n", unit, protocol));
/*
* Authentication failure: take the link down
*/
@@ -344,8 +588,8 @@ void
auth_peer_success(int unit, u16_t protocol, char *name, int namelen)
{
int pbit;
-
- AUTHDEBUG((LOG_INFO, "auth_peer_success: %d proto=%X\n", unit, protocol));
+
+ AUTHDEBUG(LOG_INFO, ("auth_peer_success: %d proto=%X\n", unit, protocol));
switch (protocol) {
case PPP_CHAP:
pbit = CHAP_PEER;
@@ -354,14 +598,14 @@ auth_peer_success(int unit, u16_t protocol, char *name, int namelen)
pbit = PAP_PEER;
break;
default:
- AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n", protocol));
+ AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol));
return;
}
-
+
/*
* Save the authenticated name of the peer for later.
*/
- if (namelen > sizeof(peer_authname) - 1) {
+ if (namelen > (int)sizeof(peer_authname) - 1) {
namelen = sizeof(peer_authname) - 1;
}
BCOPY(name, peer_authname, namelen);
@@ -383,25 +627,21 @@ void
auth_withpeer_fail(int unit, u16_t protocol)
{
int errCode = PPPERR_AUTHFAIL;
-
+
LWIP_UNUSED_ARG(protocol);
- AUTHDEBUG((LOG_INFO, "auth_withpeer_fail: %d proto=%X\n", unit, protocol));
+ AUTHDEBUG(LOG_INFO, ("auth_withpeer_fail: %d proto=%X\n", unit, protocol));
if (passwd_from_file) {
BZERO(ppp_settings.passwd, MAXSECRETLEN);
}
- /*
- * XXX Warning: the unit number indicates the interface which is
- * not necessarily the PPP connection. It works here as long
- * as we are only supporting PPP interfaces.
- */
- pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode);
/*
* We've failed to authenticate ourselves to our peer.
* He'll probably take the link down, and there's not much
* we can do except wait for that.
*/
+ pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode);
+ lcp_close(unit, "Failed to authenticate ourselves to peer");
}
/*
@@ -411,8 +651,8 @@ void
auth_withpeer_success(int unit, u16_t protocol)
{
int pbit;
-
- AUTHDEBUG((LOG_INFO, "auth_withpeer_success: %d proto=%X\n", unit, protocol));
+
+ AUTHDEBUG(LOG_INFO, ("auth_withpeer_success: %d proto=%X\n", unit, protocol));
switch (protocol) {
case PPP_CHAP:
pbit = CHAP_WITHPEER;
@@ -424,10 +664,10 @@ auth_withpeer_success(int unit, u16_t protocol)
pbit = PAP_WITHPEER;
break;
default:
- AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n", protocol));
+ AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol));
pbit = 0;
}
-
+
/*
* If there is no more authentication still being done,
* proceed to the network (or callback) phase.
@@ -448,16 +688,16 @@ np_up(int unit, u16_t proto)
LWIP_UNUSED_ARG(unit);
LWIP_UNUSED_ARG(proto);
- AUTHDEBUG((LOG_INFO, "np_up: %d proto=%X\n", unit, proto));
+ AUTHDEBUG(LOG_INFO, ("np_up: %d proto=%X\n", unit, proto));
if (num_np_up == 0) {
- AUTHDEBUG((LOG_INFO, "np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit));
+ AUTHDEBUG(LOG_INFO, ("np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit));
/*
* At this point we consider that the link has come up successfully.
*/
if (ppp_settings.idle_time_limit > 0) {
TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit);
}
-
+
/*
* Set a timeout to close the connection once the maximum
* connect time has expired.
@@ -478,7 +718,7 @@ np_down(int unit, u16_t proto)
LWIP_UNUSED_ARG(unit);
LWIP_UNUSED_ARG(proto);
- AUTHDEBUG((LOG_INFO, "np_down: %d proto=%X\n", unit, proto));
+ AUTHDEBUG(LOG_INFO, ("np_down: %d proto=%X\n", unit, proto));
if (--num_np_up == 0 && ppp_settings.idle_time_limit > 0) {
UNTIMEOUT(check_idle, NULL);
}
@@ -493,7 +733,7 @@ np_finished(int unit, u16_t proto)
LWIP_UNUSED_ARG(unit);
LWIP_UNUSED_ARG(proto);
- AUTHDEBUG((LOG_INFO, "np_finished: %d proto=%X\n", unit, proto));
+ AUTHDEBUG(LOG_INFO, ("np_finished: %d proto=%X\n", unit, proto));
if (--num_np_open <= 0) {
/* no further use for the link: shut up shop. */
lcp_close(0, "No network protocols running");
@@ -501,6 +741,85 @@ np_finished(int unit, u16_t proto)
}
/*
+ * check_idle - check whether the link has been idle for long
+ * enough that we can shut it down.
+ */
+static void
+check_idle(void *arg)
+{
+ struct ppp_idle idle;
+ u_short itime;
+
+ LWIP_UNUSED_ARG(arg);
+ if (!get_idle_time(0, &idle)) {
+ return;
+ }
+ itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle);
+ if (itime >= ppp_settings.idle_time_limit) {
+ /* link is idle: shut it down. */
+ AUTHDEBUG(LOG_INFO, ("Terminating connection due to lack of activity.\n"));
+ lcp_close(0, "Link inactive");
+ } else {
+ TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime);
+ }
+}
+
+/*
+ * connect_time_expired - log a message and close the connection.
+ */
+static void
+connect_time_expired(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+
+ AUTHDEBUG(LOG_INFO, ("Connect time expired\n"));
+ lcp_close(0, "Connect time expired"); /* Close connection */
+}
+
+#if 0 /* UNUSED */
+/*
+ * auth_check_options - called to check authentication options.
+ */
+void
+auth_check_options(void)
+{
+ lcp_options *wo = &lcp_wantoptions[0];
+ int can_auth;
+ ipcp_options *ipwo = &ipcp_wantoptions[0];
+ u32_t remote;
+
+ /* Default our_name to hostname, and user to our_name */
+ if (ppp_settings.our_name[0] == 0 || ppp_settings.usehostname) {
+ strcpy(ppp_settings.our_name, ppp_settings.hostname);
+ }
+
+ if (ppp_settings.user[0] == 0) {
+ strcpy(ppp_settings.user, ppp_settings.our_name);
+ }
+
+ /* If authentication is required, ask peer for CHAP or PAP. */
+ if (ppp_settings.auth_required && !wo->neg_chap && !wo->neg_upap) {
+ wo->neg_chap = 1;
+ wo->neg_upap = 1;
+ }
+
+ /*
+ * Check whether we have appropriate secrets to use
+ * to authenticate the peer.
+ */
+ can_auth = wo->neg_upap && have_pap_secret();
+ if (!can_auth && wo->neg_chap) {
+ remote = ipwo->accept_remote? 0: ipwo->hisaddr;
+ can_auth = have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote);
+ }
+
+ if (ppp_settings.auth_required && !can_auth) {
+ ppp_panic("No auth secret");
+ }
+}
+#endif /* UNUSED */
+
+/*
* auth_reset - called when LCP is starting negotiations to recheck
* authentication options, i.e. whether we have appropriate secrets
* to use for authenticating ourselves and/or the peer.
@@ -513,7 +832,7 @@ auth_reset(int unit)
ipcp_options *ipwo = &ipcp_wantoptions[0];
u32_t remote;
- AUTHDEBUG((LOG_INFO, "auth_reset: %d\n", unit));
+ AUTHDEBUG(LOG_INFO, ("auth_reset: %d\n", unit));
ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL));
ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/;
@@ -539,10 +858,10 @@ auth_reset(int unit)
* UPAP_AUTHACK: Authentication succeeded.
* In either case, msg points to an appropriate message.
*/
-int
+u_char
check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen, char **msg, int *msglen)
{
-#if 1
+#if 1 /* XXX Assume all entries OK. */
LWIP_UNUSED_ARG(unit);
LWIP_UNUSED_ARG(auser);
LWIP_UNUSED_ARG(userlen);
@@ -552,7 +871,7 @@ check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen,
*msg = (char *) 0;
return UPAP_AUTHACK; /* XXX Assume all entries OK. */
#else
- int ret = 0;
+ u_char ret = 0;
struct wordlist *addrs = NULL;
char passwd[256], user[256];
char secret[MAXWORDLEN];
@@ -581,11 +900,14 @@ check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen,
* On 10'th, drop the connection.
*/
if (attempts++ >= 10) {
- AUTHDEBUG((LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user));
+ AUTHDEBUG(LOG_WARNING, ("%d LOGIN FAILURES BY %s\n", attempts, user));
/*ppp_panic("Excess Bad Logins");*/
}
if (attempts > 3) {
- sys_msleep((attempts - 3) * 5);
+ /* @todo: this was sleep(), i.e. seconds, not milliseconds
+ * I don't think we really need this in lwIP - we would block tcpip_thread!
+ */
+ /*sys_msleep((attempts - 3) * 5);*/
}
if (addrs != NULL) {
free_wordlist(addrs);
@@ -607,247 +929,70 @@ check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen,
}
#endif /* PAP_SUPPORT */
-
-/*
- * auth_ip_addr - check whether the peer is authorized to use
- * a given IP address. Returns 1 if authorized, 0 otherwise.
- */
-int
-auth_ip_addr(int unit, u32_t addr)
-{
- return ip_addr_check(addr, addresses[unit]);
-}
-
-/*
- * bad_ip_adrs - return 1 if the IP address is one we don't want
- * to use, such as an address in the loopback net or a multicast address.
- * addr is in network byte order.
- */
-int
-bad_ip_adrs(u32_t addr)
-{
- addr = ntohl(addr);
- return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET
- || IN_MULTICAST(addr) || IN_BADCLASS(addr);
-}
-
-
-#if CHAP_SUPPORT
+#if 0 /* UNUSED */
/*
- * get_secret - open the CHAP secret file and return the secret
- * for authenticating the given client on the given server.
- * (We could be either client or server).
+ * This function is needed for PAM.
*/
-int get_secret( int unit, char *client, char *server, char *secret, int *secret_len, int save_addrs)
-{
-#if 1
- int len;
- struct wordlist *addrs;
- LWIP_UNUSED_ARG(unit);
- LWIP_UNUSED_ARG(server);
- LWIP_UNUSED_ARG(save_addrs);
+#ifdef USE_PAM
- addrs = NULL;
+/* lwip does not support PAM*/
- if(!client || !client[0] || strcmp(client, ppp_settings.user)) {
- return 0;
- }
+#endif /* USE_PAM */
- len = strlen(ppp_settings.passwd);
- if (len > MAXSECRETLEN) {
- AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
- len = MAXSECRETLEN;
- }
+#endif /* UNUSED */
- BCOPY(ppp_settings.passwd, secret, len);
- *secret_len = len;
- return 1;
-#else
- int ret = 0, len;
- struct wordlist *addrs;
- char secbuf[MAXWORDLEN];
-
- addrs = NULL;
- secbuf[0] = 0;
+#if 0 /* UNUSED */
+/*
+ * plogin - Check the user name and password against the system
+ * password database, and login the user if OK.
+ *
+ * returns:
+ * UPAP_AUTHNAK: Login failed.
+ * UPAP_AUTHACK: Login succeeded.
+ * In either case, msg points to an appropriate message.
+ */
+static int
+plogin(char *user, char *passwd, char **msg, int *msglen)
+{
- /* XXX Find secret. */
- if (ret < 0) {
- return 0;
- }
+ LWIP_UNUSED_ARG(user);
+ LWIP_UNUSED_ARG(passwd);
+ LWIP_UNUSED_ARG(msg);
+ LWIP_UNUSED_ARG(msglen);
- if (save_addrs) {
- set_allowed_addrs(unit, addrs);
- }
- len = strlen(secbuf);
- if (len > MAXSECRETLEN) {
- AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
- len = MAXSECRETLEN;
- }
+ /* The new lines are here align the file when
+ * compared against the pppd 2.3.11 code */
- BCOPY(secbuf, secret, len);
- BZERO(secbuf, sizeof(secbuf));
- *secret_len = len;
- return 1;
-#endif
-}
-#endif /* CHAP_SUPPORT */
-#if 0 /* UNUSED */
-/*
- * auth_check_options - called to check authentication options.
- */
-void
-auth_check_options(void)
-{
- lcp_options *wo = &lcp_wantoptions[0];
- int can_auth;
- ipcp_options *ipwo = &ipcp_wantoptions[0];
- u32_t remote;
- /* Default our_name to hostname, and user to our_name */
- if (ppp_settings.our_name[0] == 0 || ppp_settings.usehostname) {
- strcpy(ppp_settings.our_name, ppp_settings.hostname);
- }
- if (ppp_settings.user[0] == 0) {
- strcpy(ppp_settings.user, ppp_settings.our_name);
- }
- /* If authentication is required, ask peer for CHAP or PAP. */
- if (ppp_settings.auth_required && !wo->neg_chap && !wo->neg_upap) {
- wo->neg_chap = 1;
- wo->neg_upap = 1;
- }
-
- /*
- * Check whether we have appropriate secrets to use
- * to authenticate the peer.
- */
- can_auth = wo->neg_upap && have_pap_secret();
- if (!can_auth && wo->neg_chap) {
- remote = ipwo->accept_remote? 0: ipwo->hisaddr;
- can_auth = have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote);
- }
- if (ppp_settings.auth_required && !can_auth) {
- ppp_panic("No auth secret");
- }
-}
-#endif
-/**********************************/
-/*** LOCAL FUNCTION DEFINITIONS ***/
-/**********************************/
-/*
- * Proceed to the network phase.
- */
-static void
-network_phase(int unit)
-{
- int i;
- struct protent *protp;
- lcp_options *go = &lcp_gotoptions[unit];
-
- /*
- * If the peer had to authenticate, run the auth-up script now.
- */
- if ((go->neg_chap || go->neg_upap) && !did_authup) {
- /* XXX Do setup for peer authentication. */
- did_authup = 1;
- }
-#if CBCP_SUPPORT
- /*
- * If we negotiated callback, do it now.
- */
- if (go->neg_cbcp) {
- lcp_phase[unit] = PHASE_CALLBACK;
- (*cbcp_protent.open)(unit);
- return;
- }
-#endif /* CBCP_SUPPORT */
- lcp_phase[unit] = PHASE_NETWORK;
- for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
- if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) {
- (*protp->open)(unit);
- if (protp->protocol != PPP_CCP) {
- ++num_np_open;
- }
- }
- }
- if (num_np_open == 0) {
- /* nothing to do */
- lcp_close(0, "No network protocols running");
- }
-}
-
-/*
- * check_idle - check whether the link has been idle for long
- * enough that we can shut it down.
- */
-static void
-check_idle(void *arg)
-{
- struct ppp_idle idle;
- u_short itime;
-
- LWIP_UNUSED_ARG(arg);
- if (!get_idle_time(0, &idle)) {
- return;
- }
- itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle);
- if (itime >= ppp_settings.idle_time_limit) {
- /* link is idle: shut it down. */
- AUTHDEBUG((LOG_INFO, "Terminating connection due to lack of activity.\n"));
- lcp_close(0, "Link inactive");
- } else {
- TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime);
- }
-}
-/*
- * connect_time_expired - log a message and close the connection.
- */
-static void
-connect_time_expired(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- AUTHDEBUG((LOG_INFO, "Connect time expired\n"));
- lcp_close(0, "Connect time expired"); /* Close connection */
-}
-#if 0
-/*
- * login - Check the user name and password against the system
- * password database, and login the user if OK.
- *
- * returns:
- * UPAP_AUTHNAK: Login failed.
- * UPAP_AUTHACK: Login succeeded.
- * In either case, msg points to an appropriate message.
- */
-static int
-login(char *user, char *passwd, char **msg, int *msglen)
-{
/* XXX Fail until we decide that we want to support logins. */
return (UPAP_AUTHNAK);
}
#endif
+
+
/*
- * logout - Logout the user.
+ * plogout - Logout the user.
*/
static void
-logout(void)
+plogout(void)
{
logged_in = 0;
}
@@ -865,6 +1010,7 @@ null_login(int unit)
return 0;
}
+
/*
* get_pap_passwd - get a password for authenticating ourselves with
* our peer using PAP. Returns 1 on success, 0 if no suitable password
@@ -878,6 +1024,8 @@ get_pap_passwd(int unit, char *user, char *passwd)
but this causes problems with some providers (like CHT in Taiwan)
who incorrectly request PAP and expect a bogus/empty password, so
always provide a default user/passwd of "none"/"none"
+
+ @todo: This should be configured by the user, instead of being hardcoded here!
*/
if(user) {
strcpy(user, "none");
@@ -911,9 +1059,76 @@ have_chap_secret(char *client, char *server, u32_t remote)
LWIP_UNUSED_ARG(client);
LWIP_UNUSED_ARG(server);
LWIP_UNUSED_ARG(remote);
+
/* XXX Fail until we set up our passwords. */
return 0;
}
+#if CHAP_SUPPORT
+
+/*
+ * get_secret - open the CHAP secret file and return the secret
+ * for authenticating the given client on the given server.
+ * (We could be either client or server).
+ */
+int
+get_secret(int unit, char *client, char *server, char *secret, int *secret_len, int save_addrs)
+{
+#if 1
+ int len;
+ struct wordlist *addrs;
+
+ LWIP_UNUSED_ARG(unit);
+ LWIP_UNUSED_ARG(server);
+ LWIP_UNUSED_ARG(save_addrs);
+
+ addrs = NULL;
+
+ if(!client || !client[0] || strcmp(client, ppp_settings.user)) {
+ return 0;
+ }
+
+ len = (int)strlen(ppp_settings.passwd);
+ if (len > MAXSECRETLEN) {
+ AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server));
+ len = MAXSECRETLEN;
+ }
+
+ BCOPY(ppp_settings.passwd, secret, len);
+ *secret_len = len;
+
+ return 1;
+#else
+ int ret = 0, len;
+ struct wordlist *addrs;
+ char secbuf[MAXWORDLEN];
+
+ addrs = NULL;
+ secbuf[0] = 0;
+
+ /* XXX Find secret. */
+ if (ret < 0) {
+ return 0;
+ }
+
+ if (save_addrs) {
+ set_allowed_addrs(unit, addrs);
+ }
+
+ len = strlen(secbuf);
+ if (len > MAXSECRETLEN) {
+ AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server));
+ len = MAXSECRETLEN;
+ }
+
+ BCOPY(secbuf, secret, len);
+ BZERO(secbuf, sizeof(secbuf));
+ *secret_len = len;
+
+ return 1;
+#endif
+}
+#endif /* CHAP_SUPPORT */
+
#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */
/*
@@ -954,7 +1169,17 @@ set_allowed_addrs(int unit, struct wordlist *addrs)
}
#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */
-static int
+/*
+ * auth_ip_addr - check whether the peer is authorized to use
+ * a given IP address. Returns 1 if authorized, 0 otherwise.
+ */
+int
+auth_ip_addr(int unit, u32_t addr)
+{
+ return ip_addr_check(addr, addresses[unit]);
+}
+
+static int /* @todo: integrate this funtion into auth_ip_addr()*/
ip_addr_check(u32_t addr, struct wordlist *addrs)
{
/* don't allow loopback or multicast address */
@@ -970,7 +1195,71 @@ ip_addr_check(u32_t addr, struct wordlist *addrs)
return 1;
}
-#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */
+/*
+ * bad_ip_adrs - return 1 if the IP address is one we don't want
+ * to use, such as an address in the loopback net or a multicast address.
+ * addr is in network byte order.
+ */
+int
+bad_ip_adrs(u32_t addr)
+{
+ addr = ntohl(addr);
+ return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET
+ || IN_MULTICAST(addr) || IN_BADCLASS(addr);
+}
+
+#if 0 /* UNUSED */ /* PAP_SUPPORT || CHAP_SUPPORT */
+/*
+ * some_ip_ok - check a wordlist to see if it authorizes any
+ * IP address(es).
+ */
+static int
+some_ip_ok(struct wordlist *addrs)
+{
+ for (; addrs != 0; addrs = addrs->next) {
+ if (addrs->word[0] == '-')
+ break;
+ if (addrs->word[0] != '!')
+ return 1; /* some IP address is allowed */
+ }
+ return 0;
+}
+
+/*
+ * check_access - complain if a secret file has too-liberal permissions.
+ */
+static void
+check_access(FILE *f, char *filename)
+{
+ struct stat sbuf;
+
+ if (fstat(fileno(f), &sbuf) < 0) {
+ warn("cannot stat secret file %s: %m", filename);
+ } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) {
+ warn("Warning - secret file %s has world and/or group access",
+ filename);
+ }
+}
+
+
+/*
+ * scan_authfile - Scan an authorization file for a secret suitable
+ * for authenticating `client' on `server'. The return value is -1
+ * if no secret is found, otherwise >= 0. The return value has
+ * NONWILD_CLIENT set if the secret didn't have "*" for the client, and
+ * NONWILD_SERVER set if the secret didn't have "*" for the server.
+ * Any following words on the line up to a "--" (i.e. address authorization
+ * info) are placed in a wordlist and returned in *addrs. Any
+ * following words (extra options) are placed in a wordlist and
+ * returned in *opts.
+ * We assume secret is NULL or points to MAXWORDLEN bytes of space.
+ */
+static int
+scan_authfile(FILE *f, char *client, char *server, char *secret, struct wordlist **addrs, struct wordlist **opts, char *filename)
+{
+ /* We do not (currently) need this in lwip */
+ return 0; /* dummy */
+}
/*
* free_wordlist - release memory allocated for a wordlist.
*/
@@ -978,13 +1267,68 @@ static void
free_wordlist(struct wordlist *wp)
{
struct wordlist *next;
-
+
while (wp != NULL) {
next = wp->next;
free(wp);
wp = next;
}
}
-#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */
+/*
+ * auth_script_done - called when the auth-up or auth-down script
+ * has finished.
+ */
+static void
+auth_script_done(void *arg)
+{
+ auth_script_pid = 0;
+ switch (auth_script_state) {
+ case s_up:
+ if (auth_state == s_down) {
+ auth_script_state = s_down;
+ auth_script(_PATH_AUTHDOWN);
+ }
+ break;
+ case s_down:
+ if (auth_state == s_up) {
+ auth_script_state = s_up;
+ auth_script(_PATH_AUTHUP);
+ }
+ break;
+ }
+}
+
+/*
+ * auth_script - execute a script with arguments
+ * interface-name peer-name real-user tty speed
+ */
+static void
+auth_script(char *script)
+{
+ char strspeed[32];
+ struct passwd *pw;
+ char struid[32];
+ char *user_name;
+ char *argv[8];
+
+ if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL)
+ user_name = pw->pw_name;
+ else {
+ slprintf(struid, sizeof(struid), "%d", getuid());
+ user_name = struid;
+ }
+ slprintf(strspeed, sizeof(strspeed), "%d", baud_rate);
+
+ argv[0] = script;
+ argv[1] = ifname;
+ argv[2] = peer_authname;
+ argv[3] = user_name;
+ argv[4] = devnam;
+ argv[5] = strspeed;
+ argv[6] = NULL;
+
+ auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL);
+}
+#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */
#endif /* PPP_SUPPORT */
diff --git a/core/lwip/src/netif/ppp/auth.h b/core/lwip/src/netif/ppp/auth.h
index 86ff0494..a8069ec4 100644
--- a/core/lwip/src/netif/ppp/auth.h
+++ b/core/lwip/src/netif/ppp/auth.h
@@ -97,7 +97,7 @@ void auth_check_options (void);
void auth_reset (int);
/* Check peer-supplied username/password */
-int check_passwd (int, char *, int, char *, int, char **, int *);
+u_char check_passwd (int, char *, int, char *, int, char **, int *);
/* get "secret" for chap */
int get_secret (int, char *, char *, char *, int *, int);
diff --git a/core/lwip/src/netif/ppp/chap.c b/core/lwip/src/netif/ppp/chap.c
index b3ea6b22..3a49ff8a 100644
--- a/core/lwip/src/netif/ppp/chap.c
+++ b/core/lwip/src/netif/ppp/chap.c
@@ -84,19 +84,25 @@
#include <string.h>
-/*************************/
-/*** LOCAL DEFINITIONS ***/
-/*************************/
-
-
-/************************/
-/*** LOCAL DATA TYPES ***/
-/************************/
-
+#if 0 /* UNUSED */
+/*
+ * Command-line options.
+ */
+static option_t chap_option_list[] = {
+ { "chap-restart", o_int, &chap[0].timeouttime,
+ "Set timeout for CHAP" },
+ { "chap-max-challenge", o_int, &chap[0].max_transmits,
+ "Set max #xmits for challenge" },
+ { "chap-interval", o_int, &chap[0].chal_interval,
+ "Set interval for rechallenge" },
+#ifdef MSLANMAN
+ { "ms-lanman", o_bool, &ms_lanman,
+ "Use LanMan passwd when using MS-CHAP", 1 },
+#endif
+ { NULL }
+};
+#endif /* UNUSED */
-/***********************************/
-/*** LOCAL FUNCTION DECLARATIONS ***/
-/***********************************/
/*
* Protocol entry points.
*/
@@ -105,28 +111,10 @@ static void ChapLowerUp (int);
static void ChapLowerDown (int);
static void ChapInput (int, u_char *, int);
static void ChapProtocolReject (int);
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *);
#endif
-static void ChapChallengeTimeout (void *);
-static void ChapResponseTimeout (void *);
-static void ChapReceiveChallenge (chap_state *, u_char *, int, int);
-static void ChapRechallenge (void *);
-static void ChapReceiveResponse (chap_state *, u_char *, int, int);
-static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len);
-static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len);
-static void ChapSendStatus (chap_state *, int);
-static void ChapSendChallenge (chap_state *);
-static void ChapSendResponse (chap_state *);
-static void ChapGenChallenge (chap_state *);
-
-
-/******************************/
-/*** PUBLIC DATA STRUCTURES ***/
-/******************************/
-chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
-
struct protent chap_protent = {
PPP_CHAP,
ChapInit,
@@ -136,29 +124,57 @@ struct protent chap_protent = {
ChapLowerDown,
NULL,
NULL,
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
ChapPrintPkt,
NULL,
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
1,
"CHAP",
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
NULL,
NULL,
NULL
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
};
+chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
+
+static void ChapChallengeTimeout (void *);
+static void ChapResponseTimeout (void *);
+static void ChapReceiveChallenge (chap_state *, u_char *, u_char, int);
+static void ChapRechallenge (void *);
+static void ChapReceiveResponse (chap_state *, u_char *, int, int);
+static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len);
+static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len);
+static void ChapSendStatus (chap_state *, int);
+static void ChapSendChallenge (chap_state *);
+static void ChapSendResponse (chap_state *);
+static void ChapGenChallenge (chap_state *);
+
+/*
+ * ChapInit - Initialize a CHAP unit.
+ */
+static void
+ChapInit(int unit)
+{
+ chap_state *cstate = &chap[unit];
+
+ BZERO(cstate, sizeof(*cstate));
+ cstate->unit = unit;
+ cstate->clientstate = CHAPCS_INITIAL;
+ cstate->serverstate = CHAPSS_INITIAL;
+ cstate->timeouttime = CHAP_DEFTIMEOUT;
+ cstate->max_transmits = CHAP_DEFTRANSMITS;
+ /* random number generator is initialized in magic_init */
+}
+
-/***********************************/
-/*** PUBLIC FUNCTION DEFINITIONS ***/
-/***********************************/
/*
* ChapAuthWithPeer - Authenticate us with our peer (start client).
*
*/
void
-ChapAuthWithPeer(int unit, char *our_name, int digest)
+ChapAuthWithPeer(int unit, char *our_name, u_char digest)
{
chap_state *cstate = &chap[unit];
@@ -185,7 +201,7 @@ ChapAuthWithPeer(int unit, char *our_name, int digest)
* ChapAuthPeer - Authenticate our peer (start server).
*/
void
-ChapAuthPeer(int unit, char *our_name, int digest)
+ChapAuthPeer(int unit, char *our_name, u_char digest)
{
chap_state *cstate = &chap[unit];
@@ -205,27 +221,6 @@ ChapAuthPeer(int unit, char *our_name, int digest)
}
-/**********************************/
-/*** LOCAL FUNCTION DEFINITIONS ***/
-/**********************************/
-/*
- * ChapInit - Initialize a CHAP unit.
- */
-static void
-ChapInit(int unit)
-{
- chap_state *cstate = &chap[unit];
-
- BZERO(cstate, sizeof(*cstate));
- cstate->unit = unit;
- cstate->clientstate = CHAPCS_INITIAL;
- cstate->serverstate = CHAPSS_INITIAL;
- cstate->timeouttime = CHAP_DEFTIMEOUT;
- cstate->max_transmits = CHAP_DEFTRANSMITS;
- /* random number generator is initialized in magic_init */
-}
-
-
/*
* ChapChallengeTimeout - Timeout expired on sending challenge.
*/
@@ -243,7 +238,7 @@ ChapChallengeTimeout(void *arg)
if (cstate->chal_transmits >= cstate->max_transmits) {
/* give up on peer */
- CHAPDEBUG((LOG_ERR, "Peer failed to respond to CHAP challenge\n"));
+ CHAPDEBUG(LOG_ERR, ("Peer failed to respond to CHAP challenge\n"));
cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, PPP_CHAP);
return;
@@ -355,7 +350,7 @@ ChapProtocolReject(int unit)
}
if (cstate->clientstate != CHAPCS_INITIAL &&
cstate->clientstate != CHAPCS_CLOSED) {
- auth_withpeer_fail(unit, PPP_CHAP);
+ auth_withpeer_fail(unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */
}
ChapLowerDown(unit); /* shutdown chap */
}
@@ -378,18 +373,18 @@ ChapInput(int unit, u_char *inpacket, int packet_len)
*/
inp = inpacket;
if (packet_len < CHAP_HEADERLEN) {
- CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short header.\n"));
+ CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short header.\n"));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
GETSHORT(len, inp);
if (len < CHAP_HEADERLEN) {
- CHAPDEBUG((LOG_INFO, "ChapInput: rcvd illegal length.\n"));
+ CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd illegal length.\n"));
return;
}
if (len > packet_len) {
- CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet.\n"));
+ CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short packet.\n"));
return;
}
len -= CHAP_HEADERLEN;
@@ -415,7 +410,7 @@ ChapInput(int unit, u_char *inpacket, int packet_len)
break;
default: /* Need code reject? */
- CHAPDEBUG((LOG_WARNING, "Unknown CHAP code (%d) received.\n", code));
+ CHAPDEBUG(LOG_WARNING, ("Unknown CHAP code (%d) received.\n", code));
break;
}
}
@@ -425,7 +420,7 @@ ChapInput(int unit, u_char *inpacket, int packet_len)
* ChapReceiveChallenge - Receive Challenge and send Response.
*/
static void
-ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len)
+ChapReceiveChallenge(chap_state *cstate, u_char *inp, u_char id, int len)
{
int rchallenge_len;
u_char *rchallenge;
@@ -434,48 +429,52 @@ ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len)
char rhostname[256];
MD5_CTX mdContext;
u_char hash[MD5_SIGNATURE_SIZE];
-
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.\n", id));
+
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: Rcvd id %d.\n", id));
if (cstate->clientstate == CHAPCS_CLOSED ||
cstate->clientstate == CHAPCS_PENDING) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d\n",
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: in state %d\n",
cstate->clientstate));
return;
}
if (len < 2) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n"));
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
return;
}
GETCHAR(rchallenge_len, inp);
len -= sizeof (u_char) + rchallenge_len; /* now name field length */
if (len < 0) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n"));
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
return;
}
rchallenge = inp;
INCPTR(rchallenge_len, inp);
- if (len >= sizeof(rhostname)) {
+ if (len >= (int)sizeof(rhostname)) {
len = sizeof(rhostname) - 1;
}
BCOPY(inp, rhostname, len);
rhostname[len] = '\000';
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field '%s'\n", rhostname));
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: received name field '%s'\n",
+ rhostname));
/* Microsoft doesn't send their name back in the PPP packet */
if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) {
strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname));
rhostname[sizeof(rhostname) - 1] = 0;
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name\n", rhostname));
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: using '%s' as remote name\n",
+ rhostname));
}
/* get secret for authenticating ourselves with the specified host */
- if (!get_secret(cstate->unit, cstate->resp_name, rhostname, secret, &secret_len, 0)) {
+ if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
+ secret, &secret_len, 0)) {
secret_len = 0; /* assume null secret if can't find one */
- CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating us to %s\n", rhostname));
+ CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating us to %s\n",
+ rhostname));
}
/* cancel response send timeout if necessary */
@@ -499,14 +498,14 @@ ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len)
cstate->resp_length = MD5_SIGNATURE_SIZE;
break;
-#ifdef CHAPMS
+#if MSCHAP_SUPPORT
case CHAP_MICROSOFT:
ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
break;
#endif
default:
- CHAPDEBUG((LOG_INFO, "unknown digest type %d\n", cstate->resp_type));
+ CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->resp_type));
return;
}
@@ -528,12 +527,12 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
MD5_CTX mdContext;
char secret[MAXSECRETLEN];
u_char hash[MD5_SIGNATURE_SIZE];
-
- CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: Rcvd id %d.\n", id));
+
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: Rcvd id %d.\n", id));
if (cstate->serverstate == CHAPSS_CLOSED ||
cstate->serverstate == CHAPSS_PENDING) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: in state %d\n",
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: in state %d\n",
cstate->serverstate));
return;
}
@@ -557,7 +556,7 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
}
if (len < 2) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n"));
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
return;
}
GETCHAR(remmd_len, inp); /* get length of MD */
@@ -566,29 +565,30 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
len -= sizeof (u_char) + remmd_len;
if (len < 0) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n"));
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
return;
}
UNTIMEOUT(ChapChallengeTimeout, cstate);
- if (len >= sizeof(rhostname)) {
+ if (len >= (int)sizeof(rhostname)) {
len = sizeof(rhostname) - 1;
}
BCOPY(inp, rhostname, len);
rhostname[len] = '\000';
- CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: received name field: %s\n", rhostname));
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: received name field: %s\n",
+ rhostname));
/*
* Get secret for authenticating them with us,
* do the hash ourselves, and compare the result.
*/
code = CHAP_FAILURE;
- if (!get_secret(cstate->unit, rhostname, cstate->chal_name, secret, &secret_len, 1)) {
- /* CHAPDEBUG((LOG_WARNING, TL_CHAP, "No CHAP secret found for authenticating %s\n", rhostname)); */
- CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating %s\n",
- rhostname));
+ if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
+ secret, &secret_len, 1)) {
+ CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating %s\n",
+ rhostname));
} else {
/* generate MD based on negotiated type */
switch (cstate->chal_type) {
@@ -610,7 +610,7 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
break;
default:
- CHAPDEBUG((LOG_INFO, "unknown digest type %d\n", cstate->chal_type));
+ CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->chal_type));
}
}
@@ -627,7 +627,7 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
}
} else {
- CHAPDEBUG((LOG_ERR, "CHAP peer authentication failed\n"));
+ CHAPDEBUG(LOG_ERR, ("CHAP peer authentication failed\n"));
cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, PPP_CHAP);
}
@@ -642,7 +642,7 @@ ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len)
LWIP_UNUSED_ARG(id);
LWIP_UNUSED_ARG(inp);
- CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: Rcvd id %d.\n", id));
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: Rcvd id %d.\n", id));
if (cstate->clientstate == CHAPCS_OPEN) {
/* presumably an answer to a duplicate response */
@@ -651,7 +651,8 @@ ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len)
if (cstate->clientstate != CHAPCS_RESPONSE) {
/* don't know what this is */
- CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: in state %d\n", cstate->clientstate));
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: in state %d\n",
+ cstate->clientstate));
return;
}
@@ -679,11 +680,12 @@ ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len)
LWIP_UNUSED_ARG(id);
LWIP_UNUSED_ARG(inp);
- CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.\n", id));
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: Rcvd id %d.\n", id));
if (cstate->clientstate != CHAPCS_RESPONSE) {
/* don't know what this is */
- CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: in state %d\n", cstate->clientstate));
+ CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: in state %d\n",
+ cstate->clientstate));
return;
}
@@ -696,8 +698,8 @@ ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len)
PRINTMSG(inp, len);
}
- CHAPDEBUG((LOG_ERR, "CHAP authentication failed\n"));
- auth_withpeer_fail(cstate->unit, PPP_CHAP);
+ CHAPDEBUG(LOG_ERR, ("CHAP authentication failed\n"));
+ auth_withpeer_fail(cstate->unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */
}
@@ -712,25 +714,25 @@ ChapSendChallenge(chap_state *cstate)
int outlen;
chal_len = cstate->chal_len;
- name_len = strlen(cstate->chal_name);
+ name_len = (int)strlen(cstate->chal_name);
outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
outp = outpacket_buf[cstate->unit];
-
+
MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
-
+
PUTCHAR(CHAP_CHALLENGE, outp);
PUTCHAR(cstate->chal_id, outp);
PUTSHORT(outlen, outp);
-
+
PUTCHAR(chal_len, outp); /* put length of challenge */
BCOPY(cstate->challenge, outp, chal_len);
INCPTR(chal_len, outp);
-
+
BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
-
- CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.\n", cstate->chal_id));
+
+ CHAPDEBUG(LOG_INFO, ("ChapSendChallenge: Sent id %d.\n", cstate->chal_id));
TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
++cstate->chal_transmits;
@@ -745,18 +747,18 @@ ChapSendStatus(chap_state *cstate, int code)
{
u_char *outp;
int outlen, msglen;
- char msg[256];
-
+ char msg[256]; /* @todo: this can be a char*, no strcpy needed */
+
if (code == CHAP_SUCCESS) {
strcpy(msg, "Welcome!");
} else {
strcpy(msg, "I don't like you. Go 'way.");
}
- msglen = strlen(msg);
-
+ msglen = (int)strlen(msg);
+
outlen = CHAP_HEADERLEN + msglen;
outp = outpacket_buf[cstate->unit];
-
+
MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
PUTCHAR(code, outp);
@@ -764,8 +766,9 @@ ChapSendStatus(chap_state *cstate, int code)
PUTSHORT(outlen, outp);
BCOPY(msg, outp, msglen);
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
-
- CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.\n", code, cstate->chal_id));
+
+ CHAPDEBUG(LOG_INFO, ("ChapSendStatus: Sent code %d, id %d.\n", code,
+ cstate->chal_id));
}
/*
@@ -781,17 +784,18 @@ ChapGenChallenge(chap_state *cstate)
int chal_len;
u_char *ptr = cstate->challenge;
int i;
-
+
/* pick a random challenge length between MIN_CHALLENGE_LENGTH and
MAX_CHALLENGE_LENGTH */
chal_len = (unsigned)
((((magic() >> 16) *
(MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16)
+ MIN_CHALLENGE_LENGTH);
- cstate->chal_len = chal_len;
+ LWIP_ASSERT("chal_len <= 0xff", chal_len <= 0xffff);
+ cstate->chal_len = (u_char)chal_len;
cstate->chal_id = ++cstate->id;
cstate->chal_transmits = 0;
-
+
/* generate a random string */
for (i = 0; i < chal_len; i++ ) {
*ptr++ = (char) (magic() & 0xff);
@@ -808,12 +812,12 @@ ChapSendResponse(chap_state *cstate)
{
u_char *outp;
int outlen, md_len, name_len;
-
+
md_len = cstate->resp_length;
- name_len = strlen(cstate->resp_name);
+ name_len = (int)strlen(cstate->resp_name);
outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
outp = outpacket_buf[cstate->unit];
-
+
MAKEHEADER(outp, PPP_CHAP);
PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
@@ -823,18 +827,18 @@ ChapSendResponse(chap_state *cstate)
PUTCHAR(md_len, outp); /* length of MD */
BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
INCPTR(md_len, outp);
-
+
BCOPY(cstate->resp_name, outp, name_len); /* append our name */
-
+
/* send the packet */
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
-
+
cstate->clientstate = CHAPCS_RESPONSE;
TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
++cstate->resp_transmits;
}
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
static char *ChapCodenames[] = {
"Challenge", "Response", "Success", "Failure"
};
@@ -847,7 +851,7 @@ ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *
int code, id, len;
int clen, nlen;
u_char x;
-
+
if (plen < CHAP_HEADERLEN) {
return 0;
}
@@ -857,6 +861,7 @@ ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *
if (len < CHAP_HEADERLEN || len > plen) {
return 0;
}
+
if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) {
printer(arg, " %s", ChapCodenames[code-1]);
} else {
@@ -896,7 +901,7 @@ ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *
return len + CHAP_HEADERLEN;
}
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
#endif /* CHAP_SUPPORT */
diff --git a/core/lwip/src/netif/ppp/chap.h b/core/lwip/src/netif/ppp/chap.h
index 83dafd73..fedcab8d 100644
--- a/core/lwip/src/netif/ppp/chap.h
+++ b/core/lwip/src/netif/ppp/chap.h
@@ -62,16 +62,12 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: chap.h,v 1.4 2007/12/19 20:47:22 fbernon Exp $
+ * $Id: chap.h,v 1.6 2010/01/24 13:19:34 goldsimon Exp $
*/
#ifndef CHAP_H
#define CHAP_H
-/*************************
-*** PUBLIC DEFINITIONS ***
-*************************/
-
/* Code + ID + length */
#define CHAP_HEADERLEN 4
@@ -97,31 +93,6 @@
#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */
/*
- * Client (peer) states.
- */
-#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */
-#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */
-#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */
-#define CHAPCS_LISTEN 3 /* Listening for a challenge */
-#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */
-#define CHAPCS_OPEN 5 /* We've received Success */
-
-/*
- * Server (authenticator) states.
- */
-#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */
-#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */
-#define CHAPSS_PENDING 2 /* Auth peer when lower up */
-#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */
-#define CHAPSS_OPEN 4 /* We've sent a Success msg */
-#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */
-#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */
-
-/************************
-*** PUBLIC DATA TYPES ***
-************************/
-
-/*
* Each interface is described by a chap structure.
*/
@@ -148,19 +119,32 @@ typedef struct chap_state {
} chap_state;
-/******************
-*** PUBLIC DATA ***
-******************/
-extern chap_state chap[];
+/*
+ * Client (peer) states.
+ */
+#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */
+#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */
+#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */
+#define CHAPCS_LISTEN 3 /* Listening for a challenge */
+#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */
+#define CHAPCS_OPEN 5 /* We've received Success */
-extern struct protent chap_protent;
+/*
+ * Server (authenticator) states.
+ */
+#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */
+#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */
+#define CHAPSS_PENDING 2 /* Auth peer when lower up */
+#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */
+#define CHAPSS_OPEN 4 /* We've sent a Success msg */
+#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */
+#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */
+extern chap_state chap[];
-/***********************
-*** PUBLIC FUNCTIONS ***
-***********************/
+void ChapAuthWithPeer (int, char *, u_char);
+void ChapAuthPeer (int, char *, u_char);
-void ChapAuthWithPeer (int, char *, int);
-void ChapAuthPeer (int, char *, int);
+extern struct protent chap_protent;
#endif /* CHAP_H */
diff --git a/core/lwip/src/netif/ppp/chpms.c b/core/lwip/src/netif/ppp/chpms.c
index 582cfd2d..83acefce 100644
--- a/core/lwip/src/netif/ppp/chpms.c
+++ b/core/lwip/src/netif/ppp/chpms.c
@@ -85,6 +85,8 @@
#include "chap.h"
#include "chpms.h"
+#include <string.h>
+
/*************************/
/*** LOCAL DEFINITIONS ***/
@@ -137,49 +139,12 @@ static u_char Get7Bits(
int startBit
);
-
-/***********************************/
-/*** PUBLIC FUNCTION DEFINITIONS ***/
-/***********************************/
-void
-ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len)
-{
- MS_ChapResponse response;
-#ifdef MSLANMAN
- extern int ms_lanman;
-#endif
-
-#if 0
- CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'\n", secret_len, secret));
-#endif
- BZERO(&response, sizeof(response));
-
- /* Calculate both always */
- ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
-
-#ifdef MSLANMAN
- ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
-
- /* prefered method is set by option */
- response.UseNT = !ms_lanman;
-#else
- response.UseNT = 1;
-#endif
-
- BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
- cstate->resp_length = MS_CHAP_RESPONSE_LEN;
-}
-
-
-/**********************************/
-/*** LOCAL FUNCTION DEFINITIONS ***/
-/**********************************/
static void
ChallengeResponse( u_char *challenge, /* IN 8 octets */
u_char *pwHash, /* IN 16 octets */
u_char *response /* OUT 24 octets */)
{
- char ZPasswordHash[21];
+ u_char ZPasswordHash[21];
BZERO(ZPasswordHash, sizeof(ZPasswordHash));
BCOPY(pwHash, ZPasswordHash, 16);
@@ -211,19 +176,19 @@ DesEncrypt( u_char *clear, /* IN 8 octets */
MakeKey(key, des_key);
Expand(des_key, crypt_key);
- setkey(crypt_key);
+ setkey((char*)crypt_key);
#if 0
- CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
+ CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
#endif
Expand(clear, des_input);
- encrypt(des_input, 0);
+ encrypt((char*)des_input, 0);
Collapse(des_input, cipher);
#if 0
- CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
+ CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
#endif
}
@@ -243,14 +208,14 @@ DesEncrypt( u_char *clear, /* IN 8 octets */
des_set_key(&des_key, key_schedule);
#if 0
- CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
+ CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
#endif
des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
#if 0
- CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
+ CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
#endif
}
@@ -329,9 +294,9 @@ MakeKey( u_char *key, /* IN 56 bit DES key missing parity bits */
#endif
#if 0
- CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n",
+ CHAPDEBUG(LOG_INFO, ("MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n",
key[0], key[1], key[2], key[3], key[4], key[5], key[6]));
- CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
+ CHAPDEBUG(LOG_INFO, ("MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7]));
#endif
}
@@ -348,6 +313,8 @@ ChapMS_NT( char *rchallenge,
u_char unicodePassword[MAX_NT_PASSWORD * 2];
static int low_byte_first = -1;
+ LWIP_UNUSED_ARG(rchallenge_len);
+
/* Initialize the Unicode version of the secret (== password). */
/* This implicitly supports 8-bit ISO8859/1 characters. */
BZERO(unicodePassword, sizeof(unicodePassword));
@@ -358,15 +325,16 @@ ChapMS_NT( char *rchallenge,
MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */
if (low_byte_first == -1) {
- low_byte_first = (htons((unsigned short int)1) != 1);
+ low_byte_first = (PP_HTONS((unsigned short int)1) != 1);
}
if (low_byte_first == 0) {
- MDreverse((u_long *)&md4Context); /* sfb 961105 */
+ /* @todo: arg type - u_long* or u_int* ? */
+ MDreverse((unsigned int*)&md4Context); /* sfb 961105 */
}
MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */
- ChallengeResponse(rchallenge, (char *)md4Context.buffer, response->NTResp);
+ ChallengeResponse((u_char*)rchallenge, (u_char*)md4Context.buffer, response->NTResp);
}
#ifdef MSLANMAN
@@ -394,6 +362,35 @@ ChapMS_LANMan( char *rchallenge,
}
#endif
+void
+ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len)
+{
+ MS_ChapResponse response;
+#ifdef MSLANMAN
+ extern int ms_lanman;
+#endif
+
+#if 0
+ CHAPDEBUG(LOG_INFO, ("ChapMS: secret is '%.*s'\n", secret_len, secret));
+#endif
+ BZERO(&response, sizeof(response));
+
+ /* Calculate both always */
+ ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
+
+#ifdef MSLANMAN
+ ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
+
+ /* prefered method is set by option */
+ response.UseNT = !ms_lanman;
+#else
+ response.UseNT = 1;
+#endif
+
+ BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
+ cstate->resp_length = MS_CHAP_RESPONSE_LEN;
+}
+
#endif /* MSCHAP_SUPPORT */
#endif /* PPP_SUPPORT */
diff --git a/core/lwip/src/netif/ppp/fsm.c b/core/lwip/src/netif/ppp/fsm.c
index ee549f23..2e73c5af 100644
--- a/core/lwip/src/netif/ppp/fsm.c
+++ b/core/lwip/src/netif/ppp/fsm.c
@@ -66,13 +66,7 @@
#include <string.h>
-
-/*************************/
-/*** LOCAL DEFINITIONS ***/
-/*************************/
-
#if PPP_DEBUG
-
static const char *ppperr_strerr[] = {
"LS_INITIAL", /* LS_INITIAL 0 */
"LS_STARTING", /* LS_STARTING 1 */
@@ -85,17 +79,8 @@ static const char *ppperr_strerr[] = {
"LS_ACKSENT", /* LS_ACKSENT 8 */
"LS_OPENED" /* LS_OPENED 9 */
};
-
#endif /* PPP_DEBUG */
-/************************/
-/*** LOCAL DATA TYPES ***/
-/************************/
-
-
-/***********************************/
-/*** LOCAL FUNCTION DECLARATIONS ***/
-/***********************************/
static void fsm_timeout (void *);
static void fsm_rconfreq (fsm *, u_char, u_char *, int);
static void fsm_rconfack (fsm *, int, u_char *, int);
@@ -107,22 +92,9 @@ static void fsm_sconfreq (fsm *, int);
#define PROTO_NAME(f) ((f)->callbacks->proto_name)
-
-/******************************/
-/*** PUBLIC DATA STRUCTURES ***/
-/******************************/
-
-
-/*****************************/
-/*** LOCAL DATA STRUCTURES ***/
-/*****************************/
int peer_mru[NUM_PPP];
-/***********************************/
-/*** PUBLIC FUNCTION DEFINITIONS ***/
-/***********************************/
-
/*
* fsm_init - Initialize fsm.
*
@@ -168,11 +140,11 @@ fsm_lowerup(fsm *f)
break;
default:
- FSMDEBUG((LOG_INFO, "%s: Up event in state %d (%s)!\n",
+ FSMDEBUG(LOG_INFO, ("%s: Up event in state %d (%s)!\n",
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
}
-
- FSMDEBUG((LOG_INFO, "%s: lowerup state %d (%s) -> %d (%s)\n",
+
+ FSMDEBUG(LOG_INFO, ("%s: lowerup state %d (%s) -> %d (%s)\n",
PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
}
@@ -222,11 +194,11 @@ fsm_lowerdown(fsm *f)
break;
default:
- FSMDEBUG((LOG_INFO, "%s: Down event in state %d (%s)!\n",
+ FSMDEBUG(LOG_INFO, ("%s: Down event in state %d (%s)!\n",
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
}
- FSMDEBUG((LOG_INFO, "%s: lowerdown state %d (%s) -> %d (%s)\n",
+ FSMDEBUG(LOG_INFO, ("%s: lowerdown state %d (%s) -> %d (%s)\n",
PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
}
@@ -271,10 +243,23 @@ fsm_open(fsm *f)
break;
}
- FSMDEBUG((LOG_INFO, "%s: open state %d (%s) -> %d (%s)\n",
+ FSMDEBUG(LOG_INFO, ("%s: open state %d (%s) -> %d (%s)\n",
PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
}
+#if 0 /* backport pppd 2.4.4b1; */
+/*
+ * terminate_layer - Start process of shutting down the FSM
+ *
+ * Cancel any timeout running, notify upper layers we're done, and
+ * send a terminate-request message as configured.
+ */
+static void
+terminate_layer(fsm *f, int nextstate)
+{
+ /* @todo */
+}
+#endif
/*
* fsm_close - Start closing connection.
@@ -290,7 +275,7 @@ fsm_close(fsm *f, char *reason)
LWIP_UNUSED_ARG(oldState);
f->term_reason = reason;
- f->term_reason_len = (reason == NULL? 0: strlen(reason));
+ f->term_reason_len = (reason == NULL ? 0 : (int)strlen(reason));
switch( f->state ) {
case LS_STARTING:
f->state = LS_INITIAL;
@@ -322,38 +307,71 @@ fsm_close(fsm *f, char *reason)
break;
}
- FSMDEBUG((LOG_INFO, "%s: close reason=%s state %d (%s) -> %d (%s)\n",
+ FSMDEBUG(LOG_INFO, ("%s: close reason=%s state %d (%s) -> %d (%s)\n",
PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
}
/*
- * fsm_sdata - Send some data.
- *
- * Used for all packets sent to our peer by this module.
+ * fsm_timeout - Timeout expired.
*/
-void
-fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen)
+static void
+fsm_timeout(void *arg)
{
- u_char *outp;
- int outlen;
+ fsm *f = (fsm *) arg;
- /* Adjust length to be smaller than MTU */
- outp = outpacket_buf[f->unit];
- if (datalen > peer_mru[f->unit] - (int)HEADERLEN) {
- datalen = peer_mru[f->unit] - HEADERLEN;
- }
- if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) {
- BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
+ switch (f->state) {
+ case LS_CLOSING:
+ case LS_STOPPING:
+ if( f->retransmits <= 0 ) {
+ FSMDEBUG(LOG_WARNING, ("%s: timeout sending Terminate-Request state=%d (%s)\n",
+ PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
+ /*
+ * We've waited for an ack long enough. Peer probably heard us.
+ */
+ f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED;
+ if( f->callbacks->finished ) {
+ (*f->callbacks->finished)(f);
+ }
+ } else {
+ FSMDEBUG(LOG_WARNING, ("%s: timeout resending Terminate-Requests state=%d (%s)\n",
+ PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
+ /* Send Terminate-Request */
+ fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
+ (u_char *) f->term_reason, f->term_reason_len);
+ TIMEOUT(fsm_timeout, f, f->timeouttime);
+ --f->retransmits;
+ }
+ break;
+
+ case LS_REQSENT:
+ case LS_ACKRCVD:
+ case LS_ACKSENT:
+ if (f->retransmits <= 0) {
+ FSMDEBUG(LOG_WARNING, ("%s: timeout sending Config-Requests state=%d (%s)\n",
+ PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
+ f->state = LS_STOPPED;
+ if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) {
+ (*f->callbacks->finished)(f);
+ }
+ } else {
+ FSMDEBUG(LOG_WARNING, ("%s: timeout resending Config-Request state=%d (%s)\n",
+ PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
+ /* Retransmit the configure-request */
+ if (f->callbacks->retransmit) {
+ (*f->callbacks->retransmit)(f);
+ }
+ fsm_sconfreq(f, 1); /* Re-send Configure-Request */
+ if( f->state == LS_ACKRCVD ) {
+ f->state = LS_REQSENT;
+ }
+ }
+ break;
+
+ default:
+ FSMDEBUG(LOG_INFO, ("%s: UNHANDLED timeout event in state %d (%s)!\n",
+ PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
}
- outlen = datalen + HEADERLEN;
- MAKEHEADER(outp, f->protocol);
- PUTCHAR(code, outp);
- PUTCHAR(id, outp);
- PUTSHORT(outlen, outp);
- pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN);
- FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d,%d,%d.\n",
- PROTO_NAME(f), code, id, outlen));
}
@@ -372,7 +390,7 @@ fsm_input(fsm *f, u_char *inpacket, int l)
* If packet too short, drop it.
*/
if (l < HEADERLEN) {
- FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.\n",
+ FSMDEBUG(LOG_WARNING, ("fsm_input(%x): Rcvd short header.\n",
f->protocol));
return;
}
@@ -380,23 +398,23 @@ fsm_input(fsm *f, u_char *inpacket, int l)
GETCHAR(id, inp);
GETSHORT(len, inp);
if (len < HEADERLEN) {
- FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.\n",
+ FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd illegal length.\n",
f->protocol));
return;
}
if (len > l) {
- FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.\n",
+ FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd short packet.\n",
f->protocol));
return;
}
len -= HEADERLEN; /* subtract header length */
if( f->state == LS_INITIAL || f->state == LS_STARTING ) {
- FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d (%s).\n",
+ FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd packet in state %d (%s).\n",
f->protocol, f->state, ppperr_strerr[f->state]));
return;
}
- FSMDEBUG((LOG_INFO, "fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l));
+ FSMDEBUG(LOG_INFO, ("fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l));
/*
* Action depends on code.
*/
@@ -427,6 +445,7 @@ fsm_input(fsm *f, u_char *inpacket, int l)
break;
default:
+ FSMDEBUG(LOG_INFO, ("fsm_input(%s): default: \n", PROTO_NAME(f)));
if( !f->callbacks->extcode ||
!(*f->callbacks->extcode)(f, code, id, inp, len) ) {
fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
@@ -437,129 +456,6 @@ fsm_input(fsm *f, u_char *inpacket, int l)
/*
- * fsm_protreject - Peer doesn't speak this protocol.
- *
- * Treat this as a catastrophic error (RXJ-).
- */
-void
-fsm_protreject(fsm *f)
-{
- switch( f->state ) {
- case LS_CLOSING:
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- /* fall through */
- case LS_CLOSED:
- f->state = LS_CLOSED;
- if( f->callbacks->finished ) {
- (*f->callbacks->finished)(f);
- }
- break;
-
- case LS_STOPPING:
- case LS_REQSENT:
- case LS_ACKRCVD:
- case LS_ACKSENT:
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- /* fall through */
- case LS_STOPPED:
- f->state = LS_STOPPED;
- if( f->callbacks->finished ) {
- (*f->callbacks->finished)(f);
- }
- break;
-
- case LS_OPENED:
- if( f->callbacks->down ) {
- (*f->callbacks->down)(f);
- }
- /* Init restart counter, send Terminate-Request */
- f->retransmits = f->maxtermtransmits;
- fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
- (u_char *) f->term_reason, f->term_reason_len);
- TIMEOUT(fsm_timeout, f, f->timeouttime);
- --f->retransmits;
-
- f->state = LS_STOPPING;
- break;
-
- default:
- FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d (%s)!\n",
- PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
- }
-}
-
-
-
-
-
-/**********************************/
-/*** LOCAL FUNCTION DEFINITIONS ***/
-/**********************************/
-
-/*
- * fsm_timeout - Timeout expired.
- */
-static void
-fsm_timeout(void *arg)
-{
- fsm *f = (fsm *) arg;
-
- switch (f->state) {
- case LS_CLOSING:
- case LS_STOPPING:
- if( f->retransmits <= 0 ) {
- FSMDEBUG((LOG_WARNING, "%s: timeout sending Terminate-Request state=%d (%s)\n",
- PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
- /*
- * We've waited for an ack long enough. Peer probably heard us.
- */
- f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED;
- if( f->callbacks->finished ) {
- (*f->callbacks->finished)(f);
- }
- } else {
- FSMDEBUG((LOG_WARNING, "%s: timeout resending Terminate-Requests state=%d (%s)\n",
- PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
- /* Send Terminate-Request */
- fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
- (u_char *) f->term_reason, f->term_reason_len);
- TIMEOUT(fsm_timeout, f, f->timeouttime);
- --f->retransmits;
- }
- break;
-
- case LS_REQSENT:
- case LS_ACKRCVD:
- case LS_ACKSENT:
- if (f->retransmits <= 0) {
- FSMDEBUG((LOG_WARNING, "%s: timeout sending Config-Requests state=%d (%s)\n",
- PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
- f->state = LS_STOPPED;
- if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) {
- (*f->callbacks->finished)(f);
- }
- } else {
- FSMDEBUG((LOG_WARNING, "%s: timeout resending Config-Request state=%d (%s)\n",
- PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
- /* Retransmit the configure-request */
- if (f->callbacks->retransmit) {
- (*f->callbacks->retransmit)(f);
- }
- fsm_sconfreq(f, 1); /* Re-send Configure-Request */
- if( f->state == LS_ACKRCVD ) {
- f->state = LS_REQSENT;
- }
- }
- break;
-
- default:
- FSMDEBUG((LOG_INFO, "%s: UNHANDLED timeout event in state %d (%s)!\n",
- PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
- }
-}
-
-
-/*
* fsm_rconfreq - Receive Configure-Request.
*/
static void
@@ -567,7 +463,7 @@ fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len)
{
int code, reject_if_disagree;
- FSMDEBUG((LOG_INFO, "fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n",
+ FSMDEBUG(LOG_INFO, ("fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n",
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
switch( f->state ) {
case LS_CLOSED:
@@ -638,7 +534,7 @@ fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len)
static void
fsm_rconfack(fsm *f, int id, u_char *inp, int len)
{
- FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n",
+ FSMDEBUG(LOG_INFO, ("fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n",
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
if (id != f->reqid || f->seen_ack) { /* Expected id? */
@@ -646,7 +542,7 @@ fsm_rconfack(fsm *f, int id, u_char *inp, int len)
}
if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) {
/* Ack is bad - ignore it */
- FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)\n",
+ FSMDEBUG(LOG_INFO, ("%s: received bad Ack (length %d)\n",
PROTO_NAME(f), len));
return;
}
@@ -700,7 +596,7 @@ fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len)
int (*proc) (fsm *, u_char *, int);
int ret;
- FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n",
+ FSMDEBUG(LOG_INFO, ("fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n",
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
if (id != f->reqid || f->seen_ack) { /* Expected id? */
@@ -709,7 +605,7 @@ fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len)
proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
if (!proc || !((ret = proc(f, inp, len)))) {
/* Nak/reject is bad - ignore it */
- FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)\n",
+ FSMDEBUG(LOG_INFO, ("%s: received bad %s (length %d)\n",
PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len));
return;
}
@@ -759,7 +655,7 @@ fsm_rtermreq(fsm *f, int id, u_char *p, int len)
{
LWIP_UNUSED_ARG(p);
- FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n",
+ FSMDEBUG(LOG_INFO, ("fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n",
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
switch (f->state) {
@@ -770,9 +666,9 @@ fsm_rtermreq(fsm *f, int id, u_char *p, int len)
case LS_OPENED:
if (len > 0) {
- FSMDEBUG((LOG_INFO, "%s terminated by peer (%x)\n", PROTO_NAME(f), p));
+ FSMDEBUG(LOG_INFO, ("%s terminated by peer (%p)\n", PROTO_NAME(f), p));
} else {
- FSMDEBUG((LOG_INFO, "%s terminated by peer\n", PROTO_NAME(f)));
+ FSMDEBUG(LOG_INFO, ("%s terminated by peer\n", PROTO_NAME(f)));
}
if (f->callbacks->down) {
(*f->callbacks->down)(f); /* Inform upper layers */
@@ -793,7 +689,7 @@ fsm_rtermreq(fsm *f, int id, u_char *p, int len)
static void
fsm_rtermack(fsm *f)
{
- FSMDEBUG((LOG_INFO, "fsm_rtermack(%s): state=%d (%s)\n",
+ FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): state=%d (%s)\n",
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
switch (f->state) {
@@ -823,6 +719,9 @@ fsm_rtermack(fsm *f)
}
fsm_sconfreq(f, 0);
break;
+ default:
+ FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): UNHANDLED state=%d (%s)!!!\n",
+ PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
}
}
@@ -835,16 +734,16 @@ fsm_rcoderej(fsm *f, u_char *inp, int len)
{
u_char code, id;
- FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s): state=%d (%s)\n",
+ FSMDEBUG(LOG_INFO, ("fsm_rcoderej(%s): state=%d (%s)\n",
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
if (len < HEADERLEN) {
- FSMDEBUG((LOG_INFO, "fsm_rcoderej: Rcvd short Code-Reject packet!\n"));
+ FSMDEBUG(LOG_INFO, ("fsm_rcoderej: Rcvd short Code-Reject packet!\n"));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
- FSMDEBUG((LOG_WARNING, "%s: Rcvd Code-Reject for code %d, id %d\n",
+ FSMDEBUG(LOG_WARNING, ("%s: Rcvd Code-Reject for code %d, id %d\n",
PROTO_NAME(f), code, id));
if( f->state == LS_ACKRCVD ) {
@@ -854,6 +753,59 @@ fsm_rcoderej(fsm *f, u_char *inp, int len)
/*
+ * fsm_protreject - Peer doesn't speak this protocol.
+ *
+ * Treat this as a catastrophic error (RXJ-).
+ */
+void
+fsm_protreject(fsm *f)
+{
+ switch( f->state ) {
+ case LS_CLOSING:
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ /* fall through */
+ case LS_CLOSED:
+ f->state = LS_CLOSED;
+ if( f->callbacks->finished ) {
+ (*f->callbacks->finished)(f);
+ }
+ break;
+
+ case LS_STOPPING:
+ case LS_REQSENT:
+ case LS_ACKRCVD:
+ case LS_ACKSENT:
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ /* fall through */
+ case LS_STOPPED:
+ f->state = LS_STOPPED;
+ if( f->callbacks->finished ) {
+ (*f->callbacks->finished)(f);
+ }
+ break;
+
+ case LS_OPENED:
+ if( f->callbacks->down ) {
+ (*f->callbacks->down)(f);
+ }
+ /* Init restart counter, send Terminate-Request */
+ f->retransmits = f->maxtermtransmits;
+ fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
+ (u_char *) f->term_reason, f->term_reason_len);
+ TIMEOUT(fsm_timeout, f, f->timeouttime);
+ --f->retransmits;
+
+ f->state = LS_STOPPING;
+ break;
+
+ default:
+ FSMDEBUG(LOG_INFO, ("%s: Protocol-reject event in state %d (%s)!\n",
+ PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
+ }
+}
+
+
+/*
* fsm_sconfreq - Send a Configure-Request.
*/
static void
@@ -901,8 +853,38 @@ fsm_sconfreq(fsm *f, int retransmit)
--f->retransmits;
TIMEOUT(fsm_timeout, f, f->timeouttime);
- FSMDEBUG((LOG_INFO, "%s: sending Configure-Request, id %d\n",
+ FSMDEBUG(LOG_INFO, ("%s: sending Configure-Request, id %d\n",
PROTO_NAME(f), f->reqid));
}
+
+/*
+ * fsm_sdata - Send some data.
+ *
+ * Used for all packets sent to our peer by this module.
+ */
+void
+fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen)
+{
+ u_char *outp;
+ int outlen;
+
+ /* Adjust length to be smaller than MTU */
+ outp = outpacket_buf[f->unit];
+ if (datalen > peer_mru[f->unit] - (int)HEADERLEN) {
+ datalen = peer_mru[f->unit] - HEADERLEN;
+ }
+ if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) {
+ BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
+ }
+ outlen = datalen + HEADERLEN;
+ MAKEHEADER(outp, f->protocol);
+ PUTCHAR(code, outp);
+ PUTCHAR(id, outp);
+ PUTSHORT(outlen, outp);
+ pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN);
+ FSMDEBUG(LOG_INFO, ("fsm_sdata(%s): Sent code %d,%d,%d.\n",
+ PROTO_NAME(f), code, id, outlen));
+}
+
#endif /* PPP_SUPPORT */
diff --git a/core/lwip/src/netif/ppp/fsm.h b/core/lwip/src/netif/ppp/fsm.h
index 14034ec7..8d41b5f5 100644
--- a/core/lwip/src/netif/ppp/fsm.h
+++ b/core/lwip/src/netif/ppp/fsm.h
@@ -48,15 +48,12 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: fsm.h,v 1.4 2007/12/19 20:47:23 fbernon Exp $
+ * $Id: fsm.h,v 1.5 2009/12/31 17:08:08 goldsimon Exp $
*/
#ifndef FSM_H
#define FSM_H
-/*****************************************************************************
-************************* PUBLIC DEFINITIONS *********************************
-*****************************************************************************/
/*
* LCP Packet header = Code, id, length.
*/
@@ -74,32 +71,8 @@
#define TERMACK 6 /* Termination Ack */
#define CODEREJ 7 /* Code Reject */
-/*
- * Link states.
- */
-#define LS_INITIAL 0 /* Down, hasn't been opened */
-#define LS_STARTING 1 /* Down, been opened */
-#define LS_CLOSED 2 /* Up, hasn't been opened */
-#define LS_STOPPED 3 /* Open, waiting for down event */
-#define LS_CLOSING 4 /* Terminating the connection, not open */
-#define LS_STOPPING 5 /* Terminating, but open */
-#define LS_REQSENT 6 /* We've sent a Config Request */
-#define LS_ACKRCVD 7 /* We've received a Config Ack */
-#define LS_ACKSENT 8 /* We've sent a Config Ack */
-#define LS_OPENED 9 /* Connection available */
/*
- * Flags - indicate options controlling FSM operation
- */
-#define OPT_PASSIVE 1 /* Don't die if we don't get a response */
-#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */
-#define OPT_SILENT 4 /* Wait for peer to speak first */
-
-
-/*****************************************************************************
-************************* PUBLIC DATA TYPES **********************************
-*****************************************************************************/
-/*
* Each FSM is described by an fsm structure and fsm callbacks.
*/
typedef struct fsm {
@@ -141,18 +114,27 @@ typedef struct fsm_callbacks {
} fsm_callbacks;
-/*****************************************************************************
-*********************** PUBLIC DATA STRUCTURES *******************************
-*****************************************************************************/
/*
- * Variables
+ * Link states.
*/
-extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */
+#define LS_INITIAL 0 /* Down, hasn't been opened */
+#define LS_STARTING 1 /* Down, been opened */
+#define LS_CLOSED 2 /* Up, hasn't been opened */
+#define LS_STOPPED 3 /* Open, waiting for down event */
+#define LS_CLOSING 4 /* Terminating the connection, not open */
+#define LS_STOPPING 5 /* Terminating, but open */
+#define LS_REQSENT 6 /* We've sent a Config Request */
+#define LS_ACKRCVD 7 /* We've received a Config Ack */
+#define LS_ACKSENT 8 /* We've sent a Config Ack */
+#define LS_OPENED 9 /* Connection available */
+/*
+ * Flags - indicate options controlling FSM operation
+ */
+#define OPT_PASSIVE 1 /* Don't die if we don't get a response */
+#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */
+#define OPT_SILENT 4 /* Wait for peer to speak first */
-/*****************************************************************************
-************************** PUBLIC FUNCTIONS **********************************
-*****************************************************************************/
/*
* Prototypes
@@ -166,4 +148,10 @@ void fsm_input (fsm*, u_char*, int);
void fsm_protreject (fsm*);
void fsm_sdata (fsm*, u_char, u_char, u_char*, int);
+
+/*
+ * Variables
+ */
+extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */
+
#endif /* FSM_H */
diff --git a/core/lwip/src/netif/ppp/ipcp.c b/core/lwip/src/netif/ppp/ipcp.c
index 0ff4ce3f..461a600f 100644
--- a/core/lwip/src/netif/ppp/ipcp.c
+++ b/core/lwip/src/netif/ppp/ipcp.c
@@ -1,3 +1,5 @@
+/** In contrast to pppd 2.3.1, DNS support has been added, proxy-ARP and
+ dial-on-demand has been stripped. */
/*****************************************************************************
* ipcp.c - Network PPP IP Control Protocol program file.
*
@@ -61,27 +63,23 @@
#include "vj.h"
#include "ipcp.h"
+#include "lwip/inet.h"
+
#include <string.h>
-/*************************/
-/*** LOCAL DEFINITIONS ***/
-/*************************/
/* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */
-/*
- * Lengths of configuration options.
- */
-#define CILEN_VOID 2
-#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */
-#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */
-#define CILEN_ADDR 6 /* new-style single address option */
-#define CILEN_ADDRS 10 /* old-style dual address option */
+/* global vars */
+ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
+ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
+ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
+ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
+/* local vars */
+static int default_route_set[NUM_PPP]; /* Have set up a default route */
+static int cis_received[NUM_PPP]; /* # Conf-Reqs received */
-/***********************************/
-/*** LOCAL FUNCTION DECLARATIONS ***/
-/***********************************/
/*
* Callbacks for fsm code. (CI = Configuration Information)
*/
@@ -94,11 +92,33 @@ static int ipcp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */
static int ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */
static void ipcp_up (fsm *); /* We're UP */
static void ipcp_down (fsm *); /* We're DOWN */
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
static void ipcp_script (fsm *, char *); /* Run an up/down script */
#endif
static void ipcp_finished (fsm *); /* Don't need lower layer */
+
+fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
+
+
+static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
+ ipcp_resetci, /* Reset our Configuration Information */
+ ipcp_cilen, /* Length of our Configuration Information */
+ ipcp_addci, /* Add our Configuration Information */
+ ipcp_ackci, /* ACK our Configuration Information */
+ ipcp_nakci, /* NAK our Configuration Information */
+ ipcp_rejci, /* Reject our Configuration Information */
+ ipcp_reqci, /* Request peer's Configuration Information */
+ ipcp_up, /* Called when fsm reaches LS_OPENED state */
+ ipcp_down, /* Called when fsm leaves LS_OPENED state */
+ NULL, /* Called when we want the lower layer up */
+ ipcp_finished, /* Called when we want the lower layer down */
+ NULL, /* Called when Protocol-Reject received */
+ NULL, /* Retransmission is necessary */
+ NULL, /* Called to handle protocol-specific codes */
+ "IPCP" /* String name of protocol */
+};
+
/*
* Protocol entry points from main code.
*/
@@ -110,23 +130,6 @@ static void ipcp_lowerdown (int);
static void ipcp_input (int, u_char *, int);
static void ipcp_protrej (int);
-static void ipcp_clear_addrs (int);
-
-#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
- (x) == CONFNAK ? "NAK" : "REJ")
-
-
-
-/******************************/
-/*** PUBLIC DATA STRUCTURES ***/
-/******************************/
-/* global vars */
-ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
-ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
-ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
-ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
-
-fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
struct protent ipcp_protent = {
PPP_IPCP,
@@ -137,53 +140,34 @@ struct protent ipcp_protent = {
ipcp_lowerdown,
ipcp_open,
ipcp_close,
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
ipcp_printpkt,
NULL,
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
1,
"IPCP",
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
ip_check_options,
NULL,
ip_active_pkt
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
};
+static void ipcp_clear_addrs (int);
-
-/*****************************/
-/*** LOCAL DATA STRUCTURES ***/
-/*****************************/
-/* local vars */
-static int cis_received[NUM_PPP]; /* # Conf-Reqs received */
-static int default_route_set[NUM_PPP]; /* Have set up a default route */
-
-static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
- ipcp_resetci, /* Reset our Configuration Information */
- ipcp_cilen, /* Length of our Configuration Information */
- ipcp_addci, /* Add our Configuration Information */
- ipcp_ackci, /* ACK our Configuration Information */
- ipcp_nakci, /* NAK our Configuration Information */
- ipcp_rejci, /* Reject our Configuration Information */
- ipcp_reqci, /* Request peer's Configuration Information */
- ipcp_up, /* Called when fsm reaches LS_OPENED state */
- ipcp_down, /* Called when fsm leaves LS_OPENED state */
- NULL, /* Called when we want the lower layer up */
- ipcp_finished, /* Called when we want the lower layer down */
- NULL, /* Called when Protocol-Reject received */
- NULL, /* Retransmission is necessary */
- NULL, /* Called to handle protocol-specific codes */
- "IPCP" /* String name of protocol */
-};
-
+/*
+ * Lengths of configuration options.
+ */
+#define CILEN_VOID 2
+#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */
+#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */
+#define CILEN_ADDR 6 /* new-style single address option */
+#define CILEN_ADDRS 10 /* old-style dual address option */
-/**********************************/
-/*** LOCAL FUNCTION DEFINITIONS ***/
-/**********************************/
+#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
+ (x) == CONFNAK ? "NAK" : "REJ")
-#define inet_ntoa(addr) ip_ntoa(((struct ip_addr*)&(addr)))
/*
* ipcp_init - Initialize IPCP.
@@ -542,9 +526,9 @@ ipcp_ackci(fsm *f, u_char *p, int len)
goto bad;
}
return (1);
-
+
bad:
- IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp_ackci: received bad Ack!\n"));
return (0);
}
@@ -628,12 +612,12 @@ ipcp_nakci(fsm *f, u_char *p, int len)
NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
if (go->accept_local && ciaddr1) { /* Do we know our address? */
try.ouraddr = ciaddr1;
- IPCPDEBUG((LOG_INFO, "local IP address %s\n",
+ IPCPDEBUG(LOG_INFO, ("local IP address %s\n",
inet_ntoa(ciaddr1)));
}
if (go->accept_remote && ciaddr2) { /* Does he know his? */
try.hisaddr = ciaddr2;
- IPCPDEBUG((LOG_INFO, "remote IP address %s\n",
+ IPCPDEBUG(LOG_INFO, ("remote IP address %s\n",
inet_ntoa(ciaddr2)));
}
);
@@ -671,12 +655,12 @@ ipcp_nakci(fsm *f, u_char *p, int len)
NAKCIDNS(CI_MS_DNS1, req_dns1,
try.dnsaddr[0] = cidnsaddr;
- IPCPDEBUG((LOG_INFO, "primary DNS address %s\n", inet_ntoa(cidnsaddr)));
+ IPCPDEBUG(LOG_INFO, ("primary DNS address %s\n", inet_ntoa(cidnsaddr)));
);
NAKCIDNS(CI_MS_DNS2, req_dns2,
try.dnsaddr[1] = cidnsaddr;
- IPCPDEBUG((LOG_INFO, "secondary DNS address %s\n", inet_ntoa(cidnsaddr)));
+ IPCPDEBUG(LOG_INFO, ("secondary DNS address %s\n", inet_ntoa(cidnsaddr)));
);
/*
@@ -754,7 +738,7 @@ ipcp_nakci(fsm *f, u_char *p, int len)
return 1;
bad:
- IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp_nakci: received bad Nak!\n"));
return 0;
}
@@ -869,7 +853,7 @@ ipcp_rejci(fsm *f, u_char *p, int len)
return 1;
bad:
- IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp_rejci: received bad Reject!\n"));
return 0;
}
@@ -922,9 +906,9 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
if (l < 2 || /* Not enough data for CI header or */
p[1] < 2 || /* CI length too small or */
p[1] > l) { /* CI length too big? */
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: bad CI length!\n"));
orc = CONFREJ; /* Reject bad CI */
- cilen = l; /* Reject till end of packet */
+ cilen = (u_short)l;/* Reject till end of packet */
l = 0; /* Don't loop again */
goto endswitch;
}
@@ -936,7 +920,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
switch (citype) { /* Check CI type */
#ifdef OLD_CI_ADDRS /* Need to save space... */
case CI_ADDRS:
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: received ADDRS\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received ADDRS\n"));
if (!ao->neg_addr ||
cilen != CILEN_ADDRS) { /* Check CI length */
orc = CONFREJ; /* Reject CI */
@@ -951,7 +935,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
*/
GETLONG(tl, p); /* Parse source address (his) */
ciaddr1 = htonl(tl);
- IPCPDEBUG((LOG_INFO, "his addr %s\n", inet_ntoa(ciaddr1)));
+ IPCPDEBUG(LOG_INFO, ("his addr %s\n", inet_ntoa(ciaddr1)));
if (ciaddr1 != wo->hisaddr
&& (ciaddr1 == 0 || !wo->accept_remote)) {
orc = CONFNAK;
@@ -975,7 +959,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
*/
GETLONG(tl, p); /* Parse desination address (ours) */
ciaddr2 = htonl(tl);
- IPCPDEBUG((LOG_INFO, "our addr %s\n", inet_ntoa(ciaddr2)));
+ IPCPDEBUG(LOG_INFO, ("our addr %s\n", inet_ntoa(ciaddr2)));
if (ciaddr2 != wo->ouraddr) {
if (ciaddr2 == 0 || !wo->accept_local) {
orc = CONFNAK;
@@ -998,11 +982,11 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
case CI_ADDR:
if (!ao->neg_addr) {
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR not allowed\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR not allowed\n"));
orc = CONFREJ; /* Reject CI */
break;
} else if (cilen != CILEN_ADDR) { /* Check CI length */
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR bad len\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR bad len\n"));
orc = CONFREJ; /* Reject CI */
break;
}
@@ -1023,12 +1007,12 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
tl = ntohl(wo->hisaddr);
PUTLONG(tl, p);
}
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1)));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1)));
} else if (ciaddr1 == 0 && wo->hisaddr == 0) {
/*
* Don't ACK an address of 0.0.0.0 - reject it instead.
*/
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1)));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1)));
orc = CONFREJ;
wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
break;
@@ -1036,7 +1020,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
ho->neg_addr = 1;
ho->hisaddr = ciaddr1;
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1)));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1)));
break;
case CI_MS_DNS1:
@@ -1047,27 +1031,27 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
/* If we do not have a DNS address then we cannot send it */
if (ao->dnsaddr[d] == 0 ||
cilen != CILEN_ADDR) { /* Check CI length */
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting DNS%d Request\n", d+1));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting DNS%d Request\n", d+1));
orc = CONFREJ; /* Reject CI */
break;
}
GETLONG(tl, p);
if (htonl(tl) != ao->dnsaddr[d]) {
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking DNS%d Request %d\n",
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking DNS%d Request %s\n",
d+1, inet_ntoa(tl)));
DECPTR(sizeof(u32_t), p);
tl = ntohl(ao->dnsaddr[d]);
PUTLONG(tl, p);
orc = CONFNAK;
}
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: received DNS%d Request\n", d+1));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received DNS%d Request\n", d+1));
break;
case CI_MS_WINS1:
case CI_MS_WINS2:
/* Microsoft primary or secondary WINS request */
d = citype == CI_MS_WINS2;
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: received WINS%d Request\n", d+1));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received WINS%d Request\n", d+1));
/* If we do not have a DNS address then we cannot send it */
if (ao->winsaddr[d] == 0 ||
@@ -1086,11 +1070,11 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
case CI_COMPRESSTYPE:
if (!ao->neg_vj) {
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n"));
orc = CONFREJ;
break;
} else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen));
orc = CONFREJ;
break;
}
@@ -1098,7 +1082,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
if (!(cishort == IPCP_VJ_COMP ||
(cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort));
orc = CONFREJ;
break;
}
@@ -1108,7 +1092,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
if (cilen == CILEN_VJ) {
GETCHAR(maxslotindex, p);
if (maxslotindex > ao->maxslotindex) {
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ max slot %d\n", maxslotindex));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ max slot %d\n", maxslotindex));
orc = CONFNAK;
if (!reject_if_disagree) {
DECPTR(1, p);
@@ -1117,7 +1101,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
}
GETCHAR(cflag, p);
if (cflag && !ao->cflag) {
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ cflag %d\n", cflag));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ cflag %d\n", cflag));
orc = CONFNAK;
if (!reject_if_disagree) {
DECPTR(1, p);
@@ -1131,13 +1115,13 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
ho->maxslotindex = MAX_SLOTS - 1;
ho->cflag = 1;
}
- IPCPDEBUG((LOG_INFO,
+ IPCPDEBUG(LOG_INFO, (
"ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n",
ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag));
break;
default:
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting unknown CI type %d\n", citype));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting unknown CI type %d\n", citype));
orc = CONFREJ;
break;
}
@@ -1150,7 +1134,7 @@ endswitch:
if (orc == CONFNAK) { /* Nak this CI? */
if (reject_if_disagree) { /* Getting fed up with sending NAKs? */
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting too many naks\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting too many naks\n"));
orc = CONFREJ; /* Get tough if so */
} else {
if (rc == CONFREJ) { /* Rejecting prior CI? */
@@ -1187,7 +1171,7 @@ endswitch:
*/
if (rc != CONFREJ && !ho->neg_addr &&
wo->req_addr && !reject_if_disagree) {
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: Requesting peer address\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Requesting peer address\n"));
if (rc == CONFACK) {
rc = CONFNAK;
ucp = inp; /* reset pointer */
@@ -1200,7 +1184,7 @@ endswitch:
}
*len = (int)(ucp - inp); /* Compute output length */
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: returning Configure-%s\n", CODENAME(rc)));
+ IPCPDEBUG(LOG_INFO, ("ipcp_reqci: returning Configure-%s\n", CODENAME(rc)));
return (rc); /* Return final code */
}
@@ -1241,7 +1225,7 @@ ipcp_up(fsm *f)
ipcp_options *wo = &ipcp_wantoptions[f->unit];
np_up(f->unit, PPP_IP);
- IPCPDEBUG((LOG_INFO, "ipcp: up\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp: up\n"));
/*
* We must have a non-zero IP address for both ends of the link.
@@ -1251,12 +1235,12 @@ ipcp_up(fsm *f)
}
if (ho->hisaddr == 0) {
- IPCPDEBUG((LOG_ERR, "Could not determine remote IP address\n"));
+ IPCPDEBUG(LOG_ERR, ("Could not determine remote IP address\n"));
ipcp_close(f->unit, "Could not determine remote IP address");
return;
}
if (go->ouraddr == 0) {
- IPCPDEBUG((LOG_ERR, "Could not determine local IP address\n"));
+ IPCPDEBUG(LOG_ERR, ("Could not determine local IP address\n"));
ipcp_close(f->unit, "Could not determine local IP address");
return;
}
@@ -1269,7 +1253,7 @@ ipcp_up(fsm *f)
* Check that the peer is allowed to use the IP address it wants.
*/
if (!auth_ip_addr(f->unit, ho->hisaddr)) {
- IPCPDEBUG((LOG_ERR, "Peer is not authorized to use remote address %s\n",
+ IPCPDEBUG(LOG_ERR, ("Peer is not authorized to use remote address %s\n",
inet_ntoa(ho->hisaddr)));
ipcp_close(f->unit, "Unauthorized remote IP address");
return;
@@ -1284,14 +1268,14 @@ ipcp_up(fsm *f)
mask = GetMask(go->ouraddr);
if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) {
- IPCPDEBUG((LOG_WARNING, "sifaddr failed\n"));
+ IPCPDEBUG(LOG_WARNING, ("sifaddr failed\n"));
ipcp_close(f->unit, "Interface configuration failed");
return;
}
/* bring the interface up for IP */
if (!sifup(f->unit)) {
- IPCPDEBUG((LOG_WARNING, "sifup failed\n"));
+ IPCPDEBUG(LOG_WARNING, ("sifup failed\n"));
ipcp_close(f->unit, "Interface configuration failed");
return;
}
@@ -1305,13 +1289,13 @@ ipcp_up(fsm *f)
}
}
- IPCPDEBUG((LOG_NOTICE, "local IP address %s\n", inet_ntoa(go->ouraddr)));
- IPCPDEBUG((LOG_NOTICE, "remote IP address %s\n", inet_ntoa(ho->hisaddr)));
+ IPCPDEBUG(LOG_NOTICE, ("local IP address %s\n", inet_ntoa(go->ouraddr)));
+ IPCPDEBUG(LOG_NOTICE, ("remote IP address %s\n", inet_ntoa(ho->hisaddr)));
if (go->dnsaddr[0]) {
- IPCPDEBUG((LOG_NOTICE, "primary DNS address %s\n", inet_ntoa(go->dnsaddr[0])));
+ IPCPDEBUG(LOG_NOTICE, ("primary DNS address %s\n", inet_ntoa(go->dnsaddr[0])));
}
if (go->dnsaddr[1]) {
- IPCPDEBUG((LOG_NOTICE, "secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1])));
+ IPCPDEBUG(LOG_NOTICE, ("secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1])));
}
}
@@ -1325,7 +1309,7 @@ ipcp_up(fsm *f)
static void
ipcp_down(fsm *f)
{
- IPCPDEBUG((LOG_INFO, "ipcp: down\n"));
+ IPCPDEBUG(LOG_INFO, ("ipcp: down\n"));
np_down(f->unit, PPP_IP);
sifvjcomp(f->unit, 0, 0, 0);
@@ -1361,7 +1345,7 @@ ipcp_finished(fsm *f)
np_finished(f->unit, PPP_IP);
}
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
static int
ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
{
@@ -1422,6 +1406,6 @@ ip_active_pkt(u_char *pkt, int len)
}
return 1;
}
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
#endif /* PPP_SUPPORT */
diff --git a/core/lwip/src/netif/ppp/ipcp.h b/core/lwip/src/netif/ppp/ipcp.h
index dfcf4fba..de03f460 100644
--- a/core/lwip/src/netif/ppp/ipcp.h
+++ b/core/lwip/src/netif/ppp/ipcp.h
@@ -48,15 +48,12 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: ipcp.h,v 1.3 2007/12/19 20:47:23 fbernon Exp $
+ * $Id: ipcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $
*/
#ifndef IPCP_H
#define IPCP_H
-/*************************
-*** PUBLIC DEFINITIONS ***
-*************************/
/*
* Options.
*/
@@ -64,10 +61,10 @@
#define CI_COMPRESSTYPE 2 /* Compression Type */
#define CI_ADDR 3
-#define CI_MS_WINS1 128 /* Primary WINS value */
#define CI_MS_DNS1 129 /* Primary DNS value */
-#define CI_MS_WINS2 130 /* Secondary WINS value */
+#define CI_MS_WINS1 128 /* Primary WINS value */
#define CI_MS_DNS2 131 /* Secondary DNS value */
+#define CI_MS_WINS2 130 /* Secondary WINS value */
#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */
#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */
@@ -78,11 +75,6 @@
#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */
/* compression option */
-
-/************************
-*** PUBLIC DATA TYPES ***
-************************/
-
typedef struct ipcp_options {
u_int neg_addr : 1; /* Negotiate IP Address? */
u_int old_addrs : 1; /* Use old (IP-Addresses) option? */
@@ -103,11 +95,6 @@ typedef struct ipcp_options {
u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */
} ipcp_options;
-
-/*****************************
-*** PUBLIC DATA STRUCTURES ***
-*****************************/
-
extern fsm ipcp_fsm[];
extern ipcp_options ipcp_wantoptions[];
extern ipcp_options ipcp_gotoptions[];
@@ -116,9 +103,4 @@ extern ipcp_options ipcp_hisoptions[];
extern struct protent ipcp_protent;
-
-/***********************
-*** PUBLIC FUNCTIONS ***
-***********************/
-
#endif /* IPCP_H */
diff --git a/core/lwip/src/netif/ppp/lcp.c b/core/lwip/src/netif/ppp/lcp.c
index 85a0add9..21c83ac4 100644
--- a/core/lwip/src/netif/ppp/lcp.c
+++ b/core/lwip/src/netif/ppp/lcp.c
@@ -72,25 +72,43 @@
#define PPPOE_MAXMTU PPP_MAXMRU
#endif
-
-/*************************/
-/*** LOCAL DEFINITIONS ***/
-/*************************/
+#if 0 /* UNUSED */
/*
- * Length of each type of configuration option (in octets)
+ * LCP-related command-line options.
*/
-#define CILEN_VOID 2
-#define CILEN_CHAR 3
-#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */
-#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */
-#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */
-#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */
-#define CILEN_CBCP 3
+int lcp_echo_interval = 0; /* Interval between LCP echo-requests */
+int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */
+bool lax_recv = 0; /* accept control chars in asyncmap */
+static int setescape (char **);
+
+static option_t lcp_option_list[] = {
+ /* LCP options */
+ /* list stripped for simplicity */
+ {NULL}
+};
+#endif /* UNUSED */
+
+/* options */
+LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */
+static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */
+static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */
+
+/* global vars */
+static fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/
+lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */
+lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
+lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
+lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
+ext_accm xmit_accm[NUM_PPP]; /* extended transmit ACCM */
+
+static u32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */
+static u32_t lcp_echo_number = 0; /* ID number of next echo frame */
+static u32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */
+
+/* @todo: do we really need such a large buffer? The typical 1500 bytes seem too much. */
+static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */
-/***********************************/
-/*** LOCAL FUNCTION DECLARATIONS ***/
-/***********************************/
/*
* Callbacks for fsm code. (CI = Configuration Information)
*/
@@ -106,12 +124,12 @@ static void lcp_down (fsm*); /* We're DOWN */
static void lcp_starting (fsm*); /* We need lower layer up */
static void lcp_finished (fsm*); /* We need lower layer down */
static int lcp_extcode (fsm*, int, u_char, u_char*, int);
-
static void lcp_rprotrej (fsm*, u_char*, int);
/*
* routines to send LCP echos to peer
*/
+
static void lcp_echo_lowerup (int);
static void lcp_echo_lowerdown (int);
static void LcpEchoTimeout (void*);
@@ -120,41 +138,6 @@ static void LcpSendEchoRequest (fsm*);
static void LcpLinkFailure (fsm*);
static void LcpEchoCheck (fsm*);
-/*
- * Protocol entry points.
- * Some of these are called directly.
- */
-static void lcp_input (int, u_char *, int);
-static void lcp_protrej (int);
-
-#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ")
-
-
-/******************************/
-/*** PUBLIC DATA STRUCTURES ***/
-/******************************/
-/* global vars */
-LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */
-lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */
-lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
-lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
-lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
-ext_accm xmit_accm[NUM_PPP]; /* extended transmit ACCM */
-
-
-
-/*****************************/
-/*** LOCAL DATA STRUCTURES ***/
-/*****************************/
-static fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/
-static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */
-static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */
-static u32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */
-static u32_t lcp_echo_number = 0; /* ID number of next echo frame */
-static u32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */
-
-static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */
-
static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
lcp_resetci, /* Reset our Configuration Information */
lcp_cilen, /* Length of our Configuration Information */
@@ -173,6 +156,14 @@ static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
"LCP" /* String name of protocol */
};
+/*
+ * Protocol entry points.
+ * Some of these are called directly.
+ */
+
+static void lcp_input (int, u_char *, int);
+static void lcp_protrej (int);
+
struct protent lcp_protent = {
PPP_LCP,
lcp_init,
@@ -182,26 +173,66 @@ struct protent lcp_protent = {
lcp_lowerdown,
lcp_open,
lcp_close,
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
lcp_printpkt,
NULL,
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
1,
"LCP",
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
NULL,
NULL,
NULL
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
};
int lcp_loopbackfail = DEFLOOPBACKFAIL;
+/*
+ * Length of each type of configuration option (in octets)
+ */
+#define CILEN_VOID 2
+#define CILEN_CHAR 3
+#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */
+#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */
+#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */
+#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */
+#define CILEN_CBCP 3
+#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ")
+
+#if 0 /* UNUSED */
+/*
+ * setescape - add chars to the set we escape on transmission.
+ */
+static int
+setescape(argv)
+ char **argv;
+{
+ int n, ret;
+ char *p, *endp;
+
+ p = *argv;
+ ret = 1;
+ while (*p) {
+ n = strtol(p, &endp, 16);
+ if (p == endp) {
+ option_error("escape parameter contains invalid hex number '%s'", p);
+ return 0;
+ }
+ p = endp;
+ if (n < 0 || n == 0x5E || n > 0xFF) {
+ option_error("can't escape character 0x%x", n);
+ ret = 0;
+ } else
+ xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
+ while (*p == ',' || *p == ' ')
+ ++p;
+ }
+ return ret;
+}
+#endif /* UNUSED */
-/***********************************/
-/*** PUBLIC FUNCTION DEFINITIONS ***/
-/***********************************/
/*
* lcp_init - Initialize LCP.
*/
@@ -211,13 +242,13 @@ lcp_init(int unit)
fsm *f = &lcp_fsm[unit];
lcp_options *wo = &lcp_wantoptions[unit];
lcp_options *ao = &lcp_allowoptions[unit];
-
+
f->unit = unit;
f->protocol = PPP_LCP;
f->callbacks = &lcp_callbacks;
-
+
fsm_init(f);
-
+
wo->passive = 0;
wo->silent = 0;
wo->restart = 0; /* Set to 1 in kernels or multi-line implementations */
@@ -233,7 +264,7 @@ lcp_init(int unit)
wo->neg_accompression = 1;
wo->neg_lqr = 0; /* no LQR implementation yet */
wo->neg_cbcp = 0;
-
+
ao->neg_mru = 1;
ao->mru = PPP_MAXMRU;
ao->neg_asyncmap = 1;
@@ -257,7 +288,7 @@ lcp_init(int unit)
xmit_accm[unit][1] = (u_char)((ao->asyncmap >> 8) & 0xFF);
xmit_accm[unit][2] = (u_char)((ao->asyncmap >> 16) & 0xFF);
xmit_accm[unit][3] = (u_char)((ao->asyncmap >> 24) & 0xFF);
- LCPDEBUG((LOG_INFO, "lcp_init: xmit_accm=%X %X %X %X\n",
+ LCPDEBUG(LOG_INFO, ("lcp_init: xmit_accm=%X %X %X %X\n",
xmit_accm[unit][0],
xmit_accm[unit][1],
xmit_accm[unit][2],
@@ -310,7 +341,7 @@ lcp_close(int unit, char *reason)
f->state = LS_CLOSED;
lcp_finished(f);
} else {
- fsm_close(&lcp_fsm[unit], reason);
+ fsm_close(f, reason);
}
}
@@ -337,7 +368,7 @@ lcp_lowerup(int unit)
| ((u_long)xmit_accm[unit][1] << 8)
| ((u_long)xmit_accm[unit][2] << 16)
| ((u_long)xmit_accm[unit][3] << 24);
- LCPDEBUG((LOG_INFO, "lcp_lowerup: asyncmap=%X %X %X %X\n",
+ LCPDEBUG(LOG_INFO, ("lcp_lowerup: asyncmap=%X %X %X %X\n",
xmit_accm[unit][3],
xmit_accm[unit][2],
xmit_accm[unit][1],
@@ -356,25 +387,7 @@ lcp_lowerdown(int unit)
fsm_lowerdown(&lcp_fsm[unit]);
}
-/*
- * lcp_sprotrej - Send a Protocol-Reject for some protocol.
- */
-void
-lcp_sprotrej(int unit, u_char *p, int len)
-{
- /*
- * Send back the protocol and the information field of the
- * rejected packet. We only get here if LCP is in the LS_OPENED state.
- */
-
- fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len);
-}
-
-
-/**********************************/
-/*** LOCAL FUNCTION DEFINITIONS ***/
-/**********************************/
/*
* lcp_input - Input LCP packet.
*/
@@ -404,7 +417,7 @@ lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len)
if (f->state != LS_OPENED) {
break;
}
- LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d\n", id));
+ LCPDEBUG(LOG_INFO, ("lcp: Echo-Request, Rcvd id %d\n", id));
magp = inp;
PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
fsm_sdata(f, ECHOREP, id, inp, len);
@@ -413,10 +426,10 @@ lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len)
case ECHOREP:
lcp_received_echo_reply(f, id, inp, len);
break;
-
+
case DISCREQ:
break;
-
+
default:
return 0;
}
@@ -436,21 +449,21 @@ lcp_rprotrej(fsm *f, u_char *inp, int len)
struct protent *protp;
u_short prot;
- if (len < sizeof (u_short)) {
- LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd short Protocol-Reject packet!\n"));
+ if (len < (int)sizeof (u_short)) {
+ LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd short Protocol-Reject packet!\n"));
return;
}
GETSHORT(prot, inp);
- LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot));
+ LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot));
/*
* Protocol-Reject packets received in any state other than the LCP
* LS_OPENED state SHOULD be silently discarded.
*/
if( f->state != LS_OPENED ) {
- LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d\n", f->state));
+ LCPDEBUG(LOG_INFO, ("Protocol-Reject discarded: LCP in state %d\n", f->state));
return;
}
@@ -464,7 +477,7 @@ lcp_rprotrej(fsm *f, u_char *inp, int len)
}
}
- LCPDEBUG((LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x\n", prot));
+ LCPDEBUG(LOG_WARNING, ("Protocol-Reject for unsupported protocol 0x%x\n", prot));
}
@@ -478,12 +491,27 @@ lcp_protrej(int unit)
/*
* Can't reject LCP!
*/
- LCPDEBUG((LOG_WARNING, "lcp_protrej: Received Protocol-Reject for LCP!\n"));
+ LCPDEBUG(LOG_WARNING, ("lcp_protrej: Received Protocol-Reject for LCP!\n"));
fsm_protreject(&lcp_fsm[unit]);
}
/*
+ * lcp_sprotrej - Send a Protocol-Reject for some protocol.
+ */
+void
+lcp_sprotrej(int unit, u_char *p, int len)
+{
+ /*
+ * Send back the protocol and the information field of the
+ * rejected packet. We only get here if LCP is in the LS_OPENED state.
+ */
+
+ fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len);
+}
+
+
+/*
* lcp_resetci - Reset our CI.
*/
static void
@@ -500,7 +528,8 @@ lcp_resetci(fsm *f)
/*
* lcp_cilen - Return length of our CI.
*/
-static int lcp_cilen(fsm *f)
+static int
+lcp_cilen(fsm *f)
{
lcp_options *go = &lcp_gotoptions[f->unit];
@@ -537,20 +566,20 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp)
#define ADDCIVOID(opt, neg) \
if (neg) { \
- LCPDEBUG((LOG_INFO, "lcp_addci: opt=%d\n", opt)); \
+ LCPDEBUG(LOG_INFO, ("lcp_addci: opt=%d\n", opt)); \
PUTCHAR(opt, ucp); \
PUTCHAR(CILEN_VOID, ucp); \
}
#define ADDCISHORT(opt, neg, val) \
if (neg) { \
- LCPDEBUG((LOG_INFO, "lcp_addci: INT opt=%d %X\n", opt, val)); \
+ LCPDEBUG(LOG_INFO, ("lcp_addci: INT opt=%d %X\n", opt, val)); \
PUTCHAR(opt, ucp); \
PUTCHAR(CILEN_SHORT, ucp); \
PUTSHORT(val, ucp); \
}
#define ADDCICHAP(opt, neg, val, digest) \
if (neg) { \
- LCPDEBUG((LOG_INFO, "lcp_addci: CHAP opt=%d %X\n", opt, val)); \
+ LCPDEBUG(LOG_INFO, ("lcp_addci: CHAP opt=%d %X\n", opt, val)); \
PUTCHAR(opt, ucp); \
PUTCHAR(CILEN_CHAP, ucp); \
PUTSHORT(val, ucp); \
@@ -558,14 +587,14 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp)
}
#define ADDCILONG(opt, neg, val) \
if (neg) { \
- LCPDEBUG((LOG_INFO, "lcp_addci: L opt=%d %lX\n", opt, val)); \
+ LCPDEBUG(LOG_INFO, ("lcp_addci: L opt=%d %lX\n", opt, val)); \
PUTCHAR(opt, ucp); \
PUTCHAR(CILEN_LONG, ucp); \
PUTLONG(val, ucp); \
}
#define ADDCILQR(opt, neg, val) \
if (neg) { \
- LCPDEBUG((LOG_INFO, "lcp_addci: LQR opt=%d %lX\n", opt, val)); \
+ LCPDEBUG(LOG_INFO, ("lcp_addci: LQR opt=%d %lX\n", opt, val)); \
PUTCHAR(opt, ucp); \
PUTCHAR(CILEN_LQR, ucp); \
PUTSHORT(PPP_LQR, ucp); \
@@ -573,7 +602,7 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp)
}
#define ADDCICHAR(opt, neg, val) \
if (neg) { \
- LCPDEBUG((LOG_INFO, "lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \
+ LCPDEBUG(LOG_INFO, ("lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \
PUTCHAR(opt, ucp); \
PUTCHAR(CILEN_CHAR, ucp); \
PUTCHAR(val, ucp); \
@@ -591,7 +620,7 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp)
if (ucp - start_ucp != *lenp) {
/* this should never happen, because peer_mtu should be 1500 */
- LCPDEBUG((LOG_ERR, "Bug in lcp_addci: wrong length\n"));
+ LCPDEBUG(LOG_ERR, ("Bug in lcp_addci: wrong length\n"));
}
}
@@ -709,10 +738,10 @@ lcp_ackci(fsm *f, u_char *p, int len)
if (len != 0) {
goto bad;
}
- LCPDEBUG((LOG_INFO, "lcp_acki: Ack\n"));
+ LCPDEBUG(LOG_INFO, ("lcp_acki: Ack\n"));
return (1);
bad:
- LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!\n"));
+ LCPDEBUG(LOG_WARNING, ("lcp_acki: received bad Ack!\n"));
return (0);
}
@@ -1020,7 +1049,7 @@ lcp_nakci(fsm *f, u_char *p, int len)
if (f->state != LS_OPENED) {
if (looped_back) {
if (++try.numloops >= lcp_loopbackfail) {
- LCPDEBUG((LOG_NOTICE, "Serial line is looped back.\n"));
+ LCPDEBUG(LOG_NOTICE, ("Serial line is looped back.\n"));
lcp_close(f->unit, "Loopback detected");
}
} else {
@@ -1032,7 +1061,7 @@ lcp_nakci(fsm *f, u_char *p, int len)
return 1;
bad:
- LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!\n"));
+ LCPDEBUG(LOG_WARNING, ("lcp_nakci: received bad Nak!\n"));
return 0;
}
@@ -1070,7 +1099,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
len -= CILEN_VOID; \
INCPTR(CILEN_VOID, p); \
try.neg = 0; \
- LCPDEBUG((LOG_INFO, "lcp_rejci: void opt %d rejected\n", opt)); \
+ LCPDEBUG(LOG_INFO, ("lcp_rejci: void opt %d rejected\n", opt)); \
}
#define REJCISHORT(opt, neg, val) \
if (go->neg && \
@@ -1085,7 +1114,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
goto bad; \
} \
try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci: short opt %d rejected\n", opt)); \
+ LCPDEBUG(LOG_INFO, ("lcp_rejci: short opt %d rejected\n", opt)); \
}
#define REJCICHAP(opt, neg, val, digest) \
if (go->neg && \
@@ -1102,7 +1131,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
} \
try.neg = 0; \
try.neg_upap = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci: chap opt %d rejected\n", opt)); \
+ LCPDEBUG(LOG_INFO, ("lcp_rejci: chap opt %d rejected\n", opt)); \
}
#define REJCILONG(opt, neg, val) \
if (go->neg && \
@@ -1117,7 +1146,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
goto bad; \
} \
try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci: long opt %d rejected\n", opt)); \
+ LCPDEBUG(LOG_INFO, ("lcp_rejci: long opt %d rejected\n", opt)); \
}
#define REJCILQR(opt, neg, val) \
if (go->neg && \
@@ -1133,7 +1162,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
goto bad; \
} \
try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci: LQR opt %d rejected\n", opt)); \
+ LCPDEBUG(LOG_INFO, ("lcp_rejci: LQR opt %d rejected\n", opt)); \
}
#define REJCICBCP(opt, neg, val) \
if (go->neg && \
@@ -1148,7 +1177,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
goto bad; \
} \
try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci: Callback opt %d rejected\n", opt)); \
+ LCPDEBUG(LOG_INFO, ("lcp_rejci: Callback opt %d rejected\n", opt)); \
}
REJCISHORT(CI_MRU, neg_mru, go->mru);
@@ -1178,7 +1207,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
return 1;
bad:
- LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!\n"));
+ LCPDEBUG(LOG_WARNING, ("lcp_rejci: received bad Reject!\n"));
return 0;
}
@@ -1200,7 +1229,8 @@ lcp_reqci(fsm *f,
lcp_options *ho = &lcp_hisoptions[f->unit];
lcp_options *ao = &lcp_allowoptions[f->unit];
u_char *cip, *next; /* Pointer to current and next CIs */
- int cilen, citype, cichar; /* Parsed len, type, char value */
+ int cilen, citype; /* Parsed len, type */
+ u_char cichar; /* Parsed char value */
u_short cishort; /* Parsed short value */
u32_t cilong; /* Parse long value */
int rc = CONFACK; /* Final packet return code */
@@ -1211,7 +1241,7 @@ lcp_reqci(fsm *f,
int l = *lenp; /* Length left */
#if TRACELCP > 0
char traceBuf[80];
- int traceNdx = 0;
+ size_t traceNdx = 0;
#endif
/*
@@ -1231,7 +1261,7 @@ lcp_reqci(fsm *f,
if (l < 2 || /* Not enough data for CI header or */
p[1] < 2 || /* CI length too small or */
p[1] > l) { /* CI length too big? */
- LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!\n"));
+ LCPDEBUG(LOG_WARNING, ("lcp_reqci: bad CI length!\n"));
orc = CONFREJ; /* Reject bad CI */
cilen = l; /* Reject till end of packet */
l = 0; /* Don't loop again */
@@ -1246,11 +1276,11 @@ lcp_reqci(fsm *f,
switch (citype) { /* Check CI type */
case CI_MRU:
if (!ao->neg_mru) { /* Allow option? */
- LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - not allowed\n"));
+ LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - not allowed\n"));
orc = CONFREJ; /* Reject CI */
break;
} else if (cilen != CILEN_SHORT) { /* Check CI length */
- LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - bad length\n"));
+ LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - bad length\n"));
orc = CONFREJ; /* Reject CI */
break;
}
@@ -1262,7 +1292,7 @@ lcp_reqci(fsm *f,
* we'll just ignore it.
*/
if (cishort < PPP_MINMRU) {
- LCPDEBUG((LOG_INFO, "lcp_reqci: Nak - MRU too small\n"));
+ LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak - MRU too small\n"));
orc = CONFNAK; /* Nak CI */
PUTCHAR(CI_MRU, nakp);
PUTCHAR(CILEN_SHORT, nakp);
@@ -1279,11 +1309,11 @@ lcp_reqci(fsm *f,
case CI_ASYNCMAP:
if (!ao->neg_asyncmap) {
- LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP not allowed\n"));
+ LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP not allowed\n"));
orc = CONFREJ;
break;
} else if (cilen != CILEN_LONG) {
- LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP bad length\n"));
+ LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP bad length\n"));
orc = CONFREJ;
break;
}
@@ -1294,7 +1324,7 @@ lcp_reqci(fsm *f,
* which are set in lcp_allowoptions[unit].asyncmap.
*/
if ((ao->asyncmap & ~cilong) != 0) {
- LCPDEBUG((LOG_INFO, "lcp_reqci: Nak ASYNCMAP %lX missing %lX\n",
+ LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak ASYNCMAP %lX missing %lX\n",
cilong, ao->asyncmap));
orc = CONFNAK;
PUTCHAR(CI_ASYNCMAP, nakp);
@@ -1312,14 +1342,14 @@ lcp_reqci(fsm *f,
case CI_AUTHTYPE:
if (cilen < CILEN_SHORT) {
- LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE missing arg\n"));
+ LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE missing arg\n"));
orc = CONFREJ;
break;
} else if (!(ao->neg_upap || ao->neg_chap)) {
/*
* Reject the option if we're not willing to authenticate.
*/
- LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE not allowed\n"));
+ LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE not allowed\n"));
orc = CONFREJ;
break;
}
@@ -1338,16 +1368,16 @@ lcp_reqci(fsm *f,
if (cishort == PPP_PAP) {
if (ho->neg_chap) { /* we've already accepted CHAP */
- LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP already accepted\n"));
+ LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP already accepted\n"));
orc = CONFREJ;
break;
} else if (cilen != CILEN_SHORT) {
- LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP bad len\n"));
+ LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP bad len\n"));
orc = CONFREJ;
break;
}
if (!ao->neg_upap) { /* we don't want to do PAP */
- LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE PAP not allowed\n"));
+ LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE PAP not allowed\n"));
orc = CONFNAK; /* NAK it and suggest CHAP */
PUTCHAR(CI_AUTHTYPE, nakp);
PUTCHAR(CILEN_CHAP, nakp);
@@ -1364,16 +1394,16 @@ lcp_reqci(fsm *f,
}
if (cishort == PPP_CHAP) {
if (ho->neg_upap) { /* we've already accepted PAP */
- LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n"));
+ LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n"));
orc = CONFREJ;
break;
} else if (cilen != CILEN_CHAP) {
- LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP bad len\n"));
+ LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP bad len\n"));
orc = CONFREJ;
break;
}
if (!ao->neg_chap) { /* we don't want to do CHAP */
- LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP not allowed\n"));
+ LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP not allowed\n"));
orc = CONFNAK; /* NAK it and suggest PAP */
PUTCHAR(CI_AUTHTYPE, nakp);
PUTCHAR(CILEN_SHORT, nakp);
@@ -1382,11 +1412,11 @@ lcp_reqci(fsm *f,
}
GETCHAR(cichar, p); /* get digest type*/
if (cichar != CHAP_DIGEST_MD5
-#ifdef CHAPMS
+#if MSCHAP_SUPPORT
&& cichar != CHAP_MICROSOFT
#endif
) {
- LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", cichar));
+ LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", (int)cichar));
orc = CONFNAK;
PUTCHAR(CI_AUTHTYPE, nakp);
PUTCHAR(CILEN_CHAP, nakp);
@@ -1395,7 +1425,7 @@ lcp_reqci(fsm *f,
break;
}
#if TRACELCP > 0
- snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, cichar);
+ snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, (int)cichar);
traceNdx = strlen(traceBuf);
#endif
ho->chap_mdtype = cichar; /* save md type */
@@ -1411,12 +1441,12 @@ lcp_reqci(fsm *f,
orc = CONFNAK;
PUTCHAR(CI_AUTHTYPE, nakp);
if (ao->neg_chap) {
- LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort));
+ LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort));
PUTCHAR(CILEN_CHAP, nakp);
PUTSHORT(PPP_CHAP, nakp);
PUTCHAR(ao->chap_mdtype, nakp);
} else {
- LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort));
+ LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort));
PUTCHAR(CILEN_SHORT, nakp);
PUTSHORT(PPP_PAP, nakp);
}
@@ -1541,7 +1571,7 @@ lcp_reqci(fsm *f,
endswitch:
#if TRACELCP
if (traceNdx >= 80 - 32) {
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd%s\n", traceBuf));
+ LCPDEBUG(LOG_INFO, ("lcp_reqci: rcvd%s\n", traceBuf));
traceNdx = 0;
}
#endif
@@ -1595,10 +1625,10 @@ lcp_reqci(fsm *f,
#if TRACELCP > 0
if (traceNdx > 0) {
- LCPDEBUG((LOG_INFO, "lcp_reqci: %s\n", traceBuf));
+ LCPDEBUG(LOG_INFO, ("lcp_reqci: %s\n", traceBuf));
}
#endif
- LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.\n", CODENAME(rc)));
+ LCPDEBUG(LOG_INFO, ("lcp_reqci: returning CONF%s.\n", CODENAME(rc)));
return (rc); /* Return final code */
}
@@ -1645,7 +1675,7 @@ lcp_up(fsm *f)
lcp_echo_lowerup(f->unit); /* Enable echo messages */
- link_established(f->unit);
+ link_established(f->unit); /* The link is up; authenticate now */
}
@@ -1677,7 +1707,7 @@ lcp_down(fsm *f)
static void
lcp_starting(fsm *f)
{
- link_required(f->unit);
+ link_required(f->unit); /* lwip: currently does nothing */
}
@@ -1687,11 +1717,11 @@ lcp_starting(fsm *f)
static void
lcp_finished(fsm *f)
{
- link_terminated(f->unit);
+ link_terminated(f->unit); /* we are finished with the link */
}
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
/*
* print_string - print a readable representation of a string using
* printer.
@@ -1898,7 +1928,7 @@ lcp_printpkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *
return (int)(p - pstart);
}
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
/*
* Time to shut down the link because there is nothing out there.
@@ -1907,8 +1937,8 @@ static void
LcpLinkFailure (fsm *f)
{
if (f->state == LS_OPENED) {
- LCPDEBUG((LOG_INFO, "No response to %d echo-requests\n", lcp_echos_pending));
- LCPDEBUG((LOG_NOTICE, "Serial link appears to be disconnected.\n"));
+ LCPDEBUG(LOG_INFO, ("No response to %d echo-requests\n", lcp_echos_pending));
+ LCPDEBUG(LOG_NOTICE, ("Serial link appears to be disconnected.\n"));
lcp_close(f->unit, "Peer not responding");
}
}
@@ -1954,15 +1984,15 @@ lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len)
/* Check the magic number - don't count replies from ourselves. */
if (len < 4) {
- LCPDEBUG((LOG_WARNING, "lcp: received short Echo-Reply, length %d\n", len));
+ LCPDEBUG(LOG_WARNING, ("lcp: received short Echo-Reply, length %d\n", len));
return;
}
GETLONG(magic, inp);
if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) {
- LCPDEBUG((LOG_WARNING, "appear to have received our own echo-reply!\n"));
+ LCPDEBUG(LOG_WARNING, ("appear to have received our own echo-reply!\n"));
return;
}
-
+
/* Reset the number of outstanding echo frames */
lcp_echos_pending = 0;
}
@@ -1980,7 +2010,7 @@ LcpSendEchoRequest (fsm *f)
* Detect the failure of the peer at this point.
*/
if (lcp_echo_fails != 0) {
- if (lcp_echos_pending++ >= lcp_echo_fails) {
+ if (lcp_echos_pending >= lcp_echo_fails) {
LcpLinkFailure(f);
lcp_echos_pending = 0;
}
@@ -1994,6 +2024,7 @@ LcpSendEchoRequest (fsm *f)
pktp = pkt;
PUTLONG(lcp_magic, pktp);
fsm_sdata(f, ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (int)(pktp - pkt));
+ ++lcp_echos_pending;
}
}
diff --git a/core/lwip/src/netif/ppp/lcp.h b/core/lwip/src/netif/ppp/lcp.h
index 1a5e5a4c..b9201eeb 100644
--- a/core/lwip/src/netif/ppp/lcp.h
+++ b/core/lwip/src/netif/ppp/lcp.h
@@ -48,15 +48,11 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: lcp.h,v 1.3 2007/12/19 20:47:23 fbernon Exp $
+ * $Id: lcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $
*/
#ifndef LCP_H
#define LCP_H
-
-/*************************
-*** PUBLIC DEFINITIONS ***
-*************************/
/*
* Options.
*/
@@ -73,7 +69,7 @@
#define CI_EPDISC 19 /* endpoint discriminator */
/*
- * LCP-specific packet types.
+ * LCP-specific packet types (code numbers).
*/
#define PROTREJ 8 /* Protocol Reject */
#define ECHOREQ 9 /* Echo Request */
@@ -81,11 +77,6 @@
#define DISCREQ 11 /* Discard Request */
#define CBCP_OPT 6 /* Use callback control protocol */
-
-/************************
-*** PUBLIC DATA TYPES ***
-************************/
-
/*
* The state of options is described by an lcp_options structure.
*/
@@ -135,9 +126,6 @@ typedef enum {
} LinkPhase;
-/*****************************
-*** PUBLIC DATA STRUCTURES ***
-*****************************/
extern LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */
extern lcp_options lcp_wantoptions[];
@@ -147,10 +135,6 @@ extern lcp_options lcp_hisoptions[];
extern ext_accm xmit_accm[];
-/***********************
-*** PUBLIC FUNCTIONS ***
-***********************/
-
void lcp_init (int);
void lcp_open (int);
void lcp_close (int, char *);
diff --git a/core/lwip/src/netif/ppp/magic.c b/core/lwip/src/netif/ppp/magic.c
index d3922bb5..39013308 100644
--- a/core/lwip/src/netif/ppp/magic.c
+++ b/core/lwip/src/netif/ppp/magic.c
@@ -57,9 +57,7 @@
#include "randm.h"
#include "magic.h"
-/***********************************/
-/*** PUBLIC FUNCTION DEFINITIONS ***/
-/***********************************/
+
/*
* magicInit - Initialize the magic number generator.
*
diff --git a/core/lwip/src/netif/ppp/magic.h b/core/lwip/src/netif/ppp/magic.h
index bc517499..eba70d20 100644
--- a/core/lwip/src/netif/ppp/magic.h
+++ b/core/lwip/src/netif/ppp/magic.h
@@ -48,16 +48,12 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: magic.h,v 1.2 2007/12/02 22:35:55 fbernon Exp $
+ * $Id: magic.h,v 1.3 2010/01/18 20:49:43 goldsimon Exp $
*/
#ifndef MAGIC_H
#define MAGIC_H
-/*****************************************************************************
-************************** PUBLIC FUNCTIONS **********************************
-*****************************************************************************/
-
/* Initialize the magic number generator */
void magicInit(void);
diff --git a/core/lwip/src/netif/ppp/md5.c b/core/lwip/src/netif/ppp/md5.c
index 7a60d783..3cb69e2b 100644
--- a/core/lwip/src/netif/ppp/md5.c
+++ b/core/lwip/src/netif/ppp/md5.c
@@ -138,8 +138,8 @@ MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen)
unsigned int i, ii;
#if 0
- ppp_trace(LOG_INFO, "MD5Update: %u:%.*H\n", inLen, MIN(inLen, 20) * 2, inBuf);
- ppp_trace(LOG_INFO, "MD5Update: %u:%s\n", inLen, inBuf);
+ PPPDEBUG(LOG_INFO, ("MD5Update: %u:%.*H\n", inLen, LWIP_MIN(inLen, 20) * 2, inBuf));
+ PPPDEBUG(LOG_INFO, ("MD5Update: %u:%s\n", inLen, inBuf));
#endif
/* compute number of bytes mod 64 */
diff --git a/core/lwip/src/netif/ppp/pap.c b/core/lwip/src/netif/ppp/pap.c
index e8c45dff..ac44e646 100644
--- a/core/lwip/src/netif/ppp/pap.c
+++ b/core/lwip/src/netif/ppp/pap.c
@@ -63,9 +63,27 @@
#include <string.h>
-/***********************************/
-/*** LOCAL FUNCTION DECLARATIONS ***/
-/***********************************/
+#if 0 /* UNUSED */
+static bool hide_password = 1;
+
+/*
+ * Command-line options.
+ */
+static option_t pap_option_list[] = {
+ { "hide-password", o_bool, &hide_password,
+ "Don't output passwords to log", 1 },
+ { "show-password", o_bool, &hide_password,
+ "Show password string in debug log messages", 0 },
+ { "pap-restart", o_int, &upap[0].us_timeouttime,
+ "Set retransmit timeout for PAP" },
+ { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
+ "Set max number of transmissions for auth-reqs" },
+ { "pap-timeout", o_int, &upap[0].us_reqtimeout,
+ "Set time limit for peer PAP authentication" },
+ { NULL }
+};
+#endif
+
/*
* Protocol entry points.
*/
@@ -74,19 +92,10 @@ static void upap_lowerup (int);
static void upap_lowerdown (int);
static void upap_input (int, u_char *, int);
static void upap_protrej (int);
+#if PPP_ADDITIONAL_CALLBACKS
+static int upap_printpkt (u_char *, int, void (*)(void *, char *, ...), void *);
+#endif /* PPP_ADDITIONAL_CALLBACKS */
-static void upap_timeout (void *);
-static void upap_reqtimeout(void *);
-static void upap_rauthreq (upap_state *, u_char *, int, int);
-static void upap_rauthack (upap_state *, u_char *, int, int);
-static void upap_rauthnak (upap_state *, u_char *, int, int);
-static void upap_sauthreq (upap_state *);
-static void upap_sresp (upap_state *, u_char, u_char, char *, int);
-
-
-/******************************/
-/*** PUBLIC DATA STRUCTURES ***/
-/******************************/
struct protent pap_protent = {
PPP_PAP,
upap_init,
@@ -96,41 +105,51 @@ struct protent pap_protent = {
upap_lowerdown,
NULL,
NULL,
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
upap_printpkt,
NULL,
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
1,
"PAP",
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
NULL,
NULL,
NULL
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
};
upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
+static void upap_timeout (void *);
+static void upap_reqtimeout(void *);
+static void upap_rauthreq (upap_state *, u_char *, u_char, int);
+static void upap_rauthack (upap_state *, u_char *, int, int);
+static void upap_rauthnak (upap_state *, u_char *, int, int);
+static void upap_sauthreq (upap_state *);
+static void upap_sresp (upap_state *, u_char, u_char, char *, int);
-/***********************************/
-/*** PUBLIC FUNCTION DEFINITIONS ***/
-/***********************************/
/*
- * Set the default login name and password for the pap sessions
+ * upap_init - Initialize a UPAP unit.
*/
-void
-upap_setloginpasswd(int unit, const char *luser, const char *lpassword)
+static void
+upap_init(int unit)
{
upap_state *u = &upap[unit];
-
- /* Save the username and password we're given */
- u->us_user = luser;
- u->us_userlen = strlen(luser);
- u->us_passwd = lpassword;
- u->us_passwdlen = strlen(lpassword);
-}
+ UPAPDEBUG(LOG_INFO, ("upap_init: %d\n", unit));
+ u->us_unit = unit;
+ u->us_user = NULL;
+ u->us_userlen = 0;
+ u->us_passwd = NULL;
+ u->us_passwdlen = 0;
+ u->us_clientstate = UPAPCS_INITIAL;
+ u->us_serverstate = UPAPSS_INITIAL;
+ u->us_id = 0;
+ u->us_timeouttime = UPAP_DEFTIMEOUT;
+ u->us_maxtransmits = 10;
+ u->us_reqtimeout = UPAP_DEFREQTIME;
+}
/*
* upap_authwithpeer - Authenticate us with our peer (start client).
@@ -142,10 +161,14 @@ upap_authwithpeer(int unit, char *user, char *password)
{
upap_state *u = &upap[unit];
- UPAPDEBUG((LOG_INFO, "upap_authwithpeer: %d user=%s password=%s s=%d\n",
+ UPAPDEBUG(LOG_INFO, ("upap_authwithpeer: %d user=%s password=%s s=%d\n",
unit, user, password, u->us_clientstate));
- upap_setloginpasswd(unit, user, password);
+ /* Save the username and password we're given */
+ u->us_user = user;
+ u->us_userlen = (int)strlen(user);
+ u->us_passwd = password;
+ u->us_passwdlen = (int)strlen(password);
u->us_transmits = 0;
@@ -183,33 +206,6 @@ upap_authpeer(int unit)
}
}
-
-
-/**********************************/
-/*** LOCAL FUNCTION DEFINITIONS ***/
-/**********************************/
-/*
- * upap_init - Initialize a UPAP unit.
- */
-static void
-upap_init(int unit)
-{
- upap_state *u = &upap[unit];
-
- UPAPDEBUG((LOG_INFO, "upap_init: %d\n", unit));
- u->us_unit = unit;
- u->us_user = NULL;
- u->us_userlen = 0;
- u->us_passwd = NULL;
- u->us_passwdlen = 0;
- u->us_clientstate = UPAPCS_INITIAL;
- u->us_serverstate = UPAPSS_INITIAL;
- u->us_id = 0;
- u->us_timeouttime = UPAP_DEFTIMEOUT;
- u->us_maxtransmits = 10;
- u->us_reqtimeout = UPAP_DEFREQTIME;
-}
-
/*
* upap_timeout - Retransmission timer for sending auth-reqs expired.
*/
@@ -218,22 +214,23 @@ upap_timeout(void *arg)
{
upap_state *u = (upap_state *) arg;
- UPAPDEBUG((LOG_INFO, "upap_timeout: %d timeout %d expired s=%d\n",
+ UPAPDEBUG(LOG_INFO, ("upap_timeout: %d timeout %d expired s=%d\n",
u->us_unit, u->us_timeouttime, u->us_clientstate));
if (u->us_clientstate != UPAPCS_AUTHREQ) {
+ UPAPDEBUG(LOG_INFO, ("upap_timeout: not in AUTHREQ state!\n"));
return;
}
if (u->us_transmits >= u->us_maxtransmits) {
/* give up in disgust */
- UPAPDEBUG((LOG_ERR, "No response to PAP authenticate-requests\n"));
+ UPAPDEBUG(LOG_ERR, ("No response to PAP authenticate-requests\n"));
u->us_clientstate = UPAPCS_BADAUTH;
auth_withpeer_fail(u->us_unit, PPP_PAP);
return;
}
- upap_sauthreq(u); /* Send Authenticate-Request */
+ upap_sauthreq(u); /* Send Authenticate-Request and set upap timeout*/
}
@@ -264,12 +261,13 @@ upap_lowerup(int unit)
{
upap_state *u = &upap[unit];
- UPAPDEBUG((LOG_INFO, "upap_lowerup: %d s=%d\n", unit, u->us_clientstate));
+ UPAPDEBUG(LOG_INFO, ("upap_lowerup: init %d clientstate s=%d\n", unit, u->us_clientstate));
if (u->us_clientstate == UPAPCS_INITIAL) {
u->us_clientstate = UPAPCS_CLOSED;
} else if (u->us_clientstate == UPAPCS_PENDING) {
upap_sauthreq(u); /* send an auth-request */
+ /* now client state is UPAPCS__AUTHREQ */
}
if (u->us_serverstate == UPAPSS_INITIAL) {
@@ -293,7 +291,7 @@ upap_lowerdown(int unit)
{
upap_state *u = &upap[unit];
- UPAPDEBUG((LOG_INFO, "upap_lowerdown: %d s=%d\n", unit, u->us_clientstate));
+ UPAPDEBUG(LOG_INFO, ("upap_lowerdown: %d s=%d\n", unit, u->us_clientstate));
if (u->us_clientstate == UPAPCS_AUTHREQ) { /* Timeout pending? */
UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
@@ -318,11 +316,11 @@ upap_protrej(int unit)
upap_state *u = &upap[unit];
if (u->us_clientstate == UPAPCS_AUTHREQ) {
- UPAPDEBUG((LOG_ERR, "PAP authentication failed due to protocol-reject\n"));
+ UPAPDEBUG(LOG_ERR, ("PAP authentication failed due to protocol-reject\n"));
auth_withpeer_fail(unit, PPP_PAP);
}
if (u->us_serverstate == UPAPSS_LISTEN) {
- UPAPDEBUG((LOG_ERR, "PAP authentication of peer failed (protocol-reject)\n"));
+ UPAPDEBUG(LOG_ERR, ("PAP authentication of peer failed (protocol-reject)\n"));
auth_peer_fail(unit, PPP_PAP);
}
upap_lowerdown(unit);
@@ -345,19 +343,19 @@ upap_input(int unit, u_char *inpacket, int l)
* If packet too short, drop it.
*/
inp = inpacket;
- if (l < UPAP_HEADERLEN) {
- UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.\n"));
+ if (l < (int)UPAP_HEADERLEN) {
+ UPAPDEBUG(LOG_INFO, ("pap_input: rcvd short header.\n"));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
GETSHORT(len, inp);
- if (len < UPAP_HEADERLEN) {
- UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.\n"));
+ if (len < (int)UPAP_HEADERLEN) {
+ UPAPDEBUG(LOG_INFO, ("pap_input: rcvd illegal length.\n"));
return;
}
if (len > l) {
- UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.\n"));
+ UPAPDEBUG(LOG_INFO, ("pap_input: rcvd short packet.\n"));
return;
}
len -= UPAP_HEADERLEN;
@@ -379,6 +377,7 @@ upap_input(int unit, u_char *inpacket, int l)
break;
default: /* XXX Need code reject */
+ UPAPDEBUG(LOG_INFO, ("pap_input: UNHANDLED default: code: %d, id: %d, len: %d.\n", code, id, len));
break;
}
}
@@ -388,15 +387,15 @@ upap_input(int unit, u_char *inpacket, int l)
* upap_rauth - Receive Authenticate.
*/
static void
-upap_rauthreq(upap_state *u, u_char *inp, int id, int len)
+upap_rauthreq(upap_state *u, u_char *inp, u_char id, int len)
{
u_char ruserlen, rpasswdlen;
char *ruser, *rpasswd;
- int retcode;
+ u_char retcode;
char *msg;
int msglen;
- UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.\n", id));
+ UPAPDEBUG(LOG_INFO, ("pap_rauth: Rcvd id %d.\n", id));
if (u->us_serverstate < UPAPSS_LISTEN) {
return;
@@ -418,21 +417,21 @@ upap_rauthreq(upap_state *u, u_char *inp, int id, int len)
/*
* Parse user/passwd.
*/
- if (len < sizeof (u_char)) {
- UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
+ if (len < (int)sizeof (u_char)) {
+ UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n"));
return;
}
GETCHAR(ruserlen, inp);
len -= sizeof (u_char) + ruserlen + sizeof (u_char);
if (len < 0) {
- UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
+ UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n"));
return;
}
ruser = (char *) inp;
INCPTR(ruserlen, inp);
GETCHAR(rpasswdlen, inp);
if (len < rpasswdlen) {
- UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
+ UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n"));
return;
}
rpasswd = (char *) inp;
@@ -441,6 +440,7 @@ upap_rauthreq(upap_state *u, u_char *inp, int id, int len)
* Check the username and password given.
*/
retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen);
+ /* lwip: currently retcode is always UPAP_AUTHACK */
BZERO(rpasswd, rpasswdlen);
upap_sresp(u, retcode, id, msg, msglen);
@@ -470,28 +470,30 @@ upap_rauthack(upap_state *u, u_char *inp, int id, int len)
LWIP_UNUSED_ARG(id);
- UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate));
+ UPAPDEBUG(LOG_INFO, ("pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate));
if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
+ UPAPDEBUG(LOG_INFO, ("pap_rauthack: us_clientstate != UPAPCS_AUTHREQ\n"));
return;
}
/*
* Parse message.
*/
- if (len < sizeof (u_char)) {
- UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
- return;
- }
- GETCHAR(msglen, inp);
- len -= sizeof (u_char);
- if (len < msglen) {
- UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
- return;
+ if (len < (int)sizeof (u_char)) {
+ UPAPDEBUG(LOG_INFO, ("pap_rauthack: ignoring missing msg-length.\n"));
+ } else {
+ GETCHAR(msglen, inp);
+ if (msglen > 0) {
+ len -= sizeof (u_char);
+ if (len < msglen) {
+ UPAPDEBUG(LOG_INFO, ("pap_rauthack: rcvd short packet.\n"));
+ return;
+ }
+ msg = (char *) inp;
+ PRINTMSG(msg, msglen);
+ }
}
- msg = (char *) inp;
- PRINTMSG(msg, msglen);
-
UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
u->us_clientstate = UPAPCS_OPEN;
@@ -500,7 +502,7 @@ upap_rauthack(upap_state *u, u_char *inp, int id, int len)
/*
- * upap_rauthnak - Receive Authenticate-Nakk.
+ * upap_rauthnak - Receive Authenticate-Nak.
*/
static void
upap_rauthnak(upap_state *u, u_char *inp, int id, int len)
@@ -510,7 +512,7 @@ upap_rauthnak(upap_state *u, u_char *inp, int id, int len)
LWIP_UNUSED_ARG(id);
- UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate));
+ UPAPDEBUG(LOG_INFO, ("pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate));
if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
return;
@@ -520,13 +522,13 @@ upap_rauthnak(upap_state *u, u_char *inp, int id, int len)
* Parse message.
*/
if (len < sizeof (u_char)) {
- UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
+ UPAPDEBUG(LOG_INFO, ("pap_rauthnak: ignoring missing msg-length.\n"));
} else {
GETCHAR(msglen, inp);
if(msglen > 0) {
len -= sizeof (u_char);
if (len < msglen) {
- UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
+ UPAPDEBUG(LOG_INFO, ("pap_rauthnak: rcvd short packet.\n"));
return;
}
msg = (char *) inp;
@@ -536,7 +538,7 @@ upap_rauthnak(upap_state *u, u_char *inp, int id, int len)
u->us_clientstate = UPAPCS_BADAUTH;
- UPAPDEBUG((LOG_ERR, "PAP authentication failed\n"));
+ UPAPDEBUG(LOG_ERR, ("PAP authentication failed\n"));
auth_withpeer_fail(u->us_unit, PPP_PAP);
}
@@ -567,7 +569,7 @@ upap_sauthreq(upap_state *u)
pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
- UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %d\n", u->us_id));
+ UPAPDEBUG(LOG_INFO, ("pap_sauth: Sent id %d\n", u->us_id));
TIMEOUT(upap_timeout, u, u->us_timeouttime);
++u->us_transmits;
@@ -595,10 +597,14 @@ upap_sresp(upap_state *u, u_char code, u_char id, char *msg, int msglen)
BCOPY(msg, outp, msglen);
pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
- UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate));
+ UPAPDEBUG(LOG_INFO, ("pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate));
}
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
+static char *upap_codenames[] = {
+ "AuthReq", "AuthAck", "AuthNak"
+};
+
/*
* upap_printpkt - print the contents of a PAP packet.
*/
@@ -615,7 +621,7 @@ static int upap_printpkt(
LWIP_UNUSED_ARG(arg);
return 0;
}
-#endif /* 0 */
+#endif /* PPP_ADDITIONAL_CALLBACKS */
#endif /* PAP_SUPPORT */
diff --git a/core/lwip/src/netif/ppp/pap.h b/core/lwip/src/netif/ppp/pap.h
index 0a09fc84..c99a2040 100644
--- a/core/lwip/src/netif/ppp/pap.h
+++ b/core/lwip/src/netif/ppp/pap.h
@@ -54,9 +54,6 @@
#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
-/*************************
-*** PUBLIC DEFINITIONS ***
-*************************/
/*
* Packet header = Code, id, length.
*/
@@ -71,6 +68,24 @@
#define UPAP_AUTHNAK 3 /* Authenticate-Nak */
/*
+ * Each interface is described by upap structure.
+ */
+typedef struct upap_state {
+ int us_unit; /* Interface unit number */
+ const char *us_user; /* User */
+ int us_userlen; /* User length */
+ const char *us_passwd; /* Password */
+ int us_passwdlen; /* Password length */
+ int us_clientstate; /* Client state */
+ int us_serverstate; /* Server state */
+ u_char us_id; /* Current id */
+ int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */
+ int us_transmits; /* Number of auth-reqs sent */
+ int us_maxtransmits; /* Maximum number of auth-reqs to send */
+ int us_reqtimeout; /* Time to wait for auth-req from peer */
+} upap_state;
+
+/*
* Client states.
*/
#define UPAPCS_INITIAL 0 /* Connection down */
@@ -91,36 +106,8 @@
#define UPAPSS_BADAUTH 5 /* We've sent a Nak */
-/************************
-*** PUBLIC DATA TYPES ***
-************************/
-
-/*
- * Each interface is described by upap structure.
- */
-typedef struct upap_state {
- int us_unit; /* Interface unit number */
- const char *us_user; /* User */
- int us_userlen; /* User length */
- const char *us_passwd; /* Password */
- int us_passwdlen; /* Password length */
- int us_clientstate; /* Client state */
- int us_serverstate; /* Server state */
- u_char us_id; /* Current id */
- int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */
- int us_transmits; /* Number of auth-reqs sent */
- int us_maxtransmits; /* Maximum number of auth-reqs to send */
- int us_reqtimeout; /* Time to wait for auth-req from peer */
-} upap_state;
-
-
-/***********************
-*** PUBLIC FUNCTIONS ***
-***********************/
-
extern upap_state upap[];
-void upap_setloginpasswd(int unit, const char *luser, const char *lpassword);
void upap_authwithpeer (int, char *, char *);
void upap_authpeer (int);
diff --git a/core/lwip/src/netif/ppp/ppp.c b/core/lwip/src/netif/ppp/ppp.c
index 13fa5ed0..e9b433b0 100644
--- a/core/lwip/src/netif/ppp/ppp.c
+++ b/core/lwip/src/netif/ppp/ppp.c
@@ -107,12 +107,35 @@
#include "netif/ppp_oe.h"
#endif /* PPPOE_SUPPORT */
+#include "lwip/tcpip.h"
+#include "lwip/api.h"
+#include "lwip/snmp.h"
+
#include <string.h>
/*************************/
/*** LOCAL DEFINITIONS ***/
/*************************/
+/** PPP_INPROC_MULTITHREADED==1 call pppInput using tcpip_callback().
+ * Set this to 0 if pppInProc is called inside tcpip_thread or with NO_SYS==1.
+ * Default is 1 for NO_SYS==0 (multithreaded) and 0 for NO_SYS==1 (single-threaded).
+ */
+#ifndef PPP_INPROC_MULTITHREADED
+#define PPP_INPROC_MULTITHREADED (NO_SYS==0)
+#endif
+
+/** PPP_INPROC_OWNTHREAD==1: start a dedicated RX thread per PPP session.
+ * Default is 0: call pppos_input() for received raw characters, charcater
+ * reception is up to the port */
+#ifndef PPP_INPROC_OWNTHREAD
+#define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED
+#endif
+
+#if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED
+ #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1"
+#endif
+
/*
* The basic PPP frame.
*/
@@ -137,10 +160,37 @@ typedef enum {
/************************/
/*** LOCAL DATA TYPES ***/
/************************/
+
+/** RX buffer size: this may be configured smaller! */
+#ifndef PPPOS_RX_BUFSIZE
+#define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN)
+#endif
+
+typedef struct PPPControlRx_s {
+ /** unit number / ppp descriptor */
+ int pd;
+ /** the rx file descriptor */
+ sio_fd_t fd;
+ /** receive buffer - encoded data is stored here */
+ u_char rxbuf[PPPOS_RX_BUFSIZE];
+
+ /* The input packet. */
+ struct pbuf *inHead, *inTail;
+
+#if PPPOS_SUPPORT
+ u16_t inProtocol; /* The input protocol code. */
+ u16_t inFCS; /* Input Frame Check Sequence value. */
+#endif /* PPPOS_SUPPORT */
+ PPPDevStates inState; /* The input process state. */
+ char inEscaped; /* Escape next character. */
+ ext_accm inACCM; /* Async-Ctl-Char-Map for input. */
+} PPPControlRx;
+
/*
* PPP interface control block.
*/
typedef struct PPPControl_s {
+ PPPControlRx rx;
char openFlag; /* True when in use. */
#if PPPOE_SUPPORT
struct netif *ethif;
@@ -150,19 +200,11 @@ typedef struct PPPControl_s {
int errCode; /* Code indicating why interface is down. */
#if PPPOS_SUPPORT
sio_fd_t fd; /* File device ID of port. */
- int kill_link; /* Shut the link down. */
- int sig_hup; /* Carrier lost. */
- struct pbuf *inHead, *inTail; /* The input packet. */
- PPPDevStates inState; /* The input process state. */
- char inEscaped; /* Escape next character. */
- u16_t inProtocol; /* The input protocol code. */
- u16_t inFCS; /* Input Frame Check Sequence value. */
#endif /* PPPOS_SUPPORT */
- int mtu; /* Peer's mru */
+ u16_t mtu; /* Peer's mru */
int pcomp; /* Does peer accept protocol compression? */
int accomp; /* Does peer accept addr/ctl compression? */
u_long lastXMit; /* Time of last transmission. */
- ext_accm inACCM; /* Async-Ctl-Char-Map for input. */
ext_accm outACCM; /* Async-Ctl-Char-Map for output. */
#if PPPOS_SUPPORT && VJ_SUPPORT
int vjEnabled; /* Flag indicating VJ compression enabled. */
@@ -194,9 +236,11 @@ struct npioctl {
/*** LOCAL FUNCTION DECLARATIONS ***/
/***********************************/
#if PPPOS_SUPPORT
-static void pppMain(void *pd);
-static void pppDrop(PPPControl *pc);
-static void pppInProc(int pd, u_char *s, int l);
+#if PPP_INPROC_OWNTHREAD
+static void pppInputThread(void *arg);
+#endif /* PPP_INPROC_OWNTHREAD */
+static void pppDrop(PPPControlRx *pcrx);
+static void pppInProc(PPPControlRx *pcrx, u_char *s, int l);
#endif /* PPPOS_SUPPORT */
@@ -245,6 +289,7 @@ u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
#if PPPOS_SUPPORT
/*
* FCS lookup table as calculated by genfcstab.
+ * @todo: smaller, slower implementation for lower memory footprint?
*/
static const u_short fcstab[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
@@ -294,80 +339,84 @@ static u_char pppACCMMask[] = {
0x80
};
-
-void
-pppMainWakeup(int pd)
+/** Wake up the task blocked in reading from serial line (if any) */
+static void
+pppRecvWakeup(int pd)
{
- PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d\n", pd));
- sio_read_abort(pppControl[pd].fd);
+ PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd));
+ if (pppControl[pd].openFlag != 0) {
+ sio_read_abort(pppControl[pd].fd);
+ }
}
#endif /* PPPOS_SUPPORT */
void
pppLinkTerminated(int pd)
{
- PPPDEBUG((LOG_DEBUG, "pppLinkTerminated: unit %d\n", pd));
+ PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d\n", pd));
#if PPPOE_SUPPORT
- if(pppControl[pd].ethif) {
+ if (pppControl[pd].ethif) {
pppoe_disconnect(pppControl[pd].pppoe_sc);
} else
#endif /* PPPOE_SUPPORT */
{
#if PPPOS_SUPPORT
- pppMainWakeup(pd);
+ PPPControl* pc;
+ pppRecvWakeup(pd);
+ pc = &pppControl[pd];
+
+ PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
+ if (pc->linkStatusCB) {
+ pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
+ }
+
+ pc->openFlag = 0;/**/
#endif /* PPPOS_SUPPORT */
}
+ PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: finished.\n"));
}
void
pppLinkDown(int pd)
{
- PPPDEBUG((LOG_DEBUG, "pppLinkDown: unit %d\n", pd));
+ PPPDEBUG(LOG_DEBUG, ("pppLinkDown: unit %d\n", pd));
#if PPPOE_SUPPORT
- if(pppControl[pd].ethif) {
+ if (pppControl[pd].ethif) {
pppoe_disconnect(pppControl[pd].pppoe_sc);
} else
#endif /* PPPOE_SUPPORT */
{
#if PPPOS_SUPPORT
- pppMainWakeup(pd);
+ pppRecvWakeup(pd);
#endif /* PPPOS_SUPPORT */
}
}
-/* these callbacks are necessary because lcp_* functions
- must be called in the same context as pppInput(),
- namely the tcpip_thread(), essentially because
- they manipulate timeouts which are thread-private
-*/
-
+/** Initiate LCP open request */
static void
-pppStartCB(void *arg)
+pppStart(int pd)
{
- int pd = (int)arg;
-
- PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %d\n", pd));
+ PPPDEBUG(LOG_DEBUG, ("pppStart: unit %d\n", pd));
lcp_lowerup(pd);
lcp_open(pd); /* Start protocol */
+ PPPDEBUG(LOG_DEBUG, ("pppStart: finished\n"));
}
+/** LCP close request */
static void
-pppStopCB(void *arg)
+pppStop(int pd)
{
- int pd = (int)arg;
-
- PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %d\n", pd));
+ PPPDEBUG(LOG_DEBUG, ("pppStop: unit %d\n", pd));
lcp_close(pd, "User request");
}
+/** Called when carrier/link is lost */
static void
-pppHupCB(void *arg)
+pppHup(int pd)
{
- int pd = (int)arg;
-
- PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %d\n", pd));
+ PPPDEBUG(LOG_DEBUG, ("pppHupCB: unit %d\n", pd));
lcp_lowerdown(pd);
link_terminated(pd);
}
@@ -391,22 +440,14 @@ pppInit(void)
magicInit();
- subnetMask = htonl(0xffffff00);
+ subnetMask = PP_HTONL(0xffffff00UL);
for (i = 0; i < NUM_PPP; i++) {
- pppControl[i].openFlag = 0;
-
- /*
- * Initialize to the standard option set.
- */
+ /* Initialize each protocol to the standard option set. */
for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) {
(*protp->init)(i);
}
}
-
-#if PPPOE_SUPPORT
- pppoe_init();
-#endif /* PPPOE_SUPPORT */
}
void
@@ -475,50 +516,44 @@ pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
}
#if PPPOS_SUPPORT
-/* Open a new PPP connection using the given I/O device.
+/** Open a new PPP connection using the given I/O device.
* This initializes the PPP control block but does not
* attempt to negotiate the LCP session. If this port
* connects to a modem, the modem connection must be
* established before calling this.
* Return a new PPP connection descriptor on success or
- * an error code (negative) on failure. */
+ * an error code (negative) on failure.
+ *
+ * pppOpen() is directly defined to this function.
+ */
int
pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
{
PPPControl *pc;
int pd;
- /* Find a free PPP session descriptor. Critical region? */
+ if (linkStatusCB == NULL) {
+ /* PPP is single-threaded: without a callback,
+ * there is no way to know when the link is up. */
+ return PPPERR_PARAM;
+ }
+
+ /* Find a free PPP session descriptor. */
for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
if (pd >= NUM_PPP) {
pd = PPPERR_OPEN;
} else {
- pppControl[pd].openFlag = !0;
- }
-
- /* Launch a deamon thread. */
- if (pd >= 0) {
- pppControl[pd].openFlag = 1;
-
- lcp_init(pd);
pc = &pppControl[pd];
+ /* @todo: is this correct or do I overwrite something? */
+ memset(pc, 0, sizeof(PPPControl));
+ pc->rx.pd = pd;
+ pc->rx.fd = fd;
+
+ pc->openFlag = 1;
pc->fd = fd;
-#if PPPOE_SUPPORT
- pc->ethif= NULL;
-#endif /* PPPOE_SUPPORT */
- pc->kill_link = 0;
- pc->sig_hup = 0;
- pc->if_up = 0;
- pc->errCode = 0;
- pc->inState = PDIDLE;
- pc->inHead = NULL;
- pc->inTail = NULL;
- pc->inEscaped = 0;
- pc->lastXMit = 0;
#if VJ_SUPPORT
- pc->vjEnabled = 0;
vj_compress_init(&pc->vjComp);
#endif /* VJ_SUPPORT */
@@ -526,28 +561,20 @@ pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void
* Default the in and out accm so that escape and flag characters
* are always escaped.
*/
- memset(pc->inACCM, 0, sizeof(ext_accm));
- pc->inACCM[15] = 0x60;
- memset(pc->outACCM, 0, sizeof(ext_accm));
+ pc->rx.inACCM[15] = 0x60; /* no need to protect since RX is not running */
pc->outACCM[15] = 0x60;
pc->linkStatusCB = linkStatusCB;
pc->linkStatusCtx = linkStatusCtx;
- sys_thread_new(PPP_THREAD_NAME, pppMain, (void*)pd, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO);
- if(!linkStatusCB) {
- while(pd >= 0 && !pc->if_up) {
- sys_msleep(500);
- if (lcp_phase[pd] == PHASE_DEAD) {
- pppClose(pd);
- if (pc->errCode) {
- pd = pc->errCode;
- } else {
- pd = PPPERR_CONNECT;
- }
- }
- }
- }
+ /*
+ * Start the connection and handle incoming events (packet or timeout).
+ */
+ PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd));
+ pppStart(pd);
+#if PPP_INPROC_OWNTHREAD
+ sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO);
+#endif
}
return pd;
@@ -576,20 +603,24 @@ int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const cha
LWIP_UNUSED_ARG(service_name);
LWIP_UNUSED_ARG(concentrator_name);
+ if (linkStatusCB == NULL) {
+ /* PPP is single-threaded: without a callback,
+ * there is no way to know when the link is up. */
+ return PPPERR_PARAM;
+ }
+
/* Find a free PPP session descriptor. Critical region? */
for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
if (pd >= NUM_PPP) {
pd = PPPERR_OPEN;
} else {
- pppControl[pd].openFlag = !0;
- }
-
- /* PPP session descriptor found, start PPPoE */
- if (pd >= 0) {
-
- pppControl[pd].openFlag = 1;
+ pc = &pppControl[pd];
+ memset(pc, 0, sizeof(PPPControl));
+ pc->openFlag = 1;
+ pc->ethif = ethif;
- lcp_init(pd);
+ pc->linkStatusCB = linkStatusCB;
+ pc->linkStatusCtx = linkStatusCtx;
lcp_wantoptions[pd].mru = PPPOE_MAXMTU;
lcp_wantoptions[pd].neg_asyncmap = 0;
@@ -601,49 +632,12 @@ int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const cha
lcp_allowoptions[pd].neg_pcompression = 0;
lcp_allowoptions[pd].neg_accompression = 0;
- pc = &pppControl[pd];
- pc->if_up = 0;
- pc->errCode = 0;
- pc->lastXMit = 0;
-#if PPPOS_SUPPORT
- pc->kill_link = 0;
- pc->sig_hup = 0;
- pc->inState = PDIDLE;
- pc->inHead = NULL;
- pc->inTail = NULL;
- pc->inEscaped = 0;
-#if VJ_SUPPORT
- pc->vjEnabled = 0;
-#endif /* VJ_SUPPORT */
-#endif /* PPPOS_SUPPORT */
- pc->ethif= ethif;
-
- memset(pc->inACCM, 0, sizeof(ext_accm));
- memset(pc->outACCM, 0, sizeof(ext_accm));
-
- pc->linkStatusCB = linkStatusCB;
- pc->linkStatusCtx = linkStatusCtx;
-
if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) {
pc->openFlag = 0;
return PPPERR_OPEN;
}
pppoe_connect(pc->pppoe_sc);
-
- if(!linkStatusCB) {
- while(pd >= 0 && !pc->if_up) {
- sys_msleep(500);
- if (lcp_phase[pd] == PHASE_DEAD) {
- pppClose(pd);
- if (pc->errCode) {
- pd = pc->errCode;
- } else {
- pd = PPPERR_CONNECT;
- }
- }
- }
- }
}
return pd;
@@ -660,29 +654,27 @@ pppClose(int pd)
PPPControl *pc = &pppControl[pd];
int st = 0;
+ PPPDEBUG(LOG_DEBUG, ("pppClose() called\n"));
+
/* Disconnect */
#if PPPOE_SUPPORT
if(pc->ethif) {
- PPPDEBUG((LOG_DEBUG, "pppClose: unit %d kill_link -> pppStopCB\n", pd));
+ PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd));
pc->errCode = PPPERR_USER;
/* This will leave us at PHASE_DEAD. */
- tcpip_callback(pppStopCB, (void*)pd);
+ pppStop(pd);
} else
#endif /* PPPOE_SUPPORT */
{
#if PPPOS_SUPPORT
- pc->kill_link = !0;
- pppMainWakeup(pd);
+ PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd));
+ pc->errCode = PPPERR_USER;
+ /* This will leave us at PHASE_DEAD. */
+ pppStop(pd);
+ pppRecvWakeup(pd);
#endif /* PPPOS_SUPPORT */
}
- if(!pc->linkStatusCB) {
- while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) {
- sys_msleep(500);
- break;
- }
- }
-
return st;
}
@@ -690,20 +682,8 @@ pppClose(int pd)
void
pppSigHUP(int pd)
{
- PPPControl *pc = &pppControl[pd];
-
-#if PPPOE_SUPPORT
- if(pc->ethif) {
- PPPDEBUG((LOG_DEBUG, "pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
- tcpip_callback(pppHupCB, (void*)pd);
- } else
-#endif /* PPPOE_SUPPORT */
- {
-#if PPPOS_SUPPORT
- pc->sig_hup = 1;
- pppMainWakeup(pd);
-#endif /* PPPOS_SUPPORT */
- }
+ PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
+ pppHup(pd);
}
#if PPPOS_SUPPORT
@@ -715,14 +695,18 @@ nPut(PPPControl *pc, struct pbuf *nb)
for(b = nb; b != NULL; b = b->next) {
if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
- PPPDEBUG((LOG_WARNING,
- "PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c));
+ PPPDEBUG(LOG_WARNING,
+ ("PPP nPut: incomplete sio_write(fd:%"SZT_F", len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c));
LINK_STATS_INC(link.err);
pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
- break;
+ snmp_inc_ifoutdiscards(&pc->netif);
+ pbuf_free(nb);
+ return;
}
}
+ snmp_add_ifoutoctets(&pc->netif, nb->tot_len);
+ snmp_inc_ifoutucastpkts(&pc->netif);
pbuf_free(nb);
LINK_STATS_INC(link.xmit);
}
@@ -773,15 +757,18 @@ pppifOutputOverEthernet(int pd, struct pbuf *p)
struct pbuf *pb;
u_short protocol = PPP_IP;
int i=0;
+ u16_t tot_len;
- pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + sizeof(protocol), PBUF_RAM);
+ /* @todo: try to use pbuf_header() here! */
+ pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM);
if(!pb) {
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.proterr);
+ snmp_inc_ifoutdiscards(&pc->netif);
return ERR_MEM;
}
- pbuf_header(pb, -pppoe_hdrlen);
+ pbuf_header(pb, -(s16_t)PPPOE_HDRLEN);
pc->lastXMit = sys_jiffies();
@@ -791,12 +778,16 @@ pppifOutputOverEthernet(int pd, struct pbuf *p)
*((u_char*)pb->payload + i) = protocol & 0xFF;
pbuf_chain(pb, p);
+ tot_len = pb->tot_len;
if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
LINK_STATS_INC(link.err);
+ snmp_inc_ifoutdiscards(&pc->netif);
return PPPERR_DEVICE;
}
+ snmp_add_ifoutoctets(&pc->netif, tot_len);
+ snmp_inc_ifoutucastpkts(&pc->netif);
LINK_STATS_INC(link.xmit);
return ERR_OK;
}
@@ -804,9 +795,9 @@ pppifOutputOverEthernet(int pd, struct pbuf *p)
/* Send a packet on the given connection. */
static err_t
-pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
+pppifOutput(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr)
{
- int pd = (int)netif->state;
+ int pd = (int)(size_t)netif->state;
PPPControl *pc = &pppControl[pd];
#if PPPOS_SUPPORT
u_short protocol = PPP_IP;
@@ -821,18 +812,20 @@ pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
/* We let any protocol value go through - it can't hurt us
* and the peer will just drop it if it's not accepting it. */
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
- PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n",
+ PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad parms prot=%d pb=%p\n",
pd, PPP_IP, pb));
LINK_STATS_INC(link.opterr);
LINK_STATS_INC(link.drop);
+ snmp_inc_ifoutdiscards(netif);
return ERR_ARG;
}
/* Check that the link is up. */
if (lcp_phase[pd] == PHASE_DEAD) {
- PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd));
+ PPPDEBUG(LOG_ERR, ("pppifOutput[%d]: link not up\n", pd));
LINK_STATS_INC(link.rterr);
LINK_STATS_INC(link.drop);
+ snmp_inc_ifoutdiscards(netif);
return ERR_RTE;
}
@@ -846,9 +839,10 @@ pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
/* Grab an output buffer. */
headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) {
- PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd));
+ PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: first alloc fail\n", pd));
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
+ snmp_inc_ifoutdiscards(netif);
return ERR_MEM;
}
@@ -870,9 +864,10 @@ pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
protocol = PPP_VJC_UNCOMP;
break;
default:
- PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd));
+ PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad IP packet\n", pd));
LINK_STATS_INC(link.proterr);
LINK_STATS_INC(link.drop);
+ snmp_inc_ifoutdiscards(netif);
pbuf_free(headMB);
return ERR_VAL;
}
@@ -929,17 +924,18 @@ pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
/* If we failed to complete the packet, throw it away. */
if (!tailMB) {
- PPPDEBUG((LOG_WARNING,
- "pppifOutput[%d]: Alloc err - dropping proto=%d\n",
+ PPPDEBUG(LOG_WARNING,
+ ("pppifOutput[%d]: Alloc err - dropping proto=%d\n",
pd, protocol));
pbuf_free(headMB);
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
+ snmp_inc_ifoutdiscards(netif);
return ERR_MEM;
}
/* Send it. */
- PPPDEBUG((LOG_INFO, "pppifOutput[%d]: proto=0x%04X\n", pd, protocol));
+ PPPDEBUG(LOG_INFO, ("pppifOutput[%d]: proto=0x%"X16_F"\n", pd, protocol));
nPut(pc, headMB);
#endif /* PPPOS_SUPPORT */
@@ -981,7 +977,7 @@ pppIOCtl(int pd, int cmd, void *arg)
}
break;
#if PPPOS_SUPPORT
- case PPPCTLG_FD:
+ case PPPCTLG_FD: /* Get the fd associated with the ppp */
if (arg) {
*(sio_fd_t *)arg = pc->fd;
} else {
@@ -1001,11 +997,11 @@ pppIOCtl(int pd, int cmd, void *arg)
/*
* Return the Maximum Transmission Unit for the given PPP connection.
*/
-u_int
+u_short
pppMTU(int pd)
{
PPPControl *pc = &pppControl[pd];
- u_int st;
+ u_short st;
/* Validate parameters. */
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
@@ -1028,14 +1024,16 @@ pppWriteOverEthernet(int pd, const u_char *s, int n)
s += 2;
n -= 2;
- pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + n, PBUF_RAM);
+ LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN + n <= 0xffff);
+ pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HDRLEN + n), PBUF_RAM);
if(!pb) {
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.proterr);
+ snmp_inc_ifoutdiscards(&pc->netif);
return PPPERR_ALLOC;
}
- pbuf_header(pb, -pppoe_hdrlen);
+ pbuf_header(pb, -(s16_t)PPPOE_HDRLEN);
pc->lastXMit = sys_jiffies();
@@ -1043,9 +1041,12 @@ pppWriteOverEthernet(int pd, const u_char *s, int n)
if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
LINK_STATS_INC(link.err);
+ snmp_inc_ifoutdiscards(&pc->netif);
return PPPERR_DEVICE;
}
+ snmp_add_ifoutoctets(&pc->netif, (u16_t)n);
+ snmp_inc_ifoutucastpkts(&pc->netif);
LINK_STATS_INC(link.xmit);
return PPPERR_NONE;
}
@@ -1077,6 +1078,7 @@ pppWrite(int pd, const u_char *s, int n)
if (headMB == NULL) {
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.proterr);
+ snmp_inc_ifoutdiscards(&pc->netif);
return PPPERR_ALLOC;
}
@@ -1111,16 +1113,17 @@ pppWrite(int pd, const u_char *s, int n)
/* If we failed to complete the packet, throw it away.
* Otherwise send it. */
if (!tailMB) {
- PPPDEBUG((LOG_WARNING,
- "pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
+ PPPDEBUG(LOG_WARNING,
+ ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
/*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
pbuf_free(headMB);
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.proterr);
+ snmp_inc_ifoutdiscards(&pc->netif);
return PPPERR_ALLOC;
}
- PPPDEBUG((LOG_INFO, "pppWrite[%d]: len=%d\n", pd, headMB->len));
+ PPPDEBUG(LOG_INFO, ("pppWrite[%d]: len=%d\n", pd, headMB->len));
/* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
nPut(pc, headMB);
#endif /* PPPOS_SUPPORT */
@@ -1133,7 +1136,7 @@ pppWrite(int pd, const u_char *s, int n)
* the ppp interface.
*/
void
-ppp_send_config( int unit, int mtu, u32_t asyncmap, int pcomp, int accomp)
+ppp_send_config( int unit, u16_t mtu, u32_t asyncmap, int pcomp, int accomp)
{
PPPControl *pc = &pppControl[unit];
int i;
@@ -1146,7 +1149,7 @@ ppp_send_config( int unit, int mtu, u32_t asyncmap, int pcomp, int accomp)
for (i = 0; i < 32/8; i++) {
pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF);
}
- PPPDEBUG((LOG_INFO, "ppp_send_config[%d]: outACCM=%X %X %X %X\n",
+ PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n",
unit,
pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3]));
}
@@ -1159,7 +1162,7 @@ void
ppp_set_xaccm(int unit, ext_accm *accm)
{
SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm));
- PPPDEBUG((LOG_INFO, "ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n",
+ PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n",
unit,
pppControl[unit].outACCM[0],
pppControl[unit].outACCM[1],
@@ -1177,18 +1180,22 @@ ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp)
{
PPPControl *pc = &pppControl[unit];
int i;
+ SYS_ARCH_DECL_PROTECT(lev);
LWIP_UNUSED_ARG(accomp);
LWIP_UNUSED_ARG(pcomp);
LWIP_UNUSED_ARG(mru);
/* Load the ACCM bits for the 32 control codes. */
+ SYS_ARCH_PROTECT(lev);
for (i = 0; i < 32 / 8; i++) {
- pc->inACCM[i] = (u_char)(asyncmap >> (i * 8));
+ /* @todo: does this work? ext_accm has been modified from pppd! */
+ pc->rx.inACCM[i] = (u_char)(asyncmap >> (i * 8));
}
- PPPDEBUG((LOG_INFO, "ppp_recv_config[%d]: inACCM=%X %X %X %X\n",
+ SYS_ARCH_UNPROTECT(lev);
+ PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n",
unit,
- pc->inACCM[0], pc->inACCM[1], pc->inACCM[2], pc->inACCM[3]));
+ pc->rx.inACCM[0], pc->rx.inACCM[1], pc->rx.inACCM[2], pc->rx.inACCM[3]));
}
#if 0
@@ -1254,12 +1261,12 @@ GetMask(u32_t addr)
u32_t mask, nmask;
htonl(addr);
- if (IN_CLASSA(addr)) { /* determine network mask for address class */
- nmask = IN_CLASSA_NET;
- } else if (IN_CLASSB(addr)) {
- nmask = IN_CLASSB_NET;
+ if (IP_CLASSA(addr)) { /* determine network mask for address class */
+ nmask = IP_CLASSA_NET;
+ } else if (IP_CLASSB(addr)) {
+ nmask = IP_CLASSB_NET;
} else {
- nmask = IN_CLASSC_NET;
+ nmask = IP_CLASSC_NET;
}
/* class D nets are disallowed by bad_ip_adrs */
@@ -1277,7 +1284,7 @@ GetMask(u32_t addr)
* sifvjcomp - config tcp header compression
*/
int
-sifvjcomp(int pd, int vjcomp, int cidcomp, int maxcid)
+sifvjcomp(int pd, int vjcomp, u8_t cidcomp, u8_t maxcid)
{
#if PPPOS_SUPPORT && VJ_SUPPORT
PPPControl *pc = &pppControl[pd];
@@ -1285,7 +1292,7 @@ sifvjcomp(int pd, int vjcomp, int cidcomp, int maxcid)
pc->vjEnabled = vjcomp;
pc->vjComp.compressSlot = cidcomp;
pc->vjComp.maxSlotIndex = maxcid;
- PPPDEBUG((LOG_INFO, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
+ PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
vjcomp, cidcomp, maxcid));
#else /* PPPOS_SUPPORT && VJ_SUPPORT */
LWIP_UNUSED_ARG(pd);
@@ -1306,7 +1313,12 @@ pppifNetifInit(struct netif *netif)
netif->name[0] = 'p';
netif->name[1] = 'p';
netif->output = pppifOutput;
- netif->mtu = pppMTU((int)netif->state);
+ netif->mtu = pppMTU((int)(size_t)netif->state);
+ netif->flags = NETIF_FLAG_POINTTOPOINT | NETIF_FLAG_LINK_UP;
+#if LWIP_NETIF_HOSTNAME
+ /* @todo: Initialize interface hostname */
+ /* netif_set_hostname(netif, "lwip"); */
+#endif /* LWIP_NETIF_HOSTNAME */
return ERR_OK;
}
@@ -1322,21 +1334,22 @@ sifup(int pd)
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
- PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
+ PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
} else {
netif_remove(&pc->netif);
- if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, &pc->addrs.his_ipaddr, (void *)pd, pppifNetifInit, ip_input)) {
+ if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask,
+ &pc->addrs.his_ipaddr, (void *)(size_t)pd, pppifNetifInit, ip_input)) {
netif_set_up(&pc->netif);
pc->if_up = 1;
pc->errCode = PPPERR_NONE;
- PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
- if(pc->linkStatusCB) {
+ PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
+ if (pc->linkStatusCB) {
pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
}
} else {
st = 0;
- PPPDEBUG((LOG_ERR, "sifup[%d]: netif_add failed\n", pd));
+ PPPDEBUG(LOG_ERR, ("sifup[%d]: netif_add failed\n", pd));
}
}
@@ -1366,14 +1379,14 @@ sifdown(int pd)
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
- PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
+ PPPDEBUG(LOG_WARNING, ("sifdown[%d]: bad parms\n", pd));
} else {
pc->if_up = 0;
/* make sure the netif status callback is called */
netif_set_down(&pc->netif);
netif_remove(&pc->netif);
- PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
- if(pc->linkStatusCB) {
+ PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
+ if (pc->linkStatusCB) {
pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
}
}
@@ -1397,7 +1410,7 @@ sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2)
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
- PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
+ PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
} else {
SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o));
SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h));
@@ -1425,7 +1438,7 @@ cifaddr( int pd, u32_t o, u32_t h)
LWIP_UNUSED_ARG(h);
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
- PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
+ PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
} else {
IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
@@ -1450,7 +1463,7 @@ sifdefaultroute(int pd, u32_t l, u32_t g)
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
- PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
+ PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
} else {
netif_set_default(&pc->netif);
}
@@ -1474,7 +1487,7 @@ cifdefaultroute(int pd, u32_t l, u32_t g)
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
- PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
+ PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
} else {
netif_set_default(NULL);
}
@@ -1486,76 +1499,36 @@ cifdefaultroute(int pd, u32_t l, u32_t g)
/*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/
-#if PPPOS_SUPPORT
+#if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD
/* The main PPP process function. This implements the state machine according
* to section 4 of RFC 1661: The Point-To-Point Protocol. */
static void
-pppMain(void *arg)
+pppInputThread(void *arg)
{
- int pd = (int)arg;
- struct pbuf *p;
- PPPControl* pc;
- int c;
+ int count;
+ PPPControlRx *pcrx = arg;
- pc = &pppControl[pd];
-
- p = pbuf_alloc(PBUF_RAW, PPP_MRU+PPP_HDRLEN, PBUF_RAM);
- if (!p) {
- LWIP_ASSERT("p != NULL", p);
- pc->errCode = PPPERR_ALLOC;
- goto out;
- }
-
- /*
- * Start the connection and handle incoming events (packet or timeout).
- */
- PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd));
- tcpip_callback(pppStartCB, arg);
- while (lcp_phase[pd] != PHASE_DEAD) {
- if (pc->kill_link) {
- PPPDEBUG((LOG_DEBUG, "pppMain: unit %d kill_link -> pppStopCB\n", pd));
- pc->errCode = PPPERR_USER;
- /* This will leave us at PHASE_DEAD. */
- tcpip_callback(pppStopCB, arg);
- pc->kill_link = 0;
- } else if (pc->sig_hup) {
- PPPDEBUG((LOG_DEBUG, "pppMain: unit %d sig_hup -> pppHupCB\n", pd));
- pc->sig_hup = 0;
- tcpip_callback(pppHupCB, arg);
+ while (lcp_phase[pcrx->pd] != PHASE_DEAD) {
+ count = sio_read(pcrx->fd, pcrx->rxbuf, PPPOS_RX_BUFSIZE);
+ if(count > 0) {
+ pppInProc(pcrx, pcrx->rxbuf, count);
} else {
- c = sio_read(pc->fd, p->payload, p->len);
- if(c > 0) {
- pppInProc(pd, p->payload, c);
- } else {
- /* nothing received, give other tasks a chance to run */
- sys_msleep(1);
- }
+ /* nothing received, give other tasks a chance to run */
+ sys_msleep(1);
}
}
- PPPDEBUG((LOG_INFO, "pppMain: unit %d: PHASE_DEAD\n", pd));
- pppDrop(pc); /* bug fix #17726 */
- pbuf_free(p);
-
-out:
- PPPDEBUG((LOG_DEBUG, "pppMain: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
- if(pc->linkStatusCB) {
- pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
- }
-
- pc->openFlag = 0;
}
-#endif /* PPPOS_SUPPORT */
+#endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD */
#if PPPOE_SUPPORT
void
-pppOverEthernetInitFailed(void* arg)
+pppOverEthernetInitFailed(int pd)
{
PPPControl* pc;
- int pd = (int)arg;
- pppHupCB(arg);
- pppStopCB(arg);
+ pppHup(pd);
+ pppStop(pd);
pc = &pppControl[pd];
pppoe_destroy(&pc->netif);
@@ -1570,12 +1543,10 @@ static void
pppOverEthernetLinkStatusCB(int pd, int up)
{
if(up) {
- PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd));
- tcpip_callback(pppStartCB, (void*)pd);
+ PPPDEBUG(LOG_INFO, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd));
+ pppStart(pd);
} else {
- PPPControl* pc;
- pc = &pppControl[pd];
- tcpip_callback(pppOverEthernetInitFailed, (void*)pd);
+ pppOverEthernetInitFailed(pd);
}
}
#endif /* PPPOE_SUPPORT */
@@ -1592,8 +1563,8 @@ pppSingleBuf(struct pbuf *p)
q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
if(!q) {
- PPPDEBUG((LOG_ERR,
- "pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len));
+ PPPDEBUG(LOG_ERR,
+ ("pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len));
return p; /* live dangerously */
}
@@ -1632,6 +1603,8 @@ pppInput(void *arg)
}
LINK_STATS_INC(link.recv);
+ snmp_inc_ifinucastpkts(&pppControl[pd].netif);
+ snmp_add_ifinoctets(&pppControl[pd].netif, nb->tot_len);
/*
* Toss all non-LCP packets unless LCP is OPEN.
@@ -1641,7 +1614,7 @@ pppInput(void *arg)
if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) {
if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) ||
(lcp_phase[pd] != PHASE_AUTHENTICATE)) {
- PPPDEBUG((LOG_INFO, "pppInput: discarding proto 0x%04X in phase %d\n", protocol, lcp_phase[pd]));
+ PPPDEBUG(LOG_INFO, ("pppInput: discarding proto 0x%"X16_F" in phase %d\n", protocol, lcp_phase[pd]));
goto drop;
}
}
@@ -1649,7 +1622,7 @@ pppInput(void *arg)
switch(protocol) {
case PPP_VJC_COMP: /* VJ compressed TCP */
#if PPPOS_SUPPORT && VJ_SUPPORT
- PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
+ PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
/*
* Clip off the VJ header and prepend the rebuilt TCP/IP header and
* pass the result to IP.
@@ -1659,16 +1632,16 @@ pppInput(void *arg)
return;
}
/* Something's wrong so drop it. */
- PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ compressed\n", pd));
+ PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ compressed\n", pd));
#else /* PPPOS_SUPPORT && VJ_SUPPORT */
/* No handler for this protocol so drop the packet. */
- PPPDEBUG((LOG_INFO, "pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload));
+ PPPDEBUG(LOG_INFO, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload));
#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
break;
case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */
#if PPPOS_SUPPORT && VJ_SUPPORT
- PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
+ PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
/*
* Process the TCP/IP header for VJ header compression and then pass
* the packet to IP.
@@ -1678,17 +1651,17 @@ pppInput(void *arg)
return;
}
/* Something's wrong so drop it. */
- PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ uncompressed\n", pd));
+ PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ uncompressed\n", pd));
#else /* PPPOS_SUPPORT && VJ_SUPPORT */
/* No handler for this protocol so drop the packet. */
- PPPDEBUG((LOG_INFO,
- "pppInput[%d]: drop VJ UnComp in %d:.*H\n",
+ PPPDEBUG(LOG_INFO,
+ ("pppInput[%d]: drop VJ UnComp in %d:.*H\n",
pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
break;
case PPP_IP: /* Internet Protocol */
- PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len));
+ PPPDEBUG(LOG_INFO, ("pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len));
if (pppControl[pd].netif.input) {
pppControl[pd].netif.input(nb, &pppControl[pd].netif);
return;
@@ -1704,23 +1677,24 @@ pppInput(void *arg)
*/
for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
if (protp->protocol == protocol && protp->enabled_flag) {
- PPPDEBUG((LOG_INFO, "pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len));
+ PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len));
nb = pppSingleBuf(nb);
(*protp->input)(pd, nb->payload, nb->len);
+ PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd));
goto out;
}
}
/* No handler for this protocol so reject the packet. */
- PPPDEBUG((LOG_INFO, "pppInput[%d]: rejecting unsupported proto 0x%04X len=%d\n", pd, protocol, nb->len));
+ PPPDEBUG(LOG_INFO, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F" len=%d\n", pd, protocol, nb->len));
if (pbuf_header(nb, sizeof(protocol))) {
LWIP_ASSERT("pbuf_header failed\n", 0);
goto drop;
}
#if BYTE_ORDER == LITTLE_ENDIAN
protocol = htons(protocol);
- SMEMCPY(nb->payload, &protocol, sizeof(protocol));
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+ SMEMCPY(nb->payload, &protocol, sizeof(protocol));
lcp_sprotrej(pd, nb->payload, nb->len);
}
break;
@@ -1728,6 +1702,7 @@ pppInput(void *arg)
drop:
LINK_STATS_INC(link.drop);
+ snmp_inc_ifindiscards(&pppControl[pd].netif);
out:
pbuf_free(nb);
@@ -1739,118 +1714,145 @@ out:
* Drop the input packet.
*/
static void
-pppDrop(PPPControl *pc)
+pppDrop(PPPControlRx *pcrx)
{
- if (pc->inHead != NULL) {
+ if (pcrx->inHead != NULL) {
#if 0
- PPPDEBUG((LOG_INFO, "pppDrop: %d:%.*H\n", pc->inHead->len, min(60, pc->inHead->len * 2), pc->inHead->payload));
+ PPPDEBUG(LOG_INFO, ("pppDrop: %d:%.*H\n", pcrx->inHead->len, min(60, pcrx->inHead->len * 2), pcrx->inHead->payload));
#endif
- PPPDEBUG((LOG_INFO, "pppDrop: pbuf len=%d\n", pc->inHead->len));
- if (pc->inTail && (pc->inTail != pc->inHead)) {
- pbuf_free(pc->inTail);
+ PPPDEBUG(LOG_INFO, ("pppDrop: pbuf len=%d, addr %p\n", pcrx->inHead->len, (void*)pcrx->inHead));
+ if (pcrx->inTail && (pcrx->inTail != pcrx->inHead)) {
+ pbuf_free(pcrx->inTail);
}
- pbuf_free(pc->inHead);
- pc->inHead = NULL;
- pc->inTail = NULL;
+ pbuf_free(pcrx->inHead);
+ pcrx->inHead = NULL;
+ pcrx->inTail = NULL;
}
#if VJ_SUPPORT
- vj_uncompress_err(&pc->vjComp);
+ vj_uncompress_err(&pppControl[pcrx->pd].vjComp);
#endif /* VJ_SUPPORT */
LINK_STATS_INC(link.drop);
+ snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif);
+}
+
+/** Pass received raw characters to PPPoS to be decoded. This function is
+ * thread-safe and can be called from a dedicated RX-thread or from a main-loop.
+ *
+ * @param pd PPP descriptor index, returned by pppOpen()
+ * @param data received data
+ * @param len length of received data
+ */
+void
+pppos_input(int pd, u_char* data, int len)
+{
+ pppInProc(&pppControl[pd].rx, data, len);
}
/**
* Process a received octet string.
*/
static void
-pppInProc(int pd, u_char *s, int l)
+pppInProc(PPPControlRx *pcrx, u_char *s, int l)
{
- PPPControl *pc = &pppControl[pd];
struct pbuf *nextNBuf;
u_char curChar;
+ u_char escaped;
+ SYS_ARCH_DECL_PROTECT(lev);
- PPPDEBUG((LOG_DEBUG, "pppInProc[%d]: got %d bytes\n", pd, l));
+ PPPDEBUG(LOG_DEBUG, ("pppInProc[%d]: got %d bytes\n", pcrx->pd, l));
while (l-- > 0) {
curChar = *s++;
-
+
+ SYS_ARCH_PROTECT(lev);
+ escaped = ESCAPE_P(pcrx->inACCM, curChar);
+ SYS_ARCH_UNPROTECT(lev);
/* Handle special characters. */
- if (ESCAPE_P(pc->inACCM, curChar)) {
+ if (escaped) {
/* Check for escape sequences. */
/* XXX Note that this does not handle an escaped 0x5d character which
* would appear as an escape character. Since this is an ASCII ']'
* and there is no reason that I know of to escape it, I won't complicate
* the code to handle this case. GLL */
if (curChar == PPP_ESCAPE) {
- pc->inEscaped = 1;
+ pcrx->inEscaped = 1;
/* Check for the flag character. */
} else if (curChar == PPP_FLAG) {
- /* If this is just an extra flag character, ignore it. */
- if (pc->inState <= PDADDRESS) {
- /* ignore it */;
- /* If we haven't received the packet header, drop what has come in. */
- } else if (pc->inState < PDDATA) {
- PPPDEBUG((LOG_WARNING,
- "pppInProc[%d]: Dropping incomplete packet %d\n",
- pd, pc->inState));
- LINK_STATS_INC(link.lenerr);
- pppDrop(pc);
- /* If the fcs is invalid, drop the packet. */
- } else if (pc->inFCS != PPP_GOODFCS) {
- PPPDEBUG((LOG_INFO,
- "pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n",
- pd, pc->inFCS, pc->inProtocol));
- LINK_STATS_INC(link.chkerr);
- pppDrop(pc);
- /* Otherwise it's a good packet so pass it on. */
- } else {
- /* Trim off the checksum. */
- if(pc->inTail->len >= 2) {
- pc->inTail->len -= 2;
-
- pc->inTail->tot_len = pc->inTail->len;
- if (pc->inTail != pc->inHead) {
- pbuf_cat(pc->inHead, pc->inTail);
- }
- } else {
- pc->inTail->tot_len = pc->inTail->len;
- if (pc->inTail != pc->inHead) {
- pbuf_cat(pc->inHead, pc->inTail);
- }
-
- pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2);
- }
-
- /* Dispatch the packet thereby consuming it. */
- if(tcpip_callback(pppInput, pc->inHead) != ERR_OK) {
- PPPDEBUG((LOG_ERR, "pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd));
- pbuf_free(pc->inHead);
- LINK_STATS_INC(link.drop);
- }
- pc->inHead = NULL;
- pc->inTail = NULL;
- }
-
- /* Prepare for a new packet. */
- pc->inFCS = PPP_INITFCS;
- pc->inState = PDADDRESS;
- pc->inEscaped = 0;
+ /* If this is just an extra flag character, ignore it. */
+ if (pcrx->inState <= PDADDRESS) {
+ /* ignore it */;
+ /* If we haven't received the packet header, drop what has come in. */
+ } else if (pcrx->inState < PDDATA) {
+ PPPDEBUG(LOG_WARNING,
+ ("pppInProc[%d]: Dropping incomplete packet %d\n",
+ pcrx->pd, pcrx->inState));
+ LINK_STATS_INC(link.lenerr);
+ pppDrop(pcrx);
+ /* If the fcs is invalid, drop the packet. */
+ } else if (pcrx->inFCS != PPP_GOODFCS) {
+ PPPDEBUG(LOG_INFO,
+ ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n",
+ pcrx->pd, pcrx->inFCS, pcrx->inProtocol));
+ /* Note: If you get lots of these, check for UART frame errors or try different baud rate */
+ LINK_STATS_INC(link.chkerr);
+ pppDrop(pcrx);
+ /* Otherwise it's a good packet so pass it on. */
+ } else {
+ struct pbuf *inp;
+ /* Trim off the checksum. */
+ if(pcrx->inTail->len >= 2) {
+ pcrx->inTail->len -= 2;
+
+ pcrx->inTail->tot_len = pcrx->inTail->len;
+ if (pcrx->inTail != pcrx->inHead) {
+ pbuf_cat(pcrx->inHead, pcrx->inTail);
+ }
+ } else {
+ pcrx->inTail->tot_len = pcrx->inTail->len;
+ if (pcrx->inTail != pcrx->inHead) {
+ pbuf_cat(pcrx->inHead, pcrx->inTail);
+ }
+
+ pbuf_realloc(pcrx->inHead, pcrx->inHead->tot_len - 2);
+ }
+
+ /* Dispatch the packet thereby consuming it. */
+ inp = pcrx->inHead;
+ /* Packet consumed, release our references. */
+ pcrx->inHead = NULL;
+ pcrx->inTail = NULL;
+#if PPP_INPROC_MULTITHREADED
+ if(tcpip_callback_with_block(pppInput, inp, 0) != ERR_OK) {
+ PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd));
+ pbuf_free(inp);
+ LINK_STATS_INC(link.drop);
+ snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif);
+ }
+#else /* PPP_INPROC_MULTITHREADED */
+ pppInput(inp);
+#endif /* PPP_INPROC_MULTITHREADED */
+ }
+
+ /* Prepare for a new packet. */
+ pcrx->inFCS = PPP_INITFCS;
+ pcrx->inState = PDADDRESS;
+ pcrx->inEscaped = 0;
/* Other characters are usually control characters that may have
* been inserted by the physical layer so here we just drop them. */
} else {
- PPPDEBUG((LOG_WARNING,
- "pppInProc[%d]: Dropping ACCM char <%d>\n", pd, curChar));
+ PPPDEBUG(LOG_WARNING,
+ ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx->pd, curChar));
}
/* Process other characters. */
} else {
/* Unencode escaped characters. */
- if (pc->inEscaped) {
- pc->inEscaped = 0;
+ if (pcrx->inEscaped) {
+ pcrx->inEscaped = 0;
curChar ^= PPP_TRANS;
}
/* Process character relative to current state. */
- switch(pc->inState) {
+ switch(pcrx->inState) {
case PDIDLE: /* Idle state - waiting. */
/* Drop the character if it's not 0xff
* we would have processed a flag character above. */
@@ -1861,12 +1863,12 @@ pppInProc(int pd, u_char *s, int l)
/* Fall through */
case PDSTART: /* Process start flag. */
/* Prepare for a new packet. */
- pc->inFCS = PPP_INITFCS;
+ pcrx->inFCS = PPP_INITFCS;
/* Fall through */
case PDADDRESS: /* Process address field. */
if (curChar == PPP_ALLSTATIONS) {
- pc->inState = PDCONTROL;
+ pcrx->inState = PDCONTROL;
break;
}
/* Else assume compressed address and control fields so
@@ -1874,38 +1876,40 @@ pppInProc(int pd, u_char *s, int l)
case PDCONTROL: /* Process control field. */
/* If we don't get a valid control code, restart. */
if (curChar == PPP_UI) {
- pc->inState = PDPROTOCOL1;
+ pcrx->inState = PDPROTOCOL1;
break;
}
#if 0
else {
- PPPDEBUG((LOG_WARNING,
- "pppInProc[%d]: Invalid control <%d>\n", pd, curChar));
- pc->inState = PDSTART;
+ PPPDEBUG(LOG_WARNING,
+ ("pppInProc[%d]: Invalid control <%d>\n", pcrx->pd, curChar));
+ pcrx->inState = PDSTART;
}
#endif
case PDPROTOCOL1: /* Process protocol field 1. */
/* If the lower bit is set, this is the end of the protocol
* field. */
if (curChar & 1) {
- pc->inProtocol = curChar;
- pc->inState = PDDATA;
+ pcrx->inProtocol = curChar;
+ pcrx->inState = PDDATA;
} else {
- pc->inProtocol = (u_int)curChar << 8;
- pc->inState = PDPROTOCOL2;
+ pcrx->inProtocol = (u_int)curChar << 8;
+ pcrx->inState = PDPROTOCOL2;
}
break;
case PDPROTOCOL2: /* Process protocol field 2. */
- pc->inProtocol |= curChar;
- pc->inState = PDDATA;
+ pcrx->inProtocol |= curChar;
+ pcrx->inState = PDDATA;
break;
case PDDATA: /* Process data byte. */
/* Make space to receive processed data. */
- if (pc->inTail == NULL || pc->inTail->len == PBUF_POOL_BUFSIZE) {
- if(pc->inTail) {
- pc->inTail->tot_len = pc->inTail->len;
- if (pc->inTail != pc->inHead) {
- pbuf_cat(pc->inHead, pc->inTail);
+ if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) {
+ if (pcrx->inTail != NULL) {
+ pcrx->inTail->tot_len = pcrx->inTail->len;
+ if (pcrx->inTail != pcrx->inHead) {
+ pbuf_cat(pcrx->inHead, pcrx->inTail);
+ /* give up the inTail reference now */
+ pcrx->inTail = NULL;
}
}
/* If we haven't started a packet, we need a packet header. */
@@ -1914,33 +1918,33 @@ pppInProc(int pd, u_char *s, int l)
/* No free buffers. Drop the input packet and let the
* higher layers deal with it. Continue processing
* the received pbuf chain in case a new packet starts. */
- PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd));
+ PPPDEBUG(LOG_ERR, ("pppInProc[%d]: NO FREE MBUFS!\n", pcrx->pd));
LINK_STATS_INC(link.memerr);
- pppDrop(pc);
- pc->inState = PDSTART; /* Wait for flag sequence. */
+ pppDrop(pcrx);
+ pcrx->inState = PDSTART; /* Wait for flag sequence. */
break;
}
- if (pc->inHead == NULL) {
+ if (pcrx->inHead == NULL) {
struct pppInputHeader *pih = nextNBuf->payload;
- pih->unit = pd;
- pih->proto = pc->inProtocol;
+ pih->unit = pcrx->pd;
+ pih->proto = pcrx->inProtocol;
nextNBuf->len += sizeof(*pih);
- pc->inHead = nextNBuf;
+ pcrx->inHead = nextNBuf;
}
- pc->inTail = nextNBuf;
+ pcrx->inTail = nextNBuf;
}
/* Load character into buffer. */
- ((u_char*)pc->inTail->payload)[pc->inTail->len++] = curChar;
+ ((u_char*)pcrx->inTail->payload)[pcrx->inTail->len++] = curChar;
break;
}
/* update the frame check sequence number. */
- pc->inFCS = PPP_FCS(pc->inFCS, curChar);
+ pcrx->inFCS = PPP_FCS(pcrx->inFCS, curChar);
}
- }
+ } /* while (l-- > 0), all bytes processed */
avRandomize();
}
@@ -1954,7 +1958,7 @@ pppInProcOverEthernet(int pd, struct pbuf *pb)
u16_t inProtocol;
if(pb->len < sizeof(inProtocol)) {
- PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: too small for protocol field\n"));
+ PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: too small for protocol field\n"));
goto drop;
}
@@ -1962,7 +1966,7 @@ pppInProcOverEthernet(int pd, struct pbuf *pb)
/* make room for pppInputHeader - should not fail */
if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) {
- PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: could not allocate room for header\n"));
+ PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: could not allocate room for header\n"));
goto drop;
}
@@ -1972,18 +1976,45 @@ pppInProcOverEthernet(int pd, struct pbuf *pb)
pih->proto = inProtocol;
/* Dispatch the packet thereby consuming it. */
- if(tcpip_callback(pppInput, pb) != ERR_OK) {
- PPPDEBUG((LOG_ERR, "pppInProcOverEthernet[%d]: tcpip_callback() failed, dropping packet\n", pd));
- goto drop;
- }
-
+ pppInput(pb);
return;
drop:
LINK_STATS_INC(link.drop);
+ snmp_inc_ifindiscards(&pppControl[pd].netif);
pbuf_free(pb);
return;
}
#endif /* PPPOE_SUPPORT */
+#if LWIP_NETIF_STATUS_CALLBACK
+/** Set the status callback of a PPP's netif
+ *
+ * @param pd The PPP descriptor returned by pppOpen()
+ * @param status_callback pointer to the status callback function
+ *
+ * @see netif_set_status_callback
+ */
+void
+ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback)
+{
+ netif_set_status_callback(&pppControl[pd].netif, status_callback);
+}
+#endif /* LWIP_NETIF_STATUS_CALLBACK */
+
+#if LWIP_NETIF_LINK_CALLBACK
+/** Set the link callback of a PPP's netif
+ *
+ * @param pd The PPP descriptor returned by pppOpen()
+ * @param link_callback pointer to the link callback function
+ *
+ * @see netif_set_link_callback
+ */
+void
+ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback)
+{
+ netif_set_link_callback(&pppControl[pd].netif, link_callback);
+}
+#endif /* LWIP_NETIF_LINK_CALLBACK */
+
#endif /* PPP_SUPPORT */
diff --git a/core/lwip/src/netif/ppp/ppp.h b/core/lwip/src/netif/ppp/ppp.h
index ebc733be..a72ac957 100644
--- a/core/lwip/src/netif/ppp/ppp.h
+++ b/core/lwip/src/netif/ppp/ppp.h
@@ -40,12 +40,23 @@
#include "lwip/def.h"
#include "lwip/sio.h"
-#include "lwip/api.h"
-#include "lwip/sockets.h"
#include "lwip/stats.h"
#include "lwip/mem.h"
-#include "lwip/tcpip.h"
#include "lwip/netif.h"
+#include "lwip/sys.h"
+#include "lwip/timers.h"
+
+/** Some defines for code we skip compared to the original pppd.
+ * These are just here to minimise the use of the ugly "#if 0". */
+#define PPP_ADDITIONAL_CALLBACKS 0
+
+/** Some error checks to test for unsupported code */
+#if CBCP_SUPPORT
+#error "CBCP is not supported in lwIP PPP"
+#endif
+#if CCP_SUPPORT
+#error "CCP is not supported in lwIP PPP"
+#endif
/*
* pppd.h - PPP daemon global declarations.
@@ -93,7 +104,7 @@
* OR MODIFICATIONS.
*/
-#define TIMEOUT(f, a, t) sys_untimeout((f), (a)), sys_timeout((t)*1000, (f), (a))
+#define TIMEOUT(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t)*1000, (f), (a)); } while(0)
#define UNTIMEOUT(f, a) sys_untimeout((f), (a))
@@ -212,7 +223,7 @@ enum NPmode {
#define BZERO(s, n) memset(s, 0, n)
#if PPP_DEBUG
-#define PRINTMSG(m, l) { m[l] = '\0'; ppp_trace(LOG_INFO, "Remote message: %s\n", m); }
+#define PRINTMSG(m, l) { m[l] = '\0'; LWIP_DEBUGF(LOG_INFO, ("Remote message: %s\n", m)); }
#else /* PPP_DEBUG */
#define PRINTMSG(m, l)
#endif /* PPP_DEBUG */
@@ -276,24 +287,24 @@ struct protent {
void (*open) (int unit);
/* Close the protocol */
void (*close) (int unit, char *reason);
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
/* Print a packet in readable form */
int (*printpkt) (u_char *pkt, int len,
void (*printer) (void *, char *, ...),
void *arg);
/* Process a received data packet */
void (*datainput) (int unit, u_char *pkt, int len);
-#endif
- int enabled_flag; /* 0 iff protocol is disabled */
+#endif /* PPP_ADDITIONAL_CALLBACKS */
+ int enabled_flag; /* 0 if protocol is disabled */
char *name; /* Text name of protocol */
-#if 0
+#if PPP_ADDITIONAL_CALLBACKS
/* Check requested options, assign defaults */
void (*check_options) (u_long);
/* Configure interface for demand-dial */
int (*demand_conf) (int unit);
/* Say whether to bring up link for this pkt */
int (*active_pkt) (u_char *pkt, int len);
-#endif
+#endif /* PPP_ADDITIONAL_CALLBACKS */
};
/*
@@ -325,7 +336,7 @@ struct ppp_settings {
};
struct ppp_addrs {
- struct ip_addr our_ipaddr, his_ipaddr, netmask, dns1, dns2;
+ ip_addr_t our_ipaddr, his_ipaddr, netmask, dns1, dns2;
};
/*****************************
@@ -413,7 +424,7 @@ int pppIOCtl(int pd, int cmd, void *arg);
/*
* Return the Maximum Transmission Unit for the given PPP connection.
*/
-u_int pppMTU(int pd);
+u_short pppMTU(int pd);
/*
* Write n characters to a ppp link.
@@ -429,10 +440,10 @@ void pppLinkTerminated(int pd);
void pppLinkDown(int pd);
-void pppMainWakeup(int pd);
+void pppos_input(int pd, u_char* data, int len);
/* Configure i/f transmit parameters */
-void ppp_send_config (int, int, u32_t, int, int);
+void ppp_send_config (int, u16_t, u32_t, int, int);
/* Set extended transmit ACCM */
void ppp_set_xaccm (int, ext_accm *);
/* Configure i/f receive parameters */
@@ -441,7 +452,7 @@ void ppp_recv_config (int, int, u32_t, int, int);
int get_idle_time (int, struct ppp_idle *);
/* Configure VJ TCP header compression */
-int sifvjcomp (int, int, int, int);
+int sifvjcomp (int, int, u8_t, u8_t);
/* Configure i/f down (for IP) */
int sifup (int);
/* Set mode for handling packets for proto */
@@ -460,6 +471,13 @@ int cifdefaultroute (int, u32_t, u32_t);
/* Get appropriate netmask for address */
u32_t GetMask (u32_t);
+#if LWIP_NETIF_STATUS_CALLBACK
+void ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback);
+#endif /* LWIP_NETIF_STATUS_CALLBACK */
+#if LWIP_NETIF_LINK_CALLBACK
+void ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback);
+#endif /* LWIP_NETIF_LINK_CALLBACK */
+
#endif /* PPP_SUPPORT */
#endif /* PPP_H */
diff --git a/core/lwip/src/netif/ppp/ppp_oe.c b/core/lwip/src/netif/ppp/ppp_oe.c
index 5a8a45cf..040a0bc9 100644
--- a/core/lwip/src/netif/ppp/ppp_oe.c
+++ b/core/lwip/src/netif/ppp/ppp_oe.c
@@ -72,104 +72,22 @@
#if PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */
+#include "netif/ppp_oe.h"
+
#include "ppp.h"
#include "pppdebug.h"
-#include "lwip/sys.h"
-
-#include "netif/ppp_oe.h"
-#include "netif/etharp.h"
+#include "lwip/timers.h"
+#include "lwip/memp.h"
#include <string.h>
#include <stdio.h>
-/** @todo Replace this part with a simple list like other lwIP lists */
-#ifndef _SYS_QUEUE_H_
-#define _SYS_QUEUE_H_
-
-/*
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- */
-
-/*
- * List declarations.
- */
-#define LIST_HEAD(name, type) \
-struct name { \
- struct type *lh_first; /* first element */ \
-}
-
-#define LIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define LIST_ENTRY(type) \
-struct { \
- struct type *le_next; /* next element */ \
- struct type **le_prev; /* address of previous next element */ \
-}
-
-/*
- * List functions.
- */
-
-#define LIST_EMPTY(head) ((head)->lh_first == NULL)
-
-#define LIST_FIRST(head) ((head)->lh_first)
-
-#define LIST_FOREACH(var, head, field) \
- for ((var) = LIST_FIRST((head)); \
- (var); \
- (var) = LIST_NEXT((var), field))
-
-#define LIST_INIT(head) do { \
- LIST_FIRST((head)) = NULL; \
-} while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do { \
- if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL) \
- LIST_NEXT((listelm), field)->field.le_prev = \
- &LIST_NEXT((elm), field); \
- LIST_NEXT((listelm), field) = (elm); \
- (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
-} while (0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.le_prev = (listelm)->field.le_prev; \
- LIST_NEXT((elm), field) = (listelm); \
- *(listelm)->field.le_prev = (elm); \
- (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
-} while (0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do { \
- if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
- LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field); \
- LIST_FIRST((head)) = (elm); \
- (elm)->field.le_prev = &LIST_FIRST((head)); \
-} while (0)
-
-#define LIST_NEXT(elm, field) ((elm)->field.le_next)
-
-#define LIST_REMOVE(elm, field) do { \
- if (LIST_NEXT((elm), field) != NULL) \
- LIST_NEXT((elm), field)->field.le_prev = \
- (elm)->field.le_prev; \
- *(elm)->field.le_prev = LIST_NEXT((elm), field); \
-} while (0)
-
-#endif /* !_SYS_QUEUE_H_ */
-
/* Add a 16 bit unsigned value to a buffer pointed to by PTR */
#define PPPOE_ADD_16(PTR, VAL) \
- *(PTR)++ = (VAL) / 256; \
- *(PTR)++ = (VAL) % 256
+ *(PTR)++ = (u8_t)((VAL) / 256); \
+ *(PTR)++ = (u8_t)((VAL) % 256)
/* Add a complete PPPoE header to the buffer pointed to by PTR */
#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \
@@ -184,31 +102,16 @@ struct { \
#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */
#ifdef PPPOE_SERVER
+#error "PPPOE_SERVER is not yet supported under lwIP!"
/* from if_spppsubr.c */
#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */
#endif
-struct pppoe_softc {
- LIST_ENTRY(pppoe_softc) sc_list;
- struct netif *sc_ethif; /* ethernet interface we are using */
- int sc_pd; /* ppp unit number */
- void (*sc_linkStatusCB)(int pd, int up);
-
- int sc_state; /* discovery phase or session connected */
- struct eth_addr sc_dest; /* hardware address of concentrator */
- u16_t sc_session; /* PPPoE session id */
-
- char *sc_service_name; /* if != NULL: requested name of service */
- char *sc_concentrator_name; /* if != NULL: requested concentrator id */
- u8_t *sc_ac_cookie; /* content of AC cookie we must echo back */
- size_t sc_ac_cookie_len; /* length of cookie data */
-#ifdef PPPOE_SERVER
- u8_t *sc_hunique; /* content of host unique we must echo back */
- size_t sc_hunique_len; /* length of host unique */
+#ifndef PPPOE_ERRORSTRING_LEN
+#define PPPOE_ERRORSTRING_LEN 64
#endif
- int sc_padi_retried; /* number of PADI retries already done */
- int sc_padr_retried; /* number of PADR retries already done */
-};
+static char pppoe_error_tmp[PPPOE_ERRORSTRING_LEN];
+
/* input routines */
static void pppoe_dispatch_disc_pkt(struct netif *, struct pbuf *);
@@ -234,24 +137,16 @@ static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *);
static struct pppoe_softc * pppoe_find_softc_by_session(u_int, struct netif *);
static struct pppoe_softc * pppoe_find_softc_by_hunique(u8_t *, size_t, struct netif *);
-static LIST_HEAD(pppoe_softc_head, pppoe_softc) pppoe_softc_list;
-
-int pppoe_hdrlen;
-
-void
-pppoe_init(void)
-{
- pppoe_hdrlen = sizeof(struct eth_hdr) + PPPOE_HEADERLEN;
- LIST_INIT(&pppoe_softc_list);
-}
+/** linked list of created pppoe interfaces */
+static struct pppoe_softc *pppoe_softc_list;
err_t
pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr)
{
struct pppoe_softc *sc;
- sc = mem_malloc(sizeof(struct pppoe_softc));
- if(!sc) {
+ sc = (struct pppoe_softc *)memp_malloc(MEMP_PPPOE_IF);
+ if (sc == NULL) {
*scptr = NULL;
return ERR_MEM;
}
@@ -264,7 +159,9 @@ pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up),
sc->sc_linkStatusCB = linkStatusCB;
sc->sc_ethif = ethif;
- LIST_INSERT_HEAD(&pppoe_softc_list, sc, sc_list);
+ /* put the new interface at the head of the list */
+ sc->next = pppoe_softc_list;
+ pppoe_softc_list = sc;
*scptr = sc;
@@ -274,9 +171,9 @@ pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up),
err_t
pppoe_destroy(struct netif *ifp)
{
- struct pppoe_softc * sc;
+ struct pppoe_softc *sc, *prev = NULL;
- LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
+ for (sc = pppoe_softc_list; sc != NULL; prev = sc, sc = sc->next) {
if (sc->sc_ethif == ifp) {
break;
}
@@ -286,19 +183,24 @@ pppoe_destroy(struct netif *ifp)
return ERR_IF;
}
- tcpip_untimeout(pppoe_timeout, sc);
- LIST_REMOVE(sc, sc_list);
+ sys_untimeout(pppoe_timeout, sc);
+ if (prev == NULL) {
+ /* remove sc from the head of the list */
+ pppoe_softc_list = sc->next;
+ } else {
+ /* remove sc from the list */
+ prev->next = sc->next;
+ }
+#ifdef PPPOE_TODO
if (sc->sc_concentrator_name) {
mem_free(sc->sc_concentrator_name);
}
if (sc->sc_service_name) {
mem_free(sc->sc_service_name);
}
- if (sc->sc_ac_cookie) {
- mem_free(sc->sc_ac_cookie);
- }
- mem_free(sc);
+#endif /* PPPOE_TODO */
+ memp_free(MEMP_PPPOE_IF, sc);
return ERR_OK;
}
@@ -318,7 +220,7 @@ pppoe_find_softc_by_session(u_int session, struct netif *rcvif)
return NULL;
}
- LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
+ for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) {
if (sc->sc_state == PPPOE_STATE_SESSION
&& sc->sc_session == session) {
if (sc->sc_ethif == rcvif) {
@@ -338,7 +240,7 @@ pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif)
{
struct pppoe_softc *sc, *t;
- if (LIST_EMPTY(&pppoe_softc_list)) {
+ if (pppoe_softc_list == NULL) {
return NULL;
}
@@ -347,14 +249,14 @@ pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif)
}
MEMCPY(&t, token, len);
- LIST_FOREACH(sc, &pppoe_softc_list, sc_list) {
+ for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) {
if (sc == t) {
break;
}
}
if (sc == NULL) {
- PPPDEBUG((LOG_DEBUG, "pppoe: alien host unique tag, no session found\n"));
+ PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n"));
return NULL;
}
@@ -373,10 +275,8 @@ pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif)
}
static void
-pppoe_linkstatus_up(void *arg)
+pppoe_linkstatus_up(struct pppoe_softc *sc)
{
- struct pppoe_softc *sc = (struct pppoe_softc*)arg;
-
sc->sc_linkStatusCB(sc->sc_pd, 1);
}
@@ -389,9 +289,8 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
struct pppoe_softc *sc;
const char *err_msg;
char devname[6];
- char *error;
u8_t *ac_cookie;
- size_t ac_cookie_len;
+ u16_t ac_cookie_len;
#ifdef PPPOE_SERVER
u8_t *hunique;
size_t hunique_len;
@@ -439,7 +338,7 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
goto done;
}
if(pb->tot_len == pb->len) {
- pb->tot_len = pb->len = off + plen; /* ignore trailing garbage */
+ pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */
}
tag = 0;
len = 0;
@@ -492,17 +391,11 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
break;
}
if (err_msg) {
- error = NULL;
if (errortag && len) {
- error = mem_malloc(len+1);
- if (error) {
- strncpy(error, (char*)pb->payload + off + sizeof(pt), len);
- error[len-1] = '\0';
- }
- }
- if (error) {
- printf("%s: %s: %s\n", devname, err_msg, error);
- mem_free(error);
+ u16_t error_len = LWIP_MIN(len, sizeof(pppoe_error_tmp)-1);
+ strncpy(pppoe_error_tmp, (char*)pb->payload + off + sizeof(pt), error_len);
+ pppoe_error_tmp[error_len-1] = '\0';
+ printf("%s: %s: %s\n", devname, err_msg, pppoe_error_tmp);
} else {
printf("%s: %s\n", devname, err_msg);
}
@@ -554,9 +447,9 @@ breakbreak:;
sc->sc_state = PPPOE_STATE_PADO_SENT;
pppoe_send_pado(sc);
break;
- #endif /* PPPOE_SERVER */
+#endif /* PPPOE_SERVER */
case PPPOE_CODE_PADR:
- #ifdef PPPOE_SERVER
+#ifdef PPPOE_SERVER
/*
* get sc from ac_cookie if IFF_PASSIVE
*/
@@ -590,16 +483,16 @@ breakbreak:;
}
pppoe_send_pads(sc);
sc->sc_state = PPPOE_STATE_SESSION;
- tcpip_timeout (100, pppoe_linkstatus_up, sc); /* notify upper layers */
+ pppoe_linkstatus_up(sc); /* notify upper layers */
break;
- #else
+#else
/* ignore, we are no access concentrator */
goto done;
- #endif /* PPPOE_SERVER */
+#endif /* PPPOE_SERVER */
case PPPOE_CODE_PADO:
if (sc == NULL) {
/* be quiet if there is not a single pppoe instance */
- if (!LIST_EMPTY(&pppoe_softc_list)) {
+ if (pppoe_softc_list != NULL) {
printf("pppoe: received PADO but could not find request for it\n");
}
goto done;
@@ -609,34 +502,27 @@ breakbreak:;
goto done;
}
if (ac_cookie) {
- if (sc->sc_ac_cookie) {
- mem_free(sc->sc_ac_cookie);
- }
- sc->sc_ac_cookie = mem_malloc(ac_cookie_len);
- if (sc->sc_ac_cookie == NULL) {
- goto done;
- }
sc->sc_ac_cookie_len = ac_cookie_len;
MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len);
}
MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr));
- tcpip_untimeout(pppoe_timeout, sc);
+ sys_untimeout(pppoe_timeout, sc);
sc->sc_padr_retried = 0;
sc->sc_state = PPPOE_STATE_PADR_SENT;
if ((err = pppoe_send_padr(sc)) != 0) {
- PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
+ PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
}
- tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
+ sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
break;
case PPPOE_CODE_PADS:
if (sc == NULL) {
goto done;
}
sc->sc_session = session;
- tcpip_untimeout(pppoe_timeout, sc);
- PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session));
+ sys_untimeout(pppoe_timeout, sc);
+ PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session));
sc->sc_state = PPPOE_STATE_SESSION;
- tcpip_timeout (100, pppoe_linkstatus_up, sc); /* notify upper layers */
+ pppoe_linkstatus_up(sc); /* notify upper layers */
break;
case PPPOE_CODE_PADT:
if (sc == NULL) {
@@ -646,11 +532,11 @@ breakbreak:;
break;
default:
if(sc) {
- printf("%c%c%"U16_F": unknown code (0x%04x) session = 0x%04x\n",
+ printf("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n",
sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num,
- ph->code, session);
+ (u16_t)ph->code, session);
} else {
- printf("pppoe: unknown code (0x%04x) session = 0x%04x\n", ph->code, session);
+ printf("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session);
}
break;
}
@@ -664,7 +550,7 @@ void
pppoe_disc_input(struct netif *netif, struct pbuf *p)
{
/* avoid error messages if there is not a single pppoe instance */
- if (!LIST_EMPTY(&pppoe_softc_list)) {
+ if (pppoe_softc_list != NULL) {
pppoe_dispatch_disc_pkt(netif, p);
} else {
pbuf_free(p);
@@ -686,7 +572,7 @@ pppoe_data_input(struct netif *netif, struct pbuf *pb)
#endif
if (pbuf_header(pb, -(int)sizeof(struct eth_hdr)) != 0) {
/* bail out */
- PPPDEBUG((LOG_ERR, "pppoe_data_input: pbuf_header failed\n"));
+ PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n"));
LINK_STATS_INC(link.lenerr);
goto drop;
}
@@ -726,12 +612,12 @@ pppoe_data_input(struct netif *netif, struct pbuf *pb)
if (pbuf_header(pb, -(int)(PPPOE_HEADERLEN)) != 0) {
/* bail out */
- PPPDEBUG((LOG_ERR, "pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n"));
+ PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n"));
LINK_STATS_INC(link.lenerr);
goto drop;
}
- PPPDEBUG((LOG_DEBUG, "pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n",
+ PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n",
sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num,
pb->len, plen));
@@ -765,7 +651,7 @@ pppoe_output(struct pppoe_softc *sc, struct pbuf *pb)
MEMCPY(ethhdr->dest.addr, sc->sc_dest.addr, sizeof(ethhdr->dest.addr));
MEMCPY(ethhdr->src.addr, ((struct eth_addr *)sc->sc_ethif->hwaddr)->addr, sizeof(ethhdr->src.addr));
- PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n",
+ PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n",
sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype,
sc->sc_state, sc->sc_session,
sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5],
@@ -783,46 +669,59 @@ pppoe_send_padi(struct pppoe_softc *sc)
{
struct pbuf *pb;
u8_t *p;
- int len, l1 = 0, l2 = 0; /* XXX: gcc */
+ int len;
+#ifdef PPPOE_TODO
+ int l1 = 0, l2 = 0; /* XXX: gcc */
+#endif /* PPPOE_TODO */
if (sc->sc_state >PPPOE_STATE_PADI_SENT) {
- PPPDEBUG((LOG_ERR, "ERROR: pppoe_send_padi in state %d", sc->sc_state));
+ PPPDEBUG(LOG_ERR, ("ERROR: pppoe_send_padi in state %d", sc->sc_state));
}
/* calculate length of frame (excluding ethernet header + pppoe header) */
len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */
+#ifdef PPPOE_TODO
if (sc->sc_service_name != NULL) {
- l1 = strlen(sc->sc_service_name);
+ l1 = (int)strlen(sc->sc_service_name);
len += l1;
}
if (sc->sc_concentrator_name != NULL) {
- l2 = strlen(sc->sc_concentrator_name);
+ l2 = (int)strlen(sc->sc_concentrator_name);
len += 2 + 2 + l2;
}
+#endif /* PPPOE_TODO */
+ LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff",
+ sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff);
/* allocate a buffer */
- pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM);
+ pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM);
if (!pb) {
return ERR_MEM;
}
+ LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
/* fill in pkt */
- PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, len);
+ PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len);
PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
+#ifdef PPPOE_TODO
if (sc->sc_service_name != NULL) {
PPPOE_ADD_16(p, l1);
MEMCPY(p, sc->sc_service_name, l1);
p += l1;
- } else {
+ } else
+#endif /* PPPOE_TODO */
+ {
PPPOE_ADD_16(p, 0);
}
+#ifdef PPPOE_TODO
if (sc->sc_concentrator_name != NULL) {
PPPOE_ADD_16(p, PPPOE_TAG_ACNAME);
PPPOE_ADD_16(p, l2);
MEMCPY(p, sc->sc_concentrator_name, l2);
p += l2;
}
+#endif /* PPPOE_TODO */
PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE);
PPPOE_ADD_16(p, sizeof(sc));
MEMCPY(p, &sc, sizeof sc);
@@ -837,7 +736,7 @@ pppoe_timeout(void *arg)
int retry_wait, err;
struct pppoe_softc *sc = (struct pppoe_softc*)arg;
- PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
+ PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
switch (sc->sc_state) {
case PPPOE_STATE_PADI_SENT:
@@ -869,9 +768,9 @@ pppoe_timeout(void *arg)
}
if ((err = pppoe_send_padi(sc)) != 0) {
sc->sc_padi_retried--;
- PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
+ PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
}
- tcpip_timeout(retry_wait, pppoe_timeout, sc);
+ sys_timeout(retry_wait, pppoe_timeout, sc);
break;
case PPPOE_STATE_PADR_SENT:
@@ -881,16 +780,16 @@ pppoe_timeout(void *arg)
sc->sc_state = PPPOE_STATE_PADI_SENT;
sc->sc_padr_retried = 0;
if ((err = pppoe_send_padi(sc)) != 0) {
- PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
+ PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
}
- tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc);
+ sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc);
return;
}
if ((err = pppoe_send_padr(sc)) != 0) {
sc->sc_padr_retried--;
- PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
+ PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
}
- tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
+ sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc);
break;
case PPPOE_STATE_CLOSING:
pppoe_do_disconnect(sc);
@@ -920,8 +819,8 @@ pppoe_connect(struct pppoe_softc *sc)
sc->sc_state = PPPOE_STATE_PADI_SENT;
sc->sc_padr_retried = 0;
err = pppoe_send_padi(sc);
- PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
- tcpip_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc);
+ PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
+ sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc);
return err;
}
@@ -938,7 +837,7 @@ pppoe_disconnect(struct pppoe_softc *sc)
* function and defer disconnecting to the timeout handler.
*/
sc->sc_state = PPPOE_STATE_CLOSING;
- tcpip_timeout(20, pppoe_timeout, sc);
+ sys_timeout(20, pppoe_timeout, sc);
}
static int
@@ -949,17 +848,13 @@ pppoe_do_disconnect(struct pppoe_softc *sc)
if (sc->sc_state < PPPOE_STATE_SESSION) {
err = EBUSY;
} else {
- PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
+ PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
err = pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest);
}
/* cleanup softc */
sc->sc_state = PPPOE_STATE_INITIAL;
MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
- if (sc->sc_ac_cookie) {
- mem_free(sc->sc_ac_cookie);
- sc->sc_ac_cookie = NULL;
- }
sc->sc_ac_cookie_len = 0;
#ifdef PPPOE_SERVER
if (sc->sc_hunique) {
@@ -995,32 +890,43 @@ pppoe_send_padr(struct pppoe_softc *sc)
{
struct pbuf *pb;
u8_t *p;
- size_t len, l1 = 0; /* XXX: gcc */
+ size_t len;
+#ifdef PPPOE_TODO
+ size_t l1 = 0; /* XXX: gcc */
+#endif /* PPPOE_TODO */
if (sc->sc_state != PPPOE_STATE_PADR_SENT) {
return ERR_CONN;
}
len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */
+#ifdef PPPOE_TODO
if (sc->sc_service_name != NULL) { /* service name tag maybe empty */
l1 = strlen(sc->sc_service_name);
len += l1;
}
+#endif /* PPPOE_TODO */
if (sc->sc_ac_cookie_len > 0) {
len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */
}
- pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM);
+ LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff",
+ sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff);
+ pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM);
if (!pb) {
return ERR_MEM;
}
+ LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len);
PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
+#ifdef PPPOE_TODO
if (sc->sc_service_name != NULL) {
PPPOE_ADD_16(p, l1);
MEMCPY(p, sc->sc_service_name, l1);
p += l1;
- } else {
+ } else
+#endif /* PPPOE_TODO */
+ {
PPPOE_ADD_16(p, 0);
}
if (sc->sc_ac_cookie_len > 0) {
@@ -1049,9 +955,10 @@ pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest)
if (!pb) {
return ERR_MEM;
}
+ LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
ethhdr = (struct eth_hdr *)pb->payload;
- ethhdr->type = htons(ETHTYPE_PPPOEDISC);
+ ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC);
MEMCPY(ethhdr->dest.addr, dest, sizeof(ethhdr->dest.addr));
MEMCPY(ethhdr->src.addr, ((struct eth_addr *)outgoing_if->hwaddr)->addr, sizeof(ethhdr->src.addr));
@@ -1087,6 +994,7 @@ pppoe_send_pado(struct pppoe_softc *sc)
if (!pb) {
return ERR_MEM;
}
+ LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len);
PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE);
@@ -1123,6 +1031,7 @@ pppoe_send_pads(struct pppoe_softc *sc)
if (!pb) {
return ERR_MEM;
}
+ LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len);
p = (u8_t*)pb->payload + sizeof (struct eth_hdr);
PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len);
PPPOE_ADD_16(p, PPPOE_TAG_SNAME);
@@ -1158,7 +1067,7 @@ pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb)
/* make room for Ethernet header - should not fail */
if (pbuf_header(pb, sizeof(struct eth_hdr) + PPPOE_HEADERLEN) != 0) {
/* bail out */
- PPPDEBUG((LOG_ERR, "pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
+ PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
LINK_STATS_INC(link.lenerr);
pbuf_free(pb);
return ERR_BUF;
@@ -1204,8 +1113,8 @@ pppoe_clear_softc(struct pppoe_softc *sc, const char *message)
LWIP_UNUSED_ARG(message);
/* stop timer */
- tcpip_untimeout(pppoe_timeout, sc);
- PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message));
+ sys_untimeout(pppoe_timeout, sc);
+ PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message));
/* fix our state */
sc->sc_state = PPPOE_STATE_INITIAL;
@@ -1215,10 +1124,6 @@ pppoe_clear_softc(struct pppoe_softc *sc, const char *message)
/* clean up softc */
MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
- if (sc->sc_ac_cookie) {
- mem_free(sc->sc_ac_cookie);
- sc->sc_ac_cookie = NULL;
- }
sc->sc_ac_cookie_len = 0;
sc->sc_session = 0;
}
diff --git a/core/lwip/src/netif/ppp/pppdebug.h b/core/lwip/src/netif/ppp/pppdebug.h
index 6253863c..81349971 100644
--- a/core/lwip/src/netif/ppp/pppdebug.h
+++ b/core/lwip/src/netif/ppp/pppdebug.h
@@ -36,50 +36,37 @@
#ifndef PPPDEBUG_H
#define PPPDEBUG_H
-/************************
-*** PUBLIC DATA TYPES ***
-************************/
/* Trace levels. */
-typedef enum {
-LOG_CRITICAL = 0,
-LOG_ERR = 1,
-LOG_NOTICE = 2,
-LOG_WARNING = 3,
-LOG_INFO = 5,
-LOG_DETAIL = 6,
-LOG_DEBUG = 7
-} LogCodes;
+#define LOG_CRITICAL (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE)
+#define LOG_ERR (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE)
+#define LOG_NOTICE (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING)
+#define LOG_WARNING (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING)
+#define LOG_INFO (PPP_DEBUG)
+#define LOG_DETAIL (PPP_DEBUG)
+#define LOG_DEBUG (PPP_DEBUG)
-/***********************
-*** PUBLIC FUNCTIONS ***
-***********************/
-/*
- * ppp_trace - a form of printf to send tracing information to stderr
- */
-void ppp_trace(int level, const char *format,...);
-
#define TRACELCP PPP_DEBUG
#if PPP_DEBUG
-#define AUTHDEBUG(a) ppp_trace a
-#define IPCPDEBUG(a) ppp_trace a
-#define UPAPDEBUG(a) ppp_trace a
-#define LCPDEBUG(a) ppp_trace a
-#define FSMDEBUG(a) ppp_trace a
-#define CHAPDEBUG(a) ppp_trace a
-#define PPPDEBUG(a) ppp_trace a
+#define AUTHDEBUG(a, b) LWIP_DEBUGF(a, b)
+#define IPCPDEBUG(a, b) LWIP_DEBUGF(a, b)
+#define UPAPDEBUG(a, b) LWIP_DEBUGF(a, b)
+#define LCPDEBUG(a, b) LWIP_DEBUGF(a, b)
+#define FSMDEBUG(a, b) LWIP_DEBUGF(a, b)
+#define CHAPDEBUG(a, b) LWIP_DEBUGF(a, b)
+#define PPPDEBUG(a, b) LWIP_DEBUGF(a, b)
#else /* PPP_DEBUG */
-#define AUTHDEBUG(a)
-#define IPCPDEBUG(a)
-#define UPAPDEBUG(a)
-#define LCPDEBUG(a)
-#define FSMDEBUG(a)
-#define CHAPDEBUG(a)
-#define PPPDEBUG(a)
+#define AUTHDEBUG(a, b)
+#define IPCPDEBUG(a, b)
+#define UPAPDEBUG(a, b)
+#define LCPDEBUG(a, b)
+#define FSMDEBUG(a, b)
+#define CHAPDEBUG(a, b)
+#define PPPDEBUG(a, b)
#endif /* PPP_DEBUG */
diff --git a/core/lwip/src/netif/ppp/randm.c b/core/lwip/src/netif/ppp/randm.c
index 83c41741..2f35caf6 100644
--- a/core/lwip/src/netif/ppp/randm.c
+++ b/core/lwip/src/netif/ppp/randm.c
@@ -85,7 +85,7 @@ avChurnRand(char *randData, u32_t randLen)
{
MD5_CTX md5;
- /* ppp_trace(LOG_INFO, "churnRand: %u@%P\n", randLen, randData); */
+ /* LWIP_DEBUGF(LOG_INFO, ("churnRand: %u@%P\n", randLen, randData)); */
MD5Init(&md5);
MD5Update(&md5, (u_char *)randPool, sizeof(randPool));
if (randData) {
@@ -100,7 +100,7 @@ avChurnRand(char *randData, u32_t randLen)
MD5Update(&md5, (u_char *)&sysData, sizeof(sysData));
}
MD5Final((u_char *)randPool, &md5);
-/* ppp_trace(LOG_INFO, "churnRand: -> 0\n"); */
+/* LWIP_DEBUGF(LOG_INFO, ("churnRand: -> 0\n")); */
}
/*
diff --git a/core/lwip/src/netif/ppp/vj.c b/core/lwip/src/netif/ppp/vj.c
index 694b7027..b7f2d54c 100644
--- a/core/lwip/src/netif/ppp/vj.c
+++ b/core/lwip/src/netif/ppp/vj.c
@@ -47,18 +47,10 @@
#define INCR(counter)
#endif
-#if defined(NO_CHAR_BITFIELDS)
-#define getip_hl(base) ((base).ip_hl_v&0xf)
-#define getth_off(base) (((base).th_x2_off&0xf0)>>4)
-#else
-#define getip_hl(base) ((base).ip_hl)
-#define getth_off(base) ((base).th_off)
-#endif
-
void
vj_compress_init(struct vjcompress *comp)
{
- register u_int i;
+ register u_char i;
register struct cstate *tstate = comp->tstate;
#if MAX_SLOTS == 0
@@ -86,21 +78,21 @@ vj_compress_init(struct vjcompress *comp)
#define ENCODE(n) { \
if ((u_short)(n) >= 256) { \
*cp++ = 0; \
- cp[1] = (n); \
- cp[0] = (n) >> 8; \
+ cp[1] = (u_char)(n); \
+ cp[0] = (u_char)((n) >> 8); \
cp += 2; \
} else { \
- *cp++ = (n); \
+ *cp++ = (u_char)(n); \
} \
}
#define ENCODEZ(n) { \
if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \
*cp++ = 0; \
- cp[1] = (n); \
- cp[0] = (n) >> 8; \
+ cp[1] = (u_char)(n); \
+ cp[0] = (u_char)((n) >> 8); \
cp += 2; \
} else { \
- *cp++ = (n); \
+ *cp++ = (u_char)(n); \
} \
}
@@ -145,11 +137,11 @@ vj_compress_init(struct vjcompress *comp)
u_int
vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
{
- register struct ip *ip = (struct ip *)pb->payload;
+ register struct ip_hdr *ip = (struct ip_hdr *)pb->payload;
register struct cstate *cs = comp->last_cs->cs_next;
- register u_short hlen = getip_hl(*ip);
- register struct tcphdr *oth;
- register struct tcphdr *th;
+ register u_short hlen = IPH_HL(ip);
+ register struct tcp_hdr *oth;
+ register struct tcp_hdr *th;
register u_short deltaS, deltaA;
register u_long deltaL;
register u_int changes = 0;
@@ -159,7 +151,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
/*
* Check that the packet is IP proto TCP.
*/
- if (ip->ip_p != IPPROTO_TCP) {
+ if (IPH_PROTO(ip) != IP_PROTO_TCP) {
return (TYPE_IP);
}
@@ -168,11 +160,11 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
* `compressible' (i.e., ACK isn't set or some other control bit is
* set).
*/
- if ((ip->ip_off & htons(0x3fff)) || pb->tot_len < 40) {
+ if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || pb->tot_len < 40) {
return (TYPE_IP);
}
- th = (struct tcphdr *)&((long *)ip)[hlen];
- if ((th->th_flags & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) {
+ th = (struct tcp_hdr *)&((long *)ip)[hlen];
+ if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) {
return (TYPE_IP);
}
/*
@@ -183,9 +175,9 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
* again & we don't have to do any reordering if it's used.
*/
INCR(vjs_packets);
- if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr
- || ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr
- || *(long *)th != ((long *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) {
+ if (!ip_addr_cmp(&ip->src, &cs->cs_ip.src)
+ || !ip_addr_cmp(&ip->dest, &cs->cs_ip.dest)
+ || *(long *)th != ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) {
/*
* Wasn't the first -- search for it.
*
@@ -204,9 +196,9 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
do {
lcs = cs; cs = cs->cs_next;
INCR(vjs_searches);
- if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
- && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
- && *(long *)th == ((long *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) {
+ if (ip_addr_cmp(&ip->src, &cs->cs_ip.src)
+ && ip_addr_cmp(&ip->dest, &cs->cs_ip.dest)
+ && *(long *)th == ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) {
goto found;
}
} while (cs != lastcs);
@@ -221,7 +213,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
*/
INCR(vjs_misses);
comp->last_cs = lcs;
- hlen += getth_off(*th);
+ hlen += TCPH_OFFSET(th);
hlen <<= 2;
/* Check that the IP/TCP headers are contained in the first buffer. */
if (hlen > pb->len) {
@@ -242,13 +234,13 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
}
}
- oth = (struct tcphdr *)&((long *)&cs->cs_ip)[hlen];
+ oth = (struct tcp_hdr *)&((long *)&cs->cs_ip)[hlen];
deltaS = hlen;
- hlen += getth_off(*th);
+ hlen += TCPH_OFFSET(th);
hlen <<= 2;
/* Check that the IP/TCP headers are contained in the first buffer. */
if (hlen > pb->len) {
- PPPDEBUG((LOG_INFO, "vj_compress_tcp: header len %d spans buffers\n", hlen));
+ PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen));
return (TYPE_IP);
}
@@ -266,9 +258,9 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0]
|| ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3]
|| ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4]
- || getth_off(*th) != getth_off(*oth)
+ || TCPH_OFFSET(th) != TCPH_OFFSET(oth)
|| (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2))
- || (getth_off(*th) > 5 && BCMP(th + 1, oth + 1, (getth_off(*th) - 5) << 2))) {
+ || (TCPH_OFFSET(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_OFFSET(th) - 5) << 2))) {
goto uncompressed;
}
@@ -278,11 +270,11 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
* ack, seq (the order minimizes the number of temporaries
* needed in this section of code).
*/
- if (th->th_flags & TCP_URG) {
- deltaS = ntohs(th->th_urp);
+ if (TCPH_FLAGS(th) & TCP_URG) {
+ deltaS = ntohs(th->urgp);
ENCODEZ(deltaS);
changes |= NEW_U;
- } else if (th->th_urp != oth->th_urp) {
+ } else if (th->urgp != oth->urgp) {
/* argh! URG not set but urp changed -- a sensible
* implementation should never do this but RFC793
* doesn't prohibit the change so we have to deal
@@ -290,12 +282,12 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
goto uncompressed;
}
- if ((deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win))) != 0) {
+ if ((deltaS = (u_short)(ntohs(th->wnd) - ntohs(oth->wnd))) != 0) {
ENCODE(deltaS);
changes |= NEW_W;
}
- if ((deltaL = ntohl(th->th_ack) - ntohl(oth->th_ack)) != 0) {
+ if ((deltaL = ntohl(th->ackno) - ntohl(oth->ackno)) != 0) {
if (deltaL > 0xffff) {
goto uncompressed;
}
@@ -304,7 +296,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
changes |= NEW_A;
}
- if ((deltaL = ntohl(th->th_seq) - ntohl(oth->th_seq)) != 0) {
+ if ((deltaL = ntohl(th->seqno) - ntohl(oth->seqno)) != 0) {
if (deltaL > 0xffff) {
goto uncompressed;
}
@@ -323,8 +315,8 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
* retransmitted ack or window probe. Send it uncompressed
* in case the other side missed the compressed version.
*/
- if (ip->ip_len != cs->cs_ip.ip_len &&
- ntohs(cs->cs_ip.ip_len) == hlen) {
+ if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) &&
+ ntohs(IPH_LEN(&cs->cs_ip)) == hlen) {
break;
}
@@ -339,7 +331,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
goto uncompressed;
case NEW_S|NEW_A:
- if (deltaS == deltaA && deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
+ if (deltaS == deltaA && deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) {
/* special case for echoed terminal traffic */
changes = SPECIAL_I;
cp = new_seq;
@@ -347,7 +339,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
break;
case NEW_S:
- if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
+ if (deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) {
/* special case for data xfer */
changes = SPECIAL_D;
cp = new_seq;
@@ -355,19 +347,19 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
break;
}
- deltaS = (u_short)(ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id));
+ deltaS = (u_short)(ntohs(IPH_ID(ip)) - ntohs(IPH_ID(&cs->cs_ip)));
if (deltaS != 1) {
ENCODEZ(deltaS);
changes |= NEW_I;
}
- if (th->th_flags & TCP_PSH) {
+ if (TCPH_FLAGS(th) & TCP_PSH) {
changes |= TCP_PUSH_BIT;
}
/*
* Grab the cksum before we overwrite it below. Then update our
* state with this packet's header.
*/
- deltaA = ntohs(th->th_sum);
+ deltaA = ntohs(th->chksum);
BCOPY(ip, &cs->cs_ip, hlen);
/*
@@ -388,7 +380,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
LWIP_ASSERT("pbuf_header failed\n", 0);
}
cp = (u_char *)pb->payload;
- *cp++ = changes | NEW_C;
+ *cp++ = (u_char)(changes | NEW_C);
*cp++ = cs->cs_id;
} else {
hlen -= deltaS + 3;
@@ -397,10 +389,10 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
LWIP_ASSERT("pbuf_header failed\n", 0);
}
cp = (u_char *)pb->payload;
- *cp++ = changes;
+ *cp++ = (u_char)changes;
}
- *cp++ = deltaA >> 8;
- *cp++ = deltaA;
+ *cp++ = (u_char)(deltaA >> 8);
+ *cp++ = (u_char)deltaA;
BCOPY(new_seq, cp, deltaS);
INCR(vjs_compressed);
return (TYPE_COMPRESSED_TCP);
@@ -412,7 +404,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
*/
uncompressed:
BCOPY(ip, &cs->cs_ip, hlen);
- ip->ip_p = cs->cs_id;
+ IPH_PROTO_SET(ip, cs->cs_id);
comp->last_xmit = cs->cs_id;
return (TYPE_UNCOMPRESSED_TCP);
}
@@ -436,26 +428,26 @@ vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp)
{
register u_int hlen;
register struct cstate *cs;
- register struct ip *ip;
+ register struct ip_hdr *ip;
- ip = (struct ip *)nb->payload;
- hlen = getip_hl(*ip) << 2;
- if (ip->ip_p >= MAX_SLOTS
- || hlen + sizeof(struct tcphdr) > nb->len
- || (hlen += getth_off(*((struct tcphdr *)&((char *)ip)[hlen])) << 2)
+ ip = (struct ip_hdr *)nb->payload;
+ hlen = IPH_HL(ip) << 2;
+ if (IPH_PROTO(ip) >= MAX_SLOTS
+ || hlen + sizeof(struct tcp_hdr) > nb->len
+ || (hlen += TCPH_OFFSET(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2)
> nb->len
|| hlen > MAX_HDR) {
- PPPDEBUG((LOG_INFO, "vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n",
- ip->ip_p, hlen, nb->len));
+ PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n",
+ IPH_PROTO(ip), hlen, nb->len));
comp->flags |= VJF_TOSS;
INCR(vjs_errorin);
return -1;
}
- cs = &comp->rstate[comp->last_recv = ip->ip_p];
+ cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)];
comp->flags &=~ VJF_TOSS;
- ip->ip_p = IPPROTO_TCP;
+ IPH_PROTO_SET(ip, IP_PROTO_TCP);
BCOPY(ip, &cs->cs_ip, hlen);
- cs->cs_hlen = hlen;
+ cs->cs_hlen = (u_short)hlen;
INCR(vjs_uncompressedin);
return 0;
}
@@ -472,7 +464,7 @@ int
vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp)
{
u_char *cp;
- struct tcphdr *th;
+ struct tcp_hdr *th;
struct cstate *cs;
u_short *bp;
struct pbuf *n0 = *nb;
@@ -488,7 +480,7 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp)
* If we have a good state index, clear the 'discard' flag.
*/
if (*cp >= MAX_SLOTS) {
- PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: bad cid=%d\n", *cp));
+ PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp));
goto bad;
}
@@ -501,63 +493,63 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp)
* explicit state index, we have to toss the packet.
*/
if (comp->flags & VJF_TOSS) {
- PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: tossing\n"));
+ PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n"));
INCR(vjs_tossed);
return (-1);
}
}
cs = &comp->rstate[comp->last_recv];
- hlen = getip_hl(cs->cs_ip) << 2;
- th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];
- th->th_sum = htons((*cp << 8) | cp[1]);
+ hlen = IPH_HL(&cs->cs_ip) << 2;
+ th = (struct tcp_hdr *)&((u_char *)&cs->cs_ip)[hlen];
+ th->chksum = htons((*cp << 8) | cp[1]);
cp += 2;
if (changes & TCP_PUSH_BIT) {
- th->th_flags |= TCP_PSH;
+ TCPH_SET_FLAG(th, TCP_PSH);
} else {
- th->th_flags &=~ TCP_PSH;
+ TCPH_UNSET_FLAG(th, TCP_PSH);
}
switch (changes & SPECIALS_MASK) {
case SPECIAL_I:
{
- register u32_t i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
+ register u32_t i = ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen;
/* some compilers can't nest inline assembler.. */
- tmp = ntohl(th->th_ack) + i;
- th->th_ack = htonl(tmp);
- tmp = ntohl(th->th_seq) + i;
- th->th_seq = htonl(tmp);
+ tmp = ntohl(th->ackno) + i;
+ th->ackno = htonl(tmp);
+ tmp = ntohl(th->seqno) + i;
+ th->seqno = htonl(tmp);
}
break;
case SPECIAL_D:
/* some compilers can't nest inline assembler.. */
- tmp = ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
- th->th_seq = htonl(tmp);
+ tmp = ntohl(th->seqno) + ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen;
+ th->seqno = htonl(tmp);
break;
default:
if (changes & NEW_U) {
- th->th_flags |= TCP_URG;
- DECODEU(th->th_urp);
+ TCPH_SET_FLAG(th, TCP_URG);
+ DECODEU(th->urgp);
} else {
- th->th_flags &=~ TCP_URG;
+ TCPH_UNSET_FLAG(th, TCP_URG);
}
if (changes & NEW_W) {
- DECODES(th->th_win);
+ DECODES(th->wnd);
}
if (changes & NEW_A) {
- DECODEL(th->th_ack);
+ DECODEL(th->ackno);
}
if (changes & NEW_S) {
- DECODEL(th->th_seq);
+ DECODEL(th->seqno);
}
break;
}
if (changes & NEW_I) {
- DECODES(cs->cs_ip.ip_id);
+ DECODES(cs->cs_ip._id);
} else {
- cs->cs_ip.ip_id = ntohs(cs->cs_ip.ip_id) + 1;
- cs->cs_ip.ip_id = htons(cs->cs_ip.ip_id);
+ IPH_ID_SET(&cs->cs_ip, ntohs(IPH_ID(&cs->cs_ip)) + 1);
+ IPH_ID_SET(&cs->cs_ip, htons(IPH_ID(&cs->cs_ip)));
}
/*
@@ -571,27 +563,27 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp)
* We must have dropped some characters (crc should detect
* this but the old slip framing won't)
*/
- PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: head buffer %d too short %d\n",
+ PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n",
n0->len, vjlen));
goto bad;
}
#if BYTE_ORDER == LITTLE_ENDIAN
tmp = n0->tot_len - vjlen + cs->cs_hlen;
- cs->cs_ip.ip_len = htons(tmp);
+ IPH_LEN_SET(&cs->cs_ip, htons((u_short)tmp));
#else
- cs->cs_ip.ip_len = htons(n0->tot_len - vjlen + cs->cs_hlen);
+ IPH_LEN_SET(&cs->cs_ip, htons(n0->tot_len - vjlen + cs->cs_hlen));
#endif
/* recompute the ip header checksum */
bp = (u_short *) &cs->cs_ip;
- cs->cs_ip.ip_sum = 0;
+ IPH_CHKSUM_SET(&cs->cs_ip, 0);
for (tmp = 0; hlen > 0; hlen -= 2) {
tmp += *bp++;
}
tmp = (tmp & 0xffff) + (tmp >> 16);
tmp = (tmp & 0xffff) + (tmp >> 16);
- cs->cs_ip.ip_sum = (u_short)(~tmp);
+ IPH_CHKSUM_SET(&cs->cs_ip, (u_short)(~tmp));
/* Remove the compressed header and prepend the uncompressed header. */
if(pbuf_header(n0, -((s16_t)(vjlen)))) {
@@ -606,7 +598,7 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp)
np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL);
if(!np) {
- PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: realign failed\n"));
+ PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n"));
goto bad;
}
@@ -636,7 +628,7 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp)
LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE);
np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL);
if(!np) {
- PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: prepend failed\n"));
+ PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n"));
goto bad;
}
pbuf_cat(np, n0);
diff --git a/core/lwip/src/netif/ppp/vj.h b/core/lwip/src/netif/ppp/vj.h
index b9617da4..fad12136 100644
--- a/core/lwip/src/netif/ppp/vj.h
+++ b/core/lwip/src/netif/ppp/vj.h
@@ -1,7 +1,7 @@
/*
* Definitions for tcp compression routines.
*
- * $Id: vj.h,v 1.5 2007/12/19 20:47:23 fbernon Exp $
+ * $Id: vj.h,v 1.7 2010/02/22 17:52:09 goldsimon Exp $
*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved.
@@ -25,7 +25,8 @@
#ifndef VJ_H
#define VJ_H
-#include "vjbsdhdr.h"
+#include "lwip/ip.h"
+#include "lwip/tcp_impl.h"
#define MAX_SLOTS 16 /* must be > 2 and < 256 */
#define MAX_HDR 128
@@ -108,7 +109,7 @@ struct cstate {
u_char cs_filler;
union {
char csu_hdr[MAX_HDR];
- struct ip csu_ip; /* ip/tcp hdr from most recent packet */
+ struct ip_hdr csu_ip; /* ip/tcp hdr from most recent packet */
} vjcs_u;
};
#define cs_ip vjcs_u.csu_ip
diff --git a/core/lwip/src/netif/ppp/vjbsdhdr.h b/core/lwip/src/netif/ppp/vjbsdhdr.h
deleted file mode 100644
index f4626761..00000000
--- a/core/lwip/src/netif/ppp/vjbsdhdr.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef VJBSDHDR_H
-#define VJBSDHDR_H
-
-#include "lwip/tcp.h"
-
-/*
- * Structure of an internet header, naked of options.
- *
- * We declare ip_len and ip_off to be short, rather than u_short
- * pragmatically since otherwise unsigned comparisons can result
- * against negative integers quite easily, and fail in subtle ways.
- */
-PACK_STRUCT_BEGIN
-struct ip
-{
-#if defined(NO_CHAR_BITFIELDS)
- u_char ip_hl_v; /* bug in GCC for mips means the bitfield stuff will sometimes break - so we use a char for both and get round it with macro's instead... */
-#else
-#if BYTE_ORDER == LITTLE_ENDIAN
- unsigned ip_hl:4, /* header length */
- ip_v :4; /* version */
-#elif BYTE_ORDER == BIG_ENDIAN
- unsigned ip_v :4, /* version */
- ip_hl:4; /* header length */
-#else
- COMPLAIN - NO BYTE ORDER SELECTED!
-#endif
-#endif
- u_char ip_tos; /* type of service */
- u_short ip_len; /* total length */
- u_short ip_id; /* identification */
- u_short ip_off; /* fragment offset field */
-#define IP_DF 0x4000 /* dont fragment flag */
-#define IP_MF 0x2000 /* more fragments flag */
-#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
- u_char ip_ttl; /* time to live */
- u_char ip_p; /* protocol */
- u_short ip_sum; /* checksum */
- struct in_addr ip_src,ip_dst; /* source and dest address */
-};
-PACK_STRUCT_END
-
-typedef u32_t tcp_seq;
-
-/*
- * TCP header.
- * Per RFC 793, September, 1981.
- */
-PACK_STRUCT_BEGIN
-struct tcphdr
-{
- u_short th_sport; /* source port */
- u_short th_dport; /* destination port */
- tcp_seq th_seq; /* sequence number */
- tcp_seq th_ack; /* acknowledgement number */
-#if defined(NO_CHAR_BITFIELDS)
- u_char th_x2_off;
-#else
-#if BYTE_ORDER == LITTLE_ENDIAN
- unsigned th_x2 :4, /* (unused) */
- th_off:4; /* data offset */
-#endif
-#if BYTE_ORDER == BIG_ENDIAN
- unsigned th_off:4, /* data offset */
- th_x2 :4; /* (unused) */
-#endif
-#endif
- u_char th_flags;
- u_short th_win; /* window */
- u_short th_sum; /* checksum */
- u_short th_urp; /* urgent pointer */
-};
-PACK_STRUCT_END
-
-#endif /* VJBSDHDR_H */
diff --git a/core/lwip/src/netif/slipif.c b/core/lwip/src/netif/slipif.c
index 089d2d3e..c19333dd 100644
--- a/core/lwip/src/netif/slipif.c
+++ b/core/lwip/src/netif/slipif.c
@@ -88,7 +88,7 @@ struct slipif_priv {
* @return always returns ERR_OK since the serial layer does not provide return values
*/
err_t
-slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
+slipif_output(struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr)
{
struct slipif_priv *priv;
struct pbuf *q;