pcap_parser/pcapng/
simple_packet.rs

1use nom::bytes::streaming::take;
2use nom::error::ParseError;
3use nom::IResult;
4
5use crate::endianness::{PcapBE, PcapEndianness, PcapLE};
6use crate::traits::PcapNGPacketBlock;
7use crate::{PcapError, SPB_MAGIC};
8
9use super::*;
10
11/// The Simple Packet Block (SPB) is a lightweight container for storing
12/// the packets coming from the network.
13///
14/// This struct is a thin abstraction layer, and stores the raw block data.
15/// For ex the `data` field is stored with the padding.
16/// It implements the `PcapNGPacketBlock` trait, which provides helper functions.
17#[derive(Debug)]
18pub struct SimplePacketBlock<'a> {
19    /// Block type (little endian)
20    pub block_type: u32,
21    pub block_len1: u32,
22    /// Original packet length
23    pub origlen: u32,
24    pub data: &'a [u8],
25    pub block_len2: u32,
26}
27
28impl PcapNGPacketBlock for SimplePacketBlock<'_> {
29    fn big_endian(&self) -> bool {
30        self.block_type != SPB_MAGIC
31    }
32    fn truncated(&self) -> bool {
33        self.origlen as usize <= self.data.len()
34    }
35    fn orig_len(&self) -> u32 {
36        self.origlen
37    }
38    fn raw_packet_data(&self) -> &[u8] {
39        self.data
40    }
41    fn packet_data(&self) -> &[u8] {
42        let caplen = self.origlen as usize;
43        if caplen < self.data.len() {
44            &self.data[..caplen]
45        } else {
46            self.data
47        }
48    }
49}
50
51impl<'a, En: PcapEndianness> PcapNGBlockParser<'a, En, SimplePacketBlock<'a>>
52    for SimplePacketBlock<'a>
53{
54    const HDR_SZ: usize = 16;
55    const MAGIC: u32 = SPB_MAGIC;
56
57    fn inner_parse<E: ParseError<&'a [u8]>>(
58        block_type: u32,
59        block_len1: u32,
60        i: &'a [u8],
61        block_len2: u32,
62    ) -> IResult<&'a [u8], SimplePacketBlock<'a>, E> {
63        // caller function already tested header type(magic) and length
64        // read end of header
65        let (i, origlen) = En::parse_u32(i)?;
66        let (i, data) = take((block_len1 as usize) - 16)(i)?;
67        let block = SimplePacketBlock {
68            block_type,
69            block_len1,
70            origlen,
71            data,
72            block_len2,
73        };
74        Ok((i, block))
75    }
76}
77
78/// Parse a Simple Packet Block (little-endian)
79///
80/// *Note: this function does not remove padding in the `data` field.
81/// Use `packet_data` to get field without padding.*
82pub fn parse_simplepacketblock_le(
83    i: &[u8],
84) -> IResult<&[u8], SimplePacketBlock<'_>, PcapError<&[u8]>> {
85    ng_block_parser::<SimplePacketBlock, PcapLE, _, _>()(i)
86}
87
88/// Parse a Simple Packet Block (big-endian)
89///
90/// *Note: this function does not remove padding*
91pub fn parse_simplepacketblock_be(
92    i: &[u8],
93) -> IResult<&[u8], SimplePacketBlock<'_>, PcapError<&[u8]>> {
94    ng_block_parser::<SimplePacketBlock, PcapBE, _, _>()(i)
95}