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.
This commit is contained in:
Josef Söntgen 2012-08-08 10:55:09 +02:00 committed by Norman Feske
parent aa90efbf77
commit 69fd7e1c32
11 changed files with 161 additions and 85 deletions

View File

@ -16,8 +16,16 @@
#include <arch/cc.h>
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;

View File

@ -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

View File

@ -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 ? */

View File

@ -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

2
libports/ports/lwip.inc Normal file
View File

@ -0,0 +1,2 @@
LWIP_VERSION = STABLE-1_4_1-RC1
LWIP = lwip-$(LWIP_VERSION)

View File

@ -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 $@

View File

@ -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

View File

@ -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();
+}
+
/**

View File

@ -101,7 +101,6 @@ extern "C" {
#include <lwip/err.h>
#include <lwip/sys.h>
#include <lwip/dhcp.h>
#include <netif/loopif.h>
#include <arch/sys_arch.h>
#include <arch/cc.h>
#include <nic.h>
@ -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<Genode::Timed_semaphore*>(sem);
reinterpret_cast<Genode::Timed_semaphore*>(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<Genode::Timed_semaphore*>(sem);
reinterpret_cast<Genode::Timed_semaphore*>(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<Genode::Timed_semaphore*>(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<Timed_semaphore*>(sem);
Timed_semaphore *_sem = reinterpret_cast<Timed_semaphore*>(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<Mailbox*>(mbox);
Mailbox* _mbox = reinterpret_cast<Mailbox*>(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<Mailbox*>(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<Mailbox*>(mbox);
Mailbox* _mbox = reinterpret_cast<Mailbox*>(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<Mailbox*>(mbox);
Mailbox* _mbox = reinterpret_cast<Mailbox*>(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<Mailbox*>(mbox);
Mailbox* _mbox = reinterpret_cast<Mailbox*>(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" */

View File

@ -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. */

View File

@ -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