use mnl_sys::{self, libc};
use std::{io, ptr};
pub enum CbResult {
Stop,
Ok,
}
pub type Callback<T> = fn(msg: &libc::nlmsghdr, data: &mut T) -> libc::c_int;
pub fn cb_run(buffer: &[u8], seq: u32, portid: u32) -> io::Result<CbResult> {
let len = buffer.len();
let buf = buffer.as_ptr() as *const libc::c_void;
log::debug!("Processing {} byte netlink message without a callback", len);
match unsafe { mnl_sys::mnl_cb_run(buf, len, seq, portid, None, ptr::null_mut()) } {
i if i <= mnl_sys::MNL_CB_ERROR => Err(io::Error::last_os_error()),
mnl_sys::MNL_CB_STOP => Ok(CbResult::Stop),
_ => Ok(CbResult::Ok),
}
}
pub fn cb_run2<T>(
buffer: &[u8],
seq: u32,
portid: u32,
callback: Callback<T>,
data: &mut T,
) -> io::Result<CbResult> {
let len = buffer.len();
let buf = buffer.as_ptr() as *const libc::c_void;
let mut callback_context = CallbackContext { callback, data };
log::debug!("Processing {} byte netlink message with callback", len);
match unsafe {
mnl_sys::mnl_cb_run(
buf,
len,
seq,
portid,
Some(callback_wrapper::<T>),
&mut callback_context as *mut _ as *mut libc::c_void,
)
} {
i if i <= mnl_sys::MNL_CB_ERROR => Err(io::Error::last_os_error()),
mnl_sys::MNL_CB_STOP => Ok(CbResult::Stop),
_ => Ok(CbResult::Ok),
}
}
struct CallbackContext<'a, T> {
pub callback: Callback<T>,
pub data: &'a mut T,
}
extern "C" fn callback_wrapper<T>(
nlh: *const libc::nlmsghdr,
data: *mut libc::c_void,
) -> libc::c_int {
let context: &mut CallbackContext<'_, T> =
unsafe { &mut *(data as *mut CallbackContext<'_, T>) };
(context.callback)(unsafe { &*nlh }, context.data)
}