Skip to content

Commit c35ce87

Browse files
committed
pcapng: add helpers to get the most common options for ISB
1 parent 9177ab3 commit c35ce87

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

examples/pcap-info.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,33 @@ fn print_block_info_ng(block: &Block) {
106106
println!("\t\t\tif_tsoffset: {}", option.unwrap_or(0));
107107
}
108108
}
109+
Block::InterfaceStatistics(isb) => {
110+
println!("\t\tStatistics:");
111+
if let Some(option) = isb.isb_starttime() {
112+
let (ts_high, ts_low) = option.unwrap_or((0, 0));
113+
println!("\t\t\tisb_starttime: 0x{:x}:0x{:x}", ts_high, ts_low);
114+
// to decode, this require the ts_offset and resolution from the matching IDB block
115+
// for ex:
116+
// let resolution = build_ts_resolution(6).unwrap();
117+
// let ts = build_ts(ts_high, ts_low, 0, resolution);
118+
// println!("\t\t\t\t{}.{}", ts.0, ts.1);
119+
}
120+
if let Some(option) = isb.isb_ifrecv() {
121+
println!("\t\t\tisb_ifrecv: {}", option.unwrap_or(0));
122+
}
123+
if let Some(option) = isb.isb_ifdrop() {
124+
println!("\t\t\tisb_ifdrop: {}", option.unwrap_or(0));
125+
}
126+
if let Some(option) = isb.isb_filteraccept() {
127+
println!("\t\t\tisb_filteraccept: {}", option.unwrap_or(0));
128+
}
129+
if let Some(option) = isb.isb_osdrop() {
130+
println!("\t\t\tisb_osdrop: {}", option.unwrap_or(0));
131+
}
132+
if let Some(option) = isb.isb_usrdeliv() {
133+
println!("\t\t\tisb_usrdeliv: {}", option.unwrap_or(0));
134+
}
135+
}
109136
_ => (),
110137
}
111138
}

src/pcapng/interface_statistics.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,86 @@ pub struct InterfaceStatisticsBlock<'a> {
1717
pub block_len2: u32,
1818
}
1919

