Author: Artem Pisarenko <artem.k.pisarenko{at}gmail{dot}com>

 src/api/api_lib.c           | 236 +++++++++++++++++++++++++++++---------------
 src/api/api_msg.c           |  54 +++++-----
 src/api/netifapi.c          |  89 +++++++++++------
 src/api/sockets.c           |  95 ++++++------------
 src/api/tcpip.c             |  26 +++--
 src/core/memp.c             |   1 +
 src/include/lwip/api_msg.h  |  16 +--
 src/include/lwip/memp_std.h |  10 ++
 src/include/lwip/netifapi.h |   6 +-
 src/include/lwip/opt.h      |   9 ++
 src/include/lwip/sockets.h  |  45 +++++++++
 11 files changed, 365 insertions(+), 222 deletions(-)

diff --git a/src/api/api_lib.c b/src/api/api_lib.c
index adaaad4..159dbf5 100644
--- a/src/api/api_lib.c
+++ b/src/api/api_lib.c
@@ -68,14 +68,18 @@ struct netconn*
 netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
 {
   struct netconn *conn;
-  struct api_msg msg;
 
   conn = netconn_alloc(t, callback);
   if (conn != NULL) {
     err_t err;
-    msg.msg.msg.n.proto = proto;
-    msg.msg.conn = conn;
-    TCPIP_APIMSG((&msg), lwip_netconn_do_newconn, err);
+    struct api_msg *msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+    if (msg == NULL) {
+      return ERR_MEM;
+    }
+    msg->msg.msg.n.proto = proto;
+    msg->msg.conn = conn;
+    TCPIP_APIMSG(msg, lwip_netconn_do_newconn, err);
+    memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
     if (err != ERR_OK) {
       LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
       LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
@@ -103,16 +107,21 @@ netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_cal
 err_t
 netconn_delete(struct netconn *conn)
 {
-  struct api_msg msg;
+  struct api_msg *msg;
 
   /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
   if (conn == NULL) {
     return ERR_OK;
   }
 
-  msg.function = lwip_netconn_do_delconn;
-  msg.msg.conn = conn;
-  tcpip_apimsg(&msg);
+  msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+  if (msg == NULL) {
+    return ERR_MEM;
+  }
+  msg->function = lwip_netconn_do_delconn;
+  msg->msg.conn = conn;
+  tcpip_apimsg(msg);
+  memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
 
   netconn_free(conn);
 
@@ -135,18 +144,23 @@ netconn_delete(struct netconn *conn)
 err_t
 netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
 {
-  struct api_msg msg;
+  struct api_msg *msg;
   err_t err;
 
   LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
   LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
   LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);
 
-  msg.msg.conn = conn;
-  msg.msg.msg.ad.ipaddr = ip_2_ipX(addr);
-  msg.msg.msg.ad.port = port;
-  msg.msg.msg.ad.local = local;
-  TCPIP_APIMSG(&msg, lwip_netconn_do_getaddr, err);
+  msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+  if (msg == NULL) {
+    return ERR_MEM;
+  }
+  msg->msg.conn = conn;
+  msg->msg.msg.ad.local = local;
+  TCPIP_APIMSG(msg, lwip_netconn_do_getaddr, err);
+  *addr = *ipX_2_ip(&(msg->msg.msg.ad.ipaddr));
+  *port = msg->msg.msg.ad.port;
+  memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
 
   NETCONN_SET_SAFE_ERR(conn, err);
   return err;
@@ -165,15 +179,21 @@ netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
 err_t
 netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port)
 {
-  struct api_msg msg;
+  struct api_msg *msg;
   err_t err;
 
   LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
 
-  msg.msg.conn = conn;
-  msg.msg.msg.bc.ipaddr = addr;
-  msg.msg.msg.bc.port = port;
-  TCPIP_APIMSG(&msg, lwip_netconn_do_bind, err);
+  msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+  if (msg == NULL) {
+    return ERR_MEM;
+  }
+  if (addr == NULL) addr = IP_ADDR_ANY;
+  msg->msg.conn = conn;
+  msg->msg.msg.bc.ipaddr = *addr;
+  msg->msg.msg.bc.port = port;
+  TCPIP_APIMSG(msg, lwip_netconn_do_bind, err);
+  memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
 
   NETCONN_SET_SAFE_ERR(conn, err);
   return err;
@@ -190,14 +210,19 @@ netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port)
 err_t
 netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port)
 {
-  struct api_msg msg;
+  struct api_msg *msg;
   err_t err;
 
   LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
 
-  msg.msg.conn = conn;
-  msg.msg.msg.bc.ipaddr = addr;
-  msg.msg.msg.bc.port = port;
+  msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+  if (msg == NULL) {
+    return ERR_MEM;
+  }
+  if (addr == NULL) addr = IP_ADDR_ANY;
+  msg->msg.conn = conn;
+  msg->msg.msg.bc.ipaddr = *addr;
+  msg->msg.msg.bc.port = port;
 #if LWIP_TCP
 #if (LWIP_UDP || LWIP_RAW)
   if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
@@ -205,8 +230,8 @@ netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port)
   {
     /* The TCP version waits for the connect to succeed,
        so always needs to use message passing. */
-    msg.function = lwip_netconn_do_connect;
-    err = tcpip_apimsg(&msg);
+    msg->function = lwip_netconn_do_connect;
+    err = tcpip_apimsg(msg);
   }
 #endif /* LWIP_TCP */
 #if (LWIP_UDP || LWIP_RAW) && LWIP_TCP
@@ -215,9 +240,10 @@ netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port)
 #if (LWIP_UDP || LWIP_RAW)
   {
      /* UDP and RAW only set flags, so we can use core-locking. */
-     TCPIP_APIMSG(&msg, lwip_netconn_do_connect, err);
+     TCPIP_APIMSG(msg, lwip_netconn_do_connect, err);
   }
 #endif /* (LWIP_UDP || LWIP_RAW) */
+  memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
 
   NETCONN_SET_SAFE_ERR(conn, err);
   return err;
@@ -232,13 +258,18 @@ netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port)
 err_t
 netconn_disconnect(struct netconn *conn)
 {
-  struct api_msg msg;
+  struct api_msg *msg;
   err_t err;
 
   LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
 
-  msg.msg.conn = conn;
-  TCPIP_APIMSG(&msg, lwip_netconn_do_disconnect, err);
+  msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+  if (msg == NULL) {
+	  return ERR_MEM;
+  }
+  msg->msg.conn = conn;
+  TCPIP_APIMSG(msg, lwip_netconn_do_disconnect, err);
+  memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
 
   NETCONN_SET_SAFE_ERR(conn, err);
   return err;
@@ -256,7 +287,7 @@ err_t
 netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
 {
 #if LWIP_TCP
-  struct api_msg msg;
+  struct api_msg *msg;
   err_t err;
 
   /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
@@ -264,11 +295,16 @@ netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
 
   LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
 
-  msg.msg.conn = conn;
+  msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+  if (msg == NULL) {
+	  return ERR_MEM;
+  }
+  msg->msg.conn = conn;
 #if TCP_LISTEN_BACKLOG
-  msg.msg.msg.lb.backlog = backlog;
+  msg->msg.msg.lb.backlog = backlog;
 #endif /* TCP_LISTEN_BACKLOG */
-  TCPIP_APIMSG(&msg, lwip_netconn_do_listen, err);
+  TCPIP_APIMSG(msg, lwip_netconn_do_listen, err);
+  memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
 
   NETCONN_SET_SAFE_ERR(conn, err);
   return err;
@@ -294,7 +330,7 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
   struct netconn *newconn;
   err_t err;
 #if TCP_LISTEN_BACKLOG
-  struct api_msg msg;
+  struct api_msg *msg;
 #endif /* TCP_LISTEN_BACKLOG */
 
   LWIP_ERROR("netconn_accept: invalid pointer",    (new_conn != NULL),                  return ERR_ARG;);
@@ -327,9 +363,14 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
   }
 #if TCP_LISTEN_BACKLOG
   /* Let the stack know that we have accepted the connection. */
-  msg.msg.conn = conn;
+  msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+  if (msg == NULL) {
+	  return ERR_MEM;
+  }
+  msg->msg.conn = conn;
   /* don't care for the return value of lwip_netconn_do_recv */
-  TCPIP_APIMSG_NOERR(&msg, lwip_netconn_do_recv);
+  TCPIP_APIMSG_NOERR(msg, lwip_netconn_do_recv);
+  memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
 #endif /* TCP_LISTEN_BACKLOG */
 
   *new_conn = newconn;
@@ -358,7 +399,7 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
   u16_t len;
   err_t err;
 #if LWIP_TCP
-  struct api_msg msg;
+  struct api_msg *msg;
 #endif /* LWIP_TCP */
 
   LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
@@ -393,14 +434,19 @@ netconn_recv_data(struct netconn *conn, void **new_buf)
       /* Let the stack know that we have taken the data. */
       /* TODO: Speedup: Don't block and wait for the answer here
          (to prevent multiple thread-switches). */
-      msg.msg.conn = conn;
+      msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+      if (msg == NULL) {
+        return ERR_MEM;
+      }
+      msg->msg.conn = conn;
       if (buf != NULL) {
-        msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len;
+        msg->msg.msg.r.len = ((struct pbuf *)buf)->tot_len;
       } else {
-        msg.msg.msg.r.len = 1;
+        msg->msg.msg.r.len = 1;
       }
       /* don't care for the return value of lwip_netconn_do_recv */
-      TCPIP_APIMSG_NOERR(&msg, lwip_netconn_do_recv);
+      TCPIP_APIMSG_NOERR(msg, lwip_netconn_do_recv);
+      memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
     }
 
     /* If we are closed, we indicate that we no longer wish to use the socket */
