Skip to content

Commit a89e3fd

Browse files
committed
pcapng: add helpers to get the most common options for IDB
1 parent abb5620 commit a89e3fd

File tree

4 files changed

+127
-11
lines changed

4 files changed

+127
-11
lines changed

examples/pcap-info.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,15 @@ fn print_block_info_ng(block: &Block) {
9696
if let Some(option) = idb.if_os() {
9797
println!("\t\t\tif_os: {}", option.unwrap_or("<invalid>"));
9898
}
99+
if let Some(option) = idb.if_tsresol() {
100+
println!("\t\t\tif_tsresol: {}", option.unwrap_or(0));
101+
}
102+
if let Some(option) = idb.if_filter() {
103+
println!("\t\t\tif_filter: {}", option.unwrap_or("<invalid>"));
104+
}
105+
if let Some(option) = idb.if_tsoffset() {
106+
println!("\t\t\tif_tsoffset: {}", option.unwrap_or(0));
107+
}
99108
}
100109
_ => (),
101110
}

src/pcapng/interface_description.rs

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl<'a> InterfaceDescriptionBlock<'a> {
4545
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
4646
/// or `Some(Err(_))` if value is present but invalid
4747
pub fn if_name(&self) -> Option<Result<&str, PcapNGOptionError>> {
48-
options_get_as_string(&self.options, OptionCode::IfName)
48+
options_get_as_str(&self.options, OptionCode::IfName)
4949
}
5050

5151
/// Return the `if_description` option value, if present
@@ -55,7 +55,7 @@ impl<'a> InterfaceDescriptionBlock<'a> {
5555
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
5656
/// or `Some(Err(_))` if value is present but invalid
5757
pub fn if_description(&self) -> Option<Result<&str, PcapNGOptionError>> {
58-
options_get_as_string(&self.options, OptionCode::IfDescription)
58+
options_get_as_str(&self.options, OptionCode::IfDescription)
5959
}
6060

6161
/// Return the `if_os` option value, if present
@@ -65,7 +65,7 @@ impl<'a> InterfaceDescriptionBlock<'a> {
6565
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
6666
/// or `Some(Err(_))` if value is present but invalid
6767
pub fn if_os(&self) -> Option<Result<&str, PcapNGOptionError>> {
68-
options_get_as_string(&self.options, OptionCode::IfOs)
68+
options_get_as_str(&self.options, OptionCode::IfOs)
6969
}
7070

7171
/// Return the `if_ipv4addr` option values, if present
@@ -140,6 +140,66 @@ impl<'a> InterfaceDescriptionBlock<'a> {
140140
Some(res)
141141
}
142142
}
143+
144+
/// Return the `if_macaddr` option value, if present
145+
///
146+
/// If the option is present multiple times, the first value is returned.
147+
///
148+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
149+
/// or `Some(Err(_))` if value is present but invalid
150+
pub fn if_macaddr(&self) -> Option<Result<&[u8], PcapNGOptionError>> {
151+
options_get_as_bytes(&self.options, OptionCode::IfMacAddr)
152+
}
153+
154+
/// Return the `if_euiaddr` option value, if present
155+
///
156+
/// If the option is present multiple times, the first value is returned.
157+
///
158+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
159+
/// or `Some(Err(_))` if value is present but invalid
160+
pub fn if_euiaddr(&self) -> Option<Result<&[u8], PcapNGOptionError>> {
161+
options_get_as_bytes(&self.options, OptionCode::IfEuiAddr)
162+
}
163+
164+
/// Return the `if_speed` option value, if present
165+
///
166+
/// If the option is present multiple times, the first value is returned.
167+
///
168+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
169+
/// or `Some(Err(_))` if value is present but invalid
170+
pub fn if_speed(&self) -> Option<Result<u64, PcapNGOptionError>> {
171+
options_get_as_u64_le(&self.options, OptionCode::IfSpeed)
172+
}
173+
174+
/// Return the `if_tsresol` option value, if present
175+
///
176+
/// If the option is present multiple times, the first value is returned.
177+
///
178+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
179+
/// or `Some(Err(_))` if value is present but invalid
180+
pub fn if_tsresol(&self) -> Option<Result<u8, PcapNGOptionError>> {
181+
options_get_as_u8(&self.options, OptionCode::IfTsresol)
182+
}
183+
184+
/// Return the `if_filter` option value, if present
185+
///
186+
/// If the option is present multiple times, the first value is returned.
187+
///
188+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
189+
/// or `Some(Err(_))` if value is present but invalid
190+
pub fn if_filter(&self) -> Option<Result<&str, PcapNGOptionError>> {
191+
options_get_as_str(&self.options, OptionCode::IfFilter)
192+
}
193+
194+
/// Return the `if_tsoffset` option value, if present
195+
///
196+
/// If the option is present multiple times, the first value is returned.
197+
///
198+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
199+
/// or `Some(Err(_))` if value is present but invalid
200+
pub fn if_tsoffset(&self) -> Option<Result<i64, PcapNGOptionError>> {
201+
options_get_as_i64_le(&self.options, OptionCode::IfTsoffset)
202+
}
143203
}
144204

145205
impl<'a, En: PcapEndianness> PcapNGBlockParser<'a, En, InterfaceDescriptionBlock<'a>>

src/pcapng/option.rs

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ impl debug OptionCode {
2323
IfDescription = 3,
2424
ShbUserAppl = 4,
2525
IfIpv4Addr = 4,
26+
IfMacAddr = 6,
27+
IfEuiAddr = 7,
28+
IfSpeed = 8,
2629
IfTsresol = 9,
30+
IfFilter = 11,
2731
IfOs = 12,
2832
IfTsoffset = 14,
2933
Custom2988 = 2988,
@@ -177,15 +181,58 @@ pub(crate) fn opt_parse_options<'i, En: PcapEndianness, E: ParseError<&'i [u8]>>
177181
}
178182
}
179183

