netlink_packet_route/link/header.rs
1// SPDX-License-Identifier: MIT
2
3use netlink_packet_core::{
4 DecodeError, Emitable, NlaBuffer, NlasIterator, Parseable,
5};
6
7use super::link_flag::LinkFlags;
8use crate::{link::LinkLayerType, AddressFamily};
9
10const LINK_HEADER_LEN: usize = 16;
11
12buffer!(LinkMessageBuffer(LINK_HEADER_LEN) {
13 interface_family: (u8, 0),
14 reserved_1: (u8, 1),
15 link_layer_type: (u16, 2..4),
16 link_index: (u32, 4..8),
17 flags: (u32, 8..12),
18 change_mask: (u32, 12..LINK_HEADER_LEN),
19 payload: (slice, LINK_HEADER_LEN..),
20});
21
22impl<'a, T: AsRef<[u8]> + ?Sized> LinkMessageBuffer<&'a T> {
23 pub fn attributes(
24 &self,
25 ) -> impl Iterator<Item = Result<NlaBuffer<&'a [u8]>, DecodeError>> {
26 NlasIterator::new(self.payload())
27 }
28}
29
30/// High level representation of `RTM_GETLINK`, `RTM_SETLINK`, `RTM_NEWLINK` and
31/// `RTM_DELLINK` messages headers.
32///
33/// These headers have the following structure:
34///
35/// ```no_rust
36/// 0 8 16 24 32
37/// +----------------+----------------+----------------+----------------+
38/// |interface family| reserved | link layer type |
39/// +----------------+----------------+----------------+----------------+
40/// | link index |
41/// +----------------+----------------+----------------+----------------+
42/// | flags |
43/// +----------------+----------------+----------------+----------------+
44/// | change mask |
45/// +----------------+----------------+----------------+----------------+
46/// ```
47///
48/// `LinkHeader` exposes all these fields except for the "reserved" one.
49#[derive(Debug, PartialEq, Eq, Clone, Default)]
50pub struct LinkHeader {
51 /// Address family: one of the `AF_*` constants.
52 /// The [AddressFamily] has `From<u8>` and `From<AddressFamily> for u8`
53 /// implemented.
54 pub interface_family: AddressFamily,
55 /// Link index.
56 pub index: u32,
57 /// Link type. It should be set to one of the `ARPHRD_*`
58 /// constants. The most common value is [LinkLayerType::Ether] for
59 /// Ethernet.
60 /// The LinkLayerType has `From<u16>` and `From<LinkLayerType> for u16`
61 /// implemented.
62 pub link_layer_type: LinkLayerType,
63 /// State of the link, described by a combinations of `IFF_*`
64 /// constants.
65 pub flags: LinkFlags,
66 /// Change mask for the `flags` field.
67 pub change_mask: LinkFlags,
68}
69
70impl Emitable for LinkHeader {
71 fn buffer_len(&self) -> usize {
72 LINK_HEADER_LEN
73 }
74
75 fn emit(&self, buffer: &mut [u8]) {
76 let mut packet = LinkMessageBuffer::new(buffer);
77 packet.set_interface_family(u8::from(self.interface_family));
78 packet.set_link_index(self.index);
79 packet.set_change_mask(self.change_mask.bits());
80 packet.set_link_layer_type(u16::from(self.link_layer_type));
81 packet.set_flags(self.flags.bits());
82 }
83}
84
85impl<T: AsRef<[u8]>> Parseable<LinkMessageBuffer<T>> for LinkHeader {
86 fn parse(buf: &LinkMessageBuffer<T>) -> Result<Self, DecodeError> {
87 Ok(Self {
88 interface_family: buf.interface_family().into(),
89 link_layer_type: buf.link_layer_type().into(),
90 index: buf.link_index(),
91 change_mask: LinkFlags::from_bits_retain(buf.change_mask()),
92 flags: LinkFlags::from_bits_retain(buf.flags()),
93 })
94 }
95}