Пример #1
0
void gnrc_rpl_send_DIS(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
{
    (void) dodag;
    gnrc_pktsnip_t *pkt;
    icmpv6_hdr_t *icmp;
    gnrc_rpl_dis_t *dis;
    /* TODO: Currently the DIS is too small so that wireshark complains about an incorrect
     * ethernet frame check sequence. In order to prevent this, 4 PAD1 options are added.
     * This will be addressed in follow-up PRs */
    int size = sizeof(icmpv6_hdr_t) + sizeof(gnrc_rpl_dis_t) + 4;

    if ((pkt = gnrc_icmpv6_build(NULL, ICMPV6_RPL_CTRL, GNRC_RPL_ICMPV6_CODE_DIS, size)) == NULL) {
        DEBUG("RPL: Send DIS - no space left in packet buffer\n");
        return;
    }

    icmp = (icmpv6_hdr_t *)pkt->data;
    dis = (gnrc_rpl_dis_t *)(icmp + 1);
    dis->flags = 0;
    dis->reserved = 0;
    /* TODO: see above TODO */
    memset((dis + 1), 0, 4);

    gnrc_rpl_send(pkt, NULL, destination, (dodag ? &dodag->dodag_id : NULL));
}
Пример #2
0
void gnrc_rpl_send_DIS(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination)
{
    gnrc_pktsnip_t *pkt;
    icmpv6_hdr_t *icmp;
    gnrc_rpl_dis_t *dis;

    /* TODO: Currently the DIS is too small so that wireshark complains about an incorrect
     * ethernet frame check sequence. In order to prevent this, 4 PAD1 options are added.
     * This will be addressed in follow-up PRs */
    uint8_t padding[] = {
            0x01, 0x02, 0x00, 0x00
    };

    int size = sizeof(icmpv6_hdr_t) + sizeof(gnrc_rpl_dis_t) + sizeof(padding);

    if ((pkt = gnrc_icmpv6_build(NULL, ICMPV6_RPL_CTRL, GNRC_RPL_ICMPV6_CODE_DIS, size)) == NULL) {
        DEBUG("RPL: Send DIS - no space left in packet buffer\n");
        return;
    }

    icmp = (icmpv6_hdr_t *)pkt->data;
    dis = (gnrc_rpl_dis_t *)(icmp + 1);
    dis->flags = 0;
    dis->reserved = 0;

    /* TODO add padding may be removed if packet size grows */
    memcpy((dis + 1), padding, sizeof(padding));

    gnrc_rpl_send(pkt, NULL, destination, (inst? &(inst->dodag.dodag_id) : NULL));
}
Пример #3
0
void gnrc_rpl_send_DIO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination)
{
    if (inst == NULL) {
        DEBUG("RPL: Error - trying to send DIO without being part of a dodag.\n");
        return;
    }

    gnrc_rpl_dodag_t *dodag = &inst->dodag;
    gnrc_pktsnip_t *pkt = NULL, *tmp = NULL;
    gnrc_rpl_dio_t *dio;

#ifndef GNRC_RPL_WITHOUT_PIO
    if (dodag->req_opts & GNRC_RPL_REQ_OPT_PREFIX_INFO) {
        if ((pkt = _dio_prefix_info_build(pkt, dodag)) == NULL) {
            return;
        }
    }
#endif

    if (dodag->req_opts & GNRC_RPL_REQ_OPT_DODAG_CONF) {
        if ((pkt = _dio_dodag_conf_build(pkt, dodag)) == NULL) {
            return;
        }
        dodag->req_opts &= ~GNRC_RPL_REQ_OPT_DODAG_CONF;
    }

    if ((tmp = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_rpl_dio_t), GNRC_NETTYPE_UNDEF)) == NULL) {
        DEBUG("RPL: Send DIO - no space left in packet buffer\n");
        gnrc_pktbuf_release(pkt);
        return;
    }
    pkt = tmp;
    dio = pkt->data;
    dio->instance_id = inst->id;
    dio->version_number = dodag->version;
    /* a leaf node announces an INFINITE_RANK */
    dio->rank = ((dodag->node_status == GNRC_RPL_LEAF_NODE) ?
                 byteorder_htons(GNRC_RPL_INFINITE_RANK) : byteorder_htons(dodag->my_rank));
    dio->g_mop_prf = (dodag->grounded << GNRC_RPL_GROUNDED_SHIFT) |
                     (inst->mop << GNRC_RPL_MOP_SHIFT) | dodag->prf;
    dio->dtsn = dodag->dtsn;
    dio->flags = 0;
    dio->reserved = 0;
    dio->dodag_id = dodag->dodag_id;

    if ((tmp = gnrc_icmpv6_build(pkt, ICMPV6_RPL_CTRL, GNRC_RPL_ICMPV6_CODE_DIO,
                                 sizeof(icmpv6_hdr_t))) == NULL) {
        DEBUG("RPL: Send DIO - no space left in packet buffer\n");
        gnrc_pktbuf_release(pkt);
        return;
    }
    pkt = tmp;

    gnrc_rpl_send(pkt, NULL, destination, &dodag->dodag_id);
}
Пример #4
0
void gnrc_rpl_p2p_send_DRO(gnrc_pktsnip_t *pkt, gnrc_rpl_p2p_ext_t *p2p_ext)
{
    assert(p2p_ext != NULL);

    if (pkt == NULL) {
        if ((pkt = _build_initial_DRO(p2p_ext)) == NULL) {
            DEBUG("RPL-P2P: BUILD INITIAL DRO - no space left in packet buffer\n");
            return;
        }
    }

    gnrc_rpl_send(pkt, p2p_ext->dodag->iface, NULL, NULL, &p2p_ext->dodag->dodag_id);

    return;
}
Пример #5
0
void gnrc_rpl_send_DIO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
{
    if (dodag == NULL) {
        DEBUG("RPL: Error - trying to send DIO without being part of a dodag.\n");
        return;
    }

    gnrc_pktsnip_t *pkt;
    icmpv6_hdr_t *icmp;
    gnrc_rpl_dio_t *dio;
    uint8_t *pos;
    int size = sizeof(icmpv6_hdr_t) + sizeof(gnrc_rpl_dio_t);

    if ((dodag->dodag_conf_counter % 3) == 0) {
        size += sizeof(gnrc_rpl_opt_dodag_conf_t);
        size += sizeof(gnrc_rpl_opt_prefix_info_t);
    }

    if ((pkt = gnrc_icmpv6_build(NULL, ICMPV6_RPL_CTRL, GNRC_RPL_ICMPV6_CODE_DIO, size)) == NULL) {
        DEBUG("RPL: Send DIO - no space left in packet buffer\n");
        return;
    }

    icmp = (icmpv6_hdr_t *)pkt->data;
    dio = (gnrc_rpl_dio_t *)(icmp + 1);
    pos = (uint8_t *) dio;
    dio->instance_id = dodag->instance->id;
    dio->version_number = dodag->version;
    dio->rank = byteorder_htons(dodag->my_rank);
    dio->g_mop_prf = (dodag->grounded << GNRC_RPL_GROUNDED_SHIFT) |
        (dodag->instance->mop << GNRC_RPL_MOP_SHIFT) | dodag->prf;
    dio->dtsn = dodag->dtsn;
    dio->flags = 0;
    dio->reserved = 0;
    dio->dodag_id = dodag->dodag_id;

    pos += sizeof(*dio);

    if ((dodag->dodag_conf_counter % 3) == 0) {
        gnrc_rpl_opt_dodag_conf_t *dodag_conf;
        dodag_conf = (gnrc_rpl_opt_dodag_conf_t *) pos;
        dodag_conf->type = GNRC_RPL_OPT_DODAG_CONF;
        dodag_conf->length = GNRC_RPL_OPT_DODAG_CONF_LEN;
        dodag_conf->flags_a_pcs = 0;
        dodag_conf->dio_int_doubl = dodag->dio_interval_doubl;
        dodag_conf->dio_int_min = dodag->dio_min;
        dodag_conf->dio_redun = dodag->dio_redun;
        dodag_conf->max_rank_inc = byteorder_htons(dodag->instance->max_rank_inc);
        dodag_conf->min_hop_rank_inc = byteorder_htons(dodag->instance->min_hop_rank_inc);
        dodag_conf->ocp = byteorder_htons(dodag->instance->of->ocp);
        dodag_conf->reserved = 0;
        dodag_conf->default_lifetime = dodag->default_lifetime;
        dodag_conf->lifetime_unit = byteorder_htons(dodag->lifetime_unit);
        pos += sizeof(*dodag_conf);

        gnrc_rpl_opt_prefix_info_t *prefix_info;
        prefix_info = (gnrc_rpl_opt_prefix_info_t *) pos;
        prefix_info->type = GNRC_RPL_OPT_PREFIX_INFO;
        prefix_info->length = GNRC_RPL_OPT_PREFIX_INFO_LEN;
        /* auto-address configuration */
        prefix_info->LAR_flags = GNRC_RPL_PREFIX_AUTO_ADDRESS_BIT;
        prefix_info->valid_lifetime = dodag->addr_valid;
        prefix_info->pref_lifetime = dodag->addr_preferred;
        prefix_info->prefix_len = dodag->prefix_len;
        prefix_info->reserved = 0;

        memset(&prefix_info->prefix, 0, sizeof(prefix_info->prefix));
        ipv6_addr_init_prefix(&prefix_info->prefix, &dodag->dodag_id, dodag->prefix_len);
    }

    dodag->dodag_conf_counter++;
    gnrc_rpl_send(pkt, NULL, destination, &dodag->dodag_id);
}
Пример #6
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) {
        gnrc_ipv6_nib_ft_add(&p2p_ext->target, IPV6_ADDR_BIT_LEN, src, dodag->iface,
                             p2p_ext->dodag->default_lifetime *
                             p2p_ext->dodag->lifetime_unit);

        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;
}