kernel_pid_t ng_ipv6_netif_find_by_addr(ng_ipv6_addr_t **out, const ng_ipv6_addr_t *addr) { for (int i = 0; i < NG_NETIF_NUMOF; i++) { if (out != NULL) { *out = ng_ipv6_netif_find_addr(ipv6_ifs[i].pid, addr); if (*out != NULL) { DEBUG("ipv6 netif: Found %s on interface %" PRIkernel_pid "\n", ng_ipv6_addr_to_str(addr_str, *out, sizeof(addr_str)), ipv6_ifs[i].pid); return ipv6_ifs[i].pid; } } else { if (ng_ipv6_netif_find_addr(ipv6_ifs[i].pid, addr) != NULL) { DEBUG("ipv6 netif: Found %s on interface %" PRIkernel_pid "\n", ng_ipv6_addr_to_str(addr_str, *out, sizeof(addr_str)), ipv6_ifs[i].pid); return ipv6_ifs[i].pid; } } } if (out != NULL) { *out = NULL; } return KERNEL_PID_UNDEF; }
static void test_ipv6_netif_remove_addr__not_allocated(void) { ng_ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; ng_ipv6_addr_t other_addr = OTHER_TEST_IPV6_ADDR; test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to * DEFAULT_TEST_NETIF */ ng_ipv6_netif_remove_addr(DEFAULT_TEST_NETIF, &other_addr); TEST_ASSERT_NULL(ng_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &other_addr)); TEST_ASSERT_NOT_NULL(ng_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr)); }
static void test_ipv6_netif_find_addr__success(void) { ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; ipv6_addr_t *out = NULL; test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to * DEFAULT_TEST_NETIF */ TEST_ASSERT_NOT_NULL((out = ng_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); TEST_ASSERT(out != &addr); TEST_ASSERT_EQUAL_INT(true, ipv6_addr_equal(out, &addr)); /* also test for link local address */ ipv6_addr_set_link_local_prefix(&addr); TEST_ASSERT_NOT_NULL((out = ng_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); TEST_ASSERT_EQUAL_INT(true, ipv6_addr_equal(out, &addr)); }
static void test_ipv6_netif_find_addr__wrong_addr(void) { ng_ipv6_addr_t addr = OTHER_TEST_IPV6_ADDR; test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to * DEFAULT_TEST_NETIF */ TEST_ASSERT_NULL(ng_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr)); }
/* functions for receiving */ static inline bool _pkt_not_for_me(kernel_pid_t *iface, ng_ipv6_hdr_t *hdr) { if (*iface == KERNEL_PID_UNDEF) { *iface = ng_ipv6_netif_find_by_addr(NULL, &hdr->dst); return (*iface == KERNEL_PID_UNDEF); } else { return (ng_ipv6_netif_find_addr(*iface, &hdr->dst) == NULL); } }
void ng_ndp_nbr_sol_handle(kernel_pid_t iface, ng_pktsnip_t *pkt, ng_ipv6_hdr_t *ipv6, ng_ndp_nbr_sol_t *nbr_sol, size_t icmpv6_size) { uint16_t opt_offset = 0; uint8_t *buf = ((uint8_t *)nbr_sol) + sizeof(ng_ndp_nbr_sol_t); ng_ipv6_addr_t *tgt; int sicmpv6_size = (int)icmpv6_size; /* check validity */ if ((ipv6->hl != 255) || (nbr_sol->code != 0) || (icmpv6_size < sizeof(ng_ndp_nbr_sol_t)) || ng_ipv6_addr_is_multicast(&nbr_sol->tgt) || (ng_ipv6_addr_is_unspecified(&ipv6->src) && ng_ipv6_addr_is_solicited_node(&ipv6->dst))) { DEBUG("ndp: neighbor solicitation was invalid.\n"); /* ipv6 releases */ return; } if ((tgt = ng_ipv6_netif_find_addr(iface, &nbr_sol->tgt)) == NULL) { DEBUG("ndp: Target address is not to interface %" PRIkernel_pid "\n", iface); /* ipv6 releases */ return; } sicmpv6_size -= sizeof(ng_ndp_nbr_sol_t); while (sicmpv6_size > 0) { ng_ndp_opt_t *opt = (ng_ndp_opt_t *)(buf + opt_offset); switch (opt->type) { case NG_NDP_OPT_SL2A: if (!_handle_sl2a_opt(iface, pkt, ipv6, nbr_sol->type, opt)) { /* invalid source link-layer address option */ return; } break; default: /* silently discard all other options */ break; } opt_offset += (opt->len * 8); sicmpv6_size -= (opt->len * 8); } _send_nbr_adv(iface, tgt, &ipv6->src, ng_ipv6_addr_is_multicast(&ipv6->dst)); return; }
static void test_ipv6_netif_addr_is_non_unicast__unicast(void) { ng_ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; ng_ipv6_addr_t *out = NULL; test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to * DEFAULT_TEST_NETIF */ TEST_ASSERT_NOT_NULL((out = ng_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); TEST_ASSERT_EQUAL_INT(false, ng_ipv6_netif_addr_is_non_unicast(out)); }
static void test_ipv6_netif_reset_addr__success(void) { ng_ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to * DEFAULT_TEST_NETIF */ ng_ipv6_netif_reset_addr(DEFAULT_TEST_NETIF); TEST_ASSERT_NULL(ng_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr)); }
static void test_ipv6_netif_find_addr__success(void) { ng_ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; ng_ipv6_addr_t *out = NULL; test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to * DEFAULT_TEST_NETIF */ TEST_ASSERT_NOT_NULL((out = ng_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); TEST_ASSERT(out != &addr); TEST_ASSERT_EQUAL_INT(true, ng_ipv6_addr_equal(out, &addr)); }
static void test_ipv6_netif_addr_is_non_unicast__multicast1(void) { ipv6_addr_t addr = IPV6_ADDR_ALL_ROUTERS_LINK_LOCAL; ipv6_addr_t *out = NULL; test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ TEST_ASSERT_NOT_NULL(ng_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &addr, DEFAULT_TEST_PREFIX_LEN, 0)); TEST_ASSERT_NOT_NULL((out = ng_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); TEST_ASSERT_EQUAL_INT(true, ng_ipv6_netif_addr_is_non_unicast(out)); }
static void test_ipv6_netif_addr_is_non_unicast__anycast(void) { ng_ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; ng_ipv6_addr_t *out = NULL; test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ TEST_ASSERT_EQUAL_INT(0, ng_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &addr, DEFAULT_TEST_PREFIX_LEN, true)); TEST_ASSERT_NOT_NULL((out = ng_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); TEST_ASSERT_EQUAL_INT(true, ng_ipv6_netif_addr_is_non_unicast(out)); }
static void test_ipv6_netif_find_addr__no_iface(void) { ng_ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; TEST_ASSERT_NULL(ng_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr)); }
static void _send(ng_pktsnip_t *pkt, bool prep_hdr) { kernel_pid_t iface = KERNEL_PID_UNDEF; ng_pktsnip_t *ipv6, *payload; ng_ipv6_addr_t *tmp; ng_ipv6_hdr_t *hdr; /* get IPv6 snip and (if present) generic interface header */ if (pkt->type == NG_NETTYPE_NETIF) { /* If there is already a netif header (routing protocols and * neighbor discovery might add them to preset sending interface) */ iface = ((ng_netif_hdr_t *)pkt->data)->if_pid; /* seize payload as temporary variable */ ipv6 = ng_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"); ng_pktbuf_release(pkt); return; } pkt = ipv6; /* Reset pkt from temporary variable */ ipv6 = pkt->next; } else { ipv6 = pkt; } /* seize payload as temporary variable */ payload = ng_pktbuf_start_write(ipv6); if (payload == NULL) { DEBUG("ipv6: unable to get write access to IPv6 header, dropping packet\n"); ng_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 */ } ipv6 = payload; /* Reset ipv6 from temporary variable */ hdr = ipv6->data; payload = ipv6->next; if (ng_ipv6_addr_is_multicast(&hdr->dst)) { _send_multicast(iface, pkt, ipv6, payload, prep_hdr); } else if ((ng_ipv6_addr_is_loopback(&hdr->dst)) || /* dst is loopback address */ ((iface == KERNEL_PID_UNDEF) && /* or dst registered to any local interface */ ((iface = ng_ipv6_netif_find_by_addr(&tmp, &hdr->dst)) != KERNEL_PID_UNDEF)) || ((iface != KERNEL_PID_UNDEF) && /* or dst registered to given interface */ (ng_ipv6_netif_find_addr(iface, &hdr->dst) != NULL))) { uint8_t *rcv_data; ng_pktsnip_t *ptr = ipv6, *rcv_pkt; if (prep_hdr) { if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) { /* error on filling up header */ ng_pktbuf_release(pkt); return; } } rcv_pkt = ng_pktbuf_add(NULL, NULL, ng_pkt_len(ipv6), NG_NETTYPE_IPV6); if (rcv_pkt == NULL) { DEBUG("ipv6: error on generating loopback packet\n"); ng_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; } ng_pktbuf_release(pkt); DEBUG("ipv6: packet is addressed to myself => loopback\n"); ng_netapi_receive(ng_ipv6_pid, rcv_pkt); } else { uint8_t l2addr_len = NG_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"); ng_pktbuf_release(pkt); return; } if (prep_hdr) { if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) { /* error on filling up header */ ng_pktbuf_release(pkt); return; } } _send_unicast(iface, l2addr, l2addr_len, pkt); } }