20+
impl<'a> InterfaceStatisticsBlock<'a> {
21+
/// Return the `isb_starttime` option value, if present
22+
///
23+
/// The returned value is `(ts_high,ts_low)`. To convert to a full timestamp,
24+
/// use the [build_ts] function with the `ts_offset` and `resolution` values from
25+
/// the `InterfaceDescriptionBlock` matching `self.if_id`.
26+
///
27+
/// If the option is present multiple times, the first value is returned.
28+
///
29+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
30+
/// or `Some(Err(_))` if value is present but invalid
31+
pub fn isb_starttime(&self) -> Option<Result<(u32, u32), PcapNGOptionError>> {
32+
options_get_as_ts(&self.options, OptionCode::IsbStartTime)
33+
}
34+
35+
/// Return the `isb_endtime` option value, if present
36+
///
37+
/// The returned value is `(ts_high,ts_low)`. To convert to a full timestamp,
38+
/// use the [build_ts] function with the `ts_offset` and `resolution` values from
39+
/// the `InterfaceDescriptionBlock` matching `self.if_id`.
40+
///
41+
/// If the option is present multiple times, the first value is returned.
42+
///
43+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
44+
/// or `Some(Err(_))` if value is present but invalid
45+
pub fn isb_endtime(&self) -> Option<Result<(u32, u32), PcapNGOptionError>> {
46+
options_get_as_ts(&self.options, OptionCode::IsbEndTime)
47+
}
48+
49+
/// Return the `isb_ifrecv` option value, if present
50+
///
51+
/// If the option is present multiple times, the first value is returned.
52+
///
53+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
54+
/// or `Some(Err(_))` if value is present but invalid
55+
pub fn isb_ifrecv(&self) -> Option<Result<u64, PcapNGOptionError>> {
56+
options_get_as_u64_le(&self.options, OptionCode::IsbIfRecv)
57+
}
58+
59+
/// Return the `isb_ifdrop` option value, if present
60+
///
61+
/// If the option is present multiple times, the first value is returned.
62+
///
63+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
64+
/// or `Some(Err(_))` if value is present but invalid
65+
pub fn isb_ifdrop(&self) -> Option<Result<u64, PcapNGOptionError>> {
66+
options_get_as_u64_le(&self.options, OptionCode::IsbIfDrop)
67+
}
68+
69+
/// Return the `isb_filteraccept` option value, if present
70+
///
71+
/// If the option is present multiple times, the first value is returned.
72+
///
73+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
74+
/// or `Some(Err(_))` if value is present but invalid
75+
pub fn isb_filteraccept(&self) -> Option<Result<u64, PcapNGOptionError>> {
76+
options_get_as_u64_le(&self.options, OptionCode::IsbFilterAccept)
77+
}
78+
79+
/// Return the `isb_osdrop` option value, if present
80+
///
81+
/// If the option is present multiple times, the first value is returned.
82+
///
83+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
84+
/// or `Some(Err(_))` if value is present but invalid
85+
pub fn isb_osdrop(&self) -> Option<Result<u64, PcapNGOptionError>> {
86+
options_get_as_u64_le(&self.options, OptionCode::IsbOsDrop)
87+
}
88+
89+
/// Return the `isb_usrdeliv` option value, if present
90+
///
91+
/// If the option is present multiple times, the first value is returned.
92+
///
93+
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
94+
/// or `Some(Err(_))` if value is present but invalid
95+
pub fn isb_usrdeliv(&self) -> Option<Result<u64, PcapNGOptionError>> {
96+
options_get_as_u64_le(&self.options, OptionCode::IsbUsrDeliv)
97+
}
98+
}
99+
20100
impl<'a, En: PcapEndianness> PcapNGBlockParser<'a, En, InterfaceStatisticsBlock<'a>>
21101
for InterfaceStatisticsBlock<'a>
22102
{

src/pcapng/option.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,20 @@ impl debug OptionCode {
1919
Comment = 1,
2020
ShbHardware = 2,
2121
IfName = 2,
22+
IsbStartTime = 2,
2223
ShbOs = 3,
2324
IfDescription = 3,
25+
IsbEndTime = 3,
2426
ShbUserAppl = 4,
2527
IfIpv4Addr = 4,
28+
IsbIfRecv = 4,
29+
IsbIfDrop = 5,
2630
IfMacAddr = 6,
31+
IsbFilterAccept = 6,
2732
IfEuiAddr = 7,
33+
IsbOsDrop = 7,
2834
IfSpeed = 8,
35+
IsbUsrDeliv = 8,
2936
IfTsresol = 9,
3037
IfFilter = 11,
3138
IfOs = 12,
@@ -247,3 +254,23 @@ pub(crate) fn options_get_as_u64_le(
247254
) -> Option<Result<u64, PcapNGOptionError>> {
248255
options_find_map(options, code, |opt| opt.as_u64_le())
249256
}
257+
258+
pub(crate) fn options_get_as_ts(
259+
options: &[PcapNGOption],
260+
code: OptionCode,
261+
) -> Option<Result<(u32, u32), PcapNGOptionError>> {
262+
options_find_map(options, code, |opt| {
263+
let value = opt.value();
264+
if opt.len == 8 && value.len() == 8 {
265+
let bytes_ts_high =
266+
<[u8; 4]>::try_from(&value[..4]).or(Err(PcapNGOptionError::InvalidLength))?;
267+
let bytes_ts_low =
268+
<[u8; 4]>::try_from(&value[4..8]).or(Err(PcapNGOptionError::InvalidLength))?;
269+
let ts_high = u32::from_le_bytes(bytes_ts_high);
270+
let ts_low = u32::from_le_bytes(bytes_ts_low);
271+
Ok((ts_high, ts_low))
272+
} else {
273+
Err(PcapNGOptionError::InvalidLength)
274+
}
275+
})
276+
}

0 commit comments

Comments
 (0)