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