void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_pktsnip_t *pkt, size_t frag_size, size_t offset) { rbuf_t *entry; /* cppcheck is clearly wrong here */ /* cppcheck-suppress variableScope */ unsigned int data_offset = 0; ng_sixlowpan_frag_t *frag = pkt->data; rbuf_int_t *ptr; uint8_t *data = ((uint8_t *)pkt->data) + sizeof(ng_sixlowpan_frag_t); _rbuf_gc(); entry = _rbuf_get(ng_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len, ng_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len, byteorder_ntohs(frag->disp_size) & NG_SIXLOWPAN_FRAG_SIZE_MASK, byteorder_ntohs(frag->tag)); if (entry == NULL) { DEBUG("6lo rbuf: reassembly buffer full.\n"); return; } ptr = entry->ints; /* dispatches in the first fragment are ignored */ if (offset == 0) { if (data[0] == NG_SIXLOWPAN_UNCOMPRESSED) { data++; /* skip 6LoWPAN dispatch */ frag_size--; } #ifdef MODULE_NG_SIXLOWPAN_IPHC else if (ng_sixlowpan_iphc_is(data)) { size_t iphc_len; iphc_len = ng_sixlowpan_iphc_decode(entry->pkt, pkt, sizeof(ng_sixlowpan_frag_t)); if (iphc_len == 0) { DEBUG("6lo rfrag: could not decode IPHC dispatch\n"); ng_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } data += iphc_len; /* take remaining data as data */ frag_size -= iphc_len; /* and reduce frag size by IPHC dispatch length */ frag_size += sizeof(ipv6_hdr_t); /* but add IPv6 header length */ data_offset += sizeof(ipv6_hdr_t); /* start copying after IPv6 header */ } #endif } else { data++; /* FRAGN header is one byte longer (offset) */ } if ((offset + frag_size) > entry->pkt->size) { DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n"); ng_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } while (ptr != NULL) { if (_rbuf_int_in(ptr, offset, offset + frag_size - 1)) { DEBUG("6lo rfrag: overlapping or same intervals, discarding datagram\n"); ng_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } ptr = ptr->next; } if (_rbuf_update_ints(entry, offset, frag_size)) { DEBUG("6lo rbuf: add fragment data\n"); entry->cur_size += (uint16_t)frag_size; memcpy(((uint8_t *)entry->pkt->data) + offset + data_offset, data, frag_size - data_offset); } if (entry->cur_size == entry->pkt->size) { kernel_pid_t iface = netif_hdr->if_pid; ng_pktsnip_t *netif = ng_netif_hdr_build(entry->src, entry->src_len, entry->dst, entry->dst_len); if (netif == NULL) { DEBUG("6lo rbuf: error allocating netif header\n"); ng_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } netif_hdr = netif->data; netif_hdr->if_pid = iface; LL_APPEND(entry->pkt, netif); if (!ng_netapi_dispatch_receive(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL, entry->pkt)) { DEBUG("6lo rbuf: No receivers for this packet found\n"); ng_pktbuf_release(entry->pkt); } _rbuf_rem(entry); } }
static void _receive(ng_pktsnip_t *pkt) { ng_pktsnip_t *payload; uint8_t *dispatch; /* seize payload as a temporary variable */ payload = ng_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) && defined(ENABLE_DEBUG) ng_pktbuf_stats(); #endif ng_pktbuf_release(pkt); return; } pkt = payload; /* reset pkt from temporary variable */ LL_SEARCH_SCALAR(pkt, payload, type, NG_NETTYPE_SIXLOWPAN); if ((payload == NULL) || (payload->size < 1)) { DEBUG("6lo: Received packet has no 6LoWPAN payload\n"); ng_pktbuf_release(pkt); return; } dispatch = payload->data; if (dispatch[0] == NG_SIXLOWPAN_UNCOMPRESSED) { ng_pktsnip_t *sixlowpan; DEBUG("6lo: received uncompressed IPv6 packet\n"); payload = ng_pktbuf_start_write(payload); if (payload == NULL) { DEBUG("6lo: can not get write access on received packet\n"); #if defined(DEVELHELP) && defined(ENABLE_DEBUG) ng_pktbuf_stats(); #endif ng_pktbuf_release(pkt); return; } /* packet is uncompressed: just mark and remove the dispatch */ sixlowpan = ng_pktbuf_add(payload, payload->data, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN); if (sixlowpan == NULL) { DEBUG("6lo: can not mark 6LoWPAN dispatch\n"); ng_pktbuf_release(pkt); return; } pkt = ng_pktbuf_remove_snip(pkt, sixlowpan); } #ifdef MODULE_NG_SIXLOWPAN_FRAG else if (ng_sixlowpan_frag_is((ng_sixlowpan_frag_t *)dispatch)) { DEBUG("6lo: received 6LoWPAN fragment\n"); ng_sixlowpan_frag_handle_pkt(pkt); return; } #endif else { DEBUG("6lo: dispatch %02x ... is not supported\n", dispatch[0]); ng_pktbuf_release(pkt); return; } #ifdef MODULE_NG_SIXLOWPAN_IPHC if (ng_sixlowpan_iphc_is(payload->data)) { if (!ng_sixlowpan_iphc_decode(pkt)) { DEBUG("6lo: error on IPHC decoding\n"); ng_pktbuf_release(pkt); return; } LL_SEARCH_SCALAR(pkt, payload, type, NG_NETTYPE_IPV6); } #endif payload->type = NG_NETTYPE_IPV6; if (!ng_netapi_dispatch_receive(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL, pkt)) { DEBUG("ipv6: No receivers for this packet found\n"); ng_pktbuf_release(pkt); } }