netlink_packet_route/rtnl/nsid/
message.rs1use anyhow::Context;
4use netlink_packet_utils::{
5 traits::{Emitable, Parseable},
6 DecodeError,
7};
8
9use crate::{nlas::nsid::Nla, NsidHeader, NsidMessageBuffer};
10
11#[derive(Debug, PartialEq, Eq, Clone, Default)]
12#[non_exhaustive]
13pub struct NsidMessage {
14 pub header: NsidHeader,
15 pub nlas: Vec<Nla>,
16}
17
18impl<'a, T: AsRef<[u8]> + 'a> Parseable<NsidMessageBuffer<&'a T>>
19 for NsidMessage
20{
21 fn parse(buf: &NsidMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
22 Ok(Self {
23 header: NsidHeader::parse(buf)
24 .context("failed to parse nsid message header")?,
25 nlas: Vec::<Nla>::parse(buf)
26 .context("failed to parse nsid message NLAs")?,
27 })
28 }
29}
30
31impl<'a, T: AsRef<[u8]> + 'a> Parseable<NsidMessageBuffer<&'a T>> for Vec<Nla> {
32 fn parse(buf: &NsidMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
33 let mut nlas = vec![];
34 for nla_buf in buf.nlas() {
35 nlas.push(Nla::parse(&nla_buf?)?);
36 }
37 Ok(nlas)
38 }
39}
40
41impl Emitable for NsidMessage {
42 fn buffer_len(&self) -> usize {
43 self.header.buffer_len() + self.nlas.as_slice().buffer_len()
44 }
45
46 fn emit(&self, buffer: &mut [u8]) {
47 self.header.emit(buffer);
48 self.nlas
49 .as_slice()
50 .emit(&mut buffer[self.header.buffer_len()..]);
51 }
52}
53
54#[cfg(test)]
55mod test {
56 use crate::{
57 nlas::nsid::Nla, NsidHeader, NsidMessage, RtnlMessage,
58 RtnlMessageBuffer, NETNSA_NSID_NOT_ASSIGNED, RTM_GETNSID, RTM_NEWNSID,
59 };
60 use netlink_packet_core::NetlinkBuffer;
61 use netlink_packet_utils::traits::ParseableParametrized;
62
63 #[rustfmt::skip]
64 #[test]
65 fn get_ns_id_request() {
66 let data = vec![
67 0x1c, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00 ];
81 let expected = RtnlMessage::GetNsId(NsidMessage {
82 header: NsidHeader { rtgen_family: 0 },
83 nlas: vec![Nla::Fd(4)],
84 });
85 let actual = RtnlMessage::parse_with_param(&RtnlMessageBuffer::new(&NetlinkBuffer::new(&data).payload()), RTM_GETNSID).unwrap();
86 assert_eq!(expected, actual);
87 }
88
89 #[rustfmt::skip]
90 #[test]
91 fn get_ns_id_response() {
92 let data = vec![
93 0x1c, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff ];
107 let expected = RtnlMessage::NewNsId(NsidMessage {
108 header: NsidHeader { rtgen_family: 0 },
109 nlas: vec![Nla::Id(NETNSA_NSID_NOT_ASSIGNED)],
110 });
111 let nl_buffer = NetlinkBuffer::new(&data).payload();
112 let rtnl_buffer = RtnlMessageBuffer::new(&nl_buffer);
113 let actual = RtnlMessage::parse_with_param(&rtnl_buffer, RTM_NEWNSID).unwrap();
114 assert_eq!(expected, actual);
115 }
116}