use std::ops::{Deref, DerefMut};
use anyhow::{anyhow, Result};
use crate::{
core::message::Message,
handle::zero_terminated,
types::{
generic::{GenlFamilies, GenlFamily},
message::{Attribute, GenlMessage, RouteAttr},
},
};
use super::handle::SocketHandle;
pub struct GenericHandle<'a> {
pub socket: &'a mut SocketHandle,
}
impl<'a> Deref for GenericHandle<'a> {
type Target = SocketHandle;
fn deref(&self) -> &Self::Target {
self.socket
}
}
impl DerefMut for GenericHandle<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.socket
}
}
impl<'a> From<&'a mut SocketHandle> for GenericHandle<'a> {
fn from(socket: &'a mut SocketHandle) -> Self {
Self { socket }
}
}
impl GenericHandle<'_> {
pub fn list_family(&mut self) -> Result<GenlFamilies> {
let mut req = Message::new(libc::GENL_ID_CTRL as u16, libc::NLM_F_DUMP);
let msg = GenlMessage::get_family_message();
req.add(&msg.serialize()?);
let msgs = self.request(&mut req, 0)?;
GenlFamilies::try_from(msgs)
}
pub fn get_family(&mut self, name: &str) -> Result<GenlFamily> {
let mut req = Message::new(libc::GENL_ID_CTRL as u16, 0);
let msg = GenlMessage::get_family_message();
let family_name =
RouteAttr::new(libc::CTRL_ATTR_FAMILY_NAME as u16, &zero_terminated(name));
req.add(&msg.serialize()?);
req.add(&family_name.serialize()?);
let msgs = self.request(&mut req, 0)?;
GenlFamilies::try_from(msgs)?
.first()
.cloned()
.ok_or_else(|| anyhow!("invalid response for GENL_CTRL_CMD_GETFAMILY"))
}
}