@@ -531,14 +577,18 @@ netconn_recved(struct netconn *conn, u32_t length)
 #if LWIP_TCP
   if ((conn != NULL) && (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) &&
       (netconn_get_noautorecved(conn))) {
-    struct api_msg msg;
     /* Let the stack know that we have taken the data. */
     /* TODO: Speedup: Don't block and wait for the answer here
        (to prevent multiple thread-switches). */
-    msg.msg.conn = conn;
-    msg.msg.msg.r.len = length;
+    struct api_msg *msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+    if (msg == NULL) {
+      return ERR_MEM;
+    }
+    msg->msg.conn = conn;
+    msg->msg.msg.r.len = length;
     /* don't care for the return value of lwip_netconn_do_recv */
-    TCPIP_APIMSG_NOERR(&msg, lwip_netconn_do_recv);
+    TCPIP_APIMSG_NOERR(msg, lwip_netconn_do_recv);
+    memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
   }
 #else /* LWIP_TCP */
   LWIP_UNUSED_ARG(conn);
@@ -577,15 +627,20 @@ netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t
 err_t
 netconn_send(struct netconn *conn, struct netbuf *buf)
 {
-  struct api_msg msg;
+  struct api_msg *msg;
   err_t err;
 
   LWIP_ERROR("netconn_send: invalid conn",  (conn != NULL), return ERR_ARG;);
 
   LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
-  msg.msg.conn = conn;
-  msg.msg.msg.b = buf;
-  TCPIP_APIMSG(&msg, lwip_netconn_do_send, err);
+  msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+  if (msg == NULL) {
+	  return ERR_MEM;
+  }
+  msg->msg.conn = conn;
+  msg->msg.msg.b = buf;
+  TCPIP_APIMSG(msg, lwip_netconn_do_send, err);
+  memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
 
   NETCONN_SET_SAFE_ERR(conn, err);
   return err;
@@ -608,7 +663,7 @@ err_t
 netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
                      u8_t apiflags, size_t *bytes_written)
 {
-  struct api_msg msg;
+  struct api_msg *msg;
   err_t err;
   u8_t dontblock;
 
@@ -624,25 +679,29 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
     return ERR_VAL;
   }
 
