Skip to content

Commit

Permalink
pcapng: add helpers to get the most common options for ISB
Browse files Browse the repository at this point in the history
  • Loading branch information
chifflier committed Aug 29, 2024
1 parent 19fba79 commit f6f1896
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 0 deletions.
27 changes: 27 additions & 0 deletions examples/pcap-info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,33 @@ fn print_block_info_ng(block: &Block) {
println!("\t\t\tif_tsoffset: {}", option.unwrap_or(0));
}
}
Block::InterfaceStatistics(isb) => {
println!("\t\tStatistics:");
if let Some(option) = isb.isb_starttime() {
let (ts_high, ts_low) = option.unwrap_or((0, 0));
println!("\t\t\tisb_starttime: 0x{:x}:0x{:x}", ts_high, ts_low);
// to decode, this require the ts_offset and resolution from the matching IDB block
// for ex:
// let resolution = build_ts_resolution(6).unwrap();
// let ts = build_ts(ts_high, ts_low, 0, resolution);
// println!("\t\t\t\t{}.{}", ts.0, ts.1);
}
if let Some(option) = isb.isb_ifrecv() {
println!("\t\t\tisb_ifrecv: {}", option.unwrap_or(0));
}
if let Some(option) = isb.isb_ifdrop() {
println!("\t\t\tisb_ifdrop: {}", option.unwrap_or(0));
}
if let Some(option) = isb.isb_filteraccept() {
println!("\t\t\tisb_filteraccept: {}", option.unwrap_or(0));
}
if let Some(option) = isb.isb_osdrop() {
println!("\t\t\tisb_osdrop: {}", option.unwrap_or(0));
}
if let Some(option) = isb.isb_usrdeliv() {
println!("\t\t\tisb_usrdeliv: {}", option.unwrap_or(0));
}
}
_ => (),
}
}
80 changes: 80 additions & 0 deletions src/pcapng/interface_statistics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,86 @@ pub struct InterfaceStatisticsBlock<'a> {
pub block_len2: u32,
}

impl<'a> InterfaceStatisticsBlock<'a> {
/// Return the `isb_starttime` option value, if present
///
/// The returned value is `(ts_high,ts_low)`. To convert to a full timestamp,
/// use the [build_ts] function with the `ts_offset` and `resolution` values from
/// the `InterfaceDescriptionBlock` matching `self.if_id`.
///
/// If the option is present multiple times, the first value is returned.
///
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
/// or `Some(Err(_))` if value is present but invalid
pub fn isb_starttime(&self) -> Option<Result<(u32, u32), PcapNGOptionError>> {
options_get_as_ts(&self.options, OptionCode::IsbStartTime)
}

/// Return the `isb_endtime` option value, if present
///
/// The returned value is `(ts_high,ts_low)`. To convert to a full timestamp,
/// use the [build_ts] function with the `ts_offset` and `resolution` values from
/// the `InterfaceDescriptionBlock` matching `self.if_id`.
///
/// If the option is present multiple times, the first value is returned.
///
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
/// or `Some(Err(_))` if value is present but invalid
pub fn isb_endtime(&self) -> Option<Result<(u32, u32), PcapNGOptionError>> {
options_get_as_ts(&self.options, OptionCode::IsbEndTime)
}

/// Return the `isb_ifrecv` option value, if present
///
/// If the option is present multiple times, the first value is returned.
///
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
/// or `Some(Err(_))` if value is present but invalid
pub fn isb_ifrecv(&self) -> Option<Result<u64, PcapNGOptionError>> {
options_get_as_u64_le(&self.options, OptionCode::IsbIfRecv)
}

/// Return the `isb_ifdrop` option value, if present
///
/// If the option is present multiple times, the first value is returned.
///
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
/// or `Some(Err(_))` if value is present but invalid
pub fn isb_ifdrop(&self) -> Option<Result<u64, PcapNGOptionError>> {
options_get_as_u64_le(&self.options, OptionCode::IsbIfDrop)
}

/// Return the `isb_filteraccept` option value, if present
///
/// If the option is present multiple times, the first value is returned.
///
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
/// or `Some(Err(_))` if value is present but invalid
pub fn isb_filteraccept(&self) -> Option<Result<u64, PcapNGOptionError>> {
options_get_as_u64_le(&self.options, OptionCode::IsbFilterAccept)
}

/// Return the `isb_osdrop` option value, if present
///
/// If the option is present multiple times, the first value is returned.
///
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
/// or `Some(Err(_))` if value is present but invalid
pub fn isb_osdrop(&self) -> Option<Result<u64, PcapNGOptionError>> {
options_get_as_u64_le(&self.options, OptionCode::IsbOsDrop)
}

/// Return the `isb_usrdeliv` option value, if present
///
/// If the option is present multiple times, the first value is returned.
///
/// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
/// or `Some(Err(_))` if value is present but invalid
pub fn isb_usrdeliv(&self) -> Option<Result<u64, PcapNGOptionError>> {
options_get_as_u64_le(&self.options, OptionCode::IsbUsrDeliv)
}
}

impl<'a, En: PcapEndianness> PcapNGBlockParser<'a, En, InterfaceStatisticsBlock<'a>>
for InterfaceStatisticsBlock<'a>
{
Expand Down
27 changes: 27 additions & 0 deletions src/pcapng/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,20 @@ impl debug OptionCode {
Comment = 1,
ShbHardware = 2,
IfName = 2,
IsbStartTime = 2,
ShbOs = 3,
IfDescription = 3,
IsbEndTime = 3,
ShbUserAppl = 4,
IfIpv4Addr = 4,
IsbIfRecv = 4,
IsbIfDrop = 5,
IfMacAddr = 6,
IsbFilterAccept = 6,
IfEuiAddr = 7,
IsbOsDrop = 7,
IfSpeed = 8,
IsbUsrDeliv = 8,
IfTsresol = 9,
IfFilter = 11,
IfOs = 12,
Expand Down Expand Up @@ -247,3 +254,23 @@ pub(crate) fn options_get_as_u64_le(
) -> Option<Result<u64, PcapNGOptionError>> {
options_find_map(options, code, |opt| opt.as_u64_le())
}

pub(crate) fn options_get_as_ts(
options: &[PcapNGOption],
code: OptionCode,
) -> Option<Result<(u32, u32), PcapNGOptionError>> {
options_find_map(options, code, |opt| {
let value = opt.value();
if opt.len == 8 && value.len() == 8 {
let bytes_ts_high =
<[u8; 4]>::try_from(&value[..4]).or(Err(PcapNGOptionError::InvalidLength))?;
let bytes_ts_low =
<[u8; 4]>::try_from(&value[4..8]).or(Err(PcapNGOptionError::InvalidLength))?;
let ts_high = u32::from_le_bytes(bytes_ts_high);
let ts_low = u32::from_le_bytes(bytes_ts_low);
Ok((ts_high, ts_low))
} else {
Err(PcapNGOptionError::InvalidLength)
}
})
}

0 comments on commit f6f1896

Please sign in to comment.