rsmnl_linux/
rtnetlink.rs

1use errno::Errno;
2use libc::{c_int, c_uchar, c_uint, c_ushort, sa_family_t};
3use std::{
4    mem,
5    net::{Ipv4Addr, Ipv6Addr},
6};
7
8use mnl::{Attr, AttrTbl, MsgVec, Result};
9use netlink::{self, Nlmsghdr};
10
11// rtnetlink families. Values up to 127 are reserved for real address
12// families, values above 128 may be used arbitrarily.
13pub const RTNL_FAMILY_IPMR: u8 = 128;
14pub const RTNL_FAMILY_IP6MR: u8 = 129;
15pub const RTNL_FAMILY_MAX: u8 = 129;
16
17// Routing/neighbour discovery messages.
18#[repr(u16)]
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20pub enum Rtm {
21    // BASE		= 16,
22    Newlink = 16,
23    Dellink = 17,
24    Getlink = 18,
25    Tbllink = 19,
26    Newaddr = 20,
27    Deladdr = 21,
28    Getaddr = 22,
29    Newroute = 24,
30    Delroute = 25,
31    Getroute = 26,
32    Newneigh = 28,
33    Delneigh = 29,
34    Getneigh = 30,
35    Newrule = 32,
36    Delrule = 33,
37    Getrule = 34,
38    Newqdisc = 36,
39    Delqdisc = 37,
40    Getqdisc = 38,
41    Newtclass = 40,
42    Deltclass = 41,
43    Gettclass = 42,
44    Newtfilter = 44,
45    Deltfilter = 45,
46    Gettfilter = 46,
47    Newaction = 48,
48    Delaction = 49,
49    Getaction = 50,
50    Newprefix = 52,
51    Getmulticast = 58,
52    Getanycast = 62,
53    Newneightbl = 64,
54    Getneightbl = 66,
55    Tblneightbl = 67,
56    Newnduseropt = 68,
57    Newaddrlabel = 72,
58    Deladdrlabel = 73,
59    Getaddrlabel = 74,
60    Getdcb = 78,
61    Tbldcb = 79,
62    Newnetconf = 80,
63    Delnetconf = 81,
64    Getnetconf = 82,
65    Newmdb = 84,
66    Delmdb = 85,
67    Getmdb = 86,
68    Newnsid = 88,
69    Delnsid = 89,
70    Getnsid = 90,
71    Newstats = 92,
72    Getstats = 94,
73    Newcachereport = 96,
74    Newchain = 100,
75    Delchain = 101,
76    Getchain = 102,
77    Newnexthop = 104,
78    Delnexthop = 105,
79    Getnexthop = 106,
80    Newlinkprop = 108,
81    Dellinkprop = 109,
82    Getlinkprop = 110,
83    Newvlan = 112,
84    Delvlan = 113,
85    Getvlan = 114,
86    _MAX,
87}
88pub const RTM_BASE: u16 = Rtm::Newlink as u16; // XXX
89pub const RTM_NEWLINK: u16 = Rtm::Newlink as u16;
90pub const RTM_DELLINK: u16 = Rtm::Dellink as u16;
91pub const RTM_GETLINK: u16 = Rtm::Getlink as u16;
92pub const RTM_SETLINK: u16 = Rtm::Tbllink as u16;
93pub const RTM_NEWADDR: u16 = Rtm::Newaddr as u16;
94pub const RTM_DELADDR: u16 = Rtm::Deladdr as u16;
95pub const RTM_GETADDR: u16 = Rtm::Getaddr as u16;
96pub const RTM_NEWROUTE: u16 = Rtm::Newroute as u16;
97pub const RTM_DELROUTE: u16 = Rtm::Delroute as u16;
98pub const RTM_GETROUTE: u16 = Rtm::Getroute as u16;
99pub const RTM_NEWNEIGH: u16 = Rtm::Newneigh as u16;
100pub const RTM_DELNEIGH: u16 = Rtm::Delneigh as u16;
101pub const RTM_GETNEIGH: u16 = Rtm::Getneigh as u16;
102pub const RTM_NEWRULE: u16 = Rtm::Newrule as u16;
103pub const RTM_DELRULE: u16 = Rtm::Delrule as u16;
104pub const RTM_GETRULE: u16 = Rtm::Getrule as u16;
105pub const RTM_NEWQDISC: u16 = Rtm::Newqdisc as u16;
106pub const RTM_DELQDISC: u16 = Rtm::Delqdisc as u16;
107pub const RTM_GETQDISC: u16 = Rtm::Getqdisc as u16;
108pub const RTM_NEWTCLASS: u16 = Rtm::Newtclass as u16;
109pub const RTM_DELTCLASS: u16 = Rtm::Deltclass as u16;
110pub const RTM_GETTCLASS: u16 = Rtm::Gettclass as u16;
111pub const RTM_NEWTFILTER: u16 = Rtm::Newtfilter as u16;
112pub const RTM_DELTFILTER: u16 = Rtm::Deltfilter as u16;
113pub const RTM_GETTFILTER: u16 = Rtm::Gettfilter as u16;
114pub const RTM_NEWACTION: u16 = Rtm::Newaction as u16;
115pub const RTM_DELACTION: u16 = Rtm::Delaction as u16;
116pub const RTM_GETACTION: u16 = Rtm::Getaction as u16;
117pub const RTM_NEWPREFIX: u16 = Rtm::Newprefix as u16;
118pub const RTM_GETMULTICAST: u16 = Rtm::Getmulticast as u16;
119pub const RTM_GETANYCAST: u16 = Rtm::Getanycast as u16;
120pub const RTM_NEWNEIGHTBL: u16 = Rtm::Newneightbl as u16;
121pub const RTM_GETNEIGHTBL: u16 = Rtm::Getneightbl as u16;
122pub const RTM_SETNEIGHTBL: u16 = Rtm::Tblneightbl as u16;
123pub const RTM_NEWNDUSEROPT: u16 = Rtm::Newnduseropt as u16;
124pub const RTM_NEWADDRLABEL: u16 = Rtm::Newaddrlabel as u16;
125pub const RTM_DELADDRLABEL: u16 = Rtm::Deladdrlabel as u16;
126pub const RTM_GETADDRLABEL: u16 = Rtm::Getaddrlabel as u16;
127pub const RTM_GETDCB: u16 = Rtm::Getdcb as u16;
128pub const RTM_SETDCB: u16 = Rtm::Tbldcb as u16;
129pub const RTM_NEWNETCONF: u16 = Rtm::Newnetconf as u16;
130pub const RTM_DELNETCONF: u16 = Rtm::Delnetconf as u16;
131pub const RTM_GETNETCONF: u16 = Rtm::Getnetconf as u16;
132pub const RTM_NEWMDB: u16 = Rtm::Newmdb as u16;
133pub const RTM_DELMDB: u16 = Rtm::Delmdb as u16;
134pub const RTM_GETMDB: u16 = Rtm::Getmdb as u16;
135pub const RTM_NEWNSID: u16 = Rtm::Newnsid as u16;
136pub const RTM_DELNSID: u16 = Rtm::Delnsid as u16;
137pub const RTM_GETNSID: u16 = Rtm::Getnsid as u16;
138pub const RTM_NEWSTATS: u16 = Rtm::Newstats as u16;
139pub const RTM_GETSTATS: u16 = Rtm::Getstats as u16;
140pub const RTM_NEWCACHEREPORT: u16 = Rtm::Newcachereport as u16;
141pub const RTM_NEWCHAIN: u16 = Rtm::Newchain as u16;
142pub const RTM_DELCHAIN: u16 = Rtm::Delchain as u16;
143pub const RTM_GETCHAIN: u16 = Rtm::Getchain as u16;
144pub const RTM_NEWNEXTHOP: u16 = Rtm::Newnexthop as u16;
145pub const RTM_DELNEXTHOP: u16 = Rtm::Delnexthop as u16;
146pub const RTM_GETNEXTHOP: u16 = Rtm::Getnexthop as u16;
147pub const RTM_NEWLINKPROP: u16 = Rtm::Newlinkprop as u16;
148pub const RTM_DELLINKPROP: u16 = Rtm::Dellinkprop as u16;
149pub const RTM_GETLINKPROP: u16 = Rtm::Getlinkprop as u16;
150pub const RTM_NEWNVLAN: u16 = Rtm::Newvlan as u16;
151pub const RTM_DELVLAN: u16 = Rtm::Delvlan as u16;
152pub const RTM_GETVLAN: u16 = Rtm::Getvlan as u16;
153pub const __RTM_MAX: u16 = Rtm::_MAX as u16;
154pub const RTM_MAX: u16 = ((__RTM_MAX as u16 + 3) & !3) - 1;
155
156pub const RTM_NR_MSGTYPES: u16 = RTM_MAX + 1 - RTM_BASE;
157pub const RTM_NR_FAMILIES: u16 = RTM_NR_MSGTYPES >> 2;
158pub const fn rtm_fam(cmd: u16) -> u16 {
159    (cmd - RTM_BASE) >> 2
160}
161
162// Generic structure for encapsulation of optional route information.
163// It is reminiscent of sockaddr, but with sa_family replaced
164// with attribute type.
165#[repr(C)]
166#[derive(Debug, Clone, Copy)]
167pub struct Rtattr {
168    pub rta_len: c_ushort,
169    pub rta_type: c_ushort,
170}
171
172// Macros to handle rtattributes
173pub const RTA_ALIGNTO: u16 = 4;
174pub const fn rta_align(len: u16) -> u16 {
175    (len + RTA_ALIGNTO - 1) & !(RTA_ALIGNTO - 1)
176}
177pub const fn rta_ok(rta: &Rtattr, len: u16) -> bool {
178    len >= mem::size_of::<Rtattr>() as u16
179        && rta.rta_len >= mem::size_of::<Rtattr>() as c_ushort
180        && rta.rta_len <= len
181}
182pub unsafe fn rta_next<'a>(rta: &'a mut Rtattr, attrlen: &mut u16) -> &'a mut Rtattr {
183    *attrlen -= rta_align(rta.rta_len);
184    &mut *((rta as *mut _ as *mut u8).offset(rta.rta_len as isize) as *mut Rtattr)
185}
186pub const fn rta_length(len: u16) -> u16 {
187    rta_align(mem::size_of::<Rtattr>() as u16 + len)
188}
189pub const fn rta_space(len: u16) -> u16 {
190    rta_align(rta_length(len))
191}
192pub unsafe fn rta_data<T>(rta: &mut Rtattr) -> &mut T {
193    &mut *((rta as *mut _ as *mut u8).offset(rta_length(0) as isize) as *mut T)
194}
195pub const fn rta_payload(rta: &Rtattr) -> u16 {
196    rta.rta_len - rta_length(0)
197}
198
199// Definitions used in routing table administration.
200#[repr(C)]
201#[derive(Debug, Clone, Copy)]
202pub struct Rtmsg {
203    pub rtm_family: c_uchar,
204    pub rtm_dst_len: c_uchar,
205    pub rtm_src_len: c_uchar,
206    pub rtm_tos: c_uchar,
207    pub rtm_table: c_uchar,    // Routing table id
208    pub rtm_protocol: c_uchar, // Routing protocol; see below
209    pub rtm_scope: c_uchar,    // See below			::std::os::raw::c_uchar,
210    pub rtm_type: c_uchar,     // See below			::std::os::raw::c_uchar,
211    pub rtm_flags: c_uint,
212}
213
214// rtm_type
215#[repr(u8)]
216#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
217pub enum Rtn {
218    Unspec = 0,
219    Unicast,   // Gateway or direct route
220    Local,     // Accept locally
221    Broadcast, // Accept locally as broadcast,
222    // send as broadcast
223    Anycast, // Accept locally as broadcast,
224    // but send as unicast
225    Multicast,   // Multicast route
226    Blackhole,   // Drop
227    Unreachable, // Destination is unreachable
228    Prohibit,    // Administratively prohibited
229    Throw,       // Not in this table
230    Nat,         // Translate this address
231    Xresolve,    // Use external resolver
232    _MAX,
233}
234pub const RTN_UNSPEC: u8 = Rtn::Unspec as u8;
235pub const RTN_UNICAST: u8 = Rtn::Unicast as u8;
236pub const RTN_LOCAL: u8 = Rtn::Local as u8;
237pub const RTN_BROADCAST: u8 = Rtn::Broadcast as u8;
238pub const RTN_ANYCAST: u8 = Rtn::Anycast as u8;
239pub const RTN_MULTICAST: u8 = Rtn::Multicast as u8;
240pub const RTN_BLACKHOLE: u8 = Rtn::Blackhole as u8;
241pub const RTN_UNREACHABLE: u8 = Rtn::Unreachable as u8;
242pub const RTN_PROHIBIT: u8 = Rtn::Prohibit as u8;
243pub const RTN_THROW: u8 = Rtn::Throw as u8;
244pub const RTN_NAT: u8 = Rtn::Nat as u8;
245pub const RTN_XRESOLVE: u8 = Rtn::Xresolve as u8;
246pub const __RTN_MAX: u8 = Rtn::_MAX as u8;
247pub const RTN_MAX: u8 = __RTN_MAX - 1;
248
249// rtm_protocol
250pub const RTPROT_UNSPEC: u8 = 0;
251pub const RTPROT_REDIRECT: u8 = 1; // Route installed by ICMP redirects;
252                                   // not used by current IPv4
253pub const RTPROT_KERNEL: u8 = 2; // Route installed by kernel
254pub const RTPROT_BOOT: u8 = 3; // Route installed during boot
255pub const RTPROT_STATIC: u8 = 4; // Route installed by administrator
256
257// Values of protocol >= RTPROT_STATIC are not interpreted by kernel;
258// they are just passed from user and back as is.
259// It will be used by hypothetical multiple routing daemons.
260// Note that protocol values should be standardized in order to
261// avoid conflicts.
262
263pub const RTPROT_GATED: u8 = 8; // Apparently, GateD
264pub const RTPROT_RA: u8 = 9; // RDISC/ND router advertisements
265pub const RTPROT_MRT: u8 = 10; // Merit MRT
266pub const RTPROT_ZEBRA: u8 = 11; // Zebra
267pub const RTPROT_BIRD: u8 = 12; // BIRD
268pub const RTPROT_DNROUTED: u8 = 13; // DECnet routing daemon
269pub const RTPROT_XORP: u8 = 14; // XORP
270pub const RTPROT_NTK: u8 = 15; // Netsukuku
271pub const RTPROT_DHCP: u8 = 16; // DHCP client
272pub const RTPROT_MROUTED: u8 = 17; // Multicast daemon
273pub const RTPROT_BABEL: u8 = 42; // Babel daemon
274
275// rtm_scope
276//
277// Really it is not scope, but sort of distance to the destination.
278// NOWHERE are reserved for not existing destinations, HOST is our
279// local addresses, LINK are destinations, located on directly attached
280// link and UNIVERSE is everywhere in the Universe.
281//
282// Intermediate values are also possible f.e. interior routes
283// could be assigned a value between UNIVERSE and LINK.
284#[repr(u8)]
285#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
286pub enum RtScope {
287    Universe = 0,
288    // User defined values
289    Site = 200,
290    Link = 253,
291    Host = 254,
292    Nowhere = 255,
293}
294pub const RT_SCOPE_UNIVERSE: u8 = RtScope::Universe as u8;
295pub const RT_SCOPE_SITE: u8 = RtScope::Site as u8;
296pub const RT_SCOPE_LINK: u8 = RtScope::Link as u8;
297pub const RT_SCOPE_HOST: u8 = RtScope::Host as u8;
298pub const RT_SCOPE_NOWHERE: u8 = RtScope::Nowhere as u8;
299
300// rtm_flags
301pub const RTM_F_NOTIFY: u32 = 0x100; // Notify user of route change
302pub const RTM_F_CLONED: u32 = 0x200; // This route is cloned
303pub const RTM_F_EQUALIZE: u32 = 0x400; // Multipath equalizer: NI
304pub const RTM_F_PREFIX: u32 = 0x800; // Prefix addresses
305pub const RTM_F_LOOKUP_TABLE: u32 = 0x1000; // set rtm_table to FIB lookup result
306pub const RTM_F_FIB_MATCH: u32 = 0x2000; // return full fib lookup match
307
308#[repr(u32)]
309#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
310pub enum RtClass {
311    Unspec = 0,
312    // User defined values
313    Compat = 252,
314    Default = 253,
315    Main = 254,
316    Local = 255,
317    Max = 0xFFFFFFFF,
318}
319pub const RT_TABLE_UNSPEC: u32 = RtClass::Unspec as u32;
320pub const RT_TABLE_COMPAT: u32 = RtClass::Compat as u32;
321pub const RT_TABLE_DEFAULT: u32 = RtClass::Default as u32;
322pub const RT_TABLE_MAIN: u32 = RtClass::Main as u32;
323pub const RT_TABLE_LOCAL: u32 = RtClass::Local as u32;
324pub const RT_TABLE_MAX: u32 = RtClass::Max as u32;
325
326// Routing message attributes
327#[repr(u16)]
328#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, NlaType)]
329#[tbname = "RtattrTypeTbl"]
330pub enum RtattrType {
331    Unspec = 0,
332
333    #[nla_type(Ipv4Addr, v4dst)]
334    #[nla_type(Ipv6Addr, v6dst)]
335    Dst,
336
337    #[nla_type(Ipv4Addr, v4src)]
338    #[nla_type(Ipv6Addr, v6src)]
339    Src,
340
341    #[nla_type(u32, iif)]
342    Iif,
343
344    #[nla_type(u32, oif)]
345    Oif,
346
347    #[nla_type(Ipv4Addr, v4gateway)]
348    #[nla_type(Ipv6Addr, v6gateway)]
349    Gateway,
350
351    #[nla_type(u32, priority)]
352    Priority,
353
354    #[nla_type(Ipv4Addr, v4prefsrc)]
355    #[nla_type(Ipv6Addr, v6prefsrc)]
356    Prefsrc,
357
358    #[nla_nest(RtaxTbl, metrics)]
359    Metrics,
360
361    Multipath,
362    Protoinfo, // no longer used
363
364    #[nla_type(u32, flow)]
365    Flow,
366
367    Cacheinfo,
368    Session, // no longer used
369    MpAlgo,  // no longer used
370
371    #[nla_type(u32, table)]
372    Table,
373
374    Mark,
375    MfcStats,
376    Via,
377    Newdst,
378    Pref,
379    EncapType,
380    Encap,
381    Expires,
382    Pad,
383    Uid,
384    TtlPropagate,
385    IpProto,
386    Sport,
387    Dport,
388    NhId,
389    _MAX,
390}
391
392pub unsafe fn rtm_rta(r: &mut Rtmsg) -> &mut Rtattr {
393    &mut *((r as *mut _ as *mut u8)
394        .offset(netlink::nlmsg_align(mem::size_of::<Rtmsg>() as u32) as isize)
395        as *mut Rtattr)
396}
397pub const fn rtm_payload(n: &Nlmsghdr) -> u32 {
398    netlink::nlmsg_payload(n, mem::size_of::<Rtmsg>() as u32)
399}
400
401// RTM_MULTIPATH --- array of struct rtnexthop.
402//
403// "struct rtnexthop" describes all necessary nexthop information,
404// i.e. parameters of path to a destination via this nexthop.
405//
406// At the moment it is impossible to set different prefsrc, mtu, window
407// and rtt for different paths from multipath.
408#[repr(C)]
409#[derive(Debug, Clone, Copy)]
410pub struct Rtnexthop {
411    pub rtnh_len: c_ushort,
412    pub rtnh_flags: c_uchar,
413    pub rtnh_hops: c_uchar,
414    pub rtnh_ifindex: c_int,
415}
416
417// rtnh_flags
418pub const RTNH_F_DEAD: u8 = 1; // Nexthop is dead (used by multipath)
419pub const RTNH_F_PERVASIVE: u8 = 2; // Do recursive gateway lookup
420pub const RTNH_F_ONLINK: u8 = 4; // Gateway is forced on link
421pub const RTNH_F_OFFLOAD: u8 = 8; // offloaded route
422pub const RTNH_F_LINKDOWN: u8 = 16; // carrier-down on nexthop
423pub const RTNH_F_UNRESOLVED: u8 = 32; // The entry is unresolved (ipmr)
424
425pub const RTNH_COMPARE_MASK: u8 = RTNH_F_DEAD | RTNH_F_LINKDOWN | RTNH_F_OFFLOAD;
426
427// Macros to handle hexthops
428pub const RTNH_ALIGNTO: u16 = 4;
429pub const fn rtnh_align(len: u16) -> u16 {
430    (len + RTNH_ALIGNTO - 1) & !(RTNH_ALIGNTO - 1)
431}
432pub const fn rtnh_ok(rtnh: &Rtnexthop, len: u16) -> bool {
433    rtnh.rtnh_len >= mem::size_of::<Rtnexthop>() as u16 && rtnh.rtnh_len <= len
434}
435pub unsafe fn rtnh_next(rtnh: &mut Rtnexthop) -> &mut Rtnexthop {
436    &mut *((rtnh as *mut _ as *mut u8).offset(rtnh_align(rtnh.rtnh_len) as isize) as *mut Rtnexthop)
437}
438pub const fn rtnh_length(len: u16) -> u16 {
439    rtnh_align(mem::size_of::<Rtnexthop>() as u16 + len)
440}
441pub const fn rtnh_space(len: u16) -> u16 {
442    rtnh_align(rtnh_length(len))
443}
444pub unsafe fn rtnh_data(rtnh: &mut Rtnexthop) -> &mut Rtattr {
445    &mut *((rtnh as *mut _ as *mut u8).offset(rtnh_length(0) as isize) as *mut Rtattr)
446}
447
448// RTA_VIA
449#[repr(C)]
450#[derive(Debug, Clone, Copy)]
451pub struct Rtvia {
452    pub rtvia_family: sa_family_t,
453    pub rtvia_addr: [u8; 0],
454}
455
456// RTM_CACHEINFO
457#[repr(C)]
458#[derive(Debug, Clone, Copy)]
459pub struct RtaCacheinfo {
460    pub rta_clntref: u32,
461    pub rta_lastuse: u32,
462    pub rta_expires: i32,
463    pub rta_error: u32,
464    pub rta_used: u32,
465    pub rta_id: u32,
466    pub rta_ts: u32,
467    pub rta_tsage: u32,
468}
469pub const RTNETLINK_HAVE_PEERINFO: u32 = 1; // XXX: ???
470
471// RTM_METRICS --- array of struct rtattr with types of RTAX_*
472#[repr(u16)]
473#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, NlaType)]
474#[tbname = "RtaxTbl"]
475pub enum Rtax {
476    Unspec = 0,
477
478    #[nla_type(u32, lock)]
479    Lock,
480
481    #[nla_type(u32, mtu)]
482    Mtu,
483
484    #[nla_type(u32, window)]
485    Window,
486
487    #[nla_type(u32, rtt)]
488    Rtt,
489
490    #[nla_type(u32, rttvar)]
491    Rttvar,
492
493    #[nla_type(u32, ssthresh)]
494    Ssthresh,
495
496    #[nla_type(u32, cwnd)]
497    Cwnd,
498
499    #[nla_type(u32, advmss)]
500    Advmss,
501
502    #[nla_type(u32, reordering)]
503    Reordering,
504
505    #[nla_type(u32, hoplimit)]
506    Hoplimit,
507
508    #[nla_type(u32, initcwnd)]
509    Initcwnd,
510
511    #[nla_type(u32, features)]
512    Features,
513
514    #[nla_type(u32, rto_min)]
515    RtoMin,
516
517    #[nla_type(u32, initrwnd)]
518    Initrwnd,
519
520    #[nla_type(u32, quickack)]
521    Quickack,
522
523    #[nla_type(str, cc_algo)]
524    CcAlgo,
525
526    #[nla_type(u32, fastopen_no_cookie)]
527    FastopenNoCookie,
528    _MAX,
529}
530pub const RTAX_UNSPEC: c_int = Rtax::Unspec as c_int;
531pub const RTAX_LOCK: c_int = Rtax::Lock as c_int;
532pub const RTAX_MTU: c_int = Rtax::Mtu as c_int;
533pub const RTAX_WINDOW: c_int = Rtax::Window as c_int;
534pub const RTAX_RTT: c_int = Rtax::Rtt as c_int;
535pub const RTAX_RTTVAR: c_int = Rtax::Rttvar as c_int;
536pub const RTAX_SSTHRESH: c_int = Rtax::Ssthresh as c_int;
537pub const RTAX_CWND: c_int = Rtax::Cwnd as c_int;
538pub const RTAX_ADVMSS: c_int = Rtax::Advmss as c_int;
539pub const RTAX_REORDERING: c_int = Rtax::Reordering as c_int;
540pub const RTAX_HOPLIMIT: c_int = Rtax::Hoplimit as c_int;
541pub const RTAX_INITCWND: c_int = Rtax::Initcwnd as c_int;
542pub const RTAX_FEATURES: c_int = Rtax::Features as c_int;
543pub const RTAX_RTO_MIN: c_int = Rtax::RtoMin as c_int;
544pub const RTAX_INITRWND: c_int = Rtax::Initrwnd as c_int;
545pub const RTAX_QUICKACK: c_int = Rtax::Quickack as c_int;
546pub const RTAX_CC_ALGO: c_int = Rtax::CcAlgo as c_int;
547pub const RTAX_FASTOPEN_NO_COOKIE: c_int = Rtax::FastopenNoCookie as c_int;
548pub const __RTAX_MAX: c_int = Rtax::_MAX as c_int;
549pub const RTAX_MAX: c_int = __RTAX_MAX - 1;
550
551pub const RTAX_FEATURE_ECN: u32 = 1 << 0;
552pub const RTAX_FEATURE_SACK: u32 = 1 << 1;
553pub const RTAX_FEATURE_TIMESTAMP: u32 = 1 << 2;
554pub const RTAX_FEATURE_ALLFRAG: u32 = 1 << 3;
555pub const RTAX_FEATURE_MASK: u32 =
556    RTAX_FEATURE_ECN | RTAX_FEATURE_SACK | RTAX_FEATURE_TIMESTAMP | RTAX_FEATURE_ALLFRAG;
557#[repr(C)]
558// #[derive(Debug, Clone, Copy)]
559#[derive(Clone, Copy)]
560pub struct RtaSession {
561    pub proto: u8,
562    pub pad1: u8,
563    pub pad2: u16,
564    pub u: _RtaSesseionUnion,
565}
566#[repr(C)]
567// #[derive(Debug, Clone, Copy)]
568#[derive(Clone, Copy)]
569pub union _RtaSesseionUnion {
570    pub ports: _RtaSessionUnionPorts,
571    pub icmpt: _RtaSesseionUnionIcmpt,
572    pub spi: u32,
573}
574#[derive(Debug, Clone, Copy)]
575pub struct _RtaSessionUnionPorts {
576    sport: u16,
577    dport: u16,
578}
579#[derive(Debug, Clone, Copy)]
580pub struct _RtaSesseionUnionIcmpt {
581    itype: u8,
582    code: u8,
583    ident: u16,
584}
585
586#[repr(C)]
587#[derive(Debug, Clone, Copy)]
588pub struct RtaMfcStats {
589    pub mfcs_packets: u64,
590    pub mfcs_bytes: u64,
591    pub mfcs_wrong_if: u64,
592}
593
594// General form of address family dependent message.
595#[repr(C)]
596#[derive(Debug, Clone, Copy)]
597pub struct Rtgenmsg {
598    pub rtgen_family: c_uchar,
599}
600
601// Link layer specific messages.
602
603// struct ifinfomsg
604// passes link level specific information, not dependent
605// on network protocol.
606#[repr(C)]
607#[derive(Debug, Clone, Copy)]
608pub struct Ifinfomsg {
609    pub ifi_family: c_uchar,
610    pub __ifi_pad: c_uchar,
611    pub ifi_type: c_ushort, // ARPHRD_*
612    pub ifi_index: c_int,   // Link index
613    pub ifi_flags: c_uint,  // IFF_* flags
614    pub ifi_change: c_uint, // IFF_* change mask
615}
616
617// prefix information
618#[repr(C)]
619#[derive(Debug, Clone, Copy)]
620pub struct prefixmsg {
621    pub prefix_family: c_uchar,
622    pub prefix_pad1: c_uchar,
623    pub prefix_pad2: c_ushort,
624    pub prefix_ifindex: c_int,
625    pub prefix_type: c_uchar,
626    pub prefix_len: c_uchar,
627    pub prefix_flags: c_uchar,
628    pub prefix_pad3: c_uchar,
629}
630
631#[repr(u16)]
632#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, NlaType)]
633#[tbname = "PrefixTbl"]
634pub enum Prefix {
635    Unspec = 0,
636    Address = 1,
637    Cacheinfo = 2,
638    _MAX = 3,
639}
640
641#[repr(C)]
642#[derive(Debug, Clone, Copy)]
643pub struct PrefixCacheinfo {
644    pub preferred_time: u32,
645    pub valid_time: u32,
646}
647
648// Traffic control messages.
649#[allow(non_snake_case)]
650#[repr(C)]
651#[derive(Debug, Clone, Copy)]
652pub struct Tcmsg {
653    pub tcm_family: c_uchar,
654    pub tcm__pad1: c_uchar,
655    pub tcm__pad2: c_uchar,
656    pub tcm_ifindex: c_uint,
657    pub tcm_handle: u32,
658
659    // XXX: tcm_block_index is used instead of tcm_parent
660    // in case tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK
661    // macro_rules! tcm_block_index { tcm_parent }
662    pub tcm_parent: u32,
663
664    pub tcm_info: u32,
665}
666
667// For manipulation of filters in shared block, tcm_ifindex is set to
668// TCM_IFINDEX_MAGIC_BLOCK, and tcm_parent is aliased to tcm_block_index
669// which is the block index.
670// XXX: #define TCM_IFINDEX_MAGIC_BLOCK (0xFFFFFFFFU)
671pub const TCM_IFINDEX_MAGIC_BLOCK: c_int = -1;
672
673#[repr(u16)]
674#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, NlaType)]
675#[tbname = "TcaTbl"]
676pub enum Tca {
677    Unspec = 0,
678    Kind,
679    Options,
680    Stats,
681    Xstats,
682    Rate,
683    Fcnt,
684    Stats2,
685    Stab,
686    Pad,
687    DumpInvisible,
688    Chain,
689    HwOffload,
690    IngressBlock,
691    EgressBlock,
692    DumpFlags,
693    _MAX,
694}
695
696pub const TCA_DUMP_FLAGS_TERSE: u32 = 1 << 0; // Means that in dump user gets only basic
697                                              // data necessary to identify the objects
698                                              // (handle, cookie, etc.) and stats.
699
700pub unsafe fn tca_rta(r: &mut Tcmsg) -> &mut Rtattr {
701    &mut *((r as *mut _ as *mut u8)
702        .offset(netlink::nlmsg_align(mem::size_of::<Tcmsg>() as u32) as isize)
703        as *mut Rtattr)
704}
705
706pub fn tca_payload(n: &netlink::Nlmsghdr) -> u32 {
707    netlink::nlmsg_payload(n, mem::size_of::<Tcmsg>() as u32)
708}
709
710// Neighbor Discovery userland options
711#[repr(C)]
712#[derive(Debug, Clone, Copy)]
713pub struct nduseroptmsg {
714    pub nduseropt_family: c_uchar,
715    pub nduseropt_pad1: c_uchar,
716    pub nduseropt_opts_len: c_ushort, // Total length of options
717    pub nduseropt_ifindex: c_int,
718    pub nduseropt_icmp_type: u8,
719    pub nduseropt_icmp_code: u8,
720    pub nduseropt_pad2: c_ushort,
721    pub nduseropt_pad3: c_uint,
722    // Followed by one or more ND options
723}
724
725#[repr(u16)]
726#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, NlaType)]
727#[tbname = "NduseportTbl"]
728pub enum Nduseropt {
729    Unspec = 0,
730    Srcaddr,
731    _MAX,
732}
733
734// RTnetlink multicast groups - backwards compatibility for userspace
735pub const RTMGRP_LINK: u32 = 1;
736pub const RTMGRP_NOTIFY: u32 = 2;
737pub const RTMGRP_NEIGH: u32 = 4;
738pub const RTMGRP_TC: u32 = 8;
739pub const RTMGRP_IPV4_IFADDR: u32 = 0x10;
740pub const RTMGRP_IPV4_MROUTE: u32 = 0x20;
741pub const RTMGRP_IPV4_ROUTE: u32 = 0x40;
742pub const RTMGRP_IPV4_RULE: u32 = 0x80;
743pub const RTMGRP_IPV6_IFADDR: u32 = 0x100;
744pub const RTMGRP_IPV6_MROUTE: u32 = 0x200;
745pub const RTMGRP_IPV6_ROUTE: u32 = 0x400;
746pub const RTMGRP_IPV6_IFINFO: u32 = 0x800;
747#[allow(non_upper_case_globals)]
748pub const RTMGRP_DECnet_IFADDR: u32 = 0x1000;
749#[allow(non_upper_case_globals)]
750pub const RTMGRP_DECnet_ROUTE: u32 = 0x4000;
751pub const RTMGRP_IPV6_PREFIX: u32 = 0x20000;
752
753// RTnetlink multicast groups
754#[repr(u32)]
755#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
756pub enum RtnetlinkGroups {
757    None = 0,
758    Link,
759    Notify,
760    Neigh,
761    Tc,
762    Ipv4Ifaddr,
763    Ipv4Mroute,
764    Ipv4Route,
765    Ipv4Rule,
766    Ipv6Ifaddr,
767    Ipv6Mroute,
768    Ipv6Route,
769    Ipv6Ifinfo,
770    DecnetIfaddr,
771    Nop2,
772    DecnetRoute,
773    DecnetRule,
774    Nop4,
775    Ipv6Prefix,
776    Ipv6Rule,
777    NdUseropt,
778    PhonetIfaddr,
779    PhonetRoute,
780    Dcb,
781    Ipv4Netconf,
782    Ipv6Netconf,
783    Mdb,
784    MplsRoute,
785    Nsid,
786    MplsNetconf,
787    Ipv4MrouteR,
788    Ipv6MrouteR,
789    Nexthop,
790    Brvlan,
791    _MAX,
792}
793pub const RTNLGRP_NONE: u32 = RtnetlinkGroups::None as u32;
794pub const RTNLGRP_LINK: u32 = RtnetlinkGroups::Link as u32;
795pub const RTNLGRP_NOTIFY: u32 = RtnetlinkGroups::Notify as u32;
796pub const RTNLGRP_NEIGH: u32 = RtnetlinkGroups::Neigh as u32;
797pub const RTNLGRP_TC: u32 = RtnetlinkGroups::Tc as u32;
798pub const RTNLGRP_IPV4_IFADDR: u32 = RtnetlinkGroups::Ipv4Ifaddr as u32;
799pub const RTNLGRP_IPV4_MROUTE: u32 = RtnetlinkGroups::Ipv4Mroute as u32;
800pub const RTNLGRP_IPV4_ROUTE: u32 = RtnetlinkGroups::Ipv4Route as u32;
801pub const RTNLGRP_IPV4_RULE: u32 = RtnetlinkGroups::Ipv4Rule as u32;
802pub const RTNLGRP_IPV6_IFADDR: u32 = RtnetlinkGroups::Ipv6Ifaddr as u32;
803pub const RTNLGRP_IPV6_MROUTE: u32 = RtnetlinkGroups::Ipv6Mroute as u32;
804pub const RTNLGRP_IPV6_ROUTE: u32 = RtnetlinkGroups::Ipv6Route as u32;
805pub const RTNLGRP_IPV6_IFINFO: u32 = RtnetlinkGroups::Ipv6Ifinfo as u32;
806#[allow(non_upper_case_globals)]
807pub const RTNLGRP_DECnet_IFADDR: u32 = RtnetlinkGroups::DecnetIfaddr as u32;
808pub const RTNLGRP_NOP2: u32 = RtnetlinkGroups::Nop2 as u32;
809#[allow(non_upper_case_globals)]
810pub const RTNLGRP_DECnet_ROUTE: u32 = RtnetlinkGroups::DecnetRoute as u32;
811#[allow(non_upper_case_globals)]
812pub const RTNLGRP_DECnet_RULE: u32 = RtnetlinkGroups::DecnetRule as u32;
813pub const RTNLGRP_NOP4: u32 = RtnetlinkGroups::Nop4 as u32;
814pub const RTNLGRP_IPV6_PREFIX: u32 = RtnetlinkGroups::Ipv6Prefix as u32;
815pub const RTNLGRP_IPV6_RULE: u32 = RtnetlinkGroups::Ipv6Rule as u32;
816pub const RTNLGRP_ND_USEROPT: u32 = RtnetlinkGroups::NdUseropt as u32;
817pub const RTNLGRP_PHONET_IFADDR: u32 = RtnetlinkGroups::PhonetIfaddr as u32;
818pub const RTNLGRP_PHONET_ROUTE: u32 = RtnetlinkGroups::PhonetRoute as u32;
819pub const RTNLGRP_DCB: u32 = RtnetlinkGroups::Dcb as u32;
820pub const RTNLGRP_IPV4_NETCONF: u32 = RtnetlinkGroups::Ipv4Netconf as u32;
821pub const RTNLGRP_IPV6_NETCONF: u32 = RtnetlinkGroups::Ipv6Netconf as u32;
822pub const RTNLGRP_MDB: u32 = RtnetlinkGroups::Mdb as u32;
823pub const RTNLGRP_MPLS_ROUTE: u32 = RtnetlinkGroups::MplsRoute as u32;
824pub const RTNLGRP_NSID: u32 = RtnetlinkGroups::Nsid as u32;
825pub const RTNLGRP_MPLS_NETCONF: u32 = RtnetlinkGroups::MplsNetconf as u32;
826pub const RTNLGRP_IPV4_MROUTE_R: u32 = RtnetlinkGroups::Ipv4MrouteR as u32;
827pub const RTNLGRP_IPV6_MROUTE_R: u32 = RtnetlinkGroups::Ipv6MrouteR as u32;
828pub const RTNLGRP_NEXTHOP: u32 = RtnetlinkGroups::Nexthop as u32;
829pub const RTNLGRP_BRVLAN: u32 = RtnetlinkGroups::Brvlan as u32;
830pub const __RTNLGRP_MAX: u32 = RtnetlinkGroups::_MAX as u32;
831pub const RTNLGRP_MAX: u32 = __RTNLGRP_MAX - 1;
832
833// TC action piece
834#[allow(non_snake_case)]
835#[repr(C)]
836#[derive(Debug, Clone, Copy)]
837pub struct Tcamsg {
838    pub tca_family: c_uchar,
839    pub tca__pad1: c_uchar,
840    pub tca__pad2: c_uchar,
841}
842
843#[repr(u16)]
844#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, NlaType)]
845pub enum TcaRoot {
846    Unspec = 0,
847    Tab,
848    Flags,
849    Count,
850    TimeDelta,
851    _MAX,
852}
853
854pub unsafe fn ta_rta(r: &mut Tcamsg) -> &mut Rtattr {
855    &mut *((r as *mut _ as *mut u8)
856        .offset(netlink::nlmsg_align(mem::size_of::<Tcamsg>() as u32) as isize)
857        as *mut Rtattr)
858}
859pub fn ta_payload(n: &netlink::Nlmsghdr) -> u32 {
860    netlink::nlmsg_payload(n, mem::size_of::<Tcamsg>() as u32)
861}
862
863// tcamsg flags stored in attribute TCA_ROOT_FLAGS
864//
865// TCA_FLAG_LARGE_DUMP_ON user->kernel to request for larger than TCA_ACT_MAX_PRIO
866// actions in a dump. All dump responses will contain the number of actions
867// being dumped stored in for user app's consumption in TCA_ROOT_COUNT
868pub const TCA_FLAG_LARGE_DUMP_ON: u32 = 1 << 0;
869
870// New extended info filters for IFLA_EXT_MASK
871pub const RTEXT_FILTER_VF: u32 = 1 << 0;
872pub const RTEXT_FILTER_BRVLAN: u32 = 1 << 1;
873pub const RTEXT_FILTER_BRVLAN_COMPRESSED: u32 = 1 << 2;
874pub const RTEXT_FILTER_SKIP_STATS: u32 = 1 << 3;
875
876// End of information exported to user level