+  msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+  if (msg == NULL) {
+	  return ERR_MEM;
+  }
   /* non-blocking write sends as much  */
-  msg.msg.conn = conn;
-  msg.msg.msg.w.dataptr = dataptr;
-  msg.msg.msg.w.apiflags = apiflags;
-  msg.msg.msg.w.len = size;
+  msg->msg.conn = conn;
+  msg->msg.msg.w.dataptr = dataptr;
+  msg->msg.msg.w.apiflags = apiflags;
+  msg->msg.msg.w.len = size;
 #if LWIP_SO_SNDTIMEO
   if (conn->send_timeout != 0) {
     /* get the time we started, which is later compared to
         sys_now() + conn->send_timeout */
-    msg.msg.msg.w.time_started = sys_now();
+    msg->msg.msg.w.time_started = sys_now();
   } else {
-    msg.msg.msg.w.time_started = 0;
+    msg->msg.msg.w.time_started = 0;
   }
 #endif /* LWIP_SO_SNDTIMEO */
 
   /* For locking the core: this _can_ be delayed on low memory/low send buffer,
      but if it is, this is done inside api_msg.c:do_write(), so we can use the
      non-blocking version here. */
-  TCPIP_APIMSG(&msg, lwip_netconn_do_write, err);
+  TCPIP_APIMSG(msg, lwip_netconn_do_write, err);
   if ((err == ERR_OK) && (bytes_written != NULL)) {
     if (dontblock
 #if LWIP_SO_SNDTIMEO
@@ -650,12 +709,13 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
 #endif /* LWIP_SO_SNDTIMEO */
        ) {
       /* nonblocking write: maybe the data has been sent partly */
-      *bytes_written = msg.msg.msg.w.len;
+      *bytes_written = msg->msg.msg.w.len;
     } else {
       /* blocking call succeeded: all data has been sent if it */
       *bytes_written = size;
     }
   }
+  memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
 
   NETCONN_SET_SAFE_ERR(conn, err);
   return err;
