static int _list_all_inet6(int argc, char **argv) { (void)argc; (void)argv; gnrc_netif_t *netif = NULL; unsigned addr_qty = 0; while ((netif = gnrc_netif_iter(netif))) { ipv6_addr_t ipv6_addrs[GNRC_NETIF_IPV6_ADDRS_NUMOF]; int res = gnrc_netapi_get(netif->pid, NETOPT_IPV6_ADDR, 0, ipv6_addrs, sizeof(ipv6_addrs)); if (res >= 0) { uint8_t ipv6_addrs_flags[GNRC_NETIF_IPV6_ADDRS_NUMOF]; memset(ipv6_addrs_flags, 0, sizeof(ipv6_addrs_flags)); /* assume it to succeed (otherwise array will stay 0) */ gnrc_netapi_get(netif->pid, NETOPT_IPV6_ADDR_FLAGS, 0, ipv6_addrs_flags, sizeof(ipv6_addrs_flags)); /* yes, the res of NETOPT_IPV6_ADDR is meant to be here ;-) */ for (unsigned i = 0; i < (res / sizeof(ipv6_addr_t)); i++) { _print_addr(&ipv6_addrs[i], ipv6_addrs_flags[i]); addr_qty++; } } } if (!addr_qty) { printf("no addresses found\n"); } return 0; }
static size_t _get_l2src(kernel_pid_t iface, uint8_t *l2src, size_t l2src_maxlen) { bool try_long = false; int res; uint16_t l2src_len; /* maximum address length that fits into a minimum length (8) S/TL2A option */ const uint16_t max_short_len = 6; /* try getting source address */ if ((gnrc_netapi_get(iface, NETOPT_SRC_LEN, 0, &l2src_len, sizeof(l2src_len)) >= 0) && (l2src_len > max_short_len)) { try_long = true; } if (try_long && ((res = gnrc_netapi_get(iface, NETOPT_ADDRESS_LONG, 0, l2src, l2src_maxlen)) > max_short_len)) { l2src_len = (uint16_t)res; } else if ((res = gnrc_netapi_get(iface, NETOPT_ADDRESS, 0, l2src, l2src_maxlen)) >= 0) { l2src_len = (uint16_t)res; } else { DEBUG("ndp internal: no link-layer address found.\n"); l2src_len = 0; } return l2src_len; }
void gnrc_ipv6_netif_init_by_dev(void) { kernel_pid_t ifs[GNRC_NETIF_NUMOF]; size_t ifnum = gnrc_netif_get(ifs); for (size_t i = 0; i < ifnum; i++) { ipv6_addr_t addr; eui64_t iid; gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(ifs[i]); if (ipv6_if == NULL) { continue; } mutex_lock(&ipv6_if->mutex); #ifdef MODULE_GNRC_SIXLOWPAN gnrc_nettype_t if_type = GNRC_NETTYPE_UNDEF; if ((gnrc_netapi_get(ifs[i], NETOPT_PROTO, 0, &if_type, sizeof(if_type)) != -ENOTSUP) && (if_type == GNRC_NETTYPE_SIXLOWPAN)) { uint16_t src_len = 8; uint16_t max_frag_size = UINT16_MAX; DEBUG("ipv6 netif: Set 6LoWPAN flag\n"); ipv6_ifs[i].flags |= GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN; /* use EUI-64 (8-byte address) for IID generation and for sending * packets */ gnrc_netapi_set(ifs[i], NETOPT_SRC_LEN, 0, &src_len, sizeof(src_len)); /* don't care for result */ if (gnrc_netapi_get(ifs[i], NETOPT_MAX_PACKET_SIZE, 0, &max_frag_size, sizeof(max_frag_size)) < 0) { /* if error we assume it works */ DEBUG("ipv6 netif: Can not get max packet size from interface %" PRIkernel_pid "\n", ifs[i]); } gnrc_sixlowpan_netif_add(ifs[i], max_frag_size); } #endif if ((gnrc_netapi_get(ifs[i], NETOPT_IPV6_IID, 0, &iid, sizeof(eui64_t)) < 0)) { mutex_unlock(&ipv6_if->mutex); continue; } ipv6_addr_set_aiid(&addr, iid.uint8); ipv6_addr_set_link_local_prefix(&addr); _add_addr_to_entry(ipv6_if, &addr, 64, 0); mutex_unlock(&ipv6_if->mutex); } }
static void set_interface_roles(void) { kernel_pid_t ifs[GNRC_NETIF_NUMOF]; size_t numof = gnrc_netif_get(ifs); for (size_t i = 0; i < numof && i < GNRC_NETIF_NUMOF; i++) { kernel_pid_t dev = ifs[i]; int is_wired = gnrc_netapi_get(dev, NETOPT_IS_WIRED, 0, NULL, 0); if ((!gnrc_border_interface) && (is_wired == 1)) { ipv6_addr_t addr, defroute; gnrc_border_interface = dev; ipv6_addr_from_str(&addr, "fe80::2"); gnrc_ipv6_netif_add_addr(dev, &addr, 64, GNRC_IPV6_NETIF_ADDR_FLAGS_UNICAST); ipv6_addr_from_str(&defroute, "::"); ipv6_addr_from_str(&addr, "fe80::1"); fib_add_entry(&gnrc_ipv6_fib_table, dev, defroute.u8, 16, 0x00, addr.u8, 16, 0, (uint32_t)FIB_LIFETIME_NO_EXPIRE); } else if ((!gnrc_wireless_interface) && (is_wired != 1)) { gnrc_wireless_interface = dev; } if (gnrc_border_interface && gnrc_wireless_interface) { break; } } LOG_INFO("gnrc_uhcpc: Using %u as border interface and %u as wireless interface.\n", gnrc_border_interface, gnrc_wireless_interface); }
static bool _try_l2addr_reconfiguration(gnrc_netif_t *netif) { uint8_t hwaddr[GNRC_NETIF_L2ADDR_MAXLEN]; uint16_t hwaddr_len; if (gnrc_netapi_get(netif->pid, NETOPT_SRC_LEN, 0, &hwaddr_len, sizeof(hwaddr_len)) < 0) { return false; } luid_get(hwaddr, hwaddr_len); #if GNRC_IPV6_NIB_CONF_6LN if (hwaddr_len == IEEE802154_LONG_ADDRESS_LEN) { if (gnrc_netapi_set(netif->pid, NETOPT_ADDRESS_LONG, 0, hwaddr, hwaddr_len) < 0) { return false; } } else #endif if (gnrc_netapi_set(netif->pid, NETOPT_ADDRESS, 0, hwaddr, hwaddr_len) < 0) { return false; } return true; }
static struct ccnl_face_s *_intern_face_get(char *addr_str) { /* initialize address with 0xFF for broadcast */ size_t addr_len = (strlen(addr_str) + 1) / 3; uint8_t relay_addr[addr_len]; memset(relay_addr, UINT8_MAX, addr_len); addr_len = gnrc_netif_addr_from_str(relay_addr, sizeof(relay_addr), addr_str); if (addr_len == 0) { printf("Error: %s is not a valid link layer address\n", addr_str); return NULL; } sockunion sun; sun.sa.sa_family = AF_PACKET; memcpy(&(sun.linklayer.sll_addr), relay_addr, addr_len); sun.linklayer.sll_halen = addr_len; sun.linklayer.sll_protocol = htons(ETHERTYPE_NDN); int i; uint16_t devType; for(i = 0; i < ccnl_relay.ifcount; i++) { gnrc_netapi_get(ccnl_relay.ifs[i].if_pid, NETOPT_DEVICE_TYPE, 0, &devType, sizeof(devType)); if( (addr_len == 8 && devType == NETDEV2_TYPE_IEEE802154) || (addr_len == 6 && devType == NETDEV2_TYPE_ETHERNET) ) break; } return ccnl_get_face_or_create(&ccnl_relay, ccnl_relay.ifs[i].if_pid, &sun.sa, sizeof(sun.linklayer)); }
static int _netif_stats(kernel_pid_t iface, unsigned module, bool reset) { netstats_t *stats; int res = gnrc_netapi_get(iface, NETOPT_STATS, module, &stats, sizeof(&stats)); if (res < 0) { puts(" Protocol or device doesn't provide statistics."); } else if (reset) { memset(stats, 0, sizeof(netstats_t)); printf("Reset statistics for module %s!\n", _netstats_module_to_str(module)); } else { printf(" Statistics for %s\n" " RX packets %u bytes %u\n" " TX packets %u (Multicast: %u) bytes %u\n" " TX succeeded %u errors %u\n", _netstats_module_to_str(module), (unsigned) stats->rx_count, (unsigned) stats->rx_bytes, (unsigned) (stats->tx_unicast_count + stats->tx_mcast_count), (unsigned) stats->tx_mcast_count, (unsigned) stats->tx_bytes, (unsigned) stats->tx_success, (unsigned) stats->tx_failed); res = 0; } return res; }
int _cs(int argc, char **argv) { (void) argc; (void) argv; #if DOW_DEBUG gnrc_netapi_get(ccnl_pid, NETOPT_CCN, CCNL_CTX_PRINT_CS, &ccnl_relay, sizeof(ccnl_relay)); #else printf("%u CS command\n", (unsigned) xtimer_now().ticks32); //if ((dow_state != DOW_STATE_INACTIVE) && (dow_state != DOW_STATE_HANDOVER)) { if ((dow_state != DOW_STATE_INACTIVE) && (dow_state != DOW_STATE_STOPPED)) { gnrc_netapi_get(ccnl_pid, NETOPT_CCN, CCNL_CTX_PRINT_CS, &ccnl_relay, sizeof(ccnl_relay)); //ccnl_cs_dump(&ccnl_relay); printf("%u DONE\n", (unsigned) xtimer_now().ticks32); } else { puts("NOP"); } #endif return 0; }
gnrc_nettest_res_t gnrc_nettest_set(kernel_pid_t pid, netopt_t opt, uint16_t context, void *data, size_t data_len, int exp_res) { if (exp_res != gnrc_netapi_get(pid, opt, context, data, data_len)) { return GNRC_NETTEST_FAIL; } return GNRC_NETTEST_SUCCESS; }
static void _send(void *data, size_t len, char *dest, size_t *dest_len) { gnrc_pktsnip_t *payload = gnrc_pktbuf_add(NULL, data, len, GNRC_NETTYPE_UNDEF); gnrc_netapi_send(_kiss_pid, payload); // force an ack using gnrc_netapi_get gnrc_netapi_get(_kiss_pid, 0, 0, NULL, 0); // read back from the file *dest_len = (size_t) ftell(_kiss_file); fseek(_kiss_file, 0, SEEK_SET); fread(dest, 1, *dest_len, _kiss_file); }
static unsigned _netif_list_flag(kernel_pid_t iface, netopt_t opt, char *str, unsigned line_thresh) { netopt_enable_t enable = NETOPT_DISABLE; int res = gnrc_netapi_get(iface, opt, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("%s", str); line_thresh = _newline(_LINE_THRESHOLD, ++line_thresh); } return line_thresh; }
/* get the maximum allowed transfer unit to avoid 6Lo fragmentation */ static uint16_t _tftp_get_maximum_block_size(void) { uint16_t tmp; kernel_pid_t ifs[GNRC_NETIF_NUMOF]; size_t ifnum = gnrc_netif_get(ifs); if (ifnum > 0 && gnrc_netapi_get(ifs[0], NETOPT_MAX_PACKET_SIZE, 0, &tmp, sizeof(uint16_t)) >= 0) { /* TODO calculate proper block size */ return tmp - sizeof(udp_hdr_t) - sizeof(ipv6_hdr_t) - 10; } return GNRC_TFTP_MAX_TRANSFER_UNIT; }
/* tests getter */ static int test_get_addr(void) { uint8_t tmp[sizeof(_dev_addr)]; if (gnrc_netapi_get(_mac_pid, NETOPT_ADDRESS, 0, tmp, sizeof(tmp)) != sizeof(_dev_addr)) { puts("Error getting device address"); return 0; } else if (memcmp(tmp, _dev_addr, sizeof(_dev_addr)) != 0) { puts("Got wrong device address"); return 0; } return 1; }
void uhcp_handle_prefix(uint8_t *prefix, uint8_t prefix_len, uint16_t lifetime, uint8_t *src, uhcp_iface_t iface) { (void)prefix_len; (void)lifetime; (void)src; eui64_t iid; if (!gnrc_wireless_interface) { LOG_WARNING("gnrc_uhcpc: uhcp_handle_prefix(): received prefix, but don't know any wireless interface\n"); return; } if ((kernel_pid_t)iface != gnrc_border_interface) { LOG_WARNING("gnrc_uhcpc: uhcp_handle_prefix(): received prefix from unexpected interface\n"); return; } if (gnrc_netapi_get(gnrc_wireless_interface, NETOPT_IPV6_IID, 0, &iid, sizeof(eui64_t)) >= 0) { ipv6_addr_set_aiid((ipv6_addr_t*)prefix, iid.uint8); } else { LOG_WARNING("gnrc_uhcpc: uhcp_handle_prefix(): cannot get IID of wireless interface\n"); return; } if (ipv6_addr_equal(&_prefix, (ipv6_addr_t*)prefix)) { LOG_WARNING("gnrc_uhcpc: uhcp_handle_prefix(): got same prefix again\n"); return; } gnrc_ipv6_netif_add_addr(gnrc_wireless_interface, (ipv6_addr_t*)prefix, 64, GNRC_IPV6_NETIF_ADDR_FLAGS_UNICAST | GNRC_IPV6_NETIF_ADDR_FLAGS_NDP_AUTO); gnrc_ipv6_netif_remove_addr(gnrc_wireless_interface, &_prefix); print_str("gnrc_uhcpc: uhcp_handle_prefix(): configured new prefix "); ipv6_addr_print((ipv6_addr_t*)prefix); puts("/64"); if (!ipv6_addr_is_unspecified(&_prefix)) { gnrc_ipv6_netif_remove_addr(gnrc_wireless_interface, &_prefix); print_str("gnrc_uhcpc: uhcp_handle_prefix(): removed old prefix "); ipv6_addr_print(&_prefix); puts("/64"); } memcpy(&_prefix, prefix, 16); }
int main(void) { #ifdef WITH_SHELL /* initialize message queue */ msg_init_queue(_main_msg_q, Q_SZ); #endif eui64_t iid; // uint16_t chan = 15; netopt_enable_t acks = NETOPT_DISABLE; kernel_pid_t ifs[GNRC_NETIF_NUMOF]; gnrc_netif_get(ifs); gnrc_netapi_set(ifs[0], NETOPT_AUTOACK, 0, &acks, sizeof(acks)); // gnrc_netapi_set(ifs[0], NETOPT_CHANNEL, 0, &chan, sizeof(chan)); ipv6_addr_from_str(&dst_addr, "2001:affe:1234::1"); // ipv6_addr_from_str(&dst_addr, "fd38:3734:ad48:0:211d:50ce:a189:7cc4"); /* initialize senml payload */ gnrc_netapi_get(ifs[0], NETOPT_IPV6_IID, 0, &iid, sizeof(eui64_t)); initial_pos = sprintf(&p_buf[initial_pos], "[{\"bn\":\"urn:dev:mac:"); initial_pos += sprintf(&p_buf[initial_pos], "%02x%02x%02x%02x%02x%02x%02x%02x", iid.uint8[0], iid.uint8[1], iid.uint8[2], iid.uint8[3], iid.uint8[4], iid.uint8[5], iid.uint8[6], iid.uint8[7]); initial_pos += sprintf(&p_buf[initial_pos], "\"},"); /* initialize sensors */ hdc1000_init(&th_dev, HDC1000_I2C, HDC1000_ADDR); hdc1000_startmeasure(&th_dev); mpl3115a2_init(&p_dev, MPL3115A2_I2C, MPL3115A2_ADDR, MPL3115A2_OS_RATIO_DEFAULT); mpl3115a2_set_active(&p_dev); tcs37727_init(&light_dev, TCS37727_I2C, TCS37727_ADDR, TCS37727_ATIME_DEFAULT); tcs37727_set_rgbc_active(&light_dev); #ifdef WITH_SHELL thread_create(beac_stack, sizeof(beac_stack), PRIO, THREAD_CREATE_STACKTEST, beaconing, NULL, "beaconing"); char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); #else beaconing(NULL); #endif return 0; }
static int _netif_stats(kernel_pid_t dev, unsigned module, bool reset) { netstats_t *stats; int res = -ENOTSUP; if (module == NETSTATS_LAYER2) { res = gnrc_netapi_get(dev, NETOPT_STATS, 0, &stats, sizeof(&stats)); } #ifdef MODULE_NETSTATS_IPV6 else if (module == NETSTATS_IPV6) { stats = gnrc_ipv6_netif_get_stats(dev); if (stats != NULL) { res = 1; } } #endif if (res < 0) { puts(" Protocol or device doesn't provide statistics."); } else if (reset) { memset(stats, 0, sizeof(netstats_t)); printf("Reset statistics for module %s!\n", _netstats_module_to_str(module)); } else { printf(" Statistics for %s\n" " RX packets %u bytes %u\n" " TX packets %u (Multicast: %u) bytes %u\n" " TX succeeded %u errors %u\n", _netstats_module_to_str(module), (unsigned) stats->rx_count, (unsigned) stats->rx_bytes, (unsigned) (stats->tx_unicast_count + stats->tx_mcast_count), (unsigned) stats->tx_mcast_count, (unsigned) stats->tx_bytes, (unsigned) stats->tx_success, (unsigned) stats->tx_failed); res = 0; } return res; }
static int test_set_addr(void) { static const uint8_t new_addr[] = { 0x71, 0x29, 0x5b, 0xc8, 0x52, 0x65 }; uint8_t tmp[sizeof(new_addr)]; if (gnrc_netapi_set(_mac_pid, NETOPT_ADDRESS, 0, (void *)new_addr, sizeof(new_addr)) != sizeof(new_addr)) { puts("Error setting device address"); return 0; } if (gnrc_netapi_get(_mac_pid, NETOPT_ADDRESS, 0, tmp, sizeof(tmp)) != sizeof(tmp)) { puts("Error setting device address"); return 0; } else if (memcmp(tmp, new_addr, sizeof(new_addr)) != 0) { puts("Set to wrong device address"); return 0; } return 1; }
int main(void) { #ifdef WITH_SHELL /* initialize message queue */ msg_init_queue(_main_msg_q, Q_SZ); #endif eui64_t iid; // uint16_t chan = 15; netopt_enable_t acks = NETOPT_DISABLE; kernel_pid_t ifs[GNRC_NETIF_NUMOF]; gnrc_netif_get(ifs); gnrc_netapi_set(ifs[0], NETOPT_AUTOACK, 0, &acks, sizeof(acks)); ipv6_addr_from_str(&dst_addr, "2001:affe:1234::1"); // gnrc_netapi_set(ifs[0], NETOPT_CHANNEL, 0, &chan, sizeof(chan)); // ipv6_addr_from_str(&dst_addr, "fd38:3734:ad48:0:211d:50ce:a189:7cc4"); /* initialize senml payload */ gnrc_netapi_get(ifs[0], NETOPT_IPV6_IID, 0, &iid, sizeof(eui64_t)); initial_pos = sprintf(&p_buf[initial_pos], "[{\"bn\":\"urn:dev:mac:"); initial_pos += sprintf(&p_buf[initial_pos], "%02x%02x%02x%02x%02x%02x%02x%02x", iid.uint8[0], iid.uint8[1], iid.uint8[2], iid.uint8[3], iid.uint8[4], iid.uint8[5], iid.uint8[6], iid.uint8[7]); initial_pos += sprintf(&p_buf[initial_pos], "\"},"); thread_create(coap_stack, sizeof(coap_stack), PRIO - 1, THREAD_CREATE_STACKTEST, microcoap_server, NULL, "coap"); #ifdef WITH_SHELL thread_create(beac_stack, sizeof(beac_stack), PRIO, THREAD_CREATE_STACKTEST, beaconing, NULL, "beaconing"); char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); #else beaconing(NULL); #endif return 0; }
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_ndp_internal_send_nbr_sol(kernel_pid_t iface, ipv6_addr_t *src, ipv6_addr_t *tgt, ipv6_addr_t *dst) { #ifdef MODULE_GNRC_SIXLOWPAN_ND gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface); assert(ipv6_iface != NULL); #endif gnrc_pktsnip_t *hdr, *pkt = NULL; /* both suppressions, since they are needed in the MODULE_GNRC_SIXLOWPAN_ND branch */ /* cppcheck-suppress variableScope */ uint8_t l2src[8]; /* cppcheck-suppress variableScope */ size_t l2src_len = 0; DEBUG("ndp internal: send neighbor solicitation (iface: %" PRIkernel_pid ", src: %s, ", iface, ipv6_addr_to_str(addr_str, src, sizeof(addr_str))); DEBUG(" tgt: %s, ", ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s)\n", ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); /* check if there is a fitting source address to target */ if (src == NULL) { src = gnrc_ipv6_netif_find_best_src_addr(iface, tgt); } if (src != NULL) { l2src_len = _get_l2src(iface, l2src, sizeof(l2src)); if (l2src_len > 0) { /* add source address link-layer address option */ pkt = gnrc_ndp_opt_sl2a_build(l2src, l2src_len, NULL); if (pkt == NULL) { DEBUG("ndp internal: error allocating Source Link-layer address option.\n"); gnrc_pktbuf_release(pkt); return; } } } #ifdef MODULE_GNRC_SIXLOWPAN_ND if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) { if (l2src_len != sizeof(eui64_t)) { l2src_len = (uint16_t)gnrc_netapi_get(iface, NETOPT_ADDRESS_LONG, 0, l2src, sizeof(l2src)); if (l2src_len != sizeof(eui64_t)) { DEBUG("ndp internal: can't get EUI-64 of the interface\n"); gnrc_pktbuf_release(pkt); return; } } hdr = gnrc_sixlowpan_nd_opt_ar_build(0, GNRC_SIXLOWPAN_ND_AR_LTIME, (eui64_t *)l2src, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocatin Address Registration option.\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; } #endif hdr = gnrc_ndp_nbr_sol_build(tgt, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocating Neighbor solicitation.\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; hdr = _build_headers(iface, pkt, dst, src); if (hdr == NULL) { DEBUG("ndp internal: error adding lower-layer headers.\n"); gnrc_pktbuf_release(pkt); return; } else if (gnrc_netapi_send(gnrc_ipv6_pid, hdr) < 1) { DEBUG("ndp internal: unable to send neighbor solicitation\n"); gnrc_pktbuf_release(hdr); } }
static void _netif_list(kernel_pid_t iface) { #ifdef MODULE_GNRC_IPV6 ipv6_addr_t ipv6_addrs[GNRC_NETIF_IPV6_ADDRS_NUMOF]; ipv6_addr_t ipv6_groups[GNRC_NETIF_IPV6_GROUPS_NUMOF]; #endif uint8_t hwaddr[GNRC_NETIF_L2ADDR_MAXLEN]; uint32_t u32; uint16_t u16; int16_t i16; uint8_t u8; int res; netopt_state_t state; unsigned line_thresh = 1; printf("Iface %2d ", iface); res = gnrc_netapi_get(iface, NETOPT_ADDRESS, 0, hwaddr, sizeof(hwaddr)); if (res >= 0) { char hwaddr_str[res * 3]; printf(" HWaddr: %s ", gnrc_netif_addr_to_str(hwaddr, res, hwaddr_str)); } res = gnrc_netapi_get(iface, NETOPT_CHANNEL, 0, &u16, sizeof(u16)); if (res >= 0) { printf(" Channel: %" PRIu16 " ", u16); } res = gnrc_netapi_get(iface, NETOPT_CHANNEL_FREQUENCY, 0, &u32, sizeof(u32)); if (res >= 0) { printf(" Frequency: %" PRIu32 "Hz ", u32); } res = gnrc_netapi_get(iface, NETOPT_CHANNEL_PAGE, 0, &u16, sizeof(u16)); if (res >= 0) { printf(" Page: %" PRIu16 " ", u16); } res = gnrc_netapi_get(iface, NETOPT_NID, 0, &u16, sizeof(u16)); if (res >= 0) { printf(" NID: 0x%" PRIx16, u16); } res = gnrc_netapi_get(iface, NETOPT_BANDWIDTH, 0, &u8, sizeof(u8)); if (res >= 0) { printf(" BW: %skHz ", _netopt_bandwidth_str[u8]); } res = gnrc_netapi_get(iface, NETOPT_SPREADING_FACTOR, 0, &u8, sizeof(u8)); if (res >= 0) { printf(" SF: %u ", u8); } res = gnrc_netapi_get(iface, NETOPT_CODING_RATE, 0, &u8, sizeof(u8)); if (res >= 0) { printf(" CR: %s ", _netopt_coding_rate_str[u8]); } res = gnrc_netapi_get(iface, NETOPT_LINK_CONNECTED, 0, &u8, sizeof(u8)); if (res >= 0) { printf(" Link: %s ", (netopt_enable_t)u8 ? "up" : "down" ); } line_thresh = _newline(0U, line_thresh); res = gnrc_netapi_get(iface, NETOPT_ADDRESS_LONG, 0, hwaddr, sizeof(hwaddr)); if (res >= 0) { char hwaddr_str[res * 3]; printf("Long HWaddr: "); printf("%s ", gnrc_netif_addr_to_str(hwaddr, res, hwaddr_str)); line_thresh++; } line_thresh = _newline(0U, line_thresh); res = gnrc_netapi_get(iface, NETOPT_TX_POWER, 0, &i16, sizeof(i16)); if (res >= 0) { printf(" TX-Power: %" PRIi16 "dBm ", i16); } res = gnrc_netapi_get(iface, NETOPT_STATE, 0, &state, sizeof(state)); if (res >= 0) { printf(" State: %s ", _netopt_state_str[state]); line_thresh++; } res = gnrc_netapi_get(iface, NETOPT_RETRANS, 0, &u8, sizeof(u8)); if (res >= 0) { printf(" max. Retrans.: %u ", (unsigned)u8); line_thresh++; } res = gnrc_netapi_get(iface, NETOPT_CSMA_RETRIES, 0, &u8, sizeof(u8)); if (res >= 0) { netopt_enable_t enable = NETOPT_DISABLE; res = gnrc_netapi_get(iface, NETOPT_CSMA, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf(" CSMA Retries: %u ", (unsigned)u8); } line_thresh++; } line_thresh = _newline(0U, line_thresh); line_thresh = _netif_list_flag(iface, NETOPT_PROMISCUOUSMODE, "PROMISC ", line_thresh); line_thresh = _netif_list_flag(iface, NETOPT_AUTOACK, "AUTOACK ", line_thresh); line_thresh = _netif_list_flag(iface, NETOPT_ACK_REQ, "ACK_REQ ", line_thresh); line_thresh = _netif_list_flag(iface, NETOPT_PRELOADING, "PRELOAD ", line_thresh); line_thresh = _netif_list_flag(iface, NETOPT_RAWMODE, "RAWMODE ", line_thresh); line_thresh = _netif_list_flag(iface, NETOPT_MAC_NO_SLEEP, "MAC_NO_SLEEP ", line_thresh); line_thresh = _netif_list_flag(iface, NETOPT_CSMA, "CSMA ", line_thresh); line_thresh += _LINE_THRESHOLD + 1; /* enforce linebreak after this option */ line_thresh = _netif_list_flag(iface, NETOPT_AUTOCCA, "AUTOCCA", line_thresh); line_thresh = _netif_list_flag(iface, NETOPT_IQ_INVERT, "IQ_INVERT", line_thresh); line_thresh = _netif_list_flag(iface, NETOPT_SINGLE_RECEIVE, "RX_SINGLE", line_thresh); line_thresh = _netif_list_flag(iface, NETOPT_CHANNEL_HOP, "CHAN_HOP", line_thresh); res = gnrc_netapi_get(iface, NETOPT_MAX_PDU_SIZE, 0, &u16, sizeof(u16)); if (res > 0) { printf("L2-PDU:%" PRIu16 " ", u16); line_thresh++; } #ifdef MODULE_GNRC_IPV6 res = gnrc_netapi_get(iface, NETOPT_MAX_PDU_SIZE, GNRC_NETTYPE_IPV6, &u16, sizeof(u16)); if (res > 0) { printf("MTU:%" PRIu16 " ", u16); line_thresh++; } res = gnrc_netapi_get(iface, NETOPT_HOP_LIMIT, 0, &u8, sizeof(u8)); if (res > 0) { printf("HL:%u ", u8); line_thresh++; } line_thresh = _netif_list_flag(iface, NETOPT_IPV6_FORWARDING, "RTR ", line_thresh); #ifndef MODULE_GNRC_SIXLOWPAN_IPHC line_thresh += _LINE_THRESHOLD + 1; /* enforce linebreak after this option */ #endif line_thresh = _netif_list_flag(iface, NETOPT_IPV6_SND_RTR_ADV, "RTR_ADV ", line_thresh); #ifdef MODULE_GNRC_SIXLOWPAN line_thresh = _netif_list_flag(iface, NETOPT_6LO, "6LO ", line_thresh); #endif #ifdef MODULE_GNRC_SIXLOWPAN_IPHC line_thresh += _LINE_THRESHOLD + 1; /* enforce linebreak after this option */ line_thresh = _netif_list_flag(iface, NETOPT_6LO_IPHC, "IPHC ", line_thresh); #endif #endif res = gnrc_netapi_get(iface, NETOPT_SRC_LEN, 0, &u16, sizeof(u16)); if (res >= 0) { printf("Source address length: %" PRIu16 , u16); line_thresh++; } line_thresh = _newline(0U, line_thresh); #ifdef MODULE_GNRC_IPV6 printf("Link type: %s", (gnrc_netapi_get(iface, NETOPT_IS_WIRED, 0, &u16, sizeof(u16)) > 0) ? "wired" : "wireless"); line_thresh = _newline(0U, ++line_thresh); res = gnrc_netapi_get(iface, NETOPT_IPV6_ADDR, 0, ipv6_addrs, sizeof(ipv6_addrs)); if (res >= 0) { uint8_t ipv6_addrs_flags[GNRC_NETIF_IPV6_ADDRS_NUMOF]; memset(ipv6_addrs_flags, 0, sizeof(ipv6_addrs_flags)); /* assume it to succeed (otherwise array will stay 0) */ gnrc_netapi_get(iface, NETOPT_IPV6_ADDR_FLAGS, 0, ipv6_addrs_flags, sizeof(ipv6_addrs_flags)); /* yes, the res of NETOPT_IPV6_ADDR is meant to be here ;-) */ for (unsigned i = 0; i < (res / sizeof(ipv6_addr_t)); i++) { _netif_list_ipv6(&ipv6_addrs[i], ipv6_addrs_flags[i]); } } res = gnrc_netapi_get(iface, NETOPT_IPV6_GROUP, 0, ipv6_groups, sizeof(ipv6_groups)); if (res >= 0) { for (unsigned i = 0; i < (res / sizeof(ipv6_addr_t)); i++) { _netif_list_groups(&ipv6_groups[i]); } } #endif #ifdef MODULE_L2FILTER l2filter_t *filter = NULL; res = gnrc_netapi_get(iface, NETOPT_L2FILTER, 0, &filter, sizeof(filter)); if (res > 0) { #ifdef MODULE_L2FILTER_WHITELIST puts("\n White-listed link layer addresses:"); #else puts("\n Black-listed link layer addresses:"); #endif int count = 0; for (unsigned i = 0; i < L2FILTER_LISTSIZE; i++) { if (filter[i].addr_len > 0) { char hwaddr_str[filter[i].addr_len * 3]; gnrc_netif_addr_to_str(filter[i].addr, filter[i].addr_len, hwaddr_str); printf(" %2i: %s\n", count++, hwaddr_str); } } if (count == 0) { puts(" --- none ---"); } } #endif #ifdef MODULE_NETSTATS_L2 puts(""); _netif_stats(iface, NETSTATS_LAYER2, false); #endif #ifdef MODULE_NETSTATS_IPV6 _netif_stats(iface, NETSTATS_IPV6, false); #endif puts(""); }
uint8_t gnrc_sixlowpan_nd_opt_ar_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6, uint8_t icmpv6_type, sixlowpan_nd_opt_ar_t *ar_opt, uint8_t *sl2a, size_t sl2a_len) { eui64_t eui64; gnrc_ipv6_netif_t *ipv6_iface; gnrc_ipv6_nc_t *nc_entry; uint8_t status = 0; (void)sl2a; (void)sl2a_len; if (ar_opt->len != SIXLOWPAN_ND_OPT_AR_LEN) { /* discard silently: see https://tools.ietf.org/html/rfc6775#section-5.5.2 */ return 0; } if (gnrc_netapi_get(iface, NETOPT_ADDRESS_LONG, 0, &eui64, sizeof(eui64)) < 0) { /* discard silently: see https://tools.ietf.org/html/rfc6775#section-5.5.2 */ return 0; } ipv6_iface = gnrc_ipv6_netif_get(iface); nc_entry = gnrc_ipv6_nc_get(iface, &ipv6->src); switch (icmpv6_type) { case ICMPV6_NBR_ADV: if (!(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) { DEBUG("6lo nd: interface not a 6LoWPAN interface\n"); return 0; } if (eui64.uint64.u64 != ar_opt->eui64.uint64.u64) { /* discard silently: see https://tools.ietf.org/html/rfc6775#section-5.5.2 */ return 0; } switch (ar_opt->status) { case SIXLOWPAN_ND_STATUS_SUCCESS: DEBUG("6lo nd: address registration successful\n"); mutex_lock(&ipv6_iface->mutex); /* reschedule 1 minute before lifetime expires */ timex_t t = { (uint32_t)(byteorder_ntohs(ar_opt->ltime) - 1) * 60, 0 }; vtimer_remove(&nc_entry->nbr_sol_timer); vtimer_set_msg(&nc_entry->nbr_sol_timer, t, gnrc_ipv6_pid, GNRC_NDP_MSG_NBR_SOL_RETRANS, nc_entry); mutex_unlock(&ipv6_iface->mutex); break; case SIXLOWPAN_ND_STATUS_DUP: DEBUG("6lo nd: address registration determined duplicated\n"); /* TODO: handle DAD failed case */ gnrc_ipv6_netif_remove_addr(iface, &ipv6->dst); /* address should not be used anymore */ break; case SIXLOWPAN_ND_STATUS_NC_FULL: DEBUG("6lo nd: neighbor cache on router is full\n"); gnrc_ipv6_nc_remove(iface, &ipv6->src); /* try to find another router */ gnrc_sixlowpan_nd_init(ipv6_iface); break; default: DEBUG("6lo nd: unknown status for registration received\n"); break; } break; #ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER case ICMPV6_NBR_SOL: if (!(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) && !(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) { DEBUG("6lo nd: interface not a 6LoWPAN or forwarding interface\n"); return 0; } if ((ar_opt->status != 0) || ipv6_addr_is_unspecified(&ipv6->src)) { /* discard silently */ return 0; } /* TODO multihop DAD */ if ((nc_entry != NULL) && ((gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_REGISTERED) || (gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_TENTATIVE)) && ((nc_entry->eui64.uint64.u64 != 0) && (ar_opt->eui64.uint64.u64 != nc_entry->eui64.uint64.u64))) { /* there is already another node with this address */ DEBUG("6lo nd: duplicate address detected\n"); status = SIXLOWPAN_ND_STATUS_DUP; } else if ((nc_entry != NULL) && (ar_opt->ltime.u16 == 0)) { gnrc_ipv6_nc_remove(iface, &ipv6->src); /* TODO, notify routing protocol */ } else if (ar_opt->ltime.u16 != 0) { /* TODO: multihop DAD behavior */ uint16_t reg_ltime; if (nc_entry == NULL) { if ((nc_entry = gnrc_ipv6_nc_add(iface, &ipv6->src, sl2a, sl2a_len, GNRC_IPV6_NC_STATE_STALE)) == NULL) { DEBUG("6lo nd: neighbor cache is full\n"); return SIXLOWPAN_ND_STATUS_NC_FULL; } nc_entry->eui64 = ar_opt->eui64; } nc_entry->flags &= ~GNRC_IPV6_NC_TYPE_MASK; nc_entry->flags |= GNRC_IPV6_NC_TYPE_REGISTERED; reg_ltime = byteorder_ntohs(ar_opt->ltime); /* TODO: notify routing protocol */ vtimer_remove(&nc_entry->type_timeout); vtimer_set_msg(&nc_entry->type_timeout, timex_set(reg_ltime * 60, 0), gnrc_ipv6_pid, GNRC_SIXLOWPAN_ND_MSG_AR_TIMEOUT, nc_entry); } break; #endif default: break; } return status; }
/** @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); }
int watr_li_network_init (void) { DEBUG("%s()\n", __func__); kernel_pid_t ifs[GNRC_NETIF_NUMOF]; uint16_t channel = WATR_LI_CHANNEL; uint16_t pan_id = WATR_LI_PAN; if (0 >= gnrc_netif_get(ifs)) { puts ("[watr_li_network_init] ERROR: failed to get ifaces!"); return -1; } if (0 > gnrc_netapi_set(ifs[0], NETOPT_CHANNEL, 0, (uint16_t *)&channel, sizeof(uint16_t))) { puts ("[watr_li_network_init] ERROR: failed to set channel!"); return -1; } if (0 > gnrc_netapi_set(ifs[0], NETOPT_NID, 0, (uint16_t *)&pan_id, sizeof(uint16_t))) { puts ("[watr_li_network_init] ERROR: failed to set pan_id!"); return -1; } uint8_t iid[8]; if (0 > gnrc_netapi_get(ifs[0], NETOPT_IPV6_IID, 0, &iid, sizeof(iid))) { puts ("[watr_li_network_init] ERROR: failed to get IPv6 IID!"); return -1; } #ifdef WATR_LI_GLOBAL_IPV6 ipv6_addr_t myaddr; ipv6_addr_set_aiid(&myaddr, iid); myaddr.u64[0] = byteorder_htonll(0x2015110700000000); if (0 > gnrc_ipv6_netif_add_addr(ifs[0], &myaddr, 64, 0)) { puts ("[watr_li_network_init] ERROR: failed to set IPv6 addr!"); return -1; } #endif send_sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (send_sock < 0) { puts("[watr_li_network_init] ERROR: initializing send socket!"); return -1; } /* FIXME stringify my_id. we'll be needing this in a sec. */ memset(my_id, 0, sizeof(my_id)); sprintf(my_id, "%02X%02X%02X%02X%02X%02X%02X%02X", iid[0],iid[1],iid[2],iid[3],iid[4],iid[5],iid[6],iid[7]); /* Add my_id to humidity_path */ register_path = (coap_endpoint_path_t) {1, {"nodes"}}; //FIXME: should be nodes/my_id ? humidity_path = (coap_endpoint_path_t) {3, {"nodes", my_id, "humidity"}}; if (0 > watr_li_set_root_addr(watr_li_root_addr_str)) { puts("[watr_li_network_init] ERROR: failed to set root_addr!"); return -1; } if (0 > watr_li_register_at_root(my_id)) { puts("[watr_li_network_init] ERROR: failed to register at root!"); return -1; } return 0; }
void gnrc_ipv6_netif_init_by_dev(void) { kernel_pid_t ifs[GNRC_NETIF_NUMOF]; size_t ifnum = gnrc_netif_get(ifs); #ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER bool abr_init = false; #endif for (size_t i = 0; i < ifnum; i++) { ipv6_addr_t addr; eui64_t iid; uint16_t tmp; gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(ifs[i]); if (ipv6_if == NULL) { continue; } mutex_lock(&ipv6_if->mutex); #ifdef MODULE_GNRC_SIXLOWPAN gnrc_nettype_t if_type = GNRC_NETTYPE_UNDEF; if ((gnrc_netapi_get(ifs[i], NETOPT_PROTO, 0, &if_type, sizeof(if_type)) != -ENOTSUP) && (if_type == GNRC_NETTYPE_SIXLOWPAN)) { uint16_t src_len = 8; uint16_t max_frag_size = UINT16_MAX; DEBUG("ipv6 netif: Set 6LoWPAN flag\n"); ipv6_ifs[i].flags |= GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN; /* the router flag must be set early here, because otherwise * _add_addr_to_entry() wouldn't set the solicited node address. * However, addresses have to be configured before calling * gnrc_ipv6_netif_set_router(). */ #ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER DEBUG("ipv6 netif: Set router flag\n"); ipv6_ifs[i].flags |= GNRC_IPV6_NETIF_FLAGS_ROUTER; #endif /* use EUI-64 (8-byte address) for IID generation and for sending * packets */ gnrc_netapi_set(ifs[i], NETOPT_SRC_LEN, 0, &src_len, sizeof(src_len)); /* don't care for result */ if (gnrc_netapi_get(ifs[i], NETOPT_MAX_PACKET_SIZE, 0, &max_frag_size, sizeof(max_frag_size)) < 0) { /* if error we assume it works */ DEBUG("ipv6 netif: Can not get max packet size from interface %" PRIkernel_pid "\n", ifs[i]); } gnrc_sixlowpan_netif_add(ifs[i], max_frag_size); } #endif /* set link-local address */ if ((gnrc_netapi_get(ifs[i], NETOPT_IPV6_IID, 0, &iid, sizeof(eui64_t)) < 0)) { mutex_unlock(&ipv6_if->mutex); continue; } ipv6_addr_set_aiid(&addr, iid.uint8); ipv6_addr_set_link_local_prefix(&addr); _add_addr_to_entry(ipv6_if, &addr, 64, 0); /* set link MTU */ if ((gnrc_netapi_get(ifs[i], NETOPT_MAX_PACKET_SIZE, 0, &tmp, sizeof(uint16_t)) >= 0)) { if (tmp >= IPV6_MIN_MTU) { ipv6_if->mtu = tmp; } /* otherwise leave at GNRC_IPV6_NETIF_DEFAULT_MTU as initialized in * gnrc_ipv6_netif_add() */ } if (gnrc_netapi_get(ifs[i], NETOPT_IS_WIRED, 0, &tmp, sizeof(int)) > 0) { ipv6_if->flags |= GNRC_IPV6_NETIF_FLAGS_IS_WIRED; } else { ipv6_if->flags &= ~GNRC_IPV6_NETIF_FLAGS_IS_WIRED; } mutex_unlock(&ipv6_if->mutex); #if (defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER)) gnrc_ipv6_netif_set_router(ipv6_if, true); #endif #ifdef MODULE_GNRC_SIXLOWPAN_ND if (ipv6_if->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) { #ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER /* first interface wins */ if (!abr_init) { gnrc_sixlowpan_nd_router_abr_create(&addr, 0); gnrc_ipv6_netif_set_rtr_adv(ipv6_if, true); abr_init = true; } #endif gnrc_sixlowpan_nd_init(ipv6_if); continue; /* skip gnrc_ndp_host_init() */ } #endif #ifdef MODULE_GNRC_NDP_HOST /* start periodic router solicitations */ gnrc_ndp_host_init(ipv6_if); #endif } }
/** @todo allow target prefixes in target options to be of variable length */ bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt_t *opt, uint16_t len, ipv6_addr_t *src, uint32_t *included_opts) { uint16_t l = 0; gnrc_rpl_opt_target_t *first_target = NULL; gnrc_rpl_dodag_t *dodag = &inst->dodag; eui64_t iid; *included_opts = 0; ipv6_addr_t *me; if (!_gnrc_rpl_check_options_validity(msg_type, inst, opt, len)) { return false; } while(l < len) { switch(opt->type) { case (GNRC_RPL_OPT_PAD1): DEBUG("RPL: PAD1 option parsed\n"); *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_PAD1; l += 1; opt = (gnrc_rpl_opt_t *) (((uint8_t *) opt) + 1); continue; case (GNRC_RPL_OPT_PADN): DEBUG("RPL: PADN option parsed\n"); *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_PADN; break; case (GNRC_RPL_OPT_DODAG_CONF): DEBUG("RPL: DODAG CONF DIO option parsed\n"); *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_DODAG_CONF; dodag->dio_opts |= GNRC_RPL_REQ_DIO_OPT_DODAG_CONF; 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) { inst->of = of; } else { DEBUG("RPL: Unsupported OCP 0x%02x\n", byteorder_ntohs(dc->ocp)); inst->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; inst->max_rank_inc = byteorder_ntohs(dc->max_rank_inc); inst->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"); *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_PREFIX_INFO; #ifndef GNRC_RPL_WITHOUT_PIO dodag->dio_opts |= GNRC_RPL_REQ_DIO_OPT_PREFIX_INFO; #endif gnrc_rpl_opt_prefix_info_t *pi = (gnrc_rpl_opt_prefix_info_t *) opt; /* check for the auto address-configuration flag */ if ((gnrc_netapi_get(dodag->iface, 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); me = gnrc_ipv6_netif_add_addr(dodag->iface, &pi->prefix, pi->prefix_len, 0); if (me) { dodag->netif_addr = gnrc_ipv6_netif_addr_get(me); } break; case (GNRC_RPL_OPT_TARGET): DEBUG("RPL: RPL TARGET DAO option parsed\n"); *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_TARGET; gnrc_rpl_opt_target_t *target = (gnrc_rpl_opt_target_t *) opt; if (first_target == NULL) { first_target = target; } uint32_t fib_dst_flags = 0; if (target->prefix_length < IPV6_ADDR_BIT_LEN) { fib_dst_flags = ((uint32_t)(target->prefix_length) << FIB_FLAG_NET_PREFIX_SHIFT); } DEBUG("RPL: adding fib entry %s/%d 0x%" PRIx32 "\n", ipv6_addr_to_str(addr_str, &(target->target), sizeof(addr_str)), target->prefix_length, fib_dst_flags); fib_add_entry(&gnrc_ipv6_fib_table, dodag->iface, target->target.u8, sizeof(ipv6_addr_t), fib_dst_flags, src->u8, sizeof(ipv6_addr_t), FIB_FLAG_RPL_ROUTE, (dodag->default_lifetime * dodag->lifetime_unit) * SEC_IN_MS); break; case (GNRC_RPL_OPT_TRANSIT): DEBUG("RPL: RPL TRANSIT INFO DAO option parsed\n"); *included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_TRANSIT; 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 { DEBUG("RPL: updating fib entry %s/%d\n", ipv6_addr_to_str(addr_str, &(first_target->target), sizeof(addr_str)), first_target->prefix_length); fib_update_entry(&gnrc_ipv6_fib_table, first_target->target.u8, sizeof(ipv6_addr_t), src->u8, sizeof(ipv6_addr_t), ((transit->e_flags & GNRC_RPL_OPT_TRANSIT_E_FLAG) ? 0x0 : FIB_FLAG_RPL_ROUTE), (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; #ifdef MODULE_GNRC_RPL_P2P case (GNRC_RPL_P2P_OPT_RDO): gnrc_rpl_p2p_rdo_parse((gnrc_rpl_p2p_opt_rdo_t *) opt, gnrc_rpl_p2p_ext_get(dodag)); break; #endif } l += opt->length + sizeof(gnrc_rpl_opt_t); opt = (gnrc_rpl_opt_t *) (((uint8_t *) (opt + 1)) + opt->length); } return true; }
static void _netif_list(kernel_pid_t dev) { uint8_t hwaddr[MAX_ADDR_LEN]; uint16_t u16; int16_t i16; int res; netopt_state_t state; netopt_enable_t enable; bool linebreak = false; #ifdef MODULE_GNRC_IPV6_NETIF gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(dev); char ipv6_addr[IPV6_ADDR_MAX_STR_LEN]; #endif printf("Iface %2d ", dev); res = gnrc_netapi_get(dev, NETOPT_ADDRESS, 0, hwaddr, sizeof(hwaddr)); if (res >= 0) { char hwaddr_str[res * 3]; printf(" HWaddr: "); printf("%s", gnrc_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str), hwaddr, res)); printf(" "); } res = gnrc_netapi_get(dev, NETOPT_CHANNEL, 0, &u16, sizeof(u16)); if (res >= 0) { printf(" Channel: %" PRIu16 " ", u16); } res = gnrc_netapi_get(dev, NETOPT_NID, 0, &u16, sizeof(u16)); if (res >= 0) { printf(" NID: 0x%" PRIx16 " ", u16); } res = gnrc_netapi_get(dev, NETOPT_TX_POWER, 0, &i16, sizeof(i16)); if (res >= 0) { printf(" TX-Power: %" PRIi16 "dBm ", i16); } res = gnrc_netapi_get(dev, NETOPT_STATE, 0, &state, sizeof(state)); if (res >= 0) { printf(" State: "); _print_netopt_state(state); } printf("\n "); res = gnrc_netapi_get(dev, NETOPT_ADDRESS_LONG, 0, hwaddr, sizeof(hwaddr)); if (res >= 0) { char hwaddr_str[res * 3]; printf("Long HWaddr: "); printf("%s", gnrc_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str), hwaddr, res)); printf("\n "); } res = gnrc_netapi_get(dev, NETOPT_PROMISCUOUSMODE, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("PROMISC "); linebreak = true; } res = gnrc_netapi_get(dev, NETOPT_AUTOACK, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("AUTOACK "); linebreak = true; } res = gnrc_netapi_get(dev, NETOPT_PRELOADING, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("PRELOAD "); linebreak = true; } res = gnrc_netapi_get(dev, NETOPT_RAWMODE, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("RAWMODE "); linebreak = true; } #ifdef MODULE_GNRC_IPV6_NETIF if ((entry != NULL) && (entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) { printf("6LO "); linebreak = true; } #endif #if defined(MODULE_GNRC_SIXLOWPAN_NETIF) && defined(MODULE_GNRC_SIXLOWPAN_IPHC) gnrc_sixlowpan_netif_t *sixlo_entry = gnrc_sixlowpan_netif_get(dev); if ((sixlo_entry != NULL) && (sixlo_entry->iphc_enabled)) { printf("IPHC "); linebreak = true; } #endif if (linebreak) { printf("\n "); } res = gnrc_netapi_get(dev, NETOPT_SRC_LEN, 0, &u16, sizeof(u16)); if (res >= 0) { printf("Source address length: %" PRIu16 "\n ", u16); } #ifdef MODULE_GNRC_IPV6_NETIF for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) { if (!ipv6_addr_is_unspecified(&entry->addrs[i].addr)) { printf("inet6 addr: "); if (ipv6_addr_to_str(ipv6_addr, &entry->addrs[i].addr, IPV6_ADDR_MAX_STR_LEN)) { printf("%s/%" PRIu8 " scope: ", ipv6_addr, entry->addrs[i].prefix_len); if ((ipv6_addr_is_link_local(&entry->addrs[i].addr))) { printf("local"); } else { printf("global"); } if (entry->addrs[i].flags & GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST) { if (ipv6_addr_is_multicast(&entry->addrs[i].addr)) { printf(" [multicast]"); } else { printf(" [anycast]"); } } } else { printf("error in conversion"); } printf("\n "); } } #endif puts(""); }
static void _netif_list(kernel_pid_t dev) { uint8_t hwaddr[MAX_ADDR_LEN]; uint16_t u16; int16_t i16; uint8_t u8; int res; netopt_state_t state; netopt_enable_t enable = NETOPT_DISABLE; bool linebreak = false; #ifdef MODULE_GNRC_IPV6_NETIF gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(dev); char ipv6_addr[IPV6_ADDR_MAX_STR_LEN]; #endif printf("Iface %2d ", dev); res = gnrc_netapi_get(dev, NETOPT_ADDRESS, 0, hwaddr, sizeof(hwaddr)); if (res >= 0) { char hwaddr_str[res * 3]; printf(" HWaddr: "); printf("%s", gnrc_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str), hwaddr, res)); printf(" "); } res = gnrc_netapi_get(dev, NETOPT_CHANNEL, 0, &u16, sizeof(u16)); if (res >= 0) { printf(" Channel: %" PRIu16 " ", u16); } res = gnrc_netapi_get(dev, NETOPT_CHANNEL_PAGE, 0, &u16, sizeof(u16)); if (res >= 0) { printf(" Page: %" PRIu16 " ", u16); } res = gnrc_netapi_get(dev, NETOPT_NID, 0, &u16, sizeof(u16)); if (res >= 0) { printf(" NID: 0x%" PRIx16, u16); } printf("\n "); res = gnrc_netapi_get(dev, NETOPT_ADDRESS_LONG, 0, hwaddr, sizeof(hwaddr)); if (res >= 0) { char hwaddr_str[res * 3]; printf("Long HWaddr: "); printf("%s ", gnrc_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str), hwaddr, res)); linebreak = true; } if (linebreak) { printf("\n "); } res = gnrc_netapi_get(dev, NETOPT_TX_POWER, 0, &i16, sizeof(i16)); if (res >= 0) { printf(" TX-Power: %" PRIi16 "dBm ", i16); } res = gnrc_netapi_get(dev, NETOPT_STATE, 0, &state, sizeof(state)); if (res >= 0) { printf(" State: "); _print_netopt_state(state); printf(" "); } res = gnrc_netapi_get(dev, NETOPT_RETRANS, 0, &u8, sizeof(u8)); if (res >= 0) { printf(" max. Retrans.: %u ", (unsigned)u8); } res = gnrc_netapi_get(dev, NETOPT_CSMA_RETRIES, 0, &u8, sizeof(u8)); if (res >= 0) { res = gnrc_netapi_get(dev, NETOPT_CSMA, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf(" CSMA Retries: %u ", (unsigned)u8); } } printf("\n "); res = gnrc_netapi_get(dev, NETOPT_PROMISCUOUSMODE, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("PROMISC "); linebreak = true; } res = gnrc_netapi_get(dev, NETOPT_AUTOACK, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("AUTOACK "); linebreak = true; } res = gnrc_netapi_get(dev, NETOPT_ACK_REQ, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("ACK_REQ "); linebreak = true; } res = gnrc_netapi_get(dev, NETOPT_PRELOADING, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("PRELOAD "); linebreak = true; } res = gnrc_netapi_get(dev, NETOPT_RAWMODE, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("RAWMODE "); linebreak = true; } res = gnrc_netapi_get(dev, NETOPT_CSMA, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("CSMA "); linebreak = true; } res = gnrc_netapi_get(dev, NETOPT_AUTOCCA, 0, &enable, sizeof(enable)); if ((res >= 0) && (enable == NETOPT_ENABLE)) { printf("AUTOCCA "); linebreak = true; } #ifdef MODULE_GNRC_IPV6_NETIF if (entry != NULL) { printf("MTU:%" PRIu16 " ", entry->mtu); printf("HL:%u ", (unsigned)entry->cur_hl); if (entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) { printf("6LO "); } if (entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) { printf("RTR "); } if (entry->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV) { printf("RTR_ADV "); } linebreak = true; } #endif #if defined(MODULE_GNRC_SIXLOWPAN_NETIF) && defined(MODULE_GNRC_SIXLOWPAN_IPHC) gnrc_sixlowpan_netif_t *sixlo_entry = gnrc_sixlowpan_netif_get(dev); if ((sixlo_entry != NULL) && (sixlo_entry->iphc_enabled)) { printf("IPHC "); linebreak = true; } #endif if (linebreak) { printf("\n "); } res = gnrc_netapi_get(dev, NETOPT_SRC_LEN, 0, &u16, sizeof(u16)); if (res >= 0) { printf("Source address length: %" PRIu16 "\n ", u16); } #ifdef MODULE_GNRC_IPV6_NETIF if (entry == NULL) { puts(""); return; } printf("Link type: %s", (entry->flags & GNRC_IPV6_NETIF_FLAGS_IS_WIRED) ? "wired" : "wireless"); printf("\n "); for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) { if (!ipv6_addr_is_unspecified(&entry->addrs[i].addr)) { printf("inet6 addr: "); if (ipv6_addr_to_str(ipv6_addr, &entry->addrs[i].addr, IPV6_ADDR_MAX_STR_LEN)) { printf("%s/%u scope: ", ipv6_addr, (unsigned)entry->addrs[i].prefix_len); if ((ipv6_addr_is_link_local(&entry->addrs[i].addr))) { printf("local"); } else { printf("global"); } if (entry->addrs[i].flags & GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST) { if (ipv6_addr_is_multicast(&entry->addrs[i].addr)) { printf(" [multicast]"); } else { printf(" [anycast]"); } } } else { printf("error in conversion"); } printf("\n "); } } #endif #ifdef MODULE_L2FILTER l2filter_t *filter = NULL; res = gnrc_netapi_get(dev, NETOPT_L2FILTER, 0, &filter, sizeof(filter)); if (res > 0) { #ifdef MODULE_L2FILTER_WHITELIST puts("\n White-listed link layer addresses:"); #else puts("\n Black-listed link layer addresses:"); #endif int count = 0; for (unsigned i = 0; i < L2FILTER_LISTSIZE; i++) { if (filter[i].addr_len > 0) { char hwaddr_str[filter[i].addr_len * 3]; gnrc_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str), filter[i].addr, filter[i].addr_len); printf(" %2i: %s\n", count++, hwaddr_str); } } if (count == 0) { puts(" --- none ---"); } } #endif #ifdef MODULE_NETSTATS_L2 puts(""); _netif_stats(dev, NETSTATS_LAYER2, false); #endif #ifdef MODULE_NETSTATS_IPV6 _netif_stats(dev, NETSTATS_IPV6, false); #endif puts(""); }