Exemple #1
0
static void set_interface_roles(void)
{
    kernel_pid_t ifs[GNRC_NETIF_NUMOF];
    size_t numof = gnrc_netif_get(ifs);

    for (size_t i = 0; i < numof && i < GNRC_NETIF_NUMOF; i++) {
        kernel_pid_t dev = ifs[i];
        int is_wired = gnrc_netapi_get(dev, NETOPT_IS_WIRED, 0, NULL, 0);
        if ((!gnrc_border_interface) && (is_wired == 1)) {
            ipv6_addr_t addr, defroute;
            gnrc_border_interface = dev;

            ipv6_addr_from_str(&addr, "fe80::2");
            gnrc_ipv6_netif_add_addr(dev, &addr, 64,
                                     GNRC_IPV6_NETIF_ADDR_FLAGS_UNICAST);

            ipv6_addr_from_str(&defroute, "::");
            ipv6_addr_from_str(&addr, "fe80::1");
            fib_add_entry(&gnrc_ipv6_fib_table, dev, defroute.u8, 16,
                    0x00, addr.u8, 16, 0,
                    (uint32_t)FIB_LIFETIME_NO_EXPIRE);
        }
        else if ((!gnrc_wireless_interface) && (is_wired != 1)) {
            gnrc_wireless_interface = dev;
        }

        if (gnrc_border_interface && gnrc_wireless_interface) {
            break;
        }
    }

    LOG_INFO("gnrc_uhcpc: Using %u as border interface and %u as wireless interface.\n", gnrc_border_interface, gnrc_wireless_interface);
}
Exemple #2
0
static void test_fib_15_get_lifetime(void)
{
    uint64_t lifetime, now;
    kernel_pid_t iface_id = 1;
    char addr_dst[] = "Test address151";
    char addr_nxt[] = "Test address152";
    size_t add_buf_size = 16;
    uint32_t addr_dst_flags = 0x77777777;
    uint32_t addr_nxt_flags = 0x77777777;

    TEST_ASSERT_EQUAL_INT(0, fib_add_entry(&test_fib_table,
                          iface_id, (uint8_t *)addr_dst, add_buf_size - 1,
                          addr_dst_flags, (uint8_t *)addr_nxt, add_buf_size - 1,
                          addr_nxt_flags, 1000));

    TEST_ASSERT_EQUAL_INT(0, fib_devel_get_lifetime(&test_fib_table, &lifetime,
                                                    (uint8_t *)addr_dst,
                                                    add_buf_size - 1));

    /* assuming some ms passed during these operations... */
    now = xtimer_now64();
    uint64_t cmp_lifetime = now + 900000lU;
    uint64_t cmp_max_lifetime = now + 1100000lU;

    TEST_ASSERT_EQUAL_INT(1, (lifetime > cmp_lifetime));
    /* make sure lifetime hasn't grown magically either */
    TEST_ASSERT_EQUAL_INT(1, (lifetime < cmp_max_lifetime));

    fib_deinit(&test_fib_table);
}
Exemple #3
0
static void test_fib_15_get_lifetime(void)
{
    timex_t lifetime, now;
    kernel_pid_t iface_id = 1;
    char addr_dst[] = "Test address151";
    char addr_nxt[] = "Test address152";
    size_t add_buf_size = 16;
    uint32_t addr_dst_flags = 0x77777777;
    uint32_t addr_nxt_flags = 0x77777777;

    TEST_ASSERT_EQUAL_INT(0, fib_add_entry(iface_id, (uint8_t *)addr_dst, add_buf_size - 1,
                          addr_dst_flags, (uint8_t *)addr_nxt, add_buf_size - 1,
                          addr_nxt_flags, 1000));

    TEST_ASSERT_EQUAL_INT(0, fib_devel_get_lifetime(&lifetime, (uint8_t *)addr_dst, add_buf_size - 1));

    /* assuming some ms passed during these operations... */
    vtimer_now(&now);
    timex_t cmp_lifetime = timex_add(now, timex_set(0, 900000));
    timex_t cmp_max_lifetime = timex_add(now, timex_set(1,1));
    TEST_ASSERT_EQUAL_INT(1, timex_cmp(lifetime, cmp_lifetime));
    /* make sure lifetime hasn't grown magically either */
    TEST_ASSERT_EQUAL_INT(-1, timex_cmp(lifetime, cmp_max_lifetime));

    fib_deinit();
}
Exemple #4
0
/*
* @brief filling the FIB with entries and adding an additional one (not fitting)
* It is expected to have 20 FIB entries and to receive FPC_ERROR on adding an additional one
*/
static void test_fib_10_add_exceed(void)
{
    size_t add_buf_size = 16; /* includes space for terminating \0 */
    char addr_dst[] = "Test address 98";
    char addr_nxt[] = "Test address 99";

    size_t entries = 20;
    _fill_FIB_unique(entries);

    TEST_ASSERT_EQUAL_INT(20, fib_get_num_used_entries());
    TEST_ASSERT_EQUAL_INT(40, universal_address_get_num_used_entries());

    int ret = fib_add_entry(42, (uint8_t *)addr_dst, add_buf_size - 1, 0x98,
                            (uint8_t *)addr_nxt, add_buf_size - 1, 0x99, 9999);

    TEST_ASSERT_EQUAL_INT(-ENOMEM, ret);
    TEST_ASSERT_EQUAL_INT(20, fib_get_num_used_entries());
    TEST_ASSERT_EQUAL_INT(40, universal_address_get_num_used_entries());

#if (TEST_FIB_SHOW_OUTPUT == 1)
    fib_print_fib_table();
    puts("");
    universal_address_print_table();
    puts("");
#endif
    fib_deinit();
}
Exemple #5
0
static void _fib_add(const char *dest, const char *next, kernel_pid_t pid, uint32_t lifetime)
{
    unsigned char *dst = (unsigned char *)dest;
    size_t dst_size = (strlen(dest));
    uint32_t dst_flags = 0xffff;
    unsigned char *nxt = (unsigned char *)next;
    size_t nxt_size = (strlen(next));
    uint32_t nxt_flags = 0xffff;

    /* determine destination address */
    if (inet_pton(AF_INET6, dest, tmp_ipv6_dst)) {
        dst = tmp_ipv6_dst;
        dst_size = IN6ADDRSZ;
        dst_flags = AF_INET6;
    }
    else if (inet_pton(AF_INET, dest, tmp_ipv4_dst)) {
        dst = tmp_ipv4_dst;
        dst_size = INADDRSZ;
        dst_flags = AF_INET;
    }

    /* determine next-hop address */
    if (inet_pton(AF_INET6, next, tmp_ipv6_nxt)) {
        nxt = tmp_ipv6_nxt;
        nxt_size = IN6ADDRSZ;
        nxt_flags = AF_INET6;
    }
    else if (inet_pton(AF_INET, next, tmp_ipv4_nxt)) {
        nxt = tmp_ipv4_nxt;
        nxt_size = INADDRSZ;
        nxt_flags = AF_INET;
    }

    fib_add_entry(pid, dst, dst_size, dst_flags, nxt, nxt_size, nxt_flags, lifetime);
}
Exemple #6
0
/*
* @brief testing receiving an destination address set matching a specific prefix
*/
static void test_fib_17_get_entry_set(void)
{
    size_t addr_buf_size = 16;
    char addr_dst[addr_buf_size];
    char addr_nxt[addr_buf_size];

    /* fill 20 addresses */
    for (size_t i = 0; i < 20; ++i) {
        /* construct "addresses" for the FIB */
        snprintf(addr_dst, addr_buf_size, "Test address %02d", (int)i);
        snprintf(addr_nxt, addr_buf_size, "Test address %02d", i % 11);
        fib_add_entry(42, (uint8_t *)addr_dst, addr_buf_size - 1, 0x0,
                      (uint8_t *)addr_nxt, addr_buf_size - 1, 0x0, 100000);
    }

    size_t arr_size = 20;
    fib_destination_set_entry_t arr_dst[arr_size];
    char prefix[addr_buf_size];
    memset(prefix,0, addr_buf_size);
    snprintf(prefix, addr_buf_size, "Test address 1");

    int ret = fib_get_destination_set((uint8_t *)prefix, addr_buf_size-1, &arr_dst[0], &arr_size);
    TEST_ASSERT_EQUAL_INT(0, ret);

    /* we should receive 10 entries 10 to 19 */
    TEST_ASSERT_EQUAL_INT(10, arr_size);
    arr_size = 20;

    memset(prefix,0, addr_buf_size);
    snprintf(prefix, addr_buf_size, "Test address 0");

    ret = fib_get_destination_set((uint8_t *)prefix, addr_buf_size-1, &arr_dst[0], &arr_size);
    TEST_ASSERT_EQUAL_INT(0, ret);

    /* we should receive 20 entries 0-19 */
    TEST_ASSERT_EQUAL_INT(20, arr_size);
    arr_size = 20;

    memset(prefix,0, addr_buf_size);
    snprintf(prefix, addr_buf_size, "Test address");

    ret = fib_get_destination_set((uint8_t *)prefix, addr_buf_size-1, &arr_dst[0], &arr_size);
    TEST_ASSERT_EQUAL_INT(0, ret);

    /* we should receive 20 entries 0-19 */
    TEST_ASSERT_EQUAL_INT(20, arr_size);

#if (TEST_FIB_SHOW_OUTPUT == 1)
    puts("");
    for(size_t i = 0; i < arr_size; ++i) {
        for( size_t j = 0; j < arr_dst[i].dest_size; ++j) {
            printf("%c", (char)arr_dst[i].dest[j]);
        }
        puts("");
    }
#endif

    fib_deinit();
}
Exemple #7
0
static void _fib_add(const char *dest, const char *next, kernel_pid_t pid, uint32_t lifetime)
{
    uint32_t prefix = 0;
    /* Get the prefix length */
    size_t i = 0;
    for (i = strlen(dest); i > 0; --i) {
        if (dest[i] == '/') {
           prefix = atoi(&dest[i+1]);
           break;
        }
        if (dest[i] == ':' || dest[i] == '.') {
           i = strlen(dest);
           break;
        }
    }

    size_t dst_size = (i+1);
    unsigned char dst_arr[dst_size];
    memset(dst_arr, 0, dst_size);
    memcpy(dst_arr, dest, i);
    unsigned char *dst = &dst_arr[0];
    uint32_t dst_flags = 0;

    unsigned char *nxt = (unsigned char *)next;
    size_t nxt_size = (strlen(next));
    uint32_t nxt_flags = 0;

    /* determine destination address */
    if (inet_pton(AF_INET6, (char*)dst, tmp_ipv6_dst)) {
        dst = tmp_ipv6_dst;
        dst_size = IN6ADDRSZ;
    }
    else if (inet_pton(AF_INET, dest, tmp_ipv4_dst)) {
        dst = tmp_ipv4_dst;
        dst_size = INADDRSZ;
    }

    /* determine next-hop address */
    if (inet_pton(AF_INET6, next, tmp_ipv6_nxt)) {
        nxt = tmp_ipv6_nxt;
        nxt_size = IN6ADDRSZ;
    }
    else if (inet_pton(AF_INET, next, tmp_ipv4_nxt)) {
        nxt = tmp_ipv4_nxt;
        nxt_size = INADDRSZ;
    }

    dst_flags |= (prefix << FIB_FLAG_NET_PREFIX_SHIFT);
    fib_add_entry(&gnrc_ipv6_fib_table, pid, dst, dst_size, dst_flags, nxt,
                  nxt_size, nxt_flags, lifetime);
}
Exemple #8
0
/*
* @brief helper to fill FIB with multiple used entries
* The modulus adjusts the number of reused addresses
*/
static void _fill_FIB_multiple(size_t entries, size_t modulus)
{
    size_t add_buf_size = 16;
    char addr_dst[add_buf_size];
    char addr_nxt[add_buf_size];
    uint32_t addr_dst_flags = 0x33333333;
    uint32_t addr_nxt_flags = 0x33333333;

    for (size_t i = 0; i < entries; ++i) {
        /* construct "addresses" for the FIB */
        snprintf(addr_dst, add_buf_size, "Test address %02d", (int)i);
        snprintf(addr_nxt, add_buf_size, "Test address %02d", i % modulus);
        fib_add_entry(42, (uint8_t *)addr_dst, add_buf_size - 1, addr_dst_flags,
                      (uint8_t *)addr_nxt, add_buf_size - 1, addr_nxt_flags, 10000);
    }
}
Exemple #9
0
/*
* @brief helper to fill FIB with unique entries
*/
static void _fill_FIB_unique(size_t entries)
{
    size_t add_buf_size = 16;
    char addr_dst[add_buf_size];
    char addr_nxt[add_buf_size];
    uint32_t addr_dst_flags = 0x77777777;
    uint32_t addr_nxt_flags = 0x77777777;

    for (size_t i = 0; i < entries; ++i) {
        /* construct "addresses" for the FIB */
        snprintf(addr_dst, add_buf_size, "Test address %02d", (int)i);
        snprintf(addr_nxt, add_buf_size, "Test address %02d", entries + i);
        /* the terminating \0 is unnecessary here */
        fib_add_entry(42, (uint8_t *)addr_dst, add_buf_size - 1, addr_dst_flags,
                      (uint8_t *)addr_nxt, add_buf_size - 1, addr_nxt_flags, 10000);
    }
}
Exemple #10
0
void gnrc_rpl_p2p_recv_DRO(gnrc_pktsnip_t *pkt, ipv6_addr_t *src)
{
    gnrc_pktsnip_t *icmpv6_snip = gnrc_pktbuf_mark(pkt, sizeof(icmpv6_hdr_t), GNRC_NETTYPE_ICMPV6);
    gnrc_pktsnip_t *dro_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_rpl_p2p_dro_t),
                                                GNRC_NETTYPE_UNDEF);
    gnrc_pktsnip_t *rdo_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_rpl_p2p_opt_rdo_t),
                                                GNRC_NETTYPE_UNDEF);
    gnrc_pktsnip_t *addr_snip = pkt;
    gnrc_rpl_instance_t *inst;
    gnrc_rpl_dodag_t *dodag;
    gnrc_rpl_p2p_ext_t *p2p_ext;
    gnrc_rpl_p2p_dro_t *dro;
    gnrc_rpl_p2p_opt_rdo_t *rdo;
    uint8_t *addr_vec;
    uint16_t flags;
    size_t addr_len;

    if (!rdo_snip || !dro_snip) {
        DEBUG("RPL-P2P: Error - No DRO or RDO received\n");
        gnrc_pktbuf_release(pkt);
        return;
    }

    dro = dro_snip->data;

    if ((inst = gnrc_rpl_instance_get(dro->instance_id)) == NULL) {
        DEBUG("RPL-P2P: Error - Instance (%d) does not exist\n", dro->instance_id);
        return;
    }

    dodag = &inst->dodag;

    if ((p2p_ext = gnrc_rpl_p2p_ext_get(dodag)) == NULL) {
        DEBUG("RPL-P2P: Error - No P2P-RPL DODAG extension found\n");
        return;
    }

    if (p2p_ext->for_me) {
        DEBUG("RPL-P2P: Ignore DRO\n");
        return;
    }

    flags = byteorder_ntohs(dro->flags_rev);
    p2p_ext->stop = (flags & (1 << GNRC_RPL_P2P_DRO_FLAGS_STOP)) >> GNRC_RPL_P2P_DRO_FLAGS_STOP;
    p2p_ext->dro_ack = (flags & (1 << GNRC_RPL_P2P_DRO_FLAGS_ACK)) >> GNRC_RPL_P2P_DRO_FLAGS_ACK;
    p2p_ext->dro_seq = (flags & (0x3 << GNRC_RPL_P2P_DRO_FLAGS_SEQ)) >> GNRC_RPL_P2P_DRO_FLAGS_SEQ;

    addr_len = sizeof(ipv6_addr_t) - p2p_ext->compr;
    ipv6_addr_t addr = p2p_ext->dodag->dodag_id;
    ipv6_addr_t *me = NULL;
    addr_vec = addr_snip->data;

    rdo = rdo_snip->data;

    if (rdo->lmn > 0) {
        rdo->lmn--;
        memcpy(&addr.u8[p2p_ext->compr], &addr_vec[addr_len * rdo->lmn], addr_len);
    }

    if (gnrc_ipv6_netif_find_by_addr(&me, &addr) == dodag->iface) {
        fib_add_entry(&gnrc_ipv6_fib_table, dodag->iface, p2p_ext->target.u8,
                      sizeof(ipv6_addr_t), 0x0, src->u8,
                      sizeof(ipv6_addr_t), FIB_FLAG_RPL_ROUTE,
                      p2p_ext->dodag->default_lifetime *
                      p2p_ext->dodag->lifetime_unit * MS_PER_SEC);

        if (p2p_ext->dodag->node_status != GNRC_RPL_ROOT_NODE) {
            if ((rdo_snip = gnrc_pktbuf_start_write(rdo_snip)) == NULL) {
                DEBUG("RPL-P2P: Error - Cannot allocate new RDO\n");
                return;
            }

            addr_snip->next = NULL;
            rdo_snip->next = addr_snip;
            dro_snip->next = rdo_snip;

            icmpv6_snip = gnrc_icmpv6_build(dro_snip, ICMPV6_RPL_CTRL, GNRC_RPL_P2P_ICMPV6_CODE_DRO,
                                            sizeof(icmpv6_hdr_t));
            if (icmpv6_snip == NULL) {
                DEBUG("RPL-P2P: cannot allocate ICMPv6 - no space left in packet buffer\n");
                gnrc_pktbuf_release(pkt);
                return;
            }

            gnrc_rpl_send(icmpv6_snip, p2p_ext->dodag->iface, NULL, NULL, &p2p_ext->dodag->dodag_id);
            return;
        }
    }

    gnrc_pktbuf_release(pkt);

    return;
}
Exemple #11
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;
}
/** @todo allow target prefixes in target options to be of variable length */
bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt, uint16_t len,
                    ipv6_addr_t *src)
{
    uint16_t l = 0;
    gnrc_rpl_opt_target_t *first_target = NULL;
    eui64_t iid;
    kernel_pid_t if_id = KERNEL_PID_UNDEF;

    if (!_gnrc_rpl_check_options_validity(msg_type, dodag, opt, len)) {
        return false;
    }

    while(l < len) {
        switch(opt->type) {
            case (GNRC_RPL_OPT_PAD1):
                DEBUG("RPL: PAD1 option parsed\n");
                l += 1;
                opt = (gnrc_rpl_opt_t *) (((uint8_t *) opt) + 1);
                continue;

            case (GNRC_RPL_OPT_PADN):
                DEBUG("RPL: PADN option parsed\n");
                break;

            case (GNRC_RPL_OPT_DODAG_CONF):
                DEBUG("RPL: DODAG CONF DIO option parsed\n");
                gnrc_rpl_opt_dodag_conf_t *dc = (gnrc_rpl_opt_dodag_conf_t *) opt;
                gnrc_rpl_of_t *of = gnrc_rpl_get_of_for_ocp(byteorder_ntohs(dc->ocp));
                if (of != NULL) {
                    dodag->instance->of = of;
                }
                else {
                    DEBUG("RPL: Unsupported OCP 0x%02x\n", byteorder_ntohs(dc->ocp));
                    dodag->instance->of = gnrc_rpl_get_of_for_ocp(GNRC_RPL_DEFAULT_OCP);
                }
                dodag->dio_interval_doubl = dc->dio_int_doubl;
                dodag->dio_min = dc->dio_int_min;
                dodag->dio_redun = dc->dio_redun;
                dodag->instance->max_rank_inc = byteorder_ntohs(dc->max_rank_inc);
                dodag->instance->min_hop_rank_inc = byteorder_ntohs(dc->min_hop_rank_inc);
                dodag->default_lifetime = dc->default_lifetime;
                dodag->lifetime_unit = byteorder_ntohs(dc->lifetime_unit);
                dodag->trickle.Imin = (1 << dodag->dio_min);
                dodag->trickle.Imax = dodag->dio_interval_doubl;
                dodag->trickle.k = dodag->dio_redun;
                break;

            case (GNRC_RPL_OPT_PREFIX_INFO):
                DEBUG("RPL: Prefix Information DIO option parsed\n");
                gnrc_rpl_opt_prefix_info_t *pi = (gnrc_rpl_opt_prefix_info_t *) opt;
                ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR;
                if_id = gnrc_ipv6_netif_find_by_addr(NULL, &all_RPL_nodes);
                /* check for the auto address-configuration flag */
                if ((gnrc_netapi_get(if_id, NETOPT_IPV6_IID, 0, &iid, sizeof(eui64_t)) < 0) &&
                        !(pi->LAR_flags & GNRC_RPL_PREFIX_AUTO_ADDRESS_BIT)) {
                    break;
                }
                ipv6_addr_set_aiid(&pi->prefix, iid.uint8);
                gnrc_ipv6_netif_add_addr(if_id, &pi->prefix, pi->prefix_len, 0);

                break;

            case (GNRC_RPL_OPT_TARGET):
                DEBUG("RPL: RPL TARGET DAO option parsed\n");
                if_id = gnrc_ipv6_netif_find_by_prefix(NULL, &dodag->dodag_id);
                if (if_id == KERNEL_PID_UNDEF) {
                    DEBUG("RPL: no interface found for the configured DODAG id\n");
                    return false;
                }

                gnrc_rpl_opt_target_t *target = (gnrc_rpl_opt_target_t *) opt;
                if (first_target == NULL) {
                    first_target = target;
                }

                fib_add_entry(gnrc_ipv6_fib_table, if_id, target->target.u8,
                              sizeof(ipv6_addr_t), AF_INET6, src->u8,
                              sizeof(ipv6_addr_t), AF_INET6,
                              (dodag->default_lifetime * dodag->lifetime_unit) *
                              SEC_IN_MS);
                break;

            case (GNRC_RPL_OPT_TRANSIT):
                DEBUG("RPL: RPL TRANSIT INFO DAO option parsed\n");
                gnrc_rpl_opt_transit_t *transit = (gnrc_rpl_opt_transit_t *) opt;
                if (first_target == NULL) {
                    DEBUG("RPL: Encountered a RPL TRANSIT DAO option without \
a preceding RPL TARGET DAO option\n");
                    break;
                }

                do {
                    fib_update_entry(gnrc_ipv6_fib_table, first_target->target.u8,
                                     sizeof(ipv6_addr_t), src->u8,
                                     sizeof(ipv6_addr_t), AF_INET6,
                            (transit->path_lifetime * dodag->lifetime_unit * SEC_IN_MS));
                    first_target = (gnrc_rpl_opt_target_t *) (((uint8_t *) (first_target)) +
                        sizeof(gnrc_rpl_opt_t) + first_target->length);
                }
                while (first_target->type == GNRC_RPL_OPT_TARGET);

                first_target = NULL;
                break;

        }
        l += opt->length + sizeof(gnrc_rpl_opt_t);
        opt = (gnrc_rpl_opt_t *) (((uint8_t *) (opt + 1)) + opt->length);
    }
Exemple #13
0
/**
 * This callback is called every time the _rreq_consumer finishes reading a
 * packet.
 * @param cont
 * @param dropped indicates wehther the packet has been dropped previously by
 *                another callback
 */
static enum rfc5444_result _cb_rrep_end_callback(
    struct rfc5444_reader_tlvblock_context *cont, bool dropped)
{
    (void) cont;

    VDEBUG("%s()\n", __func__);

    struct aodvv2_routing_entry_t *rt_entry;
#if ENABLE_DEBUG
    struct netaddr_str nbuf;
#endif
    timex_t now;

    /* Check if packet contains the required information */
    if (dropped) {
        DEBUG("\t Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if ((packet_data.origNode.addr._type == AF_UNSPEC)
        || !packet_data.origNode.seqnum) {
        DEBUG("\tERROR: missing OrigNode Address or SeqNum. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if ((packet_data.targNode.addr._type == AF_UNSPEC)
        || !packet_data.targNode.seqnum) {
        DEBUG("\tERROR: missing TargNode Address or SeqNum. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if ((_get_max_metric(packet_data.metricType) - _get_link_cost(packet_data.metricType))
        <= packet_data.targNode.metric) {
        DEBUG("\tMetric Limit reached. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }

    /* Update the cost of the route, since the packet has successfully traversed
     * one more hop. */
    packet_data.targNode.metric = _get_route_cost(packet_data.metricType,
                                                  packet_data.targNode.metric);
    vtimer_now(&now);
    packet_data.timestamp = now;

    /* for every relevant address (RteMsg.Addr) in the RteMsg, HandlingRtr
    searches its route table to see if there is a route table entry with the
    same MetricType of the RteMsg, matching RteMsg.Addr. */

    rt_entry = routingtable_get_entry(&packet_data.targNode.addr, packet_data.metricType);

    if (!rt_entry || (rt_entry->metricType != packet_data.metricType)) {
        /* CAUTION SUPER HACKY FIX FIXME ASAP
        problem: sometimes we get broadcasted RREQs from 2 hop neighbors and then
        AODVv2 gets super confused when they're not in the routing table and starts a
        Route discovery to find them and all hell breaks loose. let's see if we can fix
        this (horribly).

        (another fix would be to stop bouncing the RREP back to the sender and asking
        the routing table for the next hop (or just send towards TargNode and let the network stack figure out the rest?))
        TODO evaluate that
        */

        ipv6_addr_t sender_tmp;
        netaddr_to_ipv6_addr_t(&packet_data.sender, &sender_tmp);
        ndp_neighbor_cache_t *ndp_nc_entry = ndp_neighbor_cache_search(&sender_tmp);

        if (ndp_nc_entry == NULL) {
            DEBUG("OH NOES! No bidirectional link to sender. Dropping packet.\n");
            return RFC5444_DROP_PACKET;
        }
        /* HACKY FIX ENDS HERE */
        VDEBUG("\tCreating new Routing Table entry...\n");

        struct aodvv2_routing_entry_t *tmp_rt_entry = (struct aodvv2_routing_entry_t *)
                                                       malloc(sizeof(struct aodvv2_routing_entry_t));
        memset(tmp_rt_entry, 0, sizeof(*tmp_rt_entry));

        routingtable_fill_routing_entry_t_rrep(&packet_data, tmp_rt_entry);
        routingtable_add_entry(tmp_rt_entry);

        /* add entry to FIB */
        fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ipv6_addr_t), 0,
                      tmp_rt_entry->nextHopAddr._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t);

        free(tmp_rt_entry);
    }
    else {
        if (!routingtable_offers_improvement(rt_entry, &packet_data.targNode)) {
            DEBUG("\tPacket offers no improvement over known route. Dropping Packet.\n");
            return RFC5444_DROP_PACKET;
        }
        /* The incoming routing information is better than existing routing
         * table information and SHOULD be used to improve the route table. */
        VDEBUG("\tUpdating Routing Table entry...\n");
        routingtable_fill_routing_entry_t_rrep(&packet_data, rt_entry);

        /* update the FIB */
        fib_update_entry(rt_entry->addr._addr, sizeof(ipv6_addr_t), rt_entry->nextHopAddr._addr,
                         sizeof(ipv6_addr_t), 0, aodvv2_validity_t);
    }

    /* If HandlingRtr is RREQ_Gen then the RREP satisfies RREQ_Gen's
    earlier RREQ, and RREP processing is completed.  Any packets
    buffered for OrigNode should be transmitted. */
    if (clienttable_is_client(&packet_data.origNode.addr)) {
#if ENABLE_DEBUG
        static struct netaddr_str nbuf2;
#endif

        DEBUG("\t{%" PRIu32 ":%" PRIu32 "} %s:  This is my RREP (SeqNum: %d). We are done here, thanks %s!\n",
              now.seconds, now.microseconds, netaddr_to_string(&nbuf, &packet_data.origNode.addr),
              packet_data.origNode.seqnum, netaddr_to_string(&nbuf2, &packet_data.targNode.addr));
    }

    else {
        /* If HandlingRtr is not RREQ_Gen then the outgoing RREP is sent to the
         * Route.NextHopAddress for the RREP.AddrBlk[OrigNodeNdx]. */
        AODV_DEBUG("Not my RREP, passing it on to the next hop\n");
        aodv_send_rrep(&packet_data,
                       routingtable_get_next_hop(&packet_data.origNode.addr,packet_data.metricType));
    }
    return RFC5444_OKAY;
}
Exemple #14
0
/**
 * This callback is called every time the _rreq_consumer finishes reading a
 * packet.
 * @param cont
 * @param dropped indicates whether the packet has been dropped previously by
 *                another callback
 */
static enum rfc5444_result _cb_rreq_end_callback(
    struct rfc5444_reader_tlvblock_context *cont, bool dropped)
{
    (void) cont;

    struct aodvv2_routing_entry_t *rt_entry;
    timex_t now;

    /* Check if packet contains the required information */
    if (dropped) {
        DEBUG("\t Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if ((packet_data.origNode.addr._type == AF_UNSPEC) || !packet_data.origNode.seqnum) {
        DEBUG("\tERROR: missing OrigNode Address or SeqNum. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if (packet_data.targNode.addr._type == AF_UNSPEC) {
        DEBUG("\tERROR: missing TargNode Address. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if (packet_data.hoplimit == 0) {
        DEBUG("\tERROR: Hoplimit is 0. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }
    if ((_get_max_metric(packet_data.metricType) - _get_link_cost(packet_data.metricType))
        <= packet_data.origNode.metric) {
        DEBUG("\tMetric Limit reached. Dropping packet.\n");
        return RFC5444_DROP_PACKET;
    }

    /*
      The incoming RREQ MUST be checked against previously received
      information from the RREQ Table Section 7.6.  If the information
      in the incoming RteMsg is redundant, then then no further action
      is taken.
    */
    if (rreqtable_is_redundant(&packet_data)) {
        DEBUG("\tPacket is redundant. Dropping Packet. %i\n", RFC5444_DROP_PACKET);
        return RFC5444_DROP_PACKET;
    }

    /* Update the cost of the route, since the packet has successfully traversed
     * one more hop. */
    packet_data.origNode.metric = _get_route_cost(packet_data.metricType,
                                                  packet_data.origNode.metric);
    vtimer_now(&now);
    packet_data.timestamp = now;

    /* for every relevant
     * address (RteMsg.Addr) in the RteMsg, HandlingRtr searches its route
     * table to see if there is a route table entry with the same MetricType
     * of the RteMsg, matching RteMsg.Addr.
     */

    rt_entry = routingtable_get_entry(&packet_data.origNode.addr, packet_data.metricType);

    if (!rt_entry || (rt_entry->metricType != packet_data.metricType)) {
        /* CAUTION SUPER HACKY FIX FIXME ASAP
        problem: sometimes we get broadcasted RREQs from 2 hop neighbors and then
        AODVv2 gets super confused when they're not in the routing table and starts a
        Route discovery to find them and all hell breaks loose. let's see if we can fix
        this (horribly).

        (another fix would be to stop bouncing the RREP back to the sender and asking
        the routing table for the next hop (or just send towards TargNode and let the
        network stack figure out the rest?))
        TODO evaluate that
        */

        ipv6_addr_t sender_tmp;
        netaddr_to_ipv6_addr_t(&packet_data.sender, &sender_tmp);
        ndp_neighbor_cache_t *ndp_nc_entry = ndp_neighbor_cache_search(&sender_tmp);

        if (ndp_nc_entry == NULL) {
            DEBUG("OH NOES! No bidirectional link to sender. Dropping packet.\n");
            return RFC5444_DROP_PACKET;
        }
        /* HACKY FIX ENDS HERE */

        VDEBUG("\tCreating new Routing Table entry...\n");

        struct aodvv2_routing_entry_t *tmp_rt_entry = (struct aodvv2_routing_entry_t *)
                                                       malloc(sizeof(struct aodvv2_routing_entry_t));
        memset(tmp_rt_entry, 0, sizeof(*tmp_rt_entry));

        routingtable_fill_routing_entry_t_rreq(&packet_data, tmp_rt_entry);
        routingtable_add_entry(tmp_rt_entry);

        /* add entry to FIB */
        fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ipv6_addr_t), 0,
                      tmp_rt_entry->nextHopAddr._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t);

        free(tmp_rt_entry);
    }
    else {
        if (!routingtable_offers_improvement(rt_entry, &packet_data.origNode)) {
            DEBUG("\tPacket offers no improvement over known route. Dropping Packet.\n");
            return RFC5444_DROP_PACKET;
        }
        /* The incoming routing information is better than existing routing
         * table information and SHOULD be used to improve the route table. */
        VDEBUG("\tUpdating Routing Table entry...\n");
        routingtable_fill_routing_entry_t_rreq(&packet_data, rt_entry);

        /* update the FIB */
        fib_update_entry(rt_entry->addr._addr, sizeof(ipv6_addr_t), rt_entry->nextHopAddr._addr,
                         sizeof(ipv6_addr_t), 0, aodvv2_validity_t);
    }

    /*
     * If TargNode is a client of the router receiving the RREQ, then the
     * router generates a RREP message as specified in Section 7.4, and
     * subsequently processing for the RREQ is complete.  Otherwise,
     * processing continues as follows.
     */
    if (clienttable_is_client(&packet_data.targNode.addr)) {
        AODV_DEBUG("TargNode is in client list, sending RREP\n");

        /* make sure to start with a clean metric value */
        packet_data.targNode.metric = 0;
        aodv_send_rrep(&packet_data, &packet_data.sender);
    }
    else {
        AODV_DEBUG("I am not TargNode, forwarding RREQ\n");
        aodv_send_rreq(&packet_data);
    }
    return RFC5444_OKAY;
}
Exemple #15
0
/*
* @brief testing default gateway address
*/
static void test_fib_19_default_gateway(void)
{
    size_t add_buf_size = 16;
    char addr_dst[add_buf_size];
    char addr_nxt_hop[add_buf_size];
    char addr_nxt[add_buf_size];
    char addr_lookup[add_buf_size];
    kernel_pid_t iface_id = KERNEL_PID_UNDEF;
    uint32_t next_hop_flags = 0;

    memset(addr_dst, 0, add_buf_size);
    memset(addr_nxt, 0, add_buf_size);
    memset(addr_nxt_hop, 0, add_buf_size);
    memset(addr_lookup, 0, add_buf_size);

    snprintf(addr_lookup, add_buf_size, "Some address X1");

    /* set the bytes to 0x01..0x10 of the next-hop */
    for(size_t i = 0; i < add_buf_size; i++) {
        addr_nxt[i] = i+1;
    }

    /* add a default gateway entry */
    fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
                  add_buf_size, 0x123, (uint8_t *)addr_nxt, add_buf_size, 0x23,
                  100000);

    /* check if it matches all */
    int ret = fib_get_next_hop(&test_fib_table, &iface_id,
                               (uint8_t *)addr_nxt_hop, &add_buf_size,
                               &next_hop_flags, (uint8_t *)addr_lookup,
                               add_buf_size, 0x123);

    TEST_ASSERT_EQUAL_INT(0, ret);
    TEST_ASSERT_EQUAL_INT(0, memcmp(addr_nxt, addr_nxt_hop, add_buf_size));

    memset(addr_nxt_hop, 0, add_buf_size);

    /* set the bytes to 0x02..0x11 of the new next-hop for the default gateway */
    for(size_t i = 0; i < add_buf_size; ++i) {
        addr_nxt[i] = i+2;
    }

    /* change the default gateway entry */
    fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
                  add_buf_size, 0x123, (uint8_t *)addr_nxt, add_buf_size, 0x24,
                  100000);

    /* and check again if it matches all */
    ret = fib_get_next_hop(&test_fib_table, &iface_id,
                           (uint8_t *)addr_nxt_hop, &add_buf_size, &next_hop_flags,
                           (uint8_t *)addr_lookup, add_buf_size, 0x123);

    TEST_ASSERT_EQUAL_INT(0, ret);
    TEST_ASSERT_EQUAL_INT(0, memcmp(addr_nxt, addr_nxt_hop, add_buf_size));

#if (TEST_FIB_SHOW_OUTPUT == 1)
    fib_print_fib_table(&test_fib_table);
    puts("");
    universal_address_print_table();
    puts("");
#endif
    fib_deinit(&test_fib_table);
}
Exemple #16
0
/*
* @brief testing prefix with bits
*/
static void test_fib_16_prefix_match(void)
{
    size_t add_buf_size = 16;
    char addr_dst[add_buf_size];
    char addr_nxt[add_buf_size];
    char addr_lookup[add_buf_size];
    kernel_pid_t iface_id = KERNEL_PID_UNDEF;
    uint32_t next_hop_flags = 0;

    memset(addr_dst, 0, add_buf_size);
    memset(addr_nxt, 0, add_buf_size);
    memset(addr_lookup, 0, add_buf_size);

    snprintf(addr_dst, add_buf_size, "Test address 1X");
    snprintf(addr_nxt, add_buf_size, "Test address 99");
    snprintf(addr_lookup, add_buf_size, "Test address 1X");

    /* now we change the last byte of addr_dst to have defined trailing 0 bits */
    /* test success */
    addr_dst[14] = (char)0x80;    /* 1000 0000 */
    addr_lookup[14] = (char)0x87; /* 1000 0111 */

    fib_add_entry(42, (uint8_t *)addr_dst, add_buf_size - 1, 0x123,
                  (uint8_t *)addr_nxt, add_buf_size - 1, 0x23, 100000);

    addr_dst[14] = (char)0x3c;    /* 0011 1100 */
    fib_add_entry(42, (uint8_t *)addr_dst, add_buf_size - 1, 0x123,
                  (uint8_t *)addr_nxt, add_buf_size - 1, 0x23, 100000);

    memset(addr_nxt, 0, add_buf_size);

    int ret = fib_get_next_hop(&iface_id,
                             (uint8_t *)addr_nxt, &add_buf_size, &next_hop_flags,
                             (uint8_t *)addr_lookup, add_buf_size - 1, 0x123);

    TEST_ASSERT_EQUAL_INT(0, ret);

    /* test fail */
    addr_dst[14] = (char)0x3c;    /* 0011 1100 */
    addr_lookup[14] = (char)0x34; /* 0011 0100 */
    add_buf_size = 16;

    fib_add_entry(42, (uint8_t *)addr_dst, add_buf_size - 1, 0x123,
                (uint8_t *)addr_nxt, add_buf_size - 1, 0x23, 100000);

    memset(addr_nxt, 0, add_buf_size);

    ret = fib_get_next_hop(&iface_id,
                             (uint8_t *)addr_nxt, &add_buf_size, &next_hop_flags,
                             (uint8_t *)addr_lookup, add_buf_size - 1, 0x123);

    TEST_ASSERT_EQUAL_INT(-EHOSTUNREACH, ret);

    /* test success (again) by adjusting the lsb */
    addr_lookup[14] = (char)0x3e; /* 0011 1110 */
    add_buf_size = 16;

    memset(addr_nxt, 0, add_buf_size);

    ret = fib_get_next_hop(&iface_id,
                             (uint8_t *)addr_nxt, &add_buf_size, &next_hop_flags,
                             (uint8_t *)addr_lookup, add_buf_size - 1, 0x123);

    TEST_ASSERT_EQUAL_INT(0, ret);

#if (TEST_FIB_SHOW_OUTPUT == 1)
    fib_print_fib_table();
    puts("");
    universal_address_print_table();
    puts("");
#endif
    fib_deinit();
}
Exemple #17
0
/*
* @brief testing prefix entry changing
*/
static void test_fib_20_replace_prefix(void)
{
    size_t add_buf_size = 16;
    char addr_dst[add_buf_size];
    char addr_nxt_hop[add_buf_size];
    char addr_nxt[add_buf_size];
    char addr_lookup[add_buf_size];
    kernel_pid_t iface_id = KERNEL_PID_UNDEF;
    uint32_t next_hop_flags = 0;

    memset(addr_dst, 0, add_buf_size);
    memset(addr_nxt, 0, add_buf_size);
    memset(addr_nxt_hop, 0, add_buf_size);
    memset(addr_lookup, 0, add_buf_size);

    /* set the bytes to 0x01..0x10 of the next-hop */
    for(size_t i = 0; i < add_buf_size; i++) {
        addr_nxt[i] = i+1;
    }

    /* set the bytes to 0x01..0x08 of the destination prefix */
    for(size_t i = 0; i < add_buf_size/2; i++) {
        addr_dst[i] = i+1;
    }

    /* set the bytes to 0x01..0x0e of the lookup address */
    for(size_t i = 0; i < 14; i++) {
        addr_lookup[i] = i+1;
    }

    /* add a prefix entry */
    fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
                  add_buf_size, 0x123, (uint8_t *)addr_nxt, add_buf_size, 0x23,
                  100000);

    /* check if it matches */
    int ret = fib_get_next_hop(&test_fib_table, &iface_id,
                               (uint8_t *)addr_nxt_hop, &add_buf_size,
                               &next_hop_flags, (uint8_t *)addr_lookup,
                               add_buf_size, 0x123);

    TEST_ASSERT_EQUAL_INT(0, ret);
    TEST_ASSERT_EQUAL_INT(0, memcmp(addr_nxt, addr_nxt_hop, add_buf_size));

    fib_remove_entry(&test_fib_table, (uint8_t *)addr_dst,
                     add_buf_size);

    memset(addr_nxt_hop, 0, add_buf_size);

    /* set the bytes to 0x02..0x11 of the new next-hop */
    for(size_t i = 0; i < add_buf_size; ++i) {
        addr_nxt[i] = i+2;
    }

    /* set the bytes to 0x01..0x0d of the new destination prefix */
    for(size_t i = 0; i < 13; i++) {
        addr_dst[i] = i+1;
    }

    /* change the prefix entry */
    fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
                  add_buf_size, 0x123, (uint8_t *)addr_nxt, add_buf_size, 0x24,
                  100000);

    /* and check again if it matches  */
    ret = fib_get_next_hop(&test_fib_table, &iface_id,
                           (uint8_t *)addr_nxt_hop, &add_buf_size, &next_hop_flags,
                           (uint8_t *)addr_lookup, add_buf_size, 0x123);

    TEST_ASSERT_EQUAL_INT(0, ret);
    TEST_ASSERT_EQUAL_INT(0, memcmp(addr_nxt, addr_nxt_hop, add_buf_size));

#if (TEST_FIB_SHOW_OUTPUT == 1)
    fib_print_fib_table(&test_fib_table);
    puts("");
    universal_address_print_table();
    puts("");
#endif
    fib_deinit(&test_fib_table);
}
Exemple #18
0
/*
* @brief testing prefix and exact match
* It is expected receive 23 for addr123 as exact match and
* 12 for addr124
*/
static void test_fib_14_exact_and_prefix_match(void)
{
    size_t add_buf_size = 16;
    char addr_dst[add_buf_size];
    char addr_nxt[add_buf_size];
    kernel_pid_t iface_id = KERNEL_PID_UNDEF;
    uint32_t next_hop_flags = 0;
    char addr_lookup[add_buf_size];
    memset(addr_dst, 0, add_buf_size);
    memset(addr_nxt, 0, add_buf_size);

    snprintf(addr_dst, add_buf_size, "Test addr12");
    snprintf(addr_nxt, add_buf_size, "Test address %02d", 12);
    fib_add_entry(42, (uint8_t *)addr_dst, add_buf_size - 1, 0x12,
                  (uint8_t *)addr_nxt, add_buf_size - 1, 0x12, 100000);

    snprintf(addr_dst, add_buf_size, "Test addr123");
    snprintf(addr_nxt, add_buf_size, "Test address %02d", 23);
    fib_add_entry(42, (uint8_t *)addr_dst, add_buf_size - 1, 0x123,
                  (uint8_t *)addr_nxt, add_buf_size - 1, 0x23, 100000);

    snprintf(addr_dst, add_buf_size, "Test addr1234");
    snprintf(addr_nxt, add_buf_size, "Test address %02d", 34);
    fib_add_entry(42, (uint8_t *)addr_dst, add_buf_size - 1, 0x1234,
                  (uint8_t *)addr_nxt, add_buf_size - 1, 0x34, 100000);

    memset(addr_lookup, 0, add_buf_size);
    /* exact match */
    snprintf(addr_lookup, add_buf_size, "Test addr123");
    int ret = fib_get_next_hop(&iface_id,
                               (uint8_t *)addr_nxt, &add_buf_size, &next_hop_flags,
                               (uint8_t *)addr_lookup, add_buf_size - 1, 0x123);

    TEST_ASSERT_EQUAL_INT(0, ret);
    add_buf_size = 16;

    char addr_expect_01[] = "Test address 23";
    ret = strncmp(addr_expect_01, addr_nxt, add_buf_size - 1);
    TEST_ASSERT_EQUAL_INT(0, ret);

    /* prefix match */
    add_buf_size = 16;
    memset(addr_nxt, 0, add_buf_size);
    memset(addr_lookup, 0, add_buf_size);

    /* cppcheck: addr_lookup is only passed but not required to be read,
    *            since we test prefix matching
    */
    /* cppcheck-suppress redundantCopy */
    snprintf(addr_lookup, add_buf_size, "Test addr124");
    ret = fib_get_next_hop(&iface_id,
                           (uint8_t *)addr_nxt, &add_buf_size, &next_hop_flags,
                           (uint8_t *)addr_lookup, add_buf_size - 1, 0x124);

    TEST_ASSERT_EQUAL_INT(0, ret);

    add_buf_size = 16;
    char addr_expect_02[] = "Test address 12";
    ret = strncmp(addr_expect_02, addr_nxt, add_buf_size);
    TEST_ASSERT_EQUAL_INT(0, ret);

#if (TEST_FIB_SHOW_OUTPUT == 1)
    fib_print_fib_table();
    puts("");
    universal_address_print_table();
    puts("");
#endif
    fib_deinit();
}
/** @todo allow target prefixes in target options to be of variable length */
bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt_t *opt, uint16_t len,
                    ipv6_addr_t *src, uint32_t *included_opts)
{
    uint16_t l = 0;
    gnrc_rpl_opt_target_t *first_target = NULL;
    gnrc_rpl_dodag_t *dodag = &inst->dodag;
    eui64_t iid;
    *included_opts = 0;
    ipv6_addr_t *me;

    if (!_gnrc_rpl_check_options_validity(msg_type, inst, opt, len)) {
        return false;
    }

    while(l < len) {
        switch(opt->type) {
            case (GNRC_RPL_OPT_PAD1):
                DEBUG("RPL: PAD1 option parsed\n");
                *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_PAD1;
                l += 1;
                opt = (gnrc_rpl_opt_t *) (((uint8_t *) opt) + 1);
                continue;

            case (GNRC_RPL_OPT_PADN):
                DEBUG("RPL: PADN option parsed\n");
                *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_PADN;
                break;

            case (GNRC_RPL_OPT_DODAG_CONF):
                DEBUG("RPL: DODAG CONF DIO option parsed\n");
                *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_DODAG_CONF;
                dodag->dio_opts |= GNRC_RPL_REQ_DIO_OPT_DODAG_CONF;
                gnrc_rpl_opt_dodag_conf_t *dc = (gnrc_rpl_opt_dodag_conf_t *) opt;
                gnrc_rpl_of_t *of = gnrc_rpl_get_of_for_ocp(byteorder_ntohs(dc->ocp));
                if (of != NULL) {
                    inst->of = of;
                }
                else {
                    DEBUG("RPL: Unsupported OCP 0x%02x\n", byteorder_ntohs(dc->ocp));
                    inst->of = gnrc_rpl_get_of_for_ocp(GNRC_RPL_DEFAULT_OCP);
                }
                dodag->dio_interval_doubl = dc->dio_int_doubl;
                dodag->dio_min = dc->dio_int_min;
                dodag->dio_redun = dc->dio_redun;
                inst->max_rank_inc = byteorder_ntohs(dc->max_rank_inc);
                inst->min_hop_rank_inc = byteorder_ntohs(dc->min_hop_rank_inc);
                dodag->default_lifetime = dc->default_lifetime;
                dodag->lifetime_unit = byteorder_ntohs(dc->lifetime_unit);
                dodag->trickle.Imin = (1 << dodag->dio_min);
                dodag->trickle.Imax = dodag->dio_interval_doubl;
                dodag->trickle.k = dodag->dio_redun;
                break;

            case (GNRC_RPL_OPT_PREFIX_INFO):
                DEBUG("RPL: Prefix Information DIO option parsed\n");
                *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_PREFIX_INFO;
#ifndef GNRC_RPL_WITHOUT_PIO
                dodag->dio_opts |= GNRC_RPL_REQ_DIO_OPT_PREFIX_INFO;
#endif
                gnrc_rpl_opt_prefix_info_t *pi = (gnrc_rpl_opt_prefix_info_t *) opt;
                /* check for the auto address-configuration flag */
                if ((gnrc_netapi_get(dodag->iface, NETOPT_IPV6_IID, 0, &iid, sizeof(eui64_t)) < 0)
                     && !(pi->LAR_flags & GNRC_RPL_PREFIX_AUTO_ADDRESS_BIT)) {
                    break;
                }
                ipv6_addr_set_aiid(&pi->prefix, iid.uint8);
                me = gnrc_ipv6_netif_add_addr(dodag->iface, &pi->prefix, pi->prefix_len, 0);
                if (me) {
                    dodag->netif_addr = gnrc_ipv6_netif_addr_get(me);
                }

                break;

            case (GNRC_RPL_OPT_TARGET):
                DEBUG("RPL: RPL TARGET DAO option parsed\n");
                *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_TARGET;

                gnrc_rpl_opt_target_t *target = (gnrc_rpl_opt_target_t *) opt;
                if (first_target == NULL) {
                    first_target = target;
                }

                uint32_t fib_dst_flags = 0;

                if (target->prefix_length < IPV6_ADDR_BIT_LEN) {
                    fib_dst_flags = ((uint32_t)(target->prefix_length) << FIB_FLAG_NET_PREFIX_SHIFT);
                }

                DEBUG("RPL: adding fib entry %s/%d 0x%" PRIx32 "\n",
                      ipv6_addr_to_str(addr_str, &(target->target), sizeof(addr_str)),
                      target->prefix_length,
                      fib_dst_flags);

                fib_add_entry(&gnrc_ipv6_fib_table, dodag->iface, target->target.u8,
                              sizeof(ipv6_addr_t), fib_dst_flags, src->u8,
                              sizeof(ipv6_addr_t), FIB_FLAG_RPL_ROUTE,
                              (dodag->default_lifetime * dodag->lifetime_unit) *
                              SEC_IN_MS);
                break;

            case (GNRC_RPL_OPT_TRANSIT):
                DEBUG("RPL: RPL TRANSIT INFO DAO option parsed\n");
                *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_TRANSIT;
                gnrc_rpl_opt_transit_t *transit = (gnrc_rpl_opt_transit_t *) opt;
                if (first_target == NULL) {
                    DEBUG("RPL: Encountered a RPL TRANSIT DAO option without "
                          "a preceding RPL TARGET DAO option\n");
                    break;
                }

                do {
                    DEBUG("RPL: updating fib entry %s/%d\n",
                          ipv6_addr_to_str(addr_str, &(first_target->target), sizeof(addr_str)),
                          first_target->prefix_length);

                    fib_update_entry(&gnrc_ipv6_fib_table,
                                     first_target->target.u8,
                                     sizeof(ipv6_addr_t), src->u8,
                                     sizeof(ipv6_addr_t),
                                     ((transit->e_flags & GNRC_RPL_OPT_TRANSIT_E_FLAG) ?
                                      0x0 : FIB_FLAG_RPL_ROUTE),
                                     (transit->path_lifetime *
                                      dodag->lifetime_unit * SEC_IN_MS));
                    first_target = (gnrc_rpl_opt_target_t *) (((uint8_t *) (first_target)) +
                                   sizeof(gnrc_rpl_opt_t) + first_target->length);
                }
                while (first_target->type == GNRC_RPL_OPT_TARGET);

                first_target = NULL;
                break;

#ifdef MODULE_GNRC_RPL_P2P
            case (GNRC_RPL_P2P_OPT_RDO):
                gnrc_rpl_p2p_rdo_parse((gnrc_rpl_p2p_opt_rdo_t *) opt, gnrc_rpl_p2p_ext_get(dodag));
                break;
#endif
        }
        l += opt->length + sizeof(gnrc_rpl_opt_t);
        opt = (gnrc_rpl_opt_t *) (((uint8_t *) (opt + 1)) + opt->length);
    }
    return true;
}