netlink_packet_route/rtnl/nsid/
message.rs

1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4
5use crate::{
6    nlas::nsid::Nla,
7    traits::{Emitable, Parseable},
8    DecodeError,
9    NsidHeader,
10    NsidMessageBuffer,
11};
12
13#[derive(Debug, PartialEq, Eq, Clone, Default)]
14pub struct NsidMessage {
15    pub header: NsidHeader,
16    pub nlas: Vec<Nla>,
17}
18
19impl<'a, T: AsRef<[u8]> + 'a> Parseable<NsidMessageBuffer<&'a T>> for NsidMessage {
20    fn parse(buf: &NsidMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
21        Ok(Self {
22            header: NsidHeader::parse(buf).context("failed to parse nsid message header")?,
23            nlas: Vec::<Nla>::parse(buf).context("failed to parse nsid message NLAs")?,
24        })
25    }
26}
27
28impl<'a, T: AsRef<[u8]> + 'a> Parseable<NsidMessageBuffer<&'a T>> for Vec<Nla> {
29    fn parse(buf: &NsidMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
30        let mut nlas = vec![];
31        for nla_buf in buf.nlas() {
32            nlas.push(Nla::parse(&nla_buf?)?);
33        }
34        Ok(nlas)
35    }
36}
37
38impl Emitable for NsidMessage {
39    fn buffer_len(&self) -> usize {
40        self.header.buffer_len() + self.nlas.as_slice().buffer_len()
41    }
42
43    fn emit(&self, buffer: &mut [u8]) {
44        self.header.emit(buffer);
45        self.nlas
46            .as_slice()
47            .emit(&mut buffer[self.header.buffer_len()..]);
48    }
49}
50
51#[cfg(test)]
52mod test {
53    use crate::{
54        nlas::nsid::Nla,
55        traits::ParseableParametrized,
56        NetlinkBuffer,
57        NsidHeader,
58        NsidMessage,
59        RtnlMessage,
60        RtnlMessageBuffer,
61        NETNSA_NSID_NOT_ASSIGNED,
62        RTM_GETNSID,
63        RTM_NEWNSID,
64    };
65
66    #[rustfmt::skip]
67    #[test]
68    fn get_ns_id_request() {
69        let data = vec![
70            0x1c, 0x00, 0x00, 0x00, // length = 28
71            0x5a, 0x00, // message type = 90 = RTM_GETNSID
72            0x01, 0x00, // flags
73            0x00, 0x00, 0x00, 0x00, // seq number
74            0x00, 0x00, 0x00, 0x00, // pid
75
76            // GETNSID message
77            0x00, // rtgen family
78            0x00, 0x00, 0x00, // padding
79            // NLA
80            0x08, 0x00, // length = 8
81            0x03, 0x00, // type = 3 (Fd)
82            0x04, 0x00, 0x00, 0x00 // 4
83        ];
84        let expected = RtnlMessage::GetNsId(NsidMessage {
85            header: NsidHeader { rtgen_family: 0 },
86            nlas: vec![Nla::Fd(4)],
87        });
88        let actual = RtnlMessage::parse_with_param(&RtnlMessageBuffer::new(&NetlinkBuffer::new(&data).payload()), RTM_GETNSID).unwrap();
89        assert_eq!(expected, actual);
90    }
91
92    #[rustfmt::skip]
93    #[test]
94    fn get_ns_id_response() {
95        let data = vec![
96            0x1c, 0x00, 0x00, 0x00, // length = 28
97            0x58, 0x00, // message type = RTM_NEWNSID
98            0x00, 0x00, // flags
99            0x00, 0x00, 0x00, 0x00, // seq number
100            0x76, 0x12, 0x00, 0x00, // pid
101
102            // NETNSID message
103            0x00, // rtgen family
104            0x00, 0x00, 0x00, // padding
105            // NLA
106            0x08, 0x00, // length
107            0x01, 0x00, // type = NETNSA_NSID
108            0xff, 0xff, 0xff, 0xff // -1
109        ];
110        let expected = RtnlMessage::NewNsId(NsidMessage {
111            header: NsidHeader { rtgen_family: 0 },
112            nlas: vec![Nla::Id(NETNSA_NSID_NOT_ASSIGNED)],
113        });
114        let nl_buffer = NetlinkBuffer::new(&data).payload();
115        let rtnl_buffer = RtnlMessageBuffer::new(&nl_buffer);
116        let actual = RtnlMessage::parse_with_param(&rtnl_buffer, RTM_NEWNSID).unwrap();
117        assert_eq!(expected, actual);
118    }
119}