From 69fd7e1c3238cc35bd01f3485a87032cc02652fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Wed, 8 Aug 2012 10:55:09 +0200 Subject: [PATCH] libports: update lwip to STABLE-1.4.1-RC1 The new version works fine but there is an issue with connect() that needs the included patch: There is no actual handling of EALREADY in lwip. It sets errno to EALREADY when the connection was established. Unfortunatly this is really bad because most programs expect to receive errno EISCONN if the connection was successfully established. So this behaviour breaks Qt4 and several noux/net packages (like lynx) because those programs end up in an endless loop trying to connect via an already connected socket. The longterm solution would be fixing the wrong behaviour in lwip (there are already bug-reports on lwip's mailinglist) but for now, it works well enough to simple change lwip's err_to_errno table to set errno to EISCONN when the connection was established. --- libports/include/lwip/arch/sys_arch.h | 12 +- libports/include/lwip/genode.h | 3 - libports/include/lwip/lwipopts.h | 1 + libports/lib/mk/lwip.mk | 8 +- libports/ports/lwip.inc | 2 + libports/ports/lwip.mk | 18 +-- libports/src/lib/lwip/errno.patch | 7 +- .../src/lib/lwip/libc_select_notify.patch | 21 ++- libports/src/lib/lwip/platform/sys_arch.cc | 150 ++++++++++++------ libports/src/lib/lwip/sockets_c_errno.patch | 16 ++ .../src/lib/lwip/sol_socket_definition.patch | 8 +- 11 files changed, 161 insertions(+), 85 deletions(-) create mode 100644 libports/ports/lwip.inc create mode 100644 libports/src/lib/lwip/sockets_c_errno.patch diff --git a/libports/include/lwip/arch/sys_arch.h b/libports/include/lwip/arch/sys_arch.h index 0849802f2..b8f17cd65 100644 --- a/libports/include/lwip/arch/sys_arch.h +++ b/libports/include/lwip/arch/sys_arch.h @@ -16,8 +16,16 @@ #include -typedef mem_ptr_t sys_sem_t; -typedef mem_ptr_t sys_mbox_t; +struct _sys_sem_t { + void* ptr; +}; +typedef struct _sys_sem_t sys_sem_t; + +struct _sys_mbox_t { + void* ptr; +}; +typedef struct _sys_mbox_t sys_mbox_t; + typedef mem_ptr_t sys_thread_t; typedef mem_ptr_t sys_prot_t; diff --git a/libports/include/lwip/genode.h b/libports/include/lwip/genode.h index e26839844..7731d61b6 100644 --- a/libports/include/lwip/genode.h +++ b/libports/include/lwip/genode.h @@ -42,9 +42,6 @@ void lwip_tcpip_init(void); int lwip_nic_init(genode_int32_t ip_addr, genode_int32_t netmask, genode_int32_t gateway); -/** Initialize lwIP for loopback only */ -struct netif *lwip_loopback_init(void); - #ifdef __cplusplus } #endif diff --git a/libports/include/lwip/lwipopts.h b/libports/include/lwip/lwipopts.h index 06b2bdaf0..d4dea2e54 100644 --- a/libports/include/lwip/lwipopts.h +++ b/libports/include/lwip/lwipopts.h @@ -27,6 +27,7 @@ #define LWIP_DHCP 1 /* DHCP support */ #define LWIP_SOCKET 1 /* LwIP socket API */ #define LWIP_COMPAT_SOCKETS 0 /* Libc compatibility layer */ +#define LWIP_COMPAT_MUTEX 1 /* use binary semaphore instead of mutex */ #define LWIP_NETIF_API 1 /* Network interface API */ #define LWIP_NETIF_LOOPBACK 1 /* Looping back to same address? */ #define LWIP_HAVE_LOOPIF 1 /* 127.0.0.1 support ? */ diff --git a/libports/lib/mk/lwip.mk b/libports/lib/mk/lwip.mk index 06dffa1db..f4d2b8b52 100644 --- a/libports/lib/mk/lwip.mk +++ b/libports/lib/mk/lwip.mk @@ -4,14 +4,16 @@ # The library implementes TCP and UDP as well as DNS and DHCP. # -LWIP_DIR = $(REP_DIR)/contrib/lwip-1.3.2 +include $(REP_DIR)/ports/lwip.inc + +LWIP_DIR = $(REP_DIR)/contrib/$(LWIP) # Genode platform files SRC_CC = nic.cc printf.cc sys_arch.cc # Core files SRC_C = init.c mem.c memp.c netif.c pbuf.c stats.c udp.c raw.c sys.c \ - tcp.c tcp_in.c tcp_out.c dhcp.c dns.c + tcp.c tcp_in.c tcp_out.c dhcp.c dns.c timers.c def.c # IPv4 files SRC_C += icmp.c inet.c ip_addr.c ip.c ip_frag.c inet_chksum.c @@ -21,7 +23,7 @@ SRC_C += err.c api_lib.c api_msg.c netbuf.c netdb.c netifapi.c sockets.c \ tcpip.c # Network interface files -SRC_C += etharp.c loopif.c +SRC_C += etharp.c LIBS = thread cxx alarm signal libc timed_semaphore diff --git a/libports/ports/lwip.inc b/libports/ports/lwip.inc new file mode 100644 index 000000000..1554482d2 --- /dev/null +++ b/libports/ports/lwip.inc @@ -0,0 +1,2 @@ +LWIP_VERSION = STABLE-1_4_1-RC1 +LWIP = lwip-$(LWIP_VERSION) diff --git a/libports/ports/lwip.mk b/libports/ports/lwip.mk index db789b82d..7824671c9 100644 --- a/libports/ports/lwip.mk +++ b/libports/ports/lwip.mk @@ -1,6 +1,7 @@ -LWIP = lwip-1.3.2 -LWIP_ZIP = $(LWIP).zip -LWIP_URL = http://mirrors.zerg.biz/nongnu/lwip/$(LWIP_ZIP) +include ports/lwip.inc + +LWIP_TGZ = $(LWIP).tar.gz +LWIP_URL = http://git.savannah.gnu.org/cgit/lwip.git/snapshot/$(LWIP_TGZ) # # Interface to top-level prepare Makefile @@ -19,14 +20,13 @@ $(CONTRIB_DIR)/$(LWIP): clean-lwip # # Port-specific local rules # -$(DOWNLOAD_DIR)/$(LWIP_ZIP): +$(DOWNLOAD_DIR)/$(LWIP_TGZ): $(VERBOSE)wget -c -P $(DOWNLOAD_DIR) $(LWIP_URL) && touch $@ -$(CONTRIB_DIR)/$(LWIP): $(DOWNLOAD_DIR)/$(LWIP_ZIP) - $(VERBOSE)unzip $< -d $(CONTRIB_DIR) && touch $@ - $(VERBOSE)patch -d $(CONTRIB_DIR) -p0 -i ../src/lib/lwip/libc_select_notify.patch - $(VERBOSE)patch -d $(CONTRIB_DIR) -p0 -i ../src/lib/lwip/errno.patch - $(VERBOSE)patch -d $(CONTRIB_DIR) -p0 -i ../src/lib/lwip/sol_socket_definition.patch +$(CONTRIB_DIR)/$(LWIP): $(DOWNLOAD_DIR)/$(LWIP_TGZ) + $(VERBOSE)tar xvzf $< -C $(CONTRIB_DIR) && touch $@ + $(VERBOSE)find ./src/lib/lwip/ -name "*.patch" |\ + xargs -ixxx sh -c "patch -p0 -r - -N -d $(CONTRIB_DIR) < xxx" || true include/lwip/lwip: $(VERBOSE)mkdir -p $@ diff --git a/libports/src/lib/lwip/errno.patch b/libports/src/lib/lwip/errno.patch index 4dca112db..4097b9a29 100644 --- a/libports/src/lib/lwip/errno.patch +++ b/libports/src/lib/lwip/errno.patch @@ -1,7 +1,6 @@ -diff -urN lwip-1.3.2.orig/src/include/lwip/arch.h lwip-1.3.2/src/include/lwip/arch.h ---- lwip-1.3.2.orig/src/include/lwip/arch.h 2009-12-24 16:38:19.000000000 +0100 -+++ lwip-1.3.2/src/include/lwip/arch.h 2010-11-01 15:43:34.000000000 +0100 -@@ -224,6 +224,12 @@ +--- lwip-STABLE-1_4_1-RC1/src/include/lwip/arch.h.orig ++++ lwip-STABLE-1_4_1-RC1/src/include/lwip/arch.h +@@ -208,6 +208,12 @@ extern "C" { extern int errno; #endif diff --git a/libports/src/lib/lwip/libc_select_notify.patch b/libports/src/lib/lwip/libc_select_notify.patch index 425367ba1..a5638368b 100644 --- a/libports/src/lib/lwip/libc_select_notify.patch +++ b/libports/src/lib/lwip/libc_select_notify.patch @@ -1,7 +1,6 @@ -diff -urN lwip-1.3.2.orig/src/api/sockets.c lwip-1.3.2/src/api/sockets.c ---- lwip-1.3.2.orig/src/api/sockets.c 2009-12-24 16:38:19.000000000 +0100 -+++ lwip-1.3.2/src/api/sockets.c 2010-02-16 11:27:00.000000000 +0100 -@@ -162,6 +162,9 @@ +--- lwip-STABLE-1_4_1-RC1/src/api/sockets.c.orig ++++ lwip-STABLE-1_4_1-RC1/src/api/sockets.c +@@ -171,6 +171,9 @@ static const int err_to_errno_table[] = { set_errno(sk->err); \ } while (0) @@ -11,7 +10,7 @@ diff -urN lwip-1.3.2.orig/src/api/sockets.c lwip-1.3.2/src/api/sockets.c /* Forward delcaration of some functions */ static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); static void lwip_getsockopt_internal(void *arg); -@@ -1034,7 +1037,7 @@ +@@ -1244,7 +1247,7 @@ return_copy_fdsets: * Processes recvevent (data available) and wakes up tasks waiting for select. */ static void @@ -19,9 +18,9 @@ diff -urN lwip-1.3.2.orig/src/api/sockets.c lwip-1.3.2/src/api/sockets.c +orig_event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) { int s; - struct lwip_socket *sock; -@@ -1123,6 +1126,17 @@ - } + struct lwip_sock *sock; +@@ -1359,6 +1362,17 @@ again: + SYS_ARCH_UNPROTECT(lev); } +/* Wrapper for the original event_callback() function that additionally calls @@ -30,9 +29,9 @@ diff -urN lwip-1.3.2.orig/src/api/sockets.c lwip-1.3.2/src/api/sockets.c +static void +event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) +{ -+ orig_event_callback(conn, evt, len); -+ if (libc_select_notify) -+ libc_select_notify(); ++ orig_event_callback(conn, evt, len); ++ if (libc_select_notify) ++ libc_select_notify(); +} + /** diff --git a/libports/src/lib/lwip/platform/sys_arch.cc b/libports/src/lib/lwip/platform/sys_arch.cc index 8127e374d..71dc4b3f5 100644 --- a/libports/src/lib/lwip/platform/sys_arch.cc +++ b/libports/src/lib/lwip/platform/sys_arch.cc @@ -101,7 +101,6 @@ extern "C" { #include #include #include -#include #include #include #include @@ -140,7 +139,6 @@ extern "C" { { static struct netif netif; struct ip_addr ip, nm, gw; - struct netif *loopif = lwip_loopback_init(); ip.addr = ip_addr; nm.addr = netmask; gw.addr = gateway; @@ -179,7 +177,6 @@ extern "C" { dhcp_semaphore()->down(20000); } catch (Genode::Timeout_exception) { PWRN("DHCP timed out!"); - netif_set_default(loopif); return 1; } PDBG("got IP address %d.%d.%d.%d", @@ -193,30 +190,13 @@ extern "C" { #endif /* LWIP_DHCP */ } } catch (Nic_not_availble) { - PWRN("NIC not available, set loopback as default"); - netif_set_default(loopif); + PWRN("NIC not available, loopback is used as default"); return 2; } return 0; } - /* in lwip/genode.h */ - struct netif *lwip_loopback_init(void) - { - /* setup LwIP's loopback device (as default NIC) */ - static struct netif loop_netif; - struct ip_addr loop_ipaddr, loop_netmask, loop_gw; - IP4_ADDR(&loop_gw, 127,0,0,1); - IP4_ADDR(&loop_ipaddr, 127,0,0,1); - IP4_ADDR(&loop_netmask, 255,255,255,0); - netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, - loopif_init, ip_input); - netif_set_up(&loop_netif); - return &loop_netif; - } - - /*************** ** Semaphore ** ***************/ @@ -227,18 +207,21 @@ extern "C" { * \param count specifies the initial state of the semaphore. * \return the semaphore, or SYS_SEM_NULL on error. */ - sys_sem_t sys_sem_new(u8_t count) + err_t sys_sem_new(sys_sem_t* sem, u8_t count) { try { Genode::Timed_semaphore *_sem = new (Genode::env()->heap()) Genode::Timed_semaphore(count); - return (sys_sem_t) _sem; + sem->ptr = _sem; + return ERR_OK; } catch (Genode::Allocator::Out_of_memory) { PWRN("Out of memory"); - return SYS_SEM_NULL; + return ERR_MEM; } catch (...) { PERR("Unknown Exception occured!"); - return SYS_SEM_NULL; + /* we just use a arbitrary value that is + * not defined in err.h */ + return -32; } } @@ -248,11 +231,11 @@ extern "C" { * * \param sem the semaphore to free */ - void sys_sem_free(sys_sem_t sem) + void sys_sem_free(sys_sem_t* sem) { try { Genode::Timed_semaphore *_sem = - reinterpret_cast(sem); + reinterpret_cast(sem->ptr); if (_sem) destroy(Genode::env()->heap(), _sem); } catch (...) { @@ -265,13 +248,13 @@ extern "C" { * Signals (or releases) a semaphore. * */ - void sys_sem_signal(sys_sem_t sem) + void sys_sem_signal(sys_sem_t* sem) { try { Genode::Timed_semaphore *_sem = - reinterpret_cast(sem); + reinterpret_cast(sem->ptr); if (!_sem) { - PERR("Invalid semaphore pointer at: %lx", sem); + //PERR("Invalid semaphore pointer at: %lx", *sem->ptr); return; } _sem->up(); @@ -281,6 +264,37 @@ extern "C" { } + /** + * Checks if a semaphore is valid + * + * \param sem semaphore to check + * + * \return 1 if semaphore is valid, 0 otherwise. + */ + int sys_sem_valid(sys_sem_t* sem) + { + try { + Genode::Timed_semaphore *_sem = + reinterpret_cast(sem->ptr); + + if (_sem) + return 1; + } catch (...) { } + + return 0; + } + + + /** + * Sets a semaphore to invalid + * + * \param sem semaphore to set invalid + */ + void sys_sem_set_invalid(sys_sem_t* sem) + { + sem->ptr = NULL; + } + /** * Blocks the thread while waiting for the semaphore to be signaled. * @@ -291,13 +305,13 @@ extern "C" { * acquires the semaphore, it should return how many * milliseconds expired while waiting for the semaphore. */ - u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) + u32_t sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout) { using namespace Genode; try { - Timed_semaphore *_sem = reinterpret_cast(sem); + Timed_semaphore *_sem = reinterpret_cast(sem->ptr); if (!_sem) { - PERR("Invalid semaphore pointer at: %lx", sem); + //PERR("Invalid semaphore pointer at: %lx", *sem->ptr); return EINVAL; } @@ -357,17 +371,19 @@ extern "C" { * \param size size of the mailbox * \return a new mailbox, or SYS_MBOX_NULL on error. */ - sys_mbox_t sys_mbox_new(int size) { + err_t sys_mbox_new(sys_mbox_t *mbox, int size) { LWIP_UNUSED_ARG(size); try { Mailbox* _mbox = new (Genode::env()->heap()) Mailbox(); - return (sys_mbox_t) _mbox; + mbox->ptr = _mbox; + return ERR_OK; } catch (Genode::Allocator::Out_of_memory) { PWRN("Out of memory"); + return ERR_MEM; } catch (...) { PERR("Unknown Exception occured!"); + return -32; } - return SYS_MBOX_NULL; } @@ -376,10 +392,10 @@ extern "C" { * * \param mbox mailbox to free */ - void sys_mbox_free(sys_mbox_t mbox) + void sys_mbox_free(sys_mbox_t* mbox) { try { - Mailbox* _mbox = reinterpret_cast(mbox); + Mailbox* _mbox = reinterpret_cast(mbox->ptr); if (_mbox) destroy(Genode::env()->heap(), _mbox); } catch (...) { @@ -387,6 +403,40 @@ extern "C" { } } + /** + * Checks if a mailbox is valid. + * + * \param mbox mailbox to check + * + * \return 1 if mailbox is valid, 0 otherwise. + */ + int sys_mbox_valid(sys_mbox_t* mbox) + { + try { + Mailbox* _mbox = reinterpret_cast(mbox->ptr); + if (_mbox) { + return 1; + } + } catch (...) { } + + return 0; + } + + + /** + * Invalidate a mailbox + * + * Afterwards sys_mbox_valid() returns 0. + * ATTENTION: This does NOT mean that the mailbox shall be deallocated: + * sys_mbox_free() is always called before calling this function! + * + * \param mbox mailbox to set invalid + */ + void sys_mbox_set_invalid(sys_mbox_t* mbox) + { + mbox->ptr = NULL; + } + /** * Posts the "msg" to the mailbox. @@ -394,13 +444,13 @@ extern "C" { * \param mbox target mailbox * \param msg message to post */ - void sys_mbox_post(sys_mbox_t mbox, void *msg) + void sys_mbox_post(sys_mbox_t* mbox, void *msg) { while (true) { try { - Mailbox* _mbox = reinterpret_cast(mbox); + Mailbox* _mbox = reinterpret_cast(mbox->ptr); if (!_mbox) { - PERR("Invalid mailbox pointer at %lx", mbox); + //PERR("Invalid mailbox pointer at %lx", *mbox->ptr); return; } _mbox->add(msg); @@ -420,12 +470,12 @@ extern "C" { * \param mbox target mailbox * \param msg message to post */ - err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg) + err_t sys_mbox_trypost(sys_mbox_t* mbox, void *msg) { try { - Mailbox* _mbox = reinterpret_cast(mbox); + Mailbox* _mbox = reinterpret_cast(mbox->ptr); if (!_mbox) { - PERR("Invalid mailbox pointer at %lx", mbox); + //PERR("Invalid mailbox pointer at %lx", *mbox->ptr); return EINVAL; } _mbox->add(msg); @@ -446,7 +496,7 @@ extern "C" { * \param msg pointer to message buffer * \param timeout how long will it block, if no message is available */ - u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) + u32_t sys_arch_mbox_fetch(sys_mbox_t* mbox, void **msg, u32_t timeout) { /* * The mailbox might be invalid to indicate, @@ -456,9 +506,9 @@ extern "C" { return 0; try { - Mailbox* _mbox = reinterpret_cast(mbox); + Mailbox* _mbox = reinterpret_cast(mbox->ptr); if (!_mbox) { - PERR("Invalid mailbox pointer at %lx", mbox); + //PERR("Invalid mailbox pointer at %lx", *mbox->ptr); return EINVAL; } return _mbox->get(msg, timeout); @@ -483,7 +533,7 @@ extern "C" { * This is similar to sys_arch_mbox_fetch, however if a message is not present * in the mailbox, it immediately returns with the code SYS_MBOX_EMPTY. */ - u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg) + u32_t sys_arch_mbox_tryfetch(sys_mbox_t* mbox, void **msg) { return sys_arch_mbox_fetch(mbox, msg, Mailbox::NO_BLOCK); } @@ -502,7 +552,7 @@ extern "C" { * \param stacksize size of the thread's stack * \param prio priority of new thread */ - sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), + sys_thread_t sys_thread_new(const char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) { try @@ -523,6 +573,7 @@ extern "C" { } +#if 0 /************** ** Timeouts ** **************/ @@ -568,5 +619,6 @@ extern "C" { return 0; } } +#endif } /* extern "C" */ diff --git a/libports/src/lib/lwip/sockets_c_errno.patch b/libports/src/lib/lwip/sockets_c_errno.patch new file mode 100644 index 000000000..46c5e7b5f --- /dev/null +++ b/libports/src/lib/lwip/sockets_c_errno.patch @@ -0,0 +1,16 @@ +This patch is necessary because lwip always returns EALREADY if the +connection is established but never EISCONN. So most programs will +fail to connect because they at one point while connecting expect to +get EISCONN. + +--- lwip-STABLE-1_4_1-RC1/src/api/sockets.c.orig ++++ lwip-STABLE-1_4_1-RC1/src/api/sockets.c +@@ -142,7 +142,7 @@ static const int err_to_errno_table[] = { + EINVAL, /* ERR_VAL -6 Illegal value. */ + EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ + EADDRINUSE, /* ERR_USE -8 Address in use. */ +- EALREADY, /* ERR_ISCONN -9 Already connected. */ ++ EISCONN, /* ERR_ISCONN -9 Already connected. */ + ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */ + ECONNRESET, /* ERR_RST -11 Connection reset. */ + ENOTCONN, /* ERR_CLSD -12 Connection closed. */ diff --git a/libports/src/lib/lwip/sol_socket_definition.patch b/libports/src/lib/lwip/sol_socket_definition.patch index c8f71606c..a20129fa0 100644 --- a/libports/src/lib/lwip/sol_socket_definition.patch +++ b/libports/src/lib/lwip/sol_socket_definition.patch @@ -2,14 +2,14 @@ Our FreeBSD libc based libc defines SOL_SOCKET as 0xffff. We change lwip's definition from 0xfff to match ours. This prevents us from converting the level when we call {g,s}etsockopt. ---- lwip-1.3.2.orig/src/include/lwip/sockets.h -+++ lwip-1.3.2/src/include/lwip/sockets.h -@@ -113,7 +113,7 @@ struct linger { +--- lwip-STABLE-1_4_1-RC1/src/include/lwip/sockets.h.orig ++++ lwip-STABLE-1_4_1-RC1/src/include/lwip/sockets.h +@@ -115,7 +115,7 @@ struct linger { /* * Level number for (get/set)sockopt() to apply to socket itself. */ -#define SOL_SOCKET 0xfff /* options for socket level */ -+#define SOL_SOCKET 0xffff /* options for socket level */ ++#define SOL_SOCKET 0xffff /* options for socket level */ #define AF_UNSPEC 0