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