diff --git a/Makefile.dep b/Makefile.dep
index 8504c0addc30018e790dc0b35639e98d70b1d1e9..303b888587d1b316af110e56302cc9825cae2e6d 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -39,13 +39,13 @@ ifneq (,$(filter ieee802154,$(USEMODULE)))
     USEMODULE += gnrc_sixlowpan
   endif
   ifneq (,$(filter gnrc_ipv6_router, $(USEMODULE)))
-    USEMODULE += gnrc_sixlowpan   # TODO: replace with gnrc_sixlowpan_router
+    USEMODULE += gnrc_sixlowpan_router
   endif
   ifneq (,$(filter gnrc_ipv6_default, $(USEMODULE)))
     USEMODULE += gnrc_sixlowpan_default
   endif
   ifneq (,$(filter gnrc_ipv6_router_default, $(USEMODULE)))
-    USEMODULE += gnrc_sixlowpan_default   # TODO: replace with gnrc_sixlowpan_router_default
+    USEMODULE += gnrc_sixlowpan_router_default
   endif
 endif
 
@@ -57,6 +57,17 @@ ifneq (,$(filter gnrc_sixlowpan_default,$(USEMODULE)))
   USEMODULE += gnrc_sixlowpan_iphc
 endif
 
+ifneq (,$(filter gnrc_sixlowpan_router_default,$(USEMODULE)))
+  USEMODULE += gnrc_ipv6_router_default
+  USEMODULE += gnrc_sixlowpan_router
+  USEMODULE += gnrc_sixlowpan_frag
+  USEMODULE += gnrc_sixlowpan_iphc
+endif
+
+ifneq (,$(filter gnrc_sixlowpan_router,$(USEMODULE)))
+  USEMODULE += gnrc_sixlowpan
+endif
+
 ifneq (,$(filter gnrc_sixlowpan_frag,$(USEMODULE)))
   USEMODULE += gnrc_sixlowpan
   USEMODULE += vtimer
@@ -78,6 +89,10 @@ ifneq (,$(filter gnrc_sixlowpan_ctx,$(USEMODULE)))
   USEMODULE += vtimer
 endif
 
+ifneq (,$(filter gnrc_sixlowpan_nd_router,$(USEMODULE)))
+  USEMODULE += gnrc_sixlowpan_nd
+endif
+
 ifneq (,$(filter gnrc_sixlowpan_nd,$(USEMODULE)))
   USEMODULE += gnrc_ndp
   USEMODULE += gnrc_ndp_internal
@@ -101,7 +116,13 @@ endif
 ifneq (,$(filter gnrc_ipv6_router_default,$(USEMODULE)))
   USEMODULE += gnrc_ipv6_router
   USEMODULE += gnrc_icmpv6
-  USEMODULE += gnrc_ndp_router
+  ifeq (1,$(GNRC_NETIF_NUMOF))
+    ifeq (,$(filter gnrc_sixlowpan_nd_router,$(USEMODULE)))
+      USEMODULE += gnrc_ndp_router
+    endif
+  else
+    USEMODULE += gnrc_ndp_router
+  endif
 endif
 
 ifneq (,$(filter gnrc_ndp_host,$(USEMODULE)))
diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules
index b2bd7c549d6cc497b4f42194071da88b4abab0a1..a9c4dea1d12c2ca94cc631c2ad5c06fe7877d997 100644
--- a/Makefile.pseudomodules
+++ b/Makefile.pseudomodules
@@ -3,6 +3,8 @@ PSEUDOMODULES += gnrc_ipv6_default
 PSEUDOMODULES += gnrc_ipv6_router
 PSEUDOMODULES += gnrc_ipv6_router_default
 PSEUDOMODULES += gnrc_sixlowpan_default
+PSEUDOMODULES += gnrc_sixlowpan_router
+PSEUDOMODULES += gnrc_sixlowpan_router_default
 PSEUDOMODULES += gnrc_pktbuf
 PSEUDOMODULES += ieee802154
 PSEUDOMODULES += log
diff --git a/doc/doxygen/riot.doxyfile b/doc/doxygen/riot.doxyfile
index 74e66b4cb3445e74ae5cb326e5a8ab27da190b39..0c7a5e369150ce0596bcebc96c0655b80b0eb159 100644
--- a/doc/doxygen/riot.doxyfile
+++ b/doc/doxygen/riot.doxyfile
@@ -2000,7 +2000,8 @@ PREDEFINED             = DOXYGEN \
                          DEVELHELP \
                          ENABLE_DEBUG \
                          TEST_SUITES \
