3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
5 # Author: Scott Feldman, sfeldma@cumulusnetworks.com
6 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
9 from socket
import NETLINK_ROUTE
, AF_INET
, AF_INET6
10 from string
import printable
16 logger
= logging
.getLogger(__name__
)
19 # from /usr/include/linux/rtnetlink.h
23 RTMGRP_IPV4_IFADDR
= 0x10
24 RTMGRP_IPV4_ROUTE
= 0x40
25 RTMGRP_IPV6_IFADDR
= 0x100
26 RTMGRP_IPV6_ROUTE
= 0x400
39 # Definitions used in routing table administration.
41 class Nlmsg(Structure
):
44 return string_at(addressof(self
), sizeof(self
))
46 def __eq__(self
, other
):
47 return self
._stringify
() == other
._stringify
() and \
48 self
.__dict
__ == other
.__dict
__
51 return Rtattr
.from_address(addressof(self
) + NLMSG_ALIGN(sizeof(self
)))
53 def pack_extra(self
, extra
, addr
):
54 memmove(addr
, addressof(extra
), sizeof(extra
))
55 return NLMSG_ALIGN(sizeof(extra
))
57 def pack_rtas(self
, rtas
, addr
):
59 for rta_type
, value
in rtas
.iteritems():
60 rta
= Rtattr
.from_address(addr
)
61 rta
.rta_type
= rta_type
62 pack_fn
= self
.rta_fn(rta_type
)
63 rta_len
= NLMSG_ALIGN(pack_fn(rta
, value
))
68 def pack_rtas_new(self
, rtas
, addr
, policy
):
71 for rta_type
, value
in rtas
.iteritems():
72 if type(value
) == dict:
73 rta
= Rtattr
.from_address(addr
)
74 rta
.rta_type
= rta_type
75 rta
.rta_len
= RTA_LENGTH(0)
76 rta_len
= NLMSG_ALIGN(rta
.rta_len
)
79 pack_fn
= policy
.get(rta_type
)
80 rta_len
= NLMSG_ALIGN(pack_fn(addr
, value
))
82 rta
.rta_len
+= rta_len
84 rta
= Rtattr
.from_address(addr
)
85 rta
.rta_type
= rta_type
86 pack_fn
= policy
.get(rta_type
)
87 rta_len
= NLMSG_ALIGN(pack_fn(rta
, value
))
92 def rta_linkinfo(self
, addr
, rtas
):
95 # Check interface kind
96 kind
= rtas
.get(IFLA_INFO_KIND
)
98 data_policy
= self
.rta_linkinfo_data_vlan_policy()
100 data_policy
= self
.rta_linkinfo_data_macvlan_policy()
103 rta
= Rtattr
.from_address(addr
)
104 rta
.rta_type
= IFLA_INFO_KIND
105 rta_len
= NLMSG_ALIGN(self
.rta_string(rta
, kind
))
109 # nest start link info data
110 rta
= Rtattr
.from_address(addr
)
111 rta
.rta_type
= IFLA_INFO_DATA
112 rta
.rta_len
= RTA_LENGTH(0)
113 rta_len
= NLMSG_ALIGN(rta
.rta_len
)
116 rta_len
= self
.pack_rtas_new(rtas
.get(IFLA_INFO_DATA
), addr
,
118 rta
.rta_len
+= rta_len
125 def rta_bridge_vlan_info(self
, rta
, value
):
128 memmove(data
, addressof(value
), sizeof(value
))
129 rta
.rta_len
= RTA_LENGTH(sizeof(value
))
132 def rta_af_spec(self
, addr
, rtas
):
135 # XXX: Check family (Assumes bridge family for now)
136 rta_len
= self
.pack_rtas_new(rtas
, addr
,
137 self
.rta_bridge_af_spec_policy())
141 def unpack_rtas(self
, which_ones
=[]):
142 len = self
.nlh
.nlmsg_len
- NLMSG_LENGTH(sizeof(self
))
145 while RTA_OK(rta
, len):
146 rta_type
= rta
.rta_type
147 if not which_ones
or rta_type
in which_ones
:
148 unpack_fn
= self
.rta_fn(rta_type
)
149 rtas
[rta_type
] = unpack_fn(rta
)
150 len, rta
= RTA_NEXT(rta
, len)
154 rtas
= self
.unpack_rtas()
155 for type, value
in rtas
.iteritems():
156 print "rta", type, ":", value
158 class _IPv6Addr(BigEndianStructure
):
164 class _IPv4Addr(BigEndianStructure
):
169 def rta_uint8(self
, rta
, value
=None):
172 c_uint8
.from_address(data
).value
= value
173 rta
.rta_len
= RTA_LENGTH(sizeof(c_uint8
))
176 return c_uint8
.from_address(data
).value
178 def rta_uint16(self
, rta
, value
=None):
181 c_uint16
.from_address(data
).value
= value
182 rta
.rta_len
= RTA_LENGTH(sizeof(c_uint16
))
185 return c_uint16
.from_address(data
).value
187 def rta_uint32(self
, rta
, value
=None):
190 c_uint32
.from_address(data
).value
= value
191 rta
.rta_len
= RTA_LENGTH(sizeof(c_uint32
))
194 return c_uint32
.from_address(data
).value
196 def rta_string(self
, rta
, value
=None):
199 s
= create_string_buffer(value
)
200 memmove(data
, addressof(s
), len(value
))
201 rta
.rta_len
= RTA_LENGTH(len(value
))
204 return c_char_p(data
).value
206 def rta_addr(self
, rta
, value
=None):
209 if isinstance(value
, IPv4Address
):
210 self
._IPv
4Addr
.from_address(data
).addr
= value
._ip
211 rta
.rta_len
= RTA_LENGTH(sizeof(self
._IPv
4Addr
))
212 elif isinstance(value
, IPv6Address
):
213 addr
= self
._IPv
6Addr
.from_address(data
)
214 addr
.upper
= value
._ip
>> 64
215 addr
.lower
= value
._ip
& 0xffffffffffffffff
216 rta
.rta_len
= RTA_LENGTH(sizeof(self
._IPv
6Addr
))
221 if RTA_PAYLOAD(rta
) == 4:
222 addr
= c_uint32
.__ctype_be__
.from_address(data
).value
223 addr
= IPv4Address(addr
)
225 addr
= self
._IPv
6Addr
.from_address(data
)
226 addr
= IPv6Address((addr
.upper
<< 64) + addr
.lower
)
229 def rta_uint8_array(self
, rta
, value
=None):
232 s
= (c_uint8
* len(value
)).from_buffer_copy(value
)
233 memmove(data
, addressof(s
), len(value
))
234 rta
.rta_len
= RTA_LENGTH(len(value
))
237 array
= (c_uint8
* RTA_PAYLOAD(rta
))()
238 memmove(array
, data
, RTA_PAYLOAD(rta
))
241 def rta_uint32_array(self
, rta
, value
=None):
246 size
= RTA_PAYLOAD(rta
) / sizeof(c_uint32
)
247 array
= (c_uint32
* size
)()
248 memmove(array
, data
, RTA_PAYLOAD(rta
))
251 def rta_multipath(self
, rta
, value
=None):
255 def rta_wtf(self
, rta
, value
=None):
258 def rta_none(self
, rta
, value
=None):
261 def rta_fn(self
, rta_type
):
268 RTN_UNICAST
= 1 # Gateway or direct route
269 RTN_LOCAL
= 2 # Accept locally
270 RTN_BROADCAST
= 3 # Accept locally as broadcast,
272 RTN_ANYCAST
= 4 # Accept locally as broadcast,
273 # but send as unicast
274 RTN_MULTICAST
= 5 # Multicast route
275 RTN_BLACKHOLE
= 6 # Drop
276 RTN_UNREACHABLE
= 7 # Destination is unreachable
277 RTN_PROHIBIT
= 8 # Administratively prohibited
278 RTN_THROW
= 9 # Not in this table
279 RTN_NAT
= 10 # Translate this address
280 RTN_XRESOLVE
= 11 # Use external resolver
286 RTPROT_REDIRECT
= 1 # Route installed by ICMP redirects;
287 # not used by current IPv4
288 RTPROT_KERNEL
= 2 # Route installed by kernel
289 RTPROT_BOOT
= 3 # Route installed during boot
290 RTPROT_STATIC
= 4 # Route installed by administrator
292 # Values of protocol >= RTPROT_STATIC are not interpreted by kernel;
293 # they are just passed from user and back as is.
294 # It will be used by hypothetical multiple routing daemons.
295 # Note that protocol values should be standardized in order to
298 RTPROT_GATED
= 8 # Apparently, GateD
299 RTPROT_RA
= 9 # RDISC/ND router advertisements
300 RTPROT_MRT
= 10 # Merit MRT
301 RTPROT_ZEBRA
= 11 # Zebra
302 RTPROT_BIRD
= 12 # BIRD
303 RTPROT_DNROUTED
= 13 # DECnet routing daemon
304 RTPROT_XORP
= 14 # XORP
305 RTPROT_NTK
= 15 # Netsukuku
306 RTPROT_DHCP
= 16 # DHCP client
310 # Really it is not scope, but sort of distance to the destination.
311 # NOWHERE are reserved for not existing destinations, HOST is our
312 # local addresses, LINK are destinations, located on directly attached
313 # link and UNIVERSE is everywhere in the Universe.
315 # Intermediate values are also possible f.e. interior routes
316 # could be assigned a value between UNIVERSE and LINK.
318 RT_SCOPE_UNIVERSE
= 0
319 # User defined values
327 RTM_F_NOTIFY
= 0x100 # Notify user of route change
328 RTM_F_CLONED
= 0x200 # This route is cloned
329 RTM_F_EQUALIZE
= 0x400 # Multipath equalizer: NI
330 RTM_F_PREFIX
= 0x800 # Prefix addresses
332 # Reserved table identifiers
335 # User defined values
336 RT_TABLE_COMPAT
= 252
337 RT_TABLE_DEFAULT
= 253
340 RT_TABLE_MAX
= 0xFFFFFFFF
342 # Generic structure for encapsulation of optional route information.
343 # It is reminiscent of sockaddr, but with sa_family replaced
344 # with attribute type.
346 class Rtattr(Structure
):
349 ('rta_len', c_uint16
),
350 ('rta_type', c_uint16
),
353 # Routing message attributes
365 RTA_PROTOINFO
= 10 # no longer used
368 RTA_SESSION
= 13 # no longer used
369 RTA_MP_ALGO
= 14 # no longer used
373 # Macros to handle rtattributes
377 return (len + RTA_ALIGNTO
- 1) & ~
(RTA_ALIGNTO
- 1)
378 def RTA_OK(rta
, len):
379 return len >= sizeof(Rtattr
) and \
380 rta
.rta_len
>= sizeof(Rtattr
) and \
382 def RTA_NEXT(rta
, len):
383 cur
= RTA_ALIGN(rta
.rta_len
)
384 rta
= Rtattr
.from_address(addressof(rta
) + cur
)
385 return len - cur
, rta
387 return len + RTA_ALIGN(sizeof(Rtattr
))
389 return RTA_ALIGN(RTA_LENGTH(len))
391 return addressof(rta
) + RTA_LENGTH(0)
392 def RTA_PAYLOAD(rta
):
393 return rta
.rta_len
- RTA_LENGTH(0)
395 RTNH_F_DEAD
= 1 # Nexthop is dead (used by multipath)
396 RTNH_F_PERVASIVE
= 2 # Do recursive gateway lookup
397 RTNH_F_ONLINK
= 4 # Gateway is forced on link
399 # Reserved table identifiers
402 # User defined values
403 RT_TABLE_COMPAT
= 252
404 RT_TABLE_DEFAULT
= 253
407 RT_TABLE_MAX
= 0xFFFFFFFF
412 ('rtm_family', c_uint8
),
413 ('rtm_dst_len', c_uint8
),
414 ('rtm_src_len', c_uint8
),
415 ('rtm_tos', c_uint8
),
416 ('rtm_table', c_uint8
),
417 ('rtm_protocol', c_uint8
),
418 ('rtm_scope', c_uint8
),
419 ('rtm_type', c_uint8
),
420 ('rtm_flags', c_uint32
),
424 RT_TABLE_UNSPEC
: "unspecified",
425 RT_TABLE_COMPAT
: "compat",
426 RT_TABLE_DEFAULT
: "default",
427 RT_TABLE_MAIN
: "main",
428 RT_TABLE_LOCAL
: "local",
432 RTPROT_UNSPEC
: "none",
433 RTPROT_REDIRECT
: "redirect",
434 RTPROT_KERNEL
: "kernel",
436 RTPROT_STATIC
: "static",
437 RTPROT_GATED
: "gated",
439 RTPROT_MRT
: "mrtmrt",
440 RTPROT_ZEBRA
: "zebra",
442 RTPROT_DNROUTED
: "dnrouted",
449 RT_SCOPE_UNIVERSE
: "universe",
450 RT_SCOPE_SITE
: "site",
451 RT_SCOPE_LINK
: "link",
452 RT_SCOPE_HOST
: "host",
453 RT_SCOPE_NOWHERE
: "nowhere",
457 RTN_UNSPEC
: "unspecified",
458 RTN_UNICAST
: "unicast",
460 RTN_BROADCAST
: "broadcast",
461 RTN_ANYCAST
: "anycast",
462 RTN_MULTICAST
: "multicast",
463 RTN_BLACKHOLE
: "blackhole",
464 RTN_UNREACHABLE
: "unreachable",
465 RTN_PROHIBIT
: "prohibit",
468 RTN_XRESOLVE
: "xresolve",
472 print 'rtm_family', self
.rtm_family
473 print 'rtm_dst_len', self
.rtm_dst_len
474 print 'rtm_src_len', self
.rtm_src_len
475 print 'rtm_tos', self
.rtm_tos
476 print 'rtm_table', self
._table
_str
.get(self
.rtm_table
, self
.rtm_table
)
477 print 'rtm_protocol', self
._proto
_str
.get(self
.rtm_protocol
)
478 print 'rtm_scope', self
._scope
_str
.get(self
.rtm_scope
)
479 print 'rtm_type', self
._type
_str
.get(self
.rtm_type
)
480 print 'rtm_flags 0x%08x' % self
.rtm_flags
482 def rta_fn(self
, rta_type
):
484 RTA_DST
: self
.rta_addr
,
485 RTA_SRC
: self
.rta_addr
,
486 RTA_IIF
: self
.rta_uint32
,
487 RTA_OIF
: self
.rta_uint32
,
488 RTA_GATEWAY
: self
.rta_addr
,
489 RTA_PRIORITY
: self
.rta_uint32
,
490 RTA_PREFSRC
: self
.rta_addr
,
491 RTA_METRICS
: self
.rta_uint32_array
,
492 RTA_MULTIPATH
: self
.rta_multipath
,
493 RTA_PROTOINFO
: self
.rta_none
,
494 RTA_FLOW
: self
.rta_uint32
,
495 RTA_CACHEINFO
: self
.rta_none
,
496 RTA_SESSION
: self
.rta_none
,
497 RTA_MP_ALGO
: self
.rta_none
,
498 RTA_TABLE
: self
.rta_uint32
,
501 return fns
.get(rta_type
)
503 class Rtgenmsg(Nlmsg
):
506 ('rtgen_family', c_uint8
),
510 print 'rtgen_family', self
.rtgen_family
512 # New extended info filters for IFLA_EXT_MASK
513 RTEXT_FILTER_VF
= (1 << 0)
515 # passes link level specific information, not dependent
516 # on network protocol.
529 IFLA_WIRELESS
= 11 # Wireless Extension event - see wireless.h
530 IFLA_PROTINFO
= 12 # Protocol specific information for a link
539 IFLA_NUM_VF
= 21 # Number of VFs if device is SR-IOV PF
540 IFLA_VFINFO_LIST
= 22
545 IFLA_GROUP
= 27 # Group the device belongs to
547 IFLA_EXT_MASK
= 29 # Extended info mask, VFs, etc
551 # IFLA_LINKINFO attributes
558 # IFLA_LINKINFO_DATA attributes for vlan
562 # IFLA_LINKINFO_DATA attributes for macvlan
563 IFLA_MACVLAN_UNSPEC
= 0
564 IFLA_MACVLAN_MODE
= 1
567 MACVLAN_MODE_PRIVATE
= 1
568 MACVLAN_MODE_VEPA
= 2
569 MACVLAN_MODE_BRIDGE
= 3
570 MACVLAN_MODE_PASSTHRU
= 4
572 # BRIDGE IFLA_AF_SPEC attributes
573 IFLA_BRIDGE_FLAGS
= 0
575 IFLA_BRIDGE_VLAN_INFO
= 2
577 # BRIDGE_VLAN_INFO flags
578 BRIDGE_VLAN_INFO_MASTER
= 1
579 BRIDGE_VLAN_INFO_PVID
= 2
580 BRIDGE_VLAN_INFO_UNTAGGED
= 4
583 BRIDGE_FLAGS_MASTER
= 1
584 BRIDGE_FLAGS_SELF
= 2
586 class BridgeVlanInfo(Structure
):
590 ('vid_end', c_uint16
),
593 class Ifinfomsg(Nlmsg
):
596 ('ifi_family', c_uint8
),
597 ('__ifi_pad', c_uint8
),
598 ('ifi_type', c_uint16
), # ARPHRD_*
599 ('ifi_index', c_int32
), # Link index
600 ('ifi_flags', c_uint32
), # IFF_* flags
601 ('ifi_change', c_uint32
), # IFF_* change mask
605 print 'ifi_family', self
.ifi_family
606 print 'ifi_type', self
.ifi_type
607 print 'ifi_index', self
.ifi_index
608 print 'ifi_flags 0x%08x' % self
.ifi_flags
609 print 'ifi_change 0x%08x' % self
.ifi_change
611 def rta_linkinfo_data_vlan_policy(self
):
613 IFLA_VLAN_ID
: self
.rta_uint16
,
617 def rta_linkinfo_data_macvlan_policy(self
):
619 IFLA_MACVLAN_MODE
: self
.rta_uint32
,
623 def rta_linkinfo_policy(self
):
625 IFLA_INFO_KIND
: self
.rta_string
,
626 IFLA_INFO_DATA
: self
.rta_linkinfo_data
,
630 def rta_bridge_af_spec_policy(self
):
631 # Assume bridge family for now
633 IFLA_BRIDGE_FLAGS
: self
.rta_uint16
,
634 IFLA_BRIDGE_VLAN_INFO
: self
.rta_bridge_vlan_info
,
638 def rta_policy(self
):
640 IFLA_UNSPEC
: self
.rta_wtf
,
641 IFLA_ADDRESS
: self
.rta_uint8_array
,
642 IFLA_BROADCAST
: self
.rta_uint8_array
,
643 IFLA_IFNAME
: self
.rta_string
,
644 IFLA_MTU
: self
.rta_uint32
,
645 IFLA_LINK
: self
.rta_uint32
,
646 IFLA_QDISC
: self
.rta_string
,
647 IFLA_STATS
: self
.rta_none
,
648 IFLA_COST
: self
.rta_none
,
649 IFLA_PRIORITY
: self
.rta_none
,
650 IFLA_MASTER
: self
.rta_uint32
,
651 IFLA_WIRELESS
: self
.rta_none
,
652 IFLA_PROTINFO
: self
.rta_none
,
653 IFLA_TXQLEN
: self
.rta_uint32
,
654 IFLA_MAP
: self
.rta_none
,
655 IFLA_WEIGHT
: self
.rta_uint32
,
656 IFLA_OPERSTATE
: self
.rta_uint8
,
657 IFLA_LINKMODE
: self
.rta_uint8
,
658 IFLA_LINKINFO
: self
.rta_linkinfo
,
659 IFLA_NET_NS_PID
: self
.rta_uint32
,
660 IFLA_IFALIAS
: self
.rta_string
,
661 IFLA_NUM_VF
: self
.rta_uint32
,
662 IFLA_VFINFO_LIST
: self
.rta_none
,
663 IFLA_STATS64
: self
.rta_none
,
664 IFLA_VF_PORTS
: self
.rta_none
,
665 IFLA_PORT_SELF
: self
.rta_none
,
666 IFLA_AF_SPEC
: self
.rta_af_spec
,
667 IFLA_GROUP
: self
.rta_none
,
668 IFLA_NET_NS_FD
: self
.rta_none
,
669 IFLA_EXT_MASK
: self
.rta_none
,
673 def rta_fn(self
, rta_type
):
675 IFLA_UNSPEC
: self
.rta_wtf
,
676 IFLA_ADDRESS
: self
.rta_uint8_array
,
677 IFLA_BROADCAST
: self
.rta_uint8_array
,
678 IFLA_IFNAME
: self
.rta_string
,
679 IFLA_MTU
: self
.rta_uint32
,
680 IFLA_LINK
: self
.rta_uint32
,
681 IFLA_QDISC
: self
.rta_string
,
682 IFLA_STATS
: self
.rta_none
,
683 IFLA_COST
: self
.rta_none
,
684 IFLA_PRIORITY
: self
.rta_none
,
685 IFLA_MASTER
: self
.rta_uint32
,
686 IFLA_WIRELESS
: self
.rta_none
,
687 IFLA_PROTINFO
: self
.rta_none
,
688 IFLA_TXQLEN
: self
.rta_uint32
,
689 IFLA_MAP
: self
.rta_none
,
690 IFLA_WEIGHT
: self
.rta_uint32
,
691 IFLA_OPERSTATE
: self
.rta_uint8
,
692 IFLA_LINKMODE
: self
.rta_uint8
,
693 IFLA_LINKINFO
: self
.rta_linkinfo
,
694 IFLA_NET_NS_PID
: self
.rta_uint32
,
695 IFLA_IFALIAS
: self
.rta_string
,
696 IFLA_NUM_VF
: self
.rta_uint32
,
697 IFLA_VFINFO_LIST
: self
.rta_none
,
698 IFLA_STATS64
: self
.rta_none
,
699 IFLA_VF_PORTS
: self
.rta_none
,
700 IFLA_PORT_SELF
: self
.rta_none
,
701 IFLA_AF_SPEC
: self
.rta_af_spec
,
702 IFLA_GROUP
: self
.rta_none
,
703 IFLA_NET_NS_FD
: self
.rta_none
,
704 IFLA_EXT_MASK
: self
.rta_none
,
706 return fns
.get(rta_type
)
708 # passes address specific information
711 # IFA_ADDRESS is prefix address, rather than local interface address.
712 # It makes no difference for normally configured broadcast interfaces,
713 # but for point-to-point IFA_ADDRESS is DESTINATION address,
714 # local address is supplied in IFA_LOCAL attribute.
726 class Ifaddrmsg(Nlmsg
):
729 ('ifa_family', c_uint8
),
730 ('ifa_prefixlen', c_uint8
), # The prefix length
731 ('ifa_flags', c_uint8
), # Flags
732 ('ifa_scope', c_uint8
), # Address scope
733 ('ifa_index', c_uint32
), # Link index
742 print 'ifa_family', self
.ifa_family
743 print 'ifa_prefixlen', self
.ifa_prefixlen
744 print 'ifa_flags 0x%02x' % self
.ifa_flags
745 print 'ifa_scope', self
.ifa_scope
746 print 'ifa_index', self
.ifa_index
748 def rta_fn(self
, rta_type
):
750 IFA_ADDRESS
: self
.rta_addr
,
751 IFA_LOCAL
: self
.rta_addr
,
752 IFA_LABEL
: self
.rta_string
,
753 IFA_BROADCAST
: self
.rta_addr
,
754 IFA_ANYCAST
: self
.rta_addr
,
755 IFA_CACHEINFO
: self
.rta_none
,
756 IFA_MULTICAST
: self
.rta_addr
,
758 return fns
.get(rta_type
)
760 class RtNetlinkError(Exception):
762 def __init__(self
, message
):
763 Exception.__init
__(self
, message
)
764 logger
.error(message
)
766 class RtNetlink(Netlink
):
768 def __init__(self
, pid
):
769 Netlink
.__init
__(self
, pid
, NETLINK_ROUTE
)
771 _rt_nlmsg_type_str
= {
772 RTM_NEWROUTE
: "RTM_NEWROUTE",
773 RTM_DELROUTE
: "RTM_DELROUTE",
774 RTM_NEWLINK
: "RTM_NEWLINK",
775 RTM_SETLINK
: "RTM_SETLINK",
776 RTM_DELLINK
: "RTM_DELLINK",
777 RTM_GETLINK
: "RTM_GETLINK",
778 RTM_NEWADDR
: "RTM_NEWADDR",
779 RTM_DELADDR
: "RTM_DELADDR",
782 def _hexdump(self
, buf
):
786 nums
= ["%02x" % c
for c
in chunk
]
787 txt
= [chr(c
) if chr(c
) in printable
[:-5] else '.' for c
in chunk
]
788 print " ".join(nums
).ljust(48), "".join(txt
)
791 nlmsg
= self
.nlmsg(nlh
)
793 self
._hexdump
(self
.sendbuf
[:nlh
.nlmsg_len
])
801 def nlmsg(self
, nlh
):
806 RTM_NEWLINK
: Ifinfomsg
,
807 RTM_SETLINK
: Ifinfomsg
,
808 RTM_DELLINK
: Ifinfomsg
,
809 RTM_GETLINK
: Rtgenmsg
,
810 RTM_NEWADDR
: Ifaddrmsg
,
811 RTM_DELADDR
: Ifaddrmsg
,
812 RTM_GETADDR
: Rtgenmsg
,
814 nldata
= NLMSG_DATA(nlh
)
815 nlmsg
= nlmsg_struct
[nlh
.nlmsg_type
].from_address(nldata
)
819 def _nl_cb(self
, nlh
):
820 # print "nl cb", self._rt_nlmsg_type_str[nlh.nlmsg_type]
822 if nlh
.nlmsg_type
in self
._cbs
:
824 nlmsg
= self
.nlmsg(nlh
)
827 if nlh
.nlmsg_len
- NLMSG_LENGTH(sizeof(nlmsg
)) < 0:
828 raise RtNetlinkError("invalid nl length")
830 self
._cbs
[nlh
.nlmsg_type
](nlh
, nlmsg
)
832 def bind(self
, groups
, cbs
):
834 Netlink
.bind(self
, groups
, self
._nl
_cb
)
836 def request(self
, nlmsg_type
, flags
, extra
, rtas
={}):
838 nlh
= Nlmsghdr
.from_buffer(self
.sendbuf
)
839 nlh_p
= addressof(nlh
)
844 nlh
.nlmsg_len
= NLMSG_HDRLEN()
845 nlh
.nlmsg_type
= nlmsg_type
846 nlh
.nlmsg_flags
= flags
850 nlmsg
= self
.nlmsg(nlh
)
852 nlh
.nlmsg_len
+= nlmsg
.pack_extra(extra
, nlh_p
+ nlh
.nlmsg_len
)
853 nlh
.nlmsg_len
+= nlmsg
.pack_rtas_new(rtas
, nlh_p
+ nlh
.nlmsg_len
,
856 self
.sendall(string_at(nlh_p
, nlh
.nlmsg_len
))