diff --git a/pkg/emb6/Makefile.dep b/pkg/emb6/Makefile.dep
index 652cc1063f2b08891cef735e4563ea75a2969889..9d1c709d44e205d4e8d39f1d4458d02fd723e1ee 100644
--- a/pkg/emb6/Makefile.dep
+++ b/pkg/emb6/Makefile.dep
@@ -2,6 +2,11 @@ ifneq (,$(filter emb6_conn_udp,$(USEMODULE)))
   USEMODULE += emb6_sock
 endif
 
+ifneq (,$(filter emb6_sock_%,$(USEMODULE)))
+  USEMODULE += core_mbox
+  USEMODULE += emb6_sock
+endif
+
 ifneq (,$(filter emb6_%,$(USEMODULE)))
   USEMODULE += emb6
 endif
@@ -19,4 +24,5 @@ ifneq (,$(filter emb6,$(USEMODULE)))
   USEMODULE += emb6_rpl
   USEMODULE += emb6_sicslowpan
   USEMODULE += emb6_utils
+  USEMODULE += xtimer
 endif
diff --git a/pkg/emb6/Makefile.include b/pkg/emb6/Makefile.include
index 5b15adedeb47ac54025e285b61a13e4742da3b5c..34308ae713287b28d43203b0beb1190200e7fe7c 100644
--- a/pkg/emb6/Makefile.include
+++ b/pkg/emb6/Makefile.include
@@ -65,6 +65,11 @@ ifneq (,$(filter emb6_sock,$(USEMODULE)))
   INCLUDES += -I$(EMB6_DIR)/emb6/inc/tport
 endif
 
+ifneq (,$(filter emb6_sock_udp,$(USEMODULE)))
+  DIRS += $(EMB6_CONTRIB)/sock/udp
+  CFLAGS += -DSOCK_HAS_IPV6
+endif
+
 ifneq (,$(filter emb6_utils,$(USEMODULE)))
   DIRS += $(EMB6_DIR)/utils/src
   INCLUDES += -I$(EMB6_DIR)/utils/inc
