diff --git a/Makefile.dep b/Makefile.dep
index be838d4c121e73e76f0dcde790239575354ad119..5ddbbb837f85d8a952da2380cf6a60d0de9e5c71 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -372,6 +372,7 @@ ifneq (,$(filter newlib,$(USEMODULE)))
 endif
 
 ifneq (,$(filter posix_sockets,$(USEMODULE)))
+  USEMODULE += bitfield
   USEMODULE += posix
   USEMODULE += random
 endif
diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules
index 98ef44062f2743da02fdd18db2c6f8013143917c..a91c8c63ea152548a62f519c4d9f1654ec1cab5a 100644
--- a/Makefile.pseudomodules
+++ b/Makefile.pseudomodules
@@ -52,10 +52,6 @@ PSEUDOMODULES += printf_float
 PSEUDOMODULES += saul_adc
 PSEUDOMODULES += saul_default
 PSEUDOMODULES += saul_gpio
-PSEUDOMODULES += sock
-PSEUDOMODULES += sock_ip
-PSEUDOMODULES += sock_tcp
-PSEUDOMODULES += sock_udp
 PSEUDOMODULES += schedstatistics
 PSEUDOMODULES += sock
 PSEUDOMODULES += sock_ip
diff --git a/examples/posix_sockets/Makefile b/examples/posix_sockets/Makefile
index acdf20d83dd54dcea520279b6abaaca70bba628f..3064fc866aad29aec65cb9f429992acefd4fccbc 100644
--- a/examples/posix_sockets/Makefile
+++ b/examples/posix_sockets/Makefile
@@ -19,7 +19,7 @@ USEMODULE += auto_init_gnrc_netif
 # Specify the mandatory networking modules for socket communication via UDP
 USEMODULE += gnrc_ipv6_default
 USEMODULE += gnrc_udp
-USEMODULE += gnrc_conn_udp
+USEMODULE += gnrc_sock_udp
 USEMODULE += posix_sockets
 # Add also the shell, some shell commands
 USEMODULE += shell
diff --git a/pkg/libcoap/Makefile.dep b/pkg/libcoap/Makefile.dep
index b05216b27e67c36b49f9d33e6ea6c7163c1899e4..d29ba7ddb409b3df63e9846578e6c093233beabd 100644
--- a/pkg/libcoap/Makefile.dep
+++ b/pkg/libcoap/Makefile.dep
@@ -1,4 +1,4 @@
 ifneq (,$(filter libcoap,$(USEPKG)))
     USEMODULE += posix_sockets
-    USEMODULE += gnrc_conn_udp
+    USEMODULE += gnrc_sock_udp
 endif