@@ -671,18 +731,23 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
 static err_t
 netconn_close_shutdown(struct netconn *conn, u8_t how)
 {
-  struct api_msg msg;
+  struct api_msg *msg;
   err_t err;
 
   LWIP_ERROR("netconn_close: invalid conn",  (conn != NULL), return ERR_ARG;);
 
-  msg.function = lwip_netconn_do_close;
-  msg.msg.conn = conn;
+  msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+  if (msg == NULL) {
+    return ERR_MEM;
+  }
+  msg->function = lwip_netconn_do_close;
+  msg->msg.conn = conn;
   /* shutting down both ends is the same as closing */
-  msg.msg.msg.sd.shut = how;
+  msg->msg.msg.sd.shut = how;
   /* because of the LWIP_TCPIP_CORE_LOCKING implementation of lwip_netconn_do_close,
      don't use TCPIP_APIMSG here */
-  err = tcpip_apimsg(&msg);
+  err = tcpip_apimsg(msg);
+  memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
 
   NETCONN_SET_SAFE_ERR(conn, err);
   return err;
@@ -730,16 +795,23 @@ netconn_join_leave_group(struct netconn *conn,
                          ip_addr_t *netif_addr,
                          enum netconn_igmp join_or_leave)
 {
-  struct api_msg msg;
+  struct api_msg *msg;
   err_t err;
 
   LWIP_ERROR("netconn_join_leave_group: invalid conn",  (conn != NULL), return ERR_ARG;);
 
-  msg.msg.conn = conn;
-  msg.msg.msg.jl.multiaddr = ip_2_ipX(multiaddr);
-  msg.msg.msg.jl.netif_addr = ip_2_ipX(netif_addr);
-  msg.msg.msg.jl.join_or_leave = join_or_leave;
-  TCPIP_APIMSG(&msg, lwip_netconn_do_join_leave_group, err);
+  msg = (struct api_msg *)memp_malloc(MEMP_TCPIP_API_MSG_DATA);
+  if (msg == NULL) {
+    return ERR_MEM;
+  }
+  if (multiaddr == NULL) multiaddr = IP_ADDR_ANY;
+  if (netif_addr == NULL) netif_addr = IP_ADDR_ANY;
+  msg->msg.conn = conn;
+  msg->msg.msg.jl.multiaddr = *ip_2_ipX(multiaddr);
+  msg->msg.msg.jl.netif_addr = *ip_2_ipX(netif_addr);
+  msg->msg.msg.jl.join_or_leave = join_or_leave;
+  TCPIP_APIMSG(msg, lwip_netconn_do_join_leave_group, err);
+  memp_free(MEMP_TCPIP_API_MSG_DATA, msg);
 
   NETCONN_SET_SAFE_ERR(conn, err);
   return err;
@@ -760,26 +832,32 @@ netconn_join_leave_group(struct netconn *conn,
 err_t
 netconn_gethostbyname(const char *name, ip_addr_t *addr)
 {
-  struct dns_api_msg msg;
+  struct dns_api_msg *msg;
   err_t err;
-  sys_sem_t sem;
 
   LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
   LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
 
-  err = sys_sem_new(&sem, 0);
+  msg = (struct dns_api_msg *)memp_malloc(MEMP_DNS_API_MSG_DATA);
+  if (msg == NULL) {
+    return ERR_MEM;
+  }
+  msg->name = name;
+  msg->err = ERR_OK;
+
+  err = sys_sem_new(&(msg->sem), 0);
   if (err != ERR_OK) {
+    memp_free(MEMP_DNS_API_MSG_DATA, msg);
     return err;
   }
 
-  msg.name = name;
-  msg.addr = addr;
-  msg.err = &err;
-  msg.sem = &sem;
+  tcpip_callback(lwip_netconn_do_gethostbyname, msg);
+  sys_sem_wait(&(msg->sem));
+  sys_sem_free(&(msg->sem));
+  err = msg->err;
+  *addr = msg->addr;
 
-  tcpip_callback(lwip_netconn_do_gethostbyname, &msg);
-  sys_sem_wait(&sem);
-  sys_sem_free(&sem);
+  memp_free(MEMP_DNS_API_MSG_DATA, msg);
 
   return err;
 }
diff --git a/src/api/api_msg.c b/src/api/api_msg.c
index b1a9b77..b29f1f5 100644
--- a/src/api/api_msg.c
+++ b/src/api/api_msg.c
@@ -906,17 +906,17 @@ lwip_netconn_do_bind(struct api_msg_msg *msg)
       switch (NETCONNTYPE_GROUP(msg->conn->type)) {
 #if LWIP_RAW
       case NETCONN_RAW:
-        msg->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
+        msg->err = raw_bind(msg->conn->pcb.raw, &(msg->msg.bc.ipaddr));
         break;
 #endif /* LWIP_RAW */
 #if LWIP_UDP
       case NETCONN_UDP:
-        msg->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
+        msg->err = udp_bind(msg->conn->pcb.udp, &(msg->msg.bc.ipaddr), msg->msg.bc.port);
         break;
 #endif /* LWIP_UDP */
 #if LWIP_TCP
       case NETCONN_TCP:
-        msg->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port);
+        msg->err = tcp_bind(msg->conn->pcb.tcp, &(msg->msg.bc.ipaddr), msg->msg.bc.port);
         break;
 #endif /* LWIP_TCP */
       default:
@@ -996,12 +996,12 @@ lwip_netconn_do_connect(struct api_msg_msg *msg)
     switch (NETCONNTYPE_GROUP(msg->conn->type)) {
 #if LWIP_RAW
     case NETCONN_RAW:
-      msg->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
+      msg->err = raw_connect(msg->conn->pcb.raw, &(msg->msg.bc.ipaddr));
       break;
 #endif /* LWIP_RAW */
 #if LWIP_UDP
     case NETCONN_UDP:
-      msg->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
+      msg->err = udp_connect(msg->conn->pcb.udp, &(msg->msg.bc.ipaddr), msg->msg.bc.port);
       break;
 #endif /* LWIP_UDP */
 #if LWIP_TCP
@@ -1011,7 +1011,7 @@ lwip_netconn_do_connect(struct api_msg_msg *msg)
         msg->err = ERR_ISCONN;
       } else {
         setup_tcp(msg->conn);
-        msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr,
+        msg->err = tcp_connect(msg->conn->pcb.tcp, &(msg->msg.bc.ipaddr),
           msg->msg.bc.port, lwip_netconn_do_connected);
         if (msg->err == ERR_OK) {
           u8_t non_blocking = netconn_is_nonblocking(msg->conn);
@@ -1421,10 +1421,10 @@ lwip_netconn_do_getaddr(struct api_msg_msg *msg)
 {
   if (msg->conn->pcb.ip != NULL) {
     if (msg->msg.ad.local) {
-      ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), *(msg->msg.ad.ipaddr),
+      ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), msg->msg.ad.ipaddr,
         msg->conn->pcb.ip->local_ip);
     } else {
-      ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), *(msg->msg.ad.ipaddr),
+      ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), msg->msg.ad.ipaddr,
         msg->conn->pcb.ip->remote_ip);
     }
     msg->err = ERR_OK;
@@ -1432,7 +1432,7 @@ lwip_netconn_do_getaddr(struct api_msg_msg *msg)
 #if LWIP_RAW
     case NETCONN_RAW:
       if (msg->msg.ad.local) {
-        *(msg->msg.ad.port) = msg->conn->pcb.raw->protocol;
+        msg->msg.ad.port = msg->conn->pcb.raw->protocol;
       } else {
         /* return an error as connecting is only a helper for upper layers */
         msg->err = ERR_CONN;
@@ -1442,19 +1442,19 @@ lwip_netconn_do_getaddr(struct api_msg_msg *msg)
 #if LWIP_UDP
     case NETCONN_UDP:
       if (msg->msg.ad.local) {
-        *(msg->msg.ad.port) = msg->conn->pcb.udp->local_port;
+        msg->msg.ad.port = msg->conn->pcb.udp->local_port;
       } else {
         if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) {
           msg->err = ERR_CONN;
         } else {
-          *(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port;
+          msg->msg.ad.port = msg->conn->pcb.udp->remote_port;
         }
       }
       break;
 #endif /* LWIP_UDP */
 #if LWIP_TCP
     case NETCONN_TCP:
-      *(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port);
+      msg->msg.ad.port = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port);
       break;
 #endif /* LWIP_TCP */
     default:
@@ -1527,11 +1527,11 @@ lwip_netconn_do_join_leave_group(struct api_msg_msg *msg)
 #if LWIP_IPV6 && LWIP_IPV6_MLD
         if (PCB_ISIPV6(msg->conn->pcb.udp)) {
           if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
-            msg->err = mld6_joingroup(ipX_2_ip6(msg->msg.jl.netif_addr),
-              ipX_2_ip6(msg->msg.jl.multiaddr));
+            msg->err = mld6_joingroup(ipX_2_ip6(&(msg->msg.jl.netif_addr)),
+              ipX_2_ip6(&(msg->msg.jl.multiaddr)));
           } else {
-            msg->err = mld6_leavegroup(ipX_2_ip6(msg->msg.jl.netif_addr),
-              ipX_2_ip6(msg->msg.jl.multiaddr));
+            msg->err = mld6_leavegroup(ipX_2_ip6(&(msg->msg.jl.netif_addr)),
+              ipX_2_ip6(&(msg->msg.jl.multiaddr)));
           }
         }
         else
