netlink_packet/netlink/header.rs
1use super::{NetlinkBuffer, NetlinkFlags, NETLINK_HEADER_LEN};
2use crate::{DecodeError, Emitable, Parseable};
3
4/// A Netlink header representation.
5///
6/// A netlink header has the following structure:
7///
8/// ```no_rust
9/// 0 8 16 24 32
10/// +----------------+----------------+----------------+----------------+
11/// | packet length (including header) |
12/// +----------------+----------------+----------------+----------------+
13/// | message type | flags |
14/// +----------------+----------------+----------------+----------------+
15/// | sequence number |
16/// +----------------+----------------+----------------+----------------+
17/// | port number (formerly known as PID) |
18/// +----------------+----------------+----------------+----------------+
19/// ```
20///
21/// # Example: parsing a netlink header
22///
23/// ```rust
24/// extern crate netlink_packet;
25/// use netlink_packet::{NetlinkBuffer, NetlinkHeader, Parseable};
26/// use netlink_packet::constants::{RTM_GETLINK, NLM_F_ROOT, NLM_F_REQUEST, NLM_F_MATCH};
27///
28/// // a packet captured with tcpdump that was sent when running `ip link show`
29/// static PKT: [u8; 40] = [
30/// 0x28, 0x00, 0x00, 0x00, // length = 40
31/// 0x12, 0x00, // message type = 18 (RTM_GETLINK)
32/// 0x01, 0x03, // flags = Request + Specify Tree Root + Return All Matching
33/// 0x34, 0x0e, 0xf9, 0x5a, // sequence number = 1526271540
34/// 0x00, 0x00, 0x00, 0x00, // port id = 0
35/// // payload
36/// 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37/// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38/// 0x08, 0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x00];
39///
40/// fn main() {
41/// let pkt: NetlinkHeader = NetlinkBuffer::new_checked(&PKT[..]).unwrap().parse().unwrap();
42/// assert_eq!(pkt.length(), 40);
43/// assert_eq!(pkt.message_type(), RTM_GETLINK);
44/// assert_eq!(pkt.sequence_number(), 1_526_271_540);
45/// assert_eq!(pkt.port_number(), 0);
46/// assert_eq!(u16::from(pkt.flags()), NLM_F_ROOT | NLM_F_REQUEST | NLM_F_MATCH);
47/// }
48/// ```
49///
50/// # Example: emitting a netlink header
51///
52/// ```
53/// extern crate netlink_packet;
54/// use netlink_packet::{NetlinkBuffer, NetlinkHeader, NetlinkFlags, Emitable};
55/// use netlink_packet::constants::{RTM_GETLINK, NLM_F_ROOT, NLM_F_REQUEST, NLM_F_MATCH};
56///
57/// // a packet captured with tcpdump that was sent when running `ip link show`
58/// static PKT: [u8; 40] = [
59/// 0x28, 0x00, 0x00, 0x00, // length = 40
60/// 0x12, 0x00, // message type = 18 (RTM_GETLINK)
61/// 0x01, 0x03, // flags = Request + Specify Tree Root + Return All Matching
62/// 0x34, 0x0e, 0xf9, 0x5a, // sequence number = 1526271540
63/// 0x00, 0x00, 0x00, 0x00, // port id = 0
64/// // payload
65/// 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66/// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67/// 0x08, 0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x00];
68///
69/// fn main() {
70/// let flags = NetlinkFlags::from(NLM_F_ROOT | NLM_F_REQUEST | NLM_F_MATCH);
71/// let pkt = NetlinkHeader::new(40, RTM_GETLINK, flags, 0x5af9_0e34, 0);
72/// assert_eq!(pkt.buffer_len(), 16);
73/// let mut buf = vec![0; 16];
74/// pkt.emit(&mut buf[..]);
75/// assert_eq!(&buf[..], &PKT[..16]);
76/// }
77/// ```
78#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Default)]
79pub struct NetlinkHeader {
80 /// Length of the netlink packet, including the header and the payload
81 length: u32,
82
83 /// NetlinkMessage type. The meaning of this field depends on the netlink protocol family in use.
84 message_type: u16,
85
86 /// Flags
87 flags: NetlinkFlags,
88
89 /// Sequence number of the packet
90 sequence_number: u32,
91
92 /// Port number (usually set to the the process ID)
93 port_number: u32,
94}
95
96impl NetlinkHeader {
97 /// Create a new header, initialized with the given values
98 pub fn new(
99 length: u32,
100 message_type: u16,
101 flags: NetlinkFlags,
102 sequence_number: u32,
103 port_number: u32,
104 ) -> Self {
105 NetlinkHeader {
106 length,
107 message_type,
108 flags,
109 sequence_number,
110 port_number,
111 }
112 }
113
114 /// Get the length field
115 pub fn length(&self) -> u32 {
116 self.length
117 }
118
119 /// Get a mutable reference to the length field
120 pub fn length_mut(&mut self) -> &mut u32 {
121 &mut self.length
122 }
123
124 /// Setter for the length field
125 pub fn set_length(&mut self, value: u32) -> &mut Self {
126 self.length = value;
127 self
128 }
129
130 /// Get the message type field
131 pub fn message_type(&self) -> u16 {
132 self.message_type
133 }
134
135 /// Get a mutable reference to the message type field
136 pub fn message_type_mut(&mut self) -> &mut u16 {
137 &mut self.message_type
138 }
139
140 /// Setter for the message_type field
141 pub fn set_message_type(&mut self, value: u16) -> &mut Self {
142 self.message_type = value;
143 self
144 }
145
146 /// Get the flags field
147 pub fn flags(&self) -> NetlinkFlags {
148 self.flags
149 }
150
151 /// Get a mutable reference to the flags field
152 pub fn flags_mut(&mut self) -> &mut NetlinkFlags {
153 &mut self.flags
154 }
155
156 /// Setter for the flags field
157 pub fn set_flags(&mut self, value: NetlinkFlags) -> &mut Self {
158 self.flags = value;
159 self
160 }
161
162 /// Get the sequence number field
163 pub fn sequence_number(&self) -> u32 {
164 self.sequence_number
165 }
166
167 /// Get a mutable reference to the sequence number field
168 pub fn sequence_number_mut(&mut self) -> &mut u32 {
169 &mut self.sequence_number
170 }
171
172 /// Setter for the sequence number field
173 pub fn set_sequence_number(&mut self, value: u32) -> &mut Self {
174 self.sequence_number = value;
175 self
176 }
177
178 /// Get the port number field
179 pub fn port_number(&self) -> u32 {
180 self.port_number
181 }
182
183 /// Get a mutable reference to the port number field
184 pub fn port_number_mut(&mut self) -> &mut u32 {
185 &mut self.port_number
186 }
187
188 /// Setter for the port number field
189 pub fn set_port_number(&mut self, value: u32) -> &mut Self {
190 self.port_number = value;
191 self
192 }
193}
194
195impl Emitable for NetlinkHeader {
196 fn buffer_len(&self) -> usize {
197 NETLINK_HEADER_LEN
198 }
199
200 fn emit(&self, buffer: &mut [u8]) {
201 let mut buffer = NetlinkBuffer::new(buffer);
202 buffer.set_message_type(self.message_type);
203 buffer.set_length(self.length);
204 buffer.set_flags(self.flags);
205 buffer.set_sequence_number(self.sequence_number);
206 buffer.set_port_number(self.port_number);
207 }
208}
209
210impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NetlinkHeader> for NetlinkBuffer<&'a T> {
211 fn parse(&self) -> Result<NetlinkHeader, DecodeError> {
212 Ok(NetlinkHeader {
213 length: self.length(),
214 message_type: self.message_type(),
215 flags: self.flags(),
216 sequence_number: self.sequence_number(),
217 port_number: self.port_number(),
218 })
219 }
220}
221
222#[cfg(all(test, feature = "rtnetlink"))]
223mod tests {
224 use super::*;
225 use crate::constants::*;
226 use crate::flags::*;
227
228 // a packet captured with tcpdump that was sent when running `ip link show`
229 #[rustfmt::skip]
230 static IP_LINK_SHOW_PKT: [u8; 40] = [
231 0x28, 0x00, 0x00, 0x00, // length = 40
232 0x12, 0x00, // message type = 18 (RTM_GETLINK)
233 0x01, 0x03, // flags = Request + Specify Tree Root + Return All Matching
234 0x34, 0x0e, 0xf9, 0x5a, // sequence number = 1526271540
235 0x00, 0x00, 0x00, 0x00, // port id = 0
236 // payload
237 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239 0x08, 0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x00];
240
241 #[test]
242 fn repr_parse() {
243 let repr: NetlinkHeader = NetlinkBuffer::new_checked(&IP_LINK_SHOW_PKT[..])
244 .unwrap()
245 .parse()
246 .unwrap();
247 assert_eq!(repr.length, 40);
248 assert_eq!(repr.message_type, RTM_GETLINK);
249 assert_eq!(repr.sequence_number, 1_526_271_540);
250 assert_eq!(repr.port_number, 0);
251 assert_eq!(
252 Into::<u16>::into(repr.flags),
253 NLM_F_ROOT | NLM_F_REQUEST | NLM_F_MATCH
254 );
255 }
256
257 #[test]
258 fn repr_emit() {
259 let repr = NetlinkHeader {
260 length: 40,
261 message_type: RTM_GETLINK,
262 sequence_number: 1_526_271_540,
263 flags: NetlinkFlags::from(NLM_F_ROOT | NLM_F_REQUEST | NLM_F_MATCH),
264 port_number: 0,
265 };
266 assert_eq!(repr.buffer_len(), 16);
267 let mut buf = vec![0; 16];
268 repr.emit(&mut buf[..]);
269 assert_eq!(&buf[..], &IP_LINK_SHOW_PKT[..16]);
270 }
271}