void _handle_snd_mc_ra(gnrc_netif_t *netif) { gnrc_netif_acquire(netif); assert(netif != NULL); if (!gnrc_netif_is_6ln(netif)) { bool final_ra = (netif->ipv6.ra_sent > (UINT8_MAX - NDP_MAX_FIN_RA_NUMOF)); uint32_t next_ra_time = random_uint32_range(NDP_MIN_RA_INTERVAL_MS, NDP_MAX_RA_INTERVAL_MS); uint32_t next_scheduled = _evtimer_lookup(netif, GNRC_IPV6_NIB_SND_MC_RA); /* router has router advertising interface or the RA is one of the * (now deactivated) routers final one (and there is no next * scheduled within the possible time for next_ra_time) */ if ((final_ra && (next_scheduled > NDP_MAX_RA_INTERVAL_MS)) || gnrc_netif_is_rtr_adv(netif)) { _snd_rtr_advs(netif, NULL, final_ra); netif->ipv6.last_ra = (xtimer_now_usec64() / US_PER_MS) & UINT32_MAX; if ((netif->ipv6.ra_sent < NDP_MAX_INIT_RA_NUMOF) || final_ra) { if ((netif->ipv6.ra_sent < NDP_MAX_INIT_RA_NUMOF) && (next_ra_time > NDP_MAX_INIT_RA_INTERVAL)) { next_ra_time = NDP_MAX_INIT_RA_INTERVAL; } netif->ipv6.ra_sent++; } /* netif->ipv6.ra_sent overflowed => this was our last final RA */ if (netif->ipv6.ra_sent != 0) { _evtimer_add(netif, GNRC_IPV6_NIB_SND_MC_RA, &netif->ipv6.snd_mc_ra, next_ra_time); } } } gnrc_netif_release(netif); }
void _handle_reply_rs(_nib_onl_entry_t *host) { gnrc_netif_t *netif = gnrc_netif_get_by_pid(_nib_onl_get_if(host)); assert(netif != NULL); gnrc_netif_acquire(netif); if (gnrc_netif_is_rtr_adv(netif)) { _snd_rtr_advs(netif, &host->ipv6, false); } gnrc_netif_release(netif); }
int gnrc_netif_get_from_netdev(gnrc_netif_t *netif, gnrc_netapi_opt_t *opt) { int res = -ENOTSUP; gnrc_netif_acquire(netif); switch (opt->opt) { case NETOPT_HOP_LIMIT: assert(opt->data_len == sizeof(uint8_t)); *((uint8_t *)opt->data) = netif->cur_hl; res = sizeof(uint8_t); break; case NETOPT_STATS: /* XXX discussed this with Oleg, it's supposed to be a pointer */ switch ((int16_t)opt->context) { #if defined(MODULE_NETSTATS_IPV6) && defined(MODULE_GNRC_IPV6) case NETSTATS_IPV6: assert(opt->data_len == sizeof(netstats_t *)); *((netstats_t **)opt->data) = &netif->ipv6.stats; res = sizeof(&netif->ipv6.stats); break; #endif default: /* take from device */ break; } break; #ifdef MODULE_GNRC_IPV6 case NETOPT_IPV6_ADDR: { assert(opt->data_len >= sizeof(ipv6_addr_t)); ipv6_addr_t *tgt = opt->data; res = 0; for (unsigned i = 0; (res < (int)opt->data_len) && (i < GNRC_NETIF_IPV6_ADDRS_NUMOF); i++) { if (netif->ipv6.addrs_flags[i] != 0) { memcpy(tgt, &netif->ipv6.addrs[i], sizeof(ipv6_addr_t)); res += sizeof(ipv6_addr_t); tgt++; } } } break; case NETOPT_IPV6_ADDR_FLAGS: { assert(opt->data_len >= sizeof(uint8_t)); uint8_t *tgt = opt->data; res = 0; for (unsigned i = 0; (res < (int)opt->data_len) && (i < GNRC_NETIF_IPV6_ADDRS_NUMOF); i++) { if (netif->ipv6.addrs_flags[i] != 0) { *tgt = netif->ipv6.addrs_flags[i]; res += sizeof(uint8_t); tgt++; } } } break; case NETOPT_IPV6_GROUP: { assert(opt->data_len >= sizeof(ipv6_addr_t)); ipv6_addr_t *tgt = opt->data; res = 0; for (unsigned i = 0; (res < (int)opt->data_len) && (i < GNRC_NETIF_IPV6_GROUPS_NUMOF); i++) { if (!ipv6_addr_is_unspecified(&netif->ipv6.groups[i])) { memcpy(tgt, &netif->ipv6.groups[i], sizeof(ipv6_addr_t)); res += sizeof(ipv6_addr_t); tgt++; } } } break; case NETOPT_IPV6_IID: assert(opt->data_len >= sizeof(eui64_t)); if (gnrc_netif_ipv6_get_iid(netif, opt->data) == 0) { res = sizeof(eui64_t); } break; case NETOPT_MAX_PACKET_SIZE: if (opt->context == GNRC_NETTYPE_IPV6) { assert(opt->data_len == sizeof(uint16_t)); *((uint16_t *)opt->data) = netif->ipv6.mtu; res = sizeof(uint16_t); } /* else ask device */ break; #if GNRC_IPV6_NIB_CONF_ROUTER case NETOPT_IPV6_FORWARDING: assert(opt->data_len == sizeof(netopt_enable_t)); *((netopt_enable_t *)opt->data) = (gnrc_netif_is_rtr(netif)) ? NETOPT_ENABLE : NETOPT_DISABLE; res = sizeof(netopt_enable_t); break; case NETOPT_IPV6_SND_RTR_ADV: assert(opt->data_len == sizeof(netopt_enable_t)); *((netopt_enable_t *)opt->data) = (gnrc_netif_is_rtr_adv(netif)) ? NETOPT_ENABLE : NETOPT_DISABLE; res = sizeof(netopt_enable_t); break; #endif /* GNRC_IPV6_NIB_CONF_ROUTER */ #endif /* MODULE_GNRC_IPV6 */ #ifdef MODULE_GNRC_SIXLOWPAN_IPHC case NETOPT_6LO_IPHC: assert(opt->data_len == sizeof(netopt_enable_t)); *((netopt_enable_t *)opt->data) = (netif->flags & GNRC_NETIF_FLAGS_6LO_HC) ? NETOPT_ENABLE : NETOPT_DISABLE; res = sizeof(netopt_enable_t); break; #endif /* MODULE_GNRC_SIXLOWPAN_IPHC */ default: break; } if (res == -ENOTSUP) { res = netif->dev->driver->get(netif->dev, opt->opt, opt->data, opt->data_len); } gnrc_netif_release(netif); return res; }
int gnrc_netif_set_from_netdev(gnrc_netif_t *netif, const gnrc_netapi_opt_t *opt) { int res = -ENOTSUP; gnrc_netif_acquire(netif); switch (opt->opt) { case NETOPT_HOP_LIMIT: assert(opt->data_len == sizeof(uint8_t)); netif->cur_hl = *((uint8_t *)opt->data); res = sizeof(uint8_t); break; #ifdef MODULE_GNRC_IPV6 case NETOPT_IPV6_ADDR: { assert(opt->data_len == sizeof(ipv6_addr_t)); /* always assume manually added */ uint8_t flags = ((((uint8_t)opt->context & 0xff) & ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK) | GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID); uint8_t pfx_len = (uint8_t)(opt->context >> 8U); /* acquire locks a recursive mutex so we are safe calling this * public function */ res = gnrc_netif_ipv6_addr_add_internal(netif, opt->data, pfx_len, flags); if (res >= 0) { res = sizeof(ipv6_addr_t); } } break; case NETOPT_IPV6_ADDR_REMOVE: assert(opt->data_len == sizeof(ipv6_addr_t)); /* acquire locks a recursive mutex so we are safe calling this * public function */ gnrc_netif_ipv6_addr_remove_internal(netif, opt->data); res = sizeof(ipv6_addr_t); break; case NETOPT_IPV6_GROUP: assert(opt->data_len == sizeof(ipv6_addr_t)); /* acquire locks a recursive mutex so we are safe calling this * public function */ res = gnrc_netif_ipv6_group_join_internal(netif, opt->data); if (res >= 0) { res = sizeof(ipv6_addr_t); } break; case NETOPT_IPV6_GROUP_LEAVE: assert(opt->data_len == sizeof(ipv6_addr_t)); /* acquire locks a recursive mutex so we are safe calling this * public function */ gnrc_netif_ipv6_group_leave_internal(netif, opt->data); res = sizeof(ipv6_addr_t); break; case NETOPT_MAX_PACKET_SIZE: if (opt->context == GNRC_NETTYPE_IPV6) { assert(opt->data_len == sizeof(uint16_t)); netif->ipv6.mtu = *((uint16_t *)opt->data); res = sizeof(uint16_t); } /* else set device */ break; #if GNRC_IPV6_NIB_CONF_ROUTER case NETOPT_IPV6_FORWARDING: assert(opt->data_len == sizeof(netopt_enable_t)); if (*(((netopt_enable_t *)opt->data)) == NETOPT_ENABLE) { netif->flags |= GNRC_NETIF_FLAGS_IPV6_FORWARDING; } else { if (gnrc_netif_is_rtr_adv(netif)) { gnrc_ipv6_nib_change_rtr_adv_iface(netif, false); } netif->flags &= ~GNRC_NETIF_FLAGS_IPV6_FORWARDING; } res = sizeof(netopt_enable_t); break; case NETOPT_IPV6_SND_RTR_ADV: assert(opt->data_len == sizeof(netopt_enable_t)); gnrc_ipv6_nib_change_rtr_adv_iface(netif, (*(((netopt_enable_t *)opt->data)) == NETOPT_ENABLE)); res = sizeof(netopt_enable_t); break; #endif /* GNRC_IPV6_NIB_CONF_ROUTER */ #endif /* MODULE_GNRC_IPV6 */ #ifdef MODULE_GNRC_SIXLOWPAN_IPHC case NETOPT_6LO_IPHC: assert(opt->data_len == sizeof(netopt_enable_t)); if (*(((netopt_enable_t *)opt->data)) == NETOPT_ENABLE) { netif->flags |= GNRC_NETIF_FLAGS_6LO_HC; } else { netif->flags &= ~GNRC_NETIF_FLAGS_6LO_HC; } res = sizeof(netopt_enable_t); break; #endif /* MODULE_GNRC_SIXLOWPAN_IPHC */ default: break; } if (res == -ENOTSUP) { res = netif->dev->driver->set(netif->dev, opt->opt, opt->data, opt->data_len); if (res > 0) { switch (opt->opt) { case NETOPT_ADDRESS: case NETOPT_ADDRESS_LONG: case NETOPT_ADDR_LEN: case NETOPT_SRC_LEN: _update_l2addr_from_dev(netif); break; default: break; } } } gnrc_netif_release(netif); return res; }