@@ -1539,11 +1539,11 @@ lwip_netconn_do_join_leave_group(struct api_msg_msg *msg)
         {
 #if LWIP_IGMP
           if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
-            msg->err = igmp_joingroup(ipX_2_ip(msg->msg.jl.netif_addr),
-              ipX_2_ip(msg->msg.jl.multiaddr));
+            msg->err = igmp_joingroup(ipX_2_ip(&(msg->msg.jl.netif_addr)),
+              ipX_2_ip(&(msg->msg.jl.multiaddr)));
           } else {
-            msg->err = igmp_leavegroup(ipX_2_ip(msg->msg.jl.netif_addr),
-              ipX_2_ip(msg->msg.jl.multiaddr));
+            msg->err = igmp_leavegroup(ipX_2_ip(&(msg->msg.jl.netif_addr)),
+              ipX_2_ip(&(msg->msg.jl.multiaddr)));
           }
 #endif /* LWIP_IGMP */
         }
@@ -1577,14 +1577,14 @@ lwip_netconn_do_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
 
   if (ipaddr == NULL) {
     /* timeout or memory error */
-    *msg->err = ERR_VAL;
+    msg->err = ERR_VAL;
   } else {
     /* address was resolved */
-    *msg->err = ERR_OK;
-    *msg->addr = *ipaddr;
+    msg->err = ERR_OK;
+    msg->addr = *ipaddr;
   }
   /* wake up the application task waiting in netconn_gethostbyname */
-  sys_sem_signal(msg->sem);
+  sys_sem_signal(&(msg->sem));
 }
 
 /**
@@ -1598,11 +1598,11 @@ lwip_netconn_do_gethostbyname(void *arg)
 {
   struct dns_api_msg *msg = (struct dns_api_msg*)arg;
 
-  *msg->err = dns_gethostbyname(msg->name, msg->addr, lwip_netconn_do_dns_found, msg);
-  if (*msg->err != ERR_INPROGRESS) {
+  msg->err = dns_gethostbyname(msg->name, &(msg->addr), lwip_netconn_do_dns_found, msg);
+  if (msg->err != ERR_INPROGRESS) {
     /* on error or immediate success, wake up the application
      * task waiting in netconn_gethostbyname */
-    sys_sem_signal(msg->sem);
+    sys_sem_signal(&(msg->sem));
   }
 }
 #endif /* LWIP_DNS */
diff --git a/src/api/netifapi.c b/src/api/netifapi.c
index 81403f8..39d2468 100644
--- a/src/api/netifapi.c
+++ b/src/api/netifapi.c
@@ -37,6 +37,7 @@
 
 #include "lwip/netifapi.h"
 #include "lwip/tcpip.h"
