diff --git a/src/common/interf_desc.rs b/src/common/interf_desc.rs index 2220264..a80c37c 100644 --- a/src/common/interf_desc.rs +++ b/src/common/interf_desc.rs @@ -1,12 +1,25 @@ +use std::net::SocketAddr; use std::fmt::{Display, Formatter, Error as FmtError}; +/// Describes the addresses of a network interface. +#[derive(Debug, Clone)] +pub struct AddressDescription { + pub address: Option, + pub netmask: Option, + pub broadcast_address: Option, + pub dest_address: Option, +} + /// Describes a network interface. #[derive(Debug, Clone)] pub struct InterfaceDescription { ///Interface name that can be used as an argument for open_interface() function. pub name: String, /// Human friendly interface description. - pub description: String + pub description: String, + /// Network addresses of the interface. + /// *Only provided in pcap.* + pub addresses: Option> } impl Display for InterfaceDescription{ diff --git a/src/common/mod.rs b/src/common/mod.rs index f6e4172..82666de 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -11,7 +11,7 @@ use std::sync::Arc; pub use self::lib_version::LibraryVersion; pub use self::packet::{Packet, OwnedPacket, BorrowedPacket}; -pub use self::interf_desc::InterfaceDescription; +pub use self::interf_desc::{InterfaceDescription, AddressDescription}; pub use self::data_link::DataLink; pub use self::err::Error; diff --git a/src/common/packet.rs b/src/common/packet.rs index 2b15873..549a9c5 100644 --- a/src/common/packet.rs +++ b/src/common/packet.rs @@ -1,5 +1,5 @@ use time::Timespec; -use std::ops::Deref; +use std::ops::{Deref, DerefMut}; use std::fmt::{Display, Formatter, Error as FmtError, LowerHex}; ///Trait for obtained packets - common part between borrowed and owned versions. @@ -80,6 +80,13 @@ impl Deref for OwnedPacket { } } +impl DerefMut for OwnedPacket { + + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.packet + } +} + impl Display for OwnedPacket { fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { for b in &self.packet { diff --git a/src/lib.rs b/src/lib.rs index 89646c9..eb94dfd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,4 +87,4 @@ mod pcap_common; mod utils; mod common; -pub use self::common::{Packet, BorrowedPacket, OwnedPacket, DataLink, LibraryVersion, open_best_library, open_best_library_arc,InterfaceDescription, Error, Stats}; +pub use self::common::{Packet, BorrowedPacket, OwnedPacket, DataLink, LibraryVersion, open_best_library, open_best_library_arc,InterfaceDescription, AddressDescription, Error, Stats}; diff --git a/src/pcap_common/structs.rs b/src/pcap_common/structs.rs index ea1327c..3ec4618 100644 --- a/src/pcap_common/structs.rs +++ b/src/pcap_common/structs.rs @@ -1,7 +1,8 @@ use std::ffi::{CStr}; -use libc::{c_char, c_void, c_uint, c_uchar, c_ushort, timeval}; +use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; +use libc::{c_char, c_void, c_uint, c_uchar, c_ushort, timeval, sockaddr, sockaddr_in, sockaddr_in6}; use std::mem::uninitialized; -use crate::common::InterfaceDescription; +use crate::common::{InterfaceDescription, AddressDescription}; use crate::utils::cstr_to_string; use super::constants::ERRBUF_SIZE; @@ -47,7 +48,7 @@ pub struct PCapInterface { pub next: * const PCapInterface, pub name: * const c_char, /* name to hand to "pcap_open_live()" */ pub description: * const c_char, /* textual description of interface, or NULL */ - pub addresses: * const c_void, + pub addresses: * const PCapAddr, pub flags: c_uint /* PCAP_IF_ interface flags */ } @@ -76,13 +77,61 @@ pub enum PCapDirection { pub type PCapHandler=extern "C" fn(user: * mut c_uchar, h: * const PCapPacketHeader, bytes: * const c_uchar); +#[repr(C)] +pub struct PCapAddr { + pub next: * const PCapAddr, + pub addr: * const sockaddr, + pub netmask: * const sockaddr, + pub broadaddr: * const sockaddr, + pub dstaddr: * const sockaddr, +} + +const AF_INET: u16 = 2; +const AF_INET6: u16 = 10; + +fn ipaddr_from_sockaddr_ptr (ptr: * const sockaddr) -> Option { + if ptr.is_null() { + None + } else { + let sa_family = unsafe {(*ptr).sa_family}; + match sa_family { + AF_INET => { + let ptr = ptr as * const sockaddr_in; + let addr = unsafe {*ptr}; + Some(SocketAddrV4::new(u32::from_be(addr.sin_addr.s_addr).into(), u16::from_be(addr.sin_port).into()).into()) + }, + AF_INET6 => { + let ptr = ptr as * const sockaddr_in6; + let addr = unsafe {*ptr}; + Some(SocketAddrV6::new(addr.sin6_addr.s6_addr.into(), u16::from_be(addr.sin6_port), addr.sin6_flowinfo, addr.sin6_scope_id).into()) + }, + _ => None, + } + } +} + +pub fn address_data_from_interface(mut addr_ptr: * const PCapAddr) -> Vec { + let mut ret = vec![]; + while let Some(addr) = unsafe {addr_ptr.as_ref()} { + ret.push(AddressDescription { + address: ipaddr_from_sockaddr_ptr(addr.addr), + netmask: ipaddr_from_sockaddr_ptr(addr.netmask), + broadcast_address: ipaddr_from_sockaddr_ptr(addr.broadaddr), + dest_address: ipaddr_from_sockaddr_ptr(addr.dstaddr), + }); + addr_ptr = addr.next; + } + ret +} + pub fn interface_data_from_pcap_list(interfs: * const PCapInterface) -> Vec { let mut interfs_descr = Vec::new(); let mut curr = interfs; while !curr.is_null() { let id = InterfaceDescription { name: cstr_to_string(unsafe{(*curr).name}), - description: cstr_to_string(unsafe{(*curr).description}) + description: cstr_to_string(unsafe{(*curr).description}), + addresses: Some(address_data_from_interface(unsafe{(*curr).addresses})) }; interfs_descr.push(id); curr = unsafe{(*curr).next}; diff --git a/src/pfring/library.rs b/src/pfring/library.rs index 2c03248..975c4ba 100644 --- a/src/pfring/library.rs +++ b/src/pfring/library.rs @@ -53,7 +53,8 @@ impl traits::Library for Library { let sn = cstr_to_string(unsafe{(*curr).sn}); let id = InterfaceDescription{ name: cstr_to_string(unsafe{(*curr).name}), - description: format!("{}, {}, {}", &system_name, &module, &sn) + description: format!("{}, {}, {}", &system_name, &module, &sn), + addresses: None }; result.push(id); curr=unsafe{(*curr).next};