use std::os::fd::AsRawFd;
use crate::{
MessageBuilder,
netlink::msg::{
NlMsgHeader,
flags::{NLM_F_ACK, NLM_F_CREATE, NLM_F_EXCL, NLM_F_REQUEST},
},
};
pub mod ipvlan_infos {
pub const IFLA_IPVLAN_MODE: u16 = 1;
pub const IFLA_IPVLAN_FLAGS: u16 = 2;
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u16)]
pub enum IpvlanMode {
L2 = 0,
L3 = 1,
L3S = 2,
}
pub struct AddIpvlanNetnsInput<'a> {
pub if_name: String,
pub parent_if_index: u32,
pub mode: IpvlanMode,
pub netns_fd: &'a dyn AsRawFd,
}
pub struct AddIpvlanNetnsMsgBuilder<'a, Buffer: std::io::Write> {
pub buffer: &'a mut Buffer,
pub nl_msg_header: NlMsgHeader,
pub if_info_msg: super::IfInfoMsg,
pub if_name: String,
pub parent_if_index: u32,
pub mode: IpvlanMode,
pub netns_fd: &'a dyn AsRawFd,
}
pub fn add_ipvlan_netns_nl_header(header: &mut NlMsgHeader) {
const FLAGS: u16 = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
header.r#type = super::RTM_NEWLINK;
header.flags = FLAGS;
}
impl<'a, Buffer: std::io::Write> MessageBuilder<'a> for AddIpvlanNetnsMsgBuilder<'a, Buffer> {
type Buffer = Buffer;
type Input = AddIpvlanNetnsInput<'a>;
type Output = ();
type ParseError = ();
fn new_with_header(
buffer: &'a mut Self::Buffer,
mut nl_msg_header: NlMsgHeader,
input: Self::Input,
) -> Self {
add_ipvlan_netns_nl_header(&mut nl_msg_header);
let AddIpvlanNetnsInput {
if_name,
parent_if_index,
mode,
netns_fd,
} = input;
Self {
buffer,
nl_msg_header,
if_info_msg: super::IfInfoMsg::default(),
if_name,
parent_if_index,
mode,
netns_fd,
}
}
fn build(mut self) -> Result<(&'a mut Self::Buffer, usize), std::io::Error> {
const KIND: &[u8; 6] = b"ipvlan";
let mut written_bytes = 0;
let if_info_data_length = crate::netlink::attr::set_attr_length_aligned(2);
let if_infos_length = crate::netlink::attr::set_attr_length_aligned(KIND.len())
+ crate::netlink::attr::set_attr_length_aligned(if_info_data_length);
self.nl_msg_header.set_playload_length(
super::IfInfoMsg::SIZE
+ crate::netlink::attr::set_string_length_aligned(self.if_name.len())
+ crate::netlink::attr::set_attr_length_aligned(4) + crate::netlink::attr::set_attr_length_aligned(4) + crate::netlink::attr::set_attr_length_aligned(if_infos_length), );
written_bytes += self.nl_msg_header.write(self.buffer)?;
written_bytes += self.if_info_msg.write(self.buffer)?;
written_bytes += crate::netlink::attr::write_string_attr(
self.buffer,
super::link_attributes::IFLA_IFNAME,
&self.if_name,
)?;
written_bytes += crate::netlink::attr::write_i32_attr(
self.buffer,
super::link_attributes::IFLA_LINK,
self.parent_if_index as i32,
)?;
written_bytes += crate::netlink::attr::write_i32_attr(
self.buffer,
super::link_attributes::IFLA_NET_NS_FD,
self.netns_fd.as_raw_fd(),
)?;
written_bytes += crate::netlink::attr::NlAttribute {
len: crate::netlink::attr::set_attr_length(if_infos_length) as u16,
r#type: super::link_attributes::IFLA_LINKINFO,
}
.write(self.buffer)?;
written_bytes += crate::netlink::attr::write_array_attr(
self.buffer,
super::link_info_attributes::IFLA_INFO_KIND,
*KIND,
)?;
written_bytes += crate::netlink::attr::NlAttribute {
len: crate::netlink::attr::set_attr_length(if_info_data_length) as u16,
r#type: super::link_info_attributes::IFLA_INFO_DATA,
}
.write(self.buffer)?;
written_bytes += crate::netlink::attr::write_u16_attr(
self.buffer,
ipvlan_infos::IFLA_IPVLAN_MODE,
self.mode as u16,
)?;
Ok((self.buffer, written_bytes))
}
fn parse_response(
reader: &mut impl std::io::Read,
) -> Result<Self::Output, crate::ResponseError<Self::ParseError>> {
crate::netlink::msg::validate_ack(reader)
.map_err(crate::ResponseError::<Self::ParseError>::HeaderParse)
}
}