static void test_pktbuf_mark__success_equally_sized(void) { gnrc_pktsnip_t *pkt1 = gnrc_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), GNRC_NETTYPE_TEST); gnrc_pktsnip_t *pkt2; TEST_ASSERT_NOT_NULL(pkt1); TEST_ASSERT_NOT_NULL((pkt2 = gnrc_pktbuf_mark(pkt1, sizeof(TEST_STRING16), GNRC_NETTYPE_UNDEF))); TEST_ASSERT(gnrc_pktbuf_is_sane()); TEST_ASSERT(pkt1->next == pkt2); TEST_ASSERT_NULL(pkt1->data); TEST_ASSERT_EQUAL_INT(0, pkt1->size); TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_TEST, pkt1->type); TEST_ASSERT_EQUAL_INT(1, pkt1->users); TEST_ASSERT_NULL(pkt2->next); TEST_ASSERT_EQUAL_INT(0, memcmp(TEST_STRING16, pkt2->data, pkt2->size)); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16), pkt2->size); TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_UNDEF, pkt2->type); TEST_ASSERT_EQUAL_INT(1, pkt2->users); TEST_ASSERT(gnrc_pktbuf_is_sane()); /* check if everything can be cleaned up */ gnrc_pktbuf_release(pkt1); TEST_ASSERT(gnrc_pktbuf_is_sane()); TEST_ASSERT(gnrc_pktbuf_is_empty()); }
static void test_pktbuf_mark__pkt_NOT_NULL__pkt_data_NULL(void) { gnrc_pktsnip_t pkt = { NULL, NULL, sizeof(TEST_STRING16), 1, GNRC_NETTYPE_TEST }; TEST_ASSERT_NULL(gnrc_pktbuf_mark(&pkt, sizeof(TEST_STRING16) - 1, GNRC_NETTYPE_TEST)); TEST_ASSERT_NULL(pkt.next); TEST_ASSERT_NULL(pkt.data); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16), pkt.size); TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_TEST, pkt.type); TEST_ASSERT_EQUAL_INT(1, pkt.users); }
static void test_pktbuf_mark__pkt_NOT_NULL__size_0(void) { gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), GNRC_NETTYPE_TEST); TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NULL(gnrc_pktbuf_mark(pkt, 0, GNRC_NETTYPE_TEST)); TEST_ASSERT_NULL(pkt->next); TEST_ASSERT_NOT_NULL(pkt->data); TEST_ASSERT_EQUAL_STRING(TEST_STRING16, pkt->data); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16), pkt->size); TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_TEST, pkt->type); TEST_ASSERT_EQUAL_INT(1, pkt->users); }
static void test_pktbuf_release__short_pktsnips(void) { gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, TEST_STRING8, sizeof(TEST_STRING8), GNRC_NETTYPE_UNDEF); gnrc_pktsnip_t *hdr = gnrc_pktbuf_mark(pkt, sizeof(TEST_STRING8) - 1, GNRC_NETTYPE_TEST); TEST_ASSERT(pkt); TEST_ASSERT(hdr); TEST_ASSERT(pkt->next == hdr); TEST_ASSERT(hdr->next == NULL); TEST_ASSERT_EQUAL_INT(hdr->size, sizeof(TEST_STRING8) - 1); TEST_ASSERT_EQUAL_INT(pkt->size, 1); gnrc_pktbuf_release(pkt); TEST_ASSERT(gnrc_pktbuf_is_empty()); }
static void test_pktbuf_mark__success_aligned(void) { uint8_t *data = (uint8_t *)(TEST_STRING16); gnrc_pktsnip_t *pkt1 = gnrc_pktbuf_add(NULL, data, sizeof(TEST_STRING16), GNRC_NETTYPE_TEST); gnrc_pktsnip_t *pkt2; uint8_t exp_data1[sizeof(TEST_STRING16) - 8]; uint8_t exp_data2[8]; memcpy(exp_data1, data + sizeof(exp_data2), sizeof(exp_data1)); memcpy(exp_data2, data, sizeof(exp_data2)); TEST_ASSERT_NOT_NULL(pkt1); TEST_ASSERT_NOT_NULL((pkt2 = gnrc_pktbuf_mark(pkt1, 8, GNRC_NETTYPE_UNDEF))); TEST_ASSERT(gnrc_pktbuf_is_sane()); TEST_ASSERT(pkt1->next == pkt2); TEST_ASSERT_NOT_NULL(pkt1->data); TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data1, pkt1->data, pkt1->size)); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16) - 8, pkt1->size); TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_TEST, pkt1->type); TEST_ASSERT_EQUAL_INT(1, pkt1->users); TEST_ASSERT_NULL(pkt2->next); TEST_ASSERT_NOT_NULL(pkt2->data); TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data2, pkt2->data, pkt2->size)); TEST_ASSERT_EQUAL_INT(8, pkt2->size); TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_UNDEF, pkt2->type); TEST_ASSERT_EQUAL_INT(1, pkt2->users); /* check if slightly larger packet would override data */ gnrc_pktbuf_remove_snip(pkt1, pkt2); pkt2 = gnrc_pktbuf_add(NULL, TEST_STRING12, 12, GNRC_NETTYPE_TEST); TEST_ASSERT(gnrc_pktbuf_is_sane()); TEST_ASSERT_NOT_NULL(pkt1->data); TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data1, pkt1->data, pkt1->size)); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16) - 8, pkt1->size); TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_TEST, pkt1->type); TEST_ASSERT_EQUAL_INT(1, pkt1->users); /* check if everything can be cleaned up */ gnrc_pktbuf_release(pkt1); gnrc_pktbuf_release(pkt2); TEST_ASSERT(gnrc_pktbuf_is_empty()); }
/** * @brief marks IPv6 extension header if needed. * updates pkt and returns next header. * @param[in] current The current header * @param[in,out] pkt The whole packet * @return The next header * @return NULL on error */ static gnrc_pktsnip_t *_mark_extension_header(gnrc_pktsnip_t *current, gnrc_pktsnip_t **pkt) { gnrc_pktsnip_t *ext_snip, *tmp, *next; ipv6_ext_t *ext = (ipv6_ext_t *) current->data; size_t offset = ((ext->len * IPV6_EXT_LEN_UNIT) + IPV6_EXT_LEN_UNIT); if (current == *pkt) { if ((tmp = gnrc_pktbuf_start_write(*pkt)) == NULL) { DEBUG("ipv6: could not get a copy of pkt\n"); gnrc_pktbuf_release(*pkt); return NULL; } *pkt = tmp; ext_snip = gnrc_pktbuf_mark(*pkt, offset, GNRC_NETTYPE_IPV6_EXT); next = *pkt; if (ext_snip == NULL) { gnrc_pktbuf_release(*pkt); return NULL; } } else { /* the header is already marked */ next = NULL; for (tmp = *pkt; tmp != NULL; tmp = tmp->next) { if (tmp->next == current) { next = tmp; break; } } assert(next != NULL); } return next; }
static void test_pktbuf_mark__pkt_NULL__size_not_0(void) { TEST_ASSERT_NULL(gnrc_pktbuf_mark(NULL, sizeof(TEST_STRING4), GNRC_NETTYPE_TEST)); }
static void test_pktbuf_mark__pkt_NULL__size_0(void) { TEST_ASSERT_NULL(gnrc_pktbuf_mark(NULL, 0, GNRC_NETTYPE_TEST)); }
static gnrc_pktsnip_t *_recv(gnrc_netdev2_t *gnrc_netdev2) { netdev2_t *netdev = gnrc_netdev2->dev; netdev2_ieee802154_rx_info_t rx_info; netdev2_ieee802154_t *state = (netdev2_ieee802154_t *)gnrc_netdev2->dev; gnrc_pktsnip_t *pkt = NULL; int bytes_expected = netdev->driver->recv(netdev, NULL, 0, NULL); if (bytes_expected > 0) { int nread; pkt = gnrc_pktbuf_add(NULL, NULL, bytes_expected, GNRC_NETTYPE_UNDEF); if (pkt == NULL) { DEBUG("_recv_ieee802154: cannot allocate pktsnip.\n"); return NULL; } nread = netdev->driver->recv(netdev, pkt->data, bytes_expected, &rx_info); if (nread <= 0) { gnrc_pktbuf_release(pkt); return NULL; } if (!(state->flags & NETDEV2_IEEE802154_RAW)) { gnrc_pktsnip_t *ieee802154_hdr, *netif_hdr; gnrc_netif_hdr_t *hdr; #if ENABLE_DEBUG char src_str[GNRC_NETIF_HDR_L2ADDR_MAX_LEN]; #endif size_t mhr_len = ieee802154_get_frame_hdr_len(pkt->data); if (mhr_len == 0) { DEBUG("_recv_ieee802154: illegally formatted frame received\n"); gnrc_pktbuf_release(pkt); return NULL; } nread -= mhr_len; /* mark IEEE 802.15.4 header */ ieee802154_hdr = gnrc_pktbuf_mark(pkt, mhr_len, GNRC_NETTYPE_UNDEF); if (ieee802154_hdr == NULL) { DEBUG("_recv_ieee802154: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return NULL; } netif_hdr = _make_netif_hdr(ieee802154_hdr->data); if (netif_hdr == NULL) { DEBUG("_recv_ieee802154: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return NULL; } hdr = netif_hdr->data; hdr->lqi = rx_info.lqi; hdr->rssi = rx_info.rssi; hdr->if_pid = thread_getpid(); pkt->type = state->proto; #if ENABLE_DEBUG DEBUG("_recv_ieee802154: received packet from %s of length %u\n", gnrc_netif_addr_to_str(src_str, sizeof(src_str), gnrc_netif_hdr_get_src_addr(hdr), hdr->src_l2addr_len), nread); #if defined(MODULE_OD) od_hex_dump(pkt->data, nread, OD_WIDTH_DEFAULT); #endif #endif gnrc_pktbuf_remove_snip(pkt, ieee802154_hdr); LL_APPEND(pkt, netif_hdr); } DEBUG("_recv_ieee802154: reallocating.\n"); gnrc_pktbuf_realloc_data(pkt, nread); } return pkt; }
void gnrc_gomach_beacon_process(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt) { assert(netif != NULL); assert(pkt != NULL); gnrc_gomach_frame_beacon_t *gomach_beacon_hdr = NULL; gnrc_pktsnip_t *gomach_snip = NULL; gnrc_gomach_l2_id_t *id_list; uint8_t *slots_list; uint8_t schedulelist_size = 0; bool got_allocated_slots; uint8_t id_position; gnrc_pktsnip_t *beacon_snip = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_GOMACH); if (beacon_snip == NULL) { LOG_ERROR("[GOMACH]: No beacon-snip found in gnrc_gomach_beacon_process().\n"); return; } else { gomach_beacon_hdr = beacon_snip->data; } if (gomach_beacon_hdr == NULL) { LOG_ERROR("ERROR: [GOMACH]: GoMacH's beacon header is null.\n"); return; } schedulelist_size = gomach_beacon_hdr->schedulelist_size; netif->mac.tx.vtdma_para.sub_channel_seq = gomach_beacon_hdr->sub_channel_seq; if (schedulelist_size == 0) { /* No allocated slots. */ netif->mac.tx.vtdma_para.slots_num = 0; netif->mac.tx.vtdma_para.slots_position = 0; return; } /* Take the ID-list out. */ gomach_snip = gnrc_pktbuf_mark(pkt, schedulelist_size * sizeof(gnrc_gomach_l2_id_t), GNRC_NETTYPE_GOMACH); id_list = gomach_snip->data; /* Take the slots-list out. */ slots_list = pkt->data; /* Check whether this device has been allocated slots. */ int i = 0; got_allocated_slots = false; id_position = 0; for (i = 0; i < schedulelist_size; i++) { if (memcmp(netif->l2addr, id_list[i].addr, netif->l2addr_len) == 0) { got_allocated_slots = true; id_position = i; break; } } if (got_allocated_slots == true) { /* Find the slots number and the related slots position. */ netif->mac.tx.vtdma_para.slots_num = slots_list[id_position]; uint8_t slots_position = 0; for (i = 0; i < id_position; i++) { slots_position += slots_list[i]; } netif->mac.tx.vtdma_para.slots_position = slots_position; } else { /* No allocated slots. */ netif->mac.tx.vtdma_para.slots_num = 0; netif->mac.tx.vtdma_para.slots_position = 0; } }
void gnrc_rpl_p2p_recv_DRO(gnrc_pktsnip_t *pkt, ipv6_addr_t *src) { gnrc_pktsnip_t *icmpv6_snip = gnrc_pktbuf_mark(pkt, sizeof(icmpv6_hdr_t), GNRC_NETTYPE_ICMPV6); gnrc_pktsnip_t *dro_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_rpl_p2p_dro_t), GNRC_NETTYPE_UNDEF); gnrc_pktsnip_t *rdo_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_rpl_p2p_opt_rdo_t), GNRC_NETTYPE_UNDEF); gnrc_pktsnip_t *addr_snip = pkt; gnrc_rpl_instance_t *inst; gnrc_rpl_dodag_t *dodag; gnrc_rpl_p2p_ext_t *p2p_ext; gnrc_rpl_p2p_dro_t *dro; gnrc_rpl_p2p_opt_rdo_t *rdo; uint8_t *addr_vec; uint16_t flags; size_t addr_len; if (!rdo_snip || !dro_snip) { DEBUG("RPL-P2P: Error - No DRO or RDO received\n"); gnrc_pktbuf_release(pkt); return; } dro = dro_snip->data; if ((inst = gnrc_rpl_instance_get(dro->instance_id)) == NULL) { DEBUG("RPL-P2P: Error - Instance (%d) does not exist\n", dro->instance_id); return; } dodag = &inst->dodag; if ((p2p_ext = gnrc_rpl_p2p_ext_get(dodag)) == NULL) { DEBUG("RPL-P2P: Error - No P2P-RPL DODAG extension found\n"); return; } if (p2p_ext->for_me) { DEBUG("RPL-P2P: Ignore DRO\n"); return; } flags = byteorder_ntohs(dro->flags_rev); p2p_ext->stop = (flags & (1 << GNRC_RPL_P2P_DRO_FLAGS_STOP)) >> GNRC_RPL_P2P_DRO_FLAGS_STOP; p2p_ext->dro_ack = (flags & (1 << GNRC_RPL_P2P_DRO_FLAGS_ACK)) >> GNRC_RPL_P2P_DRO_FLAGS_ACK; p2p_ext->dro_seq = (flags & (0x3 << GNRC_RPL_P2P_DRO_FLAGS_SEQ)) >> GNRC_RPL_P2P_DRO_FLAGS_SEQ; addr_len = sizeof(ipv6_addr_t) - p2p_ext->compr; ipv6_addr_t addr = p2p_ext->dodag->dodag_id; ipv6_addr_t *me = NULL; addr_vec = addr_snip->data; rdo = rdo_snip->data; if (rdo->lmn > 0) { rdo->lmn--; memcpy(&addr.u8[p2p_ext->compr], &addr_vec[addr_len * rdo->lmn], addr_len); } if (gnrc_ipv6_netif_find_by_addr(&me, &addr) == dodag->iface) { gnrc_ipv6_nib_ft_add(&p2p_ext->target, IPV6_ADDR_BIT_LEN, src, dodag->iface, p2p_ext->dodag->default_lifetime * p2p_ext->dodag->lifetime_unit); if (p2p_ext->dodag->node_status != GNRC_RPL_ROOT_NODE) { if ((rdo_snip = gnrc_pktbuf_start_write(rdo_snip)) == NULL) { DEBUG("RPL-P2P: Error - Cannot allocate new RDO\n"); return; } addr_snip->next = NULL; rdo_snip->next = addr_snip; dro_snip->next = rdo_snip; icmpv6_snip = gnrc_icmpv6_build(dro_snip, ICMPV6_RPL_CTRL, GNRC_RPL_P2P_ICMPV6_CODE_DRO, sizeof(icmpv6_hdr_t)); if (icmpv6_snip == NULL) { DEBUG("RPL-P2P: cannot allocate ICMPv6 - no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return; } gnrc_rpl_send(icmpv6_snip, p2p_ext->dodag->iface, NULL, NULL, &p2p_ext->dodag->dodag_id); return; } } gnrc_pktbuf_release(pkt); return; }
static gnrc_pktsnip_t *_recv(gnrc_netdev2_t *gnrc_netdev2) { netdev2_t *dev = gnrc_netdev2->dev; int bytes_expected = dev->driver->recv(dev, NULL, 0); gnrc_pktsnip_t *pkt = NULL; if (bytes_expected) { pkt = gnrc_pktbuf_add(NULL, NULL, bytes_expected, GNRC_NETTYPE_UNDEF); if(!pkt) { DEBUG("_recv_ethernet_packet: cannot allocate pktsnip.\n"); goto out; } int nread = dev->driver->recv(dev, pkt->data, bytes_expected); if(nread <= 0) { DEBUG("_recv_ethernet_packet: read error.\n"); goto safe_out; } if (nread < bytes_expected) { /* we've got less then the expected packet size, * so free the unused space.*/ DEBUG("_recv_ethernet_packet: reallocating.\n"); gnrc_pktbuf_realloc_data(pkt, nread); } /* mark ethernet header */ gnrc_pktsnip_t *eth_hdr = gnrc_pktbuf_mark(pkt, sizeof(ethernet_hdr_t), GNRC_NETTYPE_UNDEF); if (!eth_hdr) { DEBUG("gnrc_netdev2_eth: no space left in packet buffer\n"); goto safe_out; } ethernet_hdr_t *hdr = (ethernet_hdr_t *)eth_hdr->data; /* set payload type from ethertype */ pkt->type = gnrc_nettype_from_ethertype(byteorder_ntohs(hdr->type)); /* create netif header */ gnrc_pktsnip_t *netif_hdr; netif_hdr = gnrc_pktbuf_add(NULL, NULL, sizeof(gnrc_netif_hdr_t) + (2 * ETHERNET_ADDR_LEN), GNRC_NETTYPE_NETIF); if (netif_hdr == NULL) { DEBUG("gnrc_netdev2_eth: no space left in packet buffer\n"); pkt = eth_hdr; goto safe_out; } gnrc_netif_hdr_init(netif_hdr->data, ETHERNET_ADDR_LEN, ETHERNET_ADDR_LEN); gnrc_netif_hdr_set_src_addr(netif_hdr->data, hdr->src, ETHERNET_ADDR_LEN); gnrc_netif_hdr_set_dst_addr(netif_hdr->data, hdr->dst, ETHERNET_ADDR_LEN); ((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = thread_getpid(); DEBUG("gnrc_netdev2_eth: received packet from %02x:%02x:%02x:%02x:%02x:%02x " "of length %zu\n", hdr->src[0], hdr->src[1], hdr->src[2], hdr->src[3], hdr->src[4], hdr->src[5], nread); #if defined(MODULE_OD) && ENABLE_DEBUG od_hex_dump(hdr, nread, OD_WIDTH_DEFAULT); #endif gnrc_pktbuf_remove_snip(pkt, eth_hdr); LL_APPEND(pkt, netif_hdr); } out: return pkt; safe_out: gnrc_pktbuf_release(pkt); return NULL; }
static void _receive(gnrc_pktsnip_t *pkt) { kernel_pid_t iface = KERNEL_PID_UNDEF; gnrc_pktsnip_t *ipv6, *netif; ipv6_hdr_t *hdr; assert(pkt != NULL); LL_SEARCH_SCALAR(pkt, netif, type, GNRC_NETTYPE_NETIF); if (netif != NULL) { iface = ((gnrc_netif_hdr_t *)netif->data)->if_pid; } if ((pkt->next != NULL) && (pkt->next->type == GNRC_NETTYPE_IPV6) && (pkt->next->size == sizeof(ipv6_hdr_t))) { /* IP header was already marked. Take it. */ ipv6 = pkt->next; if (!ipv6_hdr_is(ipv6->data)) { DEBUG("ipv6: Received packet was not IPv6, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } } else { if (!ipv6_hdr_is(pkt->data)) { DEBUG("ipv6: Received packet was not IPv6, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } /* 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); if (ipv6 == NULL) { DEBUG("ipv6: error marking IPv6 header, dropping packet\n"); gnrc_pktbuf_release(pkt); return; } } /* 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)); } DEBUG("ipv6: Received (src = %s, ", ipv6_addr_to_str(addr_str, &(hdr->src), sizeof(addr_str))); DEBUG("dst = %s, next header = %" PRIu8 ", 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 %" PRIu8 "\n", 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 *tmp = pkt; DEBUG("ipv6: forward packet to next hop\n"); /* pkt might not be writable yet, if header was given above */ pkt = gnrc_pktbuf_start_write(tmp); ipv6 = gnrc_pktbuf_start_write(ipv6); if ((ipv6 == NULL) || (pkt == NULL)) { DEBUG("ipv6: unable to get write access to packet: dropping it\n"); gnrc_pktbuf_release(tmp); return; } gnrc_pktbuf_release(ipv6->next); /* remove headers around IPV6 */ ipv6->next = pkt; /* reorder for sending */ pkt->next = NULL; _send(ipv6, 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, pkt, hdr->nh); }
static void _receive(gnrc_pktsnip_t *pkt) { gnrc_pktsnip_t *payload; uint8_t *dispatch; /* seize payload as a temporary variable */ payload = gnrc_pktbuf_start_write(pkt); /* need to duplicate since pkt->next * might get replaced */ if (payload == NULL) { DEBUG("6lo: can not get write access on received packet\n"); #if defined(DEVELHELP) && ENABLE_DEBUG gnrc_pktbuf_stats(); #endif gnrc_pktbuf_release(pkt); return; } pkt = payload; /* reset pkt from temporary variable */ payload = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_SIXLOWPAN); if ((payload == NULL) || (payload->size < 1)) { DEBUG("6lo: Received packet has no 6LoWPAN payload\n"); gnrc_pktbuf_release(pkt); return; } dispatch = payload->data; if (dispatch[0] == SIXLOWPAN_UNCOMP) { gnrc_pktsnip_t *sixlowpan; DEBUG("6lo: received uncompressed IPv6 packet\n"); payload = gnrc_pktbuf_start_write(payload); if (payload == NULL) { DEBUG("6lo: can not get write access on received packet\n"); #if defined(DEVELHELP) && ENABLE_DEBUG gnrc_pktbuf_stats(); #endif gnrc_pktbuf_release(pkt); return; } /* packet is uncompressed: just mark and remove the dispatch */ sixlowpan = gnrc_pktbuf_mark(payload, sizeof(uint8_t), GNRC_NETTYPE_SIXLOWPAN); if (sixlowpan == NULL) { DEBUG("6lo: can not mark 6LoWPAN dispatch\n"); gnrc_pktbuf_release(pkt); return; } pkt = gnrc_pktbuf_remove_snip(pkt, sixlowpan); payload->type = GNRC_NETTYPE_IPV6; } #ifdef MODULE_GNRC_SIXLOWPAN_FRAG else if (sixlowpan_frag_is((sixlowpan_frag_t *)dispatch)) { DEBUG("6lo: received 6LoWPAN fragment\n"); gnrc_sixlowpan_frag_handle_pkt(pkt); return; } #endif #ifdef MODULE_GNRC_SIXLOWPAN_IPHC else if (sixlowpan_iphc_is(dispatch)) { size_t dispatch_size, nh_len; gnrc_pktsnip_t *sixlowpan; gnrc_pktsnip_t *dec_hdr = gnrc_pktbuf_add(NULL, NULL, sizeof(ipv6_hdr_t), GNRC_NETTYPE_IPV6); if ((dec_hdr == NULL) || (dispatch_size = gnrc_sixlowpan_iphc_decode(&dec_hdr, pkt, 0, 0, &nh_len)) == 0) { DEBUG("6lo: error on IPHC decoding\n"); if (dec_hdr != NULL) { gnrc_pktbuf_release(dec_hdr); } gnrc_pktbuf_release(pkt); return; } sixlowpan = gnrc_pktbuf_mark(pkt, dispatch_size, GNRC_NETTYPE_SIXLOWPAN); if (sixlowpan == NULL) { DEBUG("6lo: error on marking IPHC dispatch\n"); gnrc_pktbuf_release(dec_hdr); gnrc_pktbuf_release(pkt); return; } /* Remove IPHC dispatches */ /* Insert decoded header instead */ pkt = gnrc_pktbuf_replace_snip(pkt, sixlowpan, dec_hdr); payload->type = GNRC_NETTYPE_UNDEF; } #endif else { DEBUG("6lo: dispatch %02" PRIx8 " ... is not supported\n", dispatch[0]); gnrc_pktbuf_release(pkt); return; } if (!gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) { DEBUG("6lo: No receivers for this packet found\n"); gnrc_pktbuf_release(pkt); } }
static int _parse_packet(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt, gnrc_gomach_packet_info_t *info) { assert(info != NULL); assert(pkt != NULL); netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev; /* Get the packet sequence number */ info->seq = ieee802154_get_seq(pkt->next->data); gnrc_pktsnip_t *netif_snip = _make_netif_hdr(pkt->next->data); if (netif_snip == NULL) { DEBUG("gomach: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return -ENODATA; } gnrc_netif_hdr_t *netif_hdr = netif_snip->data; netif_hdr->lqi = netif->mac.prot.gomach.rx_pkt_lqi; netif_hdr->rssi = netif->mac.prot.gomach.rx_pkt_rssi; netif_hdr->if_pid = netif->pid; pkt->type = state->proto; gnrc_pktbuf_remove_snip(pkt, pkt->next); LL_APPEND(pkt, netif_snip); gnrc_pktsnip_t *gomach_snip = NULL; gnrc_gomach_hdr_t *gomach_hdr = NULL; netif_snip = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); if (netif_snip == NULL) { return -ENODATA; } else { netif_hdr = netif_snip->data; } if (netif_hdr->dst_l2addr_len > sizeof(info->dst_addr)) { return -ENODATA; } if (netif_hdr->src_l2addr_len > sizeof(info->src_addr)) { return -ENODATA; } /* Dissect GoMacH header, Every frame has header as first member */ gomach_hdr = (gnrc_gomach_hdr_t *) pkt->data; switch (gomach_hdr->type) { case GNRC_GOMACH_FRAME_BEACON: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_beacon_t), GNRC_NETTYPE_GOMACH); break; } case GNRC_GOMACH_FRAME_PREAMBLE: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_preamble_t), GNRC_NETTYPE_GOMACH); break; } case GNRC_GOMACH_FRAME_PREAMBLE_ACK: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_preamble_ack_t), GNRC_NETTYPE_GOMACH); break; } case GNRC_GOMACH_FRAME_DATA: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_data_t), GNRC_NETTYPE_GOMACH); break; } case GNRC_GOMACH_FRAME_ANNOUNCE: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_announce_t), GNRC_NETTYPE_GOMACH); break; } case GNRC_GOMACH_FRAME_BROADCAST: { gomach_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_gomach_frame_broadcast_t), GNRC_NETTYPE_GOMACH); break; } default: { return -ENODATA; } } /* Memory location may have changed while marking. */ gomach_hdr = gomach_snip->data; /* Get the destination address. */ switch (gomach_hdr->type) { case GNRC_GOMACH_FRAME_PREAMBLE: { info->dst_addr = ((gnrc_gomach_frame_preamble_t *)gomach_hdr)->dst_addr; break; } case GNRC_GOMACH_FRAME_PREAMBLE_ACK: { info->dst_addr = ((gnrc_gomach_frame_preamble_ack_t *)gomach_hdr)->dst_addr; break; } case GNRC_GOMACH_FRAME_DATA: { if (netif_hdr->dst_l2addr_len) { info->dst_addr.len = netif_hdr->dst_l2addr_len; memcpy(info->dst_addr.addr, gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len); } break; } default: { break; } } /* Get the source address. */ if (netif_hdr->src_l2addr_len) { info->src_addr.len = netif_hdr->src_l2addr_len; memcpy(info->src_addr.addr, gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len); } info->header = gomach_hdr; return 0; }
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); }
bool gnrc_ipv6_ext_demux(kernel_pid_t iface, gnrc_pktsnip_t *pkt, uint8_t nh) { gnrc_pktsnip_t *ext_snip, *tmp; ipv6_ext_t *ext; unsigned int offset = 0; ipv6_hdr_t *hdr; int res; ext = ((ipv6_ext_t *)(((uint8_t *)pkt->data) + sizeof(ipv6_hdr_t))); bool c = true; while (c) { switch (nh) { case PROTNUM_IPV6_EXT_HOPOPT: case PROTNUM_IPV6_EXT_DST: case PROTNUM_IPV6_EXT_RH: if ((tmp = gnrc_pktbuf_start_write(pkt)) == NULL) { DEBUG("ipv6: could not get a copy of pkt\n"); gnrc_pktbuf_release(pkt); return false; } pkt = tmp; hdr = pkt->data; ext = (ipv6_ext_t *) (((uint8_t *) pkt->data) + sizeof(ipv6_hdr_t) + offset); res = ipv6_ext_rh_process(hdr, (ipv6_ext_rh_t *)ext); if (res == EXT_RH_CODE_ERROR) { /* TODO: send ICMPv6 error codes */ gnrc_pktbuf_release(pkt); return false; } else if (res == EXT_RH_CODE_FORWARD) { /* forward packet */ if (!gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) { DEBUG("ipv6: could not dispatch packet to the ipv6 thread\n"); gnrc_pktbuf_release(pkt); } return false; } else if (res == EXT_RH_CODE_OK) { nh = ext->nh; offset += ((ext->len * IPV6_EXT_LEN_UNIT) + IPV6_EXT_LEN_UNIT); ext = ipv6_ext_get_next((ipv6_ext_t *)ext); } break; case PROTNUM_IPV6_EXT_FRAG: case PROTNUM_IPV6_EXT_AH: case PROTNUM_IPV6_EXT_ESP: case PROTNUM_IPV6_EXT_MOB: /* TODO: add handling of types */ nh = ext->nh; offset += ((ext->len * IPV6_EXT_LEN_UNIT) + IPV6_EXT_LEN_UNIT); ext = ipv6_ext_get_next((ipv6_ext_t *)ext); break; default: c = false; offset += ((ext->len * IPV6_EXT_LEN_UNIT) + IPV6_EXT_LEN_UNIT); ext = ipv6_ext_get_next((ipv6_ext_t *)ext); break; } } ext_snip = gnrc_pktbuf_mark(pkt, offset, GNRC_NETTYPE_IPV6); if (ext_snip == NULL) { gnrc_pktbuf_release(pkt); return false; } gnrc_ipv6_demux(iface, pkt, nh); /* demultiplex next header */ return true; }
static gnrc_pktsnip_t *_recv(gnrc_netif_t *netif) { netdev_t *dev = netif->dev; netdev_ieee802154_rx_info_t rx_info; gnrc_pktsnip_t *pkt = NULL; int bytes_expected = dev->driver->recv(dev, NULL, 0, NULL); if (bytes_expected >= (int)IEEE802154_MIN_FRAME_LEN) { int nread; pkt = gnrc_pktbuf_add(NULL, NULL, bytes_expected, GNRC_NETTYPE_UNDEF); if (pkt == NULL) { DEBUG("_recv_ieee802154: cannot allocate pktsnip.\n"); /* Discard packet on netdev device */ dev->driver->recv(dev, NULL, bytes_expected, NULL); return NULL; } nread = dev->driver->recv(dev, pkt->data, bytes_expected, &rx_info); if (nread <= 0) { gnrc_pktbuf_release(pkt); return NULL; } #ifdef MODULE_NETSTATS_L2 netif->stats.rx_count++; netif->stats.rx_bytes += nread; #endif if (netif->flags & GNRC_NETIF_FLAGS_RAWMODE) { /* Raw mode, skip packet processing, but provide rx_info via * GNRC_NETTYPE_NETIF */ gnrc_pktsnip_t *netif_snip = gnrc_netif_hdr_build(NULL, 0, NULL, 0); if (netif_snip == NULL) { DEBUG("_recv_ieee802154: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return NULL; } gnrc_netif_hdr_t *hdr = netif_snip->data; hdr->lqi = rx_info.lqi; hdr->rssi = rx_info.rssi; hdr->if_pid = netif->pid; LL_APPEND(pkt, netif_snip); } else { /* Normal mode, try to parse the frame according to IEEE 802.15.4 */ gnrc_pktsnip_t *ieee802154_hdr, *netif_hdr; gnrc_netif_hdr_t *hdr; #if ENABLE_DEBUG char src_str[GNRC_NETIF_HDR_L2ADDR_PRINT_LEN]; #endif size_t mhr_len = ieee802154_get_frame_hdr_len(pkt->data); /* nread was checked for <= 0 before so we can safely cast it to * unsigned */ if ((mhr_len == 0) || ((size_t)nread < mhr_len)) { DEBUG("_recv_ieee802154: illegally formatted frame received\n"); gnrc_pktbuf_release(pkt); return NULL; } nread -= mhr_len; /* mark IEEE 802.15.4 header */ ieee802154_hdr = gnrc_pktbuf_mark(pkt, mhr_len, GNRC_NETTYPE_UNDEF); if (ieee802154_hdr == NULL) { DEBUG("_recv_ieee802154: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return NULL; } netif_hdr = _make_netif_hdr(ieee802154_hdr->data); if (netif_hdr == NULL) { DEBUG("_recv_ieee802154: no space left in packet buffer\n"); gnrc_pktbuf_release(pkt); return NULL; } hdr = netif_hdr->data; #ifdef MODULE_L2FILTER if (!l2filter_pass(dev->filter, gnrc_netif_hdr_get_src_addr(hdr), hdr->src_l2addr_len)) { gnrc_pktbuf_release(pkt); gnrc_pktbuf_release(netif_hdr); DEBUG("_recv_ieee802154: packet dropped by l2filter\n"); return NULL; } #endif #ifdef MODULE_GNRC_NETIF_DEDUP if (_already_received(netif, hdr, ieee802154_hdr->data)) { gnrc_pktbuf_release(pkt); gnrc_pktbuf_release(netif_hdr); DEBUG("_recv_ieee802154: packet dropped by deduplication\n"); return NULL; } memcpy(netif->last_pkt.src, gnrc_netif_hdr_get_src_addr(hdr), hdr->src_l2addr_len); netif->last_pkt.src_len = hdr->src_l2addr_len; netif->last_pkt.seq = ieee802154_get_seq(ieee802154_hdr->data); #endif /* MODULE_GNRC_NETIF_DEDUP */ hdr->lqi = rx_info.lqi; hdr->rssi = rx_info.rssi; hdr->if_pid = thread_getpid(); dev->driver->get(dev, NETOPT_PROTO, &pkt->type, sizeof(pkt->type)); #if ENABLE_DEBUG DEBUG("_recv_ieee802154: received packet from %s of length %u\n", gnrc_netif_addr_to_str(gnrc_netif_hdr_get_src_addr(hdr), hdr->src_l2addr_len, src_str), nread); #if defined(MODULE_OD) od_hex_dump(pkt->data, nread, OD_WIDTH_DEFAULT); #endif #endif gnrc_pktbuf_remove_snip(pkt, ieee802154_hdr); LL_APPEND(pkt, netif_hdr); } DEBUG("_recv_ieee802154: reallocating.\n"); gnrc_pktbuf_realloc_data(pkt, nread); } else if (bytes_expected > 0) { DEBUG("_recv_ieee802154: received frame is too short\n"); dev->driver->recv(dev, NULL, bytes_expected, NULL); } return pkt; }
void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, size_t offset, unsigned page) { rbuf_t *entry; sixlowpan_frag_t *frag = pkt->data; rbuf_int_t *ptr; uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t); size_t frag_size; rbuf_gc(); entry = _rbuf_get(gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len, gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len, byteorder_ntohs(frag->disp_size) & SIXLOWPAN_FRAG_SIZE_MASK, byteorder_ntohs(frag->tag), page); if (entry == NULL) { DEBUG("6lo rbuf: reassembly buffer full.\n"); return; } ptr = entry->ints; /* dispatches in the first fragment are ignored */ if (offset == 0) { frag_size = pkt->size - sizeof(sixlowpan_frag_t); if (data[0] == SIXLOWPAN_UNCOMP) { frag_size--; } } else { frag_size = pkt->size - sizeof(sixlowpan_frag_n_t); data++; /* FRAGN header is one byte longer (offset) */ } if ((offset + frag_size) > entry->super.pkt->size) { DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n"); gnrc_pktbuf_release(entry->super.pkt); rbuf_rm(entry); return; } /* If the fragment overlaps another fragment and differs in either the size * or the offset of the overlapped fragment, discards the datagram * https://tools.ietf.org/html/rfc4944#section-5.3 */ while (ptr != NULL) { if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) { DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n"); gnrc_pktbuf_release(entry->super.pkt); rbuf_rm(entry); /* "A fresh reassembly may be commenced with the most recently * received link fragment" * https://tools.ietf.org/html/rfc4944#section-5.3 */ rbuf_add(netif_hdr, pkt, offset, page); return; } ptr = ptr->next; } if (_rbuf_update_ints(entry, offset, frag_size)) { DEBUG("6lo rbuf: add fragment data\n"); entry->super.current_size += (uint16_t)frag_size; if (offset == 0) { #ifdef MODULE_GNRC_SIXLOWPAN_IPHC if (sixlowpan_iphc_is(data)) { gnrc_pktsnip_t *frag_hdr = gnrc_pktbuf_mark(pkt, sizeof(sixlowpan_frag_t), GNRC_NETTYPE_SIXLOWPAN); if (frag_hdr == NULL) { gnrc_pktbuf_release(entry->super.pkt); rbuf_rm(entry); return; } gnrc_sixlowpan_iphc_recv(pkt, &entry->super, 0); return; } else #endif if (data[0] == SIXLOWPAN_UNCOMP) { data++; } } memcpy(((uint8_t *)entry->super.pkt->data) + offset, data, frag_size); } gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(&entry->super, netif_hdr); gnrc_pktbuf_release(pkt); }