bool gnrc_conn6_set_local_addr(uint8_t *conn_addr, const ipv6_addr_t *addr) { ipv6_addr_t *tmp; if (!ipv6_addr_is_unspecified(addr) && !ipv6_addr_is_loopback(addr) && gnrc_ipv6_netif_find_by_addr(&tmp, addr) == KERNEL_PID_UNDEF) { return false; } else if (ipv6_addr_is_loopback(addr) || ipv6_addr_is_unspecified(addr)) { ipv6_addr_set_unspecified((ipv6_addr_t *)conn_addr); } else { memcpy(conn_addr, addr, sizeof(ipv6_addr_t)); } return true; }
static int _fill_ipv6_hdr(kernel_pid_t iface, gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *payload) { int res; ipv6_hdr_t *hdr = ipv6->data; hdr->len = byteorder_htons(gnrc_pkt_len(payload)); DEBUG("ipv6: set payload length to %u (network byteorder %04" PRIx16 ")\n", (unsigned) gnrc_pkt_len(payload), hdr->len.u16); /* check if e.g. extension header was not already marked */ if (hdr->nh == PROTNUM_RESERVED) { hdr->nh = gnrc_nettype_to_protnum(payload->type); /* if still reserved: mark no next header */ if (hdr->nh == PROTNUM_RESERVED) { hdr->nh = PROTNUM_IPV6_NONXT; } } DEBUG("ipv6: set next header to %u\n", hdr->nh); if (hdr->hl == 0) { if (iface == KERNEL_PID_UNDEF) { hdr->hl = GNRC_IPV6_NETIF_DEFAULT_HL; } else { hdr->hl = gnrc_ipv6_netif_get(iface)->cur_hl; } } if (ipv6_addr_is_unspecified(&hdr->src)) { if (ipv6_addr_is_loopback(&hdr->dst)) { ipv6_addr_set_loopback(&hdr->src); } else { ipv6_addr_t *src = gnrc_ipv6_netif_find_best_src_addr(iface, &hdr->dst, false); if (src != NULL) { DEBUG("ipv6: set packet source to %s\n", ipv6_addr_to_str(addr_str, src, sizeof(addr_str))); memcpy(&hdr->src, src, sizeof(ipv6_addr_t)); } /* Otherwise leave unspecified */ } } DEBUG("ipv6: calculate checksum for upper header.\n"); if ((res = gnrc_netreg_calc_csum(payload, ipv6)) < 0) { if (res != -ENOENT) { /* if there is no checksum we are okay */ DEBUG("ipv6: checksum calculation failed.\n"); return res; } } return 0; }
/* functions for receiving */ static inline bool _pkt_not_for_me(kernel_pid_t *iface, ipv6_hdr_t *hdr) { if (ipv6_addr_is_loopback(&hdr->dst)) { return false; } else if (*iface == KERNEL_PID_UNDEF) { *iface = gnrc_ipv6_netif_find_by_addr(NULL, &hdr->dst); return (*iface == KERNEL_PID_UNDEF); } else { return (gnrc_ipv6_netif_find_addr(*iface, &hdr->dst) == NULL); } }
/* functions for receiving */ static inline bool _pkt_not_for_me(kernel_pid_t *iface, ipv6_hdr_t *hdr) { if (ipv6_addr_is_loopback(&hdr->dst)) { return false; } else if ((!ipv6_addr_is_link_local(&hdr->dst)) || (*iface == KERNEL_PID_UNDEF)) { kernel_pid_t if_pid = gnrc_ipv6_netif_find_by_addr(NULL, &hdr->dst); if (*iface == KERNEL_PID_UNDEF) { *iface = if_pid; /* Use original interface for reply if * existent */ } return (if_pid == KERNEL_PID_UNDEF); } else { return (gnrc_ipv6_netif_find_addr(*iface, &hdr->dst) == NULL); } }
int sixlowpan_lowpan_border_init(int if_id) { ipv6_net_if_addr_t *addr = NULL; uint8_t abr_addr_initialized = 0; serial_reader_pid = thread_create( serial_reader_stack, READER_STACK_SIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, serial_reader_f, "serial_reader"); ip_process_pid = thread_create(ip_process_buf, IP_PROCESS_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, border_process_lowpan, "border_process_lowpan"); if (ip_process_pid < 0) { return 0; } if (!sixlowpan_lowpan_init_interface(if_id)) { return 0; } while (net_if_iter_addresses(if_id, (net_if_addr_t **) &addr)) { if (!ipv6_addr_is_multicast(addr->addr_data) && !ipv6_addr_is_link_local(addr->addr_data) && !ipv6_addr_is_loopback(addr->addr_data) && !ipv6_addr_is_unique_local_unicast(addr->addr_data)) { abr_addr_initialized = 1; abr_addr = addr->addr_data; break; } } if (!abr_addr_initialized) { DEBUG("sixlowpan_lowpan_border_init(): A prefix must be initialized to" "interface %d first", if_id); return 0; } ipv6_init_as_router(); return 1; }
static void _send(gnrc_pktsnip_t *pkt, bool prep_hdr) { kernel_pid_t iface = KERNEL_PID_UNDEF; gnrc_pktsnip_t *ipv6, *payload; ipv6_addr_t *tmp; ipv6_hdr_t *hdr; /* get IPv6 snip and (if present) generic interface header */ if (pkt->type == GNRC_NETTYPE_NETIF) { /* If there is already a netif header (routing protocols and * neighbor discovery might add them to preset sending interface) */ iface = ((gnrc_netif_hdr_t *)pkt->data)->if_pid; /* seize payload as temporary variable */ ipv6 = gnrc_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"); gnrc_pktbuf_release(pkt); return; } pkt = ipv6; /* Reset pkt from temporary variable */ ipv6 = pkt->next; } else { ipv6 = pkt; } /* seize payload as temporary variable */ payload = gnrc_pktbuf_start_write(ipv6); if (payload == NULL) { DEBUG("ipv6: unable to get write access to IPv6 header, dropping packet\n"); gnrc_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 */ } else { pkt = payload; /* pkt is the IPv6 header so we just write-protected it */ } ipv6 = payload; /* Reset ipv6 from temporary variable */ hdr = ipv6->data; payload = ipv6->next; if (ipv6_addr_is_multicast(&hdr->dst)) { _send_multicast(iface, pkt, ipv6, payload, prep_hdr); } else if ((ipv6_addr_is_loopback(&hdr->dst)) || /* dst is loopback address */ ((iface == KERNEL_PID_UNDEF) && /* or dst registered to any local interface */ ((iface = gnrc_ipv6_netif_find_by_addr(&tmp, &hdr->dst)) != KERNEL_PID_UNDEF)) || ((iface != KERNEL_PID_UNDEF) && /* or dst registered to given interface */ (gnrc_ipv6_netif_find_addr(iface, &hdr->dst) != NULL))) { uint8_t *rcv_data; gnrc_pktsnip_t *ptr = ipv6, *rcv_pkt; if (prep_hdr) { if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) { /* error on filling up header */ gnrc_pktbuf_release(pkt); return; } } rcv_pkt = gnrc_pktbuf_add(NULL, NULL, gnrc_pkt_len(ipv6), GNRC_NETTYPE_IPV6); if (rcv_pkt == NULL) { DEBUG("ipv6: error on generating loopback packet\n"); gnrc_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; } gnrc_pktbuf_release(pkt); DEBUG("ipv6: packet is addressed to myself => loopback\n"); if (gnrc_netapi_receive(gnrc_ipv6_pid, rcv_pkt) < 1) { DEBUG("ipv6: unable to deliver packet\n"); gnrc_pktbuf_release(rcv_pkt); } } else { uint8_t l2addr_len = GNRC_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"); gnrc_pktbuf_release(pkt); return; } if (prep_hdr) { if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) { /* error on filling up header */ gnrc_pktbuf_release(pkt); return; } } _send_unicast(iface, l2addr, l2addr_len, pkt); } }
int gnrc_netif_ipv6_addr_add_internal(gnrc_netif_t *netif, const ipv6_addr_t *addr, unsigned pfx_len, uint8_t flags) { unsigned idx = UINT_MAX; assert((netif != NULL) && (addr != NULL)); assert(!(ipv6_addr_is_multicast(addr) || ipv6_addr_is_unspecified(addr) || ipv6_addr_is_loopback(addr))); assert((pfx_len > 0) && (pfx_len <= 128)); gnrc_netif_acquire(netif); if ((flags & GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK) == GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE) { /* set to first retransmission */ flags &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; flags |= 0x1; } for (unsigned i = 0; i < GNRC_NETIF_IPV6_ADDRS_NUMOF; i++) { if (ipv6_addr_equal(&netif->ipv6.addrs[i], addr)) { gnrc_netif_release(netif); return i; } if ((idx == UINT_MAX) && (netif->ipv6.addrs_flags[i] == 0)) { idx = i; } } if (idx == UINT_MAX) { gnrc_netif_release(netif); return -ENOMEM; } netif->ipv6.addrs_flags[idx] = flags; memcpy(&netif->ipv6.addrs[idx], addr, sizeof(netif->ipv6.addrs[idx])); #ifdef MODULE_GNRC_IPV6_NIB #if GNRC_IPV6_NIB_CONF_ARSM ipv6_addr_t sol_nodes; int res; /* TODO: SHOULD delay join between 0 and MAX_RTR_SOLICITATION_DELAY * for SLAAC */ ipv6_addr_set_solicited_nodes(&sol_nodes, addr); res = gnrc_netif_ipv6_group_join_internal(netif, &sol_nodes); if (res < 0) { DEBUG("nib: Can't join solicited-nodes of %s on interface %u\n", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), netif->pid); } #endif /* GNRC_IPV6_NIB_CONF_ARSM */ if (_get_state(netif, idx) == GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID) { void *state = NULL; gnrc_ipv6_nib_pl_t ple; bool in_pl = false; while (gnrc_ipv6_nib_pl_iter(netif->pid, &state, &ple)) { if (ipv6_addr_match_prefix(&ple.pfx, addr) >= pfx_len) { in_pl = true; } } if (!in_pl) { gnrc_ipv6_nib_pl_set(netif->pid, addr, pfx_len, UINT32_MAX, UINT32_MAX); } } #if GNRC_IPV6_NIB_CONF_SLAAC else { /* TODO: send out NS to solicited nodes for DAD probing */ } #endif #else (void)pfx_len; #endif gnrc_netif_release(netif); return idx; }
static int _fill_ipv6_hdr(kernel_pid_t iface, gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *payload) { int res; ipv6_hdr_t *hdr = ipv6->data; hdr->len = byteorder_htons(gnrc_pkt_len(payload)); DEBUG("ipv6: set payload length to %zu (network byteorder %04" PRIx16 ")\n", gnrc_pkt_len(payload), hdr->len.u16); /* check if e.g. extension header was not already marked */ if (hdr->nh == PROTNUM_RESERVED) { hdr->nh = gnrc_nettype_to_protnum(payload->type); /* if still reserved: mark no next header */ if (hdr->nh == PROTNUM_RESERVED) { hdr->nh = PROTNUM_IPV6_NONXT; } } DEBUG("ipv6: set next header to %" PRIu8 "\n", hdr->nh); if (hdr->hl == 0) { if (iface == KERNEL_PID_UNDEF) { hdr->hl = GNRC_IPV6_NETIF_DEFAULT_HL; } else { hdr->hl = gnrc_ipv6_netif_get(iface)->cur_hl; } } if (ipv6_addr_is_unspecified(&hdr->src)) { if (ipv6_addr_is_loopback(&hdr->dst)) { ipv6_addr_set_loopback(&hdr->src); } else { ipv6_addr_t *src = gnrc_ipv6_netif_find_best_src_addr(iface, &hdr->dst); if (src != NULL) { DEBUG("ipv6: set packet source to %s\n", ipv6_addr_to_str(addr_str, src, sizeof(addr_str))); memcpy(&hdr->src, src, sizeof(ipv6_addr_t)); } /* Otherwise leave unspecified */ } } DEBUG("ipv6: calculate checksum for upper header.\n"); #if GNRC_NETIF_NUMOF > 1 if (payload->users > 1) { gnrc_pktsnip_t *ptr = ipv6; /* We deal with multiple interfaces here (multicast) => possible * different source addresses => duplication of payload needed */ while (ptr != payload->next) { gnrc_pktsnip_t *old = ptr->next; /* duplicate everything including payload */ ptr->next = gnrc_pktbuf_start_write(ptr->next); if (ptr->next == NULL) { DEBUG("ipv6: unable to get write access to payload, drop it\n"); return -ENOBUFS; } ptr = old; } } #endif /* GNRC_NETIF_NUMOF */ if ((res = gnrc_netreg_calc_csum(payload, ipv6)) < 0) { if (res != -ENOENT) { /* if there is no checksum we are okay */ DEBUG("ipv6: checksum calculation failed.\n"); return res; } } return 0; }