static ng_ipv6_addr_t *_add_addr_to_entry(ng_ipv6_netif_t *entry, const ng_ipv6_addr_t *addr, uint8_t prefix_len, uint8_t flags) { ng_ipv6_netif_addr_t *tmp_addr = NULL; for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) { if (ng_ipv6_addr_equal(&(entry->addrs[i].addr), addr)) { return &(entry->addrs[i].addr); } if (ng_ipv6_addr_is_unspecified(&(entry->addrs[i].addr)) && !tmp_addr) { tmp_addr = &(entry->addrs[i]); } } if (!tmp_addr) { DEBUG("ipv6 netif: couldn't add %s/%" PRIu8 " to interface %" PRIkernel_pid "\n: No space left.", ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), prefix_len, entry->pid); return NULL; } memcpy(&(tmp_addr->addr), addr, sizeof(ng_ipv6_addr_t)); DEBUG("ipv6 netif: Added %s/%" PRIu8 " to interface %" PRIkernel_pid "\n", ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), prefix_len, entry->pid); tmp_addr->prefix_len = prefix_len; tmp_addr->flags = flags; if (ng_ipv6_addr_is_multicast(addr)) { tmp_addr->flags |= NG_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST; } else { ng_ipv6_addr_t sol_node; if (!ng_ipv6_addr_is_link_local(addr)) { /* add also corresponding link-local address */ ng_ipv6_addr_t ll_addr; ll_addr.u64[1] = addr->u64[1]; ng_ipv6_addr_set_link_local_prefix(&ll_addr); _add_addr_to_entry(entry, &ll_addr, 64, flags | NG_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK); } else { tmp_addr->flags |= NG_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK; } ng_ipv6_addr_set_solicited_nodes(&sol_node, addr); _add_addr_to_entry(entry, &sol_node, NG_IPV6_ADDR_BIT_LEN, 0); } return &(tmp_addr->addr); }
void ng_ipv6_netif_add(kernel_pid_t pid) { for (int i = 0; i < NG_NETIF_NUMOF; i++) { if (ipv6_ifs[i].pid == pid) { return; /* prevent duplicates */ } else if (ipv6_ifs[i].pid == KERNEL_PID_UNDEF) { ng_ipv6_addr_t addr = NG_IPV6_ADDR_ALL_NODES_LINK_LOCAL; mutex_lock(&ipv6_ifs[i].mutex); DEBUG("Add IPv6 interface %" PRIkernel_pid " (i = %d)\n", pid, i); ipv6_ifs[i].pid = pid; DEBUG(" * pid = %" PRIkernel_pid " ", ipv6_ifs[i].pid); ipv6_ifs[i].mtu = NG_IPV6_NETIF_DEFAULT_MTU; DEBUG("mtu = %d ", ipv6_ifs[i].mtu); ipv6_ifs[i].cur_hl = NG_IPV6_NETIF_DEFAULT_HL; DEBUG("cur_hl = %d ", ipv6_ifs[i].cur_hl); _add_addr_to_entry(&ipv6_ifs[i], &addr, NG_IPV6_ADDR_BIT_LEN, 0); mutex_unlock(&ipv6_ifs[i].mutex); return; } } DEBUG("Could not add %" PRIkernel_pid " to IPv6: No space left.\n", pid); }
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); } }
void gnrc_ipv6_netif_add(kernel_pid_t pid) { gnrc_ipv6_netif_t *free_entry = NULL; for (int i = 0; i < GNRC_NETIF_NUMOF; i++) { if (ipv6_ifs[i].pid == pid) { /* pid has already been added */ return; } else if ((ipv6_ifs[i].pid == KERNEL_PID_UNDEF) && !free_entry) { /* found the first free entry */ free_entry = &ipv6_ifs[i]; } } if (!free_entry) { DEBUG("ipv6 netif: Could not add %" PRIkernel_pid " to IPv6: No space left.\n", pid); return; } /* Otherwise, fill the free entry */ ipv6_addr_t addr = IPV6_ADDR_ALL_NODES_LINK_LOCAL; mutex_lock(&free_entry->mutex); DEBUG("ipv6 netif: Add IPv6 interface %" PRIkernel_pid " (i = %d)\n", pid, free_entry - ipv6_ifs); free_entry->pid = pid; free_entry->mtu = GNRC_IPV6_NETIF_DEFAULT_MTU; free_entry->cur_hl = GNRC_IPV6_NETIF_DEFAULT_HL; free_entry->flags = 0; _add_addr_to_entry(free_entry, &addr, IPV6_ADDR_BIT_LEN, 0); mutex_unlock(&free_entry->mutex); #ifdef MODULE_GNRC_NDP gnrc_ndp_netif_add(free_entry); #endif DEBUG(" * pid = %" PRIkernel_pid " ", free_entry->pid); DEBUG("cur_hl = %d ", free_entry->cur_hl); DEBUG("mtu = %d ", free_entry->mtu); DEBUG("flags = %04" PRIx16 "\n", free_entry->flags); }
void ng_ipv6_netif_init_by_dev(void) { kernel_pid_t ifs[NG_NETIF_NUMOF]; size_t ifnum = ng_netif_get(ifs); for (size_t i = 0; i < ifnum; i++) { ng_ipv6_addr_t addr; eui64_t iid; ng_ipv6_netif_t *ipv6_if = ng_ipv6_netif_get(ifs[i]); if (ipv6_if == NULL) { continue; } mutex_lock(&ipv6_if->mutex); #ifdef MODULE_NG_SIXLOWPAN ng_nettype_t if_type = NG_NETTYPE_UNDEF; if ((ng_netapi_get(ifs[i], NETCONF_OPT_PROTO, 0, &if_type, sizeof(if_type)) != -ENOTSUP) && (if_type == NG_NETTYPE_SIXLOWPAN)) { uint16_t src_len = 8; DEBUG("Set 6LoWPAN flag\n"); ipv6_ifs[i].flags |= NG_IPV6_NETIF_FLAGS_SIXLOWPAN; /* use EUI-64 (8-byte address) for IID generation and for sending * packets */ ng_netapi_set(ifs[i], NETCONF_OPT_SRC_LEN, 0, &src_len, sizeof(src_len)); /* don't care for result */ } #endif if ((ng_netapi_get(ifs[i], NETCONF_OPT_IPV6_IID, 0, &iid, sizeof(eui64_t)) < 0)) { mutex_unlock(&ipv6_if->mutex); continue; } ng_ipv6_addr_set_aiid(&addr, iid.uint8); ng_ipv6_addr_set_link_local_prefix(&addr); _add_addr_to_entry(ipv6_if, &addr, 64, 0); mutex_unlock(&ipv6_if->mutex); } }
ipv6_addr_t *gnrc_ipv6_netif_add_addr(kernel_pid_t pid, const ipv6_addr_t *addr, uint8_t prefix_len, uint8_t flags) { gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(pid); ipv6_addr_t *res; if ((entry == NULL) || (addr == NULL) || (ipv6_addr_is_unspecified(addr)) || ((prefix_len - 1) > 127)) { /* prefix_len < 1 || prefix_len > 128 */ return NULL; } mutex_lock(&entry->mutex); res = _add_addr_to_entry(entry, addr, prefix_len, flags); mutex_unlock(&entry->mutex); return res; }
int ng_ipv6_netif_add_addr(kernel_pid_t pid, const ng_ipv6_addr_t *addr, uint8_t prefix_len, bool anycast) { ng_ipv6_netif_t *entry = ng_ipv6_netif_get(pid); int res; if (entry == NULL) { return -ENOENT; } if ((addr == NULL) || (ng_ipv6_addr_is_unspecified(addr)) || ((prefix_len - 1) > 127)) { /* prefix_len < 1 || prefix_len > 128 */ return -EINVAL; } mutex_lock(&entry->mutex); res = _add_addr_to_entry(entry, addr, prefix_len, anycast); mutex_unlock(&entry->mutex); return res; }
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 } }
static ipv6_addr_t *_add_addr_to_entry(gnrc_ipv6_netif_t *entry, const ipv6_addr_t *addr, uint8_t prefix_len, uint8_t flags) { gnrc_ipv6_netif_addr_t *tmp_addr = NULL; for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) { if (ipv6_addr_equal(&(entry->addrs[i].addr), addr)) { return &(entry->addrs[i].addr); } if (ipv6_addr_is_unspecified(&(entry->addrs[i].addr)) && !tmp_addr) { tmp_addr = &(entry->addrs[i]); } } if (!tmp_addr) { DEBUG("ipv6 netif: couldn't add %s/%" PRIu8 " to interface %" PRIkernel_pid "\n: No space left.", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), prefix_len, entry->pid); return NULL; } memcpy(&(tmp_addr->addr), addr, sizeof(ipv6_addr_t)); DEBUG("ipv6 netif: Added %s/%" PRIu8 " to interface %" PRIkernel_pid "\n", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), prefix_len, entry->pid); tmp_addr->prefix_len = prefix_len; tmp_addr->flags = flags; #ifdef MODULE_GNRC_SIXLOWPAN_ND if (!ipv6_addr_is_multicast(&(tmp_addr->addr)) && (entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) { ipv6_addr_t *router = gnrc_ndp_internal_default_router(); if (router != NULL) { mutex_unlock(&entry->mutex); /* function below relocks mutex */ gnrc_ndp_internal_send_nbr_sol(entry->pid, &tmp_addr->addr, router, router); mutex_lock(&entry->mutex); /* relock mutex */ } /* otherwise there is no default router to register to */ } #endif if (ipv6_addr_is_multicast(addr)) { tmp_addr->flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST; } else { if (!ipv6_addr_is_link_local(addr)) { #ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER tmp_addr->valid = 0xFFFF; gnrc_sixlowpan_nd_router_abr_t *abr = gnrc_sixlowpan_nd_router_abr_get(); if (gnrc_sixlowpan_nd_router_abr_add_prf(abr, entry, tmp_addr) < 0) { DEBUG("ipv6_netif: error adding prefix to 6LoWPAN-ND management\n"); } #endif #if defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER) if ((entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) && (entry->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV)) { mutex_unlock(&entry->mutex); /* function below relocks mutex */ #ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER if (entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) { gnrc_ndp_internal_send_rtr_adv(entry->pid, NULL, NULL, false); } #endif #ifdef MODULE_GNRC_NDP_ROUTER /* New prefixes MAY allow the router to retransmit up to * GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF unsolicited RA * (see https://tools.ietf.org/html/rfc4861#section-6.2.4) */ if (!(entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) { entry->rtr_adv_count = GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF; gnrc_ndp_router_retrans_rtr_adv(entry); } #endif mutex_lock(&entry->mutex); /* relock mutex */ } #endif } else { tmp_addr->flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK; } #if defined(MODULE_GNRC_NDP_NODE) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER) /* add solicited-nodes multicast address for new address if interface is not a * 6LoWPAN host interface (see: https://tools.ietf.org/html/rfc6775#section-5.2) */ if (!(entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) || (entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) { ipv6_addr_t sol_node; ipv6_addr_set_solicited_nodes(&sol_node, addr); _add_addr_to_entry(entry, &sol_node, IPV6_ADDR_BIT_LEN, 0); } #endif /* TODO: send NS with ARO on 6LoWPAN interfaces, but not so many and only for the new * source address. */ } return &(tmp_addr->addr); }
static ipv6_addr_t *_add_addr_to_entry(gnrc_ipv6_netif_t *entry, const ipv6_addr_t *addr, uint8_t prefix_len, uint8_t flags) { gnrc_ipv6_netif_addr_t *tmp_addr = NULL; for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) { if (ipv6_addr_equal(&(entry->addrs[i].addr), addr)) { return &(entry->addrs[i].addr); } if (ipv6_addr_is_unspecified(&(entry->addrs[i].addr)) && !tmp_addr) { tmp_addr = &(entry->addrs[i]); } } if (!tmp_addr) { DEBUG("ipv6 netif: couldn't add %s/%" PRIu8 " to interface %" PRIkernel_pid "\n: No space left.", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), prefix_len, entry->pid); return NULL; } memcpy(&(tmp_addr->addr), addr, sizeof(ipv6_addr_t)); DEBUG("ipv6 netif: Added %s/%" PRIu8 " to interface %" PRIkernel_pid "\n", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), prefix_len, entry->pid); tmp_addr->prefix_len = prefix_len; tmp_addr->flags = flags; if (ipv6_addr_is_multicast(addr)) { tmp_addr->flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST; } else { if (!ipv6_addr_is_link_local(addr)) { /* add also corresponding link-local address */ ipv6_addr_t ll_addr; ll_addr.u64[1] = addr->u64[1]; ipv6_addr_set_link_local_prefix(&ll_addr); _add_addr_to_entry(entry, &ll_addr, 64, flags | GNRC_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK); #ifdef MODULE_GNRC_NDP_ROUTER /* New prefixes MAY allow the router to retransmit up to * GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF unsolicited RA * (see https://tools.ietf.org/html/rfc4861#section-6.2.4) */ if ((entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) && (entry->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV)) { entry->rtr_adv_count = GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF; mutex_unlock(&entry->mutex); /* function below relocks mutex */ gnrc_ndp_router_retrans_rtr_adv(entry); mutex_lock(&entry->mutex); /* relock mutex */ } #endif } else { tmp_addr->flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK; } #if defined(MODULE_GNRC_NDP_NODE) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER) /* add solicited-nodes multicast address for new address if interface is not a * 6LoWPAN host interface (see: https://tools.ietf.org/html/rfc6775#section-5.2) */ if (!(entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) || (entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) { ipv6_addr_t sol_node; ipv6_addr_set_solicited_nodes(&sol_node, addr); _add_addr_to_entry(entry, &sol_node, IPV6_ADDR_BIT_LEN, 0); } #endif /* TODO: send NS with ARO on 6LoWPAN interfaces, but not so many and only for the new * source address. */ } return &(tmp_addr->addr); }