Beispiel #1
0
kernel_pid_t ng_ipv6_netif_find_by_addr(ng_ipv6_addr_t **out, const ng_ipv6_addr_t *addr)
{
    for (int i = 0; i < NG_NETIF_NUMOF; i++) {
        if (out != NULL) {
            *out = ng_ipv6_netif_find_addr(ipv6_ifs[i].pid, addr);

            if (*out != NULL) {
                DEBUG("ipv6 netif: Found %s on interface %" PRIkernel_pid "\n",
                      ng_ipv6_addr_to_str(addr_str, *out, sizeof(addr_str)),
                      ipv6_ifs[i].pid);
                return ipv6_ifs[i].pid;
            }
        }
        else {
            if (ng_ipv6_netif_find_addr(ipv6_ifs[i].pid, addr) != NULL) {
                DEBUG("ipv6 netif: Found %s on interface %" PRIkernel_pid "\n",
                      ng_ipv6_addr_to_str(addr_str, *out, sizeof(addr_str)),
                      ipv6_ifs[i].pid);
                return ipv6_ifs[i].pid;
            }
        }
    }

    if (out != NULL) {
        *out = NULL;
    }

    return KERNEL_PID_UNDEF;
}
Beispiel #2
0
void ng_ndp_retrans_nbr_sol(ng_ipv6_nc_t *nc_entry)
{
    if ((ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_INCOMPLETE) ||
        (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_PROBE)) {
        if (nc_entry->probes_remaining > 1) {
            ng_ipv6_addr_t dst;

            DEBUG("ndp: Retransmit neighbor solicitation for %s\n",
                  ng_ipv6_addr_to_str(addr_str, &nc_entry->ipv6_addr, sizeof(addr_str)));

            /* retransmit neighbor solicatation */
            if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_INCOMPLETE) {
                ng_ipv6_addr_set_solicited_nodes(&dst, &nc_entry->ipv6_addr);
            }
            else {
                dst.u64[0] = nc_entry->ipv6_addr.u64[0];
                dst.u64[1] = nc_entry->ipv6_addr.u64[1];
            }

            nc_entry->probes_remaining--;

            if (nc_entry->iface == KERNEL_PID_UNDEF) {
                timex_t t = { 0, NG_NDP_RETRANS_TIMER };
                kernel_pid_t ifs[NG_NETIF_NUMOF];
                size_t ifnum = ng_netif_get(ifs);

                for (size_t i = 0; i < ifnum; i++) {
                    _send_nbr_sol(ifs[i], &nc_entry->ipv6_addr, &dst);
                }

                vtimer_remove(&nc_entry->nbr_sol_timer);
                vtimer_set_msg(&nc_entry->nbr_sol_timer, t, ng_ipv6_pid,
                               NG_NDP_MSG_NBR_SOL_RETRANS, nc_entry);
            }
            else {
                ng_ipv6_netif_t *ipv6_iface = ng_ipv6_netif_get(nc_entry->iface);

                _send_nbr_sol(nc_entry->iface, &nc_entry->ipv6_addr, &dst);

                mutex_lock(&ipv6_iface->mutex);
                vtimer_remove(&nc_entry->nbr_sol_timer);
                vtimer_set_msg(&nc_entry->nbr_sol_timer,
                               ipv6_iface->retrans_timer, ng_ipv6_pid,
                               NG_NDP_MSG_NBR_SOL_RETRANS, nc_entry);
                mutex_unlock(&ipv6_iface->mutex);
            }
        }
        else if (nc_entry->probes_remaining <= 1) {
            DEBUG("ndp: Remove nc entry %s for interface %" PRIkernel_pid "\n",
                  ng_ipv6_addr_to_str(addr_str, &nc_entry->ipv6_addr, sizeof(addr_str)),
                  nc_entry->iface);

#ifdef MODULE_FIB
            fib_remove_entry((uint8_t *) & (nc_entry->ipv6_addr), sizeof(ng_ipv6_addr_t));
#endif
            ng_ipv6_nc_remove(nc_entry->iface, &nc_entry->ipv6_addr);
        }
    }
}
Beispiel #3
0
ng_pktsnip_t *ng_ipv6_hdr_build(ng_pktsnip_t *payload,
                                uint8_t *src, uint8_t src_len,
                                uint8_t *dst, uint8_t dst_len)
{
    ng_pktsnip_t *ipv6;
    ng_ipv6_hdr_t *hdr;

    if (((src_len != 0) && (src_len != sizeof(ng_ipv6_addr_t))) ||
        ((dst_len != 0) && (dst_len != sizeof(ng_ipv6_addr_t)))) {
        DEBUG("ipv6_hdr: Address length was not 0 or %zu byte.\n",
              sizeof(ng_ipv6_addr_t));
        return NULL;
    }

    ipv6 = ng_pktbuf_add(payload, NULL, sizeof(ng_ipv6_hdr_t), HDR_NETTYPE);

    if (ipv6 == NULL) {
        DEBUG("ipv6_hdr: no space left in packet buffer\n");
        return NULL;
    }

    hdr = (ng_ipv6_hdr_t *)ipv6->data;

    if ((src != NULL) && (src_len != 0)) {
#ifdef MODULE_NG_IPV6_ADDR
        DEBUG("ipv6_hdr: set packet source to %s\n",
              ng_ipv6_addr_to_str(addr_str, (ng_ipv6_addr_t *)src,
                                  sizeof(addr_str)));
#endif
        memcpy(&hdr->src, src, src_len);
    }
    else {
        DEBUG("ipv6_hdr: set packet source to ::\n");
        ng_ipv6_addr_set_unspecified(&hdr->src);
    }

    memset(&hdr->dst + dst_len, 0, sizeof(ng_ipv6_addr_t) - dst_len);

    if ((dst != NULL) && (dst_len != 0)) {
#ifdef MODULE_NG_IPV6_ADDR
        DEBUG("ipv6_hdr: set packet destination to %s\n",
              ng_ipv6_addr_to_str(addr_str, (ng_ipv6_addr_t *)dst,
                                  sizeof(addr_str)));
#endif
        memcpy(&hdr->dst, dst, dst_len);
    }
    else {
        DEBUG("ipv6_hdr: set packet destination to ::1\n");
        ng_ipv6_addr_set_loopback(&hdr->dst);
    }

    hdr->v_tc_fl = byteorder_htonl(0x60000000); /* set version, tc and fl in one go*/
    hdr->nh = PROTNUM_RESERVED;
    hdr->hl = 0;

    return ipv6;
}
Beispiel #4
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);
}
Beispiel #5
0
static uint8_t _find_by_prefix_unsafe(ng_ipv6_addr_t **res, ng_ipv6_netif_t *iface,
                                      const ng_ipv6_addr_t *addr, bool only_unicast)
{
    uint8_t best_match = 0;

    for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) {
        uint8_t match;

        if ((only_unicast &&
             ng_ipv6_netif_addr_is_non_unicast(&(iface->addrs[i].addr))) ||
            ng_ipv6_addr_is_unspecified(&(iface->addrs[i].addr))) {
            continue;
        }

        match = ng_ipv6_addr_match_prefix(&(iface->addrs[i].addr), addr);

        if (only_unicast && !ng_ipv6_addr_is_multicast(addr) &&
            (match < iface->addrs[i].prefix_len)) {
            /* match but not of same subnet */
            continue;
        }

        if (match > best_match) {
            if (res != NULL) {
                *res = &(iface->addrs[i].addr);
            }

            best_match = match;
        }
    }

