]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown2/nlmanager/nlpacket.py
Add addon module for B.A.T.M.A.N. advanced interface configuration. #12
[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
3579 # Subtype attrbutes AF_INET
3580 IFLA_INET_UNSPEC = 0
3581 IFLA_INET_CONF = 1
3582 __IFLA_INET_MAX = 2
3583
3584 ifla_inet_af_spec_to_string = {
3585 IFLA_INET_UNSPEC : 'IFLA_INET_UNSPEC',
3586 IFLA_INET_CONF : 'IFLA_INET_CONF',
3587 }
3588
198ded6a
JF
3589 # BRIDGE IFLA_AF_SPEC attributes
3590 IFLA_BRIDGE_FLAGS = 0
3591 IFLA_BRIDGE_MODE = 1
3592 IFLA_BRIDGE_VLAN_INFO = 2
3593
3594 ifla_bridge_af_spec_to_string = {
3595 IFLA_BRIDGE_FLAGS : 'IFLA_BRIDGE_FLAGS',
3596 IFLA_BRIDGE_MODE : 'IFLA_BRIDGE_MODE',
3597 IFLA_BRIDGE_VLAN_INFO : 'IFLA_BRIDGE_VLAN_INFO'
3598 }
3599
3600 # BRIDGE_VLAN_INFO flags
d486dd0d
JF
3601 BRIDGE_VLAN_INFO_MASTER = 1 << 0 # Operate on Bridge device as well
3602 BRIDGE_VLAN_INFO_PVID = 1 << 1 # VLAN is PVID, ingress untagged
3603 BRIDGE_VLAN_INFO_UNTAGGED = 1 << 2 # VLAN egresses untagged
3604 BRIDGE_VLAN_INFO_RANGE_BEGIN = 1 << 3 # VLAN is start of vlan range
3605 BRIDGE_VLAN_INFO_RANGE_END = 1 << 4 # VLAN is end of vlan range
3606 BRIDGE_VLAN_INFO_BRENTRY = 1 << 5 # Global bridge VLAN entry
198ded6a
JF
3607
3608 bridge_vlan_to_string = {
26d1e82b
JF
3609 BRIDGE_VLAN_INFO_MASTER : 'BRIDGE_VLAN_INFO_MASTER',
3610 BRIDGE_VLAN_INFO_PVID : 'BRIDGE_VLAN_INFO_PVID',
3611 BRIDGE_VLAN_INFO_UNTAGGED : 'BRIDGE_VLAN_INFO_UNTAGGED',
3612 BRIDGE_VLAN_INFO_RANGE_BEGIN : 'BRIDGE_VLAN_INFO_RANGE_BEGIN',
d486dd0d
JF
3613 BRIDGE_VLAN_INFO_RANGE_END : 'BRIDGE_VLAN_INFO_RANGE_END',
3614 BRIDGE_VLAN_INFO_BRENTRY : 'BRIDGE_VLAN_INFO_BRENTRY'
198ded6a
JF
3615 }
3616
3617 # Bridge flags
3618 BRIDGE_FLAGS_MASTER = 1
3619 BRIDGE_FLAGS_SELF = 2
3620
3621 bridge_flags_to_string = {
3622 BRIDGE_FLAGS_MASTER : 'BRIDGE_FLAGS_MASTER',
3623 BRIDGE_FLAGS_SELF : 'BRIDGE_FLAGS_SELF'
3624 }
3625
26d1e82b
JF
3626 # filters for IFLA_EXT_MASK
3627 RTEXT_FILTER_VF = 1 << 0
3628 RTEXT_FILTER_BRVLAN = 1 << 1
3629 RTEXT_FILTER_BRVLAN_COMPRESSED = 1 << 2
3630 RTEXT_FILTER_SKIP_STATS = 1 << 3
3631
3632 rtext_to_string = {
3633 RTEXT_FILTER_VF : 'RTEXT_FILTER_VF',
3634 RTEXT_FILTER_BRVLAN : 'RTEXT_FILTER_BRVLAN',
3635 RTEXT_FILTER_BRVLAN_COMPRESSED : 'RTEXT_FILTER_BRVLAN_COMPRESSED',
3636 RTEXT_FILTER_SKIP_STATS : 'RTEXT_FILTER_SKIP_STATS'
3637 }
3638
c4fd4972
JF
3639 IFLA_BR_UNSPEC = 0
3640 IFLA_BR_FORWARD_DELAY = 1
3641 IFLA_BR_HELLO_TIME = 2
3642 IFLA_BR_MAX_AGE = 3
3643 IFLA_BR_AGEING_TIME = 4
3644 IFLA_BR_STP_STATE = 5
3645 IFLA_BR_PRIORITY = 6
3646 IFLA_BR_VLAN_FILTERING = 7
3647 IFLA_BR_VLAN_PROTOCOL = 8
3648 IFLA_BR_GROUP_FWD_MASK = 9
3649 IFLA_BR_ROOT_ID = 10
3650 IFLA_BR_BRIDGE_ID = 11
3651 IFLA_BR_ROOT_PORT = 12
3652 IFLA_BR_ROOT_PATH_COST = 13
3653 IFLA_BR_TOPOLOGY_CHANGE = 14
3654 IFLA_BR_TOPOLOGY_CHANGE_DETECTED = 15
3655 IFLA_BR_HELLO_TIMER = 16
3656 IFLA_BR_TCN_TIMER = 17
3657 IFLA_BR_TOPOLOGY_CHANGE_TIMER = 18
3658 IFLA_BR_GC_TIMER = 19
3659 IFLA_BR_GROUP_ADDR = 20
3660 IFLA_BR_FDB_FLUSH = 21
3661 IFLA_BR_MCAST_ROUTER = 22
3662 IFLA_BR_MCAST_SNOOPING = 23
3663 IFLA_BR_MCAST_QUERY_USE_IFADDR = 24
3664 IFLA_BR_MCAST_QUERIER = 25
3665 IFLA_BR_MCAST_HASH_ELASTICITY = 26
3666 IFLA_BR_MCAST_HASH_MAX = 27
3667 IFLA_BR_MCAST_LAST_MEMBER_CNT = 28
3668 IFLA_BR_MCAST_STARTUP_QUERY_CNT = 29
3669 IFLA_BR_MCAST_LAST_MEMBER_INTVL = 30
3670 IFLA_BR_MCAST_MEMBERSHIP_INTVL = 31
3671 IFLA_BR_MCAST_QUERIER_INTVL = 32
3672 IFLA_BR_MCAST_QUERY_INTVL = 33
3673 IFLA_BR_MCAST_QUERY_RESPONSE_INTVL = 34
3674 IFLA_BR_MCAST_STARTUP_QUERY_INTVL = 35
3675 IFLA_BR_NF_CALL_IPTABLES = 36
3676 IFLA_BR_NF_CALL_IP6TABLES = 37
3677 IFLA_BR_NF_CALL_ARPTABLES = 38
3678 IFLA_BR_VLAN_DEFAULT_PVID = 39
d486dd0d
JF
3679 IFLA_BR_PAD = 40
3680 IFLA_BR_VLAN_STATS_ENABLED = 41
3681 IFLA_BR_MCAST_STATS_ENABLED = 42
3682 IFLA_BR_MCAST_IGMP_VERSION = 43
3683 IFLA_BR_MCAST_MLD_VERSION = 44
c4fd4972
JF
3684
3685 ifla_br_to_string = {
3686 IFLA_BR_UNSPEC : 'IFLA_BR_UNSPEC',
3687 IFLA_BR_FORWARD_DELAY : 'IFLA_BR_FORWARD_DELAY',
3688 IFLA_BR_HELLO_TIME : 'IFLA_BR_HELLO_TIME',
3689 IFLA_BR_MAX_AGE : 'IFLA_BR_MAX_AGE',
3690 IFLA_BR_AGEING_TIME : 'IFLA_BR_AGEING_TIME',
3691 IFLA_BR_STP_STATE : 'IFLA_BR_STP_STATE',
3692 IFLA_BR_PRIORITY : 'IFLA_BR_PRIORITY',
3693 IFLA_BR_VLAN_FILTERING : 'IFLA_BR_VLAN_FILTERING',
3694 IFLA_BR_VLAN_PROTOCOL : 'IFLA_BR_VLAN_PROTOCOL',
3695 IFLA_BR_GROUP_FWD_MASK : 'IFLA_BR_GROUP_FWD_MASK',
3696 IFLA_BR_ROOT_ID : 'IFLA_BR_ROOT_ID',
3697 IFLA_BR_BRIDGE_ID : 'IFLA_BR_BRIDGE_ID',
3698 IFLA_BR_ROOT_PORT : 'IFLA_BR_ROOT_PORT',
3699 IFLA_BR_ROOT_PATH_COST : 'IFLA_BR_ROOT_PATH_COST',
3700 IFLA_BR_TOPOLOGY_CHANGE : 'IFLA_BR_TOPOLOGY_CHANGE',
3701 IFLA_BR_TOPOLOGY_CHANGE_DETECTED : 'IFLA_BR_TOPOLOGY_CHANGE_DETECTED',
3702 IFLA_BR_HELLO_TIMER : 'IFLA_BR_HELLO_TIMER',
3703 IFLA_BR_TCN_TIMER : 'IFLA_BR_TCN_TIMER',
3704 IFLA_BR_TOPOLOGY_CHANGE_TIMER : 'IFLA_BR_TOPOLOGY_CHANGE_TIMER',
3705 IFLA_BR_GC_TIMER : 'IFLA_BR_GC_TIMER',
3706 IFLA_BR_GROUP_ADDR : 'IFLA_BR_GROUP_ADDR',
3707 IFLA_BR_FDB_FLUSH : 'IFLA_BR_FDB_FLUSH',
3708 IFLA_BR_MCAST_ROUTER : 'IFLA_BR_MCAST_ROUTER',
3709 IFLA_BR_MCAST_SNOOPING : 'IFLA_BR_MCAST_SNOOPING',
3710 IFLA_BR_MCAST_QUERY_USE_IFADDR : 'IFLA_BR_MCAST_QUERY_USE_IFADDR',
3711 IFLA_BR_MCAST_QUERIER : 'IFLA_BR_MCAST_QUERIER',
3712 IFLA_BR_MCAST_HASH_ELASTICITY : 'IFLA_BR_MCAST_HASH_ELASTICITY',
3713 IFLA_BR_MCAST_HASH_MAX : 'IFLA_BR_MCAST_HASH_MAX',
3714 IFLA_BR_MCAST_LAST_MEMBER_CNT : 'IFLA_BR_MCAST_LAST_MEMBER_CNT',
3715 IFLA_BR_MCAST_STARTUP_QUERY_CNT : 'IFLA_BR_MCAST_STARTUP_QUERY_CNT',
3716 IFLA_BR_MCAST_LAST_MEMBER_INTVL : 'IFLA_BR_MCAST_LAST_MEMBER_INTVL',
3717 IFLA_BR_MCAST_MEMBERSHIP_INTVL : 'IFLA_BR_MCAST_MEMBERSHIP_INTVL',
3718 IFLA_BR_MCAST_QUERIER_INTVL : 'IFLA_BR_MCAST_QUERIER_INTVL',
3719 IFLA_BR_MCAST_QUERY_INTVL : 'IFLA_BR_MCAST_QUERY_INTVL',
3720 IFLA_BR_MCAST_QUERY_RESPONSE_INTVL : 'IFLA_BR_MCAST_QUERY_RESPONSE_INTVL',
3721 IFLA_BR_MCAST_STARTUP_QUERY_INTVL : 'IFLA_BR_MCAST_STARTUP_QUERY_INTVL',
3722 IFLA_BR_NF_CALL_IPTABLES : 'IFLA_BR_NF_CALL_IPTABLES',
3723 IFLA_BR_NF_CALL_IP6TABLES : 'IFLA_BR_NF_CALL_IP6TABLES',
3724 IFLA_BR_NF_CALL_ARPTABLES : 'IFLA_BR_NF_CALL_ARPTABLES',
3725 IFLA_BR_VLAN_DEFAULT_PVID : 'IFLA_BR_VLAN_DEFAULT_PVID',
d486dd0d
JF
3726 IFLA_BR_PAD : 'IFLA_BR_PAD',
3727 IFLA_BR_VLAN_STATS_ENABLED : 'IFLA_BR_VLAN_STATS_ENABLED',
3728 IFLA_BR_MCAST_STATS_ENABLED : 'IFLA_BR_MCAST_STATS_ENABLED',
3729 IFLA_BR_MCAST_IGMP_VERSION : 'IFLA_BR_MCAST_IGMP_VERSION',
3730 IFLA_BR_MCAST_MLD_VERSION : 'IFLA_BR_MCAST_MLD_VERSION'
3731 }
3732
3733 # =========================================
3734 # IFLA_INFO_DATA attributes for vrfs
3735 # =========================================
3736 IFLA_VRF_UNSPEC = 0
3737 IFLA_VRF_TABLE = 1
3738
3739 ifla_vrf_to_string = {
3740 IFLA_VRF_UNSPEC : 'IFLA_VRF_UNSPEC',
3741 IFLA_VRF_TABLE : 'IFLA_VRF_TABLE'
c4fd4972
JF
3742 }
3743
35848ca0
JF
3744 # ================================================================
3745 # IFLA_INFO_DATA attributes for (ip6)gre, (ip6)gretap, (ip6)erspan
3746 # ================================================================
3747 IFLA_GRE_UNSPEC = 0
3748 IFLA_GRE_LINK = 1
3749 IFLA_GRE_IFLAGS = 2
3750 IFLA_GRE_OFLAGS = 3
3751 IFLA_GRE_IKEY = 4
3752 IFLA_GRE_OKEY = 5
3753 IFLA_GRE_LOCAL = 6
3754 IFLA_GRE_REMOTE = 7
3755 IFLA_GRE_TTL = 8
3756 IFLA_GRE_TOS = 9
3757 IFLA_GRE_PMTUDISC = 10
3758 IFLA_GRE_ENCAP_LIMIT = 11
3759 IFLA_GRE_FLOWINFO = 12
3760 IFLA_GRE_FLAGS = 13
3761 IFLA_GRE_ENCAP_TYPE = 14
3762 IFLA_GRE_ENCAP_FLAGS = 15
3763 IFLA_GRE_ENCAP_SPORT = 16
3764 IFLA_GRE_ENCAP_DPORT = 17
3765 IFLA_GRE_COLLECT_METADATA = 18
3766 IFLA_GRE_IGNORE_DF = 19
3767 IFLA_GRE_FWMARK = 20
3768 IFLA_GRE_ERSPAN_INDEX = 21
3769 IFLA_GRE_ERSPAN_VER = 22
3770 IFLA_GRE_ERSPAN_DIR = 23
3771 IFLA_GRE_ERSPAN_HWID = 24
3772
3773 ifla_gre_to_string = {
3774 IFLA_GRE_UNSPEC : "IFLA_GRE_UNSPEC",
3775 IFLA_GRE_LINK : "IFLA_GRE_LINK",
3776 IFLA_GRE_IFLAGS : "IFLA_GRE_IFLAGS",
3777 IFLA_GRE_OFLAGS : "IFLA_GRE_OFLAGS",
3778 IFLA_GRE_IKEY : "IFLA_GRE_IKEY",
3779 IFLA_GRE_OKEY : "IFLA_GRE_OKEY",
3780 IFLA_GRE_LOCAL : "IFLA_GRE_LOCAL",
3781 IFLA_GRE_REMOTE : "IFLA_GRE_REMOTE",
3782 IFLA_GRE_TTL : "IFLA_GRE_TTL",
3783 IFLA_GRE_TOS : "IFLA_GRE_TOS",
3784 IFLA_GRE_PMTUDISC : "IFLA_GRE_PMTUDISC",
3785 IFLA_GRE_ENCAP_LIMIT : "IFLA_GRE_ENCAP_LIMIT",
3786 IFLA_GRE_FLOWINFO : "IFLA_GRE_FLOWINFO",
3787 IFLA_GRE_FLAGS : "IFLA_GRE_FLAGS",
3788 IFLA_GRE_ENCAP_TYPE : "IFLA_GRE_ENCAP_TYPE",
3789 IFLA_GRE_ENCAP_FLAGS : "IFLA_GRE_ENCAP_FLAGS",
3790 IFLA_GRE_ENCAP_SPORT : "IFLA_GRE_ENCAP_SPORT",
3791 IFLA_GRE_ENCAP_DPORT : "IFLA_GRE_ENCAP_DPORT",
3792 IFLA_GRE_COLLECT_METADATA : "IFLA_GRE_COLLECT_METADATA",
3793 IFLA_GRE_IGNORE_DF : "IFLA_GRE_IGNORE_DF",
3794 IFLA_GRE_FWMARK : "IFLA_GRE_FWMARK",
3795 IFLA_GRE_ERSPAN_INDEX : "IFLA_GRE_ERSPAN_INDEX",
3796 IFLA_GRE_ERSPAN_VER : "IFLA_GRE_ERSPAN_VER",
3797 IFLA_GRE_ERSPAN_DIR : "IFLA_GRE_ERSPAN_DIR",
3798 IFLA_GRE_ERSPAN_HWID : "IFLA_GRE_ERSPAN_HWID",
3799 }
3800
3801 # ===============================================
3802 # IFLA_INFO_DATA attributes for ipip, sit, ip6tnl
3803 # ===============================================
3804 IFLA_IPTUN_UNSPEC = 0
3805 IFLA_IPTUN_LINK = 1
3806 IFLA_IPTUN_LOCAL = 2
3807 IFLA_IPTUN_REMOTE = 3
3808 IFLA_IPTUN_TTL = 4
3809 IFLA_IPTUN_TOS = 5
3810 IFLA_IPTUN_ENCAP_LIMIT = 6
3811 IFLA_IPTUN_FLOWINFO = 7
3812 IFLA_IPTUN_FLAGS = 8
3813 IFLA_IPTUN_PROTO = 9
3814 IFLA_IPTUN_PMTUDISC = 10
3815 IFLA_IPTUN_6RD_PREFIX = 11
3816 IFLA_IPTUN_6RD_RELAY_PREFIX = 12
3817 IFLA_IPTUN_6RD_PREFIXLEN = 13
3818 IFLA_IPTUN_6RD_RELAY_PREFIXLEN = 14
3819 IFLA_IPTUN_ENCAP_TYPE = 15
3820 IFLA_IPTUN_ENCAP_FLAGS = 16
3821 IFLA_IPTUN_ENCAP_SPORT = 17
3822 IFLA_IPTUN_ENCAP_DPORT = 18
3823 IFLA_IPTUN_COLLECT_METADATA = 19
3824 IFLA_IPTUN_FWMARK = 20
3825
3826 ifla_iptun_to_string = {
3827 IFLA_IPTUN_UNSPEC : "IFLA_IPTUN_UNSPEC",
3828 IFLA_IPTUN_LINK : "IFLA_IPTUN_LINK",
3829 IFLA_IPTUN_LOCAL : "IFLA_IPTUN_LOCAL",
3830 IFLA_IPTUN_REMOTE : "IFLA_IPTUN_REMOTE",
3831 IFLA_IPTUN_TTL : "IFLA_IPTUN_TTL",
3832 IFLA_IPTUN_TOS : "IFLA_IPTUN_TOS",
3833 IFLA_IPTUN_ENCAP_LIMIT : "IFLA_IPTUN_ENCAP_LIMIT",
3834 IFLA_IPTUN_FLOWINFO : "IFLA_IPTUN_FLOWINFO",
3835 IFLA_IPTUN_FLAGS : "IFLA_IPTUN_FLAGS",
3836 IFLA_IPTUN_PROTO : "IFLA_IPTUN_PROTO",
3837 IFLA_IPTUN_PMTUDISC : "IFLA_IPTUN_PMTUDISC",
3838 IFLA_IPTUN_6RD_PREFIX : "IFLA_IPTUN_6RD_PREFIX",
3839 IFLA_IPTUN_6RD_RELAY_PREFIX : "IFLA_IPTUN_6RD_RELAY_PREFIX",
3840 IFLA_IPTUN_6RD_PREFIXLEN : "IFLA_IPTUN_6RD_PREFIXLEN",
3841 IFLA_IPTUN_6RD_RELAY_PREFIXLEN : "IFLA_IPTUN_6RD_RELAY_PREFIXLEN",
3842 IFLA_IPTUN_ENCAP_TYPE : "IFLA_IPTUN_ENCAP_TYPE",
3843 IFLA_IPTUN_ENCAP_FLAGS : "IFLA_IPTUN_ENCAP_FLAGS",
3844 IFLA_IPTUN_ENCAP_SPORT : "IFLA_IPTUN_ENCAP_SPORT",
3845 IFLA_IPTUN_ENCAP_DPORT : "IFLA_IPTUN_ENCAP_DPORT",
3846 IFLA_IPTUN_COLLECT_METADATA : "IFLA_IPTUN_COLLECT_METADATA",
3847 IFLA_IPTUN_FWMARK : "IFLA_IPTUN_FWMARK",
3848 }
3849
3850 # =========================================
3851 # IFLA_INFO_DATA attributes for vti, vti6
3852 # =========================================
3853 IFLA_VTI_UNSPEC = 0
3854 IFLA_VTI_LINK = 1
3855 IFLA_VTI_IKEY = 2
3856 IFLA_VTI_OKEY = 3
3857 IFLA_VTI_LOCAL = 4
3858 IFLA_VTI_REMOTE = 5
3859 IFLA_VTI_FWMARK = 6
3860
3861 ifla_vti_to_string = {
3862 IFLA_VTI_UNSPEC : "IFLA_VTI_UNSPEC",
3863 IFLA_VTI_LINK : "IFLA_VTI_LINK",
3864 IFLA_VTI_IKEY : "IFLA_VTI_IKEY",
3865 IFLA_VTI_OKEY : "IFLA_VTI_OKEY",
3866 IFLA_VTI_LOCAL : "IFLA_VTI_LOCAL",
3867 IFLA_VTI_REMOTE : "IFLA_VTI_REMOTE",
3868 IFLA_VTI_FWMARK : "IFLA_VTI_FWMARK",
3869 }
3870
a61d1777
SE
3871 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
3872 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
198ded6a
JF
3873 self.PACK = 'BxHiII'
3874 self.LEN = calcsize(self.PACK)
3875
3876 def get_link_type_string(self, index):
3877 return self.get_string(self.link_type_to_string, index)
3878
f8f6549b
JF
3879 def get_ifla_inet6_af_spec_to_string(self, index):
3880 return self.get_string(self.ifla_inet6_af_spec_to_string, index)
3881
3882 def get_ifla_inet_af_spec_to_string(self, index):
3883 return self.get_string(self.ifla_inet_af_spec_to_string, index)
3884
198ded6a
JF
3885 def get_ifla_bridge_af_spec_to_string(self, index):
3886 return self.get_string(self.ifla_bridge_af_spec_to_string, index)
3887
3888 def get_ifla_info_string(self, index):
3889 return self.get_string(self.ifla_info_to_string, index)
3890
3891 def get_ifla_vlan_string(self, index):
3892 return self.get_string(self.ifla_vlan_to_string, index)
3893
3894 def get_ifla_vxlan_string(self, index):
3895 return self.get_string(self.ifla_vxlan_to_string, index)
3896
3897 def get_ifla_macvlan_string(self, index):
3898 return self.get_string(self.ifla_macvlan_to_string, index)
3899
3900 def get_macvlan_mode_string(self, index):
3901 return self.get_string(self.macvlan_mode_to_string, index)
3902
35848ca0
JF
3903 def get_ifla_gre_string(self, index):
3904 return self.get_string(self.ifla_gre_to_string, index)
3905
3906 def get_ifla_vti_string(self, index):
3907 return self.get_string(self.ifla_vti_to_string, index)
3908
3909 def get_ifla_iptun_string(self, index):
3910 return self.get_string(self.ifla_iptun_to_string, index)
3911
198ded6a
JF
3912 def get_ifla_bond_string(self, index):
3913 return self.get_string(self.ifla_bond_to_string, index)
3914
d486dd0d
JF
3915 def get_ifla_bond_ad_string(self, index):
3916 return self.get_string(self.ifla_bond_ad_to_string, index)
3917
3918 def get_ifla_brport_string(self, index):
3919 return self.get_string(self.ifla_brport_to_string, index)
198ded6a 3920
c4fd4972
JF
3921 def get_ifla_br_string(self, index):
3922 return self.get_string(self.ifla_br_to_string, index)
3923
198ded6a
JF
3924 def get_bridge_vlan_string(self, index):
3925 return self.get_string(self.bridge_vlan_to_string, index)
3926
3927 def get_bridge_flags_string(self, index):
3928 return self.get_string(self.bridge_flags_to_string, index)
3929
3930 def decode_service_header(self):
3931
3932 # Nothing to do if the message did not contain a service header
3933 if self.length == self.header_LEN:
3934 return
3935
3936 (self.family, self.device_type,
3937 self.ifindex,
3938 self.flags,
3939 self.change_mask) = \
3940 unpack(self.PACK, self.msg_data[:self.LEN])
3941
3942 if self.debug:
a61d1777
SE
3943 color = yellow if self.use_color else None
3944 color_start = "\033[%dm" % color if color else ""
3945 color_end = "\033[0m" if color else ""
3946 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
3947
198ded6a
JF
3948 for x in range(0, self.LEN/4):
3949 if self.line_number == 5:
4d4aac88
JF
3950 extra = "Family %s (%s:%d), Device Type %s (%d - %s)" % \
3951 (zfilled_hex(self.family, 2), get_family_str(self.family), self.family,
198ded6a
JF
3952 zfilled_hex(self.device_type, 4), self.device_type, self.get_link_type_string(self.device_type))
3953 elif self.line_number == 6:
3954 extra = "Interface Index %s (%d)" % (zfilled_hex(self.ifindex, 8), self.ifindex)
3955 elif self.line_number == 7:
3956 extra = "Device Flags %s (%s)" % (zfilled_hex(self.flags, 8), self.get_flags_string())
3957 elif self.line_number == 8:
3958 extra = "Change Mask %s" % zfilled_hex(self.change_mask, 8)
3959 else:
3960 extra = "Unexpected line number %d" % self.line_number
3961
3962 start = x * 4
3963 end = start + 4
3964 self.dump_buffer.append(data_to_color_text(self.line_number, color, self.msg_data[start:end], extra))
3965 self.line_number += 1
3966
3967 def is_up(self):
3968 if self.flags & Link.IFF_UP:
3969 return True
3970 return False
3971
3972
3479a0c3
JF
3973class Netconf(Link):
3974 """
3975 RTM_NEWNETCONF - Service Header
3976
3977 0 1
3978 0 1 2 3 4 5 6 7 8
3979 +-+-+-+-+-+-+-+-+
3980 | Family |
3981 +-+-+-+-+-+-+-+-+
3982
3983 RTM_GETNETCONF - Service Header
3984
3985 0 1 2 3
3986 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
3987 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3988 | Family | Reserved | Device Type |
3989 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3990 | Interface Index |
3991 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3992 | Device Flags |
3993 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3994 | Change Mask |
3995 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3996 """
3997 # Netconf attributes
3998 # /usr/include/linux/netconf.h
3999 NETCONFA_UNSPEC = 0
4000 NETCONFA_IFINDEX = 1
4001 NETCONFA_FORWARDING = 2
4002 NETCONFA_RP_FILTER = 3
4003 NETCONFA_MC_FORWARDING = 4
4004 NETCONFA_PROXY_NEIGH = 5
4005 NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN = 6
4006 NETCONFA_INPUT = 7
4007 __NETCONFA_MAX = 8
4008
4009 NETCONFA_MAX = (__NETCONFA_MAX - 1)
4010
4011 NETCONFA_ALL = -1
4012 NETCONFA_IFINDEX_ALL = -1
4013 NETCONFA_IFINDEX_DEFAULT = -2
4014
4015 NETCONF_ATTR_FAMILY = 0x0001
4016 NETCONF_ATTR_IFINDEX = 0x0002
4017 NETCONF_ATTR_RP_FILTER = 0x0004
4018 NETCONF_ATTR_FWDING = 0x0008
4019 NETCONF_ATTR_MC_FWDING = 0x0010
4020 NETCONF_ATTR_PROXY_NEIGH = 0x0020
4021 NETCONF_ATTR_IGNORE_RT_LINKDWN = 0x0040
4022
4023 attribute_to_class = {
4024 NETCONFA_UNSPEC : ('NETCONFA_UNSPEC', AttributeGeneric),
4025 NETCONFA_IFINDEX : ('NETCONFA_IFINDEX', AttributeFourByteValue),
4026 NETCONFA_FORWARDING : ('NETCONFA_FORWARDING', AttributeFourByteValue),
4027 NETCONFA_RP_FILTER : ('NETCONFA_RP_FILTER', AttributeFourByteValue),
4028 NETCONFA_MC_FORWARDING : ('NETCONFA_MC_FORWARDING', AttributeFourByteValue),
4029 NETCONFA_PROXY_NEIGH : ('NETCONFA_PROXY_NEIGH', AttributeFourByteValue),
4030 NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN : ('NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN', AttributeFourByteValue),
4031 NETCONFA_INPUT : ('NETCONFA_INPUT', AttributeFourByteValue),
4032 }
4033
4034 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
4035 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
4036 if msgtype == RTM_GETNETCONF: # same as RTM_GETLINK
4037 self.PACK = 'BxHiII'
4038 self.LEN = calcsize(self.PACK)
4039 elif msgtype == RTM_NEWNETCONF:
4040 self.PACK = 'Bxxx'
4041 self.LEN = calcsize(self.PACK)
4042
4043 def decode_service_header(self):
4044 # Nothing to do if the message did not contain a service header
4045 if self.length == self.header_LEN:
4046 return
4047
4048 if self.msgtype == RTM_GETNETCONF:
4049 super(Netconf, self).decode_service_header()
4050
4051 elif self.msgtype == RTM_NEWNETCONF:
4052 (self.family,) = unpack(self.PACK, self.msg_data[:self.LEN])
4053
4054 if self.debug:
4055 color = yellow if self.use_color else None
4056 color_start = "\033[%dm" % color if color else ""
4057 color_end = "\033[0m" if color else ""
4058 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
4d4aac88 4059 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
4060
4061
198ded6a
JF
4062class Neighbor(NetlinkPacket):
4063 """
4064 Service Header
4065
4066 0 1 2 3
4067 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
4068 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4069 | Family | Reserved1 | Reserved2 |
4070 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4071 | Interface Index |
4072 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4073 | State | Flags | Type |
4074 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4075 """
4076
4077 # Neighbor attributes
4078 # /usr/include/linux/neighbour.h
4079 NDA_UNSPEC = 0x00 # Unknown type
4080 NDA_DST = 0x01 # A neighbour cache network. layer destination address
4081 NDA_LLADDR = 0x02 # A neighbor cache link layer address.
4082 NDA_CACHEINFO = 0x03 # Cache statistics
4083 NDA_PROBES = 0x04
4084 NDA_VLAN = 0x05
4085 NDA_PORT = 0x06
4086 NDA_VNI = 0x07
4087 NDA_IFINDEX = 0x08
4088 NDA_MASTER = 0x09
4089 NDA_LINK_NETNSID = 0x0A
4090
4091 attribute_to_class = {
4092 NDA_UNSPEC : ('NDA_UNSPEC', AttributeGeneric),
4093 NDA_DST : ('NDA_DST', AttributeIPAddress),
4094 NDA_LLADDR : ('NDA_LLADDR', AttributeMACAddress),
9f25ff0d 4095 NDA_CACHEINFO : ('NDA_CACHEINFO', AttributeFourByteList),
198ded6a 4096 NDA_PROBES : ('NDA_PROBES', AttributeFourByteValue),
9f25ff0d 4097 NDA_VLAN : ('NDA_VLAN', AttributeTwoByteValue),
198ded6a 4098 NDA_PORT : ('NDA_PORT', AttributeGeneric),
9f25ff0d
SE
4099 NDA_VNI : ('NDA_VNI', AttributeFourByteValue),
4100 NDA_IFINDEX : ('NDA_IFINDEX', AttributeFourByteValue),
4101 NDA_MASTER : ('NDA_MASTER', AttributeFourByteValue),
198ded6a
JF
4102 NDA_LINK_NETNSID : ('NDA_LINK_NETNSID', AttributeGeneric)
4103 }
4104
4105 # Neighbor flags
4106 # /usr/include/linux/neighbour.h
d486dd0d
JF
4107 NTF_USE = 0x01
4108 NTF_SELF = 0x02
4109 NTF_MASTER = 0x04
4110 NTF_PROXY = 0x08 # A proxy ARP entry
4111 NTF_EXT_LEARNED = 0x10 # neigh entry installed by an external APP
4112 NTF_ROUTER = 0x80 # An IPv6 router
198ded6a
JF
4113
4114 flag_to_string = {
d486dd0d
JF
4115 NTF_USE : 'NTF_USE',
4116 NTF_SELF : 'NTF_SELF',
4117 NTF_MASTER : 'NTF_MASTER',
4118 NTF_PROXY : 'NTF_PROXY',
4119 NTF_EXT_LEARNED : 'NTF_EXT_LEARNED',
4120 NTF_ROUTER : 'NTF_ROUTER'
198ded6a
JF
4121 }
4122
4123 # Neighbor states
4124 # /usr/include/linux/neighbour.h
4125 NUD_NONE = 0x00
4126 NUD_INCOMPLETE = 0x01 # Still attempting to resolve
4127 NUD_REACHABLE = 0x02 # A confirmed working cache entry
4128 NUD_STALE = 0x04 # an expired cache entry
4129 NUD_DELAY = 0x08 # Neighbor no longer reachable. Traffic sent, waiting for confirmatio.
4130 NUD_PROBE = 0x10 # A cache entry that is currently being re-solicited
4131 NUD_FAILED = 0x20 # An invalid cache entry
4132 NUD_NOARP = 0x40 # A device which does not do neighbor discovery(ARP)
4133 NUD_PERMANENT = 0x80 # A static entry
4134
4135 state_to_string = {
4136 NUD_NONE : 'NUD_NONE',
4137 NUD_INCOMPLETE : 'NUD_INCOMPLETE',
4138 NUD_REACHABLE : 'NUD_REACHABLE',
4139 NUD_STALE : 'NUD_STALE',
4140 NUD_DELAY : 'NUD_DELAY',
4141 NUD_PROBE : 'NUD_PROBE',
4142 NUD_FAILED : 'NUD_FAILED',
4143 NUD_NOARP : 'NUD_NOARP',
4144 NUD_PERMANENT : 'NUD_PERMANENT'
4145 }
4146
a61d1777
SE
4147 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
4148 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
198ded6a
JF
4149 self.PACK = 'BxxxiHBB'
4150 self.LEN = calcsize(self.PACK)
4151
4152 def get_state_string(self, index):
4153 return self.get_string(self.state_to_string, index)
4154
d486dd0d
JF
4155 def get_states_string(self, states):
4156 for_string = []
4157
4158 if states & Neighbor.NUD_INCOMPLETE:
4159 for_string.append('NUD_INCOMPLETE')
4160
4161 if states & Neighbor.NUD_REACHABLE:
4162 for_string.append('NUD_REACHABLE')
4163
4164 if states & Neighbor.NUD_STALE:
4165 for_string.append('NUD_STALE')
4166
4167 if states & Neighbor.NUD_DELAY:
4168 for_string.append('NUD_DELAY')
4169
4170 if states & Neighbor.NUD_PROBE:
4171 for_string.append('NUD_PROBE')
4172
4173 if states & Neighbor.NUD_FAILED:
4174 for_string.append('NUD_FAILED')
4175
4176 if states & Neighbor.NUD_NOARP:
4177 for_string.append('NUD_NOARP')
4178
4179 if states & Neighbor.NUD_PERMANENT:
4180 for_string.append('NUD_PERMANENT')
4181
4182 return ', '.join(for_string)
4183
4184 def get_flags_string(self, flags):
4185 for_string = []
4186
4187 if flags & Neighbor.NTF_USE:
4188 for_string.append('NTF_USE')
4189
4190 if flags & Neighbor.NTF_SELF:
4191 for_string.append('NTF_SELF')
4192
4193 if flags & Neighbor.NTF_MASTER:
4194 for_string.append('NTF_MASTER')
4195
4196 if flags & Neighbor.NTF_PROXY:
4197 for_string.append('NTF_PROXY')
4198
4199 if flags & Neighbor.NTF_ROUTER:
4200 for_string.append('NTF_ROUTER')
4201
4202 return ', '.join(for_string)
4203
198ded6a
JF
4204 def decode_service_header(self):
4205
4206 # Nothing to do if the message did not contain a service header
4207 if self.length == self.header_LEN:
4208 return
4209
4210 (self.family,
4211 self.ifindex,
4212 self.state, self.flags, self.neighbor_type) = \
4213 unpack(self.PACK, self.msg_data[:self.LEN])
4214
4215 if self.debug:
a61d1777
SE
4216 color = yellow if self.use_color else None
4217 color_start = "\033[%dm" % color if color else ""
4218 color_end = "\033[0m" if color else ""
4219 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
198ded6a
JF
4220
4221 for x in range(0, self.LEN/4):
4222 if self.line_number == 5:
4d4aac88 4223 extra = "Family %s (%s:%d)" % (zfilled_hex(self.family, 2), get_family_str(self.family), self.family)
198ded6a
JF
4224 elif self.line_number == 6:
4225 extra = "Interface Index %s (%d)" % (zfilled_hex(self.ifindex, 8), self.ifindex)
4226 elif self.line_number == 7:
d486dd0d
JF
4227 extra = "State %s (%d) %s, Flags %s (%s) %s, Type %s (%d)" % \
4228 (zfilled_hex(self.state, 4), self.state, self.get_states_string(self.state),
4229 zfilled_hex(self.flags, 2), self.flags, self.get_flags_string(self.flags),
198ded6a
JF
4230 zfilled_hex(self.neighbor_type, 4), self.neighbor_type)
4231 else:
4232 extra = "Unexpected line number %d" % self.line_number
4233
4234 start = x * 4
4235 end = start + 4
4236 self.dump_buffer.append(data_to_color_text(self.line_number, color, self.msg_data[start:end], extra))
4237 self.line_number += 1
4238
4239
4240class Route(NetlinkPacket):
4241 """
4242 Service Header
4243
4244 0 1 2 3
4245 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
4246 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4247 | Family | Dest length | Src length | TOS |
4248 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4249 | Table ID | Protocol | Scope | Type |
4250 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4251 | Flags |
4252 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4253 """
4254
4255 # Route attributes
4256 # /usr/include/linux/rtnetlink.h
4257 RTA_UNSPEC = 0x00 # Ignored.
4258 RTA_DST = 0x01 # Protocol address for route destination address.
4259 RTA_SRC = 0x02 # Protocol address for route source address.
4260 RTA_IIF = 0x03 # Input interface index.
4261 RTA_OIF = 0x04 # Output interface index.
4262 RTA_GATEWAY = 0x05 # Protocol address for the gateway of the route
4263 RTA_PRIORITY = 0x06 # Priority of broker.
4264 RTA_PREFSRC = 0x07 # Preferred source address in cases where more than one source address could be used.
4265 RTA_METRICS = 0x08 # Route metrics attributed to route and associated protocols(e.g., RTT, initial TCP window, etc.).
4266 RTA_MULTIPATH = 0x09 # Multipath route next hop's attributes.
4267 RTA_PROTOINFO = 0x0A # Firewall based policy routing attribute.
4268 RTA_FLOW = 0x0B # Route realm.
4269 RTA_CACHEINFO = 0x0C # Cached route information.
4270 RTA_SESSION = 0x0D
4271 RTA_MP_ALGO = 0x0E
4272 RTA_TABLE = 0x0F
4273 RTA_MARK = 0x10
ea2bf79d
JF
4274 RTA_MFC_STATS = 0x11
4275 RTA_VIA = 0x12
4276 RTA_NEWDST = 0x13
4277 RTA_PREF = 0x14
4278 RTA_ENCAP_TYPE= 0x15
4279 RTA_ENCAP = 0x16
198ded6a
JF
4280
4281 attribute_to_class = {
4282 RTA_UNSPEC : ('RTA_UNSPEC', AttributeGeneric),
4283 RTA_DST : ('RTA_DST', AttributeIPAddress),
4284 RTA_SRC : ('RTA_SRC', AttributeIPAddress),
4285 RTA_IIF : ('RTA_IIF', AttributeFourByteValue),
4286 RTA_OIF : ('RTA_OIF', AttributeFourByteValue),
4287 RTA_GATEWAY : ('RTA_GATEWAY', AttributeIPAddress),
4288 RTA_PRIORITY : ('RTA_PRIORITY', AttributeFourByteValue),
4289 RTA_PREFSRC : ('RTA_PREFSRC', AttributeIPAddress),
4290 RTA_METRICS : ('RTA_METRICS', AttributeGeneric),
4291 RTA_MULTIPATH : ('RTA_MULTIPATH', AttributeRTA_MULTIPATH),
4292 RTA_PROTOINFO : ('RTA_PROTOINFO', AttributeGeneric),
4293 RTA_FLOW : ('RTA_FLOW', AttributeGeneric),
4294 RTA_CACHEINFO : ('RTA_CACHEINFO', AttributeGeneric),
4295 RTA_SESSION : ('RTA_SESSION', AttributeGeneric),
4296 RTA_MP_ALGO : ('RTA_MP_ALGO', AttributeGeneric),
4297 RTA_TABLE : ('RTA_TABLE', AttributeFourByteValue),
ea2bf79d
JF
4298 RTA_MARK : ('RTA_MARK', AttributeGeneric),
4299 RTA_MFC_STATS : ('RTA_MFC_STATS', AttributeGeneric),
4300 RTA_VIA : ('RTA_VIA', AttributeGeneric),
4301 RTA_NEWDST : ('RTA_NEWDST', AttributeGeneric),
4302 RTA_PREF : ('RTA_PREF', AttributeGeneric),
4303 RTA_ENCAP_TYPE: ('RTA_ENCAP_TYPE', AttributeGeneric),
4304 RTA_ENCAP : ('RTA_ENCAP', AttributeGeneric)
198ded6a
JF
4305 }
4306
4307 # Route tables
4308 # /usr/include/linux/rtnetlink.h
4309 RT_TABLE_UNSPEC = 0x00 # An unspecified routing table
4310 RT_TABLE_COMPAT = 0xFC
4311 RT_TABLE_DEFAULT = 0xFD # The default table
4312 RT_TABLE_MAIN = 0xFE # The main table
4313 RT_TABLE_LOCAL = 0xFF # The local table
4314
4315 table_to_string = {
4316 RT_TABLE_UNSPEC : 'RT_TABLE_UNSPEC',
4317 RT_TABLE_COMPAT : 'RT_TABLE_COMPAT',
4318 RT_TABLE_DEFAULT : 'RT_TABLE_DEFAULT',
4319 RT_TABLE_MAIN : 'RT_TABLE_MAIN',
4320 RT_TABLE_LOCAL : 'RT_TABLE_LOCAL'
4321 }
4322
4323 # Route scope
4324 # /usr/include/linux/rtnetlink.h
4325 RT_SCOPE_UNIVERSE = 0x00 # Global route
4326 RT_SCOPE_SITE = 0xC8 # Interior route in the local autonomous system
4327 RT_SCOPE_LINK = 0xFD # Route on this link
4328 RT_SCOPE_HOST = 0xFE # Route on the local host
4329 RT_SCOPE_NOWHERE = 0xFF # Destination does not exist
4330
4331 scope_to_string = {
4332 RT_SCOPE_UNIVERSE : 'RT_SCOPE_UNIVERSE',
4333 RT_SCOPE_SITE : 'RT_SCOPE_SITE',
4334 RT_SCOPE_LINK : 'RT_SCOPE_LINK',
4335 RT_SCOPE_HOST : 'RT_SCOPE_HOST',
4336 RT_SCOPE_NOWHERE : 'RT_SCOPE_NOWHERE'
4337 }
4338
d486dd0d
JF
4339 # Route scope to string
4340 # iproute2/lib/rt_names.c
4341 rtnl_rtscope_tab = {
4342 RT_SCOPE_UNIVERSE: 'global',
4343 RT_SCOPE_NOWHERE: 'nowhere',
4344 RT_SCOPE_HOST: 'host',
4345 RT_SCOPE_LINK: 'link',
4346 RT_SCOPE_SITE: 'site'
4347 }
4348
198ded6a
JF
4349 # Routing stack
4350 # /usr/include/linux/rtnetlink.h
4351 RT_PROT_UNSPEC = 0x00 # Identifies what/who added the route
4352 RT_PROT_REDIRECT = 0x01 # By an ICMP redirect
4353 RT_PROT_KERNEL = 0x02 # By the kernel
4354 RT_PROT_BOOT = 0x03 # During bootup
4355 RT_PROT_STATIC = 0x04 # By the administrator
4356 RT_PROT_GATED = 0x08 # GateD
4357 RT_PROT_RA = 0x09 # RDISC/ND router advertissements
4358 RT_PROT_MRT = 0x0A # Merit MRT
4359 RT_PROT_ZEBRA = 0x0B # ZEBRA
4360 RT_PROT_BIRD = 0x0C # BIRD
4361 RT_PROT_DNROUTED = 0x0D # DECnet routing daemon
4362 RT_PROT_XORP = 0x0E # XORP
4363 RT_PROT_NTK = 0x0F # Netsukuku
4364 RT_PROT_DHCP = 0x10 # DHCP client
4365 RT_PROT_EXABGP = 0x11 # Exa Networks ExaBGP
4366
4367 prot_to_string = {
4368 RT_PROT_UNSPEC : 'RT_PROT_UNSPEC',
4369 RT_PROT_REDIRECT : 'RT_PROT_REDIRECT',
4370 RT_PROT_KERNEL : 'RT_PROT_KERNEL',
4371 RT_PROT_BOOT : 'RT_PROT_BOOT',
4372 RT_PROT_STATIC : 'RT_PROT_STATIC',
4373 RT_PROT_GATED : 'RT_PROT_GATED',
4374 RT_PROT_RA : 'RT_PROT_RA',
4375 RT_PROT_MRT : 'RT_PROT_MRT',
4376 RT_PROT_ZEBRA : 'RT_PROT_ZEBRA',
4377 RT_PROT_BIRD : 'RT_PROT_BIRD',
4378 RT_PROT_DNROUTED : 'RT_PROT_DNROUTED',
4379 RT_PROT_XORP : 'RT_PROT_XORP',
4380 RT_PROT_NTK : 'RT_PROT_NTK',
4381 RT_PROT_DHCP : 'RT_PROT_DHCP',
4382 RT_PROT_EXABGP : 'RT_PROT_EXABGP'
4383 }
4384
4385 # Route types
4386 # /usr/include/linux/rtnetlink.h
4387 RTN_UNSPEC = 0x00 # Unknown broker.
4388 RTN_UNICAST = 0x01 # A gateway or direct broker.
4389 RTN_LOCAL = 0x02 # A local interface broker.
4390 RTN_BROADCAST = 0x03 # A local broadcast route(sent as a broadcast).
4391 RTN_ANYCAST = 0x04 # An anycast broker.
4392 RTN_MULTICAST = 0x05 # A multicast broker.
4393 RTN_BLACKHOLE = 0x06 # A silent packet dropping broker.
4394 RTN_UNREACHABLE = 0x07 # An unreachable destination. Packets dropped and
4395 # host unreachable ICMPs are sent to the originator.
4396 RTN_PROHIBIT = 0x08 # A packet rejection broker. Packets are dropped and
4397 # communication prohibited ICMPs are sent to the originator.
4398 RTN_THROW = 0x09 # When used with policy routing, continue routing lookup
4399 # in another table. Under normal routing, packets are
4400 # dropped and net unreachable ICMPs are sent to the originator.
4401 RTN_NAT = 0x0A # A network address translation rule.
4402 RTN_XRESOLVE = 0x0B # Refer to an external resolver(not implemented).
4403
4404 rt_type_to_string = {
4405 RTN_UNSPEC : 'RTN_UNSPEC',
4406 RTN_UNICAST : 'RTN_UNICAST',
4407 RTN_LOCAL : 'RTN_LOCAL',
4408 RTN_BROADCAST : 'RTN_BROADCAST',
4409 RTN_ANYCAST : 'RTN_ANYCAST',
4410 RTN_MULTICAST : 'RTN_MULTICAST',
4411 RTN_BLACKHOLE : 'RTN_BLACKHOLE',
4412 RTN_UNREACHABLE : 'RTN_UNREACHABLE',
4413 RTN_PROHIBIT : 'RTN_PROHIBIT',
4414 RTN_THROW : 'RTN_THROW',
4415 RTN_NAT : 'RTN_NAT',
4416 RTN_XRESOLVE : 'RTN_XRESOLVE'
4417 }
4418
4419 # Route flags
4420 # /usr/include/linux/rtnetlink.h
4421 RTM_F_NOTIFY = 0x100 # If the route changes, notify the user
4422 RTM_F_CLONED = 0x200 # Route is cloned from another route
4423 RTM_F_EQUALIZE = 0x400 # Allow randomization of next hop path in multi-path routing(currently not implemented)
4424 RTM_F_PREFIX = 0x800 # Prefix Address
4425
4426 flag_to_string = {
4427 RTM_F_NOTIFY : 'RTM_F_NOTIFY',
4428 RTM_F_CLONED : 'RTM_F_CLONED',
4429 RTM_F_EQUALIZE : 'RTM_F_EQUALIZE',
4430 RTM_F_PREFIX : 'RTM_F_PREFIX'
4431 }
4432
a61d1777
SE
4433 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
4434 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
198ded6a
JF
4435 self.PACK = '=8BI' # or is it 8Bi ?
4436 self.LEN = calcsize(self.PACK)
198ded6a
JF
4437
4438 def get_prefix_string(self):
4439 dst = self.get_attribute_value(self.RTA_DST)
4440
4441 if dst:
4442 return "%s/%d" % (dst, self.src_len)
4443 else:
4444 if self.family == AF_INET:
4445 return "0.0.0.0/0"
4446 elif self.family == AF_INET6:
4447 return "::/0"
4448
4449 def get_protocol_string(self, index=None):
4450 if index is None:
4451 index = self.protocol
4452 return self.get_string(self.prot_to_string, index)
4453
4454 def get_rt_type_string(self, index=None):
4455 if index is None:
4456 index = self.route_type
4457 return self.get_string(self.rt_type_to_string, index)
4458
4459 def get_scope_string(self, index=None):
4460 if index is None:
4461 index = self.scope
4462 return self.get_string(self.scope_to_string, index)
4463
4464 def get_table_id_string(self, index=None):
4465 if index is None:
4466 index = self.table_id
4467 return self.get_string(self.table_to_string, index)
4468
4469 def _get_ifname_from_index(self, ifindex, ifname_by_index):
4470 if ifindex:
4471 ifname = ifname_by_index.get(ifindex)
4472
4473 if ifname is None:
4474 ifname = str(ifindex)
4475 else:
4476 ifname = None
4477
4478 return ifname
4479
4480 def get_nexthops(self, ifname_by_index={}):
4481 nexthop = self.get_attribute_value(self.RTA_GATEWAY)
4482 multipath = self.get_attribute_value(self.RTA_MULTIPATH)
4483 nexthops = []
4484
4485 if nexthop:
4486 rta_oif = self.get_attribute_value(self.RTA_OIF)
4487 ifname = self._get_ifname_from_index(rta_oif, ifname_by_index)
4488 nexthops.append((nexthop, ifname))
4489
4490 elif multipath:
4491 for (nexthop, rtnh_ifindex, rtnh_flags, rtnh_hops) in multipath:
4492 ifname = self._get_ifname_from_index(rtnh_ifindex, ifname_by_index)
4493 nexthops.append((nexthop, ifname))
4494
4495 return nexthops
4496
4497 def get_nexthops_string(self, ifname_by_index={}):
4498 output = []
4499
4500 for (nexthop, ifname) in self.get_nexthops(ifname_by_index):
4501 output.append(" via %s on %s" % (nexthop, ifname))
4502
4503 return ",".join(output)
4504
4505 def decode_service_header(self):
4506
4507 # Nothing to do if the message did not contain a service header
4508 if self.length == self.header_LEN:
4509 return
4510
4511 (self.family, self.src_len, self.dst_len, self.tos,
4512 self.table_id, self.protocol, self.scope, self.route_type,
4513 self.flags) = \
4514 unpack(self.PACK, self.msg_data[:self.LEN])
4515
4516 if self.debug:
a61d1777
SE
4517 color = yellow if self.use_color else None
4518 color_start = "\033[%dm" % color if color else ""
4519 color_end = "\033[0m" if color else ""
4520 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
198ded6a
JF
4521
4522 for x in range(0, self.LEN/4):
4523 if self.line_number == 5:
4d4aac88
JF
4524 extra = "Family %s (%s:%d), Source Length %s (%d), Destination Length %s (%d), TOS %s (%d)" % \
4525 (zfilled_hex(self.family, 2), get_family_str(self.family), self.family,
198ded6a
JF
4526 zfilled_hex(self.src_len, 2), self.src_len,
4527 zfilled_hex(self.dst_len, 2), self.dst_len,
4528 zfilled_hex(self.tos, 2), self.tos)
4529 elif self.line_number == 6:
4530 extra = "Table ID %s (%d - %s), Protocol %s (%d - %s), Scope %s (%d - %s), Type %s (%d - %s)" % \
4531 (zfilled_hex(self.table_id, 2), self.table_id, self.get_table_id_string(),
4532 zfilled_hex(self.protocol, 2), self.protocol, self.get_protocol_string(),
4533 zfilled_hex(self.scope, 2), self.scope, self.get_scope_string(),
4534 zfilled_hex(self.route_type, 2), self.route_type, self.get_rt_type_string())
4535 elif self.line_number == 7:
4536 extra = "Flags %s" % zfilled_hex(self.flags, 8)
4537 else:
4538 extra = "Unexpected line number %d" % self.line_number
4539
4540 start = x * 4
4541 end = start + 4
4542 self.dump_buffer.append(data_to_color_text(self.line_number, color, self.msg_data[start:end], extra))
4543 self.line_number += 1
d486dd0d
JF
4544
4545class Done(NetlinkPacket):
4546 """
4547 NLMSG_DONE
4548
4549 Service Header
4550 0 1 2 3
4551 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
4552 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4553 | TBD |
4554 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4555 """
4556
4557 def __init__(self, msgtype, debug=False, logger=None, use_color=True):
4558 NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
4559 self.PACK = 'i'
4560 self.LEN = calcsize(self.PACK)
4561
4562 def decode_service_header(self):
4563 foo = unpack(self.PACK, self.msg_data[:self.LEN])
4564
4565 if self.debug:
4566 color = yellow if self.use_color else None
4567 color_start = "\033[%dm" % color if color else ""
4568 color_end = "\033[0m" if color else ""
4569 self.dump_buffer.append(" %sService Header%s" % (color_start, color_end))
4570
4571 for x in range(0, self.LEN/4):
4572 extra = ''
4573 start = x * 4
4574 end = start + 4
4575 self.dump_buffer.append(data_to_color_text(self.line_number, color, self.msg_data[start:end], extra))
4576 self.line_number += 1