pcap_parser/pcapng/
interface_description.rs

1use nom::error::{ErrorKind, ParseError};
2use nom::{Err, IResult};
3
4use crate::endianness::{PcapBE, PcapEndianness, PcapLE};
5use crate::{opt_parse_options, Linktype, PcapError, PcapNGOption, IDB_MAGIC};
6
7use super::*;
8
9/// An Interface Description Block (IDB) is the container for information
10/// describing an interface on which packet data is captured.
11#[derive(Debug)]
12pub struct InterfaceDescriptionBlock<'a> {
13    pub block_type: u32,
14    pub block_len1: u32,
15    pub linktype: Linktype,
16    pub reserved: u16,
17    pub snaplen: u32,
18    pub options: Vec<PcapNGOption<'a>>,
19    pub block_len2: u32,
20    pub if_tsresol: u8,
21    pub if_tsoffset: i64,
22}
23
24impl<'a> InterfaceDescriptionBlock<'a> {
25    /// Decode the interface time resolution, in units per second
26    ///
27    /// Return the resolution, or `None` if the resolution is invalid (for ex. greater than `2^64`)
28    #[inline]
29    pub fn ts_resolution(&self) -> Option<u64> {
30        build_ts_resolution(self.if_tsresol)
31    }
32
33    /// Return the interface timestamp offset
34    #[inline]
35    pub fn ts_offset(&self) -> i64 {
36        self.if_tsoffset
37    }
38}
39
40impl<'a, En: PcapEndianness> PcapNGBlockParser<'a, En, InterfaceDescriptionBlock<'a>>
41    for InterfaceDescriptionBlock<'a>
42{
43    const HDR_SZ: usize = 20;
44    const MAGIC: u32 = IDB_MAGIC;
45
46    fn inner_parse<E: ParseError<&'a [u8]>>(
47        block_type: u32,
48        block_len1: u32,
49        i: &'a [u8],
50        block_len2: u32,
51    ) -> IResult<&'a [u8], InterfaceDescriptionBlock<'a>, E> {
52        // caller function already tested header type(magic) and length
53        // read end of header
54        let (i, linktype) = En::parse_u16(i)?;
55        let (i, reserved) = En::parse_u16(i)?;
56        let (i, snaplen) = En::parse_u32(i)?;
57        // read options
58        let (i, options) = opt_parse_options::<En, E>(i, block_len1 as usize, 20)?;
59        if block_len2 != block_len1 {
60            return Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)));
61        }
62        let (if_tsresol, if_tsoffset) = if_extract_tsoffset_and_tsresol(&options);
63        let block = InterfaceDescriptionBlock {
64            block_type,
65            block_len1,
66            linktype: Linktype(linktype as i32),
67            reserved,
68            snaplen,
69            options,
70            block_len2,
71            if_tsresol,
72            if_tsoffset,
73        };
74        Ok((i, block))
75    }
76}
77
78/// Parse an Interface Packet Block (little-endian)
79pub fn parse_interfacedescriptionblock_le(
80    i: &[u8],
81) -> IResult<&[u8], InterfaceDescriptionBlock, PcapError<&[u8]>> {
82    ng_block_parser::<InterfaceDescriptionBlock, PcapLE, _, _>()(i)
83}
84
85/// Parse an Interface Packet Block (big-endian)
86pub fn parse_interfacedescriptionblock_be(
87    i: &[u8],
88) -> IResult<&[u8], InterfaceDescriptionBlock, PcapError<&[u8]>> {
89    ng_block_parser::<InterfaceDescriptionBlock, PcapBE, _, _>()(i)
90}