#if ENABLE_DEBUG
    if (*res != NULL) {
        DEBUG("ipv6 netif: Found %s on interface %" PRIkernel_pid " matching ",
              ng_ipv6_addr_to_str(addr_str, *res, sizeof(addr_str)),
              iface->pid);
        DEBUG("%s by %" PRIu8 " bits (used as source address = %s)\n",
              ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),
              best_match,
              (only_unicast) ? "true" : "false");
    }
    else {
        DEBUG("ipv6 netif: Did not found any address on interface %" PRIkernel_pid
              " matching %s (used as source address = %s)\n",
              iface->pid,
              ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),
              (only_unicast) ? "true" : "false");
    }
#endif

    return best_match;
}
Beispiel #6
0
static void test_ipv6_addr_to_str__success3(void)
{
    ng_ipv6_addr_t a = NG_IPV6_ADDR_UNSPECIFIED;
    char result[sizeof("::")];

    TEST_ASSERT_EQUAL_STRING("::", ng_ipv6_addr_to_str(result, &a, sizeof(result)));
}
Beispiel #7
0
static int _add_addr_to_entry(ng_ipv6_netif_t *entry, const ng_ipv6_addr_t *addr,
                              uint8_t prefix_len, bool anycast)
{
    for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) {
        if (ng_ipv6_addr_equal(&(entry->addrs[i].addr), addr)) {
            return 0;
        }

        if (ng_ipv6_addr_is_unspecified(&(entry->addrs[i].addr))) {
            memcpy(&(entry->addrs[i].addr), addr, sizeof(ng_ipv6_addr_t));
            DEBUG("Added %s/%" PRIu8 " to interface %" PRIkernel_pid "\n",
                  ng_ipv6_addr_to_str(&(entry->addrs[i].addr), addr,
                                      sizeof(addr_str)),
                  prefix_len, entry->pid);

            if (anycast || ng_ipv6_addr_is_multicast(addr)) {
                if (ng_ipv6_addr_is_multicast(addr)) {
                    entry->addrs[i].prefix_len = NG_IPV6_ADDR_BIT_LEN;
                }

                entry->addrs[i].flags = NG_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST;
            }
            else {
                entry->addrs[i].prefix_len = prefix_len;

                entry->addrs[i].flags = NG_IPV6_NETIF_ADDR_FLAGS_UNICAST;
            }

            return 0;
        }
    }

    return -ENOMEM;
}
Beispiel #8
0
static void test_ipv6_addr_to_str__success4(void)
{
    ng_ipv6_addr_t a = NG_IPV6_ADDR_LOOPBACK;
    char result[sizeof("::1")];

    TEST_ASSERT_EQUAL_STRING("::1", ng_ipv6_addr_to_str(result, &a, sizeof(result)));
}
Beispiel #9
0
kernel_pid_t ng_ipv6_netif_find_by_prefix(ng_ipv6_addr_t **out, const ng_ipv6_addr_t *prefix)
{
    uint8_t best_match = 0;
    ng_ipv6_addr_t *tmp_res = NULL;
    kernel_pid_t res = KERNEL_PID_UNDEF;

    for (int i = 0; i < NG_NETIF_NUMOF; i++) {
        uint8_t match;

        mutex_lock(&(ipv6_ifs[i].mutex));

        match = _find_by_prefix_unsafe(&tmp_res, ipv6_ifs + i, prefix, false);

        if (match > best_match) {
            if (out != NULL) {
                *out = tmp_res;
            }

            res = ipv6_ifs[i].pid;
            best_match = match;
        }

        mutex_unlock(&(ipv6_ifs[i].mutex));
    }

#if ENABLE_DEBUG

    if (res != KERNEL_PID_UNDEF) {
        DEBUG("Found %s on interface %" PRIkernel_pid " globally matching ",
              ng_ipv6_addr_to_str(addr_str, *out, sizeof(addr_str)),
              res);
        DEBUG("%s by %" PRIu8 " bits\n",
              ng_ipv6_addr_to_str(addr_str, prefix, sizeof(addr_str)),
              best_match);
    }
    else {
        DEBUG("Did not found any address globally matching %s\n",
              ng_ipv6_addr_to_str(addr_str, prefix, sizeof(addr_str)));
    }

#endif

    return res;
}
Beispiel #10
0
static void test_ipv6_addr_to_str__string_too_short(void)
{
    ng_ipv6_addr_t a = { {
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
            0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
        }
    };
    char result[1];

    TEST_ASSERT_NULL(ng_ipv6_addr_to_str(result, &a, sizeof(result)));
}
Beispiel #11
0
static void _dump_ipv6_hdr(ng_ipv6_hdr_t *hdr)
{
    char addr_str[NG_IPV6_ADDR_MAX_STR_LEN];

    if (ng_ipv6_hdr_is_ipv6_hdr(hdr)) {
        printf("illegal version field: %" PRIu8 "\n", ng_ipv6_hdr_get_version(hdr));
    }

    printf("traffic class: 0x%02" PRIx8 " (ECN: 0x%" PRIx8 ", DSCP: 0x%02" PRIx8 ")\n",
           ng_ipv6_hdr_get_tc(hdr), ng_ipv6_hdr_get_tc_ecn(hdr),
           ng_ipv6_hdr_get_tc_dscp(hdr));
    printf("flow label: 0x%05" PRIx32 "\n", ng_ipv6_hdr_get_fl(hdr));
    printf("length: %" PRIu16 "  next header: %" PRIu8 "  hop limit: %" PRIu8 "\n",
           byteorder_ntohs(hdr->len), hdr->nh, hdr->hl);
    printf("source address: %s\n", ng_ipv6_addr_to_str(addr_str, &hdr->src,
            sizeof(addr_str)));
    printf("destination address: %s\n", ng_ipv6_addr_to_str(addr_str, &hdr->dst,
            sizeof(addr_str)));

}
Beispiel #12
0
static void test_ipv6_addr_to_str__success2(void)
{
    ng_ipv6_addr_t a = { {
            0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
        }
    };
    char result[NG_IPV6_ADDR_MAX_STR_LEN];

    TEST_ASSERT_EQUAL_STRING("fe80::f8f9:fafb:fcfd:feff",
                             ng_ipv6_addr_to_str(result, &a, sizeof(result)));
}
Beispiel #13
0
static void test_ipv6_addr_to_str__success(void)
{
    ng_ipv6_addr_t a = { {
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
            0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
        }
    };
    char result[NG_IPV6_ADDR_MAX_STR_LEN];

    TEST_ASSERT_EQUAL_STRING("1:203:405:607:809:a0b:c0d:e0f",
                             ng_ipv6_addr_to_str(result, &a, sizeof(result)));
}
Beispiel #14
0
static void test_ipv6_addr_to_str__success5(void)
{
    ng_ipv6_addr_t a = { {
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xff, 0xff, 192, 168, 0, 1
        }
    };
    char result[NG_IPV6_ADDR_MAX_STR_LEN];

    TEST_ASSERT_EQUAL_STRING("::ffff:192.168.0.1",
                             ng_ipv6_addr_to_str(result, &a, sizeof(result)));
}
Beispiel #15
0
static void _remove_addr_from_entry(ng_ipv6_netif_t *entry, ng_ipv6_addr_t *addr)
{
    mutex_lock(&entry->mutex);

    for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) {
        if (ng_ipv6_addr_equal(&(entry->addrs[i].addr), addr)) {
            DEBUG("ipv6 netif: Remove %s to interface %" PRIkernel_pid "\n",
                  ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), entry->pid);
            ng_ipv6_addr_set_unspecified(&(entry->addrs[i].addr));
            entry->addrs[i].flags = 0;

            mutex_unlock(&entry->mutex);
            return;
        }
    }

    mutex_unlock(&entry->mutex);
}
Beispiel #16
0
int main(void)
{
    shell_t shell;
    const char *disco_addr = DISCO_ADDR;

    port[0] = (uint8_t)DISCO_PORT;
    port[1] = (uint8_t)(DISCO_PORT >> 8);
    ng_ipv6_addr_from_str(&addr, disco_addr);

    char buf[100];
    ng_ipv6_addr_to_str(buf, &addr, 100);
    printf("got address: %s\n", buf);


    set_chan(DISCO_CHANNEL);

    shell_init(&shell, shell_commands, STDIO_RX_BUFSIZE, getchar, putchar);
    shell_run(&shell);

    return 0;
}
Beispiel #17
0
ng_ipv6_addr_t *ng_ipv6_netif_find_addr(kernel_pid_t pid, const ng_ipv6_addr_t *addr)
{
    ng_ipv6_netif_t *entry = ng_ipv6_netif_get(pid);

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

    mutex_lock(&entry->mutex);

    for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) {
        if (ng_ipv6_addr_equal(&(entry->addrs[i].addr), addr)) {
            mutex_unlock(&entry->mutex);
            DEBUG("ipv6 netif: Found %s on interface %" PRIkernel_pid "\n",
                  ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),
                  pid);
            return &(entry->addrs[i].addr);
        }
    }

    mutex_unlock(&entry->mutex);

    return NULL;
}
Beispiel #18
0
void ng_ipv6_netif_remove_addr(kernel_pid_t pid, ng_ipv6_addr_t *addr)
{
    ng_ipv6_netif_t *entry = ng_ipv6_netif_get(pid);

    if (entry == NULL) {
        return;
    }

    mutex_lock(&entry->mutex);

    for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) {
        if (ng_ipv6_addr_equal(&(entry->addrs[i].addr), addr)) {
            DEBUG("Remove %s to interface %" PRIkernel_pid "\n",
                  ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), pid);
            ng_ipv6_addr_set_unspecified(&(entry->addrs[i].addr));
            entry->addrs[i].flags = 0;

            mutex_unlock(&entry->mutex);
            return;
        }
    }

    mutex_unlock(&entry->mutex);
}
Beispiel #19
0
void ng_ndp_nbr_adv_handle(kernel_pid_t iface, ng_pktsnip_t *pkt,
                           ng_ipv6_hdr_t *ipv6, ng_ndp_nbr_adv_t *nbr_adv,
                           size_t icmpv6_size)
{
    uint16_t opt_offset = 0;
    uint8_t *buf = ((uint8_t *)nbr_adv) + sizeof(ng_ndp_nbr_adv_t);
    int l2tgt_len = 0;
    uint8_t l2tgt[NG_IPV6_NC_L2_ADDR_MAX];
    int sicmpv6_size = (int)icmpv6_size;
    ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, &nbr_adv->tgt);
    ng_pktsnip_t *netif;
    ng_netif_hdr_t *netif_hdr = NULL;

    DEBUG("ndp: received neighbor advertisement (src: %s, ",
          ng_ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str)));
    DEBUG("dst: %s, ",
          ng_ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str)));
    DEBUG("tgt: %s)\n",
          ng_ipv6_addr_to_str(addr_str, &nbr_adv->tgt, sizeof(addr_str)));

    /* check validity */
    if ((ipv6->hl != 255) || (nbr_adv->code != 0) ||
        (icmpv6_size < sizeof(ng_ndp_nbr_adv_t)) ||
        ng_ipv6_addr_is_multicast(&nbr_adv->tgt)) {
        DEBUG("ndp: neighbor advertisement was invalid.\n");
        /* ipv6 releases */
        return;
    }

    if (nc_entry == NULL) {
        /* see https://tools.ietf.org/html/rfc4861#section-7.2.5 */
        DEBUG("ndp: no neighbor cache entry found for advertisement's target\n");
        /* ipv6 releases */
        return;
    }

    sicmpv6_size -= sizeof(ng_ndp_nbr_adv_t);

    while (sicmpv6_size > 0) {
        ng_ndp_opt_t *opt = (ng_ndp_opt_t *)(buf + opt_offset);

        switch (opt->type) {
            case NG_NDP_OPT_TL2A:
                if ((l2tgt_len = _handle_tl2a_opt(pkt, ipv6, nbr_adv->type, opt,
                                                  l2tgt)) < 0) {
                    /* invalid target link-layer address option */
                    return;
                }

                break;

            default:
                /* silently discard all other options */
                break;
        }

        opt_offset += (opt->len * 8);
        sicmpv6_size -= (opt->len * 8);
    }

    LL_SEARCH_SCALAR(pkt, netif, type, NG_NETTYPE_NETIF);

    if (netif != NULL) {
        netif_hdr = netif->data;
    }

    if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_INCOMPLETE) {
        ng_pktqueue_t *queued_pkt;

        if (_pkt_has_l2addr(netif_hdr) && (l2tgt_len == 0)) {
            /* link-layer has addresses, but no TLLAO supplied: discard silently
             * (see https://tools.ietf.org/html/rfc4861#section-7.2.5) */
            return;
        }

        nc_entry->iface = iface;
        nc_entry->l2_addr_len = l2tgt_len;
        memcpy(nc_entry->l2_addr, l2tgt, l2tgt_len);

        if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_S) {
            _set_state(nc_entry, NG_IPV6_NC_STATE_REACHABLE);
        }
        else {
            _set_state(nc_entry, NG_IPV6_NC_STATE_STALE);
        }

        if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_R) {
            nc_entry->flags |= NG_IPV6_NC_IS_ROUTER;
        }
        else {
            nc_entry->flags &= ~NG_IPV6_NC_IS_ROUTER;
            /* TODO: update FIB */
        }

        while ((queued_pkt = ng_pktqueue_remove_head(&nc_entry->pkts)) != NULL) {
            ng_netapi_send(ng_ipv6_pid, queued_pkt->pkt);
            queued_pkt->pkt = NULL;
        }
    }
    else {
        /* first or-term: no link-layer, but nc_entry has l2addr,
         * second or-term: different l2addr cached */
        bool l2tgt_changed = false;

        if ((!_pkt_has_l2addr(netif_hdr)) && (l2tgt_len == 0)) {
            /* there was previously a L2 address registered */
            l2tgt_changed = (nc_entry->l2_addr_len != 0);
        }
        /* link-layer has addresses and TLLAO with different address */
        else if (_pkt_has_l2addr(netif_hdr) && (l2tgt_len != 0)) {
            l2tgt_changed = (!(l2tgt_len == nc_entry->l2_addr_len)) &&
                            (memcmp(nc_entry->l2_addr, l2tgt, l2tgt_len) == 0);
        }

        if ((nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_O) || !l2tgt_changed ||
            (l2tgt_len == 0)) {
            if (l2tgt_len != 0) {
                nc_entry->iface = iface;
                nc_entry->l2_addr_len = l2tgt_len;
                memcpy(nc_entry->l2_addr, l2tgt, l2tgt_len);
            }

            if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_S) {
                _set_state(nc_entry, NG_IPV6_NC_STATE_REACHABLE);
            }
            else if (l2tgt_changed && (l2tgt_len != 0)) {
                _set_state(nc_entry, NG_IPV6_NC_STATE_STALE);
            }

            if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_R) {
                nc_entry->flags |= NG_IPV6_NC_IS_ROUTER;
            }
            else {
                nc_entry->flags &= ~NG_IPV6_NC_IS_ROUTER;
                /* TODO: update FIB */
            }
        }
        else if (l2tgt_changed) {
            if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_REACHABLE) {
                _set_state(nc_entry, NG_IPV6_NC_STATE_STALE);

            }
        }
    }

    return;
}
Beispiel #20
0
static void _netif_list(kernel_pid_t dev)
{
    uint8_t hwaddr[MAX_ADDR_LEN];
    uint16_t u16;
    int16_t i16;
    int res;
    ng_netconf_state_t state;
    ng_netconf_enable_t enable;
    bool linebreak = false;
#ifdef MODULE_NG_IPV6_NETIF
    ng_ipv6_netif_t *entry = ng_ipv6_netif_get(dev);
    char ipv6_addr[NG_IPV6_ADDR_MAX_STR_LEN];
#endif


    printf("Iface %2d  ", dev);

    res = ng_netapi_get(dev, NETCONF_OPT_ADDRESS, 0, hwaddr, sizeof(hwaddr));

    if (res >= 0) {
        char hwaddr_str[res * 3];
        printf(" HWaddr: ");
        printf("%s", ng_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str),
                                          hwaddr, res));
        printf(" ");
    }

    res = ng_netapi_get(dev, NETCONF_OPT_CHANNEL, 0, &u16, sizeof(u16));

    if (res >= 0) {
        printf(" Channel: %" PRIu16 " ", u16);
    }

    res = ng_netapi_get(dev, NETCONF_OPT_NID, 0, &u16, sizeof(u16));

    if (res >= 0) {
        printf(" NID: 0x%" PRIx16 " ", u16);
    }

    res = ng_netapi_get(dev, NETCONF_OPT_TX_POWER, 0, &i16, sizeof(i16));

    if (res >= 0) {
        printf(" TX-Power: %" PRIi16 "dBm ", i16);
    }

    res = ng_netapi_get(dev, NETCONF_OPT_STATE, 0, &state, sizeof(state));

    if (res >= 0) {
        printf(" State: ");
        _print_netconf_state(state);
    }

    printf("\n           ");

    res = ng_netapi_get(dev, NETCONF_OPT_ADDRESS_LONG, 0, hwaddr, sizeof(hwaddr));

    if (res >= 0) {
        char hwaddr_str[res * 3];
        printf("Long HWaddr: ");
        printf("%s", ng_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str),
                                          hwaddr, res));
        printf("\n           ");
    }

    res = ng_netapi_get(dev, NETCONF_OPT_PROMISCUOUSMODE, 0, &enable, sizeof(enable));

    if ((res >= 0) && (enable == NETCONF_ENABLE)) {
        printf("PROMISC  ");
        linebreak = true;
    }

    res = ng_netapi_get(dev, NETCONF_OPT_AUTOACK, 0, &enable, sizeof(enable));

    if ((res >= 0) && (enable == NETCONF_ENABLE)) {
        printf("AUTOACK  ");
        linebreak = true;
    }

    res = ng_netapi_get(dev, NETCONF_OPT_PRELOADING, 0, &enable, sizeof(enable));

    if ((res >= 0) && (enable == NETCONF_ENABLE)) {
        printf("PRELOAD  ");
        linebreak = true;
    }

    res = ng_netapi_get(dev, NETCONF_OPT_RAWMODE, 0, &enable, sizeof(enable));

    if ((res >= 0) && (enable == NETCONF_ENABLE)) {
        printf("RAWMODE  ");
        linebreak = true;
    }

