rsmnl_linux/
netlink.rs

1use std::mem;
2
3extern crate errno;
4extern crate libc;
5
6use errno::Errno;
7use libc::{c_int, c_uint};
8
9use mnl::{Attr, AttrTbl, MsgVec, Result};
10
11#[repr(C)]
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub enum Family {
14    Route = 0,    // Routing/device hook
15    Unused = 1,   // Unused number
16    Usersock = 2, // Reserved for user mode socket protocols
17    Firewall = 3, // Unused number, formerly ip_queue
18    SockDiag = 4, // socket monitoring
19    Nflog = 5,    // netfilter/iptables ULOG
20    Xfrm = 6,     // ipsec
21    Selinux = 7,  // SELinux event notifications
22    Iscsi = 8,    // Open-iSCSI
23    Audit = 9,    // auditing
24    FibLookup = 10,
25    Connector = 11,
26    Netfilter = 12, // netfilter subsystem
27    Ip6Fw = 13,
28    Dnrtmsg = 14,       // DECnet routing messages
29    KobjectUevent = 15, // Kernel messages to userspace
30    Generic = 16,
31
32    Scsitransport = 18, // SCSI Transports
33    Ecryptfs = 19,
34    Rdma = 20,
35    Crypto = 21, // Crypto layer
36    Smc = 22,    // SMC monitoring
37
38    InetDiag, // #define NETLINK_INET_DIAG NETLINK_SOCK_DIAG
39}
40
41impl Into<c_int> for Family {
42    fn into(self) -> c_int {
43        if self == Family::InetDiag {
44            return Family::SockDiag as c_int;
45        }
46        self as c_int
47    }
48}
49
50pub const MAX_LINKS: c_int = 32;
51
52// refer libc - pub type sa_family_t = u16;
53#[repr(C)]
54#[derive(Debug, Clone, Copy)]
55pub struct SockaddrNl {
56    pub nl_family: u16,
57    nl_pad: u16,
58    pub nl_pid: u32,
59    pub nl_groups: u32,
60}
61
62impl Default for SockaddrNl {
63    fn default() -> SockaddrNl {
64        SockaddrNl {
65            nl_family: libc::AF_NETLINK as u16,
66            nl_pad: 0,
67            nl_pid: 0,
68            nl_groups: 0,
69        }
70    }
71}
72
73#[repr(C)]
74#[derive(Debug, Clone, Copy)]
75pub struct Nlmsghdr {
76    pub nlmsg_len: u32,
77    pub nlmsg_type: u16,
78    pub nlmsg_flags: u16,
79    pub nlmsg_seq: u32,
80    pub nlmsg_pid: u32,
81}
82
83// Flags values
84pub const NLM_F_REQUEST: u16 = 0x01; // It is request message.
85pub const NLM_F_MULTI: u16 = 0x02; // Multipart message, terminated by NLMSG_DONE
86pub const NLM_F_ACK: u16 = 0x04; // Reply with ack, with zero or error code
87pub const NLM_F_ECHO: u16 = 0x08; // Echo this request
88pub const NLM_F_DUMP_INTR: u16 = 0x10; // Dump was inconsistent due to sequence change
89pub const NLM_F_DUMP_FILTERED: u16 = 0x20; // Dump was filtered as requested
90
91// Modifiers to GET request
92pub const NLM_F_ROOT: u16 = 0x100; // specify tree	root
93pub const NLM_F_MATCH: u16 = 0x200; // return all matching
94pub const NLM_F_ATOMIC: u16 = 0x400; // atomic GET
95pub const NLM_F_DUMP: u16 = NLM_F_ROOT | NLM_F_MATCH;
96
97// Modifiers to NEW request
98pub const NLM_F_REPLACE: u16 = 0x100; // Override existing
99pub const NLM_F_EXCL: u16 = 0x200; // Do not touch, if it exists
100pub const NLM_F_CREATE: u16 = 0x400; // Create, if it does not exist
101pub const NLM_F_APPEND: u16 = 0x800; // Add to end of list
102
103// Modifiers to DELETE request
104pub const NLM_F_NONREC: u16 = 0x100; // Do not delete recursively
105
106// Flags for ACK message
107pub const NLM_F_CAPPED: u16 = 0x100; // request was capped
108pub const NLM_F_ACK_TLVS: u16 = 0x200; // extended ACK TVLs were included
109
110// 4.4BSD ADD		NLM_F_CREATE|NLM_F_EXCL
111// 4.4BSD CHANGE	NLM_F_REPLACE
112//
113// True CHANGE		NLM_F_CREATE|NLM_F_REPLACE
114// Append		NLM_F_CREATE
115// Check		NLM_F_EXCL
116
117pub const NLMSG_ALIGNTO: u32 = 4;
118pub const fn nlmsg_align(len: u32) -> u32 {
119    (len + NLMSG_ALIGNTO - 1) & !(NLMSG_ALIGNTO - 1)
120}
121pub const NLMSG_HDRLEN: u32 = nlmsg_align(mem::size_of::<Nlmsghdr>() as u32);
122pub const fn nlmsg_length(len: u32) -> u32 {
123    len + NLMSG_HDRLEN
124}
125pub const fn nlmsg_space(len: u32) -> u32 {
126    nlmsg_align(nlmsg_length(len))
127}
128pub unsafe fn nlmsg_data<T>(nlh: &mut Nlmsghdr) -> &mut T {
129    &mut *((nlh as *mut _ as *mut u8).offset(nlmsg_length(0) as isize) as *mut T)
130}
131pub unsafe fn nlmsg_next<'a>(nlh: &'a mut Nlmsghdr, len: &mut u32) -> &'a mut Nlmsghdr {
132    *len -= nlmsg_align(nlh.nlmsg_len);
133    &mut *((nlh as *mut _ as *mut u8).offset(nlmsg_align(nlh.nlmsg_len) as isize) as *mut Nlmsghdr)
134}
135pub fn nlmsg_ok(nlh: &Nlmsghdr, len: u32) -> bool {
136    len >= mem::size_of::<Nlmsghdr>() as u32
137        && nlh.nlmsg_len >= mem::size_of::<Nlmsghdr>() as u32
138        && nlh.nlmsg_len <= len
139}
140pub const fn nlmsg_payload(nlh: &Nlmsghdr, len: u32) -> u32 {
141    nlh.nlmsg_len - nlmsg_space(len)
142}
143
144#[derive(PartialEq, Eq, Hash)]
145pub enum MsgType {
146    Noop,    // 0x1: Nothing.
147    Error,   // 0x2: Error
148    Done,    // 0x3: End of a dump
149    Overrun, // 0x4: Data lost
150    Other(u16),
151}
152pub const NLMSG_MIN_TYPE: u16 = 0x10; // < 0x10: reserved control messages
153
154#[allow(clippy::from_over_into)]
155impl Into<u16> for MsgType {
156    fn into(self) -> u16 {
157        match self {
158            Self::Noop => 0x1,
159            Self::Error => 0x2,
160            Self::Done => 0x3,
161            Self::Overrun => 0x4,
162            Self::Other(v) => v,
163        }
164    }
165}
166
167impl std::convert::TryFrom<u16> for MsgType {
168    type Error = Errno;
169
170    fn try_from(v: u16) -> std::result::Result<Self, Errno> {
171        match v {
172            0x1 => Ok(Self::Noop),
173            0x2 => Ok(Self::Error),
174            0x3 => Ok(Self::Done),
175            0x4 => Ok(Self::Overrun),
176            n if n < NLMSG_MIN_TYPE => Err(Errno(libc::ERANGE)),
177            _ => Ok(Self::Other(v)),
178        }
179    }
180}
181
182#[repr(C)]
183#[derive(Debug, Clone, Copy)]
184pub struct Nlmsgerr {
185    // pub struct Nlmsgerr <'a> {
186    pub error: c_int,
187    pub msg: Nlmsghdr, // pub msg: Nlmsghdr<'a>,
188                       //followed by the message contents unless NETLINK_CAP_ACK was set
189                       //or the ACK indicates success (error == 0)
190                       // message length is aligned with NLMSG_ALIGN()
191
192                       // followed by TLVs defined in enum nlmsgerr_attrs
193                       // if NETLINK_EXT_ACK was set
194}
195
196// enum nlmsgerr_attrs - nlmsgerr attributes
197// @NLMSGERR_ATTR_UNUSED: unused
198// @NLMSGERR_ATTR_MSG: error message string (string)
199// @NLMSGERR_ATTR_OFFS: offset of the invalid attribute in the original
200//      message, counting from the beginning of the header (u32)
201// @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to
202//     be used - in the success case - to identify a created
203//     object or operation or similar (binary)
204// @__NLMSGERR_ATTR_MAX: number of attributes
205// @NLMSGERR_ATTR_MAX: highest attribute number
206#[repr(u16)]
207#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
208pub enum NlmsgerrAttrs {
209    Unused = 0,
210    Msg = 1,
211    Offs = 2,
212    Cookie = 3,
213    _MAX = 4,
214}
215
216pub const NETLINK_ADD_MEMBERSHIP: c_int = 1;
217pub const NETLINK_DROP_MEMBERSHIP: c_int = 2;
218pub const NETLINK_PKTINFO: c_int = 3;
219pub const NETLINK_BROADCAST_ERROR: c_int = 4;
220pub const NETLINK_NO_ENOBUFS: c_int = 5;
221// pub const NETLINK_RX_RING: c_int		= 6;
222// pub const NETLINK_TX_RING: c_int		= 7;
223pub const NETLINK_LISTEN_ALL_NSID: c_int = 8;
224pub const NETLINK_LIST_MEMBERSHIPS: c_int = 9;
225pub const NETLINK_CAP_ACK: c_int = 10;
226pub const NETLINK_EXT_ACK: c_int = 11;
227
228#[repr(C)]
229#[derive(Debug, Clone, Copy)]
230pub struct NlPktinfo {
231    group: u32,
232}
233
234pub const NET_MAJOR: c_uint = 36; // Major 36 is reserved for networking
235
236// struct sock_common.skc_state;
237pub const NETLINK_UNCONNECTED: u8 = 0;
238pub const NETLINK_CONNECTED: u8 = 1;
239
240//  <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
241// +---------------------+- - -+- - - - - - - - - -+- - -+
242// |        Header       | Pad |     Payload       | Pad |
243// |   (struct nlattr)   | ing |                   | ing |
244// +---------------------+- - -+- - - - - - - - - -+- - -+
245//  <-------------- nlattr->nla_len -------------->
246#[repr(C)]
247#[derive(Debug, Clone, Copy)]
248pub struct Nlattr {
249    pub nla_len: u16,
250    pub nla_type: u16,
251}
252
253// nla_type (16 bits)
254// +---+---+-------------------------------+
255// | N | O | Attribute Type                |
256// +---+---+-------------------------------+
257// N := Carries nested attributes
258// O := Payload stored in network byte order
259//
260// Note: The N and O flag are mutually exclusive.
261pub const NLA_F_NESTED: u16 = 1 << 15;
262pub const NLA_F_NET_BYTEORDER: u16 = 1 << 14;
263pub const NLA_TYPE_MASK: u16 = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER);
264
265pub const NLA_ALIGNTO: u16 = 4;
266
267pub const fn nla_align(len: u16) -> u16 {
268    (len + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1)
269}
270
271pub const NLA_HDRLEN: u16 = nla_align(mem::size_of::<Nlattr>() as u16);
272
273// Generic 32 bitflags attribute content sent to the kernel.
274//
275// The value is a bitmap that defines the values being set
276// The selector is a bitmask that defines which value is legit
277//
278// Examples:
279//  value = 0x0, and selector = 0x1
280//  implies we are selecting bit 1 and we want to set its value to 0.
281//
282//  value = 0x2, and selector = 0x2
283//  implies we are selecting bit 2 and we want to set its value to 1.
284#[repr(C)]
285#[derive(Debug, Clone, Copy)]
286pub struct NlaBitfield32 {
287    // struct nla_bitfield32
288    pub value: u32,
289    pub selector: u32,
290}
291
292// policy descriptions - it's specific to each family how this is used
293// Normally, it should be retrieved via a dump inside another attribute
294// specifying where it applies.
295
296// enum netlink_attribute_type - type of an attribute
297// @NL_ATTR_TYPE_INVALID: unused
298// @NL_ATTR_TYPE_FLAG: flag attribute (present/not present)
299// @NL_ATTR_TYPE_U8: 8-bit unsigned attribute
300// @NL_ATTR_TYPE_U16: 16-bit unsigned attribute
301// @NL_ATTR_TYPE_U32: 32-bit unsigned attribute
302// @NL_ATTR_TYPE_U64: 64-bit unsigned attribute
303// @NL_ATTR_TYPE_S8: 8-bit signed attribute
304// @NL_ATTR_TYPE_S16: 16-bit signed attribute
305// @NL_ATTR_TYPE_S32: 32-bit signed attribute
306// @NL_ATTR_TYPE_S64: 64-bit signed attribute
307// @NL_ATTR_TYPE_BINARY: binary data, min/max length may be specified
308// @NL_ATTR_TYPE_STRING: string, min/max length may be specified
309// @NL_ATTR_TYPE_NUL_STRING: NUL-terminated string,
310//      min/max length may be specified
311// @NL_ATTR_TYPE_NESTED: nested, i.e. the content of this attribute
312//      consists of sub-attributes. The nested policy and maxtype
313//      inside may be specified.
314// @NL_ATTR_TYPE_NESTED_ARRAY: nested array, i.e. the content of this
315//      attribute contains sub-attributes whose type is irrelevant
316//      (just used to separate the array entries) and each such array
317//      entry has attributes again, the policy for those inner ones
318//      and the corresponding maxtype may be specified.
319// @NL_ATTR_TYPE_BITFIELD32: &struct nla_bitfield32 attribute
320#[repr(u32)]
321#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
322pub enum NetlinkAttrType {
323    // NL_ATTR_TYPE_
324    Invalid,
325    Flag,
326    U8,
327    U16,
328    U32,
329    U64,
330    S8,
331    S16,
332    S32,
333    S64,
334    Binary,
335    String,
336    NulString,
337    Nested,
338    NestedArray,
339    Bitfield32,
340}
341pub const NL_ATTR_TYPE_INVALID: u32 = NetlinkAttrType::Invalid as u32;
342pub const NL_ATTR_TYPE_FLAG: u32 = NetlinkAttrType::Flag as u32;
343pub const NL_ATTR_TYPE_U8: u32 = NetlinkAttrType::U8 as u32;
344pub const NL_ATTR_TYPE_U16: u32 = NetlinkAttrType::U16 as u32;
345pub const NL_ATTR_TYPE_U32: u32 = NetlinkAttrType::U32 as u32;
346pub const NL_ATTR_TYPE_U64: u32 = NetlinkAttrType::U64 as u32;
347pub const NL_ATTR_TYPE_S8: u32 = NetlinkAttrType::S8 as u32;
348pub const NL_ATTR_TYPE_S16: u32 = NetlinkAttrType::S16 as u32;
349pub const NL_ATTR_TYPE_S32: u32 = NetlinkAttrType::S32 as u32;
350pub const NL_ATTR_TYPE_S64: u32 = NetlinkAttrType::S64 as u32;
351pub const NL_ATTR_TYPE_BINARY: u32 = NetlinkAttrType::Binary as u32;
352pub const NL_ATTR_TYPE_STRING: u32 = NetlinkAttrType::String as u32;
353pub const NL_ATTR_TYPE_NUL_STRING: u32 = NetlinkAttrType::NulString as u32;
354pub const NL_ATTR_TYPE_NESTED: u32 = NetlinkAttrType::Nested as u32;
355pub const NL_ATTR_TYPE_NESTED_ARRAY: u32 = NetlinkAttrType::NestedArray as u32;
356pub const NL_ATTR_TYPE_BITFIELD32: u32 = NetlinkAttrType::Bitfield32 as u32;
357
358// enum netlink_policy_type_attr - policy type attributes
359// @NL_POLICY_TYPE_ATTR_UNSPEC: unused
360// @NL_POLICY_TYPE_ATTR_TYPE: type of the attribute,
361//      &enum netlink_attribute_type (U32)
362// @NL_POLICY_TYPE_ATTR_MIN_VALUE_S: minimum value for signed
363//      integers (S64)
364// @NL_POLICY_TYPE_ATTR_MAX_VALUE_S: maximum value for signed
365//      integers (S64)
366// @NL_POLICY_TYPE_ATTR_MIN_VALUE_U: minimum value for unsigned
367//      integers (U64)
368// @NL_POLICY_TYPE_ATTR_MAX_VALUE_U: maximum value for unsigned
369//      integers (U64)
370// @NL_POLICY_TYPE_ATTR_MIN_LENGTH: minimum length for binary
371//      attributes, no minimum if not given (U32)
372// @NL_POLICY_TYPE_ATTR_MAX_LENGTH: maximum length for binary
373//      attributes, no maximum if not given (U32)
374// @NL_POLICY_TYPE_ATTR_POLICY_IDX: sub policy for nested and
375//      nested array types (U32)
376// @NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE: maximum sub policy
377//      attribute for nested and nested array types, this can
378//      in theory be < the size of the policy pointed to by
379//      the index, if limited inside the nesting (U32)
380// @NL_POLICY_TYPE_ATTR_BITFIELD32_MASK: valid mask for the
381//      bitfield32 type (U32)
382// @NL_POLICY_TYPE_ATTR_PAD: pad attribute for 64-bit alignment
383#[repr(u16)]
384#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, NlaType)]
385#[tbname = "NetlinkPolicyTypeAttrTbl"]
386pub enum NetlinkPolicyTypeAttr {
387    // NL_POLICY_TYPE_ATTR_
388    Unspec,
389
390    #[nla_type(u32, atype)]
391    Type,
392
393    #[nla_type(i64, min_value_s)]
394    MinValueS,
395
396    #[nla_type(i64, max_value_s)]
397    MaxValueS,
398
399    #[nla_type(u64, min_value_u)]
400    MinValueU,
401
402    #[nla_type(u64, max_value_u)]
403    MaxValueU,
404
405    #[nla_type(u32, min_length)]
406    MinLength,
407
408    #[nla_type(u32, max_length)]
409    MaxLength,
410
411    #[nla_type(u32, policy_idx)]
412    PolicyIdx,
413
414    #[nla_type(u32, policy_max_type)]
415    PolicyMaxtype,
416
417    #[nla_type(u32, bitfield32_mask)]
418    Bitfield32Mask,
419
420    Pad,
421
422    // keep last
423    _MAX,
424}