void gnrc_rpl_p2p_rdo_parse(gnrc_rpl_p2p_opt_rdo_t *rdo, gnrc_rpl_p2p_ext_t *p2p_ext) { DEBUG("RPL: Route Discovery DIO option parsed\n"); uint8_t addr_num = (rdo->length - GNRC_RPL_P2P_RDO_LEN) / (sizeof(ipv6_addr_t) - p2p_ext->compr); if (addr_num >= GNRC_RPL_P2P_ADDR_VEC_NUMOF) { DEBUG("RPL: cannot parse RDO - too many hops\n"); return; } p2p_ext->for_me = (gnrc_ipv6_netif_find_by_addr(NULL, &rdo->target) != KERNEL_PID_UNDEF); p2p_ext->reply = (rdo->compr_flags & (1 << GNRC_RPL_P2P_RDO_FLAGS_REPLY)) >> GNRC_RPL_P2P_RDO_FLAGS_REPLY; p2p_ext->hop_by_hop = (rdo->compr_flags & (1 << GNRC_RPL_P2P_RDO_FLAGS_HBH)) >> GNRC_RPL_P2P_RDO_FLAGS_HBH; p2p_ext->routes_numof = (rdo->compr_flags & (0x3 << GNRC_RPL_P2P_RDO_FLAGS_ADDRNUM)) >> GNRC_RPL_P2P_RDO_FLAGS_ADDRNUM; p2p_ext->compr = rdo->compr_flags & GNRC_RPL_P2P_RDO_FLAGS_COMPR; p2p_ext->lifetime_enc = (rdo->lmn & (0x3 << GNRC_RPL_P2P_RDO_FLAGS_LIFETIME)) >> GNRC_RPL_P2P_RDO_FLAGS_LIFETIME; if (p2p_ext->lifetime_sec == INT8_MIN) { p2p_ext->lifetime_sec = gnrc_rpl_p2p_lifetime_lookup[p2p_ext->lifetime_enc]; } p2p_ext->maxrank = rdo->lmn & GNRC_RPL_P2P_RDO_FLAGS_MAXRANK; p2p_ext->target = rdo->target; memset(&p2p_ext->addr_vec, 0, sizeof(ipv6_addr_t) * GNRC_RPL_P2P_ADDR_VEC_NUMOF); p2p_ext->addr_numof = 0; uint8_t *tmp = (uint8_t *) (rdo + 1); uint8_t *addr = NULL; uint8_t addr_len = sizeof(ipv6_addr_t) - p2p_ext->compr; uint8_t i = 0; for (i = 0; i < addr_num; i++) { addr = ((uint8_t *) &p2p_ext->addr_vec[i]) + p2p_ext->compr; memcpy(addr, tmp, addr_len); tmp += addr_len; p2p_ext->addr_numof++; } if (!p2p_ext->for_me) { ipv6_addr_t *me = NULL; if(gnrc_ipv6_netif_find_by_prefix(&me, &p2p_ext->dodag->dodag_id) == KERNEL_PID_UNDEF) { DEBUG("RPL: no address configured\n"); return; } addr = ((uint8_t *) &p2p_ext->addr_vec[i]) + p2p_ext->compr; memcpy(addr, ((uint8_t *) me) + p2p_ext->compr, addr_len); p2p_ext->addr_numof++; } else if (p2p_ext->reply) { p2p_ext->stop = true; p2p_ext->dro_ack = true; p2p_ext->dro_delay = GNRC_RPL_P2P_DRO_DELAY; } }
/** @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); }
ipv6_addr_t *conn_find_best_source(const ipv6_addr_t *dst) { ipv6_addr_t *local = NULL; gnrc_ipv6_netif_find_by_prefix(&local, dst); return local; }