use bcc_sys::bccapi::bpf_prog_type_BPF_PROG_TYPE_SOCKET_FILTER as BPF_PROG_TYPE_SOCKET_FILTER;
use std::collections::HashSet;
use std::iter::Iterator;
use socket2;
use std::os::unix::io::FromRawFd;
use crate::core::BPF;
use crate::error::BccError;
#[derive(Debug)]
pub struct SocketWrapper {
pub iface: String,
pub socket: socket2::Socket,
}
impl SocketWrapper {
pub fn new(iface: String, socket_fd: i32) -> Self {
let socket = unsafe { socket2::Socket::from_raw_fd(socket_fd) };
Self { iface, socket }
}
}
#[derive(Debug, Default)]
pub struct SocketBuilder {
handler: Option<String>,
ifaces: HashSet<String>,
}
impl SocketBuilder {
pub fn new() -> Self {
Default::default()
}
pub fn handler(mut self, handler: &str) -> Self {
self.handler = Some(handler.to_owned());
self
}
pub fn add_interface(mut self, iface: &str) -> Self {
self.ifaces.insert(iface.to_owned());
self
}
pub fn add_interfaces(mut self, ifaces: &[String]) -> Self {
self.ifaces.extend(ifaces.iter().cloned());
self
}
pub fn attach(self, bpf: &mut BPF) -> Result<Vec<SocketWrapper>, BccError> {
if self.ifaces.len() == 0 {
return Err(BccError::InvalidSocket {
message: "interface is required".to_string(),
});
}
if self.handler.is_none() {
return Err(BccError::InvalidSocket {
message: "handler is required".to_string(),
});
}
let code_fd = bpf.load(&self.handler.unwrap(), BPF_PROG_TYPE_SOCKET_FILTER, 0, 0)?;
let socket_map = self
.ifaces
.iter()
.map(|iface: &String| -> Result<SocketWrapper, BccError> {
let socket_fd = crate::core::RawSocket::attach(iface, &code_fd)?;
Ok(SocketWrapper::new(iface.to_owned(), socket_fd))
})
.collect::<Result<Vec<SocketWrapper>, BccError>>();
socket_map
}
}