diff --git a/sys/posix/include/sys/socket.h b/sys/posix/include/sys/socket.h
index 2624d5ce4bff19e096e2ba747dba70b7ce1b7045..e9ba8cba96d7c2baad577023cb480cd094ff9052 100644
--- a/sys/posix/include/sys/socket.h
+++ b/sys/posix/include/sys/socket.h
@@ -50,6 +50,29 @@
 extern "C" {
 #endif
 
+/**
+ * @brief Maximum number of sockets available on for creation with @ref socket()
+ */
+#ifndef SOCKET_POOL_SIZE
+#ifdef MODULE_SOCK_TCP
+#define SOCKET_POOL_SIZE        (6)    /* define enough for accepted sockets */
+#else
+#define SOCKET_POOL_SIZE        (4)
+#endif
+#endif
+
+/**
+ * @brief Maximum number of incoming TCP connections a listening socket can
+ *        handle
+ */
+#ifndef SOCKET_TCP_QUEUE_SIZE
+#ifdef MODULE_SOCK_TCP
+#define SOCKET_TCP_QUEUE_SIZE   (2)
+#else
+#define SOCKET_TCP_QUEUE_SIZE   (0)
+#endif
+#endif
+
 /**
  * @brief   Maximum data length for a socket address.
  *
@@ -293,31 +316,6 @@ int getsockname(int socket, struct sockaddr *__restrict address,
  */
 int listen(int socket, int backlog);
 
-/**
- * @brief   Receive a message from a connected socket.
- * @details Shall receive a message from a connection-mode or
- *          connectionless-mode socket. It is normally used with connected
- *          sockets because it does not permit the application to retrieve the
- *          source address of received data.
- *
- * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html">
- *          The Open Group Base Specification Issue 7, recv
- *      </a>
- *
- * @param[in] socket    Specifies the socket file descriptor.
- * @param[out] buffer   Points to a buffer where the message should be stored.
- * @param[in] length    Specifies the length in bytes of the buffer pointed to
- *                      by the buffer argument.
- * @param[in] flags     Specifies the type of message reception. Support for
- *                      values other than 0 is not implemented yet.
- *
- * @return  Upon successful completion, recv() shall return the length of the
- *          message in bytes. If no messages are available to be received and
- *          the peer has performed an orderly shutdown, recv() shall return 0.
- *          Otherwise, -1 shall be returned and errno set to indicate the error.
- */
-ssize_t recv(int socket, void *buffer, size_t length, int flags);
-
 /**
  * @brief   Receive a message from a socket.
  * @details The recvfrom() function shall receive a message from a
@@ -357,27 +355,32 @@ ssize_t recvfrom(int socket, void *__restrict buffer, size_t length, int flags,
                  socklen_t *__restrict address_len);
 
 /**
- * @brief   Send a message on a socket.
- * @details Shall initiate transmission of a message from the specified socket
- *          to its peer. The send() function shall send a message only when the
- *          socket is connected. If the socket is a connectionless-mode socket,
- *          the message shall be sent to the pre-specified peer address.
+ * @brief   Receive a message from a connected socket.
+ * @details Shall receive a message from a connection-mode or
+ *          connectionless-mode socket. It is normally used with connected
+ *          sockets because it does not permit the application to retrieve the
+ *          source address of received data.
  *
- * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html">
- *          The Open Group Base Specification Issue 7, send
+ * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html">
+ *          The Open Group Base Specification Issue 7, recv
  *      </a>
  *
  * @param[in] socket    Specifies the socket file descriptor.
- * @param[in] buffer    Points to the buffer containing the message to send.
- * @param[in] length    Specifies the length of the message in bytes.
- * @param[in] flags     Specifies the type of message reception. Support
- *                      for values other than 0 is not implemented yet.
+ * @param[out] buffer   Points to a buffer where the message should be stored.
+ * @param[in] length    Specifies the length in bytes of the buffer pointed to
+ *                      by the buffer argument.
+ * @param[in] flags     Specifies the type of message reception. Support for
+ *                      values other than 0 is not implemented yet.
  *
- * @return  Upon successful completion, send() shall return the number of bytes
- *          sent. Otherwise, -1 shall be returned and errno set to indicate the
- *          error.
+ * @return  Upon successful completion, recv() shall return the length of the
+ *          message in bytes. If no messages are available to be received and
+ *          the peer has performed an orderly shutdown, recv() shall return 0.
+ *          Otherwise, -1 shall be returned and errno set to indicate the error.
  */
-ssize_t send(int socket, const void *buffer, size_t length, int flags);
+static inline ssize_t recv(int socket, void *buffer, size_t length, int flags)
+{
+    return recvfrom(socket, buffer, length, flags, NULL, NULL);
+}
 
 /**
  * @brief   Send a message on a socket.
@@ -423,6 +426,33 @@ ssize_t send(int socket, const void *buffer, size_t length, int flags);
 ssize_t sendto(int socket, const void *buffer, size_t length, int flags,
                const struct sockaddr *address, socklen_t address_len);
 
+/**
+ * @brief   Send a message on a socket.
+ * @details Shall initiate transmission of a message from the specified socket
+ *          to its peer. The send() function shall send a message only when the
+ *          socket is connected. If the socket is a connectionless-mode socket,
+ *          the message shall be sent to the pre-specified peer address.
+ *
+ * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html">
+ *          The Open Group Base Specification Issue 7, send
+ *      </a>
+ *
+ * @param[in] socket    Specifies the socket file descriptor.
+ * @param[in] buffer    Points to the buffer containing the message to send.
+ * @param[in] length    Specifies the length of the message in bytes.
+ * @param[in] flags     Specifies the type of message reception. Support
+ *                      for values other than 0 is not implemented yet.
+ *
+ * @return  Upon successful completion, send() shall return the number of bytes
+ *          sent. Otherwise, -1 shall be returned and errno set to indicate the
+ *          error.
+ */
+static inline ssize_t send(int socket, const void *buffer, size_t length,
+                           int flags)
+{
+    return sendto(socket, buffer, length, flags, NULL, 0);
+}
+
 /**
  * @brief   Create an endpoint for communication.
  * @details Shall create an unbound socket in a communications domain, and
diff --git a/sys/posix/sockets/posix_sockets.c b/sys/posix/sockets/posix_sockets.c
index c8539ab4dd912eab6d23d1e549fc1d40b83c806c..0daf94b897ed0953f7d9b129471cfbfdcaa5b8e6 100644
--- a/sys/posix/sockets/posix_sockets.c
+++ b/sys/posix/sockets/posix_sockets.c
@@ -16,14 +16,15 @@
  * @todo
  */
 
+#include <assert.h>
 #include <arpa/inet.h>
 #include <errno.h>
 #include <stdbool.h>
 #include <string.h>
 
+#include "bitfield.h"
 #include "fd.h"
 #include "mutex.h"
-#include "net/conn.h"
 #include "net/ipv4/addr.h"
 #include "net/ipv6/addr.h"
 #include "random.h"
@@ -31,35 +32,35 @@
 #include "sys/socket.h"
 #include "netinet/in.h"
 
-#ifdef  MODULE_CONN_IP
-#   include "net/conn/ip.h"
-#endif  /* MODULE_CONN_IP */
-#ifdef  MODULE_CONN_TCP
-#   include "net/conn/tcp.h"
-#endif  /* MODULE_CONN_TCP */
-#ifdef  MODULE_CONN_UDP
-#   include "net/conn/udp.h"
-#endif  /* MODULE_CONN_UDP */
+#include "net/sock/ip.h"
+#include "net/sock/udp.h"
+#include "net/sock/tcp.h"
 
-#define SOCKET_POOL_SIZE    (4)
+/* enough to create sockets both with socket() and accept() */
+#define _ACTUAL_SOCKET_POOL_SIZE   (SOCKET_POOL_SIZE + \
+                                    (SOCKET_POOL_SIZE * SOCKET_TCP_QUEUE_SIZE))
 
 /**
  * @brief   Unitfied connection type.
  */
 typedef union {
-    /* is not supposed to be used */
+    /* is not supposed to be used, this is only for the case that no
+     * sock module was added (maybe useful for UNIX sockets?) */
     /* cppcheck-suppress unusedStructMember */
-    int undef;                  /**< for case that no connection module is present */
-#ifdef  MODULE_CONN_IP
-    conn_ip_t raw;              /**< raw IP connection */
-#endif  /* MODULE_CONN_IP */
-#ifdef  MODULE_CONN_TCP
-    conn_tcp_t tcp;             /**< TCP connection */
-#endif  /* MODULE_CONN_TCP */
-#ifdef  MODULE_CONN_UDP
-    conn_udp_t udp;             /**< UDP connection */
-#endif  /* MODULE_CONN_UDP */
-} socket_conn_t;
+    int undef;
+#ifdef MODULE_SOCK_IP
+    sock_ip_t raw;              /**< raw IP sock */
+#endif /* MODULE_SOCK_IP */
+#ifdef MODULE_SOCK_TCP
+    union {
+        sock_tcp_t sock;        /**< TCP sock */
+        sock_tcp_queue_t queue; /**< TCP queue */
+    } tcp;                      /**< both TCP types */
+#endif /* MODULE_SOCK_TCP */
+#ifdef MODULE_SOCK_UDP
+    sock_udp_t udp;             /**< UDP sock */
+#endif /* MODULE_SOCK_UDP */
+} socket_sock_t;
 
 typedef struct {
     int fd;
@@ -67,40 +68,66 @@ typedef struct {
     int type;
     int protocol;
     bool bound;
-    socket_conn_t conn;
-    uint16_t src_port;
+    socket_sock_t *sock;
+#ifdef MODULE_SOCK_TCP
+    sock_tcp_t *queue_array;
+    unsigned queue_array_len;
+#endif
+    sock_tcp_ep_t local;        /* to store bind before connect/listen */
 } socket_t;
 
-socket_t _pool[SOCKET_POOL_SIZE];
-mutex_t _pool_mutex = MUTEX_INIT;
+static socket_t _socket_pool[_ACTUAL_SOCKET_POOL_SIZE];
+static socket_sock_t _sock_pool[SOCKET_POOL_SIZE];
+#ifdef MODULE_SOCK_TCP
+static sock_tcp_t _tcp_sock_pool[SOCKET_POOL_SIZE][SOCKET_TCP_QUEUE_SIZE];
+#endif
+BITFIELD(_sock_pool_used, SOCKET_POOL_SIZE);
+static mutex_t _socket_pool_mutex = MUTEX_INIT;
 
 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
 
 static socket_t *_get_free_socket(void)
 {
-    for (int i = 0; i < SOCKET_POOL_SIZE; i++) {
-        if (_pool[i].domain == AF_UNSPEC) {
-            return &_pool[i];
+    for (int i = 0; i < _ACTUAL_SOCKET_POOL_SIZE; i++) {
+        if (_socket_pool[i].domain == AF_UNSPEC) {
+            return &_socket_pool[i];
         }
     }
     return NULL;
 }
 
+static socket_sock_t *_get_free_sock(void)
+{
+    int i = bf_get_unset(_sock_pool_used, SOCKET_POOL_SIZE);
+    if (i < 0) {
+        return NULL;
+    }
+    return &_sock_pool[i];
+}
+
 static socket_t *_get_socket(int fd)
 {
-    for (int i = 0; i < SOCKET_POOL_SIZE; i++) {
-        if (_pool[i].fd == fd) {
-            return &_pool[i];
+    for (int i = 0; i < _ACTUAL_SOCKET_POOL_SIZE; i++) {
+        if (_socket_pool[i].fd == fd) {
+            return &_socket_pool[i];
         }
     }
     return NULL;
 }
 
+static int _get_sock_idx(socket_sock_t *sock)
+{
+    if ((sock < &_sock_pool[0]) || (sock > &_sock_pool[SOCKET_POOL_SIZE - 1])) {
+        return -1;
+    }
+    return sock - &_sock_pool[0];
+}
+
 static inline int _choose_ipproto(int type, int protocol)
 {
     switch (type) {
-#ifdef MODULE_CONN_TCP
+#ifdef MODULE_SOCK_TCP
         case SOCK_STREAM:
             if ((protocol == 0) || (protocol == IPPROTO_TCP)) {
                 return protocol;
@@ -110,7 +137,7 @@ static inline int _choose_ipproto(int type, int protocol)
             }
             break;
 #endif
-#ifdef MODULE_CONN_UDP
+#ifdef MODULE_SOCK_UDP
         case SOCK_DGRAM:
             if ((protocol == 0) || (protocol == IPPROTO_UDP)) {
                 return protocol;
@@ -120,7 +147,7 @@ static inline int _choose_ipproto(int type, int protocol)
             }
             break;
 #endif
-#ifdef MODULE_CONN_IP
+#ifdef MODULE_SOCK_IP
         case SOCK_RAW:
             return protocol;
 #endif
@@ -132,36 +159,45 @@ static inline int _choose_ipproto(int type, int protocol)
     return -1;
 }
 
-static inline ipv4_addr_t *_in_addr_ptr(struct sockaddr_storage *addr)
-{
-    return (ipv4_addr_t *)(&((struct sockaddr_in *)addr)->sin_addr);
-}
-
-static inline uint16_t *_in_port_ptr(struct sockaddr_storage *addr)
-{
-    return &((struct sockaddr_in *)addr)->sin_port;
-}
-
-static inline ipv6_addr_t *_in6_addr_ptr(struct sockaddr_storage *addr)
-{
-    return (ipv6_addr_t *)(&((struct sockaddr_in6 *)addr)->sin6_addr);
-}
-
-static inline uint16_t *_in6_port_ptr(struct sockaddr_storage *addr)
-{
-    return &((struct sockaddr_in6 *)addr)->sin6_port;
-}
-
 static inline socklen_t _addr_truncate(struct sockaddr *out, socklen_t out_len,
-                                       struct sockaddr_storage *in, socklen_t target_size)
-{
-    out_len = (out_len < target_size) ? out_len : target_size;
+                                       struct sockaddr_storage *in,
+                                       socklen_t target_size) {
+    out_len = (out_len < target_size) ?  out_len : target_size;
     memcpy(out, in, out_len);
     return out_len;
 }
 
-static inline int _get_data_from_sockaddr(const struct sockaddr *address, size_t address_len,
-                                          void **addr, size_t *addr_len, network_uint16_t *port)
+static int _ep_to_sockaddr(const struct _sock_tl_ep *ep,
+                           struct sockaddr_storage *out)
+{
+    assert((ep->family == AF_INET) || (ep->family == AF_INET6));
+    switch (ep->family) {
+        case AF_INET: {
+            struct sockaddr_in *in_addr = (struct sockaddr_in *)out;
+
+            in_addr->sin_family = AF_INET;
+            in_addr->sin_addr.s_addr = ep->addr.ipv4_u32;
+            in_addr->sin_port = htons(ep->port);
+            return sizeof(struct sockaddr_in);
+        }
+#ifdef SOCK_HAS_IPV6
+        case AF_INET6: {
+            struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)out;
+
+            in6_addr->sin6_family = AF_INET6;
+            memcpy(&in6_addr->sin6_addr, &ep->addr.ipv6, sizeof(ep->addr.ipv6));
+            in6_addr->sin6_port = htons(ep->port);
+            return sizeof(struct sockaddr_in6);
+        }
+#endif
+        default:
+            /* should not happen */
+            return 0;
+    }
+}
+
+static int _sockaddr_to_ep(const struct sockaddr *address, socklen_t address_len,
+                           struct _sock_tl_ep *out)
 {
     switch (address->sa_family) {
         case AF_INET:
@@ -170,20 +206,22 @@ static inline int _get_data_from_sockaddr(const struct sockaddr *address, size_t
                 return -1;
             }
             struct sockaddr_in *in_addr = (struct sockaddr_in *)address;
-            *addr = &in_addr->sin_addr;
-            *addr_len = sizeof(ipv4_addr_t);
-            port->u16 = in_addr->sin_port;
+            out->family = AF_INET;
+            out->addr.ipv4_u32 = in_addr->sin_addr.s_addr;
+            out->port = ntohs(in_addr->sin_port);
             break;
+#ifdef SOCK_HAS_IPV6
         case AF_INET6:
             if (address_len < sizeof(struct sockaddr_in6)) {
                 errno = EINVAL;
                 return -1;
             }
             struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)address;
-            *addr = &in6_addr->sin6_addr;
-            *addr_len = sizeof(ipv6_addr_t);
-            port->u16 = in6_addr->sin6_port;
+            out->family = AF_INET6;
+            memcpy(&out->addr.ipv6, &in6_addr->sin6_addr, sizeof(out->addr.ipv6));
+            out->port = ntohs(in6_addr->sin6_port);
             break;
+#endif
         default:
             errno = EAFNOSUPPORT;
             return -1;
@@ -191,89 +229,50 @@ static inline int _get_data_from_sockaddr(const struct sockaddr *address, size_t
     return 0;
 }
 
-static int _implicit_bind(socket_t *s, void *addr)
-{
-    ipv6_addr_t unspec;
-    ipv6_addr_t *best_match;
-    int res;
-
-    /* TODO: ensure that this port hasn't been used yet */
-    s->src_port = (uint16_t)random_uint32_range(1LU << 10U, 1LU << 16U);
-
-    /* find the best matching source address */
-    if ((best_match = conn_find_best_source(addr)) == NULL) {
-        ipv6_addr_set_unspecified(&unspec);
-        best_match = &unspec;
-    }
-    switch (s->type) {
-#ifdef MODULE_CONN_TCP
-        case SOCK_STREAM:
-            res = conn_tcp_create(&s->conn.udp, best_match, sizeof(unspec),
-                                  s->domain, s->src_port);
-            break;
-#endif
-#ifdef MODULE_CONN_UDP
-        case SOCK_DGRAM:
-            res = conn_udp_create(&s->conn.udp, best_match, sizeof(unspec),
-                                  s->domain, s->src_port);
-            break;
-#endif
-        default:
-            res = -1;
-            break;
-    }
-    if (res < 0) {
-        errno = -res;
-    }
-    else {
-        s->bound = true;
-    }
-    return res;
-}
-
 static int socket_close(int socket)
 {
     socket_t *s;
     int res = 0;
-    if ((unsigned)(socket - 1) > (SOCKET_POOL_SIZE - 1)) {
-        return -1;
-    }
-    mutex_lock(&_pool_mutex);
-    s = &_pool[socket];
-    if (s->bound) {
-        switch (s->domain) {
-            case AF_INET:
-            case AF_INET6:
-                switch (s->type) {
-#ifdef MODULE_CONN_UDP
-                    case SOCK_DGRAM:
-                        conn_udp_close(&s->conn.udp);
-                        break;
-#endif
-#ifdef MODULE_CONN_IP
-                    case SOCK_RAW:
-                        conn_ip_close(&s->conn.raw);
-                        break;
+
+    assert((unsigned)(socket - 1) > (_ACTUAL_SOCKET_POOL_SIZE - 1));
+    s = &_socket_pool[socket];
+    assert((s->domain == AF_INET) || (s->domain == AF_INET6));
+    mutex_lock(&_socket_pool_mutex);
+    if (s->sock != NULL) {
+        int idx = _get_sock_idx(s->sock);
+        switch (s->type) {
+#ifdef MODULE_SOCK_UDP
+            case SOCK_DGRAM:
+                sock_udp_close(&s->sock->udp);
+                break;
 #endif
-#ifdef MODULE_CONN_TCP
-                    case SOCK_STREAM:
-                        conn_tcp_close(&s->conn.tcp);
-                        break;
+#ifdef MODULE_SOCK_IP
+            case SOCK_RAW:
+                sock_ip_close(&s->sock->raw);
+                break;
 #endif
-                    default:
-                        errno = EOPNOTSUPP;
-                        res = -1;
-                        break;
+#ifdef MODULE_SOCK_TCP
+            case SOCK_STREAM:
+                if (s->queue_array == 0) {
+                    sock_tcp_disconnect(&s->sock->tcp.sock);
+                }
+                else {
+                    sock_tcp_stop_listen(&s->sock->tcp.queue);
                 }
                 break;
+#endif
             default:
+                errno = EOPNOTSUPP;
                 res = -1;
                 break;
         }
+        if (idx >= 0) {
+            bf_unset(_sock_pool_used, idx);
+        }
     }
+    mutex_unlock(&_socket_pool_mutex);
+    s->sock = NULL;
     s->domain = AF_UNSPEC;
-    s->src_port = 0;
-    mutex_unlock(&_pool_mutex);
     return res;
 }
 
@@ -291,43 +290,55 @@ int socket(int domain, int type, int protocol)
 {
     int res = 0;
     socket_t *s;
-    mutex_lock(&_pool_mutex);
+
+    mutex_lock(&_socket_pool_mutex);
     s = _get_free_socket();
     if (s == NULL) {
         errno = ENFILE;
-        mutex_unlock(&_pool_mutex);
+        mutex_unlock(&_socket_pool_mutex);
         return -1;
     }
     switch (domain) {
         case AF_INET:
+#ifdef SOCK_HAS_IPV6
         case AF_INET6:
+#endif
+        {
+            int fd = fd_new(s - _socket_pool, socket_read, socket_write,
+                            socket_close);
+
+            if (fd < 0) {
+                errno = ENFILE;
+                res = -1;
+                break;
+            }
+            else {
+                s->fd = res = fd;
+            }
             s->domain = domain;
             s->type = type;
             if ((s->protocol = _choose_ipproto(type, protocol)) < 0) {
                 res = -1;
+                break;
+            }
+            s->bound = false;
+            s->sock = NULL;
+#ifdef MODULE_SOCK_TCP
+            if (type == SOCK_STREAM)  {
+                s->queue_array = NULL;
+                s->queue_array_len = 0;
+                memset(&s->local, 0, sizeof(sock_tcp_ep_t));
             }
+#endif
             break;
-
+        }
         default:
             (void)type;
             (void)protocol;
             errno = EAFNOSUPPORT;
             res = -1;
     }
-    if (res == 0) {
-        /* TODO: add read and write */
-        int fd = fd_new(s - _pool, socket_read, socket_write, socket_close);
-        if (fd < 0) {
-            errno = ENFILE;
-            res = -1;
-        }
-        else {
-            s->fd = res = fd;
-        }
-    }
-    s->bound = false;
-    s->src_port = 0;
-    mutex_unlock(&_pool_mutex);
+    mutex_unlock(&_socket_pool_mutex);
     return res;
 }
 
@@ -335,66 +346,58 @@ int socket(int domain, int type, int protocol)
 int accept(int socket, struct sockaddr *restrict address,
            socklen_t *restrict address_len)
 {
+#ifdef MODULE_SOCK_TCP
+    sock_tcp_t *sock = NULL;
     socket_t *s, *new_s = NULL;
     int res = 0;
-    /* May be kept unassigned if no conn module is available */
-    /* cppcheck-suppress unassignedVariable */
-    struct sockaddr_storage tmp;
-    void *addr;
-    uint16_t *port;
-    socklen_t tmp_len;
-    mutex_lock(&_pool_mutex);
+
+    mutex_lock(&_socket_pool_mutex);
     s = _get_socket(socket);
     if (s == NULL) {
-        mutex_unlock(&_pool_mutex);
+        mutex_unlock(&_socket_pool_mutex);
         errno = ENOTSOCK;
         return -1;
     }
-    if (!s->bound) {
-        mutex_unlock(&_pool_mutex);
+    if (s->sock == NULL) {
+        mutex_unlock(&_socket_pool_mutex);
         errno = EINVAL;
         return -1;
     }
-    switch (s->domain) {
-        case AF_INET:
-            addr = _in_addr_ptr(&tmp);
-            port = _in_port_ptr(&tmp);
-            tmp_len = sizeof(struct sockaddr_in);
-            break;
-        case AF_INET6:
-            addr = _in6_addr_ptr(&tmp);
-            port = _in6_port_ptr(&tmp);
-            tmp_len = sizeof(struct sockaddr_in6);
-            break;
-        default:
-            (void)address;
-            (void)address_len;
-            (void)new_s;
-            (void)tmp;
-            (void)addr;
-            (void)port;
-            (void)tmp_len;
-            errno = EPROTO;
-            res = -1;
-            break;
-    }
     switch (s->type) {
-#ifdef MODULE_CONN_TCP
         case SOCK_STREAM:
             new_s = _get_free_socket();
+            sock = (sock_tcp_t *)new_s->sock;
             if (new_s == NULL) {
                 errno = ENFILE;
                 res = -1;
                 break;
             }
-            if ((res = conn_tcp_accept(&s->conn.tcp, &new_s->conn.tcp)) < 0) {
+            /* TODO: apply configured timeout */
+            if ((res = sock_tcp_accept(&s->sock->tcp.queue, &sock,
+                                       SOCK_NO_TIMEOUT)) < 0) {
                 errno = -res;
                 res = -1;
                 break;
             }
-            else if ((address != NULL) && (address_len != NULL)) {
-                /* TODO: add read and write */
-                int fd = fd_new(new_s - _pool, NULL, NULL, socket_close);
+            else {
+                if ((address != NULL) && (address_len != NULL)) {
+                    sock_tcp_ep_t ep;
+                    struct sockaddr_storage sa;
+                    socklen_t sa_len;
+
+                    if ((res = sock_tcp_get_remote(sock, &ep)) < 0) {
+                        errno = -res;
+                        res = -1;
+                        break;
+                    }
+                    sa.ss_family = s->domain;
+                    sa_len = _ep_to_sockaddr(&ep, &sa);
+                    *address_len = _addr_truncate(address, *address_len, &sa,
+                                                  sa_len);
+
+                }
+                int fd = fd_new(new_s - _socket_pool, socket_read, socket_write,
+                                socket_close);
                 if (fd < 0) {
                     errno = ENFILE;
                     res = -1;
@@ -406,329 +409,356 @@ int accept(int socket, struct sockaddr *restrict address,
                 new_s->domain = s->domain;
                 new_s->type = s->type;
                 new_s->protocol = s->protocol;
-                tmp.ss_family = s->domain;
-                if ((res = conn_tcp_getpeeraddr(&s->conn.tcp, addr, port)) < 0) {
-                    errno = -res;
-                    res = -1;
-                    break;
-                }
-                *port = htons(*port); /* XXX: sin(6)_port is supposed to be
-                                         network byte order */
-                *address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
+                new_s->bound = true;
+                new_s->queue_array = NULL;
+                new_s->queue_array_len = 0;
+                memset(&s->local, 0, sizeof(sock_tcp_ep_t));
             }
             break;
-#endif
         default:
             errno = EOPNOTSUPP;
             res = -1;
             break;
     }
-    mutex_unlock(&_pool_mutex);
+    if ((res < 0) && (sock != NULL)) {
+        sock_tcp_disconnect(sock);
+    }
+    mutex_unlock(&_socket_pool_mutex);
     return res;
+#else
+    (void)socket;
+    (void)address;
+    (void)address_len;
+    errno = -EOPNOTSUPP;
+    return -1;
+#endif
 }
 
 int bind(int socket, const struct sockaddr *address, socklen_t address_len)
 {
     socket_t *s;
     int res = 0;
-    void *addr;
-    size_t addr_len;
-    network_uint16_t port = { 0 };
-    mutex_lock(&_pool_mutex);
+
+    /* only store bind data, real bind happens in _bind_connect/listen */
+    mutex_lock(&_socket_pool_mutex);
     s = _get_socket(socket);
-    mutex_unlock(&_pool_mutex);
+    mutex_unlock(&_socket_pool_mutex);
     if (s == NULL) {
         errno = ENOTSOCK;
         return -1;
     }
-    if (address->sa_family != s->domain) {
-        errno = EAFNOSUPPORT;
+    if (s->bound) {
+        errno = EINVAL;
         return -1;
     }
-    if (_get_data_from_sockaddr(address, address_len, &addr, &addr_len, &port) < 0) {
+    if (address->sa_family != s->domain) {
+        errno = EAFNOSUPPORT;
         return -1;
     }
     switch (s->type) {
-#ifdef MODULE_CONN_IP
+#ifdef MODULE_SOCK_IP
         case SOCK_RAW:
-            (void)port;
-            if ((res = conn_ip_create(&s->conn.raw, addr, addr_len, s->domain, s->protocol)) < 0) {
-                errno = -res;
-                return -1;
-            }
             break;
 #endif
-#ifdef MODULE_CONN_TCP
+#ifdef MODULE_SOCK_TCP
         case SOCK_STREAM:
-            if ((res = conn_tcp_create(&s->conn.tcp, addr, addr_len, s->domain,
-                                       byteorder_ntohs(port))) < 0) {
-                errno = -res;
-                return -1;
-            }
             break;
 #endif
-#ifdef MODULE_CONN_UDP
+#ifdef MODULE_SOCK_UDP
         case SOCK_DGRAM:
-            if ((res = conn_udp_create(&s->conn.udp, addr, addr_len, s->domain,
-                                       byteorder_ntohs(port))) < 0) {
-
-                errno = -res;
-                return -1;
-            }
             break;
 #endif
         default:
-            (void)addr;
-            (void)addr_len;
-            (void)port;
             (void)res;
             errno = EOPNOTSUPP;
             return -1;
     }
-    s->src_port = byteorder_ntohs(port);
+    if (_sockaddr_to_ep(address, address_len, &s->local) < 0) {
+        return -1;
+    }
     s->bound = true;
     return 0;
 }
 
-int connect(int socket, const struct sockaddr *address, socklen_t address_len)
+static int _bind_connect(socket_t *s, const struct sockaddr *address,
+                         socklen_t address_len)
 {
-    socket_t *s;
-    int res = 0;
-    void *addr;
-    size_t addr_len;
-    network_uint16_t port;
-    mutex_lock(&_pool_mutex);
-    s = _get_socket(socket);
-    mutex_unlock(&_pool_mutex);
-    if (s == NULL) {
-        errno = ENOTSOCK;
-        return -1;
+    struct _sock_tl_ep r, *remote = NULL, *local = NULL;
+    int res;
+    socket_sock_t *sock;
+
+    assert((s != NULL) && ((address == NULL) || (address_len > 0)));
+    if (address != NULL) {
+        if (address->sa_family != s->domain) {
+            errno = EAFNOSUPPORT;
+            return -1;
+        }
+        if (_sockaddr_to_ep(address, address_len, &r) < 0) {
+            return -1;
+        }
+        remote = &r;
     }
-    if (address->sa_family != s->domain) {
-        errno = EAFNOSUPPORT;
-        return -1;
+    if (s->bound) {
+        local = &s->local;
     }
-    if (_get_data_from_sockaddr(address, address_len, &addr, &addr_len, &port) < 0) {
+    mutex_lock(&_socket_pool_mutex);
+    sock = _get_free_sock();
+    mutex_unlock(&_socket_pool_mutex);
+    if (sock == NULL) {
+        errno = ENOMEM;
         return -1;
     }
     switch (s->type) {
-#ifdef MODULE_CONN_TCP
+#ifdef MODULE_SOCK_IP
+        case SOCK_RAW:
+            /* TODO apply flags if possible */
+            res = sock_ip_create(&sock->raw, (sock_ip_ep_t *)local,
+                                 (sock_ip_ep_t *)remote, s->protocol, 0);
+            break;
+#endif
+#ifdef MODULE_SOCK_TCP
         case SOCK_STREAM:
-            /* "If the socket has not already been bound to a local address,
-             * connect() shall bind it to an address which, unless the socket's
-             * address family is AF_UNIX, is an unused local address." (see
-             * http://pubs.opengroup.org/onlinepubs/009695399/functions/connect.html)
-             */
-            if (!s->bound) {
-                if ((res = _implicit_bind(s, addr)) < 0) {
-                    return res;
-                }
-            }
-
-            if ((res = conn_tcp_connect(&s->conn.tcp, addr, addr_len,
-                                        byteorder_ntohs(port))) < 0) {
-
-                errno = -res;
-                return -1;
-            }
+            /* TODO apply flags if possible */
+            assert(remote != NULL);
+            res = sock_tcp_connect(&sock->tcp.sock, remote,
+                                   (local == NULL) ? 0 : local->port, 0);
+            break;
+#endif
+#ifdef MODULE_SOCK_UDP
+        case SOCK_DGRAM:
+            /* TODO apply flags if possible */
+            res = sock_udp_create(&sock->udp, local, remote, 0);
             break;
 #endif
         default:
-            (void)res;
-            errno = EPROTOTYPE;
-            return -1;
+            (void)local;
+            (void)remote;
+            res = -EOPNOTSUPP;
+            break;
     }
+    if (res < 0) {
+        errno = -res;
+        /* free sock again */
+        mutex_lock(&_socket_pool_mutex);
+        bf_unset(_sock_pool_used, _get_sock_idx(sock));
+        mutex_unlock(&_socket_pool_mutex);
+        return -1;
+    }
+    s->sock = sock;
     return 0;
 }
 
-int getpeername(int socket, struct sockaddr *__restrict address,
-                socklen_t *__restrict address_len)
+int connect(int socket, const struct sockaddr *address, socklen_t address_len)
 {
     socket_t *s;
-    int res = 0;
-    /* May be kept unassigned if no conn module is available */
-    /* cppcheck-suppress unassignedVariable */
-    struct sockaddr_storage tmp;
-    void *addr;
-    uint16_t *port;
-    socklen_t tmp_len;
-    mutex_lock(&_pool_mutex);
+
+    mutex_lock(&_socket_pool_mutex);
     s = _get_socket(socket);
-    mutex_unlock(&_pool_mutex);
+    mutex_unlock(&_socket_pool_mutex);
     if (s == NULL) {
         errno = ENOTSOCK;
         return -1;
     }
-    switch (s->domain) {
-        case AF_INET:
-            addr = _in_addr_ptr(&tmp);
-            port = _in_port_ptr(&tmp);
-            tmp_len = sizeof(struct sockaddr_in);
-            break;
-        case AF_INET6:
-            addr = _in6_addr_ptr(&tmp);
-            port = _in6_port_ptr(&tmp);
-            tmp_len = sizeof(struct sockaddr_in6);
-            break;
-        default:
-            (void)address;
-            (void)address_len;
-            (void)tmp;
-            (void)addr;
-            (void)port;
-            (void)tmp_len;
-            (void)res;
-            errno = EBADF;
-            return -1;
+    if (s->sock != NULL) {
+#ifdef MODULE_SOCK_TCP
+        if (s->queue_array != NULL) {
+            errno = EOPNOTSUPP;
+        }
+        else
+#endif
+        {
+            errno = EISCONN;
+        }
+        return -1;
     }
-    if (*address_len != tmp_len) {
-        errno = EINVAL;
+    return _bind_connect(s, address, address_len);
+}
+
+static int _getpeername(socket_t *s, struct sockaddr *__restrict address,
+                        socklen_t *__restrict address_len)
+{
+    struct _sock_tl_ep ep;
+    int res = 0;
+
+    if (s->sock == NULL) {
+        errno = ENOTCONN;
         return -1;
     }
     switch (s->type) {
-#ifdef MODULE_CONN_TCP
+#ifdef MODULE_SOCK_IP
+        case SOCK_RAW:
+            res = sock_ip_get_remote(&s->sock->raw, (sock_ip_ep_t *)&ep);
+            break;
+#endif
+#ifdef MODULE_SOCK_TCP
         case SOCK_STREAM:
-            if ((res = conn_tcp_getpeeraddr(&s->conn.tcp, addr, port)) < 0) {
-                errno = -res;
-                return -1;
+            if (s->queue_array == NULL) {
+                res = sock_tcp_get_remote(&s->sock->tcp.sock, &ep);
             }
+            else {
+                res = -ENOTCONN;
+            }
+            break;
+#endif
+#ifdef MODULE_SOCK_UDP
+        case SOCK_DGRAM:
+            res = sock_udp_get_remote(&s->sock->udp, &ep);
             break;
 #endif
         default:
-            errno = ENOTCONN;
-            return -1;
+            res = -EOPNOTSUPP;
+            break;
     }
-    tmp.ss_family = s->domain;
-    *port = htons(*port); /* XXX: sin(6)_port is supposed to be network byte
-                             order */
-    *address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
-    return 0;
+    if (res < 0) {
+        errno = -res;
+        res = -1;
+    }
+    else {
+        struct sockaddr_storage sa;
+        socklen_t sa_len = _ep_to_sockaddr(&ep, &sa);
+        *address_len = _addr_truncate(address, *address_len, &sa,
+                                      sa_len);
+    }
+    return res;
+}
+
+int getpeername(int socket, struct sockaddr *__restrict address,
+                socklen_t *__restrict address_len)
+{
+    socket_t *s;
+
+    mutex_lock(&_socket_pool_mutex);
+    s = _get_socket(socket);
+    mutex_unlock(&_socket_pool_mutex);
+    if (s == NULL) {
+        errno = ENOTSOCK;
+        return -1;
+    }
+    return _getpeername(s, address, address_len);
 }
 
 int getsockname(int socket, struct sockaddr *__restrict address,
                 socklen_t *__restrict address_len)
 {
     socket_t *s;
+    struct sockaddr_storage sa;
+    socklen_t sa_len;
     int res = 0;
-    /* May be kept unassigned if no conn module is available */
-    /* cppcheck-suppress unassignedVariable */
-    struct sockaddr_storage tmp;
-    void *addr;
-    uint16_t *port;
-    socklen_t tmp_len;
-    mutex_lock(&_pool_mutex);
+
+    mutex_lock(&_socket_pool_mutex);
     s = _get_socket(socket);
-    mutex_unlock(&_pool_mutex);
+    mutex_unlock(&_socket_pool_mutex);
     if (s == NULL) {
         errno = ENOTSOCK;
         return -1;
     }
-    if (!s->bound) {
-        memset(address, 0, *address_len);
-        return 0;
-    }
-    switch (s->domain) {
-        case AF_INET:
-            addr = _in_addr_ptr(&tmp);
-            port = _in_port_ptr(&tmp);
-            tmp_len = sizeof(struct sockaddr_in);
-            break;
-        case AF_INET6:
-            addr = _in6_addr_ptr(&tmp);
-            port = _in6_port_ptr(&tmp);
-            tmp_len = sizeof(struct sockaddr_in6);
-            break;
-        default:
-            (void)address;
-            (void)address_len;
-            (void)tmp;
-            (void)addr;
-            (void)port;
-            (void)tmp_len;
-            (void)res;
-            errno = EBADF;
-            return -1;
-    }
-    if (*address_len != tmp_len) {
-        errno = EINVAL;
-        return -1;
+    if (s->sock == NULL) {
+        sa_len = _ep_to_sockaddr(&s->local, &sa);
     }
-    switch (s->type) {
-#ifdef MODULE_CONN_UDP
-        case SOCK_DGRAM:
-            if ((res = conn_udp_getlocaladdr(&s->conn.udp, addr, port)) < 0) {
-                errno = -res;
-                return -1;
-            }
-            break;
+    else {
+        struct _sock_tl_ep ep;
+        switch (s->type) {
+#ifdef MODULE_SOCK_IP
+            case SOCK_RAW:
+                res = sock_ip_get_local(&s->sock->raw, (sock_ip_ep_t *)&ep);
+                break;
 #endif
-#ifdef MODULE_CONN_IP
-        case SOCK_RAW:
-            if ((res = conn_ip_getlocaladdr(&s->conn.raw, addr)) < 0) {
-                errno = -res;
-                return -1;
-            }
-            break;
+#ifdef MODULE_SOCK_TCP
+            case SOCK_STREAM:
+                if (s->queue_array == NULL) {
+                    res = sock_tcp_get_local(&s->sock->tcp.sock, &ep);
+                }
+                else {
+                    res = sock_tcp_queue_get_local(&s->sock->tcp.queue, &ep);
+                }
+                break;
 #endif
-#ifdef MODULE_CONN_TCP
-        case SOCK_STREAM:
-            if ((res = conn_tcp_getlocaladdr(&s->conn.tcp, addr, port)) < 0) {
-                errno = -res;
-                return -1;
-            }
-            break;
+#ifdef MODULE_SOCK_UDP
+            case SOCK_DGRAM:
+                res = sock_udp_get_local(&s->sock->udp, &ep);
+                break;
 #endif
-        default:
-            errno = EOPNOTSUPP;
-            return -1;
+            default:
+                res = -EOPNOTSUPP;
+                break;
+        }
+        sa_len = _ep_to_sockaddr(&ep, &sa);
     }
-    tmp.ss_family = AF_INET;
-    *port = htons(*port); /* XXX: sin(6)_port is supposed to be network byte
-                             order */
-    *address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
-    return 0;
+    if (res < 0) {
+        errno = -res;
+        res = -1;
+    }
+    else {
+        *address_len = _addr_truncate(address, *address_len, &sa,
+                                      sa_len);
+    }
+    return res;
 }
 
 int listen(int socket, int backlog)
 {
+#ifdef MODULE_SOCK_TCP
     socket_t *s;
+    socket_sock_t *sock;
     int res = 0;
-    mutex_lock(&_pool_mutex);
+
+    mutex_lock(&_socket_pool_mutex);
     s = _get_socket(socket);
-    mutex_unlock(&_pool_mutex);
-    if (!s->bound) {
-        errno = EINVAL;
+    if (s == NULL) {
+        errno = ENOTSOCK;
+        mutex_unlock(&_socket_pool_mutex);
         return -1;
     }
-    switch (s->domain) {
-        case AF_INET:
-        case AF_INET6:
-            switch (s->type) {
-#ifdef MODULE_CONN_TCP
-                case SOCK_STREAM:
-                    if ((res = conn_tcp_listen(&s->conn.tcp, backlog)) < 0) {
-                        errno = -res;
-                        return -1;
-                    }
-                    break;
-#endif
-                default:
-                    errno = EOPNOTSUPP;
-                    return -1;
+    if (s->sock != NULL) {
+        /* or this socket is already connected, this is an error */
+        if (s->queue_array == NULL) {
+            errno = EINVAL;
+            res = -1;
+        }
+        mutex_unlock(&_socket_pool_mutex);
+        return res;
+    }
+    sock = _get_free_sock();
+    mutex_unlock(&_socket_pool_mutex);
+    if (sock == NULL) {
+        errno = ENOMEM;
+        return -1;
+    }
+    s->queue_array = _tcp_sock_pool[_get_sock_idx(sock)];
+    s->queue_array_len = (backlog < SOCKET_TCP_QUEUE_SIZE) ? backlog :
+                         SOCKET_TCP_QUEUE_SIZE;
+    switch (s->type) {
+        case SOCK_STREAM:
+            if (s->bound) {
+                /* TODO apply flags if possible */
+                res = sock_tcp_listen(&sock->tcp.queue, &s->local,
+                                      s->queue_array, s->queue_array_len, 0);
+            }
+            else {
+                res = -EDESTADDRREQ;
             }
             break;
         default:
-            (void)backlog;
-            (void)res;
-            errno = EAFNOSUPPORT;
-            return -1;
+            res = -EOPNOTSUPP;
+            break;
     }
-    return 0;
-}
-
-ssize_t recv(int socket, void *buffer, size_t length, int flags)
-{
-    return recvfrom(socket, buffer, length, flags, NULL, NULL);
+    if (res == 0) {
+        s->sock = sock;
+    }
+    else {
+        errno = -res;
+        res = -1;
+        mutex_lock(&_socket_pool_mutex);
+        bf_unset(_sock_pool_used, _get_sock_idx(sock));
+        mutex_unlock(&_socket_pool_mutex);
+    }
+    return -res;
+#else
+    (void)socket;
+    (void)backlog;
+    errno = EOPNOTSUPP;
+    return -1;
+#endif
 }
 
 ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
@@ -737,217 +767,139 @@ ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
 {
     socket_t *s;
     int res = 0;
-    /* May be kept unassigned if no conn module is available */
-    /* cppcheck-suppress unassignedVariable */
-    struct sockaddr_storage tmp;
-    void *addr;
-    size_t addr_len;
-    uint16_t *port;
-    socklen_t tmp_len;
+    struct _sock_tl_ep ep = { .port = 0 };
+
     (void)flags;
-    mutex_lock(&_pool_mutex);
+    mutex_lock(&_socket_pool_mutex);
     s = _get_socket(socket);
-    mutex_unlock(&_pool_mutex);
+    mutex_unlock(&_socket_pool_mutex);
     if (s == NULL) {
         errno = ENOTSOCK;
         return -1;
     }
-    if (!s->bound) {
-        errno = EINVAL;
-        return -1;
-    }
-    memset(&tmp, 0, sizeof(struct sockaddr_storage));
-    switch (s->domain) {
-        case AF_INET:
-            addr = _in_addr_ptr(&tmp);
-            port = _in_port_ptr(&tmp);
-            addr_len = sizeof(ipv4_addr_t);
-            tmp_len = sizeof(struct sockaddr_in);
-            break;
-        case AF_INET6:
-            addr = _in6_addr_ptr(&tmp);
-            port = _in6_port_ptr(&tmp);
-            addr_len = sizeof(ipv6_addr_t);
-            tmp_len = sizeof(struct sockaddr_in6);
-            break;
-        default:
-            (void)buffer;
-            (void)length;
-            (void)address;
-            (void)address_len;
-            (void)tmp;
-            (void)addr;
-            (void)port;
-            (void)tmp_len;
-            errno = EAFNOSUPPORT;
+    if (s->sock == NULL) {  /* socket is not connected */
+#ifdef MODULE_SOCK_TCP
+        if (s->type == SOCK_STREAM) {
+            errno = ENOTCONN;
+            return -1;
+        }
+#endif
+        /* bind implicitly */
+        if ((res = _bind_connect(s, NULL, 0)) < 0) {
+            errno = -res;
             return -1;
+        }
     }
     switch (s->type) {
-#ifdef MODULE_CONN_UDP
-        case SOCK_DGRAM:
-            if ((res = conn_udp_recvfrom(&s->conn.udp, buffer, length, addr,
-                                         &addr_len, port)) < 0) {
-                errno = -res;
-                return -1;
-            }
-            break;
-#endif
-#ifdef MODULE_CONN_IP
+#ifdef MODULE_SOCK_IP
         case SOCK_RAW:
-            if ((res = conn_ip_recvfrom(&s->conn.raw, buffer, length, addr, &addr_len)) < 0) {
-                errno = -res;
-                return -1;
-            }
+            /* TODO: apply configured timeout */
+            res = sock_ip_recv(&s->sock->raw, buffer, length, SOCK_NO_TIMEOUT,
+                               (sock_ip_ep_t *)&ep);
             break;
 #endif
-#ifdef MODULE_CONN_TCP
+#ifdef MODULE_SOCK_TCP
         case SOCK_STREAM:
-            if ((res = conn_tcp_recv(&s->conn.tcp, buffer, length)) < 0) {
-                errno = -res;
-                return -1;
-            }
-            if ((res = conn_tcp_getpeeraddr(&s->conn.tcp, addr, port)) < 0) {
-                errno = -res;
-                return -1;
-            }
+            /* TODO: apply configured timeout */
+            res = sock_tcp_read(&s->sock->tcp.sock, buffer, length,
+                                SOCK_NO_TIMEOUT);
+            break;
+#endif
+#ifdef MODULE_SOCK_UDP
+        case SOCK_DGRAM:
+            /* TODO: apply configured timeout */
+            res = sock_udp_recv(&s->sock->udp, buffer, length, SOCK_NO_TIMEOUT,
+                                &ep);
             break;
 #endif
         default:
-            (void)addr_len;
-            errno = EOPNOTSUPP;
-            return -1;
+            res = -EOPNOTSUPP;
+            break;
     }
-    if ((address != NULL) && (address_len != NULL)) {
-        tmp.ss_family = s->domain;
-        *port = htons(*port); /* XXX: sin(6)_port is supposed to be network
-                                 byte order */
-        *address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
+    if ((res == 0) && (address != NULL) && (address_len != 0)) {
+        switch (s->type) {
+#ifdef MODULE_SOCK_TCP
+            case SOCK_STREAM:
+                res = _getpeername(s, address, address_len);
+                break;
+#endif
+            default: {
+                struct sockaddr_storage sa;
+                socklen_t sa_len;
+
+                sa_len = _ep_to_sockaddr(&ep, &sa);
+                *address_len = _addr_truncate(address, *address_len, &sa,
+                                              sa_len);
+                break;
+            }
+        }
     }
     return res;
 }
 
-ssize_t send(int socket, const void *buffer, size_t length, int flags)
-{
-    return sendto(socket, buffer, length, flags, NULL, 0);
-}
-
 ssize_t sendto(int socket, const void *buffer, size_t length, int flags,
                const struct sockaddr *address, socklen_t address_len)
 {
     socket_t *s;
     int res = 0;
-    void *addr = NULL;
-    size_t addr_len = 0;
-    network_uint16_t port;
-    port.u16 = 0;
+#if defined(MODULE_SOCK_IP) || defined(MODULE_SOCK_UDP)
+    struct _sock_tl_ep ep = { .port = 0 };
+#endif
+
     (void)flags;
-    mutex_lock(&_pool_mutex);
+    mutex_lock(&_socket_pool_mutex);
     s = _get_socket(socket);
-    mutex_unlock(&_pool_mutex);
+    mutex_unlock(&_socket_pool_mutex);
     if (s == NULL) {
         errno = ENOTSOCK;
         return -1;
     }
-    if (address != NULL) {
-        if (address->sa_family != s->domain) {
-            errno = EAFNOSUPPORT;
+    if (s->sock == NULL) {  /* socket is not connected */
+#ifdef MODULE_SOCK_TCP
+        if (s->type == SOCK_STREAM) {
+            errno = ENOTCONN;
             return -1;
         }
-        if (_get_data_from_sockaddr(address, address_len, &addr, &addr_len, &port) < 0) {
+#endif
+        /* bind implicitly */
+        if ((res = _bind_connect(s, NULL, 0)) < 0) {
+            errno = -res;
             return -1;
         }
     }
+#if defined(MODULE_SOCK_IP) || defined(MODULE_SOCK_UDP)
+    _sockaddr_to_ep(address, address_len, &ep);
+#endif
     switch (s->type) {
-#ifdef MODULE_CONN_IP
+#ifdef MODULE_SOCK_IP
         case SOCK_RAW:
-            if ((address != NULL) && (s->bound)) {
-                uint8_t src_addr[sizeof(ipv6_addr_t)];
-                size_t src_len;
-                int res = conn_ip_getlocaladdr(&s->conn.raw, src_addr);
-                if (res < 0) {
-                    errno = ENOTSOCK;   /* Something seems to be wrong with the socket */
-                    return -1;
-                }
-                src_len = (size_t)res;
-                /* cppcheck bug? res is read below in l824 */
-                /* cppcheck-suppress unreadVariable */
-                res = conn_ip_sendto(buffer, length, src_addr, src_len, addr, addr_len, s->domain,
-                                     s->protocol);
-            }
-            else if (address != NULL) {
-                res = conn_ip_sendto(buffer, length, NULL, 0, addr, addr_len, s->domain,
-                                     s->protocol);
-            }
-            else {
-                errno = ENOTCONN;
-                return -1;
-            }
-            if (res < 0) {
-                errno = -res;
-                return -1;
-            }
+            res = sock_ip_send(&s->sock->raw, buffer, length,
+                               s->protocol, (sock_ip_ep_t *)&ep);
             break;
 #endif
-#ifdef MODULE_CONN_TCP
+#ifdef MODULE_SOCK_TCP
         case SOCK_STREAM:
-            if (!s->bound) {
-                errno = ENOTCONN;
-                return -1;
-            }
-            if (address != NULL) {
-                errno = EISCONN;
-                return -1;
+            if (address == NULL) {
+                (void)address_len;
+                res = sock_tcp_write(&s->sock->tcp.sock, buffer, length);
             }
-            if ((res = conn_tcp_send(&s->conn.tcp, buffer, length)) < 0) {
-                errno = -res;
-                return -1;
+            else {
+                res = EISCONN;
             }
             break;
 #endif
-#ifdef MODULE_CONN_UDP
+#ifdef MODULE_SOCK_UDP
         case SOCK_DGRAM:
-            if ((address != NULL) && (s->bound)) {
-                uint8_t src_addr[sizeof(ipv6_addr_t)];
-                size_t src_len;
-                uint16_t sport;
-                int res = conn_udp_getlocaladdr(&s->conn.udp, src_addr, &sport);
-                if (res < 0) {
-                    errno = ENOTSOCK;   /* Something seems to be wrong with the socket */
-                    return -1;
-                }
-                src_len = (size_t)res;
-                /* cppcheck bug? res is read below in l824 */
-                /* cppcheck-suppress unreadVariable */
-                res = conn_udp_sendto(buffer, length, src_addr, src_len, addr, addr_len, s->domain,
-                                      sport, byteorder_ntohs(port));
-            }
-            else if (address != NULL) {
-                if ((res = _implicit_bind(s, addr)) < 0) {
-                    return res;
-                }
-                res = conn_udp_sendto(buffer, length, NULL, 0, addr, addr_len, s->domain,
-                                      s->src_port, byteorder_ntohs(port));
-            }
-            else {
-                errno = ENOTCONN;
-                return -1;
-            }
-            if (res < 0) {
-                errno = -res;
-                return -1;
-            }
+            res = sock_udp_send(&s->sock->udp, buffer, length, &ep);
             break;
 #endif
         default:
-            (void)buffer;
-            (void)length;
-            errno = EOPNOTSUPP;
-            return -1;
+            res = -EOPNOTSUPP;
+            break;
     }
     return res;
 }
 
-
 /**
  * @}
  */
diff --git a/tests/nhdp/Makefile b/tests/nhdp/Makefile
index 2783bf2eb29f4ba1f39e8205bb1ac59cbac4d71b..c776735a21eeb6a2d092d257f8981e7537fb6140 100644
--- a/tests/nhdp/Makefile
+++ b/tests/nhdp/Makefile
@@ -8,7 +8,7 @@ BOARD_INSUFFICIENT_MEMORY := nucleo-f334 stm32f0discovery weio nucleo-f030 \
                              nucleo32-f042
 
 USEMODULE += gnrc_ipv6
-USEMODULE += gnrc_conn_udp
+USEMODULE += gnrc_sock_udp
 USEMODULE += nhdp
 
 include $(RIOTBASE)/Makefile.include
diff --git a/tests/pkg_libcoap/Makefile b/tests/pkg_libcoap/Makefile
index 0c1e1ce583fe367b2ef0caf1cb54116d42ec7795..95dbab5a0607943dca1450756bf6de9c6dfd21e4 100644
--- a/tests/pkg_libcoap/Makefile
+++ b/tests/pkg_libcoap/Makefile
@@ -9,7 +9,7 @@ BOARD_INSUFFICIENT_MEMORY := chronos msb-430 msb-430h nucleo-f334 nucleo-f030 \
                              nucleo-f070 nucleo32-f042
 
 USEMODULE += gnrc_ipv6
-USEMODULE += gnrc_conn_udp
+USEMODULE += gnrc_sock_udp
 USEPKG += libcoap
 
 include $(RIOTBASE)/Makefile.include
diff --git a/tests/pkg_oonf_api/Makefile b/tests/pkg_oonf_api/Makefile
index f699d513d607d53b51d1f68ebe2ea1c87178e99b..15f5b555d91c8dc000056c546af3d4385d290cf9 100644
--- a/tests/pkg_oonf_api/Makefile
+++ b/tests/pkg_oonf_api/Makefile
@@ -4,7 +4,7 @@ include ../Makefile.tests_common
 BOARD_WHITELIST := native
 
 USEMODULE += gnrc_ipv6
-USEMODULE += gnrc_conn_udp
+USEMODULE += gnrc_sock_udp
 USEMODULE += oonf_common
 USEMODULE += oonf_rfc5444
 USEPKG += oonf_api