+#include "lwip/memp.h"
 
 /**
  * Call netif_add() inside the tcpip_thread context.
@@ -45,9 +46,9 @@ static void
 netifapi_do_netif_add(struct netifapi_msg_msg *msg)
 {
   if (!netif_add( msg->netif,
-                  msg->msg.add.ipaddr,
-                  msg->msg.add.netmask,
-                  msg->msg.add.gw,
+                  &(msg->msg.add.ipaddr),
+                  &(msg->msg.add.netmask),
+                  &(msg->msg.add.gw),
                   msg->msg.add.state,
                   msg->msg.add.init,
                   msg->msg.add.input)) {
@@ -65,9 +66,9 @@ static void
 netifapi_do_netif_set_addr(struct netifapi_msg_msg *msg)
 {
   netif_set_addr( msg->netif,
-                  msg->msg.add.ipaddr,
-                  msg->msg.add.netmask,
-                  msg->msg.add.gw);
+                  &(msg->msg.add.ipaddr),
+                  &(msg->msg.add.netmask),
+                  &(msg->msg.add.gw));
   msg->err = ERR_OK;
   TCPIP_NETIFAPI_ACK(msg);
 }
@@ -103,17 +104,26 @@ netifapi_netif_add(struct netif *netif,
                    netif_init_fn init,
                    netif_input_fn input)
 {
-  struct netifapi_msg msg;
-  msg.function = netifapi_do_netif_add;
-  msg.msg.netif = netif;
-  msg.msg.msg.add.ipaddr  = ipaddr;
-  msg.msg.msg.add.netmask = netmask;
-  msg.msg.msg.add.gw      = gw;
-  msg.msg.msg.add.state   = state;
-  msg.msg.msg.add.init    = init;
-  msg.msg.msg.add.input   = input;
-  TCPIP_NETIFAPI(&msg);
-  return msg.msg.err;
+  err_t err;
+  struct netifapi_msg *msg = (struct netifapi_msg *)memp_malloc(MEMP_NETIF_API_MSG_DATA);
+  if (msg == NULL) {
+    return ERR_MEM;
+  }
+  if (ipaddr == NULL) ipaddr = IP_ADDR_ANY;
+  if (netmask == NULL) netmask = IP_ADDR_ANY;
+  if (gw == NULL) gw = IP_ADDR_ANY;
+  msg->function = netifapi_do_netif_add;
+  msg->msg.netif = netif;
+  msg->msg.msg.add.ipaddr  = *ipaddr;
+  msg->msg.msg.add.netmask = *netmask;
+  msg->msg.msg.add.gw      = *gw;
+  msg->msg.msg.add.state   = state;
+  msg->msg.msg.add.init    = init;
+  msg->msg.msg.add.input   = input;
+  TCPIP_NETIFAPI(msg);
+  err = msg->msg.err;
+  memp_free(MEMP_NETIF_API_MSG_DATA, msg);
+  return err;
 }
 
 /**
@@ -128,14 +138,23 @@ netifapi_netif_set_addr(struct netif *netif,
                         ip_addr_t *netmask,
                         ip_addr_t *gw)
 {
-  struct netifapi_msg msg;
-  msg.function = netifapi_do_netif_set_addr;
-  msg.msg.netif = netif;
-  msg.msg.msg.add.ipaddr  = ipaddr;
-  msg.msg.msg.add.netmask = netmask;
-  msg.msg.msg.add.gw      = gw;
-  TCPIP_NETIFAPI(&msg);
-  return msg.msg.err;
+  err_t err;
+  struct netifapi_msg *msg = (struct netifapi_msg *)memp_malloc(MEMP_NETIF_API_MSG_DATA);
+  if (msg == NULL) {
+    return ERR_MEM;
+  }
+  if (ipaddr == NULL) ipaddr = IP_ADDR_ANY;
+  if (netmask == NULL) netmask = IP_ADDR_ANY;
+  if (gw == NULL) gw = IP_ADDR_ANY;
+  msg->function = netifapi_do_netif_set_addr;
+  msg->msg.netif = netif;
+  msg->msg.msg.add.ipaddr  = *ipaddr;
+  msg->msg.msg.add.netmask = *netmask;
+  msg->msg.msg.add.gw      = *gw;
+  TCPIP_NETIFAPI(msg);
+  err = msg->msg.err;
+  memp_free(MEMP_NETIF_API_MSG_DATA, msg);
+  return err;
 }
 
 /**
@@ -148,13 +167,19 @@ err_t
 netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
                        netifapi_errt_fn errtfunc)
 {
-  struct netifapi_msg msg;
-  msg.function = netifapi_do_netif_common;
-  msg.msg.netif = netif;
-  msg.msg.msg.common.voidfunc = voidfunc;
-  msg.msg.msg.common.errtfunc = errtfunc;
-  TCPIP_NETIFAPI(&msg);
-  return msg.msg.err;
+  err_t err;
+  struct netifapi_msg *msg = (struct netifapi_msg *)memp_malloc(MEMP_NETIF_API_MSG_DATA);
+  if (msg == NULL) {
+    return ERR_MEM;
+  }
+  msg->function = netifapi_do_netif_common;
+  msg->msg.netif = netif;
+  msg->msg.msg.common.voidfunc = voidfunc;
+  msg->msg.msg.common.errtfunc = errtfunc;
+  TCPIP_NETIFAPI(msg);
+  err = msg->msg.err;
+  memp_free(MEMP_NETIF_API_MSG_DATA, msg);
+  return err;
 }
 
 #endif /* LWIP_NETIF_API */
diff --git a/src/api/sockets.c b/src/api/sockets.c
index 6603671..b0e2358 100644
--- a/src/api/sockets.c
+++ b/src/api/sockets.c
@@ -51,6 +51,7 @@
 #include "lwip/raw.h"
 #include "lwip/udp.h"
 #include "lwip/tcpip.h"
+#include "lwip/memp.h"
 #include "lwip/pbuf.h"
 #if LWIP_CHECKSUM_ON_COPY
 #include "lwip/inet_chksum.h"
@@ -120,28 +121,6 @@
 
 #define NUM_SOCKETS MEMP_NUM_NETCONN
 
-/** Contains all internal pointers and states used for a socket */
-struct lwip_sock {
-  /** sockets currently are built on netconns, each socket has one netconn */
-  struct netconn *conn;
-  /** data that was left from the previous read */
-  void *lastdata;
-  /** offset in the data that was left from the previous read */
-  u16_t lastoffset;
-  /** number of times data was received, set by event_callback(),
-      tested by the receive and select functions */
-  s16_t rcvevent;
-  /** number of times data was ACKed (free send buffer), set by event_callback(),
-      tested by select */
-  u16_t sendevent;
-  /** error happened for this socket, set by event_callback(), tested by select */
-  u16_t errevent; 
-  /** last error that occurred on this socket */
-  int err;
-  /** counter of how many threads are waiting for this socket using select */
-  int select_waiting;
-};
-
 /** Description for a task waiting in select */
 struct lwip_select_cb {
   /** Pointer to the next waiting task */
@@ -160,28 +139,6 @@ struct lwip_select_cb {
   sys_sem_t sem;
 };
 
-/** 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 struct for which to change options */
-  struct lwip_sock *sock;
-#ifdef LWIP_DEBUG
-  /** socket index for which to change options */
-  int s;
-#endif /* LWIP_DEBUG */
-  /** level of the option to process */
-  int level;
-  /** name of the option to process */
-  int optname;
-  /** set: value to set the option to
-    * get: value of the option is stored here */
-  void *optval;
-  /** size of *optval */
-  socklen_t *optlen;
-  /** if an error occures, it is temporarily stored here */
-  err_t err;
-};
-
 /** A struct sockaddr replacement that has the same alignment as sockaddr_in/
  *  sockaddr_in6 if instantiated.
  */
@@ -1526,7 +1483,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
 {
   err_t err = ERR_OK;
   struct lwip_sock *sock = get_socket(s);
-  struct lwip_setgetsockopt_data data;
+  struct lwip_setgetsockopt_data *data;
 
   if (!sock) {
     return -1;
@@ -1724,19 +1681,24 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
   }
 
   /* Now do the actual option processing */
-  data.sock = sock;
+  data = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA);
+  if (data == NULL) {
+    return ERR_MEM;
+  }
+  data->sock = sock;
 #ifdef LWIP_DEBUG
