static void test_pkt_len__2_elem__overflow(void) { ng_pktsnip_t snip1 = _INIT_ELEM_STATIC_DATA(TEST_STRING8, NULL); ng_pktsnip_t snip2 = _INIT_ELEM(SIZE_MAX, NULL, &snip1); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8) - 1, ng_pkt_len(&snip2)); /* size should overflow */ TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), ng_pkt_len(&snip1)); }
static void test_pkt_len__2_elem(void) { ng_pktsnip_t snip1 = _INIT_ELEM_STATIC_DATA(TEST_STRING8, NULL); ng_pktsnip_t snip2 = _INIT_ELEM_STATIC_DATA(TEST_STRING12, &snip1); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8) + sizeof(TEST_STRING12), ng_pkt_len(&snip2)); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), ng_pkt_len(&snip1)); }
static void _send(ng_pktsnip_t *pkt) { ng_udp_hdr_t *hdr; ng_pktsnip_t *udp_snip; ng_netreg_entry_t *sendto; /* get udp snip and hdr */ LL_SEARCH_SCALAR(pkt, udp_snip, type, NG_NETTYPE_UDP); udp_snip = ng_pktbuf_start_write(udp_snip); if (udp_snip == NULL) { DEBUG("udp: cannot send packet: unable to allocate packet\n"); ng_pktbuf_release(pkt); return; } hdr = (ng_udp_hdr_t *)udp_snip->data; /* fill in size field */ hdr->length = byteorder_htons(ng_pkt_len(udp_snip)); /* and forward packet to the network layer */ sendto = ng_netreg_lookup(pkt->type, NG_NETREG_DEMUX_CTX_ALL); /* throw away packet if no one is interested */ if (sendto == NULL) { DEBUG("udp: cannot send packet: network layer not found\n"); ng_pktbuf_release(pkt); return; } /* send packet to network layer */ ng_pktbuf_hold(pkt, ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) - 1); while (sendto != NULL) { ng_netapi_send(sendto->pid, pkt); sendto = ng_netreg_getnext(sendto); } }
/** * @brief Make a raw dump of the given packet contents */ void dump_pkt(ng_pktsnip_t *pkt) { ng_pktsnip_t *snip = pkt; printf("rftest-rx --- len 0x%02x lqi 0x%02x rx_time 0x%08lx\n\n", ng_pkt_len(pkt), 0, hwtimer_now()); while (snip) { for (size_t i = 0; i < snip->size; i++) { printf("0x%02x ", ((uint8_t *)(snip->data))[i]); } snip = snip->next; } puts("\n"); ng_pktbuf_release(pkt); }
static int _fill_ipv6_hdr(kernel_pid_t iface, ng_pktsnip_t *ipv6, ng_pktsnip_t *payload) { int res; ng_ipv6_hdr_t *hdr = ipv6->data; hdr->len = byteorder_htons(ng_pkt_len(payload)); DEBUG("ipv6: set payload length to %zu (network byteorder %04" PRIx16 ")\n", ng_pkt_len(payload), hdr->len.u16); /* check if e.g. extension header was not already marked */ if (hdr->nh == NG_PROTNUM_RESERVED) { hdr->nh = ng_nettype_to_protnum(payload->type); /* if still reserved: mark no next header */ if (hdr->nh == NG_PROTNUM_RESERVED) { hdr->nh = NG_PROTNUM_IPV6_NONXT; } } DEBUG("ipv6: set next header to %" PRIu8 "\n", hdr->nh); if (hdr->hl == 0) { hdr->hl = ng_ipv6_netif_get(iface)->cur_hl; } if (ng_ipv6_addr_is_unspecified(&hdr->src)) { ng_ipv6_addr_t *src = ng_ipv6_netif_find_best_src_addr(iface, &hdr->dst); if (src != NULL) { DEBUG("ipv6: set packet source to %s\n", ng_ipv6_addr_to_str(addr_str, src, sizeof(addr_str))); memcpy(&hdr->src, src, sizeof(ng_ipv6_addr_t)); } /* Otherwise leave unspecified */ } DEBUG("ipv6: calculate checksum for upper header.\n"); #if NG_NETIF_NUMOF > 1 if (payload->users > 1) { ng_pktsnip_t *ptr = ipv6; /* We deal with multiple interfaces here (multicast) => possible * different source addresses => duplication of payload needed */ while (ptr != payload->next) { ng_pktsnip_t *old = ptr->next; /* duplicate everything including payload */ ptr->next = ng_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 /* NG_NETIF_NUMOF */ if ((res = ng_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__1_elem__size_data(void) { ng_pktsnip_t snip = _INIT_ELEM_STATIC_DATA(TEST_STRING8, NULL); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), ng_pkt_len(&snip)); }
static void test_pkt_len__1_elem__size_0(void) { ng_pktsnip_t snip = _INIT_ELEM(0, NULL, NULL); TEST_ASSERT_EQUAL_INT(0, ng_pkt_len(&snip)); }
static void test_pkt_len__NULL(void) { TEST_ASSERT_EQUAL_INT(0, ng_pkt_len(NULL)); }
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); } }
static void _send(ng_pktsnip_t *pkt) { ng_netif_hdr_t *hdr; ng_pktsnip_t *ipv6, *sixlowpan; ng_sixlowpan_netif_t *iface; /* cppcheck: datagram_size will be read by frag */ /* cppcheck-suppress unreadVariable */ size_t payload_len, datagram_size; uint16_t max_frag_size; /* cppcheck: disp is needed in other build paths on this level already */ /* cppcheck-suppress variableScope */ uint8_t *disp; if ((pkt == NULL) || (pkt->size < sizeof(ng_netif_hdr_t))) { DEBUG("6lo: Sending packet has no netif header\n"); ng_pktbuf_release(pkt); return; } hdr = pkt->data; ipv6 = pkt->next; if ((ipv6 == NULL) || (ipv6->type != NG_NETTYPE_IPV6)) { DEBUG("6lo: Sending packet has no IPv6 header\n"); ng_pktbuf_release(pkt); return; } /* payload length and datagram size are different in that the payload * length is the length of the IPv6 datagram + 6LoWPAN dispatches, * while the datagram size is the size of only the IPv6 datagram */ payload_len = ng_pkt_len(ipv6); /* cppcheck: datagram_size will be read by ng_sixlowpan_frag implementation */ /* cppcheck-suppress unreadVariable */ datagram_size = (uint16_t)payload_len; /* use sixlowpan packet snip as temporary one */ sixlowpan = ng_pktbuf_start_write(pkt); if (sixlowpan == NULL) { DEBUG("6lo: no space left in packet buffer\n"); ng_pktbuf_release(pkt); return; } pkt = sixlowpan; iface = ng_sixlowpan_netif_get(hdr->if_pid); if (iface == NULL) { if (ng_netapi_get(hdr->if_pid, NETCONF_OPT_MAX_PACKET_SIZE, 0, &max_frag_size, sizeof(max_frag_size)) < 0) { /* if error we assume it works */ DEBUG("6lo: can not get max packet size from interface %" PRIkernel_pid "\n", hdr->if_pid); max_frag_size = UINT16_MAX; } ng_sixlowpan_netif_add(hdr->if_pid, max_frag_size); iface = ng_sixlowpan_netif_get(hdr->if_pid); } else { max_frag_size = iface->max_frag_size; } #ifdef MODULE_NG_SIXLOWPAN_IPHC if (iface->iphc_enabled) { if (!ng_sixlowpan_iphc_encode(pkt)) { DEBUG("6lo: error on IPHC encoding\n"); ng_pktbuf_release(pkt); return; } } else { DEBUG("6lo: Send uncompressed\n"); sixlowpan = ng_pktbuf_add(NULL, NULL, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN); if (sixlowpan == NULL) { DEBUG("6lo: no space left in packet buffer\n"); ng_pktbuf_release(pkt); return; } sixlowpan->next = ipv6; pkt->next = sixlowpan; disp = sixlowpan->data; disp[0] = NG_SIXLOWPAN_UNCOMPRESSED; payload_len++; } #else DEBUG("6lo: Send uncompressed\n"); sixlowpan = ng_pktbuf_add(NULL, NULL, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN); if (sixlowpan == NULL) { DEBUG("6lo: no space left in packet buffer\n"); ng_pktbuf_release(pkt); return; } sixlowpan->next = ipv6; pkt->next = sixlowpan; disp = sixlowpan->data; disp[0] = NG_SIXLOWPAN_UNCOMPRESSED; payload_len++; #endif DEBUG("6lo: max_frag_size = %" PRIu16 " for interface %" PRIkernel_pid "\n", 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 */ if (payload_len <= max_frag_size) { DEBUG("6lo: Send SND command for %p to %" PRIu16 "\n", (void *)pkt, hdr->if_pid); ng_netapi_send(hdr->if_pid, pkt); return; } #ifdef MODULE_NG_SIXLOWPAN_FRAG else { DEBUG("6lo: Send fragmented (%u > %" PRIu16 ")\n", (unsigned int)payload_len, max_frag_size); ng_sixlowpan_frag_send(hdr->if_pid, pkt, payload_len, datagram_size); } #else (void)datagram_size; DEBUG("6lo: packet too big (%u> %" PRIu16 ")\n", (unsigned int)payload_len, max_frag_size); #endif }
static void _send(ng_pktsnip_t *pkt) { ng_netif_hdr_t *hdr; ng_pktsnip_t *pkt2; ng_sixlowpan_netif_t *iface; /* datagram_size: pure IPv6 packet without 6LoWPAN dispatches or compression */ size_t datagram_size; if ((pkt == NULL) || (pkt->size < sizeof(ng_netif_hdr_t))) { DEBUG("6lo: Sending packet has no netif header\n"); ng_pktbuf_release(pkt); return; } if ((pkt->next == NULL) || (pkt->next->type != NG_NETTYPE_IPV6)) { DEBUG("6lo: Sending packet has no IPv6 header\n"); ng_pktbuf_release(pkt); return; } pkt2 = ng_pktbuf_start_write(pkt); if (pkt2 == NULL) { DEBUG("6lo: no space left in packet buffer\n"); ng_pktbuf_release(pkt); return; } hdr = pkt2->data; iface = ng_sixlowpan_netif_get(hdr->if_pid); datagram_size = ng_pkt_len(pkt2->next); if (iface == NULL) { DEBUG("6lo: Can not get 6LoWPAN specific interface information.\n"); ng_pktbuf_release(pkt); return; } #ifdef MODULE_NG_SIXLOWPAN_IPHC if (iface->iphc_enabled) { if (!ng_sixlowpan_iphc_encode(pkt2)) { DEBUG("6lo: error on IPHC encoding\n"); ng_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"); ng_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"); ng_pktbuf_release(pkt2); return; } #endif DEBUG("6lo: iface->max_frag_size = %" PRIu16 " for interface %" PRIkernel_pid "\n", iface->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 */ if (datagram_size <= iface->max_frag_size) { DEBUG("6lo: Send SND command for %p to %" PRIu16 "\n", (void *)pkt2, hdr->if_pid); ng_netapi_send(hdr->if_pid, pkt2); return; } #ifdef MODULE_NG_SIXLOWPAN_FRAG else { DEBUG("6lo: Send fragmented (%u > %" PRIu16 ")\n", (unsigned int)datagram_size, iface->max_frag_size); ng_sixlowpan_frag_send(hdr->if_pid, pkt2, datagram_size); } #else (void)datagram_size; DEBUG("6lo: packet too big (%u> %" PRIu16 ")\n", (unsigned int)datagram_size, iface->max_frag_size); #endif }
int _send(ng_netdev_t *dev, ng_pktsnip_t *pkt) { (void)dev; size_t size; size_t pos = 0; uint8_t *dst_addr; ng_netif_hdr_t *hdr; ng_pktsnip_t *payload; /* check packet */ if (pkt == NULL || pkt->next == NULL) { DEBUG("nrfmin: Error sending packet: packet incomplete\n"); return -ENOMSG; } /* check if payload is withing length bounds */ size = ng_pkt_len(pkt->next); if (size > CONF_PAYLOAD_LEN) { ng_pktbuf_release(pkt); DEBUG("nrfmin: Error sending packet: payload to large\n"); return -EOVERFLOW; } /* get netif header and check address length */ hdr = (ng_netif_hdr_t *)pkt->data; if (hdr->dst_l2addr_len != 2) { DEBUG("nrfmin: Error sending packet: dest address has invalid size\n"); ng_pktbuf_release(pkt); return -ENOMSG; } dst_addr = ng_netif_hdr_get_dst_addr(hdr); DEBUG("nrfmin: Sending packet to %02x:%02x - size %u\n", dst_addr[0], dst_addr[1], size); /* wait for any ongoing transmission to finish */ while (_state == STATE_TX); /* write data into TX buffer */ payload = pkt->next; _tx_buf.length = 6 + size; _tx_buf.src_addr[0] = (uint8_t)(_addr >> 8); _tx_buf.src_addr[1] = (uint8_t)(_addr); _tx_buf.dst_addr[0] = dst_addr[0]; _tx_buf.dst_addr[1] = dst_addr[1]; _tx_buf.proto = _nettype_to_nrftype(payload->type); while (payload) { memcpy(&(_tx_buf.payload[pos]), payload->data, payload->size); pos += payload->size; payload = payload->next; } /* save old state and switch to idle if applicable */ _tx_prestate = _state; if (_tx_prestate == STATE_RX) { _switch_to_idle(); } /* set packet pointer to TX buffer and write destination address */ NRF_RADIO->PACKETPTR = (uint32_t)(&_tx_buf); NRF_RADIO->BASE0 &= ~(0xffff); NRF_RADIO->BASE0 |= ((((uint16_t)dst_addr[0]) << 8) | dst_addr[1]); /* start transmission */ _state = STATE_TX; NRF_RADIO->TASKS_TXEN = 1; /* release packet */ ng_pktbuf_release(pkt); return (int)size; }