180-
pub(crate) fn options_get_as_string<'a>(
184+
#[inline]
185+
pub(crate) fn options_find_map<'a, F, O>(
186+
options: &'a [PcapNGOption],
187+
code: OptionCode,
188+
f: F,
189+
) -> Option<Result<O, PcapNGOptionError>>
190+
where
191+
F: Fn(&'a PcapNGOption) -> Result<O, PcapNGOptionError>,
192+
{
193+
options
194+
.iter()
195+
.find_map(|opt| if opt.code == code { Some(f(opt)) } else { None })
196+
}
197+
198+
pub(crate) fn options_get_as_bytes<'a>(
199+
options: &'a [PcapNGOption],
200+
code: OptionCode,
201+
) -> Option<Result<&'a [u8], PcapNGOptionError>> {
202+
options_find_map(options, code, |opt| opt.as_bytes())
203+
}
204+
205+
pub(crate) fn options_get_as_str<'a>(
181206
options: &'a [PcapNGOption],
182207
code: OptionCode,
183208
) -> Option<Result<&'a str, PcapNGOptionError>> {
184-
options.iter().find_map(|opt| {
185-
if opt.code == code {
186-
Some(opt.as_str())
209+
options_find_map(options, code, |opt| opt.as_str())
210+
}
211+
212+
pub(crate) fn options_get_as_u8(
213+
options: &[PcapNGOption],
214+
code: OptionCode,
215+
) -> Option<Result<u8, PcapNGOptionError>> {
216+
options_find_map(options, code, |opt| {
217+
let value = opt.value();
218+
if opt.len == 1 && !value.is_empty() {
219+
Ok(value[0])
187220
} else {
188-
None
221+
Err(PcapNGOptionError::InvalidLength)
189222
}
190223
})
191224
}
225+
226+
pub(crate) fn options_get_as_i64_le(
227+
options: &[PcapNGOption],
228+
code: OptionCode,
229+
) -> Option<Result<i64, PcapNGOptionError>> {
230+
options_find_map(options, code, |opt| opt.as_i64_le())
231+
}
232+
233+
pub(crate) fn options_get_as_u64_le(
234+
options: &[PcapNGOption],
235+
code: OptionCode,
236+
) -> Option<Result<u64, PcapNGOptionError>> {
237+
options_find_map(options, code, |opt| opt.as_u64_le())
238+
}

src/pcapng/section_header.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ impl<'a> SectionHeaderBlock<'a> {
3939
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
4040
/// or `Some(Err(_))` if value is present but invalid
4141
pub fn shb_hardware(&self) -> Option<Result<&str, PcapNGOptionError>> {
42-
options_get_as_string(&self.options, OptionCode::ShbHardware)
42+
options_get_as_str(&self.options, OptionCode::ShbHardware)
4343
}
4444

4545
/// Return the `shb_os` option value, if present
@@ -49,7 +49,7 @@ impl<'a> SectionHeaderBlock<'a> {
4949
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
5050
/// or `Some(Err(_))` if value is present but invalid
5151
pub fn shb_os(&self) -> Option<Result<&str, PcapNGOptionError>> {
52-
options_get_as_string(&self.options, OptionCode::ShbOs)
52+
options_get_as_str(&self.options, OptionCode::ShbOs)
5353
}
5454

5555
/// Return the `shb_userappl` option value, if present
@@ -59,7 +59,7 @@ impl<'a> SectionHeaderBlock<'a> {
5959
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
6060
/// or `Some(Err(_))` if value is present but invalid
6161
pub fn shb_userappl(&self) -> Option<Result<&str, PcapNGOptionError>> {
62-
options_get_as_string(&self.options, OptionCode::ShbUserAppl)
62+
options_get_as_str(&self.options, OptionCode::ShbUserAppl)
6363
}
6464
}
6565

0 commit comments

Comments
 (0)