-                         MODULE_GNRC_NDP_ROUTER
+                         MODULE_GNRC_NDP_ROUTER \
+                         MODULE_GNRC_SIXLOWPAN_ND_ROUTER
 
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
diff --git a/sys/include/net/gnrc/sixlowpan/nd.h b/sys/include/net/gnrc/sixlowpan/nd.h
index 6a3bb8b61ff36a83fd4841e3ea1f9b34ecf64efa..919008a13e2c16991cb6613917b512009b46bb6d 100644
--- a/sys/include/net/gnrc/sixlowpan/nd.h
+++ b/sys/include/net/gnrc/sixlowpan/nd.h
@@ -33,6 +33,8 @@
 #include "net/sixlowpan/nd.h"
 #include "timex.h"
 
+#include "net/gnrc/sixlowpan/nd/router.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -52,6 +54,16 @@ extern "C" {
  */
 #define GNRC_SIXLOWPAN_ND_MSG_DELETE_CTX    (0x0222)
 
+/**
+ * @brief   Message type for authoritative border router timeout
+ */
+#define GNRC_SIXLOWPAN_ND_MSG_ABR_TIMEOUT   (0x0223)
+
+/**
+ * @brief   Message type for address registration timeout
+ */
+#define GNRC_SIXLOWPAN_ND_MSG_AR_TIMEOUT    (0x0224)
+
 #ifndef GNRC_SIXLOWPAN_ND_AR_LTIME
 /**
  * @brief   Registration lifetime in minutes for the address registration option
@@ -78,6 +90,28 @@ extern "C" {
 #define GNRC_SIXLOWPAN_ND_MAX_RTR_SOL_INT   (60U)   /**< retransmission increment for exponential
                                                      *   backoff of subsequent RS */
 /** @} */
+/**
+ * @name    Router constants
+ * @{
+ * @see     <a href="https://tools.ietf.org/html/rfc6775#section-9">
+ *              RFC 6775, section 9
+ *          </a>
+ */
+#define GNRC_SIXLOWPAN_ND_MIN_RTR_ADV_DELAY (10U)   /**< replacement value (in seconds) for
+                                                     *   @ref GNRC_NDP_MIN_RTR_ADV_DELAY */
+/**
+ * @brief   replacement value (in microseconds) for @ref GNRC_NDP_MAX_RTR_ADV_DELAY
+ */
+#define GNRC_SIXLOWPAN_ND_MAX_RTR_ADV_DELAY (2U * SEC_IN_USEC)
+/**
+ * @brief   Lifetime of a tentative address entry in seconds
+ */
+#define GNRC_SIXLOWPAN_ND_TENTATIVE_NCE_LIFETIME    (20U)
+/**
+ * @brief   6LoWPAN Multihop Hoplimit
+ */
+#define GNRC_SIXLOWPAN_ND_MULTIHOP_HOPLIMIT (64U)
+/** @} */
 
 /**
  * @brief   Initializes 6LoWPAN neighbor discovery for the interface.
@@ -182,6 +216,55 @@ bool gnrc_sixlowpan_nd_opt_6ctx_handle(uint8_t icmpv6_type, sixlowpan_nd_opt_6ct
  */
 void gnrc_sixlowpan_nd_wakeup(void);
 
