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; }
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; }