Ejemplo n.º 1
0
static ng_ipv6_addr_t *_add_addr_to_entry(ng_ipv6_netif_t *entry, const ng_ipv6_addr_t *addr,
                                          uint8_t prefix_len, uint8_t flags)
{
    ng_ipv6_netif_addr_t *tmp_addr = NULL;

    for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) {
        if (ng_ipv6_addr_equal(&(entry->addrs[i].addr), addr)) {
            return &(entry->addrs[i].addr);
        }

        if (ng_ipv6_addr_is_unspecified(&(entry->addrs[i].addr)) && !tmp_addr) {
            tmp_addr = &(entry->addrs[i]);
        }
    }

    if (!tmp_addr) {
        DEBUG("ipv6 netif: couldn't add %s/%" PRIu8 " to interface %" PRIkernel_pid "\n: No space left.",
              ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),
              prefix_len, entry->pid);
        return NULL;
    }

    memcpy(&(tmp_addr->addr), addr, sizeof(ng_ipv6_addr_t));
    DEBUG("ipv6 netif: Added %s/%" PRIu8 " to interface %" PRIkernel_pid "\n",
          ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),
          prefix_len, entry->pid);

    tmp_addr->prefix_len = prefix_len;
    tmp_addr->flags = flags;

    if (ng_ipv6_addr_is_multicast(addr)) {
        tmp_addr->flags |= NG_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST;
    }
    else {
        ng_ipv6_addr_t sol_node;

        if (!ng_ipv6_addr_is_link_local(addr)) {
            /* add also corresponding link-local address */
            ng_ipv6_addr_t ll_addr;

            ll_addr.u64[1] = addr->u64[1];
            ng_ipv6_addr_set_link_local_prefix(&ll_addr);

            _add_addr_to_entry(entry, &ll_addr, 64,
                               flags | NG_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK);
        }
        else {
            tmp_addr->flags |= NG_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK;
        }

        ng_ipv6_addr_set_solicited_nodes(&sol_node, addr);
        _add_addr_to_entry(entry, &sol_node, NG_IPV6_ADDR_BIT_LEN, 0);
    }

    return &(tmp_addr->addr);
}
Ejemplo n.º 2
0
void ng_ipv6_netif_add(kernel_pid_t pid)
{
    for (int i = 0; i < NG_NETIF_NUMOF; i++) {
        if (ipv6_ifs[i].pid == pid) {
            return; /* prevent duplicates */
        }
        else if (ipv6_ifs[i].pid == KERNEL_PID_UNDEF) {
            ng_ipv6_addr_t addr = NG_IPV6_ADDR_ALL_NODES_LINK_LOCAL;
            mutex_lock(&ipv6_ifs[i].mutex);

            DEBUG("Add IPv6 interface %" PRIkernel_pid " (i = %d)\n", pid, i);
            ipv6_ifs[i].pid = pid;
            DEBUG(" * pid = %" PRIkernel_pid "  ", ipv6_ifs[i].pid);
            ipv6_ifs[i].mtu = NG_IPV6_NETIF_DEFAULT_MTU;
            DEBUG("mtu = %d  ", ipv6_ifs[i].mtu);
            ipv6_ifs[i].cur_hl = NG_IPV6_NETIF_DEFAULT_HL;
            DEBUG("cur_hl = %d  ", ipv6_ifs[i].cur_hl);

            _add_addr_to_entry(&ipv6_ifs[i], &addr, NG_IPV6_ADDR_BIT_LEN, 0);

            mutex_unlock(&ipv6_ifs[i].mutex);

            return;
        }
    }

    DEBUG("Could not add %" PRIkernel_pid " to IPv6: No space left.\n", pid);
}
Ejemplo n.º 3
0
void gnrc_ipv6_netif_init_by_dev(void)
{
    kernel_pid_t ifs[GNRC_NETIF_NUMOF];
    size_t ifnum = gnrc_netif_get(ifs);

    for (size_t i = 0; i < ifnum; i++) {
        ipv6_addr_t addr;
        eui64_t iid;
        gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(ifs[i]);

        if (ipv6_if == NULL) {
            continue;
        }

        mutex_lock(&ipv6_if->mutex);

#ifdef MODULE_GNRC_SIXLOWPAN
        gnrc_nettype_t if_type = GNRC_NETTYPE_UNDEF;

        if ((gnrc_netapi_get(ifs[i], NETOPT_PROTO, 0, &if_type,
                             sizeof(if_type)) != -ENOTSUP) &&
            (if_type == GNRC_NETTYPE_SIXLOWPAN)) {
            uint16_t src_len = 8;
            uint16_t max_frag_size = UINT16_MAX;

            DEBUG("ipv6 netif: Set 6LoWPAN flag\n");
            ipv6_ifs[i].flags |= GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN;
            /* use EUI-64 (8-byte address) for IID generation and for sending
             * packets */
            gnrc_netapi_set(ifs[i], NETOPT_SRC_LEN, 0, &src_len,
                            sizeof(src_len)); /* don't care for result */

            if (gnrc_netapi_get(ifs[i], NETOPT_MAX_PACKET_SIZE,
                                0, &max_frag_size, sizeof(max_frag_size)) < 0) {
                /* if error we assume it works */
                DEBUG("ipv6 netif: Can not get max packet size from interface %"
                      PRIkernel_pid "\n", ifs[i]);
            }

            gnrc_sixlowpan_netif_add(ifs[i], max_frag_size);
        }
#endif

        if ((gnrc_netapi_get(ifs[i], NETOPT_IPV6_IID, 0, &iid,
                             sizeof(eui64_t)) < 0)) {
            mutex_unlock(&ipv6_if->mutex);
            continue;
        }

        ipv6_addr_set_aiid(&addr, iid.uint8);
        ipv6_addr_set_link_local_prefix(&addr);
        _add_addr_to_entry(ipv6_if, &addr, 64, 0);

        mutex_unlock(&ipv6_if->mutex);
    }
}
Ejemplo n.º 4
0
void gnrc_ipv6_netif_add(kernel_pid_t pid)
{
    gnrc_ipv6_netif_t *free_entry = NULL;

    for (int i = 0; i < GNRC_NETIF_NUMOF; i++) {
        if (ipv6_ifs[i].pid == pid) {
            /* pid has already been added */
            return;
        }

        else if ((ipv6_ifs[i].pid == KERNEL_PID_UNDEF) && !free_entry) {
            /* found the first free entry */
            free_entry = &ipv6_ifs[i];
        }
    }

    if (!free_entry) {
        DEBUG("ipv6 netif: Could not add %" PRIkernel_pid " to IPv6: No space left.\n", pid);
        return;
    }

    /* Otherwise, fill the free entry */

    ipv6_addr_t addr = IPV6_ADDR_ALL_NODES_LINK_LOCAL;
    mutex_lock(&free_entry->mutex);

    DEBUG("ipv6 netif: Add IPv6 interface %" PRIkernel_pid " (i = %d)\n", pid,
          free_entry - ipv6_ifs);
    free_entry->pid = pid;
    free_entry->mtu = GNRC_IPV6_NETIF_DEFAULT_MTU;
    free_entry->cur_hl = GNRC_IPV6_NETIF_DEFAULT_HL;
    free_entry->flags = 0;

    _add_addr_to_entry(free_entry, &addr, IPV6_ADDR_BIT_LEN, 0);

    mutex_unlock(&free_entry->mutex);

#ifdef MODULE_GNRC_NDP
    gnrc_ndp_netif_add(free_entry);
#endif

    DEBUG(" * pid = %" PRIkernel_pid "  ", free_entry->pid);
    DEBUG("cur_hl = %d  ", free_entry->cur_hl);
    DEBUG("mtu = %d  ", free_entry->mtu);
    DEBUG("flags = %04" PRIx16 "\n", free_entry->flags);
}
Ejemplo n.º 5
0
void ng_ipv6_netif_init_by_dev(void)
{
    kernel_pid_t ifs[NG_NETIF_NUMOF];
    size_t ifnum = ng_netif_get(ifs);

    for (size_t i = 0; i < ifnum; i++) {
        ng_ipv6_addr_t addr;
        eui64_t iid;
        ng_ipv6_netif_t *ipv6_if = ng_ipv6_netif_get(ifs[i]);

        if (ipv6_if == NULL) {
            continue;
        }

        mutex_lock(&ipv6_if->mutex);

#ifdef MODULE_NG_SIXLOWPAN
        ng_nettype_t if_type = NG_NETTYPE_UNDEF;

        if ((ng_netapi_get(ifs[i], NETCONF_OPT_PROTO, 0, &if_type,
                           sizeof(if_type)) != -ENOTSUP) &&
            (if_type == NG_NETTYPE_SIXLOWPAN)) {
            uint16_t src_len = 8;
            DEBUG("Set 6LoWPAN flag\n");
            ipv6_ifs[i].flags |= NG_IPV6_NETIF_FLAGS_SIXLOWPAN;
            /* use EUI-64 (8-byte address) for IID generation and for sending
             * packets */
            ng_netapi_set(ifs[i], NETCONF_OPT_SRC_LEN, 0, &src_len,
                          sizeof(src_len)); /* don't care for result */
        }

#endif

        if ((ng_netapi_get(ifs[i], NETCONF_OPT_IPV6_IID, 0, &iid,
                           sizeof(eui64_t)) < 0)) {
            mutex_unlock(&ipv6_if->mutex);
            continue;
        }

        ng_ipv6_addr_set_aiid(&addr, iid.uint8);
        ng_ipv6_addr_set_link_local_prefix(&addr);
        _add_addr_to_entry(ipv6_if, &addr, 64, 0);

        mutex_unlock(&ipv6_if->mutex);
    }
}
Ejemplo n.º 6
0
ipv6_addr_t *gnrc_ipv6_netif_add_addr(kernel_pid_t pid, const ipv6_addr_t *addr,
                                      uint8_t prefix_len, uint8_t flags)
{
    gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(pid);
    ipv6_addr_t *res;

    if ((entry == NULL) || (addr == NULL) || (ipv6_addr_is_unspecified(addr)) ||
        ((prefix_len - 1) > 127)) {    /* prefix_len < 1 || prefix_len > 128 */
        return NULL;
    }

    mutex_lock(&entry->mutex);

    res = _add_addr_to_entry(entry, addr, prefix_len, flags);

    mutex_unlock(&entry->mutex);

    return res;
}
Ejemplo n.º 7
0
int ng_ipv6_netif_add_addr(kernel_pid_t pid, const ng_ipv6_addr_t *addr,
                           uint8_t prefix_len, bool anycast)
{
    ng_ipv6_netif_t *entry = ng_ipv6_netif_get(pid);
    int res;

    if (entry == NULL) {
        return -ENOENT;
    }

    if ((addr == NULL) || (ng_ipv6_addr_is_unspecified(addr)) ||
        ((prefix_len - 1) > 127)) {    /* prefix_len < 1 || prefix_len > 128 */
        return -EINVAL;
    }

    mutex_lock(&entry->mutex);

    res = _add_addr_to_entry(entry, addr, prefix_len, anycast);

    mutex_unlock(&entry->mutex);

    return res;
}
Ejemplo n.º 8
0
void gnrc_ipv6_netif_init_by_dev(void)
{
    kernel_pid_t ifs[GNRC_NETIF_NUMOF];
    size_t ifnum = gnrc_netif_get(ifs);
#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER
    bool abr_init = false;
#endif

    for (size_t i = 0; i < ifnum; i++) {
        ipv6_addr_t addr;
        eui64_t iid;
        uint16_t tmp;
        gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(ifs[i]);

        if (ipv6_if == NULL) {
            continue;
        }

        mutex_lock(&ipv6_if->mutex);

#ifdef MODULE_GNRC_SIXLOWPAN
        gnrc_nettype_t if_type = GNRC_NETTYPE_UNDEF;

        if ((gnrc_netapi_get(ifs[i], NETOPT_PROTO, 0, &if_type,
                             sizeof(if_type)) != -ENOTSUP) &&
            (if_type == GNRC_NETTYPE_SIXLOWPAN)) {
            uint16_t src_len = 8;
            uint16_t max_frag_size = UINT16_MAX;

            DEBUG("ipv6 netif: Set 6LoWPAN flag\n");
            ipv6_ifs[i].flags |= GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN;

            /* the router flag must be set early here, because otherwise
             * _add_addr_to_entry() wouldn't set the solicited node address.
             * However, addresses have to be configured before calling
             * gnrc_ipv6_netif_set_router().
             */
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
            DEBUG("ipv6 netif: Set router flag\n");
            ipv6_ifs[i].flags |= GNRC_IPV6_NETIF_FLAGS_ROUTER;
#endif
            /* use EUI-64 (8-byte address) for IID generation and for sending
             * packets */
            gnrc_netapi_set(ifs[i], NETOPT_SRC_LEN, 0, &src_len,
                            sizeof(src_len)); /* don't care for result */

            if (gnrc_netapi_get(ifs[i], NETOPT_MAX_PACKET_SIZE,
                                0, &max_frag_size, sizeof(max_frag_size)) < 0) {
                /* if error we assume it works */
                DEBUG("ipv6 netif: Can not get max packet size from interface %"
                      PRIkernel_pid "\n", ifs[i]);
            }

            gnrc_sixlowpan_netif_add(ifs[i], max_frag_size);
        }
#endif

        /* set link-local address */
        if ((gnrc_netapi_get(ifs[i], NETOPT_IPV6_IID, 0, &iid,
                             sizeof(eui64_t)) < 0)) {
            mutex_unlock(&ipv6_if->mutex);
            continue;
        }

        ipv6_addr_set_aiid(&addr, iid.uint8);
        ipv6_addr_set_link_local_prefix(&addr);
        _add_addr_to_entry(ipv6_if, &addr, 64, 0);

        /* set link MTU */
        if ((gnrc_netapi_get(ifs[i], NETOPT_MAX_PACKET_SIZE, 0, &tmp,
                             sizeof(uint16_t)) >= 0)) {
            if (tmp >= IPV6_MIN_MTU) {
                ipv6_if->mtu = tmp;
            }
            /* otherwise leave at GNRC_IPV6_NETIF_DEFAULT_MTU as initialized in
             * gnrc_ipv6_netif_add() */
        }

        if (gnrc_netapi_get(ifs[i], NETOPT_IS_WIRED, 0, &tmp, sizeof(int)) > 0) {
            ipv6_if->flags |= GNRC_IPV6_NETIF_FLAGS_IS_WIRED;
        }
        else {
            ipv6_if->flags &= ~GNRC_IPV6_NETIF_FLAGS_IS_WIRED;
        }

        mutex_unlock(&ipv6_if->mutex);
#if (defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER))
        gnrc_ipv6_netif_set_router(ipv6_if, true);
#endif
#ifdef MODULE_GNRC_SIXLOWPAN_ND
        if (ipv6_if->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER
            /* first interface wins */
            if (!abr_init) {
                gnrc_sixlowpan_nd_router_abr_create(&addr, 0);
                gnrc_ipv6_netif_set_rtr_adv(ipv6_if, true);
                abr_init = true;
            }
#endif
            gnrc_sixlowpan_nd_init(ipv6_if);
            continue;   /* skip gnrc_ndp_host_init() */
        }
#endif
#ifdef MODULE_GNRC_NDP_HOST
        /* start periodic router solicitations */
        gnrc_ndp_host_init(ipv6_if);
#endif
    }
}
Ejemplo n.º 9
0
static ipv6_addr_t *_add_addr_to_entry(gnrc_ipv6_netif_t *entry, const ipv6_addr_t *addr,
                                       uint8_t prefix_len, uint8_t flags)
{
    gnrc_ipv6_netif_addr_t *tmp_addr = NULL;

    for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) {
        if (ipv6_addr_equal(&(entry->addrs[i].addr), addr)) {
            return &(entry->addrs[i].addr);
        }

        if (ipv6_addr_is_unspecified(&(entry->addrs[i].addr)) && !tmp_addr) {
            tmp_addr = &(entry->addrs[i]);
        }
    }

    if (!tmp_addr) {
        DEBUG("ipv6 netif: couldn't add %s/%" PRIu8 " to interface %" PRIkernel_pid "\n: No space left.",
              ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),
              prefix_len, entry->pid);
        return NULL;
    }

    memcpy(&(tmp_addr->addr), addr, sizeof(ipv6_addr_t));
    DEBUG("ipv6 netif: Added %s/%" PRIu8 " to interface %" PRIkernel_pid "\n",
          ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),
          prefix_len, entry->pid);

    tmp_addr->prefix_len = prefix_len;
    tmp_addr->flags = flags;