-  data.s = s;
+  data->s = s;
 #endif /* LWIP_DEBUG */
-  data.level = level;
-  data.optname = optname;
-  data.optval = optval;
-  data.optlen = optlen;
-  data.err = err;
-  tcpip_callback(lwip_getsockopt_internal, &data);
+  data->level = level;
+  data->optname = optname;
+  data->optval = optval;
+  data->optlen = optlen;
+  data->err = err;
+  tcpip_callback(lwip_getsockopt_internal, data);
   sys_arch_sem_wait(&sock->conn->op_completed, 0);
   /* maybe lwip_getsockopt_internal has changed err */
-  err = data.err;
+  err = data->err;
+  memp_free(MEMP_SOCKET_SETGETSOCKOPT_DATA, data);
 
   sock_set_errno(sock, err);
   return err ? -1 : 0;
@@ -1972,7 +1934,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
 {
   struct lwip_sock *sock = get_socket(s);
   err_t err = ERR_OK;
-  struct lwip_setgetsockopt_data data;
+  struct lwip_setgetsockopt_data *data;
 
   if (!sock) {
     return -1;
@@ -2181,19 +2143,24 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
 
 
   /* Now do the actual option processing */
-  data.sock = sock;
+  data = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA);
+  if (data == NULL) {
+    return ERR_MEM;
+  }
+  data->sock = sock;
 #ifdef LWIP_DEBUG
-  data.s = s;
+  data->s = s;
 #endif /* LWIP_DEBUG */
-  data.level = level;
-  data.optname = optname;
-  data.optval = (void*)optval;
-  data.optlen = &optlen;
-  data.err = err;
-  tcpip_callback(lwip_setsockopt_internal, &data);
+  data->level = level;
+  data->optname = optname;
+  data->optval = (void*)optval;
+  data->optlen = &optlen;
+  data->err = err;
+  tcpip_callback(lwip_setsockopt_internal, data);
   sys_arch_sem_wait(&sock->conn->op_completed, 0);
   /* maybe lwip_setsockopt_internal has changed err */
-  err = data.err;
+  err = data->err;
+  memp_free(MEMP_SOCKET_SETGETSOCKOPT_DATA, data);
 
   sock_set_errno(sock, err);
   return err ? -1 : 0;
diff --git a/src/api/tcpip.c b/src/api/tcpip.c
index 7c1c9ca..066e5f6 100644
--- a/src/api/tcpip.c
+++ b/src/api/tcpip.c
@@ -310,17 +310,21 @@ tcpip_untimeout(sys_timeout_handler h, void *arg)
 err_t
 tcpip_apimsg(struct api_msg *apimsg)
 {
-  struct tcpip_msg msg;
 #ifdef LWIP_DEBUG
   /* catch functions that don't set err */
   apimsg->msg.err = ERR_VAL;
 #endif
   
   if (sys_mbox_valid(&mbox)) {
-    msg.type = TCPIP_MSG_API;
-    msg.msg.apimsg = apimsg;
-    sys_mbox_post(&mbox, &msg);
+    struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
+    if (msg == NULL) {
+      return ERR_MEM;
+    }
+    msg->type = TCPIP_MSG_API;
+    msg->msg.apimsg = apimsg;
+    sys_mbox_post(&mbox, msg);
     sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0);
+    memp_free(MEMP_TCPIP_MSG_API, msg);
     return apimsg->msg.err;
   }
   return ERR_VAL;
@@ -340,20 +344,24 @@ tcpip_apimsg(struct api_msg *apimsg)
 err_t
 tcpip_netifapi(struct netifapi_msg* netifapimsg)
 {
-  struct tcpip_msg msg;
-  
   if (sys_mbox_valid(&mbox)) {
+    struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
+    if (msg == NULL) {
+      return NULL;
+    }
+
     err_t err = sys_sem_new(&netifapimsg->msg.sem, 0);
     if (err != ERR_OK) {
       netifapimsg->msg.err = err;
       return err;
     }
     
-    msg.type = TCPIP_MSG_NETIFAPI;
-    msg.msg.netifapimsg = netifapimsg;
-    sys_mbox_post(&mbox, &msg);
+    msg->type = TCPIP_MSG_NETIFAPI;
+    msg->msg.netifapimsg = netifapimsg;
+    sys_mbox_post(&mbox, msg);
     sys_sem_wait(&netifapimsg->msg.sem);
     sys_sem_free(&netifapimsg->msg.sem);
+    memp_free(MEMP_TCPIP_MSG_API, msg);
     return netifapimsg->msg.err;
   }
   return ERR_VAL;
diff --git a/src/core/memp.c b/src/core/memp.c
index 1323463..d656936 100644
--- a/src/core/memp.c
+++ b/src/core/memp.c
@@ -48,6 +48,7 @@
 #include "lwip/igmp.h"
 #include "lwip/api.h"
 #include "lwip/api_msg.h"
+#include "lwip/sockets.h"
 #include "lwip/tcpip.h"
 #include "lwip/sys.h"
 #include "lwip/timers.h"
diff --git a/src/include/lwip/api_msg.h b/src/include/lwip/api_msg.h
index 8268036..4c02141 100644
--- a/src/include/lwip/api_msg.h
+++ b/src/include/lwip/api_msg.h
@@ -75,13 +75,13 @@ struct api_msg_msg {
     } n;
     /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */
     struct {
-      ip_addr_t *ipaddr;
+      ip_addr_t ipaddr;
       u16_t port;
     } bc;
     /** used for lwip_netconn_do_getaddr */
     struct {
-      ipX_addr_t *ipaddr;
-      u16_t *port;
+      ipX_addr_t ipaddr;
+      u16_t port;
       u8_t local;
     } ad;
     /** used for lwip_netconn_do_write */
@@ -104,8 +104,8 @@ struct api_msg_msg {
 #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
     /** used for lwip_netconn_do_join_leave_group */
     struct {
-      ipX_addr_t *multiaddr;
-      ipX_addr_t *netif_addr;
+      ipX_addr_t multiaddr;
+      ipX_addr_t netif_addr;
       enum netconn_igmp join_or_leave;
     } jl;
 #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
@@ -136,12 +136,12 @@ struct dns_api_msg {
   /** Hostname to query or dotted IP address string */
   const char *name;
   /** Rhe resolved address is stored here */
-  ip_addr_t *addr;
+  ip_addr_t addr;
   /** This semaphore is posted when the name is resolved, the application thread
       should wait on it. */
-  sys_sem_t *sem;
+  sys_sem_t sem;
   /** Errors are given back here */
-  err_t *err;
+  err_t err;
 };
 #endif /* LWIP_DNS */
 
diff --git a/src/include/lwip/memp_std.h b/src/include/lwip/memp_std.h
index 592a282..2f632b7 100644
--- a/src/include/lwip/memp_std.h
+++ b/src/include/lwip/memp_std.h
@@ -58,6 +58,16 @@ LWIP_MEMPOOL(NETCONN,        MEMP_NUM_NETCONN,         sizeof(struct netconn),
 
 #if NO_SYS==0
 LWIP_MEMPOOL(TCPIP_MSG_API,  MEMP_NUM_TCPIP_MSG_API,   sizeof(struct tcpip_msg),      "TCPIP_MSG_API")
+LWIP_MEMPOOL(TCPIP_API_MSG_DATA, MEMP_NUM_TCPIP_MSG_API, sizeof(struct api_msg),      "TCPIP_API_MSG_DATA")
+#if LWIP_DNS
+LWIP_MEMPOOL(DNS_API_MSG_DATA, MEMP_NUM_TCPIP_MSG_API, sizeof(struct dns_api_msg),    "DNS_API_MSG_DATA")
+#endif
+#if LWIP_SOCKET
+LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_API, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA")
+#endif
+#if LWIP_NETIF_API
+LWIP_MEMPOOL(NETIF_API_MSG_DATA, MEMP_NUM_TCPIP_MSG_API, sizeof(struct netifapi_msg),    "NETIF_API_MSG_DATA")
+#endif
 #if !LWIP_TCPIP_CORE_LOCKING_INPUT
 LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg),      "TCPIP_MSG_INPKT")
 #endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
diff --git a/src/include/lwip/netifapi.h b/src/include/lwip/netifapi.h
index 33318ef..c28092d 100644
--- a/src/include/lwip/netifapi.h
+++ b/src/include/lwip/netifapi.h
@@ -52,9 +52,9 @@ struct netifapi_msg_msg {
   struct netif *netif;
   union {
     struct {
-      ip_addr_t *ipaddr;
-      ip_addr_t *netmask;
-      ip_addr_t *gw;
+      ip_addr_t ipaddr;
+      ip_addr_t netmask;
+      ip_addr_t gw;
       void *state;
       netif_init_fn init;
       netif_input_fn input;
diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h
index e51f8e5..d470606 100644
--- a/src/include/lwip/opt.h
+++ b/src/include/lwip/opt.h
@@ -351,6 +351,15 @@
 #endif
 
 /**
+ * MEMP_NUM_SOCKET_API: the number of various structures, which are used
+ * for communication with application thread calling socket api functions.
+ * (only needed if you use sockets.c)
+ */
+#ifndef MEMP_NUM_SOCKET_API
+#define MEMP_NUM_SOCKET_API        8
+#endif
+
+/**
  * MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree.
  */
 #ifndef MEMP_NUM_SNMP_NODE
diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h
index 7346137..961b229 100644
--- a/src/include/lwip/sockets.h
+++ b/src/include/lwip/sockets.h
@@ -41,6 +41,7 @@
 #include <stddef.h> /* for size_t */
 
 #include "lwip/ip_addr.h"
+#include "lwip/err.h"
 #include "lwip/inet.h"
 #include "lwip/inet6.h"
 
@@ -84,6 +85,50 @@ struct sockaddr {
 typedef u32_t socklen_t;
 #endif
 
+/** Contains all internal pointers and states used for a socket */
+struct lwip_sock {
+  /** sockets currently are built on netconns, each socket has one netconn */
+  struct netconn *conn;
+  /** data that was left from the previous read */
+  void *lastdata;
+  /** offset in the data that was left from the previous read */
+  u16_t lastoffset;
+  /** number of times data was received, set by event_callback(),
+      tested by the receive and select functions */
+  s16_t rcvevent;
+  /** number of times data was ACKed (free send buffer), set by event_callback(),
+      tested by select */
+  u16_t sendevent;
+  /** error happened for this socket, set by event_callback(), tested by select */
+  u16_t errevent;
+  /** last error that occurred on this socket */
+  int err;
+  /** counter of how many threads are waiting for this socket using select */
+  int select_waiting;
+};
+
+/** 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 struct for which to change options */
+  struct lwip_sock *sock;
+#ifdef LWIP_DEBUG
+  /** socket index for which to change options */
+  int s;
+#endif /* LWIP_DEBUG */
+  /** level of the option to process */
+  int level;
+  /** name of the option to process */
+  int optname;
+  /** set: value to set the option to
+    * get: value of the option is stored here */
+  void *optval;
+  /** size of *optval */
+  socklen_t *optlen;
+  /** if an error occures, it is temporarily stored here */
+  err_t err;
+};
+
 /* Socket protocol types (TCP/UDP/RAW) */
 #define SOCK_STREAM     1
 #define SOCK_DGRAM      2
