1use anyhow::Context;
4use netlink_packet_utils::{
5 traits::{Emitable, Parseable, ParseableParametrized},
6 DecodeError,
7};
8
9use crate::{nlas::link::Nla, LinkHeader, LinkMessageBuffer};
10
11#[derive(Debug, PartialEq, Eq, Clone, Default)]
12#[non_exhaustive]
13pub struct LinkMessage {
14 pub header: LinkHeader,
15 pub nlas: Vec<Nla>,
16}
17
18impl Emitable for LinkMessage {
19 fn buffer_len(&self) -> usize {
20 self.header.buffer_len() + self.nlas.as_slice().buffer_len()
21 }
22
23 fn emit(&self, buffer: &mut [u8]) {
24 self.header.emit(buffer);
25 self.nlas
26 .as_slice()
27 .emit(&mut buffer[self.header.buffer_len()..]);
28 }
29}
30
31impl<'a, T: AsRef<[u8]> + 'a> Parseable<LinkMessageBuffer<&'a T>>
32 for LinkMessage
33{
34 fn parse(buf: &LinkMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
35 let header = LinkHeader::parse(buf)
36 .context("failed to parse link message header")?;
37 let interface_family = header.interface_family;
38 let nlas = Vec::<Nla>::parse_with_param(buf, interface_family)
39 .context("failed to parse link message NLAs")?;
40 Ok(LinkMessage { header, nlas })
41 }
42}
43
44impl<'a, T: AsRef<[u8]> + 'a>
45 ParseableParametrized<LinkMessageBuffer<&'a T>, u16> for Vec<Nla>
46{
47 fn parse_with_param(
48 buf: &LinkMessageBuffer<&'a T>,
49 family: u16,
50 ) -> Result<Self, DecodeError> {
51 let mut nlas = vec![];
52 for nla_buf in buf.nlas() {
53 nlas.push(Nla::parse_with_param(&nla_buf?, family)?);
54 }
55 Ok(nlas)
56 }
57}
58
59impl<'a, T: AsRef<[u8]> + 'a>
60 ParseableParametrized<LinkMessageBuffer<&'a T>, u8> for Vec<Nla>
61{
62 fn parse_with_param(
63 buf: &LinkMessageBuffer<&'a T>,
64 family: u8,
65 ) -> Result<Self, DecodeError> {
66 Vec::<Nla>::parse_with_param(buf, u16::from(family))
67 }
68}
69
70#[cfg(test)]
71mod test {
72 use crate::{
73 constants::*,
74 nlas::link::{Nla, State},
75 LinkHeader, LinkMessage, LinkMessageBuffer,
76 };
77
78 use netlink_packet_utils::traits::{Emitable, ParseableParametrized};
79
80 #[rustfmt::skip]
81 static HEADER: [u8; 96] = [
82 0x00, 0x00, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x00, 0x6c, 0x6f, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0xff, 0xff, 0x00, 0x00, 0x08, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, ];
106
107 #[test]
108 fn packet_header_read() {
109 let packet = LinkMessageBuffer::new(&HEADER[0..16]);
110 assert_eq!(packet.interface_family(), 0);
111 assert_eq!(packet.reserved_1(), 0);
112 assert_eq!(packet.link_layer_type(), ARPHRD_LOOPBACK);
113 assert_eq!(packet.link_index(), 1);
114 assert_eq!(packet.flags(), IFF_UP | IFF_LOOPBACK | IFF_RUNNING);
115 assert_eq!(packet.change_mask(), 0);
116 }
117
118 #[test]
119 fn packet_header_build() {
120 let mut buf = vec![0xff; 16];
121 {
122 let mut packet = LinkMessageBuffer::new(&mut buf);
123 packet.set_interface_family(0);
124 packet.set_reserved_1(0);
125 packet.set_link_layer_type(ARPHRD_LOOPBACK);
126 packet.set_link_index(1);
127 packet.set_flags(IFF_UP | IFF_LOOPBACK | IFF_RUNNING);
128 packet.set_change_mask(0);
129 }
130 assert_eq!(&buf[..], &HEADER[0..16]);
131 }
132
133 #[test]
134 fn packet_nlas_read() {
135 let packet = LinkMessageBuffer::new(&HEADER[..]);
136 assert_eq!(packet.nlas().count(), 10);
137 let mut nlas = packet.nlas();
138
139 let nla = nlas.next().unwrap().unwrap();
141 nla.check_buffer_length().unwrap();
142 assert_eq!(nla.length(), 7);
143 assert_eq!(nla.kind(), 3);
144 assert_eq!(nla.value(), &[0x6c, 0x6f, 0x00]);
145 let parsed = Nla::parse_with_param(&nla, AF_INET).unwrap();
146 assert_eq!(parsed, Nla::IfName(String::from("lo")));
147
148 let nla = nlas.next().unwrap().unwrap();
150 nla.check_buffer_length().unwrap();
151 assert_eq!(nla.length(), 8);
152 assert_eq!(nla.kind(), 13);
153 assert_eq!(nla.value(), &[0xe8, 0x03, 0x00, 0x00]);
154 let parsed = Nla::parse_with_param(&nla, AF_INET).unwrap();
155 assert_eq!(parsed, Nla::TxQueueLen(1000));
156
157 let nla = nlas.next().unwrap().unwrap();
159 nla.check_buffer_length().unwrap();
160 assert_eq!(nla.length(), 5);
161 assert_eq!(nla.kind(), 16);
162 assert_eq!(nla.value(), &[0x00]);
163 let parsed = Nla::parse_with_param(&nla, AF_INET).unwrap();
164 assert_eq!(parsed, Nla::OperState(State::Unknown));
165
166 let nla = nlas.next().unwrap().unwrap();
168 nla.check_buffer_length().unwrap();
169 assert_eq!(nla.length(), 5);
170 assert_eq!(nla.kind(), 17);
171 assert_eq!(nla.value(), &[0x00]);
172 let parsed = Nla::parse_with_param(&nla, AF_INET).unwrap();
173 assert_eq!(parsed, Nla::Mode(0));
174
175 let nla = nlas.next().unwrap().unwrap();
177 nla.check_buffer_length().unwrap();
178 assert_eq!(nla.length(), 8);
179 assert_eq!(nla.kind(), 4);
180 assert_eq!(nla.value(), &[0x00, 0x00, 0x01, 0x00]);
181 let parsed = Nla::parse_with_param(&nla, AF_INET).unwrap();
182 assert_eq!(parsed, Nla::Mtu(65_536));
183
184 let nla = nlas.next().unwrap().unwrap();
187 nla.check_buffer_length().unwrap();
188 assert_eq!(nla.length(), 8);
189 assert_eq!(nla.kind(), 27);
190 assert_eq!(nla.value(), &[0x00, 0x00, 0x00, 0x00]);
191 let parsed = Nla::parse_with_param(&nla, AF_INET).unwrap();
192 assert_eq!(parsed, Nla::Group(0));
193
194 let nla = nlas.next().unwrap().unwrap();
196 nla.check_buffer_length().unwrap();
197 assert_eq!(nla.length(), 8);
198 assert_eq!(nla.kind(), 30);
199 assert_eq!(nla.value(), &[0x00, 0x00, 0x00, 0x00]);
200 let parsed = Nla::parse_with_param(&nla, AF_INET).unwrap();
201 assert_eq!(parsed, Nla::Promiscuity(0));
202
203 let nla = nlas.next().unwrap().unwrap();
206 nla.check_buffer_length().unwrap();
207 assert_eq!(nla.length(), 8);
208 assert_eq!(nla.kind(), 31);
209 assert_eq!(nla.value(), &[0x01, 0x00, 0x00, 0x00]);
210 let parsed = Nla::parse_with_param(&nla, AF_INET).unwrap();
211 assert_eq!(parsed, Nla::NumTxQueues(1));
212 }
213
214 #[test]
215 fn emit() {
216 let header = LinkHeader {
217 link_layer_type: ARPHRD_LOOPBACK,
218 index: 1,
219 flags: IFF_UP | IFF_LOOPBACK | IFF_RUNNING | IFF_LOWER_UP,
220 ..Default::default()
221 };
222
223 let nlas = vec![
224 Nla::IfName("lo".into()),
225 Nla::TxQueueLen(1000),
226 Nla::OperState(State::Unknown),
227 Nla::Mode(0),
228 Nla::Mtu(0x1_0000),
229 Nla::Group(0),
230 Nla::Promiscuity(0),
231 Nla::NumTxQueues(1),
232 Nla::GsoMaxSegs(0xffff),
233 Nla::GsoMaxSize(0x1_0000),
234 ];
235
236 let packet = LinkMessage { header, nlas };
237
238 let mut buf = [0; 96];
239
240 assert_eq!(packet.buffer_len(), 96);
241 packet.emit(&mut buf[..]);
242 }
243}