#ifdef MODULE_GNRC_SIXLOWPAN_ND
    if (!ipv6_addr_is_multicast(&(tmp_addr->addr)) &&
        (entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
        ipv6_addr_t *router = gnrc_ndp_internal_default_router();
        if (router != NULL) {
            mutex_unlock(&entry->mutex);    /* function below relocks mutex */
            gnrc_ndp_internal_send_nbr_sol(entry->pid, &tmp_addr->addr, router, router);
            mutex_lock(&entry->mutex);      /* relock mutex */
        }
        /* otherwise there is no default router to register to */
    }
#endif

    if (ipv6_addr_is_multicast(addr)) {
        tmp_addr->flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST;
    }
    else {
        if (!ipv6_addr_is_link_local(addr)) {
#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER
            tmp_addr->valid = 0xFFFF;
            gnrc_sixlowpan_nd_router_abr_t *abr = gnrc_sixlowpan_nd_router_abr_get();
            if (gnrc_sixlowpan_nd_router_abr_add_prf(abr, entry, tmp_addr) < 0) {
                DEBUG("ipv6_netif: error adding prefix to 6LoWPAN-ND management\n");
            }
#endif
#if defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER)
            if ((entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) &&
                (entry->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV)) {
                mutex_unlock(&entry->mutex);    /* function below relocks mutex */
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
                if (entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
                    gnrc_ndp_internal_send_rtr_adv(entry->pid, NULL, NULL, false);
                }
#endif
#ifdef MODULE_GNRC_NDP_ROUTER
                /* New prefixes MAY allow the router to retransmit up to
                 * GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF unsolicited RA
                 * (see https://tools.ietf.org/html/rfc4861#section-6.2.4) */
                if (!(entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
                    entry->rtr_adv_count = GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF;
                    gnrc_ndp_router_retrans_rtr_adv(entry);
                }
#endif
                mutex_lock(&entry->mutex);      /* relock mutex */
            }
#endif
        }
        else {
            tmp_addr->flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK;
        }
#if defined(MODULE_GNRC_NDP_NODE) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER)
        /* add solicited-nodes multicast address for new address if interface is not a
         * 6LoWPAN host interface (see: https://tools.ietf.org/html/rfc6775#section-5.2) */
        if (!(entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) ||
            (entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) {
            ipv6_addr_t sol_node;
            ipv6_addr_set_solicited_nodes(&sol_node, addr);
            _add_addr_to_entry(entry, &sol_node, IPV6_ADDR_BIT_LEN, 0);
        }
#endif
        /* TODO: send NS with ARO on 6LoWPAN interfaces, but not so many and only for the new
         *       source address. */
    }

    return &(tmp_addr->addr);
}
Ejemplo n.º 10
0
static ipv6_addr_t *_add_addr_to_entry(gnrc_ipv6_netif_t *entry, const ipv6_addr_t *addr,
                                       uint8_t prefix_len, uint8_t flags)
{
    gnrc_ipv6_netif_addr_t *tmp_addr = NULL;

    for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) {
        if (ipv6_addr_equal(&(entry->addrs[i].addr), addr)) {
            return &(entry->addrs[i].addr);
        }

        if (ipv6_addr_is_unspecified(&(entry->addrs[i].addr)) && !tmp_addr) {
            tmp_addr = &(entry->addrs[i]);
        }
    }

    if (!tmp_addr) {
        DEBUG("ipv6 netif: couldn't add %s/%" PRIu8 " to interface %" PRIkernel_pid "\n: No space left.",
              ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),
              prefix_len, entry->pid);
        return NULL;
    }

    memcpy(&(tmp_addr->addr), addr, sizeof(ipv6_addr_t));
    DEBUG("ipv6 netif: Added %s/%" PRIu8 " to interface %" PRIkernel_pid "\n",
          ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),
          prefix_len, entry->pid);

    tmp_addr->prefix_len = prefix_len;
    tmp_addr->flags = flags;

    if (ipv6_addr_is_multicast(addr)) {
        tmp_addr->flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST;
    }
    else {
        if (!ipv6_addr_is_link_local(addr)) {
            /* add also corresponding link-local address */
            ipv6_addr_t ll_addr;

            ll_addr.u64[1] = addr->u64[1];
            ipv6_addr_set_link_local_prefix(&ll_addr);

            _add_addr_to_entry(entry, &ll_addr, 64,
                               flags | GNRC_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK);
#ifdef MODULE_GNRC_NDP_ROUTER
            /* New prefixes MAY allow the router to retransmit up to
             * GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF unsolicited RA
             * (see https://tools.ietf.org/html/rfc4861#section-6.2.4) */
            if ((entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) &&
                (entry->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV)) {
                entry->rtr_adv_count = GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF;
                mutex_unlock(&entry->mutex);    /* function below relocks mutex */
                gnrc_ndp_router_retrans_rtr_adv(entry);
                mutex_lock(&entry->mutex);      /* relock mutex */
            }
#endif
        }
        else {
            tmp_addr->flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK;
        }
#if defined(MODULE_GNRC_NDP_NODE) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER)
        /* add solicited-nodes multicast address for new address if interface is not a
         * 6LoWPAN host interface (see: https://tools.ietf.org/html/rfc6775#section-5.2) */
        if (!(entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) ||
            (entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) {
            ipv6_addr_t sol_node;
            ipv6_addr_set_solicited_nodes(&sol_node, addr);
            _add_addr_to_entry(entry, &sol_node, IPV6_ADDR_BIT_LEN, 0);
        }
#endif
        /* TODO: send NS with ARO on 6LoWPAN interfaces, but not so many and only for the new
         *       source address. */
    }

    return &(tmp_addr->addr);
}