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; } }
static gnrc_rpl_dodag_t *_root_dodag_init(uint8_t instance_id, ipv6_addr_t *dodag_id, uint8_t mop) { if (gnrc_rpl_pid == KERNEL_PID_UNDEF) { DEBUG("RPL: RPL thread not started\n"); return NULL; } ipv6_addr_t *configured_addr; gnrc_ipv6_netif_addr_t *netif_addr = NULL; gnrc_rpl_instance_t *inst = NULL; gnrc_rpl_dodag_t *dodag = NULL; if (instance_id == 0) { DEBUG("RPL: instance id (%d) must be a positive number greater than zero\n", instance_id); return NULL; } if (gnrc_ipv6_netif_find_by_addr(&configured_addr, dodag_id) == KERNEL_PID_UNDEF) { DEBUG("RPL: no IPv6 address configured to match the given dodag id: %s\n", ipv6_addr_to_str(addr_str, dodag_id, sizeof(addr_str))); return NULL; } if ((netif_addr = gnrc_ipv6_netif_addr_get(configured_addr)) == NULL) { DEBUG("RPL: no netif address found for %s\n", ipv6_addr_to_str(addr_str, configured_addr, sizeof(addr_str))); return NULL; } if (gnrc_rpl_instance_add(instance_id, &inst)) { inst->of = (gnrc_rpl_of_t *) gnrc_rpl_get_of_for_ocp(GNRC_RPL_DEFAULT_OCP); inst->mop = mop; inst->min_hop_rank_inc = GNRC_RPL_DEFAULT_MIN_HOP_RANK_INCREASE; inst->max_rank_inc = GNRC_RPL_DEFAULT_MAX_RANK_INCREASE; } else if (inst == NULL) { DEBUG("RPL: could not allocate memory for a new instance with id %d", instance_id); return NULL; } else if (inst->mop != mop) { DEBUG("RPL: instance (%d) exists with another MOP", instance_id); return NULL; } if (!gnrc_rpl_dodag_add(inst, dodag_id, &dodag)) { DEBUG("RPL: DODAG with id %s exists or no memory left for a new DODAG", ipv6_addr_to_str(addr_str, dodag_id, sizeof(addr_str))); return NULL; } dodag->prefix_len = netif_addr->prefix_len; dodag->addr_preferred = netif_addr->preferred; dodag->addr_valid = netif_addr->valid; return dodag; }
void *_udp_server(void *args) { uint16_t port = (uint16_t) atoi(args); ipv6_addr_t server_addr = IPV6_ADDR_UNSPECIFIED; msg_init_queue(server_msg_queue, SERVER_MSG_QUEUE_SIZE); if(conn_udp_create(&conn, &server_addr, sizeof(server_addr), AF_INET6, port) < 0) { return NULL; } server_running = true; printf("Success: started UDP server on port %" PRIu16 "\n", port); char *arg[4]; char *cmd = "udp_send"; char *port_str = "8888"; arg[0] = cmd; arg[2] = port_str; char src_str[IPV6_ADDR_MAX_STR_LEN]; while (1) { int res; ipv6_addr_t src; size_t src_len = sizeof(ipv6_addr_t); if ((res = conn_udp_recvfrom(&conn, server_buffer, sizeof(server_buffer), &src, &src_len, &port)) < 0) { puts("Error while receiving"); } else if (res == 0) { puts("No data received"); } else { server_buffer[res] = '\0'; if (gnrc_rpl_instances[0].state && gnrc_rpl_instances[0].dodag.node_status == GNRC_RPL_ROOT_NODE) { printf("%s;%s\n", ipv6_addr_to_str(src_str, &src, sizeof(src_str)), server_buffer); ipv6_addr_to_str(addr_str, &ipv6_addr_all_nodes_link_local, sizeof(addr_str)); arg[1] = addr_str; arg[3] = src_str; udp_send(4, arg); } else { ipv6_addr_t payload; ipv6_addr_from_str(&payload, server_buffer); if ((gnrc_ipv6_netif_find_by_addr(NULL, &payload) != KERNEL_PID_UNDEF) && (!acked)) { acked = true; printf("diff: %llu\n", xtimer_now64() - time); } } } } return NULL; }
/* functions for receiving */ static inline bool _pkt_not_for_me(kernel_pid_t *iface, ipv6_hdr_t *hdr) { if (ipv6_addr_is_loopback(&hdr->dst)) { return false; } else if (*iface == KERNEL_PID_UNDEF) { *iface = gnrc_ipv6_netif_find_by_addr(NULL, &hdr->dst); return (*iface == KERNEL_PID_UNDEF); } else { return (gnrc_ipv6_netif_find_addr(*iface, &hdr->dst) == NULL); } }
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); } }
bool gnrc_conn6_set_local_addr(uint8_t *conn_addr, const ipv6_addr_t *addr) { ipv6_addr_t *tmp; if (!ipv6_addr_is_unspecified(addr) && !ipv6_addr_is_loopback(addr) && gnrc_ipv6_netif_find_by_addr(&tmp, addr) == KERNEL_PID_UNDEF) { return false; } else if (ipv6_addr_is_loopback(addr) || ipv6_addr_is_unspecified(addr)) { ipv6_addr_set_unspecified((ipv6_addr_t *)conn_addr); } else { memcpy(conn_addr, addr, sizeof(ipv6_addr_t)); } return true; }
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); } }
/* functions for receiving */ static inline bool _pkt_not_for_me(kernel_pid_t *iface, ipv6_hdr_t *hdr) { if (ipv6_addr_is_loopback(&hdr->dst)) { return false; } else if ((!ipv6_addr_is_link_local(&hdr->dst)) || (*iface == KERNEL_PID_UNDEF)) { kernel_pid_t if_pid = gnrc_ipv6_netif_find_by_addr(NULL, &hdr->dst); if (*iface == KERNEL_PID_UNDEF) { *iface = if_pid; /* Use original interface for reply if * existent */ } return (if_pid == KERNEL_PID_UNDEF); } else { return (gnrc_ipv6_netif_find_addr(*iface, &hdr->dst) == NULL); } }
static void _send(gnrc_pktsnip_t *pkt, bool prep_hdr) { kernel_pid_t iface = KERNEL_PID_UNDEF; gnrc_pktsnip_t *ipv6, *payload; ipv6_addr_t *tmp; ipv6_hdr_t *hdr; /* get IPv6 snip and (if present) generic interface header */ if (pkt->type == GNRC_NETTYPE_NETIF) { /* If there is already a netif header (routing protocols and * neighbor discovery might add them to preset sending interface) */ iface = ((gnrc_netif_hdr_t *)pkt->data)->if_pid; /* seize payload as temporary variable */ ipv6 = gnrc_pktbuf_start_write(pkt); /* write protect for later removal * in _send_unicast() */ if (ipv6 == NULL) { DEBUG("ipv6: unable to get write access to netif header, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } pkt = ipv6; /* Reset pkt from temporary variable */ ipv6 = pkt->next; } else { ipv6 = pkt; } /* seize payload as temporary variable */ payload = gnrc_pktbuf_start_write(ipv6); if (payload == NULL) { DEBUG("ipv6: unable to get write access to IPv6 header, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } if (ipv6 != pkt) { /* in case packet has netif header */ pkt->next = payload;/* pkt is already write-protected so we can do that */ } else { pkt = payload; /* pkt is the IPv6 header so we just write-protected it */ } ipv6 = payload; /* Reset ipv6 from temporary variable */ hdr = ipv6->data; payload = ipv6->next; if (ipv6_addr_is_multicast(&hdr->dst)) { _send_multicast(iface, pkt, ipv6, payload, prep_hdr); } else if ((ipv6_addr_is_loopback(&hdr->dst)) || /* dst is loopback address */ ((iface == KERNEL_PID_UNDEF) && /* or dst registered to any local interface */ ((iface = gnrc_ipv6_netif_find_by_addr(&tmp, &hdr->dst)) != KERNEL_PID_UNDEF)) || ((iface != KERNEL_PID_UNDEF) && /* or dst registered to given interface */ (gnrc_ipv6_netif_find_addr(iface, &hdr->dst) != NULL))) { uint8_t *rcv_data; gnrc_pktsnip_t *ptr = ipv6, *rcv_pkt; if (prep_hdr) { if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) { /* error on filling up header */ gnrc_pktbuf_release(pkt); return; } } rcv_pkt = gnrc_pktbuf_add(NULL, NULL, gnrc_pkt_len(ipv6), GNRC_NETTYPE_IPV6); if (rcv_pkt == NULL) { DEBUG("ipv6: error on generating loopback packet\n"); gnrc_pktbuf_release(pkt); return; } rcv_data = rcv_pkt->data; /* "reverse" packet (by making it one snip as if received from NIC) */ while (ptr != NULL) { memcpy(rcv_data, ptr->data, ptr->size); rcv_data += ptr->size; ptr = ptr->next; } gnrc_pktbuf_release(pkt); DEBUG("ipv6: packet is addressed to myself => loopback\n"); if (gnrc_netapi_receive(gnrc_ipv6_pid, rcv_pkt) < 1) { DEBUG("ipv6: unable to deliver packet\n"); gnrc_pktbuf_release(rcv_pkt); } } else { uint8_t l2addr_len = GNRC_IPV6_NC_L2_ADDR_MAX; uint8_t l2addr[l2addr_len]; iface = _next_hop_l2addr(l2addr, &l2addr_len, iface, &hdr->dst, pkt); if (iface == KERNEL_PID_UNDEF) { DEBUG("ipv6: error determining next hop's link layer address\n"); gnrc_pktbuf_release(pkt); return; } if (prep_hdr) { if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) { /* error on filling up header */ gnrc_pktbuf_release(pkt); return; } } _send_unicast(iface, l2addr, l2addr_len, pkt); } }
static inline bool _is_me(ipv6_addr_t *addr) { ipv6_addr_t *res; return (gnrc_ipv6_netif_find_by_addr(&res, addr) != KERNEL_PID_UNDEF); }
/** @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); }
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; }
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) {
int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh) { if (rh->seg_left == 0) { return EXT_RH_CODE_OK; } uint8_t n = (((rh->len * 8) - GNRC_RPL_SRH_PADDING(rh->pad_resv) - (16 - GNRC_RPL_SRH_COMPRE(rh->compr))) / (16 - GNRC_RPL_SRH_COMPRI(rh->compr))) + 1; ipv6_addr_t addr = ipv6->dst, tmp; uint8_t i, pref_elided, tmp_pref_elided, addr_len, compri_addr_len, tmp_addr_len, found_pos = 0; uint8_t *addr_vec = (uint8_t *) (rh + 1); bool found = false; DEBUG("RPL SRH: %u addresses in the routing header\n", (unsigned) n); if (rh->seg_left > n) { DEBUG("RPL SRH: number of segments left > number of addresses - discard\n"); /* TODO ICMP Parameter Problem - Code 0 */ return EXT_RH_CODE_ERROR; } rh->seg_left--; i = n - rh->seg_left; pref_elided = rh->seg_left ? GNRC_RPL_SRH_COMPRI(rh->compr) : GNRC_RPL_SRH_COMPRE(rh->compr); compri_addr_len = sizeof(ipv6_addr_t) - GNRC_RPL_SRH_COMPRI(rh->compr); addr_len = sizeof(ipv6_addr_t) - pref_elided; memcpy(&addr.u8[pref_elided], &addr_vec[(i - 1) * compri_addr_len], addr_len); if (ipv6_addr_is_multicast(&ipv6->dst) || ipv6_addr_is_multicast(&addr)) { DEBUG("RPL SRH: found a multicast address - discard\n"); /* TODO discard the packet */ return EXT_RH_CODE_ERROR; } /* check if multiple addresses of my interface exist */ tmp_pref_elided = GNRC_RPL_SRH_COMPRI(rh->compr); tmp_addr_len = sizeof(ipv6_addr_t) - tmp_pref_elided; tmp = ipv6->dst; for (uint8_t k = 0; k < n; k++) { if (k == n - 1) { tmp_pref_elided = GNRC_RPL_SRH_COMPRE(rh->compr); tmp_addr_len = sizeof(ipv6_addr_t) - tmp_pref_elided; } memcpy(&tmp.u8[tmp_pref_elided], &addr_vec[k * compri_addr_len], tmp_addr_len); if (gnrc_ipv6_netif_find_by_addr(NULL, &tmp) != KERNEL_PID_UNDEF) { if (found && ((k - found_pos) > 1)) { DEBUG("RPL SRH: found multiple addresses that belong to me - discard\n"); /* TODO send an ICMP Parameter Problem (Code 0) and discard the packet */ return EXT_RH_CODE_ERROR; } found_pos = k; found = true; } } memcpy(&addr_vec[(i - 1) * compri_addr_len], &ipv6->dst.u8[pref_elided], addr_len); DEBUG("RPL SRH: Next hop: %s at position %d\n", ipv6_addr_to_str(addr_str, &addr, sizeof(addr_str)), i); ipv6->dst = addr; return EXT_RH_CODE_FORWARD; }