static void _send_to_iface(kernel_pid_t iface, gnrc_pktsnip_t *pkt) { ((gnrc_netif_hdr_t *)pkt->data)->if_pid = iface; gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface); assert(if_entry != NULL); if (gnrc_pkt_len(pkt->next) > if_entry->mtu) { DEBUG("ipv6: packet too big\n"); gnrc_pktbuf_release(pkt); return; } #ifdef MODULE_NETSTATS_IPV6 if_entry->stats.tx_success++; if_entry->stats.tx_bytes += gnrc_pkt_len(pkt->next); #endif #ifdef MODULE_GNRC_SIXLOWPAN if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) { DEBUG("ipv6: send to 6LoWPAN instead\n"); if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_SIXLOWPAN, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) { DEBUG("ipv6: no 6LoWPAN thread found"); gnrc_pktbuf_release(pkt); } return; } #endif if (gnrc_netapi_send(iface, pkt) < 1) { DEBUG("ipv6: unable to send packet\n"); gnrc_pktbuf_release(pkt); } }
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 void test_pkt_len__2_elem(void) { gnrc_pktsnip_t snip1 = _INIT_ELEM_STATIC_DATA(TEST_STRING8, NULL); gnrc_pktsnip_t snip2 = _INIT_ELEM_STATIC_DATA(TEST_STRING12, &snip1); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8) + sizeof(TEST_STRING12), gnrc_pkt_len(&snip2)); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), gnrc_pkt_len(&snip1)); }
static void test_pkt_len__2_elem__overflow(void) { gnrc_pktsnip_t snip1 = _INIT_ELEM_STATIC_DATA(TEST_STRING8, NULL); gnrc_pktsnip_t snip2 = _INIT_ELEM(SIZE_MAX, NULL, &snip1); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8) - 1, gnrc_pkt_len(&snip2)); /* size should overflow */ TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), gnrc_pkt_len(&snip1)); }
static int _send(gnrc_netdev_t *netdev, gnrc_pktsnip_t *pkt) { xbee_t *dev = (xbee_t *)netdev; size_t size; size_t pos; gnrc_netif_hdr_t *hdr; gnrc_pktsnip_t *payload; /* check device descriptor and packet */ if (pkt == NULL) { return -ENOMSG; } if (dev == NULL) { gnrc_pktbuf_release(pkt); return -ENODEV; } /* figure out the size of the payload to send */ size = gnrc_pkt_len(pkt->next); if (size > XBEE_MAX_PAYLOAD_LENGTH) { DEBUG("xbee: Error sending data, payload length exceeds limit\n"); gnrc_pktbuf_release(pkt); return -EOVERFLOW; } /* get netif header check address length and flags */ hdr = (gnrc_netif_hdr_t *)pkt->data; if (!((hdr->dst_l2addr_len == 2) || (hdr->dst_l2addr_len == 8) || _is_broadcast(hdr))) { gnrc_pktbuf_release(pkt); return -ENOMSG; } /* acquire TX lock */ mutex_lock(&(dev->tx_lock)); /* put together the API frame */ dev->tx_buf[0] = API_START_DELIMITER; dev->tx_buf[4] = 0; /* set to zero to disable response frame */ /* set size, API id and address field depending on dst address length */ if (_is_broadcast(hdr)) { dev->tx_buf[1] = (uint8_t)((size + 5) >> 8); dev->tx_buf[2] = (uint8_t)(size + 5); dev->tx_buf[3] = API_ID_TX_SHORT_ADDR; dev->tx_buf[4] = 0xff; dev->tx_buf[5] = 0xff; } if (hdr->dst_l2addr_len == 2) { dev->tx_buf[1] = (uint8_t)((size + 5) >> 8); dev->tx_buf[2] = (uint8_t)(size + 5); dev->tx_buf[3] = API_ID_TX_SHORT_ADDR; memcpy(dev->tx_buf + 5, gnrc_netif_hdr_get_dst_addr(hdr), 2); pos = 7; }
/** * @brief Make a raw dump of the given packet contents */ void dump_pkt(gnrc_pktsnip_t *pkt) { gnrc_pktsnip_t *snip = pkt; printf("rftest-rx --- len 0x%02x lqi 0x%02x rx_time 0x%08" PRIx64 "\n\n", gnrc_pkt_len(pkt), 0, xtimer_now64()); while (snip) { for (size_t i = 0; i < snip->size; i++) { printf("0x%02x ", ((uint8_t *)(snip->data))[i]); } snip = snip->next; } puts("\n"); gnrc_pktbuf_release(pkt); }
void gnrc_sixlowpan_frag_send(kernel_pid_t pid, gnrc_pktsnip_t *pkt, size_t datagram_size) { gnrc_sixlowpan_netif_t *iface = gnrc_sixlowpan_netif_get(pid); uint16_t offset = 0, res; /* payload_len: actual size of the packet vs * datagram_size: size of the uncompressed IPv6 packet */ size_t payload_len = gnrc_pkt_len(pkt->next); #if defined(DEVELHELP) && defined(ENABLE_DEBUG) if (iface == NULL) { DEBUG("6lo frag: iface == NULL, expect segmentation fault.\n"); gnrc_pktbuf_release(pkt); return; } #endif if ((res = _send_1st_fragment(iface, pkt, payload_len, datagram_size)) == 0) { /* error sending first fragment */ DEBUG("6lo frag: error sending 1st fragment\n"); gnrc_pktbuf_release(pkt); return; } offset += res; thread_yield(); /* (offset + (datagram_size - payload_len) < datagram_size) simplified */ while (offset < payload_len) { if ((res = _send_nth_fragment(iface, pkt, payload_len, datagram_size, offset)) == 0) { /* error sending subsequent fragment */ DEBUG("6lo frag: error sending subsequent fragment (offset = %" PRIu16 ")\n", offset); gnrc_pktbuf_release(pkt); return; } offset += res; thread_yield(); } /* remove original packet from packet buffer */ gnrc_pktbuf_release(pkt); _tag++; }
static void _receive(gnrc_pktsnip_t *pkt) { kernel_pid_t iface = KERNEL_PID_UNDEF; gnrc_pktsnip_t *ipv6, *netif, *first_ext; ipv6_hdr_t *hdr; assert(pkt != NULL); netif = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); if (netif != NULL) { iface = ((gnrc_netif_hdr_t *)netif->data)->if_pid; #ifdef MODULE_NETSTATS_IPV6 assert(iface); netstats_t *stats = gnrc_ipv6_netif_get_stats(iface); stats->rx_count++; stats->rx_bytes += (gnrc_pkt_len(pkt) - netif->size); #endif } first_ext = pkt; for (ipv6 = pkt; ipv6 != NULL; ipv6 = ipv6->next) { /* find IPv6 header if already marked */ if ((ipv6->type == GNRC_NETTYPE_IPV6) && (ipv6->size == sizeof(ipv6_hdr_t)) && (ipv6_hdr_is(ipv6->data))) { break; } first_ext = ipv6; } if (ipv6 == NULL) { if (!ipv6_hdr_is(pkt->data)) { DEBUG("ipv6: Received packet was not IPv6, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } #ifdef MODULE_GNRC_IPV6_WHITELIST if (!gnrc_ipv6_whitelisted(&((ipv6_hdr_t *)(pkt->data))->src)) { DEBUG("ipv6: Source address not whitelisted, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } #endif #ifdef MODULE_GNRC_IPV6_BLACKLIST if (gnrc_ipv6_blacklisted(&((ipv6_hdr_t *)(pkt->data))->src)) { DEBUG("ipv6: Source address blacklisted, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } #endif /* seize ipv6 as a temporary variable */ ipv6 = gnrc_pktbuf_start_write(pkt); if (ipv6 == NULL) { DEBUG("ipv6: unable to get write access to packet, drop it\n"); gnrc_pktbuf_release(pkt); return; } pkt = ipv6; /* reset pkt from temporary variable */ ipv6 = gnrc_pktbuf_mark(pkt, sizeof(ipv6_hdr_t), GNRC_NETTYPE_IPV6); first_ext = pkt; pkt->type = GNRC_NETTYPE_UNDEF; /* snip is no longer IPv6 */ if (ipv6 == NULL) { DEBUG("ipv6: error marking IPv6 header, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } } #ifdef MODULE_GNRC_IPV6_WHITELIST else if (!gnrc_ipv6_whitelisted(&((ipv6_hdr_t *)(ipv6->data))->src)) { /* if ipv6 header already marked*/ DEBUG("ipv6: Source address not whitelisted, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } #endif #ifdef MODULE_GNRC_IPV6_BLACKLIST else if (gnrc_ipv6_blacklisted(&((ipv6_hdr_t *)(ipv6->data))->src)) { /* if ipv6 header already marked*/ DEBUG("ipv6: Source address blacklisted, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } #endif /* extract header */ hdr = (ipv6_hdr_t *)ipv6->data; /* if available, remove any padding that was added by lower layers * to fulfill their minimum size requirements (e.g. ethernet) */ if (byteorder_ntohs(hdr->len) < pkt->size) { gnrc_pktbuf_realloc_data(pkt, byteorder_ntohs(hdr->len)); } else if (byteorder_ntohs(hdr->len) > (gnrc_pkt_len_upto(pkt, GNRC_NETTYPE_IPV6) - sizeof(ipv6_hdr_t))) { DEBUG("ipv6: invalid payload length: %d, actual: %d, dropping packet\n", (int) byteorder_ntohs(hdr->len), (int) (gnrc_pkt_len_upto(pkt, GNRC_NETTYPE_IPV6) - sizeof(ipv6_hdr_t))); gnrc_pktbuf_release(pkt); return; } DEBUG("ipv6: Received (src = %s, ", ipv6_addr_to_str(addr_str, &(hdr->src), sizeof(addr_str))); DEBUG("dst = %s, next header = %u, length = %" PRIu16 ")\n", ipv6_addr_to_str(addr_str, &(hdr->dst), sizeof(addr_str)), hdr->nh, byteorder_ntohs(hdr->len)); if (_pkt_not_for_me(&iface, hdr)) { /* if packet is not for me */ DEBUG("ipv6: packet destination not this host\n"); #ifdef MODULE_GNRC_IPV6_ROUTER /* only routers redirect */ /* redirect to next hop */ DEBUG("ipv6: decrement hop limit to %u\n", (uint8_t) (hdr->hl - 1)); /* RFC 4291, section 2.5.6 states: "Routers must not forward any * packets with Link-Local source or destination addresses to other * links." */ if ((ipv6_addr_is_link_local(&(hdr->src))) || (ipv6_addr_is_link_local(&(hdr->dst)))) { DEBUG("ipv6: do not forward packets with link-local source or" " destination address\n"); gnrc_pktbuf_release(pkt); return; } /* TODO: check if receiving interface is router */ else if (--(hdr->hl) > 0) { /* drop packets that *reach* Hop Limit 0 */ gnrc_pktsnip_t *reversed_pkt = NULL, *ptr = pkt; DEBUG("ipv6: forward packet to next hop\n"); /* pkt might not be writable yet, if header was given above */ ipv6 = gnrc_pktbuf_start_write(ipv6); if (ipv6 == NULL) { DEBUG("ipv6: unable to get write access to packet: dropping it\n"); gnrc_pktbuf_release(pkt); return; } /* remove L2 headers around IPV6 */ netif = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); if (netif != NULL) { gnrc_pktbuf_remove_snip(pkt, netif); } /* reverse packet snip list order */ while (ptr != NULL) { gnrc_pktsnip_t *next; ptr = gnrc_pktbuf_start_write(ptr); /* duplicate if not already done */ if (ptr == NULL) { DEBUG("ipv6: unable to get write access to packet: dropping it\n"); gnrc_pktbuf_release(reversed_pkt); gnrc_pktbuf_release(pkt); return; } next = ptr->next; ptr->next = reversed_pkt; reversed_pkt = ptr; ptr = next; } _send(reversed_pkt, false); return; } else { DEBUG("ipv6: hop limit reached 0: drop packet\n"); gnrc_pktbuf_release(pkt); return; } #else /* MODULE_GNRC_IPV6_ROUTER */ DEBUG("ipv6: dropping packet\n"); /* non rounting hosts just drop the packet */ gnrc_pktbuf_release(pkt); return; #endif /* MODULE_GNRC_IPV6_ROUTER */ } /* IPv6 internal demuxing (ICMPv6, Extension headers etc.) */ gnrc_ipv6_demux(iface, first_ext, pkt, hdr->nh); }
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); } }
static void test_pkt_len__1_elem__size_data(void) { gnrc_pktsnip_t snip = _INIT_ELEM_STATIC_DATA(TEST_STRING8, NULL); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), gnrc_pkt_len(&snip)); }
static void test_pkt_len__1_elem__size_0(void) { gnrc_pktsnip_t snip = _INIT_ELEM(0, NULL, NULL); TEST_ASSERT_EQUAL_INT(0, gnrc_pkt_len(&snip)); }
static void test_pkt_len__NULL(void) { TEST_ASSERT_EQUAL_INT(0, gnrc_pkt_len(NULL)); }
void gnrc_sixlowpan_frag_send(gnrc_pktsnip_t *pkt, void *ctx, unsigned page) { assert(ctx != NULL); gnrc_sixlowpan_msg_frag_t *fragment_msg = ctx; gnrc_netif_t *iface = gnrc_netif_get_by_pid(fragment_msg->pid); uint16_t res; /* payload_len: actual size of the packet vs * datagram_size: size of the uncompressed IPv6 packet */ size_t payload_len = gnrc_pkt_len(fragment_msg->pkt->next); msg_t msg; assert((fragment_msg->pkt == pkt) || (pkt == NULL)); (void)page; (void)pkt; #if defined(DEVELHELP) && ENABLE_DEBUG if (iface == NULL) { DEBUG("6lo frag: iface == NULL, expect segmentation fault.\n"); /* remove original packet from packet buffer */ gnrc_pktbuf_release(fragment_msg->pkt); /* 6LoWPAN free for next fragmentation */ fragment_msg->pkt = NULL; return; } #endif /* Check whether to send the first or an Nth fragment */ if (fragment_msg->offset == 0) { /* increment tag for successive, fragmented datagrams */ _tag++; if ((res = _send_1st_fragment(iface, fragment_msg->pkt, payload_len, fragment_msg->datagram_size)) == 0) { /* error sending first fragment */ DEBUG("6lo frag: error sending 1st fragment\n"); gnrc_pktbuf_release(fragment_msg->pkt); fragment_msg->pkt = NULL; return; } fragment_msg->offset += res; /* send message to self*/ msg.type = GNRC_SIXLOWPAN_MSG_FRAG_SND; msg.content.ptr = (void *)fragment_msg; msg_send_to_self(&msg); thread_yield(); } else { /* (offset + (datagram_size - payload_len) < datagram_size) simplified */ if (fragment_msg->offset < payload_len) { if ((res = _send_nth_fragment(iface, fragment_msg->pkt, payload_len, fragment_msg->datagram_size, fragment_msg->offset)) == 0) { /* error sending subsequent fragment */ DEBUG("6lo frag: error sending subsequent fragment (offset = %" PRIu16 ")\n", fragment_msg->offset); gnrc_pktbuf_release(fragment_msg->pkt); fragment_msg->pkt = NULL; return; } fragment_msg->offset += res; /* send message to self*/ msg.type = GNRC_SIXLOWPAN_MSG_FRAG_SND; msg.content.ptr = (void *)fragment_msg; msg_send_to_self(&msg); thread_yield(); } else { gnrc_pktbuf_release(fragment_msg->pkt); fragment_msg->pkt = NULL; } } }
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; }
static void _send(gnrc_pktsnip_t *pkt) { gnrc_netif_hdr_t *hdr; gnrc_pktsnip_t *pkt2; gnrc_netif_t *iface; /* datagram_size: pure IPv6 packet without 6LoWPAN dispatches or compression */ size_t datagram_size; if ((pkt == NULL) || (pkt->size < sizeof(gnrc_netif_hdr_t))) { DEBUG("6lo: Sending packet has no netif header\n"); gnrc_pktbuf_release(pkt); return; } if ((pkt->next == NULL) || (pkt->next->type != GNRC_NETTYPE_IPV6)) { DEBUG("6lo: Sending packet has no IPv6 header\n"); gnrc_pktbuf_release(pkt); return; } pkt2 = gnrc_pktbuf_start_write(pkt); if (pkt2 == NULL) { DEBUG("6lo: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return; } hdr = pkt2->data; iface = gnrc_netif_get_by_pid(hdr->if_pid); datagram_size = gnrc_pkt_len(pkt2->next); if (iface == NULL) { DEBUG("6lo: Can not get 6LoWPAN specific interface information.\n"); gnrc_pktbuf_release(pkt); return; } #ifdef MODULE_GNRC_SIXLOWPAN_IPHC if (iface->flags & GNRC_NETIF_FLAGS_6LO_HC) { if (!gnrc_sixlowpan_iphc_encode(pkt2)) { DEBUG("6lo: error on IPHC encoding\n"); gnrc_pktbuf_release(pkt2); return; } /* IPHC dispatch does not count on dispatch length since it _shortens_ * the datagram */ } else { if (!_add_uncompr_disp(pkt2)) { /* adding uncompressed dispatch failed */ DEBUG("6lo: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt2); return; } } #else /* suppress clang-analyzer report about iface being not read */ (void) iface; if (!_add_uncompr_disp(pkt2)) { /* adding uncompressed dispatch failed */ DEBUG("6lo: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt2); return; } #endif DEBUG("6lo: iface->sixlo.max_frag_size = %" PRIu16 " for interface %" PRIkernel_pid "\n", iface->sixlo.max_frag_size, hdr->if_pid); /* IP should not send anything here if it is not a 6LoWPAN interface, * so we don't need to check for NULL pointers. * Note, that datagram_size cannot be used here, because the header size * might be changed by IPHC. */ if (gnrc_pkt_len(pkt2->next) <= iface->sixlo.max_frag_size) { DEBUG("6lo: Send SND command for %p to %" PRIu16 "\n", (void *)pkt2, hdr->if_pid); if (gnrc_netapi_send(hdr->if_pid, pkt2) < 1) { DEBUG("6lo: unable to send %p over %" PRIu16 "\n", (void *)pkt, hdr->if_pid); gnrc_pktbuf_release(pkt2); } return; } #ifdef MODULE_GNRC_SIXLOWPAN_FRAG else if (fragment_msg.pkt != NULL) { DEBUG("6lo: Fragmentation already ongoing. Dropping packet\n"); gnrc_pktbuf_release(pkt2); return; } else if (datagram_size <= SIXLOWPAN_FRAG_MAX_LEN) { DEBUG("6lo: Send fragmented (%u > %" PRIu16 ")\n", (unsigned int)datagram_size, iface->max_frag_size); msg_t msg; fragment_msg.pid = hdr->if_pid; fragment_msg.pkt = pkt2; fragment_msg.datagram_size = datagram_size; /* Sending the first fragment has an offset==0 */ fragment_msg.offset = 0; /* set the outgoing message's fields */ msg.type = GNRC_SIXLOWPAN_MSG_FRAG_SND; msg.content.ptr = &fragment_msg; /* send message to self */ msg_send_to_self(&msg); } else { DEBUG("6lo: packet too big (%u > %" PRIu16 ")\n", (unsigned int)datagram_size, (uint16_t)SIXLOWPAN_FRAG_MAX_LEN); gnrc_pktbuf_release(pkt2); } #else (void) datagram_size; DEBUG("6lo: packet too big (%u > %" PRIu16 ")\n", (unsigned int)datagram_size, iface->max_frag_size); gnrc_pktbuf_release(pkt2); #endif }