diff --git a/pkg/emb6/contrib/sock/udp/Makefile b/pkg/emb6/contrib/sock/udp/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d38d86d7ac97cc4d6a4757f454ef83eff38c3d0b
--- /dev/null
+++ b/pkg/emb6/contrib/sock/udp/Makefile
@@ -0,0 +1,3 @@
+MODULE := emb6_sock_udp
+
+include $(RIOTBASE)/Makefile.base
diff --git a/pkg/emb6/contrib/sock/udp/emb6_sock_udp.c b/pkg/emb6/contrib/sock/udp/emb6_sock_udp.c
new file mode 100644
index 0000000000000000000000000000000000000000..e981444c1827e9a402913be5a31d4c35fc875f54
--- /dev/null
+++ b/pkg/emb6/contrib/sock/udp/emb6_sock_udp.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2016 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author  Martine Lenders <m.lenders@fu-berlin.de>
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include "byteorder.h"
+#include "evproc.h"
+#include "msg.h"
+#include "mutex.h"
+#include "net/af.h"
+#include "net/sock/udp.h"
+#include "net/ipv6/hdr.h"
+#include "sched.h"
+#include "uip.h"
+#include "xtimer.h"
+
+#define _MSG_TYPE_CLOSE     (0x4123)
+#define _MSG_TYPE_TIMEOUT   (0x4124)
+#define _MSG_TYPE_RCV       (0x4125)
+
+/* struct to describe a sendto command for emb6 thread */
+typedef struct {
+    mutex_t block;
+    struct udp_socket *sock;
+    const sock_udp_ep_t *remote;
+    int res;
+    const void *data;
+    size_t len;
+} _send_cmd_t;
+
+extern uint16_t uip_slen;
+
+static bool send_registered = false;
+
+static void _timeout_callback(void *arg);
+static void _input_callback(struct udp_socket *c, void *ptr,
+                            const uip_ipaddr_t *src_addr, uint16_t src_port,
+                            const uip_ipaddr_t *dst_addr, uint16_t dst_port,
+                            const uint8_t *data, uint16_t datalen);
+static void _output_callback(c_event_t c_event, p_data_t p_data);
+
+static int _reg(struct udp_socket *c, void *ptr, udp_socket_input_callback_t cb,
+                const sock_udp_ep_t *local, const sock_udp_ep_t *remote)
+{
+    if (((local != NULL) && (local->family != AF_INET6)) ||
+        ((remote != NULL) && (remote->family != AF_INET6))) {
+        return -EAFNOSUPPORT;
+    }
+    if (udp_socket_register(c, ptr, cb) < 0) {
+        return -ENOMEM;
+    }
+    if (local != NULL) {
+        if (udp_socket_bind(c, local->port) < 0) {
+            udp_socket_close(c);
+            return -EADDRINUSE;
+        }
+    }
+    if (remote != NULL) {
+        /* check of return value not necessary, since neither c nor
+         * c->udp_conn is NULL (only error case) at this point */
+        udp_socket_connect(c, (uip_ipaddr_t *)&remote->addr, remote->port);
+    }
+    return 0;
+}
+
+int sock_udp_create(sock_udp_t *sock, const sock_udp_ep_t *local,
+                    const sock_udp_ep_t *remote, uint16_t flags)
+{
+    int res;
+
+    (void)flags;
+    assert((sock != NULL));
+    assert((local == NULL) || (local->port != 0));
+    assert((remote == NULL) || (remote->port != 0));
+    if (sock->sock.input_callback != NULL) {
+        sock_udp_close(sock);
+    }
+    mutex_init(&sock->mutex);
+    mutex_lock(&sock->mutex);
+    mbox_init(&sock->mbox, sock->mbox_queue, SOCK_MBOX_SIZE);
+    atomic_flag_clear(&sock->receivers);
+    if ((res = _reg(&sock->sock, sock, _input_callback, local, remote)) < 0) {
+        sock->sock.input_callback = NULL;
+    }
+    mutex_unlock(&sock->mutex);
+    return res;
+}
+
+void sock_udp_close(sock_udp_t *sock)
+{
+    assert(sock != NULL);
+    if (sock->sock.input_callback != NULL) {
+        while (atomic_fetch_sub(&sock->receivers, 1) > 0) {
+            msg_t msg = { .type = _MSG_TYPE_CLOSE };
+            mbox_put(&sock->mbox, &msg);
+        }
+        mutex_lock(&sock->mutex);
+        udp_socket_close(&sock->sock);
+        sock->sock.input_callback = NULL;
+        mutex_unlock(&sock->mutex);
+    }
+}
+
+int sock_udp_get_local(sock_udp_t *sock, sock_udp_ep_t *ep)
+{
+    assert((sock != NULL) && (ep != NULL));
+    if ((sock->sock.input_callback != NULL) &&
+        (sock->sock.udp_conn->lport != 0)) {
+        mutex_lock(&sock->mutex);
+        /* local UDP endpoints do not have addresses in emb6 */
+        memset(&ep->addr, 0, sizeof(ipv6_addr_t));
+        ep->port = ntohs(sock->sock.udp_conn->lport);
+        mutex_unlock(&sock->mutex);
+        return sizeof(ipv6_addr_t);
+    }
+    return -EADDRNOTAVAIL;
+}
+
+int sock_udp_get_remote(sock_udp_t *sock, sock_udp_ep_t *ep)
+{
+    assert((sock != NULL) && (ep != NULL));
+    if ((sock->sock.input_callback != NULL) &&
+        (sock->sock.udp_conn->rport != 0)) {
+        mutex_lock(&sock->mutex);
+        memcpy(&ep->addr, &sock->sock.udp_conn->ripaddr, sizeof(ipv6_addr_t));
+        ep->port = ntohs(sock->sock.udp_conn->rport);
+        mutex_unlock(&sock->mutex);
+        return sizeof(ipv6_addr_t);
+    }
+    return -ENOTCONN;
+}
+
+int sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
+                  uint32_t timeout, sock_udp_ep_t *remote)
+{
+    xtimer_t timeout_timer;
+    int blocking = BLOCKING;
+    int res = -EIO;
+    msg_t msg;
+
+    assert((sock != NULL) && (data != NULL) && (max_len > 0));
+    if (sock->sock.input_callback == NULL) {
+        return -EADDRNOTAVAIL;
+    }
+    if (timeout == 0) {
+        blocking = NON_BLOCKING;
+    }
+    else if (timeout != SOCK_NO_TIMEOUT) {
+        timeout_timer.callback = _timeout_callback;
+        timeout_timer.arg = &sock->mbox;
+        xtimer_set(&timeout_timer, timeout);
+    }
+    atomic_fetch_add(&sock->receivers, 1);
+    if (_mbox_get(&sock->mbox, &msg, blocking) == 0) {
+        /* do not need to remove xtimer, since we only get here in non-blocking
+         * mode (timeout > 0) */
+        return -EAGAIN;
+    }
+    switch (msg.type) {
+        case _MSG_TYPE_CLOSE:
+            res = -EADDRNOTAVAIL;
+            break;
+        case _MSG_TYPE_TIMEOUT:
+            res = -ETIMEDOUT;
+            break;
+        case _MSG_TYPE_RCV:
+            mutex_lock(&sock->mutex);
+            if (max_len < sock->recv_info.datalen) {
+                res = -ENOBUFS;
+                mutex_unlock(&sock->mutex);
+                break;
+            }
+            memcpy(data, sock->recv_info.data, sock->recv_info.datalen);
+            if (remote != NULL) {
+                remote->family = AF_INET6;
+                remote->netif = SOCK_ADDR_ANY_NETIF;
+                memcpy(&remote->addr, &sock->recv_info.src, sizeof(ipv6_addr_t));
+                remote->port = sock->recv_info.src_port;
+            }
+            res = (int)sock->recv_info.datalen;
+            mutex_unlock(&sock->mutex);
+            break;
+    }
+    atomic_fetch_sub(&sock->receivers, 1);
+    return res;
+}
+
+int sock_udp_send(sock_udp_t *sock, const void *data, size_t len,
+                  const sock_udp_ep_t *remote)
+{
+    struct udp_socket tmp;
+    _send_cmd_t send_cmd = { .block = MUTEX_INIT,
+                             .remote = remote,
+                             .data = data,
+                             .len = len };
+
+    assert((sock != NULL) || (remote != NULL));
+    assert((len == 0) || (data != NULL));   /* (len != 0) => (data != NULL) */
+    /* we want the send in the uip thread (which udp_socket_send does not offer)
+     * so we need to do it manually */
+    if (!send_registered) {
+        if (evproc_regCallback(EVENT_TYPE_CONN_SEND, _output_callback) != E_SUCCESS) {
+            return -ENOMEM;
+        }
+        else {
+            send_registered = true;
+        }
+    }
+    if ((len > (UIP_BUFSIZE - (UIP_LLH_LEN + UIP_IPUDPH_LEN))) ||
+        (len > UINT16_MAX)) {
+        return -ENOMEM;
+    }
+    if (remote != NULL) {
+        if (remote->family != AF_INET6) {
+            return -EAFNOSUPPORT;
+        }
+        if (remote->port == 0) {
+            return -EINVAL;
+        }
+        send_cmd.remote = remote;
+    }
+    else if (sock->sock.udp_conn->rport == 0) {
+        return -ENOTCONN;
+    }
+    /* cppcheck-supress nullPointerRedundantCheck
+     * remote == NULL implies that sock != NULL (see assert at start of
+     * function) * that's why it is okay in the if-statement above to check
+     * sock->... without checking (sock != NULL) first => this check afterwards
+     * isn't redundant */
+    if (sock == NULL) {
+        int res;
+        if ((res = _reg(&tmp, NULL, NULL, NULL, NULL)) < 0) {
+            return res;
+        }
+        send_cmd.sock = &tmp;
+    }
+    else {
+        send_cmd.sock = &sock->sock;
+    }
+    mutex_lock(&send_cmd.block);
+    /* change to emb6 thread context */
+    if (evproc_putEvent(E_EVPROC_TAIL, EVENT_TYPE_CONN_SEND, &send_cmd) == E_SUCCESS) {
+        /* block thread until data was sent */
+        mutex_lock(&send_cmd.block);
+    }
+    else {
+        /* most likely error: event queue was full */
+        send_cmd.res = -ENOMEM;
+    }
+    if (send_cmd.sock == &tmp) {
+        udp_socket_close(&tmp);
+    }
+    mutex_unlock(&send_cmd.block);
+
+    return send_cmd.res;
+}
+
+static void _timeout_callback(void *arg)
+{
+    msg_t msg = { .type = _MSG_TYPE_TIMEOUT };
+    mbox_t *mbox = arg;
+
+    /* should be safe, because otherwise if mbox were filled this callback is
+     * senseless */
+    mbox_try_put(mbox, &msg);
+}
+
+static void _input_callback(struct udp_socket *c, void *ptr,
+                            const uip_ipaddr_t *src_addr, uint16_t src_port,
+                            const uip_ipaddr_t *dst_addr, uint16_t dst_port,
+                            const uint8_t *data, uint16_t datalen)
+{
+    msg_t msg = { .type = _MSG_TYPE_RCV };
+    sock_udp_t *sock = ptr;
+
+    (void)dst_addr;
+    (void)dst_port;
+    mutex_lock(&sock->mutex);
+    sock->recv_info.src_port = src_port;
+    sock->recv_info.src = (const ipv6_addr_t *)src_addr;
+    sock->recv_info.data = data;
+    sock->recv_info.datalen = datalen - sizeof(ipv6_hdr_t);
+    mutex_unlock(&sock->mutex);
+    mbox_put(&sock->mbox, &msg);
+}
+
+static void _output_callback(c_event_t c_event, p_data_t p_data)
+{
+
+    if ((c_event != EVENT_TYPE_CONN_SEND) || (p_data == NULL)) {
+        return;
+    }
+
+    _send_cmd_t *send_cmd = (_send_cmd_t *)p_data;
+
+    if (send_cmd->remote != NULL) {
+        /* send_cmd->len was previously checked */
+        send_cmd->res = udp_socket_sendto(send_cmd->sock, send_cmd->data,
+                                          (uint16_t)send_cmd->len,
+                                          (uip_ipaddr_t *)&send_cmd->remote->addr,
+                                          send_cmd->remote->port);
+    }
+    else {
+        /* send_cmd->len was previously checked */
+        send_cmd->res = udp_socket_send(send_cmd->sock, send_cmd->data,
+                                        (uint16_t)send_cmd->len);
+    }
+    send_cmd->res = (send_cmd->res < 0) ? -EHOSTUNREACH : send_cmd->res;
+    /* notify notify waiting thread */
+    mutex_unlock(&send_cmd->block);
+}
+/** @} */
diff --git a/pkg/emb6/include/sock_types.h b/pkg/emb6/include/sock_types.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ce812b6c4409e25efe183cb6fb09ac897bf162c
--- /dev/null
+++ b/pkg/emb6/include/sock_types.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup pkg_emb6_sock  emb6-specific implementation of the sock API
+ * @ingroup  pkg_emb6
+ * @brief
+ * @{
+ *
+ * @file
+ * @brief
+ *
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+#ifndef SOCK_TYPES_H_
+#define SOCK_TYPES_H_
+
+#include <stdatomic.h>
+
+#include "mbox.h"
+#include "mutex.h"
+#include "net/ipv6/addr.h"
+
+#include "uip.h"
+#include "udp-socket.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SOCK_MBOX_SIZE
+#define SOCK_MBOX_SIZE  (2)
+#endif
+
+#ifndef SOCK_HAS_IPV6
+#error "emb6 only runs with IPv6 support"
+#endif
+
+/**
+ * @brief @ref net_sock_udp definition for emb6
+ */
+struct sock_udp {
+    struct udp_socket sock;             /**< emb6 internal socket */
+    mutex_t mutex;                      /**< mutex for the connection */
+    mbox_t mbox;                        /**< mbox for receiving */
+    msg_t mbox_queue[SOCK_MBOX_SIZE];   /**< queue for mbox */
+    atomic_int receivers;               /**< current number of recv calls */
+    struct {
+        const ipv6_addr_t *src;         /**< source address */
+        const void *data;               /**< data of received packet */
+        size_t datalen;                 /**< length of received packet data */
+        uint16_t src_port;              /**< source port */
+    } recv_info;                        /**< info on received packet */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SOCK_TYPES_H_ */
+/** @} */
diff --git a/tests/emb6/Makefile b/tests/emb6/Makefile
index 18e3052f06284ed3e205d854e474cfad8a7f14aa..8f1632ed06bac30015ee16818de28a854570deb0 100644
--- a/tests/emb6/Makefile
+++ b/tests/emb6/Makefile
@@ -5,6 +5,9 @@ include ../Makefile.tests_common
 
 FEATURES_REQUIRED = periph_gpio periph_spi  # for at86rf231
 
+# MSP-430 doesn't support C11's atomic functionality yet
+BOARD_BLACKLIST := msb-430 msb-430h telosb wsn430-v1_3b wsn430-v1_4 z1
+
 BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h nucleo32-l031 nucleo32-f031 \
                              nucleo32-f042 nucleo-l053 stm32f0discovery telosb \
                              weio wsn430-v1_3b wsn430-v1_4 z1
@@ -12,7 +15,7 @@ BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h nucleo32-l031 nucleo32-f031 \
 USEPKG += emb6
 
 USEMODULE += emb6_router
-USEMODULE += emb6_conn_udp
+USEMODULE += emb6_sock_udp
 USEMODULE += ipv6_addr
 USEMODULE += shell
 USEMODULE += shell_commands
diff --git a/tests/emb6/common.h b/tests/emb6/common.h
index 0e8a419659b16b46654aed6f376f9a15a9b97969..8e873cd17a33d8acae8ace8d45f5cb38f39a5324 100644
--- a/tests/emb6/common.h
+++ b/tests/emb6/common.h
@@ -11,7 +11,7 @@
  * @{
  *
  * @file
- * @brief   Definitions for tests/lwip/
+ * @brief   Definitions for tests/emb6/
  *
  * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
  */
@@ -29,7 +29,7 @@ extern "C" {
  * @brief   Application configuration
  * @{
  */
-#define CONN_INBUF_SIZE         (256)
+#define SOCK_INBUF_SIZE         (256)
 #define SERVER_MSG_QUEUE_SIZE   (8)
 #define SERVER_BUFFER_SIZE      (64)
 /**
@@ -58,7 +58,7 @@ size_t hex2ints(uint8_t *out, const char *in);
  */
 int ping_cmd(int argc, char **argv);
 
-#ifdef MODULE_CONN_UDP
+#ifdef MODULE_EMB6_SOCK_UDP
 /**
  * @brief   UDP IP shell command
  *
diff --git a/tests/emb6/main.c b/tests/emb6/main.c
index 9f833acc5ad3652677b3a81d7bda35bc48ece424..06452f550cf8c176f893bed88897ff0e3250dca5 100644
--- a/tests/emb6/main.c
+++ b/tests/emb6/main.c
@@ -78,15 +78,14 @@ static void *_emb6_thread(void *args)
 
 static const shell_command_t shell_commands[] = {
     { "ping6", "Send pings and receive pongs", ping_cmd },
-#ifdef MODULE_CONN_UDP
+#ifdef MODULE_EMB6_SOCK_UDP
     { "udp", "Send UDP messages and listen for messages on UDP port", udp_cmd },
 #endif
     { "ifconfig", "Shows assigned IPv6 addresses", ifconfig },
     { NULL, NULL, NULL }
 };
-static char line_buf[SHELL_DEFAULT_BUFSIZE];
 
-char conn_inbuf[CONN_INBUF_SIZE];
+static char line_buf[SHELL_DEFAULT_BUFSIZE];
 
 int main(void)
 {
diff --git a/tests/emb6/udp.c b/tests/emb6/udp.c
index 748110cc6eef71389d8f387fdc75283d10ec66e2..f1ba76aa0fdabac7b6264923c6e15f6e1b15af01 100644
--- a/tests/emb6/udp.c
+++ b/tests/emb6/udp.c
@@ -25,29 +25,26 @@
 #include "common.h"
 #include "od.h"
 #include "net/af.h"
-#include "net/conn/udp.h"
+#include "net/sock/udp.h"
 #include "net/ipv6.h"
 #include "thread.h"
 #include "xtimer.h"
 
-#ifdef MODULE_CONN_UDP
-static char conn_inbuf[CONN_INBUF_SIZE];
+#ifdef MODULE_EMB6_SOCK_UDP
+static char sock_inbuf[SOCK_INBUF_SIZE];
 static bool server_running;
-static conn_udp_t server_conn;
+static sock_udp_t server_sock;
 static char server_stack[THREAD_STACKSIZE_DEFAULT];
-static msg_t server_msg_queue[SERVER_MSG_QUEUE_SIZE];
 
 static void *_server_thread(void *args)
 {
-    ipv6_addr_t server_addr = IPV6_ADDR_UNSPECIFIED;
-    uint16_t port;
     int res;
 
-    msg_init_queue(server_msg_queue, SERVER_MSG_QUEUE_SIZE);
     /* parse port */
-    port = (uint16_t)atoi((char *)args);
-    if ((res = conn_udp_create(&server_conn, &server_addr,
-                               sizeof(server_addr), AF_INET6, port)) < 0) {
+    uint16_t port = atoi(args);
+    const sock_udp_ep_t server_addr = { .family = AF_INET6,
+                                        .port = port };
+    if ((res = sock_udp_create(&server_sock, &server_addr, NULL, 0)) < 0) {
         printf("Unable to open UDP server on port %" PRIu16 " (error code %d)\n",
                port, -res);
         return NULL;
@@ -55,12 +52,10 @@ static void *_server_thread(void *args)
     server_running = true;
     printf("Success: started UDP server on port %" PRIu16 "\n", port);
     while (1) {
-        int res;
-        ipv6_addr_t src;
-        size_t src_len = sizeof(ipv6_addr_t);
-        uint16_t sport;
-        if ((res = conn_udp_recvfrom(&server_conn, conn_inbuf, sizeof(conn_inbuf), &src,
-                                     &src_len, &sport)) < 0) {
+        sock_udp_ep_t client_addr;
+
+        if ((res = sock_udp_recv(&server_sock, sock_inbuf, sizeof(sock_inbuf),
+                                 SOCK_NO_TIMEOUT, &client_addr)) < 0) {
             puts("Error on receive");
         }
         else if (res == 0) {
@@ -68,9 +63,10 @@ static void *_server_thread(void *args)
         }
         else {
             char addrstr[IPV6_ADDR_MAX_STR_LEN];
-            printf("Received from [%s]:%" PRIu16 ":\n", ipv6_addr_to_str(addrstr, &src,
-                                                                         sizeof(addrstr)), sport);
-            od_hex_dump(conn_inbuf, res, 0);
+            printf("Received from [%s]:%" PRIu16 ":\n",
+                   ipv6_addr_to_str(addrstr, (ipv6_addr_t *)&client_addr.addr,
+                                    sizeof(addrstr)), client_addr.port);
+            od_hex_dump(sock_inbuf, res, 0);
         }
     }
     return NULL;
@@ -79,27 +75,25 @@ static void *_server_thread(void *args)
 static int udp_send(char *addr_str, char *port_str, char *data, unsigned int num,
                     unsigned int delay)
 {
-    ipv6_addr_t src = IPV6_ADDR_UNSPECIFIED, dst;
-    uint16_t port;
     uint8_t byte_data[strlen(data) / 2];
+    sock_udp_ep_t dst = { .family = AF_INET6 };
     size_t data_len;
 
     /* parse destination address */
-    if (ipv6_addr_from_str(&dst, addr_str) == NULL) {
+    if (ipv6_addr_from_str((ipv6_addr_t *)&dst.addr, addr_str) == NULL) {
         puts("Error: unable to parse destination address");
         return 1;
     }
     /* parse port */
-    port = (uint16_t)atoi(port_str);
+    dst.port = atoi(port_str);
     data_len = hex2ints(byte_data, data);
     for (unsigned int i = 0; i < num; i++) {
-        if (conn_udp_sendto(byte_data, data_len, &src, sizeof(src), (struct sockaddr *)&dst,
-                            sizeof(dst), AF_INET6, port, port) < 0) {
+        if (sock_udp_send(NULL, byte_data, data_len, &dst) < 0) {
             puts("could not send");
         }
         else {
             printf("Success: send %u byte to [%s]:%" PRIu16 ")\n",
-                   (unsigned)data_len, addr_str, port);
+                   (unsigned)data_len, addr_str, dst.port);
         }
         xtimer_usleep(delay);
     }