+#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
+/**
+ * @brief   Handles authoritative border router option.
+ *
+ * @param[in] iface         Interface the source link-layer option was received
+ *                          on.
+ * @param[in] rtr_adv       The router advertisement containing the ABRO.
+ * @param[in] icmpv6_size   The size of the @p rtr_adv.
+ * @param[in] abr_opt       The ABRO.
+ *
+ * @note    Erroneous ABROs are always ignored silently.
+ */
+void gnrc_sixlowpan_nd_opt_abr_handle(kernel_pid_t iface, ndp_rtr_adv_t *rtr_adv, int icmpv6_size,
+                                      sixlowpan_nd_opt_abr_t *abr_opt);
+
+/**
+ * @brief   Builds the 6LoWPAN context option.
+ *
+ * @param[in] prefix_len    The length of the context's prefix.
+ * @param[in] flags         Flags + CID for the context.
+ * @param[in] ltime         Lifetime of the context.
+ * @param[in] prefix        The context's prefix
+ * @param[in] next      More options in the packet. NULL, if there are none.
+ *
+ * @return  The pkt snip list of options, on success
+ * @return  NULL, if packet buffer is full or on error
+ */
+gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_6ctx_build(uint8_t prefix_len, uint8_t flags, uint16_t ltime,
+                                                 ipv6_addr_t *prefix, gnrc_pktsnip_t *next);
+
+/**
+ * @brief   Builds the authoritative border router option.
+ *
+ * @param[in] version   Version of the border router information.
+ * @param[in] ltime     Registration lifetime for the border router.
+ * @param[in] braddr    The IPv6 address of the border router.
+ * @param[in] next      More options in the packet. NULL, if there are none.
+ *
+ * @return  The pkt snip list of options, on success
+ * @return  NULL, if packet buffer is full or on error
+ */
+gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_abr_build(uint32_t version, uint16_t ltime,
+                                                ipv6_addr_t *braddr, gnrc_pktsnip_t *next);
+#else
+#define gnrc_sixlowpan_nd_opt_abr_handle(iface, rtr_adv, icmpv6_size, abr_opt)
+#define gnrc_sixlowpan_nd_opt_6ctx_build(prefix_len, flags, ltime, prefix, next)        (NULL)
+#define gnrc_sixlowpan_nd_opt_abr_build(version, ltime, braddr, next)                   (NULL)
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sys/include/net/gnrc/sixlowpan/nd/router.h b/sys/include/net/gnrc/sixlowpan/nd/router.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d02c7eca634581fb8a9f115913dce1d778c1437
--- /dev/null
+++ b/sys/include/net/gnrc/sixlowpan/nd/router.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
+ *
+ * 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    gnrc_sixlowpan_nd_router    Router-part of 6LoWPAN-ND
+ * @ingroup     gnrc_sixlowpan_nd
+ * @brief       Router-part of 6LoWPAN-ND
+ * @{
+ *
+ * @file
+ * @brief   Router-definitions for 6LoWPAN-ND.
+ *
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+#ifndef GNRC_SIXLOWPAN_ND_ROUTER_H_
+#define GNRC_SIXLOWPAN_ND_ROUTER_H_
+
+#include <stdbool.h>
+
+#include "bitfield.h"
+#include "net/gnrc/sixlowpan/ctx.h"
+#include "net/gnrc/ipv6/netif.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief   Number of registerable border routers
+ *
+ * @note    More than one border routers require some way of synchronization
+ *          of the context information (see
+ *          [RFC 6775, section 8.1](https://tools.ietf.org/html/rfc6775#section-8.1))
+ */
+#ifndef GNRC_SIXLOWPAN_ND_ROUTER_ABR_NUMOF
+#define GNRC_SIXLOWPAN_ND_ROUTER_ABR_NUMOF  (1)
+#endif
+
+/**
+ * @brief   The number of non-link-local prefixes associated with border routers
+ *          at maximum.
+ */
+#ifndef GNRC_SIXLOWPAN_ND_ROUTER_ABR_PRF_NUMOF
+#define GNRC_SIXLOWPAN_ND_ROUTER_ABR_PRF_NUMOF   (GNRC_SIXLOWPAN_ND_ROUTER_ABR_NUMOF)
+#endif
+
+/**
+ * @brief   Representation for prefixes coming from a router
+ */
+typedef struct gnrc_sixlowpan_nd_router_prf {
+    struct gnrc_sixlowpan_nd_router_prf *next;  /**< next prefix */
+    gnrc_ipv6_netif_t *iface;                   /**< interface the prefix is registered too */
+    gnrc_ipv6_netif_addr_t *prefix;             /**< prefix on the interface/in the prefix list */
+} gnrc_sixlowpan_nd_router_prf_t;
+
+/**
+ * @brief   Abstract representation of a border router on all (border) routers.
+ */
+typedef struct {
+    ipv6_addr_t addr;                       /**< the IPv6 address of the border router (BR) */
+    uint32_t version;                       /**< version of the information dissiminated by the
+                                             *   BR */
+    uint16_t ltime;                         /**< the time in minutes until deletion */
+    BITFIELD(ctxs, GNRC_SIXLOWPAN_CTX_SIZE);/**< contexts associated with BR */
+    gnrc_sixlowpan_nd_router_prf_t *prfs;   /**< prefixes associated with BR */
+    vtimer_t ltimer;                        /**< timer for deletion */
+} gnrc_sixlowpan_nd_router_abr_t;
+
+/**
+ * @brief   Removes tentetative neighbor cache entries or sets registered ones to
+ *          garbage-collectible.
+ *
+ * @param[in] nc_entry  A neighbor cache entry.
+ */
+static inline void gnrc_sixlowpan_nd_router_gc_nc(gnrc_ipv6_nc_t *nc_entry)
+{
+    switch (gnrc_ipv6_nc_get_type(nc_entry)) {
+        case GNRC_IPV6_NC_TYPE_TENTATIVE:
+        case GNRC_IPV6_NC_TYPE_REGISTERED:
+            gnrc_ipv6_nc_remove(nc_entry->iface, &nc_entry->ipv6_addr);
+            break;
+        default:
+            break;
+    }
+
+}
+
+/**
+ * @brief   Set @p netif to router mode.
+ *
+ * @details This sets/unsets the GNRC_IPV6_NETIF_FLAGS_ROUTER and initializes or ceases router
+ *          behavior for 6LoWPAN neighbor discovery.
+ *
+ * @param[in] netif     An IPv6 interface. Must not be NULL.
+ * @param[in] enable    Status for the GNRC_IPV6_NETIF_FLAGS_ROUTER flag.
+ */
+static inline void gnrc_sixlowpan_nd_router_set_router(gnrc_ipv6_netif_t *netif, bool enable)
+{
+    if (enable) {
+        netif->flags |= GNRC_IPV6_NETIF_FLAGS_ROUTER;
+    }
+    else {
+        netif->flags &= ~GNRC_IPV6_NETIF_FLAGS_ROUTER;
+    }
+}
+
+/**
+ * @brief   Set/Unset GNRC_IPV6_NETIF_FLAGS_RTR_ADV flag for @p netif.
+ *
+ * @details GNRC_IPV6_NETIF_FLAGS_RTR_ADV and initializes or ceases
+ *          periodic router advertising behavior for neighbor discovery.
+ *
+ * @param[in] netif     An IPv6 interface. Must not be NULL.
+ * @param[in] enable    Status for the GNRC_IPV6_NETIF_FLAGS_RTR_ADV flag.
+ */
+static inline void gnrc_sixlowpan_nd_router_set_rtr_adv(gnrc_ipv6_netif_t *netif, bool enable)
+{
+    if (enable) {
+        netif->flags |= GNRC_IPV6_NETIF_FLAGS_RTR_ADV;
+    }
+    else {
+        netif->flags &= ~GNRC_IPV6_NETIF_FLAGS_RTR_ADV;
+    }
+}
+
+/**
+ * @brief   Get's the border router for this router.
+ *
+ * @return  The border router, if one is specified.
+ * @return  NULL, otherwise.
+ */
+gnrc_sixlowpan_nd_router_abr_t *gnrc_sixlowpan_nd_router_abr_get(void);
+
+/**
+ * @brief   Checks if the version data @p abr_opt is older than the version of the currently
+ *          registered border router.
+ *
+ * @param[in] abr_opt   An authoritative border router option containing potentially new
+ *                      information on the currently registered border router.
+ *
+ * @return  true, if the information in @p abr_opt is newer.
+ * @return  false, if the information in @p abr_opt is older.
+ */
+bool gnrc_sixlowpan_nd_router_abr_older(sixlowpan_nd_opt_abr_t *abr_opt);
+
+/**
+ * @brief   Removes the border router and all the prefixes and contexts it disseminated through
+ *          the network for this node.
+ *
+ * @param[in] abr   The border router.
+ */
+void gnrc_sixlowpan_nd_router_abr_remove(gnrc_sixlowpan_nd_router_abr_t *abr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GNRC_SIXLOWPAN_ND_ROUTER_H_ */
+/** @} */
diff --git a/sys/net/gnrc/Makefile b/sys/net/gnrc/Makefile
index ce91aa59c2e88ae4ad6a487572579665f093f0b2..0b577bdd88281cfd2194d28de88970f8b8e4ddd3 100644
--- a/sys/net/gnrc/Makefile
+++ b/sys/net/gnrc/Makefile
@@ -82,6 +82,9 @@ endif
 ifneq (,$(filter gnrc_sixlowpan_nd,$(USEMODULE)))
     DIRS += network_layer/sixlowpan/nd
 endif
+ifneq (,$(filter gnrc_sixlowpan_nd_router,$(USEMODULE)))
+    DIRS += network_layer/sixlowpan/nd/router
+endif
 ifneq (,$(filter gnrc_sixlowpan_netif,$(USEMODULE)))
     DIRS += network_layer/sixlowpan/netif
 endif
diff --git a/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c b/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c
index d87f19cfbd7615f3cdcb94dd88cc71c7ec19b1b0..cae74d1d1b900c2b1cd2eb82451f409be7f26822 100644
--- a/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c
+++ b/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c
@@ -132,6 +132,13 @@ kernel_pid_t gnrc_sixlowpan_nd_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_
             next_hop = &next_hop_actual;
         }
     }
+#endif
+#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
+    /* next hop determination: https://tools.ietf.org/html/rfc6775#section-6.5.4 */
+    nc_entry = gnrc_ipv6_nc_get(iface, dst);
+    if ((nc_entry != NULL) && (gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_REGISTERED)) {
+        next_hop = dst;
+    }
 #endif
     /* next hop determination according to: https://tools.ietf.org/html/rfc6775#section-5.6 */
     if ((next_hop == NULL) && ipv6_addr_is_link_local(dst)) {   /* prefix is "on-link" */
@@ -143,6 +150,14 @@ kernel_pid_t gnrc_sixlowpan_nd_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_
     }
 
     /* address resolution of next_hop: https://tools.ietf.org/html/rfc6775#section-5.7 */
+    if ((nc_entry == NULL) || (next_hop != dst)) {
+        /* get if not gotten from previous check */
+        nc_entry = gnrc_ipv6_nc_get(iface, next_hop);
+    }
+    if ((nc_entry == NULL) || (!gnrc_ipv6_nc_is_reachable(nc_entry)) ||
+        (gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_TENTATIVE)) {
+        return KERNEL_PID_UNDEF;
+    }
     if (ipv6_addr_is_link_local(next_hop)) {
         kernel_pid_t ifs[GNRC_NETIF_NUMOF];
         size_t ifnum = gnrc_netif_get(ifs);
@@ -162,16 +177,12 @@ kernel_pid_t gnrc_sixlowpan_nd_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_
         return iface;
     }
     else {
-        nc_entry = gnrc_ipv6_nc_get(iface, next_hop);
-        if ((nc_entry == NULL) || (!gnrc_ipv6_nc_is_reachable(nc_entry))) {
-            return KERNEL_PID_UNDEF;
-        }
         if (nc_entry->l2_addr_len > 0) {
             memcpy(l2addr, nc_entry->l2_addr, nc_entry->l2_addr_len);
         }
         *l2addr_len = nc_entry->l2_addr_len;
-        return nc_entry->iface;
     }
+    return nc_entry->iface;
 }
 
 void gnrc_sixlowpan_nd_rtr_sol_reschedule(gnrc_ipv6_nc_t *nce, uint32_t sec_delay)
@@ -206,6 +217,7 @@ uint8_t gnrc_sixlowpan_nd_opt_ar_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6, ui
     eui64_t eui64;
     gnrc_ipv6_netif_t *ipv6_iface;
     gnrc_ipv6_nc_t *nc_entry;
+    uint8_t status = 0;
     (void)sl2a;
     (void)sl2a_len;
     if (ar_opt->len != SIXLOWPAN_ND_OPT_AR_LEN) {
@@ -254,11 +266,56 @@ uint8_t gnrc_sixlowpan_nd_opt_ar_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6, ui
                     DEBUG("6lo nd: unknown status for registration received\n");
                     break;
             }
+#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
+        case ICMPV6_NBR_SOL:
+            if (!(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) &&
+                !(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) {
+                DEBUG("6lo nd: interface not a 6LoWPAN or forwarding interface\n");
+                return 0;
+            }
+            if ((ar_opt->status != 0) ||
+                ipv6_addr_is_unspecified(&ipv6->src)) {
+                /* discard silently */
+                return 0;
+            }
+            /* TODO multihop DAD */
+            if ((nc_entry != NULL) &&
+                ((gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_REGISTERED) ||
+                 (gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_TENTATIVE)) &&
+                (ar_opt->eui64.uint64.u64 != nc_entry->eui64.uint64.u64)) {
+                /* there is already another node with this address */
+                DEBUG("6lo nd: duplicate address detected\n");
+                status = SIXLOWPAN_ND_STATUS_DUP;
+            }
+            else if ((nc_entry != NULL) && (ar_opt->ltime.u16 == 0)) {
+                gnrc_ipv6_nc_remove(iface, &ipv6->src);
+                /* TODO, notify routing protocol */
+            }
+            else if (ar_opt->ltime.u16 != 0) {
+                /* TODO: multihop DAD behavior */
+                uint16_t reg_ltime;
+                if (nc_entry == NULL) {
+                    if ((nc_entry = gnrc_ipv6_nc_add(iface, &ipv6->src, sl2a, sl2a_len,
+                                                     GNRC_IPV6_NC_STATE_STALE)) == NULL) {
+                        DEBUG("6lo nd: neighbor cache is full\n");
+                        return SIXLOWPAN_ND_STATUS_NC_FULL;
+                    }
+                    nc_entry->eui64 = ar_opt->eui64;
+                }
+                nc_entry->flags &= ~GNRC_IPV6_NC_TYPE_MASK;
+                nc_entry->flags |= GNRC_IPV6_NC_TYPE_REGISTERED;
+                reg_ltime = byteorder_ntohs(ar_opt->ltime);
+                /* TODO: notify routing protocol */
+                vtimer_remove(&nc_entry->type_timeout);
+                vtimer_set_msg(&nc_entry->type_timeout, timex_set(reg_ltime * 60, 0),
+                               gnrc_ipv6_pid, GNRC_SIXLOWPAN_ND_MSG_AR_TIMEOUT, nc_entry);
+            }
+#endif
         default:
             break;
     }
 
-    return 0;
+    return status;
 }
 
 bool gnrc_sixlowpan_nd_opt_6ctx_handle(uint8_t icmpv6_type, sixlowpan_nd_opt_6ctx_t *ctx_opt)
