pcap_parser/pcapng/
name_resolution.rs

1use nom::bytes::streaming::{tag, take};
2use nom::combinator::map;
3use nom::error::{ErrorKind, ParseError};
4use nom::multi::many_till;
5use nom::{Err, IResult, Parser as _};
6use rusticata_macros::{align32, newtype_enum};
7
8use crate::endianness::{PcapBE, PcapEndianness, PcapLE};
9use crate::{opt_parse_options, PcapError, PcapNGOption, NRB_MAGIC};
10
11use super::*;
12
13#[derive(Clone, Copy, Eq, PartialEq)]
14pub struct NameRecordType(pub u16);
15
16newtype_enum! {
17    impl debug NameRecordType {
18        End = 0,
19        Ipv4 = 1,
20        Ipv6 = 2
21    }
22}
23
24#[derive(Debug)]
25pub struct NameRecord<'a> {
26    pub record_type: NameRecordType,
27    pub record_value: &'a [u8],
28}
29
30impl NameRecord<'_> {
31    pub const END: NameRecord<'static> = NameRecord {
32        record_type: NameRecordType::End,
33        record_value: &[],
34    };
35}
36
37#[derive(Debug)]
38pub struct NameResolutionBlock<'a> {
39    pub block_type: u32,
40    pub block_len1: u32,
41    pub nr: Vec<NameRecord<'a>>,
42    pub options: Vec<PcapNGOption<'a>>,
43    pub block_len2: u32,
44}
45
46impl<'a, En: PcapEndianness> PcapNGBlockParser<'a, En, NameResolutionBlock<'a>>
47    for NameResolutionBlock<'a>
48{
49    const HDR_SZ: usize = 12;
50    const MAGIC: u32 = NRB_MAGIC;
51
52    fn inner_parse<E: ParseError<&'a [u8]>>(
53        block_type: u32,
54        block_len1: u32,
55        i: &'a [u8],
56        block_len2: u32,
57    ) -> IResult<&'a [u8], NameResolutionBlock<'a>, E> {
58        let start_i = i;
59        // caller function already tested header type(magic) and length
60        // read records
61        let (i, nr) = parse_name_record_list::<En, E>(i)?;
62        // read options
63        let current_offset = 12 + (i.as_ptr() as usize) - (start_i.as_ptr() as usize);
64        let (i, options) = opt_parse_options::<En, E>(i, block_len1 as usize, current_offset)?;
65        if block_len2 != block_len1 {
66            return Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)));
67        }
68        let block = NameResolutionBlock {
69            block_type,
70            block_len1,
71            nr,
72            options,
73            block_len2,
74        };
75        Ok((i, block))
76    }
77}
78
79fn parse_name_record<'a, En: PcapEndianness, E: ParseError<&'a [u8]>>(
80    i: &'a [u8],
81) -> IResult<&'a [u8], NameRecord<'a>, E> {
82    let (i, record_type) = En::parse_u16(i)?;
83    let (i, record_len) = En::parse_u16(i)?;
84    let aligned_len = align32!(record_len as u32);
85    let (i, record_value) = take(aligned_len)(i)?;
86    let name_record = NameRecord {
87        record_type: NameRecordType(record_type),
88        record_value,
89    };
90    Ok((i, name_record))
91}
92
93fn parse_name_record_list<'a, En: PcapEndianness, E: ParseError<&'a [u8]>>(
94    i: &'a [u8],
95) -> IResult<&'a [u8], Vec<NameRecord<'a>>, E> {
96    map(
97        many_till(
98            parse_name_record::<En, E>,
99            tag(b"\x00\x00\x00\x00" as &[u8]),
100        ),
101        |(mut v, _)| {
102            v.push(NameRecord::END);
103            v
104        },
105    )
106    .parse(i)
107}
108
109/// Parse a Name Resolution Block (little-endian)
110#[inline]
111pub fn parse_nameresolutionblock_le(
112    i: &[u8],
113) -> IResult<&[u8], NameResolutionBlock<'_>, PcapError<&[u8]>> {
114    ng_block_parser::<NameResolutionBlock, PcapLE, _, _>()(i)
115}
116
117/// Parse a Name Resolution Block (big-endian)
118#[inline]
119pub fn parse_nameresolutionblock_be(
120    i: &[u8],
121) -> IResult<&[u8], NameResolutionBlock<'_>, PcapError<&[u8]>> {
122    ng_block_parser::<NameResolutionBlock, PcapBE, _, _>()(i)
123}