#ifdef MODULE_NG_IPV6_NETIF
    if ((entry != NULL) && (entry->flags & NG_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
        printf("6LO ");
        linebreak = true;
    }
#endif

    if (linebreak) {
        printf("\n           ");
    }

    res = ng_netapi_get(dev, NETCONF_OPT_SRC_LEN, 0, &u16, sizeof(u16));

    if (res >= 0) {
        printf("Source address length: %" PRIu16 "\n           ", u16);
    }

#ifdef MODULE_NG_IPV6_NETIF
    for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) {
        if (!ng_ipv6_addr_is_unspecified(&entry->addrs[i].addr)) {
            printf("inet6 addr: ");

            if (ng_ipv6_addr_to_str(ipv6_addr, &entry->addrs[i].addr,
                                    NG_IPV6_ADDR_MAX_STR_LEN)) {
                printf("%s/%" PRIu8 "  scope: ", ipv6_addr,
                       entry->addrs[i].prefix_len);

                if ((ng_ipv6_addr_is_link_local(&entry->addrs[i].addr))) {
                    printf("local");
                }
                else {
                    printf("global");
                }

                if (entry->addrs[i].flags & NG_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST) {
                    if (ng_ipv6_addr_is_multicast(&entry->addrs[i].addr)) {
                        printf(" [multicast]");
                    }
                    else {
                        printf(" [anycast]");
                    }
                }
            }
            else {
                printf("error in conversion");
            }

            printf("\n           ");
        }
    }
