netlink_rust/
route.rs

1//! Netlink route messages
2
3use libc;
4
5use crate::core::{
6    pack_vec, Attribute, ConvertFrom, MessageFlags, NativePack, NativeUnpack, SendMessage,
7};
8use crate::errors::{NetlinkError, NetlinkErrorKind, Result};
9
10extended_enum!(
11    /// Netlinkt route command
12    FamilyId, u16,
13    /// Link added
14    NewLink => 16,
15    /// Link removed
16    DeleteLink => 17,
17    /// Get link
18    GetLink => 18,
19    /// Set link
20    SetLink => 19,
21);
22
23extended_enum_default!(AddressFamilyAttribute, u16,
24    Unspecified => 0,
25    Address => 1,
26    Broadcast => 2,
27    InterfaceName => 3,
28    MTU => 4,
29    Link => 5,
30    QDisc => 6,
31    Stats => 7,
32    Cost => 8,
33    Priority => 9,
34    Master => 10,
35    WirelessExtension => 11,
36    ProtocolInformation => 12,
37    TransmitQueueLength => 13,
38    Map => 14,
39    Weight => 15,
40    OperationState => 16,
41    LinkMode => 17,
42    LinkInfo => 18,
43    NetworkNameSpacePid => 19,
44    InterfaceAlias => 20,
45    NumberVf => 21,
46    VfInfoList => 22,
47    Stats64 => 23,
48    VfPorts => 24,
49    PortSelf => 25,
50    AfSpecification => 26,
51    Group => 27,
52    NetworkNameSpaceFileDescriptor => 28,
53    ExtendedMask => 29,
54    PromiscuityCount => 30,
55    TransmitQueueCount => 31,
56    ReceiveQueueCount => 32,
57    Carrier => 33,
58    PhysPortId => 34,
59    CarrierChanges => 35,
60    PhysSwitchId => 36,
61    LinkNetworkNameSpaceId => 37,
62    PhysPortName => 38,
63    ProtocolDown => 39,
64    GsoMaximumSegs => 40,
65    GsoMaximumSize => 41,
66    Padding => 42,
67    Xdp => 43,
68    Event => 44,
69    NewNetworkNameSpaceId => 45,
70    InterfaceNetworkNameSpaceId => 46,
71);
72
73/// Netlink message for route messages
74pub struct Message {
75    /// The family
76    pub family: u16,
77    /// Message attributes
78    pub attributes: Vec<Attribute>,
79}
80
81impl Message {
82    /// Create a new message with the provided family
83    pub fn new<F: Into<u16>>(family: F) -> Message {
84        return Message {
85            family: family.into(),
86            attributes: vec![],
87        };
88    }
89}
90
91impl SendMessage for Message {
92    fn pack(&self, data: &mut [u8]) -> Result<usize> {
93        let kind: u8 = libc::AF_PACKET as u8;
94        let slice = kind.pack(data)?;
95        let size = pack_vec(slice, &self.attributes)?;
96        Ok(size + 1)
97    }
98    fn message_type(&self) -> u16 {
99        self.family
100    }
101    fn query_flags(&self) -> MessageFlags {
102        MessageFlags::REQUEST | MessageFlags::DUMP
103    }
104}
105
106/// Interface information message
107///
108/// Used to get information aabout a network interface
109pub struct InterfaceInformationMessage {
110    /// Message family
111    pub family: u8,
112    /// Message type
113    pub kind: u16,
114    /// Message index
115    pub index: i32,
116    /// Message flags
117    pub flags: u32,
118    /// Message change
119    pub change: u32,
120    /// Message attributes
121    pub attributes: Vec<Attribute>,
122}
123
124impl InterfaceInformationMessage {
125    /// Unpack byte slice into InterfaceInformationMessage
126    pub fn unpack(data: &[u8]) -> Result<(usize, InterfaceInformationMessage)> {
127        if data.len() < 16 {
128            return Err(NetlinkError::new(NetlinkErrorKind::NotEnoughData).into());
129        }
130        let family = u8::unpack_unchecked(&data[0..]);
131        // reserved u8
132        let kind = u16::unpack_unchecked(&data[2..]);
133        let index = i32::unpack_unchecked(&data[4..]);
134        let flags = u32::unpack_unchecked(&data[8..]);
135        let change = u32::unpack_unchecked(&data[12..]);
136        let (used, attributes) = Attribute::unpack_all(&data[16..]);
137        Ok((
138            used + 16,
139            InterfaceInformationMessage {
140                family: family,
141                kind: kind,
142                index: index,
143                flags: flags,
144                change: change,
145                attributes: attributes,
146            },
147        ))
148    }
149}
150
151#[cfg(test)]
152mod tests {
153    use super::*;
154    use crate::core::{Protocol, Socket};
155
156    #[test]
157    fn route_get_link() {
158        let mut socket = Socket::new(Protocol::Route).unwrap();
159        let msg = Message::new(FamilyId::GetLink);
160        socket.send_message(&msg).unwrap();
161        for m in socket.receive_messages().unwrap() {
162            assert_eq!(m.header.identifier, FamilyId::NewLink);
163        }
164    }
165}