Exemplo n.º 1
0
static void _add_prefix(kernel_pid_t iface, gnrc_sixlowpan_nd_router_abr_t *abr,
                        ndp_opt_pi_t *pi_opt)
{
    gnrc_sixlowpan_nd_router_prf_t *prf_ent;
    gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface);
    ipv6_addr_t *prefix;

    if ((pi_opt->len != NDP_OPT_PI_LEN) || ipv6_addr_is_link_local(&pi_opt->prefix) ||
        (pi_opt->flags & NDP_OPT_PI_FLAGS_A) ||
        (pi_opt->flags & NDP_OPT_PI_FLAGS_L) ||
        (pi_opt->valid_ltime.u32 == 0)) {
        return;
    }

    prefix = gnrc_ipv6_netif_match_prefix(iface, &pi_opt->prefix);

    prf_ent = _get_free_prefix(&pi_opt->prefix, pi_opt->prefix_len);

    if (prf_ent != NULL) {
        prf_ent->iface = ipv6_iface;
        prf_ent->prefix = container_of(prefix, gnrc_ipv6_netif_addr_t, addr);
    }

    LL_PREPEND(abr->prfs, prf_ent);
}
Exemplo n.º 2
0
void _gnrc_rpl_send(gnrc_pktsnip_t *pkt, ipv6_addr_t *src, ipv6_addr_t *dst,
        ipv6_addr_t *dodag_id)
{
    gnrc_pktsnip_t *hdr;
    ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR, ll_addr;
    kernel_pid_t iface = gnrc_ipv6_netif_find_by_addr(NULL, &all_RPL_nodes);
    if (iface == KERNEL_PID_UNDEF) {
        DEBUG("RPL: no suitable interface found for this destination address\n");
        gnrc_pktbuf_release(pkt);
        return;
    }

    if (src == NULL) {
        ipv6_addr_t *tmp = NULL;
        if (dodag_id != NULL) {
            tmp = gnrc_ipv6_netif_match_prefix(iface, dodag_id);
        }
        else if (dodag_id == NULL) {
            tmp = gnrc_ipv6_netif_find_best_src_addr(iface, &all_RPL_nodes);
        }

        if (tmp == NULL) {
            DEBUG("RPL: no suitable src address found\n");
            gnrc_pktbuf_release(pkt);
            return;
        }

        memcpy(&ll_addr, tmp, sizeof(ll_addr));
        ipv6_addr_set_link_local_prefix(&ll_addr);
        src = &ll_addr;
    }

    if (dst == NULL) {
        dst = &all_RPL_nodes;
    }

    hdr = gnrc_ipv6_hdr_build(pkt, (uint8_t *)src, sizeof(ipv6_addr_t), (uint8_t *)dst,
                            sizeof(ipv6_addr_t));

    if (hdr == NULL) {
        DEBUG("RPL: Send - no space left in packet buffer\n");
        gnrc_pktbuf_release(pkt);
        return;
    }

    if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL,hdr)) {
        DEBUG("RPL: cannot send packet: no subscribers found.\n");
        gnrc_pktbuf_release(hdr);
    }

}
void gnrc_rpl_send(gnrc_pktsnip_t *pkt, kernel_pid_t iface, ipv6_addr_t *src, ipv6_addr_t *dst,
                   ipv6_addr_t *dodag_id)
{
    (void)dodag_id;
    gnrc_pktsnip_t *hdr;
    if (iface == KERNEL_PID_UNDEF) {
        if ((iface = gnrc_ipv6_netif_find_by_addr(NULL, &ipv6_addr_all_rpl_nodes))
            == KERNEL_PID_UNDEF) {
            DEBUG("RPL: no suitable interface found for this destination address\n");
            gnrc_pktbuf_release(pkt);
            return;
        }
    }

    if (src == NULL) {
        src = gnrc_ipv6_netif_match_prefix(iface, &ipv6_addr_link_local_prefix);

        if (src == NULL) {
            DEBUG("RPL: no suitable src address found\n");
            gnrc_pktbuf_release(pkt);
            return;
        }
    }

    if (dst == NULL) {
        dst = (ipv6_addr_t *) &ipv6_addr_all_rpl_nodes;
    }

    hdr = gnrc_ipv6_hdr_build(pkt, src, dst);

    if (hdr == NULL) {
        DEBUG("RPL: Send - no space left in packet buffer\n");
        gnrc_pktbuf_release(pkt);
        return;
    }

    pkt = hdr;

    hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
    ((gnrc_netif_hdr_t *)hdr->data)->if_pid = iface;
    LL_PREPEND(pkt, hdr);

    if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) {
        DEBUG("RPL: cannot send packet: no subscribers found.\n");
        gnrc_pktbuf_release(pkt);
    }
}
void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, kernel_pid_t iface, ipv6_addr_t *src, uint16_t len)
{
    gnrc_rpl_instance_t *inst = NULL;
    gnrc_rpl_dodag_t *dodag = NULL;

    if (!_gnrc_rpl_check_DIO_validity(dio, len)) {
        return;
    }

    len -= (sizeof(gnrc_rpl_dio_t) + sizeof(icmpv6_hdr_t));

    if (gnrc_rpl_instance_add(dio->instance_id, &inst)) {
        /* new instance and DODAG */

        if (byteorder_ntohs(dio->rank) == GNRC_RPL_INFINITE_RANK) {
            DEBUG("RPL: ignore INFINITE_RANK DIO when we are not yet part of this DODAG\n");
            gnrc_rpl_instance_remove(inst);
            return;
        }

        inst->mop = (dio->g_mop_prf >> GNRC_RPL_MOP_SHIFT) & GNRC_RPL_SHIFTED_MOP_MASK;
        inst->of = gnrc_rpl_get_of_for_ocp(GNRC_RPL_DEFAULT_OCP);

        if (iface == KERNEL_PID_UNDEF) {
            iface = gnrc_ipv6_netif_find_by_addr(NULL, &ipv6_addr_all_rpl_nodes);
            assert(iface != KERNEL_PID_UNDEF);
        }

        gnrc_rpl_dodag_init(inst, &dio->dodag_id, iface, NULL);

        dodag = &inst->dodag;

        DEBUG("RPL: Joined DODAG (%s).\n",
               ipv6_addr_to_str(addr_str, &dio->dodag_id, sizeof(addr_str)));

        gnrc_rpl_parent_t *parent = NULL;

        if (!gnrc_rpl_parent_add_by_addr(dodag, src, &parent) && (parent == NULL)) {
            DEBUG("RPL: Could not allocate new parent.\n");
            gnrc_rpl_instance_remove(inst);
            return;
        }

        dodag->version = dio->version_number;
        dodag->grounded = dio->g_mop_prf >> GNRC_RPL_GROUNDED_SHIFT;
        dodag->prf = dio->g_mop_prf & GNRC_RPL_PRF_MASK;

        parent->rank = byteorder_ntohs(dio->rank);

        uint32_t included_opts = 0;
        if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DIO, inst, (gnrc_rpl_opt_t *)(dio + 1), len,
                           src, &included_opts)) {
            DEBUG("RPL: Error encountered during DIO option parsing - remove DODAG\n");
            gnrc_rpl_instance_remove(inst);
            return;
        }

        if (!(included_opts & (((uint32_t) 1) << GNRC_RPL_OPT_DODAG_CONF))) {
#ifndef GNRC_RPL_DODAG_CONF_OPTIONAL_ON_JOIN
            DEBUG("RPL: DIO without DODAG_CONF option - remove DODAG and request new DIO\n");
            gnrc_rpl_instance_remove(inst);
            gnrc_rpl_send_DIS(NULL, src);
            return;
#else
            DEBUG("RPL: DIO without DODAG_CONF option - use default trickle parameters\n");
            gnrc_rpl_send_DIS(NULL, src);
#endif
        }

        /* if there was no netif_addr created manually or by a PIO, then leave this DODAG */
        if (!dodag->netif_addr) {
            ipv6_addr_t *configured_addr;

            if (!(configured_addr = gnrc_ipv6_netif_match_prefix(dodag->iface, &dodag->dodag_id))) {
                DEBUG("RPL: no IPv6 address configured to match the given dodag id: %s\n",
                      ipv6_addr_to_str(addr_str, &(dodag->dodag_id), sizeof(addr_str)));
                gnrc_rpl_instance_remove(inst);
                return;
            }

            if (!(dodag->netif_addr = gnrc_ipv6_netif_addr_get(configured_addr))) {
                DEBUG("RPL: no netif address found for %s\n",
                       ipv6_addr_to_str(addr_str, configured_addr, sizeof(addr_str)));
                gnrc_rpl_instance_remove(inst);
                return;
            }
        }

        gnrc_rpl_delay_dao(dodag);
        trickle_start(gnrc_rpl_pid, &dodag->trickle, GNRC_RPL_MSG_TYPE_TRICKLE_INTERVAL,
                      GNRC_RPL_MSG_TYPE_TRICKLE_CALLBACK, (1 << dodag->dio_min),
                      dodag->dio_interval_doubl, dodag->dio_redun);

        gnrc_rpl_parent_update(dodag, parent);
        return;
    }
    else if (inst == NULL) {