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