xref: /freebsd/tests/atf_python/sys/netlink/netlink_route.py (revision 2019f3d86f783711e9969d72cc423b26a4ce2f5a)
1import socket
2import struct
3from ctypes import c_int
4from ctypes import c_ubyte
5from ctypes import c_uint
6from ctypes import c_ushort
7from ctypes import sizeof
8from ctypes import Structure
9from enum import auto
10from enum import Enum
11
12from atf_python.sys.netlink.attrs import NlAttr
13from atf_python.sys.netlink.attrs import NlAttrIp
14from atf_python.sys.netlink.attrs import NlAttrNested
15from atf_python.sys.netlink.attrs import NlAttrStr
16from atf_python.sys.netlink.attrs import NlAttrU16
17from atf_python.sys.netlink.attrs import NlAttrU32
18from atf_python.sys.netlink.attrs import NlAttrU64
19from atf_python.sys.netlink.attrs import NlAttrU8
20from atf_python.sys.netlink.message import StdNetlinkMessage
21from atf_python.sys.netlink.message import NlMsgProps
22from atf_python.sys.netlink.message import NlMsgCategory
23from atf_python.sys.netlink.utils import AttrDescr
24from atf_python.sys.netlink.utils import get_bitmask_str
25from atf_python.sys.netlink.utils import prepare_attrs_map
26
27
28class RtattrType(Enum):
29    RTA_UNSPEC = 0
30    RTA_DST = 1
31    RTA_SRC = 2
32    RTA_IIF = 3
33    RTA_OIF = 4
34    RTA_GATEWAY = 5
35    RTA_PRIORITY = 6
36    RTA_PREFSRC = 7
37    RTA_METRICS = 8
38    RTA_MULTIPATH = 9
39    # RTA_PROTOINFO = 10
40    RTA_KNH_ID = 10
41    RTA_FLOW = 11
42    RTA_CACHEINFO = 12
43    RTA_SESSION = 13
44    # RTA_MP_ALGO = 14
45    RTA_RTFLAGS = 14
46    RTA_TABLE = 15
47    RTA_MARK = 16
48    RTA_MFC_STATS = 17
49    RTA_VIA = 18
50    RTA_NEWDST = 19
51    RTA_PREF = 20
52    RTA_ENCAP_TYPE = 21
53    RTA_ENCAP = 22
54    RTA_EXPIRES = 23
55    RTA_PAD = 24
56    RTA_UID = 25
57    RTA_TTL_PROPAGATE = 26
58    RTA_IP_PROTO = 27
59    RTA_SPORT = 28
60    RTA_DPORT = 29
61    RTA_NH_ID = 30
62
63
64class NlRtMsgType(Enum):
65    RTM_NEWLINK = 16
66    RTM_DELLINK = 17
67    RTM_GETLINK = 18
68    RTM_SETLINK = 19
69    RTM_NEWADDR = 20
70    RTM_DELADDR = 21
71    RTM_GETADDR = 22
72    RTM_NEWROUTE = 24
73    RTM_DELROUTE = 25
74    RTM_GETROUTE = 26
75    RTM_NEWNEIGH = 28
76    RTM_DELNEIGH = 29
77    RTM_GETNEIGH = 30
78    RTM_NEWRULE = 32
79    RTM_DELRULE = 33
80    RTM_GETRULE = 34
81    RTM_NEWQDISC = 36
82    RTM_DELQDISC = 37
83    RTM_GETQDISC = 38
84    RTM_NEWTCLASS = 40
85    RTM_DELTCLASS = 41
86    RTM_GETTCLASS = 42
87    RTM_NEWTFILTER = 44
88    RTM_DELTFILTER = 45
89    RTM_GETTFILTER = 46
90    RTM_NEWACTION = 48
91    RTM_DELACTION = 49
92    RTM_GETACTION = 50
93    RTM_NEWPREFIX = 52
94    RTM_GETMULTICAST = 58
95    RTM_GETANYCAST = 62
96    RTM_NEWNEIGHTBL = 64
97    RTM_GETNEIGHTBL = 66
98    RTM_SETNEIGHTBL = 67
99    RTM_NEWNDUSEROPT = 68
100    RTM_NEWADDRLABEL = 72
101    RTM_DELADDRLABEL = 73
102    RTM_GETADDRLABEL = 74
103    RTM_GETDCB = 78
104    RTM_SETDCB = 79
105    RTM_NEWNETCONF = 80
106    RTM_GETNETCONF = 82
107    RTM_NEWMDB = 84
108    RTM_DELMDB = 85
109    RTM_GETMDB = 86
110    RTM_NEWNSID = 88
111    RTM_DELNSID = 89
112    RTM_GETNSID = 90
113    RTM_NEWSTATS = 92
114    RTM_GETSTATS = 94
115
116
117class RtAttr(Structure):
118    _fields_ = [
119        ("rta_len", c_ushort),
120        ("rta_type", c_ushort),
121    ]
122
123
124class RtMsgHdr(Structure):
125    _fields_ = [
126        ("rtm_family", c_ubyte),
127        ("rtm_dst_len", c_ubyte),
128        ("rtm_src_len", c_ubyte),
129        ("rtm_tos", c_ubyte),
130        ("rtm_table", c_ubyte),
131        ("rtm_protocol", c_ubyte),
132        ("rtm_scope", c_ubyte),
133        ("rtm_type", c_ubyte),
134        ("rtm_flags", c_uint),
135    ]
136
137
138class RtMsgFlags(Enum):
139    RTM_F_NOTIFY = 0x100
140    RTM_F_CLONED = 0x200
141    RTM_F_EQUALIZE = 0x400
142    RTM_F_PREFIX = 0x800
143    RTM_F_LOOKUP_TABLE = 0x1000
144    RTM_F_FIB_MATCH = 0x2000
145    RTM_F_OFFLOAD = 0x4000
146    RTM_F_TRAP = 0x8000
147    RTM_F_OFFLOAD_FAILED = 0x20000000
148
149
150class RtScope(Enum):
151    RT_SCOPE_UNIVERSE = 0
152    RT_SCOPE_SITE = 200
153    RT_SCOPE_LINK = 253
154    RT_SCOPE_HOST = 254
155    RT_SCOPE_NOWHERE = 255
156
157
158class RtType(Enum):
159    RTN_UNSPEC = 0
160    RTN_UNICAST = auto()
161    RTN_LOCAL = auto()
162    RTN_BROADCAST = auto()
163    RTN_ANYCAST = auto()
164    RTN_MULTICAST = auto()
165    RTN_BLACKHOLE = auto()
166    RTN_UNREACHABLE = auto()
167    RTN_PROHIBIT = auto()
168    RTN_THROW = auto()
169    RTN_NAT = auto()
170    RTN_XRESOLVE = auto()
171
172
173class RtProto(Enum):
174    RTPROT_UNSPEC = 0
175    RTPROT_REDIRECT = 1
176    RTPROT_KERNEL = 2
177    RTPROT_BOOT = 3
178    RTPROT_STATIC = 4
179    RTPROT_GATED = 8
180    RTPROT_RA = 9
181    RTPROT_MRT = 10
182    RTPROT_ZEBRA = 11
183    RTPROT_BIRD = 12
184    RTPROT_DNROUTED = 13
185    RTPROT_XORP = 14
186    RTPROT_NTK = 15
187    RTPROT_DHCP = 16
188    RTPROT_MROUTED = 17
189    RTPROT_KEEPALIVED = 18
190    RTPROT_BABEL = 42
191    RTPROT_OPENR = 99
192    RTPROT_BGP = 186
193    RTPROT_ISIS = 187
194    RTPROT_OSPF = 188
195    RTPROT_RIP = 189
196    RTPROT_EIGRP = 192
197
198
199class NlRtaxType(Enum):
200    RTAX_UNSPEC = 0
201    RTAX_LOCK = auto()
202    RTAX_MTU = auto()
203    RTAX_WINDOW = auto()
204    RTAX_RTT = auto()
205    RTAX_RTTVAR = auto()
206    RTAX_SSTHRESH = auto()
207    RTAX_CWND = auto()
208    RTAX_ADVMSS = auto()
209    RTAX_REORDERING = auto()
210    RTAX_HOPLIMIT = auto()
211    RTAX_INITCWND = auto()
212    RTAX_FEATURES = auto()
213    RTAX_RTO_MIN = auto()
214    RTAX_INITRWND = auto()
215    RTAX_QUICKACK = auto()
216    RTAX_CC_ALGO = auto()
217    RTAX_FASTOPEN_NO_COOKIE = auto()
218
219
220class RtFlagsBSD(Enum):
221    RTF_UP = 0x1
222    RTF_GATEWAY = 0x2
223    RTF_HOST = 0x4
224    RTF_REJECT = 0x8
225    RTF_DYNAMIC = 0x10
226    RTF_MODIFIED = 0x20
227    RTF_DONE = 0x40
228    RTF_XRESOLVE = 0x200
229    RTF_LLINFO = 0x400
230    RTF_LLDATA = 0x400
231    RTF_STATIC = 0x800
232    RTF_BLACKHOLE = 0x1000
233    RTF_PROTO2 = 0x4000
234    RTF_PROTO1 = 0x8000
235    RTF_PROTO3 = 0x40000
236    RTF_FIXEDMTU = 0x80000
237    RTF_PINNED = 0x100000
238    RTF_LOCAL = 0x200000
239    RTF_BROADCAST = 0x400000
240    RTF_MULTICAST = 0x800000
241    RTF_STICKY = 0x10000000
242    RTF_RNH_LOCKED = 0x40000000
243    RTF_GWFLAG_COMPAT = 0x80000000
244
245
246class NlRtGroup(Enum):
247    RTNLGRP_NONE = 0
248    RTNLGRP_LINK = auto()
249    RTNLGRP_NOTIFY = auto()
250    RTNLGRP_NEIGH = auto()
251    RTNLGRP_TC = auto()
252    RTNLGRP_IPV4_IFADDR = auto()
253    RTNLGRP_IPV4_MROUTE = auto()
254    RTNLGRP_IPV4_ROUTE = auto()
255    RTNLGRP_IPV4_RULE = auto()
256    RTNLGRP_IPV6_IFADDR = auto()
257    RTNLGRP_IPV6_MROUTE = auto()
258    RTNLGRP_IPV6_ROUTE = auto()
259    RTNLGRP_IPV6_IFINFO = auto()
260    RTNLGRP_DECnet_IFADDR = auto()
261    RTNLGRP_NOP2 = auto()
262    RTNLGRP_DECnet_ROUTE = auto()
263    RTNLGRP_DECnet_RULE = auto()
264    RTNLGRP_NOP4 = auto()
265    RTNLGRP_IPV6_PREFIX = auto()
266    RTNLGRP_IPV6_RULE = auto()
267    RTNLGRP_ND_USEROPT = auto()
268    RTNLGRP_PHONET_IFADDR = auto()
269    RTNLGRP_PHONET_ROUTE = auto()
270    RTNLGRP_DCB = auto()
271    RTNLGRP_IPV4_NETCONF = auto()
272    RTNLGRP_IPV6_NETCONF = auto()
273    RTNLGRP_MDB = auto()
274    RTNLGRP_MPLS_ROUTE = auto()
275    RTNLGRP_NSID = auto()
276    RTNLGRP_MPLS_NETCONF = auto()
277    RTNLGRP_IPV4_MROUTE_R = auto()
278    RTNLGRP_IPV6_MROUTE_R = auto()
279    RTNLGRP_NEXTHOP = auto()
280    RTNLGRP_BRVLAN = auto()
281
282
283class IfinfoMsg(Structure):
284    _fields_ = [
285        ("ifi_family", c_ubyte),
286        ("__ifi_pad", c_ubyte),
287        ("ifi_type", c_ushort),
288        ("ifi_index", c_int),
289        ("ifi_flags", c_uint),
290        ("ifi_change", c_uint),
291    ]
292
293
294class IflattrType(Enum):
295    IFLA_UNSPEC = 0
296    IFLA_ADDRESS = 1
297    IFLA_BROADCAST = 2
298    IFLA_IFNAME = 3
299    IFLA_MTU = 4
300    IFLA_LINK = 5
301    IFLA_QDISC = 6
302    IFLA_STATS = 7
303    IFLA_COST = 8
304    IFLA_PRIORITY = 9
305    IFLA_MASTER = 10
306    IFLA_WIRELESS = 11
307    IFLA_PROTINFO = 12
308    IFLA_TXQLEN = 13
309    IFLA_MAP = 14
310    IFLA_WEIGHT = 15
311    IFLA_OPERSTATE = 16
312    IFLA_LINKMODE = 17
313    IFLA_LINKINFO = 18
314    IFLA_NET_NS_PID = 19
315    IFLA_IFALIAS = 20
316    IFLA_NUM_VF = 21
317    IFLA_VFINFO_LIST = 22
318    IFLA_STATS64 = 23
319    IFLA_VF_PORTS = 24
320    IFLA_PORT_SELF = 25
321    IFLA_AF_SPEC = 26
322    IFLA_GROUP = 27
323    IFLA_NET_NS_FD = 28
324    IFLA_EXT_MASK = 29
325    IFLA_PROMISCUITY = 30
326    IFLA_NUM_TX_QUEUES = 31
327    IFLA_NUM_RX_QUEUES = 32
328    IFLA_CARRIER = 33
329    IFLA_PHYS_PORT_ID = 34
330    IFLA_CARRIER_CHANGES = 35
331    IFLA_PHYS_SWITCH_ID = 36
332    IFLA_LINK_NETNSID = 37
333    IFLA_PHYS_PORT_NAME = 38
334    IFLA_PROTO_DOWN = 39
335    IFLA_GSO_MAX_SEGS = 40
336    IFLA_GSO_MAX_SIZE = 41
337    IFLA_PAD = 42
338    IFLA_XDP = 43
339    IFLA_EVENT = 44
340    IFLA_NEW_NETNSID = 45
341    IFLA_IF_NETNSID = 46
342    IFLA_CARRIER_UP_COUNT = 47
343    IFLA_CARRIER_DOWN_COUNT = 48
344    IFLA_NEW_IFINDEX = 49
345    IFLA_MIN_MTU = 50
346    IFLA_MAX_MTU = 51
347    IFLA_PROP_LIST = 52
348    IFLA_ALT_IFNAME = 53
349    IFLA_PERM_ADDRESS = 54
350    IFLA_PROTO_DOWN_REASON = 55
351    IFLA_PARENT_DEV_NAME = 56
352    IFLA_PARENT_DEV_BUS_NAME = 57
353    IFLA_GRO_MAX_SIZE = 58
354    IFLA_TSO_MAX_SEGS = 59
355    IFLA_ALLMULTI = 60
356    IFLA_DEVLINK_PORT = 61
357    IFLA_GSO_IPV4_MAX_SIZE = 62
358    IFLA_GRO_IPV4_MAX_SIZE = 63
359    IFLA_FREEBSD = 64
360    IFLA_FREEBSD_VF = 65
361
362
363class IflafAttrType(Enum):
364    IFLAF_UNSPEC = 0
365    IFLAF_ORIG_IFNAME = 1
366    IFLAF_ORIG_HWADDR = 2
367    IFLAF_CAPS = 3
368    IFLAF_VF_STATUS = 5
369
370
371class IflafVfStatusType(Enum):
372    IFLAF_VFS_UNSPEC = 0
373    IFLAF_VFS_ERROR = 1
374    IFLAF_VFS_PF_LINK_STATE = 2
375    IFLAF_VFS_PF_LINK_SPEED = 3
376
377
378class IflafVfType(Enum):
379    IFLAF_VF_UNSPEC = 0
380    IFLAF_VF_INDEX = 1
381    IFLAF_VF_CONFIGURED = 2
382    IFLAF_VF_INITIALIZED = 3
383    IFLAF_VF_MAC = 4
384    IFLAF_VF_VLAN_MODE = 5
385    IFLAF_VF_VLAN = 6
386    IFLAF_VF_VLAN_PCP = 7
387    IFLAF_VF_VLAN_PROTO = 8
388    IFLAF_VF_VLAN_COUNT = 9
389    IFLAF_VF_VLAN_LIMIT = 10
390    IFLAF_VF_NUM_TX_QUEUES = 11
391    IFLAF_VF_NUM_RX_QUEUES = 12
392    IFLAF_VF_MIN_TX_RATE = 13
393    IFLAF_VF_MAX_TX_RATE = 14
394    IFLAF_VF_ALLOW_SET_MAC = 15
395    IFLAF_VF_ALLOW_SET_VLAN = 16
396    IFLAF_VF_MAC_ANTI_SPOOF = 17
397    IFLAF_VF_ALLOW_PROMISC = 18
398    IFLAF_VF_TRAFFIC_ALLOWED = 19
399    IFLAF_VF_FAULT_BLOCKED = 20
400    IFLAF_VF_QUARANTINED = 21
401    IFLAF_VF_API_VERSION = 22
402    IFLAF_VF_LINK_STATE_POLICY = 23
403    IFLAF_VF_DRIVER = 24
404
405
406class IflafVfDriverType(Enum):
407    IFLAF_VFD_UNSPEC = 0
408    IFLAF_VFD_NAME = 1
409    IFLAF_VFD_VERSION = 2
410    IFLAF_VFD_FIELD = 3
411
412
413class IflafVfDriverFieldType(Enum):
414    IFLAF_VFDF_UNSPEC = 0
415    IFLAF_VFDF_NAME = 1
416    IFLAF_VFDF_BOOL = 2
417    IFLAF_VFDF_NUMBER = 3
418    IFLAF_VFDF_STRING = 4
419    IFLAF_VFDF_BINARY = 5
420
421
422class IflinkInfo(Enum):
423    IFLA_INFO_UNSPEC = 0
424    IFLA_INFO_KIND = auto()
425    IFLA_INFO_DATA = auto()
426    IFLA_INFO_XSTATS = auto()
427    IFLA_INFO_SLAVE_KIND = auto()
428    IFLA_INFO_SLAVE_DATA = auto()
429
430
431class IfLinkInfoDataVlan(Enum):
432    IFLA_VLAN_UNSPEC = 0
433    IFLA_VLAN_ID = auto()
434    IFLA_VLAN_FLAGS = auto()
435    IFLA_VLAN_EGRESS_QOS = auto()
436    IFLA_VLAN_INGRESS_QOS = auto()
437    IFLA_VLAN_PROTOCOL = auto()
438
439
440class IfaddrMsg(Structure):
441    _fields_ = [
442        ("ifa_family", c_ubyte),
443        ("ifa_prefixlen", c_ubyte),
444        ("ifa_flags", c_ubyte),
445        ("ifa_scope", c_ubyte),
446        ("ifa_index", c_uint),
447    ]
448
449
450class IfaAttrType(Enum):
451    IFA_UNSPEC = 0
452    IFA_ADDRESS = 1
453    IFA_LOCAL = 2
454    IFA_LABEL = 3
455    IFA_BROADCAST = 4
456    IFA_ANYCAST = 5
457    IFA_CACHEINFO = 6
458    IFA_MULTICAST = 7
459    IFA_FLAGS = 8
460    IFA_RT_PRIORITY = 9
461    IFA_TARGET_NETNSID = 10
462    IFA_FREEBSD = 11
463
464
465class IfafAttrType(Enum):
466    IFAF_UNSPEC = 0
467    IFAF_VHID = 1
468    IFAF_FLAGS = 2
469
470
471class IfaCacheInfo(Structure):
472    _fields_ = [
473        ("ifa_prefered", c_uint),   # seconds till the end of the prefix considered preferred
474        ("ifa_valid", c_uint),      # seconds till the end of the prefix considered valid
475        ("cstamp", c_uint),         # creation time in 1ms intervals from the boot time
476        ("tstamp", c_uint),         # update time in 1ms intervals from the boot time
477    ]
478
479
480class IfaFlags(Enum):
481    IFA_F_TEMPORARY = 0x01
482    IFA_F_NODAD = 0x02
483    IFA_F_OPTIMISTIC = 0x04
484    IFA_F_DADFAILED = 0x08
485    IFA_F_HOMEADDRESS = 0x10
486    IFA_F_DEPRECATED = 0x20
487    IFA_F_TENTATIVE = 0x40
488    IFA_F_PERMANENT = 0x80
489    IFA_F_MANAGETEMPADDR = 0x100
490    IFA_F_NOPREFIXROUTE = 0x200
491    IFA_F_MCAUTOJOIN = 0x400
492    IFA_F_STABLE_PRIVACY = 0x800
493
494
495class IfafFlags6(Enum):
496    IN6_IFF_ANYCAST = 0x01
497    IN6_IFF_TENTATIVE = 0x02
498    IN6_IFF_DUPLICATED = 0x04
499    IN6_IFF_DETACHED = 0x08
500    IN6_IFF_DEPRECATED = 0x10
501    IN6_IFF_NODAD = 0x20
502    IN6_IFF_AUTOCONF = 0x40
503    IN6_IFF_TEMPORARY = 0x80
504    IN6_IFF_PREFER_SOURCE = 0x100
505
506
507class NdMsg(Structure):
508    _fields_ = [
509        ("ndm_family", c_ubyte),
510        ("ndm_pad1", c_ubyte),
511        ("ndm_pad2", c_ubyte),
512        ("ndm_ifindex", c_uint),
513        ("ndm_state", c_ushort),
514        ("ndm_flags", c_ubyte),
515        ("ndm_type", c_ubyte),
516    ]
517
518
519class NdAttrType(Enum):
520    NDA_UNSPEC = 0
521    NDA_DST = 1
522    NDA_LLADDR = 2
523    NDA_CACHEINFO = 3
524    NDA_PROBES = 4
525    NDA_VLAN = 5
526    NDA_PORT = 6
527    NDA_VNI = 7
528    NDA_IFINDEX = 8
529    NDA_MASTER = 9
530    NDA_LINK_NETNSID = 10
531    NDA_SRC_VNI = 11
532    NDA_PROTOCOL = 12
533    NDA_NH_ID = 13
534    NDA_FDB_EXT_ATTRS = 14
535    NDA_FLAGS_EXT = 15
536    NDA_NDM_STATE_MASK = 16
537    NDA_NDM_FLAGS_MASK = 17
538
539
540class NlAttrRtFlags(NlAttrU32):
541    def _print_attr_value(self):
542        s = get_bitmask_str(RtFlagsBSD, self.u32)
543        return " rtflags={}".format(s)
544
545
546class NlAttrIfindex(NlAttrU32):
547    def _print_attr_value(self):
548        try:
549            ifname = socket.if_indextoname(self.u32)
550            return " iface={}(#{})".format(ifname, self.u32)
551        except OSError:
552            pass
553        return " iface=if#{}".format(self.u32)
554
555
556class NlAttrTable(NlAttrU32):
557    def _print_attr_value(self):
558        return " rtable={}".format(self.u32)
559
560
561class NlAttrNhId(NlAttrU32):
562    def _print_attr_value(self):
563        return " nh_id={}".format(self.u32)
564
565
566class NlAttrKNhId(NlAttrU32):
567    def _print_attr_value(self):
568        return " knh_id={}".format(self.u32)
569
570
571class NlAttrMac(NlAttr):
572    def _print_attr_value(self):
573        return ' mac="' + ":".join(["{:02X}".format(b) for b in self._data]) + '"'
574
575
576class NlAttrIfStats(NlAttr):
577    def _print_attr_value(self):
578        return " stats={...}"
579
580
581class NlAttrCacheInfo(NlAttr):
582    def __init__(self, nla_type, data):
583        super().__init__(nla_type, data)
584        self.ci = IfaCacheInfo.from_buffer_copy(data)
585
586    @staticmethod
587    def _validate(data):
588        nla_len, nla_type = struct.unpack("@HH", data[:4])
589        data_len = nla_len - 4
590        if data_len != sizeof(IfaCacheInfo):
591            raise ValueError(
592                "Error validating attr {}: wrong size".format(nla_type)
593            )  # noqa: E501
594
595    def _print_attr_value(self):
596        return " ifa_prefered={} ifa_valid={} cstamp={} tstamp={}".format(
597                self.ci.ifa_prefered, self.ci.ifa_valid, self.ci.cstamp, self.ci.tstamp)
598
599
600class NlAttrVia(NlAttr):
601    def __init__(self, nla_type, family, addr: str):
602        super().__init__(nla_type, b"")
603        self.addr = addr
604        self.family = family
605
606    @staticmethod
607    def _validate(data):
608        nla_len, nla_type = struct.unpack("@HH", data[:4])
609        data_len = nla_len - 4
610        if data_len == 0:
611            raise ValueError(
612                "Error validating attr {}: empty data".format(nla_type)
613            )  # noqa: E501
614        family = int(data_len[0])
615        if family not in (socket.AF_INET, socket.AF_INET6):
616            raise ValueError(
617                "Error validating attr {}: unsupported AF {}".format(  # noqa: E501
618                    nla_type, family
619                )
620            )
621        if family == socket.AF_INET:
622            expected_len = 1 + 4
623        else:
624            expected_len = 1 + 16
625        if data_len != expected_len:
626            raise ValueError(
627                "Error validating attr {}: expected len {} got {}".format(  # noqa: E501
628                    nla_type, expected_len, data_len
629                )
630            )
631
632    @property
633    def nla_len(self):
634        if self.family == socket.AF_INET6:
635            return 21
636        else:
637            return 9
638
639    @classmethod
640    def _parse(cls, data):
641        nla_len, nla_type, family = struct.unpack("@HHB", data[:5])
642        off = 5
643        if family == socket.AF_INET:
644            addr = socket.inet_ntop(family, data[off:off + 4])
645        else:
646            addr = socket.inet_ntop(family, data[off:off + 16])
647        return cls(nla_type, family, addr)
648
649    def __bytes__(self):
650        addr = socket.inet_pton(self.family, self.addr)
651        return self._to_bytes(struct.pack("@B", self.family) + addr)
652
653    def _print_attr_value(self):
654        return " via={}".format(self.addr)
655
656
657rtnl_route_attrs = prepare_attrs_map(
658    [
659        AttrDescr(RtattrType.RTA_DST, NlAttrIp),
660        AttrDescr(RtattrType.RTA_SRC, NlAttrIp),
661        AttrDescr(RtattrType.RTA_IIF, NlAttrIfindex),
662        AttrDescr(RtattrType.RTA_OIF, NlAttrIfindex),
663        AttrDescr(RtattrType.RTA_GATEWAY, NlAttrIp),
664        AttrDescr(RtattrType.RTA_TABLE, NlAttrTable),
665        AttrDescr(RtattrType.RTA_PRIORITY, NlAttrU32),
666        AttrDescr(RtattrType.RTA_VIA, NlAttrVia),
667        AttrDescr(RtattrType.RTA_NH_ID, NlAttrNhId),
668        AttrDescr(RtattrType.RTA_KNH_ID, NlAttrKNhId),
669        AttrDescr(RtattrType.RTA_RTFLAGS, NlAttrRtFlags),
670        AttrDescr(
671            RtattrType.RTA_METRICS,
672            NlAttrNested,
673            [
674                AttrDescr(NlRtaxType.RTAX_MTU, NlAttrU32),
675            ],
676        ),
677    ]
678)
679
680rtnl_iflaf_vf_driver_field_attrs = [
681    AttrDescr(IflafVfDriverFieldType.IFLAF_VFDF_NAME, NlAttrStr),
682    AttrDescr(IflafVfDriverFieldType.IFLAF_VFDF_BOOL, NlAttrU8),
683    AttrDescr(IflafVfDriverFieldType.IFLAF_VFDF_NUMBER, NlAttrU64),
684    AttrDescr(IflafVfDriverFieldType.IFLAF_VFDF_STRING, NlAttrStr),
685    AttrDescr(IflafVfDriverFieldType.IFLAF_VFDF_BINARY, NlAttr),
686]
687
688rtnl_iflaf_vf_driver_attrs = [
689    AttrDescr(IflafVfDriverType.IFLAF_VFD_NAME, NlAttrStr),
690    AttrDescr(IflafVfDriverType.IFLAF_VFD_VERSION, NlAttrU32),
691    AttrDescr(
692        IflafVfDriverType.IFLAF_VFD_FIELD,
693        NlAttrNested,
694        rtnl_iflaf_vf_driver_field_attrs,
695    ),
696]
697
698rtnl_iflaf_vf_attrs = [
699    AttrDescr(IflafVfType.IFLAF_VF_INDEX, NlAttrU32),
700    AttrDescr(IflafVfType.IFLAF_VF_CONFIGURED, NlAttrU8),
701    AttrDescr(IflafVfType.IFLAF_VF_INITIALIZED, NlAttrU8),
702    AttrDescr(IflafVfType.IFLAF_VF_MAC, NlAttrMac),
703    AttrDescr(IflafVfType.IFLAF_VF_VLAN_MODE, NlAttrU8),
704    AttrDescr(IflafVfType.IFLAF_VF_VLAN, NlAttrU16),
705    AttrDescr(IflafVfType.IFLAF_VF_VLAN_PCP, NlAttrU8),
706    AttrDescr(IflafVfType.IFLAF_VF_VLAN_PROTO, NlAttrU16),
707    AttrDescr(IflafVfType.IFLAF_VF_VLAN_COUNT, NlAttrU32),
708    AttrDescr(IflafVfType.IFLAF_VF_VLAN_LIMIT, NlAttrU32),
709    AttrDescr(IflafVfType.IFLAF_VF_NUM_TX_QUEUES, NlAttrU16),
710    AttrDescr(IflafVfType.IFLAF_VF_NUM_RX_QUEUES, NlAttrU16),
711    AttrDescr(IflafVfType.IFLAF_VF_MIN_TX_RATE, NlAttrU64),
712    AttrDescr(IflafVfType.IFLAF_VF_MAX_TX_RATE, NlAttrU64),
713    AttrDescr(IflafVfType.IFLAF_VF_ALLOW_SET_MAC, NlAttrU8),
714    AttrDescr(IflafVfType.IFLAF_VF_ALLOW_SET_VLAN, NlAttrU8),
715    AttrDescr(IflafVfType.IFLAF_VF_MAC_ANTI_SPOOF, NlAttrU8),
716    AttrDescr(IflafVfType.IFLAF_VF_ALLOW_PROMISC, NlAttrU8),
717    AttrDescr(IflafVfType.IFLAF_VF_TRAFFIC_ALLOWED, NlAttrU8),
718    AttrDescr(IflafVfType.IFLAF_VF_FAULT_BLOCKED, NlAttrU8),
719    AttrDescr(IflafVfType.IFLAF_VF_QUARANTINED, NlAttrU8),
720    AttrDescr(IflafVfType.IFLAF_VF_API_VERSION, NlAttrStr),
721    AttrDescr(IflafVfType.IFLAF_VF_LINK_STATE_POLICY, NlAttrU8),
722    AttrDescr(
723        IflafVfType.IFLAF_VF_DRIVER,
724        NlAttrNested,
725        rtnl_iflaf_vf_driver_attrs,
726    ),
727]
728
729rtnl_iflaf_vf_status_attrs = [
730    AttrDescr(IflafVfStatusType.IFLAF_VFS_ERROR, NlAttrU32),
731    AttrDescr(IflafVfStatusType.IFLAF_VFS_PF_LINK_STATE, NlAttrU8),
732    AttrDescr(IflafVfStatusType.IFLAF_VFS_PF_LINK_SPEED, NlAttrU64),
733]
734
735rtnl_ifla_attrs = prepare_attrs_map(
736    [
737        AttrDescr(IflattrType.IFLA_ADDRESS, NlAttrMac),
738        AttrDescr(IflattrType.IFLA_BROADCAST, NlAttrMac),
739        AttrDescr(IflattrType.IFLA_IFNAME, NlAttrStr),
740        AttrDescr(IflattrType.IFLA_MTU, NlAttrU32),
741        AttrDescr(IflattrType.IFLA_LINK, NlAttrU32),
742        AttrDescr(IflattrType.IFLA_PROMISCUITY, NlAttrU32),
743        AttrDescr(IflattrType.IFLA_OPERSTATE, NlAttrU8),
744        AttrDescr(IflattrType.IFLA_CARRIER, NlAttrU8),
745        AttrDescr(IflattrType.IFLA_IFALIAS, NlAttrStr),
746        AttrDescr(IflattrType.IFLA_NUM_VF, NlAttrU32),
747        AttrDescr(IflattrType.IFLA_STATS64, NlAttrIfStats),
748        AttrDescr(IflattrType.IFLA_NEW_IFINDEX, NlAttrU32),
749        AttrDescr(
750            IflattrType.IFLA_LINKINFO,
751            NlAttrNested,
752            [
753                AttrDescr(IflinkInfo.IFLA_INFO_KIND, NlAttrStr),
754                AttrDescr(IflinkInfo.IFLA_INFO_DATA, NlAttr),
755            ],
756        ),
757        AttrDescr(
758            IflattrType.IFLA_FREEBSD,
759            NlAttrNested,
760            [
761                AttrDescr(IflafAttrType.IFLAF_ORIG_HWADDR, NlAttrMac),
762                AttrDescr(
763                    IflafAttrType.IFLAF_VF_STATUS,
764                    NlAttrNested,
765                    rtnl_iflaf_vf_status_attrs,
766                ),
767            ],
768        ),
769        AttrDescr(
770            IflattrType.IFLA_FREEBSD_VF,
771            NlAttrNested,
772            rtnl_iflaf_vf_attrs,
773        ),
774    ]
775)
776
777rtnl_ifa_attrs = prepare_attrs_map(
778    [
779        AttrDescr(IfaAttrType.IFA_ADDRESS, NlAttrIp),
780        AttrDescr(IfaAttrType.IFA_LOCAL, NlAttrIp),
781        AttrDescr(IfaAttrType.IFA_LABEL, NlAttrStr),
782        AttrDescr(IfaAttrType.IFA_BROADCAST, NlAttrIp),
783        AttrDescr(IfaAttrType.IFA_ANYCAST, NlAttrIp),
784        AttrDescr(IfaAttrType.IFA_FLAGS, NlAttrU32),
785        AttrDescr(IfaAttrType.IFA_CACHEINFO, NlAttrCacheInfo),
786        AttrDescr(
787            IfaAttrType.IFA_FREEBSD,
788            NlAttrNested,
789            [
790                AttrDescr(IfafAttrType.IFAF_VHID, NlAttrU32),
791                AttrDescr(IfafAttrType.IFAF_FLAGS, NlAttrU32),
792            ],
793        ),
794    ]
795)
796
797
798rtnl_nd_attrs = prepare_attrs_map(
799    [
800        AttrDescr(NdAttrType.NDA_DST, NlAttrIp),
801        AttrDescr(NdAttrType.NDA_IFINDEX, NlAttrIfindex),
802        AttrDescr(NdAttrType.NDA_FLAGS_EXT, NlAttrU32),
803        AttrDescr(NdAttrType.NDA_LLADDR, NlAttrMac),
804    ]
805)
806
807
808class BaseNetlinkRtMessage(StdNetlinkMessage):
809    pass
810
811
812class NetlinkRtMessage(BaseNetlinkRtMessage):
813    messages = [
814        NlMsgProps(NlRtMsgType.RTM_NEWROUTE, NlMsgCategory.NEW),
815        NlMsgProps(NlRtMsgType.RTM_DELROUTE, NlMsgCategory.DELETE),
816        NlMsgProps(NlRtMsgType.RTM_GETROUTE, NlMsgCategory.GET),
817    ]
818    nl_attrs_map = rtnl_route_attrs
819
820    def __init__(self, helper, nlm_type):
821        super().__init__(helper, nlm_type)
822        self.base_hdr = RtMsgHdr()
823
824    def parse_base_header(self, data):
825        if len(data) < sizeof(RtMsgHdr):
826            raise ValueError("length less than rtmsg header")
827        rtm_hdr = RtMsgHdr.from_buffer_copy(data)
828        return (rtm_hdr, sizeof(RtMsgHdr))
829
830    def print_base_header(self, hdr, prepend=""):
831        family = self.helper.get_af_name(hdr.rtm_family)
832        print(
833            "{}family={}, dst_len={}, src_len={}, tos={}, table={}, protocol={}({}), scope={}({}), type={}({}), flags={}({})".format(  # noqa: E501
834                prepend,
835                family,
836                hdr.rtm_dst_len,
837                hdr.rtm_src_len,
838                hdr.rtm_tos,
839                hdr.rtm_table,
840                self.helper.get_attr_byval(RtProto, hdr.rtm_protocol),
841                hdr.rtm_protocol,
842                self.helper.get_attr_byval(RtScope, hdr.rtm_scope),
843                hdr.rtm_scope,
844                self.helper.get_attr_byval(RtType, hdr.rtm_type),
845                hdr.rtm_type,
846                self.helper.get_bitmask_str(RtMsgFlags, hdr.rtm_flags),
847                hdr.rtm_flags,
848            )
849        )
850
851
852class NetlinkIflaMessage(BaseNetlinkRtMessage):
853    messages = [
854        NlMsgProps(NlRtMsgType.RTM_NEWLINK, NlMsgCategory.NEW),
855        NlMsgProps(NlRtMsgType.RTM_DELLINK, NlMsgCategory.DELETE),
856        NlMsgProps(NlRtMsgType.RTM_GETLINK, NlMsgCategory.GET),
857    ]
858    nl_attrs_map = rtnl_ifla_attrs
859
860    def __init__(self, helper, nlm_type):
861        super().__init__(helper, nlm_type)
862        self.base_hdr = IfinfoMsg()
863
864    def parse_base_header(self, data):
865        if len(data) < sizeof(IfinfoMsg):
866            raise ValueError("length less than IfinfoMsg header")
867        rtm_hdr = IfinfoMsg.from_buffer_copy(data)
868        return (rtm_hdr, sizeof(IfinfoMsg))
869
870    def print_base_header(self, hdr, prepend=""):
871        family = self.helper.get_af_name(hdr.ifi_family)
872        print(
873            "{}family={}, ifi_type={}, ifi_index={}, ifi_flags={}, ifi_change={}".format(  # noqa: E501
874                prepend,
875                family,
876                hdr.ifi_type,
877                hdr.ifi_index,
878                hdr.ifi_flags,
879                hdr.ifi_change,
880            )
881        )
882
883
884class NetlinkIfaMessage(BaseNetlinkRtMessage):
885    messages = [
886        NlMsgProps(NlRtMsgType.RTM_NEWADDR, NlMsgCategory.NEW),
887        NlMsgProps(NlRtMsgType.RTM_DELADDR, NlMsgCategory.DELETE),
888        NlMsgProps(NlRtMsgType.RTM_GETADDR, NlMsgCategory.GET),
889    ]
890    nl_attrs_map = rtnl_ifa_attrs
891
892    def __init__(self, helper, nlm_type):
893        super().__init__(helper, nlm_type)
894        self.base_hdr = IfaddrMsg()
895
896    def parse_base_header(self, data):
897        if len(data) < sizeof(IfaddrMsg):
898            raise ValueError("length less than IfaddrMsg header")
899        rtm_hdr = IfaddrMsg.from_buffer_copy(data)
900        return (rtm_hdr, sizeof(IfaddrMsg))
901
902    def print_base_header(self, hdr, prepend=""):
903        family = self.helper.get_af_name(hdr.ifa_family)
904        print(
905            "{}family={}, ifa_prefixlen={}, ifa_flags={}, ifa_scope={}, ifa_index={}".format(  # noqa: E501
906                prepend,
907                family,
908                hdr.ifa_prefixlen,
909                hdr.ifa_flags,
910                hdr.ifa_scope,
911                hdr.ifa_index,
912            )
913        )
914
915
916class NetlinkNdMessage(BaseNetlinkRtMessage):
917    messages = [
918        NlMsgProps(NlRtMsgType.RTM_NEWNEIGH, NlMsgCategory.NEW),
919        NlMsgProps(NlRtMsgType.RTM_DELNEIGH, NlMsgCategory.DELETE),
920        NlMsgProps(NlRtMsgType.RTM_GETNEIGH, NlMsgCategory.GET),
921    ]
922    nl_attrs_map = rtnl_nd_attrs
923
924    def __init__(self, helper, nlm_type):
925        super().__init__(helper, nlm_type)
926        self.base_hdr = NdMsg()
927
928    def parse_base_header(self, data):
929        if len(data) < sizeof(NdMsg):
930            raise ValueError("length less than NdMsg header")
931        nd_hdr = NdMsg.from_buffer_copy(data)
932        return (nd_hdr, sizeof(NdMsg))
933
934    def print_base_header(self, hdr, prepend=""):
935        family = self.helper.get_af_name(hdr.ndm_family)
936        print(
937            "{}family={}, ndm_ifindex={}, ndm_state={}, ndm_flags={}".format(  # noqa: E501
938                prepend,
939                family,
940                hdr.ndm_ifindex,
941                hdr.ndm_state,
942                hdr.ndm_flags,
943            )
944        )
945
946
947handler_classes = {
948    "netlink_route": [
949        NetlinkRtMessage,
950        NetlinkIflaMessage,
951        NetlinkIfaMessage,
952        NetlinkNdMessage,
953    ],
954}
955