@@ -293,4 +350,6 @@ void gnrc_sixlowpan_nd_wakeup(void)
     }
 }
 
+/* gnrc_sixlowpan_nd_opt_abr_handle etc. implemented in gnrc_sixlowpan_nd_router */
+
 /** @} */
diff --git a/sys/net/gnrc/network_layer/sixlowpan/nd/router/Makefile b/sys/net/gnrc/network_layer/sixlowpan/nd/router/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..bb02b5bd956f2c85318fb9060c2cd526d3cdc54f
--- /dev/null
+++ b/sys/net/gnrc/network_layer/sixlowpan/nd/router/Makefile
@@ -0,0 +1,3 @@
+MODULE = gnrc_sixlowpan_nd_router
+
+include $(RIOTBASE)/Makefile.base
diff --git a/sys/net/gnrc/network_layer/sixlowpan/nd/router/gnrc_sixlowpan_nd_router.c b/sys/net/gnrc/network_layer/sixlowpan/nd/router/gnrc_sixlowpan_nd_router.c
new file mode 100644
index 0000000000000000000000000000000000000000..a30c25bf1c994bdd18ba597d0e52a2cd0b4fc4b7
--- /dev/null
+++ b/sys/net/gnrc/network_layer/sixlowpan/nd/router/gnrc_sixlowpan_nd_router.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
+ *
+ * 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
+ */
+
+#include "net/gnrc/ipv6.h"
+#include "net/gnrc/ndp.h"
+#include "net/gnrc/sixlowpan/ctx.h"
+#include "net/gnrc/sixlowpan/nd.h"
+#include "net/icmpv6.h"
+#include "net/ndp.h"
+#include "net/sixlowpan/nd.h"
+
+#include "net/gnrc/sixlowpan/nd/router.h"
+
+static gnrc_sixlowpan_nd_router_abr_t _abrs[GNRC_SIXLOWPAN_ND_ROUTER_ABR_NUMOF];
+static gnrc_sixlowpan_nd_router_prf_t _prefixes[GNRC_SIXLOWPAN_ND_ROUTER_ABR_PRF_NUMOF];
+
+static gnrc_sixlowpan_nd_router_abr_t *_get_abr(ipv6_addr_t *addr)
+{
+    gnrc_sixlowpan_nd_router_abr_t *abr = NULL;
+
+    for (int i = 0; i < GNRC_SIXLOWPAN_ND_ROUTER_ABR_NUMOF; i++) {
+        if (ipv6_addr_equal(&_abrs[i].addr, addr)) {
+            return &_abrs[i];
+        }
+
+        if ((abr == NULL) && ipv6_addr_is_unspecified(&_abrs[i].addr)) {
+            abr = &_abrs[i];
+        }
+    }
+
+    return abr;
+}
+
+static gnrc_sixlowpan_nd_router_prf_t *_get_free_prefix(ipv6_addr_t *prefix, size_t prefix_len)
+{
+    gnrc_sixlowpan_nd_router_prf_t *prf = NULL;
+
+    for (int i = 0; i < GNRC_SIXLOWPAN_ND_ROUTER_ABR_NUMOF; i++) {
+        if ((ipv6_addr_match_prefix(&_prefixes[i].prefix->addr, prefix) >= prefix_len) &&
+            (_prefixes[i].prefix->prefix_len == prefix_len)) {
+            return &_prefixes[i];
+        }
+
+        if ((prf == NULL) && ipv6_addr_is_unspecified(&_prefixes[i].prefix->addr)) {
+            prf = &_prefixes[i];
+        }
+    }
+
+    return prf;
+}
+
+static void _add_prefix(kernel_pid_t iface, gnrc_sixlowpan_nd_router_abr_t *abr,
+                        ndp_opt_pi_t *pi_opt)
+{
+    gnrc_sixlowpan_nd_router_prf_t *prf_ent;
+    gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface);
+    ipv6_addr_t *prefix;
+
+    if ((pi_opt->len != NDP_OPT_PI_LEN) || ipv6_addr_is_link_local(&pi_opt->prefix) ||
+        (pi_opt->flags & NDP_OPT_PI_FLAGS_A) ||
+        (pi_opt->flags & NDP_OPT_PI_FLAGS_L) ||
+        (pi_opt->valid_ltime.u32 == 0)) {
+        return;
+    }
+
+    prefix = gnrc_ipv6_netif_match_prefix(iface, &pi_opt->prefix);
+
+    prf_ent = _get_free_prefix(&pi_opt->prefix, pi_opt->prefix_len);
+
+    if (prf_ent != NULL) {
+        prf_ent->iface = ipv6_iface;
+        prf_ent->prefix = container_of(prefix, gnrc_ipv6_netif_addr_t, addr);
+    }
+
+    LL_PREPEND(abr->prfs, prf_ent);
+}
+
+static void _add_ctx(gnrc_sixlowpan_nd_router_abr_t *abr, sixlowpan_nd_opt_6ctx_t *ctx_opt)
+{
+    if (((ctx_opt->ctx_len < 64) && (ctx_opt->len != 2)) ||
+        ((ctx_opt->ctx_len >= 64) && (ctx_opt->len != 3))) {
+        return;
+    }
+    bf_set(abr->ctxs, sixlowpan_nd_opt_6ctx_get_cid(ctx_opt));
+}
+
+gnrc_sixlowpan_nd_router_abr_t *gnrc_sixlowpan_nd_router_abr_get(void)
+{
+    if (ipv6_addr_is_unspecified(&_abrs[0].addr)) {
+        return NULL;
+    }
+    return _abrs;
+}
+
+bool gnrc_sixlowpan_nd_router_abr_older(sixlowpan_nd_opt_abr_t *abr_opt)
+{
+    gnrc_sixlowpan_nd_router_abr_t *abr;
+    uint32_t version;
+
+    if (abr_opt->len != SIXLOWPAN_ND_OPT_ABR_LEN) {
+        /* invalid option received */
+        return true;
+    }
+
+    abr = _get_abr(&abr_opt->braddr);
+
+    if (abr == NULL) {
+        return false;
+    }
+
+    version = byteorder_ntohs(abr_opt->vlow);
+    version |= byteorder_ntohs(abr_opt->vhigh) << 16;
+
+    return (version < abr->version);
+}
+
+void gnrc_sixlowpan_nd_router_abr_remove(gnrc_sixlowpan_nd_router_abr_t *abr)
+{
+    for (int i = 0; i < GNRC_SIXLOWPAN_CTX_SIZE; i++) {
+        if (bf_isset(abr->ctxs, i)) {
+            gnrc_sixlowpan_ctx_remove(i);
+            bf_unset(abr->ctxs, i);
+        }
+    }
+
+    while (abr->prfs != NULL) {
+        gnrc_sixlowpan_nd_router_prf_t *prefix = abr->prfs;
+        LL_DELETE(abr->prfs, prefix);
+        gnrc_ipv6_netif_remove_addr(prefix->iface->pid, &prefix->prefix->addr);
+        prefix->next = NULL;
+        prefix->iface = NULL;
+        prefix->prefix = NULL;
+    }
+    ipv6_addr_set_unspecified(&abr->addr);
+    abr->version = 0;
+}
+
+/* router-only functions from net/gnrc/sixlowpan/nd.h */
+void gnrc_sixlowpan_nd_opt_abr_handle(kernel_pid_t iface, ndp_rtr_adv_t *rtr_adv, int sicmpv6_size,
+                                      sixlowpan_nd_opt_abr_t *abr_opt)
+{
+    uint16_t opt_offset = 0;
+    uint8_t *buf = (uint8_t *)(rtr_adv + 1);
+    gnrc_sixlowpan_nd_router_abr_t *abr;
+    timex_t t = { 0, 0 };
+
+    /* validity and version was checked in previously called
+     * gnrc_sixlowpan_nd_router_abr_older() */
+
+    abr = _get_abr(&abr_opt->braddr);
+
+    if (abr == NULL) {
+        return;
+    }
+
+    abr->ltime = byteorder_ntohs(abr_opt->ltime);
+
+    if (abr->ltime == 0) {
+        gnrc_sixlowpan_nd_router_abr_remove(abr);
+        return;
+    }
+
+    sicmpv6_size -= sizeof(ndp_rtr_adv_t);
+
+    while (sicmpv6_size > 0) {
+        ndp_opt_t *opt = (ndp_opt_t *)(buf + opt_offset);
+
+        switch (opt->type) {
+            case NDP_OPT_PI:
+                _add_prefix(iface, abr, (ndp_opt_pi_t *)opt);
+
+            case NDP_OPT_6CTX:
+                _add_ctx(abr, (sixlowpan_nd_opt_6ctx_t *)opt);
+
+            default:
+                break;
+        }
+
+        opt_offset += (opt->len * 8);
+        sicmpv6_size -= (opt->len * 8);
+    }
+
+    abr->version = byteorder_ntohs(abr_opt->vlow);
+    abr->version |= byteorder_ntohs(abr_opt->vhigh) << 16;
+    abr->addr.u64[0] = abr_opt->braddr.u64[0];
+    abr->addr.u64[1] = abr_opt->braddr.u64[1];
+    memset(abr->ctxs, 0, sizeof(abr->ctxs));
+    abr->prfs = NULL;
+
+    t.seconds = abr->ltime * 60;
+
+    vtimer_set_msg(&abr->ltimer, t, gnrc_ipv6_pid,
+                   GNRC_SIXLOWPAN_ND_MSG_ABR_TIMEOUT, abr);
+}
+
+gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_6ctx_build(uint8_t prefix_len, uint8_t flags, uint16_t ltime,
+                                                 ipv6_addr_t *prefix, gnrc_pktsnip_t *next)
+{
+    gnrc_pktsnip_t *pkt = gnrc_ndp_opt_build(NDP_OPT_6CTX,
+                                             sizeof(sixlowpan_nd_opt_6ctx_t) + (prefix_len / 8),
+                                             next);
+
+    if (pkt != NULL) {
+        sixlowpan_nd_opt_6ctx_t *ctx_opt = pkt->data;
+        ctx_opt->ctx_len = prefix_len;
+        ctx_opt->resv_c_cid = flags;
+        ctx_opt->resv.u16 = 0;
+        ctx_opt->ltime = byteorder_htons(ltime);
+        /* Bits beyond prefix_len MUST be 0 */
+        memset(ctx_opt + 1, 0, pkt->size - sizeof(sixlowpan_nd_opt_6ctx_t));
+        ipv6_addr_init_prefix((ipv6_addr_t *)(ctx_opt + 1), prefix, prefix_len);
+    }
+
+    return pkt;
+}
+
+gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_abr_build(uint32_t version, uint16_t ltime,
+                                                ipv6_addr_t *braddr, gnrc_pktsnip_t *next)
+{
+    gnrc_pktsnip_t *pkt = gnrc_ndp_opt_build(NDP_OPT_ABR, sizeof(sixlowpan_nd_opt_abr_t), next);
+
+    if (pkt != NULL) {
+        sixlowpan_nd_opt_abr_t *abr_opt = pkt->data;
+        abr_opt->vlow = byteorder_htons(version & 0xffff);
+        abr_opt->vhigh = byteorder_htons(version >> 16);
+        abr_opt->ltime = byteorder_htons(ltime);
+        abr_opt->braddr.u64[0] = braddr->u64[0];
+        abr_opt->braddr.u64[1] = braddr->u64[1];
+    }
+
+    return pkt;
+}
+
+/** @} */