use crate::consts::*;
use crate::error::{Error, Result};
use crate::parse::parse_netlink_message;
use crate::proc_event::ProcEvent;
pub struct NetlinkMessageIter<'a> {
buf: &'a [u8],
pos: usize,
len: usize,
}
impl<'a> NetlinkMessageIter<'a> {
pub fn new(buf: &'a [u8], len: usize) -> Self {
NetlinkMessageIter { buf, pos: 0, len }
}
}
impl<'a> Iterator for NetlinkMessageIter<'a> {
type Item = Result<Option<ProcEvent>>;
fn next(&mut self) -> Option<Self::Item> {
if self.pos >= self.len {
return None;
}
let remaining = self.len - self.pos;
if remaining < SIZE_NLMSGHDR {
return Some(Err(Error::Truncated));
}
let nlmsg_len = read_u32(&self.buf[self.pos..], 0) as usize;
if nlmsg_len < SIZE_NLMSGHDR || nlmsg_len > remaining {
return Some(Err(Error::Truncated));
}
let msg_slice = &self.buf[self.pos..self.pos + nlmsg_len];
let nlmsg_type = read_u16(msg_slice, 4);
if nlmsg_type == NLMSG_DONE && nlmsg_len == SIZE_NLMSGHDR {
self.pos = self.len; return None; }
let result = parse_netlink_message(msg_slice, nlmsg_len);
self.pos += nlmsg_align(nlmsg_len);
Some(result)
}
}
#[inline]
fn read_u32(buf: &[u8], off: usize) -> u32 {
let arr: [u8; 4] = buf[off..off + 4].try_into().unwrap();
u32::from_ne_bytes(arr)
}
#[inline]
fn read_u16(buf: &[u8], off: usize) -> u16 {
let arr: [u8; 2] = buf[off..off + 2].try_into().unwrap();
u16::from_ne_bytes(arr)
}