gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_6ctx_build(uint8_t prefix_len, uint8_t flags, uint16_t ltime, ipv6_addr_t *prefix, gnrc_pktsnip_t *next) { gnrc_pktsnip_t *pkt = gnrc_ndp_opt_build(NDP_OPT_6CTX, sizeof(sixlowpan_nd_opt_6ctx_t) + (prefix_len / 8), next); if (pkt != NULL) { sixlowpan_nd_opt_6ctx_t *ctx_opt = pkt->data; ctx_opt->ctx_len = prefix_len; ctx_opt->resv_c_cid = flags; ctx_opt->resv.u16 = 0; ctx_opt->ltime = byteorder_htons(ltime); /* Bits beyond prefix_len MUST be 0 */ memset(ctx_opt + 1, 0, pkt->size - sizeof(sixlowpan_nd_opt_6ctx_t)); ipv6_addr_init_prefix((ipv6_addr_t *)(ctx_opt + 1), prefix, prefix_len); } return pkt; }
gnrc_sixlowpan_ctx_t *gnrc_sixlowpan_ctx_update(uint8_t id, const ipv6_addr_t *prefix, uint8_t prefix_len, uint16_t ltime, bool comp) { if ((id >= GNRC_SIXLOWPAN_CTX_SIZE) || (prefix_len == 0)) { return NULL; } mutex_lock(&_ctx_mutex); _ctxs[id].ltime = ltime; if (ltime == 0) { comp = false; } if (prefix_len > IPV6_ADDR_BIT_LEN) { _ctxs[id].prefix_len = IPV6_ADDR_BIT_LEN; } else { _ctxs[id].prefix_len = prefix_len; } _ctxs[id].flags_id = (comp) ? (GNRC_SIXLOWPAN_CTX_FLAGS_COMP | id) : id; if (!ipv6_addr_equal(&(_ctxs[id].prefix), prefix)) { ipv6_addr_set_unspecified(&(_ctxs[id].prefix)); ipv6_addr_init_prefix(&(_ctxs[id].prefix), prefix, _ctxs[id].prefix_len); } DEBUG("6lo ctx: update context (%u, %s/%" PRIu8 "), lifetime: %" PRIu16 " min\n", id, ipv6_addr_to_str(ipv6str, &_ctxs[id].prefix, sizeof(ipv6str)), _ctxs[id].prefix_len, _ctxs[id].ltime); _ctx_inval_times[id] = ltime + _current_minute(); mutex_unlock(&_ctx_mutex); return &(_ctxs[id]); }
gnrc_pktsnip_t *_dio_prefix_info_build(gnrc_pktsnip_t *pkt, gnrc_rpl_dodag_t *dodag) { gnrc_rpl_opt_prefix_info_t *prefix_info; gnrc_pktsnip_t *opt_snip; if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_rpl_opt_prefix_info_t), GNRC_NETTYPE_UNDEF)) == NULL) { DEBUG("RPL: BUILD PREFIX INFO - no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return NULL; } prefix_info = opt_snip->data; 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); return opt_snip; }
void init(char *str) { transceiver_command_t tcmd; msg_t m; uint8_t chan = RADIO_CHANNEL; char command; int res = sscanf(str, "init %c", &command); if (res < 1) { printf("Usage: init (r|n)\n"); printf("\tr\tinitialize as root\n"); printf("\tn\tinitialize as node router\n"); } uint8_t state; if ((command == 'n') || (command == 'r')) { printf("INFO: Initialize as %s on address %d\n", ((command == 'n') ? "node" : "root"), id); if (!id || (id > 255)) { printf("ERROR: address not a valid 8 bit integer\n"); return; } state = rpl_init(TRANSCEIVER, id); if (state != SIXLOWERROR_SUCCESS) { printf("Error initializing RPL\n"); } else { puts("6LoWPAN and RPL initialized."); } if (command == 'r') { rpl_init_root(); is_root = 1; } else { ipv6_iface_set_routing_provider(rpl_get_next_hop); } int monitor_pid = thread_create(monitor_stack_buffer, MONITOR_STACK_SIZE, PRIORITY_MAIN-2, CREATE_STACKTEST, monitor, "monitor"); transceiver_register(TRANSCEIVER, monitor_pid); ipv6_register_packet_handler(monitor_pid); //sixlowpan_lowpan_register(monitor_pid); } else { printf("ERROR: Unknown command '%c'\n", command); return; } /* TODO: check if this works as intended */ ipv6_addr_t prefix, tmp; ipv6_addr_init(&std_addr, 0xABCD, 0xEF12, 0, 0, 0x1034, 0x00FF, 0xFE00, id); ipv6_addr_init_prefix(&prefix, &std_addr, 64); plist_add(&prefix, 64, NDP_OPT_PI_VLIFETIME_INFINITE, 0, 1, ICMPV6_NDP_OPT_PI_FLAG_AUTONOM); ipv6_init_iface_as_router(); /* add global address */ ipv6_addr_set_by_eui64(&tmp, &std_addr); ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_GLOBAL, NDP_ADDR_STATE_PREFERRED, 0, 0); /* set channel to 10 */ tcmd.transceivers = TRANSCEIVER; tcmd.data = &chan; m.type = SET_CHANNEL; m.content.ptr = (void *) &tcmd; msg_send_receive(&m, &m, transceiver_pid); printf("Channel set to %u\n", RADIO_CHANNEL); destiny_init_transport_layer(); puts("Destiny initialized"); /* start transceiver watchdog */ }
bool gnrc_ndp_internal_pi_opt_handle(kernel_pid_t iface, uint8_t icmpv6_type, ndp_opt_pi_t *pi_opt) { ipv6_addr_t *prefix; gnrc_ipv6_netif_addr_t *netif_addr; if ((pi_opt->len != NDP_OPT_PI_LEN)) { DEBUG("ndp: invalid PI option received\n"); return false; } if (icmpv6_type != ICMPV6_RTR_ADV || ipv6_addr_is_link_local(&pi_opt->prefix)) { /* else discard silently */ return true; } #ifdef MODULE_GNRC_SIXLOWPAN_ND if ((gnrc_ipv6_netif_get(iface)->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) && (pi_opt->flags & NDP_OPT_PI_FLAGS_L)) { /* ignore: see https://tools.ietf.org/html/rfc6775#section-5.4 */ return true; } #endif prefix = gnrc_ipv6_netif_find_addr(iface, &pi_opt->prefix); if (((prefix == NULL) || (gnrc_ipv6_netif_addr_get(prefix)->prefix_len != pi_opt->prefix_len)) && (pi_opt->valid_ltime.u32 != 0)) { ipv6_addr_t pref_addr; if ((gnrc_netapi_get(iface, NETOPT_IPV6_IID, 0, &pref_addr.u64[1], sizeof(eui64_t)) < 0)) { DEBUG("ndp: could not get IID from interface %d\n", iface); return false; } ipv6_addr_init_prefix(&pref_addr, &pi_opt->prefix, pi_opt->prefix_len); prefix = gnrc_ipv6_netif_add_addr(iface, &pref_addr, pi_opt->prefix_len, pi_opt->flags & NDP_OPT_PI_FLAGS_MASK); if (prefix == NULL) { DEBUG("ndp: could not add prefix to interface %d\n", iface); return false; } #ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER gnrc_sixlowpan_nd_router_set_rtr_adv(gnrc_ipv6_netif_get(iface), true); #endif } netif_addr = gnrc_ipv6_netif_addr_get(prefix); if (pi_opt->valid_ltime.u32 == 0) { if (prefix != NULL) { gnrc_ipv6_netif_remove_addr(iface, &netif_addr->addr); } return true; } netif_addr->valid = byteorder_ntohl(pi_opt->valid_ltime); netif_addr->preferred = byteorder_ntohl(pi_opt->pref_ltime); if (netif_addr->valid != UINT32_MAX) { xtimer_set_msg(&netif_addr->valid_timeout, (byteorder_ntohl(pi_opt->valid_ltime) * SEC_IN_USEC), &netif_addr->valid_timeout_msg, thread_getpid()); } /* TODO: preferred lifetime for address auto configuration */ /* on-link flag MUST stay set if it was */ netif_addr->flags &= ~NDP_OPT_PI_FLAGS_A; netif_addr->flags |= (pi_opt->flags & NDP_OPT_PI_FLAGS_MASK); return true; }
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 rpl_udp_init(int argc, char **argv) { transceiver_command_t tcmd; msg_t m; uint8_t chan = RADIO_CHANNEL; if (argc != 2) { printf("Usage: %s (r|n)\n", argv[0]); printf("\tr\tinitialize as root\n"); printf("\tn\tinitialize as node router\n"); return; } uint8_t state; char command = argv[1][0]; if ((command == 'n') || (command == 'r')) { printf("INFO: Initialize as %s on address %d\n", ((command == 'n') ? "node" : "root"), id); if (!id || (id > 255)) { printf("ERROR: address not a valid 8 bit integer\n"); return; } DEBUGF("Setting HW address to %u\n", id); net_if_set_hardware_address(0, id); DEBUGF("Initializing RPL for interface 0\n"); state = rpl_init(0); if (state != SIXLOWERROR_SUCCESS) { printf("Error initializing RPL\n"); } else { puts("6LoWPAN and RPL initialized."); } if (command == 'r') { rpl_init_root(); is_root = 1; } else { ipv6_iface_set_routing_provider(rpl_get_next_hop); } DEBUGF("Start monitor\n"); int monitor_pid = thread_create( monitor_stack_buffer, sizeof(monitor_stack_buffer), PRIORITY_MAIN - 2, CREATE_STACKTEST, rpl_udp_monitor, NULL, "monitor"); DEBUGF("Register at transceiver %02X\n", TRANSCEIVER); transceiver_register(TRANSCEIVER, monitor_pid); ipv6_register_packet_handler(monitor_pid); //sixlowpan_lowpan_register(monitor_pid); } else { printf("ERROR: Unknown command '%c'\n", command); return; } /* TODO: check if this works as intended */ ipv6_addr_t prefix, tmp; ipv6_addr_init(&std_addr, 0xABCD, 0xEF12, 0, 0, 0x1034, 0x00FF, 0xFE00, id); ipv6_addr_init_prefix(&prefix, &std_addr, 64); ndp_add_prefix_info(0, &prefix, 64, NDP_OPT_PI_VLIFETIME_INFINITE, NDP_OPT_PI_PLIFETIME_INFINITE, 1, ICMPV6_NDP_OPT_PI_FLAG_AUTONOM); ipv6_init_as_router(); /* add global address */ ipv6_addr_set_by_eui64(&tmp, 0, &std_addr); ipv6_net_if_add_addr(0, &tmp, NDP_ADDR_STATE_PREFERRED, 0, 0, 0); /* set channel to 10 */ tcmd.transceivers = TRANSCEIVER; tcmd.data = &chan; m.type = SET_CHANNEL; m.content.ptr = (void *) &tcmd; msg_send_receive(&m, &m, transceiver_pid); printf("Channel set to %u\n", RADIO_CHANNEL); puts("Destiny initialized"); /* start transceiver watchdog */ }