#endif

    puts("");
}
Beispiel #21
0
static void test_ipv6_addr_to_str__addr_NULL(void)
{
    char result[NG_IPV6_ADDR_MAX_STR_LEN];

    TEST_ASSERT_NULL(ng_ipv6_addr_to_str(result, NULL, sizeof(result)));
}
Beispiel #22
0
static void test_ipv6_addr_to_str__result_NULL(void)
{
    ng_ipv6_addr_t a;

    TEST_ASSERT_NULL(ng_ipv6_addr_to_str(NULL, &a, NG_IPV6_ADDR_MAX_STR_LEN));
}
Beispiel #23
0
static void _send_nbr_sol(kernel_pid_t iface, ng_ipv6_addr_t *tgt,
                          ng_ipv6_addr_t *dst)
{
    ng_pktsnip_t *hdr, *pkt = NULL;
    ng_ipv6_addr_t *src = NULL;
    size_t src_len = 0;

    DEBUG("ndp: send neighbor solicitation (iface: %" PRIkernel_pid ", tgt: %s, ",
          iface, ng_ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str)));
    DEBUG("dst: %s)\n", ng_ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)));

    /* check if there is a fitting source address to target */
    if ((src = ng_ipv6_netif_find_best_src_addr(iface, tgt)) != NULL) {
        uint8_t l2src[8];
        uint16_t l2src_len;
        src_len = sizeof(ng_ipv6_addr_t);
        l2src_len = _get_l2src(l2src, sizeof(l2src), iface);

        if (l2src_len > 0) {
            /* add source address link-layer address option */
            pkt = ng_ndp_opt_sl2a_build(l2src, l2src_len, NULL);

            if (pkt == NULL) {
                DEBUG("ndp: error allocating Source Link-layer address option.\n");
                ng_pktbuf_release(pkt);
                return;
            }
        }
    }

    hdr = ng_ndp_nbr_sol_build(tgt, pkt);

    if (hdr == NULL) {
        DEBUG("ndp: error allocating Neighbor solicitation.\n");
        ng_pktbuf_release(pkt);
        return;
    }

    pkt = hdr;
    hdr = ng_ipv6_hdr_build(pkt, (uint8_t *)src, src_len, (uint8_t *)dst,
                            sizeof(ng_ipv6_addr_t));

    if (hdr == NULL) {
        DEBUG("ndp: error allocating IPv6 header.\n");
        ng_pktbuf_release(pkt);
        return;
    }

    ((ng_ipv6_hdr_t *)hdr->data)->hl = 255;

    pkt = hdr;
    /* add netif header for send interface specification */
    hdr = ng_netif_hdr_build(NULL, 0, NULL, 0);

    if (hdr == NULL) {
        DEBUG("ndp: error allocating netif header.\n");
        return;
    }

    ((ng_netif_hdr_t *)hdr->data)->if_pid = iface;

    LL_PREPEND(pkt, hdr);

    ng_netapi_send(ng_ipv6_pid, pkt);
}
Beispiel #24
0
void ng_ndp_nbr_sol_handle(kernel_pid_t iface, ng_pktsnip_t *pkt,
                           ng_ipv6_hdr_t *ipv6, ng_ndp_nbr_sol_t *nbr_sol,
                           size_t icmpv6_size)
{
    uint16_t opt_offset = 0;
    uint8_t *buf = ((uint8_t *)nbr_sol) + sizeof(ng_ndp_nbr_sol_t);
    ng_ipv6_addr_t *tgt;
    int sicmpv6_size = (int)icmpv6_size;

    DEBUG("ndp: received neighbor solicitation (src: %s, ",
          ng_ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str)));
    DEBUG("dst: %s, ",
          ng_ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str)));
    DEBUG("tgt: %s)\n",
          ng_ipv6_addr_to_str(addr_str, &nbr_sol->tgt, sizeof(addr_str)));

    /* check validity */
    if ((ipv6->hl != 255) || (nbr_sol->code != 0) ||
        (icmpv6_size < sizeof(ng_ndp_nbr_sol_t)) ||
        ng_ipv6_addr_is_multicast(&nbr_sol->tgt) ||
        (ng_ipv6_addr_is_unspecified(&ipv6->src) &&
         ng_ipv6_addr_is_solicited_node(&ipv6->dst))) {
        DEBUG("ndp: neighbor solicitation was invalid.\n");
        /* ipv6 releases */
        return;
    }

    if ((tgt = ng_ipv6_netif_find_addr(iface, &nbr_sol->tgt)) == NULL) {
        DEBUG("ndp: Target address is not to interface %" PRIkernel_pid "\n",
              iface);
        /* ipv6 releases */
        return;
    }

    sicmpv6_size -= sizeof(ng_ndp_nbr_sol_t);

    while (sicmpv6_size > 0) {
        ng_ndp_opt_t *opt = (ng_ndp_opt_t *)(buf + opt_offset);

        switch (opt->type) {
            case NG_NDP_OPT_SL2A:
                if (!_handle_sl2a_opt(iface, pkt, ipv6, nbr_sol->type, opt)) {
                    /* invalid source link-layer address option */
                    return;
                }

                break;

            default:
                /* silently discard all other options */
                break;
        }

        opt_offset += (opt->len * 8);
        sicmpv6_size -= (opt->len * 8);
    }

    _send_nbr_adv(iface, tgt, &ipv6->src,
                  ng_ipv6_addr_is_multicast(&ipv6->dst));

    return;
}
Beispiel #25
0
kernel_pid_t ng_ndp_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len,
                                    kernel_pid_t iface, ng_ipv6_addr_t *dst,
                                    ng_pktsnip_t *pkt)
{
    ng_ipv6_addr_t *next_hop_ip = NULL, *prefix = NULL;

#ifdef MODULE_NG_IPV6_EXT_RH
    next_hop_ip = ng_ipv6_ext_rh_next_hop(hdr);
#endif
#ifdef MODULE_FIB
    size_t next_hop_size = sizeof(ng_ipv6_addr_t);
    uint32_t next_hop_flags = 0;
    ng_ipv6_addr_t next_hop_actual; /* FIB copies address into this variable */

    if ((next_hop_ip == NULL) &&
        (fib_get_next_hop(&iface, next_hop_actual.u8, &next_hop_size,
                          &next_hop_flags, (uint8_t *)dst,
                          sizeof(ng_ipv6_addr_t), 0) >= 0) &&
        (next_hop_size == sizeof(ng_ipv6_addr_t))) {
        next_hop_ip = &next_hop_actual;
    }

#endif

    if (next_hop_ip == NULL) {            /* no route to host */
        if (iface == KERNEL_PID_UNDEF) {
            /* ng_ipv6_netif_t doubles as prefix list */
            iface = ng_ipv6_netif_find_by_prefix(&prefix, dst);
        }
        else {
            /* ng_ipv6_netif_t doubles as prefix list */
            prefix = ng_ipv6_netif_match_prefix(iface, dst);
        }

        if ((prefix != NULL) &&             /* prefix is on-link */
            (ng_ipv6_netif_addr_get(prefix)->flags &
             NG_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK)) {
            next_hop_ip = dst;
#ifdef MODULE_FIB
            /* We don't care if FIB is full, this is just for efficiency
             * for later sends */
            fib_add_entry(iface, (uint8_t *)dst, sizeof(ng_ipv6_addr_t), 0,
                          (uint8_t *)next_hop_ip, sizeof(ng_ipv6_addr_t), 0,
                          FIB_LIFETIME_NO_EXPIRE);
#endif
        }
    }

    if (next_hop_ip == NULL) {
        next_hop_ip = _default_router();
#ifdef MODULE_FIB
        /* We don't care if FIB is full, this is just for efficiency for later
         * sends */
        fib_add_entry(iface, (uint8_t *)dst, sizeof(ng_ipv6_addr_t), 0,
                      (uint8_t *)next_hop_ip, sizeof(ng_ipv6_addr_t), 0,
                      FIB_LIFETIME_NO_EXPIRE);
#endif
    }

    if (next_hop_ip != NULL) {
        ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, next_hop_ip);

        if ((nc_entry != NULL) && ng_ipv6_nc_is_reachable(nc_entry)) {
            DEBUG("ndp: found reachable neighbor (%s => ",
                  ng_ipv6_addr_to_str(addr_str, &nc_entry->ipv6_addr, sizeof(addr_str)));
            DEBUG("%s)\n",
                  ng_netif_addr_to_str(addr_str, sizeof(addr_str),
                                       nc_entry->l2_addr, nc_entry->l2_addr_len));

            if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_STALE) {
                _set_state(nc_entry, NG_IPV6_NC_STATE_DELAY);
            }

            memcpy(l2addr, nc_entry->l2_addr, nc_entry->l2_addr_len);
            *l2addr_len = nc_entry->l2_addr_len;
            /* TODO: unreachability check */
            return nc_entry->iface;
        }
        else if (nc_entry == NULL) {
            ng_pktqueue_t *pkt_node;
            ng_ipv6_addr_t dst_sol;

            nc_entry = ng_ipv6_nc_add(iface, next_hop_ip, NULL, 0,
                                      NG_IPV6_NC_STATE_INCOMPLETE << NG_IPV6_NC_STATE_POS);

            if (nc_entry == NULL) {
                DEBUG("ndp: could not create neighbor cache entry\n");
                return KERNEL_PID_UNDEF;
            }

            pkt_node = _alloc_pkt_node(pkt);

            if (pkt_node == NULL) {
                DEBUG("ndp: could not add packet to packet queue\n");
            }
            else {
                /* prevent packet from being released by IPv6 */
                ng_pktbuf_hold(pkt_node->pkt, 1);
                ng_pktqueue_add(&nc_entry->pkts, pkt_node);
            }

            /* address resolution */
            ng_ipv6_addr_set_solicited_nodes(&dst_sol, next_hop_ip);

            if (iface == KERNEL_PID_UNDEF) {
                timex_t t = { 0, NG_NDP_RETRANS_TIMER };
                kernel_pid_t ifs[NG_NETIF_NUMOF];
                size_t ifnum = ng_netif_get(ifs);

                for (size_t i = 0; i < ifnum; i++) {
                    _send_nbr_sol(ifs[i], next_hop_ip, &dst_sol);
                }

                vtimer_remove(&nc_entry->nbr_sol_timer);
                vtimer_set_msg(&nc_entry->nbr_sol_timer, t, ng_ipv6_pid,
                               NG_NDP_MSG_NBR_SOL_RETRANS, nc_entry);
            }
            else {
                ng_ipv6_netif_t *ipv6_iface = ng_ipv6_netif_get(iface);

                _send_nbr_sol(iface, next_hop_ip, &dst_sol);

                mutex_lock(&ipv6_iface->mutex);
                vtimer_remove(&nc_entry->nbr_sol_timer);
                vtimer_set_msg(&nc_entry->nbr_sol_timer,
                               ipv6_iface->retrans_timer, ng_ipv6_pid,
                               NG_NDP_MSG_NBR_SOL_RETRANS, nc_entry);
                mutex_unlock(&ipv6_iface->mutex);
            }
        }
    }

    return KERNEL_PID_UNDEF;
}
Beispiel #26
0
static int _fill_ipv6_hdr(kernel_pid_t iface, ng_pktsnip_t *ipv6,
                          ng_pktsnip_t *payload)
{
    int res;
    ng_ipv6_hdr_t *hdr = ipv6->data;

    hdr->len = byteorder_htons(ng_pkt_len(payload));
    DEBUG("ipv6: set payload length to %zu (network byteorder %04" PRIx16 ")\n",
          ng_pkt_len(payload), hdr->len.u16);

    /* check if e.g. extension header was not already marked */
    if (hdr->nh == NG_PROTNUM_RESERVED) {
        hdr->nh = ng_nettype_to_protnum(payload->type);

        /* if still reserved: mark no next header */
        if (hdr->nh == NG_PROTNUM_RESERVED) {
            hdr->nh = NG_PROTNUM_IPV6_NONXT;
        }
    }

    DEBUG("ipv6: set next header to %" PRIu8 "\n", hdr->nh);

    if (hdr->hl == 0) {
        hdr->hl = ng_ipv6_netif_get(iface)->cur_hl;
    }

    if (ng_ipv6_addr_is_unspecified(&hdr->src)) {
        ng_ipv6_addr_t *src = ng_ipv6_netif_find_best_src_addr(iface, &hdr->dst);

        if (src != NULL) {
            DEBUG("ipv6: set packet source to %s\n",
                  ng_ipv6_addr_to_str(addr_str, src, sizeof(addr_str)));
            memcpy(&hdr->src, src, sizeof(ng_ipv6_addr_t));
        }

        /* Otherwise leave unspecified */
    }

    DEBUG("ipv6: calculate checksum for upper header.\n");

#if NG_NETIF_NUMOF > 1
    if (payload->users > 1) {
        ng_pktsnip_t *ptr = ipv6;

        /* We deal with multiple interfaces here (multicast) => possible
         * different source addresses => duplication of payload needed */
        while (ptr != payload->next) {
            ng_pktsnip_t *old = ptr->next;
            /* duplicate everything including payload */
            ptr->next = ng_pktbuf_start_write(ptr->next);

            if (ptr->next == NULL) {
                DEBUG("ipv6: unable to get write access to payload, drop it\n");
                return -ENOBUFS;
            }

            ptr = old;
        }
    }
#endif /* NG_NETIF_NUMOF */

    if ((res = ng_netreg_calc_csum(payload, ipv6)) < 0) {
        if (res != -ENOENT) {   /* if there is no checksum we are okay */
            DEBUG("ipv6: checksum calculation failed.\n");
            return res;
        }
    }

    return 0;
}
Beispiel #27
0
static void _send_nbr_adv(kernel_pid_t iface, ng_ipv6_addr_t *tgt,
                          ng_ipv6_addr_t *dst, bool supply_tl2a)
{
    ng_pktsnip_t *hdr, *pkt = NULL;
    uint8_t adv_flags = 0;

    DEBUG("ndp: send neighbor advertisement (iface: %" PRIkernel_pid ", tgt: %s, ",
          iface, ng_ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str)));
    DEBUG("dst: %s, supply_tl2a: %d)\n",
          ng_ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), supply_tl2a);

    if (ng_ipv6_netif_get(iface)->flags & NG_IPV6_NETIF_FLAGS_ROUTER) {
        adv_flags |= NG_NDP_NBR_ADV_FLAGS_R;
    }

    if (ng_ipv6_addr_is_unspecified(dst)) {
        ng_ipv6_addr_set_all_nodes_multicast(dst,
                                             NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL);
    }
    else {
        adv_flags |= NG_NDP_NBR_ADV_FLAGS_S;
    }

    if (supply_tl2a) {
        uint8_t l2src[8];
        uint16_t l2src_len;
        /* we previously checked if we are the target, so we can take our L2src */
        l2src_len = _get_l2src(l2src, sizeof(l2src), iface);

        if (l2src_len > 0) {
            /* add target address link-layer address option */
            pkt = ng_ndp_opt_tl2a_build(l2src, l2src_len, NULL);

            if (pkt == NULL) {
                DEBUG("ndp: error allocating Target Link-layer address option.\n");
                ng_pktbuf_release(pkt);
                return;
            }
        }
    }

    /* TODO: also check if the node provides proxy servies for tgt */
    if ((pkt != NULL) && !ng_ipv6_netif_addr_is_non_unicast(tgt)) {
        /* TL2A is not supplied and tgt is not anycast */
        adv_flags |= NG_NDP_NBR_ADV_FLAGS_O;
    }

    hdr = ng_ndp_nbr_adv_build(adv_flags, tgt, pkt);

    if (hdr == NULL) {
        DEBUG("ndp: error allocating Neighbor advertisement.\n");
        ng_pktbuf_release(pkt);
        return;
    }

    pkt = hdr;
    hdr = ng_ipv6_hdr_build(pkt, NULL, 0, (uint8_t *)dst,
                            sizeof(ng_ipv6_addr_t));

    if (hdr == NULL) {
        DEBUG("ndp: error allocating IPv6 header.\n");
        ng_pktbuf_release(pkt);
        return;
    }

    ((ng_ipv6_hdr_t *)hdr->data)->hl = 255;

    pkt = hdr;
    /* add netif header for send interface specification */
    hdr = ng_netif_hdr_build(NULL, 0, NULL, 0);

    if (hdr == NULL) {
        DEBUG("ndp: error allocating netif header.\n");
        return;
    }

    ((ng_netif_hdr_t *)hdr->data)->if_pid = iface;

    LL_PREPEND(pkt, hdr);

    if (ng_ipv6_netif_addr_is_non_unicast(tgt)) {
        /* avoid collision for anycast addresses
         * (see https://tools.ietf.org/html/rfc4861#section-7.2.7) */
        timex_t delay = { _rand(0, NG_NDP_MAX_AC_TGT_DELAY), 0 };
        ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, tgt);
        DEBUG("ndp: delay neighbor advertisement for %" PRIu32 " sec.",
              delay.seconds);

        /* nc_entry must be set so no need to check it */
        _send_delayed(&nc_entry->nbr_adv_timer, delay, pkt);
    }
    else {
        ng_netapi_send(ng_ipv6_pid, pkt);
    }
}
Beispiel #28
0
static void _receive(ng_pktsnip_t *pkt)
{
    kernel_pid_t iface = KERNEL_PID_UNDEF;
    ng_pktsnip_t *ipv6, *netif;
    ng_ipv6_hdr_t *hdr;

    LL_SEARCH_SCALAR(pkt, netif, type, NG_NETTYPE_NETIF);

    if (netif != NULL) {
        iface = ((ng_netif_hdr_t *)netif->data)->if_pid;
    }

    if ((pkt->next != NULL) && (pkt->next->type == NG_NETTYPE_IPV6) &&
        (pkt->next->size == sizeof(ng_ipv6_hdr_t))) {
        /* IP header was already marked. Take it. */
        ipv6 = pkt->next;

        if (!ng_ipv6_hdr_is(ipv6->data)) {
            DEBUG("ipv6: Received packet was not IPv6, dropping packet\n");
            ng_pktbuf_release(pkt);
            return;
        }
    }
    else {
        if (!ng_ipv6_hdr_is(pkt->data)) {
            DEBUG("ipv6: Received packet was not IPv6, dropping packet\n");
            ng_pktbuf_release(pkt);
            return;
        }

        /* seize ipv6 as a temporary variable */
        ipv6 = ng_pktbuf_start_write(pkt);

        if (ipv6 == NULL) {
            DEBUG("ipv6: unable to get write access to packet, drop it\n");
            ng_pktbuf_release(pkt);
            return;
        }

        pkt = ipv6;     /* reset pkt from temporary variable */

        ipv6 = ng_pktbuf_add(pkt, pkt->data, sizeof(ng_ipv6_hdr_t),
                             NG_NETTYPE_IPV6);

        if (ipv6 == NULL) {
            DEBUG("ipv6: error marking IPv6 header, dropping packet\n");
            ng_pktbuf_release(pkt);
            return;
        }
    }

    /* extract header */
    hdr = (ng_ipv6_hdr_t *)ipv6->data;

    DEBUG("ipv6: Received (src = %s, ",
          ng_ipv6_addr_to_str(addr_str, &(hdr->src), sizeof(addr_str)));
    DEBUG("dst = %s, next header = %" PRIu8 ", length = %" PRIu16 ")\n",
          ng_ipv6_addr_to_str(addr_str, &(hdr->dst), sizeof(addr_str)),
          hdr->nh, byteorder_ntohs(hdr->len));

    if (_pkt_not_for_me(&iface, hdr)) { /* if packet is not for me */
        DEBUG("ipv6: packet destination not this host\n");

#ifdef MODULE_NG_IPV6_ROUTER    /* only routers redirect */
        /* redirect to next hop */
        DEBUG("ipv6: decrement hop limit to %" PRIu8 "\n", hdr->hl - 1);

        /* TODO: check if receiving interface is router */
        if (--(hdr->hl) > 0) {  /* drop packets that *reach* Hop Limit 0 */
            ng_pktsnip_t *tmp = pkt;

            DEBUG("ipv6: forward packet to next hop\n");

            /* pkt might not be writable yet, if header was given above */
            pkt = ng_pktbuf_start_write(tmp);
            ipv6 = ng_pktbuf_start_write(ipv6);

            if ((ipv6 == NULL) || (pkt == NULL)) {
                DEBUG("ipv6: unable to get write access to packet: dropping it\n");
                ng_pktbuf_release(tmp);
                return;
            }

            ng_pktbuf_release(ipv6->next);  /* remove headers around IPV6 */
            ipv6->next = pkt;           /* reorder for sending */
            pkt->next = NULL;
            _send(ipv6, false);
        }
        else {
            DEBUG("ipv6: hop limit reached 0: drop packet\n");
            ng_pktbuf_release(pkt);
            return;
        }

#else  /* MODULE_NG_IPV6_ROUTER */
        DEBUG("ipv6: dropping packet\n");
        /* non rounting hosts just drop the packet */
        ng_pktbuf_release(pkt);
        return;
#endif /* MODULE_NG_IPV6_ROUTER */
    }

    /* IPv6 internal demuxing (ICMPv6, Extension headers etc.) */
    ng_ipv6_demux(iface, pkt, hdr->nh);
}
Beispiel #29
0
static void _set_state(ng_ipv6_nc_t *nc_entry, uint8_t state)
{
    ng_ipv6_netif_t *ipv6_iface;
    timex_t t = { NG_NDP_FIRST_PROBE_DELAY, 0 };

    nc_entry->flags &= ~NG_IPV6_NC_STATE_MASK;
    nc_entry->flags |= state;

    DEBUG("ndp: set %s state to ",
          ng_ipv6_addr_to_str(addr_str, &nc_entry->ipv6_addr, sizeof(addr_str)));

    switch (state) {
        case NG_IPV6_NC_STATE_REACHABLE:
            ipv6_iface = ng_ipv6_netif_get(nc_entry->iface);
            DEBUG("REACHABLE (reachable time = %" PRIu32 ".%06" PRIu32 ")\n",
                  ipv6_iface->reach_time.seconds,
                  ipv6_iface->reach_time.microseconds);
            t = ipv6_iface->reach_time;
            /* we intentionally fall through here to set the desired timeout t */
        case NG_IPV6_NC_STATE_DELAY:
#if ENABLE_DEBUG
            if (state == NG_IPV6_NC_STATE_DELAY) {
                DEBUG("DELAY (probe with unicast NS in %u seconds)\n",
                      NG_NDP_FIRST_PROBE_DELAY);
            }
#endif
            vtimer_remove(&nc_entry->nbr_sol_timer);
            vtimer_set_msg(&nc_entry->nbr_sol_timer, t, ng_ipv6_pid,
                           NG_NDP_MSG_NC_STATE_TIMEOUT, nc_entry);
            break;

        case NG_IPV6_NC_STATE_PROBE:
            ipv6_iface = ng_ipv6_netif_get(nc_entry->iface);

            nc_entry->probes_remaining = NG_NDP_MAX_UC_NBR_SOL_NUMOF;
            DEBUG("PROBE (probe with %" PRIu8 " unicast NS every %" PRIu32
                  ".%06" PRIu32 " seconds)\n", nc_entry->probes_remaining,
                  ipv6_iface->retrans_timer.seconds,
                  ipv6_iface->retrans_timer.microseconds);

            _send_nbr_sol(nc_entry->iface, &nc_entry->ipv6_addr,
                          &nc_entry->ipv6_addr);

            mutex_lock(&ipv6_iface->mutex);
            vtimer_remove(&nc_entry->nbr_sol_timer);
            vtimer_set_msg(&nc_entry->nbr_sol_timer,
                           ipv6_iface->retrans_timer, ng_ipv6_pid,
                           NG_NDP_MSG_NBR_SOL_RETRANS, nc_entry);
            mutex_unlock(&ipv6_iface->mutex);
            break;

#ifdef ENABLE_DEBUG
        case NG_IPV6_NC_STATE_STALE:
            DEBUG("STALE (go into DELAY on next packet)\n");
            break;
#endif

        default:
            DEBUG("errorneous or unknown\n");
            break;
    }
}
Beispiel #30
0
static void _send(ng_pktsnip_t *pkt, bool prep_hdr)
{
    kernel_pid_t iface = KERNEL_PID_UNDEF;
    ng_pktsnip_t *ipv6, *payload;
    ng_ipv6_hdr_t *hdr;
    ng_ipv6_nc_t *nc_entry;

    /* seize payload as temporary variable */
    payload = ng_pktbuf_start_write(pkt);

    if (payload == NULL) {
        DEBUG("ipv6: unable to get write access to packet, dropping packet\n");
        ng_pktbuf_release(pkt);
        return;
    }

    pkt = payload;  /* Reset pkt from temporary variable */

    /* get IPv6 snip and (if present) generic interface header */
    if (pkt->type == NG_NETTYPE_NETIF) {
        /* If there is already a netif header (routing protocols and
         * neighbor discovery might add them to preset sending interface) */
        iface = ((ng_netif_hdr_t *)pkt->data)->if_pid;
        ipv6 = pkt->next;
    }
    else {
        ipv6 = pkt;
    }

    hdr = ipv6->data;
    payload = ipv6->next;       /* TODO: parse extension headers */

    if (ng_ipv6_addr_is_multicast(&hdr->dst)) {
        _send_multicast(iface, pkt, ipv6, payload, prep_hdr);
    }
    else {
        ng_ipv6_addr_t *next_hop = NULL;

        next_hop = &hdr->dst;   /* TODO: next hop determination */

        if ((nc_entry = ng_ipv6_nc_get_reachable(iface, next_hop)) == NULL) {
            DEBUG("ipv6: No link layer address for next_hop %s found.\n",
                  ng_ipv6_addr_to_str(addr_str, next_hop, sizeof(addr_str)));
            ng_pktbuf_release(pkt);
            return;
        }
        else {
            iface = nc_entry->iface;
        }

        if (iface == KERNEL_PID_UNDEF) {
            DEBUG("ipv6: no interface for %s registered, dropping packet\n",
                  ng_ipv6_addr_to_str(addr_str, next_hop, sizeof(addr_str)));
            ng_pktbuf_release(pkt);
            return;
        }

        if (prep_hdr) {
            if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) {
                /* error on filling up header */
                ng_pktbuf_release(pkt);
                return;
            }
        }

        _send_unicast(iface, nc_entry->l2_addr, nc_entry->l2_addr_len, pkt);
    }
}