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