1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
use crate::block::opts::*;
use crate::block::util::*;
use bytes::Buf;
use tracing::*;
/// Defines the most important characteristics of the capture file.
///
/// The Section Header Block (SHB) is mandatory. It identifies the beginning of a section of the
/// capture capture file. The Section Header Block does not contain data but it rather identifies a
/// list of blocks (interfaces, packets) that are logically correlated.
///
/// This documentation is copyright (c) 2018 IETF Trust and the persons identified as the
/// authors of [this document][1]. All rights reserved. Please see the linked document for the full
/// copyright notice.
///
/// [1]: https://github.com/pcapng/pcapng
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct SectionHeader {
/// Used to distinguish sections that have been saved on little-endian machines from the ones
/// saved on big-endian machines.
pub endianness: Endianness,
/// Number of the current mayor version of the format. Current value is 1. This value should
/// change if the format changes in such a way that code that reads the new format could not
/// read the old format (i.e., code to read both formats would have to check the version number
/// and use different code paths for the two formats) and code that reads the old format could
/// not read the new format.
pub major_version: u16,
/// Number of the current minor version of the format. Current value is 0. This value should
/// change if the format changes in such a way that code that reads the new format could read
/// the old format without checking the version number but code that reads the old format could
/// not read all files in the new format.
pub minor_version: u16,
/// A signed 64-bit value specifying the length in octets of the following section, excluding
/// the Section Header Block itself. This field can be used to skip the section, for faster
/// navigation inside large files. Section Length equal -1 (0xFFFFFFFFFFFFFFFF) means that the
/// size of the section is not specified, and the only way to skip the section is to parse the
/// blocks that it contains. Please note that if this field is valid (i.e. not negative), its
/// value is always aligned to 32 bits, as all the blocks are aligned to and padded to 32-bit
/// boundaries. Also, special care should be taken in accessing this field: since the alignment
/// of all the blocks in the file is 32-bits, this field is not guaranteed to be aligned to a
/// 64-bit boundary. This could be a problem on 64-bit processors.
pub section_length: Option<u64>,
/// The shb_hardware option is a UTF-8 string containing the description
/// of the hardware used to create this section. The string is not
/// zero-terminated.
pub shb_hardware: String,
/// The shb_os option is a UTF-8 string containing the name of the
/// operating system used to create this section. The string is not
/// zero-terminated.
pub shb_os: String,
/// The shb_userappl option is a UTF-8 string containing the name of
/// the application used to create this section. The string is not
/// zero-terminated.
pub shb_userappl: String,
}
impl FromBytes for SectionHeader {
fn parse<T: Buf>(mut buf: T, endianness: Endianness) -> Result<SectionHeader, BlockError> {
ensure_remaining!(buf, 12);
buf.advance(4); // the endianness - we've already parsed it
let major_version = read_u16(&mut buf, endianness);
let minor_version = read_u16(&mut buf, endianness);
let section_length = match read_i64(&mut buf, endianness) {
-1 => None,
x => match u64::try_from(x) {
Ok(x) => Some(x),
Err(_) => {
warn!("SHB lists the length as {x}, but this is invalid");
None
}
},
};
let mut shb_hardware = String::new();
let mut shb_os = String::new();
let mut shb_userappl = String::new();
parse_options(buf, endianness, |option_type, option_bytes| {
match option_type {
2 => shb_hardware = String::from_utf8_lossy(&option_bytes).to_string(),
3 => shb_os = String::from_utf8_lossy(&option_bytes).to_string(),
4 => shb_userappl = String::from_utf8_lossy(&option_bytes).to_string(),
_ => (), // Ignore unknown
}
});
Ok(SectionHeader {
endianness,
major_version,
minor_version,
section_length,
shb_hardware,
shb_os,
shb_userappl,
})
}
}