]> git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/nlmanager/nlpacket.py
This release adds support for the new IPSec Interface XFRM.
[mirror_ifupdown2.git] / ifupdown2 / nlmanager / nlpacket.py
1 # Copyright (c) 2009-2013, Exa Networks Limited
2 # Copyright (c) 2009-2013, Thomas Mangin
3 # Copyright (c) 2015-2017 Cumulus Networks, Inc.
4 #
5 # All rights reserved.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # Redistributions of source code must retain the above copyright notice, this
10 # list of conditions and the following disclaimer.
11 #
12 # Redistributions in binary form must reproduce the above copyright notice,
13 # this list of conditions and the following disclaimer in the documentation
14 # and/or other materials provided with the distribution.
15 #
16 # The names of the Exa Networks Limited, Cumulus Networks, Inc. nor the names
17 # of its contributors may be used to endorse or promote products derived from
18 # this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26 # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 import logging
32 import struct
33 from ipaddr import IPv4Address, IPv6Address, IPAddress
34 from binascii import hexlify
35 from pprint import pformat
36 from socket import AF_UNSPEC, AF_INET, AF_INET6, AF_BRIDGE, htons
37 from string import printable
38 from struct import pack, unpack, calcsize
39
40 log = logging.getLogger(__name__)
41 SYSLOG_EXTRA_DEBUG = 5
42
43
44 # Interface name buffer size #define IFNAMSIZ 16 (kernel source)
45 IF_NAME_SIZE = 15 # 15 because python doesn't have \0
46
47 # Netlink message types
48 NLMSG_NOOP = 0x01
49 NLMSG_ERROR = 0x02
50 NLMSG_DONE = 0x03
51 NLMSG_OVERRUN = 0x04
52
53 RTM_NEWLINK = 0x10 # Create a new network interface
54 RTM_DELLINK = 0x11 # Destroy a network interface
55 RTM_GETLINK = 0x12 # Retrieve information about a network interface(ifinfomsg)
56 RTM_SETLINK = 0x13 #
57
58 RTM_NEWADDR = 0x14
59 RTM_DELADDR = 0x15
60 RTM_GETADDR = 0x16
61
62 RTM_NEWNEIGH = 0x1C
63 RTM_DELNEIGH = 0x1D
64 RTM_GETNEIGH = 0x1E
65
66 RTM_NEWROUTE = 0x18
67 RTM_DELROUTE = 0x19
68 RTM_GETROUTE = 0x1A
69
70 RTM_NEWQDISC = 0x24
71 RTM_DELQDISC = 0x25
72 RTM_GETQDISC = 0x26
73
74 RTM_NEWNETCONF = 80
75 RTM_GETNETCONF = 82
76
77 # Netlink message flags
78 NLM_F_REQUEST = 0x01 # It is query message.
79 NLM_F_MULTI = 0x02 # Multipart message, terminated by NLMSG_DONE
80 NLM_F_ACK = 0x04 # Reply with ack, with zero or error code
81 NLM_F_ECHO = 0x08 # Echo this query
82
83 # Modifiers to GET query
84 NLM_F_ROOT = 0x100 # specify tree root
85 NLM_F_MATCH = 0x200 # return all matching
86 NLM_F_DUMP = NLM_F_ROOT | NLM_F_MATCH
87 NLM_F_ATOMIC = 0x400 # atomic GET
88
89 # Modifiers to NEW query
90 NLM_F_REPLACE = 0x100 # Override existing
91 NLM_F_EXCL = 0x200 # Do not touch, if it exists
92 NLM_F_CREATE = 0x400 # Create, if it does not exist
93 NLM_F_APPEND = 0x800 # Add to end of list
94
95 NLA_F_NESTED = 0x8000
96 NLA_F_NET_BYTEORDER = 0x4000
97 NLA_TYPE_MASK = ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
98
99 # Groups
100 RTMGRP_LINK = 0x1
101 RTMGRP_NOTIFY = 0x2
102 RTMGRP_NEIGH = 0x4
103 RTMGRP_TC = 0x8
104 RTMGRP_IPV4_IFADDR = 0x10
105 RTMGRP_IPV4_MROUTE = 0x20
106 RTMGRP_IPV4_ROUTE = 0x40
107 RTMGRP_IPV4_RULE = 0x80
108 RTMGRP_IPV6_IFADDR = 0x100
109 RTMGRP_IPV6_MROUTE = 0x200
110 RTMGRP_IPV6_ROUTE = 0x400
111 RTMGRP_IPV6_IFINFO = 0x800
112 RTMGRP_DECnet_IFADDR = 0x1000
113 RTMGRP_DECnet_ROUTE = 0x4000
114 RTMGRP_IPV6_PREFIX = 0x20000
115
116 RTMGRP_ALL = (RTMGRP_LINK | RTMGRP_NOTIFY | RTMGRP_NEIGH | RTMGRP_TC |
117 RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_MROUTE | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_RULE |
118 RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_MROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFINFO |
119 RTMGRP_DECnet_IFADDR | RTMGRP_DECnet_ROUTE |
120 RTMGRP_IPV6_PREFIX)
121
122 AF_MPLS = 28
123
124
125 AF_FAMILY = dict()
126
127 import socket
128
129 for family in [attr for attr in dir(socket) if attr.startswith('AF_')]:
130 AF_FAMILY[getattr(socket, family)] = family
131
132 AF_FAMILY[AF_MPLS] = 'AF_MPLS'
133
134
135 def get_family_str(family):
136 return AF_FAMILY.get(family, 'UNKNOWN')
137
138 # Colors for logging
139 red = 91
140 green = 92
141 yellow = 93
142 blue = 94
143
144 value_to_bool_dict = {
145 False: False,
146 None: False,
147 0: False,
148 '0': False,
149 'no': False,
150 'off': False,
151 'slow': False,
152 'None': False,
153 True: True,
154 1: True,
155 '1': True,
156 'on': True,
157 'yes': True,
158 'fast': True
159 }
160
161
162 def set_log_level(level):
163 log.setLevel(level)
164
165
166 def zfilled_hex(value, digits):
167 return '0x' + hex(value)[2:].zfill(digits)
168
169
170 def remove_trailing_null(line):
171 """
172 Remove the last character if it is a NULL...having that NULL
173 causes python to print a garbage character
174 """
175
176 if ord(line[-1]) == 0:
177 line = line[:-1]
178
179 return line
180
181
182 def mac_int_to_str(mac_int):
183 """
184 Return an integer in MAC string format
185 """
186
187 # [2:] to remove the leading 0x, then fill out to 12 zeroes, then uppercase
188 all_caps = hex(int(mac_int))[2:].zfill(12).upper()
189
190 if all_caps[-1] == 'L':
191 all_caps = all_caps[:-1]
192 all_caps = all_caps.zfill(12).upper()
193
194 return "%s.%s.%s" % (all_caps[0:4], all_caps[4:8], all_caps[8:12])
195
196
197 def data_to_color_text(line_number, color, data, extra=''):
198 (c1, c2, c3, c4) = unpack('BBBB', data[0:4])
199 in_ascii = []
200
201 for c in (c1, c2, c3, c4):
202 char_c = chr(c)
203
204 if char_c in printable[:-5]:
205 in_ascii.append(char_c)
206 else:
207 in_ascii.append('.')
208
209 if color:
210 return ' %2d: \033[%dm0x%02x%02x%02x%02x\033[0m %s %s' % (line_number, color, c1, c2, c3, c4, ''.join(in_ascii), extra)
211
212 return ' %2d: 0x%02x%02x%02x%02x %s %s' % (line_number, c1, c2, c3, c4, ''.join(in_ascii), extra)
213
214
215 def padded_length(length):
216 return int((length + 3) / 4) * 4
217
218
219 class Attribute(object):
220
221 def __init__(self, atype, string, logger):
222 self.atype = atype
223 self.string = string
224 self.HEADER_PACK = '=HH'
225 self.HEADER_LEN = calcsize(self.HEADER_PACK)
226 self.PACK = None
227 self.LEN = None
228 self.value = None
229 self.nested = False
230 self.net_byteorder = False
231 self.log = logger
232
233 def __str__(self):
234 return self.string
235
236 def set_value(self, value):
237 self.value = value
238
239 def set_nested(self, nested):
240 self.nested = nested
241
242 def set_net_byteorder(self, net_byteorder):
243 self.net_byteorder = net_byteorder
244
245 def pad_bytes_needed(self, length):
246 """
247 Return the number of bytes that should be added to align on a 4-byte boundry
248 """
249 remainder = length % 4
250
251 if remainder:
252 return 4 - remainder
253
254 return 0
255
256 def pad(self, length, raw):
257 pad = self.pad_bytes_needed(length)
258
259 if pad:
260 raw += '\0' * pad
261
262 return raw
263
264 def encode(self):
265
266 if not self.LEN:
267 raise Exception('Please define an encode() method in your child attribute class, or do not use AttributeGeneric')
268
269 length = self.HEADER_LEN + self.LEN
270 attr_type_with_flags = self.atype
271
272 if self.nested:
273 attr_type_with_flags = attr_type_with_flags | NLA_F_NESTED
274
275 if self.net_byteorder:
276 attr_type_with_flags = attr_type_with_flags | NLA_F_NET_BYTEORDER
277
278 raw = pack(self.HEADER_PACK, length, attr_type_with_flags) + pack(self.PACK, self.value)
279 raw = self.pad(length, raw)
280 return raw
281
282 def decode_length_type(self, data):
283 """
284 The first two bytes of an attribute are the length, the next two bytes are the type
285 """
286 self.data = data
287 prev_atype = self.atype
288 (data1, data2) = unpack(self.HEADER_PACK, data[:self.HEADER_LEN])
289 self.length = int(data1)
290 self.atype = int(data2)
291 self.attr_end = padded_length(self.length)
292
293 self.nested = True if self.atype & NLA_F_NESTED else False
294 self.net_byteorder = True if self.atype & NLA_F_NET_BYTEORDER else False
295 self.atype = self.atype & NLA_TYPE_MASK
296
297 # Should never happen
298 assert self.atype == prev_atype, "This object changes attribute type from %d to %d, this is bad" % (prev_atype, self.atype)
299
300 def dump_first_line(self, dump_buffer, line_number, color):
301 """
302 Add the "Length....Type..." line to the dump buffer
303 """
304 if self.attr_end == self.length:
305 padded_to = ', '
306 else:
307 padded_to = ' padded to %d, ' % self.attr_end
308
309 extra = 'Length %s (%d)%sType %s%s%s (%d) %s' % \
310 (zfilled_hex(self.length, 4), self.length,
311 padded_to,
312 zfilled_hex(self.atype, 4),
313 " (NLA_F_NESTED set)" if self.nested else "",
314 " (NLA_F_NET_BYTEORDER set)" if self.net_byteorder else "",
315 self.atype,
316 self)
317
318 dump_buffer.append(data_to_color_text(line_number, color, self.data[0:4], extra))
319 return line_number + 1
320
321 def dump_lines(self, dump_buffer, line_number, color):
322 line_number = self.dump_first_line(dump_buffer, line_number, color)
323
324 for x in xrange(1, self.attr_end/4):
325 start = x * 4
326 end = start + 4
327 dump_buffer.append(data_to_color_text(line_number, color, self.data[start:end], ''))
328 line_number += 1
329
330 return line_number
331
332 def get_pretty_value(self, obj=None):
333 if obj and callable(obj):
334 return obj(self.value)
335 return self.value
336
337
338 class AttributeFourByteList(Attribute):
339
340 def __init__(self, atype, string, family, logger):
341 Attribute.__init__(self, atype, string, logger)
342
343 def decode(self, parent_msg, data):
344 self.decode_length_type(data)
345 wordcount = (self.attr_end - 4)/4
346 self.PACK = '=%dL' % wordcount
347 self.LEN = calcsize(self.PACK)
348
349 try:
350 self.value = unpack(self.PACK, self.data[4:])
351 except struct.error:
352 self.log.error("%s unpack of %s failed, data 0x%s" % (self, self.PACK, hexlify(self.data[4:])))
353 raise
354
355 def dump_lines(self, dump_buffer, line_number, color):
356 line_number = self.dump_first_line(dump_buffer, line_number, color)
357 idx = 1
358 for val in self.value:
359 dump_buffer.append(data_to_color_text(line_number, color, self.data[4*idx:4*(idx+1)], val))
360 line_number += 1
361 idx += 1
362 return line_number
363
364
365 class AttributeFourByteValue(Attribute):
366
367 def __init__(self, atype, string, family, logger):
368 Attribute.__init__(self, atype, string, logger)
369 self.PACK = '=L'
370 self.LEN = calcsize(self.PACK)
371
372 def decode(self, parent_msg, data):
373 self.decode_length_type(data)
374 assert self.attr_end == 8, "Attribute length for %s must be 8, it is %d" % (self, self.attr_end)
375
376 try:
377 self.value = int(unpack(self.PACK, self.data[4:])[0])
378 except struct.error:
379 self.log.error("%s unpack of %s failed, data 0x%s" % (self, self.PACK, hexlify(self.data[4:])))
380 raise
381
382 def dump_lines(self, dump_buffer, line_number, color):
383 line_number = self.dump_first_line(dump_buffer, line_number, color)
384 dump_buffer.append(data_to_color_text(line_number, color, self.data[4:8], self.value))
385 return line_number + 1
386
387
388 class AttributeTwoByteValue(Attribute):
389
390 def __init__(self, atype, string, family, logger):
391 Attribute.__init__(self, atype, string, logger)
392 self.PACK = '=Hxx'
393 self.LEN = calcsize(self.PACK)
394
395 def decode(self, parent_msg, data):
396 self.decode_length_type(data)
397 assert self.attr_end == 8, "Attribute length for %s must be 8, it is %d" % (self, self.attr_end)
398
399 try:
400 self.value = int(unpack(self.PACK, self.data[4:8])[0])
401 except struct.error:
402 self.log.error("%s unpack of %s failed, data 0x%s" % (self, self.PACK, hexlify(self.data[4:6])))
403 raise
404
405 def encode(self):
406 length = self.HEADER_LEN + self.LEN
407 raw = pack(self.HEADER_PACK, length-2, self.atype) + pack(self.PACK, self.value)
408 raw = self.pad(length, raw)
409 return raw
410
411 def dump_lines(self, dump_buffer, line_number, color):
412 line_number = self.dump_first_line(dump_buffer, line_number, color)
413 dump_buffer.append(data_to_color_text(line_number, color, self.data[4:8], self.value))
414 return line_number + 1
415
416
417 class AttributeString(Attribute):
418
419 def __init__(self, atype, string, family, logger):
420 Attribute.__init__(self, atype, string, logger)
421 self.PACK = None
422 self.LEN = None
423
424 def encode(self):
425 # some interface names come from JSON as unicode strings
426 # and cannot be packed as is so we must convert them to strings
427 if isinstance(self.value, unicode):
428 self.value = str(self.value)
429 self.PACK = '%ds' % len(self.value)
430 self.LEN = calcsize(self.PACK)
431
432 length = self.HEADER_LEN + self.LEN
433 raw = pack(self.HEADER_PACK, length, self.atype) + pack(self.PACK, self.value)
434 raw = self.pad(length, raw)
435 return raw
436
437 def decode(self, parent_msg, data):
438 self.decode_length_type(data)
439 self.PACK = '%ds' % (self.length - 4)
440 self.LEN = calcsize(self.PACK)
441
442 try:
443 self.value = remove_trailing_null(unpack(self.PACK, self.data[4:self.length])[0])
444 except struct.error:
445 self.log.error("%s unpack of %s failed, data 0x%s" % (self, self.PACK, hexlify(self.data[4:self.length])))
446 raise
447
448
449 class AttributeStringInterfaceName(AttributeString):
450
451 def __init__(self, atype, string, family, logger):
452 AttributeString.__init__(self, atype, string, family, logger)
453
454 def set_value(self, value):
455 if value and len(value) > IF_NAME_SIZE:
456 raise Exception('interface name exceeds max length of %d' % IF_NAME_SIZE)
457 self.value = value
458
459
460 class AttributeIPAddress(Attribute):
461
462 def __init__(self, atype, string, family, logger):
463 Attribute.__init__(self, atype, string, logger)
464 self.value_int = None
465 self.value_int_str = None
466 self.family = family
467
468 if self.family == AF_INET:
469 self.PACK = '>L'
470
471 elif self.family == AF_INET6:
472 self.PACK = '>QQ'
473
474 elif self.family == AF_BRIDGE:
475 self.PACK = '>L'
476
477 else:
478 raise Exception("%s is not a supported address family" % self.family)
479
480 self.LEN = calcsize(self.PACK)
481
482 def set_value(self, value):
483 if value is None:
484 self.value = None
485 else:
486 self.value = IPAddress(value)
487
488 def decode(self, parent_msg, data):
489 self.decode_length_type(data)
490
491 try:
492 if self.family == AF_INET:
493 self.value = IPv4Address(unpack(self.PACK, self.data[4:])[0])
494
495 elif self.family == AF_INET6:
496 (data1, data2) = unpack(self.PACK, self.data[4:])
497 self.value = IPv6Address(data1 << 64 | data2)
498
499 elif self.family == AF_BRIDGE:
500 self.value = IPv4Address(unpack(self.PACK, self.data[4:])[0])
501
502 self.value_int = int(self.value)
503 self.value_int_str = str(self.value_int)
504
505 except struct.error:
506 self.value = None
507 self.value_int = None
508 self.value_int_str = None
509 self.log.error("%s unpack of %s failed, data 0x%s" % (self, self.PACK, hexlify(self.data[4:])))
510 raise
511
512 def encode(self):
513 length = self.HEADER_LEN + self.LEN
514
515 if self.family not in [AF_INET, AF_INET6, AF_BRIDGE]:
516 raise Exception("%s is not a supported address family" % self.family)
517
518 raw = pack(self.HEADER_PACK, length, self.atype) + self.value.packed
519 raw = self.pad(length, raw)
520 return raw
521
522 def dump_lines(self, dump_buffer, line_number, color):
523 line_number = self.dump_first_line(dump_buffer, line_number, color)
524
525 if self.family == AF_INET:
526 dump_buffer.append(data_to_color_text(line_number, color, self.data[4:8], self.value))
527 line_number += 1
528
529 elif self.family == AF_INET6:
530
531 for x in xrange(1, self.attr_end/4):
532 start = x * 4
533 end = start + 4
534 dump_buffer.append(data_to_color_text(line_number, color, self.data[start:end], self.value))
535 line_number += 1
536
537 elif self.family == AF_BRIDGE:
538 dump_buffer.append(data_to_color_text(line_number, color, self.data[4:8], self.value))
539 line_number += 1
540
541 return line_number
542
543
544 class AttributeMACAddress(Attribute):
545
546 def __init__(self, atype, string, family, logger):
547 Attribute.__init__(self, atype, string, logger)
548 self.PACK = '>LHxx'
549 self.LEN = calcsize(self.PACK)
550
551 def decode(self, parent_msg, data):
552 self.decode_length_type(data)
553
554 # IFLA_ADDRESS and IFLA_BROADCAST attributes for all interfaces has been a
555 # 6-byte MAC address. But the GRE interface uses a 4-byte IP address and
556 # GREv6 uses a 16-byte IPv6 address for this attribute.
557 try:
558 # GRE interface uses a 4-byte IP address for this attribute
559 if self.length == 8:
560 self.value = IPv4Address(unpack('>L', self.data[4:])[0])
561 self.value_int = int(self.value)
562 self.value_int_str = str(self.value_int)
563 # MAC Address
564 elif self.length == 10:
565 (data1, data2) = unpack(self.PACK, self.data[4:])
566 self.value = mac_int_to_str(data1 << 16 | data2)
567 # GREv6 interface uses a 16-byte IP address for this attribute
568 elif self.length == 20:
569 self.value = IPv6Address(unpack('>L', self.data[16:])[0])
570 self.value_int = int(self.value)
571 self.value_int_str = str(self.value_int)
572 else:
573 raise Exception("Length of MACAddress attribute not supported: %d" % self.length)
574
575 except struct.error:
576 self.log.error("%s unpack of %s failed, data 0x%s" % (self, self.PACK, hexlify(self.data[4:])))
577 raise
578
579 def encode(self):
580 length = self.HEADER_LEN + self.LEN
581 mac_raw = int(self.value.replace('.', '').replace(':', ''), 16)
582 raw = pack(self.HEADER_PACK, length-2, self.atype) + pack(self.PACK, mac_raw >> 16, mac_raw & 0x0000FFFF)
583 raw = self.pad(length, raw)
584 return raw
585
586 def dump_lines(self, dump_buffer, line_number, color):
587 line_number = self.dump_first_line(dump_buffer, line_number, color)
588 dump_buffer.append(data_to_color_text(line_number, color, self.data[4:8], self.value))
589 line_number += 1
590 if len(self.data) >= 12:
591 dump_buffer.append(data_to_color_text(line_number, color, self.data[8:12]))
592 line_number += 1
593 return line_number
594
595
596 class AttributeMplsLabel(Attribute):
597
598 def __init__(self, atype, string, family, logger):
599 Attribute.__init__(self, atype, string, logger)
600 self.value_int = None
601 self.value_int_str = None
602 self.family = family
603 self.PACK = '>HBB'
604
605 def decode(self, parent_msg, data):
606 self.decode_length_type(data)
607
608 try:
609 (label_high, label_low_tc_s, self.ttl) = unpack(self.PACK, self.data[4:])
610 self.s_bit = label_low_tc_s & 0x1
611 self.traffic_class = ((label_low_tc_s & 0xf) >> 1)
612 self.label = (label_high << 4) | (label_low_tc_s >> 4)
613 self.value = self.label
614 self.value_int = self.value
615 self.value_int_str = str(self.value_int)
616
617 except struct.error:
618 self.value = None
619 self.value_int = None
620 self.value_int_str = None
621 self.log.error("%s unpack of %s failed, data 0x%s" % (self, self.PACK, hexlify(self.data[4:])))
622 raise
623
624 def dump_lines(self, dump_buffer, line_number, color):
625 line_number = self.dump_first_line(dump_buffer, line_number, color)
626 dump_buffer.append(data_to_color_text(line_number, color, self.data[4:8],
627 'label %s, TC %s, bottom-of-stack %s, TTL %d' %
628 (self.label, self.traffic_class, self.s_bit, self.ttl)))
629 line_number += 1
630
631 return line_number
632
633
634 class AttributeGeneric(Attribute):
635
636 def __init__(self, atype, string, family, logger):
637 Attribute.__init__(self, atype, string, logger)
638 self.PACK = None
639 self.LEN = None
640
641 def decode(self, parent_msg, data):
642 self.decode_length_type(data)
643 wordcount = (self.attr_end - 4)/4
644 self.PACK = '=%dL' % wordcount
645 self.LEN = calcsize(self.PACK)
646
647 try:
648 self.value = ''.join(map(str, unpack(self.PACK, self.data[4:])))
649 except struct.error:
650 self.log.error("%s unpack of %s failed, data 0x%s" % (self, self.PACK, hexlify(self.data[4:])))
651 raise
652
653
654 class AttributeOneByteValue(AttributeGeneric):
655
656 def __init__(self, atype, string, family, logger):
657 AttributeGeneric.__init__(self, atype, string, family, logger)
658 self.PACK = '=Bxxx'
659 self.LEN = calcsize(self.PACK)
660
661 def decode(self, parent_msg, data):
662 self.decode_length_type(data)
663 assert self.attr_end == 8, "Attribute length for %s must be 8, it is %d" % (self, self.attr_end)
664
665 try:
666 self.value = int(unpack(self.PACK, self.data[4:8])[0])
667 except struct.error:
668 self.log.error("%s unpack of %s failed, data 0x%s" % (self, self.PACK, hexlify(self.data[4:5])))
669 raise
670
671 def encode(self):
672 length = self.HEADER_LEN + self.LEN
673 raw = pack(self.HEADER_PACK, length-3, self.atype) + pack(self.PACK, self.value)
674 raw = self.pad(length, raw)
675 return raw
676
677 def dump_lines(self, dump_buffer, line_number, color):
678 line_number = self.dump_first_line(dump_buffer, line_number, color)
679 dump_buffer.append(data_to_color_text(line_number, color, self.data[4:8], self.value))
680 return line_number + 1
681
682
683 class AttributeIFLA_AF_SPEC(Attribute):
684 """
685 value will be a dictionary such as:
686 {
687 Link.IFLA_BRIDGE_FLAGS: flags,
688 Link.IFLA_BRIDGE_VLAN_INFO: (vflags, vlanid)
689 }
690 """
691 def __init__(self, atype, string, family, logger):
692 Attribute.__init__(self, atype, string, logger)
693 self.family = family
694
695 def encode(self):
696 pack_layout = [self.HEADER_PACK]
697 payload = [0, self.atype | NLA_F_NESTED]
698 attr_length_index = 0
699
700 # For now this assumes that all data will be packed in the native endian
701 # order (=). If a field is added that needs to be packed via network
702 # order (>) then some smarts will need to be added to split the pack_layout
703 # string at the >, split the payload and make the needed pack() calls.
704 #
705 # Until we cross that bridge though we will keep things nice and simple and
706 # pack everything via a single pack() call.
707 sub_attr_to_add = []
708
709 for (sub_attr_type, sub_attr_value) in self.value.iteritems():
710
711 if sub_attr_type == Link.IFLA_BRIDGE_FLAGS:
712 sub_attr_to_add.append((sub_attr_type, sub_attr_value))
713
714 elif sub_attr_type == Link.IFLA_BRIDGE_VLAN_INFO:
715 for (vlan_flag, vlan_id) in sub_attr_value:
716 sub_attr_to_add.append((sub_attr_type, (vlan_flag, vlan_id)))
717
718 else:
719 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for encoding IFLA_AF_SPEC sub-attribute type %d' % sub_attr_type)
720 continue
721
722 for (sub_attr_type, sub_attr_value) in sub_attr_to_add:
723 sub_attr_pack_layout = ['=', 'HH']
724 sub_attr_payload = [0, sub_attr_type]
725 sub_attr_length_index = 0
726
727 if sub_attr_type == Link.IFLA_BRIDGE_FLAGS:
728 sub_attr_pack_layout.append('H')
729 sub_attr_payload.append(sub_attr_value)
730
731 elif sub_attr_type == Link.IFLA_BRIDGE_VLAN_INFO:
732 sub_attr_pack_layout.append('HH')
733 sub_attr_payload.append(sub_attr_value[0])
734 sub_attr_payload.append(sub_attr_value[1])
735
736 sub_attr_length = calcsize(''.join(sub_attr_pack_layout))
737 sub_attr_payload[sub_attr_length_index] = sub_attr_length
738
739 # add padding
740 for x in xrange(self.pad_bytes_needed(sub_attr_length)):
741 sub_attr_pack_layout.append('x')
742
743 # The [1:] is to remove the leading = so that when we do the ''.join() later
744 # we do not end up with an = in the middle of the pack layout string. There
745 # will be an = at the beginning via self.HEADER_PACK
746 sub_attr_pack_layout = sub_attr_pack_layout[1:]
747
748 # Now extend the ovarall attribute pack_layout/payload to include this sub-attribute
749 pack_layout.extend(sub_attr_pack_layout)
750 payload.extend(sub_attr_payload)
751
752 pack_layout = ''.join(pack_layout)
753
754 # Fill in the length field
755 length = calcsize(pack_layout)
756 payload[attr_length_index] = length
757
758 raw = pack(pack_layout, *payload)
759 raw = self.pad(length, raw)
760 return raw
761
762 def decode(self, parent_msg, data):
763 """
764 value is a dictionary such as:
765 {
766 Link.IFLA_BRIDGE_FLAGS: flags,
767 Link.IFLA_BRIDGE_VLAN_INFO: (vflags, vlanid)
768 }
769
770 FROM: David Ahern
771 The encoding of the IFLA_AF_SPEC attribute varies depending on the family
772 used for the request (RTM_GETLINK) message. For AF_UNSPEC the encoding
773 has another level of nesting for each address family with the type encoded
774 first. i.e.,
775 af_spec = nla_nest_start(skb, IFLA_AF_SPEC)
776 for each family:
777 af = nla_nest_start(skb, af_ops->family)
778 af_ops->fill_link_af(skb, dev, ext_filter_mask)
779 nest_end
780 nest_end
781
782 This allows the parser to find the address family by looking at the first
783 type.
784
785 Whereas AF_BRIDGE encoding is just:
786 af_spec = nla_nest_start(skb, IFLA_AF_SPEC)
787 br_fill_ifvlaninfo{_compressed}(skb, vg)
788 nest_end
789
790 which means the parser can not use the attribute itself to know the family
791 to which the attribute belongs.
792
793 /include/uapi/linux/if_link.h
794 /*
795 * IFLA_AF_SPEC
796 * Contains nested attributes for address family specific attributes.
797 * Each address family may create a attribute with the address family
798 * number as type and create its own attribute structure in it.
799 *
800 * Example:
801 * [IFLA_AF_SPEC] = {
802 * [AF_INET] = {
803 * [IFLA_INET_CONF] = ...,
804 * },
805 * [AF_INET6] = {
806 * [IFLA_INET6_FLAGS] = ...,
807 * [IFLA_INET6_CONF] = ...,
808 * }
809 * }
810 */
811
812 """
813 self.decode_length_type(data)
814 self.value = {}
815
816 data = self.data[4:]
817
818 while data:
819 (sub_attr_length, sub_attr_type) = unpack('=HH', data[:4])
820 sub_attr_end = padded_length(sub_attr_length)
821
822 if not sub_attr_length:
823 self.log.error('parsed a zero length sub-attr')
824 return
825
826 sub_attr_data = data[4:sub_attr_end]
827
828 if self.family == AF_BRIDGE:
829 if sub_attr_type == Link.IFLA_BRIDGE_FLAGS:
830 self.value[Link.IFLA_BRIDGE_FLAGS] = unpack("=H", sub_attr_data[0:2])[0]
831
832 elif sub_attr_type == Link.IFLA_BRIDGE_VLAN_INFO:
833 if Link.IFLA_BRIDGE_VLAN_INFO not in self.value:
834 self.value[Link.IFLA_BRIDGE_VLAN_INFO] = []
835 self.value[Link.IFLA_BRIDGE_VLAN_INFO].append(tuple(unpack("=HH", sub_attr_data[0:4])))
836
837 else:
838 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for decoding IFLA_AF_SPEC sub-attribute '
839 'type %s (%d), length %d, padded to %d' %
840 (parent_msg.get_ifla_bridge_af_spec_to_string(sub_attr_type),
841 sub_attr_type, sub_attr_length, sub_attr_end))
842
843 elif self.family == AF_UNSPEC:
844
845 if sub_attr_type == AF_INET6:
846 inet6_attr = {}
847
848 while sub_attr_data:
849 (inet6_attr_length, inet6_attr_type) = unpack('=HH', sub_attr_data[:4])
850 inet6_attr_end = padded_length(inet6_attr_length)
851
852 # 1 byte attr
853 if inet6_attr_type == Link.IFLA_INET6_ADDR_GEN_MODE:
854 inet6_attr[inet6_attr_type] = unpack('=B', sub_attr_data[4])[0]
855 # nlmanager doesn't support multiple kernel version
856 # all the other attributes like IFLA_INET6_CONF are
857 # based on DEVCONF_MAX from _UAPI_IPV6_H.
858 # we can opti the code and break this loop once we
859 # found the attribute that we are interested in.
860 # It's not really worth going through all the other
861 # attributes to log that we don't support them yet
862 break
863 else:
864 self.log.log(
865 SYSLOG_EXTRA_DEBUG,
866 'Add support for decoding AF_INET6 IFLA_AF_SPEC '
867 'sub-attribute type %s (%d), length %d, padded to %d'
868 % (
869 parent_msg.get_ifla_inet6_af_spec_to_string(inet6_attr_type),
870 inet6_attr_type, inet6_attr_length, inet6_attr_end
871 )
872 )
873
874 sub_attr_data = sub_attr_data[inet6_attr_end:]
875 self.value[AF_INET6] = inet6_attr
876 else:
877 self.value[sub_attr_type] = {}
878
879 # Uncomment the following block to implement the AF_INET attributes
880 # see Link.get_ifla_inet_af_spec_to_string (dict)
881 #elif sub_attr_type == AF_INET:
882 # inet_attr = {}
883 #
884 # while sub_attr_data:
885 # (inet_attr_length, inet_attr_type) = unpack('=HH', sub_attr_data[:4])
886 # inet_attr_end = padded_length(inet_attr_length)
887 #
888 # self.log.error(
889 # # SYSLOG_EXTRA_DEBUG,
890 # 'Add support for decoding AF_INET IFLA_AF_SPEC '
891 # 'sub-attribute type %s (%d), length %d, padded to %d'
892 # % (
893 # parent_msg.get_ifla_inet_af_spec_to_string(inet_attr_type),
894 # inet_attr_type, inet_attr_length, inet_attr_end
895 # )
896 # )
897 #
898 # sub_attr_data = sub_attr_data[inet_attr_end:]
899 #
900 # self.value[AF_INET] = inet_attr
901 else:
902 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for decoding IFLA_AF_SPEC sub-attribute '
903 'family %d, length %d, padded to %d'
904 % (self.family, sub_attr_length, sub_attr_end))
905
906 data = data[sub_attr_end:]
907
908 def dump_lines(self, dump_buffer, line_number, color):
909 line_number = self.dump_first_line(dump_buffer, line_number, color)
910 extra = ''
911
912 next_sub_attr_line = 0
913 sub_attr_line = True
914
915 for x in xrange(1, self.attr_end/4):
916 start = x * 4
917 end = start + 4
918
919 if line_number == next_sub_attr_line:
920 sub_attr_line = True
921
922 if sub_attr_line:
923 sub_attr_line = False
924
925 (sub_attr_length, sub_attr_type) = unpack('=HH', self.data[start:start+4])
926 sub_attr_end = padded_length(sub_attr_length)
927
928 next_sub_attr_line = line_number + (sub_attr_end/4)
929
930 if sub_attr_end == sub_attr_length:
931 padded_to = ','
932 else:
933 padded_to = ' padded to %d,' % sub_attr_end
934
935 if self.family == AF_BRIDGE:
936 extra = 'Nested Attribute - Length %s (%d)%s Type %s (%d) %s' % \
937 (zfilled_hex(sub_attr_length, 4), sub_attr_length,
938 padded_to,
939 zfilled_hex(sub_attr_type, 4), sub_attr_type,
940 Link.ifla_bridge_af_spec_to_string.get(sub_attr_type))
941 elif self.family == AF_UNSPEC:
942 if sub_attr_type == AF_INET6:
943 family = 'AF_INET6'
944 elif sub_attr_type == AF_INET:
945 family = 'AF_INET'
946 else:
947 family = 'Unsupported family %d' % sub_attr_type
948
949 extra = 'Nested Attribute Structure for %s - Length %s (%d)%s Type %s (%d)' % (
950 family, zfilled_hex(sub_attr_length, 4), sub_attr_length, padded_to,
951 zfilled_hex(sub_attr_type, 4), sub_attr_type,
952 )
953 else:
954 extra = ''
955
956 dump_buffer.append(data_to_color_text(line_number, color, self.data[start:end], extra))
957 line_number += 1
958
959 return line_number
960
961 def get_pretty_value(self, obj=None):
962
963 if obj and callable(obj):
964 return obj(self.value)
965
966 # We do this so we can print a more human readable dictionary
967 # with the names of the nested keys instead of their numbers
968 value_pretty = {}
969
970 if self.family == AF_BRIDGE:
971 for (sub_key, sub_value) in self.value.iteritems():
972 sub_key_pretty = "(%2d) %s" % (sub_key, Link.ifla_bridge_af_spec_to_string.get(sub_key))
973 value_pretty[sub_key_pretty] = sub_value
974 elif self.family == AF_UNSPEC:
975 for (family, family_attr) in self.value.iteritems():
976 family_value_pretty = {}
977
978 if family == AF_INET6:
979 family_af_spec_to_string = Link.ifla_inet6_af_spec_to_string
980 elif family == AF_INET:
981 family_af_spec_to_string = Link.ifla_inet_af_spec_to_string
982 else:
983 continue # log error?
984
985 for (sub_key, sub_value) in family_attr.iteritems():
986 sub_key_pretty = "(%2d) %s" % (sub_key, family_af_spec_to_string.get(sub_key))
987 family_value_pretty[sub_key_pretty] = sub_value
988 value_pretty = family_value_pretty
989
990 return value_pretty
991
992
993
994 class AttributeRTA_MULTIPATH(Attribute):
995 """
996 /* RTA_MULTIPATH --- array of struct rtnexthop.
997 *
998 * "struct rtnexthop" describes all necessary nexthop information,
999 * i.e. parameters of path to a destination via this nexthop.
1000 *
1001 * At the moment it is impossible to set different prefsrc, mtu, window
1002 * and rtt for different paths from multipath.
1003 */
1004
1005 struct rtnexthop {
1006 unsigned short rtnh_len;
1007 unsigned char rtnh_flags;
1008 unsigned char rtnh_hops;
1009 int rtnh_ifindex;
1010 };
1011 """
1012
1013 def __init__(self, atype, string, family, logger):
1014 Attribute.__init__(self, atype, string, logger)
1015 self.family = family
1016 self.PACK = None
1017 self.LEN = None
1018 self.RTNH_PACK = '=HBBL' # rtnh_len, flags, hops, ifindex
1019 self.RTNH_LEN = calcsize(self.RTNH_PACK)
1020 self.IPV4_LEN = 4
1021 self.IPV6_LEN = 16
1022
1023 def encode(self):
1024
1025 # Calculate the length
1026 if self.family == AF_INET:
1027 ip_len = self.IPV4_LEN
1028 elif self.family == AF_INET6:
1029 ip_len = self.IPV6_LEN
1030
1031 # Attribute header
1032 length = self.HEADER_LEN + ((self.RTNH_LEN + self.HEADER_LEN + ip_len) * len(self.value))
1033 raw = pack(self.HEADER_PACK, length, self.atype)
1034
1035 rtnh_flags = 0
1036 rtnh_hops = 0
1037 rtnh_len = self.RTNH_LEN + self.HEADER_LEN + ip_len
1038
1039 for (nexthop, rtnh_ifindex) in self.value:
1040
1041 # rtnh structure
1042 raw += pack(self.RTNH_PACK, rtnh_len, rtnh_flags, rtnh_hops, rtnh_ifindex)
1043
1044 # Gateway
1045 raw += pack(self.HEADER_PACK, self.HEADER_LEN + ip_len, Route.RTA_GATEWAY)
1046
1047 if self.family == AF_INET:
1048 raw += pack('>L', nexthop)
1049 elif self.family == AF_INET6:
1050 raw += pack('>QQ', nexthop >> 64, nexthop & 0x0000000000000000FFFFFFFFFFFFFFFF)
1051
1052 raw = self.pad(length, raw)
1053 return raw
1054
1055 def decode(self, parent_msg, data):
1056 self.decode_length_type(data)
1057 self.value = []
1058
1059 data = self.data[4:]
1060
1061 while data:
1062 (rtnh_len, rtnh_flags, rtnh_hops, rtnh_ifindex) = unpack(self.RTNH_PACK, data[:self.RTNH_LEN])
1063 data = data[self.RTNH_LEN:]
1064
1065 (attr_type, attr_length) = unpack(self.HEADER_PACK, self.data[:self.HEADER_LEN])
1066 data = data[self.HEADER_LEN:]
1067
1068 if self.family == AF_INET:
1069 if len(data) < self.IPV4_LEN:
1070 break
1071 nexthop = IPv4Address(unpack('>L', data[:self.IPV4_LEN])[0])
1072 self.value.append((nexthop, rtnh_ifindex, rtnh_flags, rtnh_hops))
1073
1074 elif self.family == AF_INET6:
1075 if len(data) < self.IPV6_LEN:
1076 break
1077 (data1, data2) = unpack('>QQ', data[:self.IPV6_LEN])
1078 nexthop = IPv6Address(data1 << 64 | data2)
1079 self.value.append((nexthop, rtnh_ifindex, rtnh_flags, rtnh_hops))
1080
1081 data = data[(rtnh_len-self.RTNH_LEN-self.HEADER_LEN):]
1082
1083 self.value = tuple(self.value)
1084
1085
1086 class AttributeIFLA_LINKINFO(Attribute):
1087 """
1088 value is a dictionary such as:
1089
1090 {
1091 Link.IFLA_INFO_KIND : 'vlan',
1092 Link.IFLA_INFO_DATA : {
1093 Link.IFLA_VLAN_ID : vlanid,
1094 }
1095 }
1096 """
1097 def __init__(self, atype, string, family, logger):
1098 Attribute.__init__(self, atype, string, logger)
1099
1100 def encode(self):
1101 pack_layout = [self.HEADER_PACK]
1102 payload = [0, self.atype | NLA_F_NESTED]
1103 attr_length_index = 0
1104
1105 kind = self.value.get(Link.IFLA_INFO_KIND)
1106 slave_kind = self.value.get(Link.IFLA_INFO_SLAVE_KIND)
1107
1108 if not slave_kind and kind not in ('vlan', 'macvlan', 'vxlan', 'bond', 'bridge', 'xfrm'):
1109 raise Exception('Unsupported IFLA_INFO_KIND %s' % kind)
1110 elif not kind and slave_kind != 'bridge':
1111 # only support brport for now.
1112 raise Exception('Unsupported IFLA_INFO_SLAVE_KIND %s' % slave_kind)
1113
1114 # For now this assumes that all data will be packed in the native endian
1115 # order (=). If a field is added that needs to be packed via network
1116 # order (>) then some smarts will need to be added to split the pack_layout
1117 # string at the >, split the payload and make the needed pack() calls.
1118 #
1119 # Until we cross that bridge though we will keep things nice and simple and
1120 # pack everything via a single pack() call.
1121 for (sub_attr_type, sub_attr_value) in self.value.iteritems():
1122 sub_attr_pack_layout = ['=', 'HH']
1123 sub_attr_payload = [0, sub_attr_type]
1124 sub_attr_length_index = 0
1125
1126 if sub_attr_type == Link.IFLA_INFO_KIND:
1127 sub_attr_pack_layout.append('%ds' % len(sub_attr_value))
1128 sub_attr_payload.append(sub_attr_value)
1129
1130 elif sub_attr_type == Link.IFLA_INFO_DATA:
1131
1132 sub_attr_payload = [0, sub_attr_type | NLA_F_NESTED]
1133
1134 for (info_data_type, info_data_value) in sub_attr_value.iteritems():
1135
1136 if kind == 'vlan':
1137 if info_data_type == Link.IFLA_VLAN_ID:
1138 sub_attr_pack_layout.append('HH')
1139 sub_attr_payload.append(6) # length
1140 sub_attr_payload.append(info_data_type)
1141
1142 # The vlan-id
1143 sub_attr_pack_layout.append('H')
1144 sub_attr_payload.append(info_data_value)
1145
1146 # pad 2 bytes
1147 sub_attr_pack_layout.extend('xx')
1148
1149 elif info_data_type == Link.IFLA_VLAN_PROTOCOL:
1150 sub_attr_pack_layout.append('HH')
1151 sub_attr_payload.append(6) # length
1152 sub_attr_payload.append(info_data_type)
1153
1154 # vlan protocol
1155 vlan_protocol = Link.ifla_vlan_protocol_dict.get(info_data_value)
1156 if not vlan_protocol:
1157 raise NotImplementedError('vlan protocol %s not implemented' % info_data_value)
1158
1159 sub_attr_pack_layout.append('H')
1160 sub_attr_payload.append(htons(vlan_protocol))
1161
1162 # pad 2 bytes
1163 sub_attr_pack_layout.extend('xx')
1164 else:
1165 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for encoding IFLA_INFO_DATA vlan sub-attribute type %d' % info_data_type)
1166
1167 elif kind == 'macvlan':
1168 if info_data_type == Link.IFLA_MACVLAN_MODE:
1169 sub_attr_pack_layout.append('HH')
1170 sub_attr_payload.append(8) # length
1171 sub_attr_payload.append(info_data_type)
1172
1173 # macvlan mode
1174 sub_attr_pack_layout.append('L')
1175 sub_attr_payload.append(info_data_value)
1176
1177 else:
1178 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for encoding IFLA_INFO_DATA macvlan sub-attribute type %d' % info_data_type)
1179
1180 elif kind == 'xfrm':
1181 if info_data_type in (Link.IFLA_XFRM_IF_ID, Link.IFLA_XFRM_LINK):
1182 sub_attr_pack_layout.append('HH')
1183 sub_attr_payload.append(8) # length
1184 sub_attr_payload.append(info_data_type)
1185
1186 sub_attr_pack_layout.append('L')
1187 sub_attr_payload.append(info_data_value)
1188
1189 elif kind == 'vxlan':
1190 if info_data_type in (Link.IFLA_VXLAN_ID,
1191 Link.IFLA_VXLAN_LINK,
1192 Link.IFLA_VXLAN_AGEING,
1193 Link.IFLA_VXLAN_LIMIT,
1194 Link.IFLA_VXLAN_PORT_RANGE):
1195 sub_attr_pack_layout.append('HH')
1196 sub_attr_payload.append(8) # length
1197 sub_attr_payload.append(info_data_type)
1198
1199 sub_attr_pack_layout.append('L')
1200 sub_attr_payload.append(info_data_value)
1201
1202 elif info_data_type in (Link.IFLA_VXLAN_GROUP,
1203 Link.IFLA_VXLAN_LOCAL):
1204 sub_attr_pack_layout.append('HH')
1205 sub_attr_payload.append(8) # length
1206 sub_attr_payload.append(info_data_type)
1207
1208 sub_attr_pack_layout.append('L')
1209
1210 reorder = unpack('<L', IPv4Address(info_data_value).packed)[0]
1211 sub_attr_payload.append(IPv4Address(reorder))
1212
1213 elif info_data_type in (Link.IFLA_VXLAN_PORT,):
1214 sub_attr_pack_layout.append('HH')
1215 sub_attr_payload.append(6)
1216 sub_attr_payload.append(info_data_type)
1217
1218 sub_attr_pack_layout.append('H')
1219
1220 # byte swap
1221 swaped = pack(">H", info_data_value)
1222 sub_attr_payload.append(unpack("<H", swaped)[0])
1223
1224 sub_attr_pack_layout.extend('xx')
1225
1226 elif info_data_type in (Link.IFLA_VXLAN_TTL,
1227 Link.IFLA_VXLAN_TOS,
1228 Link.IFLA_VXLAN_LEARNING,
1229 Link.IFLA_VXLAN_PROXY,
1230 Link.IFLA_VXLAN_RSC,
1231 Link.IFLA_VXLAN_L2MISS,
1232 Link.IFLA_VXLAN_L3MISS,
1233 Link.IFLA_VXLAN_UDP_CSUM,
1234 Link.IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
1235 Link.IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
1236 Link.IFLA_VXLAN_REMCSUM_TX,
1237 Link.IFLA_VXLAN_REMCSUM_RX,
1238 Link.IFLA_VXLAN_REPLICATION_TYPE):
1239 sub_attr_pack_layout.append('HH')
1240 sub_attr_payload.append(5)
1241 sub_attr_payload.append(info_data_type)
1242
1243 sub_attr_pack_layout.append('B')
1244 sub_attr_payload.append(info_data_value)
1245 sub_attr_pack_layout.extend('xxx')
1246
1247 else:
1248 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for encoding IFLA_INFO_DATA vxlan sub-attribute type %d' % info_data_type)
1249
1250 elif kind == 'bond':
1251 if info_data_type in (Link.IFLA_BOND_AD_ACTOR_SYSTEM, ):
1252 sub_attr_pack_layout.append('HH')
1253 sub_attr_payload.append(10) # length
1254 sub_attr_payload.append(info_data_type)
1255
1256 sub_attr_pack_layout.append('6B')
1257 for mbyte in info_data_value.replace('.', ' ').replace(':', ' ').split():
1258 sub_attr_payload.append(int(mbyte, 16))
1259 sub_attr_pack_layout.extend('xx')
1260
1261 elif info_data_type == Link.IFLA_BOND_AD_ACTOR_SYS_PRIO:
1262 sub_attr_pack_layout.append('HH')
1263 sub_attr_payload.append(6) # length
1264 sub_attr_payload.append(info_data_type)
1265
1266 # 2 bytes
1267 sub_attr_pack_layout.append('H')
1268 sub_attr_payload.append(int(info_data_value))
1269
1270 # pad 2 bytes
1271 sub_attr_pack_layout.extend('xx')
1272
1273 elif info_data_type == Link.IFLA_BOND_NUM_PEER_NOTIF:
1274 sub_attr_pack_layout.append('HH')
1275 sub_attr_payload.append(5) # length
1276 sub_attr_payload.append(info_data_type)
1277
1278 # 1 byte
1279 sub_attr_pack_layout.append('B')
1280 sub_attr_payload.append(int(info_data_value))
1281
1282 # pad 3 bytes
1283 sub_attr_pack_layout.extend('xxx')
1284
1285
1286 elif info_data_type in (Link.IFLA_BOND_AD_LACP_RATE,
1287 Link.IFLA_BOND_AD_LACP_BYPASS,
1288 Link.IFLA_BOND_USE_CARRIER):
1289 # converts yes/no/on/off/0/1 strings to boolean value
1290 bool_value = self.get_bool_value(info_data_value)
1291
1292 sub_attr_pack_layout.append('HH')
1293 sub_attr_payload.append(5) # length
1294 sub_attr_payload.append(info_data_type)
1295
1296 # 1 byte
1297 sub_attr_pack_layout.append('B')
1298 sub_attr_payload.append(bool_value)
1299
1300 # pad 3 bytes
1301 sub_attr_pack_layout.extend('xxx')
1302
1303 elif info_data_type == Link.IFLA_BOND_XMIT_HASH_POLICY:
1304 index = self.get_index(Link.ifla_bond_xmit_hash_policy_tbl,
1305 'bond xmit hash policy',
1306 info_data_value)
1307
1308 sub_attr_pack_layout.append('HH')
1309 sub_attr_payload.append(5) # length
1310 sub_attr_payload.append(info_data_type)
1311
1312 # 1 byte
1313 sub_attr_pack_layout.append('B')
1314 sub_attr_payload.append(index)
1315
1316 # pad 3 bytes
1317 sub_attr_pack_layout.extend('xxx')
1318
1319 elif info_data_type == Link.IFLA_BOND_MODE:
1320 index = self.get_index(Link.ifla_bond_mode_tbl,
1321 'bond mode',
1322 info_data_value)
1323
1324 sub_attr_pack_layout.append('HH')
1325 sub_attr_payload.append(5) # length
1326 sub_attr_payload.append(info_data_type)
1327
1328 # 1 byte
1329 sub_attr_pack_layout.append('B')
1330 sub_attr_payload.append(index)
1331
1332 # pad 3 bytes
1333 sub_attr_pack_layout.extend('xxx')
1334
1335 elif info_data_type in (Link.IFLA_BOND_MIIMON,
1336 Link.IFLA_BOND_UPDELAY,
1337 Link.IFLA_BOND_DOWNDELAY,
1338 Link.IFLA_BOND_MIN_LINKS):
1339 sub_attr_pack_layout.append('HH')
1340 sub_attr_payload.append(8) # length
1341 sub_attr_payload.append(info_data_type)
1342
1343 sub_attr_pack_layout.append('L')
1344 sub_attr_payload.append(int(info_data_value))
1345
1346 else:
1347 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for encoding IFLA_INFO_DATA bond sub-attribute type %d' % info_data_type)
1348
1349 elif kind == 'bridge':
1350 if info_data_type == Link.IFLA_BR_VLAN_PROTOCOL:
1351 sub_attr_pack_layout.append('HH')
1352 sub_attr_payload.append(6) # length
1353 sub_attr_payload.append(info_data_type)
1354
1355 # vlan protocol
1356 vlan_protocol = Link.ifla_vlan_protocol_dict.get(info_data_value)
1357 if not vlan_protocol:
1358 raise NotImplementedError('vlan protocol %s not implemented' % info_data_value)
1359
1360 sub_attr_pack_layout.append('H')
1361 sub_attr_payload.append(htons(vlan_protocol))
1362
1363 # pad 2 bytes
1364 sub_attr_pack_layout.extend('xx')
1365
1366 # 1 byte
1367 elif info_data_type in (Link.IFLA_BR_VLAN_FILTERING,
1368 Link.IFLA_BR_TOPOLOGY_CHANGE,
1369 Link.IFLA_BR_TOPOLOGY_CHANGE_DETECTED,
1370 Link.IFLA_BR_MCAST_ROUTER,
1371 Link.IFLA_BR_MCAST_SNOOPING,
1372 Link.IFLA_BR_MCAST_QUERY_USE_IFADDR,
1373 Link.IFLA_BR_MCAST_QUERIER,
1374 Link.IFLA_BR_NF_CALL_IPTABLES,
1375 Link.IFLA_BR_NF_CALL_IP6TABLES,
1376 Link.IFLA_BR_NF_CALL_ARPTABLES,
1377 Link.IFLA_BR_VLAN_STATS_ENABLED,
1378 Link.IFLA_BR_MCAST_STATS_ENABLED,
1379 Link.IFLA_BR_MCAST_IGMP_VERSION,
1380 Link.IFLA_BR_MCAST_MLD_VERSION):
1381 sub_attr_pack_layout.append('HH')
1382 sub_attr_payload.append(5) # length
1383 sub_attr_payload.append(info_data_type)
1384
1385 # 1 byte
1386 sub_attr_pack_layout.append('B')
1387 sub_attr_payload.append(int(info_data_value))
1388
1389 # pad 3 bytes
1390 sub_attr_pack_layout.extend('xxx')
1391
1392 # 2 bytes
1393 elif info_data_type in (Link.IFLA_BR_PRIORITY,
1394 Link.IFLA_BR_GROUP_FWD_MASK,
1395 Link.IFLA_BR_ROOT_PORT,
1396 Link.IFLA_BR_VLAN_DEFAULT_PVID):
1397 sub_attr_pack_layout.append('HH')
1398 sub_attr_payload.append(6) # length
1399 sub_attr_payload.append(info_data_type)
1400
1401 # 2 bytes
1402 sub_attr_pack_layout.append('H')
1403 sub_attr_payload.append(int(info_data_value))
1404
1405 # pad 2 bytes
1406 sub_attr_pack_layout.extend('xx')
1407
1408 # 4 bytes
1409 elif info_data_type in (Link.IFLA_BR_FORWARD_DELAY,
1410 Link.IFLA_BR_HELLO_TIME,
1411 Link.IFLA_BR_MAX_AGE,
1412 Link.IFLA_BR_AGEING_TIME,
1413 Link.IFLA_BR_STP_STATE,
1414 Link.IFLA_BR_ROOT_PATH_COST,
1415 Link.IFLA_BR_MCAST_QUERIER,
1416 Link.IFLA_BR_MCAST_HASH_ELASTICITY,
1417 Link.IFLA_BR_MCAST_HASH_MAX,
1418 Link.IFLA_BR_MCAST_LAST_MEMBER_CNT,
1419 Link.IFLA_BR_MCAST_STARTUP_QUERY_CNT):
1420 sub_attr_pack_layout.append('HH')
1421 sub_attr_payload.append(8) # length
1422 sub_attr_payload.append(info_data_type)
1423
1424 sub_attr_pack_layout.append('L')
1425 sub_attr_payload.append(int(info_data_value))
1426
1427 # 8 bytes
1428 elif info_data_type in (Link.IFLA_BR_MCAST_LAST_MEMBER_INTVL,
1429 Link.IFLA_BR_MCAST_MEMBERSHIP_INTVL,
1430 Link.IFLA_BR_MCAST_QUERIER_INTVL,
1431 Link.IFLA_BR_MCAST_QUERY_INTVL,
1432 Link.IFLA_BR_MCAST_QUERY_RESPONSE_INTVL,
1433 Link.IFLA_BR_MCAST_STARTUP_QUERY_INTVL):
1434 sub_attr_pack_layout.append('HH')
1435 sub_attr_payload.append(12) # length
1436 sub_attr_payload.append(info_data_type)
1437
1438 sub_attr_pack_layout.append('Q')
1439 sub_attr_payload.append(int(info_data_value))
1440
1441 else:
1442 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for encoding IFLA_INFO_DATA bridge sub-attribute type %d' % info_data_type)
1443
1444 elif sub_attr_type == Link.IFLA_INFO_SLAVE_DATA:
1445
1446 sub_attr_payload = [0, sub_attr_type | NLA_F_NESTED]
1447
1448 for (info_slave_data_type, info_slave_data_value) in sub_attr_value.iteritems():
1449
1450 if slave_kind == 'bridge':
1451
1452 # 1 byte
1453 if info_slave_data_type in (Link.IFLA_BRPORT_STATE,
1454 Link.IFLA_BRPORT_MODE,
1455 Link.IFLA_BRPORT_GUARD,
1456 Link.IFLA_BRPORT_PROTECT,
1457 Link.IFLA_BRPORT_FAST_LEAVE,
1458 Link.IFLA_BRPORT_LEARNING,
1459 Link.IFLA_BRPORT_UNICAST_FLOOD,
1460 Link.IFLA_BRPORT_PROXYARP,
1461 Link.IFLA_BRPORT_LEARNING_SYNC,
1462 Link.IFLA_BRPORT_PROXYARP_WIFI,
1463 Link.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
1464 Link.IFLA_BRPORT_CONFIG_PENDING,
1465 Link.IFLA_BRPORT_MULTICAST_ROUTER,
1466 Link.IFLA_BRPORT_MCAST_FLOOD,
1467 Link.IFLA_BRPORT_MCAST_TO_UCAST,
1468 Link.IFLA_BRPORT_VLAN_TUNNEL,
1469 Link.IFLA_BRPORT_BCAST_FLOOD,
1470 Link.IFLA_BRPORT_PEER_LINK,
1471 Link.IFLA_BRPORT_DUAL_LINK,
1472 Link.IFLA_BRPORT_ARP_SUPPRESS,
1473 Link.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT):
1474 sub_attr_pack_layout.append('HH')
1475 sub_attr_payload.append(5) # length
1476 sub_attr_payload.append(info_slave_data_type)
1477
1478 # 1 byte
1479 sub_attr_pack_layout.append('B')
1480 sub_attr_payload.append(int(info_slave_data_value))
1481
1482 # pad 3 bytes
1483 sub_attr_pack_layout.extend('xxx')
1484
1485 # 2 bytes
1486 elif info_slave_data_type in (Link.IFLA_BRPORT_PRIORITY,
1487 Link.IFLA_BRPORT_DESIGNATED_PORT,
1488 Link.IFLA_BRPORT_DESIGNATED_COST,
1489 Link.IFLA_BRPORT_ID,
1490 Link.IFLA_BRPORT_NO,
1491 Link.IFLA_BRPORT_GROUP_FWD_MASK,
1492 Link.IFLA_BRPORT_GROUP_FWD_MASKHI):
1493 sub_attr_pack_layout.append('HH')
1494 sub_attr_payload.append(6) # length
1495 sub_attr_payload.append(info_slave_data_type)
1496
1497 # 2 bytes
1498 sub_attr_pack_layout.append('H')
1499 sub_attr_payload.append(int(info_slave_data_value))
1500
1501 # pad 2 bytes
1502 sub_attr_pack_layout.extend('xx')
1503
1504 # 4 bytes
1505 elif info_slave_data_type == Link.IFLA_BRPORT_COST:
1506 sub_attr_pack_layout.append('HH')
1507 sub_attr_payload.append(8) # length
1508 sub_attr_payload.append(info_slave_data_type)
1509
1510 sub_attr_pack_layout.append('L')
1511 sub_attr_payload.append(int(info_slave_data_value))
1512
1513 else:
1514 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for encoding IFLA_INFO_SLAVE_DATA bond sub-attribute type %d' % info_slave_data_type)
1515
1516 else:
1517 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for encoding IFLA_LINKINFO kind %s' % slave_kind)
1518
1519 else:
1520 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for encoding IFLA_LINKINFO sub-attribute type %d' % sub_attr_type)
1521 continue
1522
1523 sub_attr_length = calcsize(''.join(sub_attr_pack_layout))
1524 sub_attr_payload[sub_attr_length_index] = sub_attr_length
1525
1526 # add padding
1527 for x in xrange(self.pad_bytes_needed(sub_attr_length)):
1528 sub_attr_pack_layout.append('x')
1529
1530 # The [1:] is to remove the leading = so that when we do the ''.join() later
1531 # we do not end up with an = in the middle of the pack layout string. There
1532 # will be an = at the beginning via self.HEADER_PACK
1533 sub_attr_pack_layout = sub_attr_pack_layout[1:]
1534
1535 # Now extend the ovarall attribute pack_layout/payload to include this sub-attribute
1536 pack_layout.extend(sub_attr_pack_layout)
1537 payload.extend(sub_attr_payload)
1538
1539 pack_layout = ''.join(pack_layout)
1540
1541 # Fill in the length field
1542 length = calcsize(pack_layout)
1543 payload[attr_length_index] = length
1544
1545 raw = pack(pack_layout, *payload)
1546 raw = self.pad(length, raw)
1547 return raw
1548
1549 def get_bool_value(self, value, default=None):
1550 try:
1551 return value_to_bool_dict[value]
1552 except KeyError:
1553 self.log.debug('%s: unsupported boolean value' % value)
1554 return default
1555
1556 def get_index(self, tbl, attr, value, default=None):
1557 try:
1558 return tbl[value]
1559 except KeyError:
1560 self.log.debug('unsupported %s value %s (%s)' % (attr, value, tbl.keys()))
1561 return default
1562
1563 def decode(self, parent_msg, data):
1564 """
1565 value is a dictionary such as:
1566
1567 {
1568 Link.IFLA_INFO_KIND : 'vlan',
1569 Link.IFLA_INFO_DATA : {
1570 Link.IFLA_VLAN_ID : vlanid,
1571 }
1572 }
1573 """
1574 self.decode_length_type(data)
1575 self.value = {}
1576
1577 data = self.data[4:]
1578
1579 # IFLA_MACVLAN_MODE and IFLA_VLAN_ID both have a value of 1 and both are
1580 # valid IFLA_INFO_DATA entries :( The sender must TX IFLA_INFO_KIND
1581 # first in order for us to know if "1" is IFLA_MACVLAN_MODE vs IFLA_VLAN_ID.
1582
1583 while data:
1584 (sub_attr_length, sub_attr_type) = unpack('=HH', data[:4])
1585 sub_attr_end = padded_length(sub_attr_length)
1586
1587 if not sub_attr_length:
1588 self.log.error('parsed a zero length sub-attr')
1589 return
1590
1591 if sub_attr_type in (Link.IFLA_INFO_KIND, Link.IFLA_INFO_SLAVE_KIND):
1592 self.value[sub_attr_type] = remove_trailing_null(unpack('%ds' % (sub_attr_length - 4), data[4:sub_attr_length])[0])
1593
1594 elif sub_attr_type == Link.IFLA_INFO_SLAVE_DATA:
1595 sub_attr_data = data[4:sub_attr_end]
1596
1597 ifla_info_slave_data = dict()
1598 ifla_info_slave_kind = self.value.get(Link.IFLA_INFO_SLAVE_KIND)
1599
1600 if not ifla_info_slave_kind:
1601 self.log.warning('IFLA_INFO_SLAVE_KIND is not known...we cannot parse IFLA_INFO_SLAVE_DATA')
1602 else:
1603 while sub_attr_data:
1604 (info_data_length, info_data_type) = unpack('=HH', sub_attr_data[:4])
1605 info_data_end = padded_length(info_data_length)
1606 try:
1607 if ifla_info_slave_kind == 'bridge':
1608 # 1 byte
1609 if info_data_type in (Link.IFLA_BRPORT_STATE,
1610 Link.IFLA_BRPORT_MODE,
1611 Link.IFLA_BRPORT_GUARD,
1612 Link.IFLA_BRPORT_PROTECT,
1613 Link.IFLA_BRPORT_FAST_LEAVE,
1614 Link.IFLA_BRPORT_LEARNING,
1615 Link.IFLA_BRPORT_UNICAST_FLOOD,
1616 Link.IFLA_BRPORT_PROXYARP,
1617 Link.IFLA_BRPORT_LEARNING_SYNC,
1618 Link.IFLA_BRPORT_PROXYARP_WIFI,
1619 Link.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
1620 Link.IFLA_BRPORT_CONFIG_PENDING,
1621 Link.IFLA_BRPORT_MULTICAST_ROUTER,
1622 Link.IFLA_BRPORT_MCAST_FLOOD,
1623 Link.IFLA_BRPORT_MCAST_TO_UCAST,
1624 Link.IFLA_BRPORT_VLAN_TUNNEL,
1625 Link.IFLA_BRPORT_PEER_LINK,
1626 Link.IFLA_BRPORT_DUAL_LINK,
1627 Link.IFLA_BRPORT_ARP_SUPPRESS,
1628 Link.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT):
1629 ifla_info_slave_data[info_data_type] = unpack('=B', sub_attr_data[4])[0]
1630
1631 # 2 bytes
1632 elif info_data_type in (Link.IFLA_BRPORT_PRIORITY,
1633 Link.IFLA_BRPORT_DESIGNATED_PORT,
1634 Link.IFLA_BRPORT_DESIGNATED_COST,
1635 Link.IFLA_BRPORT_ID,
1636 Link.IFLA_BRPORT_NO,
1637 Link.IFLA_BRPORT_GROUP_FWD_MASK,
1638 Link.IFLA_BRPORT_GROUP_FWD_MASKHI):
1639 ifla_info_slave_data[info_data_type] = unpack('=H', sub_attr_data[4:6])[0]
1640
1641 # 4 bytes
1642 elif info_data_type == Link.IFLA_BRPORT_COST:
1643 ifla_info_slave_data[info_data_type] = unpack('=L', sub_attr_data[4:8])[0]
1644
1645 elif ifla_info_slave_kind == 'bond':
1646
1647 # 1 byte
1648 if info_data_type in (
1649 Link.IFLA_BOND_SLAVE_STATE,
1650 Link.IFLA_BOND_SLAVE_MII_STATUS,
1651 Link.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
1652 Link.IFLA_BOND_SLAVE_AD_RX_BYPASS,
1653 ):
1654 ifla_info_slave_data[info_data_type] = unpack('=B', sub_attr_data[4])[0]
1655
1656 # 2 bytes
1657 elif info_data_type in (
1658 Link.IFLA_BOND_SLAVE_QUEUE_ID,
1659 Link.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
1660 ):
1661 ifla_info_slave_data[info_data_type] = unpack('=H', sub_attr_data[4:6])[0]
1662
1663 # 4 bytes
1664 elif info_data_type == (
1665 Link.IFLA_BOND_SLAVE_PERM_HWADDR,
1666 Link.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT
1667 ):
1668 ifla_info_slave_data[info_data_type] = unpack('=L', sub_attr_data[4:8])[0]
1669
1670 except Exception as e:
1671 self.log.debug('%s: attribute %s: %s'
1672 % (self.value[Link.IFLA_INFO_SLAVE_KIND],
1673 info_data_type,
1674 str(e)))
1675 sub_attr_data = sub_attr_data[info_data_end:]
1676
1677 self.value[Link.IFLA_INFO_SLAVE_DATA] = ifla_info_slave_data
1678
1679 elif sub_attr_type == Link.IFLA_INFO_DATA:
1680 sub_attr_data = data[4:sub_attr_end]
1681 self.value[Link.IFLA_INFO_DATA] = {}
1682
1683 ifla_info_kind = self.value.get(Link.IFLA_INFO_KIND)
1684 if not ifla_info_kind:
1685 self.log.warning('IFLA_INFO_KIND is not known...we cannot parse IFLA_INFO_DATA')
1686 else:
1687 while sub_attr_data:
1688 (info_data_length, info_data_type) = unpack('=HH', sub_attr_data[:4])
1689 info_data_end = padded_length(info_data_length)
1690 try:
1691 if ifla_info_kind == 'vlan':
1692 if info_data_type == Link.IFLA_VLAN_ID:
1693 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=H', sub_attr_data[4:6])[0]
1694
1695 elif info_data_type == Link.IFLA_VLAN_PROTOCOL:
1696 hex_value = '0x%s' % sub_attr_data[4:6].encode('hex')
1697 vlan_protocol = Link.ifla_vlan_protocol_dict.get(int(hex_value, base=16))
1698
1699 if vlan_protocol:
1700 self.value[Link.IFLA_INFO_DATA][info_data_type] = vlan_protocol
1701 else:
1702 self.log.warning('IFLA_VLAN_PROTOCOL: cannot decode vlan protocol %s' % hex_value)
1703
1704 else:
1705 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for decoding IFLA_INFO_KIND vlan type %s (%d), length %d, padded to %d' %
1706 (parent_msg.get_ifla_vlan_string(info_data_type), info_data_type, info_data_length, info_data_end))
1707
1708 elif ifla_info_kind == 'macvlan':
1709 if info_data_type == Link.IFLA_MACVLAN_MODE:
1710 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=L', sub_attr_data[4:8])[0]
1711 else:
1712 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for decoding IFLA_INFO_KIND macvlan type %s (%d), length %d, padded to %d' %
1713 (parent_msg.get_ifla_macvlan_string(info_data_type), info_data_type, info_data_length, info_data_end))
1714
1715 elif ifla_info_kind == 'xfrm':
1716 # 4-byte int
1717 if info_data_type in (Link.IFLA_XFRM_IF_ID, Link.IFLA_XFRM_LINK):
1718 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=L', sub_attr_data[4:8])[0]
1719
1720 elif ifla_info_kind == 'vxlan':
1721
1722 # IPv4Address
1723 if info_data_type in (Link.IFLA_VXLAN_GROUP,
1724 Link.IFLA_VXLAN_LOCAL):
1725 self.value[Link.IFLA_INFO_DATA][info_data_type] = IPv4Address(unpack('>L', sub_attr_data[4:8])[0])
1726
1727 # 4-byte int
1728 elif info_data_type in (Link.IFLA_VXLAN_ID,
1729 Link.IFLA_VXLAN_LINK,
1730 Link.IFLA_VXLAN_AGEING,
1731 Link.IFLA_VXLAN_LIMIT,
1732 Link.IFLA_VXLAN_PORT_RANGE):
1733 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=L', sub_attr_data[4:8])[0]
1734
1735 # 2-byte int
1736 elif info_data_type in (Link.IFLA_VXLAN_PORT, ):
1737 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('!H', sub_attr_data[4:6])[0]
1738 # The form '!' is available for those poor souls who claim they can't
1739 # remember whether network byte order is big-endian or little-endian.
1740
1741 # 1-byte int
1742 elif info_data_type in (Link.IFLA_VXLAN_TTL,
1743 Link.IFLA_VXLAN_TOS,
1744 Link.IFLA_VXLAN_LEARNING,
1745 Link.IFLA_VXLAN_PROXY,
1746 Link.IFLA_VXLAN_RSC,
1747 Link.IFLA_VXLAN_L2MISS,
1748 Link.IFLA_VXLAN_L3MISS,
1749 Link.IFLA_VXLAN_UDP_CSUM,
1750 Link.IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
1751 Link.IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
1752 Link.IFLA_VXLAN_REMCSUM_TX,
1753 Link.IFLA_VXLAN_REMCSUM_RX,
1754 Link.IFLA_VXLAN_REPLICATION_TYPE):
1755 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=B', sub_attr_data[4])[0]
1756
1757 else:
1758 # sub_attr_end = padded_length(sub_attr_length)
1759 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for decoding IFLA_INFO_KIND vxlan type %s (%d), length %d, padded to %d' %
1760 (parent_msg.get_ifla_vxlan_string(info_data_type), info_data_type, info_data_length, info_data_end))
1761
1762 elif ifla_info_kind == 'bond':
1763
1764 if info_data_type in (Link.IFLA_BOND_AD_INFO, ):
1765 ad_attr_data = sub_attr_data[4:info_data_end]
1766 self.value[Link.IFLA_INFO_DATA][Link.IFLA_BOND_AD_INFO] = {}
1767
1768 while ad_attr_data:
1769 (ad_data_length, ad_data_type) = unpack('=HH', ad_attr_data[:4])
1770 ad_data_end = padded_length(ad_data_length)
1771
1772 if ad_data_type in (Link.IFLA_BOND_AD_INFO_PARTNER_MAC,):
1773 (data1, data2) = unpack('>LHxx', ad_attr_data[4:12])
1774 self.value[Link.IFLA_INFO_DATA][Link.IFLA_BOND_AD_INFO][ad_data_type] = mac_int_to_str(data1 << 16 | data2)
1775
1776 ad_attr_data = ad_attr_data[ad_data_end:]
1777
1778 # 1-byte int
1779 elif info_data_type in (Link.IFLA_BOND_MODE,
1780 Link.IFLA_BOND_USE_CARRIER,
1781 Link.IFLA_BOND_AD_LACP_RATE,
1782 Link.IFLA_BOND_AD_LACP_BYPASS,
1783 Link.IFLA_BOND_XMIT_HASH_POLICY,
1784 Link.IFLA_BOND_NUM_PEER_NOTIF):
1785 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=B', sub_attr_data[4])[0]
1786
1787 # 2-bytes int
1788 elif info_data_type == Link.IFLA_BOND_AD_ACTOR_SYS_PRIO:
1789 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=H', sub_attr_data[4:6])[0]
1790
1791 # 4-bytes int
1792 elif info_data_type in (Link.IFLA_BOND_MIIMON,
1793 Link.IFLA_BOND_UPDELAY,
1794 Link.IFLA_BOND_DOWNDELAY,
1795 Link.IFLA_BOND_MIN_LINKS):
1796 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=L', sub_attr_data[4:8])[0]
1797
1798 # mac address
1799 elif info_data_type in (Link.IFLA_BOND_AD_ACTOR_SYSTEM, ):
1800 (data1, data2) = unpack('>LHxx', sub_attr_data[4:12])
1801 self.value[Link.IFLA_INFO_DATA][info_data_type] = mac_int_to_str(data1 << 16 | data2)
1802
1803 else:
1804 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for decoding IFLA_INFO_KIND bond type %s (%d), length %d, padded to %d' %
1805 (parent_msg.get_ifla_bond_string(info_data_type), info_data_type, info_data_length, info_data_end))
1806
1807 elif ifla_info_kind == 'bridge':
1808 # 4 bytes
1809 if info_data_type in (Link.IFLA_BR_AGEING_TIME,
1810 Link.IFLA_BR_FORWARD_DELAY,
1811 Link.IFLA_BR_HELLO_TIME,
1812 Link.IFLA_BR_MAX_AGE,
1813 Link.IFLA_BR_STP_STATE,
1814 Link.IFLA_BR_ROOT_PATH_COST,
1815 Link.IFLA_BR_MCAST_HASH_ELASTICITY,
1816 Link.IFLA_BR_MCAST_HASH_MAX,
1817 Link.IFLA_BR_MCAST_LAST_MEMBER_CNT,
1818 Link.IFLA_BR_MCAST_STARTUP_QUERY_CNT):
1819 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=L', sub_attr_data[4:8])[0]
1820
1821 # 2 bytes
1822 elif info_data_type in (Link.IFLA_BR_PRIORITY,
1823 Link.IFLA_BR_GROUP_FWD_MASK,
1824 Link.IFLA_BR_ROOT_PORT,
1825 Link.IFLA_BR_VLAN_DEFAULT_PVID):
1826 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=H', sub_attr_data[4:6])[0]
1827
1828 elif info_data_type == Link.IFLA_BR_VLAN_PROTOCOL:
1829 hex_value = '0x%s' % sub_attr_data[4:6].encode('hex')
1830 vlan_protocol = Link.ifla_vlan_protocol_dict.get(int(hex_value, base=16))
1831
1832 if vlan_protocol:
1833 self.value[Link.IFLA_INFO_DATA][info_data_type] = vlan_protocol
1834 else:
1835 self.log.warning('IFLA_VLAN_PROTOCOL: cannot decode vlan protocol %s' % hex_value)
1836
1837 # 8 bytes
1838 elif info_data_type in (Link.IFLA_BR_MCAST_MEMBERSHIP_INTVL,
1839 Link.IFLA_BR_MCAST_QUERIER_INTVL,
1840 Link.IFLA_BR_MCAST_LAST_MEMBER_INTVL,
1841 Link.IFLA_BR_MCAST_MEMBERSHIP_INTVL,
1842 Link.IFLA_BR_MCAST_QUERIER_INTVL,
1843 Link.IFLA_BR_MCAST_QUERY_INTVL,
1844 Link.IFLA_BR_MCAST_QUERY_RESPONSE_INTVL,
1845 Link.IFLA_BR_MCAST_STARTUP_QUERY_INTVL):
1846 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=Q', sub_attr_data[4:12])[0]
1847
1848 # 1 bytes
1849 elif info_data_type in (Link.IFLA_BR_VLAN_FILTERING,
1850 Link.IFLA_BR_TOPOLOGY_CHANGE,
1851 Link.IFLA_BR_TOPOLOGY_CHANGE_DETECTED,
1852 Link.IFLA_BR_MCAST_ROUTER,
1853 Link.IFLA_BR_MCAST_SNOOPING,
1854 Link.IFLA_BR_MCAST_QUERY_USE_IFADDR,
1855 Link.IFLA_BR_MCAST_QUERIER,
1856 Link.IFLA_BR_NF_CALL_IPTABLES,
1857 Link.IFLA_BR_NF_CALL_IP6TABLES,
1858 Link.IFLA_BR_NF_CALL_ARPTABLES,
1859 Link.IFLA_BR_VLAN_STATS_ENABLED,
1860 Link.IFLA_BR_MCAST_STATS_ENABLED,
1861 Link.IFLA_BR_MCAST_IGMP_VERSION,
1862 Link.IFLA_BR_MCAST_MLD_VERSION):
1863 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=B', sub_attr_data[4])[0]
1864 else:
1865 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for decoding IFLA_INFO_KIND bridge type %s (%d), length %d, padded to %d' %
1866 (parent_msg.get_ifla_br_string(info_data_type), info_data_type, info_data_length, info_data_end))
1867
1868 elif ifla_info_kind == 'vrf':
1869
1870 if info_data_type in (Link.IFLA_VRF_TABLE,):
1871 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=L', sub_attr_data[4:8])[0]
1872
1873 elif ifla_info_kind in ("gre", "gretap", "erspan", "ip6gre", "ip6gretap", "ip6erspan"):
1874
1875 # 1-byte
1876 if info_data_type in (Link.IFLA_GRE_TTL, Link.IFLA_GRE_TOS, Link.IFLA_GRE_PMTUDISC):
1877 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=B', sub_attr_data[4])[0]
1878
1879 # 2-bytes
1880 elif info_data_type in (
1881 Link.IFLA_GRE_IFLAGS,
1882 Link.IFLA_GRE_OFLAGS,
1883 Link.IFLA_GRE_ENCAP_TYPE,
1884 Link.IFLA_GRE_ENCAP_SPORT,
1885 Link.IFLA_GRE_ENCAP_DPORT,
1886 Link.IFLA_GRE_ENCAP_FLAGS
1887 ):
1888 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=H', sub_attr_data[4:6])[0]
1889
1890 # 4 bytes
1891 elif info_data_type in (Link.IFLA_GRE_LINK, Link.IFLA_GRE_IKEY, Link.IFLA_GRE_OKEY):
1892 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=L', sub_attr_data[4:8])[0]
1893
1894 # ip addr
1895 elif info_data_type in (Link.IFLA_GRE_LOCAL, Link.IFLA_GRE_REMOTE):
1896 if ifla_info_kind in ("ip6gre", "ip6gretap", "ip6erspan"):
1897 (data1, data2) = unpack(">QQ", sub_attr_data[4:20])
1898 self.value[Link.IFLA_INFO_DATA][info_data_type] = IPv6Address(data1 << 64 | data2)
1899 else:
1900 self.value[Link.IFLA_INFO_DATA][info_data_type] = IPv4Address(unpack(">L", sub_attr_data[4:8])[0])
1901
1902 else:
1903 self.log.log(SYSLOG_EXTRA_DEBUG,
1904 'Add support for decoding IFLA_INFO_KIND %s type %s (%d), length %d, padded to %d' %
1905 (ifla_info_kind, parent_msg.get_ifla_gre_string(info_data_type), info_data_type,
1906 info_data_length, info_data_end))
1907
1908 elif ifla_info_kind in ("ipip", "sit", "ip6tnl"):
1909
1910 # 1-byte
1911 if info_data_type in (Link.IFLA_IPTUN_TTL, Link.IFLA_IPTUN_TOS, Link.IFLA_IPTUN_PMTUDISC):
1912 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=B', sub_attr_data[4])[0]
1913
1914 # 2-bytes
1915 elif info_data_type in (Link.IFLA_IPTUN_ENCAP_TYPE, Link.IFLA_IPTUN_ENCAP_SPORT, Link.IFLA_IPTUN_ENCAP_DPORT, Link.IFLA_IPTUN_ENCAP_FLAGS):
1916 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=H', sub_attr_data[4:6])[
1917 0]
1918
1919 # 4 bytes
1920 elif info_data_type == Link.IFLA_IPTUN_LINK:
1921 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=L', sub_attr_data[4:8])[
1922 0]
1923
1924 # ip addr
1925 elif info_data_type in (Link.IFLA_IPTUN_LOCAL, Link.IFLA_IPTUN_REMOTE):
1926 if ifla_info_kind == "ip6tnl":
1927 (data1, data2) = unpack(">QQ", sub_attr_data[4:20])
1928 self.value[Link.IFLA_INFO_DATA][info_data_type] = IPv6Address(data1 << 64 | data2)
1929 else:
1930 self.value[Link.IFLA_INFO_DATA][info_data_type] = IPv4Address(unpack(">L", sub_attr_data[4:8])[0])
1931
1932 else:
1933 self.log.log(SYSLOG_EXTRA_DEBUG,
1934 'Add support for decoding IFLA_INFO_KIND %s type %s (%d), length %d, padded to %d' %
1935 (ifla_info_kind, parent_msg.get_ifla_iptun_string(info_data_type), info_data_type,
1936 info_data_length, info_data_end))
1937
1938 elif ifla_info_kind in ("vti", "vti6"):
1939 # 4 bytes
1940 if info_data_type in (Link.IFLA_VTI_LINK, Link.IFLA_VTI_IKEY, Link.IFLA_VTI_OKEY):
1941 self.value[Link.IFLA_INFO_DATA][info_data_type] = unpack('=L', sub_attr_data[4:8])[0]
1942
1943 # ip addr
1944 elif info_data_type in (Link.IFLA_VTI_LOCAL, Link.IFLA_VTI_REMOTE):
1945 if ifla_info_kind == "vti6":
1946 (data1, data2) = unpack(">QQ", sub_attr_data[4:20])
1947 self.value[Link.IFLA_INFO_DATA][info_data_type] = IPv6Address(data1 << 64 | data2)
1948 else:
1949 self.value[Link.IFLA_INFO_DATA][info_data_type] = IPv4Address(unpack(">L", sub_attr_data[4:8])[0])
1950
1951 else:
1952 self.log.log(SYSLOG_EXTRA_DEBUG,
1953 'Add support for decoding IFLA_INFO_KIND %s type %s (%d), length %d, padded to %d' %
1954 (ifla_info_kind, parent_msg.get_ifla_vti_string(info_data_type), info_data_type,
1955 info_data_length, info_data_end))
1956
1957 else:
1958 self.log.log(SYSLOG_EXTRA_DEBUG, "Add support for decoding IFLA_INFO_KIND %s (%d), length %d, padded to %d" %
1959 (ifla_info_kind, info_data_type, info_data_length, info_data_end))
1960
1961 except Exception as e:
1962 self.log.debug('%s: attribute %s: %s'
1963 % (self.value[Link.IFLA_INFO_KIND],
1964 info_data_type,
1965 str(e)))
1966 sub_attr_data = sub_attr_data[info_data_end:]
1967
1968 else:
1969 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for decoding IFLA_LINKINFO sub-attribute type %s (%d), length %d, padded to %d' %
1970 (parent_msg.get_ifla_info_string(sub_attr_type), sub_attr_type, sub_attr_length, sub_attr_end))
1971
1972 data = data[sub_attr_end:]
1973
1974 # self.log.info('IFLA_LINKINFO values %s' % pformat(self.value))
1975
1976 def dump_lines(self, dump_buffer, line_number, color):
1977 line_number = self.dump_first_line(dump_buffer, line_number, color)
1978 extra = ''
1979
1980 next_sub_attr_line = 0
1981 sub_attr_line = True
1982
1983 for x in xrange(1, self.attr_end/4):
1984 start = x * 4
1985 end = start + 4
1986
1987 if line_number == next_sub_attr_line:
1988 sub_attr_line = True
1989
1990 if sub_attr_line:
1991 sub_attr_line = False
1992
1993 (sub_attr_length, sub_attr_type) = unpack('=HH', self.data[start:start+4])
1994 sub_attr_end = padded_length(sub_attr_length)
1995
1996 next_sub_attr_line = line_number + (sub_attr_end/4)
1997
1998 if sub_attr_end == sub_attr_length:
1999 padded_to = ', '
2000 else:
2001 padded_to = ' padded to %d, ' % sub_attr_end
2002
2003 extra = 'Nested Attribute - Length %s (%d)%s Type %s (%d) %s' % \
2004 (zfilled_hex(sub_attr_length, 4), sub_attr_length,
2005 padded_to,
2006 zfilled_hex(sub_attr_type, 4), sub_attr_type,
2007 Link.ifla_info_to_string.get(sub_attr_type))
2008 else:
2009 extra = ''
2010
2011 dump_buffer.append(data_to_color_text(line_number, color, self.data[start:end], extra))
2012 line_number += 1
2013
2014 return line_number
2015
2016 def get_pretty_value(self, obj=None):
2017
2018 if obj and callable(obj):
2019 return obj(self.value)
2020
2021 value_pretty = self.value
2022 ifla_info_kind = self.value.get(Link.IFLA_INFO_KIND)
2023 ifla_info_slave_kind = self.value.get(Link.IFLA_INFO_SLAVE_KIND)
2024
2025 kind_dict = dict()
2026
2027 # We do this so we can print a more human readable dictionary
2028 # with the names of the nested keys instead of their numbers
2029
2030 # Most of these are placeholders...we need to add support
2031 # for more human readable dictionaries for bond, bridge, etc
2032 kind_dict[Link.IFLA_INFO_DATA] = {
2033 'bond': Link.ifla_bond_to_string,
2034 'vlan': Link.ifla_vlan_to_string,
2035 'vxlan': Link.ifla_vxlan_to_string,
2036 'bridge': Link.ifla_br_to_string,
2037 'macvlan': Link.ifla_macvlan_to_string,
2038 'gre': Link.ifla_gre_to_string,
2039 'gretap': Link.ifla_gre_to_string,
2040 'erspan': Link.ifla_gre_to_string,
2041 'ip6gre': Link.ifla_gre_to_string,
2042 'ip6gretap': Link.ifla_gre_to_string,
2043 'ip6erspan': Link.ifla_gre_to_string,
2044 'vti': Link.ifla_vti_to_string,
2045 'vti6': Link.ifla_vti_to_string,
2046 'ipip': Link.ifla_iptun_to_string,
2047 'sit': Link.ifla_iptun_to_string,
2048 'ip6tnl': Link.ifla_iptun_to_string,
2049 'xfrm': Link.ifla_xfrm_to_string
2050 }.get(ifla_info_kind, {})
2051
2052 kind_dict[Link.IFLA_INFO_SLAVE_DATA] = {
2053 'bridge': Link.ifla_brport_to_string,
2054 'bond': Link.ifla_bond_slave_to_string
2055 }.get(ifla_info_slave_kind, {})
2056
2057 if ifla_info_kind or ifla_info_slave_kind:
2058 value_pretty = {}
2059
2060 for (sub_key, sub_value) in self.value.iteritems():
2061 sub_key_pretty = "(%2d) %s" % (sub_key, Link.ifla_info_to_string.get(sub_key, 'UNKNOWN'))
2062 sub_value_pretty = sub_value
2063
2064 if sub_key in (Link.IFLA_INFO_DATA, Link.IFLA_INFO_SLAVE_DATA):
2065 kind_to_string_dict = kind_dict.get(sub_key, {})
2066 sub_value_pretty = {}
2067
2068 for (sub_sub_key, sub_sub_value) in sub_value.iteritems():
2069 sub_sub_key_pretty = "(%2d) %s" % (sub_sub_key, kind_to_string_dict.get(sub_sub_key, 'UNKNOWN'))
2070 sub_value_pretty[sub_sub_key_pretty] = sub_sub_value
2071
2072 value_pretty[sub_key_pretty] = sub_value_pretty
2073
2074 return value_pretty
2075
2076
2077 class AttributeIFLA_PROTINFO(Attribute):
2078 """
2079 IFLA_PROTINFO nested attributes.
2080 """
2081 def __init__(self, atype, string, family, logger):
2082 Attribute.__init__(self, atype, string, logger)
2083 self.family = family
2084
2085 def encode(self):
2086 pack_layout = [self.HEADER_PACK]
2087 payload = [0, self.atype | NLA_F_NESTED]
2088 attr_length_index = 0
2089
2090 if self.family not in (AF_BRIDGE,):
2091 raise Exception('Unsupported IFLA_PROTINFO family %d' % self.family)
2092
2093 # For now this assumes that all data will be packed in the native endian
2094 # order (=). If a field is added that needs to be packed via network
2095 # order (>) then some smarts will need to be added to split the pack_layout
2096 # string at the >, split the payload and make the needed pack() calls.
2097 #
2098 # Until we cross that bridge though we will keep things nice and simple and
2099 # pack everything via a single pack() call.
2100 for (sub_attr_type, sub_attr_value) in self.value.iteritems():
2101 sub_attr_pack_layout = ['=', 'HH']
2102 sub_attr_payload = [0, sub_attr_type]
2103 sub_attr_length_index = 0
2104
2105 if self.family == AF_BRIDGE:
2106 # 1 Byte attributes
2107 if sub_attr_type in (Link.IFLA_BRPORT_STATE,
2108 Link.IFLA_BRPORT_MODE,
2109 Link.IFLA_BRPORT_GUARD,
2110 Link.IFLA_BRPORT_PROTECT,
2111 Link.IFLA_BRPORT_FAST_LEAVE,
2112 Link.IFLA_BRPORT_LEARNING,
2113 Link.IFLA_BRPORT_UNICAST_FLOOD,
2114 Link.IFLA_BRPORT_PROXYARP,
2115 Link.IFLA_BRPORT_LEARNING_SYNC,
2116 Link.IFLA_BRPORT_PROXYARP_WIFI,
2117 Link.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
2118 Link.IFLA_BRPORT_CONFIG_PENDING,
2119 Link.IFLA_BRPORT_FLUSH,
2120 Link.IFLA_BRPORT_MULTICAST_ROUTER,
2121 Link.IFLA_BRPORT_PEER_LINK,
2122 Link.IFLA_BRPORT_DUAL_LINK,
2123 Link.IFLA_BRPORT_ARP_SUPPRESS,
2124 Link.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT):
2125 sub_attr_pack_layout.append('B')
2126 sub_attr_payload.append(sub_attr_value)
2127 sub_attr_pack_layout.extend('xxx')
2128
2129 # 2 Byte attributes
2130 elif sub_attr_type in (Link.IFLA_BRPORT_PRIORITY,
2131 Link.IFLA_BRPORT_DESIGNATED_PORT,
2132 Link.IFLA_BRPORT_DESIGNATED_COST,
2133 Link.IFLA_BRPORT_ID,
2134 Link.IFLA_BRPORT_NO):
2135 sub_attr_pack_layout.append('H')
2136 sub_attr_payload.append(sub_attr_value)
2137 sub_attr_pack_layout.extend('xx')
2138
2139 # 4 Byte attributes
2140 elif sub_attr_type in (Link.IFLA_BRPORT_COST,):
2141 sub_attr_pack_layout.append('L')
2142 sub_attr_payload.append(sub_attr_value)
2143
2144 # 8 Byte attributes
2145 elif sub_attr_type in (Link.IFLA_BRPORT_MESSAGE_AGE_TIMER,
2146 Link.IFLA_BRPORT_FORWARD_DELAY_TIMER,
2147 Link.IFLA_BRPORT_HOLD_TIMER):
2148 sub_attr_pack_layout.append('Q')
2149 sub_attr_payload.append(sub_attr_value)
2150
2151 else:
2152 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for encoding IFLA_PROTINFO sub-attribute type %d' % sub_attr_type)
2153
2154 sub_attr_length = calcsize(''.join(sub_attr_pack_layout))
2155 sub_attr_payload[sub_attr_length_index] = sub_attr_length
2156
2157 # add padding
2158 for x in xrange(self.pad_bytes_needed(sub_attr_length)):
2159 sub_attr_pack_layout.append('x')
2160
2161 # The [1:] is to remove the leading = so that when we do the ''.join() later
2162 # we do not end up with an = in the middle of the pack layout string. There
2163 # will be an = at the beginning via self.HEADER_PACK
2164 sub_attr_pack_layout = sub_attr_pack_layout[1:]
2165
2166 # Now extend the ovarall attribute pack_layout/payload to include this sub-attribute
2167 pack_layout.extend(sub_attr_pack_layout)
2168 payload.extend(sub_attr_payload)
2169
2170 pack_layout = ''.join(pack_layout)
2171
2172 # Fill in the length field
2173 length = calcsize(pack_layout)
2174 payload[attr_length_index] = length
2175
2176 raw = pack(pack_layout, *payload)
2177 raw = self.pad(length, raw)
2178 return raw
2179
2180 def decode(self, parent_msg, data):
2181 """
2182 value is a dictionary such as:
2183 {
2184 Link.IFLA_BRPORT_STATE : 3,
2185 Link.IFLA_BRPORT_PRIORITY : 8
2186 Link.IFLA_BRPORT_COST : 2
2187 ...
2188 }
2189 """
2190 self.decode_length_type(data)
2191 self.value = {}
2192
2193 data = self.data[4:]
2194
2195 while data:
2196 (sub_attr_length, sub_attr_type) = unpack('=HH', data[:4])
2197 sub_attr_end = padded_length(sub_attr_length)
2198
2199 if not sub_attr_length:
2200 self.log.error('parsed a zero length sub-attr')
2201 return
2202
2203 if self.family == AF_BRIDGE:
2204
2205 # 1 Byte attributes
2206 if sub_attr_type in (Link.IFLA_BRPORT_STATE,
2207 Link.IFLA_BRPORT_MODE,
2208 Link.IFLA_BRPORT_GUARD,
2209 Link.IFLA_BRPORT_PROTECT,
2210 Link.IFLA_BRPORT_FAST_LEAVE,
2211 Link.IFLA_BRPORT_LEARNING,
2212 Link.IFLA_BRPORT_UNICAST_FLOOD,
2213 Link.IFLA_BRPORT_PROXYARP,
2214 Link.IFLA_BRPORT_LEARNING_SYNC,
2215 Link.IFLA_BRPORT_PROXYARP_WIFI,
2216 Link.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
2217 Link.IFLA_BRPORT_CONFIG_PENDING,
2218 Link.IFLA_BRPORT_FLUSH,
2219 Link.IFLA_BRPORT_MULTICAST_ROUTER,
2220 Link.IFLA_BRPORT_PEER_LINK,
2221 Link.IFLA_BRPORT_DUAL_LINK,
2222 Link.IFLA_BRPORT_ARP_SUPPRESS,
2223 Link.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT):
2224 self.value[sub_attr_type] = unpack('=B', data[4])[0]
2225
2226 # 2 Byte attributes
2227 elif sub_attr_type in (Link.IFLA_BRPORT_PRIORITY,
2228 Link.IFLA_BRPORT_DESIGNATED_PORT,
2229 Link.IFLA_BRPORT_DESIGNATED_COST,
2230 Link.IFLA_BRPORT_ID,
2231 Link.IFLA_BRPORT_NO):
2232 self.value[sub_attr_type] = unpack('=H', data[4:6])[0]
2233
2234 # 4 Byte attributes
2235 elif sub_attr_type in (Link.IFLA_BRPORT_COST,):
2236 self.value[sub_attr_type] = unpack('=L', data[4:8])[0]
2237
2238 # 8 Byte attributes
2239 elif sub_attr_type in (Link.IFLA_BRPORT_MESSAGE_AGE_TIMER,
2240 Link.IFLA_BRPORT_FORWARD_DELAY_TIMER,
2241 Link.IFLA_BRPORT_HOLD_TIMER):
2242 self.value[sub_attr_type] = unpack('=Q', data[4:12])[0]
2243
2244 else:
2245 self.log.log(SYSLOG_EXTRA_DEBUG, 'Add support for decoding IFLA_PROTINFO sub-attribute type %s (%d), length %d, padded to %d' %
2246 (parent_msg.get_ifla_brport_string(sub_attr_type), sub_attr_type, sub_attr_length, sub_attr_end))
2247
2248 data = data[sub_attr_end:]
2249
2250 def dump_lines(self, dump_buffer, line_number, color):
2251 line_number = self.dump_first_line(dump_buffer, line_number, color)
2252 extra = ''
2253
2254 next_sub_attr_line = 0
2255 sub_attr_line = True
2256
2257 for x in xrange(1, self.attr_end/4):
2258 start = x * 4
2259 end = start + 4
2260
2261 if line_number == next_sub_attr_line:
2262 sub_attr_line = True
2263
2264 if sub_attr_line:
2265 sub_attr_line = False
2266
2267 (sub_attr_length, sub_attr_type) = unpack('=HH', self.data[start:start+4])
2268 sub_attr_end = padded_length(sub_attr_length)
2269
2270 next_sub_attr_line = line_number + (sub_attr_end/4)
2271
2272 if sub_attr_end == sub_attr_length:
2273 padded_to = ', '
2274 else:
2275 padded_to = ' padded to %d, ' % sub_attr_end
2276
2277 extra = 'Nested Attribute - Length %s (%d)%s Type %s (%d) %s' % \
2278 (zfilled_hex(sub_attr_length, 4), sub_attr_length,
2279 padded_to,
2280 zfilled_hex(sub_attr_type, 4), sub_attr_type,
2281 Link.ifla_brport_to_string.get(sub_attr_type))
2282 else:
2283 extra = ''
2284
2285 dump_buffer.append(data_to_color_text(line_number, color, self.data[start:end], extra))
2286 line_number += 1
2287
2288 return line_number
2289
2290 def get_pretty_value(self, obj=None):
2291
2292 if obj and callable(obj):
2293 return obj(self.value)
2294
2295 value_pretty = {}
2296
2297 for (sub_key, sub_value) in self.value.iteritems():
2298 sub_key_pretty = "(%2d) %s" % (sub_key, Link.ifla_brport_to_string.get(sub_key, 'UNKNOWN'))
2299 sub_value_pretty = sub_value
2300 value_pretty[sub_key_pretty] = sub_value_pretty
2301
2302 return value_pretty
2303
2304
2305
2306 class NetlinkPacket(object):
2307 """
2308 Netlink Header
2309
2310 0 1 2 3
2311 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2312 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2313 | Length |
2314 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2315 | Type | Flags |
2316 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2317 | Sequence Number |
2318 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2319 | Process ID (PID) |
2320 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2321 """
2322
2323 header_PACK = 'IHHII'
2324 header_LEN = calcsize(header_PACK)
2325
2326 # Netlink packet types
2327 # /usr/include/linux/rtnetlink.h
2328 type_to_string = {
2329 NLMSG_NOOP : 'NLMSG_NOOP',
2330 NLMSG_ERROR : 'NLMSG_ERROR',
2331 NLMSG_DONE : 'NLMSG_DONE',
2332 NLMSG_OVERRUN : 'NLMSG_OVERRUN',
2333 RTM_NEWLINK : 'RTM_NEWLINK',
2334 RTM_DELLINK : 'RTM_DELLINK',
2335 RTM_GETLINK : 'RTM_GETLINK',
2336 RTM_SETLINK : 'RTM_SETLINK',
2337 RTM_NEWADDR : 'RTM_NEWADDR',
2338 RTM_DELADDR : 'RTM_DELADDR',
2339 RTM_GETADDR : 'RTM_GETADDR',
2340 RTM_NEWNEIGH : 'RTM_NEWNEIGH',
2341 RTM_DELNEIGH : 'RTM_DELNEIGH',
2342 RTM_GETNEIGH : 'RTM_GETNEIGH',
2343 RTM_NEWROUTE : 'RTM_NEWROUTE',
2344 RTM_DELROUTE : 'RTM_DELROUTE',
2345 RTM_GETROUTE : 'RTM_GETROUTE',
2346 RTM_NEWQDISC : 'RTM_NEWQDISC',
2347 RTM_DELQDISC : 'RTM_DELQDISC',
2348 RTM_GETQDISC : 'RTM_GETQDISC',
2349 RTM_NEWNETCONF: 'RTM_NEWNETCONF',
2350 RTM_GETNETCONF: 'RTM_GETNETCONF'
2351 }
2352
2353 af_family_to_string = {
2354 AF_INET : 'inet',
2355 AF_INET6 : 'inet6'
2356 }
2357
2358 def __init__(self, msgtype, debug, owner_logger=None, use_color=True):
2359 self.msgtype = msgtype
2360 self.attributes = {}
2361 self.dump_buffer = ['']
2362 self.line_number = 1
2363 self.debug = debug
2364 self.message = None
2365 self.use_color = use_color
2366 self.family = None
2367
2368 if owner_logger:
2369 self.log = owner_logger
2370 else:
2371 self.log = log
2372
2373 def __str__(self):
2374 return self.get_type_string()
2375
2376 def get_string(self, to_string, index):
2377 """
2378 Used to do lookups in all of the various FOO_to_string dictionaries
2379 but returns 'UNKNOWN' if the key is bogus
2380 """
2381 if index in to_string:
2382 return to_string[index]
2383 return 'UNKNOWN'
2384
2385 def get_type_string(self, msgtype=None):
2386 if not msgtype:
2387 msgtype = self.msgtype
2388 return self.get_string(self.type_to_string, msgtype)
2389
2390 def get_flags_string(self):
2391 foo = []
2392
2393 for (flag, flag_string) in self.flag_to_string.iteritems():
2394 if self.flags & flag:
2395 foo.append(flag_string)
2396
2397 return ', '.join(foo)
2398
2399 def decode_packet(self, length, flags, seq, pid, data):
2400 self.length = length
2401 self.flags = flags
2402 self.seq = seq
2403 self.pid = pid
2404 self.header_data = data[0:self.header_LEN]
2405 self.msg_data = data[self.header_LEN:length]
2406
2407 self.decode_netlink_header()
2408 self.decode_service_header()
2409
2410 # NLMSG_ERROR is special case, it does not have attributes to decode
2411 if self.msgtype != NLMSG_ERROR:
2412 self.decode_attributes()
2413
2414 def get_netlink_header_flags_string(self, msg_type, flags):
2415 foo = []
2416
2417 if flags & NLM_F_REQUEST:
2418 foo.append('NLM_F_REQUEST')
2419
2420 if flags & NLM_F_MULTI:
2421 foo.append('NLM_F_MULTI')
2422
2423 if flags & NLM_F_ACK:
2424 foo.append('NLM_F_ACK')
2425
2426 if flags & NLM_F_ECHO:
2427 foo.append('NLM_F_ECHO')
2428
2429 # Modifiers to GET query
2430 if msg_type in (RTM_GETLINK, RTM_GETADDR, RTM_GETNEIGH, RTM_GETROUTE, RTM_GETQDISC, RTM_GETNETCONF):
2431 if flags & NLM_F_DUMP:
2432 foo.append('NLM_F_DUMP')
2433 else:
2434 if flags & NLM_F_MATCH:
2435 foo.append('NLM_F_MATCH')
2436
2437 if flags & NLM_F_ROOT:
2438 foo.append('NLM_F_ROOT')
2439
2440 if flags & NLM_F_ATOMIC:
2441 foo.append('NLM_F_ATOMIC')
2442
2443 # Modifiers to NEW query
2444 elif msg_type in (RTM_NEWLINK, RTM_NEWADDR, RTM_NEWNEIGH, RTM_NEWROUTE, RTM_NEWQDISC):
2445 if flags & NLM_F_REPLACE:
2446 foo.append('NLM_F_REPLACE')
2447
2448 if flags & NLM_F_EXCL:
2449 foo.append('NLM_F_EXCL')
2450
2451 if flags & NLM_F_CREATE:
2452 foo.append('NLM_F_CREATE')
2453
2454 if flags & NLM_F_APPEND:
2455 foo.append('NLM_F_APPEND')
2456
2457 return ', '.join(foo)
2458
2459 # When we first RXed the netlink message we had to decode the header to
2460 # determine what type of netlink message we were dealing with. So the
2461 # header has actually already been decoded...what we do here is
2462 # populate the dump_buffer lines with the header content.
2463 def decode_netlink_header(self):
2464
2465 if not self.debug:
2466 return
2467
2468 header_data = self.header_data
2469
2470 # Print the netlink header in red
2471 netlink_header_length = 16
2472 color = red if self.use_color else None
2473 color_start = "\033[%dm" % color if color else ""
2474 color_end = "\033[0m" if color else ""
2475 self.dump_buffer.append(" %sNetlink Header%s" % (color_start, color_end))
2476
2477 for x in range(0, netlink_header_length/4):
2478 start = x * 4
2479 end = start + 4
2480
2481 if self.line_number == 1:
2482 data = unpack('=L', header_data[start:end])[0]
2483 extra = "Length %s (%d)" % (zfilled_hex(data, 8), data)
2484
2485 elif self.line_number == 2:
2486 (data1, data2) = unpack('HH', header_data[start:end])
2487 extra = "Type %s (%d - %s), Flags %s (%s)" % \
2488 (zfilled_hex(data1, 4), data1, self.get_type_string(data1),
2489 zfilled_hex(data2, 4), self.get_netlink_header_flags_string(data1, data2))
2490
2491 elif self.line_number == 3:
2492 data = unpack('=L', header_data[start:end])[0]
2493 extra = "Sequence Number %s (%d)" % (zfilled_hex(data, 8), data)
2494
2495 elif self.line_number == 4:
2496 data = unpack('=L', header_data[start:end])[0]
2497 extra = "Process ID %s (%d)" % (zfilled_hex(data, 8), data)
2498 else:
2499 extra = "Unexpected line number %d" % self.line_number
2500
2501 self.dump_buffer.append(data_to_color_text(self.line_number, color, header_data[start:end], extra))
2502 self.line_number += 1
2503
2504 def decode_attributes(self):
2505 """
2506 Decode the attributes and populate the dump_buffer
2507 """
2508
2509 if self.debug:
2510 self.dump_buffer.append(" Attributes")
2511 color = green if self.use_color else None
2512
2513 data = self.msg_data[self.LEN:]
2514
2515 while data:
2516 (length, attr_type) = unpack('=HH', data[:4])
2517
2518 # If this is zero we will stay in this loop for forever
2519 if not length:
2520 self.log.error('Length is zero')
2521 return
2522
2523 if len(data) < length:
2524 self.log.error("Buffer underrun %d < %d" % (len(data), length))
2525 return
2526
2527 attr = self.add_attribute(attr_type, None)
2528
2529 # Find the end of 'data' for this attribute and decode our section
2530 # of 'data'. attributes are padded for alignment thus the attr_end.
2531 #
2532 # How the attribute is decoded/unpacked is specific per AttributeXXXX class.
2533 attr_end = padded_length(length)
2534 attr.decode(self, data[0:attr_end])
2535
2536 if self.debug:
2537 self.line_number = attr.dump_lines(self.dump_buffer, self.line_number, color)
2538
2539 # Alternate back and forth between green and blue
2540 if self.use_color:
2541 if color == green:
2542 color = blue
2543 else:
2544 color = green
2545
2546 data = data[attr_end:]
2547
2548 def add_attribute(self, attr_type, value):
2549 nested = True if attr_type & NLA_F_NESTED else False
2550 net_byteorder = True if attr_type & NLA_F_NET_BYTEORDER else False
2551 attr_type = attr_type & NLA_TYPE_MASK
2552
2553 # Given an attr_type (say RTA_DST) find the type of AttributeXXXX class
2554 # that we will use to store this attribute...AttributeIPAddress in the
2555 # case of RTA_DST.
2556 if attr_type in self.attribute_to_class:
2557 (attr_string, attr_class) = self.attribute_to_class[attr_type]
2558
2559 '''
2560 attribute_to_class is a dictionary where the key is the attr_type, it doesn't
2561 take the family into account. For now we'll handle this as a special case for
2562 MPLS but long term we may need to make key a tuple of the attr_type and family.
2563 '''
2564 if self.msgtype not in (RTM_NEWNETCONF, RTM_GETNETCONF) and attr_type == Route.RTA_DST and self.family == AF_MPLS:
2565 attr_string = 'RTA_DST'
2566 attr_class = AttributeMplsLabel
2567
2568 else:
2569 attr_string = "UNKNOWN_ATTRIBUTE_%d" % attr_type
2570 attr_class = AttributeGeneric
2571 self.log.debug("Attribute %d is not defined in %s.attribute_to_class, assuming AttributeGeneric" %
2572 (attr_type, self.__class__.__name__))
2573
2574 attr = attr_class(attr_type, attr_string, self.family, self.log)
2575
2576 attr.set_value(value)
2577 attr.set_nested(nested)
2578 attr.set_net_byteorder(net_byteorder)
2579
2580 # self.attributes is a dictionary keyed by the attribute type where
2581 # the value is an instance of the corresponding AttributeXXXX class.
2582 self.attributes[attr_type] = attr
2583
2584 return attr
2585
2586 def get_attribute_value(self, attr_type, default=None):
2587 if attr_type not in self.attributes:
2588 return default
2589
2590 return self.attributes[attr_type].value
2591
2592 def get_attr_string(self, attr_type):
2593 """
2594 Example: If attr_type is Address.IFA_CACHEINFO return the string 'IFA_CACHEINFO'
2595 """
2596 if attr_type in self.attribute_to_class:
2597 (attr_string, attr_class) = self.attribute_to_class[attr_type]
2598 return attr_string
2599 return str(attr_type)
2600
2601 def build_message(self, seq, pid):
2602 self.seq = seq
2603 self.pid = pid
2604 attrs = ''
2605
2606 for attr in self.attributes.itervalues():
2607 attrs += attr.encode()
2608
2609 self.length = self.header_LEN + len(self.body) + len(attrs)
2610 self.header_data = pack(self.header_PACK, self.length, self.msgtype, self.flags, self.seq, self.pid)
2611 self.msg_data = self.body + attrs
2612 self.message = self.header_data + self.msg_data
2613
2614 if self.debug:
2615 self.decode_netlink_header()
2616 self.decode_service_header()
2617 self.decode_attributes()
2618 self.dump("TXed %s, length %d, seq %d, pid %d, flags 0x%x (%s)" %
2619 (self, self.length, self.seq, self.pid, self.flags,
2620 self.get_netlink_header_flags_string(self.msgtype, self.flags)))
2621
2622 def pretty_display_dict(self, dic, level):
2623 for k,v in dic.iteritems():
2624 if isinstance(v, dict):
2625 self.log.debug(' '*level + str(k) + ':')
2626 self.pretty_display_dict(v, level+5)
2627 else:
2628 self.log.debug(' '*level + str(k) + ': ' + str(v))
2629
2630 # Print the netlink message in hex. This is only used for debugging.
2631 def dump(self, desc=None):
2632 attr_string = {}
2633
2634 if desc is None:
2635 desc = "RXed %s, length %d, seq %d, pid %d, flags 0x%x" % (self, self.length, self.seq, self.pid, self.flags)
2636
2637 for (attr_type, attr_obj) in self.attributes.iteritems():
2638 key_string = "(%2d) %s" % (attr_type, self.get_attr_string(attr_type))
2639 attr_string[key_string] = attr_obj.get_pretty_value()
2640
2641 if self.use_color:
2642 self.log.debug("%s\n%s\n\nAttributes Summary\n%s\n" %
2643 (desc, '\n'.join(self.dump_buffer), pformat(attr_string)))
2644 else:
2645 # Assume if we are not allowing color output we also don't want embedded
2646 # newline characters in the output. Output each line individually.
2647 self.log.debug(desc)
2648 for line in self.dump_buffer:
2649 self.log.debug(line)
2650 self.log.debug("")
2651 self.log.debug("Attributes Summary")
2652 self.pretty_display_dict(attr_string, 1)
2653
2654
2655 class Address(NetlinkPacket):
2656 """
2657 Service Header
2658 0 1 2 3
2659 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2660 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2661 | Family | Length | Flags | Scope |
2662 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2663 | Interface Index |
2664 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2665 """
2666
2667 # Address attributes
2668 # /usr/include/linux/if_addr.h
2669 IFA_UNSPEC = 0x00
2670 IFA_ADDRESS = 0x01
2671 IFA_LOCAL = 0x02
2672 IFA_LABEL = 0x03
2673 IFA_BROADCAST = 0x04
2674 IFA_ANYCAST = 0x05
2675 IFA_CACHEINFO = 0x06
2676 IFA_MULTICAST = 0x07
2677 IFA_FLAGS = 0x08
2678
2679 attribute_to_class = {
2680 IFA_UNSPEC : ('IFA_UNSPEC', AttributeGeneric),
2681 IFA_ADDRESS : ('IFA_ADDRESS', AttributeIPAddress),
2682 IFA_LOCAL : ('IFA_LOCAL', AttributeIPAddress),
2683 IFA_LABEL : ('IFA_LABEL', AttributeString),
2684 IFA_BROADCAST : ('IFA_BROADCAST', AttributeIPAddress),
2685 IFA_ANYCAST : ('IFA_ANYCAST', AttributeIPAddress),
2686 IFA_CACHEINFO : ('IFA_CACHEINFO', AttributeGeneric),
2687 IFA_MULTICAST : ('IFA_MULTICAST', AttributeIPAddress),
2688 IFA_FLAGS : ('IFA_FLAGS', AttributeGeneric)
2689 }
2690
2691 # Address flags
2692 # /usr/include/linux/if_addr.h
2693 IFA_F_SECONDARY = 0x01
2694 IFA_F_NODAD = 0x02
2695 IFA_F_OPTIMISTIC = 0x04
2696 IFA_F_DADFAILED = 0x08
2697 IFA_F_HOMEADDRESS = 0x10
2698 IFA_F_DEPRECATED = 0x20
2699 IFA_F_TENTATIVE = 0x40
2700 IFA_F_PERMANENT = 0x80
2701
2702 flag_to_string = {
2703 IFA_F_SECONDARY : 'IFA_F_SECONDARY',
2704 IFA_F_NODAD : 'IFA_F_NODAD',
2705 IFA_F_OPTIMISTIC : 'IFA_F_OPTIMISTIC',
2706 IFA_F_DADFAILED : 'IFA_F_DADFAILED',
2707 IFA_F_HOMEADDRESS : 'IFA_F_HOMEADDRESS',
2708 IFA_F_DEPRECATED : 'IFA_F_DEPRECATED',
2709 IFA_F_TENTATIVE : 'IFA_F_TENTATIVE',
2710 IFA_F_PERMANENT : 'IFA_F_PERMANENT'
2711 }
2712
2713 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
2714 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
2715 self.PACK = '4Bi'
2716 self.LEN = calcsize(self.PACK)
2717
2718 def decode_service_header(self):
2719
2720 # Nothing to do if the message did not contain a service header
2721 if self.length == self.header_LEN:
2722 return
2723
2724 (self.family, self.prefixlen, self.flags, self.scope,
2725 self.ifindex) = \
2726 unpack(self.PACK, self.msg_data[:self.LEN])
2727
2728 if self.debug:
2729 color = yellow if self.use_color else None
2730 color_start = "\033[%dm" % color if color else ""
2731 color_end = "\033[0m" if color else ""
2732 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
2733
2734 for x in range(0, self.LEN/4):
2735 if self.line_number == 5:
2736 extra = "Family %s (%s:%d), Length %s (%d), Flags %s, Scope %s (%d)" % \
2737 (zfilled_hex(self.family, 2), get_family_str(self.family), self.family,
2738 zfilled_hex(self.prefixlen, 2), self.prefixlen,
2739 zfilled_hex(self.flags, 2),
2740 zfilled_hex(self.scope, 2), self.scope)
2741 elif self.line_number == 6:
2742 extra = "Interface Index %s (%d)" % (zfilled_hex(self.ifindex, 8), self.ifindex)
2743 else:
2744 extra = "Unexpected line number %d" % self.line_number
2745
2746 start = x * 4
2747 end = start + 4
2748 self.dump_buffer.append(data_to_color_text(self.line_number, color, self.msg_data[start:end], extra))
2749 self.line_number += 1
2750
2751
2752 class Error(NetlinkPacket):
2753
2754 # Error codes
2755 # /include/netlink/errno.h
2756 NLE_SUCCESS = 0x00
2757 NLE_FAILURE = 0x01
2758 NLE_INTR = 0x02
2759 NLE_BAD_SOCK = 0x03
2760 NLE_AGAIN = 0x04
2761 NLE_NOMEM = 0x05
2762 NLE_EXIST = 0x06
2763 NLE_INVAL = 0x07
2764 NLE_RANGE = 0x08
2765 NLE_MSGSIZE = 0x09
2766 NLE_OPNOTSUPP = 0x0A
2767 NLE_AF_NOSUPPORT = 0x0B
2768 NLE_OBJ_NOTFOUND = 0x0C
2769 NLE_NOATTR = 0x0D
2770 NLE_MISSING_ATTR = 0x0E
2771 NLE_AF_MISMATCH = 0x0F
2772 NLE_SEQ_MISMATCH = 0x10
2773 NLE_MSG_OVERFLOW = 0x11
2774 NLE_MSG_TRUNC = 0x12
2775 NLE_NOADDR = 0x13
2776 NLE_SRCRT_NOSUPPORT = 0x14
2777 NLE_MSG_TOOSHORT = 0x15
2778 NLE_MSGTYPE_NOSUPPORT = 0x16
2779 NLE_OBJ_MISMATCH = 0x17
2780 NLE_NOCACHE = 0x18
2781 NLE_BUSY = 0x19
2782 NLE_PROTO_MISMATCH = 0x1A
2783 NLE_NOACCESS = 0x1B
2784 NLE_PERM = 0x1C
2785 NLE_PKTLOC_FILE = 0x1D
2786 NLE_PARSE_ERR = 0x1E
2787 NLE_NODEV = 0x1F
2788 NLE_IMMUTABLE = 0x20
2789 NLE_DUMP_INTR = 0x21
2790
2791 error_to_string = {
2792 NLE_SUCCESS : 'NLE_SUCCESS',
2793 NLE_FAILURE : 'NLE_FAILURE',
2794 NLE_INTR : 'NLE_INTR',
2795 NLE_BAD_SOCK : 'NLE_BAD_SOCK',
2796 NLE_AGAIN : 'NLE_AGAIN',
2797 NLE_NOMEM : 'NLE_NOMEM',
2798 NLE_EXIST : 'NLE_EXIST',
2799 NLE_INVAL : 'NLE_INVAL',
2800 NLE_RANGE : 'NLE_RANGE',
2801 NLE_MSGSIZE : 'NLE_MSGSIZE',
2802 NLE_OPNOTSUPP : 'NLE_OPNOTSUPP',
2803 NLE_AF_NOSUPPORT : 'NLE_AF_NOSUPPORT',
2804 NLE_OBJ_NOTFOUND : 'NLE_OBJ_NOTFOUND',
2805 NLE_NOATTR : 'NLE_NOATTR',
2806 NLE_MISSING_ATTR : 'NLE_MISSING_ATTR',
2807 NLE_AF_MISMATCH : 'NLE_AF_MISMATCH',
2808 NLE_SEQ_MISMATCH : 'NLE_SEQ_MISMATCH',
2809 NLE_MSG_OVERFLOW : 'NLE_MSG_OVERFLOW',
2810 NLE_MSG_TRUNC : 'NLE_MSG_TRUNC',
2811 NLE_NOADDR : 'NLE_NOADDR',
2812 NLE_SRCRT_NOSUPPORT : 'NLE_SRCRT_NOSUPPORT',
2813 NLE_MSG_TOOSHORT : 'NLE_MSG_TOOSHORT',
2814 NLE_MSGTYPE_NOSUPPORT : 'NLE_MSGTYPE_NOSUPPORT',
2815 NLE_OBJ_MISMATCH : 'NLE_OBJ_MISMATCH',
2816 NLE_NOCACHE : 'NLE_NOCACHE',
2817 NLE_BUSY : 'NLE_BUSY',
2818 NLE_PROTO_MISMATCH : 'NLE_PROTO_MISMATCH',
2819 NLE_NOACCESS : 'NLE_NOACCESS',
2820 NLE_PERM : 'NLE_PERM',
2821 NLE_PKTLOC_FILE : 'NLE_PKTLOC_FILE',
2822 NLE_PARSE_ERR : 'NLE_PARSE_ERR',
2823 NLE_NODEV : 'NLE_NODEV',
2824 NLE_IMMUTABLE : 'NLE_IMMUTABLE',
2825 NLE_DUMP_INTR : 'NLE_DUMP_INTR'
2826 }
2827
2828 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
2829 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
2830 self.PACK = '=iLHHLL'
2831 self.LEN = calcsize(self.PACK)
2832
2833 def decode_service_header(self):
2834
2835 # Nothing to do if the message did not contain a service header
2836 if self.length == self.header_LEN:
2837 return
2838
2839 (self.negative_errno, self.bad_msg_len, self.bad_msg_type,
2840 self.bad_msg_flag, self.bad_msg_seq, self.bad_msg_pid) =\
2841 unpack(self.PACK, self.msg_data[:self.LEN])
2842
2843 if self.debug:
2844 color = yellow if self.use_color else None
2845 color_start = "\033[%dm" % color if color else ""
2846 color_end = "\033[0m" if color else ""
2847 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
2848
2849 for x in range(0, self.LEN/4):
2850
2851 if self.line_number == 5:
2852 extra = "Error Number %s is %s" % (self.negative_errno, self.error_to_string.get(abs(self.negative_errno)))
2853 # zfilled_hex(self.negative_errno, 2)
2854
2855 elif self.line_number == 6:
2856 extra = "Length %s (%d)" % (zfilled_hex(self.bad_msg_len, 8), self.bad_msg_len)
2857
2858 elif self.line_number == 7:
2859 extra = "Type %s (%d - %s), Flags %s (%s)" % \
2860 (zfilled_hex(self.bad_msg_type, 4), self.bad_msg_type, self.get_type_string(self.bad_msg_type),
2861 zfilled_hex(self.bad_msg_flag, 4), self.get_netlink_header_flags_string(self.bad_msg_type, self.bad_msg_flag))
2862
2863 elif self.line_number == 8:
2864 extra = "Sequence Number %s (%d)" % (zfilled_hex(self.bad_msg_seq, 8), self.bad_msg_seq)
2865
2866 elif self.line_number == 9:
2867 extra = "Process ID %s (%d)" % (zfilled_hex(self.bad_msg_pid, 8), self.bad_msg_pid)
2868
2869 else:
2870 extra = "Unexpected line number %d" % self.line_number
2871
2872 start = x * 4
2873 end = start + 4
2874 self.dump_buffer.append(data_to_color_text(self.line_number, color, self.msg_data[start:end], extra))
2875 self.line_number += 1
2876
2877
2878 class Link(NetlinkPacket):
2879 """
2880 Service Header
2881
2882 0 1 2 3
2883 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2884 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2885 | Family | Reserved | Device Type |
2886 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2887 | Interface Index |
2888 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2889 | Device Flags |
2890 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2891 | Change Mask |
2892 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2893 """
2894
2895 # Link attributes
2896 # /usr/include/linux/if_link.h
2897 IFLA_UNSPEC = 0
2898 IFLA_ADDRESS = 1
2899 IFLA_BROADCAST = 2
2900 IFLA_IFNAME = 3
2901 IFLA_MTU = 4
2902 IFLA_LINK = 5
2903 IFLA_QDISC = 6
2904 IFLA_STATS = 7
2905 IFLA_COST = 8
2906 IFLA_PRIORITY = 9
2907 IFLA_MASTER = 10
2908 IFLA_WIRELESS = 11
2909 IFLA_PROTINFO = 12
2910 IFLA_TXQLEN = 13
2911 IFLA_MAP = 14
2912 IFLA_WEIGHT = 15
2913 IFLA_OPERSTATE = 16
2914 IFLA_LINKMODE = 17
2915 IFLA_LINKINFO = 18
2916 IFLA_NET_NS_PID = 19
2917 IFLA_IFALIAS = 20
2918 IFLA_NUM_VF = 21
2919 IFLA_VFINFO_LIST = 22
2920 IFLA_STATS64 = 23
2921 IFLA_VF_PORTS = 24
2922 IFLA_PORT_SELF = 25
2923 IFLA_AF_SPEC = 26
2924 IFLA_GROUP = 27
2925 IFLA_NET_NS_FD = 28
2926 IFLA_EXT_MASK = 29
2927 IFLA_PROMISCUITY = 30
2928 IFLA_NUM_TX_QUEUES = 31
2929 IFLA_NUM_RX_QUEUES = 32
2930 IFLA_CARRIER = 33
2931 IFLA_PHYS_PORT_ID = 34
2932 IFLA_CARRIER_CHANGES = 35
2933 IFLA_PHYS_SWITCH_ID = 36
2934 IFLA_LINK_NETNSID = 37
2935 IFLA_PHYS_PORT_NAME = 38
2936 IFLA_PROTO_DOWN = 39
2937 IFLA_GSO_MAX_SEGS = 40
2938 IFLA_GSO_MAX_SIZE = 41
2939
2940 attribute_to_class = {
2941 IFLA_UNSPEC : ('IFLA_UNSPEC', AttributeGeneric),
2942 IFLA_ADDRESS : ('IFLA_ADDRESS', AttributeMACAddress),
2943 IFLA_BROADCAST : ('IFLA_BROADCAST', AttributeMACAddress),
2944 IFLA_IFNAME : ('IFLA_IFNAME', AttributeStringInterfaceName),
2945 IFLA_MTU : ('IFLA_MTU', AttributeFourByteValue),
2946 IFLA_LINK : ('IFLA_LINK', AttributeFourByteValue),
2947 IFLA_QDISC : ('IFLA_QDISC', AttributeString),
2948 IFLA_STATS : ('IFLA_STATS', AttributeGeneric),
2949 IFLA_COST : ('IFLA_COST', AttributeGeneric),
2950 IFLA_PRIORITY : ('IFLA_PRIORITY', AttributeGeneric),
2951 IFLA_MASTER : ('IFLA_MASTER', AttributeFourByteValue),
2952 IFLA_WIRELESS : ('IFLA_WIRELESS', AttributeGeneric),
2953 IFLA_PROTINFO : ('IFLA_PROTINFO', AttributeIFLA_PROTINFO),
2954 IFLA_TXQLEN : ('IFLA_TXQLEN', AttributeFourByteValue),
2955 IFLA_MAP : ('IFLA_MAP', AttributeGeneric),
2956 IFLA_WEIGHT : ('IFLA_WEIGHT', AttributeGeneric),
2957 IFLA_OPERSTATE : ('IFLA_OPERSTATE', AttributeOneByteValue),
2958 IFLA_LINKMODE : ('IFLA_LINKMODE', AttributeOneByteValue),
2959 IFLA_LINKINFO : ('IFLA_LINKINFO', AttributeIFLA_LINKINFO),
2960 IFLA_NET_NS_PID : ('IFLA_NET_NS_PID', AttributeGeneric),
2961 IFLA_IFALIAS : ('IFLA_IFALIAS', AttributeGeneric),
2962 IFLA_NUM_VF : ('IFLA_NUM_VF', AttributeGeneric),
2963 IFLA_VFINFO_LIST : ('IFLA_VFINFO_LIST', AttributeGeneric),
2964 IFLA_STATS64 : ('IFLA_STATS64', AttributeGeneric),
2965 IFLA_VF_PORTS : ('IFLA_VF_PORTS', AttributeGeneric),
2966 IFLA_PORT_SELF : ('IFLA_PORT_SELF', AttributeGeneric),
2967 IFLA_AF_SPEC : ('IFLA_AF_SPEC', AttributeIFLA_AF_SPEC),
2968 IFLA_GROUP : ('IFLA_GROUP', AttributeFourByteValue),
2969 IFLA_NET_NS_FD : ('IFLA_NET_NS_FD', AttributeGeneric),
2970 IFLA_EXT_MASK : ('IFLA_EXT_MASK', AttributeFourByteValue),
2971 IFLA_PROMISCUITY : ('IFLA_PROMISCUITY', AttributeGeneric),
2972 IFLA_NUM_TX_QUEUES : ('IFLA_NUM_TX_QUEUES', AttributeGeneric),
2973 IFLA_NUM_RX_QUEUES : ('IFLA_NUM_RX_QUEUES', AttributeGeneric),
2974 IFLA_CARRIER : ('IFLA_CARRIER', AttributeGeneric),
2975 IFLA_PHYS_PORT_ID : ('IFLA_PHYS_PORT_ID', AttributeGeneric),
2976 IFLA_CARRIER_CHANGES : ('IFLA_CARRIER_CHANGES', AttributeGeneric),
2977 IFLA_PHYS_SWITCH_ID : ('IFLA_PHYS_SWITCH_ID', AttributeGeneric),
2978 IFLA_LINK_NETNSID : ('IFLA_LINK_NETNSID', AttributeGeneric),
2979 IFLA_PHYS_PORT_NAME : ('IFLA_PHYS_PORT_NAME', AttributeGeneric),
2980 IFLA_PROTO_DOWN : ('IFLA_PROTO_DOWN', AttributeOneByteValue),
2981 IFLA_GSO_MAX_SEGS : ('IFLA_GSO_MAX_SEGS', AttributeFourByteValue),
2982 IFLA_GSO_MAX_SIZE : ('IFLA_GSO_MAX_SIZE', AttributeFourByteValue)
2983 }
2984
2985 # Link flags
2986 # /usr/include/linux/if.h
2987 IFF_UP = 0x0001 # Interface is administratively up.
2988 IFF_BROADCAST = 0x0002 # Valid broadcast address set.
2989 IFF_DEBUG = 0x0004 # Internal debugging flag.
2990 IFF_LOOPBACK = 0x0008 # Interface is a loopback interface.
2991 IFF_POINTOPOINT = 0x0010 # Interface is a point-to-point link.
2992 IFF_NOTRAILERS = 0x0020 # Avoid use of trailers.
2993 IFF_RUNNING = 0x0040 # Interface is operationally up.
2994 IFF_NOARP = 0x0080 # No ARP protocol needed for this interface.
2995 IFF_PROMISC = 0x0100 # Interface is in promiscuous mode.
2996 IFF_ALLMULTI = 0x0200 # Receive all multicast packets.
2997 IFF_MASTER = 0x0400 # Master of a load balancing bundle.
2998 IFF_SLAVE = 0x0800 # Slave of a load balancing bundle.
2999 IFF_MULTICAST = 0x1000 # Supports multicast.
3000 IFF_PORTSEL = 0x2000 # Is able to select media type via ifmap.
3001 IFF_AUTOMEDIA = 0x4000 # Auto media selection active.
3002 IFF_DYNAMIC = 0x8000 # Interface was dynamically created.
3003 IFF_LOWER_UP = 0x10000 # driver signals L1 up
3004 IFF_DORMANT = 0x20000 # driver signals dormant
3005 IFF_ECHO = 0x40000 # echo sent packet
3006 IFF_PROTO_DOWN = 0x1000000 # protocol is down on the interface
3007
3008 flag_to_string = {
3009 IFF_UP : 'IFF_UP',
3010 IFF_BROADCAST : 'IFF_BROADCAST',
3011 IFF_DEBUG : 'IFF_DEBUG',
3012 IFF_LOOPBACK : 'IFF_LOOPBACK',
3013 IFF_POINTOPOINT : 'IFF_POINTOPOINT',
3014 IFF_NOTRAILERS : 'IFF_NOTRAILERS',
3015 IFF_RUNNING : 'IFF_RUNNING',
3016 IFF_NOARP : 'IFF_NOARP',
3017 IFF_PROMISC : 'IFF_PROMISC',
3018 IFF_ALLMULTI : 'IFF_ALLMULTI',
3019 IFF_MASTER : 'IFF_MASTER',
3020 IFF_SLAVE : 'IFF_SLAVE',
3021 IFF_MULTICAST : 'IFF_MULTICAST',
3022 IFF_PORTSEL : 'IFF_PORTSEL',
3023 IFF_AUTOMEDIA : 'IFF_AUTOMEDIA',
3024 IFF_DYNAMIC : 'IFF_DYNAMIC',
3025 IFF_LOWER_UP : 'IFF_LOWER_UP',
3026 IFF_DORMANT : 'IFF_DORMANT',
3027 IFF_ECHO : 'IFF_ECHO',
3028 IFF_PROTO_DOWN : 'IFF_PROTO_DOWN'
3029 }
3030
3031 # RFC 2863 operational status
3032 IF_OPER_UNKNOWN = 0
3033 IF_OPER_NOTPRESENT = 1
3034 IF_OPER_DOWN = 2
3035 IF_OPER_LOWERLAYERDOWN = 3
3036 IF_OPER_TESTING = 4
3037 IF_OPER_DORMANT = 5
3038 IF_OPER_UP = 6
3039
3040 oper_to_string = {
3041 IF_OPER_UNKNOWN : 'IF_OPER_UNKNOWN',
3042 IF_OPER_NOTPRESENT : 'IF_OPER_NOTPRESENT',
3043 IF_OPER_DOWN : 'IF_OPER_DOWN',
3044 IF_OPER_LOWERLAYERDOWN : 'IF_OPER_LOWERLAYERDOWN',
3045 IF_OPER_TESTING : 'IF_OPER_TESTING',
3046 IF_OPER_DORMANT : 'IF_OPER_DORMANT',
3047 IF_OPER_UP : 'IF_OPER_UP'
3048 }
3049
3050 # Link types
3051 # /usr/include/linux/if_arp.h
3052 # ARP protocol HARDWARE identifiers
3053 ARPHRD_NETROM = 0 # from KA9Q: NET/ROM pseudo
3054 ARPHRD_ETHER = 1 # Ethernet 10Mbps
3055 ARPHRD_EETHER = 2 # Experimental Ethernet
3056 ARPHRD_AX25 = 3 # AX.25 Level 2
3057 ARPHRD_PRONET = 4 # PROnet token ring
3058 ARPHRD_CHAOS = 5 # Chaosnet
3059 ARPHRD_IEEE802 = 6 # IEEE 802.2 Ethernet/TR/TB
3060 ARPHRD_ARCNET = 7 # ARCnet
3061 ARPHRD_APPLETLK = 8 # APPLEtalk
3062 ARPHRD_DLCI = 15 # Frame Relay DLCI
3063 ARPHRD_ATM = 19 # ATM
3064 ARPHRD_METRICOM = 23 # Metricom STRIP (new IANA id)
3065 ARPHRD_IEEE1394 = 24 # IEEE 1394 IPv4 - RFC 2734
3066 ARPHRD_EUI64 = 27 # EUI-64
3067 ARPHRD_INFINIBAND = 32 # InfiniBand
3068 # Dummy types for non ARP hardware
3069 ARPHRD_SLIP = 256
3070 ARPHRD_CSLIP = 257
3071 ARPHRD_SLIP6 = 258
3072 ARPHRD_CSLIP6 = 259
3073 ARPHRD_RSRVD = 260 # Notional KISS type
3074 ARPHRD_ADAPT = 264
3075 ARPHRD_ROSE = 270
3076 ARPHRD_X25 = 271 # CCITT X.25
3077 ARPHRD_HWX25 = 272 # Boards with X.25 in firmware
3078 ARPHRD_CAN = 280 # Controller Area Network
3079 ARPHRD_PPP = 512
3080 ARPHRD_CISCO = 513 # Cisco HDLC
3081 ARPHRD_HDLC = ARPHRD_CISCO
3082 ARPHRD_LAPB = 516 # LAPB
3083 ARPHRD_DDCMP = 517 # Digital's DDCMP protocol
3084 ARPHRD_RAWHDLC = 518 # Raw HDLC
3085 ARPHRD_TUNNEL = 768 # IPIP tunnel
3086 ARPHRD_TUNNEL6 = 769 # IP6IP6 tunnel
3087 ARPHRD_FRAD = 770 # Frame Relay Access Device
3088 ARPHRD_SKIP = 771 # SKIP vif
3089 ARPHRD_LOOPBACK = 772 # Loopback device
3090 ARPHRD_LOCALTLK = 773 # Localtalk device
3091 ARPHRD_FDDI = 774 # Fiber Distributed Data Interface
3092 ARPHRD_BIF = 775 # AP1000 BIF
3093 ARPHRD_SIT = 776 # sit0 device - IPv6-in-IPv4
3094 ARPHRD_IPDDP = 777 # IP over DDP tunneller
3095 ARPHRD_IPGRE = 778 # GRE over IP
3096 ARPHRD_PIMREG = 779 # PIMSM register interface
3097 ARPHRD_HIPPI = 780 # High Performance Parallel Interface
3098 ARPHRD_ASH = 781 # Nexus 64Mbps Ash
3099 ARPHRD_ECONET = 782 # Acorn Econet
3100 ARPHRD_IRDA = 783 # Linux-IrDA
3101 ARPHRD_FCPP = 784 # Point to point fibrechannel
3102 ARPHRD_FCAL = 785 # Fibrechannel arbitrated loop
3103 ARPHRD_FCPL = 786 # Fibrechannel public loop
3104 ARPHRD_FCFABRIC = 787 # Fibrechannel fabric
3105 # 787->799 reserved for fibrechannel media types
3106 ARPHRD_IEEE802_TR = 800 # Magic type ident for TR
3107 ARPHRD_IEEE80211 = 801 # IEEE 802.11
3108 ARPHRD_IEEE80211_PRISM = 802 # IEEE 802.11 + Prism2 header
3109 ARPHRD_IEEE80211_RADIOTAP = 803 # IEEE 802.11 + radiotap header
3110 ARPHRD_IEEE802154 = 804
3111 ARPHRD_PHONET = 820 # PhoNet media type
3112 ARPHRD_PHONET_PIPE = 821 # PhoNet pipe header
3113 ARPHRD_CAIF = 822 # CAIF media type
3114 ARPHRD_VOID = 0xFFFF # Void type, nothing is known
3115 ARPHRD_NONE = 0xFFFE # zero header length
3116
3117 link_type_to_string = {
3118 ARPHRD_NETROM : 'ARPHRD_NETROM',
3119 ARPHRD_ETHER : 'ARPHRD_ETHER',
3120 ARPHRD_EETHER : 'ARPHRD_EETHER',
3121 ARPHRD_AX25 : 'ARPHRD_AX25',
3122 ARPHRD_PRONET : 'ARPHRD_PRONET',
3123 ARPHRD_CHAOS : 'ARPHRD_CHAOS',
3124 ARPHRD_IEEE802 : 'ARPHRD_IEEE802',
3125 ARPHRD_ARCNET : 'ARPHRD_ARCNET',
3126 ARPHRD_APPLETLK : 'ARPHRD_APPLETLK',
3127 ARPHRD_DLCI : 'ARPHRD_DLCI',
3128 ARPHRD_ATM : 'ARPHRD_ATM',
3129 ARPHRD_METRICOM : 'ARPHRD_METRICOM',
3130 ARPHRD_IEEE1394 : 'ARPHRD_IEEE1394',
3131 ARPHRD_EUI64 : 'ARPHRD_EUI64',
3132 ARPHRD_INFINIBAND : 'ARPHRD_INFINIBAND',
3133 ARPHRD_SLIP : 'ARPHRD_SLIP',
3134 ARPHRD_CSLIP : 'ARPHRD_CSLIP',
3135 ARPHRD_SLIP6 : 'ARPHRD_SLIP6',
3136 ARPHRD_CSLIP6 : 'ARPHRD_CSLIP6',
3137 ARPHRD_RSRVD : 'ARPHRD_RSRVD',
3138 ARPHRD_ADAPT : 'ARPHRD_ADAPT',
3139 ARPHRD_ROSE : 'ARPHRD_ROSE',
3140 ARPHRD_X25 : 'ARPHRD_X25',
3141 ARPHRD_HWX25 : 'ARPHRD_HWX25',
3142 ARPHRD_CAN : 'ARPHRD_CAN',
3143 ARPHRD_PPP : 'ARPHRD_PPP',
3144 ARPHRD_CISCO : 'ARPHRD_CISCO',
3145 ARPHRD_HDLC : 'ARPHRD_HDLC',
3146 ARPHRD_LAPB : 'ARPHRD_LAPB',
3147 ARPHRD_DDCMP : 'ARPHRD_DDCMP',
3148 ARPHRD_RAWHDLC : 'ARPHRD_RAWHDLC',
3149 ARPHRD_TUNNEL : 'ARPHRD_TUNNEL',
3150 ARPHRD_TUNNEL6 : 'ARPHRD_TUNNEL6',
3151 ARPHRD_FRAD : 'ARPHRD_FRAD',
3152 ARPHRD_SKIP : 'ARPHRD_SKIP',
3153 ARPHRD_LOOPBACK : 'ARPHRD_LOOPBACK',
3154 ARPHRD_LOCALTLK : 'ARPHRD_LOCALTLK',
3155 ARPHRD_FDDI : 'ARPHRD_FDDI',
3156 ARPHRD_BIF : 'ARPHRD_BIF',
3157 ARPHRD_SIT : 'ARPHRD_SIT',
3158 ARPHRD_IPDDP : 'ARPHRD_IPDDP',
3159 ARPHRD_IPGRE : 'ARPHRD_IPGRE',
3160 ARPHRD_PIMREG : 'ARPHRD_PIMREG',
3161 ARPHRD_HIPPI : 'ARPHRD_HIPPI',
3162 ARPHRD_ASH : 'ARPHRD_ASH',
3163 ARPHRD_ECONET : 'ARPHRD_ECONET',
3164 ARPHRD_IRDA : 'ARPHRD_IRDA',
3165 ARPHRD_FCPP : 'ARPHRD_FCPP',
3166 ARPHRD_FCAL : 'ARPHRD_FCAL',
3167 ARPHRD_FCPL : 'ARPHRD_FCPL',
3168 ARPHRD_FCFABRIC : 'ARPHRD_FCFABRIC',
3169 ARPHRD_IEEE802_TR : 'ARPHRD_IEEE802_TR',
3170 ARPHRD_IEEE80211 : 'ARPHRD_IEEE80211',
3171 ARPHRD_IEEE80211_PRISM : 'ARPHRD_IEEE80211_PRISM',
3172 ARPHRD_IEEE80211_RADIOTAP : 'ARPHRD_IEEE80211_RADIOTAP',
3173 ARPHRD_IEEE802154 : 'ARPHRD_IEEE802154',
3174 ARPHRD_PHONET : 'ARPHRD_PHONET',
3175 ARPHRD_PHONET_PIPE : 'ARPHRD_PHONET_PIPE',
3176 ARPHRD_CAIF : 'ARPHRD_CAIF',
3177 ARPHRD_VOID : 'ARPHRD_VOID',
3178 ARPHRD_NONE : 'ARPHRD_NONE'
3179 }
3180
3181 # =========================================
3182 # IFLA_LINKINFO attributes
3183 # =========================================
3184 IFLA_INFO_UNSPEC = 0
3185 IFLA_INFO_KIND = 1
3186 IFLA_INFO_DATA = 2
3187 IFLA_INFO_XSTATS = 3
3188 IFLA_INFO_SLAVE_KIND = 4
3189 IFLA_INFO_SLAVE_DATA = 5
3190 IFLA_INFO_MAX = 6
3191
3192 ifla_info_to_string = {
3193 IFLA_INFO_UNSPEC : 'IFLA_INFO_UNSPEC',
3194 IFLA_INFO_KIND : 'IFLA_INFO_KIND',
3195 IFLA_INFO_DATA : 'IFLA_INFO_DATA',
3196 IFLA_INFO_XSTATS : 'IFLA_INFO_XSTATS',
3197 IFLA_INFO_SLAVE_KIND : 'IFLA_INFO_SLAVE_KIND',
3198 IFLA_INFO_SLAVE_DATA : 'IFLA_INFO_SLAVE_DATA',
3199 IFLA_INFO_MAX : 'IFLA_INFO_MAX'
3200 }
3201
3202 # =========================================
3203 # IFLA_INFO_DATA attributes for vlan
3204 # =========================================
3205 IFLA_VLAN_UNSPEC = 0
3206 IFLA_VLAN_ID = 1
3207 IFLA_VLAN_FLAGS = 2
3208 IFLA_VLAN_EGRESS_QOS = 3
3209 IFLA_VLAN_INGRESS_QOS = 4
3210 IFLA_VLAN_PROTOCOL = 5
3211
3212 ifla_vlan_to_string = {
3213 IFLA_VLAN_UNSPEC : 'IFLA_VLAN_UNSPEC',
3214 IFLA_VLAN_ID : 'IFLA_VLAN_ID',
3215 IFLA_VLAN_FLAGS : 'IFLA_VLAN_FLAGS',
3216 IFLA_VLAN_EGRESS_QOS : 'IFLA_VLAN_EGRESS_QOS',
3217 IFLA_VLAN_INGRESS_QOS : 'IFLA_VLAN_INGRESS_QOS',
3218 IFLA_VLAN_PROTOCOL : 'IFLA_VLAN_PROTOCOL'
3219 }
3220
3221 ifla_vlan_protocol_dict = {
3222 '802.1Q': 0x8100,
3223 '802.1q': 0x8100,
3224
3225 '802.1ad': 0x88A8,
3226 '802.1AD': 0x88A8,
3227 '802.1Ad': 0x88A8,
3228 '802.1aD': 0x88A8,
3229
3230 0x8100: '802.1Q',
3231 0x88A8: '802.1ad'
3232 }
3233
3234 # =========================================
3235 # IFLA_INFO_DATA attributes for macvlan
3236 # =========================================
3237 IFLA_MACVLAN_UNSPEC = 0
3238 IFLA_MACVLAN_MODE = 1
3239
3240 ifla_macvlan_to_string = {
3241 IFLA_MACVLAN_UNSPEC : 'IFLA_MACVLAN_UNSPEC',
3242 IFLA_MACVLAN_MODE : 'IFLA_MACVLAN_MODE'
3243 }
3244
3245 # macvlan modes
3246 MACVLAN_MODE_PRIVATE = 1
3247 MACVLAN_MODE_VEPA = 2
3248 MACVLAN_MODE_BRIDGE = 3
3249 MACVLAN_MODE_PASSTHRU = 4
3250
3251 macvlan_mode_to_string = {
3252 MACVLAN_MODE_PRIVATE : 'MACVLAN_MODE_PRIVATE',
3253 MACVLAN_MODE_VEPA : 'MACVLAN_MODE_VEPA',
3254 MACVLAN_MODE_BRIDGE : 'MACVLAN_MODE_BRIDGE',
3255 MACVLAN_MODE_PASSTHRU : 'MACVLAN_MODE_PASSTHRU'
3256 }
3257
3258 # =========================================
3259 # IFLA_INFO_DATA attributes for xfrm
3260 # =========================================
3261 IFLA_XFRM_UNSPEC = 0
3262 IFLA_XFRM_LINK = 1
3263 IFLA_XFRM_IF_ID = 2
3264
3265 ifla_xfrm_to_string = {
3266 IFLA_XFRM_UNSPEC : 'IFLA_XFRM_UNSPEC',
3267 IFLA_XFRM_LINK : 'IFLA_XFRM_LINK',
3268 IFLA_XFRM_IF_ID : 'IFLA_XFRM_IF_ID'
3269 }
3270
3271 # =========================================
3272 # IFLA_INFO_DATA attributes for vxlan
3273 # =========================================
3274 IFLA_VXLAN_UNSPEC = 0
3275 IFLA_VXLAN_ID = 1
3276 IFLA_VXLAN_GROUP = 2
3277 IFLA_VXLAN_LINK = 3
3278 IFLA_VXLAN_LOCAL = 4
3279 IFLA_VXLAN_TTL = 5
3280 IFLA_VXLAN_TOS = 6
3281 IFLA_VXLAN_LEARNING = 7
3282 IFLA_VXLAN_AGEING = 8
3283 IFLA_VXLAN_LIMIT = 9
3284 IFLA_VXLAN_PORT_RANGE = 10
3285 IFLA_VXLAN_PROXY = 11
3286 IFLA_VXLAN_RSC = 12
3287 IFLA_VXLAN_L2MISS = 13
3288 IFLA_VXLAN_L3MISS = 14
3289 IFLA_VXLAN_PORT = 15
3290 IFLA_VXLAN_GROUP6 = 16
3291 IFLA_VXLAN_LOCAL6 = 17
3292 IFLA_VXLAN_UDP_CSUM = 18
3293 IFLA_VXLAN_UDP_ZERO_CSUM6_TX = 19
3294 IFLA_VXLAN_UDP_ZERO_CSUM6_RX = 20
3295 IFLA_VXLAN_REMCSUM_TX = 21
3296 IFLA_VXLAN_REMCSUM_RX = 22
3297 IFLA_VXLAN_GBP = 23
3298 IFLA_VXLAN_REMCSUM_NOPARTIAL = 24
3299 IFLA_VXLAN_COLLECT_METADATA = 25
3300 IFLA_VXLAN_REPLICATION_NODE = 253
3301 IFLA_VXLAN_REPLICATION_TYPE = 254
3302
3303 ifla_vxlan_to_string = {
3304 IFLA_VXLAN_UNSPEC : 'IFLA_VXLAN_UNSPEC',
3305 IFLA_VXLAN_ID : 'IFLA_VXLAN_ID',
3306 IFLA_VXLAN_GROUP : 'IFLA_VXLAN_GROUP',
3307 IFLA_VXLAN_LINK : 'IFLA_VXLAN_LINK',
3308 IFLA_VXLAN_LOCAL : 'IFLA_VXLAN_LOCAL',
3309 IFLA_VXLAN_TTL : 'IFLA_VXLAN_TTL',
3310 IFLA_VXLAN_TOS : 'IFLA_VXLAN_TOS',
3311 IFLA_VXLAN_LEARNING : 'IFLA_VXLAN_LEARNING',
3312 IFLA_VXLAN_AGEING : 'IFLA_VXLAN_AGEING',
3313 IFLA_VXLAN_LIMIT : 'IFLA_VXLAN_LIMIT',
3314 IFLA_VXLAN_PORT_RANGE : 'IFLA_VXLAN_PORT_RANGE',
3315 IFLA_VXLAN_PROXY : 'IFLA_VXLAN_PROXY',
3316 IFLA_VXLAN_RSC : 'IFLA_VXLAN_RSC',
3317 IFLA_VXLAN_L2MISS : 'IFLA_VXLAN_L2MISS',
3318 IFLA_VXLAN_L3MISS : 'IFLA_VXLAN_L3MISS',
3319 IFLA_VXLAN_PORT : 'IFLA_VXLAN_PORT',
3320 IFLA_VXLAN_GROUP6 : 'IFLA_VXLAN_GROUP6',
3321 IFLA_VXLAN_LOCAL6 : 'IFLA_VXLAN_LOCAL6',
3322 IFLA_VXLAN_UDP_CSUM : 'IFLA_VXLAN_UDP_CSUM',
3323 IFLA_VXLAN_UDP_ZERO_CSUM6_TX : 'IFLA_VXLAN_UDP_ZERO_CSUM6_TX',
3324 IFLA_VXLAN_UDP_ZERO_CSUM6_RX : 'IFLA_VXLAN_UDP_ZERO_CSUM6_RX',
3325 IFLA_VXLAN_REMCSUM_TX : 'IFLA_VXLAN_REMCSUM_TX',
3326 IFLA_VXLAN_REMCSUM_RX : 'IFLA_VXLAN_REMCSUM_RX',
3327 IFLA_VXLAN_GBP : 'IFLA_VXLAN_GBP',
3328 IFLA_VXLAN_REMCSUM_NOPARTIAL : 'IFLA_VXLAN_REMCSUM_NOPARTIAL',
3329 IFLA_VXLAN_COLLECT_METADATA : 'IFLA_VXLAN_COLLECT_METADATA',
3330 IFLA_VXLAN_REPLICATION_NODE : 'IFLA_VXLAN_REPLICATION_NODE',
3331 IFLA_VXLAN_REPLICATION_TYPE : 'IFLA_VXLAN_REPLICATION_TYPE'
3332 }
3333
3334 # =========================================
3335 # IFLA_INFO_DATA attributes for bonds
3336 # =========================================
3337 IFLA_BOND_UNSPEC = 0
3338 IFLA_BOND_MODE = 1
3339 IFLA_BOND_ACTIVE_SLAVE = 2
3340 IFLA_BOND_MIIMON = 3
3341 IFLA_BOND_UPDELAY = 4
3342 IFLA_BOND_DOWNDELAY = 5
3343 IFLA_BOND_USE_CARRIER = 6
3344 IFLA_BOND_ARP_INTERVAL = 7
3345 IFLA_BOND_ARP_IP_TARGET = 8
3346 IFLA_BOND_ARP_VALIDATE = 9
3347 IFLA_BOND_ARP_ALL_TARGETS = 10
3348 IFLA_BOND_PRIMARY = 11
3349 IFLA_BOND_PRIMARY_RESELECT = 12
3350 IFLA_BOND_FAIL_OVER_MAC = 13
3351 IFLA_BOND_XMIT_HASH_POLICY = 14
3352 IFLA_BOND_RESEND_IGMP = 15
3353 IFLA_BOND_NUM_PEER_NOTIF = 16
3354 IFLA_BOND_ALL_SLAVES_ACTIVE = 17
3355 IFLA_BOND_MIN_LINKS = 18
3356 IFLA_BOND_LP_INTERVAL = 19
3357 IFLA_BOND_PACKETS_PER_SLAVE = 20
3358 IFLA_BOND_AD_LACP_RATE = 21
3359 IFLA_BOND_AD_SELECT = 22
3360 IFLA_BOND_AD_INFO = 23
3361 IFLA_BOND_AD_ACTOR_SYS_PRIO = 24
3362 IFLA_BOND_AD_USER_PORT_KEY = 25
3363 IFLA_BOND_AD_ACTOR_SYSTEM = 26
3364 IFLA_BOND_AD_LACP_BYPASS = 100
3365
3366 ifla_bond_to_string = {
3367 IFLA_BOND_UNSPEC : 'IFLA_BOND_UNSPEC',
3368 IFLA_BOND_MODE : 'IFLA_BOND_MODE',
3369 IFLA_BOND_ACTIVE_SLAVE : 'IFLA_BOND_ACTIVE_SLAVE',
3370 IFLA_BOND_MIIMON : 'IFLA_BOND_MIIMON',
3371 IFLA_BOND_UPDELAY : 'IFLA_BOND_UPDELAY',
3372 IFLA_BOND_DOWNDELAY : 'IFLA_BOND_DOWNDELAY',
3373 IFLA_BOND_USE_CARRIER : 'IFLA_BOND_USE_CARRIER',
3374 IFLA_BOND_ARP_INTERVAL : 'IFLA_BOND_ARP_INTERVAL',
3375 IFLA_BOND_ARP_IP_TARGET : 'IFLA_BOND_ARP_IP_TARGET',
3376 IFLA_BOND_ARP_VALIDATE : 'IFLA_BOND_ARP_VALIDATE',
3377 IFLA_BOND_ARP_ALL_TARGETS : 'IFLA_BOND_ARP_ALL_TARGETS',
3378 IFLA_BOND_PRIMARY : 'IFLA_BOND_PRIMARY',
3379 IFLA_BOND_PRIMARY_RESELECT : 'IFLA_BOND_PRIMARY_RESELECT',
3380 IFLA_BOND_FAIL_OVER_MAC : 'IFLA_BOND_FAIL_OVER_MAC',
3381 IFLA_BOND_XMIT_HASH_POLICY : 'IFLA_BOND_XMIT_HASH_POLICY',
3382 IFLA_BOND_RESEND_IGMP : 'IFLA_BOND_RESEND_IGMP',
3383 IFLA_BOND_NUM_PEER_NOTIF : 'IFLA_BOND_NUM_PEER_NOTIF',
3384 IFLA_BOND_ALL_SLAVES_ACTIVE : 'IFLA_BOND_ALL_SLAVES_ACTIVE',
3385 IFLA_BOND_MIN_LINKS : 'IFLA_BOND_MIN_LINKS',
3386 IFLA_BOND_LP_INTERVAL : 'IFLA_BOND_LP_INTERVAL',
3387 IFLA_BOND_PACKETS_PER_SLAVE : 'IFLA_BOND_PACKETS_PER_SLAVE',
3388 IFLA_BOND_AD_LACP_RATE : 'IFLA_BOND_AD_LACP_RATE',
3389 IFLA_BOND_AD_SELECT : 'IFLA_BOND_AD_SELECT',
3390 IFLA_BOND_AD_INFO : 'IFLA_BOND_AD_INFO',
3391 IFLA_BOND_AD_ACTOR_SYS_PRIO : 'IFLA_BOND_AD_ACTOR_SYS_PRIO',
3392 IFLA_BOND_AD_USER_PORT_KEY : 'IFLA_BOND_AD_USER_PORT_KEY',
3393 IFLA_BOND_AD_ACTOR_SYSTEM : 'IFLA_BOND_AD_ACTOR_SYSTEM',
3394 IFLA_BOND_AD_LACP_BYPASS : 'IFLA_BOND_AD_LACP_BYPASS'
3395 }
3396
3397 IFLA_BOND_AD_INFO_UNSPEC = 0
3398 IFLA_BOND_AD_INFO_AGGREGATOR = 1
3399 IFLA_BOND_AD_INFO_NUM_PORTS = 2
3400 IFLA_BOND_AD_INFO_ACTOR_KEY = 3
3401 IFLA_BOND_AD_INFO_PARTNER_KEY = 4
3402 IFLA_BOND_AD_INFO_PARTNER_MAC = 5
3403
3404 ifla_bond_ad_to_string = {
3405 IFLA_BOND_AD_INFO_UNSPEC : 'IFLA_BOND_AD_INFO_UNSPEC',
3406 IFLA_BOND_AD_INFO_AGGREGATOR : 'IFLA_BOND_AD_INFO_AGGREGATOR',
3407 IFLA_BOND_AD_INFO_NUM_PORTS : 'IFLA_BOND_AD_INFO_NUM_PORTS',
3408 IFLA_BOND_AD_INFO_ACTOR_KEY : 'IFLA_BOND_AD_INFO_ACTOR_KEY',
3409 IFLA_BOND_AD_INFO_PARTNER_KEY : 'IFLA_BOND_AD_INFO_PARTNER_KEY',
3410 IFLA_BOND_AD_INFO_PARTNER_MAC : 'IFLA_BOND_AD_INFO_PARTNER_MAC'
3411 }
3412
3413 ifla_bond_mode_tbl = {
3414 'balance-rr': 0,
3415 'active-backup': 1,
3416 'balance-xor': 2,
3417 'broadcast': 3,
3418 '802.3ad': 4,
3419 'balance-tlb': 5,
3420 'balance-alb': 6,
3421 '0': 0,
3422 '1': 1,
3423 '2': 2,
3424 '3': 3,
3425 '4': 4,
3426 '5': 5,
3427 '6': 6,
3428 0: 0,
3429 1: 1,
3430 2: 2,
3431 3: 3,
3432 4: 4,
3433 5: 5,
3434 6: 6
3435 }
3436
3437 ifla_bond_mode_pretty_tbl = {
3438 0: 'balance-rr',
3439 1: 'active-backup',
3440 2: 'balance-xor',
3441 3: 'broadcast',
3442 4: '802.3ad',
3443 5: 'balance-tlb',
3444 6: 'balance-alb'
3445 }
3446
3447 ifla_bond_xmit_hash_policy_tbl = {
3448 'layer2': 0,
3449 'layer3+4': 1,
3450 'layer2+3': 2,
3451 'encap2+3': 3,
3452 'encap3+4': 4,
3453 '0': 0,
3454 '1': 1,
3455 '2': 2,
3456 '3': 3,
3457 '4': 4,
3458 0: 0,
3459 1: 1,
3460 2: 2,
3461 3: 3,
3462 4: 4
3463 }
3464
3465 ifla_bond_xmit_hash_policy_pretty_tbl = {
3466 0: 'layer2',
3467 1: 'layer3+4',
3468 2: 'layer2+3',
3469 3: 'encap2+3',
3470 4: 'encap3+4',
3471 }
3472
3473 # =========================================
3474 # IFLA_INFO_SLAVE_DATA attributes for bonds
3475 # =========================================
3476 IFLA_BOND_SLAVE_UNSPEC = 0
3477 IFLA_BOND_SLAVE_STATE = 1
3478 IFLA_BOND_SLAVE_MII_STATUS = 2
3479 IFLA_BOND_SLAVE_LINK_FAILURE_COUNT = 3
3480 IFLA_BOND_SLAVE_PERM_HWADDR = 4
3481 IFLA_BOND_SLAVE_QUEUE_ID = 5
3482 IFLA_BOND_SLAVE_AD_AGGREGATOR_ID = 6
3483 IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE = 7
3484 IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE = 8
3485 IFLA_BOND_SLAVE_CL_START = 50
3486 IFLA_BOND_SLAVE_AD_RX_BYPASS = IFLA_BOND_SLAVE_CL_START
3487
3488 ifla_bond_slave_to_string = {
3489 IFLA_BOND_SLAVE_UNSPEC : 'IFLA_BOND_SLAVE_UNSPEC',
3490 IFLA_BOND_SLAVE_STATE : 'IFLA_BOND_SLAVE_STATE',
3491 IFLA_BOND_SLAVE_MII_STATUS : 'IFLA_BOND_SLAVE_MII_STATUS',
3492 IFLA_BOND_SLAVE_LINK_FAILURE_COUNT : 'IFLA_BOND_SLAVE_LINK_FAILURE_COUNT',
3493 IFLA_BOND_SLAVE_PERM_HWADDR : 'IFLA_BOND_SLAVE_PERM_HWADDR',
3494 IFLA_BOND_SLAVE_QUEUE_ID : 'IFLA_BOND_SLAVE_QUEUE_ID',
3495 IFLA_BOND_SLAVE_AD_AGGREGATOR_ID : 'IFLA_BOND_SLAVE_AD_AGGREGATOR_ID',
3496 IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE : 'IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE',
3497 IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE : 'IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE',
3498 IFLA_BOND_SLAVE_CL_START : 'IFLA_BOND_SLAVE_CL_START',
3499 IFLA_BOND_SLAVE_AD_RX_BYPASS : 'IFLA_BOND_SLAVE_AD_RX_BYPASS'
3500 }
3501
3502 # =========================================
3503 # IFLA_PROTINFO attributes for bridge ports
3504 # =========================================
3505 IFLA_BRPORT_UNSPEC = 0
3506 IFLA_BRPORT_STATE = 1
3507 IFLA_BRPORT_PRIORITY = 2
3508 IFLA_BRPORT_COST = 3
3509 IFLA_BRPORT_MODE = 4
3510 IFLA_BRPORT_GUARD = 5
3511 IFLA_BRPORT_PROTECT = 6
3512 IFLA_BRPORT_FAST_LEAVE = 7
3513 IFLA_BRPORT_LEARNING = 8
3514 IFLA_BRPORT_UNICAST_FLOOD = 9
3515 IFLA_BRPORT_PROXYARP = 10
3516 IFLA_BRPORT_LEARNING_SYNC = 11
3517 IFLA_BRPORT_PROXYARP_WIFI = 12
3518 IFLA_BRPORT_ROOT_ID = 13
3519 IFLA_BRPORT_BRIDGE_ID = 14
3520 IFLA_BRPORT_DESIGNATED_PORT = 15
3521 IFLA_BRPORT_DESIGNATED_COST = 16
3522 IFLA_BRPORT_ID = 17
3523 IFLA_BRPORT_NO = 18
3524 IFLA_BRPORT_TOPOLOGY_CHANGE_ACK = 19
3525 IFLA_BRPORT_CONFIG_PENDING = 20
3526 IFLA_BRPORT_MESSAGE_AGE_TIMER = 21
3527 IFLA_BRPORT_FORWARD_DELAY_TIMER = 22
3528 IFLA_BRPORT_HOLD_TIMER = 23
3529 IFLA_BRPORT_FLUSH = 24
3530 IFLA_BRPORT_MULTICAST_ROUTER = 25
3531 IFLA_BRPORT_PAD = 26
3532 IFLA_BRPORT_MCAST_FLOOD = 27
3533 IFLA_BRPORT_MCAST_TO_UCAST = 28
3534 IFLA_BRPORT_VLAN_TUNNEL = 29
3535 IFLA_BRPORT_BCAST_FLOOD = 30
3536 IFLA_BRPORT_GROUP_FWD_MASK = 31
3537 IFLA_BRPORT_ARP_SUPPRESS = 32
3538 IFLA_BRPORT_PEER_LINK = 150
3539 IFLA_BRPORT_DUAL_LINK = 151
3540 IFLA_BRPORT_GROUP_FWD_MASKHI = 153
3541 IFLA_BRPORT_DOWN_PEERLINK_REDIRECT = 154
3542
3543 ifla_brport_to_string = {
3544 IFLA_BRPORT_UNSPEC : 'IFLA_BRPORT_UNSPEC',
3545 IFLA_BRPORT_STATE : 'IFLA_BRPORT_STATE',
3546 IFLA_BRPORT_PRIORITY : 'IFLA_BRPORT_PRIORITY',
3547 IFLA_BRPORT_COST : 'IFLA_BRPORT_COST',
3548 IFLA_BRPORT_MODE : 'IFLA_BRPORT_MODE',
3549 IFLA_BRPORT_GUARD : 'IFLA_BRPORT_GUARD',
3550 IFLA_BRPORT_PROTECT : 'IFLA_BRPORT_PROTECT',
3551 IFLA_BRPORT_FAST_LEAVE : 'IFLA_BRPORT_FAST_LEAVE',
3552 IFLA_BRPORT_LEARNING : 'IFLA_BRPORT_LEARNING',
3553 IFLA_BRPORT_UNICAST_FLOOD : 'IFLA_BRPORT_UNICAST_FLOOD',
3554 IFLA_BRPORT_PROXYARP : 'IFLA_BRPORT_PROXYARP',
3555 IFLA_BRPORT_LEARNING_SYNC : 'IFLA_BRPORT_LEARNING_SYNC',
3556 IFLA_BRPORT_PROXYARP_WIFI : 'IFLA_BRPORT_PROXYARP_WIFI',
3557 IFLA_BRPORT_ROOT_ID : 'IFLA_BRPORT_ROOT_ID',
3558 IFLA_BRPORT_BRIDGE_ID : 'IFLA_BRPORT_BRIDGE_ID',
3559 IFLA_BRPORT_DESIGNATED_PORT : 'IFLA_BRPORT_DESIGNATED_PORT',
3560 IFLA_BRPORT_DESIGNATED_COST : 'IFLA_BRPORT_DESIGNATED_COST',
3561 IFLA_BRPORT_ID : 'IFLA_BRPORT_ID',
3562 IFLA_BRPORT_NO : 'IFLA_BRPORT_NO',
3563 IFLA_BRPORT_TOPOLOGY_CHANGE_ACK : 'IFLA_BRPORT_TOPOLOGY_CHANGE_ACK',
3564 IFLA_BRPORT_CONFIG_PENDING : 'IFLA_BRPORT_CONFIG_PENDING',
3565 IFLA_BRPORT_MESSAGE_AGE_TIMER : 'IFLA_BRPORT_MESSAGE_AGE_TIMER',
3566 IFLA_BRPORT_FORWARD_DELAY_TIMER : 'IFLA_BRPORT_FORWARD_DELAY_TIMER',
3567 IFLA_BRPORT_HOLD_TIMER : 'IFLA_BRPORT_HOLD_TIMER',
3568 IFLA_BRPORT_FLUSH : 'IFLA_BRPORT_FLUSH',
3569 IFLA_BRPORT_MULTICAST_ROUTER : 'IFLA_BRPORT_MULTICAST_ROUTER',
3570 IFLA_BRPORT_PAD : 'IFLA_BRPORT_PAD',
3571 IFLA_BRPORT_MCAST_FLOOD : 'IFLA_BRPORT_MCAST_FLOOD',
3572 IFLA_BRPORT_MCAST_TO_UCAST : 'IFLA_BRPORT_MCAST_TO_UCAST',
3573 IFLA_BRPORT_VLAN_TUNNEL : 'IFLA_BRPORT_VLAN_TUNNEL',
3574 IFLA_BRPORT_BCAST_FLOOD : 'IFLA_BRPORT_BCAST_FLOOD',
3575 IFLA_BRPORT_GROUP_FWD_MASK : 'IFLA_BRPORT_GROUP_FWD_MASK',
3576 IFLA_BRPORT_PEER_LINK : 'IFLA_BRPORT_PEER_LINK',
3577 IFLA_BRPORT_DUAL_LINK : 'IFLA_BRPORT_DUAL_LINK',
3578 IFLA_BRPORT_ARP_SUPPRESS : 'IFLA_BRPORT_ARP_SUPPRESS',
3579 IFLA_BRPORT_GROUP_FWD_MASKHI : 'IFLA_BRPORT_GROUP_FWD_MASKHI',
3580 IFLA_BRPORT_DOWN_PEERLINK_REDIRECT : 'IFLA_BRPORT_DOWN_PEERLINK_REDIRECT'
3581 }
3582
3583 # Subtype attributes for IFLA_AF_SPEC
3584 IFLA_INET6_UNSPEC = 0
3585 IFLA_INET6_FLAGS = 1 # link flags
3586 IFLA_INET6_CONF = 2 # sysctl parameters
3587 IFLA_INET6_STATS = 3 # statistics
3588 IFLA_INET6_MCAST = 4 # MC things. What of them?
3589 IFLA_INET6_CACHEINFO = 5 # time values and max reasm size
3590 IFLA_INET6_ICMP6STATS = 6 # statistics (icmpv6)
3591 IFLA_INET6_TOKEN = 7 # device token
3592 IFLA_INET6_ADDR_GEN_MODE = 8 # implicit address generator mode
3593 __IFLA_INET6_MAX = 9
3594
3595 ifla_inet6_af_spec_to_string = {
3596 IFLA_INET6_UNSPEC : 'IFLA_INET6_UNSPEC',
3597 IFLA_INET6_FLAGS : 'IFLA_INET6_FLAGS',
3598 IFLA_INET6_CONF : 'IFLA_INET6_CONF',
3599 IFLA_INET6_STATS : 'IFLA_INET6_STATS',
3600 IFLA_INET6_MCAST : 'IFLA_INET6_MCAST',
3601 IFLA_INET6_CACHEINFO : 'IFLA_INET6_CACHEINFO',
3602 IFLA_INET6_ICMP6STATS : 'IFLA_INET6_ICMP6STATS',
3603 IFLA_INET6_TOKEN : 'IFLA_INET6_TOKEN',
3604 IFLA_INET6_ADDR_GEN_MODE : 'IFLA_INET6_ADDR_GEN_MODE',
3605 }
3606
3607 # IFLA_INET6_ADDR_GEN_MODE values
3608 IN6_ADDR_GEN_MODE_EUI64 = 0
3609 IN6_ADDR_GEN_MODE_NONE = 1
3610 IN6_ADDR_GEN_MODE_STABLE_PRIVACY = 2
3611 IN6_ADDR_GEN_MODE_RANDOM = 3
3612
3613 ifla_inet6_addr_gen_mode_dict = {
3614 IN6_ADDR_GEN_MODE_EUI64: "eui64",
3615 IN6_ADDR_GEN_MODE_NONE: "none",
3616 IN6_ADDR_GEN_MODE_STABLE_PRIVACY: "stable_secret",
3617 IN6_ADDR_GEN_MODE_RANDOM: "random"
3618 }
3619
3620 # Subtype attrbutes AF_INET
3621 IFLA_INET_UNSPEC = 0
3622 IFLA_INET_CONF = 1
3623 __IFLA_INET_MAX = 2
3624
3625 ifla_inet_af_spec_to_string = {
3626 IFLA_INET_UNSPEC : 'IFLA_INET_UNSPEC',
3627 IFLA_INET_CONF : 'IFLA_INET_CONF',
3628 }
3629
3630 # BRIDGE IFLA_AF_SPEC attributes
3631 IFLA_BRIDGE_FLAGS = 0
3632 IFLA_BRIDGE_MODE = 1
3633 IFLA_BRIDGE_VLAN_INFO = 2
3634
3635 ifla_bridge_af_spec_to_string = {
3636 IFLA_BRIDGE_FLAGS : 'IFLA_BRIDGE_FLAGS',
3637 IFLA_BRIDGE_MODE : 'IFLA_BRIDGE_MODE',
3638 IFLA_BRIDGE_VLAN_INFO : 'IFLA_BRIDGE_VLAN_INFO'
3639 }
3640
3641 # BRIDGE_VLAN_INFO flags
3642 BRIDGE_VLAN_INFO_MASTER = 1 << 0 # Operate on Bridge device as well
3643 BRIDGE_VLAN_INFO_PVID = 1 << 1 # VLAN is PVID, ingress untagged
3644 BRIDGE_VLAN_INFO_UNTAGGED = 1 << 2 # VLAN egresses untagged
3645 BRIDGE_VLAN_INFO_RANGE_BEGIN = 1 << 3 # VLAN is start of vlan range
3646 BRIDGE_VLAN_INFO_RANGE_END = 1 << 4 # VLAN is end of vlan range
3647 BRIDGE_VLAN_INFO_BRENTRY = 1 << 5 # Global bridge VLAN entry
3648
3649 bridge_vlan_to_string = {
3650 BRIDGE_VLAN_INFO_MASTER : 'BRIDGE_VLAN_INFO_MASTER',
3651 BRIDGE_VLAN_INFO_PVID : 'BRIDGE_VLAN_INFO_PVID',
3652 BRIDGE_VLAN_INFO_UNTAGGED : 'BRIDGE_VLAN_INFO_UNTAGGED',
3653 BRIDGE_VLAN_INFO_RANGE_BEGIN : 'BRIDGE_VLAN_INFO_RANGE_BEGIN',
3654 BRIDGE_VLAN_INFO_RANGE_END : 'BRIDGE_VLAN_INFO_RANGE_END',
3655 BRIDGE_VLAN_INFO_BRENTRY : 'BRIDGE_VLAN_INFO_BRENTRY'
3656 }
3657
3658 # Bridge flags
3659 BRIDGE_FLAGS_MASTER = 1
3660 BRIDGE_FLAGS_SELF = 2
3661
3662 bridge_flags_to_string = {
3663 BRIDGE_FLAGS_MASTER : 'BRIDGE_FLAGS_MASTER',
3664 BRIDGE_FLAGS_SELF : 'BRIDGE_FLAGS_SELF'
3665 }
3666
3667 # filters for IFLA_EXT_MASK
3668 RTEXT_FILTER_VF = 1 << 0
3669 RTEXT_FILTER_BRVLAN = 1 << 1
3670 RTEXT_FILTER_BRVLAN_COMPRESSED = 1 << 2
3671 RTEXT_FILTER_SKIP_STATS = 1 << 3
3672
3673 rtext_to_string = {
3674 RTEXT_FILTER_VF : 'RTEXT_FILTER_VF',
3675 RTEXT_FILTER_BRVLAN : 'RTEXT_FILTER_BRVLAN',
3676 RTEXT_FILTER_BRVLAN_COMPRESSED : 'RTEXT_FILTER_BRVLAN_COMPRESSED',
3677 RTEXT_FILTER_SKIP_STATS : 'RTEXT_FILTER_SKIP_STATS'
3678 }
3679
3680 IFLA_BR_UNSPEC = 0
3681 IFLA_BR_FORWARD_DELAY = 1
3682 IFLA_BR_HELLO_TIME = 2
3683 IFLA_BR_MAX_AGE = 3
3684 IFLA_BR_AGEING_TIME = 4
3685 IFLA_BR_STP_STATE = 5
3686 IFLA_BR_PRIORITY = 6
3687 IFLA_BR_VLAN_FILTERING = 7
3688 IFLA_BR_VLAN_PROTOCOL = 8
3689 IFLA_BR_GROUP_FWD_MASK = 9
3690 IFLA_BR_ROOT_ID = 10
3691 IFLA_BR_BRIDGE_ID = 11
3692 IFLA_BR_ROOT_PORT = 12
3693 IFLA_BR_ROOT_PATH_COST = 13
3694 IFLA_BR_TOPOLOGY_CHANGE = 14
3695 IFLA_BR_TOPOLOGY_CHANGE_DETECTED = 15
3696 IFLA_BR_HELLO_TIMER = 16
3697 IFLA_BR_TCN_TIMER = 17
3698 IFLA_BR_TOPOLOGY_CHANGE_TIMER = 18
3699 IFLA_BR_GC_TIMER = 19
3700 IFLA_BR_GROUP_ADDR = 20
3701 IFLA_BR_FDB_FLUSH = 21
3702 IFLA_BR_MCAST_ROUTER = 22
3703 IFLA_BR_MCAST_SNOOPING = 23
3704 IFLA_BR_MCAST_QUERY_USE_IFADDR = 24
3705 IFLA_BR_MCAST_QUERIER = 25
3706 IFLA_BR_MCAST_HASH_ELASTICITY = 26
3707 IFLA_BR_MCAST_HASH_MAX = 27
3708 IFLA_BR_MCAST_LAST_MEMBER_CNT = 28
3709 IFLA_BR_MCAST_STARTUP_QUERY_CNT = 29
3710 IFLA_BR_MCAST_LAST_MEMBER_INTVL = 30
3711 IFLA_BR_MCAST_MEMBERSHIP_INTVL = 31
3712 IFLA_BR_MCAST_QUERIER_INTVL = 32
3713 IFLA_BR_MCAST_QUERY_INTVL = 33
3714 IFLA_BR_MCAST_QUERY_RESPONSE_INTVL = 34
3715 IFLA_BR_MCAST_STARTUP_QUERY_INTVL = 35
3716 IFLA_BR_NF_CALL_IPTABLES = 36
3717 IFLA_BR_NF_CALL_IP6TABLES = 37
3718 IFLA_BR_NF_CALL_ARPTABLES = 38
3719 IFLA_BR_VLAN_DEFAULT_PVID = 39
3720 IFLA_BR_PAD = 40
3721 IFLA_BR_VLAN_STATS_ENABLED = 41
3722 IFLA_BR_MCAST_STATS_ENABLED = 42
3723 IFLA_BR_MCAST_IGMP_VERSION = 43
3724 IFLA_BR_MCAST_MLD_VERSION = 44
3725
3726 ifla_br_to_string = {
3727 IFLA_BR_UNSPEC : 'IFLA_BR_UNSPEC',
3728 IFLA_BR_FORWARD_DELAY : 'IFLA_BR_FORWARD_DELAY',
3729 IFLA_BR_HELLO_TIME : 'IFLA_BR_HELLO_TIME',
3730 IFLA_BR_MAX_AGE : 'IFLA_BR_MAX_AGE',
3731 IFLA_BR_AGEING_TIME : 'IFLA_BR_AGEING_TIME',
3732 IFLA_BR_STP_STATE : 'IFLA_BR_STP_STATE',
3733 IFLA_BR_PRIORITY : 'IFLA_BR_PRIORITY',
3734 IFLA_BR_VLAN_FILTERING : 'IFLA_BR_VLAN_FILTERING',
3735 IFLA_BR_VLAN_PROTOCOL : 'IFLA_BR_VLAN_PROTOCOL',
3736 IFLA_BR_GROUP_FWD_MASK : 'IFLA_BR_GROUP_FWD_MASK',
3737 IFLA_BR_ROOT_ID : 'IFLA_BR_ROOT_ID',
3738 IFLA_BR_BRIDGE_ID : 'IFLA_BR_BRIDGE_ID',
3739 IFLA_BR_ROOT_PORT : 'IFLA_BR_ROOT_PORT',
3740 IFLA_BR_ROOT_PATH_COST : 'IFLA_BR_ROOT_PATH_COST',
3741 IFLA_BR_TOPOLOGY_CHANGE : 'IFLA_BR_TOPOLOGY_CHANGE',
3742 IFLA_BR_TOPOLOGY_CHANGE_DETECTED : 'IFLA_BR_TOPOLOGY_CHANGE_DETECTED',
3743 IFLA_BR_HELLO_TIMER : 'IFLA_BR_HELLO_TIMER',
3744 IFLA_BR_TCN_TIMER : 'IFLA_BR_TCN_TIMER',
3745 IFLA_BR_TOPOLOGY_CHANGE_TIMER : 'IFLA_BR_TOPOLOGY_CHANGE_TIMER',
3746 IFLA_BR_GC_TIMER : 'IFLA_BR_GC_TIMER',
3747 IFLA_BR_GROUP_ADDR : 'IFLA_BR_GROUP_ADDR',
3748 IFLA_BR_FDB_FLUSH : 'IFLA_BR_FDB_FLUSH',
3749 IFLA_BR_MCAST_ROUTER : 'IFLA_BR_MCAST_ROUTER',
3750 IFLA_BR_MCAST_SNOOPING : 'IFLA_BR_MCAST_SNOOPING',
3751 IFLA_BR_MCAST_QUERY_USE_IFADDR : 'IFLA_BR_MCAST_QUERY_USE_IFADDR',
3752 IFLA_BR_MCAST_QUERIER : 'IFLA_BR_MCAST_QUERIER',
3753 IFLA_BR_MCAST_HASH_ELASTICITY : 'IFLA_BR_MCAST_HASH_ELASTICITY',
3754 IFLA_BR_MCAST_HASH_MAX : 'IFLA_BR_MCAST_HASH_MAX',
3755 IFLA_BR_MCAST_LAST_MEMBER_CNT : 'IFLA_BR_MCAST_LAST_MEMBER_CNT',
3756 IFLA_BR_MCAST_STARTUP_QUERY_CNT : 'IFLA_BR_MCAST_STARTUP_QUERY_CNT',
3757 IFLA_BR_MCAST_LAST_MEMBER_INTVL : 'IFLA_BR_MCAST_LAST_MEMBER_INTVL',
3758 IFLA_BR_MCAST_MEMBERSHIP_INTVL : 'IFLA_BR_MCAST_MEMBERSHIP_INTVL',
3759 IFLA_BR_MCAST_QUERIER_INTVL : 'IFLA_BR_MCAST_QUERIER_INTVL',
3760 IFLA_BR_MCAST_QUERY_INTVL : 'IFLA_BR_MCAST_QUERY_INTVL',
3761 IFLA_BR_MCAST_QUERY_RESPONSE_INTVL : 'IFLA_BR_MCAST_QUERY_RESPONSE_INTVL',
3762 IFLA_BR_MCAST_STARTUP_QUERY_INTVL : 'IFLA_BR_MCAST_STARTUP_QUERY_INTVL',
3763 IFLA_BR_NF_CALL_IPTABLES : 'IFLA_BR_NF_CALL_IPTABLES',
3764 IFLA_BR_NF_CALL_IP6TABLES : 'IFLA_BR_NF_CALL_IP6TABLES',
3765 IFLA_BR_NF_CALL_ARPTABLES : 'IFLA_BR_NF_CALL_ARPTABLES',
3766 IFLA_BR_VLAN_DEFAULT_PVID : 'IFLA_BR_VLAN_DEFAULT_PVID',
3767 IFLA_BR_PAD : 'IFLA_BR_PAD',
3768 IFLA_BR_VLAN_STATS_ENABLED : 'IFLA_BR_VLAN_STATS_ENABLED',
3769 IFLA_BR_MCAST_STATS_ENABLED : 'IFLA_BR_MCAST_STATS_ENABLED',
3770 IFLA_BR_MCAST_IGMP_VERSION : 'IFLA_BR_MCAST_IGMP_VERSION',
3771 IFLA_BR_MCAST_MLD_VERSION : 'IFLA_BR_MCAST_MLD_VERSION'
3772 }
3773
3774 # =========================================
3775 # IFLA_INFO_DATA attributes for vrfs
3776 # =========================================
3777 IFLA_VRF_UNSPEC = 0
3778 IFLA_VRF_TABLE = 1
3779
3780 ifla_vrf_to_string = {
3781 IFLA_VRF_UNSPEC : 'IFLA_VRF_UNSPEC',
3782 IFLA_VRF_TABLE : 'IFLA_VRF_TABLE'
3783 }
3784
3785 # ================================================================
3786 # IFLA_INFO_DATA attributes for (ip6)gre, (ip6)gretap, (ip6)erspan
3787 # ================================================================
3788 IFLA_GRE_UNSPEC = 0
3789 IFLA_GRE_LINK = 1
3790 IFLA_GRE_IFLAGS = 2
3791 IFLA_GRE_OFLAGS = 3
3792 IFLA_GRE_IKEY = 4
3793 IFLA_GRE_OKEY = 5
3794 IFLA_GRE_LOCAL = 6
3795 IFLA_GRE_REMOTE = 7
3796 IFLA_GRE_TTL = 8
3797 IFLA_GRE_TOS = 9
3798 IFLA_GRE_PMTUDISC = 10
3799 IFLA_GRE_ENCAP_LIMIT = 11
3800 IFLA_GRE_FLOWINFO = 12
3801 IFLA_GRE_FLAGS = 13
3802 IFLA_GRE_ENCAP_TYPE = 14
3803 IFLA_GRE_ENCAP_FLAGS = 15
3804 IFLA_GRE_ENCAP_SPORT = 16
3805 IFLA_GRE_ENCAP_DPORT = 17
3806 IFLA_GRE_COLLECT_METADATA = 18
3807 IFLA_GRE_IGNORE_DF = 19
3808 IFLA_GRE_FWMARK = 20
3809 IFLA_GRE_ERSPAN_INDEX = 21
3810 IFLA_GRE_ERSPAN_VER = 22
3811 IFLA_GRE_ERSPAN_DIR = 23
3812 IFLA_GRE_ERSPAN_HWID = 24
3813
3814 ifla_gre_to_string = {
3815 IFLA_GRE_UNSPEC : "IFLA_GRE_UNSPEC",
3816 IFLA_GRE_LINK : "IFLA_GRE_LINK",
3817 IFLA_GRE_IFLAGS : "IFLA_GRE_IFLAGS",
3818 IFLA_GRE_OFLAGS : "IFLA_GRE_OFLAGS",
3819 IFLA_GRE_IKEY : "IFLA_GRE_IKEY",
3820 IFLA_GRE_OKEY : "IFLA_GRE_OKEY",
3821 IFLA_GRE_LOCAL : "IFLA_GRE_LOCAL",
3822 IFLA_GRE_REMOTE : "IFLA_GRE_REMOTE",
3823 IFLA_GRE_TTL : "IFLA_GRE_TTL",
3824 IFLA_GRE_TOS : "IFLA_GRE_TOS",
3825 IFLA_GRE_PMTUDISC : "IFLA_GRE_PMTUDISC",
3826 IFLA_GRE_ENCAP_LIMIT : "IFLA_GRE_ENCAP_LIMIT",
3827 IFLA_GRE_FLOWINFO : "IFLA_GRE_FLOWINFO",
3828 IFLA_GRE_FLAGS : "IFLA_GRE_FLAGS",
3829 IFLA_GRE_ENCAP_TYPE : "IFLA_GRE_ENCAP_TYPE",
3830 IFLA_GRE_ENCAP_FLAGS : "IFLA_GRE_ENCAP_FLAGS",
3831 IFLA_GRE_ENCAP_SPORT : "IFLA_GRE_ENCAP_SPORT",
3832 IFLA_GRE_ENCAP_DPORT : "IFLA_GRE_ENCAP_DPORT",
3833 IFLA_GRE_COLLECT_METADATA : "IFLA_GRE_COLLECT_METADATA",
3834 IFLA_GRE_IGNORE_DF : "IFLA_GRE_IGNORE_DF",
3835 IFLA_GRE_FWMARK : "IFLA_GRE_FWMARK",
3836 IFLA_GRE_ERSPAN_INDEX : "IFLA_GRE_ERSPAN_INDEX",
3837 IFLA_GRE_ERSPAN_VER : "IFLA_GRE_ERSPAN_VER",
3838 IFLA_GRE_ERSPAN_DIR : "IFLA_GRE_ERSPAN_DIR",
3839 IFLA_GRE_ERSPAN_HWID : "IFLA_GRE_ERSPAN_HWID",
3840 }
3841
3842 # ===============================================
3843 # IFLA_INFO_DATA attributes for ipip, sit, ip6tnl
3844 # ===============================================
3845 IFLA_IPTUN_UNSPEC = 0
3846 IFLA_IPTUN_LINK = 1
3847 IFLA_IPTUN_LOCAL = 2
3848 IFLA_IPTUN_REMOTE = 3
3849 IFLA_IPTUN_TTL = 4
3850 IFLA_IPTUN_TOS = 5
3851 IFLA_IPTUN_ENCAP_LIMIT = 6
3852 IFLA_IPTUN_FLOWINFO = 7
3853 IFLA_IPTUN_FLAGS = 8
3854 IFLA_IPTUN_PROTO = 9
3855 IFLA_IPTUN_PMTUDISC = 10
3856 IFLA_IPTUN_6RD_PREFIX = 11
3857 IFLA_IPTUN_6RD_RELAY_PREFIX = 12
3858 IFLA_IPTUN_6RD_PREFIXLEN = 13
3859 IFLA_IPTUN_6RD_RELAY_PREFIXLEN = 14
3860 IFLA_IPTUN_ENCAP_TYPE = 15
3861 IFLA_IPTUN_ENCAP_FLAGS = 16
3862 IFLA_IPTUN_ENCAP_SPORT = 17
3863 IFLA_IPTUN_ENCAP_DPORT = 18
3864 IFLA_IPTUN_COLLECT_METADATA = 19
3865 IFLA_IPTUN_FWMARK = 20
3866
3867 ifla_iptun_to_string = {
3868 IFLA_IPTUN_UNSPEC : "IFLA_IPTUN_UNSPEC",
3869 IFLA_IPTUN_LINK : "IFLA_IPTUN_LINK",
3870 IFLA_IPTUN_LOCAL : "IFLA_IPTUN_LOCAL",
3871 IFLA_IPTUN_REMOTE : "IFLA_IPTUN_REMOTE",
3872 IFLA_IPTUN_TTL : "IFLA_IPTUN_TTL",
3873 IFLA_IPTUN_TOS : "IFLA_IPTUN_TOS",
3874 IFLA_IPTUN_ENCAP_LIMIT : "IFLA_IPTUN_ENCAP_LIMIT",
3875 IFLA_IPTUN_FLOWINFO : "IFLA_IPTUN_FLOWINFO",
3876 IFLA_IPTUN_FLAGS : "IFLA_IPTUN_FLAGS",
3877 IFLA_IPTUN_PROTO : "IFLA_IPTUN_PROTO",
3878 IFLA_IPTUN_PMTUDISC : "IFLA_IPTUN_PMTUDISC",
3879 IFLA_IPTUN_6RD_PREFIX : "IFLA_IPTUN_6RD_PREFIX",
3880 IFLA_IPTUN_6RD_RELAY_PREFIX : "IFLA_IPTUN_6RD_RELAY_PREFIX",
3881 IFLA_IPTUN_6RD_PREFIXLEN : "IFLA_IPTUN_6RD_PREFIXLEN",
3882 IFLA_IPTUN_6RD_RELAY_PREFIXLEN : "IFLA_IPTUN_6RD_RELAY_PREFIXLEN",
3883 IFLA_IPTUN_ENCAP_TYPE : "IFLA_IPTUN_ENCAP_TYPE",
3884 IFLA_IPTUN_ENCAP_FLAGS : "IFLA_IPTUN_ENCAP_FLAGS",
3885 IFLA_IPTUN_ENCAP_SPORT : "IFLA_IPTUN_ENCAP_SPORT",
3886 IFLA_IPTUN_ENCAP_DPORT : "IFLA_IPTUN_ENCAP_DPORT",
3887 IFLA_IPTUN_COLLECT_METADATA : "IFLA_IPTUN_COLLECT_METADATA",
3888 IFLA_IPTUN_FWMARK : "IFLA_IPTUN_FWMARK",
3889 }
3890
3891 # =========================================
3892 # IFLA_INFO_DATA attributes for vti, vti6
3893 # =========================================
3894 IFLA_VTI_UNSPEC = 0
3895 IFLA_VTI_LINK = 1
3896 IFLA_VTI_IKEY = 2
3897 IFLA_VTI_OKEY = 3
3898 IFLA_VTI_LOCAL = 4
3899 IFLA_VTI_REMOTE = 5
3900 IFLA_VTI_FWMARK = 6
3901
3902 ifla_vti_to_string = {
3903 IFLA_VTI_UNSPEC : "IFLA_VTI_UNSPEC",
3904 IFLA_VTI_LINK : "IFLA_VTI_LINK",
3905 IFLA_VTI_IKEY : "IFLA_VTI_IKEY",
3906 IFLA_VTI_OKEY : "IFLA_VTI_OKEY",
3907 IFLA_VTI_LOCAL : "IFLA_VTI_LOCAL",
3908 IFLA_VTI_REMOTE : "IFLA_VTI_REMOTE",
3909 IFLA_VTI_FWMARK : "IFLA_VTI_FWMARK",
3910 }
3911
3912 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
3913 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
3914 self.PACK = 'BxHiII'
3915 self.LEN = calcsize(self.PACK)
3916
3917 def get_link_type_string(self, index):
3918 return self.get_string(self.link_type_to_string, index)
3919
3920 def get_ifla_inet6_af_spec_to_string(self, index):
3921 return self.get_string(self.ifla_inet6_af_spec_to_string, index)
3922
3923 def get_ifla_inet_af_spec_to_string(self, index):
3924 return self.get_string(self.ifla_inet_af_spec_to_string, index)
3925
3926 def get_ifla_bridge_af_spec_to_string(self, index):
3927 return self.get_string(self.ifla_bridge_af_spec_to_string, index)
3928
3929 def get_ifla_info_string(self, index):
3930 return self.get_string(self.ifla_info_to_string, index)
3931
3932 def get_ifla_vlan_string(self, index):
3933 return self.get_string(self.ifla_vlan_to_string, index)
3934
3935 def get_ifla_vxlan_string(self, index):
3936 return self.get_string(self.ifla_vxlan_to_string, index)
3937
3938 def get_ifla_macvlan_string(self, index):
3939 return self.get_string(self.ifla_macvlan_to_string, index)
3940
3941 def get_ifla_xfrm_string(self, index):
3942 return self.get_string(self.ifla_xfrm_to_string, index)
3943
3944 def get_macvlan_mode_string(self, index):
3945 return self.get_string(self.macvlan_mode_to_string, index)
3946
3947 def get_ifla_gre_string(self, index):
3948 return self.get_string(self.ifla_gre_to_string, index)
3949
3950 def get_ifla_vti_string(self, index):
3951 return self.get_string(self.ifla_vti_to_string, index)
3952
3953 def get_ifla_iptun_string(self, index):
3954 return self.get_string(self.ifla_iptun_to_string, index)
3955
3956 def get_ifla_bond_string(self, index):
3957 return self.get_string(self.ifla_bond_to_string, index)
3958
3959 def get_ifla_bond_ad_string(self, index):
3960 return self.get_string(self.ifla_bond_ad_to_string, index)
3961
3962 def get_ifla_brport_string(self, index):
3963 return self.get_string(self.ifla_brport_to_string, index)
3964
3965 def get_ifla_br_string(self, index):
3966 return self.get_string(self.ifla_br_to_string, index)
3967
3968 def get_bridge_vlan_string(self, index):
3969 return self.get_string(self.bridge_vlan_to_string, index)
3970
3971 def get_bridge_flags_string(self, index):
3972 return self.get_string(self.bridge_flags_to_string, index)
3973
3974 def decode_service_header(self):
3975
3976 # Nothing to do if the message did not contain a service header
3977 if self.length == self.header_LEN:
3978 return
3979
3980 (self.family, self.device_type,
3981 self.ifindex,
3982 self.flags,
3983 self.change_mask) = \
3984 unpack(self.PACK, self.msg_data[:self.LEN])
3985
3986 if self.debug:
3987 color = yellow if self.use_color else None
3988 color_start = "\033[%dm" % color if color else ""
3989 color_end = "\033[0m" if color else ""
3990 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
3991
3992 for x in range(0, self.LEN/4):
3993 if self.line_number == 5:
3994 extra = "Family %s (%s:%d), Device Type %s (%d - %s)" % \
3995 (zfilled_hex(self.family, 2), get_family_str(self.family), self.family,
3996 zfilled_hex(self.device_type, 4), self.device_type, self.get_link_type_string(self.device_type))
3997 elif self.line_number == 6:
3998 extra = "Interface Index %s (%d)" % (zfilled_hex(self.ifindex, 8), self.ifindex)
3999 elif self.line_number == 7:
4000 extra = "Device Flags %s (%s)" % (zfilled_hex(self.flags, 8), self.get_flags_string())
4001 elif self.line_number == 8:
4002 extra = "Change Mask %s" % zfilled_hex(self.change_mask, 8)
4003 else:
4004 extra = "Unexpected line number %d" % self.line_number
4005
4006 start = x * 4
4007 end = start + 4
4008 self.dump_buffer.append(data_to_color_text(self.line_number, color, self.msg_data[start:end], extra))
4009 self.line_number += 1
4010
4011 def is_up(self):
4012 if self.flags & Link.IFF_UP:
4013 return True
4014 return False
4015
4016
4017 class Netconf(Link):
4018 """
4019 RTM_NEWNETCONF - Service Header
4020
4021 0 1
4022 0 1 2 3 4 5 6 7 8
4023 +-+-+-+-+-+-+-+-+
4024 | Family |
4025 +-+-+-+-+-+-+-+-+
4026
4027 RTM_GETNETCONF - Service Header
4028
4029 0 1 2 3
4030 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
4031 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4032 | Family | Reserved | Device Type |
4033 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4034 | Interface Index |
4035 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4036 | Device Flags |
4037 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4038 | Change Mask |
4039 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4040 """
4041 # Netconf attributes
4042 # /usr/include/linux/netconf.h
4043 NETCONFA_UNSPEC = 0
4044 NETCONFA_IFINDEX = 1
4045 NETCONFA_FORWARDING = 2
4046 NETCONFA_RP_FILTER = 3
4047 NETCONFA_MC_FORWARDING = 4
4048 NETCONFA_PROXY_NEIGH = 5
4049 NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN = 6
4050 NETCONFA_INPUT = 7
4051 __NETCONFA_MAX = 8
4052
4053 NETCONFA_MAX = (__NETCONFA_MAX - 1)
4054
4055 NETCONFA_ALL = -1
4056 NETCONFA_IFINDEX_ALL = -1
4057 NETCONFA_IFINDEX_DEFAULT = -2
4058
4059 NETCONF_ATTR_FAMILY = 0x0001
4060 NETCONF_ATTR_IFINDEX = 0x0002
4061 NETCONF_ATTR_RP_FILTER = 0x0004
4062 NETCONF_ATTR_FWDING = 0x0008
4063 NETCONF_ATTR_MC_FWDING = 0x0010
4064 NETCONF_ATTR_PROXY_NEIGH = 0x0020
4065 NETCONF_ATTR_IGNORE_RT_LINKDWN = 0x0040
4066
4067 attribute_to_class = {
4068 NETCONFA_UNSPEC : ('NETCONFA_UNSPEC', AttributeGeneric),
4069 NETCONFA_IFINDEX : ('NETCONFA_IFINDEX', AttributeFourByteValue),
4070 NETCONFA_FORWARDING : ('NETCONFA_FORWARDING', AttributeFourByteValue),
4071 NETCONFA_RP_FILTER : ('NETCONFA_RP_FILTER', AttributeFourByteValue),
4072 NETCONFA_MC_FORWARDING : ('NETCONFA_MC_FORWARDING', AttributeFourByteValue),
4073 NETCONFA_PROXY_NEIGH : ('NETCONFA_PROXY_NEIGH', AttributeFourByteValue),
4074 NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN : ('NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN', AttributeFourByteValue),
4075 NETCONFA_INPUT : ('NETCONFA_INPUT', AttributeFourByteValue),
4076 }
4077
4078 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
4079 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
4080 if msgtype == RTM_GETNETCONF: # same as RTM_GETLINK
4081 self.PACK = 'BxHiII'
4082 self.LEN = calcsize(self.PACK)
4083 elif msgtype == RTM_NEWNETCONF:
4084 self.PACK = 'Bxxx'
4085 self.LEN = calcsize(self.PACK)
4086
4087 def decode_service_header(self):
4088 # Nothing to do if the message did not contain a service header
4089 if self.length == self.header_LEN:
4090 return
4091
4092 if self.msgtype == RTM_GETNETCONF:
4093 super(Netconf, self).decode_service_header()
4094
4095 elif self.msgtype == RTM_NEWNETCONF:
4096 (self.family,) = unpack(self.PACK, self.msg_data[:self.LEN])
4097
4098 if self.debug:
4099 color = yellow if self.use_color else None
4100 color_start = "\033[%dm" % color if color else ""
4101 color_end = "\033[0m" if color else ""
4102 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
4103 self.dump_buffer.append(data_to_color_text(1, color, bytearray(struct.pack('!I', self.family)), "Family %s (%s:%d)" % (zfilled_hex(self.family, 2), get_family_str(self.family), self.family)))
4104
4105
4106 class Neighbor(NetlinkPacket):
4107 """
4108 Service Header
4109
4110 0 1 2 3
4111 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
4112 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4113 | Family | Reserved1 | Reserved2 |
4114 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4115 | Interface Index |
4116 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4117 | State | Flags | Type |
4118 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4119 """
4120
4121 # Neighbor attributes
4122 # /usr/include/linux/neighbour.h
4123 NDA_UNSPEC = 0x00 # Unknown type
4124 NDA_DST = 0x01 # A neighbour cache network. layer destination address
4125 NDA_LLADDR = 0x02 # A neighbor cache link layer address.
4126 NDA_CACHEINFO = 0x03 # Cache statistics
4127 NDA_PROBES = 0x04
4128 NDA_VLAN = 0x05
4129 NDA_PORT = 0x06
4130 NDA_VNI = 0x07
4131 NDA_IFINDEX = 0x08
4132 NDA_MASTER = 0x09
4133 NDA_LINK_NETNSID = 0x0A
4134
4135 attribute_to_class = {
4136 NDA_UNSPEC : ('NDA_UNSPEC', AttributeGeneric),
4137 NDA_DST : ('NDA_DST', AttributeIPAddress),
4138 NDA_LLADDR : ('NDA_LLADDR', AttributeMACAddress),
4139 NDA_CACHEINFO : ('NDA_CACHEINFO', AttributeFourByteList),
4140 NDA_PROBES : ('NDA_PROBES', AttributeFourByteValue),
4141 NDA_VLAN : ('NDA_VLAN', AttributeTwoByteValue),
4142 NDA_PORT : ('NDA_PORT', AttributeGeneric),
4143 NDA_VNI : ('NDA_VNI', AttributeFourByteValue),
4144 NDA_IFINDEX : ('NDA_IFINDEX', AttributeFourByteValue),
4145 NDA_MASTER : ('NDA_MASTER', AttributeFourByteValue),
4146 NDA_LINK_NETNSID : ('NDA_LINK_NETNSID', AttributeGeneric)
4147 }
4148
4149 # Neighbor flags
4150 # /usr/include/linux/neighbour.h
4151 NTF_USE = 0x01
4152 NTF_SELF = 0x02
4153 NTF_MASTER = 0x04
4154 NTF_PROXY = 0x08 # A proxy ARP entry
4155 NTF_EXT_LEARNED = 0x10 # neigh entry installed by an external APP
4156 NTF_ROUTER = 0x80 # An IPv6 router
4157
4158 flag_to_string = {
4159 NTF_USE : 'NTF_USE',
4160 NTF_SELF : 'NTF_SELF',
4161 NTF_MASTER : 'NTF_MASTER',
4162 NTF_PROXY : 'NTF_PROXY',
4163 NTF_EXT_LEARNED : 'NTF_EXT_LEARNED',
4164 NTF_ROUTER : 'NTF_ROUTER'
4165 }
4166
4167 # Neighbor states
4168 # /usr/include/linux/neighbour.h
4169 NUD_NONE = 0x00
4170 NUD_INCOMPLETE = 0x01 # Still attempting to resolve
4171 NUD_REACHABLE = 0x02 # A confirmed working cache entry
4172 NUD_STALE = 0x04 # an expired cache entry
4173 NUD_DELAY = 0x08 # Neighbor no longer reachable. Traffic sent, waiting for confirmatio.
4174 NUD_PROBE = 0x10 # A cache entry that is currently being re-solicited
4175 NUD_FAILED = 0x20 # An invalid cache entry
4176 NUD_NOARP = 0x40 # A device which does not do neighbor discovery(ARP)
4177 NUD_PERMANENT = 0x80 # A static entry
4178
4179 state_to_string = {
4180 NUD_NONE : 'NUD_NONE',
4181 NUD_INCOMPLETE : 'NUD_INCOMPLETE',
4182 NUD_REACHABLE : 'NUD_REACHABLE',
4183 NUD_STALE : 'NUD_STALE',
4184 NUD_DELAY : 'NUD_DELAY',
4185 NUD_PROBE : 'NUD_PROBE',
4186 NUD_FAILED : 'NUD_FAILED',
4187 NUD_NOARP : 'NUD_NOARP',
4188 NUD_PERMANENT : 'NUD_PERMANENT'
4189 }
4190
4191 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
4192 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
4193 self.PACK = 'BxxxiHBB'
4194 self.LEN = calcsize(self.PACK)
4195
4196 def get_state_string(self, index):
4197 return self.get_string(self.state_to_string, index)
4198
4199 def get_states_string(self, states):
4200 for_string = []
4201
4202 if states & Neighbor.NUD_INCOMPLETE:
4203 for_string.append('NUD_INCOMPLETE')
4204
4205 if states & Neighbor.NUD_REACHABLE:
4206 for_string.append('NUD_REACHABLE')
4207
4208 if states & Neighbor.NUD_STALE:
4209 for_string.append('NUD_STALE')
4210
4211 if states & Neighbor.NUD_DELAY:
4212 for_string.append('NUD_DELAY')
4213
4214 if states & Neighbor.NUD_PROBE:
4215 for_string.append('NUD_PROBE')
4216
4217 if states & Neighbor.NUD_FAILED:
4218 for_string.append('NUD_FAILED')
4219
4220 if states & Neighbor.NUD_NOARP:
4221 for_string.append('NUD_NOARP')
4222
4223 if states & Neighbor.NUD_PERMANENT:
4224 for_string.append('NUD_PERMANENT')
4225
4226 return ', '.join(for_string)
4227
4228 def get_flags_string(self, flags):
4229 for_string = []
4230
4231 if flags & Neighbor.NTF_USE:
4232 for_string.append('NTF_USE')
4233
4234 if flags & Neighbor.NTF_SELF:
4235 for_string.append('NTF_SELF')
4236
4237 if flags & Neighbor.NTF_MASTER:
4238 for_string.append('NTF_MASTER')
4239
4240 if flags & Neighbor.NTF_PROXY:
4241 for_string.append('NTF_PROXY')
4242
4243 if flags & Neighbor.NTF_ROUTER:
4244 for_string.append('NTF_ROUTER')
4245
4246 return ', '.join(for_string)
4247
4248 def decode_service_header(self):
4249
4250 # Nothing to do if the message did not contain a service header
4251 if self.length == self.header_LEN:
4252 return
4253
4254 (self.family,
4255 self.ifindex,
4256 self.state, self.flags, self.neighbor_type) = \
4257 unpack(self.PACK, self.msg_data[:self.LEN])
4258
4259 if self.debug:
4260 color = yellow if self.use_color else None
4261 color_start = "\033[%dm" % color if color else ""
4262 color_end = "\033[0m" if color else ""
4263 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
4264
4265 for x in range(0, self.LEN/4):
4266 if self.line_number == 5:
4267 extra = "Family %s (%s:%d)" % (zfilled_hex(self.family, 2), get_family_str(self.family), self.family)
4268 elif self.line_number == 6:
4269 extra = "Interface Index %s (%d)" % (zfilled_hex(self.ifindex, 8), self.ifindex)
4270 elif self.line_number == 7:
4271 extra = "State %s (%d) %s, Flags %s (%s) %s, Type %s (%d)" % \
4272 (zfilled_hex(self.state, 4), self.state, self.get_states_string(self.state),
4273 zfilled_hex(self.flags, 2), self.flags, self.get_flags_string(self.flags),
4274 zfilled_hex(self.neighbor_type, 4), self.neighbor_type)
4275 else:
4276 extra = "Unexpected line number %d" % self.line_number
4277
4278 start = x * 4
4279 end = start + 4
4280 self.dump_buffer.append(data_to_color_text(self.line_number, color, self.msg_data[start:end], extra))
4281 self.line_number += 1
4282
4283
4284 class Route(NetlinkPacket):
4285 """
4286 Service Header
4287
4288 0 1 2 3
4289 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
4290 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4291 | Family | Dest length | Src length | TOS |
4292 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4293 | Table ID | Protocol | Scope | Type |
4294 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4295 | Flags |
4296 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4297 """
4298
4299 # Route attributes
4300 # /usr/include/linux/rtnetlink.h
4301 RTA_UNSPEC = 0x00 # Ignored.
4302 RTA_DST = 0x01 # Protocol address for route destination address.
4303 RTA_SRC = 0x02 # Protocol address for route source address.
4304 RTA_IIF = 0x03 # Input interface index.
4305 RTA_OIF = 0x04 # Output interface index.
4306 RTA_GATEWAY = 0x05 # Protocol address for the gateway of the route
4307 RTA_PRIORITY = 0x06 # Priority of broker.
4308 RTA_PREFSRC = 0x07 # Preferred source address in cases where more than one source address could be used.
4309 RTA_METRICS = 0x08 # Route metrics attributed to route and associated protocols(e.g., RTT, initial TCP window, etc.).
4310 RTA_MULTIPATH = 0x09 # Multipath route next hop's attributes.
4311 RTA_PROTOINFO = 0x0A # Firewall based policy routing attribute.
4312 RTA_FLOW = 0x0B # Route realm.
4313 RTA_CACHEINFO = 0x0C # Cached route information.
4314 RTA_SESSION = 0x0D
4315 RTA_MP_ALGO = 0x0E
4316 RTA_TABLE = 0x0F
4317 RTA_MARK = 0x10
4318 RTA_MFC_STATS = 0x11
4319 RTA_VIA = 0x12
4320 RTA_NEWDST = 0x13
4321 RTA_PREF = 0x14
4322 RTA_ENCAP_TYPE= 0x15
4323 RTA_ENCAP = 0x16
4324
4325 attribute_to_class = {
4326 RTA_UNSPEC : ('RTA_UNSPEC', AttributeGeneric),
4327 RTA_DST : ('RTA_DST', AttributeIPAddress),
4328 RTA_SRC : ('RTA_SRC', AttributeIPAddress),
4329 RTA_IIF : ('RTA_IIF', AttributeFourByteValue),
4330 RTA_OIF : ('RTA_OIF', AttributeFourByteValue),
4331 RTA_GATEWAY : ('RTA_GATEWAY', AttributeIPAddress),
4332 RTA_PRIORITY : ('RTA_PRIORITY', AttributeFourByteValue),
4333 RTA_PREFSRC : ('RTA_PREFSRC', AttributeIPAddress),
4334 RTA_METRICS : ('RTA_METRICS', AttributeGeneric),
4335 RTA_MULTIPATH : ('RTA_MULTIPATH', AttributeRTA_MULTIPATH),
4336 RTA_PROTOINFO : ('RTA_PROTOINFO', AttributeGeneric),
4337 RTA_FLOW : ('RTA_FLOW', AttributeGeneric),
4338 RTA_CACHEINFO : ('RTA_CACHEINFO', AttributeGeneric),
4339 RTA_SESSION : ('RTA_SESSION', AttributeGeneric),
4340 RTA_MP_ALGO : ('RTA_MP_ALGO', AttributeGeneric),
4341 RTA_TABLE : ('RTA_TABLE', AttributeFourByteValue),
4342 RTA_MARK : ('RTA_MARK', AttributeGeneric),
4343 RTA_MFC_STATS : ('RTA_MFC_STATS', AttributeGeneric),
4344 RTA_VIA : ('RTA_VIA', AttributeGeneric),
4345 RTA_NEWDST : ('RTA_NEWDST', AttributeGeneric),
4346 RTA_PREF : ('RTA_PREF', AttributeGeneric),
4347 RTA_ENCAP_TYPE: ('RTA_ENCAP_TYPE', AttributeGeneric),
4348 RTA_ENCAP : ('RTA_ENCAP', AttributeGeneric)
4349 }
4350
4351 # Route tables
4352 # /usr/include/linux/rtnetlink.h
4353 RT_TABLE_UNSPEC = 0x00 # An unspecified routing table
4354 RT_TABLE_COMPAT = 0xFC
4355 RT_TABLE_DEFAULT = 0xFD # The default table
4356 RT_TABLE_MAIN = 0xFE # The main table
4357 RT_TABLE_LOCAL = 0xFF # The local table
4358
4359 table_to_string = {
4360 RT_TABLE_UNSPEC : 'RT_TABLE_UNSPEC',
4361 RT_TABLE_COMPAT : 'RT_TABLE_COMPAT',
4362 RT_TABLE_DEFAULT : 'RT_TABLE_DEFAULT',
4363 RT_TABLE_MAIN : 'RT_TABLE_MAIN',
4364 RT_TABLE_LOCAL : 'RT_TABLE_LOCAL'
4365 }
4366
4367 # Route scope
4368 # /usr/include/linux/rtnetlink.h
4369 RT_SCOPE_UNIVERSE = 0x00 # Global route
4370 RT_SCOPE_SITE = 0xC8 # Interior route in the local autonomous system
4371 RT_SCOPE_LINK = 0xFD # Route on this link
4372 RT_SCOPE_HOST = 0xFE # Route on the local host
4373 RT_SCOPE_NOWHERE = 0xFF # Destination does not exist
4374
4375 scope_to_string = {
4376 RT_SCOPE_UNIVERSE : 'RT_SCOPE_UNIVERSE',
4377 RT_SCOPE_SITE : 'RT_SCOPE_SITE',
4378 RT_SCOPE_LINK : 'RT_SCOPE_LINK',
4379 RT_SCOPE_HOST : 'RT_SCOPE_HOST',
4380 RT_SCOPE_NOWHERE : 'RT_SCOPE_NOWHERE'
4381 }
4382
4383 # Route scope to string
4384 # iproute2/lib/rt_names.c
4385 rtnl_rtscope_tab = {
4386 RT_SCOPE_UNIVERSE: 'global',
4387 RT_SCOPE_NOWHERE: 'nowhere',
4388 RT_SCOPE_HOST: 'host',
4389 RT_SCOPE_LINK: 'link',
4390 RT_SCOPE_SITE: 'site'
4391 }
4392
4393 # Routing stack
4394 # /usr/include/linux/rtnetlink.h
4395 RT_PROT_UNSPEC = 0x00 # Identifies what/who added the route
4396 RT_PROT_REDIRECT = 0x01 # By an ICMP redirect
4397 RT_PROT_KERNEL = 0x02 # By the kernel
4398 RT_PROT_BOOT = 0x03 # During bootup
4399 RT_PROT_STATIC = 0x04 # By the administrator
4400 RT_PROT_GATED = 0x08 # GateD
4401 RT_PROT_RA = 0x09 # RDISC/ND router advertissements
4402 RT_PROT_MRT = 0x0A # Merit MRT
4403 RT_PROT_ZEBRA = 0x0B # ZEBRA
4404 RT_PROT_BIRD = 0x0C # BIRD
4405 RT_PROT_DNROUTED = 0x0D # DECnet routing daemon
4406 RT_PROT_XORP = 0x0E # XORP
4407 RT_PROT_NTK = 0x0F # Netsukuku
4408 RT_PROT_DHCP = 0x10 # DHCP client
4409 RT_PROT_EXABGP = 0x11 # Exa Networks ExaBGP
4410
4411 prot_to_string = {
4412 RT_PROT_UNSPEC : 'RT_PROT_UNSPEC',
4413 RT_PROT_REDIRECT : 'RT_PROT_REDIRECT',
4414 RT_PROT_KERNEL : 'RT_PROT_KERNEL',
4415 RT_PROT_BOOT : 'RT_PROT_BOOT',
4416 RT_PROT_STATIC : 'RT_PROT_STATIC',
4417 RT_PROT_GATED : 'RT_PROT_GATED',
4418 RT_PROT_RA : 'RT_PROT_RA',
4419 RT_PROT_MRT : 'RT_PROT_MRT',
4420 RT_PROT_ZEBRA : 'RT_PROT_ZEBRA',
4421 RT_PROT_BIRD : 'RT_PROT_BIRD',
4422 RT_PROT_DNROUTED : 'RT_PROT_DNROUTED',
4423 RT_PROT_XORP : 'RT_PROT_XORP',
4424 RT_PROT_NTK : 'RT_PROT_NTK',
4425 RT_PROT_DHCP : 'RT_PROT_DHCP',
4426 RT_PROT_EXABGP : 'RT_PROT_EXABGP'
4427 }
4428
4429 # Route types
4430 # /usr/include/linux/rtnetlink.h
4431 RTN_UNSPEC = 0x00 # Unknown broker.
4432 RTN_UNICAST = 0x01 # A gateway or direct broker.
4433 RTN_LOCAL = 0x02 # A local interface broker.
4434 RTN_BROADCAST = 0x03 # A local broadcast route(sent as a broadcast).
4435 RTN_ANYCAST = 0x04 # An anycast broker.
4436 RTN_MULTICAST = 0x05 # A multicast broker.
4437 RTN_BLACKHOLE = 0x06 # A silent packet dropping broker.
4438 RTN_UNREACHABLE = 0x07 # An unreachable destination. Packets dropped and
4439 # host unreachable ICMPs are sent to the originator.
4440 RTN_PROHIBIT = 0x08 # A packet rejection broker. Packets are dropped and
4441 # communication prohibited ICMPs are sent to the originator.
4442 RTN_THROW = 0x09 # When used with policy routing, continue routing lookup
4443 # in another table. Under normal routing, packets are
4444 # dropped and net unreachable ICMPs are sent to the originator.
4445 RTN_NAT = 0x0A # A network address translation rule.
4446 RTN_XRESOLVE = 0x0B # Refer to an external resolver(not implemented).
4447
4448 rt_type_to_string = {
4449 RTN_UNSPEC : 'RTN_UNSPEC',
4450 RTN_UNICAST : 'RTN_UNICAST',
4451 RTN_LOCAL : 'RTN_LOCAL',
4452 RTN_BROADCAST : 'RTN_BROADCAST',
4453 RTN_ANYCAST : 'RTN_ANYCAST',
4454 RTN_MULTICAST : 'RTN_MULTICAST',
4455 RTN_BLACKHOLE : 'RTN_BLACKHOLE',
4456 RTN_UNREACHABLE : 'RTN_UNREACHABLE',
4457 RTN_PROHIBIT : 'RTN_PROHIBIT',
4458 RTN_THROW : 'RTN_THROW',
4459 RTN_NAT : 'RTN_NAT',
4460 RTN_XRESOLVE : 'RTN_XRESOLVE'
4461 }
4462
4463 # Route flags
4464 # /usr/include/linux/rtnetlink.h
4465 RTM_F_NOTIFY = 0x100 # If the route changes, notify the user
4466 RTM_F_CLONED = 0x200 # Route is cloned from another route
4467 RTM_F_EQUALIZE = 0x400 # Allow randomization of next hop path in multi-path routing(currently not implemented)
4468 RTM_F_PREFIX = 0x800 # Prefix Address
4469
4470 flag_to_string = {
4471 RTM_F_NOTIFY : 'RTM_F_NOTIFY',
4472 RTM_F_CLONED : 'RTM_F_CLONED',
4473 RTM_F_EQUALIZE : 'RTM_F_EQUALIZE',
4474 RTM_F_PREFIX : 'RTM_F_PREFIX'
4475 }
4476
4477 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
4478 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
4479 self.PACK = '=8BI' # or is it 8Bi ?
4480 self.LEN = calcsize(self.PACK)
4481
4482 def get_prefix_string(self):
4483 dst = self.get_attribute_value(self.RTA_DST)
4484
4485 if dst:
4486 return "%s/%d" % (dst, self.src_len)
4487 else:
4488 if self.family == AF_INET:
4489 return "0.0.0.0/0"
4490 elif self.family == AF_INET6:
4491 return "::/0"
4492
4493 def get_protocol_string(self, index=None):
4494 if index is None:
4495 index = self.protocol
4496 return self.get_string(self.prot_to_string, index)
4497
4498 def get_rt_type_string(self, index=None):
4499 if index is None:
4500 index = self.route_type
4501 return self.get_string(self.rt_type_to_string, index)
4502
4503 def get_scope_string(self, index=None):
4504 if index is None:
4505 index = self.scope
4506 return self.get_string(self.scope_to_string, index)
4507
4508 def get_table_id_string(self, index=None):
4509 if index is None:
4510 index = self.table_id
4511 return self.get_string(self.table_to_string, index)
4512
4513 def _get_ifname_from_index(self, ifindex, ifname_by_index):
4514 if ifindex:
4515 ifname = ifname_by_index.get(ifindex)
4516
4517 if ifname is None:
4518 ifname = str(ifindex)
4519 else:
4520 ifname = None
4521
4522 return ifname
4523
4524 def get_nexthops(self, ifname_by_index={}):
4525 nexthop = self.get_attribute_value(self.RTA_GATEWAY)
4526 multipath = self.get_attribute_value(self.RTA_MULTIPATH)
4527 nexthops = []
4528
4529 if nexthop:
4530 rta_oif = self.get_attribute_value(self.RTA_OIF)
4531 ifname = self._get_ifname_from_index(rta_oif, ifname_by_index)
4532 nexthops.append((nexthop, ifname))
4533
4534 elif multipath:
4535 for (nexthop, rtnh_ifindex, rtnh_flags, rtnh_hops) in multipath:
4536 ifname = self._get_ifname_from_index(rtnh_ifindex, ifname_by_index)
4537 nexthops.append((nexthop, ifname))
4538
4539 return nexthops
4540
4541 def get_nexthops_string(self, ifname_by_index={}):
4542 output = []
4543
4544 for (nexthop, ifname) in self.get_nexthops(ifname_by_index):
4545 output.append(" via %s on %s" % (nexthop, ifname))
4546
4547 return ",".join(output)
4548
4549 def decode_service_header(self):
4550
4551 # Nothing to do if the message did not contain a service header
4552 if self.length == self.header_LEN:
4553 return
4554
4555 (self.family, self.src_len, self.dst_len, self.tos,
4556 self.table_id, self.protocol, self.scope, self.route_type,
4557 self.flags) = \
4558 unpack(self.PACK, self.msg_data[:self.LEN])
4559
4560 if self.debug:
4561 color = yellow if self.use_color else None
4562 color_start = "\033[%dm" % color if color else ""
4563 color_end = "\033[0m" if color else ""
4564 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
4565
4566 for x in range(0, self.LEN/4):
4567 if self.line_number == 5:
4568 extra = "Family %s (%s:%d), Source Length %s (%d), Destination Length %s (%d), TOS %s (%d)" % \
4569 (zfilled_hex(self.family, 2), get_family_str(self.family), self.family,
4570 zfilled_hex(self.src_len, 2), self.src_len,
4571 zfilled_hex(self.dst_len, 2), self.dst_len,
4572 zfilled_hex(self.tos, 2), self.tos)
4573 elif self.line_number == 6:
4574 extra = "Table ID %s (%d - %s), Protocol %s (%d - %s), Scope %s (%d - %s), Type %s (%d - %s)" % \
4575 (zfilled_hex(self.table_id, 2), self.table_id, self.get_table_id_string(),
4576 zfilled_hex(self.protocol, 2), self.protocol, self.get_protocol_string(),
4577 zfilled_hex(self.scope, 2), self.scope, self.get_scope_string(),
4578 zfilled_hex(self.route_type, 2), self.route_type, self.get_rt_type_string())
4579 elif self.line_number == 7:
4580 extra = "Flags %s" % zfilled_hex(self.flags, 8)
4581 else:
4582 extra = "Unexpected line number %d" % self.line_number
4583
4584 start = x * 4
4585 end = start + 4
4586 self.dump_buffer.append(data_to_color_text(self.line_number, color, self.msg_data[start:end], extra))
4587 self.line_number += 1
4588
4589 class Done(NetlinkPacket):
4590 """
4591 NLMSG_DONE
4592
4593 Service Header
4594 0 1 2 3
4595 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
4596 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4597 | TBD |
4598 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4599 """
4600
4601 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
4602 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
4603 self.PACK = 'i'
4604 self.LEN = calcsize(self.PACK)
4605
4606 def decode_service_header(self):
4607 foo = unpack(self.PACK, self.msg_data[:self.LEN])
4608
4609 if self.debug:
4610 color = yellow if self.use_color else None
4611 color_start = "\033[%dm" % color if color else ""
4612 color_end = "\033[0m" if color else ""
4613 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
4614
4615 for x in range(0, self.LEN/4):
4616 extra = ''
4617 start = x * 4
4618 end = start + 4
4619 self.dump_buffer.append(data_to_color_text(self.line_number, color, self.msg_data[start:end], extra))
4620 self.line_number += 1