use crate::block::{InterfaceDescription, InterfaceStatistics, Timestamp};
use std::fmt;
use std::time::{Duration, SystemTime};
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum LinkType {
NULL,
ETHERNET,
EXP_ETHERNET,
AX24,
PRONET,
CHAOS,
TOKEN_RING,
ARCNET,
SLIP,
PPP,
FDDI,
PPP_HDLC,
PPP_ETHER,
SYMANTEC_FIREWALL,
ATM_RFC1483,
RAW,
SLIP_BSDOS,
PPP_BSDOS,
C_HDLC,
IEEE802_11,
ATM_CLIP,
FRELAY,
LOOP,
ENC,
LANE8023,
HIPPI,
HDLC,
LINUX_SLL,
LTALK,
ECONET,
IPFILTER,
PFLOG,
CISCO_IOS,
PRISM_HEADER,
AIRONET_HEADER,
HHDLC,
IP_OVER_FC,
SUNATM,
RIO,
PCI_EXP,
AURORA,
IEEE802_11_RADIO,
TZSP,
ARCNET_LINUX,
JUNIPER_MLPPP,
JUNIPER_MLFR,
JUNIPER_ES,
JUNIPER_GGSN,
JUNIPER_MFR,
JUNIPER_ATM2,
JUNIPER_SERVICES,
JUNIPER_ATM1,
APPLE_IP_OVER_IEEE1394,
MTP2_WITH_PHDR,
MTP2,
MTP3,
SCCP,
DOCSIS,
LINUX_IRDA,
IBM_SP,
IBM_SN,
Unknown(u16),
}
impl LinkType {
pub fn from_u16(i: u16) -> LinkType {
match i {
0 => LinkType::NULL,
1 => LinkType::ETHERNET,
2 => LinkType::EXP_ETHERNET,
3 => LinkType::AX24,
4 => LinkType::PRONET,
5 => LinkType::CHAOS,
6 => LinkType::TOKEN_RING,
7 => LinkType::ARCNET,
8 => LinkType::SLIP,
9 => LinkType::PPP,
10 => LinkType::FDDI,
50 => LinkType::PPP_HDLC,
51 => LinkType::PPP_ETHER,
99 => LinkType::SYMANTEC_FIREWALL,
100 => LinkType::ATM_RFC1483,
101 => LinkType::RAW,
102 => LinkType::SLIP_BSDOS,
103 => LinkType::PPP_BSDOS,
104 => LinkType::C_HDLC,
105 => LinkType::IEEE802_11,
106 => LinkType::ATM_CLIP,
107 => LinkType::FRELAY,
108 => LinkType::LOOP,
109 => LinkType::ENC,
110 => LinkType::LANE8023,
111 => LinkType::HIPPI,
112 => LinkType::HDLC,
113 => LinkType::LINUX_SLL,
114 => LinkType::LTALK,
115 => LinkType::ECONET,
116 => LinkType::IPFILTER,
117 => LinkType::PFLOG,
118 => LinkType::CISCO_IOS,
119 => LinkType::PRISM_HEADER,
120 => LinkType::AIRONET_HEADER,
121 => LinkType::HHDLC,
122 => LinkType::IP_OVER_FC,
123 => LinkType::SUNATM,
124 => LinkType::RIO,
125 => LinkType::PCI_EXP,
126 => LinkType::AURORA,
127 => LinkType::IEEE802_11_RADIO,
128 => LinkType::TZSP,
129 => LinkType::ARCNET_LINUX,
130 => LinkType::JUNIPER_MLPPP,
131 => LinkType::JUNIPER_MLFR,
132 => LinkType::JUNIPER_ES,
133 => LinkType::JUNIPER_GGSN,
134 => LinkType::JUNIPER_MFR,
135 => LinkType::JUNIPER_ATM2,
136 => LinkType::JUNIPER_SERVICES,
137 => LinkType::JUNIPER_ATM1,
138 => LinkType::APPLE_IP_OVER_IEEE1394,
139 => LinkType::MTP2_WITH_PHDR,
140 => LinkType::MTP2,
141 => LinkType::MTP3,
142 => LinkType::SCCP,
143 => LinkType::DOCSIS,
144 => LinkType::LINUX_IRDA,
145 => LinkType::IBM_SP,
146 => LinkType::IBM_SN,
12 => LinkType::RAW,
14 => LinkType::RAW,
x => LinkType::Unknown(x),
}
}
}
#[derive(Clone, PartialEq, Eq, Debug, Copy)]
pub struct InterfaceId(pub u32, pub u32);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InterfaceInfo {
pub(crate) descr: InterfaceDescription,
pub(crate) stats: Option<InterfaceStatistics>,
}
impl InterfaceInfo {
pub(crate) fn resolve_ts(&self, ts: Timestamp) -> SystemTime {
let units_per_sec = u64::from(self.descr.if_tsresol);
let secs = ts.0 / units_per_sec;
let nanos = ((ts.0 % units_per_sec) * 1_000_000_000 / units_per_sec) as u32;
SystemTime::UNIX_EPOCH + Duration::new(secs, nanos)
}
}
impl InterfaceInfo {
pub fn link_type(&self) -> LinkType {
self.descr.link_type
}
pub fn snap_len(&self) -> Option<u32> {
self.descr.snap_len
}
pub fn name(&self) -> &str {
&self.descr.if_name
}
pub fn description(&self) -> &str {
&self.descr.if_description
}
pub fn ipv4_addrs(&self) -> &[[u8; 8]] {
&self.descr.if_ipv4_addr
}
pub fn ipv6_addrs(&self) -> &[[u8; 17]] {
&self.descr.if_ipv6_addr
}
pub fn mac_addr(&self) -> Option<[u8; 6]> {
self.descr.if_mac_addr
}
pub fn eui_addr(&self) -> Option<[u8; 8]> {
self.descr.if_eui_addr
}
pub fn speed(&self) -> Option<u64> {
self.descr.if_speed
}
pub fn tzone(&self) -> Option<[u8; 4]> {
self.descr.if_tzone
}
pub fn filter(&self) -> &str {
&self.descr.if_filter
}
pub fn os(&self) -> &str {
&self.descr.if_os
}
pub fn fcslen(&self) -> Option<[u8; 1]> {
self.descr.if_fcslen
}
pub fn tsoffset(&self) -> Option<[u8; 8]> {
self.descr.if_tsoffset
}
pub fn hardware(&self) -> &str {
&self.descr.if_hardware
}
pub fn txspeed(&self) -> Option<[u8; 8]> {
self.descr.if_txspeed
}
pub fn rxspeed(&self) -> Option<[u8; 8]> {
self.descr.if_rxspeed
}
pub fn stats_timestamp(&self) -> Option<SystemTime> {
self.stats
.as_ref()
.map(|stats| self.resolve_ts(stats.timestamp))
}
pub fn starttime(&self) -> Option<SystemTime> {
self.stats
.as_ref()
.and_then(|stats| stats.isb_starttime)
.map(|ts| self.resolve_ts(ts))
}
pub fn endtime(&self) -> Option<SystemTime> {
self.stats
.as_ref()
.and_then(|stats| stats.isb_endtime)
.map(|ts| self.resolve_ts(ts))
}
pub fn ifrecv(&self) -> Option<u64> {
self.stats.as_ref().and_then(|stats| stats.isb_ifrecv)
}
pub fn ifdrop(&self) -> Option<u64> {
self.stats.as_ref().and_then(|stats| stats.isb_ifdrop)
}
pub fn filter_accept(&self) -> Option<u64> {
self.stats
.as_ref()
.and_then(|stats| stats.isb_filter_accept)
}
pub fn osdrop(&self) -> Option<u64> {
self.stats.as_ref().and_then(|stats| stats.isb_osdrop)
}
pub fn usrdeliv(&self) -> Option<u64> {
self.stats.as_ref().and_then(|stats| stats.isb_usrdeliv)
}
}
impl fmt::Display for InterfaceInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "{} ({})", self.name(), self.description())?;
if !self.filter().is_empty() {
writeln!(f, "filter: {}", self.filter())?;
}
if !self.os().is_empty() {
writeln!(f, "OS: {}", self.os())?;
}
if !self.hardware().is_empty() {
writeln!(f, "hardware: {}", self.hardware())?;
}
if self.ipv4_addrs().len() + self.ipv6_addrs().len() > 0 {
writeln!(
f,
"ip addrs: {:?} {:?}",
self.ipv4_addrs(),
self.ipv6_addrs(),
)?;
}
if let Some(x) = self.mac_addr() {
writeln!(f, "MAC addr: {x:?}")?;
}
if let Some(x) = self.eui_addr() {
writeln!(f, "EUI addr: {x:?}")?;
}
if let Some(x) = self.speed() {
writeln!(f, "speed: {x}")?;
}
if let Some(x) = self.tzone() {
writeln!(f, "tzone: {x:?}")?;
}
if let Some(x) = self.fcslen() {
writeln!(f, "fcslen: {x:?}")?;
}
if let Some(x) = self.tsoffset() {
writeln!(f, "tsoffset: {x:?}")?;
}
if let Some(x) = self.txspeed() {
writeln!(f, "txspeed: {x:?}")?;
}
if let Some(x) = self.rxspeed() {
writeln!(f, "rxspeed: {x:?}")?;
}
if let Some(x) = self.stats_timestamp() {
writeln!(f, "stats_timestamp: {x:?}")?; }
if let Some(x) = self.starttime() {
writeln!(f, "starttime: {x:?}")?; }
if let Some(x) = self.endtime() {
writeln!(f, "endtime: {x:?}")?; }
if let Some(x) = self.ifrecv() {
writeln!(f, "ifrecv: {x}")?;
}
if let Some(x) = self.ifdrop() {
writeln!(f, "ifdrop: {x}")?;
}
if let Some(x) = self.filter_accept() {
writeln!(f, "filter_accept: {x}")?;
}
if let Some(x) = self.osdrop() {
writeln!(f, "osdrop: {x}")?;
}
if let Some(x) = self.usrdeliv() {
writeln!(f, "usrdeliv: {x}")?;
}
Ok(())
}
}