diff -Nru lwip-2.0.3/debian/changelog lwip-2.0.3/debian/changelog --- lwip-2.0.3/debian/changelog 2018-06-10 22:47:22.000000000 +0000 +++ lwip-2.0.3/debian/changelog 2018-11-03 23:25:58.000000000 +0000 @@ -1,3 +1,16 @@ +lwip (2.0.3-3) unstable; urgency=medium + + [ Samuel Thibault ] + * Mark liblwip-doc Multi-Arch: foreign. + * copyright: Make some licence names more precise. + + [ Joan Lledó ] + * Update patches: Fixing interruptibility and thread safety. Convert to DOS + format to mach lwip sources. + * getpeername_dual: Cherry-pick upstream fix for dual-stack sockets. + + -- Samuel Thibault Sun, 04 Nov 2018 00:25:58 +0100 + lwip (2.0.3-2) unstable; urgency=medium * Fix shipping lwip/priv/{tcp,tcpip}_priv.h. diff -Nru lwip-2.0.3/debian/control lwip-2.0.3/debian/control --- lwip-2.0.3/debian/control 2018-04-30 23:56:27.000000000 +0000 +++ lwip-2.0.3/debian/control 2018-07-17 08:03:55.000000000 +0000 @@ -46,6 +46,7 @@ Package: liblwip-doc Section: doc Architecture: all +Multi-Arch: foreign Depends: ${misc:Depends} Description: small implementation of the TCP/IP protocol suite - documentation lwIP is a small independent implementation of the TCP/IPv4/IPv6 protocol diff -Nru lwip-2.0.3/debian/copyright lwip-2.0.3/debian/copyright --- lwip-2.0.3/debian/copyright 2018-05-01 00:05:50.000000000 +0000 +++ lwip-2.0.3/debian/copyright 2018-11-03 23:25:58.000000000 +0000 @@ -29,7 +29,7 @@ 2015 Dirk Ziegelmeier 2016 Erik Andersson 2016 Elias Oenal. -License: BSD +License: BSD-3-Clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: . @@ -149,7 +149,7 @@ Files: src/include/netif/ppp/chap_ms.h src/include/netif/ppp/chap_ms.c src/netif/ppp/pppcrypt.c src/include/netif/ppp/pppcrypt.h Copyright: 1995 Eric Rosenquist. -License: BSD +License: BSD-3-Clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -245,7 +245,7 @@ Files: src/include/netif/ppp/ecp.h Copyright: 2002 Google, Inc. 1994-2002 Paul Mackerras. All rights reserved. -License: BSD +License: BSD-3-Clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -272,7 +272,7 @@ Files: src/netif/ppp/eui64.c src/include/netif/ppp/eui64.h Copyright: 1999 Tommi Komulainen. -License: BSD +License: BSD-4-Clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -304,7 +304,7 @@ Files: src/netif/ppp/fsm.c src/include/netif/ppp/fsm.h src/netif/ppp/ipcp.c src/include/netif/ppp/ipcp.h src/netif/ppp/lcp.c src/include/netif/ppp/lcp.h src/netif/ppp/upap.c src/include/netif/ppp/upap.h Copyright: 1984-2000 Carnegie Mellon University. -License: BSD +License: BSD-4-Clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -345,7 +345,7 @@ Copyright: 1999 Tommi Komulainen. 1995-1999 Francis.Dupont@inria.fr, INRIA Rocquencourt, Alain.Durand@imag.fr, IMAG, Jean-Luc.Richier@imag.fr, IMAG-LSR. 1984-2000 Carnegie Mellon University. All rights reserved. -License: BSD +License: BSD-4-Clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -473,7 +473,7 @@ Copyright: 1984-2000 Carnegie Mellon University. All rights reserved. 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 1998 by Global Election Systems Inc. -License: BSD +License: BSD-4-Clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -530,7 +530,7 @@ Files: src/netif/ppp/mppe.c Copyright: 2002,2003,2004 Google, Inc. -License: BSD +License: ISC Permission to use, copy, modify, and distribute this software and its documentation is hereby granted, provided that the above copyright notice appears in all copies. This software is provided without any @@ -538,7 +538,7 @@ Files: src/include/netif/ppp/mppe.h Copyright: 2008 Paul Mackerras. -License: BSD +License: BSD-4-Clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff -Nru lwip-2.0.3/debian/patches/bug-36167 lwip-2.0.3/debian/patches/bug-36167 --- lwip-2.0.3/debian/patches/bug-36167 2018-04-30 23:15:05.000000000 +0000 +++ lwip-2.0.3/debian/patches/bug-36167 2018-08-28 21:27:25.000000000 +0000 @@ -1,10 +1,8 @@ Already upstream -diff --git a/src/core/tcp.c b/src/core/tcp.c -index 7103a52..ccfa3c1 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c -@@ -804,7 +804,7 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len) +@@ -804,7 +804,7 @@ pcb->rcv_wnd = TCP_WND_MAX(pcb); } else if (pcb->rcv_wnd == 0) { /* rcv_wnd overflowed */ @@ -13,11 +11,9 @@ /* In passive close, we allow this, since the FIN bit is added to rcv_wnd by the stack itself, since it is not mandatory for an application to call tcp_recved() for the FIN bit, but e.g. the netconn API does so. */ -diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h -index 3845b9f..fb7fa17 100644 --- a/src/include/lwip/tcp.h +++ b/src/include/lwip/tcp.h -@@ -424,6 +424,9 @@ const char* tcp_debug_state_str(enum tcp_state s); +@@ -424,6 +424,9 @@ /* for compatibility with older implementation */ #define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6) diff -Nru lwip-2.0.3/debian/patches/errno lwip-2.0.3/debian/patches/errno --- lwip-2.0.3/debian/patches/errno 2018-04-30 23:07:15.000000000 +0000 +++ lwip-2.0.3/debian/patches/errno 2018-08-28 21:27:25.000000000 +0000 @@ -1,10 +1,8 @@ Already upstream -Index: lwip/src/api/sockets.c -=================================================================== ---- lwip.orig/src/api/sockets.c -+++ lwip/src/api/sockets.c -@@ -213,7 +213,7 @@ struct lwip_sock { +--- a/src/api/sockets.c ++++ b/src/api/sockets.c +@@ -223,7 +223,7 @@ /** error happened for this socket, set by event_callback(), tested by select */ u16_t errevent; /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */ @@ -13,7 +11,7 @@ /** counter of how many threads are waiting for this socket using select */ SELWAIT_T select_waiting; }; -@@ -299,7 +299,7 @@ static volatile int select_cb_ctr; +@@ -309,7 +309,7 @@ #define sock_set_errno(sk, e) do { \ const int sockerr = (e); \ @@ -22,7 +20,7 @@ set_errno(sockerr); \ } while (0) -@@ -309,8 +309,8 @@ static void event_callback(struct netcon +@@ -319,8 +319,8 @@ static void lwip_getsockopt_callback(void *arg); static void lwip_setsockopt_callback(void *arg); #endif @@ -33,7 +31,7 @@ #if LWIP_IPV4 && LWIP_IPV6 static void -@@ -1792,7 +1792,7 @@ lwip_getsockname(int s, struct sockaddr +@@ -1804,7 +1804,7 @@ int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) { @@ -42,7 +40,7 @@ struct lwip_sock *sock = get_socket(s); #if !LWIP_TCPIP_CORE_LOCKING LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); -@@ -1887,10 +1887,10 @@ lwip_getsockopt_callback(void *arg) +@@ -1899,10 +1899,10 @@ /** lwip_getsockopt_impl: the actual implementation of getsockopt: * same argument as lwip_getsockopt, either called directly or through callback */ @@ -55,7 +53,7 @@ struct lwip_sock *sock = tryget_socket(s); if (!sock) { return EBADF; -@@ -2198,7 +2198,7 @@ lwip_getsockopt_impl(int s, int level, i +@@ -2210,7 +2210,7 @@ int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) { @@ -64,7 +62,7 @@ struct lwip_sock *sock = get_socket(s); #if !LWIP_TCPIP_CORE_LOCKING LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); -@@ -2288,10 +2288,10 @@ lwip_setsockopt_callback(void *arg) +@@ -2300,10 +2300,10 @@ /** lwip_setsockopt_impl: the actual implementation of setsockopt: * same argument as lwip_setsockopt, either called directly or through callback */ diff -Nru lwip-2.0.3/debian/patches/getpeername_dual lwip-2.0.3/debian/patches/getpeername_dual --- lwip-2.0.3/debian/patches/getpeername_dual 1970-01-01 00:00:00.000000000 +0000 +++ lwip-2.0.3/debian/patches/getpeername_dual 2018-08-31 09:53:36.000000000 +0000 @@ -0,0 +1,13 @@ +cherry-picked from upstream d9a738 + +--- a/src/api/sockets.c ++++ b/src/api/sockets.c +@@ -123,7 +123,7 @@ + ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \ + (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type)))) + #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \ +- if (IP_IS_V6(ipaddr)) { \ ++ if (((ipaddr) && IP_IS_ANY_TYPE_VAL(*ipaddr)) || IP_IS_V6(ipaddr)) { \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \ + } else { \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \ diff -Nru lwip-2.0.3/debian/patches/max_sockets lwip-2.0.3/debian/patches/max_sockets --- lwip-2.0.3/debian/patches/max_sockets 2018-04-30 23:16:54.000000000 +0000 +++ lwip-2.0.3/debian/patches/max_sockets 2018-08-28 21:27:25.000000000 +0000 @@ -33,7 +33,7 @@ * in seconds. (does not require sockets.c, and will affect tcp.c) --- a/src/api/sockets.c +++ b/src/api/sockets.c -@@ -198,6 +198,12 @@ +@@ -208,6 +208,12 @@ /** Contains all internal pointers and states used for a socket */ struct lwip_sock { @@ -46,7 +46,7 @@ /** sockets currently are built on netconns, each socket has one netconn */ struct netconn *conn; /** data that was left from the previous read */ -@@ -287,8 +293,13 @@ +@@ -297,8 +303,13 @@ static void lwip_socket_drop_registered_memberships(int s); #endif /* LWIP_IGMP */ @@ -60,7 +60,7 @@ /** The global list of tasks waiting for select */ static struct lwip_select_cb *select_cb_list; /** This counter is increased from lwip_select when the list is changed -@@ -359,15 +370,26 @@ +@@ -369,15 +380,29 @@ s -= LWIP_SOCKET_OFFSET; @@ -76,10 +76,13 @@ } +#if LWIP_SOCKET_OPEN_COUNT ++ SYS_ARCH_DECL_PROTECT(lev); ++ SYS_ARCH_PROTECT(lev); + for(sock = sockets; sock != NULL; sock = sock->next) { + if(sock->count == s) + break; + } ++ SYS_ARCH_UNPROTECT(lev); +#else /* LWIP_SOCKET_OPEN_COUNT */ sock = &sockets[s]; +#endif /* LWIP_SOCKET_OPEN_COUNT */ @@ -89,9 +92,14 @@ LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET)); set_errno(EBADF); return NULL; -@@ -386,13 +408,26 @@ +@@ -395,14 +420,33 @@ + static struct lwip_sock * tryget_socket(int s) { ++#if LWIP_SOCKET_OPEN_COUNT ++ struct lwip_sock *sock; ++#endif /* LWIP_SOCKET_OPEN_COUNT */ ++ s -= LWIP_SOCKET_OFFSET; - if ((s < 0) || (s >= NUM_SOCKETS)) { + if ((s < 0) @@ -102,11 +110,13 @@ return NULL; } +#if LWIP_SOCKET_OPEN_COUNT -+ struct lwip_sock *sock; ++ SYS_ARCH_DECL_PROTECT(lev); ++ SYS_ARCH_PROTECT(lev); + for(sock = sockets; sock != NULL; sock = sock->next) { + if(sock->count == s) + break; + } ++ SYS_ARCH_UNPROTECT(lev); + return sock; +#else /* LWIP_SOCKET_OPEN_COUNT */ if (!sockets[s].conn) { @@ -117,7 +127,7 @@ } /** -@@ -407,30 +442,70 @@ +@@ -417,30 +461,70 @@ alloc_socket(struct netconn *newconn, int accepted) { int i; @@ -199,33 +209,34 @@ } /** Free a socket. The socket's netconn must have been -@@ -442,9 +517,14 @@ - static void +@@ -453,6 +537,9 @@ free_socket(struct lwip_sock *sock, int is_tcp) { -- void *lastdata; -- -- lastdata = sock->lastdata; -+ void *lastdata = sock->lastdata; + void *lastdata; +#if LWIP_SOCKET_OPEN_COUNT + struct lwip_sock **it = &sockets; -+ -+ while(*it != sock) it = &(*it)->next; -+ *it = (*it)->next; -+ mem_free(sock); -+#else /* LWIP_SOCKET_OPEN_COUNT */ ++#endif /* LWIP_SOCKET_OPEN_COUNT */ + + lastdata = sock->lastdata; sock->lastdata = NULL; - sock->lastoffset = 0; +@@ -460,7 +547,15 @@ sock->err = 0; -@@ -452,6 +532,7 @@ + /* Protect socket array */ - SYS_ARCH_SET(sock->conn, NULL); - /* don't use 'sock' after this line, as another task might have allocated it */ +- SYS_ARCH_SET(sock->conn, NULL); ++ SYS_ARCH_DECL_PROTECT(lev); ++ SYS_ARCH_PROTECT(lev); ++ sock->conn = NULL; ++#if LWIP_SOCKET_OPEN_COUNT ++ while(*it != sock) it = &(*it)->next; ++ *it = (*it)->next; ++ mem_free(sock); +#endif /* LWIP_SOCKET_OPEN_COUNT */ ++ SYS_ARCH_UNPROTECT(lev); + /* don't use 'sock' after this line, as another task might have allocated it */ if (lastdata != NULL) { - if (is_tcp) { -@@ -512,7 +593,9 @@ +@@ -522,7 +617,9 @@ sock_set_errno(sock, ENFILE); return -1; } @@ -238,12 +249,12 @@ --- a/port/include/lwipopts.h +++ b/port/include/lwipopts.h @@ -26,6 +26,9 @@ - /* Don't rename Sockets API functions */ - #define LWIP_COMPAT_SOCKETS 0 - -+/* Don't limit the number of sockets */ -+#define LWIP_SOCKET_OPEN_COUNT 1 -+ - /* We're using lwip_poll() */ - #define LWIP_POLL 1 - + /* Don't rename Sockets API functions */ + #define LWIP_COMPAT_SOCKETS 0 + ++/* Don't limit the number of sockets */ ++#define LWIP_SOCKET_OPEN_COUNT 1 ++ + /* We're using lwip_poll() */ + #define LWIP_POLL 1 + diff -Nru lwip-2.0.3/debian/patches/poll lwip-2.0.3/debian/patches/poll --- lwip-2.0.3/debian/patches/poll 2018-04-30 23:16:25.000000000 +0000 +++ lwip-2.0.3/debian/patches/poll 2018-08-28 21:27:25.000000000 +0000 @@ -2,7 +2,7 @@ --- a/src/api/sockets.c +++ b/src/api/sockets.c -@@ -238,6 +238,12 @@ +@@ -248,6 +248,12 @@ fd_set *writeset; /** unimplemented: exceptset passed to select */ fd_set *exceptset; @@ -15,7 +15,7 @@ /** don't signal the same semaphore twice: set to 1 when signalled */ int sem_signalled; /** semaphore to wake up a task waiting for select */ -@@ -1288,6 +1294,51 @@ +@@ -1302,6 +1308,51 @@ return lwip_sendmsg(s, &msg, 0); } @@ -67,7 +67,7 @@ /** * Go through the readset and writeset lists and see which socket of the sockets * set in the sets has events. On return, readset, writeset and exceptset have -@@ -1411,6 +1462,10 @@ +@@ -1425,6 +1476,10 @@ select_cb.readset = readset; select_cb.writeset = writeset; select_cb.exceptset = exceptset; @@ -78,7 +78,7 @@ select_cb.sem_signalled = 0; #if LWIP_NETCONN_SEM_PER_THREAD select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET(); -@@ -1422,20 +1477,7 @@ +@@ -1436,20 +1491,7 @@ } #endif /* LWIP_NETCONN_SEM_PER_THREAD */ @@ -100,7 +100,7 @@ /* Increase select_waiting for each socket we are interested in */ maxfdp2 = maxfdp1; -@@ -1505,21 +1547,7 @@ +@@ -1519,21 +1561,7 @@ SYS_ARCH_UNPROTECT(lev); } } @@ -123,7 +123,7 @@ #if LWIP_NETCONN_SEM_PER_THREAD if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) { -@@ -1563,6 +1591,253 @@ +@@ -1577,6 +1605,253 @@ return nready; } @@ -304,7 +304,7 @@ + LWIP_ASSERT("timeout > 0", timeout > 0); + msectimeout = timeout; + } -+ waitres = sys_arch_sem_wait_intr(SELECT_SEM_PTR(select_cb.sem), msectimeout); ++ waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout); +#if LWIP_NETCONN_SEM_PER_THREAD + waited = 1; +#endif @@ -332,12 +332,12 @@ + + if (waitres == SYS_ARCH_TIMEOUT) { + /* Timeout */ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_poll: timeout expired\n")); + goto return_success; + } + } + -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_poll: nready=%d\n", nready)); +return_success: + set_errno(0); + return nready; @@ -377,7 +377,7 @@ /** * Callback registered in the netconn layer for each socket-netconn. * Processes recvevent (data available) and wakes up tasks waiting for select. -@@ -1649,20 +1924,27 @@ +@@ -1663,20 +1938,27 @@ if (scb->sem_signalled == 0) { /* semaphore not signalled yet */ int do_signal = 0; @@ -419,7 +419,7 @@ if (do_signal) { --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h -@@ -1751,6 +1751,17 @@ +@@ -1751,6 +1751,17 @@ #endif /** @@ -439,49 +439,49 @@ * names (read, write & close). (only used if you use sockets.c) --- a/src/include/lwip/lwip_sockets.h +++ b/src/include/lwip/lwip_sockets.h -@@ -430,6 +430,21 @@ - #error "external FD_SETSIZE too small for number of sockets" - #endif /* FD_SET */ - -+#if LWIP_POLL == 2 -+#define POLLIN 0x01 -+#define POLLOUT 0x02 -+#define POLLERR 0x04 -+#define POLLNVAL 0x08 -+/* No support for POLLPRI, POLLHUP, POLLMSG, POLLRDBAND, POLLWRBAND. */ -+typedef int nfds_t; -+struct pollfd -+{ -+ int fd; -+ short events; -+ short revents; -+}; -+#endif -+ - /** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided - * by your system, set this to 0 and include in cc.h */ - #ifndef LWIP_TIMEVAL_PRIVATE -@@ -466,6 +481,9 @@ - #define lwip_sendto sendto - #define lwip_socket socket - #define lwip_select select -+#if LWIP_POLL -+#define lwip_poll poll -+#endif - #define lwip_ioctlsocket ioctl - - #if LWIP_POSIX_SOCKETS_IO_NAMES -@@ -516,6 +534,10 @@ - #define socket(domain,type,protocol) lwip_socket(domain,type,protocol) - /** @ingroup socket */ - #define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) -+#if LWIP_POLL -+/** @ingroup socket */ -+#define poll(fds,nfds,timeout) lwip_poll(fds,nfds,timeout) -+#endif - /** @ingroup socket */ - #define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) - +@@ -432,6 +432,21 @@ + #error "external FD_SETSIZE too small for number of sockets" + #endif /* FD_SET */ + ++#if LWIP_POLL == 2 ++#define POLLIN 0x01 ++#define POLLOUT 0x02 ++#define POLLERR 0x04 ++#define POLLNVAL 0x08 ++/* No support for POLLPRI, POLLHUP, POLLMSG, POLLRDBAND, POLLWRBAND. */ ++typedef int nfds_t; ++struct pollfd ++{ ++ int fd; ++ short events; ++ short revents; ++}; ++#endif ++ + /** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ + #ifndef LWIP_TIMEVAL_PRIVATE +@@ -468,6 +483,9 @@ + #define lwip_sendto sendto + #define lwip_socket socket + #define lwip_select select ++#if LWIP_POLL ++#define lwip_poll poll ++#endif + #define lwip_ioctlsocket ioctl + + #if LWIP_POSIX_SOCKETS_IO_NAMES +@@ -518,6 +536,10 @@ + #define socket(domain,type,protocol) lwip_socket(domain,type,protocol) + /** @ingroup socket */ + #define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) ++#if LWIP_POLL ++/** @ingroup socket */ ++#define poll(fds,nfds,timeout) lwip_poll(fds,nfds,timeout) ++#endif + /** @ingroup socket */ + #define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) + --- a/src/include/lwip/sockets.h +++ b/src/include/lwip/sockets.h @@ -75,6 +75,9 @@ @@ -497,24 +497,24 @@ --- a/port/include/lwipopts.h +++ b/port/include/lwipopts.h @@ -26,6 +26,9 @@ - /* Don't rename Sockets API functions */ - #define LWIP_COMPAT_SOCKETS 0 - -+/* We're using lwip_poll() */ -+#define LWIP_POLL 1 -+ - /* Use Glibc's sockets headers */ - #define LWIP_STD_SOCKETS 1 - #define LWIP_INCLUDE_STD_SOCKETS "posix/socket.h" + /* Don't rename Sockets API functions */ + #define LWIP_COMPAT_SOCKETS 0 + ++/* We're using lwip_poll() */ ++#define LWIP_POLL 1 ++ + /* Use Glibc's sockets headers */ + #define LWIP_STD_SOCKETS 1 + #define LWIP_INCLUDE_STD_SOCKETS "posix/socket.h" --- a/port/include/arch/cc.h +++ b/port/include/arch/cc.h -@@ -46,6 +46,9 @@ - #include - #include - -+/* We use poll() instead of select()*/ -+#include -+ - /* Use our own htons() and pals */ - #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 - +@@ -40,6 +40,9 @@ + /* Use our own ioctls */ + #include + ++/* We use poll() instead of select()*/ ++#include ++ + /* Use our own htons() and pals */ + #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 + diff -Nru lwip-2.0.3/debian/patches/port lwip-2.0.3/debian/patches/port --- lwip-2.0.3/debian/patches/port 2018-04-30 23:05:15.000000000 +0000 +++ lwip-2.0.3/debian/patches/port 2018-08-28 21:27:25.000000000 +0000 @@ -3,1022 +3,941 @@ --- /dev/null +++ b/port/include/arch/cc.h @@ -0,0 +1,68 @@ -+/* -+ Copyright (C) 2017 Free Software Foundation, Inc. -+ Written by Joan Lledó. -+ -+ This file is part of the GNU Hurd. -+ -+ The GNU Hurd is free software; you can redistribute it and/or -+ modify it under the terms of the GNU General Public License as -+ published by the Free Software Foundation; either version 2, or (at -+ your option) any later version. -+ -+ The GNU Hurd is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with the GNU Hurd. If not, see . */ -+ -+#ifndef LWIP_ARCH_CC_H -+#define LWIP_ARCH_CC_H -+ -+#include /* rand() */ -+#include /* printf() */ -+ -+/* Use Glibc's fcntl() macros */ -+#include -+ -+/* Use Glibc's */ -+#include -+#define LWIP_ERR_T int -+ -+/* System provides its own struct timeval */ -+#define LWIP_TIMEVAL_PRIVATE 0 -+#include -+ -+/* We need INT_MAX */ -+#include -+ -+/* Use our own ioctls */ -+#include -+ -+/* Use our own htons() and pals */ -+#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 -+ -+/* printf() codes */ -+#define S16_F "d" -+#define U16_F "u" -+#define X16_F "x" -+ -+#define S32_F "d" -+#define U32_F "u" -+#define X32_F "x" -+ -+#ifdef LWIP_DEBUG -+#define LWIP_PLATFORM_DIAG(x) do { printf x; fflush(NULL);} while(0) -+#endif -+ -+/* Redefine LWIP_ERROR to not abort the process if the assertion failed */ -+#define LWIP_ERROR(message, expression, handler) \ -+ do { \ -+ if (!(expression)) { \ -+ printf("Assertion \"%s\" failed at line %d in %s\n", \ -+ message, __LINE__, __FILE__); fflush(NULL); \ -+ handler;} \ -+ } while(0) -+ -+#endif /* LWIP_ARCH_CC_H */ ++/* ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ Written by Joan Lledó. ++ ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License as ++ published by the Free Software Foundation; either version 2, or (at ++ your option) any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with the GNU Hurd. If not, see . */ ++ ++#ifndef LWIP_ARCH_CC_H ++#define LWIP_ARCH_CC_H ++ ++#include /* rand() */ ++#include /* printf() */ ++ ++/* Use Glibc's fcntl() macros */ ++#include ++ ++/* Use Glibc's */ ++#include ++#define LWIP_ERR_T int ++ ++/* System provides its own struct timeval */ ++#define LWIP_TIMEVAL_PRIVATE 0 ++#include ++ ++/* We need INT_MAX */ ++#include ++ ++/* Use our own ioctls */ ++#include ++ ++/* Use our own htons() and pals */ ++#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 ++ ++/* printf() codes */ ++#define S16_F "d" ++#define U16_F "u" ++#define X16_F "x" ++ ++#define S32_F "d" ++#define U32_F "u" ++#define X32_F "x" ++ ++#ifdef LWIP_DEBUG ++#define LWIP_PLATFORM_DIAG(x) do { printf x; fflush(NULL);} while(0) ++#endif ++ ++/* Redefine LWIP_ERROR to not abort the process if the assertion failed */ ++#define LWIP_ERROR(message, expression, handler) \ ++ do { \ ++ if (!(expression)) { \ ++ printf("Assertion \"%s\" failed at line %d in %s\n", \ ++ message, __LINE__, __FILE__); fflush(NULL); \ ++ handler;} \ ++ } while(0) ++ ++#endif /* LWIP_ARCH_CC_H */ --- /dev/null +++ b/port/include/arch/sys_arch.h -@@ -0,0 +1,64 @@ -+/* -+ * Copyright (c) 2001-2003 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 -+ * -+ */ -+#ifndef LWIP_ARCH_SYS_ARCH_H -+#define LWIP_ARCH_SYS_ARCH_H -+ -+#define SYS_MBOX_NULL NULL -+#define SYS_SEM_NULL NULL -+ -+/* Return code for an interrupted timed wait */ -+#define SYS_ARCH_INTR 0xfffffffeUL -+ -+typedef u32_t sys_prot_t; -+ -+struct sys_sem; -+typedef struct sys_sem * sys_sem_t; -+#define sys_sem_valid(sem) (*(sem) != NULL) -+#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0) -+ -+struct sys_mutex; -+typedef struct sys_mutex * sys_mutex_t; -+#define sys_mutex_valid(mutex) sys_sem_valid(mutex) -+#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) -+ -+struct sys_mbox; -+typedef struct sys_mbox * sys_mbox_t; -+#define sys_mbox_valid(mbox) sys_sem_valid(mbox) -+#define sys_mbox_set_invalid(mbox) sys_sem_set_invalid(mbox) -+ -+struct sys_thread; -+typedef struct sys_thread * sys_thread_t; -+ -+u32_t sys_arch_sem_wait_intr(sys_sem_t *sem, u32_t timeout); -+ -+#endif /* LWIP_ARCH_SYS_ARCH_H */ -+ +@@ -0,0 +1,62 @@ ++/* ++ * Copyright (c) 2001-2003 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 ++ * ++ */ ++#ifndef LWIP_ARCH_SYS_ARCH_H ++#define LWIP_ARCH_SYS_ARCH_H ++ ++#define SYS_MBOX_NULL NULL ++#define SYS_SEM_NULL NULL ++ ++/* Return code for an interrupted timed wait */ ++#define SYS_ARCH_INTR 0xfffffffeUL ++ ++typedef u32_t sys_prot_t; ++ ++struct sys_sem; ++typedef struct sys_sem * sys_sem_t; ++#define sys_sem_valid(sem) (*(sem) != NULL) ++#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0) ++ ++struct sys_mutex; ++typedef struct sys_mutex * sys_mutex_t; ++#define sys_mutex_valid(mutex) sys_sem_valid(mutex) ++#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) ++ ++struct sys_mbox; ++typedef struct sys_mbox * sys_mbox_t; ++#define sys_mbox_valid(mbox) sys_sem_valid(mbox) ++#define sys_mbox_set_invalid(mbox) sys_sem_set_invalid(mbox) ++ ++struct sys_thread; ++typedef struct sys_thread * sys_thread_t; ++ ++#endif /* LWIP_ARCH_SYS_ARCH_H */ ++ --- /dev/null +++ b/port/include/lwipopts.h @@ -0,0 +1,131 @@ -+/* -+ Copyright (C) 2017 Free Software Foundation, Inc. -+ Written by Joan Lledó. -+ -+ This file is part of the GNU Hurd. -+ -+ The GNU Hurd is free software; you can redistribute it and/or -+ modify it under the terms of the GNU General Public License as -+ published by the Free Software Foundation; either version 2, or (at -+ your option) any later version. -+ -+ The GNU Hurd is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with the GNU Hurd. If not, see . */ -+ -+#ifndef HURD_LWIP_LWIPOPTS_H -+#define HURD_LWIP_LWIPOPTS_H -+ -+/* An OS is present */ -+#define NO_SYS 0 -+ -+/* Don't rename Sockets API functions */ -+#define LWIP_COMPAT_SOCKETS 0 -+ -+/* Use Glibc malloc()/free() */ -+#define MEM_LIBC_MALLOC 1 -+#define MEMP_MEM_MALLOC 1 -+#define MEM_USE_POOLS 0 -+#define MEM_ALIGNMENT 4 -+ -+/* Only send complete packets to the device */ -+#define LWIP_NETIF_TX_SINGLE_PBUF 1 -+ -+/* Randomize local ports */ -+#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 -+ -+/* Glibc sends more than one packet in a row during an ARP resolution */ -+#define ARP_QUEUEING 1 -+#define ARP_QUEUE_LEN 10 -+ -+/* Netif API is needed to add or remove interfaces on run time */ -+#define LWIP_NETIF_API 1 -+ -+/* IPv4 stuff */ -+#define IP_FORWARD 1 -+ -+/* SLAAC support and other IPv6 stuff */ -+#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 -+#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 -+#define LWIP_IPV6_AUTOCONFIG 1 -+#define LWIP_IPV6_FORWARD 1 -+#define MEMP_NUM_MLD6_GROUP 16 -+#define LWIP_IPV6_NUM_ADDRESSES 6 -+ -+/* TCP tuning */ -+#define TCP_MSS 1460 -+#define TCP_WND 0xFFFF -+#define TCP_SND_BUF TCP_WND -+ -+/* Throughput settings */ -+#define LWIP_CHECKSUM_ON_COPY 1 -+ -+/* Disable stats */ -+#define LWIP_STATS 0 -+#define LWIP_STATS_DISPLAY 0 -+ -+/* Enable all socket operations */ -+#define LWIP_TCP_KEEPALIVE 1 -+#define LWIP_SO_SNDTIMEO 1 -+#define LWIP_SO_RCVTIMEO 1 -+#define LWIP_SO_RCVBUF 1 -+#define LWIP_SO_LINGER 1 -+#define SO_REUSE 1 -+#define LWIP_MULTICAST_TX_OPTIONS 1 -+ -+/* Enable modules */ -+#define LWIP_ARP 1 -+#define LWIP_ETHERNET 1 -+#define LWIP_IPV4 1 -+#define LWIP_ICMP 1 -+#define LWIP_IGMP 1 -+#define LWIP_RAW 1 -+#define LWIP_UDP 1 -+#define LWIP_UDPLITE 1 -+#define LWIP_TCP 1 -+#define LWIP_IPV6 1 -+#define LWIP_ICMP6 1 -+#define LWIP_IPV6_MLD 1 -+#define LWIP_NETIF_LOOPBACK 1 -+ -+/* Debug mode */ -+#ifdef LWIP_DEBUG -+#define ETHARP_DEBUG LWIP_DBG_OFF -+#define NETIF_DEBUG LWIP_DBG_OFF -+#define PBUF_DEBUG LWIP_DBG_OFF -+#define API_LIB_DEBUG LWIP_DBG_OFF -+#define API_MSG_DEBUG LWIP_DBG_OFF -+#define SOCKETS_DEBUG LWIP_DBG_OFF -+#define ICMP_DEBUG LWIP_DBG_OFF -+#define IGMP_DEBUG LWIP_DBG_OFF -+#define INET_DEBUG LWIP_DBG_OFF -+#define IP_DEBUG LWIP_DBG_OFF -+#define IP_REASS_DEBUG LWIP_DBG_OFF -+#define RAW_DEBUG LWIP_DBG_OFF -+#define MEM_DEBUG LWIP_DBG_OFF -+#define MEMP_DEBUG LWIP_DBG_OFF -+#define SYS_DEBUG LWIP_DBG_OFF -+#define TIMERS_DEBUG LWIP_DBG_OFF -+#define TCP_DEBUG LWIP_DBG_OFF -+#define TCP_INPUT_DEBUG LWIP_DBG_OFF -+#define TCP_FR_DEBUG LWIP_DBG_OFF -+#define TCP_RTO_DEBUG LWIP_DBG_OFF -+#define TCP_CWND_DEBUG LWIP_DBG_OFF -+#define TCP_WND_DEBUG LWIP_DBG_OFF -+#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF -+#define TCP_RST_DEBUG LWIP_DBG_OFF -+#define TCP_QLEN_DEBUG LWIP_DBG_OFF -+#define UDP_DEBUG LWIP_DBG_OFF -+#define TCPIP_DEBUG LWIP_DBG_OFF -+#define SLIP_DEBUG LWIP_DBG_OFF -+#define DHCP_DEBUG LWIP_DBG_OFF -+#define AUTOIP_DEBUG LWIP_DBG_OFF -+#define DNS_DEBUG LWIP_DBG_OFF -+#define IP6_DEBUG LWIP_DBG_OFF -+#endif -+ -+#endif ++/* ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ Written by Joan Lledó. ++ ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License as ++ published by the Free Software Foundation; either version 2, or (at ++ your option) any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with the GNU Hurd. If not, see . */ ++ ++#ifndef HURD_LWIP_LWIPOPTS_H ++#define HURD_LWIP_LWIPOPTS_H ++ ++/* An OS is present */ ++#define NO_SYS 0 ++ ++/* Don't rename Sockets API functions */ ++#define LWIP_COMPAT_SOCKETS 0 ++ ++/* Use Glibc malloc()/free() */ ++#define MEM_LIBC_MALLOC 1 ++#define MEMP_MEM_MALLOC 1 ++#define MEM_USE_POOLS 0 ++#define MEM_ALIGNMENT 4 ++ ++/* Only send complete packets to the device */ ++#define LWIP_NETIF_TX_SINGLE_PBUF 1 ++ ++/* Randomize local ports */ ++#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 ++ ++/* Glibc sends more than one packet in a row during an ARP resolution */ ++#define ARP_QUEUEING 1 ++#define ARP_QUEUE_LEN 10 ++ ++/* Netif API is needed to add or remove interfaces on run time */ ++#define LWIP_NETIF_API 1 ++ ++/* IPv4 stuff */ ++#define IP_FORWARD 1 ++ ++/* SLAAC support and other IPv6 stuff */ ++#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 ++#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 ++#define LWIP_IPV6_AUTOCONFIG 1 ++#define LWIP_IPV6_FORWARD 1 ++#define MEMP_NUM_MLD6_GROUP 16 ++#define LWIP_IPV6_NUM_ADDRESSES 6 ++ ++/* TCP tuning */ ++#define TCP_MSS 1460 ++#define TCP_WND 0xFFFF ++#define TCP_SND_BUF TCP_WND ++ ++/* Throughput settings */ ++#define LWIP_CHECKSUM_ON_COPY 1 ++ ++/* Disable stats */ ++#define LWIP_STATS 0 ++#define LWIP_STATS_DISPLAY 0 ++ ++/* Enable all socket operations */ ++#define LWIP_TCP_KEEPALIVE 1 ++#define LWIP_SO_SNDTIMEO 1 ++#define LWIP_SO_RCVTIMEO 1 ++#define LWIP_SO_RCVBUF 1 ++#define LWIP_SO_LINGER 1 ++#define SO_REUSE 1 ++#define LWIP_MULTICAST_TX_OPTIONS 1 ++ ++/* Enable modules */ ++#define LWIP_ARP 1 ++#define LWIP_ETHERNET 1 ++#define LWIP_IPV4 1 ++#define LWIP_ICMP 1 ++#define LWIP_IGMP 1 ++#define LWIP_RAW 1 ++#define LWIP_UDP 1 ++#define LWIP_UDPLITE 1 ++#define LWIP_TCP 1 ++#define LWIP_IPV6 1 ++#define LWIP_ICMP6 1 ++#define LWIP_IPV6_MLD 1 ++#define LWIP_NETIF_LOOPBACK 1 ++ ++/* Debug mode */ ++#ifdef LWIP_DEBUG ++#define ETHARP_DEBUG LWIP_DBG_OFF ++#define NETIF_DEBUG LWIP_DBG_OFF ++#define PBUF_DEBUG LWIP_DBG_OFF ++#define API_LIB_DEBUG LWIP_DBG_OFF ++#define API_MSG_DEBUG LWIP_DBG_OFF ++#define SOCKETS_DEBUG LWIP_DBG_OFF ++#define ICMP_DEBUG LWIP_DBG_OFF ++#define IGMP_DEBUG LWIP_DBG_OFF ++#define INET_DEBUG LWIP_DBG_OFF ++#define IP_DEBUG LWIP_DBG_OFF ++#define IP_REASS_DEBUG LWIP_DBG_OFF ++#define RAW_DEBUG LWIP_DBG_OFF ++#define MEM_DEBUG LWIP_DBG_OFF ++#define MEMP_DEBUG LWIP_DBG_OFF ++#define SYS_DEBUG LWIP_DBG_OFF ++#define TIMERS_DEBUG LWIP_DBG_OFF ++#define TCP_DEBUG LWIP_DBG_OFF ++#define TCP_INPUT_DEBUG LWIP_DBG_OFF ++#define TCP_FR_DEBUG LWIP_DBG_OFF ++#define TCP_RTO_DEBUG LWIP_DBG_OFF ++#define TCP_CWND_DEBUG LWIP_DBG_OFF ++#define TCP_WND_DEBUG LWIP_DBG_OFF ++#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF ++#define TCP_RST_DEBUG LWIP_DBG_OFF ++#define TCP_QLEN_DEBUG LWIP_DBG_OFF ++#define UDP_DEBUG LWIP_DBG_OFF ++#define TCPIP_DEBUG LWIP_DBG_OFF ++#define SLIP_DEBUG LWIP_DBG_OFF ++#define DHCP_DEBUG LWIP_DBG_OFF ++#define AUTOIP_DEBUG LWIP_DBG_OFF ++#define DNS_DEBUG LWIP_DBG_OFF ++#define IP6_DEBUG LWIP_DBG_OFF ++#endif ++ ++#endif --- /dev/null +++ b/port/sys_arch.c -@@ -0,0 +1,747 @@ -+/* -+ * Copyright (c) 2001-2003 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 -+ * -+ */ -+ -+/* -+ * Wed Apr 17 16:05:29 EDT 2002 (James Roth) -+ * -+ * - Fixed an unlikely sys_thread_new() race condition. -+ * -+ * - Made current_thread() work with threads which where -+ * not created with sys_thread_new(). This includes -+ * the main thread and threads made with pthread_create(). -+ * -+ * - Catch overflows where more than SYS_MBOX_SIZE messages -+ * are waiting to be read. The sys_mbox_post() routine -+ * will block until there is more room instead of just -+ * leaking messages. -+ */ -+#include "lwip/debug.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "lwip/def.h" -+ -+#ifdef LWIP_UNIX_MACH -+#include -+#include -+#endif -+ -+#include "lwip/sys.h" -+#include "lwip/opt.h" -+#include "lwip/stats.h" -+ -+static void -+get_monotonic_time(struct timespec *ts) -+{ -+#ifdef LWIP_UNIX_MACH -+ /* darwin impl (no CLOCK_MONOTONIC) */ -+ uint64_t t = mach_absolute_time(); -+ mach_timebase_info_data_t timebase_info = {0, 0}; -+ mach_timebase_info(&timebase_info); -+ uint64_t nano = (t * timebase_info.numer) / (timebase_info.denom); -+ uint64_t sec = nano/1000000000L; -+ nano -= sec * 1000000000L; -+ ts->tv_sec = sec; -+ ts->tv_nsec = nano; -+#else -+ clock_gettime(CLOCK_MONOTONIC, ts); -+#endif -+} -+ -+#if !NO_SYS -+ -+static struct sys_thread *threads = NULL; -+static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER; -+ -+struct sys_mbox_msg { -+ struct sys_mbox_msg *next; -+ void *msg; -+}; -+ -+#define SYS_MBOX_SIZE 128 -+ -+struct sys_mbox { -+ int first, last; -+ void *msgs[SYS_MBOX_SIZE]; -+ struct sys_sem *not_empty; -+ struct sys_sem *not_full; -+ struct sys_sem *mutex; -+ int wait_send; -+}; -+ -+struct sys_sem { -+ unsigned int c; -+ pthread_condattr_t condattr; -+ pthread_cond_t cond; -+ pthread_mutex_t mutex; -+}; -+ -+struct sys_mutex { -+ pthread_mutex_t mutex; -+}; -+ -+struct sys_thread { -+ struct sys_thread *next; -+ pthread_t pthread; -+}; -+ -+#if SYS_LIGHTWEIGHT_PROT -+static pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER; -+static pthread_t lwprot_thread = (pthread_t)0xDEAD; -+static int lwprot_count = 0; -+#endif /* SYS_LIGHTWEIGHT_PROT */ -+ -+static struct sys_sem *sys_sem_new_internal(u8_t count); -+static void sys_sem_free_internal(struct sys_sem *sem); -+ -+static u32_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex, -+ u32_t timeout); -+ -+static u32_t cond_wait_intr(pthread_cond_t * cond, pthread_mutex_t * mutex, -+ u32_t timeout); -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Threads */ -+static struct sys_thread * -+introduce_thread(pthread_t id) -+{ -+ struct sys_thread *thread; -+ -+ thread = (struct sys_thread *)malloc(sizeof(struct sys_thread)); -+ -+ if (thread != NULL) { -+ pthread_mutex_lock(&threads_mutex); -+ thread->next = threads; -+ thread->pthread = id; -+ threads = thread; -+ pthread_mutex_unlock(&threads_mutex); -+ } -+ -+ return thread; -+} -+ -+sys_thread_t -+sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio) -+{ -+ int code; -+ pthread_t tmp; -+ struct sys_thread *st = NULL; -+ LWIP_UNUSED_ARG(name); -+ LWIP_UNUSED_ARG(stacksize); -+ LWIP_UNUSED_ARG(prio); -+ -+ code = pthread_create(&tmp, -+ NULL, -+ (void *(*)(void *)) -+ function, -+ arg); -+ -+ if (0 == code) { -+ st = introduce_thread(tmp); -+ } -+ -+ if (NULL == st) { -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%lx", -+ code, (unsigned long)st)); -+ abort(); -+ } -+ return st; -+} -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Mailbox */ -+err_t -+sys_mbox_new(struct sys_mbox **mb, int size) -+{ -+ struct sys_mbox *mbox; -+ LWIP_UNUSED_ARG(size); -+ -+ mbox = (struct sys_mbox *)malloc(sizeof(struct sys_mbox)); -+ if (mbox == NULL) { -+ return ERR_MEM; -+ } -+ mbox->first = mbox->last = 0; -+ mbox->not_empty = sys_sem_new_internal(0); -+ mbox->not_full = sys_sem_new_internal(0); -+ mbox->mutex = sys_sem_new_internal(1); -+ mbox->wait_send = 0; -+ -+ SYS_STATS_INC_USED(mbox); -+ *mb = mbox; -+ return ERR_OK; -+} -+ -+void -+sys_mbox_free(struct sys_mbox **mb) -+{ -+ if ((mb != NULL) && (*mb != SYS_MBOX_NULL)) { -+ struct sys_mbox *mbox = *mb; -+ SYS_STATS_DEC(mbox.used); -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ -+ sys_sem_free_internal(mbox->not_empty); -+ sys_sem_free_internal(mbox->not_full); -+ sys_sem_free_internal(mbox->mutex); -+ mbox->not_empty = mbox->not_full = mbox->mutex = NULL; -+ /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */ -+ free(mbox); -+ } -+} -+ -+err_t -+sys_mbox_trypost(struct sys_mbox **mb, void *msg) -+{ -+ u8_t first; -+ struct sys_mbox *mbox; -+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); -+ mbox = *mb; -+ -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n", -+ (void *)mbox, (void *)msg)); -+ -+ if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { -+ sys_sem_signal(&mbox->mutex); -+ return ERR_MEM; -+ } -+ -+ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; -+ -+ if (mbox->last == mbox->first) { -+ first = 1; -+ } else { -+ first = 0; -+ } -+ -+ mbox->last++; -+ -+ if (first) { -+ sys_sem_signal(&mbox->not_empty); -+ } -+ -+ sys_sem_signal(&mbox->mutex); -+ -+ return ERR_OK; -+} -+ -+void -+sys_mbox_post(struct sys_mbox **mb, void *msg) -+{ -+ u8_t first; -+ struct sys_mbox *mbox; -+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); -+ mbox = *mb; -+ -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg)); -+ -+ while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { -+ mbox->wait_send++; -+ sys_sem_signal(&mbox->mutex); -+ sys_arch_sem_wait(&mbox->not_full, 0); -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ mbox->wait_send--; -+ } -+ -+ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; -+ -+ if (mbox->last == mbox->first) { -+ first = 1; -+ } else { -+ first = 0; -+ } -+ -+ mbox->last++; -+ -+ if (first) { -+ sys_sem_signal(&mbox->not_empty); -+ } -+ -+ sys_sem_signal(&mbox->mutex); -+} -+ -+u32_t -+sys_arch_mbox_tryfetch(struct sys_mbox **mb, void **msg) -+{ -+ struct sys_mbox *mbox; -+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); -+ mbox = *mb; -+ -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ -+ if (mbox->first == mbox->last) { -+ sys_sem_signal(&mbox->mutex); -+ return SYS_MBOX_EMPTY; -+ } -+ -+ if (msg != NULL) { -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg)); -+ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; -+ } -+ else{ -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox)); -+ } -+ -+ mbox->first++; -+ -+ if (mbox->wait_send) { -+ sys_sem_signal(&mbox->not_full); -+ } -+ -+ sys_sem_signal(&mbox->mutex); -+ -+ return 0; -+} -+ -+u32_t -+sys_arch_mbox_fetch(struct sys_mbox **mb, void **msg, u32_t timeout) -+{ -+ u32_t time_needed = 0; -+ struct sys_mbox *mbox; -+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); -+ mbox = *mb; -+ -+ /* The mutex lock is quick so we don't bother with the timeout -+ stuff here. */ -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ -+ while (mbox->first == mbox->last) { -+ sys_sem_signal(&mbox->mutex); -+ -+ /* We block while waiting for a mail to arrive in the mailbox. We -+ must be prepared to timeout. */ -+ if (timeout != 0) { -+ time_needed = sys_arch_sem_wait(&mbox->not_empty, timeout); -+ -+ if (time_needed == SYS_ARCH_TIMEOUT) { -+ return SYS_ARCH_TIMEOUT; -+ } -+ } else { -+ sys_arch_sem_wait(&mbox->not_empty, 0); -+ } -+ -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ } -+ -+ if (msg != NULL) { -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg)); -+ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; -+ } -+ else{ -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox)); -+ } -+ -+ mbox->first++; -+ -+ if (mbox->wait_send) { -+ sys_sem_signal(&mbox->not_full); -+ } -+ -+ sys_sem_signal(&mbox->mutex); -+ -+ return time_needed; -+} -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Semaphore */ -+static struct sys_sem * -+sys_sem_new_internal(u8_t count) -+{ -+ struct sys_sem *sem; -+ -+ sem = (struct sys_sem *)malloc(sizeof(struct sys_sem)); -+ if (sem != NULL) { -+ sem->c = count; -+ pthread_condattr_init(&(sem->condattr)); -+#if !(defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21)) -+ pthread_condattr_setclock(&(sem->condattr), CLOCK_MONOTONIC); -+#endif -+ pthread_cond_init(&(sem->cond), &(sem->condattr)); -+ pthread_mutex_init(&(sem->mutex), NULL); -+ } -+ return sem; -+} -+ -+err_t -+sys_sem_new(struct sys_sem **sem, u8_t count) -+{ -+ SYS_STATS_INC_USED(sem); -+ *sem = sys_sem_new_internal(count); -+ if (*sem == NULL) { -+ return ERR_MEM; -+ } -+ return ERR_OK; -+} -+ -+static u32_t -+cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout) -+{ -+ struct timespec rtime1, rtime2, ts; -+ int ret; -+ -+ if (timeout == 0) { -+ pthread_cond_wait(cond, mutex); -+ return 0; -+ } -+ -+ /* Get a timestamp and add the timeout value. */ -+ get_monotonic_time(&rtime1); -+#if defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21) -+ ts.tv_sec = timeout / 1000L; -+ ts.tv_nsec = (timeout % 1000L) * 1000000L; -+ ret = pthread_cond_timedwait_relative_np(cond, mutex, &ts); -+#else -+ ts.tv_sec = rtime1.tv_sec + timeout / 1000L; -+ ts.tv_nsec = rtime1.tv_nsec + (timeout % 1000L) * 1000000L; -+ if (ts.tv_nsec >= 1000000000L) { -+ ts.tv_sec++; -+ ts.tv_nsec -= 1000000000L; -+ } -+ -+ ret = pthread_cond_timedwait(cond, mutex, &ts); -+#endif -+ if (ret == ETIMEDOUT) { -+ return SYS_ARCH_TIMEOUT; -+ } -+ -+ /* Calculate for how long we waited for the cond. */ -+ get_monotonic_time(&rtime2); -+ ts.tv_sec = rtime2.tv_sec - rtime1.tv_sec; -+ ts.tv_nsec = rtime2.tv_nsec - rtime1.tv_nsec; -+ if (ts.tv_nsec < 0) { -+ ts.tv_sec--; -+ ts.tv_nsec += 1000000000L; -+ } -+ return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); -+} -+ -+u32_t -+sys_arch_sem_wait(struct sys_sem **s, u32_t timeout) -+{ -+ u32_t time_needed = 0; -+ struct sys_sem *sem; -+ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); -+ sem = *s; -+ -+ pthread_mutex_lock(&(sem->mutex)); -+ while (sem->c <= 0) { -+ if (timeout > 0) { -+ time_needed = cond_wait(&(sem->cond), &(sem->mutex), timeout); -+ -+ if (time_needed == SYS_ARCH_TIMEOUT) { -+ pthread_mutex_unlock(&(sem->mutex)); -+ return SYS_ARCH_TIMEOUT; -+ } -+ /* pthread_mutex_unlock(&(sem->mutex)); -+ return time_needed; */ -+ } else { -+ cond_wait(&(sem->cond), &(sem->mutex), 0); -+ } -+ } -+ sem->c--; -+ pthread_mutex_unlock(&(sem->mutex)); -+ return (u32_t)time_needed; -+} -+ -+/* -+ * Like cond_wait(), but it calls Hurd's non portable -+ * functions to receive cancellation requests -+ */ -+static u32_t -+cond_wait_intr(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout) -+{ -+ struct timespec rtime1, rtime2, ts; -+ int ret; -+ -+#ifdef __GNU__ -+ #define pthread_cond_wait pthread_hurd_cond_wait_np -+ #define pthread_cond_timedwait pthread_hurd_cond_timedwait_np -+#endif -+ -+ if (timeout == 0) { -+ ret = pthread_cond_wait(cond, mutex); -+ return ret; -+ } -+ -+ /* Get a timestamp and add the timeout value. */ -+ get_monotonic_time(&rtime1); -+#if defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21) -+ ts.tv_sec = timeout / 1000L; -+ ts.tv_nsec = (timeout % 1000L) * 1000000L; -+ ret = pthread_cond_timedwait_relative_np(cond, mutex, &ts); -+#else -+ ts.tv_sec = rtime1.tv_sec + timeout / 1000L; -+ ts.tv_nsec = rtime1.tv_nsec + (timeout % 1000L) * 1000000L; -+ if (ts.tv_nsec >= 1000000000L) { -+ ts.tv_sec++; -+ ts.tv_nsec -= 1000000000L; -+ } -+ -+ ret = pthread_cond_timedwait(cond, mutex, &ts); -+#endif -+ if (ret == ETIMEDOUT) { -+ return SYS_ARCH_TIMEOUT; -+ } else if (ret == EINTR) { -+ return SYS_ARCH_INTR; -+ } -+ -+ /* Calculate for how long we waited for the cond. */ -+ get_monotonic_time(&rtime2); -+ ts.tv_sec = rtime2.tv_sec - rtime1.tv_sec; -+ ts.tv_nsec = rtime2.tv_nsec - rtime1.tv_nsec; -+ if (ts.tv_nsec < 0) { -+ ts.tv_sec--; -+ ts.tv_nsec += 1000000000L; -+ } -+ return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); -+} -+ -+/* -+ * Like sys_arch_sem_wait(), but it handles thread cancellations. -+ */ -+u32_t -+sys_arch_sem_wait_intr(struct sys_sem **s, u32_t timeout) -+{ -+ u32_t time_needed = 0; -+ struct sys_sem *sem; -+ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); -+ sem = *s; -+ -+ pthread_mutex_lock(&(sem->mutex)); -+ while (sem->c <= 0) { -+ if (timeout > 0) { -+ time_needed = cond_wait_intr(&(sem->cond), &(sem->mutex), timeout); -+ -+ if (time_needed == SYS_ARCH_TIMEOUT) { -+ pthread_mutex_unlock(&(sem->mutex)); -+ return SYS_ARCH_TIMEOUT; -+ } else if(time_needed == SYS_ARCH_INTR) { -+ /* This means we were interrupted, so don't wait again */ -+ sem->c++; -+ -+ if (sem->c > 1) { -+ sem->c = 1; -+ } -+ } -+ } else { -+ if(cond_wait_intr(&(sem->cond), &(sem->mutex), 0)) { -+ /* This means we were interrupted, so don't wait again */ -+ sem->c++; -+ -+ if (sem->c > 1) { -+ sem->c = 1; -+ } -+ } -+ } -+ } -+ sem->c--; -+ pthread_mutex_unlock(&(sem->mutex)); -+ return (u32_t)time_needed; -+} -+ -+void -+sys_sem_signal(struct sys_sem **s) -+{ -+ struct sys_sem *sem; -+ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); -+ sem = *s; -+ -+ pthread_mutex_lock(&(sem->mutex)); -+ sem->c++; -+ -+ if (sem->c > 1) { -+ sem->c = 1; -+ } -+ -+ pthread_cond_broadcast(&(sem->cond)); -+ pthread_mutex_unlock(&(sem->mutex)); -+} -+ -+static void -+sys_sem_free_internal(struct sys_sem *sem) -+{ -+ pthread_cond_destroy(&(sem->cond)); -+ pthread_condattr_destroy(&(sem->condattr)); -+ pthread_mutex_destroy(&(sem->mutex)); -+ free(sem); -+} -+ -+void -+sys_sem_free(struct sys_sem **sem) -+{ -+ if ((sem != NULL) && (*sem != SYS_SEM_NULL)) { -+ SYS_STATS_DEC(sem.used); -+ sys_sem_free_internal(*sem); -+ } -+} -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Mutex */ -+/** Create a new mutex -+ * @param mutex pointer to the mutex to create -+ * @return a new mutex */ -+err_t -+sys_mutex_new(struct sys_mutex **mutex) -+{ -+ struct sys_mutex *mtx; -+ -+ mtx = (struct sys_mutex *)malloc(sizeof(struct sys_mutex)); -+ if (mtx != NULL) { -+ pthread_mutex_init(&(mtx->mutex), NULL); -+ *mutex = mtx; -+ return ERR_OK; -+ } -+ else { -+ return ERR_MEM; -+ } -+} -+ -+/** Lock a mutex -+ * @param mutex the mutex to lock */ -+void -+sys_mutex_lock(struct sys_mutex **mutex) -+{ -+ pthread_mutex_lock(&((*mutex)->mutex)); -+} -+ -+/** Unlock a mutex -+ * @param mutex the mutex to unlock */ -+void -+sys_mutex_unlock(struct sys_mutex **mutex) -+{ -+ pthread_mutex_unlock(&((*mutex)->mutex)); -+} -+ -+/** Delete a mutex -+ * @param mutex the mutex to delete */ -+void -+sys_mutex_free(struct sys_mutex **mutex) -+{ -+ pthread_mutex_destroy(&((*mutex)->mutex)); -+ free(*mutex); -+} -+ -+#endif /* !NO_SYS */ -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Time */ -+u32_t -+sys_now(void) -+{ -+ struct timespec ts; -+ -+ get_monotonic_time(&ts); -+ return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); -+} -+ -+u32_t -+sys_jiffies(void) -+{ -+ struct timespec ts; -+ -+ get_monotonic_time(&ts); -+ return (u32_t)(ts.tv_sec * 1000000000L + ts.tv_nsec); -+} -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Init */ -+ -+void -+sys_init(void) -+{ -+} -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Critical section */ -+#if SYS_LIGHTWEIGHT_PROT -+/** sys_prot_t sys_arch_protect(void) -+ -+This optional function does a "fast" critical region protection and returns -+the previous protection level. This function is only called during very short -+critical regions. An embedded system which supports ISR-based drivers might -+want to implement this function by disabling interrupts. Task-based systems -+might want to implement this by using a mutex or disabling tasking. This -+function should support recursive calls from the same task or interrupt. In -+other words, sys_arch_protect() could be called while already protected. In -+that case the return value indicates that it is already protected. -+ -+sys_arch_protect() is only required if your port is supporting an operating -+system. -+*/ -+sys_prot_t -+sys_arch_protect(void) -+{ -+ /* Note that for the UNIX port, we are using a lightweight mutex, and our -+ * own counter (which is locked by the mutex). The return code is not actually -+ * used. */ -+ if (lwprot_thread != pthread_self()) -+ { -+ /* We are locking the mutex where it has not been locked before * -+ * or is being locked by another thread */ -+ pthread_mutex_lock(&lwprot_mutex); -+ lwprot_thread = pthread_self(); -+ lwprot_count = 1; -+ } -+ else -+ /* It is already locked by THIS thread */ -+ lwprot_count++; -+ return 0; -+} -+ -+/** void sys_arch_unprotect(sys_prot_t pval) -+ -+This optional function does a "fast" set of critical region protection to the -+value specified by pval. See the documentation for sys_arch_protect() for -+more information. This function is only required if your port is supporting -+an operating system. -+*/ -+void -+sys_arch_unprotect(sys_prot_t pval) -+{ -+ LWIP_UNUSED_ARG(pval); -+ if (lwprot_thread == pthread_self()) -+ { -+ if (--lwprot_count == 0) -+ { -+ lwprot_thread = (pthread_t) 0xDEAD; -+ pthread_mutex_unlock(&lwprot_mutex); -+ } -+ } -+} -+#endif /* SYS_LIGHTWEIGHT_PROT */ +@@ -0,0 +1,668 @@ ++/* ++ * Copyright (c) 2001-2003 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 ++ * ++ */ ++ ++/* ++ * Wed Apr 17 16:05:29 EDT 2002 (James Roth) ++ * ++ * - Fixed an unlikely sys_thread_new() race condition. ++ * ++ * - Made current_thread() work with threads which where ++ * not created with sys_thread_new(). This includes ++ * the main thread and threads made with pthread_create(). ++ * ++ * - Catch overflows where more than SYS_MBOX_SIZE messages ++ * are waiting to be read. The sys_mbox_post() routine ++ * will block until there is more room instead of just ++ * leaking messages. ++ */ ++#include "lwip/debug.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "lwip/def.h" ++ ++#ifdef LWIP_UNIX_MACH ++#include ++#include ++#endif ++ ++#include "lwip/sys.h" ++#include "lwip/opt.h" ++#include "lwip/stats.h" ++ ++static void ++get_monotonic_time(struct timespec *ts) ++{ ++#ifdef LWIP_UNIX_MACH ++ /* darwin impl (no CLOCK_MONOTONIC) */ ++ uint64_t t = mach_absolute_time(); ++ mach_timebase_info_data_t timebase_info = {0, 0}; ++ mach_timebase_info(&timebase_info); ++ uint64_t nano = (t * timebase_info.numer) / (timebase_info.denom); ++ uint64_t sec = nano/1000000000L; ++ nano -= sec * 1000000000L; ++ ts->tv_sec = sec; ++ ts->tv_nsec = nano; ++#else ++ clock_gettime(CLOCK_MONOTONIC, ts); ++#endif ++} ++ ++#if !NO_SYS ++ ++static struct sys_thread *threads = NULL; ++static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++struct sys_mbox_msg { ++ struct sys_mbox_msg *next; ++ void *msg; ++}; ++ ++#define SYS_MBOX_SIZE 128 ++ ++struct sys_mbox { ++ int first, last; ++ void *msgs[SYS_MBOX_SIZE]; ++ struct sys_sem *not_empty; ++ struct sys_sem *not_full; ++ struct sys_sem *mutex; ++ int wait_send; ++}; ++ ++struct sys_sem { ++ unsigned int c; ++ pthread_condattr_t condattr; ++ pthread_cond_t cond; ++ pthread_mutex_t mutex; ++}; ++ ++struct sys_mutex { ++ pthread_mutex_t mutex; ++}; ++ ++struct sys_thread { ++ struct sys_thread *next; ++ pthread_t pthread; ++}; ++ ++#if SYS_LIGHTWEIGHT_PROT ++static pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER; ++static pthread_t lwprot_thread = (pthread_t)0xDEAD; ++static int lwprot_count = 0; ++#endif /* SYS_LIGHTWEIGHT_PROT */ ++ ++static struct sys_sem *sys_sem_new_internal(u8_t count); ++static void sys_sem_free_internal(struct sys_sem *sem); ++ ++static u32_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex, ++ u32_t timeout); ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Threads */ ++static struct sys_thread * ++introduce_thread(pthread_t id) ++{ ++ struct sys_thread *thread; ++ ++ thread = (struct sys_thread *)malloc(sizeof(struct sys_thread)); ++ ++ if (thread != NULL) { ++ pthread_mutex_lock(&threads_mutex); ++ thread->next = threads; ++ thread->pthread = id; ++ threads = thread; ++ pthread_mutex_unlock(&threads_mutex); ++ } ++ ++ return thread; ++} ++ ++sys_thread_t ++sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio) ++{ ++ int code; ++ pthread_t tmp; ++ struct sys_thread *st = NULL; ++ LWIP_UNUSED_ARG(name); ++ LWIP_UNUSED_ARG(stacksize); ++ LWIP_UNUSED_ARG(prio); ++ ++ code = pthread_create(&tmp, ++ NULL, ++ (void *(*)(void *)) ++ function, ++ arg); ++ ++ if (0 == code) { ++ st = introduce_thread(tmp); ++ } ++ ++ if (NULL == st) { ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%lx", ++ code, (unsigned long)st)); ++ abort(); ++ } ++ return st; ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Mailbox */ ++err_t ++sys_mbox_new(struct sys_mbox **mb, int size) ++{ ++ struct sys_mbox *mbox; ++ LWIP_UNUSED_ARG(size); ++ ++ mbox = (struct sys_mbox *)malloc(sizeof(struct sys_mbox)); ++ if (mbox == NULL) { ++ return ERR_MEM; ++ } ++ mbox->first = mbox->last = 0; ++ mbox->not_empty = sys_sem_new_internal(0); ++ mbox->not_full = sys_sem_new_internal(0); ++ mbox->mutex = sys_sem_new_internal(1); ++ mbox->wait_send = 0; ++ ++ SYS_STATS_INC_USED(mbox); ++ *mb = mbox; ++ return ERR_OK; ++} ++ ++void ++sys_mbox_free(struct sys_mbox **mb) ++{ ++ if ((mb != NULL) && (*mb != SYS_MBOX_NULL)) { ++ struct sys_mbox *mbox = *mb; ++ SYS_STATS_DEC(mbox.used); ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ ++ sys_sem_free_internal(mbox->not_empty); ++ sys_sem_free_internal(mbox->not_full); ++ sys_sem_free_internal(mbox->mutex); ++ mbox->not_empty = mbox->not_full = mbox->mutex = NULL; ++ /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */ ++ free(mbox); ++ } ++} ++ ++err_t ++sys_mbox_trypost(struct sys_mbox **mb, void *msg) ++{ ++ u8_t first; ++ struct sys_mbox *mbox; ++ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); ++ mbox = *mb; ++ ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n", ++ (void *)mbox, (void *)msg)); ++ ++ if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { ++ sys_sem_signal(&mbox->mutex); ++ return ERR_MEM; ++ } ++ ++ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; ++ ++ if (mbox->last == mbox->first) { ++ first = 1; ++ } else { ++ first = 0; ++ } ++ ++ mbox->last++; ++ ++ if (first) { ++ sys_sem_signal(&mbox->not_empty); ++ } ++ ++ sys_sem_signal(&mbox->mutex); ++ ++ return ERR_OK; ++} ++ ++void ++sys_mbox_post(struct sys_mbox **mb, void *msg) ++{ ++ u8_t first; ++ struct sys_mbox *mbox; ++ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); ++ mbox = *mb; ++ ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg)); ++ ++ while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { ++ mbox->wait_send++; ++ sys_sem_signal(&mbox->mutex); ++ sys_arch_sem_wait(&mbox->not_full, 0); ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ mbox->wait_send--; ++ } ++ ++ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; ++ ++ if (mbox->last == mbox->first) { ++ first = 1; ++ } else { ++ first = 0; ++ } ++ ++ mbox->last++; ++ ++ if (first) { ++ sys_sem_signal(&mbox->not_empty); ++ } ++ ++ sys_sem_signal(&mbox->mutex); ++} ++ ++u32_t ++sys_arch_mbox_tryfetch(struct sys_mbox **mb, void **msg) ++{ ++ struct sys_mbox *mbox; ++ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); ++ mbox = *mb; ++ ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ ++ if (mbox->first == mbox->last) { ++ sys_sem_signal(&mbox->mutex); ++ return SYS_MBOX_EMPTY; ++ } ++ ++ if (msg != NULL) { ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg)); ++ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; ++ } ++ else{ ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox)); ++ } ++ ++ mbox->first++; ++ ++ if (mbox->wait_send) { ++ sys_sem_signal(&mbox->not_full); ++ } ++ ++ sys_sem_signal(&mbox->mutex); ++ ++ return 0; ++} ++ ++u32_t ++sys_arch_mbox_fetch(struct sys_mbox **mb, void **msg, u32_t timeout) ++{ ++ u32_t time_needed = 0; ++ struct sys_mbox *mbox; ++ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); ++ mbox = *mb; ++ ++ /* The mutex lock is quick so we don't bother with the timeout ++ stuff here. */ ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ ++ while (mbox->first == mbox->last) { ++ sys_sem_signal(&mbox->mutex); ++ ++ /* We block while waiting for a mail to arrive in the mailbox. We ++ must be prepared to timeout. */ ++ if (timeout != 0) { ++ time_needed = sys_arch_sem_wait(&mbox->not_empty, timeout); ++ ++ if (time_needed == SYS_ARCH_TIMEOUT) { ++ return SYS_ARCH_TIMEOUT; ++ } ++ } else { ++ sys_arch_sem_wait(&mbox->not_empty, 0); ++ } ++ ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ } ++ ++ if (msg != NULL) { ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg)); ++ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; ++ } ++ else{ ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox)); ++ } ++ ++ mbox->first++; ++ ++ if (mbox->wait_send) { ++ sys_sem_signal(&mbox->not_full); ++ } ++ ++ sys_sem_signal(&mbox->mutex); ++ ++ return time_needed; ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Semaphore */ ++static struct sys_sem * ++sys_sem_new_internal(u8_t count) ++{ ++ struct sys_sem *sem; ++ ++ sem = (struct sys_sem *)malloc(sizeof(struct sys_sem)); ++ if (sem != NULL) { ++ sem->c = count; ++ pthread_condattr_init(&(sem->condattr)); ++#if !(defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21)) ++ pthread_condattr_setclock(&(sem->condattr), CLOCK_MONOTONIC); ++#endif ++ pthread_cond_init(&(sem->cond), &(sem->condattr)); ++ pthread_mutex_init(&(sem->mutex), NULL); ++ } ++ return sem; ++} ++ ++err_t ++sys_sem_new(struct sys_sem **sem, u8_t count) ++{ ++ SYS_STATS_INC_USED(sem); ++ *sem = sys_sem_new_internal(count); ++ if (*sem == NULL) { ++ return ERR_MEM; ++ } ++ return ERR_OK; ++} ++ ++/* ++ * Like cond_wait(), but it calls Hurd's non portable ++ * functions to receive cancellation requests ++ */ ++static u32_t ++cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout) ++{ ++ struct timespec rtime1, rtime2, ts; ++ int ret; ++ ++#ifdef __GNU__ ++ #define pthread_cond_wait pthread_hurd_cond_wait_np ++ #define pthread_cond_timedwait pthread_hurd_cond_timedwait_np ++#endif ++ ++ if (timeout == 0) { ++ ret = pthread_cond_wait(cond, mutex); ++ return ret; ++ } ++ ++ /* Get a timestamp and add the timeout value. */ ++ get_monotonic_time(&rtime1); ++#if defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21) ++ ts.tv_sec = timeout / 1000L; ++ ts.tv_nsec = (timeout % 1000L) * 1000000L; ++ ret = pthread_cond_timedwait_relative_np(cond, mutex, &ts); ++#else ++ ts.tv_sec = rtime1.tv_sec + timeout / 1000L; ++ ts.tv_nsec = rtime1.tv_nsec + (timeout % 1000L) * 1000000L; ++ if (ts.tv_nsec >= 1000000000L) { ++ ts.tv_sec++; ++ ts.tv_nsec -= 1000000000L; ++ } ++ ++ ret = pthread_cond_timedwait(cond, mutex, &ts); ++#endif ++ if (ret == ETIMEDOUT) { ++ return SYS_ARCH_TIMEOUT; ++ } else if (ret == EINTR) { ++ return SYS_ARCH_INTR; ++ } ++ ++ /* Calculate for how long we waited for the cond. */ ++ get_monotonic_time(&rtime2); ++ ts.tv_sec = rtime2.tv_sec - rtime1.tv_sec; ++ ts.tv_nsec = rtime2.tv_nsec - rtime1.tv_nsec; ++ if (ts.tv_nsec < 0) { ++ ts.tv_sec--; ++ ts.tv_nsec += 1000000000L; ++ } ++ return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); ++} ++ ++/* ++ * Like sys_arch_sem_wait(), but it handles thread cancellations. ++ */ ++u32_t ++sys_arch_sem_wait(struct sys_sem **s, u32_t timeout) ++{ ++ u32_t time_needed = 0; ++ struct sys_sem *sem; ++ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); ++ sem = *s; ++ ++ pthread_mutex_lock(&(sem->mutex)); ++ while (sem->c <= 0) { ++ if (timeout > 0) { ++ time_needed = cond_wait(&(sem->cond), &(sem->mutex), timeout); ++ ++ if (time_needed == SYS_ARCH_TIMEOUT) { ++ pthread_mutex_unlock(&(sem->mutex)); ++ return SYS_ARCH_TIMEOUT; ++ } else if(time_needed == SYS_ARCH_INTR) { ++ /* This means we were interrupted */ ++ pthread_mutex_unlock(&(sem->mutex)); ++ return SYS_ARCH_INTR; ++ } ++ } else { ++ if(cond_wait(&(sem->cond), &(sem->mutex), 0)) { ++ /* This means we were interrupted */ ++ pthread_mutex_unlock(&(sem->mutex)); ++ return SYS_ARCH_INTR; ++ } ++ } ++ } ++ sem->c--; ++ pthread_mutex_unlock(&(sem->mutex)); ++ return (u32_t)time_needed; ++} ++ ++void ++sys_sem_signal(struct sys_sem **s) ++{ ++ struct sys_sem *sem; ++ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); ++ sem = *s; ++ ++ pthread_mutex_lock(&(sem->mutex)); ++ sem->c++; ++ ++ if (sem->c > 1) { ++ sem->c = 1; ++ } ++ ++ pthread_cond_broadcast(&(sem->cond)); ++ pthread_mutex_unlock(&(sem->mutex)); ++} ++ ++static void ++sys_sem_free_internal(struct sys_sem *sem) ++{ ++ pthread_cond_destroy(&(sem->cond)); ++ pthread_condattr_destroy(&(sem->condattr)); ++ pthread_mutex_destroy(&(sem->mutex)); ++ free(sem); ++} ++ ++void ++sys_sem_free(struct sys_sem **sem) ++{ ++ if ((sem != NULL) && (*sem != SYS_SEM_NULL)) { ++ SYS_STATS_DEC(sem.used); ++ sys_sem_free_internal(*sem); ++ } ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Mutex */ ++/** Create a new mutex ++ * @param mutex pointer to the mutex to create ++ * @return a new mutex */ ++err_t ++sys_mutex_new(struct sys_mutex **mutex) ++{ ++ struct sys_mutex *mtx; ++ ++ mtx = (struct sys_mutex *)malloc(sizeof(struct sys_mutex)); ++ if (mtx != NULL) { ++ pthread_mutex_init(&(mtx->mutex), NULL); ++ *mutex = mtx; ++ return ERR_OK; ++ } ++ else { ++ return ERR_MEM; ++ } ++} ++ ++/** Lock a mutex ++ * @param mutex the mutex to lock */ ++void ++sys_mutex_lock(struct sys_mutex **mutex) ++{ ++ pthread_mutex_lock(&((*mutex)->mutex)); ++} ++ ++/** Unlock a mutex ++ * @param mutex the mutex to unlock */ ++void ++sys_mutex_unlock(struct sys_mutex **mutex) ++{ ++ pthread_mutex_unlock(&((*mutex)->mutex)); ++} ++ ++/** Delete a mutex ++ * @param mutex the mutex to delete */ ++void ++sys_mutex_free(struct sys_mutex **mutex) ++{ ++ pthread_mutex_destroy(&((*mutex)->mutex)); ++ free(*mutex); ++} ++ ++#endif /* !NO_SYS */ ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Time */ ++u32_t ++sys_now(void) ++{ ++ struct timespec ts; ++ ++ get_monotonic_time(&ts); ++ return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); ++} ++ ++u32_t ++sys_jiffies(void) ++{ ++ struct timespec ts; ++ ++ get_monotonic_time(&ts); ++ return (u32_t)(ts.tv_sec * 1000000000L + ts.tv_nsec); ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Init */ ++ ++void ++sys_init(void) ++{ ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Critical section */ ++#if SYS_LIGHTWEIGHT_PROT ++/** sys_prot_t sys_arch_protect(void) ++ ++This optional function does a "fast" critical region protection and returns ++the previous protection level. This function is only called during very short ++critical regions. An embedded system which supports ISR-based drivers might ++want to implement this function by disabling interrupts. Task-based systems ++might want to implement this by using a mutex or disabling tasking. This ++function should support recursive calls from the same task or interrupt. In ++other words, sys_arch_protect() could be called while already protected. In ++that case the return value indicates that it is already protected. ++ ++sys_arch_protect() is only required if your port is supporting an operating ++system. ++*/ ++sys_prot_t ++sys_arch_protect(void) ++{ ++ /* Note that for the UNIX port, we are using a lightweight mutex, and our ++ * own counter (which is locked by the mutex). The return code is not actually ++ * used. */ ++ if (lwprot_thread != pthread_self()) ++ { ++ /* We are locking the mutex where it has not been locked before * ++ * or is being locked by another thread */ ++ pthread_mutex_lock(&lwprot_mutex); ++ lwprot_thread = pthread_self(); ++ lwprot_count = 1; ++ } ++ else ++ /* It is already locked by THIS thread */ ++ lwprot_count++; ++ return 0; ++} ++ ++/** void sys_arch_unprotect(sys_prot_t pval) ++ ++This optional function does a "fast" set of critical region protection to the ++value specified by pval. See the documentation for sys_arch_protect() for ++more information. This function is only required if your port is supporting ++an operating system. ++*/ ++void ++sys_arch_unprotect(sys_prot_t pval) ++{ ++ LWIP_UNUSED_ARG(pval); ++ if (lwprot_thread == pthread_self()) ++ { ++ if (--lwprot_count == 0) ++ { ++ lwprot_thread = (pthread_t) 0xDEAD; ++ pthread_mutex_unlock(&lwprot_mutex); ++ } ++ } ++} ++#endif /* SYS_LIGHTWEIGHT_PROT */ diff -Nru lwip-2.0.3/debian/patches/posix lwip-2.0.3/debian/patches/posix --- lwip-2.0.3/debian/patches/posix 2018-04-30 23:29:51.000000000 +0000 +++ lwip-2.0.3/debian/patches/posix 2018-08-28 21:27:25.000000000 +0000 @@ -18,117 +18,117 @@ --- /dev/null +++ b/port/include/posix/inet.h @@ -0,0 +1,63 @@ -+/* -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ Written by Joan Lledó. -+ -+ This file is part of the GNU Hurd. -+ -+ The GNU Hurd is free software; you can redistribute it and/or -+ modify it under the terms of the GNU General Public License as -+ published by the Free Software Foundation; either version 2, or (at -+ your option) any later version. -+ -+ The GNU Hurd is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with the GNU Hurd. If not, see . */ -+ -+#ifndef HURD_LWIP_POSIX_INET_H -+#define HURD_LWIP_POSIX_INET_H -+ -+#include -+#include -+#include -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#define SIN_ZERO_LEN sizeof (struct sockaddr) - \ -+ __SOCKADDR_COMMON_SIZE - \ -+ sizeof (in_port_t) - \ -+ sizeof (struct in_addr) -+ -+#if LWIP_IPV4 -+ -+#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) -+#define inet_addr_to_ip4addr(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 ip4_addr_t are an u32_t effectively! */ -+#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) -+ -+#endif /* LWIP_IPV4 */ -+ -+#if LWIP_IPV6 -+#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->s6_addr32[0] = (source_ip6addr)->addr[0]; \ -+ (target_in6addr)->s6_addr32[1] = (source_ip6addr)->addr[1]; \ -+ (target_in6addr)->s6_addr32[2] = (source_ip6addr)->addr[2]; \ -+ (target_in6addr)->s6_addr32[3] = (source_ip6addr)->addr[3];} -+#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->s6_addr32[0]; \ -+ (target_ip6addr)->addr[1] = (source_in6addr)->s6_addr32[1]; \ -+ (target_ip6addr)->addr[2] = (source_in6addr)->s6_addr32[2]; \ -+ (target_ip6addr)->addr[3] = (source_in6addr)->s6_addr32[3];} -+/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ -+#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) -+#endif /* LWIP_IPV6 */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* HURD_LWIP_POSIX_INET_H */ ++/* ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ Written by Joan Lledó. ++ ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License as ++ published by the Free Software Foundation; either version 2, or (at ++ your option) any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with the GNU Hurd. If not, see . */ ++ ++#ifndef HURD_LWIP_POSIX_INET_H ++#define HURD_LWIP_POSIX_INET_H ++ ++#include ++#include ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define SIN_ZERO_LEN sizeof (struct sockaddr) - \ ++ __SOCKADDR_COMMON_SIZE - \ ++ sizeof (in_port_t) - \ ++ sizeof (struct in_addr) ++ ++#if LWIP_IPV4 ++ ++#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) ++#define inet_addr_to_ip4addr(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 ip4_addr_t are an u32_t effectively! */ ++#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) ++ ++#endif /* LWIP_IPV4 */ ++ ++#if LWIP_IPV6 ++#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->s6_addr32[0] = (source_ip6addr)->addr[0]; \ ++ (target_in6addr)->s6_addr32[1] = (source_ip6addr)->addr[1]; \ ++ (target_in6addr)->s6_addr32[2] = (source_ip6addr)->addr[2]; \ ++ (target_in6addr)->s6_addr32[3] = (source_ip6addr)->addr[3];} ++#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->s6_addr32[0]; \ ++ (target_ip6addr)->addr[1] = (source_in6addr)->s6_addr32[1]; \ ++ (target_ip6addr)->addr[2] = (source_in6addr)->s6_addr32[2]; \ ++ (target_ip6addr)->addr[3] = (source_in6addr)->s6_addr32[3];} ++/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ ++#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) ++#endif /* LWIP_IPV6 */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* HURD_LWIP_POSIX_INET_H */ --- /dev/null +++ b/port/include/posix/socket.h @@ -0,0 +1,45 @@ -+/* -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ Written by Joan Lledó. -+ -+ This file is part of the GNU Hurd. -+ -+ The GNU Hurd is free software; you can redistribute it and/or -+ modify it under the terms of the GNU General Public License as -+ published by the Free Software Foundation; either version 2, or (at -+ your option) any later version. -+ -+ The GNU Hurd is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with the GNU Hurd. If not, see . */ -+ -+#ifndef HURD_LWIP_POSIX_SOCKET_H -+#define HURD_LWIP_POSIX_SOCKET_H -+ -+#include -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/* Unsuported indetifiers */ -+#ifndef SO_NO_CHECK -+#define SO_NO_CHECK 0x0 -+#endif -+#ifndef MSG_MORE -+#define MSG_MORE 0x0 -+#endif -+#ifndef TCP_KEEPALIVE -+#define TCP_KEEPALIVE 0x0 -+#endif -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* HURD_LWIP_POSIX_SOCKET_H */ ++/* ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ Written by Joan Lledó. ++ ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License as ++ published by the Free Software Foundation; either version 2, or (at ++ your option) any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with the GNU Hurd. If not, see . */ ++ ++#ifndef HURD_LWIP_POSIX_SOCKET_H ++#define HURD_LWIP_POSIX_SOCKET_H ++ ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Unsuported indetifiers */ ++#ifndef SO_NO_CHECK ++#define SO_NO_CHECK 0x0 ++#endif ++#ifndef MSG_MORE ++#define MSG_MORE 0x0 ++#endif ++#ifndef TCP_KEEPALIVE ++#define TCP_KEEPALIVE 0x0 ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* HURD_LWIP_POSIX_SOCKET_H */ --- a/src/include/lwip/inet.h +++ b/src/include/lwip/inet.h @@ -41,132 +41,11 @@ @@ -270,7 +270,7 @@ #endif /* LWIP_HDR_INET_H */ --- a/src/include/lwip/ip.h +++ b/src/include/lwip/ip.h -@@ -94,9 +94,16 @@ struct ip_pcb { +@@ -94,9 +94,16 @@ /* * Option flags per-socket. These are the same like SO_XXX in sockets.h */ @@ -290,742 +290,742 @@ --- /dev/null +++ b/src/include/lwip/lwip_inet.h @@ -0,0 +1,164 @@ -+/* -+ * 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 -+ * -+ */ -+#ifndef LWIP_HDR_PRIV_INET_H -+#define LWIP_HDR_PRIV_INET_H -+ -+#include "lwip/opt.h" -+#include "lwip/def.h" -+#include "lwip/ip_addr.h" -+#include "lwip/ip6_addr.h" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED -+ to prevent this code from redefining it. */ -+#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) -+typedef u32_t in_addr_t; -+#endif -+ -+struct in_addr { -+ in_addr_t s_addr; -+}; -+ -+struct in6_addr { -+ union { -+ u32_t u32_addr[4]; -+ u8_t u8_addr[16]; -+ } un; -+#define s6_addr un.u8_addr -+}; -+ -+/** 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 -+ -+/** This macro can be used to initialize a variable of type struct in6_addr -+ to the IPv6 wildcard address. */ -+#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} -+/** This macro can be used to initialize a variable of type struct in6_addr -+ to the IPv6 loopback address. */ -+#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} -+/** This variable is initialized by the system to contain the wildcard IPv6 address. */ -+extern const struct in6_addr in6addr_any; -+ -+/* Definitions of the bits in an (IPv4) 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 -+ -+ -+#ifndef INET_ADDRSTRLEN -+#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX -+#endif -+#if LWIP_IPV6 -+#ifndef INET6_ADDRSTRLEN -+#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX -+#endif -+#endif -+ -+#if LWIP_IPV4 -+ -+#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) -+#define inet_addr_to_ip4addr(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 ip4_addr_t are an u32_t effectively! */ -+#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) -+ -+/* directly map this to the lwip internal functions */ -+#define inet_addr(cp) ipaddr_addr(cp) -+#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) -+#define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) -+#define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) -+ -+#endif /* LWIP_IPV4 */ -+ -+#if LWIP_IPV6 -+#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ -+ (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ -+ (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ -+ (target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];} -+#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \ -+ (target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \ -+ (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ -+ (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];} -+/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ -+#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) -+ -+/* directly map this to the lwip internal functions */ -+#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) -+#define inet6_ntoa(addr) ip6addr_ntoa((const ip6_addr_t*)&(addr)) -+#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) -+ -+#endif /* LWIP_IPV6 */ -+ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* LWIP_HDR_PRIV_INET_H */ ++/* ++ * 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 ++ * ++ */ ++#ifndef LWIP_HDR_PRIV_INET_H ++#define LWIP_HDR_PRIV_INET_H ++ ++#include "lwip/opt.h" ++#include "lwip/def.h" ++#include "lwip/ip_addr.h" ++#include "lwip/ip6_addr.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED ++ to prevent this code from redefining it. */ ++#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) ++typedef u32_t in_addr_t; ++#endif ++ ++struct in_addr { ++ in_addr_t s_addr; ++}; ++ ++struct in6_addr { ++ union { ++ u32_t u32_addr[4]; ++ u8_t u8_addr[16]; ++ } un; ++#define s6_addr un.u8_addr ++}; ++ ++/** 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 ++ ++/** This macro can be used to initialize a variable of type struct in6_addr ++ to the IPv6 wildcard address. */ ++#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} ++/** This macro can be used to initialize a variable of type struct in6_addr ++ to the IPv6 loopback address. */ ++#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} ++/** This variable is initialized by the system to contain the wildcard IPv6 address. */ ++extern const struct in6_addr in6addr_any; ++ ++/* Definitions of the bits in an (IPv4) 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 ++ ++ ++#ifndef INET_ADDRSTRLEN ++#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX ++#endif ++#if LWIP_IPV6 ++#ifndef INET6_ADDRSTRLEN ++#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX ++#endif ++#endif ++ ++#if LWIP_IPV4 ++ ++#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) ++#define inet_addr_to_ip4addr(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 ip4_addr_t are an u32_t effectively! */ ++#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) ++ ++/* directly map this to the lwip internal functions */ ++#define inet_addr(cp) ipaddr_addr(cp) ++#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) ++#define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) ++#define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) ++ ++#endif /* LWIP_IPV4 */ ++ ++#if LWIP_IPV6 ++#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ ++ (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ ++ (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ ++ (target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];} ++#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \ ++ (target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \ ++ (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ ++ (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];} ++/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ ++#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) ++ ++/* directly map this to the lwip internal functions */ ++#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) ++#define inet6_ntoa(addr) ip6addr_ntoa((const ip6_addr_t*)&(addr)) ++#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) ++ ++#endif /* LWIP_IPV6 */ ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LWIP_HDR_PRIV_INET_H */ --- /dev/null +++ b/src/include/lwip/lwip_sockets.h @@ -0,0 +1,569 @@ -+/** -+ * @file -+ * Socket API (to be used from non-TCPIP threads) -+ */ -+ -+/* -+ * 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 -+ * -+ */ -+ -+ -+#ifndef LWIP_HDR_PRIV_SOCKETS_H -+#define LWIP_HDR_PRIV_SOCKETS_H -+ -+#include "lwip/opt.h" -+ -+#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ -+ -+#include "lwip/ip_addr.h" -+#include "lwip/err.h" -+#include "lwip/inet.h" -+#include "lwip/errno.h" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#define _HAVE_SA_LEN 1 -+ -+/* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED -+ to prevent this code from redefining it. */ -+#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) -+typedef u8_t sa_family_t; -+#endif -+/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED -+ to prevent this code from redefining it. */ -+#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) -+typedef u16_t in_port_t; -+#endif -+ -+#if LWIP_IPV4 -+/* members are in network byte order */ -+struct sockaddr_in { -+ u8_t sin_len; -+ sa_family_t sin_family; -+ in_port_t sin_port; -+ struct in_addr sin_addr; -+#define SIN_ZERO_LEN 8 -+ char sin_zero[SIN_ZERO_LEN]; -+}; -+#endif /* LWIP_IPV4 */ -+ -+#if LWIP_IPV6 -+struct sockaddr_in6 { -+ u8_t sin6_len; /* length of this structure */ -+ sa_family_t sin6_family; /* AF_INET6 */ -+ in_port_t sin6_port; /* Transport layer port # */ -+ u32_t sin6_flowinfo; /* IPv6 flow information */ -+ struct in6_addr sin6_addr; /* IPv6 address */ -+ u32_t sin6_scope_id; /* Set of interfaces for scope */ -+}; -+#endif /* LWIP_IPV6 */ -+ -+struct sockaddr { -+ u8_t sa_len; -+ sa_family_t sa_family; -+ char sa_data[14]; -+}; -+ -+struct sockaddr_storage { -+ u8_t s2_len; -+ sa_family_t ss_family; -+ char s2_data1[2]; -+ u32_t s2_data2[3]; -+#if LWIP_IPV6 -+ u32_t s2_data3[3]; -+#endif /* LWIP_IPV6 */ -+}; -+ -+/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED -+ to prevent this code from redefining it. */ -+#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) -+typedef u32_t socklen_t; -+#endif -+ -+struct lwip_sock; -+ -+#if !LWIP_TCPIP_CORE_LOCKING -+/** Maximum optlen used by setsockopt/getsockopt */ -+#define LWIP_SETGETSOCKOPT_MAXOPTLEN 16 -+ -+/** This struct is used to pass data to the set/getsockopt_internal -+ * functions running in tcpip_thread context (only a void* is allowed) */ -+struct lwip_setgetsockopt_data { -+ /** socket index for which to change options */ -+ int s; -+ /** level of the option to process */ -+ int level; -+ /** name of the option to process */ -+ int optname; -+ /** set: value to set the option to -+ * get: value of the option is stored here */ -+#if LWIP_MPU_COMPATIBLE -+ u8_t optval[LWIP_SETGETSOCKOPT_MAXOPTLEN]; -+#else -+ union { -+ void *p; -+ const void *pc; -+ } optval; -+#endif -+ /** size of *optval */ -+ socklen_t optlen; -+ /** if an error occurs, it is temporarily stored here */ -+ err_t err; -+ /** semaphore to wake up the calling task */ -+ void* completed_sem; -+}; -+#endif /* !LWIP_TCPIP_CORE_LOCKING */ -+ -+#if !defined(iovec) -+struct iovec { -+ void *iov_base; -+ size_t iov_len; -+}; -+#endif -+ -+struct msghdr { -+ void *msg_name; -+ socklen_t msg_namelen; -+ struct iovec *msg_iov; -+ int msg_iovlen; -+ void *msg_control; -+ socklen_t msg_controllen; -+ int msg_flags; -+}; -+ -+/* Socket protocol types (TCP/UDP/RAW) */ -+#define SOCK_STREAM 1 -+#define SOCK_DGRAM 2 -+#define SOCK_RAW 3 -+ -+/* -+ * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) -+ */ -+#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ -+#define SO_KEEPALIVE 0x0008 /* keep connections alive */ -+#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ -+ -+ -+/* -+ * Additional options, not kept in so_options. -+ */ -+#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ -+#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ -+#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ -+#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ -+#define SO_LINGER 0x0080 /* linger on close if data present */ -+#define SO_DONTLINGER ((int)(~SO_LINGER)) -+#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ -+#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ -+#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ -+#define SO_RCVBUF 0x1002 /* receive buffer size */ -+#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ -+#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ -+#define SO_SNDTIMEO 0x1005 /* send timeout */ -+#define SO_RCVTIMEO 0x1006 /* receive timeout */ -+#define SO_ERROR 0x1007 /* get error status and clear */ -+#define SO_TYPE 0x1008 /* get socket type */ -+#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ -+#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ -+ -+ -+/* -+ * Structure used for manipulating linger option. -+ */ -+struct linger { -+ int l_onoff; /* option on/off */ -+ int l_linger; /* linger time in seconds */ -+}; -+ -+/* -+ * Level number for (get/set)sockopt() to apply to socket itself. -+ */ -+#define SOL_SOCKET 0xfff /* options for socket level */ -+ -+ -+#define AF_UNSPEC 0 -+#define AF_INET 2 -+#if LWIP_IPV6 -+#define AF_INET6 10 -+#else /* LWIP_IPV6 */ -+#define AF_INET6 AF_UNSPEC -+#endif /* LWIP_IPV6 */ -+#define PF_INET AF_INET -+#define PF_INET6 AF_INET6 -+#define PF_UNSPEC AF_UNSPEC -+ -+#define IPPROTO_IP 0 -+#define IPPROTO_ICMP 1 -+#define IPPROTO_TCP 6 -+#define IPPROTO_UDP 17 -+#if LWIP_IPV6 -+#define IPPROTO_IPV6 41 -+#define IPPROTO_ICMPV6 58 -+#endif /* LWIP_IPV6 */ -+#define IPPROTO_UDPLITE 136 -+#define IPPROTO_RAW 255 -+ -+/* Flags we can use with send and recv. */ -+#define MSG_PEEK 0x01 /* Peeks at an incoming message */ -+#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ -+#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ -+#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ -+#define MSG_MORE 0x10 /* Sender will send more */ -+ -+ -+/* -+ * Options for level IPPROTO_IP -+ */ -+#define IP_TOS 1 -+#define IP_TTL 2 -+ -+#if LWIP_TCP -+/* -+ * Options for level IPPROTO_TCP -+ */ -+#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ -+#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ -+#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ -+#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ -+#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ -+#endif /* LWIP_TCP */ -+ -+#if LWIP_IPV6 -+/* -+ * Options for level IPPROTO_IPV6 -+ */ -+#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ -+#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ -+#endif /* LWIP_IPV6 */ -+ -+#if LWIP_UDP && LWIP_UDPLITE -+/* -+ * Options for level IPPROTO_UDPLITE -+ */ -+#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ -+#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ -+#endif /* LWIP_UDP && LWIP_UDPLITE*/ -+ -+ -+#if LWIP_MULTICAST_TX_OPTIONS -+/* -+ * Options and types for UDP multicast traffic handling -+ */ -+#define IP_MULTICAST_TTL 5 -+#define IP_MULTICAST_IF 6 -+#define IP_MULTICAST_LOOP 7 -+#endif /* LWIP_MULTICAST_TX_OPTIONS */ -+ -+#if LWIP_IGMP -+/* -+ * Options and types related to multicast membership -+ */ -+#define IP_ADD_MEMBERSHIP 3 -+#define IP_DROP_MEMBERSHIP 4 -+ -+typedef struct ip_mreq { -+ struct in_addr imr_multiaddr; /* IP multicast address of group */ -+ struct in_addr imr_interface; /* local IP address of interface */ -+} ip_mreq; -+#endif /* LWIP_IGMP */ -+ -+/* -+ * The Type of Service provides an indication of the abstract -+ * parameters of the quality of service desired. These parameters are -+ * to be used to guide the selection of the actual service parameters -+ * when transmitting a datagram through a particular network. Several -+ * networks offer service precedence, which somehow treats high -+ * precedence traffic as more important than other traffic (generally -+ * by accepting only traffic above a certain precedence at time of high -+ * load). The major choice is a three way tradeoff between low-delay, -+ * high-reliability, and high-throughput. -+ * The use of the Delay, Throughput, and Reliability indications may -+ * increase the cost (in some sense) of the service. In many networks -+ * better performance for one of these parameters is coupled with worse -+ * performance on another. Except for very unusual cases at most two -+ * of these three indications should be set. -+ */ -+#define IPTOS_TOS_MASK 0x1E -+#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) -+#define IPTOS_LOWDELAY 0x10 -+#define IPTOS_THROUGHPUT 0x08 -+#define IPTOS_RELIABILITY 0x04 -+#define IPTOS_LOWCOST 0x02 -+#define IPTOS_MINCOST IPTOS_LOWCOST -+ -+/* -+ * The Network Control precedence designation is intended to be used -+ * within a network only. The actual use and control of that -+ * designation is up to each network. The Internetwork Control -+ * designation is intended for use by gateway control originators only. -+ * If the actual use of these precedence designations is of concern to -+ * a particular network, it is the responsibility of that network to -+ * control the access to, and use of, those precedence designations. -+ */ -+#define IPTOS_PREC_MASK 0xe0 -+#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) -+#define IPTOS_PREC_NETCONTROL 0xe0 -+#define IPTOS_PREC_INTERNETCONTROL 0xc0 -+#define IPTOS_PREC_CRITIC_ECP 0xa0 -+#define IPTOS_PREC_FLASHOVERRIDE 0x80 -+#define IPTOS_PREC_FLASH 0x60 -+#define IPTOS_PREC_IMMEDIATE 0x40 -+#define IPTOS_PREC_PRIORITY 0x20 -+#define IPTOS_PREC_ROUTINE 0x00 -+ -+ -+/* -+ * Commands for ioctlsocket(), taken from the BSD file fcntl.h. -+ * lwip_ioctl only supports FIONREAD and FIONBIO, for now -+ * -+ * Ioctl's have the command encoded in the lower word, -+ * and the size of any in or out parameters in the upper -+ * word. The high 2 bits of the upper word are used -+ * to encode the in/out status of the parameter; for now -+ * we restrict parameters to at most 128 bytes. -+ */ -+#if !defined(FIONREAD) || !defined(FIONBIO) -+#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ -+#define IOC_VOID 0x20000000UL /* no parameters */ -+#define IOC_OUT 0x40000000UL /* copy out parameters */ -+#define IOC_IN 0x80000000UL /* copy in parameters */ -+#define IOC_INOUT (IOC_IN|IOC_OUT) -+ /* 0x20000000 distinguishes new & -+ old ioctl's */ -+#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) -+ -+#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) -+ -+#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) -+#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ -+ -+#ifndef FIONREAD -+#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ -+#endif -+#ifndef FIONBIO -+#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ -+#endif -+ -+/* Socket I/O Controls: unimplemented */ -+#ifndef SIOCSHIWAT -+#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ -+#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ -+#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ -+#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ -+#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ -+#endif -+ -+/* 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 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 */ -+#ifndef FD_SET -+#undef FD_SETSIZE -+/* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ -+#define FD_SETSIZE MEMP_NUM_NETCONN -+#define FDSETSAFESET(n, code) do { \ -+ if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \ -+ code; }} while(0) -+#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ -+ (code) : 0) -+#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -+#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -+#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -+#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) -+ -+typedef struct fd_set -+{ -+ unsigned char fd_bits [(FD_SETSIZE+7)/8]; -+} fd_set; -+ -+#elif LWIP_SOCKET_OFFSET -+#error LWIP_SOCKET_OFFSET does not work with external FD_SET! -+#elif FD_SETSIZE < MEMP_NUM_NETCONN -+#error "external FD_SETSIZE too small for number of sockets" -+#endif /* FD_SET */ -+ -+/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided -+ * by your system, set this to 0 and include in cc.h */ -+#ifndef LWIP_TIMEVAL_PRIVATE -+#define LWIP_TIMEVAL_PRIVATE 1 -+#endif -+ -+#if LWIP_TIMEVAL_PRIVATE -+struct timeval { -+ long tv_sec; /* seconds */ -+ long tv_usec; /* and microseconds */ -+}; -+#endif /* LWIP_TIMEVAL_PRIVATE */ -+ -+#define lwip_socket_init() /* Compatibility define, no init needed. */ -+void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ -+void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ -+ -+#if LWIP_COMPAT_SOCKETS == 2 -+/* This helps code parsers/code completion by not having the COMPAT functions as defines */ -+#define lwip_accept accept -+#define lwip_bind bind -+#define lwip_shutdown shutdown -+#define lwip_getpeername getpeername -+#define lwip_getsockname getsockname -+#define lwip_setsockopt setsockopt -+#define lwip_getsockopt getsockopt -+#define lwip_close closesocket -+#define lwip_connect connect -+#define lwip_listen listen -+#define lwip_recv recv -+#define lwip_recvfrom recvfrom -+#define lwip_send send -+#define lwip_sendmsg sendmsg -+#define lwip_sendto sendto -+#define lwip_socket socket -+#define lwip_select select -+#define lwip_ioctlsocket ioctl -+ -+#if LWIP_POSIX_SOCKETS_IO_NAMES -+#define lwip_read read -+#define lwip_write write -+#define lwip_writev writev -+#undef lwip_close -+#define lwip_close close -+#define closesocket(s) close(s) -+#define lwip_fcntl fcntl -+#define lwip_ioctl ioctl -+#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ -+#endif /* LWIP_COMPAT_SOCKETS == 2 */ -+ -+#if LWIP_COMPAT_SOCKETS -+#if LWIP_COMPAT_SOCKETS != 2 -+/** @ingroup socket */ -+#define accept(s,addr,addrlen) lwip_accept(s,addr,addrlen) -+/** @ingroup socket */ -+#define bind(s,name,namelen) lwip_bind(s,name,namelen) -+/** @ingroup socket */ -+#define shutdown(s,how) lwip_shutdown(s,how) -+/** @ingroup socket */ -+#define getpeername(s,name,namelen) lwip_getpeername(s,name,namelen) -+/** @ingroup socket */ -+#define getsockname(s,name,namelen) lwip_getsockname(s,name,namelen) -+/** @ingroup socket */ -+#define setsockopt(s,level,optname,opval,optlen) lwip_setsockopt(s,level,optname,opval,optlen) -+/** @ingroup socket */ -+#define getsockopt(s,level,optname,opval,optlen) lwip_getsockopt(s,level,optname,opval,optlen) -+/** @ingroup socket */ -+#define closesocket(s) lwip_close(s) -+/** @ingroup socket */ -+#define connect(s,name,namelen) lwip_connect(s,name,namelen) -+/** @ingroup socket */ -+#define listen(s,backlog) lwip_listen(s,backlog) -+/** @ingroup socket */ -+#define recv(s,mem,len,flags) lwip_recv(s,mem,len,flags) -+/** @ingroup socket */ -+#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom(s,mem,len,flags,from,fromlen) -+/** @ingroup socket */ -+#define send(s,dataptr,size,flags) lwip_send(s,dataptr,size,flags) -+/** @ingroup socket */ -+#define sendmsg(s,message,flags) lwip_sendmsg(s,message,flags) -+/** @ingroup socket */ -+#define sendto(s,dataptr,size,flags,to,tolen) lwip_sendto(s,dataptr,size,flags,to,tolen) -+/** @ingroup socket */ -+#define socket(domain,type,protocol) lwip_socket(domain,type,protocol) -+/** @ingroup socket */ -+#define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) -+/** @ingroup socket */ -+#define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) -+ -+#if LWIP_POSIX_SOCKETS_IO_NAMES -+/** @ingroup socket */ -+#define read(s,mem,len) lwip_read(s,mem,len) -+/** @ingroup socket */ -+#define write(s,dataptr,len) lwip_write(s,dataptr,len) -+/** @ingroup socket */ -+#define writev(s,iov,iovcnt) lwip_writev(s,iov,iovcnt) -+/** @ingroup socket */ -+#define close(s) lwip_close(s) -+/** @ingroup socket */ -+#define fcntl(s,cmd,val) lwip_fcntl(s,cmd,val) -+/** @ingroup socket */ -+#define ioctl(s,cmd,argp) lwip_ioctl(s,cmd,argp) -+#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ -+#endif /* LWIP_COMPAT_SOCKETS != 2 */ -+ -+#if LWIP_IPV4 && LWIP_IPV6 -+/** @ingroup socket */ -+#define inet_ntop(af,src,dst,size) \ -+ (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) \ -+ : (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL)) -+/** @ingroup socket */ -+#define inet_pton(af,src,dst) \ -+ (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) \ -+ : (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0)) -+#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ -+#define inet_ntop(af,src,dst,size) \ -+ (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL) -+#define inet_pton(af,src,dst) \ -+ (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0) -+#else /* LWIP_IPV4 && LWIP_IPV6 */ -+#define inet_ntop(af,src,dst,size) \ -+ (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) : NULL) -+#define inet_pton(af,src,dst) \ -+ (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) : 0) -+#endif /* LWIP_IPV4 && LWIP_IPV6 */ -+ -+#endif /* LWIP_COMPAT_SOCKETS */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* LWIP_SOCKET */ -+ -+#endif /* LWIP_HDR_PRIV_SOCKETS_H */ ++/** ++ * @file ++ * Socket API (to be used from non-TCPIP threads) ++ */ ++ ++/* ++ * 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 ++ * ++ */ ++ ++ ++#ifndef LWIP_HDR_PRIV_SOCKETS_H ++#define LWIP_HDR_PRIV_SOCKETS_H ++ ++#include "lwip/opt.h" ++ ++#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ ++ ++#include "lwip/ip_addr.h" ++#include "lwip/err.h" ++#include "lwip/inet.h" ++#include "lwip/errno.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define _HAVE_SA_LEN 1 ++ ++/* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED ++ to prevent this code from redefining it. */ ++#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) ++typedef u8_t sa_family_t; ++#endif ++/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED ++ to prevent this code from redefining it. */ ++#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) ++typedef u16_t in_port_t; ++#endif ++ ++#if LWIP_IPV4 ++/* members are in network byte order */ ++struct sockaddr_in { ++ u8_t sin_len; ++ sa_family_t sin_family; ++ in_port_t sin_port; ++ struct in_addr sin_addr; ++#define SIN_ZERO_LEN 8 ++ char sin_zero[SIN_ZERO_LEN]; ++}; ++#endif /* LWIP_IPV4 */ ++ ++#if LWIP_IPV6 ++struct sockaddr_in6 { ++ u8_t sin6_len; /* length of this structure */ ++ sa_family_t sin6_family; /* AF_INET6 */ ++ in_port_t sin6_port; /* Transport layer port # */ ++ u32_t sin6_flowinfo; /* IPv6 flow information */ ++ struct in6_addr sin6_addr; /* IPv6 address */ ++ u32_t sin6_scope_id; /* Set of interfaces for scope */ ++}; ++#endif /* LWIP_IPV6 */ ++ ++struct sockaddr { ++ u8_t sa_len; ++ sa_family_t sa_family; ++ char sa_data[14]; ++}; ++ ++struct sockaddr_storage { ++ u8_t s2_len; ++ sa_family_t ss_family; ++ char s2_data1[2]; ++ u32_t s2_data2[3]; ++#if LWIP_IPV6 ++ u32_t s2_data3[3]; ++#endif /* LWIP_IPV6 */ ++}; ++ ++/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED ++ to prevent this code from redefining it. */ ++#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) ++typedef u32_t socklen_t; ++#endif ++ ++struct lwip_sock; ++ ++#if !LWIP_TCPIP_CORE_LOCKING ++/** Maximum optlen used by setsockopt/getsockopt */ ++#define LWIP_SETGETSOCKOPT_MAXOPTLEN 16 ++ ++/** This struct is used to pass data to the set/getsockopt_internal ++ * functions running in tcpip_thread context (only a void* is allowed) */ ++struct lwip_setgetsockopt_data { ++ /** socket index for which to change options */ ++ int s; ++ /** level of the option to process */ ++ int level; ++ /** name of the option to process */ ++ int optname; ++ /** set: value to set the option to ++ * get: value of the option is stored here */ ++#if LWIP_MPU_COMPATIBLE ++ u8_t optval[LWIP_SETGETSOCKOPT_MAXOPTLEN]; ++#else ++ union { ++ void *p; ++ const void *pc; ++ } optval; ++#endif ++ /** size of *optval */ ++ socklen_t optlen; ++ /** if an error occurs, it is temporarily stored here */ ++ err_t err; ++ /** semaphore to wake up the calling task */ ++ void* completed_sem; ++}; ++#endif /* !LWIP_TCPIP_CORE_LOCKING */ ++ ++#if !defined(iovec) ++struct iovec { ++ void *iov_base; ++ size_t iov_len; ++}; ++#endif ++ ++struct msghdr { ++ void *msg_name; ++ socklen_t msg_namelen; ++ struct iovec *msg_iov; ++ int msg_iovlen; ++ void *msg_control; ++ socklen_t msg_controllen; ++ int msg_flags; ++}; ++ ++/* Socket protocol types (TCP/UDP/RAW) */ ++#define SOCK_STREAM 1 ++#define SOCK_DGRAM 2 ++#define SOCK_RAW 3 ++ ++/* ++ * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) ++ */ ++#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ ++#define SO_KEEPALIVE 0x0008 /* keep connections alive */ ++#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ ++ ++ ++/* ++ * Additional options, not kept in so_options. ++ */ ++#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ ++#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ ++#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ ++#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ ++#define SO_LINGER 0x0080 /* linger on close if data present */ ++#define SO_DONTLINGER ((int)(~SO_LINGER)) ++#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ ++#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ ++#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ ++#define SO_RCVBUF 0x1002 /* receive buffer size */ ++#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ ++#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ ++#define SO_SNDTIMEO 0x1005 /* send timeout */ ++#define SO_RCVTIMEO 0x1006 /* receive timeout */ ++#define SO_ERROR 0x1007 /* get error status and clear */ ++#define SO_TYPE 0x1008 /* get socket type */ ++#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ ++#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ ++ ++ ++/* ++ * Structure used for manipulating linger option. ++ */ ++struct linger { ++ int l_onoff; /* option on/off */ ++ int l_linger; /* linger time in seconds */ ++}; ++ ++/* ++ * Level number for (get/set)sockopt() to apply to socket itself. ++ */ ++#define SOL_SOCKET 0xfff /* options for socket level */ ++ ++ ++#define AF_UNSPEC 0 ++#define AF_INET 2 ++#if LWIP_IPV6 ++#define AF_INET6 10 ++#else /* LWIP_IPV6 */ ++#define AF_INET6 AF_UNSPEC ++#endif /* LWIP_IPV6 */ ++#define PF_INET AF_INET ++#define PF_INET6 AF_INET6 ++#define PF_UNSPEC AF_UNSPEC ++ ++#define IPPROTO_IP 0 ++#define IPPROTO_ICMP 1 ++#define IPPROTO_TCP 6 ++#define IPPROTO_UDP 17 ++#if LWIP_IPV6 ++#define IPPROTO_IPV6 41 ++#define IPPROTO_ICMPV6 58 ++#endif /* LWIP_IPV6 */ ++#define IPPROTO_UDPLITE 136 ++#define IPPROTO_RAW 255 ++ ++/* Flags we can use with send and recv. */ ++#define MSG_PEEK 0x01 /* Peeks at an incoming message */ ++#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ ++#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ ++#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ ++#define MSG_MORE 0x10 /* Sender will send more */ ++ ++ ++/* ++ * Options for level IPPROTO_IP ++ */ ++#define IP_TOS 1 ++#define IP_TTL 2 ++ ++#if LWIP_TCP ++/* ++ * Options for level IPPROTO_TCP ++ */ ++#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ ++#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ ++#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ ++#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ ++#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ ++#endif /* LWIP_TCP */ ++ ++#if LWIP_IPV6 ++/* ++ * Options for level IPPROTO_IPV6 ++ */ ++#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ ++#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ ++#endif /* LWIP_IPV6 */ ++ ++#if LWIP_UDP && LWIP_UDPLITE ++/* ++ * Options for level IPPROTO_UDPLITE ++ */ ++#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ ++#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ ++#endif /* LWIP_UDP && LWIP_UDPLITE*/ ++ ++ ++#if LWIP_MULTICAST_TX_OPTIONS ++/* ++ * Options and types for UDP multicast traffic handling ++ */ ++#define IP_MULTICAST_TTL 5 ++#define IP_MULTICAST_IF 6 ++#define IP_MULTICAST_LOOP 7 ++#endif /* LWIP_MULTICAST_TX_OPTIONS */ ++ ++#if LWIP_IGMP ++/* ++ * Options and types related to multicast membership ++ */ ++#define IP_ADD_MEMBERSHIP 3 ++#define IP_DROP_MEMBERSHIP 4 ++ ++typedef struct ip_mreq { ++ struct in_addr imr_multiaddr; /* IP multicast address of group */ ++ struct in_addr imr_interface; /* local IP address of interface */ ++} ip_mreq; ++#endif /* LWIP_IGMP */ ++ ++/* ++ * The Type of Service provides an indication of the abstract ++ * parameters of the quality of service desired. These parameters are ++ * to be used to guide the selection of the actual service parameters ++ * when transmitting a datagram through a particular network. Several ++ * networks offer service precedence, which somehow treats high ++ * precedence traffic as more important than other traffic (generally ++ * by accepting only traffic above a certain precedence at time of high ++ * load). The major choice is a three way tradeoff between low-delay, ++ * high-reliability, and high-throughput. ++ * The use of the Delay, Throughput, and Reliability indications may ++ * increase the cost (in some sense) of the service. In many networks ++ * better performance for one of these parameters is coupled with worse ++ * performance on another. Except for very unusual cases at most two ++ * of these three indications should be set. ++ */ ++#define IPTOS_TOS_MASK 0x1E ++#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) ++#define IPTOS_LOWDELAY 0x10 ++#define IPTOS_THROUGHPUT 0x08 ++#define IPTOS_RELIABILITY 0x04 ++#define IPTOS_LOWCOST 0x02 ++#define IPTOS_MINCOST IPTOS_LOWCOST ++ ++/* ++ * The Network Control precedence designation is intended to be used ++ * within a network only. The actual use and control of that ++ * designation is up to each network. The Internetwork Control ++ * designation is intended for use by gateway control originators only. ++ * If the actual use of these precedence designations is of concern to ++ * a particular network, it is the responsibility of that network to ++ * control the access to, and use of, those precedence designations. ++ */ ++#define IPTOS_PREC_MASK 0xe0 ++#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) ++#define IPTOS_PREC_NETCONTROL 0xe0 ++#define IPTOS_PREC_INTERNETCONTROL 0xc0 ++#define IPTOS_PREC_CRITIC_ECP 0xa0 ++#define IPTOS_PREC_FLASHOVERRIDE 0x80 ++#define IPTOS_PREC_FLASH 0x60 ++#define IPTOS_PREC_IMMEDIATE 0x40 ++#define IPTOS_PREC_PRIORITY 0x20 ++#define IPTOS_PREC_ROUTINE 0x00 ++ ++ ++/* ++ * Commands for ioctlsocket(), taken from the BSD file fcntl.h. ++ * lwip_ioctl only supports FIONREAD and FIONBIO, for now ++ * ++ * Ioctl's have the command encoded in the lower word, ++ * and the size of any in or out parameters in the upper ++ * word. The high 2 bits of the upper word are used ++ * to encode the in/out status of the parameter; for now ++ * we restrict parameters to at most 128 bytes. ++ */ ++#if !defined(FIONREAD) || !defined(FIONBIO) ++#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ ++#define IOC_VOID 0x20000000UL /* no parameters */ ++#define IOC_OUT 0x40000000UL /* copy out parameters */ ++#define IOC_IN 0x80000000UL /* copy in parameters */ ++#define IOC_INOUT (IOC_IN|IOC_OUT) ++ /* 0x20000000 distinguishes new & ++ old ioctl's */ ++#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) ++ ++#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) ++ ++#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) ++#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ ++ ++#ifndef FIONREAD ++#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ ++#endif ++#ifndef FIONBIO ++#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ ++#endif ++ ++/* Socket I/O Controls: unimplemented */ ++#ifndef SIOCSHIWAT ++#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ ++#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ ++#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ ++#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ ++#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ ++#endif ++ ++/* 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 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 */ ++#ifndef FD_SET ++#undef FD_SETSIZE ++/* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ ++#define FD_SETSIZE MEMP_NUM_NETCONN ++#define FDSETSAFESET(n, code) do { \ ++ if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \ ++ code; }} while(0) ++#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ ++ (code) : 0) ++#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) ++#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) ++#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) ++#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) ++ ++typedef struct fd_set ++{ ++ unsigned char fd_bits [(FD_SETSIZE+7)/8]; ++} fd_set; ++ ++#elif LWIP_SOCKET_OFFSET ++#error LWIP_SOCKET_OFFSET does not work with external FD_SET! ++#elif FD_SETSIZE < MEMP_NUM_NETCONN ++#error "external FD_SETSIZE too small for number of sockets" ++#endif /* FD_SET */ ++ ++/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided ++ * by your system, set this to 0 and include in cc.h */ ++#ifndef LWIP_TIMEVAL_PRIVATE ++#define LWIP_TIMEVAL_PRIVATE 1 ++#endif ++ ++#if LWIP_TIMEVAL_PRIVATE ++struct timeval { ++ long tv_sec; /* seconds */ ++ long tv_usec; /* and microseconds */ ++}; ++#endif /* LWIP_TIMEVAL_PRIVATE */ ++ ++#define lwip_socket_init() /* Compatibility define, no init needed. */ ++void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ ++void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ ++ ++#if LWIP_COMPAT_SOCKETS == 2 ++/* This helps code parsers/code completion by not having the COMPAT functions as defines */ ++#define lwip_accept accept ++#define lwip_bind bind ++#define lwip_shutdown shutdown ++#define lwip_getpeername getpeername ++#define lwip_getsockname getsockname ++#define lwip_setsockopt setsockopt ++#define lwip_getsockopt getsockopt ++#define lwip_close closesocket ++#define lwip_connect connect ++#define lwip_listen listen ++#define lwip_recv recv ++#define lwip_recvfrom recvfrom ++#define lwip_send send ++#define lwip_sendmsg sendmsg ++#define lwip_sendto sendto ++#define lwip_socket socket ++#define lwip_select select ++#define lwip_ioctlsocket ioctl ++ ++#if LWIP_POSIX_SOCKETS_IO_NAMES ++#define lwip_read read ++#define lwip_write write ++#define lwip_writev writev ++#undef lwip_close ++#define lwip_close close ++#define closesocket(s) close(s) ++#define lwip_fcntl fcntl ++#define lwip_ioctl ioctl ++#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ ++#endif /* LWIP_COMPAT_SOCKETS == 2 */ ++ ++#if LWIP_COMPAT_SOCKETS ++#if LWIP_COMPAT_SOCKETS != 2 ++/** @ingroup socket */ ++#define accept(s,addr,addrlen) lwip_accept(s,addr,addrlen) ++/** @ingroup socket */ ++#define bind(s,name,namelen) lwip_bind(s,name,namelen) ++/** @ingroup socket */ ++#define shutdown(s,how) lwip_shutdown(s,how) ++/** @ingroup socket */ ++#define getpeername(s,name,namelen) lwip_getpeername(s,name,namelen) ++/** @ingroup socket */ ++#define getsockname(s,name,namelen) lwip_getsockname(s,name,namelen) ++/** @ingroup socket */ ++#define setsockopt(s,level,optname,opval,optlen) lwip_setsockopt(s,level,optname,opval,optlen) ++/** @ingroup socket */ ++#define getsockopt(s,level,optname,opval,optlen) lwip_getsockopt(s,level,optname,opval,optlen) ++/** @ingroup socket */ ++#define closesocket(s) lwip_close(s) ++/** @ingroup socket */ ++#define connect(s,name,namelen) lwip_connect(s,name,namelen) ++/** @ingroup socket */ ++#define listen(s,backlog) lwip_listen(s,backlog) ++/** @ingroup socket */ ++#define recv(s,mem,len,flags) lwip_recv(s,mem,len,flags) ++/** @ingroup socket */ ++#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom(s,mem,len,flags,from,fromlen) ++/** @ingroup socket */ ++#define send(s,dataptr,size,flags) lwip_send(s,dataptr,size,flags) ++/** @ingroup socket */ ++#define sendmsg(s,message,flags) lwip_sendmsg(s,message,flags) ++/** @ingroup socket */ ++#define sendto(s,dataptr,size,flags,to,tolen) lwip_sendto(s,dataptr,size,flags,to,tolen) ++/** @ingroup socket */ ++#define socket(domain,type,protocol) lwip_socket(domain,type,protocol) ++/** @ingroup socket */ ++#define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) ++/** @ingroup socket */ ++#define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) ++ ++#if LWIP_POSIX_SOCKETS_IO_NAMES ++/** @ingroup socket */ ++#define read(s,mem,len) lwip_read(s,mem,len) ++/** @ingroup socket */ ++#define write(s,dataptr,len) lwip_write(s,dataptr,len) ++/** @ingroup socket */ ++#define writev(s,iov,iovcnt) lwip_writev(s,iov,iovcnt) ++/** @ingroup socket */ ++#define close(s) lwip_close(s) ++/** @ingroup socket */ ++#define fcntl(s,cmd,val) lwip_fcntl(s,cmd,val) ++/** @ingroup socket */ ++#define ioctl(s,cmd,argp) lwip_ioctl(s,cmd,argp) ++#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ ++#endif /* LWIP_COMPAT_SOCKETS != 2 */ ++ ++#if LWIP_IPV4 && LWIP_IPV6 ++/** @ingroup socket */ ++#define inet_ntop(af,src,dst,size) \ ++ (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) \ ++ : (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL)) ++/** @ingroup socket */ ++#define inet_pton(af,src,dst) \ ++ (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) \ ++ : (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0)) ++#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ ++#define inet_ntop(af,src,dst,size) \ ++ (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL) ++#define inet_pton(af,src,dst) \ ++ (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0) ++#else /* LWIP_IPV4 && LWIP_IPV6 */ ++#define inet_ntop(af,src,dst,size) \ ++ (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) : NULL) ++#define inet_pton(af,src,dst) \ ++ (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) : 0) ++#endif /* LWIP_IPV4 && LWIP_IPV6 */ ++ ++#endif /* LWIP_COMPAT_SOCKETS */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LWIP_SOCKET */ ++ ++#endif /* LWIP_HDR_PRIV_SOCKETS_H */ --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -1760,6 +1760,15 @@ @@ -1497,7 +1497,7 @@ int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); int lwip_shutdown(int s, int how); -@@ -506,88 +78,16 @@ int lwip_select(int maxfdp1, fd_set *rea +@@ -506,88 +78,16 @@ int lwip_ioctl(int s, long cmd, void *argp); int lwip_fcntl(int s, int cmd, int val); @@ -1596,35 +1596,20 @@ --- a/port/include/lwipopts.h +++ b/port/include/lwipopts.h @@ -26,6 +26,11 @@ - /* Don't rename Sockets API functions */ - #define LWIP_COMPAT_SOCKETS 0 - -+/* Use Glibc's sockets headers */ -+#define LWIP_STD_SOCKETS 1 -+#define LWIP_INCLUDE_STD_SOCKETS "posix/socket.h" -+#define LWIP_INCLUDE_STD_INET "posix/inet.h" -+ - /* Use Glibc malloc()/free() */ - #define MEM_LIBC_MALLOC 1 - #define MEMP_MEM_MALLOC 1 ---- a/port/include/arch/cc.h -+++ b/port/include/arch/cc.h -@@ -40,6 +40,12 @@ - /* Use our own ioctls */ - #include - -+/* Use our own */ -+#include -+#include -+#include -+#include -+ - /* Use our own htons() and pals */ - #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 - + /* Don't rename Sockets API functions */ + #define LWIP_COMPAT_SOCKETS 0 + ++/* Use Glibc's sockets headers */ ++#define LWIP_STD_SOCKETS 1 ++#define LWIP_INCLUDE_STD_SOCKETS "posix/socket.h" ++#define LWIP_INCLUDE_STD_INET "posix/inet.h" ++ + /* Use Glibc malloc()/free() */ + #define MEM_LIBC_MALLOC 1 + #define MEMP_MEM_MALLOC 1 --- a/src/api/netdb.c +++ b/src/api/netdb.c -@@ -374,7 +374,9 @@ lwip_getaddrinfo(const char *nodename, c +@@ -374,7 +374,9 @@ /* set up sockaddr */ inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); sa6->sin6_family = AF_INET6; @@ -1634,7 +1619,7 @@ sa6->sin6_port = lwip_htons((u16_t)port_nr); ai->ai_family = AF_INET6; #endif /* LWIP_IPV6 */ -@@ -384,7 +386,9 @@ lwip_getaddrinfo(const char *nodename, c +@@ -384,7 +386,9 @@ /* set up sockaddr */ inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); sa4->sin_family = AF_INET; @@ -1676,7 +1661,7 @@ (sin6)->sin6_family = AF_INET6; \ (sin6)->sin6_port = lwip_htons((port)); \ (sin6)->sin6_flowinfo = 0; \ -@@ -537,9 +547,11 @@ lwip_accept(int s, struct sockaddr *addr +@@ -537,9 +547,11 @@ LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); @@ -1688,7 +1673,7 @@ MEMCPY(addr, &tempaddr, *addrlen); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); -@@ -878,9 +890,11 @@ lwip_recvfrom(int s, void *mem, size_t l +@@ -878,9 +890,11 @@ if (from && fromlen) #endif /* SOCKETS_DEBUG */ { @@ -1700,7 +1685,7 @@ MEMCPY(from, &saddr, *fromlen); } } -@@ -1764,9 +1778,11 @@ lwip_getaddrname(int s, struct sockaddr +@@ -1764,9 +1778,11 @@ ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); diff -Nru lwip-2.0.3/debian/patches/series lwip-2.0.3/debian/patches/series --- lwip-2.0.3/debian/patches/series 2018-04-30 23:10:13.000000000 +0000 +++ lwip-2.0.3/debian/patches/series 2018-08-30 08:47:30.000000000 +0000 @@ -3,5 +3,6 @@ errno autoconf bug-36167 +getpeername_dual poll max_sockets