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