rust/ffi: add flow accessors to flow wrapper

Ticket: #8599
pull/16053/head
Jason Ish 3 months ago committed by Victor Julien
parent d3d206faa5
commit 17bd53c29c

@ -98,8 +98,32 @@ fn log_eve_wrapped(
jb.set_string("example", "eve-callback")?;
jb.set_string("has_flow", if f.is_some() { "true" } else { "false" })?;
// If we have a flow, log something from flow storage.
// If we have a flow, show the `Flow` wrapper accessors and log something
// from flow storage.
if let Some(f) = f {
let src_ip = f
.source_address()
.map(|addr| addr.to_string())
.unwrap_or_else(|| "<unknown>".to_string());
let dst_ip = f
.destination_address()
.map(|addr| addr.to_string())
.unwrap_or_else(|| "<unknown>".to_string());
let toserver = f.to_server_packet_count();
let toclient = f.to_client_packet_count();
jb.open_object("flow_accessors")?;
jb.set_string("src_ip", &src_ip)?;
jb.set_uint("src_port", f.source_port() as u64)?;
jb.set_string("dest_ip", &dst_ip)?;
jb.set_uint("dest_port", f.destination_port() as u64)?;
jb.set_uint("ip_proto", f.ip_protocol() as u64)?;
jb.set_uint("app_proto", f.app_protocol() as u64)?;
jb.set_uint("toserver_pkts", toserver as u64)?;
jb.set_uint("toclient_pkts", toclient as u64)?;
jb.set_uint("last_seen", f.last_time().as_secs())?;
jb.close()?;
if let Some(state) = flow_storage.get(f) {
jb.set_uint("flow_packets", state.packets)?;
}

@ -17,7 +17,9 @@
use std::ffi::CString;
use std::marker::PhantomData;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::os::raw::c_void;
use std::time::Duration;
use suricata_sys::sys::{
self, Packet, SCFlowGetStorageById, SCFlowRegisterFinishCallback, SCFlowRegisterInitCallback,
@ -58,6 +60,92 @@ impl<'a> Flow<'a> {
fn as_mut_ptr(&mut self) -> *mut sys::Flow {
self.flow
}
/// Return the time of the last flow update as a `Duration` since the epoch.
pub fn last_time(&self) -> Duration {
let mut secs: u64 = 0;
let mut usecs: u64 = 0;
unsafe {
sys::SCFlowGetLastTimeAsParts(self.as_ptr(), &mut secs, &mut usecs);
}
Duration::new(secs, usecs as u32 * 1000)
}
/// Return the flow flags.
pub fn flags(&self) -> u64 {
unsafe { sys::SCFlowGetFlags(self.as_ptr()) }
}
/// Return true if the flow is IPv4.
pub fn is_ipv4(&self) -> bool {
unsafe { sys::SCFlowIsIPv4(self.as_ptr()) }
}
/// Return true if the flow is IPv6.
pub fn is_ipv6(&self) -> bool {
unsafe { sys::SCFlowIsIPv6(self.as_ptr()) }
}
/// Return the flow IP protocol.
pub fn ip_protocol(&self) -> u8 {
unsafe { sys::SCFlowGetIPProtocol(self.as_ptr()) }
}
/// Return the flow app-layer protocol.
pub fn app_protocol(&self) -> sys::AppProto {
unsafe { sys::SCFlowGetAppProtocol(self.as_ptr()) }
}
/// Return the flow source port.
pub fn source_port(&self) -> u16 {
unsafe { sys::SCFlowGetSourcePort(self.as_ptr()) }
}
/// Return the flow destination port.
pub fn destination_port(&self) -> u16 {
unsafe { sys::SCFlowGetDestinationPort(self.as_ptr()) }
}
/// Return an owned copy the flow's source address.
pub fn source_address(&self) -> Option<IpAddr> {
let ptr = unsafe { sys::SCFlowGetSourceAddressAsRawPtr(self.as_ptr()) };
self.address_from_ptr(ptr)
}
/// Return an owned copy the flow's destination address.
pub fn destination_address(&self) -> Option<IpAddr> {
let ptr = unsafe { sys::SCFlowGetDestinationAddressAsRawPtr(self.as_ptr()) };
self.address_from_ptr(ptr)
}
/// Return the number of packets seen to-server.
pub fn to_server_packet_count(&self) -> u32 {
unsafe { sys::SCFlowGetToServerPacketCount(self.as_ptr()) }
}
/// Return the number of packets seen to-client.
pub fn to_client_packet_count(&self) -> u32 {
unsafe { sys::SCFlowGetToClientPacketCount(self.as_ptr()) }
}
fn address_from_ptr(&self, ptr: *const u8) -> Option<IpAddr> {
if ptr.is_null() {
return None;
}
if self.is_ipv4() {
let bytes = unsafe { std::slice::from_raw_parts(ptr, 4) };
Some(IpAddr::V4(Ipv4Addr::new(
bytes[0], bytes[1], bytes[2], bytes[3],
)))
} else if self.is_ipv6() {
let bytes = unsafe { std::slice::from_raw_parts(ptr, 16) };
let mut addr = [0; 16];
addr.copy_from_slice(bytes);
Some(IpAddr::V6(Ipv6Addr::from(addr)))
} else {
None
}
}
}
/// A typed handle to a per-flow storage slot.

Loading…
Cancel
Save