aboutsummaryrefslogtreecommitdiffstats
path: root/node-admin
diff options
context:
space:
mode:
authorHarald Musum <musum@yahoo-inc.com>2017-01-27 14:51:34 +0100
committerGitHub <noreply@github.com>2017-01-27 14:51:34 +0100
commit76b770820899ef0122cb30181245515c565cbda2 (patch)
treede31bf0e4ebc0c284ac59414533ce3300bbce727 /node-admin
parentd75e79e7af6f98688f12c2fa2333645596b818ca (diff)
parent7985aacf67ee318e022b5d37c003976471be1547 (diff)
Merge pull request #1635 from yahoo/freva/remove-old-scripts
Remove old scripts
Diffstat (limited to 'node-admin')
-rwxr-xr-xnode-admin/scripts/configure-container-networking.py115
-rw-r--r--node-admin/scripts/ipaddress.py2411
-rwxr-xr-xnode-admin/scripts/maintenance.sh10
-rw-r--r--node-admin/scripts/pyroute2/__init__.py95
-rw-r--r--node-admin/scripts/pyroute2/arp.py69
-rw-r--r--node-admin/scripts/pyroute2/common.py288
-rw-r--r--node-admin/scripts/pyroute2/config.py10
-rw-r--r--node-admin/scripts/pyroute2/debugger.py85
-rw-r--r--node-admin/scripts/pyroute2/dhcp/__init__.py300
-rw-r--r--node-admin/scripts/pyroute2/dhcp/dhcp4msg.py60
-rw-r--r--node-admin/scripts/pyroute2/dhcp/dhcp4socket.py135
-rw-r--r--node-admin/scripts/pyroute2/ipdb/__init__.py981
-rw-r--r--node-admin/scripts/pyroute2/ipdb/common.py51
-rw-r--r--node-admin/scripts/pyroute2/ipdb/interface.py709
-rw-r--r--node-admin/scripts/pyroute2/ipdb/linkedset.py134
-rw-r--r--node-admin/scripts/pyroute2/ipdb/route.py354
-rw-r--r--node-admin/scripts/pyroute2/ipdb/transactional.py402
-rw-r--r--node-admin/scripts/pyroute2/iproute.py888
-rw-r--r--node-admin/scripts/pyroute2/ipset.py149
-rw-r--r--node-admin/scripts/pyroute2/iwutil.py355
-rw-r--r--node-admin/scripts/pyroute2/netlink/__init__.py1349
-rw-r--r--node-admin/scripts/pyroute2/netlink/generic/__init__.py74
-rw-r--r--node-admin/scripts/pyroute2/netlink/ipq/__init__.py131
-rw-r--r--node-admin/scripts/pyroute2/netlink/nfnetlink/__init__.py33
-rw-r--r--node-admin/scripts/pyroute2/netlink/nfnetlink/ipset.py77
-rw-r--r--node-admin/scripts/pyroute2/netlink/nl80211/__init__.py609
-rw-r--r--node-admin/scripts/pyroute2/netlink/nlsocket.py856
-rw-r--r--node-admin/scripts/pyroute2/netlink/rtnl/__init__.py156
-rw-r--r--node-admin/scripts/pyroute2/netlink/rtnl/errmsg.py11
-rw-r--r--node-admin/scripts/pyroute2/netlink/rtnl/fibmsg.py60
-rw-r--r--node-admin/scripts/pyroute2/netlink/rtnl/ifaddrmsg.py96
-rw-r--r--node-admin/scripts/pyroute2/netlink/rtnl/ifinfmsg.py1068
-rw-r--r--node-admin/scripts/pyroute2/netlink/rtnl/iprsocket.py164
-rw-r--r--node-admin/scripts/pyroute2/netlink/rtnl/iw_event.py85
-rw-r--r--node-admin/scripts/pyroute2/netlink/rtnl/ndmsg.py61
-rw-r--r--node-admin/scripts/pyroute2/netlink/rtnl/req.py182
-rw-r--r--node-admin/scripts/pyroute2/netlink/rtnl/rtmsg.py90
-rw-r--r--node-admin/scripts/pyroute2/netlink/rtnl/tcmsg.py917
-rw-r--r--node-admin/scripts/pyroute2/netlink/taskstats/__init__.py167
-rw-r--r--node-admin/scripts/pyroute2/netns/__init__.py123
-rw-r--r--node-admin/scripts/pyroute2/netns/nslink.py310
-rw-r--r--node-admin/scripts/pyroute2/netns/process/__init__.py39
-rw-r--r--node-admin/scripts/pyroute2/netns/process/base_p2.py7
-rw-r--r--node-admin/scripts/pyroute2/netns/process/base_p3.py7
-rw-r--r--node-admin/scripts/pyroute2/netns/process/proxy.py163
-rw-r--r--node-admin/scripts/pyroute2/protocols/__init__.py234
-rw-r--r--node-admin/scripts/pyroute2/protocols/rawsocket.py70
-rw-r--r--node-admin/scripts/pyroute2/proxy.py65
48 files changed, 0 insertions, 14805 deletions
diff --git a/node-admin/scripts/configure-container-networking.py b/node-admin/scripts/configure-container-networking.py
deleted file mode 100755
index 2efe0891e00..00000000000
--- a/node-admin/scripts/configure-container-networking.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-# Quick and dirty script to specify the default gateway on docker interface
-
-from __future__ import print_function
-
-import os
-import sys
-
-from pyroute2 import NetNS
-from socket import AF_INET6
-
-def create_directory_ignore_exists(path, permissions):
- if not os.path.isdir(path):
- os.mkdir(path, permissions)
-
-
-def create_symlink_ignore_exists(path_to_point_to, symlink_location):
- if not os.path.islink(symlink_location):
- os.symlink(path_to_point_to, symlink_location)
-
-
-def get_attribute(struct_with_attrs, name):
- try:
- matching_values = [attribute[1] for attribute in struct_with_attrs['attrs'] if attribute[0] == name]
- if len(matching_values) == 0:
- raise RuntimeError("No such attribute: %s" % name)
- elif len(matching_values) != 1:
- raise RuntimeError("Multiple values for attribute %s" %name)
- else:
- return matching_values[0]
- except Exception as e:
- raise RuntimeError("Couldn't find attribute %s for value: %s" % (name, struct_with_attrs), e)
-
-def net_namespace_path(pid):
- return "/host/proc/%d/ns/net" % pid
-
-def get_net_namespace_for_pid(pid):
- net_ns_path = net_namespace_path(pid)
- if not os.path.isfile(net_ns_path):
- raise RuntimeError("No such net namespace %s" % net_ns_path )
- create_directory_ignore_exists("/var/run/netns", 0766)
- create_symlink_ignore_exists(net_ns_path, "/var/run/netns/%d" % pid)
- return NetNS(str(pid))
-
-def index_of_interface_in_namespace(interface_name, namespace):
- interface_index_list = namespace.link_lookup(ifname=interface_name)
- if not interface_index_list:
- return None
- assert len(interface_index_list) == 1
- return interface_index_list[0]
-
-
-def get_default_route(net_namespace, family):
- # route format: {
- # 'family': 2,
- # 'dst_len': 0,
- # 'proto': 3,
- # 'tos': 0,
- # 'event': 'RTM_NEWROUTE',
- # 'header': {
- # 'pid': 43,
- # 'length': 52,
- # 'flags': 2,
- # 'error': None,
- # 'type': 24,
- # 'sequence_number': 255
- # },
- # 'flags': 0,
- # 'attrs': [
- # ['RTA_TABLE', 254],
- # ['RTA_GATEWAY', '172.17.42.1'],
- # ['RTA_OIF', 18]
- # ],
- # 'table': 254,
- # 'src_len': 0,
- # 'type': 1,
- # 'scope': 0
- # }
- default_routes = net_namespace.get_default_routes()
- for route in default_routes:
- if route['family'] == family:
- return route
- raise RuntimeError("Couldn't find default route: " + str(default_routes))
-
-
-# There is a bug in the Docker networking setup which requires us to manually specify the default gateway
-# https://github.com/docker/libnetwork/issues/1443
-def set_docker_gateway_on_docker_interface():
- if len(sys.argv) != 2:
- raise RuntimeError("Usage: %s --fix-docker-gateway <container-pid>" % sys.argv[0])
- try:
- container_pid = int(sys.argv[1])
- except ValueError:
- raise RuntimeError("Container pid must be an integer, got %s" % sys.argv[1])
- host_ns = get_net_namespace_for_pid(1)
- container_ns = get_net_namespace_for_pid(container_pid)
- container_interface_index = index_of_interface_in_namespace(interface_name="eth1", namespace=container_ns)
-
- host_default_route = get_default_route(net_namespace=host_ns, family=AF_INET6)
- host_default_route_gateway = get_attribute(host_default_route, 'RTA_GATEWAY')
- container_ns.route(command="replace", gateway=host_default_route_gateway, index=container_interface_index, family=AF_INET6)
-
-
-# Parse arguments
-flag_fix_docker_gateway = "--fix-docker-gateway"
-fix_docker_gateway = flag_fix_docker_gateway in sys.argv
-if fix_docker_gateway:
- sys.argv.remove(flag_fix_docker_gateway)
-
-if fix_docker_gateway:
- set_docker_gateway_on_docker_interface()
-else:
- raise RuntimeError("Only valid flag is %s, got %s" % (flag_fix_docker_gateway, sys.argv[1])) \ No newline at end of file
diff --git a/node-admin/scripts/ipaddress.py b/node-admin/scripts/ipaddress.py
deleted file mode 100644
index a08eb743285..00000000000
--- a/node-admin/scripts/ipaddress.py
+++ /dev/null
@@ -1,2411 +0,0 @@
-# Copyright 2007 Google Inc.
-# Licensed to PSF under a Contributor Agreement.
-
-"""A fast, lightweight IPv4/IPv6 manipulation library in Python.
-
-This library is used to create/poke/manipulate IPv4 and IPv6 addresses
-and networks.
-
-"""
-
-from __future__ import unicode_literals
-
-
-import itertools
-import struct
-
-__version__ = '1.0.14'
-
-# Compatibility functions
-_compat_int_types = (int,)
-try:
- _compat_int_types = (int, long)
-except NameError:
- pass
-try:
- _compat_str = unicode
-except NameError:
- _compat_str = str
- assert bytes != str
-if b'\0'[0] == 0: # Python 3 semantics
- def _compat_bytes_to_byte_vals(byt):
- return byt
-else:
- def _compat_bytes_to_byte_vals(byt):
- return [struct.unpack(b'!B', b)[0] for b in byt]
-try:
- _compat_int_from_byte_vals = int.from_bytes
-except AttributeError:
- def _compat_int_from_byte_vals(bytvals, endianess):
- assert endianess == 'big'
- res = 0
- for bv in bytvals:
- assert isinstance(bv, _compat_int_types)
- res = (res << 8) + bv
- return res
-
-
-def _compat_to_bytes(intval, length, endianess):
- assert isinstance(intval, _compat_int_types)
- assert endianess == 'big'
- if length == 4:
- if intval < 0 or intval >= 2 ** 32:
- raise struct.error("integer out of range for 'I' format code")
- return struct.pack(b'!I', intval)
- elif length == 16:
- if intval < 0 or intval >= 2 ** 128:
- raise struct.error("integer out of range for 'QQ' format code")
- return struct.pack(b'!QQ', intval >> 64, intval & 0xffffffffffffffff)
- else:
- raise NotImplementedError()
-if hasattr(int, 'bit_length'):
- # Not int.bit_length , since that won't work in 2.7 where long exists
- def _compat_bit_length(i):
- return i.bit_length()
-else:
- def _compat_bit_length(i):
- for res in itertools.count():
- if i >> res == 0:
- return res
-
-
-def _compat_range(start, end, step=1):
- assert step > 0
- i = start
- while i < end:
- yield i
- i += step
-
-
-class _TotalOrderingMixin(object):
- __slots__ = ()
-
- # Helper that derives the other comparison operations from
- # __lt__ and __eq__
- # We avoid functools.total_ordering because it doesn't handle
- # NotImplemented correctly yet (http://bugs.python.org/issue10042)
- def __eq__(self, other):
- raise NotImplementedError
-
- def __ne__(self, other):
- equal = self.__eq__(other)
- if equal is NotImplemented:
- return NotImplemented
- return not equal
-
- def __lt__(self, other):
- raise NotImplementedError
-
- def __le__(self, other):
- less = self.__lt__(other)
- if less is NotImplemented or not less:
- return self.__eq__(other)
- return less
-
- def __gt__(self, other):
- less = self.__lt__(other)
- if less is NotImplemented:
- return NotImplemented
- equal = self.__eq__(other)
- if equal is NotImplemented:
- return NotImplemented
- return not (less or equal)
-
- def __ge__(self, other):
- less = self.__lt__(other)
- if less is NotImplemented:
- return NotImplemented
- return not less
-
-
-IPV4LENGTH = 32
-IPV6LENGTH = 128
-
-
-class AddressValueError(ValueError):
- """A Value Error related to the address."""
-
-
-class NetmaskValueError(ValueError):
- """A Value Error related to the netmask."""
-
-
-def ip_address(address):
- """Take an IP string/int and return an object of the correct type.
-
- Args:
- address: A string or integer, the IP address. Either IPv4 or
- IPv6 addresses may be supplied; integers less than 2**32 will
- be considered to be IPv4 by default.
-
- Returns:
- An IPv4Address or IPv6Address object.
-
- Raises:
- ValueError: if the *address* passed isn't either a v4 or a v6
- address
-
- """
- try:
- return IPv4Address(address)
- except (AddressValueError, NetmaskValueError):
- pass
-
- try:
- return IPv6Address(address)
- except (AddressValueError, NetmaskValueError):
- pass
-
- if isinstance(address, bytes):
- raise AddressValueError(
- '%r does not appear to be an IPv4 or IPv6 address. '
- 'Did you pass in a bytes (str in Python 2) instead of'
- ' a unicode object?' % address)
-
- raise ValueError('%r does not appear to be an IPv4 or IPv6 address' %
- address)
-
-
-def ip_network(address, strict=True):
- """Take an IP string/int and return an object of the correct type.
-
- Args:
- address: A string or integer, the IP network. Either IPv4 or
- IPv6 networks may be supplied; integers less than 2**32 will
- be considered to be IPv4 by default.
-
- Returns:
- An IPv4Network or IPv6Network object.
-
- Raises:
- ValueError: if the string passed isn't either a v4 or a v6
- address. Or if the network has host bits set.
-
- """
- try:
- return IPv4Network(address, strict)
- except (AddressValueError, NetmaskValueError):
- pass
-
- try:
- return IPv6Network(address, strict)
- except (AddressValueError, NetmaskValueError):
- pass
-
- raise ValueError('%r does not appear to be an IPv4 or IPv6 network' %
- address)
-
-
-def ip_interface(address):
- """Take an IP string/int and return an object of the correct type.
-
- Args:
- address: A string or integer, the IP address. Either IPv4 or
- IPv6 addresses may be supplied; integers less than 2**32 will
- be considered to be IPv4 by default.
-
- Returns:
- An IPv4Interface or IPv6Interface object.
-
- Raises:
- ValueError: if the string passed isn't either a v4 or a v6
- address.
-
- Notes:
- The IPv?Interface classes describe an Address on a particular
- Network, so they're basically a combination of both the Address
- and Network classes.
-
- """
- try:
- return IPv4Interface(address)
- except (AddressValueError, NetmaskValueError):
- pass
-
- try:
- return IPv6Interface(address)
- except (AddressValueError, NetmaskValueError):
- pass
-
- raise ValueError('%r does not appear to be an IPv4 or IPv6 interface' %
- address)
-
-
-def v4_int_to_packed(address):
- """Represent an address as 4 packed bytes in network (big-endian) order.
-
- Args:
- address: An integer representation of an IPv4 IP address.
-
- Returns:
- The integer address packed as 4 bytes in network (big-endian) order.
-
- Raises:
- ValueError: If the integer is negative or too large to be an
- IPv4 IP address.
-
- """
- try:
- return _compat_to_bytes(address, 4, 'big')
- except (struct.error, OverflowError):
- raise ValueError("Address negative or too large for IPv4")
-
-
-def v6_int_to_packed(address):
- """Represent an address as 16 packed bytes in network (big-endian) order.
-
- Args:
- address: An integer representation of an IPv6 IP address.
-
- Returns:
- The integer address packed as 16 bytes in network (big-endian) order.
-
- """
- try:
- return _compat_to_bytes(address, 16, 'big')
- except (struct.error, OverflowError):
- raise ValueError("Address negative or too large for IPv6")
-
-
-def _split_optional_netmask(address):
- """Helper to split the netmask and raise AddressValueError if needed"""
- addr = _compat_str(address).split('/')
- if len(addr) > 2:
- raise AddressValueError("Only one '/' permitted in %r" % address)
- return addr
-
-
-def _find_address_range(addresses):
- """Find a sequence of sorted deduplicated IPv#Address.
-
- Args:
- addresses: a list of IPv#Address objects.
-
- Yields:
- A tuple containing the first and last IP addresses in the sequence.
-
- """
- it = iter(addresses)
- first = last = next(it)
- for ip in it:
- if ip._ip != last._ip + 1:
- yield first, last
- first = ip
- last = ip
- yield first, last
-
-
-def _count_righthand_zero_bits(number, bits):
- """Count the number of zero bits on the right hand side.
-
- Args:
- number: an integer.
- bits: maximum number of bits to count.
-
- Returns:
- The number of zero bits on the right hand side of the number.
-
- """
- if number == 0:
- return bits
- return min(bits, _compat_bit_length(~number & (number - 1)))
-
-
-def summarize_address_range(first, last):
- """Summarize a network range given the first and last IP addresses.
-
- Example:
- >>> list(summarize_address_range(IPv4Address('192.0.2.0'),
- ... IPv4Address('192.0.2.130')))
- ... #doctest: +NORMALIZE_WHITESPACE
- [IPv4Network('192.0.2.0/25'), IPv4Network('192.0.2.128/31'),
- IPv4Network('192.0.2.130/32')]
-
- Args:
- first: the first IPv4Address or IPv6Address in the range.
- last: the last IPv4Address or IPv6Address in the range.
-
- Returns:
- An iterator of the summarized IPv(4|6) network objects.
-
- Raise:
- TypeError:
- If the first and last objects are not IP addresses.
- If the first and last objects are not the same version.
- ValueError:
- If the last object is not greater than the first.
- If the version of the first address is not 4 or 6.
-
- """
- if (not (isinstance(first, _BaseAddress) and
- isinstance(last, _BaseAddress))):
- raise TypeError('first and last must be IP addresses, not networks')
- if first.version != last.version:
- raise TypeError("%s and %s are not of the same version" % (
- first, last))
- if first > last:
- raise ValueError('last IP address must be greater than first')
-
- if first.version == 4:
- ip = IPv4Network
- elif first.version == 6:
- ip = IPv6Network
- else:
- raise ValueError('unknown IP version')
-
- ip_bits = first._max_prefixlen
- first_int = first._ip
- last_int = last._ip
- while first_int <= last_int:
- nbits = min(_count_righthand_zero_bits(first_int, ip_bits),
- _compat_bit_length(last_int - first_int + 1) - 1)
- net = ip((first_int, ip_bits - nbits))
- yield net
- first_int += 1 << nbits
- if first_int - 1 == ip._ALL_ONES:
- break
-
-
-def _collapse_addresses_internal(addresses):
- """Loops through the addresses, collapsing concurrent netblocks.
-
- Example:
-
- ip1 = IPv4Network('192.0.2.0/26')
- ip2 = IPv4Network('192.0.2.64/26')
- ip3 = IPv4Network('192.0.2.128/26')
- ip4 = IPv4Network('192.0.2.192/26')
-
- _collapse_addresses_internal([ip1, ip2, ip3, ip4]) ->
- [IPv4Network('192.0.2.0/24')]
-
- This shouldn't be called directly; it is called via
- collapse_addresses([]).
-
- Args:
- addresses: A list of IPv4Network's or IPv6Network's
-
- Returns:
- A list of IPv4Network's or IPv6Network's depending on what we were
- passed.
-
- """
- # First merge
- to_merge = list(addresses)
- subnets = {}
- while to_merge:
- net = to_merge.pop()
- supernet = net.supernet()
- existing = subnets.get(supernet)
- if existing is None:
- subnets[supernet] = net
- elif existing != net:
- # Merge consecutive subnets
- del subnets[supernet]
- to_merge.append(supernet)
- # Then iterate over resulting networks, skipping subsumed subnets
- last = None
- for net in sorted(subnets.values()):
- if last is not None:
- # Since they are sorted,
- # last.network_address <= net.network_address is a given.
- if last.broadcast_address >= net.broadcast_address:
- continue
- yield net
- last = net
-
-
-def collapse_addresses(addresses):
- """Collapse a list of IP objects.
-
- Example:
- collapse_addresses([IPv4Network('192.0.2.0/25'),
- IPv4Network('192.0.2.128/25')]) ->
- [IPv4Network('192.0.2.0/24')]
-
- Args:
- addresses: An iterator of IPv4Network or IPv6Network objects.
-
- Returns:
- An iterator of the collapsed IPv(4|6)Network objects.
-
- Raises:
- TypeError: If passed a list of mixed version objects.
-
- """
- addrs = []
- ips = []
- nets = []
-
- # split IP addresses and networks
- for ip in addresses:
- if isinstance(ip, _BaseAddress):
- if ips and ips[-1]._version != ip._version:
- raise TypeError("%s and %s are not of the same version" % (
- ip, ips[-1]))
- ips.append(ip)
- elif ip._prefixlen == ip._max_prefixlen:
- if ips and ips[-1]._version != ip._version:
- raise TypeError("%s and %s are not of the same version" % (
- ip, ips[-1]))
- try:
- ips.append(ip.ip)
- except AttributeError:
- ips.append(ip.network_address)
- else:
- if nets and nets[-1]._version != ip._version:
- raise TypeError("%s and %s are not of the same version" % (
- ip, nets[-1]))
- nets.append(ip)
-
- # sort and dedup
- ips = sorted(set(ips))
-
- # find consecutive address ranges in the sorted sequence and summarize them
- if ips:
- for first, last in _find_address_range(ips):
- addrs.extend(summarize_address_range(first, last))
-
- return _collapse_addresses_internal(addrs + nets)
-
-
-def get_mixed_type_key(obj):
- """Return a key suitable for sorting between networks and addresses.
-
- Address and Network objects are not sortable by default; they're
- fundamentally different so the expression
-
- IPv4Address('192.0.2.0') <= IPv4Network('192.0.2.0/24')
-
- doesn't make any sense. There are some times however, where you may wish
- to have ipaddress sort these for you anyway. If you need to do this, you
- can use this function as the key= argument to sorted().
-
- Args:
- obj: either a Network or Address object.
- Returns:
- appropriate key.
-
- """
- if isinstance(obj, _BaseNetwork):
- return obj._get_networks_key()
- elif isinstance(obj, _BaseAddress):
- return obj._get_address_key()
- return NotImplemented
-
-
-class _IPAddressBase(_TotalOrderingMixin):
-
- """The mother class."""
-
- __slots__ = ()
-
- @property
- def exploded(self):
- """Return the longhand version of the IP address as a string."""
- return self._explode_shorthand_ip_string()
-
- @property
- def compressed(self):
- """Return the shorthand version of the IP address as a string."""
- return _compat_str(self)
-
- @property
- def reverse_pointer(self):
- """The name of the reverse DNS pointer for the IP address, e.g.:
- >>> ipaddress.ip_address("127.0.0.1").reverse_pointer
- '1.0.0.127.in-addr.arpa'
- >>> ipaddress.ip_address("2001:db8::1").reverse_pointer
- '1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa'
-
- """
- return self._reverse_pointer()
-
- @property
- def version(self):
- msg = '%200s has no version specified' % (type(self),)
- raise NotImplementedError(msg)
-
- def _check_int_address(self, address):
- if address < 0:
- msg = "%d (< 0) is not permitted as an IPv%d address"
- raise AddressValueError(msg % (address, self._version))
- if address > self._ALL_ONES:
- msg = "%d (>= 2**%d) is not permitted as an IPv%d address"
- raise AddressValueError(msg % (address, self._max_prefixlen,
- self._version))
-
- def _check_packed_address(self, address, expected_len):
- address_len = len(address)
- if address_len != expected_len:
- msg = (
- '%r (len %d != %d) is not permitted as an IPv%d address. '
- 'Did you pass in a bytes (str in Python 2) instead of'
- ' a unicode object?'
- )
- raise AddressValueError(msg % (address, address_len,
- expected_len, self._version))
-
- @classmethod
- def _ip_int_from_prefix(cls, prefixlen):
- """Turn the prefix length into a bitwise netmask
-
- Args:
- prefixlen: An integer, the prefix length.
-
- Returns:
- An integer.
-
- """
- return cls._ALL_ONES ^ (cls._ALL_ONES >> prefixlen)
-
- @classmethod
- def _prefix_from_ip_int(cls, ip_int):
- """Return prefix length from the bitwise netmask.
-
- Args:
- ip_int: An integer, the netmask in expanded bitwise format
-
- Returns:
- An integer, the prefix length.
-
- Raises:
- ValueError: If the input intermingles zeroes & ones
- """
- trailing_zeroes = _count_righthand_zero_bits(ip_int,
- cls._max_prefixlen)
- prefixlen = cls._max_prefixlen - trailing_zeroes
- leading_ones = ip_int >> trailing_zeroes
- all_ones = (1 << prefixlen) - 1
- if leading_ones != all_ones:
- byteslen = cls._max_prefixlen // 8
- details = _compat_to_bytes(ip_int, byteslen, 'big')
- msg = 'Netmask pattern %r mixes zeroes & ones'
- raise ValueError(msg % details)
- return prefixlen
-
- @classmethod
- def _report_invalid_netmask(cls, netmask_str):
- msg = '%r is not a valid netmask' % netmask_str
- raise NetmaskValueError(msg)
-
- @classmethod
- def _prefix_from_prefix_string(cls, prefixlen_str):
- """Return prefix length from a numeric string
-
- Args:
- prefixlen_str: The string to be converted
-
- Returns:
- An integer, the prefix length.
-
- Raises:
- NetmaskValueError: If the input is not a valid netmask
- """
- # int allows a leading +/- as well as surrounding whitespace,
- # so we ensure that isn't the case
- if not _BaseV4._DECIMAL_DIGITS.issuperset(prefixlen_str):
- cls._report_invalid_netmask(prefixlen_str)
- try:
- prefixlen = int(prefixlen_str)
- except ValueError:
- cls._report_invalid_netmask(prefixlen_str)
- if not (0 <= prefixlen <= cls._max_prefixlen):
- cls._report_invalid_netmask(prefixlen_str)
- return prefixlen
-
- @classmethod
- def _prefix_from_ip_string(cls, ip_str):
- """Turn a netmask/hostmask string into a prefix length
-
- Args:
- ip_str: The netmask/hostmask to be converted
-
- Returns:
- An integer, the prefix length.
-
- Raises:
- NetmaskValueError: If the input is not a valid netmask/hostmask
- """
- # Parse the netmask/hostmask like an IP address.
- try:
- ip_int = cls._ip_int_from_string(ip_str)
- except AddressValueError:
- cls._report_invalid_netmask(ip_str)
-
- # Try matching a netmask (this would be /1*0*/ as a bitwise regexp).
- # Note that the two ambiguous cases (all-ones and all-zeroes) are
- # treated as netmasks.
- try:
- return cls._prefix_from_ip_int(ip_int)
- except ValueError:
- pass
-
- # Invert the bits, and try matching a /0+1+/ hostmask instead.
- ip_int ^= cls._ALL_ONES
- try:
- return cls._prefix_from_ip_int(ip_int)
- except ValueError:
- cls._report_invalid_netmask(ip_str)
-
- def __reduce__(self):
- return self.__class__, (_compat_str(self),)
-
-
-class _BaseAddress(_IPAddressBase):
-
- """A generic IP object.
-
- This IP class contains the version independent methods which are
- used by single IP addresses.
- """
-
- __slots__ = ()
-
- def __int__(self):
- return self._ip
-
- def __eq__(self, other):
- try:
- return (self._ip == other._ip and
- self._version == other._version)
- except AttributeError:
- return NotImplemented
-
- def __lt__(self, other):
- if not isinstance(other, _IPAddressBase):
- return NotImplemented
- if not isinstance(other, _BaseAddress):
- raise TypeError('%s and %s are not of the same type' % (
- self, other))
- if self._version != other._version:
- raise TypeError('%s and %s are not of the same version' % (
- self, other))
- if self._ip != other._ip:
- return self._ip < other._ip
- return False
-
- # Shorthand for Integer addition and subtraction. This is not
- # meant to ever support addition/subtraction of addresses.
- def __add__(self, other):
- if not isinstance(other, _compat_int_types):
- return NotImplemented
- return self.__class__(int(self) + other)
-
- def __sub__(self, other):
- if not isinstance(other, _compat_int_types):
- return NotImplemented
- return self.__class__(int(self) - other)
-
- def __repr__(self):
- return '%s(%r)' % (self.__class__.__name__, _compat_str(self))
-
- def __str__(self):
- return _compat_str(self._string_from_ip_int(self._ip))
-
- def __hash__(self):
- return hash(hex(int(self._ip)))
-
- def _get_address_key(self):
- return (self._version, self)
-
- def __reduce__(self):
- return self.__class__, (self._ip,)
-
-
-class _BaseNetwork(_IPAddressBase):
-
- """A generic IP network object.
-
- This IP class contains the version independent methods which are
- used by networks.
-
- """
- def __init__(self, address):
- self._cache = {}
-
- def __repr__(self):
- return '%s(%r)' % (self.__class__.__name__, _compat_str(self))
-
- def __str__(self):
- return '%s/%d' % (self.network_address, self.prefixlen)
-
- def hosts(self):
- """Generate Iterator over usable hosts in a network.
-
- This is like __iter__ except it doesn't return the network
- or broadcast addresses.
-
- """
- network = int(self.network_address)
- broadcast = int(self.broadcast_address)
- for x in _compat_range(network + 1, broadcast):
- yield self._address_class(x)
-
- def __iter__(self):
- network = int(self.network_address)
- broadcast = int(self.broadcast_address)
- for x in _compat_range(network, broadcast + 1):
- yield self._address_class(x)
-
- def __getitem__(self, n):
- network = int(self.network_address)
- broadcast = int(self.broadcast_address)
- if n >= 0:
- if network + n > broadcast:
- raise IndexError
- return self._address_class(network + n)
- else:
- n += 1
- if broadcast + n < network:
- raise IndexError
- return self._address_class(broadcast + n)
-
- def __lt__(self, other):
- if not isinstance(other, _IPAddressBase):
- return NotImplemented
- if not isinstance(other, _BaseNetwork):
- raise TypeError('%s and %s are not of the same type' % (
- self, other))
- if self._version != other._version:
- raise TypeError('%s and %s are not of the same version' % (
- self, other))
- if self.network_address != other.network_address:
- return self.network_address < other.network_address
- if self.netmask != other.netmask:
- return self.netmask < other.netmask
- return False
-
- def __eq__(self, other):
- try:
- return (self._version == other._version and
- self.network_address == other.network_address and
- int(self.netmask) == int(other.netmask))
- except AttributeError:
- return NotImplemented
-
- def __hash__(self):
- return hash(int(self.network_address) ^ int(self.netmask))
-
- def __contains__(self, other):
- # always false if one is v4 and the other is v6.
- if self._version != other._version:
- return False
- # dealing with another network.
- if isinstance(other, _BaseNetwork):
- return False
- # dealing with another address
- else:
- # address
- return (int(self.network_address) <= int(other._ip) <=
- int(self.broadcast_address))
-
- def overlaps(self, other):
- """Tell if self is partly contained in other."""
- return self.network_address in other or (
- self.broadcast_address in other or (
- other.network_address in self or (
- other.broadcast_address in self)))
-
- @property
- def broadcast_address(self):
- x = self._cache.get('broadcast_address')
- if x is None:
- x = self._address_class(int(self.network_address) |
- int(self.hostmask))
- self._cache['broadcast_address'] = x
- return x
-
- @property
- def hostmask(self):
- x = self._cache.get('hostmask')
- if x is None:
- x = self._address_class(int(self.netmask) ^ self._ALL_ONES)
- self._cache['hostmask'] = x
- return x
-
- @property
- def with_prefixlen(self):
- return '%s/%d' % (self.network_address, self._prefixlen)
-
- @property
- def with_netmask(self):
- return '%s/%s' % (self.network_address, self.netmask)
-
- @property
- def with_hostmask(self):
- return '%s/%s' % (self.network_address, self.hostmask)
-
- @property
- def num_addresses(self):
- """Number of hosts in the current subnet."""
- return int(self.broadcast_address) - int(self.network_address) + 1
-
- @property
- def _address_class(self):
- # Returning bare address objects (rather than interfaces) allows for
- # more consistent behaviour across the network address, broadcast
- # address and individual host addresses.
- msg = '%200s has no associated address class' % (type(self),)
- raise NotImplementedError(msg)
-
- @property
- def prefixlen(self):
- return self._prefixlen
-
- def address_exclude(self, other):
- """Remove an address from a larger block.
-
- For example:
-
- addr1 = ip_network('192.0.2.0/28')
- addr2 = ip_network('192.0.2.1/32')
- addr1.address_exclude(addr2) =
- [IPv4Network('192.0.2.0/32'), IPv4Network('192.0.2.2/31'),
- IPv4Network('192.0.2.4/30'), IPv4Network('192.0.2.8/29')]
-
- or IPv6:
-
- addr1 = ip_network('2001:db8::1/32')
- addr2 = ip_network('2001:db8::1/128')
- addr1.address_exclude(addr2) =
- [ip_network('2001:db8::1/128'),
- ip_network('2001:db8::2/127'),
- ip_network('2001:db8::4/126'),
- ip_network('2001:db8::8/125'),
- ...
- ip_network('2001:db8:8000::/33')]
-
- Args:
- other: An IPv4Network or IPv6Network object of the same type.
-
- Returns:
- An iterator of the IPv(4|6)Network objects which is self
- minus other.
-
- Raises:
- TypeError: If self and other are of differing address
- versions, or if other is not a network object.
- ValueError: If other is not completely contained by self.
-
- """
- if not self._version == other._version:
- raise TypeError("%s and %s are not of the same version" % (
- self, other))
-
- if not isinstance(other, _BaseNetwork):
- raise TypeError("%s is not a network object" % other)
-
- if not other.subnet_of(self):
- raise ValueError('%s not contained in %s' % (other, self))
- if other == self:
- return
-
- # Make sure we're comparing the network of other.
- other = other.__class__('%s/%s' % (other.network_address,
- other.prefixlen))
-
- s1, s2 = self.subnets()
- while s1 != other and s2 != other:
- if other.subnet_of(s1):
- yield s2
- s1, s2 = s1.subnets()
- elif other.subnet_of(s2):
- yield s1
- s1, s2 = s2.subnets()
- else:
- # If we got here, there's a bug somewhere.
- raise AssertionError('Error performing exclusion: '
- 's1: %s s2: %s other: %s' %
- (s1, s2, other))
- if s1 == other:
- yield s2
- elif s2 == other:
- yield s1
- else:
- # If we got here, there's a bug somewhere.
- raise AssertionError('Error performing exclusion: '
- 's1: %s s2: %s other: %s' %
- (s1, s2, other))
-
- def compare_networks(self, other):
- """Compare two IP objects.
-
- This is only concerned about the comparison of the integer
- representation of the network addresses. This means that the
- host bits aren't considered at all in this method. If you want
- to compare host bits, you can easily enough do a
- 'HostA._ip < HostB._ip'
-
- Args:
- other: An IP object.
-
- Returns:
- If the IP versions of self and other are the same, returns:
-
- -1 if self < other:
- eg: IPv4Network('192.0.2.0/25') < IPv4Network('192.0.2.128/25')
- IPv6Network('2001:db8::1000/124') <
- IPv6Network('2001:db8::2000/124')
- 0 if self == other
- eg: IPv4Network('192.0.2.0/24') == IPv4Network('192.0.2.0/24')
- IPv6Network('2001:db8::1000/124') ==
- IPv6Network('2001:db8::1000/124')
- 1 if self > other
- eg: IPv4Network('192.0.2.128/25') > IPv4Network('192.0.2.0/25')
- IPv6Network('2001:db8::2000/124') >
- IPv6Network('2001:db8::1000/124')
-
- Raises:
- TypeError if the IP versions are different.
-
- """
- # does this need to raise a ValueError?
- if self._version != other._version:
- raise TypeError('%s and %s are not of the same type' % (
- self, other))
- # self._version == other._version below here:
- if self.network_address < other.network_address:
- return -1
- if self.network_address > other.network_address:
- return 1
- # self.network_address == other.network_address below here:
- if self.netmask < other.netmask:
- return -1
- if self.netmask > other.netmask:
- return 1
- return 0
-
- def _get_networks_key(self):
- """Network-only key function.
-
- Returns an object that identifies this address' network and
- netmask. This function is a suitable "key" argument for sorted()
- and list.sort().
-
- """
- return (self._version, self.network_address, self.netmask)
-
- def subnets(self, prefixlen_diff=1, new_prefix=None):
- """The subnets which join to make the current subnet.
-
- In the case that self contains only one IP
- (self._prefixlen == 32 for IPv4 or self._prefixlen == 128
- for IPv6), yield an iterator with just ourself.
-
- Args:
- prefixlen_diff: An integer, the amount the prefix length
- should be increased by. This should not be set if
- new_prefix is also set.
- new_prefix: The desired new prefix length. This must be a
- larger number (smaller prefix) than the existing prefix.
- This should not be set if prefixlen_diff is also set.
-
- Returns:
- An iterator of IPv(4|6) objects.
-
- Raises:
- ValueError: The prefixlen_diff is too small or too large.
- OR
- prefixlen_diff and new_prefix are both set or new_prefix
- is a smaller number than the current prefix (smaller
- number means a larger network)
-
- """
- if self._prefixlen == self._max_prefixlen:
- yield self
- return
-
- if new_prefix is not None:
- if new_prefix < self._prefixlen:
- raise ValueError('new prefix must be longer')
- if prefixlen_diff != 1:
- raise ValueError('cannot set prefixlen_diff and new_prefix')
- prefixlen_diff = new_prefix - self._prefixlen
-
- if prefixlen_diff < 0:
- raise ValueError('prefix length diff must be > 0')
- new_prefixlen = self._prefixlen + prefixlen_diff
-
- if new_prefixlen > self._max_prefixlen:
- raise ValueError(
- 'prefix length diff %d is invalid for netblock %s' % (
- new_prefixlen, self))
-
- start = int(self.network_address)
- end = int(self.broadcast_address)
- step = (int(self.hostmask) + 1) >> prefixlen_diff
- for new_addr in _compat_range(start, end, step):
- current = self.__class__((new_addr, new_prefixlen))
- yield current
-
- def supernet(self, prefixlen_diff=1, new_prefix=None):
- """The supernet containing the current network.
-
- Args:
- prefixlen_diff: An integer, the amount the prefix length of
- the network should be decreased by. For example, given a
- /24 network and a prefixlen_diff of 3, a supernet with a
- /21 netmask is returned.
-
- Returns:
- An IPv4 network object.
-
- Raises:
- ValueError: If self.prefixlen - prefixlen_diff < 0. I.e., you have
- a negative prefix length.
- OR
- If prefixlen_diff and new_prefix are both set or new_prefix is a
- larger number than the current prefix (larger number means a
- smaller network)
-
- """
- if self._prefixlen == 0:
- return self
-
- if new_prefix is not None:
- if new_prefix > self._prefixlen:
- raise ValueError('new prefix must be shorter')
- if prefixlen_diff != 1:
- raise ValueError('cannot set prefixlen_diff and new_prefix')
- prefixlen_diff = self._prefixlen - new_prefix
-
- new_prefixlen = self.prefixlen - prefixlen_diff
- if new_prefixlen < 0:
- raise ValueError(
- 'current prefixlen is %d, cannot have a prefixlen_diff of %d' %
- (self.prefixlen, prefixlen_diff))
- return self.__class__((
- int(self.network_address) & (int(self.netmask) << prefixlen_diff),
- new_prefixlen
- ))
-
- @property
- def is_multicast(self):
- """Test if the address is reserved for multicast use.
-
- Returns:
- A boolean, True if the address is a multicast address.
- See RFC 2373 2.7 for details.
-
- """
- return (self.network_address.is_multicast and
- self.broadcast_address.is_multicast)
-
- def subnet_of(self, other):
- # always false if one is v4 and the other is v6.
- if self._version != other._version:
- return False
- # dealing with another network.
- if (hasattr(other, 'network_address') and
- hasattr(other, 'broadcast_address')):
- return (other.network_address <= self.network_address and
- other.broadcast_address >= self.broadcast_address)
- # dealing with another address
- else:
- raise TypeError('Unable to test subnet containment with element '
- 'of type %s' % type(other))
-
- def supernet_of(self, other):
- # always false if one is v4 and the other is v6.
- if self._version != other._version:
- return False
- # dealing with another network.
- if (hasattr(other, 'network_address') and
- hasattr(other, 'broadcast_address')):
- return (other.network_address >= self.network_address and
- other.broadcast_address <= self.broadcast_address)
- # dealing with another address
- else:
- raise TypeError('Unable to test subnet containment with element '
- 'of type %s' % type(other))
-
- @property
- def is_reserved(self):
- """Test if the address is otherwise IETF reserved.
-
- Returns:
- A boolean, True if the address is within one of the
- reserved IPv6 Network ranges.
-
- """
- return (self.network_address.is_reserved and
- self.broadcast_address.is_reserved)
-
- @property
- def is_link_local(self):
- """Test if the address is reserved for link-local.
-
- Returns:
- A boolean, True if the address is reserved per RFC 4291.
-
- """
- return (self.network_address.is_link_local and
- self.broadcast_address.is_link_local)
-
- @property
- def is_private(self):
- """Test if this address is allocated for private networks.
-
- Returns:
- A boolean, True if the address is reserved per
- iana-ipv4-special-registry or iana-ipv6-special-registry.
-
- """
- return (self.network_address.is_private and
- self.broadcast_address.is_private)
-
- @property
- def is_global(self):
- """Test if this address is allocated for public networks.
-
- Returns:
- A boolean, True if the address is not reserved per
- iana-ipv4-special-registry or iana-ipv6-special-registry.
-
- """
- return not self.is_private
-
- @property
- def is_unspecified(self):
- """Test if the address is unspecified.
-
- Returns:
- A boolean, True if this is the unspecified address as defined in
- RFC 2373 2.5.2.
-
- """
- return (self.network_address.is_unspecified and
- self.broadcast_address.is_unspecified)
-
- @property
- def is_loopback(self):
- """Test if the address is a loopback address.
-
- Returns:
- A boolean, True if the address is a loopback address as defined in
- RFC 2373 2.5.3.
-
- """
- return (self.network_address.is_loopback and
- self.broadcast_address.is_loopback)
-
-
-class _BaseV4(object):
-
- """Base IPv4 object.
-
- The following methods are used by IPv4 objects in both single IP
- addresses and networks.
-
- """
-
- __slots__ = ()
- _version = 4
- # Equivalent to 255.255.255.255 or 32 bits of 1's.
- _ALL_ONES = (2 ** IPV4LENGTH) - 1
- _DECIMAL_DIGITS = frozenset('0123456789')
-
- # the valid octets for host and netmasks. only useful for IPv4.
- _valid_mask_octets = frozenset([255, 254, 252, 248, 240, 224, 192, 128, 0])
-
- _max_prefixlen = IPV4LENGTH
- # There are only a handful of valid v4 netmasks, so we cache them all
- # when constructed (see _make_netmask()).
- _netmask_cache = {}
-
- def _explode_shorthand_ip_string(self):
- return _compat_str(self)
-
- @classmethod
- def _make_netmask(cls, arg):
- """Make a (netmask, prefix_len) tuple from the given argument.
-
- Argument can be:
- - an integer (the prefix length)
- - a string representing the prefix length (e.g. "24")
- - a string representing the prefix netmask (e.g. "255.255.255.0")
- """
- if arg not in cls._netmask_cache:
- if isinstance(arg, _compat_int_types):
- prefixlen = arg
- else:
- try:
- # Check for a netmask in prefix length form
- prefixlen = cls._prefix_from_prefix_string(arg)
- except NetmaskValueError:
- # Check for a netmask or hostmask in dotted-quad form.
- # This may raise NetmaskValueError.
- prefixlen = cls._prefix_from_ip_string(arg)
- netmask = IPv4Address(cls._ip_int_from_prefix(prefixlen))
- cls._netmask_cache[arg] = netmask, prefixlen
- return cls._netmask_cache[arg]
-
- @classmethod
- def _ip_int_from_string(cls, ip_str):
- """Turn the given IP string into an integer for comparison.
-
- Args:
- ip_str: A string, the IP ip_str.
-
- Returns:
- The IP ip_str as an integer.
-
- Raises:
- AddressValueError: if ip_str isn't a valid IPv4 Address.
-
- """
- if not ip_str:
- raise AddressValueError('Address cannot be empty')
-
- octets = ip_str.split('.')
- if len(octets) != 4:
- raise AddressValueError("Expected 4 octets in %r" % ip_str)
-
- try:
- return _compat_int_from_byte_vals(
- map(cls._parse_octet, octets), 'big')
- except ValueError as exc:
- raise AddressValueError("%s in %r" % (exc, ip_str))
-
- @classmethod
- def _parse_octet(cls, octet_str):
- """Convert a decimal octet into an integer.
-
- Args:
- octet_str: A string, the number to parse.
-
- Returns:
- The octet as an integer.
-
- Raises:
- ValueError: if the octet isn't strictly a decimal from [0..255].
-
- """
- if not octet_str:
- raise ValueError("Empty octet not permitted")
- # Whitelist the characters, since int() allows a lot of bizarre stuff.
- if not cls._DECIMAL_DIGITS.issuperset(octet_str):
- msg = "Only decimal digits permitted in %r"
- raise ValueError(msg % octet_str)
- # We do the length check second, since the invalid character error
- # is likely to be more informative for the user
- if len(octet_str) > 3:
- msg = "At most 3 characters permitted in %r"
- raise ValueError(msg % octet_str)
- # Convert to integer (we know digits are legal)
- octet_int = int(octet_str, 10)
- # Any octets that look like they *might* be written in octal,
- # and which don't look exactly the same in both octal and
- # decimal are rejected as ambiguous
- if octet_int > 7 and octet_str[0] == '0':
- msg = "Ambiguous (octal/decimal) value in %r not permitted"
- raise ValueError(msg % octet_str)
- if octet_int > 255:
- raise ValueError("Octet %d (> 255) not permitted" % octet_int)
- return octet_int
-
- @classmethod
- def _string_from_ip_int(cls, ip_int):
- """Turns a 32-bit integer into dotted decimal notation.
-
- Args:
- ip_int: An integer, the IP address.
-
- Returns:
- The IP address as a string in dotted decimal notation.
-
- """
- return '.'.join(_compat_str(struct.unpack(b'!B', b)[0]
- if isinstance(b, bytes)
- else b)
- for b in _compat_to_bytes(ip_int, 4, 'big'))
-
- def _is_hostmask(self, ip_str):
- """Test if the IP string is a hostmask (rather than a netmask).
-
- Args:
- ip_str: A string, the potential hostmask.
-
- Returns:
- A boolean, True if the IP string is a hostmask.
-
- """
- bits = ip_str.split('.')
- try:
- parts = [x for x in map(int, bits) if x in self._valid_mask_octets]
- except ValueError:
- return False
- if len(parts) != len(bits):
- return False
- if parts[0] < parts[-1]:
- return True
- return False
-
- def _reverse_pointer(self):
- """Return the reverse DNS pointer name for the IPv4 address.
-
- This implements the method described in RFC1035 3.5.
-
- """
- reverse_octets = _compat_str(self).split('.')[::-1]
- return '.'.join(reverse_octets) + '.in-addr.arpa'
-
- @property
- def max_prefixlen(self):
- return self._max_prefixlen
-
- @property
- def version(self):
- return self._version
-
-
-class IPv4Address(_BaseV4, _BaseAddress):
-
- """Represent and manipulate single IPv4 Addresses."""
-
- __slots__ = ('_ip', '__weakref__')
-
- def __init__(self, address):
-
- """
- Args:
- address: A string or integer representing the IP
-
- Additionally, an integer can be passed, so
- IPv4Address('192.0.2.1') == IPv4Address(3221225985).
- or, more generally
- IPv4Address(int(IPv4Address('192.0.2.1'))) ==
- IPv4Address('192.0.2.1')
-
- Raises:
- AddressValueError: If ipaddress isn't a valid IPv4 address.
-
- """
- # Efficient constructor from integer.
- if isinstance(address, _compat_int_types):
- self._check_int_address(address)
- self._ip = address
- return
-
- # Constructing from a packed address
- if isinstance(address, bytes):
- self._check_packed_address(address, 4)
- bvs = _compat_bytes_to_byte_vals(address)
- self._ip = _compat_int_from_byte_vals(bvs, 'big')
- return
-
- # Assume input argument to be string or any object representation
- # which converts into a formatted IP string.
- addr_str = _compat_str(address)
- if '/' in addr_str:
- raise AddressValueError("Unexpected '/' in %r" % address)
- self._ip = self._ip_int_from_string(addr_str)
-
- @property
- def packed(self):
- """The binary representation of this address."""
- return v4_int_to_packed(self._ip)
-
- @property
- def is_reserved(self):
- """Test if the address is otherwise IETF reserved.
-
- Returns:
- A boolean, True if the address is within the
- reserved IPv4 Network range.
-
- """
- return self in self._constants._reserved_network
-
- @property
- def is_private(self):
- """Test if this address is allocated for private networks.
-
- Returns:
- A boolean, True if the address is reserved per
- iana-ipv4-special-registry.
-
- """
- return any(self in net for net in self._constants._private_networks)
-
- @property
- def is_multicast(self):
- """Test if the address is reserved for multicast use.
-
- Returns:
- A boolean, True if the address is multicast.
- See RFC 3171 for details.
-
- """
- return self in self._constants._multicast_network
-
- @property
- def is_unspecified(self):
- """Test if the address is unspecified.
-
- Returns:
- A boolean, True if this is the unspecified address as defined in
- RFC 5735 3.
-
- """
- return self == self._constants._unspecified_address
-
- @property
- def is_loopback(self):
- """Test if the address is a loopback address.
-
- Returns:
- A boolean, True if the address is a loopback per RFC 3330.
-
- """
- return self in self._constants._loopback_network
-
- @property
- def is_link_local(self):
- """Test if the address is reserved for link-local.
-
- Returns:
- A boolean, True if the address is link-local per RFC 3927.
-
- """
- return self in self._constants._linklocal_network
-
-
-class IPv4Interface(IPv4Address):
-
- def __init__(self, address):
- if isinstance(address, (bytes, _compat_int_types)):
- IPv4Address.__init__(self, address)
- self.network = IPv4Network(self._ip)
- self._prefixlen = self._max_prefixlen
- return
-
- if isinstance(address, tuple):
- IPv4Address.__init__(self, address[0])
- if len(address) > 1:
- self._prefixlen = int(address[1])
- else:
- self._prefixlen = self._max_prefixlen
-
- self.network = IPv4Network(address, strict=False)
- self.netmask = self.network.netmask
- self.hostmask = self.network.hostmask
- return
-
- addr = _split_optional_netmask(address)
- IPv4Address.__init__(self, addr[0])
-
- self.network = IPv4Network(address, strict=False)
- self._prefixlen = self.network._prefixlen
-
- self.netmask = self.network.netmask
- self.hostmask = self.network.hostmask
-
- def __str__(self):
- return '%s/%d' % (self._string_from_ip_int(self._ip),
- self.network.prefixlen)
-
- def __eq__(self, other):
- address_equal = IPv4Address.__eq__(self, other)
- if not address_equal or address_equal is NotImplemented:
- return address_equal
- try:
- return self.network == other.network
- except AttributeError:
- # An interface with an associated network is NOT the
- # same as an unassociated address. That's why the hash
- # takes the extra info into account.
- return False
-
- def __lt__(self, other):
- address_less = IPv4Address.__lt__(self, other)
- if address_less is NotImplemented:
- return NotImplemented
- try:
- return self.network < other.network
- except AttributeError:
- # We *do* allow addresses and interfaces to be sorted. The
- # unassociated address is considered less than all interfaces.
- return False
-
- def __hash__(self):
- return self._ip ^ self._prefixlen ^ int(self.network.network_address)
-
- __reduce__ = _IPAddressBase.__reduce__
-
- @property
- def ip(self):
- return IPv4Address(self._ip)
-
- @property
- def with_prefixlen(self):
- return '%s/%s' % (self._string_from_ip_int(self._ip),
- self._prefixlen)
-
- @property
- def with_netmask(self):
- return '%s/%s' % (self._string_from_ip_int(self._ip),
- self.netmask)
-
- @property
- def with_hostmask(self):
- return '%s/%s' % (self._string_from_ip_int(self._ip),
- self.hostmask)
-
-
-class IPv4Network(_BaseV4, _BaseNetwork):
-
- """This class represents and manipulates 32-bit IPv4 network + addresses..
-
- Attributes: [examples for IPv4Network('192.0.2.0/27')]
- .network_address: IPv4Address('192.0.2.0')
- .hostmask: IPv4Address('0.0.0.31')
- .broadcast_address: IPv4Address('192.0.2.32')
- .netmask: IPv4Address('255.255.255.224')
- .prefixlen: 27
-
- """
- # Class to use when creating address objects
- _address_class = IPv4Address
-
- def __init__(self, address, strict=True):
-
- """Instantiate a new IPv4 network object.
-
- Args:
- address: A string or integer representing the IP [& network].
- '192.0.2.0/24'
- '192.0.2.0/255.255.255.0'
- '192.0.0.2/0.0.0.255'
- are all functionally the same in IPv4. Similarly,
- '192.0.2.1'
- '192.0.2.1/255.255.255.255'
- '192.0.2.1/32'
- are also functionally equivalent. That is to say, failing to
- provide a subnetmask will create an object with a mask of /32.
-
- If the mask (portion after the / in the argument) is given in
- dotted quad form, it is treated as a netmask if it starts with a
- non-zero field (e.g. /255.0.0.0 == /8) and as a hostmask if it
- starts with a zero field (e.g. 0.255.255.255 == /8), with the
- single exception of an all-zero mask which is treated as a
- netmask == /0. If no mask is given, a default of /32 is used.
-
- Additionally, an integer can be passed, so
- IPv4Network('192.0.2.1') == IPv4Network(3221225985)
- or, more generally
- IPv4Interface(int(IPv4Interface('192.0.2.1'))) ==
- IPv4Interface('192.0.2.1')
-
- Raises:
- AddressValueError: If ipaddress isn't a valid IPv4 address.
- NetmaskValueError: If the netmask isn't valid for
- an IPv4 address.
- ValueError: If strict is True and a network address is not
- supplied.
-
- """
- _BaseNetwork.__init__(self, address)
-
- # Constructing from a packed address or integer
- if isinstance(address, (_compat_int_types, bytes)):
- self.network_address = IPv4Address(address)
- self.netmask, self._prefixlen = self._make_netmask(
- self._max_prefixlen)
- # fixme: address/network test here.
- return
-
- if isinstance(address, tuple):
- if len(address) > 1:
- arg = address[1]
- else:
- # We weren't given an address[1]
- arg = self._max_prefixlen
- self.network_address = IPv4Address(address[0])
- self.netmask, self._prefixlen = self._make_netmask(arg)
- packed = int(self.network_address)
- if packed & int(self.netmask) != packed:
- if strict:
- raise ValueError('%s has host bits set' % self)
- else:
- self.network_address = IPv4Address(packed &
- int(self.netmask))
- return
-
- # Assume input argument to be string or any object representation
- # which converts into a formatted IP prefix string.
- addr = _split_optional_netmask(address)
- self.network_address = IPv4Address(self._ip_int_from_string(addr[0]))
-
- if len(addr) == 2:
- arg = addr[1]
- else:
- arg = self._max_prefixlen
- self.netmask, self._prefixlen = self._make_netmask(arg)
-
- if strict:
- if (IPv4Address(int(self.network_address) & int(self.netmask)) !=
- self.network_address):
- raise ValueError('%s has host bits set' % self)
- self.network_address = IPv4Address(int(self.network_address) &
- int(self.netmask))
-
- if self._prefixlen == (self._max_prefixlen - 1):
- self.hosts = self.__iter__
-
- @property
- def is_global(self):
- """Test if this address is allocated for public networks.
-
- Returns:
- A boolean, True if the address is not reserved per
- iana-ipv4-special-registry.
-
- """
- return (not (self.network_address in IPv4Network('100.64.0.0/10') and
- self.broadcast_address in IPv4Network('100.64.0.0/10')) and
- not self.is_private)
-
-
-class _IPv4Constants(object):
-
- _linklocal_network = IPv4Network('169.254.0.0/16')
-
- _loopback_network = IPv4Network('127.0.0.0/8')
-
- _multicast_network = IPv4Network('224.0.0.0/4')
-
- _private_networks = [
- IPv4Network('0.0.0.0/8'),
- IPv4Network('10.0.0.0/8'),
- IPv4Network('127.0.0.0/8'),
- IPv4Network('169.254.0.0/16'),
- IPv4Network('172.16.0.0/12'),
- IPv4Network('192.0.0.0/29'),
- IPv4Network('192.0.0.170/31'),
- IPv4Network('192.0.2.0/24'),
- IPv4Network('192.168.0.0/16'),
- IPv4Network('198.18.0.0/15'),
- IPv4Network('198.51.100.0/24'),
- IPv4Network('203.0.113.0/24'),
- IPv4Network('240.0.0.0/4'),
- IPv4Network('255.255.255.255/32'),
- ]
-
- _reserved_network = IPv4Network('240.0.0.0/4')
-
- _unspecified_address = IPv4Address('0.0.0.0')
-
-
-IPv4Address._constants = _IPv4Constants
-
-
-class _BaseV6(object):
-
- """Base IPv6 object.
-
- The following methods are used by IPv6 objects in both single IP
- addresses and networks.
-
- """
-
- __slots__ = ()
- _version = 6
- _ALL_ONES = (2 ** IPV6LENGTH) - 1
- _HEXTET_COUNT = 8
- _HEX_DIGITS = frozenset('0123456789ABCDEFabcdef')
- _max_prefixlen = IPV6LENGTH
-
- # There are only a bunch of valid v6 netmasks, so we cache them all
- # when constructed (see _make_netmask()).
- _netmask_cache = {}
-
- @classmethod
- def _make_netmask(cls, arg):
- """Make a (netmask, prefix_len) tuple from the given argument.
-
- Argument can be:
- - an integer (the prefix length)
- - a string representing the prefix length (e.g. "24")
- - a string representing the prefix netmask (e.g. "255.255.255.0")
- """
- if arg not in cls._netmask_cache:
- if isinstance(arg, _compat_int_types):
- prefixlen = arg
- else:
- prefixlen = cls._prefix_from_prefix_string(arg)
- netmask = IPv6Address(cls._ip_int_from_prefix(prefixlen))
- cls._netmask_cache[arg] = netmask, prefixlen
- return cls._netmask_cache[arg]
-
- @classmethod
- def _ip_int_from_string(cls, ip_str):
- """Turn an IPv6 ip_str into an integer.
-
- Args:
- ip_str: A string, the IPv6 ip_str.
-
- Returns:
- An int, the IPv6 address
-
- Raises:
- AddressValueError: if ip_str isn't a valid IPv6 Address.
-
- """
- if not ip_str:
- raise AddressValueError('Address cannot be empty')
-
- parts = ip_str.split(':')
-
- # An IPv6 address needs at least 2 colons (3 parts).
- _min_parts = 3
- if len(parts) < _min_parts:
- msg = "At least %d parts expected in %r" % (_min_parts, ip_str)
- raise AddressValueError(msg)
-
- # If the address has an IPv4-style suffix, convert it to hexadecimal.
- if '.' in parts[-1]:
- try:
- ipv4_int = IPv4Address(parts.pop())._ip
- except AddressValueError as exc:
- raise AddressValueError("%s in %r" % (exc, ip_str))
- parts.append('%x' % ((ipv4_int >> 16) & 0xFFFF))
- parts.append('%x' % (ipv4_int & 0xFFFF))
-
- # An IPv6 address can't have more than 8 colons (9 parts).
- # The extra colon comes from using the "::" notation for a single
- # leading or trailing zero part.
- _max_parts = cls._HEXTET_COUNT + 1
- if len(parts) > _max_parts:
- msg = "At most %d colons permitted in %r" % (
- _max_parts - 1, ip_str)
- raise AddressValueError(msg)
-
- # Disregarding the endpoints, find '::' with nothing in between.
- # This indicates that a run of zeroes has been skipped.
- skip_index = None
- for i in _compat_range(1, len(parts) - 1):
- if not parts[i]:
- if skip_index is not None:
- # Can't have more than one '::'
- msg = "At most one '::' permitted in %r" % ip_str
- raise AddressValueError(msg)
- skip_index = i
-
- # parts_hi is the number of parts to copy from above/before the '::'
- # parts_lo is the number of parts to copy from below/after the '::'
- if skip_index is not None:
- # If we found a '::', then check if it also covers the endpoints.
- parts_hi = skip_index
- parts_lo = len(parts) - skip_index - 1
- if not parts[0]:
- parts_hi -= 1
- if parts_hi:
- msg = "Leading ':' only permitted as part of '::' in %r"
- raise AddressValueError(msg % ip_str) # ^: requires ^::
- if not parts[-1]:
- parts_lo -= 1
- if parts_lo:
- msg = "Trailing ':' only permitted as part of '::' in %r"
- raise AddressValueError(msg % ip_str) # :$ requires ::$
- parts_skipped = cls._HEXTET_COUNT - (parts_hi + parts_lo)
- if parts_skipped < 1:
- msg = "Expected at most %d other parts with '::' in %r"
- raise AddressValueError(msg % (cls._HEXTET_COUNT - 1, ip_str))
- else:
- # Otherwise, allocate the entire address to parts_hi. The
- # endpoints could still be empty, but _parse_hextet() will check
- # for that.
- if len(parts) != cls._HEXTET_COUNT:
- msg = "Exactly %d parts expected without '::' in %r"
- raise AddressValueError(msg % (cls._HEXTET_COUNT, ip_str))
- if not parts[0]:
- msg = "Leading ':' only permitted as part of '::' in %r"
- raise AddressValueError(msg % ip_str) # ^: requires ^::
- if not parts[-1]:
- msg = "Trailing ':' only permitted as part of '::' in %r"
- raise AddressValueError(msg % ip_str) # :$ requires ::$
- parts_hi = len(parts)
- parts_lo = 0
- parts_skipped = 0
-
- try:
- # Now, parse the hextets into a 128-bit integer.
- ip_int = 0
- for i in range(parts_hi):
- ip_int <<= 16
- ip_int |= cls._parse_hextet(parts[i])
- ip_int <<= 16 * parts_skipped
- for i in range(-parts_lo, 0):
- ip_int <<= 16
- ip_int |= cls._parse_hextet(parts[i])
- return ip_int
- except ValueError as exc:
- raise AddressValueError("%s in %r" % (exc, ip_str))
-
- @classmethod
- def _parse_hextet(cls, hextet_str):
- """Convert an IPv6 hextet string into an integer.
-
- Args:
- hextet_str: A string, the number to parse.
-
- Returns:
- The hextet as an integer.
-
- Raises:
- ValueError: if the input isn't strictly a hex number from
- [0..FFFF].
-
- """
- # Whitelist the characters, since int() allows a lot of bizarre stuff.
- if not cls._HEX_DIGITS.issuperset(hextet_str):
- raise ValueError("Only hex digits permitted in %r" % hextet_str)
- # We do the length check second, since the invalid character error
- # is likely to be more informative for the user
- if len(hextet_str) > 4:
- msg = "At most 4 characters permitted in %r"
- raise ValueError(msg % hextet_str)
- # Length check means we can skip checking the integer value
- return int(hextet_str, 16)
-
- @classmethod
- def _compress_hextets(cls, hextets):
- """Compresses a list of hextets.
-
- Compresses a list of strings, replacing the longest continuous
- sequence of "0" in the list with "" and adding empty strings at
- the beginning or at the end of the string such that subsequently
- calling ":".join(hextets) will produce the compressed version of
- the IPv6 address.
-
- Args:
- hextets: A list of strings, the hextets to compress.
-
- Returns:
- A list of strings.
-
- """
- best_doublecolon_start = -1
- best_doublecolon_len = 0
- doublecolon_start = -1
- doublecolon_len = 0
- for index, hextet in enumerate(hextets):
- if hextet == '0':
- doublecolon_len += 1
- if doublecolon_start == -1:
- # Start of a sequence of zeros.
- doublecolon_start = index
- if doublecolon_len > best_doublecolon_len:
- # This is the longest sequence of zeros so far.
- best_doublecolon_len = doublecolon_len
- best_doublecolon_start = doublecolon_start
- else:
- doublecolon_len = 0
- doublecolon_start = -1
-
- if best_doublecolon_len > 1:
- best_doublecolon_end = (best_doublecolon_start +
- best_doublecolon_len)
- # For zeros at the end of the address.
- if best_doublecolon_end == len(hextets):
- hextets += ['']
- hextets[best_doublecolon_start:best_doublecolon_end] = ['']
- # For zeros at the beginning of the address.
- if best_doublecolon_start == 0:
- hextets = [''] + hextets
-
- return hextets
-
- @classmethod
- def _string_from_ip_int(cls, ip_int=None):
- """Turns a 128-bit integer into hexadecimal notation.
-
- Args:
- ip_int: An integer, the IP address.
-
- Returns:
- A string, the hexadecimal representation of the address.
-
- Raises:
- ValueError: The address is bigger than 128 bits of all ones.
-
- """
- if ip_int is None:
- ip_int = int(cls._ip)
-
- if ip_int > cls._ALL_ONES:
- raise ValueError('IPv6 address is too large')
-
- hex_str = '%032x' % ip_int
- hextets = ['%x' % int(hex_str[x:x + 4], 16) for x in range(0, 32, 4)]
-
- hextets = cls._compress_hextets(hextets)
- return ':'.join(hextets)
-
- def _explode_shorthand_ip_string(self):
- """Expand a shortened IPv6 address.
-
- Args:
- ip_str: A string, the IPv6 address.
-
- Returns:
- A string, the expanded IPv6 address.
-
- """
- if isinstance(self, IPv6Network):
- ip_str = _compat_str(self.network_address)
- elif isinstance(self, IPv6Interface):
- ip_str = _compat_str(self.ip)
- else:
- ip_str = _compat_str(self)
-
- ip_int = self._ip_int_from_string(ip_str)
- hex_str = '%032x' % ip_int
- parts = [hex_str[x:x + 4] for x in range(0, 32, 4)]
- if isinstance(self, (_BaseNetwork, IPv6Interface)):
- return '%s/%d' % (':'.join(parts), self._prefixlen)
- return ':'.join(parts)
-
- def _reverse_pointer(self):
- """Return the reverse DNS pointer name for the IPv6 address.
-
- This implements the method described in RFC3596 2.5.
-
- """
- reverse_chars = self.exploded[::-1].replace(':', '')
- return '.'.join(reverse_chars) + '.ip6.arpa'
-
- @property
- def max_prefixlen(self):
- return self._max_prefixlen
-
- @property
- def version(self):
- return self._version
-
-
-class IPv6Address(_BaseV6, _BaseAddress):
-
- """Represent and manipulate single IPv6 Addresses."""
-
- __slots__ = ('_ip', '__weakref__')
-
- def __init__(self, address):
- """Instantiate a new IPv6 address object.
-
- Args:
- address: A string or integer representing the IP
-
- Additionally, an integer can be passed, so
- IPv6Address('2001:db8::') ==
- IPv6Address(42540766411282592856903984951653826560)
- or, more generally
- IPv6Address(int(IPv6Address('2001:db8::'))) ==
- IPv6Address('2001:db8::')
-
- Raises:
- AddressValueError: If address isn't a valid IPv6 address.
-
- """
- # Efficient constructor from integer.
- if isinstance(address, _compat_int_types):
- self._check_int_address(address)
- self._ip = address
- return
-
- # Constructing from a packed address
- if isinstance(address, bytes):
- self._check_packed_address(address, 16)
- bvs = _compat_bytes_to_byte_vals(address)
- self._ip = _compat_int_from_byte_vals(bvs, 'big')
- return
-
- # Assume input argument to be string or any object representation
- # which converts into a formatted IP string.
- addr_str = _compat_str(address)
- if '/' in addr_str:
- raise AddressValueError("Unexpected '/' in %r" % address)
- self._ip = self._ip_int_from_string(addr_str)
-
- @property
- def packed(self):
- """The binary representation of this address."""
- return v6_int_to_packed(self._ip)
-
- @property
- def is_multicast(self):
- """Test if the address is reserved for multicast use.
-
- Returns:
- A boolean, True if the address is a multicast address.
- See RFC 2373 2.7 for details.
-
- """
- return self in self._constants._multicast_network
-
- @property
- def is_reserved(self):
- """Test if the address is otherwise IETF reserved.
-
- Returns:
- A boolean, True if the address is within one of the
- reserved IPv6 Network ranges.
-
- """
- return any(self in x for x in self._constants._reserved_networks)
-
- @property
- def is_link_local(self):
- """Test if the address is reserved for link-local.
-
- Returns:
- A boolean, True if the address is reserved per RFC 4291.
-
- """
- return self in self._constants._linklocal_network
-
- @property
- def is_site_local(self):
- """Test if the address is reserved for site-local.
-
- Note that the site-local address space has been deprecated by RFC 3879.
- Use is_private to test if this address is in the space of unique local
- addresses as defined by RFC 4193.
-
- Returns:
- A boolean, True if the address is reserved per RFC 3513 2.5.6.
-
- """
- return self in self._constants._sitelocal_network
-
- @property
- def is_private(self):
- """Test if this address is allocated for private networks.
-
- Returns:
- A boolean, True if the address is reserved per
- iana-ipv6-special-registry.
-
- """
- return any(self in net for net in self._constants._private_networks)
-
- @property
- def is_global(self):
- """Test if this address is allocated for public networks.
-
- Returns:
- A boolean, true if the address is not reserved per
- iana-ipv6-special-registry.
-
- """
- return not self.is_private
-
- @property
- def is_unspecified(self):
- """Test if the address is unspecified.
-
- Returns:
- A boolean, True if this is the unspecified address as defined in
- RFC 2373 2.5.2.
-
- """
- return self._ip == 0
-
- @property
- def is_loopback(self):
- """Test if the address is a loopback address.
-
- Returns:
- A boolean, True if the address is a loopback address as defined in
- RFC 2373 2.5.3.
-
- """
- return self._ip == 1
-
- @property
- def ipv4_mapped(self):
- """Return the IPv4 mapped address.
-
- Returns:
- If the IPv6 address is a v4 mapped address, return the
- IPv4 mapped address. Return None otherwise.
-
- """
- if (self._ip >> 32) != 0xFFFF:
- return None
- return IPv4Address(self._ip & 0xFFFFFFFF)
-
- @property
- def teredo(self):
- """Tuple of embedded teredo IPs.
-
- Returns:
- Tuple of the (server, client) IPs or None if the address
- doesn't appear to be a teredo address (doesn't start with
- 2001::/32)
-
- """
- if (self._ip >> 96) != 0x20010000:
- return None
- return (IPv4Address((self._ip >> 64) & 0xFFFFFFFF),
- IPv4Address(~self._ip & 0xFFFFFFFF))
-
- @property
- def sixtofour(self):
- """Return the IPv4 6to4 embedded address.
-
- Returns:
- The IPv4 6to4-embedded address if present or None if the
- address doesn't appear to contain a 6to4 embedded address.
-
- """
- if (self._ip >> 112) != 0x2002:
- return None
- return IPv4Address((self._ip >> 80) & 0xFFFFFFFF)
-
-
-class IPv6Interface(IPv6Address):
-
- def __init__(self, address):
- if isinstance(address, (bytes, _compat_int_types)):
- IPv6Address.__init__(self, address)
- self.network = IPv6Network(self._ip)
- self._prefixlen = self._max_prefixlen
- return
- if isinstance(address, tuple):
- IPv6Address.__init__(self, address[0])
- if len(address) > 1:
- self._prefixlen = int(address[1])
- else:
- self._prefixlen = self._max_prefixlen
- self.network = IPv6Network(address, strict=False)
- self.netmask = self.network.netmask
- self.hostmask = self.network.hostmask
- return
-
- addr = _split_optional_netmask(address)
- IPv6Address.__init__(self, addr[0])
- self.network = IPv6Network(address, strict=False)
- self.netmask = self.network.netmask
- self._prefixlen = self.network._prefixlen
- self.hostmask = self.network.hostmask
-
- def __str__(self):
- return '%s/%d' % (self._string_from_ip_int(self._ip),
- self.network.prefixlen)
-
- def __eq__(self, other):
- address_equal = IPv6Address.__eq__(self, other)
- if not address_equal or address_equal is NotImplemented:
- return address_equal
- try:
- return self.network == other.network
- except AttributeError:
- # An interface with an associated network is NOT the
- # same as an unassociated address. That's why the hash
- # takes the extra info into account.
- return False
-
- def __lt__(self, other):
- address_less = IPv6Address.__lt__(self, other)
- if address_less is NotImplemented:
- return NotImplemented
- try:
- return self.network < other.network
- except AttributeError:
- # We *do* allow addresses and interfaces to be sorted. The
- # unassociated address is considered less than all interfaces.
- return False
-
- def __hash__(self):
- return self._ip ^ self._prefixlen ^ int(self.network.network_address)
-
- __reduce__ = _IPAddressBase.__reduce__
-
- @property
- def ip(self):
- return IPv6Address(self._ip)
-
- @property
- def with_prefixlen(self):
- return '%s/%s' % (self._string_from_ip_int(self._ip),
- self._prefixlen)
-
- @property
- def with_netmask(self):
- return '%s/%s' % (self._string_from_ip_int(self._ip),
- self.netmask)
-
- @property
- def with_hostmask(self):
- return '%s/%s' % (self._string_from_ip_int(self._ip),
- self.hostmask)
-
- @property
- def is_unspecified(self):
- return self._ip == 0 and self.network.is_unspecified
-
- @property
- def is_loopback(self):
- return self._ip == 1 and self.network.is_loopback
-
-
-class IPv6Network(_BaseV6, _BaseNetwork):
-
- """This class represents and manipulates 128-bit IPv6 networks.
-
- Attributes: [examples for IPv6('2001:db8::1000/124')]
- .network_address: IPv6Address('2001:db8::1000')
- .hostmask: IPv6Address('::f')
- .broadcast_address: IPv6Address('2001:db8::100f')
- .netmask: IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0')
- .prefixlen: 124
-
- """
-
- # Class to use when creating address objects
- _address_class = IPv6Address
-
- def __init__(self, address, strict=True):
- """Instantiate a new IPv6 Network object.
-
- Args:
- address: A string or integer representing the IPv6 network or the
- IP and prefix/netmask.
- '2001:db8::/128'
- '2001:db8:0000:0000:0000:0000:0000:0000/128'
- '2001:db8::'
- are all functionally the same in IPv6. That is to say,
- failing to provide a subnetmask will create an object with
- a mask of /128.
-
- Additionally, an integer can be passed, so
- IPv6Network('2001:db8::') ==
- IPv6Network(42540766411282592856903984951653826560)
- or, more generally
- IPv6Network(int(IPv6Network('2001:db8::'))) ==
- IPv6Network('2001:db8::')
-
- strict: A boolean. If true, ensure that we have been passed
- A true network address, eg, 2001:db8::1000/124 and not an
- IP address on a network, eg, 2001:db8::1/124.
-
- Raises:
- AddressValueError: If address isn't a valid IPv6 address.
- NetmaskValueError: If the netmask isn't valid for
- an IPv6 address.
- ValueError: If strict was True and a network address was not
- supplied.
-
- """
- _BaseNetwork.__init__(self, address)
-
- # Efficient constructor from integer or packed address
- if isinstance(address, (bytes, _compat_int_types)):
- self.network_address = IPv6Address(address)
- self.netmask, self._prefixlen = self._make_netmask(
- self._max_prefixlen)
- return
-
- if isinstance(address, tuple):
- if len(address) > 1:
- arg = address[1]
- else:
- arg = self._max_prefixlen
- self.netmask, self._prefixlen = self._make_netmask(arg)
- self.network_address = IPv6Address(address[0])
- packed = int(self.network_address)
- if packed & int(self.netmask) != packed:
- if strict:
- raise ValueError('%s has host bits set' % self)
- else:
- self.network_address = IPv6Address(packed &
- int(self.netmask))
- return
-
- # Assume input argument to be string or any object representation
- # which converts into a formatted IP prefix string.
- addr = _split_optional_netmask(address)
-
- self.network_address = IPv6Address(self._ip_int_from_string(addr[0]))
-
- if len(addr) == 2:
- arg = addr[1]
- else:
- arg = self._max_prefixlen
- self.netmask, self._prefixlen = self._make_netmask(arg)
-
- if strict:
- if (IPv6Address(int(self.network_address) & int(self.netmask)) !=
- self.network_address):
- raise ValueError('%s has host bits set' % self)
- self.network_address = IPv6Address(int(self.network_address) &
- int(self.netmask))
-
- if self._prefixlen == (self._max_prefixlen - 1):
- self.hosts = self.__iter__
-
- def hosts(self):
- """Generate Iterator over usable hosts in a network.
-
- This is like __iter__ except it doesn't return the
- Subnet-Router anycast address.
-
- """
- network = int(self.network_address)
- broadcast = int(self.broadcast_address)
- for x in _compat_range(network + 1, broadcast + 1):
- yield self._address_class(x)
-
- @property
- def is_site_local(self):
- """Test if the address is reserved for site-local.
-
- Note that the site-local address space has been deprecated by RFC 3879.
- Use is_private to test if this address is in the space of unique local
- addresses as defined by RFC 4193.
-
- Returns:
- A boolean, True if the address is reserved per RFC 3513 2.5.6.
-
- """
- return (self.network_address.is_site_local and
- self.broadcast_address.is_site_local)
-
-
-class _IPv6Constants(object):
-
- _linklocal_network = IPv6Network('fe80::/10')
-
- _multicast_network = IPv6Network('ff00::/8')
-
- _private_networks = [
- IPv6Network('::1/128'),
- IPv6Network('::/128'),
- IPv6Network('::ffff:0:0/96'),
- IPv6Network('100::/64'),
- IPv6Network('2001::/23'),
- IPv6Network('2001:2::/48'),
- IPv6Network('2001:db8::/32'),
- IPv6Network('2001:10::/28'),
- IPv6Network('fc00::/7'),
- IPv6Network('fe80::/10'),
- ]
-
- _reserved_networks = [
- IPv6Network('::/8'), IPv6Network('100::/8'),
- IPv6Network('200::/7'), IPv6Network('400::/6'),
- IPv6Network('800::/5'), IPv6Network('1000::/4'),
- IPv6Network('4000::/3'), IPv6Network('6000::/3'),
- IPv6Network('8000::/3'), IPv6Network('A000::/3'),
- IPv6Network('C000::/3'), IPv6Network('E000::/4'),
- IPv6Network('F000::/5'), IPv6Network('F800::/6'),
- IPv6Network('FE00::/9'),
- ]
-
- _sitelocal_network = IPv6Network('fec0::/10')
-
-
-IPv6Address._constants = _IPv6Constants
diff --git a/node-admin/scripts/maintenance.sh b/node-admin/scripts/maintenance.sh
deleted file mode 100755
index 1a3b7fcd4a9..00000000000
--- a/node-admin/scripts/maintenance.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-
-if [ -z "$CLASSPATH" ]; then
- CLASSPATH=/home/y/lib/jars/node-admin-maintenance-jar-with-dependencies.jar:/home/y/lib/jars/docker-api-jar-with-dependencies.jar:/home/y/lib/jars/vespalog.jar:/home/y/lib/jars/vespajlib.jar
-fi
-
-java \
- -cp $CLASSPATH \
- com.yahoo.vespa.hosted.node.maintenance.Maintainer "$@" \ No newline at end of file
diff --git a/node-admin/scripts/pyroute2/__init__.py b/node-admin/scripts/pyroute2/__init__.py
deleted file mode 100644
index 014651fccf9..00000000000
--- a/node-admin/scripts/pyroute2/__init__.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-##
-# Defer all root imports
-#
-# This allows to safely import config, change it, and
-# only after that actually run imports, though the
-# import statement can be on the top of the file
-#
-# Viva PEP8, morituri te salutant!
-#
-# Surely, you still can import modules directly from their
-# places, like `from pyroute2.iproute import IPRoute`
-##
-__all__ = []
-_modules = {'IPRoute': 'pyroute2.iproute',
- 'IPSet': 'pyroute2.ipset',
- 'IPDB': 'pyroute2.ipdb',
- 'IW': 'pyroute2.iwutil',
- 'NetNS': 'pyroute2.netns.nslink',
- 'NSPopen': 'pyroute2.netns.process.proxy',
- 'IPRSocket': 'pyroute2.netlink.rtnl.iprsocket',
- 'TaskStats': 'pyroute2.netlink.taskstats',
- 'NL80211': 'pyroute2.netlink.nl80211',
- 'IPQSocket': 'pyroute2.netlink.ipq',
- 'GenericNetlinkSocket': 'pyroute2.netlink.generic',
- 'NetlinkError': 'pyroute2.netlink'}
-
-_DISCLAIMER = '''\n\nNotice:\n
-This is a proxy class. To read full docs, please run
-the `help()` method on the instance instead.
-
-Usage of the proxy allows to postpone the module load,
-thus providing a safe way to substitute base classes,
-if it is required. More details see in the `pyroute2.config`
-module.
-\n'''
-
-
-class _ProxyMeta(type):
- '''
- All this metaclass alchemy is implemented to provide a
- reasonable, though not exhaustive documentation on the
- proxy classes.
- '''
-
- def __init__(cls, name, bases, dct):
-
- class doc(str):
- def __repr__(self):
- return repr(cls.proxy['doc'])
-
- def __str__(self):
- return str(cls.proxy['doc'])
-
- def expandtabs(self, ts=4):
- return cls.proxy['doc'].expandtabs(ts)
-
- class proxy(object):
- def __init__(self):
- self.target = {}
-
- def __getitem__(self, key):
- if not self.target:
- module = __import__(_modules[cls.name],
- globals(),
- locals(),
- [cls.name], 0)
- self.target['constructor'] = getattr(module, cls.name)
- self.target['doc'] = self.target['constructor'].__doc__
- try:
- self.target['doc'] += _DISCLAIMER
- except TypeError:
- # ignore cases, when __doc__ is not a string, e.g. None
- pass
- return self.target[key]
-
- def __call__(self, *argv, **kwarg):
- '''
- Actually load the module and call the constructor.
- '''
- return self.proxy['constructor'](*argv, **kwarg)
-
- cls.name = name
- cls.proxy = proxy()
- cls.__call__ = __call__
- cls.__doc__ = doc()
-
- super(_ProxyMeta, cls).__init__(name, bases, dct)
-
-
-for name in _modules:
-
- f = _ProxyMeta(name, (), {})()
- globals()[name] = f
- __all__.append(name)
diff --git a/node-admin/scripts/pyroute2/arp.py b/node-admin/scripts/pyroute2/arp.py
deleted file mode 100644
index aaa83c7503c..00000000000
--- a/node-admin/scripts/pyroute2/arp.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-from pyroute2.common import map_namespace
-
-# ARP protocol HARDWARE identifiers.
-ARPHRD_NETROM = 0 # from KA9Q: NET/ROM pseudo
-ARPHRD_ETHER = 1 # Ethernet 10Mbps
-ARPHRD_EETHER = 2 # Experimental Ethernet
-ARPHRD_AX25 = 3 # AX.25 Level 2
-ARPHRD_PRONET = 4 # PROnet token ring
-ARPHRD_CHAOS = 5 # Chaosnet
-ARPHRD_IEEE802 = 6 # IEEE 802.2 Ethernet/TR/TB
-ARPHRD_ARCNET = 7 # ARCnet
-ARPHRD_APPLETLK = 8 # APPLEtalk
-ARPHRD_DLCI = 15 # Frame Relay DLCI
-ARPHRD_ATM = 19 # ATM
-ARPHRD_METRICOM = 23 # Metricom STRIP (new IANA id)
-ARPHRD_IEEE1394 = 24 # IEEE 1394 IPv4 - RFC 2734
-ARPHRD_EUI64 = 27 # EUI-64
-ARPHRD_INFINIBAND = 32 # InfiniBand
-
-# Dummy types for non ARP hardware
-ARPHRD_SLIP = 256
-ARPHRD_CSLIP = 257
-ARPHRD_SLIP6 = 258
-ARPHRD_CSLIP6 = 259
-ARPHRD_RSRVD = 260 # Notional KISS type
-ARPHRD_ADAPT = 264
-ARPHRD_ROSE = 270
-ARPHRD_X25 = 271 # CCITT X.25
-ARPHRD_HWX25 = 272 # Boards with X.25 in firmware
-ARPHRD_PPP = 512
-ARPHRD_CISCO = 513 # Cisco HDLC
-ARPHRD_HDLC = ARPHRD_CISCO
-ARPHRD_LAPB = 516 # LAPB
-ARPHRD_DDCMP = 517 # Digital's DDCMP protocol
-ARPHRD_RAWHDLC = 518 # Raw HDLC
-
-ARPHRD_TUNNEL = 768 # IPIP tunnel
-ARPHRD_TUNNEL6 = 769 # IP6IP6 tunnel
-ARPHRD_FRAD = 770 # Frame Relay Access Device
-ARPHRD_SKIP = 771 # SKIP vif
-ARPHRD_LOOPBACK = 772 # Loopback device
-ARPHRD_LOCALTLK = 773 # Localtalk device
-ARPHRD_FDDI = 774 # Fiber Distributed Data Interface
-ARPHRD_BIF = 775 # AP1000 BIF
-ARPHRD_SIT = 776 # sit0 device - IPv6-in-IPv4
-ARPHRD_IPDDP = 777 # IP over DDP tunneller
-ARPHRD_IPGRE = 778 # GRE over IP
-ARPHRD_PIMREG = 779 # PIMSM register interface
-ARPHRD_HIPPI = 780 # High Performance Parallel Interface
-ARPHRD_ASH = 781 # Nexus 64Mbps Ash
-ARPHRD_ECONET = 782 # Acorn Econet
-ARPHRD_IRDA = 783 # Linux-IrDA
-# ARP works differently on different FC media .. so
-ARPHRD_FCPP = 784 # Point to point fibrechannel
-ARPHRD_FCAL = 785 # Fibrechannel arbitrated loop
-ARPHRD_FCPL = 786 # Fibrechannel public loop
-ARPHRD_FCFABRIC = 787 # Fibrechannel fabric
-# 787->799 reserved for fibrechannel media types
-ARPHRD_IEEE802_TR = 800 # Magic type ident for TR
-ARPHRD_IEEE80211 = 801 # IEEE 802.11
-ARPHRD_IEEE80211_PRISM = 802 # IEEE 802.11 + Prism2 header
-ARPHRD_IEEE80211_RADIOTAP = 803 # IEEE 802.11 + radiotap header
-ARPHRD_MPLS_TUNNEL = 899 # MPLS Tunnel Interface
-
-ARPHRD_VOID = 0xFFFF # Void type, nothing is known
-ARPHRD_NONE = 0xFFFE # zero header length
-
-(ARPHRD_NAMES, ARPHRD_VALUES) = map_namespace("ARPHRD_", globals())
diff --git a/node-admin/scripts/pyroute2/common.py b/node-admin/scripts/pyroute2/common.py
deleted file mode 100644
index 60eae5b88df..00000000000
--- a/node-admin/scripts/pyroute2/common.py
+++ /dev/null
@@ -1,288 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-# -*- coding: utf-8 -*-
-'''
-Common utilities
-'''
-import re
-import os
-import sys
-import types
-import struct
-import platform
-import threading
-
-from socket import inet_aton
-
-try:
- basestring = basestring
-except NameError:
- basestring = (str, bytes)
-
-AF_PIPE = 255 # Right now AF_MAX == 40
-DEFAULT_RCVBUF = 16384
-ANCIENT = (platform.dist()[0] in ('redhat', 'centos') and
- platform.dist()[1].startswith('6.') or
- os.environ.get('PYROUTE2_ANCIENT', False))
-
-size_suffixes = {'b': 1,
- 'k': 1024,
- 'kb': 1024,
- 'm': 1024 * 1024,
- 'mb': 1024 * 1024,
- 'g': 1024 * 1024 * 1024,
- 'gb': 1024 * 1024 * 1024,
- 'kbit': 1024 / 8,
- 'mbit': 1024 * 1024 / 8,
- 'gbit': 1024 * 1024 * 1024 / 8}
-
-
-time_suffixes = {'s': 1,
- 'sec': 1,
- 'secs': 1,
- 'ms': 1000,
- 'msec': 1000,
- 'msecs': 1000,
- 'us': 1000000,
- 'usec': 1000000,
- 'usecs': 1000000}
-
-rate_suffixes = {'bit': 1,
- 'Kibit': 1024,
- 'kbit': 1000,
- 'mibit': 1024 * 1024,
- 'mbit': 1000000,
- 'gibit': 1024 * 1024 * 1024,
- 'gbit': 1000000000,
- 'tibit': 1024 * 1024 * 1024 * 1024,
- 'tbit': 1000000000000,
- 'Bps': 8,
- 'KiBps': 8 * 1024,
- 'KBps': 8000,
- 'MiBps': 8 * 1024 * 1024,
- 'MBps': 8000000,
- 'GiBps': 8 * 1024 * 1024 * 1024,
- 'GBps': 8000000000,
- 'TiBps': 8 * 1024 * 1024 * 1024 * 1024,
- 'TBps': 8000000000000}
-
-
-##
-# General purpose
-#
-class Dotkeys(dict):
- '''
- This is a sick-minded hack of dict, intended to be an eye-candy.
- It allows to get dict's items byt dot reference:
-
- ipdb["lo"] == ipdb.lo
- ipdb["eth0"] == ipdb.eth0
-
- Obviously, it will not work for some cases, like unicode names
- of interfaces and so on. Beside of that, it introduces some
- complexity.
-
- But it simplifies live for old-school admins, who works with good
- old "lo", "eth0", and like that naming schemes.
- '''
- var_name = re.compile('^[a-zA-Z_]+[a-zA-Z_0-9]*$')
-
- def __dir__(self):
- return [i for i in self if
- type(i) == str and self.var_name.match(i)]
-
- def __getattribute__(self, key, *argv):
- try:
- return dict.__getattribute__(self, key)
- except AttributeError as e:
- if key == '__deepcopy__':
- raise e
- return self[key]
-
- def __setattr__(self, key, value):
- if key in self:
- self[key] = value
- else:
- dict.__setattr__(self, key, value)
-
- def __delattr__(self, key):
- if key in self:
- del self[key]
- else:
- dict.__delattr__(self, key)
-
-
-def map_namespace(prefix, ns, normalize=None):
- '''
- Take the namespace prefix, list all constants and build two
- dictionaries -- straight and reverse mappings. E.g.:
-
- ## neighbor attributes
- NDA_UNSPEC = 0
- NDA_DST = 1
- NDA_LLADDR = 2
- NDA_CACHEINFO = 3
- NDA_PROBES = 4
- (NDA_NAMES, NDA_VALUES) = map_namespace('NDA', globals())
-
- Will lead to::
-
- NDA_NAMES = {'NDA_UNSPEC': 0,
- ...
- 'NDA_PROBES': 4}
- NDA_VALUES = {0: 'NDA_UNSPEC',
- ...
- 4: 'NDA_PROBES'}
-
- The `normalize` parameter can be:
-
- - None — no name transformation will be done
- - True — cut the prefix and `lower()` the rest
- - lambda x: … — apply the function to every name
-
- '''
- nmap = {None: lambda x: x,
- True: lambda x: x[len(prefix):].lower()}
-
- if not isinstance(normalize, types.FunctionType):
- normalize = nmap[normalize]
-
- by_name = dict([(normalize(i), ns[i]) for i in ns.keys()
- if i.startswith(prefix)])
- by_value = dict([(ns[i], normalize(i)) for i in ns.keys()
- if i.startswith(prefix)])
- return (by_name, by_value)
-
-
-def dqn2int(mask):
- '''
- IPv4 dotted quad notation to int mask conversion
- '''
- return bin(struct.unpack('>L', inet_aton(mask))[0]).count('1')
-
-
-def hexdump(payload, length=0):
- '''
- Represent byte string as hex -- for debug purposes
- '''
- if sys.version[0] == '3':
- return ':'.join('{0:02x}'.format(c)
- for c in payload[:length] or payload)
- else:
- return ':'.join('{0:02x}'.format(ord(c))
- for c in payload[:length] or payload)
-
-
-class AddrPool(object):
- '''
- Address pool
- '''
- cell = 0xffffffffffffffff
-
- def __init__(self,
- minaddr=0xf,
- maxaddr=0xffffff,
- reverse=False,
- release=False):
- self.cell_size = 0 # in bits
- mx = self.cell
- self.reverse = reverse
- self.release = release
- self.allocated = 0
- if self.release:
- assert isinstance(self.release, int)
- self.ban = []
- while mx:
- mx >>= 8
- self.cell_size += 1
- self.cell_size *= 8
- # calculate, how many ints we need to bitmap all addresses
- self.cells = int((maxaddr - minaddr) / self.cell_size + 1)
- # initial array
- self.addr_map = [self.cell]
- self.minaddr = minaddr
- self.maxaddr = maxaddr
- self.lock = threading.RLock()
-
- def alloc(self):
- with self.lock:
- # gc self.ban:
- for item in tuple(self.ban):
- if item['counter'] == 0:
- self.free(item['addr'])
- self.ban.remove(item)
- else:
- item['counter'] -= 1
-
- # iterate through addr_map
- base = 0
- for cell in self.addr_map:
- if cell:
- # not allocated addr
- bit = 0
- while True:
- if (1 << bit) & self.addr_map[base]:
- self.addr_map[base] ^= 1 << bit
- break
- bit += 1
- ret = (base * self.cell_size + bit)
-
- if self.reverse:
- ret = self.maxaddr - ret
- else:
- ret = ret + self.minaddr
-
- if self.minaddr <= ret <= self.maxaddr:
- if self.release:
- self.free(ret, ban=self.release)
- self.allocated += 1
- return ret
- else:
- self.free(ret)
- raise KeyError('no free address available')
-
- base += 1
- # no free address available
- if len(self.addr_map) < self.cells:
- # create new cell to allocate address from
- self.addr_map.append(self.cell)
- return self.alloc()
- else:
- raise KeyError('no free address available')
-
- def locate(self, addr):
- if self.reverse:
- addr = self.maxaddr - addr
- else:
- addr -= self.minaddr
- base = addr // self.cell_size
- bit = addr % self.cell_size
- try:
- is_allocated = not self.addr_map[base] & (1 << bit)
- except IndexError:
- is_allocated = False
- return (base, bit, is_allocated)
-
- def setaddr(self, addr, value):
- assert value in ('free', 'allocated')
- with self.lock:
- base, bit, is_allocated = self.locate(addr)
- if value == 'free' and is_allocated:
- self.allocated -= 1
- self.addr_map[base] |= 1 << bit
- elif value == 'allocated' and not is_allocated:
- self.allocated += 1
- self.addr_map[base] &= ~(1 << bit)
-
- def free(self, addr, ban=0):
- with self.lock:
- if ban != 0:
- self.ban.append({'addr': addr,
- 'counter': ban})
- else:
- base, bit, is_allocated = self.locate(addr)
- if len(self.addr_map) <= base:
- raise KeyError('address is not allocated')
- if self.addr_map[base] & (1 << bit):
- raise KeyError('address is not allocated')
- self.allocated -= 1
- self.addr_map[base] ^= 1 << bit
diff --git a/node-admin/scripts/pyroute2/config.py b/node-admin/scripts/pyroute2/config.py
deleted file mode 100644
index 0dbbbae6089..00000000000
--- a/node-admin/scripts/pyroute2/config.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-import socket
-import multiprocessing
-
-SocketBase = socket.socket
-MpPipe = multiprocessing.Pipe
-MpQueue = multiprocessing.Queue
-MpProcess = multiprocessing.Process
-
-commit_barrier = 0.2
diff --git a/node-admin/scripts/pyroute2/debugger.py b/node-admin/scripts/pyroute2/debugger.py
deleted file mode 100644
index 1e63644cada..00000000000
--- a/node-admin/scripts/pyroute2/debugger.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-import select
-import socket
-import struct
-import threading
-from pyroute2.iproute import IPRoute
-try:
- from Queue import Queue
-except ImportError:
- from queue import Queue
-
-
-class Server(object):
-
- def __init__(self, addr='0.0.0.0', port=3546):
- self.addr = addr
- self.port = port
-
- def run(self):
- nat = {}
- clients = []
-
- srv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- srv.bind((self.addr, self.port))
- ipr = IPRoute()
- ipr.bind()
-
- poll = select.poll()
- poll.register(ipr, select.POLLIN | select.POLLPRI)
- poll.register(srv, select.POLLIN | select.POLLPRI)
-
- while True:
- events = poll.poll()
- for (fd, event) in events:
- if fd == ipr.fileno():
- bufsize = ipr.getsockopt(socket.SOL_SOCKET,
- socket.SO_RCVBUF) // 2
- data = ipr.recv(bufsize)
- cookie = struct.unpack('I', data[8:12])[0]
- if cookie == 0:
- for address in clients:
- srv.sendto(data, address)
- else:
- srv.sendto(data, nat[cookie])
- else:
- data, address = srv.recvfrom(16384)
- if data is None:
- clients.remove(address)
- continue
- cookie = struct.unpack('I', data[8:12])[0]
- nat[cookie] = address
- ipr.sendto(data, (0, 0))
-
-
-class Client(IPRoute):
-
- def __init__(self, addr):
- IPRoute.__init__(self)
- self.proxy = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- self.proxy.bind(('0.0.0.0', 3547))
- self.proxy_addr = addr
- self.proxy_queue = Queue()
-
- def recv():
- while True:
- (data, addr) = self.proxy.recvfrom(16384)
- self.proxy_queue.put(data)
-
- self.pthread = threading.Thread(target=recv)
- self.pthread.setDaemon(True)
- self.pthread.start()
-
- def sendto(buf, *argv, **kwarg):
- return self.proxy.sendto(buf, (self.proxy_addr, 3546))
-
- def recv(*argv, **kwarg):
- return self.proxy_queue.get()
-
- self._sendto = sendto
- self._recv = recv
-
- def close(self):
- self.proxy.close()
- self.recv = lambda *x, **y: None
- self.proxy_queue.put(None)
diff --git a/node-admin/scripts/pyroute2/dhcp/__init__.py b/node-admin/scripts/pyroute2/dhcp/__init__.py
deleted file mode 100644
index 46dc26dadef..00000000000
--- a/node-admin/scripts/pyroute2/dhcp/__init__.py
+++ /dev/null
@@ -1,300 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-DHCP protocol
-=============
-
-The DHCP implementation here is far from complete, but
-already provides some basic functionality. Later it will
-be extended with IPv6 support and more DHCP options
-will be added.
-
-Right now it can be interesting mostly to developers,
-but not users and/or system administrators. So, the
-development hints first.
-
-The packet structure description is intentionally
-implemented as for netlink packets. Later these two
-parsers, netlink and generic, can be merged, so the
-syntax is more or less compatible.
-
-Packet fields
--------------
-
-There are two big groups of items within any DHCP packet.
-First, there are BOOTP/DHCP packet fields, they're defined
-with the `fields` attribute::
-
- class dhcp4msg(msg):
- fields = ((name, format, policy),
- (name, format, policy),
- ...
- (name, format, policy))
-
-The `name` can be any literal. Format should be specified
-as for the struct module, like `B` for `uint8`, or `i` for
-`int32`, or `>Q` for big-endian uint64. There are also
-aliases defined, so one can write `uint8` or `be16`, or
-like that. Possible aliases can be seen in the
-`pyroute2.protocols` module.
-
-The `policy` is a bit complicated. It can be a number or
-literal, and it will mean that it is a default value, that
-should be encoded if no other value is given.
-
-But when the `policy` is a dictionary, it can contain keys
-as follows::
-
- 'l2addr': {'format': '6B',
- 'decode': ...,
- 'encode': ...}
-
-Keys `encode` and `decode` should contain filters to be used
-in decoding and encoding procedures. The encoding filter
-should accept the value from user's definition and should
-return a value that can be packed using `format`. The decoding
-filter should accept a value, decoded according to `format`,
-and should return value that can be used by a user.
-
-The `struct` module can not decode IP addresses etc, so they
-should be decoded as `4s`, e.g. Further transformation from
-4 bytes string to a string like '10.0.0.1' performs the filter.
-
-DHCP options
-------------
-
-DHCP options are described in a similar way::
-
- options = ((code, name, format),
- (code, name, format),
- ...
- (code, name, format))
-
-Code is a `uint8` value, name can be any string literal. Format
-is a string, that must have a corresponding class, inherited from
-`pyroute2.dhcp.option`. One can find these classes in
-`pyroute2.dhcp` (more generic) or in `pyroute2.dhcp.dhcp4msg`
-(IPv4-specific). The option class must reside within dhcp message
-class.
-
-Every option class can be decoded in two ways. If it has fixed
-width fields, it can be decoded with ordinary `msg` routines, and
-in this case it can look like that::
-
- class client_id(option):
- fields = (('type', 'uint8'),
- ('key', 'l2addr'))
-
-If it must be decoded by some custom rules, one can define the
-policy just like for the fields above::
-
- class array8(option):
- policy = {'format': 'string',
- 'encode': lambda x: array('B', x).tobytes(),
- 'decode': lambda x: array('B', x).tolist()}
-
-In the corresponding modules, like in `pyroute2.dhcp.dhcp4msg`,
-one can define as many custom DHCP options, as one need. Just
-be sure, that they are compatible with the DHCP server and all
-fit into 1..254 (`uint8`) -- the 0 code is used for padding and
-the code 255 is the end of options code.
-'''
-
-import sys
-import struct
-from array import array
-from pyroute2.common import basestring
-from pyroute2.protocols import msg
-
-BOOTREQUEST = 1
-BOOTREPLY = 2
-
-DHCPDISCOVER = 1
-DHCPOFFER = 2
-DHCPREQUEST = 3
-DHCPDECLINE = 4
-DHCPACK = 5
-DHCPNAK = 6
-DHCPRELEASE = 7
-DHCPINFORM = 8
-
-
-if not hasattr(array, 'tobytes'):
- # Python2 and Python3 versions of array differ,
- # but we need here a consistent API w/o warnings
- class array(array):
- tobytes = array.tostring
-
-
-class option(msg):
-
- code = 0
- data_length = 0
- policy = None
- value = None
-
- def __init__(self, content=None, buf=b'', offset=0, value=None, code=0):
- msg.__init__(self, content=content, buf=buf,
- offset=offset, value=value)
- self.code = code
-
- @property
- def length(self):
- if self.data_length is None:
- return None
- if self.data_length == 0:
- return 1
- else:
- return self.data_length + 2
-
- def encode(self):
- # pack code
- self.buf += struct.pack('B', self.code)
- if self.code in (0, 255):
- return self
- # save buf
- save = self.buf
- self.buf = b''
- # pack data into the new buf
- if self.policy is not None:
- value = self.policy.get('encode', lambda x: x)(self.value)
- if self.policy['format'] == 'string':
- fmt = '%is' % len(value)
- else:
- fmt = self.policy['format']
- if sys.version_info[0] == 3 and isinstance(value, str):
- value = value.encode('utf-8')
- self.buf = struct.pack(fmt, value)
- else:
- msg.encode(self)
- # get the length
- data = self.buf
- self.buf = save
- self.buf += struct.pack('B', len(data))
- # attach the packed data
- self.buf += data
- return self
-
- def decode(self):
- if self.policy is not None:
- self.data_length = struct.unpack('B', self.buf[self.offset + 1:
- self.offset + 2])[0]
- if self.policy['format'] == 'string':
- fmt = '%is' % self.data_length
- else:
- fmt = self.policy['format']
- value = struct.unpack(fmt, self.buf[self.offset + 2:
- self.offset + 2 +
- self.data_length])
- if len(value) == 1:
- value = value[0]
- value = self.policy.get('decode', lambda x: x)(value)
- if isinstance(value, basestring) and \
- self.policy['format'] == 'string':
- value = value[:value.find('\x00')]
- self.value = value
- else:
- msg.decode(self)
- return self
-
-
-class dhcpmsg(msg):
- options = ()
- l2addr = None
- _encode_map = {}
- _decode_map = {}
-
- def _register_options(self):
- for option in self.options:
- code, name, fmt = option[:3]
- self._decode_map[code] =\
- self._encode_map[name] = {'name': name,
- 'code': code,
- 'format': fmt}
-
- def decode(self):
- msg.decode(self)
- self._register_options()
- self['options'] = {}
- while self.offset < len(self.buf):
- code = struct.unpack('B', self.buf[self.offset:self.offset + 1])[0]
- if code == 0:
- self.offset += 1
- continue
- if code == 255:
- return self
- # code is unknown -- bypass it
- if code not in self._decode_map:
- length = struct.unpack('B', self.buf[self.offset + 1:
- self.offset + 2])[0]
- self.offset += length + 2
- continue
-
- # code is known, work on it
- option_class = getattr(self, self._decode_map[code]['format'])
- option = option_class(buf=self.buf, offset=self.offset)
- option.decode()
- self.offset += option.length
- if option.value is not None:
- value = option.value
- else:
- value = option
- self['options'][self._decode_map[code]['name']] = value
- return self
-
- def encode(self):
- msg.encode(self)
- self._register_options()
- # put message type
- options = self.get('options') or {'message_type': DHCPDISCOVER,
- 'parameter_list': [1, 3, 6,
- 12, 15, 28]}
-
- self.buf += self.uint8(code=53,
- value=options['message_type']).encode().buf
- self.buf += self.client_id({'type': 1,
- 'key': self['chaddr']},
- code=61).encode().buf
- self.buf += self.string(code=60, value='pyroute2').encode().buf
-
- for (name, value) in options.items():
- if name in ('message_type', 'client_id', 'vendor_id'):
- continue
- fmt = self._encode_map.get(name, {'format': None})['format']
- if fmt is None:
- continue
- # name is known, ok
- option_class = getattr(self, fmt)
- if isinstance(value, dict):
- option = option_class(value,
- code=self._encode_map[name]['code'])
- else:
- option = option_class(code=self._encode_map[name]['code'],
- value=value)
- self.buf += option.encode().buf
-
- self.buf += self.none(code=255).encode().buf
- return self
-
- class none(option):
- pass
-
- class be16(option):
- policy = {'format': '>H'}
-
- class be32(option):
- policy = {'format': '>I'}
-
- class uint8(option):
- policy = {'format': 'B'}
-
- class string(option):
- policy = {'format': 'string'}
-
- class array8(option):
- policy = {'format': 'string',
- 'encode': lambda x: array('B', x).tobytes(),
- 'decode': lambda x: array('B', x).tolist()}
-
- class client_id(option):
- fields = (('type', 'uint8'),
- ('key', 'l2addr'))
diff --git a/node-admin/scripts/pyroute2/dhcp/dhcp4msg.py b/node-admin/scripts/pyroute2/dhcp/dhcp4msg.py
deleted file mode 100644
index 4cd27c5d75c..00000000000
--- a/node-admin/scripts/pyroute2/dhcp/dhcp4msg.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-from socket import inet_pton
-from socket import inet_ntop
-from socket import AF_INET
-from pyroute2.dhcp import dhcpmsg
-from pyroute2.dhcp import option
-
-
-class dhcp4msg(dhcpmsg):
- #
- # https://www.ietf.org/rfc/rfc2131.txt
- #
- fields = (('op', 'uint8', 1), # request
- ('htype', 'uint8', 1), # ethernet
- ('hlen', 'uint8', 6), # ethernet addr len
- ('hops', 'uint8'),
- ('xid', 'uint32'),
- ('secs', 'uint16'),
- ('flags', 'uint16'),
- ('ciaddr', 'ip4addr'),
- ('yiaddr', 'ip4addr'),
- ('siaddr', 'ip4addr'),
- ('giaddr', 'ip4addr'),
- ('chaddr', 'l2paddr'),
- ('sname', '64s'),
- ('file', '128s'),
- ('cookie', '4s', b'c\x82Sc'))
- #
- # https://www.ietf.org/rfc/rfc2132.txt
- #
- options = ((0, 'pad', 'none'),
- (1, 'subnet_mask', 'ip4addr'),
- (2, 'time_offset', 'be32'),
- (3, 'router', 'ip4list'),
- (4, 'time_server', 'ip4list'),
- (5, 'ien_name_server', 'ip4list'),
- (6, 'name_server', 'ip4list'),
- (7, 'log_server', 'ip4list'),
- (8, 'cookie_server', 'ip4list'),
- (9, 'lpr_server', 'ip4list'),
- (50, 'requested_ip', 'ip4addr'),
- (53, 'message_type', 'uint8'),
- (54, 'server_id', 'ip4addr'),
- (55, 'parameter_list', 'array8'),
- (57, 'messagi_size', 'be16'),
- (60, 'vendor_id', 'string'),
- (61, 'client_id', 'client_id'),
- (255, 'end', 'none'))
-
- class ip4addr(option):
- policy = {'format': '4s',
- 'encode': lambda x: inet_pton(AF_INET, x),
- 'decode': lambda x: inet_ntop(AF_INET, x)}
-
- class ip4list(option):
- policy = {'format': 'string',
- 'encode': lambda x: ''.join([inet_pton(AF_INET, i) for i
- in x]),
- 'decode': lambda x: [inet_ntop(AF_INET, x[i*4:i*4+4]) for i
- in range(len(x)//4)]}
diff --git a/node-admin/scripts/pyroute2/dhcp/dhcp4socket.py b/node-admin/scripts/pyroute2/dhcp/dhcp4socket.py
deleted file mode 100644
index 7928d5a0745..00000000000
--- a/node-admin/scripts/pyroute2/dhcp/dhcp4socket.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-IPv4 DHCP socket
-================
-
-'''
-from pyroute2.common import AddrPool
-from pyroute2.protocols import udpmsg
-from pyroute2.protocols import udp4_pseudo_header
-from pyroute2.protocols import ethmsg
-from pyroute2.protocols import ip4msg
-from pyroute2.protocols.rawsocket import RawSocket
-from pyroute2.dhcp.dhcp4msg import dhcp4msg
-
-
-def listen_udp_port(port=68):
- # pre-scripted BPF code that matches UDP port
- bpf_code = [[40, 0, 0, 12],
- [21, 0, 8, 2048],
- [48, 0, 0, 23],
- [21, 0, 6, 17],
- [40, 0, 0, 20],
- [69, 4, 0, 8191],
- [177, 0, 0, 14],
- [72, 0, 0, 16],
- [21, 0, 1, port],
- [6, 0, 0, 65535],
- [6, 0, 0, 0]]
- return bpf_code
-
-
-class DHCP4Socket(RawSocket):
- '''
- Parameters:
-
- * ifname -- interface name to work on
-
- This raw socket binds to an interface and installs BPF filter
- to get only its UDP port. It can be used in poll/select and
- provides also the context manager protocol, so can be used in
- `with` statements.
-
- It does not provide any DHCP state machine, and does not inspect
- DHCP packets, it is totally up to you. No default values are
- provided here, except `xid` -- DHCP transaction ID. If `xid` is
- not provided, DHCP4Socket generates it for outgoing messages.
- '''
-
- def __init__(self, ifname, port=68):
- RawSocket.__init__(self, ifname, listen_udp_port(port))
- self.port = port
- # Create xid pool
- #
- # Every allocated xid will be released automatically after 1024
- # alloc() calls, there is no need to call free(). Minimal xid == 16
- self.xid_pool = AddrPool(minaddr=16, release=1024)
-
- def __enter__(self):
- return self
-
- def __exit__(self, exc_type, exc_value, traceback):
- self.close()
-
- def put(self, msg=None, dport=67):
- '''
- Put DHCP message. Parameters:
-
- * msg -- dhcp4msg instance
- * dport -- DHCP server port
-
- If `msg` is not provided, it is constructed as default
- BOOTREQUEST + DHCPDISCOVER.
-
- Examples::
-
- sock.put(dhcp4msg({'op': BOOTREQUEST,
- 'chaddr': 'ff:11:22:33:44:55',
- 'options': {'message_type': DHCPREQUEST,
- 'parameter_list': [1, 3, 6, 12, 15],
- 'requested_ip': '172.16.101.2',
- 'server_id': '172.16.101.1'}}))
-
- The method returns dhcp4msg that was sent, so one can get from
- there `xid` (transaction id) and other details.
- '''
- # DHCP layer
- dhcp = msg or dhcp4msg({'chaddr': self.l2addr})
-
- # dhcp transaction id
- if dhcp['xid'] is None:
- dhcp['xid'] = self.xid_pool.alloc()
-
- data = dhcp.encode().buf
-
- # UDP layer
- udp = udpmsg({'sport': self.port,
- 'dport': dport,
- 'len': 8 + len(data)})
- udph = udp4_pseudo_header({'dst': '255.255.255.255',
- 'len': 8 + len(data)})
- udp['csum'] = self.csum(udph.encode().buf + udp.encode().buf + data)
- udp.reset()
-
- # IPv4 layer
- ip4 = ip4msg({'len': 20 + 8 + len(data),
- 'proto': 17,
- 'dst': '255.255.255.255'})
- ip4['csum'] = self.csum(ip4.encode().buf)
- ip4.reset()
-
- # MAC layer
- eth = ethmsg({'dst': 'ff:ff:ff:ff:ff:ff',
- 'src': self.l2addr,
- 'type': 0x800})
-
- data = eth.encode().buf +\
- ip4.encode().buf +\
- udp.encode().buf +\
- data
- self.send(data)
- dhcp.reset()
- return dhcp
-
- def get(self):
- '''
- Get the next incoming packet from the socket and try
- to decode it as IPv4 DHCP. No analysis is done here,
- only MAC/IPv4/UDP headers are stripped out, and the
- rest is interpreted as DHCP.
- '''
- (data, addr) = self.recvfrom(4096)
- eth = ethmsg(buf=data).decode()
- ip4 = ip4msg(buf=data, offset=eth.offset).decode()
- udp = udpmsg(buf=data, offset=ip4.offset).decode()
- return dhcp4msg(buf=data, offset=udp.offset).decode()
diff --git a/node-admin/scripts/pyroute2/ipdb/__init__.py b/node-admin/scripts/pyroute2/ipdb/__init__.py
deleted file mode 100644
index 5887bb61bb2..00000000000
--- a/node-admin/scripts/pyroute2/ipdb/__init__.py
+++ /dev/null
@@ -1,981 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-# -*- coding: utf-8 -*-
-'''
-IPDB module
-===========
-
-Basically, IPDB is a transactional database, containing records,
-representing network stack objects. Any change in the database
-is not reflected immediately in OS (unless you ask for that
-explicitly), but waits until `commit()` is called. One failed
-operation during `commit()` rolls back all the changes, has been
-made so far. Moreover, IPDB has commit hooks API, that allows
-you to roll back changes depending on your own function calls,
-e.g. when a host or a network becomes unreachable.
-
-IPDB vs. IPRoute
-----------------
-
-These two modules, IPRoute and IPDB, use completely different
-approaches. The first one, IPRoute, is synchronous by default,
-and can be used in the same way, as usual Linux utilities. It
-doesn't spawn any additional threads or processes, until you
-explicitly ask for that.
-
-The latter, IPDB, is an asynchronously updated database, that
-starts several additional threads by default. If your project's
-policy doesn't allow implicit threads, keep it in mind.
-
-The choice depends on your project's workflow. If you plan to
-retrieve the system info not too often (or even once), or you
-are sure there will be not too many network object, it is better
-to use IPRoute. If you plan to lookup the network info on a
-regular basis and there can be loads of network objects, it is
-better to use IPDB. Why?
-
-IPRoute just loads what you ask -- and loads all the information
-you ask to. While IPDB loads all the info upon startup, and
-later is just updated by asynchronous broadcast netlink messages.
-Assume you want to lookup ARP cache that contains hundreds or
-even thousands of objects. Using IPRoute, you have to load all
-the ARP cache every time you want to make a lookup. While IPDB
-will load all the cache once, and then maintain it up-to-date
-just inserting new records or removing them by one.
-
-So, IPRoute is much simpler when you need to make a call and
-then exit. While IPDB is cheaper in terms of CPU performance
-if you implement a long-running program like a daemon. Later
-it can change, if there will be (an optional) cache for IPRoute
-too.
-
-quickstart
-----------
-
-Simple tutorial::
-
- from pyroute2 import IPDB
- # several IPDB instances are supported within on process
- ip = IPDB()
-
- # commit is called automatically upon the exit from `with`
- # statement
- with ip.interfaces.eth0 as i:
- i.address = '00:11:22:33:44:55'
- i.ifname = 'bala'
- i.txqlen = 2000
-
- # basic routing support
- ip.routes.add({'dst': 'default', 'gateway': '10.0.0.1'}).commit()
-
- # do not forget to shutdown IPDB
- ip.release()
-
-Please, notice `ip.release()` call in the end. Though it is
-not forced in an interactive python session for the better
-user experience, it is required in the scripts to sync the
-IPDB state before exit.
-
-IPDB uses IPRoute as a transport, and monitors all broadcast
-netlink messages from the kernel, thus keeping the database
-up-to-date in an asynchronous manner. IPDB inherits `dict`
-class, and has two keys::
-
- >>> from pyroute2 import IPDB
- >>> ip = IPDB()
- >>> ip.by_name.keys()
- ['bond0', 'lo', 'em1', 'wlan0', 'dummy0', 'virbr0-nic', 'virbr0']
- >>> ip.by_index.keys()
- [32, 1, 2, 3, 4, 5, 8]
- >>> ip.interfaces.keys()
- [32,
- 1,
- 2,
- 3,
- 4,
- 5,
- 8,
- 'lo',
- 'em1',
- 'wlan0',
- 'bond0',
- 'dummy0',
- 'virbr0-nic',
- 'virbr0']
- >>> ip.interfaces['em1']['address']
- 'f0:de:f1:93:94:0d'
- >>> ip.interfaces['em1']['ipaddr']
- [('10.34.131.210', 23),
- ('2620:52:0:2282:f2de:f1ff:fe93:940d', 64),
- ('fe80::f2de:f1ff:fe93:940d', 64)]
- >>>
-
-One can address objects in IPDB not only with dict notation, but
-with dot notation also::
-
- >>> ip.interfaces.em1.address
- 'f0:de:f1:93:94:0d'
- >>> ip.interfaces.em1.ipaddr
- [('10.34.131.210', 23),
- ('2620:52:0:2282:f2de:f1ff:fe93:940d', 64),
- ('fe80::f2de:f1ff:fe93:940d', 64)]
- ```
-
-It is up to you, which way to choose. The former, being more flexible,
-is better for developers, the latter, the shorter form -- for system
-administrators.
-
-
-The library has also IPDB module. It is a database synchronized with
-the kernel, containing some of the information. It can be used also
-to set up IP settings in a transactional manner:
-
- >>> from pyroute2 import IPDB
- >>> from pprint import pprint
- >>> ip = IPDB()
- >>> pprint(ip.by_name.keys())
- ['bond0',
- 'lo',
- 'vnet0',
- 'em1',
- 'wlan0',
- 'macvtap0',
- 'dummy0',
- 'virbr0-nic',
- 'virbr0']
- >>> ip.interfaces.lo
- {'promiscuity': 0,
- 'operstate': 'UNKNOWN',
- 'qdisc': 'noqueue',
- 'group': 0,
- 'family': 0,
- 'index': 1,
- 'linkmode': 0,
- 'ipaddr': [('127.0.0.1', 8), ('::1', 128)],
- 'mtu': 65536,
- 'broadcast': '00:00:00:00:00:00',
- 'num_rx_queues': 1,
- 'txqlen': 0,
- 'ifi_type': 772,
- 'address': '00:00:00:00:00:00',
- 'flags': 65609,
- 'ifname': 'lo',
- 'num_tx_queues': 1,
- 'ports': [],
- 'change': 0}
- >>>
-
-transaction modes
------------------
-IPDB has several operating modes:
-
- - 'direct' -- any change goes immediately to the OS level
- - 'implicit' (default) -- the first change starts an implicit
- transaction, that have to be committed
- - 'explicit' -- you have to begin() a transaction prior to
- make any change
- - 'snapshot' -- no changes will go to the OS in any case
-
-The default is to use implicit transaction. This behaviour can
-be changed in the future, so use 'mode' argument when creating
-IPDB instances.
-
-The sample session with explicit transactions::
-
- In [1]: from pyroute2 import IPDB
- In [2]: ip = IPDB(mode='explicit')
- In [3]: ifdb = ip.interfaces
- In [4]: ifdb.tap0.begin()
- Out[3]: UUID('7a637a44-8935-4395-b5e7-0ce40d31d937')
- In [5]: ifdb.tap0.up()
- In [6]: ifdb.tap0.address = '00:11:22:33:44:55'
- In [7]: ifdb.tap0.add_ip('10.0.0.1', 24)
- In [8]: ifdb.tap0.add_ip('10.0.0.2', 24)
- In [9]: ifdb.tap0.review()
- Out[8]:
- {'+ipaddr': set([('10.0.0.2', 24), ('10.0.0.1', 24)]),
- '-ipaddr': set([]),
- 'address': '00:11:22:33:44:55',
- 'flags': 4099}
- In [10]: ifdb.tap0.commit()
-
-
-Note, that you can `review()` the `last()` transaction, and
-`commit()` or `drop()` it. Also, multiple `self._transactions`
-are supported, use uuid returned by `begin()` to identify them.
-
-Actually, the form like 'ip.tap0.address' is an eye-candy. The
-IPDB objects are dictionaries, so you can write the code above
-as that::
-
- ip.interfaces['tap0'].down()
- ip.interfaces['tap0']['address'] = '00:11:22:33:44:55'
- ...
-
-context managers
-----------------
-
-Also, interface objects in transactional mode can operate as
-context managers::
-
- with ip.interfaces.tap0 as i:
- i.address = '00:11:22:33:44:55'
- i.ifname = 'vpn'
- i.add_ip('10.0.0.1', 24)
- i.add_ip('10.0.0.1', 24)
-
-On exit, the context manager will authomatically `commit()` the
-transaction.
-
-create interfaces
------------------
-
-IPDB can also create interfaces::
-
- with ip.create(kind='bridge', ifname='control') as i:
- i.add_port(ip.interfaces.eth1)
- i.add_port(ip.interfaces.eth2)
- i.add_ip('10.0.0.1/24') # the same as i.add_ip('10.0.0.1', 24)
-
-IPDB supports many interface types, see docs below for the
-`IPDB.create()` method.
-
-routing management
-------------------
-
-IPDB has a simple yet useful routing management interface.
-To add a route, one can use almost any syntax::
-
- # spec as a dictionary
- spec = {'dst': '172.16.1.0/24',
- 'oif': 4,
- 'gateway': '192.168.122.60',
- 'metrics': {'mtu': 1400,
- 'advmss': 500}}
-
- # pass spec as is
- ip.routes.add(spec).commit()
-
- # pass spec as kwargs
- ip.routes.add(**spec).commit()
-
- # use keyword arguments explicitly
- ip.routes.add(dst='172.16.1.0/24', oif=4, ...).commit()
-
-To access and change the routes, one can use notations as follows::
-
- # default table (254)
- #
- # change the route gateway and mtu
- #
- with ip.routes['172.16.1.0/24'] as route:
- route.gateway = '192.168.122.60'
- route.metrics.mtu = 1500
-
- # access the default route
- print(ip.routes['default])
-
- # change the default gateway
- with ip.routes['default'] as route:
- route.gateway = '10.0.0.1'
-
- # list automatic routes keys
- print(ip.routes.tables[255].keys())
-
-
-performance issues
-------------------
-
-In the case of bursts of Netlink broadcast messages, all
-the activity of the pyroute2-based code in the async mode
-becomes suppressed to leave more CPU resources to the
-packet reader thread. So please be ready to cope with
-delays in the case of Netlink broadcast storms. It means
-also, that IPDB state will be synchronized with OS also
-after some delay.
-
-classes
--------
-'''
-import sys
-import atexit
-import logging
-import traceback
-import threading
-
-from socket import AF_INET
-from socket import AF_INET6
-from pyroute2.common import Dotkeys
-from pyroute2.iproute import IPRoute
-from pyroute2.netlink.rtnl import RTM_GETLINK
-from pyroute2.ipdb.common import CreateException
-from pyroute2.ipdb.interface import Interface
-from pyroute2.ipdb.linkedset import LinkedSet
-from pyroute2.ipdb.linkedset import IPaddrSet
-from pyroute2.ipdb.common import compat
-from pyroute2.ipdb.common import SYNC_TIMEOUT
-from pyroute2.ipdb.route import RoutingTableSet
-
-
-def get_addr_nla(msg):
- '''
- Utility function to get NLA, containing the interface
- address.
-
- Incosistency in Linux IP addressing scheme is that
- IPv4 uses IFA_LOCAL to store interface's ip address,
- and IPv6 uses for the same IFA_ADDRESS.
-
- IPv4 sets IFA_ADDRESS to == IFA_LOCAL or to a
- tunneling endpoint.
-
- Args:
- - msg (nlmsg): RTM\_.*ADDR message
-
- Returns:
- - nla (nla): IFA_LOCAL for IPv4 and IFA_ADDRESS for IPv6
- '''
- nla = None
- if msg['family'] == AF_INET:
- nla = msg.get_attr('IFA_LOCAL')
- elif msg['family'] == AF_INET6:
- nla = msg.get_attr('IFA_ADDRESS')
- return nla
-
-
-class Watchdog(object):
- def __init__(self, ipdb, action, kwarg):
- self.event = threading.Event()
- self.ipdb = ipdb
-
- def cb(ipdb, msg, _action):
- if _action != action:
- return
-
- for key in kwarg:
- if (msg.get(key, None) != kwarg[key]) and \
- (msg.get_attr(msg.name2nla(key)) != kwarg[key]):
- return
- self.event.set()
- self.cb = cb
- # register callback prior to other things
- self.ipdb.register_callback(self.cb)
-
- def wait(self, timeout=SYNC_TIMEOUT):
- self.event.wait(timeout=timeout)
- self.cancel()
-
- def cancel(self):
- self.ipdb.unregister_callback(self.cb)
-
-
-class IPDB(object):
- '''
- The class that maintains information about network setup
- of the host. Monitoring netlink events allows it to react
- immediately. It uses no polling.
- '''
-
- def __init__(self, nl=None, mode='implicit',
- restart_on_error=None):
- '''
- Parameters:
- - nl -- IPRoute() reference
- - mode -- (implicit, explicit, direct)
- - iclass -- the interface class type
-
- If you do not provide iproute instance, ipdb will
- start it automatically.
- '''
- self.mode = mode
- self.iclass = Interface
- self._stop = False
- # see also 'register_callback'
- self._post_callbacks = []
- self._pre_callbacks = []
- self._cb_threads = set()
-
- # locks and events
- self._links_event = threading.Event()
- self.exclusive = threading.RLock()
- self._shutdown_lock = threading.Lock()
-
- # load information
- self.restart_on_error = restart_on_error if \
- restart_on_error is not None else nl is None
- self.initdb(nl)
-
- # start monitoring thread
- self._mthread = threading.Thread(target=self.serve_forever)
- if hasattr(sys, 'ps1') and self.nl.__class__.__name__ != 'Client':
- self._mthread.setDaemon(True)
- self._mthread.start()
- #
- atexit.register(self.release)
-
- def __enter__(self):
- return self
-
- def __exit__(self, exc_type, exc_value, traceback):
- self.release()
-
- def initdb(self, nl=None):
- '''
- Restart IPRoute channel, and create all the DB
- from scratch. Can be used when sync is lost.
- '''
- self.nl = nl or IPRoute()
- self.nl.monitor = True
- self.nl.bind(async=True)
-
- # resolvers
- self.interfaces = Dotkeys()
- self.routes = RoutingTableSet(ipdb=self)
- self.by_name = Dotkeys()
- self.by_index = Dotkeys()
-
- # caches
- self.ipaddr = {}
- self.neighbors = {}
-
- # load information
- links = self.nl.get_links()
- for link in links:
- self.device_put(link, skip_slaves=True)
- for link in links:
- self.update_slaves(link)
- self.update_addr(self.nl.get_addr())
- self.update_neighbors(self.nl.get_neighbors())
- routes4 = self.nl.get_routes(family=AF_INET)
- routes6 = self.nl.get_routes(family=AF_INET6)
- self.update_routes(routes4)
- self.update_routes(routes6)
-
- def register_callback(self, callback, mode='post'):
- '''
- IPDB callbacks are routines executed on a RT netlink
- message arrival. There are two types of callbacks:
- "post" and "pre" callbacks.
-
- ...
-
- "Post" callbacks are executed after the message is
- processed by IPDB and all corresponding objects are
- created or deleted. Using ipdb reference in "post"
- callbacks you will access the most up-to-date state
- of the IP database.
-
- "Post" callbacks are executed asynchronously in
- separate threads. These threads can work as long
- as you want them to. Callback threads are joined
- occasionally, so for a short time there can exist
- stopped threads.
-
- ...
-
- "Pre" callbacks are synchronous routines, executed
- before the message gets processed by IPDB. It gives
- you the way to patch arriving messages, but also
- places a restriction: until the callback exits, the
- main event IPDB loop is blocked.
-
- Normally, only "post" callbacks are required. But in
- some specific cases "pre" also can be useful.
-
- ...
-
- The routine, `register_callback()`, takes two arguments:
- - callback function
- - mode (optional, default="post")
-
- The callback should be a routine, that accepts three
- arguments::
-
- cb(ipdb, msg, action)
-
- Arguments are:
-
- - **ipdb** is a reference to IPDB instance, that invokes
- the callback.
- - **msg** is a message arrived
- - **action** is just a msg['event'] field
-
- E.g., to work on a new interface, you should catch
- action == 'RTM_NEWLINK' and with the interface index
- (arrived in msg['index']) get it from IPDB::
-
- index = msg['index']
- interface = ipdb.interfaces[index]
- '''
- lock = threading.Lock()
-
- def safe(*argv, **kwarg):
- with lock:
- callback(*argv, **kwarg)
-
- safe.hook = callback
- if mode == 'post':
- self._post_callbacks.append(safe)
- elif mode == 'pre':
- self._pre_callbacks.append(safe)
-
- def unregister_callback(self, callback, mode='post'):
- if mode == 'post':
- cbchain = self._post_callbacks
- elif mode == 'pre':
- cbchain = self._pre_callbacks
- else:
- raise KeyError('Unknown callback mode')
- for cb in tuple(cbchain):
- if callback == cb.hook:
- for t in tuple(self._cb_threads):
- t.join(3)
- return cbchain.pop(cbchain.index(cb))
-
- def release(self):
- '''
- Shutdown IPDB instance and sync the state. Since
- IPDB is asyncronous, some operations continue in the
- background, e.g. callbacks. So, prior to exit the
- script, it is required to properly shutdown IPDB.
-
- The shutdown sequence is not forced in an interactive
- python session, since it is easier for users and there
- is enough time to sync the state. But for the scripts
- the `release()` call is required.
- '''
- with self._shutdown_lock:
- if self._stop:
- return
-
- self._stop = True
- try:
- self.nl.put({'index': 1}, RTM_GETLINK)
- self._mthread.join()
- except Exception:
- # Just give up.
- # We can not handle this case
- pass
- self.nl.close()
- self.nl = None
-
- # flush all the objects
- # -- interfaces
- for key in tuple(self.interfaces.keys()):
- self.detach(key)
- # -- routes
- for key in tuple(self.routes.tables.keys()):
- del self.routes.tables[key]
- self.routes.tables[254] = None
- # -- ipaddr
- for key in tuple(self.ipaddr.keys()):
- del self.ipaddr[key]
- # -- neighbors
- for key in tuple(self.neighbors.keys()):
- del self.neighbors[key]
-
- def create(self, kind, ifname, reuse=False, **kwarg):
- '''
- Create an interface. Arguments 'kind' and 'ifname' are
- required.
-
- - kind — interface type, can be of:
- - bridge
- - bond
- - vlan
- - tun
- - dummy
- - veth
- - macvlan
- - macvtap
- - gre
- - team
- - ovs-bridge
- - ifname — interface name
- - reuse — if such interface exists, return it anyway
-
- Different interface kinds can require different
- arguments for creation.
-
- â–º **veth**
-
- To properly create `veth` interface, one should specify
- `peer` also, since `veth` interfaces are created in pairs::
-
- with ip.create(ifname='v1p0', kind='veth', peer='v1p1') as i:
- i.add_ip('10.0.0.1/24')
- i.add_ip('10.0.0.2/24')
-
- The code above creates two interfaces, `v1p0` and `v1p1`, and
- adds two addresses to `v1p0`.
-
- â–º **macvlan**
-
- Macvlan interfaces act like VLANs within OS. The macvlan driver
- provides an ability to add several MAC addresses on one interface,
- where every MAC address is reflected with a virtual interface in
- the system.
-
- In some setups macvlan interfaces can replace bridge interfaces,
- providing more simple and at the same time high-performance
- solution::
-
- ip.create(ifname='mvlan0',
- kind='macvlan',
- link=ip.interfaces.em1,
- macvlan_mode='private').commit()
-
- Several macvlan modes are available: 'private', 'vepa', 'bridge',
- 'passthru'. Ususally the default is 'vepa'.
-
- â–º **macvtap**
-
- Almost the same as macvlan, but creates also a character tap device::
-
- ip.create(ifname='mvtap0',
- kind='macvtap',
- link=ip.interfaces.em1,
- macvtap_mode='vepa').commit()
-
- Will create a device file `"/dev/tap%s" % ip.interfaces.mvtap0.index`
-
- â–º **gre**
-
- Create GRE tunnel::
-
- with ip.create(ifname='grex',
- kind='gre',
- gre_local='172.16.0.1',
- gre_remote='172.16.0.101',
- gre_ttl=16) as i:
- i.add_ip('192.168.0.1/24')
- i.up()
-
-
- â–º **vlan**
-
- VLAN interfaces require additional parameters, `vlan_id` and
- `link`, where `link` is a master interface to create VLAN on::
-
- ip.create(ifname='v100',
- kind='vlan',
- link=ip.interfaces.eth0,
- vlan_id=100)
-
- ip.create(ifname='v100',
- kind='vlan',
- link=1,
- vlan_id=100)
-
- The `link` parameter should be either integer, interface id, or
- an interface object. VLAN id must be integer.
-
- â–º **vxlan**
-
- VXLAN interfaces are like VLAN ones, but require a bit more
- parameters::
-
- ip.create(ifname='vx101',
- kind='vxlan',
- vxlan_link=ip.interfaces.eth0,
- vxlan_id=101,
- vxlan_group='239.1.1.1',
- vxlan_ttl=16)
-
- All possible vxlan parameters are listed in the module
- `pyroute2.netlink.rtnl.ifinfmsg:... vxlan_data`.
-
- â–º **tuntap**
-
- Possible `tuntap` keywords:
-
- - `mode` — "tun" or "tap"
- - `uid` — integer
- - `gid` — integer
- - `ifr` — dict of tuntap flags (see tuntapmsg.py)
- '''
- with self.exclusive:
- # check for existing interface
- if ifname in self.interfaces:
- if self.interfaces[ifname]._flicker or reuse:
- device = self.interfaces[ifname]
- device._flicker = False
- else:
- raise CreateException("interface %s exists" %
- ifname)
- else:
- device = \
- self.by_name[ifname] = \
- self.interfaces[ifname] = \
- self.iclass(ipdb=self, mode='snapshot')
- device.update(kwarg)
- if isinstance(kwarg.get('link', None), Interface):
- device['link'] = kwarg['link']['index']
- if isinstance(kwarg.get('vxlan_link', None), Interface):
- device['vxlan_link'] = kwarg['vxlan_link']['index']
- device['kind'] = kind
- device['index'] = kwarg.get('index', 0)
- device['ifname'] = ifname
- device._mode = self.mode
- tid = device.begin()
- #
- # All the device methods are handled via `transactional.update()`
- # except of the very creation.
- #
- # Commit the changes in the 'direct' mode, since this call is not
- # decorated.
- if self.mode == 'direct':
- device.commit(tid)
- return device
-
- def device_del(self, msg):
- # check for flicker devices
- if (msg.get('index', None) in self.interfaces) and \
- self.interfaces[msg['index']]._flicker:
- self.interfaces[msg['index']].sync()
- return
- try:
- self.update_slaves(msg)
- if msg['change'] == 0xffffffff:
- # FIXME catch exception
- ifname = self.interfaces[msg['index']]['ifname']
- self.interfaces[msg['index']].sync()
- del self.by_name[ifname]
- del self.by_index[msg['index']]
- del self.interfaces[ifname]
- del self.interfaces[msg['index']]
- del self.ipaddr[msg['index']]
- del self.neighbors[msg['index']]
- except KeyError:
- pass
-
- def device_put(self, msg, skip_slaves=False):
- # check, if a record exists
- index = msg.get('index', None)
- ifname = msg.get_attr('IFLA_IFNAME', None)
- # scenario #1: no matches for both: new interface
- # scenario #2: ifname exists, index doesn't: index changed
- # scenario #3: index exists, ifname doesn't: name changed
- # scenario #4: both exist: assume simple update and
- # an optional name change
- if ((index not in self.interfaces) and
- (ifname not in self.interfaces)):
- # scenario #1, new interface
- if compat.fix_check_link(self.nl, index):
- return
- device = \
- self.by_index[index] = \
- self.interfaces[index] = \
- self.interfaces[ifname] = \
- self.by_name[ifname] = self.iclass(ipdb=self)
- elif ((index not in self.interfaces) and
- (ifname in self.interfaces)):
- # scenario #2, index change
- old_index = self.interfaces[ifname]['index']
- device = \
- self.interfaces[index] = \
- self.by_index[index] = self.interfaces[ifname]
- if old_index in self.interfaces:
- del self.interfaces[old_index]
- del self.by_index[old_index]
- if old_index in self.ipaddr:
- self.ipaddr[index] = self.ipaddr[old_index]
- del self.ipaddr[old_index]
- if old_index in self.neighbors:
- self.neighbors[index] = self.neighbors[old_index]
- del self.neighbors[old_index]
- else:
- # scenario #3, interface rename
- # scenario #4, assume rename
- old_name = self.interfaces[index]['ifname']
- if old_name != ifname:
- # unlink old name
- del self.interfaces[old_name]
- del self.by_name[old_name]
- device = \
- self.interfaces[ifname] = \
- self.by_name[ifname] = self.interfaces[index]
-
- if index not in self.ipaddr:
- # for interfaces, created by IPDB
- self.ipaddr[index] = IPaddrSet()
-
- if index not in self.neighbors:
- self.neighbors[index] = LinkedSet()
-
- device.load_netlink(msg)
-
- if not skip_slaves:
- self.update_slaves(msg)
-
- def detach(self, item):
- with self.exclusive:
- if item in self.interfaces:
- del self.interfaces[item]
- if item in self.by_name:
- del self.by_name[item]
- if item in self.by_index:
- del self.by_index[item]
-
- def watchdog(self, action='RTM_NEWLINK', **kwarg):
- return Watchdog(self, action, kwarg)
-
- def update_routes(self, routes):
- for msg in routes:
- self.routes.load_netlink(msg)
-
- def _lookup_master(self, msg):
- master = None
- # lookup for IFLA_OVS_MASTER_IFNAME
- li = msg.get_attr('IFLA_LINKINFO')
- if li:
- data = li.get_attr('IFLA_INFO_DATA')
- if data:
- try:
- master = data.get_attr('IFLA_OVS_MASTER_IFNAME')
- except AttributeError:
- # IFLA_INFO_DATA can be undecoded, in that case
- # it will be just a string with a hex dump
- pass
- # lookup for IFLA_MASTER
- if master is None:
- master = msg.get_attr('IFLA_MASTER')
- # pls keep in mind, that in the case of IFLA_MASTER
- # lookup is done via interface index, while in the case
- # of IFLA_OVS_MASTER_IFNAME lookup is done via ifname
- return self.interfaces.get(master, None)
-
- def update_slaves(self, msg):
- # Update slaves list -- only after update IPDB!
-
- master = self._lookup_master(msg)
- index = msg['index']
- # there IS a master for the interface
- if master is not None:
- if msg['event'] == 'RTM_NEWLINK':
- # TODO tags: ipdb
- # The code serves one particular case, when
- # an enslaved interface is set to belong to
- # another master. In this case there will be
- # no 'RTM_DELLINK', only 'RTM_NEWLINK', and
- # we can end up in a broken state, when two
- # masters refers to the same slave
- for device in self.by_index:
- if index in self.interfaces[device]['ports']:
- self.interfaces[device].del_port(index,
- direct=True)
- master.add_port(index, direct=True)
- elif msg['event'] == 'RTM_DELLINK':
- if index in master['ports']:
- master.del_port(index, direct=True)
- # there is NO masters for the interface, clean them if any
- else:
- device = self.interfaces[msg['index']]
-
- # clean device from ports
- for master in self.by_index:
- if index in self.interfaces[master]['ports']:
- self.interfaces[master].del_port(index,
- direct=True)
- master = device.if_master
- if master is not None:
- if 'master' in device:
- device.del_item('master')
- if (master in self.interfaces) and \
- (msg['index'] in self.interfaces[master].ports):
- self.interfaces[master].del_port(msg['index'],
- direct=True)
-
- def update_addr(self, addrs, action='add'):
- # Update address list of an interface.
-
- for addr in addrs:
- nla = get_addr_nla(addr)
- if nla is not None:
- try:
- method = getattr(self.ipaddr[addr['index']], action)
- method(key=(nla, addr['prefixlen']), raw=addr)
- except:
- pass
-
- def update_neighbors(self, neighs, action='add'):
-
- for neigh in neighs:
- nla = neigh.get_attr('NDA_DST')
- if nla is not None:
- try:
- method = getattr(self.neighbors[neigh['ifindex']], action)
- method(key=nla, raw=neigh)
- except:
- pass
-
- def serve_forever(self):
- '''
- Main monitoring cycle. It gets messages from the
- default iproute queue and updates objects in the
- database.
-
- .. note::
- Should not be called manually.
- '''
- while not self._stop:
- try:
- messages = self.nl.get()
- ##
- # Check it again
- #
- # NOTE: one should not run callbacks or
- # anything like that after setting the
- # _stop flag, since IPDB is not valid
- # anymore
- if self._stop:
- break
- except:
- logging.error('Restarting IPDB instance after '
- 'error:\n%s', traceback.format_exc())
- if self.restart_on_error:
- self.initdb()
- continue
- else:
- raise RuntimeError('Emergency shutdown')
- for msg in messages:
- # Run pre-callbacks
- # NOTE: pre-callbacks are synchronous
- for cb in self._pre_callbacks:
- try:
- cb(self, msg, msg['event'])
- except:
- pass
-
- with self.exclusive:
- # FIXME: refactor it to a dict
- if msg.get('event', None) == 'RTM_NEWLINK':
- self.device_put(msg)
- self._links_event.set()
- elif msg.get('event', None) == 'RTM_DELLINK':
- self.device_del(msg)
- elif msg.get('event', None) == 'RTM_NEWADDR':
- self.update_addr([msg], 'add')
- elif msg.get('event', None) == 'RTM_DELADDR':
- self.update_addr([msg], 'remove')
- elif msg.get('event', None) == 'RTM_NEWNEIGH':
- self.update_neighbors([msg], 'add')
- elif msg.get('event', None) == 'RTM_DELNEIGH':
- self.update_neighbors([msg], 'remove')
- elif msg.get('event', None) in ('RTM_NEWROUTE'
- 'RTM_DELROUTE'):
- self.update_routes([msg])
-
- # run post-callbacks
- # NOTE: post-callbacks are asynchronous
- for cb in self._post_callbacks:
- t = threading.Thread(name="callback %s" % (id(cb)),
- target=cb,
- args=(self, msg, msg['event']))
- t.start()
- self._cb_threads.add(t)
-
- # occasionally join cb threads
- for t in tuple(self._cb_threads):
- t.join(0)
- if not t.is_alive():
- self._cb_threads.remove(t)
diff --git a/node-admin/scripts/pyroute2/ipdb/common.py b/node-admin/scripts/pyroute2/ipdb/common.py
deleted file mode 100644
index 0e915e47c64..00000000000
--- a/node-admin/scripts/pyroute2/ipdb/common.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-import time
-import errno
-from pyroute2.common import ANCIENT
-from pyroute2.netlink import NetlinkError
-# How long should we wait on EACH commit() checkpoint: for ipaddr,
-# ports etc. That's not total commit() timeout.
-SYNC_TIMEOUT = 5
-
-
-class DeprecationException(Exception):
- pass
-
-
-class CommitException(Exception):
- pass
-
-
-class CreateException(Exception):
- pass
-
-
-def bypass(f):
- if ANCIENT:
- return f
- else:
- return staticmethod(lambda *x, **y: None)
-
-
-class compat(object):
- '''
- A namespace to keep all compat-related methods.
- '''
- @bypass
- @staticmethod
- def fix_timeout(timeout):
- time.sleep(timeout)
-
- @bypass
- @staticmethod
- def fix_check_link(nl, index):
- # check, if the link really exists --
- # on some old kernels you can receive
- # broadcast RTM_NEWLINK after the link
- # was deleted
- try:
- nl.get_links(index)
- except NetlinkError as e:
- if e.code == errno.ENODEV: # No such device
- # just drop this message then
- return True
diff --git a/node-admin/scripts/pyroute2/ipdb/interface.py b/node-admin/scripts/pyroute2/ipdb/interface.py
deleted file mode 100644
index a2c4f72ec1b..00000000000
--- a/node-admin/scripts/pyroute2/ipdb/interface.py
+++ /dev/null
@@ -1,709 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-import time
-import errno
-import socket
-import threading
-import traceback
-from pyroute2 import config
-from pyroute2.common import basestring
-from pyroute2.common import dqn2int
-from pyroute2.netlink import NetlinkError
-from pyroute2.netlink.rtnl.req import IPLinkRequest
-from pyroute2.netlink.rtnl.ifinfmsg import IFF_MASK
-from pyroute2.netlink.rtnl.ifinfmsg import ifinfmsg
-from pyroute2.ipdb.transactional import Transactional
-from pyroute2.ipdb.transactional import update
-from pyroute2.ipdb.linkedset import LinkedSet
-from pyroute2.ipdb.linkedset import IPaddrSet
-from pyroute2.ipdb.common import CommitException
-from pyroute2.ipdb.common import SYNC_TIMEOUT
-from pyroute2.ipdb.common import compat
-
-
-class Interface(Transactional):
- '''
- Objects of this class represent network interface and
- all related objects:
- * addresses
- * (todo) neighbors
- * (todo) routes
-
- Interfaces provide transactional model and can act as
- context managers. Any attribute change implicitly
- starts a transaction. The transaction can be managed
- with three methods:
- * review() -- review changes
- * rollback() -- drop all the changes
- * commit() -- try to apply changes
-
- If anything will go wrong during transaction commit,
- it will be rolled back authomatically and an
- exception will be raised. Failed transaction review
- will be attached to the exception.
- '''
- _fields_cmp = {'flags': lambda x, y: x & y & IFF_MASK == y & IFF_MASK}
-
- def __init__(self, ipdb, mode=None, parent=None, uid=None):
- '''
- Parameters:
- * ipdb -- ipdb() reference
- * mode -- transaction mode
- '''
- Transactional.__init__(self, ipdb, mode)
- self.cleanup = ('header',
- 'linkinfo',
- 'af_spec',
- 'attrs',
- 'event',
- 'map',
- 'stats',
- 'stats64',
- '__align')
- self.ingress = None
- self.egress = None
- self._exists = False
- self._flicker = False
- self._exception = None
- self._tb = None
- self._virtual_fields = ('removal', 'flicker', 'state')
- self._xfields = {'common': [ifinfmsg.nla2name(i[0]) for i
- in ifinfmsg.nla_map]}
- self._xfields['common'].append('index')
- self._xfields['common'].append('flags')
- self._xfields['common'].append('mask')
- self._xfields['common'].append('change')
- self._xfields['common'].append('kind')
- self._xfields['common'].append('peer')
- self._xfields['common'].append('vlan_id')
- self._xfields['common'].append('bond_mode')
-
- for data in ('bridge_data',
- 'bond_data',
- 'tuntap_data',
- 'vxlan_data',
- 'gre_data',
- 'macvlan_data',
- 'macvtap_data'):
- msg = getattr(ifinfmsg.ifinfo, data)
- self._xfields['common'].extend([msg.nla2name(i[0]) for i
- in msg.nla_map])
- for ftype in self._xfields:
- self._fields += self._xfields[ftype]
- self._fields.extend(self._virtual_fields)
- self._load_event = threading.Event()
- self._linked_sets.add('ipaddr')
- self._linked_sets.add('ports')
- self._freeze = None
- # 8<-----------------------------------
- # local setup: direct state is required
- with self._direct_state:
- self['ipaddr'] = IPaddrSet()
- self['ports'] = LinkedSet()
- for i in self._fields:
- self[i] = None
- for i in ('state', 'change', 'mask'):
- del self[i]
- # 8<-----------------------------------
-
- def __hash__(self):
- return self['index']
-
- @property
- def if_master(self):
- '''
- [property] Link to the parent interface -- if it exists
- '''
- return self.get('master', None)
-
- def freeze(self):
- dump = self.dump()
-
- def cb(ipdb, msg, action):
- if msg.get('index', -1) == dump['index']:
- tr = self.load(dump)
- for _ in range(3):
- try:
- self.commit(transaction=tr)
- except (CommitException, RuntimeError):
- # ignore here both CommitExceptions
- # and RuntimeErrors (aka rollback errors),
- # since ususally it is a races between
- # 3d party setup and freeze; just
- # sliently try again for several times
- continue
- except NetlinkError:
- # on the netlink errors just give up
- pass
- break
-
- self._freeze = cb
- self.ipdb.register_callback(self._freeze)
- return self
-
- def unfreeze(self):
- self.ipdb.unregister_callback(self._freeze)
- self._freeze = None
- return self
-
- def load(self, data):
- with self._write_lock:
- template = self.__class__(ipdb=self.ipdb, mode='snapshot')
- template.load_dict(data)
- return template
-
- def load_dict(self, data):
- with self._direct_state:
- for key in data:
- if key == 'ipaddr':
- for addr in data[key]:
- if isinstance(addr, basestring):
- addr = (addr, )
- self.add_ip(*addr)
- elif key == 'ports':
- for port in data[key]:
- self.add_port(port)
- elif key == 'neighbors':
- # ignore neighbors on load
- pass
- else:
- self[key] = data[key]
-
- def load_netlink(self, dev):
- '''
- Update the interface info from RTM_NEWLINK message.
-
- This call always bypasses open transactions, loading
- changes directly into the interface data.
- '''
- with self._direct_state:
- self._exists = True
- self.nlmsg = dev
- for (name, value) in dev.items():
- self[name] = value
- for item in dev['attrs']:
- name, value = item[:2]
- norm = ifinfmsg.nla2name(name)
- self[norm] = value
- # load interface kind
- linkinfo = dev.get_attr('IFLA_LINKINFO')
- if linkinfo is not None:
- kind = linkinfo.get_attr('IFLA_INFO_KIND')
- if kind is not None:
- self['kind'] = kind
- if kind == 'vlan':
- data = linkinfo.get_attr('IFLA_INFO_DATA')
- self['vlan_id'] = data.get_attr('IFLA_VLAN_ID')
- if kind in ('vxlan', 'macvlan', 'macvtap', 'gre'):
- data = linkinfo.get_attr('IFLA_INFO_DATA')
- for nla in data.get('attrs', []):
- norm = ifinfmsg.nla2name(nla[0])
- self[norm] = nla[1]
- # get OVS master and override IFLA_MASTER value
- try:
- data = linkinfo.get_attr('IFLA_INFO_DATA')
- master = data.get_attr('IFLA_OVS_MASTER_IFNAME')
- self['master'] = self.ipdb.interfaces[master].index
- except (AttributeError, KeyError):
- pass
- # the rest is possible only when interface
- # is used in IPDB, not standalone
- if self.ipdb is not None:
- self['ipaddr'] = self.ipdb.ipaddr[self['index']]
- self['neighbors'] = self.ipdb.neighbors[self['index']]
- # finally, cleanup all not needed
- for item in self.cleanup:
- if item in self:
- del self[item]
-
- self.sync()
-
- def sync(self):
- self._load_event.set()
-
- @update
- def add_ip(self, direct, ip, mask=None,
- brd=None, broadcast=None):
- '''
- Add IP address to an interface
- '''
- # split mask
- if mask is None:
- ip, mask = ip.split('/')
- if mask.find('.') > -1:
- mask = dqn2int(mask)
- else:
- mask = int(mask, 0)
- elif isinstance(mask, basestring):
- mask = dqn2int(mask)
- brd = brd or broadcast
- # FIXME: make it more generic
- # skip IPv6 link-local addresses
- if ip[:4] == 'fe80' and mask == 64:
- return self
- if not direct:
- transaction = self.last()
- transaction.add_ip(ip, mask, brd)
- else:
- self['ipaddr'].unlink((ip, mask))
- if brd is not None:
- raw = {'IFA_BROADCAST': brd}
- self['ipaddr'].add((ip, mask), raw=raw)
- else:
- self['ipaddr'].add((ip, mask))
- return self
-
- @update
- def del_ip(self, direct, ip, mask=None):
- '''
- Delete IP address from an interface
- '''
- if mask is None:
- ip, mask = ip.split('/')
- if mask.find('.') > -1:
- mask = dqn2int(mask)
- else:
- mask = int(mask, 0)
- if not direct:
- transaction = self.last()
- if (ip, mask) in transaction['ipaddr']:
- transaction.del_ip(ip, mask)
- else:
- self['ipaddr'].unlink((ip, mask))
- self['ipaddr'].remove((ip, mask))
- return self
-
- @update
- def add_port(self, direct, port):
- '''
- Add a slave port to a bridge or bonding
- '''
- if isinstance(port, Interface):
- port = port['index']
- if not direct:
- transaction = self.last()
- transaction.add_port(port)
- else:
- self['ports'].unlink(port)
- self['ports'].add(port)
- return self
-
- @update
- def del_port(self, direct, port):
- '''
- Remove a slave port from a bridge or bonding
- '''
- if isinstance(port, Interface):
- port = port['index']
- if not direct:
- transaction = self.last()
- if port in transaction['ports']:
- transaction.del_port(port)
- else:
- self['ports'].unlink(port)
- self['ports'].remove(port)
- return self
-
- def reload(self):
- '''
- Reload interface information
- '''
- countdown = 3
- while countdown:
- links = self.nl.get_links(self['index'])
- if links:
- self.load_netlink(links[0])
- break
- else:
- countdown -= 1
- time.sleep(1)
- return self
-
- def filter(self, ftype):
- ret = {}
- for key in self:
- if key in self._xfields[ftype]:
- ret[key] = self[key]
- return ret
-
- def commit(self, tid=None, transaction=None, rollback=False, newif=False):
- '''
- Commit transaction. In the case of exception all
- changes applied during commit will be reverted.
- '''
- error = None
- added = None
- removed = None
- drop = True
- if tid:
- transaction = self._transactions[tid]
- else:
- if transaction:
- drop = False
- else:
- transaction = self.last()
-
- wd = None
- with self._write_lock:
- # if the interface does not exist, create it first ;)
- if not self._exists:
- request = IPLinkRequest(self.filter('common'))
-
- # create watchdog
- wd = self.ipdb.watchdog(ifname=self['ifname'])
-
- newif = True
- try:
- # 8<----------------------------------------------------
- # ACHTUNG: hack for old platforms
- if request.get('address', None) == '00:00:00:00:00:00':
- del request['address']
- del request['broadcast']
- # 8<----------------------------------------------------
- try:
- self.nl.link('add', **request)
- except NetlinkError as x:
- # File exists
- if x.code == errno.EEXIST:
- # A bit special case, could be one of two cases:
- #
- # 1. A race condition between two different IPDB
- # processes
- # 2. An attempt to create dummy0, gre0, bond0 when
- # the corrseponding module is not loaded. Being
- # loaded, the module creates a default interface
- # by itself, causing the request to fail
- #
- # The exception in that case can cause the DB
- # inconsistence, since there can be queued not only
- # the interface creation, but also IP address
- # changes etc.
- #
- # So we ignore this particular exception and try to
- # continue, as it is created by us.
- pass
-
- # Operation not supported
- elif x.code == errno.EOPNOTSUPP and \
- request.get('index', 0) != 0:
- # ACHTUNG: hack for old platforms
- request = IPLinkRequest({'ifname': self['ifname'],
- 'kind': self['kind'],
- 'index': 0})
- self.nl.link('add', **request)
- else:
- raise
- except Exception as e:
- # on failure, invalidate the interface and detach it
- # from the parent
- # 1. drop the IPRoute() link
- self.nl = None
- # 2. clean up ipdb
- self.ipdb.detach(self['index'])
- self.ipdb.detach(self['ifname'])
- # 3. invalidate the interface
- with self._direct_state:
- for i in tuple(self.keys()):
- del self[i]
- # 4. the rest
- self._mode = 'invalid'
- self._exception = e
- self._tb = traceback.format_exc()
- # raise the exception
- raise
-
- if wd is not None:
- wd.wait()
-
- # now we have our index and IP set and all other stuff
- snapshot = self.pick()
-
- try:
- removed = snapshot - transaction
- added = transaction - snapshot
-
- # 8<---------------------------------------------
- # Interface slaves
- self['ports'].set_target(transaction['ports'])
-
- for i in removed['ports']:
- # detach the port
- port = self.ipdb.interfaces[i]
- port.set_target('master', None)
- port.mirror_target('master', 'link')
- self.nl.link('set', index=port['index'], master=0)
-
- for i in added['ports']:
- # enslave the port
- port = self.ipdb.interfaces[i]
- port.set_target('master', self['index'])
- port.mirror_target('master', 'link')
- self.nl.link('set',
- index=port['index'],
- master=self['index'])
-
- if removed['ports'] or added['ports']:
- self.nl.get_links(*(removed['ports'] | added['ports']))
- self['ports'].target.wait(SYNC_TIMEOUT)
- if not self['ports'].target.is_set():
- raise CommitException('ports target is not set')
-
- # RHEL 6.5 compat fix -- an explicit timeout
- # it gives a time for all the messages to pass
- compat.fix_timeout(1)
-
- # wait for proper targets on ports
- for i in list(added['ports']) + list(removed['ports']):
- port = self.ipdb.interfaces[i]
- target = port._local_targets['master']
- target.wait(SYNC_TIMEOUT)
- del port._local_targets['master']
- del port._local_targets['link']
- if not target.is_set():
- raise CommitException('master target failed')
- if i in added['ports']:
- assert port.if_master == self['index']
- else:
- assert port.if_master != self['index']
-
- # 8<---------------------------------------------
- # Interface changes
- request = IPLinkRequest()
- for key in added:
- if key in self._xfields['common']:
- request[key] = added[key]
- request['index'] = self['index']
-
- # apply changes only if there is something to apply
- if any([request[item] is not None for item in request
- if item != 'index']):
- self.nl.link('set', **request)
- # hardcoded pause -- if the interface was moved
- # across network namespaces
- if 'net_ns_fd' in request:
- while True:
- # wait until the interface will disappear
- # from the main network namespace
- try:
- self.nl.get_links(self['index'])
- except NetlinkError as e:
- if e.code == errno.ENODEV:
- break
- raise
- except Exception:
- raise
- time.sleep(0.1)
-
- # 8<---------------------------------------------
- # IP address changes
- self['ipaddr'].set_target(transaction['ipaddr'])
-
- for i in removed['ipaddr']:
- # Ignore link-local IPv6 addresses
- if i[0][:4] == 'fe80' and i[1] == 64:
- continue
- # When you remove a primary IP addr, all subnetwork
- # can be removed. In this case you will fail, but
- # it is OK, no need to roll back
- try:
- self.nl.addr('delete', self['index'], i[0], i[1])
- except NetlinkError as x:
- # bypass only errno 99, 'Cannot assign address'
- if x.code != errno.EADDRNOTAVAIL:
- raise
- except socket.error as x:
- # bypass illegal IP requests
- if not x.args[0].startswith('illegal IP'):
- raise
-
- for i in added['ipaddr']:
- # Ignore link-local IPv6 addresses
- if i[0][:4] == 'fe80' and i[1] == 64:
- continue
- # Try to fetch additional address attributes
- try:
- kwarg = transaction.ipaddr[i]
- except KeyError:
- kwarg = None
- self.nl.addr('add', self['index'], i[0], i[1],
- **kwarg if kwarg else {})
-
- # 8<--------------------------------------
- # FIXME: kernel bug, sometimes `addr add` for
- # bond interfaces returns success, but does
- # really nothing
-
- if self['kind'] == 'bond':
- while True:
- try:
- # dirtiest hack, but we have to use it here
- time.sleep(0.1)
- self.nl.addr('add', self['index'], i[0], i[1])
- # continue to try to add the address
- # until the kernel reports `file exists`
- #
- # a stupid solution, but must help
- except NetlinkError as e:
- if e.code == errno.EEXIST:
- break
- else:
- raise
- except Exception:
- raise
- # 8<--------------------------------------
-
- if removed['ipaddr'] or added['ipaddr']:
- # 8<--------------------------------------
- # bond and bridge interfaces do not send
- # IPv6 address updates, when are down
- #
- # beside of that, bridge interfaces are
- # down by default, so they never send
- # address updates from beginning
- #
- # so if we need, force address load
- #
- # FIXME: probably, we should handle other
- # types as well
- if self['kind'] in ('bond', 'bridge', 'veth'):
- self.nl.get_addr()
- # 8<--------------------------------------
- self['ipaddr'].target.wait(SYNC_TIMEOUT)
- if not self['ipaddr'].target.is_set():
- raise CommitException('ipaddr target is not set')
-
- # 8<---------------------------------------------
- # reload interface to hit targets
- if transaction._targets:
- try:
- self.reload()
- except NetlinkError as e:
- if e.code == errno.ENODEV: # No such device
- if ('net_ns_fd' in added) or \
- ('net_ns_pid' in added):
- # it means, that the device was moved
- # to another netns; just give up
- if drop:
- self.drop(transaction)
- return self
-
- # wait for targets
- transaction._wait_all_targets()
-
- # 8<---------------------------------------------
- # Interface removal
- if added.get('removal') or \
- added.get('flicker') or\
- (newif and rollback):
- wd = self.ipdb.watchdog(action='RTM_DELLINK',
- ifname=self['ifname'])
- if added.get('flicker'):
- self._flicker = True
- self.nl.link('delete', **self)
- wd.wait()
- if added.get('flicker'):
- self._exists = False
- if added.get('removal'):
- self._mode = 'invalid'
- if drop:
- self.drop(transaction)
- return self
- # 8<---------------------------------------------
-
- # Iterate callback chain
- for ch in self._commit_hooks:
- # An exception will rollback the transaction
- ch(self.dump(), snapshot.dump(), transaction.dump())
- # 8<---------------------------------------------
-
- except Exception as e:
- # something went wrong: roll the transaction back
- if not rollback:
- ret = self.commit(transaction=snapshot,
- rollback=True,
- newif=newif)
- # if some error was returned by the internal
- # closure, substitute the initial one
- if isinstance(ret, Exception):
- error = ret
- else:
- error = e
- error.traceback = traceback.format_exc()
- elif isinstance(e, NetlinkError) and \
- getattr(e, 'code', 0) == errno.EPERM:
- # It is <Operation not permitted>, catched in
- # rollback. So return it -- see ~5 lines above
- e.traceback = traceback.format_exc()
- return e
- else:
- # somethig went wrong during automatic rollback.
- # that's the worst case, but it is still possible,
- # since we have no locks on OS level.
- self['ipaddr'].set_target(None)
- self['ports'].set_target(None)
- # reload all the database -- it can take a long time,
- # but it is required since we have no idea, what is
- # the result of the failure
- #
- # ACHTUNG: database reload is asynchronous, so after
- # getting RuntimeError() from commit(), take a seat
- # and rest for a while. It is an extremal case, it
- # should not became at all, and there is no sync.
- self.nl.get_links()
- self.nl.get_addr()
- x = RuntimeError()
- x.cause = e
- x.traceback = traceback.format_exc()
- raise x
-
- # if it is not a rollback turn
- if drop and not rollback:
- # drop last transaction in any case
- self.drop(transaction)
-
- # raise exception for failed transaction
- if error is not None:
- error.transaction = transaction
- raise error
-
- time.sleep(config.commit_barrier)
- return self
-
- def up(self):
- '''
- Shortcut: change the interface state to 'up'.
- '''
- if self['flags'] is None:
- self['flags'] = 1
- else:
- self['flags'] |= 1
- return self
-
- def down(self):
- '''
- Shortcut: change the interface state to 'down'.
- '''
- if self['flags'] is None:
- self['flags'] = 0
- else:
- self['flags'] &= ~(self['flags'] & 1)
- return self
-
- def remove(self):
- '''
- Mark the interface for removal
- '''
- self['removal'] = True
- return self
-
- def shadow(self):
- '''
- Remove the interface from the OS, but leave it in the
- database. When one will try to re-create interface with
- the same name, all the old saved attributes will apply
- to the new interface, incl. MAC-address and even the
- interface index. Please be aware, that the interface
- index can be reused by OS while the interface is "in the
- shadow state", in this case re-creation will fail.
- '''
- self['flicker'] = True
- return self
diff --git a/node-admin/scripts/pyroute2/ipdb/linkedset.py b/node-admin/scripts/pyroute2/ipdb/linkedset.py
deleted file mode 100644
index 15c762f3670..00000000000
--- a/node-admin/scripts/pyroute2/ipdb/linkedset.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-'''
-import threading
-
-
-class LinkedSet(set):
- '''
- Utility class, used by `Interface` to track ip addresses
- and ports. Called "linked" as it automatically updates all
- instances, linked with it.
-
- Target filter is a function, that returns `True` if a set
- member should be counted in target checks (target methods
- see below), or `False` if it should be ignored.
- '''
- def target_filter(self, x):
- return True
-
- def __init__(self, *argv, **kwarg):
- set.__init__(self, *argv, **kwarg)
- self.lock = threading.RLock()
- self.target = threading.Event()
- self._ct = None
- self.raw = {}
- self.links = []
- self.exclusive = set()
-
- def __getitem__(self, key):
- return self.raw[key]
-
- def set_target(self, value):
- '''
- Set target state for the object and clear the target
- event. Once the target is reached, the event will be
- set, see also: `check_target()`
-
- Args:
- - value (set): the target state to compare with
- '''
- with self.lock:
- if value is None:
- self._ct = None
- self.target.clear()
- else:
- self._ct = set(value)
- self.target.clear()
- # immediately check, if the target already
- # reached -- otherwise you will miss the
- # target forever
- self.check_target()
-
- def check_target(self):
- '''
- Check the target state and set the target event in the
- case the state is reached. Called from mutators, `add()`
- and `remove()`
- '''
- with self.lock:
- if self._ct is not None:
- if set(filter(self.target_filter, self)) == \
- set(filter(self.target_filter, self._ct)):
- self._ct = None
- self.target.set()
-
- def add(self, key, raw=None, cascade=False):
- '''
- Add an item to the set and all connected instances,
- check the target state.
-
- Args:
- - key: any hashable object
- - raw (optional): raw representation of the object
-
- Raw representation is not required. It can be used, e.g.,
- to store RTM_NEWADDR RTNL messages along with
- human-readable ip addr representation.
- '''
- with self.lock:
- if cascade and (key in self.exclusive):
- return
- if key not in self:
- self.raw[key] = raw
- set.add(self, key)
- for link in self.links:
- link.add(key, raw, cascade=True)
- self.check_target()
-
- def remove(self, key, raw=None, cascade=False):
- '''
- Remove an item from the set and all connected instances,
- check the target state.
- '''
- with self.lock:
- if cascade and (key in self.exclusive):
- return
- set.remove(self, key)
- for link in self.links:
- if key in link:
- link.remove(key, cascade=True)
- self.check_target()
-
- def unlink(self, key):
- '''
- Exclude key from cascade updates.
- '''
- self.exclusive.add(key)
-
- def relink(self, key):
- '''
- Do not ignore key on cascade updates.
- '''
- self.exclusive.remove(key)
-
- def connect(self, link):
- '''
- Connect a LinkedSet instance to this one. Connected
- sets will be updated together with this instance.
- '''
- assert isinstance(link, LinkedSet)
- self.links.append(link)
-
- def __repr__(self):
- return repr(list(self))
-
-
-class IPaddrSet(LinkedSet):
- '''
- LinkedSet child class with different target filter. The
- filter ignores link local IPv6 addresses when sets and checks
- the target.
- '''
- def target_filter(self, x):
- return not ((x[0][:4] == 'fe80') and (x[1] == 64))
diff --git a/node-admin/scripts/pyroute2/ipdb/route.py b/node-admin/scripts/pyroute2/ipdb/route.py
deleted file mode 100644
index 86692f3c839..00000000000
--- a/node-admin/scripts/pyroute2/ipdb/route.py
+++ /dev/null
@@ -1,354 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-import logging
-import threading
-from socket import AF_UNSPEC
-from pyroute2.common import basestring
-from pyroute2.netlink import nlmsg
-from pyroute2.netlink.rtnl.rtmsg import rtmsg
-from pyroute2.netlink.rtnl.req import IPRouteRequest
-from pyroute2.ipdb.transactional import Transactional
-
-
-class Metrics(Transactional):
-
- def __init__(self, *argv, **kwarg):
- Transactional.__init__(self, *argv, **kwarg)
- self._fields = [rtmsg.metrics.nla2name(i[0]) for i
- in rtmsg.metrics.nla_map]
-
-
-class RouteKey(dict):
- '''
- Construct from a netlink message a key that can be used
- to locate the route in the table
- '''
- def __init__(self, msg):
- # calculate dst
- if msg.get_attr('RTA_DST', None) is not None:
- dst = '%s/%s' % (msg.get_attr('RTA_DST'),
- msg['dst_len'])
- else:
- dst = 'default'
- self['dst'] = dst
- # use output | input interfaces as key also
- for key in ('oif', 'iif'):
- value = msg.get_attr(msg.name2nla(key))
- if value:
- self[key] = value
-
-
-class Route(Transactional):
- '''
- Persistent transactional route object
- '''
-
- def __init__(self, ipdb, mode=None, parent=None, uid=None):
- Transactional.__init__(self, ipdb, mode, parent, uid)
- self._exists = False
- self._load_event = threading.Event()
- self._fields = [rtmsg.nla2name(i[0]) for i in rtmsg.nla_map]
- self._fields.append('flags')
- self._fields.append('src_len')
- self._fields.append('dst_len')
- self._fields.append('table')
- self._fields.append('removal')
- self.cleanup = ('attrs',
- 'header',
- 'event')
- with self._direct_state:
- self['metrics'] = Metrics(parent=self)
-
- def load_netlink(self, msg):
- with self._direct_state:
- self._exists = True
- self.update(msg)
-
- # re-init metrics
- metrics = self.get('metrics', Metrics(parent=self))
- with metrics._direct_state:
- for metric in tuple(metrics.keys()):
- del metrics[metric]
- self['metrics'] = metrics
-
- # merge key
- for (name, value) in msg['attrs']:
- norm = rtmsg.nla2name(name)
- # normalize RTAX
- if norm == 'metrics':
- with self['metrics']._direct_state:
- for (rtax, rtax_value) in value['attrs']:
- rtax_norm = rtmsg.metrics.nla2name(rtax)
- self['metrics'][rtax_norm] = rtax_value
- else:
- self[norm] = value
-
- if msg.get_attr('RTA_DST', None) is not None:
- dst = '%s/%s' % (msg.get_attr('RTA_DST'),
- msg['dst_len'])
- else:
- dst = 'default'
- self['dst'] = dst
- # finally, cleanup all not needed
- for item in self.cleanup:
- if item in self:
- del self[item]
-
- self.sync()
-
- def sync(self):
- self._load_event.set()
-
- def reload(self):
- # do NOT call get_routes() here, it can cause race condition
- self._load_event.wait()
- return self
-
- def commit(self, tid=None, transaction=None, rollback=False):
- self._load_event.clear()
- error = None
-
- if tid:
- transaction = self._transactions[tid]
- else:
- transaction = transaction or self.last()
-
- # create a new route
- if not self._exists:
- try:
- self.nl.route('add', **IPRouteRequest(self))
- except Exception:
- self.nl = None
- self.ipdb.routes.remove(self)
- raise
-
- # work on existing route
- snapshot = self.pick()
- try:
- # route set
- request = IPRouteRequest(transaction - snapshot)
- if any([request[x] not in (None, {'attrs': []}) for x in request]):
- self.nl.route('set', **IPRouteRequest(transaction))
-
- if transaction.get('removal'):
- self.nl.route('delete', **IPRouteRequest(snapshot))
-
- except Exception as e:
- if not rollback:
- ret = self.commit(transaction=snapshot, rollback=True)
- if isinstance(ret, Exception):
- error = ret
- else:
- error = e
- else:
- self.drop()
- x = RuntimeError()
- x.cause = e
- raise x
-
- if not rollback:
- self.drop()
-
- if error is not None:
- error.transaction = transaction
- raise error
-
- if not rollback:
- self.reload()
-
- return self
-
- def remove(self):
- self['removal'] = True
- return self
-
-
-class RoutingTable(object):
-
- def __init__(self, ipdb, prime=None):
- self.ipdb = ipdb
- self.records = prime or []
-
- def __repr__(self):
- return repr(self.records)
-
- def __len__(self):
- return len(self.records)
-
- def __iter__(self):
- for record in tuple(self.records):
- yield record
-
- def keys(self, key='dst'):
- return [x[key] for x in self.records]
-
- def describe(self, target, forward=True):
- if isinstance(target, int):
- return {'route': self.records[target],
- 'index': target}
- if isinstance(target, basestring):
- target = {'dst': target}
- if not isinstance(target, dict):
- raise TypeError('unsupported key type')
-
- for record in self.records:
- for key in target:
- # skip non-existing keys
- #
- # it's a hack, but newly-created routes
- # don't contain all the fields that are
- # in the netlink message
- if record.get(key) is None:
- continue
- # if any key doesn't match
- if target[key] != record[key]:
- break
- else:
- # if all keys match
- return {'route': record,
- 'index': self.records.index(record)}
-
- if not forward:
- raise KeyError('route not found')
-
- # split masks
- if target.get('dst', '').find('/') >= 0:
- dst = target['dst'].split('/')
- target['dst'] = dst[0]
- target['dst_len'] = int(dst[1])
-
- if target.get('src', '').find('/') >= 0:
- src = target['src'].split('/')
- target['src'] = src[0]
- target['src_len'] = int(src[1])
-
- # load and return the route, if exists
- route = Route(self.ipdb)
- route.load_netlink(self.ipdb.nl.get_routes(**target)[0])
- return {'route': route,
- 'index': None}
-
- def __delitem__(self, key):
- self.records.pop(self.describe(key, forward=False)['index'])
-
- def __setitem__(self, key, value):
- try:
- record = self.describe(key, forward=False)
- except KeyError:
- record = {'route': Route(self.ipdb),
- 'index': None}
-
- if isinstance(value, nlmsg):
- record['route'].load_netlink(value)
- elif isinstance(value, Route):
- record['route'] = value
- elif isinstance(value, dict):
- with record['route']._direct_state:
- record['route'].update(value)
-
- if record['index'] is None:
- self.records.append(record['route'])
- else:
- self.records[record['index']] = record['route']
-
- def __getitem__(self, key):
- return self.describe(key, forward=True)['route']
-
- def __contains__(self, key):
- try:
- self.describe(key, forward=False)
- return True
- except KeyError:
- return False
-
-
-class RoutingTableSet(object):
-
- def __init__(self, ipdb):
- self.ipdb = ipdb
- self.tables = {254: RoutingTable(self.ipdb)}
-
- def add(self, spec=None, **kwarg):
- '''
- Create a route from a dictionary
- '''
- spec = spec or kwarg
- table = spec.get('table', 254)
- assert 'dst' in spec
- if table not in self.tables:
- self.tables[table] = RoutingTable(self.ipdb)
- route = Route(self.ipdb)
- metrics = spec.pop('metrics', {})
- route.update(spec)
- route.metrics.update(metrics)
- self.tables[table][route['dst']] = route
- route.begin()
- return route
-
- def load_netlink(self, msg):
- '''
- Loads an existing route from a rtmsg
- '''
- table = msg.get('table', 254)
- # construct a key
- # FIXME: temporary solution
- # FIXME: can `Route()` be used as a key?
- key = RouteKey(msg)
-
- # RTM_DELROUTE
- if msg['event'] == 'RTM_DELROUTE':
- try:
- # locate the record
- record = self.tables[table][key]
- # delete the record
- del self.tables[table][key]
- # sync ???
- record.sync()
- except Exception as e:
- logging.debug(e)
- logging.debug(msg)
- return
-
- # RTM_NEWROUTE
- if table not in self.tables:
- self.tables[table] = RoutingTable(self.ipdb)
- self.tables[table][key] = msg
- return self.tables[table][key]
-
- def remove(self, route, table=None):
- if isinstance(route, Route):
- table = route.get('table', 254)
- route = route.get('dst', 'default')
- else:
- table = table or 254
- del self.tables[table][route]
-
- def describe(self, spec, table=254):
- return self.tables[table].describe(spec)
-
- def get(self, dst, table=None):
- table = table or 254
- return self.tables[table][dst]
-
- def keys(self, table=254, family=AF_UNSPEC):
- return [x['dst'] for x in self.tables[table]
- if (x['family'] == family)
- or (family == AF_UNSPEC)]
-
- def has_key(self, key, table=254):
- return key in self.tables[table]
-
- def __contains__(self, key):
- return key in self.tables[254]
-
- def __getitem__(self, key):
- return self.get(key)
-
- def __setitem__(self, key, value):
- assert key == value['dst']
- return self.add(value)
-
- def __delitem__(self, key):
- return self.remove(key)
-
- def __repr__(self):
- return repr(self.tables[254])
diff --git a/node-admin/scripts/pyroute2/ipdb/transactional.py b/node-admin/scripts/pyroute2/ipdb/transactional.py
deleted file mode 100644
index 533f3b9fd7f..00000000000
--- a/node-admin/scripts/pyroute2/ipdb/transactional.py
+++ /dev/null
@@ -1,402 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-'''
-import uuid
-import threading
-from pyroute2.common import Dotkeys
-from pyroute2.ipdb.common import SYNC_TIMEOUT
-from pyroute2.ipdb.common import CommitException
-from pyroute2.ipdb.common import DeprecationException
-from pyroute2.ipdb.linkedset import LinkedSet
-
-
-class State(object):
-
- def __init__(self, lock=None):
- self.lock = lock or threading.Lock()
- self.flag = 0
-
- def acquire(self):
- self.lock.acquire()
- self.flag += 1
-
- def release(self):
- assert self.flag > 0
- self.flag -= 1
- self.lock.release()
-
- def is_set(self):
- return self.flag
-
- def __enter__(self):
- self.acquire()
- return self
-
- def __exit__(self, exc_type, exc_value, traceback):
- self.release()
-
-
-def update(f):
- def decorated(self, *argv, **kwarg):
- # obtain update lock
- ret = None
- tid = None
- direct = True
- with self._write_lock:
- dcall = kwarg.pop('direct', False)
- if dcall:
- self._direct_state.acquire()
-
- direct = self._direct_state.is_set()
- if not direct:
- # 1. begin transaction for 'direct' type
- if self._mode == 'direct':
- tid = self.begin()
- # 2. begin transaction, if there is none
- elif self._mode == 'implicit':
- if not self._tids:
- self.begin()
- # 3. require open transaction for 'explicit' type
- elif self._mode == 'explicit':
- if not self._tids:
- raise TypeError('start a transaction first')
- # 4. transactions can not require transactions :)
- elif self._mode == 'snapshot':
- direct = True
- # do not support other modes
- else:
- raise TypeError('transaction mode not supported')
- # now that the transaction _is_ open
- ret = f(self, direct, *argv, **kwarg)
-
- if dcall:
- self._direct_state.release()
-
- if tid:
- # close the transaction for 'direct' type
- self.commit(tid)
-
- return ret
- decorated.__doc__ = f.__doc__
- return decorated
-
-
-class Transactional(Dotkeys):
- '''
- Utility class that implements common transactional logic.
- '''
- _fields_cmp = {}
-
- def __init__(self, ipdb=None, mode=None, parent=None, uid=None):
- #
- if ipdb is not None:
- self.nl = ipdb.nl
- self.ipdb = ipdb
- else:
- self.nl = None
- self.ipdb = None
- #
- self._parent = None
- if parent is not None:
- self._mode = mode or parent._mode
- self._parent = parent
- elif ipdb is not None:
- self._mode = mode or ipdb.mode
- else:
- self._mode = mode or 'implicit'
- #
- self.nlmsg = None
- self.uid = uid or uuid.uuid4()
- self.last_error = None
- self._commit_hooks = []
- self._fields = []
- self._sids = []
- self._ts = threading.local()
- self._snapshots = {}
- self._targets = {}
- self._local_targets = {}
- self._write_lock = threading.RLock()
- self._direct_state = State(self._write_lock)
- self._linked_sets = set()
-
- @property
- def _tids(self):
- if not hasattr(self._ts, 'tids'):
- self._ts.tids = []
- return self._ts.tids
-
- @property
- def _transactions(self):
- if not hasattr(self._ts, 'transactions'):
- self._ts.transactions = {}
- return self._ts.transactions
-
- def register_callback(self, callback):
- raise DeprecationException("deprecated since 0.2.15;"
- "use `register_commit_hook()`")
-
- def register_commit_hook(self, hook):
- # FIXME: write docs
- self._commit_hooks.append(hook)
-
- def unregister_callback(self, callback):
- raise DeprecationException("deprecated since 0.2.15;"
- "use `unregister_commit_hook()`")
-
- def unregister_commit_hook(self, hook):
- # FIXME: write docs
- with self._write_lock:
- for cb in tuple(self._commit_hooks):
- if hook == cb:
- self._commit_hooks.pop(self._commit_hooks.index(cb))
-
- def pick(self, detached=True, uid=None, parent=None, forge_tids=False):
- '''
- Get a snapshot of the object. Can be of two
- types:
- * detached=True -- (default) "true" snapshot
- * detached=False -- keep ip addr set updated from OS
-
- Please note, that "updated" doesn't mean "in sync".
- The reason behind this logic is that snapshots can be
- used as transactions.
- '''
- with self._write_lock:
- res = self.__class__(ipdb=self.ipdb,
- mode='snapshot',
- parent=parent,
- uid=uid)
- for (key, value) in self.items():
- if key in self._fields:
- if isinstance(value, Transactional):
- t = value.pick(detached=detached,
- uid=res.uid,
- parent=self)
- if forge_tids:
- # forge the transaction for nested objects
- value._transactions[res.uid] = t
- value._tids.append(res.uid)
- res[key] = t
- else:
- res[key] = self[key]
- for key in self._linked_sets:
- res[key] = LinkedSet(self[key])
- if not detached:
- self[key].connect(res[key])
- return res
-
- def __enter__(self):
- # FIXME: use a bitmask?
- if self._mode not in ('implicit', 'explicit'):
- raise TypeError('context managers require a transactional mode')
- if not self._tids:
- self.begin()
- return self
-
- def __exit__(self, exc_type, exc_value, traceback):
- # apply transaction only if there was no error
- if exc_type is None:
- try:
- self.commit()
- except Exception as e:
- self.last_error = e
- raise
-
- def __repr__(self):
- res = {}
- for i in self:
- if self[i] is not None:
- res[i] = self[i]
- return res.__repr__()
-
- def __sub__(self, vs):
- res = self.__class__(ipdb=self.ipdb, mode='snapshot')
- with self._direct_state:
- # simple keys
- for key in self:
- if (key in self._fields) and \
- ((key not in vs) or (self[key] != vs[key])):
- res[key] = self[key]
- for key in self._linked_sets:
- diff = LinkedSet(self[key] - vs[key])
- if diff:
- res[key] = diff
- return res
-
- def dump(self, not_none=True):
- with self._write_lock:
- res = {}
- for key in self:
- if self[key] is not None and key[0] != '_':
- if isinstance(self[key], Transactional):
- res[key] = self[key].dump()
- elif isinstance(self[key], LinkedSet):
- res[key] = tuple(self[key])
- else:
- res[key] = self[key]
- return res
-
- def load(self, data):
- pass
-
- def commit(self, *args, **kwarg):
- pass
-
- def last_snapshot_id(self):
- return self._sids[-1]
-
- def revert(self, sid):
- with self._write_lock:
- self._transactions[sid] = self._snapshots[sid]
- self._tids.append(sid)
- self._sids.remove(sid)
- del self._snapshots[sid]
- return self
-
- def snapshot(self):
- '''
- Create new snapshot
- '''
- return self._begin(mapping=self._snapshots,
- ids=self._sids,
- detached=True)
-
- def begin(self):
- '''
- Start new transaction
- '''
- if self._parent is not None:
- self._parent.begin()
- else:
- return self._begin(mapping=self._transactions,
- ids=self._tids,
- detached=False)
-
- def _begin(self, mapping, ids, detached):
- # keep snapshot's ip addr set updated from the OS
- # it is required by the commit logic
- if (self.ipdb is not None) and self.ipdb._stop:
- raise RuntimeError("Can't start transaction on released IPDB")
- t = self.pick(detached=detached, forge_tids=True)
- mapping[t.uid] = t
- ids.append(t.uid)
- return t.uid
-
- def last_snapshot(self):
- if not self._sids:
- raise TypeError('create a snapshot first')
- return self._snapshots[self._sids[-1]]
-
- def last(self):
- '''
- Return last open transaction
- '''
- with self._write_lock:
- if not self._tids:
- raise TypeError('start a transaction first')
-
- return self._transactions[self._tids[-1]]
-
- def review(self):
- '''
- Review last open transaction
- '''
- if not self._tids:
- raise TypeError('start a transaction first')
-
- with self._write_lock:
- added = self.last() - self
- removed = self - self.last()
- for key in self._linked_sets:
- added['-%s' % (key)] = removed[key]
- added['+%s' % (key)] = added[key]
- del added[key]
- return added
-
- def drop(self, tid=None):
- '''
- Drop a transaction.
- '''
- with self._write_lock:
- if isinstance(tid, Transactional):
- tid = tid.uid
- elif tid is None:
- tid = self._tids[-1]
- self._tids.remove(tid)
- del self._transactions[tid]
- for (key, value) in self.items():
- if isinstance(value, Transactional):
- try:
- value.drop(tid)
- except KeyError:
- pass
-
- @update
- def __setitem__(self, direct, key, value):
- with self._write_lock:
- if not direct:
- # automatically set target on the last transaction,
- # which must be started prior to that call
- transaction = self.last()
- transaction[key] = value
- transaction._targets[key] = threading.Event()
- else:
- # set the item
- Dotkeys.__setitem__(self, key, value)
-
- # update on local targets
- if key in self._local_targets:
- func = self._fields_cmp.get(key, lambda x, y: x == y)
- if func(value, self._local_targets[key].value):
- self._local_targets[key].set()
-
- # cascade update on nested targets
- for tn in tuple(self._transactions.values()):
- if (key in tn._targets) and (key in tn):
- if self._fields_cmp.\
- get(key, lambda x, y: x == y)(value, tn[key]):
- tn._targets[key].set()
-
- @update
- def __delitem__(self, direct, key):
- with self._write_lock:
- # firstly set targets
- self[key] = None
-
- # then continue with delete
- if not direct:
- transaction = self.last()
- if key in transaction:
- del transaction[key]
- else:
- Dotkeys.__delitem__(self, key)
-
- def option(self, key, value):
- self[key] = value
- return self
-
- def unset(self, key):
- del self[key]
- return self
-
- def _wait_all_targets(self):
- for key, target in self._targets.items():
- if key not in self._virtual_fields:
- target.wait(SYNC_TIMEOUT)
- if not target.is_set():
- raise CommitException('target %s is not set' % key)
-
- def set_target(self, key, value):
- self._local_targets[key] = threading.Event()
- self._local_targets[key].value = value
-
- def mirror_target(self, key_from, key_to):
- self._local_targets[key_to] = self._local_targets[key_from]
-
- def set_item(self, key, value):
- with self._direct_state:
- self[key] = value
-
- def del_item(self, key):
- with self._direct_state:
- del self[key]
diff --git a/node-admin/scripts/pyroute2/iproute.py b/node-admin/scripts/pyroute2/iproute.py
deleted file mode 100644
index 09312945979..00000000000
--- a/node-admin/scripts/pyroute2/iproute.py
+++ /dev/null
@@ -1,888 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-# -*- coding: utf-8 -*-
-'''
-IPRoute module
-==============
-
-iproute quickstart
-------------------
-
-**IPRoute** in two words::
-
- $ sudo pip install pyroute2
-
- $ cat example.py
- from pyroute2 import IPRoute
- ip = IPRoute()
- print([x.get_attr('IFLA_IFNAME') for x in ip.get_links()])
-
- $ python example.py
- ['lo', 'p6p1', 'wlan0', 'virbr0', 'virbr0-nic']
-
-threaded vs. threadless architecture
-------------------------------------
-
-Since v0.3.2, IPRoute class is threadless by default.
-It spawns no additional threads, and receives only
-responses to own requests, no broadcast messages. So,
-if you prefer not to cope with implicit threading, you
-can safely use this module.
-
-To get broadcast messages, use `IPRoute.bind()` call.
-Please notice, that after calling `IPRoute.bind()` you
-MUST get all the messages in time. In the case of the
-kernel buffer overflow, you will have to restart the
-socket.
-
-With `IPRoute.bind(async=True)` one can launch async
-message receiver thread with `Queue`-based buffer. The
-buffer is thread-safe and completely transparent from
-the programmer's perspective. Please read also
-`NetlinkSocket` documentation to know more about async
-mode.
-
-think about IPDB
-----------------
-
-If you plan to regularly fetch loads of objects, think
-about IPDB also. Unlike to IPRoute, IPDB does not fetch
-all the objects from OS every time you request them, but
-keeps a cache that is asynchronously updated by the netlink
-broadcasts. For a long-term running programs, that often
-retrieve info about hundreds or thousands of objects, it
-can be better to use IPDB as it will load CPU significantly
-less.
-
-classes
--------
-'''
-
-from socket import htons
-from socket import AF_INET
-from socket import AF_INET6
-from socket import AF_UNSPEC
-from pyroute2.netlink import NLMSG_ERROR
-from pyroute2.netlink import NLM_F_ATOMIC
-from pyroute2.netlink import NLM_F_ROOT
-from pyroute2.netlink import NLM_F_REPLACE
-from pyroute2.netlink import NLM_F_REQUEST
-from pyroute2.netlink import NLM_F_ACK
-from pyroute2.netlink import NLM_F_DUMP
-from pyroute2.netlink import NLM_F_CREATE
-from pyroute2.netlink import NLM_F_EXCL
-from pyroute2.netlink.rtnl import RTM_NEWADDR
-from pyroute2.netlink.rtnl import RTM_GETADDR
-from pyroute2.netlink.rtnl import RTM_DELADDR
-from pyroute2.netlink.rtnl import RTM_NEWLINK
-from pyroute2.netlink.rtnl import RTM_GETLINK
-from pyroute2.netlink.rtnl import RTM_DELLINK
-from pyroute2.netlink.rtnl import RTM_NEWQDISC
-from pyroute2.netlink.rtnl import RTM_GETQDISC
-from pyroute2.netlink.rtnl import RTM_DELQDISC
-from pyroute2.netlink.rtnl import RTM_NEWTFILTER
-from pyroute2.netlink.rtnl import RTM_GETTFILTER
-from pyroute2.netlink.rtnl import RTM_DELTFILTER
-from pyroute2.netlink.rtnl import RTM_NEWTCLASS
-from pyroute2.netlink.rtnl import RTM_GETTCLASS
-from pyroute2.netlink.rtnl import RTM_DELTCLASS
-from pyroute2.netlink.rtnl import RTM_GETNEIGH
-from pyroute2.netlink.rtnl import RTM_NEWRULE
-from pyroute2.netlink.rtnl import RTM_GETRULE
-from pyroute2.netlink.rtnl import RTM_DELRULE
-from pyroute2.netlink.rtnl import RTM_NEWROUTE
-from pyroute2.netlink.rtnl import RTM_GETROUTE
-from pyroute2.netlink.rtnl import RTM_DELROUTE
-from pyroute2.netlink.rtnl import RTM_SETLINK
-from pyroute2.netlink.rtnl import TC_H_INGRESS
-from pyroute2.netlink.rtnl import TC_H_ROOT
-from pyroute2.netlink.rtnl import rtprotos
-from pyroute2.netlink.rtnl import rtypes
-from pyroute2.netlink.rtnl import rtscopes
-from pyroute2.netlink.rtnl.req import IPLinkRequest
-from pyroute2.netlink.rtnl.tcmsg import get_htb_parameters
-from pyroute2.netlink.rtnl.tcmsg import get_htb_class_parameters
-from pyroute2.netlink.rtnl.tcmsg import get_tbf_parameters
-from pyroute2.netlink.rtnl.tcmsg import get_sfq_parameters
-from pyroute2.netlink.rtnl.tcmsg import get_u32_parameters
-from pyroute2.netlink.rtnl.tcmsg import get_netem_parameters
-from pyroute2.netlink.rtnl.tcmsg import get_fw_parameters
-from pyroute2.netlink.rtnl.tcmsg import tcmsg
-from pyroute2.netlink.rtnl.rtmsg import rtmsg
-from pyroute2.netlink.rtnl.ndmsg import ndmsg
-from pyroute2.netlink.rtnl.fibmsg import fibmsg
-from pyroute2.netlink.rtnl.fibmsg import FR_ACT_NAMES
-from pyroute2.netlink.rtnl.ifinfmsg import ifinfmsg
-from pyroute2.netlink.rtnl.ifaddrmsg import ifaddrmsg
-from pyroute2.netlink.rtnl.iprsocket import IPRSocket
-
-from pyroute2.common import basestring
-
-DEFAULT_TABLE = 254
-
-
-def transform_handle(handle):
- if isinstance(handle, basestring):
- (major, minor) = [int(x if x else '0', 16) for x in handle.split(':')]
- handle = (major << 8 * 2) | minor
- return handle
-
-
-class IPRouteMixin(object):
- '''
- `IPRouteMixin` should not be instantiated by itself. It is intended
- to be used as a mixin class that provides iproute2-like API. You
- should use `IPRoute` or `NetNS` classes.
-
- All following info you can consider as IPRoute info as well.
-
- It is an old-school API, that provides access to rtnetlink as is.
- It helps you to retrieve and change almost all the data, available
- through rtnetlink::
-
- from pyroute2 import IPRoute
- ipr = IPRoute()
- # lookup interface by name
- dev = ipr.link_lookup(ifname='tap0')[0]
- # bring it down
- ipr.link('set', dev, state='down')
- # change interface MAC address and rename it
- ipr.link('set', dev, address='00:11:22:33:44:55', ifname='vpn')
- # add primary IP address
- ipr.addr('add', dev, address='10.0.0.1', mask=24)
- # add secondary IP address
- ipr.addr('add', dev, address='10.0.0.2', mask=24)
- # bring it up
- ipr.link('set', dev, state='up')
-
- '''
-
- # 8<---------------------------------------------------------------
- #
- # Listing methods
- #
- def get_qdiscs(self, index=None):
- '''
- Get all queue disciplines for all interfaces or for specified
- one.
- '''
- msg = tcmsg()
- msg['family'] = AF_UNSPEC
- ret = self.nlm_request(msg, RTM_GETQDISC)
- if index is None:
- return ret
- else:
- return [x for x in ret if x['index'] == index]
-
- def get_filters(self, index=0, handle=0, parent=0):
- '''
- Get filters for specified interface, handle and parent.
- '''
- msg = tcmsg()
- msg['family'] = AF_UNSPEC
- msg['index'] = index
- msg['handle'] = handle
- msg['parent'] = parent
- return self.nlm_request(msg, RTM_GETTFILTER)
-
- def get_classes(self, index=0):
- '''
- Get classes for specified interface.
- '''
- msg = tcmsg()
- msg['family'] = AF_UNSPEC
- msg['index'] = index
- return self.nlm_request(msg, RTM_GETTCLASS)
-
- def get_links(self, *argv, **kwarg):
- '''
- Get network interfaces.
-
- By default returns all interfaces. Arguments vector
- can contain interface indices or a special keyword
- 'all'::
-
- ip.get_links()
- ip.get_links('all')
- ip.get_links(1, 2, 3)
-
- interfaces = [1, 2, 3]
- ip.get_links(*interfaces)
- '''
- result = []
- links = argv or ['all']
- msg_flags = NLM_F_REQUEST | NLM_F_DUMP
- for index in links:
- msg = ifinfmsg()
- msg['family'] = kwarg.get('family', AF_UNSPEC)
- if index != 'all':
- msg['index'] = index
- msg_flags = NLM_F_REQUEST
- result.extend(self.nlm_request(msg, RTM_GETLINK, msg_flags))
- return result
-
- def get_neighbors(self, family=AF_UNSPEC):
- '''
- Retrieve ARP cache records.
- '''
- msg = ndmsg()
- msg['family'] = family
- return self.nlm_request(msg, RTM_GETNEIGH)
-
- def get_addr(self, family=AF_UNSPEC, index=None):
- '''
- Get addresses::
- ip.get_addr() # get all addresses
- ip.get_addr(index=2) # get addresses for the 2nd interface
- '''
- msg = ifaddrmsg()
- msg['family'] = family
- ret = self.nlm_request(msg, RTM_GETADDR)
- if index is not None:
- return [x for x in ret if x.get('index') == index]
- else:
- return ret
-
- def get_rules(self, family=AF_UNSPEC):
- '''
- Get all rules.
- You can specify inet family, by default return rules for all families.
-
- Example::
- ip.get_rules() # get all the rules for all families
- ip.get_routes(family=AF_INET6) # get only IPv6 rules
- '''
- msg = fibmsg()
- msg['family'] = family
- msg_flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_ATOMIC
- return self.nlm_request(msg, RTM_GETRULE, msg_flags)
-
- def get_routes(self, family=AF_INET, **kwarg):
- '''
- Get all routes. You can specify the table. There
- are 255 routing classes (tables), and the kernel
- returns all the routes on each request. So the
- routine filters routes from full output.
-
- Example::
-
- ip.get_routes() # get all the routes for all families
- ip.get_routes(family=AF_INET6) # get only IPv6 routes
- ip.get_routes(table=254) # get routes from 254 table
- '''
-
- msg_flags = NLM_F_DUMP | NLM_F_REQUEST
- msg = rtmsg()
- # you can specify the table here, but the kernel
- # will ignore this setting
- table = kwarg.get('table', DEFAULT_TABLE)
- msg['table'] = table if table <= 255 else 252
-
- # explicitly look for IPv6
- if any([kwarg.get(x, '').find(':') >= 0 for x
- in ('dst', 'src', 'gateway', 'prefsrc')]):
- family = AF_INET6
- msg['family'] = family
-
- # get a particular route
- if kwarg.get('dst', None) is not None:
- dlen = 32 if family == AF_INET else \
- 128 if family == AF_INET6 else 0
- msg_flags = NLM_F_REQUEST
- msg['dst_len'] = kwarg.get('dst_len', dlen)
-
- for key in kwarg:
- nla = rtmsg.name2nla(key)
- if kwarg[key] is not None:
- msg['attrs'].append([nla, kwarg[key]])
-
- routes = self.nlm_request(msg, RTM_GETROUTE, msg_flags)
- return [x for x in routes
- if x.get_attr('RTA_TABLE') == table or
- kwarg.get('table', None) is None]
- # 8<---------------------------------------------------------------
-
- # 8<---------------------------------------------------------------
- #
- # Shortcuts
- #
- # addr_add(), addr_del(), route_add(), route_del() shortcuts are
- # removed due to redundancy. Only link shortcuts are left here for
- # now. Possibly, they should be moved to a separate module.
- #
- def get_default_routes(self, family=AF_UNSPEC, table=DEFAULT_TABLE):
- '''
- Get default routes
- '''
- # according to iproute2/ip/iproute.c:print_route()
- return [x for x in self.get_routes(family, table=table)
- if (x.get_attr('RTA_DST', None) is None and
- x['dst_len'] == 0)]
-
- def link_create(self, **kwarg):
- '''
- Create a link. The method parameters will be
- passed to the `IPLinkRequest()` constructor as
- a dictionary.
-
- Examples::
-
- ip.link_create(ifname='very_dummy', kind='dummy')
- ip.link_create(ifname='br0', kind='bridge')
- ip.link_create(ifname='v101', kind='vlan', vlan_id=101, link=1)
- '''
- return self.link('add', **IPLinkRequest(kwarg))
-
- def link_up(self, index):
- '''
- Switch an interface up unconditionally.
- '''
- self.link('set', index=index, state='up')
-
- def link_down(self, index):
- '''
- Switch an interface down unconditilnally.
- '''
- self.link('set', index=index, state='down')
-
- def link_rename(self, index, name):
- '''
- Rename an interface. Please note, that the interface must be
- in the `DOWN` state in order to be renamed, otherwise you
- will get an error.
- '''
- self.link('set', index=index, ifname=name)
-
- def link_remove(self, index):
- '''
- Remove an interface
- '''
- self.link('delete', index=index)
-
- def link_lookup(self, **kwarg):
- '''
- Lookup interface index (indeces) by first level NLA
- value.
-
- Example::
-
- ip.link_lookup(address="52:54:00:9d:4e:3d")
- ip.link_lookup(ifname="lo")
- ip.link_lookup(operstate="UP")
-
- Please note, that link_lookup() returns list, not one
- value.
- '''
- name = tuple(kwarg.keys())[0]
- value = kwarg[name]
-
- name = str(name).upper()
- if not name.startswith('IFLA_'):
- name = 'IFLA_%s' % (name)
-
- return [k['index'] for k in
- [i for i in self.get_links() if 'attrs' in i] if
- [l for l in k['attrs'] if l[0] == name and l[1] == value]]
-
- def flush_routes(self, *argv, **kwarg):
- '''
- Flush routes -- purge route records from a table.
- Arguments are the same as for `get_routes()`
- routine. Actually, this routine implements a pipe from
- `get_routes()` to `nlm_request()`.
- '''
- flags = NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST
- ret = []
- kwarg['table'] = kwarg.get('table', DEFAULT_TABLE)
- for route in self.get_routes(*argv, **kwarg):
- ret.append(self.nlm_request(route,
- msg_type=RTM_DELROUTE,
- msg_flags=flags))
- return ret
- # 8<---------------------------------------------------------------
-
- # 8<---------------------------------------------------------------
- #
- # General low-level configuration methods
- #
- def link(self, command, **kwarg):
- '''
- Link operations.
-
- * command -- set, add or delete
- * index -- device index
- * \*\*kwarg -- keywords, NLA
-
- Example::
-
- x = 62 # interface index
- ip.link("set", index=x, state="down")
- ip.link("set", index=x, address="00:11:22:33:44:55", name="bala")
- ip.link("set", index=x, mtu=1000, txqlen=2000)
- ip.link("set", index=x, state="up")
-
- Keywords "state", "flags" and "mask" are reserved. State can
- be "up" or "down", it is a shortcut::
-
- state="up": flags=1, mask=1
- state="down": flags=0, mask=0
-
- For more flags grep IFF in the kernel code, until we write
- human-readable flag resolver.
-
- Other keywords are from ifinfmsg.nla_map, look into the
- corresponding module. You can use the form "ifname" as well
- as "IFLA_IFNAME" and so on, so that's equal::
-
- ip.link("set", index=x, mtu=1000)
- ip.link("set", index=x, IFLA_MTU=1000)
-
- You can also delete interface with::
-
- ip.link("delete", index=x)
- '''
-
- commands = {'set': RTM_SETLINK,
- 'add': RTM_NEWLINK,
- 'del': RTM_DELLINK,
- 'remove': RTM_DELLINK,
- 'delete': RTM_DELLINK}
- command = commands.get(command, command)
-
- msg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL
- msg = ifinfmsg()
- # index is required
- msg['index'] = kwarg.get('index')
-
- flags = kwarg.pop('flags', 0) or 0
- mask = kwarg.pop('mask', 0) or kwarg.pop('change', 0) or 0
-
- if 'state' in kwarg:
- mask = 1 # IFF_UP mask
- if kwarg['state'].lower() == 'up':
- flags = 1 # 0 (down) or 1 (up)
- del kwarg['state']
-
- msg['flags'] = flags
- msg['change'] = mask
-
- for key in kwarg:
- nla = type(msg).name2nla(key)
- if kwarg[key] is not None:
- msg['attrs'].append([nla, kwarg[key]])
-
- return self.nlm_request(msg, msg_type=command, msg_flags=msg_flags)
-
- def addr(self, command, index, address, mask=24,
- family=None, scope=0, **kwarg):
- '''
- Address operations
-
- * command -- add, delete
- * index -- device index
- * address -- IPv4 or IPv6 address
- * mask -- address mask
- * family -- socket.AF_INET for IPv4 or socket.AF_INET6 for IPv6
- * scope -- the address scope, see /etc/iproute2/rt_scopes
-
- Example::
-
- index = 62
- ip.addr("add", index, address="10.0.0.1", mask=24)
- ip.addr("add", index, address="10.0.0.2", mask=24)
- '''
-
- commands = {'add': RTM_NEWADDR,
- 'del': RTM_DELADDR,
- 'remove': RTM_DELADDR,
- 'delete': RTM_DELADDR}
- command = commands.get(command, command)
-
- flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL
-
- # try to guess family, if it is not forced
- if family is None:
- if address.find(":") > -1:
- family = AF_INET6
- else:
- family = AF_INET
-
- msg = ifaddrmsg()
- msg['index'] = index
- msg['family'] = family
- msg['prefixlen'] = mask
- msg['scope'] = scope
- if family == AF_INET:
- msg['attrs'] = [['IFA_LOCAL', address],
- ['IFA_ADDRESS', address]]
- elif family == AF_INET6:
- msg['attrs'] = [['IFA_ADDRESS', address]]
- for key in kwarg:
- nla = ifaddrmsg.name2nla(key)
- if kwarg[key] is not None:
- msg['attrs'].append([nla, kwarg[key]])
- return self.nlm_request(msg,
- msg_type=command,
- msg_flags=flags,
- terminate=lambda x: x['header']['type'] ==
- NLMSG_ERROR)
-
- def tc(self, command, kind, index, handle=0, **kwarg):
- '''
- "Swiss knife" for traffic control. With the method you can
- add, delete or modify qdiscs, classes and filters.
-
- * command -- add or delete qdisc, class, filter.
- * kind -- a string identifier -- "sfq", "htb", "u32" and so on.
- * handle -- integer or string
-
- Command can be one of ("add", "del", "add-class", "del-class",
- "add-filter", "del-filter") (see `commands` dict in the code).
-
- Handle notice: traditional iproute2 notation, like "1:0", actually
- represents two parts in one four-bytes integer::
-
- 1:0 -> 0x10000
- 1:1 -> 0x10001
- ff:0 -> 0xff0000
- ffff:1 -> 0xffff0001
-
- For pyroute2 tc() you can use both forms: integer like 0xffff0000
- or string like 'ffff:0000'. By default, handle is 0, so you can add
- simple classless queues w/o need to specify handle. Ingress queue
- causes handle to be 0xffff0000.
-
- So, to set up sfq queue on interface 1, the function call
- will be like that::
-
- ip = IPRoute()
- ip.tc("add", "sfq", 1)
-
- Instead of string commands ("add", "del"...), you can use also
- module constants, `RTM_NEWQDISC`, `RTM_DELQDISC` and so on::
-
- ip = IPRoute()
- ip.tc(RTM_NEWQDISC, "sfq", 1)
-
- More complex example with htb qdisc, lets assume eth0 == 2::
-
- # u32 --> +--> htb 1:10 --> sfq 10:0
- # | |
- # | |
- # eth0 -- htb 1:0 -- htb 1:1
- # | |
- # | |
- # u32 --> +--> htb 1:20 --> sfq 20:0
-
- eth0 = 2
- # add root queue 1:0
- ip.tc("add", "htb", eth0, 0x10000, default=0x200000)
-
- # root class 1:1
- ip.tc("add-class", "htb", eth0, 0x10001,
- parent=0x10000,
- rate="256kbit",
- burst=1024 * 6)
-
- # two branches: 1:10 and 1:20
- ip.tc("add-class", "htb", eth0, 0x10010,
- parent=0x10001,
- rate="192kbit",
- burst=1024 * 6,
- prio=1)
- ip.tc("add-class", "htb", eht0, 0x10020,
- parent=0x10001,
- rate="128kbit",
- burst=1024 * 6,
- prio=2)
-
- # two leaves: 10:0 and 20:0
- ip.tc("add", "sfq", eth0, 0x100000,
- parent=0x10010,
- perturb=10)
- ip.tc("add", "sfq", eth0, 0x200000,
- parent=0x10020,
- perturb=10)
-
- # two filters: one to load packets into 1:10 and the
- # second to 1:20
- ip.tc("add-filter", "u32", eth0,
- parent=0x10000,
- prio=10,
- protocol=socket.AF_INET,
- target=0x10010,
- keys=["0x0006/0x00ff+8", "0x0000/0xffc0+2"])
- ip.tc("add-filter", "u32", eth0,
- parent=0x10000,
- prio=10,
- protocol=socket.AF_INET,
- target=0x10020,
- keys=["0x5/0xf+0", "0x10/0xff+33"])
- '''
-
- commands = {'add': RTM_NEWQDISC,
- 'del': RTM_DELQDISC,
- 'remove': RTM_DELQDISC,
- 'delete': RTM_DELQDISC,
- 'add-class': RTM_NEWTCLASS,
- 'del-class': RTM_DELTCLASS,
- 'add-filter': RTM_NEWTFILTER,
- 'del-filter': RTM_DELTFILTER}
- command = commands.get(command, command)
- flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL
- msg = tcmsg()
- # transform handle, parent and target, if needed:
- handle = transform_handle(handle)
- for item in ('parent', 'target', 'default'):
- if item in kwarg and kwarg[item] is not None:
- kwarg[item] = transform_handle(kwarg[item])
- msg['index'] = index
- msg['handle'] = handle
- opts = kwarg.get('opts', None)
- if kind == 'ingress':
- msg['parent'] = TC_H_INGRESS
- msg['handle'] = 0xffff0000
- elif kind == 'tbf':
- msg['parent'] = TC_H_ROOT
- if kwarg:
- opts = get_tbf_parameters(kwarg)
- elif kind == 'htb':
- msg['parent'] = kwarg.get('parent', TC_H_ROOT)
- if kwarg:
- if command in (RTM_NEWQDISC, RTM_DELQDISC):
- opts = get_htb_parameters(kwarg)
- elif command in (RTM_NEWTCLASS, RTM_DELTCLASS):
- opts = get_htb_class_parameters(kwarg)
- elif kind == 'netem':
- msg['parent'] = kwarg.get('parent', TC_H_ROOT)
- if kwarg:
- opts = get_netem_parameters(kwarg)
- elif kind == 'sfq':
- msg['parent'] = kwarg.get('parent', TC_H_ROOT)
- if kwarg:
- opts = get_sfq_parameters(kwarg)
- elif kind == 'u32':
- msg['parent'] = kwarg.get('parent')
- msg['info'] = htons(kwarg.get('protocol', 0) & 0xffff) |\
- ((kwarg.get('prio', 0) << 16) & 0xffff0000)
- if kwarg:
- opts = get_u32_parameters(kwarg)
- elif kind == 'fw':
- msg['parent'] = kwarg.get('parent')
- msg['info'] = htons(kwarg.get('protocol', 0) & 0xffff) |\
- ((kwarg.get('prio', 0) << 16) & 0xffff0000)
- if kwarg:
- opts = get_fw_parameters(kwarg)
- else:
- msg['parent'] = kwarg.get('parent', TC_H_ROOT)
-
- if kind is not None:
- msg['attrs'] = [['TCA_KIND', kind]]
- if opts is not None:
- msg['attrs'].append(['TCA_OPTIONS', opts])
- return self.nlm_request(msg, msg_type=command, msg_flags=flags)
-
- def route(self, command,
- rtype='RTN_UNICAST',
- rtproto='RTPROT_STATIC',
- rtscope='RT_SCOPE_UNIVERSE',
- **kwarg):
- '''
- Route operations
-
- * command -- add, delete, change, replace
- * prefix -- route prefix
- * mask -- route prefix mask
- * rtype -- route type (default: "RTN_UNICAST")
- * rtproto -- routing protocol (default: "RTPROT_STATIC")
- * rtscope -- routing scope (default: "RT_SCOPE_UNIVERSE")
- * family -- socket.AF_INET (default) or socket.AF_INET6
-
- `pyroute2/netlink/rtnl/rtmsg.py` rtmsg.nla_map:
-
- * table -- routing table to use (default: 254)
- * gateway -- via address
- * prefsrc -- preferred source IP address
- * dst -- the same as `prefix`
- * src -- source address
- * iif -- incoming traffic interface
- * oif -- outgoing traffic interface
-
- etc.
-
- Example::
-
- ip.route("add", dst="10.0.0.0", mask=24, gateway="192.168.0.1")
-
- Commands `change` and `replace` have the same meanings, as
- in ip-route(8): `change` modifies only existing route, while
- `replace` creates a new one, if there is no such route yet.
- '''
-
- # 8<----------------------------------------------------
- # FIXME
- # flags should be moved to some more general place
- flags_base = NLM_F_REQUEST | NLM_F_ACK
- flags_make = flags_base | NLM_F_CREATE | NLM_F_EXCL
- flags_change = flags_base | NLM_F_REPLACE
- flags_replace = flags_change | NLM_F_CREATE
- # 8<----------------------------------------------------
- commands = {'add': (RTM_NEWROUTE, flags_make),
- 'set': (RTM_NEWROUTE, flags_replace),
- 'replace': (RTM_NEWROUTE, flags_replace),
- 'change': (RTM_NEWROUTE, flags_change),
- 'del': (RTM_DELROUTE, flags_make),
- 'remove': (RTM_DELROUTE, flags_make),
- 'delete': (RTM_DELROUTE, flags_make)}
- (command, flags) = commands.get(command, command)
- msg = rtmsg()
- # table is mandatory; by default == 254
- # if table is not defined in kwarg, save it there
- # also for nla_attr:
- table = kwarg.get('table', 254)
- msg['table'] = table if table <= 255 else 252
- msg['family'] = kwarg.get('family', AF_INET)
- msg['proto'] = rtprotos[rtproto]
- msg['type'] = rtypes[rtype]
- msg['scope'] = rtscopes[rtscope]
- msg['dst_len'] = kwarg.get('dst_len', None) or \
- kwarg.get('mask', 0)
- msg['attrs'] = []
- # FIXME
- # deprecated "prefix" support:
- if 'prefix' in kwarg:
- kwarg['dst'] = kwarg['prefix']
-
- for key in kwarg:
- nla = rtmsg.name2nla(key)
- if kwarg[key] is not None:
- msg['attrs'].append([nla, kwarg[key]])
-
- return self.nlm_request(msg, msg_type=command,
- msg_flags=flags)
-
- def rule(self, command, table, priority=32000,
- action='FR_ACT_NOP', family=AF_INET,
- src=None, src_len=None,
- dst=None, dst_len=None,
- fwmark=None, iifname=None, oifname=None):
- '''
- Rule operations
-
- - command — add, delete
- - table — 0 < table id < 253
- - priority — 0 < rule's priority < 32766
- - action — type of rule, default 'FR_ACT_NOP' (see fibmsg.py)
- - rtscope — routing scope, default RT_SCOPE_UNIVERSE
- `(RT_SCOPE_UNIVERSE|RT_SCOPE_SITE|\
- RT_SCOPE_LINK|RT_SCOPE_HOST|RT_SCOPE_NOWHERE)`
- - family — rule's family (socket.AF_INET (default) or
- socket.AF_INET6)
- - src — IP source for Source Based (Policy Based) routing's rule
- - dst — IP for Destination Based (Policy Based) routing's rule
- - src_len — Mask for Source Based (Policy Based) routing's rule
- - dst_len — Mask for Destination Based (Policy Based) routing's
- rule
- - iifname — Input interface for Interface Based (Policy Based)
- routing's rule
- - oifname — Output interface for Interface Based (Policy Based)
- routing's rule
-
- Example::
- ip.rule('add', 10, 32000)
-
- Will create::
- #ip ru sh
- ...
- 32000: from all lookup 10
- ....
-
- Example::
- iproute.rule('add', 11, 32001, 'FR_ACT_UNREACHABLE')
-
- Will create::
- #ip ru sh
- ...
- 32001: from all lookup 11 unreachable
- ....
-
- Example::
- iproute.rule('add', 14, 32004, src='10.64.75.141')
-
- Will create::
- #ip ru sh
- ...
- 32004: from 10.64.75.141 lookup 14
- ...
-
- Example::
- iproute.rule('add', 15, 32005, dst='10.64.75.141', dst_len=24)
-
- Will create::
- #ip ru sh
- ...
- 32005: from 10.64.75.141/24 lookup 15
- ...
-
- Example::
- iproute.rule('add', 15, 32006, dst='10.64.75.141', fwmark=10)
-
- Will create::
- #ip ru sh
- ...
- 32006: from 10.64.75.141 fwmark 0xa lookup 15
- ...
- '''
- if table < 0:
- raise ValueError('unsupported table number')
-
- commands = {'add': RTM_NEWRULE,
- 'del': RTM_DELRULE,
- 'remove': RTM_DELRULE,
- 'delete': RTM_DELRULE}
- command = commands.get(command, command)
-
- msg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL
- msg = fibmsg()
- msg['table'] = table if table <= 255 else 252
- msg['family'] = family
- msg['action'] = FR_ACT_NAMES[action]
- msg['attrs'] = [['FRA_TABLE', table]]
- msg['attrs'].append(['FRA_PRIORITY', priority])
- if fwmark is not None:
- msg['attrs'].append(['FRA_FWMARK', fwmark])
- addr_len = {AF_INET6: 128, AF_INET: 32}[family]
- if(dst_len is not None and dst_len >= 0 and dst_len <= addr_len):
- msg['dst_len'] = dst_len
- else:
- msg['dst_len'] = 0
- if(src_len is not None and src_len >= 0 and src_len <= addr_len):
- msg['src_len'] = src_len
- else:
- msg['src_len'] = 0
- if src is not None:
- msg['attrs'].append(['FRA_SRC', src])
- if src_len is None:
- msg['src_len'] = addr_len
- if dst is not None:
- msg['attrs'].append(['FRA_DST', dst])
- if dst_len is None:
- msg['dst_len'] = addr_len
- if iifname is not None:
- msg['attrs'].append(['FRA_IIFNAME', iifname])
- if oifname is not None:
- msg['attrs'].append(['FRA_OIFNAME', oifname])
-
- return self.nlm_request(msg, msg_type=command,
- msg_flags=msg_flags)
- # 8<---------------------------------------------------------------
-
-
-class IPRoute(IPRouteMixin, IPRSocket):
- '''
- Production class that provides iproute API over normal Netlink
- socket.
-
- You can think of this class in some way as of plain old iproute2
- utility.
- '''
- pass
diff --git a/node-admin/scripts/pyroute2/ipset.py b/node-admin/scripts/pyroute2/ipset.py
deleted file mode 100644
index e12b0551357..00000000000
--- a/node-admin/scripts/pyroute2/ipset.py
+++ /dev/null
@@ -1,149 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-IPSet module
-============
-
-The very basic ipset support.
-
-Right now it is tested only for hash:ip and doesn't support
-many useful options. But it can be easily extended, so you
-are welcome to help with that.
-'''
-import socket
-from pyroute2.netlink import NLMSG_ERROR
-from pyroute2.netlink import NLM_F_REQUEST
-from pyroute2.netlink import NLM_F_DUMP
-from pyroute2.netlink import NLM_F_ACK
-from pyroute2.netlink import NLM_F_EXCL
-from pyroute2.netlink import NETLINK_NETFILTER
-from pyroute2.netlink.nlsocket import NetlinkSocket
-from pyroute2.netlink.nfnetlink import NFNL_SUBSYS_IPSET
-from pyroute2.netlink.nfnetlink.ipset import IPSET_CMD_PROTOCOL
-from pyroute2.netlink.nfnetlink.ipset import IPSET_CMD_CREATE
-from pyroute2.netlink.nfnetlink.ipset import IPSET_CMD_DESTROY
-from pyroute2.netlink.nfnetlink.ipset import IPSET_CMD_SWAP
-from pyroute2.netlink.nfnetlink.ipset import IPSET_CMD_LIST
-from pyroute2.netlink.nfnetlink.ipset import IPSET_CMD_ADD
-from pyroute2.netlink.nfnetlink.ipset import IPSET_CMD_DEL
-from pyroute2.netlink.nfnetlink.ipset import ipset_msg
-
-
-def _nlmsg_error(msg):
- return msg['header']['type'] == NLMSG_ERROR
-
-
-class IPSet(NetlinkSocket):
- '''
- NFNetlink socket (family=NETLINK_NETFILTER).
-
- Implements API to the ipset functionality.
- '''
-
- policy = {IPSET_CMD_PROTOCOL: ipset_msg,
- IPSET_CMD_LIST: ipset_msg}
-
- def __init__(self, version=6, attr_revision=2, nfgen_family=2):
- super(IPSet, self).__init__(family=NETLINK_NETFILTER)
- policy = dict([(x | (NFNL_SUBSYS_IPSET << 8), y)
- for (x, y) in self.policy.items()])
- self.register_policy(policy)
- self._proto_version = version
- self._attr_revision = attr_revision
- self._nfgen_family = nfgen_family
-
- def request(self, msg, msg_type,
- msg_flags=NLM_F_REQUEST | NLM_F_DUMP,
- terminate=None):
- msg['nfgen_family'] = self._nfgen_family
- return self.nlm_request(msg,
- msg_type | (NFNL_SUBSYS_IPSET << 8),
- msg_flags, terminate=terminate)
-
- def list(self, name=None):
- '''
- List installed ipsets. If `name` is provided, list
- the named ipset or return an empty list.
-
- It looks like nfnetlink doesn't return an error,
- when requested ipset doesn't exist.
- '''
- msg = ipset_msg()
- msg['attrs'] = [['IPSET_ATTR_PROTOCOL', self._proto_version]]
- if name is not None:
- msg['attrs'].append(['IPSET_ATTR_SETNAME', name])
- return self.request(msg, IPSET_CMD_LIST)
-
- def destroy(self, name):
- '''
- Destroy an ipset
- '''
- msg = ipset_msg()
- msg['attrs'] = [['IPSET_ATTR_PROTOCOL', self._proto_version],
- ['IPSET_ATTR_SETNAME', name]]
- return self.request(msg, IPSET_CMD_DESTROY,
- msg_flags=NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL,
- terminate=_nlmsg_error)
-
- def create(self, name, stype='hash:ip', family=socket.AF_INET,
- exclusive=True):
- '''
- Create an ipset `name` of type `stype`, by default
- `hash:ip`.
-
- Very simple and stupid method, should be extended
- to support ipset options.
- '''
- excl_flag = NLM_F_EXCL if exclusive else 0
- msg = ipset_msg()
- msg['attrs'] = [['IPSET_ATTR_PROTOCOL', self._proto_version],
- ['IPSET_ATTR_SETNAME', name],
- ['IPSET_ATTR_TYPENAME', stype],
- ['IPSET_ATTR_FAMILY', family],
- ['IPSET_ATTR_REVISION', self._attr_revision]]
-
- return self.request(msg, IPSET_CMD_CREATE,
- msg_flags=NLM_F_REQUEST | NLM_F_ACK | excl_flag,
- terminate=_nlmsg_error)
-
- def _add_delete(self, name, entry, family, cmd, exclusive):
- if family == socket.AF_INET:
- entry_type = 'IPSET_ATTR_IPADDR_IPV4'
- elif family == socket.AF_INET6:
- entry_type = 'IPSET_ATTR_IPADDR_IPV6'
- else:
- raise TypeError('unknown family')
- excl_flag = NLM_F_EXCL if exclusive else 0
-
- msg = ipset_msg()
- msg['attrs'] = [['IPSET_ATTR_PROTOCOL', self._proto_version],
- ['IPSET_ATTR_SETNAME', name],
- ['IPSET_ATTR_DATA',
- {'attrs': [['IPSET_ATTR_IP',
- {'attrs': [[entry_type, entry]]}]]}]]
- return self.request(msg, cmd,
- msg_flags=NLM_F_REQUEST | NLM_F_ACK | excl_flag,
- terminate=_nlmsg_error)
-
- def add(self, name, entry, family=socket.AF_INET, exclusive=True):
- '''
- Add a member to the ipset
- '''
- return self._add_delete(name, entry, family, IPSET_CMD_ADD, exclusive)
-
- def delete(self, name, entry, family=socket.AF_INET, exclusive=True):
- '''
- Delete a member from the ipset
- '''
- return self._add_delete(name, entry, family, IPSET_CMD_DEL, exclusive)
-
- def swap(self, set_a, set_b):
- '''
- Swap two ipsets
- '''
- msg = ipset_msg()
- msg['attrs'] = [['IPSET_ATTR_PROTOCOL', self._proto_version],
- ['IPSET_ATTR_SETNAME', set_a],
- ['IPSET_ATTR_TYPENAME', set_b]]
- return self.request(msg, IPSET_CMD_SWAP,
- msg_flags=NLM_F_REQUEST | NLM_F_ACK,
- terminate=_nlmsg_error)
diff --git a/node-admin/scripts/pyroute2/iwutil.py b/node-admin/scripts/pyroute2/iwutil.py
deleted file mode 100644
index 835f5fc773a..00000000000
--- a/node-admin/scripts/pyroute2/iwutil.py
+++ /dev/null
@@ -1,355 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-# -*- coding: utf-8 -*-
-'''
-IW module
-=========
-
-Experimental wireless module — nl80211 support.
-
-Disclaimer
-----------
-
-Unlike IPRoute, which is mostly usable, though is far from
-complete yet, the IW module is in the very initial state.
-Neither the module itself, nor the message class cover the
-nl80211 functionality reasonably enough. So if you're
-going to use it, brace yourself — debug is coming.
-
-Messages
---------
-
-nl80211 messages are defined here::
-
- pyroute2/netlink/nl80211/__init__.py
-
-Pls notice NLAs of type `hex`. On the early development stage
-`hex` allows to inspect incoming data as a hex dump and,
-occasionally, even make requests with such NLAs. But it's
-not a production way.
-
-The type `hex` in the NLA definitions means that this
-particular NLA is not handled yet properly. If you want to
-use some NLA which is defined as `hex` yet, pls find out a
-specific type, patch the message class and submit your pull
-request on github.
-
-If you're not familiar with NLA types, take a look at RTNL
-definitions::
-
- pyroute2/netlink/rtnl/ndmsg.py
-
-and so on.
-
-Communication with the kernel
------------------------------
-
-There are several methods of the communication with the kernel.
-
- * `sendto()` — lowest possible, send a raw binary data
- * `put()` — send a netlink message
- * `nlm_request()` — send a message, return the response
- * `get()` — get a netlink message
- * `recv()` — get a raw binary data from the kernel
-
-There are no errors on `put()` usually. Any `permission denied`,
-any `invalid value` errors are returned from the kernel with
-netlink also. So if you do `put()`, but don't do `get()`, be
-prepared to miss errors.
-
-The preferred method for the communication is `nlm_request()`.
-It tracks the message ID, returns the corresponding response.
-In the case of errors `nlm_request()` raises an exception.
-To get the response on any operation with nl80211, use flag
-`NLM_F_ACK`.
-
-Reverse it
-----------
-
-If you're too lazy to read the kernel sources, but still need
-something not implemented here, you can use reverse engineering
-on a reference implementation. E.g.::
-
- # strace -e trace=network -f -x -s 4096 \\
- iw phy phy0 interface add test type monitor
-
-Will dump all the netlink traffic between the program `iw` and
-the kernel. Three first packets are the generic netlink protocol
-discovery, you can ignore them. All that follows, is the
-nl80211 traffic::
-
- sendmsg(3, {msg_name(12)={sa_family=AF_NETLINK, ... },
- msg_iov(1)=[{"\\x30\\x00\\x00\\x00\\x1b\\x00\\x05 ...", 48}],
- msg_controllen=0, msg_flags=0}, 0) = 48
- recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, ... },
- msg_iov(1)=[{"\\x58\\x00\\x00\\x00\\x1b\\x00\\x00 ...", 16384}],
- msg_controllen=0, msg_flags=0}, 0) = 88
- ...
-
-With `-s 4096` you will get the full dump. Then copy the strings
-from `msg_iov` to a file, let's say `data`, and run the decoder::
-
- $ pwd
- /home/user/Projects/pyroute2
- $ export PYTHONPATH=`pwd`
- $ python scripts/decoder.py pyroute2.netlink.nl80211.nl80211cmd data
-
-You will get the session decoded::
-
- {'attrs': [['NL80211_ATTR_WIPHY', 0],
- ['NL80211_ATTR_IFNAME', 'test'],
- ['NL80211_ATTR_IFTYPE', 6]],
- 'cmd': 7,
- 'header': {'flags': 5,
- 'length': 48,
- 'pid': 3292542647,
- 'sequence_number': 1430426434,
- 'type': 27},
- 'reserved': 0,
- 'version': 0}
- {'attrs': [['NL80211_ATTR_IFINDEX', 23811],
- ['NL80211_ATTR_IFNAME', 'test'],
- ['NL80211_ATTR_WIPHY', 0],
- ['NL80211_ATTR_IFTYPE', 6],
- ['NL80211_ATTR_WDEV', 4],
- ['NL80211_ATTR_MAC', 'a4:4e:31:43:1c:7c'],
- ['NL80211_ATTR_GENERATION', '02:00:00:00']],
- 'cmd': 7,
- 'header': {'flags': 0,
- 'length': 88,
- 'pid': 3292542647,
- 'sequence_number': 1430426434,
- 'type': 27},
- 'reserved': 0,
- 'version': 1}
-
-Now you know, how to do a request and what you will get as a
-response. Sample collected data is in the `scripts` directory.
-
-Submit changes
---------------
-
-Please do not hesitate to submit the changes on github. Without
-your patches this module will not evolve.
-'''
-from pyroute2.netlink import NLM_F_ACK
-from pyroute2.netlink import NLM_F_REQUEST
-from pyroute2.netlink import NLM_F_DUMP
-from pyroute2.netlink.nl80211 import NL80211
-from pyroute2.netlink.nl80211 import nl80211cmd
-from pyroute2.netlink.nl80211 import NL80211_NAMES
-from pyroute2.netlink.nl80211 import IFTYPE_NAMES
-
-
-class IW(NL80211):
-
- def __init__(self, *argv, **kwarg):
- # get specific groups kwarg
- if 'groups' in kwarg:
- groups = kwarg['groups']
- del kwarg['groups']
- else:
- groups = None
-
- # get specific async kwarg
- if 'async' in kwarg:
- async = kwarg['async']
- del kwarg['async']
- else:
- async = False
-
- # align groups with async
- if groups is None:
- groups = ~0 if async else 0
-
- # continue with init
- super(IW, self).__init__(*argv, **kwarg)
-
- # do automatic bind
- # FIXME: unfortunately we can not omit it here
- self.bind(groups, async)
-
- def del_interface(self, dev):
- '''
- Delete a virtual interface
-
- - dev — device index
- '''
- msg = nl80211cmd()
- msg['cmd'] = NL80211_NAMES['NL80211_CMD_DEL_INTERFACE']
- msg['attrs'] = [['NL80211_ATTR_IFINDEX', dev]]
- self.nlm_request(msg,
- msg_type=self.prid,
- msg_flags=NLM_F_REQUEST | NLM_F_ACK)
-
- def add_interface(self, ifname, iftype, dev=None, phy=0):
- '''
- Create a virtual interface
-
- - ifname — name of the interface to create
- - iftype — interface type to create
- - dev — device index
- - phy — phy index
-
- One should specify `dev` (device index) or `phy`
- (phy index). If no one specified, phy == 0.
-
- `iftype` can be integer or string:
-
- 1. adhoc
- 2. station
- 3. ap
- 4. ap_vlan
- 5. wds
- 6. monitor
- 7. mesh_point
- 8. p2p_client
- 9. p2p_go
- 10. p2p_device
- 11. ocb
- '''
- # lookup the interface type
- iftype = IFTYPE_NAMES.get(iftype, iftype)
- assert isinstance(iftype, int)
-
- msg = nl80211cmd()
- msg['cmd'] = NL80211_NAMES['NL80211_CMD_NEW_INTERFACE']
- msg['attrs'] = [['NL80211_ATTR_IFNAME', ifname],
- ['NL80211_ATTR_IFTYPE', iftype]]
- if dev is not None:
- msg['attrs'].append(['NL80211_ATTR_IFINDEX', dev])
- elif phy is not None:
- msg['attrs'].append(['NL80211_ATTR_WIPHY', phy])
- else:
- raise TypeError('no device specified')
- self.nlm_request(msg,
- msg_type=self.prid,
- msg_flags=NLM_F_REQUEST | NLM_F_ACK)
-
- def list_wiphy(self):
- '''
- Get all list of phy device
- '''
- msg = nl80211cmd()
- msg['cmd'] = NL80211_NAMES['NL80211_CMD_GET_WIPHY']
- return self.nlm_request(msg,
- msg_type=self.prid,
- msg_flags=NLM_F_REQUEST | NLM_F_DUMP)
-
- def _get_phy_name(self, attr):
- return 'phy%i' % attr.get_attr('NL80211_ATTR_WIPHY')
-
- def _get_frequency(self, attr):
- try:
- return attr.get_attr('NL80211_ATTR_WIPHY_FREQ') + 2304
- except:
- return 0
-
- def get_interfaces_dict(self):
- '''
- Get interfaces dictionary
- '''
- ret = {}
- for wif in self.get_interfaces_dump():
- chan_width = wif.get_attr('NL80211_ATTR_CHANNEL_WIDTH')
- freq = self._get_frequency(wif) if chan_width is not None else 0
- wifname = wif.get_attr('NL80211_ATTR_IFNAME')
- ret[wifname] = [wif.get_attr('NL80211_ATTR_IFINDEX'),
- self._get_phy_name(wif),
- wif.get_attr('NL80211_ATTR_MAC'),
- freq, chan_width]
- return ret
-
- def get_interfaces_dump(self):
- '''
- Get interfaces dump
- '''
- msg = nl80211cmd()
- msg['cmd'] = NL80211_NAMES['NL80211_CMD_GET_INTERFACE']
- return self.nlm_request(msg,
- msg_type=self.prid,
- msg_flags=NLM_F_REQUEST | NLM_F_DUMP)
-
- def get_interface_by_phy(self, attr):
- '''
- Get interface by phy ( use x.get_attr('NL80211_ATTR_WIPHY') )
- '''
- msg = nl80211cmd()
- msg['cmd'] = NL80211_NAMES['NL80211_CMD_GET_INTERFACE']
- msg['attrs'] = [['NL80211_ATTR_WIPHY', attr]]
- return self.nlm_request(msg,
- msg_type=self.prid,
- msg_flags=NLM_F_REQUEST | NLM_F_DUMP)
-
- def get_interface_by_ifindex(self, ifindex):
- '''
- Get interface by ifindex ( use x.get_attr('NL80211_ATTR_IFINDEX')
- '''
- msg = nl80211cmd()
- msg['cmd'] = NL80211_NAMES['NL80211_CMD_GET_INTERFACE']
- msg['attrs'] = [['NL80211_ATTR_IFINDEX', ifindex]]
- return self.nlm_request(msg,
- msg_type=self.prid,
- msg_flags=NLM_F_REQUEST)
-
- def connect(self, ifindex, ssid, bssid=None):
- '''
- Connect to the ap with ssid and bssid
- '''
- msg = nl80211cmd()
- msg['cmd'] = NL80211_NAMES['NL80211_CMD_CONNECT']
- msg['attrs'] = [['NL80211_ATTR_IFINDEX', ifindex],
- ['NL80211_ATTR_SSID', ssid]]
- if bssid is not None:
- msg['attrs'].append(['NL80211_ATTR_MAC', bssid])
-
- self.nlm_request(msg,
- msg_type=self.prid,
- msg_flags=NLM_F_REQUEST | NLM_F_ACK)
-
- def disconnect(self, ifindex):
- '''
- Disconnect the device
- '''
- msg = nl80211cmd()
- msg['cmd'] = NL80211_NAMES['NL80211_CMD_DISCONNECT']
- msg['attrs'] = [['NL80211_ATTR_IFINDEX', ifindex]]
- self.nlm_request(msg,
- msg_type=self.prid,
- msg_flags=NLM_F_REQUEST | NLM_F_ACK)
-
- def scan(self, ifindex):
- '''
- Scan wifi
- '''
- # Prepare a second netlink socket to get the scan results.
- # The issue is that the kernel can send the results notification
- # before we get answer for the NL80211_CMD_TRIGGER_SCAN
- nsock = NL80211()
- nsock.bind()
- nsock.add_membership('scan')
-
- # send scan request
- msg = nl80211cmd()
- msg['cmd'] = NL80211_NAMES['NL80211_CMD_TRIGGER_SCAN']
- msg['attrs'] = [['NL80211_ATTR_IFINDEX', ifindex]]
- self.nlm_request(msg,
- msg_type=self.prid,
- msg_flags=NLM_F_REQUEST | NLM_F_ACK)
-
- # monitor the results notification on the secondary socket
- scanResultNotFound = True
- while scanResultNotFound:
- listMsg = nsock.get()
- for msg in listMsg:
- if msg["event"] == "NL80211_CMD_NEW_SCAN_RESULTS":
- scanResultNotFound = False
- break
- # close the secondary socket
- nsock.close()
-
- # request the results
- msg2 = nl80211cmd()
- msg2['cmd'] = NL80211_NAMES['NL80211_CMD_GET_SCAN']
- msg2['attrs'] = [['NL80211_ATTR_IFINDEX', ifindex]]
- return self.nlm_request(msg2, msg_type=self.prid,
- msg_flags=NLM_F_REQUEST | NLM_F_DUMP)
diff --git a/node-admin/scripts/pyroute2/netlink/__init__.py b/node-admin/scripts/pyroute2/netlink/__init__.py
deleted file mode 100644
index 499c7ab79d3..00000000000
--- a/node-admin/scripts/pyroute2/netlink/__init__.py
+++ /dev/null
@@ -1,1349 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-Netlink basics
-==============
-
-General netlink packet structure::
-
- nlmsg packet:
- + header
- + data
-
-Generic netlink message header::
-
- nlmsg header:
- + uint32 length
- + uint16 type
- + uint16 flags
- + uint32 sequence number
- + uint32 pid
-
-The `length` field is the length of all the packet, including
-data and header. The `type` field is used to distinguish different
-message types, commands etc. Please note, that there is no
-explicit protocol field -- you choose a netlink protocol, when
-you create a socket.
-
-The `sequence number` is very important. Netlink is an asynchronous
-protocol -- it means, that the packet order doesn't matter and is
-not guaranteed. But responses to a request are always marked with
-the same sequence number, so you can treat it as a cookie.
-
-Please keep in mind, that a netlink request can initiate a
-cascade of events, and netlink messages from these events can
-carry sequence number == 0. E.g., it is so when you remove a
-primary IP addr from an interface, when `promote_secondaries`
-sysctl is set.
-
-Beside of incapsulated headers and other protocol-specific data,
-netlink messages can carry NLA (netlink attributes). NLA
-structure is as follows::
-
- NLA header:
- + uint16 length
- + uint16 type
- NLA data:
- + data-specific struct
- # optional:
- + NLA
- + NLA
- + ...
-
-So, NLA structures can be nested, forming a tree.
-
-Complete structure of a netlink packet::
-
- nlmsg header:
- + uint32 length
- + uint16 type
- + uint16 flags
- + uint32 sequence number
- + uint32 pid
- [ optional protocol-specific data ]
- [ optional NLA tree ]
-
-More information about netlink protocol you can find in
-the man pages.
-
-Pyroute2 and netlink
-====================
-
-packets
--------
-
-To simplify the development, pyroute2 provides an easy way to
-describe packet structure. As an example, you can take the
-ifaddrmsg description -- `pyroute2/netlink/rtnl/ifaddrmsg.py`.
-
-To describe a packet, you need to inherit from `nlmsg` class::
-
- from pyroute2.netlink import nlmsg
-
- class foo_msg(nlmsg):
- fields = ( ... )
- nla_map = ( ... )
-
-NLA are described in the same way, but the parent class should be
-`nla`, instead of `nlmsg`. And yes, it is important to use the
-proper parent class -- it affects the header structure.
-
-fields attribute
-----------------
-
-The `fields` attribute describes the structure of the
-protocol-specific data. It is a tuple of tuples, where each
-member contains a field name and its data format.
-
-Field data format should be specified as for Python `struct`
-module. E.g., ifaddrmsg structure::
-
- ifaddrmsg structure:
- + unsigned char ifa_family
- + unsigned char ifa_prefixlen
- + unsigned char ifa_flags
- + unsigned char ifa_scope
- + int ifa_index
-
-should be described as follows::
-
- class ifaddrmsg(nlmsg):
- fields = (('family', 'B'),
- ('prefixlen', 'B'),
- ('flags', 'B'),
- ('scope', 'B'),
- ('index', 'I'))
-
-Format strings are passed directly to the `struct` module,
-so you can use all the notations like `>I`, `16s` etc. All
-fields are parsed from the stream separately, so if you
-want to explicitly fix alignemt, as if it were C struct,
-use the `pack` attribute::
-
- class tstats(nla):
- pack = 'struct'
- fields = (('version', 'H'),
- ('ac_exitcode', 'I'),
- ('ac_flag', 'B'),
- ...)
-
-Explicit padding bytes also can be used, when struct
-packing doesn't work well::
-
- class ipq_mode_msg(nlmsg):
- pack = 'struct'
- fields = (('value', 'B'),
- ('__pad', '7x'),
- ('range', 'I'),
- ('__pad', '12x'))
-
-
-nla_map attribute
------------------
-
-The `nla_map` attribute is a tuple of NLA descriptions. Each
-description is also a tuple in two different forms: either
-two fields, name and format, or three fields: type, name and
-format.
-
-Please notice, that the format field is a string name of
-corresponding NLA class::
-
- class ifaddrmsg(nlmsg):
- ...
- nla_map = (('IFA_UNSPEC', 'hex'),
- ('IFA_ADDRESS', 'ipaddr'),
- ('IFA_LOCAL', 'ipaddr'),
- ...)
-
-This code will create mapping, where IFA_ADDRESS NLA will be of
-type 1 and IFA_LOCAL -- of type 2, etc. Both NLA will be decoded
-as IP addresses (class `ipaddr`). IFA_UNSPEC will be of type 0,
-and if it will be in the NLA tree, it will be just dumped in hex.
-
-NLA class names are should be specified as strings, since they
-are resolved in runtime.
-
-There are several pre-defined NLA types, that you will get with
-`nla` class:
-
- - none # forces pyroute2 just to skip this NLA
- - uint8
- - uint16
- - uint32 # there are dedicated NLA of these types as well
- - ipaddr # IP address, IPv4 or IPv6, depending on the socket
- - l2addr # MAC address
- - hex # hex dump as a string -- useful for debugging
- - cdata # just a binary string
- - asciiz # zero-terminated ASCII string
-
-Please refer to `pyroute2/netlink/__init__.py` for details.
-
-You can also make your own NLA descriptions::
-
- class ifaddrmsg(nlmsg):
- ...
- nla_map = (...
- ('IFA_CACHEINFO', 'cacheinfo'),
- ...)
-
- class cacheinfo(nla):
- fields = (('ifa_prefered', 'I'),
- ('ifa_valid', 'I'),
- ('cstamp', 'I'),
- ('tstamp', 'I'))
-
-Custom NLA descriptions should be defined in the same class,
-where they are used.
-
-Also, it is possible to use not autogenerated type numbers, as
-for ifaddrmsg, but specify them explicitly::
-
- class iw_event(nla):
- ...
- nla_map = ((0x8B00, 'SIOCSIWCOMMIT', 'hex'),
- (0x8B01, 'SIOCGIWNAME', 'hex'),
- (0x8B02, 'SIOCSIWNWID', 'hex'),
- (0x8B03, 'SIOCGIWNWID', 'hex'),
- ...)
-
-Here you can see custom NLA type numbers -- 0x8B00, 0x8B01 etc.
-It is not permitted to mix these two forms in one class: you should
-use ether autogenerated type numbers (two fields tuples), or
-explicit numbers (three fields typles).
-
-parsed netlink message
-----------------------
-
-Netlink messages are represented by pyroute2 as dictionaries
-as follows::
-
- {'header': {'pid': ...,
- 'length: ...,
- 'flags': ...,
- 'error': None, # if you are lucky
- 'type': ...,
- 'sequence_number': ...},
-
- # fields attributes
- 'field_name1': value,
- ...
- 'field_nameX': value,
-
- # nla tree
- 'attrs': [['NLA_NAME1', value],
- ...
- ['NLA_NAMEX', value],
- ['NLA_NAMEY', {'field_name1': value,
- ...
- 'field_nameX': value,
- 'attrs': [['NLA_NAME.... ]]}]]}
-
-As an example, a message from the wireless subsystem about new
-scan event::
-
- {'index': 4,
- 'family': 0,
- '__align': 0,
- 'header': {'pid': 0,
- 'length': 64,
- 'flags': 0,
- 'error': None,
- 'type': 16,
- 'sequence_number': 0},
- 'flags': 69699,
- 'ifi_type': 1,
- 'event': 'RTM_NEWLINK',
- 'change': 0,
- 'attrs': [['IFLA_IFNAME', 'wlp3s0'],
- ['IFLA_WIRELESS',
- {'attrs': [['SIOCGIWSCAN',
- '00:00:00:00:00:00:00:00:00:00:00:00']]}]]}
-
-create and send messages
-------------------------
-
-Using high-level interfaces like `IPRoute` or `IPDB`, you will never
-need to manually construct and send netlink messages. But in the case
-you really need it, it is simple as well.
-
-Having a description class, like `ifaddrmsg` from above, you need to:
-
- - instantiate it
- - fill the fields
- - encode the packet
- - send the encoded data
-
-The code::
-
- from pyroute2.netlink import NLM_F_REQUEST
- from pyroute2.netlink import NLM_F_ACK
- from pyroute2.netlink import NLM_F_CREATE
- from pyroute2.netlink import NLM_F_EXCL
- from pyroute2.iproute import RTM_NEWADDR
- from pyroute2.netlink.rtnl.ifaddrmsg import ifaddrmsg
-
- ##
- # add an addr to an interface
- #
-
- # create the message
- msg = ifaddrmsg()
-
- # fill the protocol-specific fields
- msg['index'] = index # index of the interface
- msg['family'] = AF_INET # address family
- msg['prefixlen'] = 24 # the address mask
- msg['scope'] = scope # see /etc/iproute2/rt_scopes
-
- # attach NLA -- it MUST be a list / mutable
- msg['attrs'] = [['IFA_LOCAL', '192.168.0.1'],
- ['IFA_ADDRESS', '192.162.0.1']]
-
- # fill generic netlink fields
- msg['header']['sequence_number'] = nonce # an unique seq number
- msg['header']['pid'] = os.getpid()
- msg['header']['type'] = RTM_NEWADDR
- msg['header']['flags'] = NLM_F_REQUEST |\\
- NLM_F_ACK |\\
- NLM_F_CREATE |\\
- NLM_F_EXCL
-
- # encode the packet
- msg.encode()
-
- # send the buffer
- nlsock.sendto(msg.buf.getvalue(), (0, 0))
-
-Please notice, that NLA list *MUST* be mutable.
-
-------------------
-
-Module contents:
-'''
-
-import traceback
-import logging
-import socket
-import struct
-import types
-import sys
-import io
-import re
-import os
-
-from pyroute2.common import hexdump
-from pyroute2.common import basestring
-
-_letters = re.compile('[A-Za-z]')
-_fmt_letters = re.compile('[^!><@=][!><@=]')
-
-##
-# That's a hack for the code linter, which works under
-# Python3, see unicode reference in the code below
-if sys.version[0] == '3':
- unicode = str
-
-NLMSG_MIN_TYPE = 0x10
-
-GENL_NAMSIZ = 16 # length of family name
-GENL_MIN_ID = NLMSG_MIN_TYPE
-GENL_MAX_ID = 1023
-
-GENL_ADMIN_PERM = 0x01
-GENL_CMD_CAP_DO = 0x02
-GENL_CMD_CAP_DUMP = 0x04
-GENL_CMD_CAP_HASPOL = 0x08
-
-#
-# List of reserved static generic netlink identifiers:
-#
-GENL_ID_GENERATE = 0
-GENL_ID_CTRL = NLMSG_MIN_TYPE
-
-#
-# Controller
-#
-
-CTRL_CMD_UNSPEC = 0x0
-CTRL_CMD_NEWFAMILY = 0x1
-CTRL_CMD_DELFAMILY = 0x2
-CTRL_CMD_GETFAMILY = 0x3
-CTRL_CMD_NEWOPS = 0x4
-CTRL_CMD_DELOPS = 0x5
-CTRL_CMD_GETOPS = 0x6
-CTRL_CMD_NEWMCAST_GRP = 0x7
-CTRL_CMD_DELMCAST_GRP = 0x8
-CTRL_CMD_GETMCAST_GRP = 0x9 # unused
-
-
-CTRL_ATTR_UNSPEC = 0x0
-CTRL_ATTR_FAMILY_ID = 0x1
-CTRL_ATTR_FAMILY_NAME = 0x2
-CTRL_ATTR_VERSION = 0x3
-CTRL_ATTR_HDRSIZE = 0x4
-CTRL_ATTR_MAXATTR = 0x5
-CTRL_ATTR_OPS = 0x6
-CTRL_ATTR_MCAST_GROUPS = 0x7
-
-CTRL_ATTR_OP_UNSPEC = 0x0
-CTRL_ATTR_OP_ID = 0x1
-CTRL_ATTR_OP_FLAGS = 0x2
-
-CTRL_ATTR_MCAST_GRP_UNSPEC = 0x0
-CTRL_ATTR_MCAST_GRP_NAME = 0x1
-CTRL_ATTR_MCAST_GRP_ID = 0x2
-
-
-# Different Netlink families
-#
-NETLINK_ROUTE = 0 # Routing/device hook
-NETLINK_UNUSED = 1 # Unused number
-NETLINK_USERSOCK = 2 # Reserved for user mode socket protocols
-NETLINK_FIREWALL = 3 # Firewalling hook
-NETLINK_INET_DIAG = 4 # INET socket monitoring
-NETLINK_NFLOG = 5 # netfilter/iptables ULOG
-NETLINK_XFRM = 6 # ipsec
-NETLINK_SELINUX = 7 # SELinux event notifications
-NETLINK_ISCSI = 8 # Open-iSCSI
-NETLINK_AUDIT = 9 # auditing
-NETLINK_FIB_LOOKUP = 10
-NETLINK_CONNECTOR = 11
-NETLINK_NETFILTER = 12 # netfilter subsystem
-NETLINK_IP6_FW = 13
-NETLINK_DNRTMSG = 14 # DECnet routing messages
-NETLINK_KOBJECT_UEVENT = 15 # Kernel messages to userspace
-NETLINK_GENERIC = 16
-# leave room for NETLINK_DM (DM Events)
-NETLINK_SCSITRANSPORT = 18 # SCSI Transports
-
-# NLA flags
-NLA_F_NESTED = 1 << 15
-NLA_F_NET_BYTEORDER = 1 << 14
-
-NLMSG_ALIGNTO = 4
-
-
-class NetlinkError(Exception):
- '''
- Base netlink error
- '''
- def __init__(self, code, msg=None):
- msg = msg or os.strerror(code)
- super(NetlinkError, self).__init__(code, msg)
- self.code = code
-
-
-class NetlinkDecodeError(Exception):
- '''
- Base decoding error class.
-
- Incapsulates underlying error for the following analysis
- '''
- def __init__(self, exception):
- self.exception = exception
-
-
-class NetlinkHeaderDecodeError(NetlinkDecodeError):
- '''
- The error occured while decoding a header
- '''
- pass
-
-
-class NetlinkDataDecodeError(NetlinkDecodeError):
- '''
- The error occured while decoding the message fields
- '''
- pass
-
-
-class NetlinkNLADecodeError(NetlinkDecodeError):
- '''
- The error occured while decoding NLA chain
- '''
- pass
-
-
-def NLMSG_ALIGN(l):
- return (l + NLMSG_ALIGNTO - 1) & ~ (NLMSG_ALIGNTO - 1)
-
-
-class NotInitialized(Exception):
- pass
-
-
-# Netlink message flags values (nlmsghdr.flags)
-#
-NLM_F_REQUEST = 1 # It is request message.
-NLM_F_MULTI = 2 # Multipart message, terminated by NLMSG_DONE
-NLM_F_ACK = 4 # Reply with ack, with zero or error code
-NLM_F_ECHO = 8 # Echo this request
-# Modifiers to GET request
-NLM_F_ROOT = 0x100 # specify tree root
-NLM_F_MATCH = 0x200 # return all matching
-NLM_F_ATOMIC = 0x400 # atomic GET
-NLM_F_DUMP = (NLM_F_ROOT | NLM_F_MATCH)
-# Modifiers to NEW request
-NLM_F_REPLACE = 0x100 # Override existing
-NLM_F_EXCL = 0x200 # Do not touch, if it exists
-NLM_F_CREATE = 0x400 # Create, if it does not exist
-NLM_F_APPEND = 0x800 # Add to end of list
-
-NLMSG_NOOP = 0x1 # Nothing
-NLMSG_ERROR = 0x2 # Error
-NLMSG_DONE = 0x3 # End of a dump
-NLMSG_OVERRUN = 0x4 # Data lost
-NLMSG_CONTROL = 0xe # Custom message type for messaging control
-NLMSG_TRANSPORT = 0xf # Custom message type for NL as a transport
-NLMSG_MIN_TYPE = 0x10 # < 0x10: reserved control messages
-NLMSG_MAX_LEN = 0xffff # Max message length
-
-mtypes = {1: 'NLMSG_NOOP',
- 2: 'NLMSG_ERROR',
- 3: 'NLMSG_DONE',
- 4: 'NLMSG_OVERRUN'}
-
-IPRCMD_NOOP = 0
-IPRCMD_STOP = 1
-IPRCMD_ACK = 2
-IPRCMD_ERR = 3
-IPRCMD_REGISTER = 4
-IPRCMD_RELOAD = 5
-IPRCMD_ROUTE = 6
-IPRCMD_CONNECT = 7
-IPRCMD_DISCONNECT = 8
-IPRCMD_SERVE = 9
-IPRCMD_SHUTDOWN = 10
-IPRCMD_SUBSCRIBE = 11
-IPRCMD_UNSUBSCRIBE = 12
-IPRCMD_PROVIDE = 13
-IPRCMD_REMOVE = 14
-IPRCMD_DISCOVER = 15
-IPRCMD_UNREGISTER = 16
-
-SOL_NETLINK = 270
-
-NETLINK_ADD_MEMBERSHIP = 1
-NETLINK_DROP_MEMBERSHIP = 2
-NETLINK_PKTINFO = 3
-NETLINK_BROADCAST_ERROR = 4
-NETLINK_NO_ENOBUFS = 5
-NETLINK_RX_RING = 6
-NETLINK_TX_RING = 7
-
-
-class nlmsg_base(dict):
- '''
- Netlink base class. You do not need to inherit it directly, unless
- you're inventing completely new protocol structure.
-
- Use nlmsg or nla classes.
-
- The class provides several methods, but often one need to customize
- only `decode()` and `encode()`.
- '''
-
- fields = [] # data field names, to build a dictionary
- header = None # optional header class
- pack = None # pack pragma
- array = False
- nla_map = {} # NLA mapping
- nla_flags = 0 # NLA flags
- value_map = {}
-
- def __init__(self, buf=None, length=None, parent=None, debug=False):
- dict.__init__(self)
- for i in self.fields:
- self[i[0]] = 0 # FIXME: only for number values
- self.raw = None
- self.debug = debug
- self.length = length or 0
- self.parent = parent
- self.offset = 0
- self.prefix = None
- self['attrs'] = []
- self['value'] = NotInitialized
- self.value = NotInitialized
- self.register_nlas()
- self.r_value_map = dict([(x[1], x[0]) for x in self.value_map.items()])
- self.reset(buf)
- self.clean_cbs = []
- if self.header is not None:
- self['header'] = self.header(self.buf)
-
- def copy(self):
- '''
- Return a decoded copy of the netlink message. Works
- correctly only if the message was encoded, or is
- received from the socket.
- '''
- ret = type(self)(self.buf.getvalue())
- ret.decode()
- return ret
-
- def reset(self, buf=None):
- '''
- Reset the message buffer. Optionally, set the message
- from the `buf` parameter. This parameter can be either
- string, or io.BytesIO, or dict instance.
- '''
- if isinstance(buf, basestring):
- b = io.BytesIO()
- b.write(buf)
- b.seek(0)
- buf = b
- if isinstance(buf, dict):
- self.setvalue(buf)
- buf = None
- self.buf = buf or io.BytesIO()
- if 'header' in self:
- self['header'].buf = self.buf
-
- def register_clean_cb(self, cb):
- if self.parent is not None:
- return self.parent.register_clean_cb(cb)
- else:
- self.clean_cbs.append(cb)
-
- def _strip_one(self, name):
- for i in tuple(self['attrs']):
- if i[0] == name:
- self['attrs'].remove(i)
- return self
-
- def strip(self, attrs):
- '''
- Remove an NLA from the attrs chain. The `attrs`
- parameter can be either string, or iterable. In
- the latter case, will be stripped NLAs, specified
- in the provided list.
- '''
- if isinstance(attrs, basestring):
- self._strip_one(attrs)
- else:
- for name in attrs:
- self._strip_one(name)
- return self
-
- def __ops(self, rvalue, op0, op1):
- lvalue = self.getvalue()
- res = self.__class__()
- for key in lvalue:
- if key not in ('header', 'attrs'):
- if op0 == '__sub__':
- # operator -, complement
- if (key not in rvalue) or (lvalue[key] != rvalue[key]):
- res[key] = lvalue[key]
- elif op0 == '__and__':
- # operator &, intersection
- if (key in rvalue) and (lvalue[key] == rvalue[key]):
- res[key] = lvalue[key]
- if 'attrs' in lvalue:
- res['attrs'] = []
- for attr in lvalue['attrs']:
- if isinstance(attr[1], nla):
- diff = getattr(attr[1], op0)(rvalue.get_attr(attr[0]))
- if diff is not None:
- res['attrs'].append([attr[0], diff])
- else:
- if op0 == '__sub__':
- # operator -, complement
- if rvalue.get_attr(attr[0]) != attr[1]:
- res['attrs'].append(attr)
- elif op0 == '__and__':
- # operator &, intersection
- if rvalue.get_attr(attr[0]) == attr[1]:
- res['attrs'].append(attr)
- if not len(res):
- return None
- else:
- if 'header' in res:
- del res['header']
- if 'value' in res:
- del res['value']
- if 'attrs' in res and not len(res['attrs']):
- del res['attrs']
- return res
-
- def __sub__(self, rvalue):
- '''
- Subjunction operation.
- '''
- return self.__ops(rvalue, '__sub__', '__ne__')
-
- def __and__(self, rvalue):
- '''
- Conjunction operation.
- '''
- return self.__ops(rvalue, '__and__', '__eq__')
-
- def __eq__(self, rvalue):
- '''
- Having nla, we are able to use it in operations like::
-
- if nla == 'some value':
- ...
- '''
- lvalue = self.getvalue()
- if lvalue is self:
- for key in self:
- try:
- assert self.get(key) == rvalue.get(key)
- except Exception:
- # on any error -- is not equal
- return False
- return True
- else:
- return lvalue == rvalue
-
- @classmethod
- def get_size(self):
- size = 0
- for field in self.fields:
- size += struct.calcsize(field[1])
- return size
-
- @classmethod
- def nla2name(self, name):
- '''
- Convert NLA name into human-friendly name
-
- Example: IFLA_ADDRESS -> address
-
- Requires self.prefix to be set
- '''
- return name[(name.find(self.prefix) + 1) * len(self.prefix):].lower()
-
- @classmethod
- def name2nla(self, name):
- '''
- Convert human-friendly name into NLA name
-
- Example: address -> IFLA_ADDRESS
-
- Requires self.prefix to be set
- '''
- name = name.upper()
- if name.find(self.prefix) == -1:
- name = "%s%s" % (self.prefix, name)
- return name
-
- def reserve(self):
- '''
- Reserve space in the buffer for data. This can be used
- to skip encoding of the header until some fields will
- be known.
- '''
- size = 0
- for i in self.fields:
- size += struct.calcsize(i[1])
- self.buf.seek(size, 1)
-
- def decode(self):
- '''
- Decode the message. The message should have the `buf`
- attribute initialized. e.g.::
-
- data = sock.recv(16384)
- msg = ifinfmsg(data)
-
- If you want to customize the decoding process, override
- the method, but don't forget to call parent's `decode()`::
-
- class CustomMessage(nlmsg):
-
- def decode(self):
- nlmsg.decode(self)
- ... # do some custom data tuning
- '''
- self.offset = self.buf.tell()
- # decode the header
- if self.header is not None:
- try:
- self['header'].decode()
- # update length from header
- # it can not be less than 4
- self.length = max(self['header']['length'], 4)
- save = self.buf.tell()
- self.buf.seek(self.offset)
- self.raw = self.buf.read(self.length)
- self.buf.seek(save)
- except Exception as e:
- raise NetlinkHeaderDecodeError(e)
- # handle the array case
- if self.array:
- self.setvalue([])
- while self.buf.tell() < self.offset + self.length:
- cell = type(self)(self.buf, parent=self, debug=self.debug)
- cell.array = False
- cell.decode()
- self.value.append(cell)
- # decode the data
- try:
- if self.pack == 'struct':
- names = []
- formats = []
- for field in self.fields:
- names.append(field[0])
- formats.append(field[1])
- fields = ((','.join(names), ''.join(formats)), )
- else:
- fields = self.fields
-
- for field in fields:
- name = field[0]
- fmt = field[1]
-
- # 's' and 'z' can be used only in connection with
- # length, encoded in the header
- if field[1] in ('s', 'z'):
- fmt = '%is' % (self.length - 4)
-
- size = struct.calcsize(fmt)
- raw = self.buf.read(size)
- actual_size = len(raw)
-
- # FIXME: adjust string size again
- if field[1] in ('s', 'z'):
- size = actual_size
- fmt = '%is' % (actual_size)
- if size == actual_size:
- value = struct.unpack(fmt, raw)
- if len(value) == 1:
- self[name] = value[0]
- # cut zero-byte from z-strings
- # 0x00 -- python3; '\0' -- python2
- if field[1] == 'z' and self[name][-1] in (0x00, '\0'):
- self[name] = self[name][:-1]
- else:
- if self.pack == 'struct':
- names = name.split(',')
- values = list(value)
- for name in names:
- if name[0] != '_':
- self[name] = values.pop(0)
- else:
- self[name] = value
-
- else:
- # FIXME: log an error
- pass
-
- except Exception as e:
- raise NetlinkDataDecodeError(e)
- # decode NLA
- try:
- # align NLA chain start
- self.buf.seek(NLMSG_ALIGN(self.buf.tell()))
- # read NLA chain
- if self.nla_map:
- self.decode_nlas()
- except Exception as e:
- logging.warning(traceback.format_exc())
- raise NetlinkNLADecodeError(e)
- if len(self['attrs']) == 0:
- del self['attrs']
- if self['value'] is NotInitialized:
- del self['value']
-
- def encode(self):
- '''
- Encode the message into the binary buffer::
-
- msg.encode()
- sock.send(msg.buf.getvalue())
-
- If you want to customize the encoding process, override
- the method::
-
- class CustomMessage(nlmsg):
-
- def encode(self):
- ... # do some custom data tuning
- nlmsg.encode(self)
- '''
- init = self.buf.tell()
- diff = 0
- # reserve space for the header
- if self.header is not None:
- self['header'].reserve()
-
- if self.getvalue() is not None:
-
- payload = b''
- for i in self.fields:
- name = i[0]
- fmt = i[1]
- value = self[name]
-
- if fmt == 's':
- length = len(value)
- fmt = '%is' % (length)
- elif fmt == 'z':
- length = len(value) + 1
- fmt = '%is' % (length)
-
- # in python3 we should force it
- if sys.version[0] == '3':
- if isinstance(value, str):
- value = bytes(value, 'utf-8')
- elif isinstance(value, float):
- value = int(value)
- elif sys.version[0] == '2':
- if isinstance(value, unicode):
- value = value.encode('utf-8')
-
- try:
- if fmt[-1] == 'x':
- payload += struct.pack(fmt)
- elif type(value) in (list, tuple, set):
- payload += struct.pack(fmt, *value)
- else:
- payload += struct.pack(fmt, value)
- except struct.error:
- logging.error(traceback.format_exc())
- logging.error("error pack: %s %s %s" %
- (fmt, value, type(value)))
- raise
-
- diff = NLMSG_ALIGN(len(payload)) - len(payload)
- self.buf.write(payload)
- self.buf.write(b'\0' * diff)
- # write NLA chain
- if self.nla_map:
- diff = 0
- self.encode_nlas()
- # calculate the size and write it
- if self.header is not None:
- self.update_length(init, diff)
-
- def update_length(self, start, diff=0):
- save = self.buf.tell()
- self['header']['length'] = save - start - diff
- self.buf.seek(start)
- self['header'].encode()
- self.buf.seek(save)
-
- def setvalue(self, value):
- if isinstance(value, dict):
- self.update(value)
- else:
- try:
- value = self.r_value_map.get(value, value)
- except TypeError:
- pass
- self['value'] = value
- self.value = value
-
- def get_encoded(self, attr, default=None):
- '''
- Return the first encoded NLA by name
- '''
- return self.get_attr(attr, default, 'encoded')
-
- def get_attr(self, attr, default=None, fmt='raw'):
- '''
- Return the first attr by name or None
- '''
- try:
- attrs = self.get_attrs(attr, fmt)
- except KeyError:
- return default
- if attrs:
- return attrs[0]
- else:
- return default
-
- def get_attrs(self, attr, fmt='raw'):
- '''
- Return attrs by name
- '''
- fmt_map = {'raw': 1,
- 'encoded': 2}
- return [i[fmt_map[fmt]] for i in self['attrs'] if i[0] == attr]
-
- def getvalue(self):
- '''
- Atomic NLAs return their value in the 'value' field,
- not as a dictionary. Complex NLAs return whole dictionary.
- '''
- if self.value != NotInitialized:
- # value decoded by custom decoder
- return self.value
-
- if 'value' in self and self['value'] != NotInitialized:
- # raw value got by generic decoder
- return self.value_map.get(self['value'], self['value'])
-
- return self
-
- def register_nlas(self):
- '''
- Convert 'nla_map' tuple into two dictionaries for mapping
- and reverse mapping of NLA types.
-
- ex: given::
-
- nla_map = (('TCA_HTB_UNSPEC', 'none'),
- ('TCA_HTB_PARMS', 'htb_parms'),
- ('TCA_HTB_INIT', 'htb_glob'))
-
- creates::
-
- t_nla_map = {0: (<class 'pyroute2...none'>, 'TCA_HTB_UNSPEC'),
- 1: (<class 'pyroute2...htb_parms'>, 'TCA_HTB_PARMS'),
- 2: (<class 'pyroute2...htb_glob'>, 'TCA_HTB_INIT')}
- r_nla_map = {'TCA_HTB_UNSPEC': (<class 'pyroute2...none'>, 0),
- 'TCA_HTB_PARMS': (<class 'pyroute2...htb_parms'>, 1),
- 'TCA_HTB_INIT': (<class 'pyroute2...htb_glob'>, 2)}
-
- nla_map format::
-
- nla_map = (([ID, ] NAME, TYPE[, FLAGS]), ...)
-
- Items in `[...]` are optional. If ID is not given, then the map will
- be autonumerated from 0. If flags are not given, they are 0 by default.
-
- '''
- # clean up NLA mappings
- self.t_nla_map = {}
- self.r_nla_map = {}
-
- # work only on non-empty mappings
- if not self.nla_map:
- return
-
- # fix nla flags
- nla_map = []
- for item in self.nla_map:
- if not isinstance(item[-1], int):
- item = list(item)
- item.append(0)
- nla_map.append(item)
-
- # detect, whether we have pre-defined keys
- if not isinstance(nla_map[0][0], int):
- # create enumeration
- nla_types = enumerate((i[0] for i in nla_map))
- # that's a little bit tricky, but to reduce
- # the required amount of code in modules, we have
- # to jump over the head
- zipped = [(k[1][0], k[0][0], k[0][1], k[0][2]) for k in
- zip(nla_map, nla_types)]
- else:
- zipped = nla_map
-
- for (key, name, nla_class, nla_flags) in zipped:
- # is it an array
- if nla_class[0] == '*':
- nla_class = nla_class[1:]
- array = True
- else:
- array = False
- # lookup NLA class
- if nla_class == 'recursive':
- nla_class = type(self)
- else:
- nla_class = getattr(self, nla_class)
- # update mappings
- self.t_nla_map[key] = (nla_class, name, nla_flags, array)
- self.r_nla_map[name] = (nla_class, key, nla_flags, array)
-
- def encode_nlas(self):
- '''
- Encode the NLA chain. Should not be called manually, since
- it is called from `encode()` routine.
- '''
- for i in self['attrs']:
- if i[0] in self.r_nla_map:
- msg_class = self.r_nla_map[i[0]][0]
- msg_type = self.r_nla_map[i[0]][1]
- # is it a class or a function?
- if isinstance(msg_class, types.MethodType):
- # if it is a function -- use it to get the class
- msg_class = msg_class()
- # encode NLA
- nla = msg_class(self.buf, parent=self)
- nla.nla_flags |= self.r_nla_map[i[0]][2]
- nla['header']['type'] = msg_type | nla.nla_flags
- nla.setvalue(i[1])
- try:
- nla.encode()
- except:
- raise
- else:
- if len(i) == 2:
- i.append(nla)
- elif len(i) == 3:
- i[2] = nla
-
- def decode_nlas(self):
- '''
- Decode the NLA chain. Should not be called manually, since
- it is called from `decode()` routine.
- '''
- while self.buf.tell() < (self.offset + self.length):
- init = self.buf.tell()
- nla = None
- # pick the length and the type
- (length, msg_type) = struct.unpack('HH', self.buf.read(4))
- # first two bits of msg_type are flags:
- msg_type = msg_type & ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
- # rewind to the beginning
- self.buf.seek(init)
- length = min(max(length, 4),
- (self.length - self.buf.tell() + self.offset))
-
- # we have a mapping for this NLA
- if msg_type in self.t_nla_map:
- # get the class
- msg_class = self.t_nla_map[msg_type][0]
- # is it a class or a function?
- if isinstance(msg_class, types.MethodType):
- # if it is a function -- use it to get the class
- msg_class = msg_class(buf=self.buf, length=length)
- # and the name
- msg_name = self.t_nla_map[msg_type][1]
- # is it an array?
- msg_array = self.t_nla_map[msg_type][3]
- # decode NLA
- nla = msg_class(self.buf, length, self, debug=self.debug)
- nla.array = msg_array
- try:
- nla.decode()
- nla.nla_flags = msg_type & (NLA_F_NESTED |
- NLA_F_NET_BYTEORDER)
- except Exception:
- logging.warning("decoding %s" % (msg_name))
- logging.warning(traceback.format_exc())
- self.buf.seek(init)
- msg_name = 'UNDECODED'
- msg_value = hexdump(self.buf.read(length))
- else:
- msg_value = nla.getvalue()
- else:
- msg_name = 'UNKNOWN'
- msg_value = hexdump(self.buf.read(length))
-
- self['attrs'].append([msg_name, msg_value])
-
- # fix the offset
- self.buf.seek(init + NLMSG_ALIGN(length))
-
-
-class nla_header(nlmsg_base):
- '''
- The NLA header structure: uin16 length and uint16 type.
- '''
- fields = (('length', 'H'),
- ('type', 'H'))
-
-
-class nla_base(nlmsg_base):
- '''
- The NLA base class. Use `nla_header` class as the header.
- '''
- header = nla_header
-
-
-class nlmsg_header(nlmsg_base):
- '''
- Common netlink message header
- '''
- fields = (('length', 'I'),
- ('type', 'H'),
- ('flags', 'H'),
- ('sequence_number', 'I'),
- ('pid', 'I'))
-
-
-class nlmsg_atoms(nlmsg_base):
- '''
- A collection of base NLA types
- '''
- class none(nla_base):
- '''
- 'none' type is used to skip decoding of NLA. You can
- also use 'hex' type to dump NLA's content.
- '''
- def decode(self):
- nla_base.decode(self)
- self.value = None
-
- class uint8(nla_base):
- fields = [('value', 'B')]
-
- class uint16(nla_base):
- fields = [('value', 'H')]
-
- class uint32(nla_base):
- fields = [('value', 'I')]
-
- class uint64(nla_base):
- fields = [('value', 'Q')]
-
- class be8(nla_base):
- fields = [('value', '>B')]
-
- class be16(nla_base):
- fields = [('value', '>H')]
-
- class be32(nla_base):
- fields = [('value', '>I')]
-
- class be64(nla_base):
- fields = [('value', '>Q')]
-
- class ipXaddr(nla_base):
- fields = [('value', 's')]
- family = None
-
- def encode(self):
- self['value'] = socket.inet_pton(self.family,
- self.value)
- nla_base.encode(self)
-
- def decode(self):
- nla_base.decode(self)
- self.value = socket.inet_ntop(self.family,
- self['value'])
-
- class ip4addr(ipXaddr):
- '''
- Explicit IPv4 address type class.
- '''
- family = socket.AF_INET
-
- class ip6addr(ipXaddr):
- '''
- Explicit IPv6 address type class.
- '''
- family = socket.AF_INET6
-
- class ipaddr(nla_base):
- '''
- This class is used to decode IP addresses according to
- the family. Socket library currently supports only two
- families, AF_INET and AF_INET6.
-
- We do not specify here the string size, it will be
- calculated in runtime.
- '''
- fields = [('value', 's')]
- family_map = {socket.AF_INET: socket.AF_INET,
- socket.AF_BRIDGE: socket.AF_INET,
- socket.AF_INET6: socket.AF_INET6}
-
- def encode(self):
- family = self.family_map[self.parent['family']]
- self['value'] = socket.inet_pton(family, self.value)
- nla_base.encode(self)
-
- def decode(self):
- nla_base.decode(self)
- family = self.family_map[self.parent['family']]
- self.value = socket.inet_ntop(family, self['value'])
-
- class l2addr(nla_base):
- '''
- Decode MAC address.
- '''
- fields = [('value', '=6s')]
-
- def encode(self):
- self['value'] = struct.pack('BBBBBB',
- *[int(i, 16) for i in
- self.value.split(':')])
- nla_base.encode(self)
-
- def decode(self):
- nla_base.decode(self)
- self.value = ':'.join('%02x' % (i) for i in
- struct.unpack('BBBBBB', self['value']))
-
- class hex(nla_base):
- '''
- Represent NLA's content with header as hex string.
- '''
- fields = [('value', 's')]
-
- def decode(self):
- nla_base.decode(self)
- self.value = hexdump(self['value'])
-
- class cdata(nla_base):
- '''
- Binary data
- '''
- fields = [('value', 's')]
-
- class asciiz(nla_base):
- '''
- Zero-terminated string.
- '''
- # FIXME: move z-string hacks from general decode here?
- fields = [('value', 'z')]
-
- def encode(self):
- if isinstance(self['value'], str) and sys.version[0] == '3':
- self['value'] = bytes(self['value'], 'utf-8')
- nla_base.encode(self)
-
- def decode(self):
- nla_base.decode(self)
- try:
- assert sys.version[0] == '3'
- self.value = self['value'].decode('utf-8')
- except (AssertionError, UnicodeDecodeError):
- self.value = self['value']
-
-
-class nla(nla_base, nlmsg_atoms):
- '''
- Main NLA class
- '''
- def decode(self):
- nla_base.decode(self)
- if not self.debug:
- del self['header']
-
-
-class nlmsg(nlmsg_atoms):
- '''
- Main netlink message class
- '''
- header = nlmsg_header
-
-
-class genlmsg(nlmsg):
- '''
- Generic netlink message
- '''
- fields = (('cmd', 'B'),
- ('version', 'B'),
- ('reserved', 'H'))
-
-
-class ctrlmsg(genlmsg):
- '''
- Netlink control message
- '''
- # FIXME: to be extended
- nla_map = (('CTRL_ATTR_UNSPEC', 'none'),
- ('CTRL_ATTR_FAMILY_ID', 'uint16'),
- ('CTRL_ATTR_FAMILY_NAME', 'asciiz'),
- ('CTRL_ATTR_VERSION', 'uint32'),
- ('CTRL_ATTR_HDRSIZE', 'uint32'),
- ('CTRL_ATTR_MAXATTR', 'uint32'),
- ('CTRL_ATTR_OPS', '*ops'),
- ('CTRL_ATTR_MCAST_GROUPS', '*mcast_groups'))
-
- class ops(nla):
- nla_map = (('CTRL_ATTR_OP_UNSPEC', 'none'),
- ('CTRL_ATTR_OP_ID', 'uint32'),
- ('CTRL_ATTR_OP_FLAGS', 'uint32'))
-
- class mcast_groups(nla):
- nla_map = (('CTRL_ATTR_MCAST_GRP_UNSPEC', 'none'),
- ('CTRL_ATTR_MCAST_GRP_NAME', 'asciiz'),
- ('CTRL_ATTR_MCAST_GRP_ID', 'uint32'))
diff --git a/node-admin/scripts/pyroute2/netlink/generic/__init__.py b/node-admin/scripts/pyroute2/netlink/generic/__init__.py
deleted file mode 100644
index 8dfb8cc5fab..00000000000
--- a/node-admin/scripts/pyroute2/netlink/generic/__init__.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-# -*- coding: utf-8 -*-
-'''
-Generic netlink
-===============
-
-Describe
-'''
-
-from pyroute2.netlink import CTRL_CMD_GETFAMILY
-from pyroute2.netlink import GENL_ID_CTRL
-from pyroute2.netlink import NLM_F_REQUEST
-from pyroute2.netlink import SOL_NETLINK
-from pyroute2.netlink import NETLINK_ADD_MEMBERSHIP
-from pyroute2.netlink import NETLINK_DROP_MEMBERSHIP
-from pyroute2.netlink import ctrlmsg
-from pyroute2.netlink.nlsocket import NetlinkSocket
-
-
-class GenericNetlinkSocket(NetlinkSocket):
- '''
- Low-level socket interface. Provides all the
- usual socket does, can be used in poll/select,
- doesn't create any implicit threads.
- '''
-
- mcast_groups = {}
-
- def bind(self, proto, msg_class, groups=0, pid=0, async=False):
- '''
- Bind the socket and performs generic netlink
- proto lookup. The `proto` parameter is a string,
- like "TASKSTATS", `msg_class` is a class to
- parse messages with.
- '''
- NetlinkSocket.bind(self, groups, pid, async)
- self.marshal.msg_map[GENL_ID_CTRL] = ctrlmsg
- msg = self.discovery(proto)
- self.prid = msg.get_attr('CTRL_ATTR_FAMILY_ID')
- self.mcast_groups = \
- dict([(x.get_attr('CTRL_ATTR_MCAST_GRP_NAME'),
- x.get_attr('CTRL_ATTR_MCAST_GRP_ID')) for x
- in msg.get_attr('CTRL_ATTR_MCAST_GROUPS', [])])
- self.marshal.msg_map[self.prid] = msg_class
-
- def add_membership(self, group):
- self.setsockopt(SOL_NETLINK,
- NETLINK_ADD_MEMBERSHIP,
- self.mcast_groups[group])
-
- def drop_membership(self, group):
- self.setsockopt(SOL_NETLINK,
- NETLINK_DROP_MEMBERSHIP,
- self.mcast_groups[group])
-
- def discovery(self, proto):
- '''
- Resolve generic netlink protocol -- takes a string
- as the only parameter, return protocol description
- '''
- msg = ctrlmsg()
- msg['cmd'] = CTRL_CMD_GETFAMILY
- msg['version'] = 1
- msg['attrs'].append(['CTRL_ATTR_FAMILY_NAME', proto])
- msg['header']['type'] = GENL_ID_CTRL
- msg['header']['flags'] = NLM_F_REQUEST
- msg['header']['pid'] = self.pid
- msg.encode()
- self.sendto(msg.buf.getvalue(), (0, 0))
- msg = self.get()[0]
- err = msg['header'].get('error', None)
- if err is not None:
- raise err
- return msg
diff --git a/node-admin/scripts/pyroute2/netlink/ipq/__init__.py b/node-admin/scripts/pyroute2/netlink/ipq/__init__.py
deleted file mode 100644
index 7408f50e877..00000000000
--- a/node-admin/scripts/pyroute2/netlink/ipq/__init__.py
+++ /dev/null
@@ -1,131 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-IPQ -- userspace firewall
-=========================
-
-Netlink family for dealing with `QUEUE` iptables
-target. All the packets routed to the target
-`QUEUE` should be handled by a userspace program
-and the program should response with a verdict.
-E.g., the verdict can be `NF_DROP` and in that
-case the packet will be silently dropped, or
-`NF_ACCEPT`, and the packet will be pass the
-rule.
-'''
-from pyroute2.netlink import NLM_F_REQUEST
-from pyroute2.netlink import nlmsg
-from pyroute2.netlink.nlsocket import NetlinkSocket
-from pyroute2.netlink.nlsocket import Marshal
-# constants
-IFNAMSIZ = 16
-IPQ_MAX_PAYLOAD = 0x800
-
-# IPQ messages
-IPQM_BASE = 0x10
-IPQM_MODE = IPQM_BASE + 1
-IPQM_VERDICT = IPQM_BASE + 2
-IPQM_PACKET = IPQM_BASE + 3
-
-# IPQ modes
-IPQ_COPY_NONE = 0
-IPQ_COPY_META = 1
-IPQ_COPY_PACKET = 2
-
-# verdict types
-NF_DROP = 0
-NF_ACCEPT = 1
-NF_STOLEN = 2
-NF_QUEUE = 3
-NF_REPEAT = 4
-NF_STOP = 5
-
-
-class ipq_base_msg(nlmsg):
- def decode(self):
- nlmsg.decode(self)
- self['payload'] = self.buf.read(self['data_len'])
-
- def encode(self):
- init = self.buf.tell()
- nlmsg.encode(self)
- if 'payload' in self:
- self.buf.write(self['payload'])
- self.update_length(init)
-
-
-class ipq_packet_msg(ipq_base_msg):
- fields = (('packet_id', 'L'),
- ('mark', 'L'),
- ('timestamp_sec', 'l'),
- ('timestamp_usec', 'l'),
- ('hook', 'I'),
- ('indev_name', '%is' % IFNAMSIZ),
- ('outdev_name', '%is' % IFNAMSIZ),
- ('hw_protocol', '>H'),
- ('hw_type', 'H'),
- ('hw_addrlen', 'B'),
- ('hw_addr', '6B'),
- ('__pad', '9x'),
- ('data_len', 'I'),
- ('__pad', '4x'))
-
-
-class ipq_mode_msg(nlmsg):
- pack = 'struct'
- fields = (('value', 'B'),
- ('__pad', '7x'),
- ('range', 'I'),
- ('__pad', '12x'))
-
-
-class ipq_verdict_msg(ipq_base_msg):
- pack = 'struct'
- fields = (('value', 'I'),
- ('__pad', '4x'),
- ('id', 'L'),
- ('data_len', 'I'),
- ('__pad', '4x'))
-
-
-class MarshalIPQ(Marshal):
-
- msg_map = {IPQM_MODE: ipq_mode_msg,
- IPQM_VERDICT: ipq_verdict_msg,
- IPQM_PACKET: ipq_packet_msg}
-
-
-class IPQSocket(NetlinkSocket):
- '''
- Low-level socket interface. Provides all the
- usual socket does, can be used in poll/select,
- doesn't create any implicit threads.
- '''
-
- def bind(self, mode=IPQ_COPY_PACKET):
- '''
- Bind the socket and performs IPQ mode configuration.
- The only parameter is mode, the default value is
- IPQ_COPY_PACKET (copy all the packet data).
- '''
- NetlinkSocket.bind(self, groups=0, pid=0)
- self.register_policy(MarshalIPQ.msg_map)
- msg = ipq_mode_msg()
- msg['value'] = mode
- msg['range'] = IPQ_MAX_PAYLOAD
- msg['header']['type'] = IPQM_MODE
- msg['header']['flags'] = NLM_F_REQUEST
- msg.encode()
- self.sendto(msg.buf.getvalue(), (0, 0))
-
- def verdict(self, seq, v):
- '''
- Issue a verdict `v` for a packet `seq`.
- '''
- msg = ipq_verdict_msg()
- msg['value'] = v
- msg['id'] = seq
- msg['data_len'] = 0
- msg['header']['type'] = IPQM_VERDICT
- msg['header']['flags'] = NLM_F_REQUEST
- msg.encode()
- self.sendto(msg.buf.getvalue(), (0, 0))
diff --git a/node-admin/scripts/pyroute2/netlink/nfnetlink/__init__.py b/node-admin/scripts/pyroute2/netlink/nfnetlink/__init__.py
deleted file mode 100644
index 682414a0ff7..00000000000
--- a/node-admin/scripts/pyroute2/netlink/nfnetlink/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-Nfnetlink
-=========
-
-The support of nfnetlink families is now at the
-very beginning. So there is no public exports
-yet, but you can review the code. Work is in
-progress, stay tuned.
-
-nf-queue
-++++++++
-
-Netfilter protocol for NFQUEUE iptables target.
-'''
-
-from pyroute2.netlink import nlmsg
-
-
-NFNL_SUBSYS_NONE = 0
-NFNL_SUBSYS_CTNETLINK = 1
-NFNL_SUBSYS_CTNETLINK_EXP = 2
-NFNL_SUBSYS_QUEUE = 3
-NFNL_SUBSYS_ULOG = 4
-NFNL_SUBSYS_OSF = 5
-NFNL_SUBSYS_IPSET = 6
-NFNL_SUBSYS_COUNT = 7
-
-
-class nfgen_msg(nlmsg):
- fields = (('nfgen_family', 'B'),
- ('version', 'B'),
- ('res_id', 'H'))
diff --git a/node-admin/scripts/pyroute2/netlink/nfnetlink/ipset.py b/node-admin/scripts/pyroute2/netlink/nfnetlink/ipset.py
deleted file mode 100644
index 10c6d57024e..00000000000
--- a/node-admin/scripts/pyroute2/netlink/nfnetlink/ipset.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-from pyroute2.netlink import nla
-from pyroute2.netlink import NLA_F_NESTED
-from pyroute2.netlink import NLA_F_NET_BYTEORDER
-from pyroute2.netlink.nfnetlink import nfgen_msg
-
-
-IPSET_MAXNAMELEN = 32
-
-IPSET_CMD_NONE = 0
-IPSET_CMD_PROTOCOL = 1 # Return protocol version
-IPSET_CMD_CREATE = 2 # Create a new (empty) set
-IPSET_CMD_DESTROY = 3 # Destroy a (empty) set
-IPSET_CMD_FLUSH = 4 # Remove all elements from a set
-IPSET_CMD_RENAME = 5 # Rename a set
-IPSET_CMD_SWAP = 6 # Swap two sets
-IPSET_CMD_LIST = 7 # List sets
-IPSET_CMD_SAVE = 8 # Save sets
-IPSET_CMD_ADD = 9 # Add an element to a set
-IPSET_CMD_DEL = 10 # Delete an element from a set
-IPSET_CMD_TEST = 11 # Test an element in a set
-IPSET_CMD_HEADER = 12 # Get set header data only
-IPSET_CMD_TYPE = 13 # 13: Get set type
-
-
-class ipset_msg(nfgen_msg):
- '''
- Since the support just begins to be developed,
- many attrs are still in `hex` format -- just to
- dump the content.
- '''
- nla_map = (('IPSET_ATTR_UNSPEC', 'none'),
- ('IPSET_ATTR_PROTOCOL', 'uint8'),
- ('IPSET_ATTR_SETNAME', 'asciiz'),
- ('IPSET_ATTR_TYPENAME', 'asciiz'),
- ('IPSET_ATTR_REVISION', 'uint8'),
- ('IPSET_ATTR_FAMILY', 'uint8'),
- ('IPSET_ATTR_FLAGS', 'hex'),
- ('IPSET_ATTR_DATA', 'data'),
- ('IPSET_ATTR_ADT', 'data'),
- ('IPSET_ATTR_LINENO', 'hex'),
- ('IPSET_ATTR_PROTOCOL_MIN', 'hex'))
-
- class data(nla):
- nla_flags = NLA_F_NESTED
- nla_map = ((0, 'IPSET_ATTR_UNSPEC', 'none'),
- (1, 'IPSET_ATTR_IP', 'ipset_ip'),
- (1, 'IPSET_ATTR_IP_FROM', 'ipset_ip'),
- (2, 'IPSET_ATTR_IP_TO', 'ipset_ip'),
- (3, 'IPSET_ATTR_CIDR', 'hex'),
- (4, 'IPSET_ATTR_PORT', 'hex'),
- (4, 'IPSET_ATTR_PORT_FROM', 'hex'),
- (5, 'IPSET_ATTR_PORT_TO', 'hex'),
- (6, 'IPSET_ATTR_TIMEOUT', 'hex'),
- (7, 'IPSET_ATTR_PROTO', 'recursive'),
- (8, 'IPSET_ATTR_CADT_FLAGS', 'hex'),
- (9, 'IPSET_ATTR_CADT_LINENO', 'be32'),
- (10, 'IPSET_ATTR_MARK', 'hex'),
- (11, 'IPSET_ATTR_MARKMASK', 'hex'),
- (17, 'IPSET_ATTR_GC', 'hex'),
- (18, 'IPSET_ATTR_HASHSIZE', 'be32'),
- (19, 'IPSET_ATTR_MAXELEM', 'be32'),
- (20, 'IPSET_ATTR_NETMASK', 'hex'),
- (21, 'IPSET_ATTR_PROBES', 'hex'),
- (22, 'IPSET_ATTR_RESIZE', 'hex'),
- (23, 'IPSET_ATTR_SIZE', 'hex'),
- (24, 'IPSET_ATTR_ELEMENTS', 'hex'),
- (25, 'IPSET_ATTR_REFERENCES', 'be32'),
- (26, 'IPSET_ATTR_MEMSIZE', 'be32'))
-
- class ipset_ip(nla):
- nla_flags = NLA_F_NESTED
- nla_map = (('IPSET_ATTR_UNSPEC', 'none'),
- ('IPSET_ATTR_IPADDR_IPV4', 'ip4addr',
- NLA_F_NET_BYTEORDER),
- ('IPSET_ATTR_IPADDR_IPV6', 'ip6addr',
- NLA_F_NET_BYTEORDER))
diff --git a/node-admin/scripts/pyroute2/netlink/nl80211/__init__.py b/node-admin/scripts/pyroute2/netlink/nl80211/__init__.py
deleted file mode 100644
index a2946b06dc1..00000000000
--- a/node-admin/scripts/pyroute2/netlink/nl80211/__init__.py
+++ /dev/null
@@ -1,609 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-NL80211 module
-==============
-
-TODO
-'''
-from pyroute2.common import map_namespace
-from pyroute2.netlink import genlmsg
-from pyroute2.netlink.generic import GenericNetlinkSocket
-from pyroute2.netlink.nlsocket import Marshal
-from pyroute2.netlink import nla
-from pyroute2.netlink import nla_base
-
-
-# import pdb
-import struct
-from pyroute2.common import hexdump
-
-# nl80211 commands
-
-NL80211_CMD_UNSPEC = 0
-NL80211_CMD_GET_WIPHY = 1
-NL80211_CMD_SET_WIPHY = 2
-NL80211_CMD_NEW_WIPHY = 3
-NL80211_CMD_DEL_WIPHY = 4
-NL80211_CMD_GET_INTERFACE = 5
-NL80211_CMD_SET_INTERFACE = 6
-NL80211_CMD_NEW_INTERFACE = 7
-NL80211_CMD_DEL_INTERFACE = 8
-NL80211_CMD_GET_KEY = 9
-NL80211_CMD_SET_KEY = 10
-NL80211_CMD_NEW_KEY = 11
-NL80211_CMD_DEL_KEY = 12
-NL80211_CMD_GET_BEACON = 13
-NL80211_CMD_SET_BEACON = 14
-NL80211_CMD_START_AP = 15
-NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP
-NL80211_CMD_STOP_AP = 16
-NL80211_CMD_DEL_BEACON = NL80211_CMD_STOP_AP
-NL80211_CMD_GET_STATION = 17
-NL80211_CMD_SET_STATION = 18
-NL80211_CMD_NEW_STATION = 19
-NL80211_CMD_DEL_STATION = 20
-NL80211_CMD_GET_MPATH = 21
-NL80211_CMD_SET_MPATH = 22
-NL80211_CMD_NEW_MPATH = 23
-NL80211_CMD_DEL_MPATH = 24
-NL80211_CMD_SET_BSS = 25
-NL80211_CMD_SET_REG = 26
-NL80211_CMD_REQ_SET_REG = 27
-NL80211_CMD_GET_MESH_CONFIG = 28
-NL80211_CMD_SET_MESH_CONFIG = 29
-NL80211_CMD_SET_MGMT_EXTRA_IE = 30
-NL80211_CMD_GET_REG = 31
-NL80211_CMD_GET_SCAN = 32
-NL80211_CMD_TRIGGER_SCAN = 33
-NL80211_CMD_NEW_SCAN_RESULTS = 34
-NL80211_CMD_SCAN_ABORTED = 35
-NL80211_CMD_REG_CHANGE = 36
-NL80211_CMD_AUTHENTICATE = 37
-NL80211_CMD_ASSOCIATE = 38
-NL80211_CMD_DEAUTHENTICATE = 39
-NL80211_CMD_DISASSOCIATE = 40
-NL80211_CMD_MICHAEL_MIC_FAILURE = 41
-NL80211_CMD_REG_BEACON_HINT = 42
-NL80211_CMD_JOIN_IBSS = 43
-NL80211_CMD_LEAVE_IBSS = 44
-NL80211_CMD_TESTMODE = 45
-NL80211_CMD_CONNECT = 46
-NL80211_CMD_ROAM = 47
-NL80211_CMD_DISCONNECT = 48
-NL80211_CMD_SET_WIPHY_NETNS = 49
-NL80211_CMD_GET_SURVEY = 50
-NL80211_CMD_NEW_SURVEY_RESULTS = 51
-NL80211_CMD_SET_PMKSA = 52
-NL80211_CMD_DEL_PMKSA = 53
-NL80211_CMD_FLUSH_PMKSA = 54
-NL80211_CMD_REMAIN_ON_CHANNEL = 55
-NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL = 56
-NL80211_CMD_SET_TX_BITRATE_MASK = 57
-NL80211_CMD_REGISTER_FRAME = 58
-NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME
-NL80211_CMD_FRAME = 59
-NL80211_CMD_ACTION = NL80211_CMD_FRAME
-NL80211_CMD_FRAME_TX_STATUS = 60
-NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS
-NL80211_CMD_SET_POWER_SAVE = 61
-NL80211_CMD_GET_POWER_SAVE = 62
-NL80211_CMD_SET_CQM = 63
-NL80211_CMD_NOTIFY_CQM = 64
-NL80211_CMD_SET_CHANNEL = 65
-NL80211_CMD_SET_WDS_PEER = 66
-NL80211_CMD_FRAME_WAIT_CANCEL = 67
-NL80211_CMD_JOIN_MESH = 68
-NL80211_CMD_LEAVE_MESH = 69
-NL80211_CMD_UNPROT_DEAUTHENTICATE = 70
-NL80211_CMD_UNPROT_DISASSOCIATE = 71
-NL80211_CMD_NEW_PEER_CANDIDATE = 72
-NL80211_CMD_GET_WOWLAN = 73
-NL80211_CMD_SET_WOWLAN = 74
-NL80211_CMD_START_SCHED_SCAN = 75
-NL80211_CMD_STOP_SCHED_SCAN = 76
-NL80211_CMD_SCHED_SCAN_RESULTS = 77
-NL80211_CMD_SCHED_SCAN_STOPPED = 78
-NL80211_CMD_SET_REKEY_OFFLOAD = 79
-NL80211_CMD_PMKSA_CANDIDATE = 80
-NL80211_CMD_TDLS_OPER = 81
-NL80211_CMD_TDLS_MGMT = 82
-NL80211_CMD_UNEXPECTED_FRAME = 83
-NL80211_CMD_PROBE_CLIENT = 84
-NL80211_CMD_REGISTER_BEACONS = 85
-NL80211_CMD_UNEXPECTED_4ADDR_FRAME = 86
-NL80211_CMD_SET_NOACK_MAP = 87
-NL80211_CMD_CH_SWITCH_NOTIFY = 88
-NL80211_CMD_START_P2P_DEVICE = 89
-NL80211_CMD_STOP_P2P_DEVICE = 90
-NL80211_CMD_CONN_FAILED = 91
-NL80211_CMD_SET_MCAST_RATE = 92
-NL80211_CMD_SET_MAC_ACL = 93
-NL80211_CMD_RADAR_DETECT = 94
-NL80211_CMD_GET_PROTOCOL_FEATURES = 95
-NL80211_CMD_UPDATE_FT_IES = 96
-NL80211_CMD_FT_EVENT = 97
-NL80211_CMD_CRIT_PROTOCOL_START = 98
-NL80211_CMD_CRIT_PROTOCOL_STOP = 99
-NL80211_CMD_GET_COALESCE = 100
-NL80211_CMD_SET_COALESCE = 101
-NL80211_CMD_CHANNEL_SWITCH = 102
-NL80211_CMD_VENDOR = 103
-NL80211_CMD_SET_QOS_MAP = 104
-NL80211_CMD_ADD_TX_TS = 105
-NL80211_CMD_DEL_TX_TS = 106
-NL80211_CMD_GET_MPP = 107
-NL80211_CMD_JOIN_OCB = 108
-NL80211_CMD_LEAVE_OCB = 109
-NL80211_CMD_CH_SWITCH_STARTED_NOTIFY = 110
-NL80211_CMD_TDLS_CHANNEL_SWITCH = 111
-NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH = 112
-NL80211_CMD_WIPHY_REG_CHANGE = 113
-NL80211_CMD_MAX = NL80211_CMD_WIPHY_REG_CHANGE
-(NL80211_NAMES, NL80211_VALUES) = map_namespace('NL80211_CMD_', globals())
-
-NL80211_BSS_ELEMENTS_SSID = 0
-NL80211_BSS_ELEMENTS_SUPPORTED_RATES = 1
-NL80211_BSS_ELEMENTS_CHANNEL = 3
-NL80211_BSS_ELEMENTS_VENDOR = 221
-
-BSS_MEMBERSHIP_SELECTOR_HT_PHY = 127
-BSS_MEMBERSHIP_SELECTOR_VHT_PHY = 126
-
-# interface types
-NL80211_IFTYPE_UNSPECIFIED = 0
-NL80211_IFTYPE_ADHOC = 1
-NL80211_IFTYPE_STATION = 2
-NL80211_IFTYPE_AP = 3
-NL80211_IFTYPE_AP_VLAN = 4
-NL80211_IFTYPE_WDS = 5
-NL80211_IFTYPE_MONITOR = 6
-NL80211_IFTYPE_MESH_POINT = 7
-NL80211_IFTYPE_P2P_CLIENT = 8
-NL80211_IFTYPE_P2P_GO = 9
-NL80211_IFTYPE_P2P_DEVICE = 10
-NL80211_IFTYPE_OCB = 11
-(IFTYPE_NAMES, IFTYPE_VALUES) = map_namespace('NL80211_IFTYPE_',
- globals(),
- normalize=True)
-
-
-class nl80211cmd(genlmsg):
- nla_map = (('NL80211_ATTR_UNSPEC', 'none'),
- ('NL80211_ATTR_WIPHY', 'uint32'),
- ('NL80211_ATTR_WIPHY_NAME', 'asciiz'),
- ('NL80211_ATTR_IFINDEX', 'uint32'),
- ('NL80211_ATTR_IFNAME', 'asciiz'),
- ('NL80211_ATTR_IFTYPE', 'uint32'),
- ('NL80211_ATTR_MAC', 'l2addr'),
- ('NL80211_ATTR_KEY_DATA', 'hex'),
- ('NL80211_ATTR_KEY_IDX', 'hex'),
- ('NL80211_ATTR_KEY_CIPHER', 'uint32'),
- ('NL80211_ATTR_KEY_SEQ', 'hex'),
- ('NL80211_ATTR_KEY_DEFAULT', 'hex'),
- ('NL80211_ATTR_BEACON_INTERVAL', 'hex'),
- ('NL80211_ATTR_DTIM_PERIOD', 'hex'),
- ('NL80211_ATTR_BEACON_HEAD', 'hex'),
- ('NL80211_ATTR_BEACON_TAIL', 'hex'),
- ('NL80211_ATTR_STA_AID', 'hex'),
- ('NL80211_ATTR_STA_FLAGS', 'hex'),
- ('NL80211_ATTR_STA_LISTEN_INTERVAL', 'hex'),
- ('NL80211_ATTR_STA_SUPPORTED_RATES', 'hex'),
- ('NL80211_ATTR_STA_VLAN', 'hex'),
- ('NL80211_ATTR_STA_INFO', 'hex'),
- ('NL80211_ATTR_WIPHY_BANDS', 'hex'),
- ('NL80211_ATTR_MNTR_FLAGS', 'hex'),
- ('NL80211_ATTR_MESH_ID', 'hex'),
- ('NL80211_ATTR_STA_PLINK_ACTION', 'hex'),
- ('NL80211_ATTR_MPATH_NEXT_HOP', 'hex'),
- ('NL80211_ATTR_MPATH_INFO', 'hex'),
- ('NL80211_ATTR_BSS_CTS_PROT', 'hex'),
- ('NL80211_ATTR_BSS_SHORT_PREAMBLE', 'hex'),
- ('NL80211_ATTR_BSS_SHORT_SLOT_TIME', 'hex'),
- ('NL80211_ATTR_HT_CAPABILITY', 'hex'),
- ('NL80211_ATTR_SUPPORTED_IFTYPES', 'hex'),
- ('NL80211_ATTR_REG_ALPHA2', 'hex'),
- ('NL80211_ATTR_REG_RULES', 'hex'),
- ('NL80211_ATTR_MESH_CONFIG', 'hex'),
- ('NL80211_ATTR_BSS_BASIC_RATES', 'hex'),
- ('NL80211_ATTR_WIPHY_TXQ_PARAMS', 'hex'),
- ('NL80211_ATTR_WIPHY_FREQ', 'uint32'),
- ('NL80211_ATTR_WIPHY_CHANNEL_TYPE', 'hex'),
- ('NL80211_ATTR_KEY_DEFAULT_MGMT', 'hex'),
- ('NL80211_ATTR_MGMT_SUBTYPE', 'hex'),
- ('NL80211_ATTR_IE', 'hex'),
- ('NL80211_ATTR_MAX_NUM_SCAN_SSIDS', 'hex'),
- ('NL80211_ATTR_SCAN_FREQUENCIES', 'hex'),
- ('NL80211_ATTR_SCAN_SSIDS', 'hex'),
- ('NL80211_ATTR_GENERATION', 'hex'),
- ('NL80211_ATTR_BSS', 'bss'),
- ('NL80211_ATTR_REG_INITIATOR', 'hex'),
- ('NL80211_ATTR_REG_TYPE', 'hex'),
- ('NL80211_ATTR_SUPPORTED_COMMANDS', 'hex'),
- ('NL80211_ATTR_FRAME', 'hex'),
- ('NL80211_ATTR_SSID', 'hex'),
- ('NL80211_ATTR_AUTH_TYPE', 'hex'),
- ('NL80211_ATTR_REASON_CODE', 'hex'),
- ('NL80211_ATTR_KEY_TYPE', 'hex'),
- ('NL80211_ATTR_MAX_SCAN_IE_LEN', 'hex'),
- ('NL80211_ATTR_CIPHER_SUITES', 'hex'),
- ('NL80211_ATTR_FREQ_BEFORE', 'hex'),
- ('NL80211_ATTR_FREQ_AFTER', 'hex'),
- ('NL80211_ATTR_FREQ_FIXED', 'hex'),
- ('NL80211_ATTR_WIPHY_RETRY_SHORT', 'hex'),
- ('NL80211_ATTR_WIPHY_RETRY_LONG', 'hex'),
- ('NL80211_ATTR_WIPHY_FRAG_THRESHOLD', 'hex'),
- ('NL80211_ATTR_WIPHY_RTS_THRESHOLD', 'hex'),
- ('NL80211_ATTR_TIMED_OUT', 'hex'),
- ('NL80211_ATTR_USE_MFP', 'hex'),
- ('NL80211_ATTR_STA_FLAGS2', 'hex'),
- ('NL80211_ATTR_CONTROL_PORT', 'hex'),
- ('NL80211_ATTR_TESTDATA', 'hex'),
- ('NL80211_ATTR_PRIVACY', 'hex'),
- ('NL80211_ATTR_DISCONNECTED_BY_AP', 'hex'),
- ('NL80211_ATTR_STATUS_CODE', 'hex'),
- ('NL80211_ATTR_CIPHER_SUITES_PAIRWISE', 'hex'),
- ('NL80211_ATTR_CIPHER_SUITE_GROUP', 'hex'),
- ('NL80211_ATTR_WPA_VERSIONS', 'hex'),
- ('NL80211_ATTR_AKM_SUITES', 'hex'),
- ('NL80211_ATTR_REQ_IE', 'hex'),
- ('NL80211_ATTR_RESP_IE', 'hex'),
- ('NL80211_ATTR_PREV_BSSID', 'hex'),
- ('NL80211_ATTR_KEY', 'hex'),
- ('NL80211_ATTR_KEYS', 'hex'),
- ('NL80211_ATTR_PID', 'hex'),
- ('NL80211_ATTR_4ADDR', 'hex'),
- ('NL80211_ATTR_SURVEY_INFO', 'hex'),
- ('NL80211_ATTR_PMKID', 'hex'),
- ('NL80211_ATTR_MAX_NUM_PMKIDS', 'hex'),
- ('NL80211_ATTR_DURATION', 'hex'),
- ('NL80211_ATTR_COOKIE', 'hex'),
- ('NL80211_ATTR_WIPHY_COVERAGE_CLASS', 'hex'),
- ('NL80211_ATTR_TX_RATES', 'hex'),
- ('NL80211_ATTR_FRAME_MATCH', 'hex'),
- ('NL80211_ATTR_ACK', 'hex'),
- ('NL80211_ATTR_PS_STATE', 'hex'),
- ('NL80211_ATTR_CQM', 'hex'),
- ('NL80211_ATTR_LOCAL_STATE_CHANGE', 'hex'),
- ('NL80211_ATTR_AP_ISOLATE', 'hex'),
- ('NL80211_ATTR_WIPHY_TX_POWER_SETTING', 'hex'),
- ('NL80211_ATTR_WIPHY_TX_POWER_LEVEL', 'hex'),
- ('NL80211_ATTR_TX_FRAME_TYPES', 'hex'),
- ('NL80211_ATTR_RX_FRAME_TYPES', 'hex'),
- ('NL80211_ATTR_FRAME_TYPE', 'hex'),
- ('NL80211_ATTR_CONTROL_PORT_ETHERTYPE', 'hex'),
- ('NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT', 'hex'),
- ('NL80211_ATTR_SUPPORT_IBSS_RSN', 'hex'),
- ('NL80211_ATTR_WIPHY_ANTENNA_TX', 'hex'),
- ('NL80211_ATTR_WIPHY_ANTENNA_RX', 'hex'),
- ('NL80211_ATTR_MCAST_RATE', 'hex'),
- ('NL80211_ATTR_OFFCHANNEL_TX_OK', 'hex'),
- ('NL80211_ATTR_BSS_HT_OPMODE', 'hex'),
- ('NL80211_ATTR_KEY_DEFAULT_TYPES', 'hex'),
- ('NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION', 'hex'),
- ('NL80211_ATTR_MESH_SETUP', 'hex'),
- ('NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX', 'hex'),
- ('NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX', 'hex'),
- ('NL80211_ATTR_SUPPORT_MESH_AUTH', 'hex'),
- ('NL80211_ATTR_STA_PLINK_STATE', 'hex'),
- ('NL80211_ATTR_WOWLAN_TRIGGERS', 'hex'),
- ('NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED', 'hex'),
- ('NL80211_ATTR_SCHED_SCAN_INTERVAL', 'hex'),
- ('NL80211_ATTR_INTERFACE_COMBINATIONS', 'hex'),
- ('NL80211_ATTR_SOFTWARE_IFTYPES', 'hex'),
- ('NL80211_ATTR_REKEY_DATA', 'hex'),
- ('NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS', 'hex'),
- ('NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN', 'hex'),
- ('NL80211_ATTR_SCAN_SUPP_RATES', 'hex'),
- ('NL80211_ATTR_HIDDEN_SSID', 'hex'),
- ('NL80211_ATTR_IE_PROBE_RESP', 'hex'),
- ('NL80211_ATTR_IE_ASSOC_RESP', 'hex'),
- ('NL80211_ATTR_STA_WME', 'hex'),
- ('NL80211_ATTR_SUPPORT_AP_UAPSD', 'hex'),
- ('NL80211_ATTR_ROAM_SUPPORT', 'hex'),
- ('NL80211_ATTR_SCHED_SCAN_MATCH', 'hex'),
- ('NL80211_ATTR_MAX_MATCH_SETS', 'hex'),
- ('NL80211_ATTR_PMKSA_CANDIDATE', 'hex'),
- ('NL80211_ATTR_TX_NO_CCK_RATE', 'hex'),
- ('NL80211_ATTR_TDLS_ACTION', 'hex'),
- ('NL80211_ATTR_TDLS_DIALOG_TOKEN', 'hex'),
- ('NL80211_ATTR_TDLS_OPERATION', 'hex'),
- ('NL80211_ATTR_TDLS_SUPPORT', 'hex'),
- ('NL80211_ATTR_TDLS_EXTERNAL_SETUP', 'hex'),
- ('NL80211_ATTR_DEVICE_AP_SME', 'hex'),
- ('NL80211_ATTR_DONT_WAIT_FOR_ACK', 'hex'),
- ('NL80211_ATTR_FEATURE_FLAGS', 'hex'),
- ('NL80211_ATTR_PROBE_RESP_OFFLOAD', 'hex'),
- ('NL80211_ATTR_PROBE_RESP', 'hex'),
- ('NL80211_ATTR_DFS_REGION', 'hex'),
- ('NL80211_ATTR_DISABLE_HT', 'hex'),
- ('NL80211_ATTR_HT_CAPABILITY_MASK', 'hex'),
- ('NL80211_ATTR_NOACK_MAP', 'hex'),
- ('NL80211_ATTR_INACTIVITY_TIMEOUT', 'hex'),
- ('NL80211_ATTR_RX_SIGNAL_DBM', 'hex'),
- ('NL80211_ATTR_BG_SCAN_PERIOD', 'hex'),
- ('NL80211_ATTR_WDEV', 'uint32'),
- ('NL80211_ATTR_USER_REG_HINT_TYPE', 'hex'),
- ('NL80211_ATTR_CONN_FAILED_REASON', 'hex'),
- ('NL80211_ATTR_SAE_DATA', 'hex'),
- ('NL80211_ATTR_VHT_CAPABILITY', 'hex'),
- ('NL80211_ATTR_SCAN_FLAGS', 'hex'),
- ('NL80211_ATTR_CHANNEL_WIDTH', 'uint32'),
- ('NL80211_ATTR_CENTER_FREQ1', 'hex'),
- ('NL80211_ATTR_CENTER_FREQ2', 'hex'),
- ('NL80211_ATTR_P2P_CTWINDOW', 'hex'),
- ('NL80211_ATTR_P2P_OPPPS', 'hex'),
- ('NL80211_ATTR_LOCAL_MESH_POWER_MODE', 'hex'),
- ('NL80211_ATTR_ACL_POLICY', 'hex'),
- ('NL80211_ATTR_MAC_ADDRS', 'hex'),
- ('NL80211_ATTR_MAC_ACL_MAX', 'hex'),
- ('NL80211_ATTR_RADAR_EVENT', 'hex'),
- ('NL80211_ATTR_EXT_CAPA', 'hex'),
- ('NL80211_ATTR_EXT_CAPA_MASK', 'hex'),
- ('NL80211_ATTR_STA_CAPABILITY', 'hex'),
- ('NL80211_ATTR_STA_EXT_CAPABILITY', 'hex'),
- ('NL80211_ATTR_PROTOCOL_FEATURES', 'hex'),
- ('NL80211_ATTR_SPLIT_WIPHY_DUMP', 'hex'),
- ('NL80211_ATTR_DISABLE_VHT', 'hex'),
- ('NL80211_ATTR_VHT_CAPABILITY_MASK', 'hex'),
- ('NL80211_ATTR_MDID', 'hex'),
- ('NL80211_ATTR_IE_RIC', 'hex'),
- ('NL80211_ATTR_CRIT_PROT_ID', 'hex'),
- ('NL80211_ATTR_MAX_CRIT_PROT_DURATION', 'hex'),
- ('NL80211_ATTR_PEER_AID', 'hex'),
- ('NL80211_ATTR_COALESCE_RULE', 'hex'),
- ('NL80211_ATTR_CH_SWITCH_COUNT', 'hex'),
- ('NL80211_ATTR_CH_SWITCH_BLOCK_TX', 'hex'),
- ('NL80211_ATTR_CSA_IES', 'hex'),
- ('NL80211_ATTR_CSA_C_OFF_BEACON', 'hex'),
- ('NL80211_ATTR_CSA_C_OFF_PRESP', 'hex'),
- ('NL80211_ATTR_RXMGMT_FLAGS', 'hex'),
- ('NL80211_ATTR_STA_SUPPORTED_CHANNELS', 'hex'),
- ('NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES', 'hex'),
- ('NL80211_ATTR_HANDLE_DFS', 'hex'),
- ('NL80211_ATTR_SUPPORT_5_MHZ', 'hex'),
- ('NL80211_ATTR_SUPPORT_10_MHZ', 'hex'),
- ('NL80211_ATTR_OPMODE_NOTIF', 'hex'),
- ('NL80211_ATTR_VENDOR_ID', 'hex'),
- ('NL80211_ATTR_VENDOR_SUBCMD', 'hex'),
- ('NL80211_ATTR_VENDOR_DATA', 'hex'),
- ('NL80211_ATTR_VENDOR_EVENTS', 'hex'),
- ('NL80211_ATTR_QOS_MAP', 'hex'),
- ('NL80211_ATTR_MAC_HINT', 'hex'),
- ('NL80211_ATTR_WIPHY_FREQ_HINT', 'hex'),
- ('NL80211_ATTR_MAX_AP_ASSOC_STA', 'hex'),
- ('NL80211_ATTR_TDLS_PEER_CAPABILITY', 'hex'),
- ('NL80211_ATTR_SOCKET_OWNER', 'hex'),
- ('NL80211_ATTR_CSA_C_OFFSETS_TX', 'hex'),
- ('NL80211_ATTR_MAX_CSA_COUNTERS', 'hex'),
- ('NL80211_ATTR_TDLS_INITIATOR', 'hex'),
- ('NL80211_ATTR_USE_RRM', 'hex'),
- ('NL80211_ATTR_WIPHY_DYN_ACK', 'hex'),
- ('NL80211_ATTR_TSID', 'hex'),
- ('NL80211_ATTR_USER_PRIO', 'hex'),
- ('NL80211_ATTR_ADMITTED_TIME', 'hex'),
- ('NL80211_ATTR_SMPS_MODE', 'hex'),
- ('NL80211_ATTR_OPER_CLASS', 'hex'),
- ('NL80211_ATTR_MAC_MASK', 'hex'),
- ('NL80211_ATTR_WIPHY_SELF_MANAGED_REG', 'hex'),
- ('NUM_NL80211_ATTR', 'hex'))
-
- class bss(nla):
- class elementsBinary(nla_base):
-
- def binary_supported_rates(self, rawdata):
- # pdb.set_trace()
- string = ""
- for byteRaw in rawdata:
- (byte,) = struct.unpack("B", byteRaw)
- r = byte & 0x7f
-
- if r == BSS_MEMBERSHIP_SELECTOR_VHT_PHY and byte & 0x80:
- string += "VHT"
- elif r == BSS_MEMBERSHIP_SELECTOR_HT_PHY and byte & 0x80:
- string += "HT"
- else:
- string += "%d.%d" % (r / 2, 5 * (r & 1))
-
- string += "%s " % ("*" if byte & 0x80 else "")
-
- return string
-
- def binary_vendor(self, rawdata):
- '''
- Extract vendor data
- '''
- vendor = {}
-# pdb.set_trace()
- size = len(rawdata)
- # if len > 4 and rawdata[0] == ms_oui[0]
- # and rawdata[1] == ms_oui[1] and rawdata[2] == ms_oui[2]
-
- if size < 3:
- vendor["VENDOR_NAME"] = "Vendor specific: <too short data:"
- + hexdump(rawdata)
- return vendor
-
- def decode_nlas(self):
-
- return
-
- def decode(self):
- nla_base.decode(self)
-
- self.value = {}
-
- init = self.buf.tell()
-
- while (self.buf.tell()-init) < (self.length-4):
- (msg_type, length) = struct.unpack('BB', self.buf.read(2))
- data = self.buf.read(length)
- if msg_type == NL80211_BSS_ELEMENTS_SSID:
- self.value["SSID"] = data
-
- if msg_type == NL80211_BSS_ELEMENTS_SUPPORTED_RATES:
- supported_rates = self.binary_supported_rates(data)
- self.value["SUPPORTED_RATES"] = supported_rates
-
- if msg_type == NL80211_BSS_ELEMENTS_CHANNEL:
- (channel,) = struct.unpack("B", data[0])
- self.value["CHANNEL"] = channel
-
- if msg_type == NL80211_BSS_ELEMENTS_VENDOR:
- self.binary_vendor(data)
-
- self.buf.seek(init)
-
- prefix = 'NL80211_BSS_'
- nla_map = (('NL80211_BSS_UNSPEC', 'none'),
- ('NL80211_BSS_BSSID', 'hex'),
- ('NL80211_BSS_FREQUENCY', 'uint32'),
- ('NL80211_BSS_TSF', 'uint64'),
- ('NL80211_BSS_BEACON_INTERVAL', 'uint16'),
- ('NL80211_BSS_CAPABILITY', 'uint8'),
- ('NL80211_BSS_INFORMATION_ELEMENTS', 'elementsBinary'),
- ('NL80211_BSS_SIGNAL_MBM', 'uint32'),
- ('NL80211_BSS_STATUS', 'uint32'),
- ('NL80211_BSS_SEEN_MS_AGO', 'uint32'),
- ('NL80211_BSS_BEACON_IES', 'hex'),
- ('NL80211_BSS_CHAN_WIDTH', 'uint32'),
- ('NL80211_BSS_BEACON_TSF', 'uint64')
- )
-
-
-class MarshalNl80211(Marshal):
- msg_map = {NL80211_CMD_UNSPEC: nl80211cmd,
- NL80211_CMD_GET_WIPHY: nl80211cmd,
- NL80211_CMD_SET_WIPHY: nl80211cmd,
- NL80211_CMD_NEW_WIPHY: nl80211cmd,
- NL80211_CMD_DEL_WIPHY: nl80211cmd,
- NL80211_CMD_GET_INTERFACE: nl80211cmd,
- NL80211_CMD_SET_INTERFACE: nl80211cmd,
- NL80211_CMD_NEW_INTERFACE: nl80211cmd,
- NL80211_CMD_DEL_INTERFACE: nl80211cmd,
- NL80211_CMD_GET_KEY: nl80211cmd,
- NL80211_CMD_SET_KEY: nl80211cmd,
- NL80211_CMD_NEW_KEY: nl80211cmd,
- NL80211_CMD_DEL_KEY: nl80211cmd,
- NL80211_CMD_GET_BEACON: nl80211cmd,
- NL80211_CMD_SET_BEACON: nl80211cmd,
- NL80211_CMD_START_AP: nl80211cmd,
- NL80211_CMD_NEW_BEACON: nl80211cmd,
- NL80211_CMD_STOP_AP: nl80211cmd,
- NL80211_CMD_DEL_BEACON: nl80211cmd,
- NL80211_CMD_GET_STATION: nl80211cmd,
- NL80211_CMD_SET_STATION: nl80211cmd,
- NL80211_CMD_NEW_STATION: nl80211cmd,
- NL80211_CMD_DEL_STATION: nl80211cmd,
- NL80211_CMD_GET_MPATH: nl80211cmd,
- NL80211_CMD_SET_MPATH: nl80211cmd,
- NL80211_CMD_NEW_MPATH: nl80211cmd,
- NL80211_CMD_DEL_MPATH: nl80211cmd,
- NL80211_CMD_SET_BSS: nl80211cmd,
- NL80211_CMD_SET_REG: nl80211cmd,
- NL80211_CMD_REQ_SET_REG: nl80211cmd,
- NL80211_CMD_GET_MESH_CONFIG: nl80211cmd,
- NL80211_CMD_SET_MESH_CONFIG: nl80211cmd,
- NL80211_CMD_SET_MGMT_EXTRA_IE: nl80211cmd,
- NL80211_CMD_GET_REG: nl80211cmd,
- NL80211_CMD_GET_SCAN: nl80211cmd,
- NL80211_CMD_TRIGGER_SCAN: nl80211cmd,
- NL80211_CMD_NEW_SCAN_RESULTS: nl80211cmd,
- NL80211_CMD_SCAN_ABORTED: nl80211cmd,
- NL80211_CMD_REG_CHANGE: nl80211cmd,
- NL80211_CMD_AUTHENTICATE: nl80211cmd,
- NL80211_CMD_ASSOCIATE: nl80211cmd,
- NL80211_CMD_DEAUTHENTICATE: nl80211cmd,
- NL80211_CMD_DISASSOCIATE: nl80211cmd,
- NL80211_CMD_MICHAEL_MIC_FAILURE: nl80211cmd,
- NL80211_CMD_REG_BEACON_HINT: nl80211cmd,
- NL80211_CMD_JOIN_IBSS: nl80211cmd,
- NL80211_CMD_LEAVE_IBSS: nl80211cmd,
- NL80211_CMD_TESTMODE: nl80211cmd,
- NL80211_CMD_CONNECT: nl80211cmd,
- NL80211_CMD_ROAM: nl80211cmd,
- NL80211_CMD_DISCONNECT: nl80211cmd,
- NL80211_CMD_SET_WIPHY_NETNS: nl80211cmd,
- NL80211_CMD_GET_SURVEY: nl80211cmd,
- NL80211_CMD_NEW_SURVEY_RESULTS: nl80211cmd,
- NL80211_CMD_SET_PMKSA: nl80211cmd,
- NL80211_CMD_DEL_PMKSA: nl80211cmd,
- NL80211_CMD_FLUSH_PMKSA: nl80211cmd,
- NL80211_CMD_REMAIN_ON_CHANNEL: nl80211cmd,
- NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: nl80211cmd,
- NL80211_CMD_SET_TX_BITRATE_MASK: nl80211cmd,
- NL80211_CMD_REGISTER_FRAME: nl80211cmd,
- NL80211_CMD_REGISTER_ACTION: nl80211cmd,
- NL80211_CMD_FRAME: nl80211cmd,
- NL80211_CMD_ACTION: nl80211cmd,
- NL80211_CMD_FRAME_TX_STATUS: nl80211cmd,
- NL80211_CMD_ACTION_TX_STATUS: nl80211cmd,
- NL80211_CMD_SET_POWER_SAVE: nl80211cmd,
- NL80211_CMD_GET_POWER_SAVE: nl80211cmd,
- NL80211_CMD_SET_CQM: nl80211cmd,
- NL80211_CMD_NOTIFY_CQM: nl80211cmd,
- NL80211_CMD_SET_CHANNEL: nl80211cmd,
- NL80211_CMD_SET_WDS_PEER: nl80211cmd,
- NL80211_CMD_FRAME_WAIT_CANCEL: nl80211cmd,
- NL80211_CMD_JOIN_MESH: nl80211cmd,
- NL80211_CMD_LEAVE_MESH: nl80211cmd,
- NL80211_CMD_UNPROT_DEAUTHENTICATE: nl80211cmd,
- NL80211_CMD_UNPROT_DISASSOCIATE: nl80211cmd,
- NL80211_CMD_NEW_PEER_CANDIDATE: nl80211cmd,
- NL80211_CMD_GET_WOWLAN: nl80211cmd,
- NL80211_CMD_SET_WOWLAN: nl80211cmd,
- NL80211_CMD_START_SCHED_SCAN: nl80211cmd,
- NL80211_CMD_STOP_SCHED_SCAN: nl80211cmd,
- NL80211_CMD_SCHED_SCAN_RESULTS: nl80211cmd,
- NL80211_CMD_SCHED_SCAN_STOPPED: nl80211cmd,
- NL80211_CMD_SET_REKEY_OFFLOAD: nl80211cmd,
- NL80211_CMD_PMKSA_CANDIDATE: nl80211cmd,
- NL80211_CMD_TDLS_OPER: nl80211cmd,
- NL80211_CMD_TDLS_MGMT: nl80211cmd,
- NL80211_CMD_UNEXPECTED_FRAME: nl80211cmd,
- NL80211_CMD_PROBE_CLIENT: nl80211cmd,
- NL80211_CMD_REGISTER_BEACONS: nl80211cmd,
- NL80211_CMD_UNEXPECTED_4ADDR_FRAME: nl80211cmd,
- NL80211_CMD_SET_NOACK_MAP: nl80211cmd,
- NL80211_CMD_CH_SWITCH_NOTIFY: nl80211cmd,
- NL80211_CMD_START_P2P_DEVICE: nl80211cmd,
- NL80211_CMD_STOP_P2P_DEVICE: nl80211cmd,
- NL80211_CMD_CONN_FAILED: nl80211cmd,
- NL80211_CMD_SET_MCAST_RATE: nl80211cmd,
- NL80211_CMD_SET_MAC_ACL: nl80211cmd,
- NL80211_CMD_RADAR_DETECT: nl80211cmd,
- NL80211_CMD_GET_PROTOCOL_FEATURES: nl80211cmd,
- NL80211_CMD_UPDATE_FT_IES: nl80211cmd,
- NL80211_CMD_FT_EVENT: nl80211cmd,
- NL80211_CMD_CRIT_PROTOCOL_START: nl80211cmd,
- NL80211_CMD_CRIT_PROTOCOL_STOP: nl80211cmd,
- NL80211_CMD_GET_COALESCE: nl80211cmd,
- NL80211_CMD_SET_COALESCE: nl80211cmd,
- NL80211_CMD_CHANNEL_SWITCH: nl80211cmd,
- NL80211_CMD_VENDOR: nl80211cmd,
- NL80211_CMD_SET_QOS_MAP: nl80211cmd,
- NL80211_CMD_ADD_TX_TS: nl80211cmd,
- NL80211_CMD_DEL_TX_TS: nl80211cmd,
- NL80211_CMD_GET_MPP: nl80211cmd,
- NL80211_CMD_JOIN_OCB: nl80211cmd,
- NL80211_CMD_LEAVE_OCB: nl80211cmd,
- NL80211_CMD_CH_SWITCH_STARTED_NOTIFY: nl80211cmd,
- NL80211_CMD_TDLS_CHANNEL_SWITCH: nl80211cmd,
- NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH: nl80211cmd,
- NL80211_CMD_WIPHY_REG_CHANGE: nl80211cmd}
-
- def fix_message(self, msg):
- try:
- msg['event'] = NL80211_VALUES[msg['cmd']]
- except Exception:
- pass
-
-
-class NL80211(GenericNetlinkSocket):
-
- def __init__(self):
- GenericNetlinkSocket.__init__(self)
- self.marshal = MarshalNl80211()
-
- def bind(self, groups=0, async=False):
- GenericNetlinkSocket.bind(self, 'nl80211', nl80211cmd,
- groups, None, async)
diff --git a/node-admin/scripts/pyroute2/netlink/nlsocket.py b/node-admin/scripts/pyroute2/netlink/nlsocket.py
deleted file mode 100644
index 432c2a55c4b..00000000000
--- a/node-admin/scripts/pyroute2/netlink/nlsocket.py
+++ /dev/null
@@ -1,856 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-Base netlink socket and marshal
-===============================
-
-All the netlink providers are derived from the socket
-class, so they provide normal socket API, including
-`getsockopt()`, `setsockopt()`, they can be used in
-poll/select I/O loops etc.
-
-asynchronous I/O
-----------------
-
-To run async reader thread, one should call
-`NetlinkSocket.bind(async=True)`. In that case a
-background thread will be launched. The thread will
-automatically collect all the messages and store
-into a userspace buffer.
-
-.. note::
- There is no need to turn on async I/O, if you
- don't plan to receive broadcast messages.
-
-ENOBUF and async I/O
---------------------
-
-When Netlink messages arrive faster than a program
-reads then from the socket, the messages overflow
-the socket buffer and one gets ENOBUF on `recv()`::
-
- ... self.recv(bufsize)
- error: [Errno 105] No buffer space available
-
-One way to avoid ENOBUF, is to use async I/O. Then the
-library not only reads and buffers all the messages, but
-also re-prioritizes threads. Suppressing the parser
-activity, the library increases the response delay, but
-spares CPU to read and enqueue arriving messages as
-fast, as it is possible.
-
-With logging level DEBUG you can notice messages, that
-the library started to calm down the parser thread::
-
- DEBUG:root:Packet burst: the reader thread priority
- is increased, beware of delays on netlink calls
- Counters: delta=25 qsize=25 delay=0.1
-
-This state requires no immediate action, but just some
-more attention. When the delay between messages on the
-parser thread exceeds 1 second, DEBUG messages become
-WARNING ones::
-
- WARNING:root:Packet burst: the reader thread priority
- is increased, beware of delays on netlink calls
- Counters: delta=2525 qsize=213536 delay=3
-
-This state means, that almost all the CPU resources are
-dedicated to the reader thread. It doesn't mean, that
-the reader thread consumes 100% CPU -- it means, that the
-CPU is reserved for the case of more intensive bursts. The
-library will return to the normal state only when the
-broadcast storm will be over, and then the CPU will be
-100% loaded with the parser for some time, when it will
-process all the messages queued so far.
-
-when async I/O doesn't help
----------------------------
-
-Sometimes, even turning async I/O doesn't fix ENOBUF.
-Mostly it means, that in this particular case the Python
-performance is not enough even to read and store the raw
-data from the socket. There is no workaround for such
-cases, except of using something *not* Python-based.
-
-One can still play around with SO_RCVBUF socket option,
-but it doesn't help much. So keep it in mind, and if you
-expect massive broadcast Netlink storms, perform stress
-testing prior to deploy a solution in the production.
-
-classes
--------
-'''
-
-import os
-import sys
-import time
-import select
-import struct
-import logging
-import traceback
-import threading
-
-from socket import AF_NETLINK
-from socket import SOCK_DGRAM
-from socket import MSG_PEEK
-from socket import SOL_SOCKET
-from socket import SO_RCVBUF
-from socket import SO_SNDBUF
-
-from pyroute2.config import SocketBase
-from pyroute2.common import AddrPool
-from pyroute2.common import DEFAULT_RCVBUF
-from pyroute2.netlink import nlmsg
-from pyroute2.netlink import mtypes
-from pyroute2.netlink import NetlinkError
-from pyroute2.netlink import NetlinkDecodeError
-from pyroute2.netlink import NetlinkHeaderDecodeError
-from pyroute2.netlink import NLMSG_ERROR
-from pyroute2.netlink import NLMSG_DONE
-from pyroute2.netlink import NETLINK_GENERIC
-from pyroute2.netlink import NLM_F_DUMP
-from pyroute2.netlink import NLM_F_MULTI
-from pyroute2.netlink import NLM_F_REQUEST
-
-try:
- from Queue import Queue
-except ImportError:
- from queue import Queue
-
-
-class Marshal(object):
- '''
- Generic marshalling class
- '''
-
- msg_map = {}
- debug = False
-
- def __init__(self):
- self.lock = threading.Lock()
- # one marshal instance can be used to parse one
- # message at once
- self.msg_map = self.msg_map or {}
- self.defragmentation = {}
-
- def parse(self, data):
- '''
- Parse string data.
-
- At this moment all transport, except of the native
- Netlink is deprecated in this library, so we should
- not support any defragmentation on that level
- '''
- offset = 0
- result = []
- while offset < len(data):
- # pick type and length
- (length, msg_type) = struct.unpack('IH', data[offset:offset+6])
- error = None
- if msg_type == NLMSG_ERROR:
- code = abs(struct.unpack('i', data[offset+16:offset+20])[0])
- if code > 0:
- error = NetlinkError(code)
-
- msg_class = self.msg_map.get(msg_type, nlmsg)
- msg = msg_class(data[offset:offset+length], debug=self.debug)
-
- try:
- msg.decode()
- msg['header']['error'] = error
- # try to decode encapsulated error message
- if error is not None:
- enc_type = struct.unpack('H', msg.raw[24:26])[0]
- enc_class = self.msg_map.get(enc_type, nlmsg)
- enc = enc_class(msg.raw[20:])
- enc.decode()
- msg['header']['errmsg'] = enc
- except NetlinkHeaderDecodeError as e:
- # in the case of header decoding error,
- # create an empty message
- msg = nlmsg()
- msg['header']['error'] = e
- except NetlinkDecodeError as e:
- msg['header']['error'] = e
-
- mtype = msg['header'].get('type', None)
- if mtype in (1, 2, 3, 4):
- msg['event'] = mtypes.get(mtype, 'none')
- self.fix_message(msg)
- offset += msg.length
- result.append(msg)
-
- return result
-
- def fix_message(self, msg):
- pass
-
-
-# 8<-----------------------------------------------------------
-# Singleton, containing possible modifiers to the NetlinkSocket
-# bind() call.
-#
-# Normally, you can open only one netlink connection for one
-# process, but there is a hack. Current PID_MAX_LIMIT is 2^22,
-# so we can use the rest to midify pid field.
-#
-# See also libnl library, lib/socket.c:generate_local_port()
-sockets = AddrPool(minaddr=0x0,
- maxaddr=0x3ff,
- reverse=True)
-# 8<-----------------------------------------------------------
-
-
-class LockProxy(object):
-
- def __init__(self, factory, key):
- self.factory = factory
- self.refcount = 0
- self.key = key
- self.internal = threading.Lock()
- self.lock = factory.klass()
-
- def acquire(self, *argv, **kwarg):
- with self.internal:
- self.refcount += 1
- return self.lock.acquire()
-
- def release(self):
- with self.internal:
- self.refcount -= 1
- if (self.refcount == 0) and (self.key != 0):
- try:
- del self.factory.locks[self.key]
- except KeyError:
- pass
- return self.lock.release()
-
- def __enter__(self):
- self.acquire()
-
- def __exit__(self, exc_type, exc_value, traceback):
- self.release()
-
-
-class LockFactory(object):
-
- def __init__(self, klass=threading.RLock):
- self.klass = klass
- self.locks = {0: LockProxy(self, 0)}
-
- def __enter__(self):
- self.locks[0].acquire()
-
- def __exit__(self, exc_type, exc_value, traceback):
- self.locks[0].release()
-
- def __getitem__(self, key):
- if key is None:
- key = 0
- if key not in self.locks:
- self.locks[key] = LockProxy(self, key)
- return self.locks[key]
-
- def __delitem__(self, key):
- del self.locks[key]
-
-
-class NetlinkMixin(object):
- '''
- Generic netlink socket
- '''
-
- def __init__(self,
- family=NETLINK_GENERIC,
- port=None,
- pid=None,
- fileno=None):
- #
- # That's a trick. Python 2 is not able to construct
- # sockets from an open FD.
- #
- # So raise an exception, if the major version is < 3
- # and fileno is not None.
- #
- # Do NOT use fileno in a core pyroute2 functionality,
- # since the core should be both Python 2 and 3
- # compatible.
- #
- super(NetlinkMixin, self).__init__()
- if fileno is not None and sys.version_info[0] < 3:
- raise NotImplementedError('fileno parameter is not supported '
- 'on Python < 3.2')
-
- # 8<-----------------------------------------
- # PID init is here only for compatibility,
- # later it will be completely moved to bind()
- self.addr_pool = AddrPool(minaddr=0xff)
- self.epid = None
- self.port = 0
- self.fixed = True
- self.family = family
- self._fileno = fileno
- self.backlog = {0: []}
- self.monitor = False
- self.callbacks = [] # [(predicate, callback, args), ...]
- self.clean_cbs = {} # {msg_seq: [callback, ...], ...}
- self.pthread = None
- self.closed = False
- self.backlog_lock = threading.Lock()
- self.read_lock = threading.Lock()
- self.change_master = threading.Event()
- self.lock = LockFactory()
- self._sock = None
- self._ctrl_read, self._ctrl_write = os.pipe()
- self.buffer_queue = Queue()
- self.qsize = 0
- self.log = []
- self.get_timeout = 30
- self.get_timeout_exception = None
- if pid is None:
- self.pid = os.getpid() & 0x3fffff
- self.port = port
- self.fixed = self.port is not None
- elif pid == 0:
- self.pid = os.getpid()
- else:
- self.pid = pid
- # 8<-----------------------------------------
- self.groups = 0
- self.marshal = Marshal()
- # 8<-----------------------------------------
- # Set defaults
- self.post_init()
-
- def __enter__(self):
- return self
-
- def __exit__(self, exc_type, exc_value, traceback):
- self.close()
-
- def release(self):
- logging.warning("The `release()` call is deprecated")
- logging.warning("Use `close()` instead")
- self.close()
-
- def register_callback(self, callback,
- predicate=lambda x: True, args=None):
- '''
- Register a callback to run on a message arrival.
-
- Callback is the function that will be called with the
- message as the first argument. Predicate is the optional
- callable object, that returns True or False. Upon True,
- the callback will be called. Upon False it will not.
- Args is a list or tuple of arguments.
-
- Simplest example, assume ipr is the IPRoute() instance::
-
- # create a simplest callback that will print messages
- def cb(msg):
- print(msg)
-
- # register callback for any message:
- ipr.register_callback(cb)
-
- More complex example, with filtering::
-
- # Set object's attribute after the message key
- def cb(msg, obj):
- obj.some_attr = msg["some key"]
-
- # Register the callback only for the loopback device, index 1:
- ipr.register_callback(cb,
- lambda x: x.get('index', None) == 1,
- (self, ))
-
- Please note: you do **not** need to register the default 0 queue
- to invoke callbacks on broadcast messages. Callbacks are
- iterated **before** messages get enqueued.
- '''
- if args is None:
- args = []
- self.callbacks.append((predicate, callback, args))
-
- def unregister_callback(self, callback):
- '''
- Remove the first reference to the function from the callback
- register
- '''
- cb = tuple(self.callbacks)
- for cr in cb:
- if cr[1] == callback:
- self.callbacks.pop(cb.index(cr))
- return
-
- def register_policy(self, policy, msg_class=None):
- '''
- Register netlink encoding/decoding policy. Can
- be specified in two ways:
- `nlsocket.register_policy(MSG_ID, msg_class)`
- to register one particular rule, or
- `nlsocket.register_policy({MSG_ID1: msg_class})`
- to register several rules at once.
- E.g.::
-
- policy = {RTM_NEWLINK: ifinfmsg,
- RTM_DELLINK: ifinfmsg,
- RTM_NEWADDR: ifaddrmsg,
- RTM_DELADDR: ifaddrmsg}
- nlsocket.register_policy(policy)
-
- One can call `register_policy()` as many times,
- as one want to -- it will just extend the current
- policy scheme, not replace it.
- '''
- if isinstance(policy, int) and msg_class is not None:
- policy = {policy: msg_class}
-
- assert isinstance(policy, dict)
- for key in policy:
- self.marshal.msg_map[key] = policy[key]
-
- return self.marshal.msg_map
-
- def unregister_policy(self, policy):
- '''
- Unregister policy. Policy can be:
-
- - int -- then it will just remove one policy
- - list or tuple of ints -- remove all given
- - dict -- remove policies by keys from dict
-
- In the last case the routine will ignore dict values,
- it is implemented so just to make it compatible with
- `get_policy_map()` return value.
- '''
- if isinstance(policy, int):
- policy = [policy]
- elif isinstance(policy, dict):
- policy = list(policy)
-
- assert isinstance(policy, (tuple, list, set))
-
- for key in policy:
- del self.marshal.msg_map[key]
-
- return self.marshal.msg_map
-
- def get_policy_map(self, policy=None):
- '''
- Return policy for a given message type or for all
- message types. Policy parameter can be either int,
- or a list of ints. Always return dictionary.
- '''
- if policy is None:
- return self.marshal.msg_map
-
- if isinstance(policy, int):
- policy = [policy]
-
- assert isinstance(policy, (list, tuple, set))
-
- ret = {}
- for key in policy:
- ret[key] = self.marshal.msg_map[key]
-
- return ret
-
- def sendto(self, *argv, **kwarg):
- return self._sendto(*argv, **kwarg)
-
- def recv(self, *argv, **kwarg):
- return self._recv(*argv, **kwarg)
-
- def async_recv(self):
- poll = select.poll()
- poll.register(self._sock, select.POLLIN | select.POLLPRI)
- poll.register(self._ctrl_read, select.POLLIN | select.POLLPRI)
- sockfd = self._sock.fileno()
- while True:
- events = poll.poll()
- for (fd, event) in events:
- if fd == sockfd:
- try:
- self.buffer_queue.put(self._sock.recv(1024 * 1024))
- except Exception as e:
- self.buffer_queue.put(e)
- else:
- return
-
- def put(self, msg, msg_type,
- msg_flags=NLM_F_REQUEST,
- addr=(0, 0),
- msg_seq=0,
- msg_pid=None):
- '''
- Construct a message from a dictionary and send it to
- the socket. Parameters:
-
- - msg -- the message in the dictionary format
- - msg_type -- the message type
- - msg_flags -- the message flags to use in the request
- - addr -- `sendto()` addr, default `(0, 0)`
- - msg_seq -- sequence number to use
- - msg_pid -- pid to use, if `None` -- use os.getpid()
-
- Example::
-
- s = IPRSocket()
- s.bind()
- s.put({'index': 1}, RTM_GETLINK)
- s.get()
- s.close()
-
- Please notice, that the return value of `s.get()` can be
- not the result of `s.put()`, but any broadcast message.
- To fix that, use `msg_seq` -- the response must contain the
- same `msg['header']['sequence_number']` value.
- '''
- if msg_seq != 0:
- self.lock[msg_seq].acquire()
- try:
- if msg_seq not in self.backlog:
- self.backlog[msg_seq] = []
- if not isinstance(msg, nlmsg):
- msg_class = self.marshal.msg_map[msg_type]
- msg = msg_class(msg)
- if msg_pid is None:
- msg_pid = os.getpid()
- msg['header']['type'] = msg_type
- msg['header']['flags'] = msg_flags
- msg['header']['sequence_number'] = msg_seq
- msg['header']['pid'] = msg_pid
- msg.encode()
- if msg_seq not in self.clean_cbs:
- self.clean_cbs[msg_seq] = []
- self.clean_cbs[msg_seq].extend(msg.clean_cbs)
- self.sendto(msg.buf.getvalue(), addr)
- except:
- raise
- finally:
- if msg_seq != 0:
- self.lock[msg_seq].release()
-
- def get(self, bufsize=DEFAULT_RCVBUF, msg_seq=0, terminate=None):
- '''
- Get parsed messages list. If `msg_seq` is given, return
- only messages with that `msg['header']['sequence_number']`,
- saving all other messages into `self.backlog`.
-
- The routine is thread-safe.
-
- The `bufsize` parameter can be:
-
- - -1: bufsize will be calculated from the first 4 bytes of
- the network data
- - 0: bufsize will be calculated from SO_RCVBUF sockopt
- - int >= 0: just a bufsize
- '''
- ctime = time.time()
-
- with self.lock[msg_seq]:
- if bufsize == -1:
- # get bufsize from the network data
- bufsize = struct.unpack("I", self.recv(4, MSG_PEEK))[0]
- elif bufsize == 0:
- # get bufsize from SO_RCVBUF
- bufsize = self.getsockopt(SOL_SOCKET, SO_RCVBUF) // 2
-
- ret = []
- enough = False
- while not enough:
- # 8<-----------------------------------------------------------
- #
- # This stage changes the backlog, so use mutex to
- # prevent side changes
- self.backlog_lock.acquire()
- ##
- # Stage 1. BEGIN
- #
- # 8<-----------------------------------------------------------
- #
- # Check backlog and return already collected
- # messages.
- #
- if msg_seq == 0 and self.backlog[0]:
- # Zero queue.
- #
- # Load the backlog, if there is valid
- # content in it
- ret.extend(self.backlog[0])
- self.backlog[0] = []
- # And just exit
- self.backlog_lock.release()
- break
- elif self.backlog.get(msg_seq, None):
- # Any other msg_seq.
- #
- # Collect messages up to the terminator.
- # Terminator conditions:
- # * NLMSG_ERROR != 0
- # * NLMSG_DONE
- # * terminate() function (if defined)
- # * not NLM_F_MULTI
- #
- # Please note, that if terminator not occured,
- # more `recv()` rounds CAN be required.
- for msg in tuple(self.backlog[msg_seq]):
-
- # Drop the message from the backlog, if any
- self.backlog[msg_seq].remove(msg)
-
- # If there is an error, raise exception
- if msg['header'].get('error', None) is not None:
- self.backlog[0].extend(self.backlog[msg_seq])
- del self.backlog[msg_seq]
- # The loop is done
- self.backlog_lock.release()
- raise msg['header']['error']
-
- # If it is the terminator message, say "enough"
- # and requeue all the rest into Zero queue
- if (msg['header']['type'] == NLMSG_DONE) or \
- (terminate is not None and terminate(msg)):
- # The loop is done
- enough = True
-
- # If it is just a normal message, append it to
- # the response
- if not enough:
- ret.append(msg)
- # But finish the loop on single messages
- if not msg['header']['flags'] & NLM_F_MULTI:
- # but not multi -- so end the loop
- enough = True
-
- # Enough is enough, requeue the rest and delete
- # our backlog
- if enough:
- self.backlog[0].extend(self.backlog[msg_seq])
- del self.backlog[msg_seq]
- break
-
- # Next iteration
- self.backlog_lock.release()
- else:
- # Stage 1. END
- #
- # 8<-------------------------------------------------------
- #
- # Stage 2. BEGIN
- #
- # 8<-------------------------------------------------------
- #
- # Receive the data from the socket and put the messages
- # into the backlog
- #
- self.backlog_lock.release()
- ##
- #
- # Control the timeout. We should not be within the
- # function more than TIMEOUT seconds. All the locks
- # MUST be released here.
- #
- if time.time() - ctime > self.get_timeout:
- if self.get_timeout_exception:
- raise self.get_timeout_exception()
- else:
- return ret
- #
- if self.read_lock.acquire(False):
- self.change_master.clear()
- # If the socket is free to read from, occupy
- # it and wait for the data
- #
- # This is a time consuming process, so all the
- # locks, except the read lock must be released
- data = self.recv(bufsize)
- # Parse data
- msgs = self.marshal.parse(data)
- # Reset ctime -- timeout should be measured
- # for every turn separately
- ctime = time.time()
- #
- current = self.buffer_queue.qsize()
- delta = current - self.qsize
- if delta > 10:
- delay = min(3, max(0.1, float(current) / 60000))
- message = ("Packet burst: the reader thread "
- "priority is increased, beware of "
- "delays on netlink calls\n\tCounters: "
- "delta=%s qsize=%s delay=%s "
- % (delta, current, delay))
- if delay < 1:
- logging.debug(message)
- else:
- logging.warning(message)
- time.sleep(delay)
- self.qsize = current
-
- # We've got the data, lock the backlog again
- self.backlog_lock.acquire()
- for msg in msgs:
- seq = msg['header']['sequence_number']
- if seq in self.clean_cbs:
- for cb in self.clean_cbs[seq]:
- try:
- cb()
- except:
- logging.warning("Cleanup callback"
- "fail: %s" % (cb))
- logging.warning(traceback.format_exc())
- del self.clean_cbs[seq]
- if seq not in self.backlog:
- if msg['header']['type'] == NLMSG_ERROR:
- # Drop orphaned NLMSG_ERROR messages
- continue
- seq = 0
- # 8<-----------------------------------------------
- # Callbacks section
- for cr in self.callbacks:
- try:
- if cr[0](msg):
- cr[1](msg, *cr[2])
- except:
- logging.warning("Callback fail: %s" % (cr))
- logging.warning(traceback.format_exc())
- # 8<-----------------------------------------------
- self.backlog[seq].append(msg)
- # Monitor mode:
- if self.monitor and seq != 0:
- self.backlog[0].append(msg)
- # We finished with the backlog, so release the lock
- self.backlog_lock.release()
-
- # Now wake up other threads
- self.change_master.set()
-
- # Finally, release the read lock: all data processed
- self.read_lock.release()
- else:
- # If the socket is occupied and there is still no
- # data for us, wait for the next master change or
- # for a timeout
- self.change_master.wait(1)
- # 8<-------------------------------------------------------
- #
- # Stage 2. END
- #
- # 8<-------------------------------------------------------
-
- return ret
-
- def nlm_request(self, msg, msg_type,
- msg_flags=NLM_F_REQUEST | NLM_F_DUMP,
- terminate=None):
- msg_seq = self.addr_pool.alloc()
- with self.lock[msg_seq]:
- try:
- self.put(msg, msg_type, msg_flags, msg_seq=msg_seq)
- ret = self.get(msg_seq=msg_seq, terminate=terminate)
- return ret
- except:
- raise
- finally:
- # Ban this msg_seq for 0xff rounds
- #
- # It's a long story. Modern kernels for RTM_SET.* operations
- # always return NLMSG_ERROR(0) == success, even not setting
- # NLM_F_MULTY flag on other response messages and thus w/o
- # any NLMSG_DONE. So, how to detect the response end? One
- # can not rely on NLMSG_ERROR on old kernels, but we have to
- # support them too. Ty, we just ban msg_seq for several rounds,
- # and NLMSG_ERROR, being received, will become orphaned and
- # just dropped.
- #
- # Hack, but true.
- self.addr_pool.free(msg_seq, ban=0xff)
-
-
-class NetlinkSocket(NetlinkMixin):
-
- def post_init(self):
- # recreate the underlying socket
- with self.lock:
- if self._sock is not None:
- self._sock.close()
- self._sock = SocketBase(AF_NETLINK,
- SOCK_DGRAM,
- self.family,
- self._fileno)
- for name in ('getsockname', 'getsockopt', 'makefile',
- 'setsockopt', 'setblocking', 'settimeout',
- 'gettimeout', 'shutdown', 'recvfrom',
- 'recv_into', 'recvfrom_into', 'fileno'):
- setattr(self, name, getattr(self._sock, name))
-
- self._sendto = getattr(self._sock, 'sendto')
- self._recv = getattr(self._sock, 'recv')
-
- self.setsockopt(SOL_SOCKET, SO_SNDBUF, 32768)
- self.setsockopt(SOL_SOCKET, SO_RCVBUF, 1024 * 1024)
-
- def bind(self, groups=0, pid=None, async=False):
- '''
- Bind the socket to given multicast groups, using
- given pid.
-
- - If pid is None, use automatic port allocation
- - If pid == 0, use process' pid
- - If pid == <int>, use the value instead of pid
- '''
- if pid is not None:
- self.port = 0
- self.fixed = True
- self.pid = pid or os.getpid()
-
- self.groups = groups
- # if we have pre-defined port, use it strictly
- if self.fixed:
- self.epid = self.pid + (self.port << 22)
- self._sock.bind((self.epid, self.groups))
- else:
- for port in range(1024):
- try:
- self.port = port
- self.epid = self.pid + (self.port << 22)
- self._sock.bind((self.epid, self.groups))
- break
- except Exception:
- # create a new underlying socket -- on kernel 4
- # one failed bind() makes the socket useless
- self.post_init()
- else:
- raise KeyError('no free address available')
- # all is OK till now, so start async recv, if we need
- if async:
- def recv_plugin(*argv, **kwarg):
- data = self.buffer_queue.get()
- if isinstance(data, Exception):
- raise data
- else:
- return data
- self._recv = recv_plugin
- self.pthread = threading.Thread(target=self.async_recv)
- self.pthread.setDaemon(True)
- self.pthread.start()
-
- def close(self):
- '''
- Correctly close the socket and free all resources.
- '''
- with self.lock:
- if self.closed:
- return
- self.closed = True
-
- if self.pthread:
- os.write(self._ctrl_write, b'exit')
- self.pthread.join()
-
- os.close(self._ctrl_write)
- os.close(self._ctrl_read)
-
- # Common shutdown procedure
- self._sock.close()
diff --git a/node-admin/scripts/pyroute2/netlink/rtnl/__init__.py b/node-admin/scripts/pyroute2/netlink/rtnl/__init__.py
deleted file mode 100644
index fd4c4d03a96..00000000000
--- a/node-admin/scripts/pyroute2/netlink/rtnl/__init__.py
+++ /dev/null
@@ -1,156 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-RTNetlink: network setup
-========================
-
-RTNL is a netlink protocol, used to get and set information
-about different network objects -- addresses, routes, interfaces
-etc.
-
-RTNL protocol-specific data in messages depends on the object
-type. E.g., complete packet with the interface address information::
-
- nlmsg header:
- + uint32 length
- + uint16 type
- + uint16 flags
- + uint32 sequence number
- + uint32 pid
- ifaddrmsg structure:
- + unsigned char ifa_family
- + unsigned char ifa_prefixlen
- + unsigned char ifa_flags
- + unsigned char ifa_scope
- + uint32 ifa_index
- [ optional NLA tree ]
-
-NLA for this kind of packets can be of type IFA_ADDRESS, IFA_LOCAL
-etc. -- please refer to the corresponding source.
-
-Other objects types require different structures, sometimes really
-complex. All these structures are described in sources.
-
----------------------------
-
-Module contents:
-
-'''
-from pyroute2.common import map_namespace
-
-# RTnetlink multicast groups
-RTNLGRP_NONE = 0x0
-RTNLGRP_LINK = 0x1
-RTNLGRP_NOTIFY = 0x2
-RTNLGRP_NEIGH = 0x4
-RTNLGRP_TC = 0x8
-RTNLGRP_IPV4_IFADDR = 0x10
-RTNLGRP_IPV4_MROUTE = 0x20
-RTNLGRP_IPV4_ROUTE = 0x40
-RTNLGRP_IPV4_RULE = 0x80
-RTNLGRP_IPV6_IFADDR = 0x100
-RTNLGRP_IPV6_MROUTE = 0x200
-RTNLGRP_IPV6_ROUTE = 0x400
-RTNLGRP_IPV6_IFINFO = 0x800
-RTNLGRP_DECnet_IFADDR = 0x1000
-RTNLGRP_NOP2 = 0x2000
-RTNLGRP_DECnet_ROUTE = 0x4000
-RTNLGRP_DECnet_RULE = 0x8000
-RTNLGRP_NOP4 = 0x10000
-RTNLGRP_IPV6_PREFIX = 0x20000
-RTNLGRP_IPV6_RULE = 0x40000
-
-# Types of messages
-# RTM_BASE = 16
-RTM_NEWLINK = 16
-RTM_DELLINK = 17
-RTM_GETLINK = 18
-RTM_SETLINK = 19
-RTM_NEWADDR = 20
-RTM_DELADDR = 21
-RTM_GETADDR = 22
-RTM_NEWROUTE = 24
-RTM_DELROUTE = 25
-RTM_GETROUTE = 26
-RTM_NEWNEIGH = 28
-RTM_DELNEIGH = 29
-RTM_GETNEIGH = 30
-RTM_NEWRULE = 32
-RTM_DELRULE = 33
-RTM_GETRULE = 34
-RTM_NEWQDISC = 36
-RTM_DELQDISC = 37
-RTM_GETQDISC = 38
-RTM_NEWTCLASS = 40
-RTM_DELTCLASS = 41
-RTM_GETTCLASS = 42
-RTM_NEWTFILTER = 44
-RTM_DELTFILTER = 45
-RTM_GETTFILTER = 46
-RTM_NEWACTION = 48
-RTM_DELACTION = 49
-RTM_GETACTION = 50
-RTM_NEWPREFIX = 52
-RTM_GETMULTICAST = 58
-RTM_GETANYCAST = 62
-RTM_NEWNEIGHTBL = 64
-RTM_GETNEIGHTBL = 66
-RTM_SETNEIGHTBL = 67
-# custom message types
-RTM_GETBRIDGE = 88
-RTM_SETBRIDGE = 89
-RTM_GETBOND = 90
-RTM_SETBOND = 91
-(RTM_NAMES, RTM_VALUES) = map_namespace('RTM', globals())
-
-TC_H_INGRESS = 0xfffffff1
-TC_H_ROOT = 0xffffffff
-
-
-RTNL_GROUPS = RTNLGRP_IPV4_IFADDR |\
- RTNLGRP_IPV6_IFADDR |\
- RTNLGRP_IPV4_ROUTE |\
- RTNLGRP_IPV6_ROUTE |\
- RTNLGRP_NEIGH |\
- RTNLGRP_LINK |\
- RTNLGRP_TC
-
-
-rtypes = {'RTN_UNSPEC': 0,
- 'RTN_UNICAST': 1, # Gateway or direct route
- 'RTN_LOCAL': 2, # Accept locally
- 'RTN_BROADCAST': 3, # Accept locally as broadcast
- # send as broadcast
- 'RTN_ANYCAST': 4, # Accept locally as broadcast,
- # but send as unicast
- 'RTN_MULTICAST': 5, # Multicast route
- 'RTN_BLACKHOLE': 6, # Drop
- 'RTN_UNREACHABLE': 7, # Destination is unreachable
- 'RTN_PROHIBIT': 8, # Administratively prohibited
- 'RTN_THROW': 9, # Not in this table
- 'RTN_NAT': 10, # Translate this address
- 'RTN_XRESOLVE': 11} # Use external resolver
-
-rtprotos = {'RTPROT_UNSPEC': 0,
- 'RTPROT_REDIRECT': 1, # Route installed by ICMP redirects;
- # not used by current IPv4
- 'RTPROT_KERNEL': 2, # Route installed by kernel
- 'RTPROT_BOOT': 3, # Route installed during boot
- 'RTPROT_STATIC': 4, # Route installed by administrator
- # Values of protocol >= RTPROT_STATIC are not
- # interpreted by kernel;
- # keep in sync with iproute2 !
- 'RTPROT_GATED': 8, # gated
- 'RTPROT_RA': 9, # RDISC/ND router advertisements
- 'RTPROT_MRT': 10, # Merit MRT
- 'RTPROT_ZEBRA': 11, # Zebra
- 'RTPROT_BIRD': 12, # BIRD
- 'RTPROT_DNROUTED': 13, # DECnet routing daemon
- 'RTPROT_XORP': 14, # XORP
- 'RTPROT_NTK': 15, # Netsukuku
- 'RTPROT_DHCP': 16} # DHCP client
-
-rtscopes = {'RT_SCOPE_UNIVERSE': 0,
- 'RT_SCOPE_SITE': 200,
- 'RT_SCOPE_LINK': 253,
- 'RT_SCOPE_HOST': 254,
- 'RT_SCOPE_NOWHERE': 255}
diff --git a/node-admin/scripts/pyroute2/netlink/rtnl/errmsg.py b/node-admin/scripts/pyroute2/netlink/rtnl/errmsg.py
deleted file mode 100644
index 2bea8091730..00000000000
--- a/node-admin/scripts/pyroute2/netlink/rtnl/errmsg.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-from pyroute2.netlink import nlmsg
-
-
-class errmsg(nlmsg):
- '''
- Custom message type
-
- Error ersatz-message
- '''
- fields = (('code', 'i'), )
diff --git a/node-admin/scripts/pyroute2/netlink/rtnl/fibmsg.py b/node-admin/scripts/pyroute2/netlink/rtnl/fibmsg.py
deleted file mode 100644
index 686160da398..00000000000
--- a/node-admin/scripts/pyroute2/netlink/rtnl/fibmsg.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-
-from pyroute2.common import map_namespace
-from pyroute2.netlink import nlmsg
-
-FR_ACT_UNSPEC = 0
-FR_ACT_TO_TBL = 1
-FR_ACT_GOTO = 2
-FR_ACT_NOP = 3
-FR_ACT_BLACKHOLE = 6
-FR_ACT_UNREACHABLE = 7
-FR_ACT_PROHIBIT = 8
-(FR_ACT_NAMES, FR_ACT_VALUES) = map_namespace('FR_ACT', globals())
-
-
-class fibmsg(nlmsg):
- '''
- IP rule message
-
- C structure::
-
- struct fib_rule_hdr {
- __u8 family;
- __u8 dst_len;
- __u8 src_len;
- __u8 tos;
- __u8 table;
- __u8 res1; /* reserved */
- __u8 res2; /* reserved */
- __u8 action;
- __u32 flags;
- };
- '''
- prefix = 'FRA_'
-
- fields = (('family', 'B'),
- ('dst_len', 'B'),
- ('src_len', 'B'),
- ('tos', 'B'),
- ('table', 'B'),
- ('res1', 'B'),
- ('res2', 'B'),
- ('action', 'B'),
- ('flags', 'I'))
-
- # fibmsg NLA numbers are not sequential, so
- # give it here explicitly
- nla_map = ((0, 'FRA_UNSPEC', 'none'),
- (1, 'FRA_DST', 'ipaddr'),
- (2, 'FRA_SRC', 'ipaddr'),
- (3, 'FRA_IIFNAME', 'asciiz'),
- (4, 'FRA_GOTO', 'uint32'),
- (6, 'FRA_PRIORITY', 'uint32'),
- (10, 'FRA_FWMARK', 'uint32'),
- (11, 'FRA_FLOW', 'uint32'),
- (13, 'FRA_SUPPRESS_IFGROUP', 'uint32'),
- (14, 'FRA_SUPPRESS_PREFIXLEN', 'uint32'),
- (15, 'FRA_TABLE', 'uint32'),
- (16, 'FRA_FWMASK', 'uint32'),
- (17, 'FRA_OIFNAME', 'asciiz'))
diff --git a/node-admin/scripts/pyroute2/netlink/rtnl/ifaddrmsg.py b/node-admin/scripts/pyroute2/netlink/rtnl/ifaddrmsg.py
deleted file mode 100644
index 0ecb2273611..00000000000
--- a/node-admin/scripts/pyroute2/netlink/rtnl/ifaddrmsg.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-import socket
-from pyroute2.common import map_namespace
-from pyroute2.netlink import nlmsg
-from pyroute2.netlink import nla
-
-# address attributes
-#
-# Important comment:
-# For IPv4, IFA_ADDRESS is a prefix address, not a local interface
-# address. It makes no difference for normal interfaces, but
-# for point-to-point ones IFA_ADDRESS means DESTINATION address,
-# and the local address is supplied in IFA_LOCAL attribute.
-#
-
-IFA_F_SECONDARY = 0x01
-# IFA_F_TEMPORARY IFA_F_SECONDARY
-IFA_F_NODAD = 0x02
-IFA_F_OPTIMISTIC = 0x04
-IFA_F_DADFAILED = 0x08
-IFA_F_HOMEADDRESS = 0x10
-IFA_F_DEPRECATED = 0x20
-IFA_F_TENTATIVE = 0x40
-IFA_F_PERMANENT = 0x80
-IFA_F_MANAGETEMPADDR = 0x100
-IFA_F_NOPREFIXROUTE = 0x200
-
-(IFA_F_NAMES, IFA_F_VALUES) = map_namespace('IFA_F', globals())
-# 8<----------------------------------------------
-IFA_F_TEMPORARY = IFA_F_SECONDARY
-IFA_F_NAMES['IFA_F_TEMPORARY'] = IFA_F_TEMPORARY
-IFA_F_VALUES6 = IFA_F_VALUES
-IFA_F_VALUES6[IFA_F_TEMPORARY] = 'IFA_F_TEMPORARY'
-# 8<----------------------------------------------
-
-
-class ifaddrmsg(nlmsg):
- '''
- IP address information
-
- C structure::
-
- struct ifaddrmsg {
- unsigned char ifa_family; /* Address type */
- unsigned char ifa_prefixlen; /* Prefixlength of address */
- unsigned char ifa_flags; /* Address flags */
- unsigned char ifa_scope; /* Address scope */
- int ifa_index; /* Interface index */
- };
-
- '''
- prefix = 'IFA_'
-
- fields = (('family', 'B'),
- ('prefixlen', 'B'),
- ('flags', 'B'),
- ('scope', 'B'),
- ('index', 'I'))
-
- nla_map = (('IFA_UNSPEC', 'hex'),
- ('IFA_ADDRESS', 'ipaddr'),
- ('IFA_LOCAL', 'ipaddr'),
- ('IFA_LABEL', 'asciiz'),
- ('IFA_BROADCAST', 'ipaddr'),
- ('IFA_ANYCAST', 'ipaddr'),
- ('IFA_CACHEINFO', 'cacheinfo'),
- ('IFA_MULTICAST', 'ipaddr'),
- ('IFA_FLAGS', 'uint32'))
-
- class cacheinfo(nla):
- fields = (('ifa_prefered', 'I'),
- ('ifa_valid', 'I'),
- ('cstamp', 'I'),
- ('tstamp', 'I'))
-
- @staticmethod
- def flags2names(flags, family=socket.AF_INET):
- if family == socket.AF_INET6:
- ifa_f_values = IFA_F_VALUES6
- else:
- ifa_f_values = IFA_F_VALUES
- ret = []
- for f in ifa_f_values:
- if f & flags:
- ret.append(ifa_f_values[f])
- return ret
-
- @staticmethod
- def names2flags(flags):
- ret = 0
- for f in flags:
- if f[0] == '!':
- f = f[1:]
- else:
- ret |= IFA_F_NAMES[f]
- return ret
diff --git a/node-admin/scripts/pyroute2/netlink/rtnl/ifinfmsg.py b/node-admin/scripts/pyroute2/netlink/rtnl/ifinfmsg.py
deleted file mode 100644
index 02bc1cf17a7..00000000000
--- a/node-admin/scripts/pyroute2/netlink/rtnl/ifinfmsg.py
+++ /dev/null
@@ -1,1068 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-import os
-import time
-import json
-import struct
-import logging
-import platform
-import subprocess
-from fcntl import ioctl
-from pyroute2.common import map_namespace
-from pyroute2.common import ANCIENT
-# from pyroute2.netlink import NLMSG_ERROR
-from pyroute2.netlink import nla
-from pyroute2.netlink import nlmsg
-from pyroute2.netlink import nlmsg_atoms
-from pyroute2.netlink.rtnl.iw_event import iw_event
-
-
-# it's simpler to double constants here, than to change all the
-# module layout; but it is a subject of the future refactoring
-RTM_NEWLINK = 16
-RTM_DELLINK = 17
-#
-
-_ANCIENT_BARRIER = 0.3
-_BONDING_MASTERS = '/sys/class/net/bonding_masters'
-_BONDING_SLAVES = '/sys/class/net/%s/bonding/slaves'
-_BRIDGE_MASTER = '/sys/class/net/%s/brport/bridge/ifindex'
-_BONDING_MASTER = '/sys/class/net/%s/master/ifindex'
-IFNAMSIZ = 16
-
-TUNDEV = '/dev/net/tun'
-arch = platform.machine()
-if arch == 'x86_64':
- TUNSETIFF = 0x400454ca
- TUNSETPERSIST = 0x400454cb
- TUNSETOWNER = 0x400454cc
- TUNSETGROUP = 0x400454ce
-elif arch in ('ppc64', 'mips'):
- TUNSETIFF = 0x800454ca
- TUNSETPERSIST = 0x800454cb
- TUNSETOWNER = 0x800454cc
- TUNSETGROUP = 0x800454ce
-else:
- TUNSETIFF = None
-
-##
-#
-# tuntap flags
-#
-IFT_TUN = 0x0001
-IFT_TAP = 0x0002
-IFT_NO_PI = 0x1000
-IFT_ONE_QUEUE = 0x2000
-IFT_VNET_HDR = 0x4000
-IFT_TUN_EXCL = 0x8000
-IFT_MULTI_QUEUE = 0x0100
-IFT_ATTACH_QUEUE = 0x0200
-IFT_DETACH_QUEUE = 0x0400
-# read-only
-IFT_PERSIST = 0x0800
-IFT_NOFILTER = 0x1000
-
-##
-#
-# normal flags
-#
-IFF_UP = 0x1 # interface is up
-IFF_BROADCAST = 0x2 # broadcast address valid
-IFF_DEBUG = 0x4 # turn on debugging
-IFF_LOOPBACK = 0x8 # is a loopback net
-IFF_POINTOPOINT = 0x10 # interface is has p-p link
-IFF_NOTRAILERS = 0x20 # avoid use of trailers
-IFF_RUNNING = 0x40 # interface RFC2863 OPER_UP
-IFF_NOARP = 0x80 # no ARP protocol
-IFF_PROMISC = 0x100 # receive all packets
-IFF_ALLMULTI = 0x200 # receive all multicast packets
-IFF_MASTER = 0x400 # master of a load balancer
-IFF_SLAVE = 0x800 # slave of a load balancer
-IFF_MULTICAST = 0x1000 # Supports multicast
-IFF_PORTSEL = 0x2000 # can set media type
-IFF_AUTOMEDIA = 0x4000 # auto media select active
-IFF_DYNAMIC = 0x8000 # dialup device with changing addresses
-IFF_LOWER_UP = 0x10000 # driver signals L1 up
-IFF_DORMANT = 0x20000 # driver signals dormant
-IFF_ECHO = 0x40000 # echo sent packets
-
-(IFF_NAMES, IFF_VALUES) = map_namespace('IFF', globals())
-
-IFF_MASK = IFF_UP |\
- IFF_DEBUG |\
- IFF_NOTRAILERS |\
- IFF_NOARP |\
- IFF_PROMISC |\
- IFF_ALLMULTI
-
-IFF_VOLATILE = IFF_LOOPBACK |\
- IFF_POINTOPOINT |\
- IFF_BROADCAST |\
- IFF_ECHO |\
- IFF_MASTER |\
- IFF_SLAVE |\
- IFF_RUNNING |\
- IFF_LOWER_UP |\
- IFF_DORMANT
-
-states = ('UNKNOWN',
- 'NOTPRESENT',
- 'DOWN',
- 'LOWERLAYERDOWN',
- 'TESTING',
- 'DORMANT',
- 'UP')
-state_by_name = dict(((i[1], i[0]) for i in enumerate(states)))
-state_by_code = dict(enumerate(states))
-stats_names = ('rx_packets',
- 'tx_packets',
- 'rx_bytes',
- 'tx_bytes',
- 'rx_errors',
- 'tx_errors',
- 'rx_dropped',
- 'tx_dropped',
- 'multicast',
- 'collisions',
- 'rx_length_errors',
- 'rx_over_errors',
- 'rx_crc_errors',
- 'rx_frame_errors',
- 'rx_fifo_errors',
- 'rx_missed_errors',
- 'tx_aborted_errors',
- 'tx_carrier_errors',
- 'tx_fifo_errors',
- 'tx_heartbeat_errors',
- 'tx_window_errors',
- 'rx_compressed',
- 'tx_compressed')
-
-
-class ifinfbase(object):
- '''
- Network interface message.
-
- C structure::
-
- struct ifinfomsg {
- unsigned char ifi_family; /* AF_UNSPEC */
- unsigned short ifi_type; /* Device type */
- int ifi_index; /* Interface index */
- unsigned int ifi_flags; /* Device flags */
- unsigned int ifi_change; /* change mask */
- };
- '''
- prefix = 'IFLA_'
-
- fields = (('family', 'B'),
- ('__align', 'B'),
- ('ifi_type', 'H'),
- ('index', 'i'),
- ('flags', 'I'),
- ('change', 'I'))
-
- nla_map = (('IFLA_UNSPEC', 'none'),
- ('IFLA_ADDRESS', 'l2addr'),
- ('IFLA_BROADCAST', 'l2addr'),
- ('IFLA_IFNAME', 'asciiz'),
- ('IFLA_MTU', 'uint32'),
- ('IFLA_LINK', 'uint32'),
- ('IFLA_QDISC', 'asciiz'),
- ('IFLA_STATS', 'ifstats'),
- ('IFLA_COST', 'hex'),
- ('IFLA_PRIORITY', 'hex'),
- ('IFLA_MASTER', 'uint32'),
- ('IFLA_WIRELESS', 'wireless'),
- ('IFLA_PROTINFO', 'hex'),
- ('IFLA_TXQLEN', 'uint32'),
- ('IFLA_MAP', 'ifmap'),
- ('IFLA_WEIGHT', 'hex'),
- ('IFLA_OPERSTATE', 'state'),
- ('IFLA_LINKMODE', 'uint8'),
- ('IFLA_LINKINFO', 'ifinfo'),
- ('IFLA_NET_NS_PID', 'uint32'),
- ('IFLA_IFALIAS', 'asciiz'),
- ('IFLA_NUM_VF', 'uint32'),
- ('IFLA_VFINFO_LIST', 'hex'),
- ('IFLA_STATS64', 'ifstats64'),
- ('IFLA_VF_PORTS', 'hex'),
- ('IFLA_PORT_SELF', 'hex'),
- ('IFLA_AF_SPEC', 'af_spec'),
- ('IFLA_GROUP', 'uint32'),
- ('IFLA_NET_NS_FD', 'netns_fd'),
- ('IFLA_EXT_MASK', 'hex'),
- ('IFLA_PROMISCUITY', 'uint32'),
- ('IFLA_NUM_TX_QUEUES', 'uint32'),
- ('IFLA_NUM_RX_QUEUES', 'uint32'),
- ('IFLA_CARRIER', 'uint8'),
- ('IFLA_PHYS_PORT_ID', 'hex'),
- ('IFLA_CARRIER_CHANGES', 'uint32'))
-
- @staticmethod
- def flags2names(flags, mask=0xffffffff):
- ret = []
- for flag in IFF_VALUES:
- if (flag & mask & flags) == flag:
- ret.append(IFF_VALUES[flag])
- return ret
-
- @staticmethod
- def names2flags(flags):
- ret = 0
- mask = 0
- for flag in flags:
- if flag[0] == '!':
- flag = flag[1:]
- else:
- ret |= IFF_NAMES[flag]
- mask |= IFF_NAMES[flag]
- return (ret, mask)
-
- def encode(self):
- # convert flags
- if isinstance(self['flags'], (set, tuple, list)):
- self['flags'], self['change'] = self.names2flags(self['flags'])
- return super(ifinfbase, self).encode()
-
- class netns_fd(nla):
- fields = [('value', 'I')]
- netns_run_dir = '/var/run/netns'
- netns_fd = None
-
- def encode(self):
- self.close()
- #
- # There are two ways to specify netns
- #
- # 1. provide fd to an open file
- # 2. provide a file name
- #
- # In the first case, the value is passed to the kernel
- # as is. In the second case, the object opens appropriate
- # file from `self.netns_run_dir` and closes it upon
- # `__del__(self)`
- if isinstance(self.value, int):
- self['value'] = self.value
- else:
- self.netns_fd = os.open('%s/%s' % (self.netns_run_dir,
- self.value), os.O_RDONLY)
- self['value'] = self.netns_fd
- nla.encode(self)
- self.register_clean_cb(self.close)
-
- def close(self):
- if self.netns_fd is not None:
- os.close(self.netns_fd)
-
- class wireless(iw_event):
- pass
-
- class state(nla):
- fields = (('value', 'B'), )
-
- def encode(self):
- self['value'] = state_by_name[self.value]
- nla.encode(self)
-
- def decode(self):
- nla.decode(self)
- self.value = state_by_code[self['value']]
-
- class ifstats(nla):
- fields = [(i, 'I') for i in stats_names]
-
- class ifstats64(nla):
- fields = [(i, 'Q') for i in stats_names]
-
- class ifmap(nla):
- fields = (('mem_start', 'Q'),
- ('mem_end', 'Q'),
- ('base_addr', 'Q'),
- ('irq', 'H'),
- ('dma', 'B'),
- ('port', 'B'))
-
- class ifinfo(nla):
- nla_map = (('IFLA_INFO_UNSPEC', 'none'),
- ('IFLA_INFO_KIND', 'asciiz'),
- ('IFLA_INFO_DATA', 'info_data'),
- ('IFLA_INFO_XSTATS', 'hex'),
- ('IFLA_INFO_SLAVE_KIND', 'asciiz'),
- ('IFLA_INFO_SLAVE_DATA', 'info_data'))
-
- def info_data(self, *argv, **kwarg):
- '''
- The function returns appropriate IFLA_INFO_DATA
- type according to IFLA_INFO_KIND info. Return
- 'hex' type for all unknown kind's and when the
- kind is not known.
- '''
- kind = self.get_attr('IFLA_INFO_KIND')
- slave = self.get_attr('IFLA_INFO_SLAVE_KIND')
- data_map = {'vlan': self.vlan_data,
- 'vxlan': self.vxlan_data,
- 'macvlan': self.macvlan_data,
- 'macvtap': self.macvtap_data,
- 'gre': self.gre_data,
- 'bond': self.bond_data,
- 'veth': self.veth_data,
- 'tuntap': self.tuntap_data,
- 'bridge': self.bridge_data}
- slave_map = {'openvswitch': self.ovs_data}
- return data_map.get(kind, slave_map.get(slave, self.hex))
-
- class tuntap_data(nla):
- '''
- Fake data type
- '''
- prefix = 'IFTUN_'
-
- nla_map = (('IFTUN_UNSPEC', 'none'),
- ('IFTUN_MODE', 'asciiz'),
- ('IFTUN_UID', 'uint32'),
- ('IFTUN_GID', 'uint32'),
- ('IFTUN_IFR', 'flags'))
-
- class flags(nla):
- fields = (('no_pi', 'B'),
- ('one_queue', 'B'),
- ('vnet_hdr', 'B'),
- ('tun_excl', 'B'),
- ('multi_queue', 'B'),
- ('persist', 'B'),
- ('nofilter', 'B'))
-
- class veth_data(nla):
- nla_map = (('VETH_INFO_UNSPEC', 'none'),
- ('VETH_INFO_PEER', 'info_peer'))
-
- def info_peer(self, *argv, **kwarg):
- return ifinfveth
-
- class ovs_data(nla):
- prefix = 'IFLA_'
- nla_map = (('IFLA_OVS_UNSPEC', 'none'),
- ('IFLA_OVS_MASTER_IFNAME', 'asciiz'))
-
- class vxlan_data(nla):
- prefix = 'IFLA_'
- nla_map = (('IFLA_VXLAN_UNSPEC', 'none'),
- ('IFLA_VXLAN_ID', 'uint32'),
- ('IFLA_VXLAN_GROUP', 'ip4addr'),
- ('IFLA_VXLAN_LINK', 'uint32'),
- ('IFLA_VXLAN_LOCAL', 'ip4addr'),
- ('IFLA_VXLAN_TTL', 'uint8'),
- ('IFLA_VXLAN_TOS', 'uint8'),
- ('IFLA_VXLAN_LEARNING', 'uint8'),
- ('IFLA_VXLAN_AGEING', 'uint32'),
- ('IFLA_VXLAN_LIMIT', 'uint32'),
- ('IFLA_VXLAN_PORT_RANGE', 'port_range'),
- ('IFLA_VXLAN_PROXY', 'uint8'),
- ('IFLA_VXLAN_RSC', 'uint8'),
- ('IFLA_VXLAN_L2MISS', 'uint8'),
- ('IFLA_VXLAN_L3MISS', 'uint8'),
- ('IFLA_VXLAN_PORT', 'uint16'),
- ('IFLA_VXLAN_GROUP6', 'ip6addr'),
- ('IFLA_VXLAN_LOCAL6', 'ip6addr'),
- ('IFLA_VXLAN_UDP_CSUM', 'uint8'),
- ('IFLA_VXLAN_UDP_ZERO_CSUM6_TX', 'uint8'),
- ('IFLA_VXLAN_UDP_ZERO_CSUM6_RX', 'uint8'))
-
- class port_range(nla):
- fields = (('low', '>H'),
- ('high', '>H'))
-
- class gre_data(nla):
- prefix = 'IFLA_'
-
- nla_map = (('IFLA_GRE_UNSPEC', 'none'),
- ('IFLA_GRE_LINK', 'uint32'),
- ('IFLA_GRE_IFLAGS', 'uint16'),
- ('IFLA_GRE_OFLAGS', 'uint16'),
- ('IFLA_GRE_IKEY', 'uint32'),
- ('IFLA_GRE_OKEY', 'uint32'),
- ('IFLA_GRE_LOCAL', 'ip4addr'),
- ('IFLA_GRE_REMOTE', 'ip4addr'),
- ('IFLA_GRE_TTL', 'uint8'),
- ('IFLA_GRE_TOS', 'uint8'),
- ('IFLA_GRE_PMTUDISC', 'uint8'),
- ('IFLA_GRE_ENCAP_LIMIT', 'uint8'),
- ('IFLA_GRE_FLOWINFO', 'uint32'),
- ('IFLA_GRE_FLAGS', 'uint32'))
-
- class macvx_data(nla):
- prefix = 'IFLA_'
-
- class mode(nlmsg_atoms.uint32):
- value_map = {0: 'none',
- 1: 'private',
- 2: 'vepa',
- 4: 'bridge',
- 8: 'passthru'}
-
- class flags(nlmsg_atoms.uint16):
- value_map = {0: 'none',
- 1: 'nopromisc'}
-
- class macvtap_data(macvx_data):
- nla_map = (('IFLA_MACVTAP_UNSPEC', 'none'),
- ('IFLA_MACVTAP_MODE', 'mode'),
- ('IFLA_MACVTAP_FLAGS', 'flags'))
-
- class macvlan_data(macvx_data):
- nla_map = (('IFLA_MACVLAN_UNSPEC', 'none'),
- ('IFLA_MACVLAN_MODE', 'mode'),
- ('IFLA_MACVLAN_FLAGS', 'flags'))
-
- class vlan_data(nla):
- nla_map = (('IFLA_VLAN_UNSPEC', 'none'),
- ('IFLA_VLAN_ID', 'uint16'),
- ('IFLA_VLAN_FLAGS', 'vlan_flags'),
- ('IFLA_VLAN_EGRESS_QOS', 'hex'),
- ('IFLA_VLAN_INGRESS_QOS', 'hex'))
-
- class vlan_flags(nla):
- fields = (('flags', 'I'),
- ('mask', 'I'))
-
- class bridge_data(nla):
- prefix = 'IFLA_BRIDGE_'
- nla_map = (('IFLA_BRIDGE_STP_STATE', 'uint32'),
- ('IFLA_BRIDGE_MAX_AGE', 'uint32'))
-
- class bond_data(nla):
- prefix = 'IFLA_BOND_'
- nla_map = (('IFLA_BOND_UNSPEC', 'none'),
- ('IFLA_BOND_MODE', 'uint8'),
- ('IFLA_BOND_ACTIVE_SLAVE', 'uint32'),
- ('IFLA_BOND_MIIMON', 'uint32'),
- ('IFLA_BOND_UPDELAY', 'uint32'),
- ('IFLA_BOND_DOWNDELAY', 'uint32'),
- ('IFLA_BOND_USE_CARRIER', 'uint8'),
- ('IFLA_BOND_ARP_INTERVAL', 'uint32'),
- ('IFLA_BOND_ARP_IP_TARGET', 'arp_ip_target'),
- ('IFLA_BOND_ARP_VALIDATE', 'uint32'),
- ('IFLA_BOND_ARP_ALL_TARGETS', 'uint32'),
- ('IFLA_BOND_PRIMARY', 'uint32'),
- ('IFLA_BOND_PRIMARY_RESELECT', 'uint8'),
- ('IFLA_BOND_FAIL_OVER_MAC', 'uint8'),
- ('IFLA_BOND_XMIT_HASH_POLICY', 'uint8'),
- ('IFLA_BOND_RESEND_IGMP', 'uint32'),
- ('IFLA_BOND_NUM_PEER_NOTIF', 'uint8'),
- ('IFLA_BOND_ALL_SLAVES_ACTIVE', 'uint8'),
- ('IFLA_BOND_MIN_LINKS', 'uint32'),
- ('IFLA_BOND_LP_INTERVAL', 'uint32'),
- ('IFLA_BOND_PACKETS_PER_SLAVE', 'uint32'),
- ('IFLA_BOND_AD_LACP_RATE', 'uint8'),
- ('IFLA_BOND_AD_SELECT', 'uint8'),
- ('IFLA_BOND_AD_INFO', 'ad_info'))
-
- class ad_info(nla):
- nla_map = (('IFLA_BOND_AD_INFO_UNSPEC', 'none'),
- ('IFLA_BOND_AD_INFO_AGGREGATOR', 'uint16'),
- ('IFLA_BOND_AD_INFO_NUM_PORTS', 'uint16'),
- ('IFLA_BOND_AD_INFO_ACTOR_KEY', 'uint16'),
- ('IFLA_BOND_AD_INFO_PARTNER_KEY', 'uint16'),
- ('IFLA_BOND_AD_INFO_PARTNER_MAC', 'l2addr'))
-
- class arp_ip_target(nla):
- fields = (('targets', '16I'), )
-
- class af_spec(nla):
- nla_map = (('AF_UNSPEC', 'none'),
- ('AF_UNIX', 'hex'),
- ('AF_INET', 'inet'),
- ('AF_AX25', 'hex'),
- ('AF_IPX', 'hex'),
- ('AF_APPLETALK', 'hex'),
- ('AF_NETROM', 'hex'),
- ('AF_BRIDGE', 'hex'),
- ('AF_ATMPVC', 'hex'),
- ('AF_X25', 'hex'),
- ('AF_INET6', 'inet6'))
-
- class inet(nla):
- # ./include/linux/inetdevice.h: struct ipv4_devconf
- field_names = ('sysctl',
- 'forwarding',
- 'mc_forwarding',
- 'proxy_arp',
- 'accept_redirects',
- 'secure_redirects',
- 'send_redirects',
- 'shared_media',
- 'rp_filter',
- 'accept_source_route',
- 'bootp_relay',
- 'log_martians',
- 'tag',
- 'arp_filter',
- 'medium_id',
- 'disable_xfrm',
- 'disable_policy',
- 'force_igmp_version',
- 'arp_announce',
- 'arp_ignore',
- 'promote_secondaries',
- 'arp_accept',
- 'arp_notify',
- 'accept_local',
- 'src_valid_mark',
- 'proxy_arp_pvlan',
- 'route_localnet')
- fields = [(i, 'I') for i in field_names]
-
- class inet6(nla):
- nla_map = (('IFLA_INET6_UNSPEC', 'none'),
- ('IFLA_INET6_FLAGS', 'uint32'),
- ('IFLA_INET6_CONF', 'ipv6_devconf'),
- ('IFLA_INET6_STATS', 'ipv6_stats'),
- ('IFLA_INET6_MCAST', 'hex'),
- ('IFLA_INET6_CACHEINFO', 'ipv6_cache_info'),
- ('IFLA_INET6_ICMP6STATS', 'icmp6_stats'),
- ('IFLA_INET6_TOKEN', 'ip6addr'),
- ('IFLA_INET6_ADDR_GEN_MODE', 'uint8'))
-
- class ipv6_devconf(nla):
- # ./include/uapi/linux/ipv6.h
- # DEVCONF_
- field_names = ('forwarding',
- 'hop_limit',
- 'mtu',
- 'accept_ra',
- 'accept_redirects',
- 'autoconf',
- 'dad_transmits',
- 'router_solicitations',
- 'router_solicitation_interval',
- 'router_solicitation_delay',
- 'use_tempaddr',
- 'temp_valid_lft',
- 'temp_prefered_lft',
- 'regen_max_retry',
- 'max_desync_factor',
- 'max_addresses',
- 'force_mld_version',
- 'accept_ra_defrtr',
- 'accept_ra_pinfo',
- 'accept_ra_rtr_pref',
- 'router_probe_interval',
- 'accept_ra_rt_info_max_plen',
- 'proxy_ndp',
- 'optimistic_dad',
- 'accept_source_route',
- 'mc_forwarding',
- 'disable_ipv6',
- 'accept_dad',
- 'force_tllao',
- 'ndisc_notify')
- fields = [(i, 'I') for i in field_names]
-
- class ipv6_cache_info(nla):
- # ./include/uapi/linux/if_link.h: struct ifla_cacheinfo
- fields = (('max_reasm_len', 'I'),
- ('tstamp', 'I'),
- ('reachable_time', 'I'),
- ('retrans_time', 'I'))
-
- class ipv6_stats(nla):
- field_names = ('inoctets',
- 'fragcreates',
- 'indiscards',
- 'num',
- 'outoctets',
- 'outnoroutes',
- 'inbcastoctets',
- 'outforwdatagrams',
- 'outpkts',
- 'reasmtimeout',
- 'inhdrerrors',
- 'reasmreqds',
- 'fragfails',
- 'outmcastpkts',
- 'inaddrerrors',
- 'inmcastpkts',
- 'reasmfails',
- 'outdiscards',
- 'outbcastoctets',
- 'inmcastoctets',
- 'inpkts',
- 'fragoks',
- 'intoobigerrors',
- 'inunknownprotos',
- 'intruncatedpkts',
- 'outbcastpkts',
- 'reasmoks',
- 'inbcastpkts',
- 'innoroutes',
- 'indelivers',
- 'outmcastoctets')
- fields = [(i, 'I') for i in field_names]
-
- class icmp6_stats(nla):
- fields = (('num', 'Q'),
- ('inerrors', 'Q'),
- ('outmsgs', 'Q'),
- ('outerrors', 'Q'),
- ('inmsgs', 'Q'))
-
-
-class ifinfmsg(ifinfbase, nlmsg):
- pass
-
-
-class ifinfveth(ifinfbase, nla):
- pass
-
-
-def compat_fix_attrs(msg):
- kind = None
- ifname = msg.get_attr('IFLA_IFNAME')
-
- # fix master
- if ANCIENT:
- master = compat_get_master(ifname)
- if master is not None:
- msg['attrs'].append(['IFLA_MASTER', master])
-
- # fix linkinfo & kind
- li = msg.get_attr('IFLA_LINKINFO')
- if li is not None:
- kind = li.get_attr('IFLA_INFO_KIND')
- slave_kind = li.get_attr('IFLA_INFO_SLAVE_KIND')
- if kind is None:
- kind = get_interface_type(ifname)
- li['attrs'].append(['IFLA_INFO_KIND', kind])
- else:
- kind = get_interface_type(ifname)
- slave_kind = None
- msg['attrs'].append(['IFLA_LINKINFO',
- {'attrs': [['IFLA_INFO_KIND', kind]]}])
-
- li = msg.get_attr('IFLA_LINKINFO')
- # fetch specific interface data
- if slave_kind == 'openvswitch':
- # fix master for the OVS slave
- proc = subprocess.Popen(['ovs-vsctl', 'iface-to-br', ifname],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- ret = proc.communicate()
- if ret[1]:
- logging.warning("ovs communication error: %s" % ret[1])
- commands = [['IFLA_OVS_MASTER_IFNAME', ret[0].strip()]]
- li['attrs'].append(['IFLA_INFO_DATA', {'attrs': commands}])
-
- if (kind in ('bridge', 'bond')) and \
- [x for x in li['attrs'] if x[0] == 'IFLA_INFO_DATA']:
- if kind == 'bridge':
- t = '/sys/class/net/%s/bridge/%s'
- ifdata = ifinfmsg.ifinfo.bridge_data
- elif kind == 'bond':
- t = '/sys/class/net/%s/bonding/%s'
- ifdata = ifinfmsg.ifinfo.bond_data
-
- commands = []
- for cmd, _ in ifdata.nla_map:
- try:
- with open(t % (ifname, ifdata.nla2name(cmd)), 'r') as f:
- value = f.read()
- if cmd == 'IFLA_BOND_MODE':
- value = value.split()[1]
- commands.append([cmd, int(value)])
- except:
- pass
- if commands:
- li['attrs'].append(['IFLA_INFO_DATA', {'attrs': commands}])
-
-
-def proxy_linkinfo(data, nl):
- offset = 0
- inbox = []
- while offset < len(data):
- msg = ifinfmsg(data[offset:])
- msg.decode()
- inbox.append(msg)
- offset += msg['header']['length']
-
- data = b''
- for msg in inbox:
- # Sysfs operations can require root permissions,
- # but the script can be run under a normal user
- # Bug-Url: https://github.com/svinota/pyroute2/issues/113
- try:
- compat_fix_attrs(msg)
- except OSError:
- # We can safely ignore here any OSError.
- # In the worst case, we just return what we have got
- # from the kernel via netlink
- pass
-
- msg.reset()
- msg.encode()
- data += msg.buf.getvalue()
-
- return {'verdict': 'forward',
- 'data': data}
-
-
-def proxy_setlink(data, nl):
-
- def get_interface(index):
- msg = nl.get_links(index)[0]
- try:
- ovs_master = msg.\
- get_attr('IFLA_LINKINFO').\
- get_attr('IFLA_INFO_DATA').\
- get_attr('IFLA_OVS_MASTER_IFNAME')
- except Exception:
- ovs_master = None
- return {'ifname': msg.get_attr('IFLA_IFNAME'),
- 'master': msg.get_attr('IFLA_MASTER'),
- 'ovs-master': ovs_master,
- 'kind': msg.
- get_attr('IFLA_LINKINFO').
- get_attr('IFLA_INFO_KIND')}
-
- msg = ifinfmsg(data)
- msg.decode()
- forward = True
-
- kind = None
- infodata = None
-
- ifname = msg.get_attr('IFLA_IFNAME') or \
- get_interface(msg['index'])['ifname']
- linkinfo = msg.get_attr('IFLA_LINKINFO')
- if linkinfo:
- kind = linkinfo.get_attr('IFLA_INFO_KIND')
- infodata = linkinfo.get_attr('IFLA_INFO_DATA')
-
- if kind in ('bond', 'bridge'):
- code = 0
- #
- if kind == 'bond':
- func = compat_set_bond
- elif kind == 'bridge':
- func = compat_set_bridge
- #
- for (cmd, value) in infodata.get('attrs', []):
- cmd = infodata.nla2name(cmd)
- code = func(ifname, cmd, value) or code
- #
- if code:
- err = OSError()
- err.errno = code
- raise err
-
- # is it a port setup?
- master = msg.get_attr('IFLA_MASTER')
- if master is not None:
-
- if master == 0:
- # port delete
- # 1. get the current master
- iface = get_interface(msg['index'])
- if iface['ovs-master'] is not None:
- master = {'ifname': iface['ovs-master'],
- 'kind': 'openvswitch'}
- else:
- master = get_interface(iface['master'])
- cmd = 'del'
- else:
- # port add
- # 1. get the master
- master = get_interface(master)
- cmd = 'add'
-
- # 2. manage the port
- forward_map = {'team': manage_team_port,
- 'bridge': compat_bridge_port,
- 'bond': compat_bond_port,
- 'openvswitch': manage_ovs_port}
- forward = forward_map[master['kind']](cmd, master['ifname'], ifname)
-
- if forward is not None:
- return {'verdict': 'forward',
- 'data': data}
-
-
-def proxy_dellink(data, nl):
- orig_msg = ifinfmsg(data)
- orig_msg.decode()
-
- # get full interface description
- msg = nl.get_links(orig_msg['index'])[0]
- msg['header']['type'] = orig_msg['header']['type']
-
- # get the interface kind
- kind = None
- li = msg.get_attr('IFLA_LINKINFO')
- if li is not None:
- kind = li.get_attr('IFLA_INFO_KIND')
-
- if kind in ('ovs-bridge', 'openvswitch'):
- return manage_ovs(msg)
-
- if ANCIENT and kind in ('bridge', 'bond'):
- # route the request
- if kind == 'bridge':
- compat_del_bridge(msg.get_attr('IFLA_IFNAME'))
- elif kind == 'bond':
- compat_del_bond(msg.get_attr('IFLA_IFNAME'))
- # while RTM_NEWLINK is not intercepted -- sleep
- time.sleep(_ANCIENT_BARRIER)
- return
-
- return {'verdict': 'forward',
- 'data': data}
-
-
-def proxy_newlink(data, nl):
- msg = ifinfmsg(data)
- msg.decode()
- kind = None
-
- # get the interface kind
- linkinfo = msg.get_attr('IFLA_LINKINFO')
- if linkinfo is not None:
- kind = [x[1] for x in linkinfo['attrs']
- if x[0] == 'IFLA_INFO_KIND']
- if kind:
- kind = kind[0]
-
- if kind == 'tuntap':
- return manage_tuntap(msg)
- elif kind == 'team':
- return manage_team(msg)
- elif kind in ('ovs-bridge', 'openvswitch'):
- return manage_ovs(msg)
-
- if ANCIENT and kind in ('bridge', 'bond'):
- # route the request
- if kind == 'bridge':
- compat_create_bridge(msg.get_attr('IFLA_IFNAME'))
- elif kind == 'bond':
- compat_create_bond(msg.get_attr('IFLA_IFNAME'))
- # while RTM_NEWLINK is not intercepted -- sleep
- time.sleep(_ANCIENT_BARRIER)
- return
-
- return {'verdict': 'forward',
- 'data': data}
-
-
-def manage_team(msg):
-
- assert msg['header']['type'] == RTM_NEWLINK
-
- config = {'device': msg.get_attr('IFLA_IFNAME'),
- 'runner': {'name': 'activebackup'},
- 'link_watch': {'name': 'ethtool'}}
-
- with open(os.devnull, 'w') as fnull:
- subprocess.check_call(['teamd', '-d', '-n', '-c', json.dumps(config)],
- stdout=fnull,
- stderr=fnull)
-
-
-def manage_team_port(cmd, master, ifname):
- with open(os.devnull, 'w') as fnull:
- subprocess.check_call(['teamdctl', master, 'port',
- 'remove' if cmd == 'del' else 'add', ifname],
- stdout=fnull,
- stderr=fnull)
-
-
-def manage_ovs_port(cmd, master, ifname):
- with open(os.devnull, 'w') as fnull:
- subprocess.check_call(['ovs-vsctl', '%s-port' % cmd, master, ifname],
- stdout=fnull,
- stderr=fnull)
-
-
-def manage_ovs(msg):
- linkinfo = msg.get_attr('IFLA_LINKINFO')
- ifname = msg.get_attr('IFLA_IFNAME')
- kind = linkinfo.get_attr('IFLA_INFO_KIND')
-
- # operations map
- op_map = {RTM_NEWLINK: {'ovs-bridge': 'add-br',
- 'openvswitch': 'add-br'},
- RTM_DELLINK: {'ovs-bridge': 'del-br',
- 'openvswitch': 'del-br'}}
- op = op_map[msg['header']['type']][kind]
-
- # make a call
- with open(os.devnull, 'w') as fnull:
- subprocess.check_call(['ovs-vsctl', op, ifname],
- stdout=fnull,
- stderr=fnull)
-
-
-def manage_tuntap(msg):
-
- if TUNSETIFF is None:
- raise Exception('unsupported arch')
-
- if msg['header']['type'] != RTM_NEWLINK:
- raise Exception('unsupported event')
-
- ifru_flags = 0
- linkinfo = msg.get_attr('IFLA_LINKINFO')
- infodata = linkinfo.get_attr('IFLA_INFO_DATA')
-
- flags = infodata.get_attr('IFTUN_IFR', None)
- if infodata.get_attr('IFTUN_MODE') == 'tun':
- ifru_flags |= IFT_TUN
- elif infodata.get_attr('IFTUN_MODE') == 'tap':
- ifru_flags |= IFT_TAP
- else:
- raise ValueError('invalid mode')
- if flags is not None:
- if flags['no_pi']:
- ifru_flags |= IFT_NO_PI
- if flags['one_queue']:
- ifru_flags |= IFT_ONE_QUEUE
- if flags['vnet_hdr']:
- ifru_flags |= IFT_VNET_HDR
- if flags['multi_queue']:
- ifru_flags |= IFT_MULTI_QUEUE
- ifr = msg.get_attr('IFLA_IFNAME')
- if len(ifr) > IFNAMSIZ:
- raise ValueError('ifname too long')
- ifr += (IFNAMSIZ - len(ifr)) * '\0'
- ifr = ifr.encode('ascii')
- ifr += struct.pack('H', ifru_flags)
-
- user = infodata.get_attr('IFTUN_UID')
- group = infodata.get_attr('IFTUN_GID')
- #
- fd = os.open(TUNDEV, os.O_RDWR)
- try:
- ioctl(fd, TUNSETIFF, ifr)
- if user is not None:
- ioctl(fd, TUNSETOWNER, user)
- if group is not None:
- ioctl(fd, TUNSETGROUP, group)
- ioctl(fd, TUNSETPERSIST, 1)
- except Exception:
- raise
- finally:
- os.close(fd)
-
-
-def compat_create_bridge(name):
- with open(os.devnull, 'w') as fnull:
- subprocess.check_call(['brctl', 'addbr', name],
- stdout=fnull,
- stderr=fnull)
-
-
-def compat_create_bond(name):
- with open(_BONDING_MASTERS, 'w') as f:
- f.write('+%s' % (name))
-
-
-def compat_set_bond(name, cmd, value):
- # FIXME: join with bridge
- # FIXME: use internal IO, not bash
- t = 'echo %s >/sys/class/net/%s/bonding/%s'
- with open(os.devnull, 'w') as fnull:
- return subprocess.call(['bash', '-c', t % (value, name, cmd)],
- stdout=fnull,
- stderr=fnull)
-
-
-def compat_set_bridge(name, cmd, value):
- t = 'echo %s >/sys/class/net/%s/bridge/%s'
- with open(os.devnull, 'w') as fnull:
- return subprocess.call(['bash', '-c', t % (value, name, cmd)],
- stdout=fnull,
- stderr=fnull)
-
-
-def compat_del_bridge(name):
- with open(os.devnull, 'w') as fnull:
- subprocess.check_call(['ip', 'link', 'set',
- 'dev', name, 'down'])
- subprocess.check_call(['brctl', 'delbr', name],
- stdout=fnull,
- stderr=fnull)
-
-
-def compat_del_bond(name):
- subprocess.check_call(['ip', 'link', 'set',
- 'dev', name, 'down'])
- with open(_BONDING_MASTERS, 'w') as f:
- f.write('-%s' % (name))
-
-
-def compat_bridge_port(cmd, master, port):
- if not ANCIENT:
- return True
- with open(os.devnull, 'w') as fnull:
- subprocess.check_call(['brctl', '%sif' % (cmd), master, port],
- stdout=fnull,
- stderr=fnull)
-
-
-def compat_bond_port(cmd, master, port):
- if not ANCIENT:
- return True
- remap = {'add': '+',
- 'del': '-'}
- cmd = remap[cmd]
- with open(_BONDING_SLAVES % (master), 'w') as f:
- f.write('%s%s' % (cmd, port))
-
-
-def compat_get_master(name):
- f = None
-
- for i in (_BRIDGE_MASTER, _BONDING_MASTER):
- try:
- f = open(i % (name))
- break
- except IOError:
- pass
-
- if f is not None:
- master = int(f.read())
- f.close()
- return master
-
-
-def get_interface_type(name):
- '''
- Utility function to get interface type.
-
- Unfortunately, we can not rely on RTNL or even ioctl().
- RHEL doesn't support interface type in RTNL and doesn't
- provide extended (private) interface flags via ioctl().
-
- Args:
- * name (str): interface name
-
- Returns:
- * False -- sysfs info unavailable
- * None -- type not known
- * str -- interface type:
- - 'bond'
- - 'bridge'
- '''
- # FIXME: support all interface types? Right now it is
- # not needed
- try:
- ifattrs = os.listdir('/sys/class/net/%s/' % (name))
- except OSError as e:
- if e.errno == 2:
- return 'unknown'
- else:
- raise
-
- if 'bonding' in ifattrs:
- return 'bond'
- elif 'bridge' in ifattrs:
- return 'bridge'
- else:
- return 'unknown'
diff --git a/node-admin/scripts/pyroute2/netlink/rtnl/iprsocket.py b/node-admin/scripts/pyroute2/netlink/rtnl/iprsocket.py
deleted file mode 100644
index 5f03649ab8b..00000000000
--- a/node-admin/scripts/pyroute2/netlink/rtnl/iprsocket.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-
-from pyroute2.proxy import NetlinkProxy
-from pyroute2.common import ANCIENT
-from pyroute2.netlink import NETLINK_ROUTE
-from pyroute2.netlink.nlsocket import Marshal
-from pyroute2.netlink.nlsocket import NetlinkSocket
-from pyroute2.netlink import rtnl
-from pyroute2.netlink.rtnl.tcmsg import tcmsg
-from pyroute2.netlink.rtnl.rtmsg import rtmsg
-from pyroute2.netlink.rtnl.ndmsg import ndmsg
-from pyroute2.netlink.rtnl.fibmsg import fibmsg
-from pyroute2.netlink.rtnl.ifinfmsg import ifinfmsg
-from pyroute2.netlink.rtnl.ifinfmsg import proxy_newlink
-from pyroute2.netlink.rtnl.ifinfmsg import proxy_setlink
-from pyroute2.netlink.rtnl.ifinfmsg import proxy_dellink
-from pyroute2.netlink.rtnl.ifinfmsg import proxy_linkinfo
-from pyroute2.netlink.rtnl.ifaddrmsg import ifaddrmsg
-
-
-class MarshalRtnl(Marshal):
- msg_map = {rtnl.RTM_NEWLINK: ifinfmsg,
- rtnl.RTM_DELLINK: ifinfmsg,
- rtnl.RTM_GETLINK: ifinfmsg,
- rtnl.RTM_SETLINK: ifinfmsg,
- rtnl.RTM_NEWADDR: ifaddrmsg,
- rtnl.RTM_DELADDR: ifaddrmsg,
- rtnl.RTM_GETADDR: ifaddrmsg,
- rtnl.RTM_NEWROUTE: rtmsg,
- rtnl.RTM_DELROUTE: rtmsg,
- rtnl.RTM_GETROUTE: rtmsg,
- rtnl.RTM_NEWRULE: fibmsg,
- rtnl.RTM_DELRULE: fibmsg,
- rtnl.RTM_GETRULE: fibmsg,
- rtnl.RTM_NEWNEIGH: ndmsg,
- rtnl.RTM_DELNEIGH: ndmsg,
- rtnl.RTM_GETNEIGH: ndmsg,
- rtnl.RTM_NEWQDISC: tcmsg,
- rtnl.RTM_DELQDISC: tcmsg,
- rtnl.RTM_GETQDISC: tcmsg,
- rtnl.RTM_NEWTCLASS: tcmsg,
- rtnl.RTM_DELTCLASS: tcmsg,
- rtnl.RTM_GETTCLASS: tcmsg,
- rtnl.RTM_NEWTFILTER: tcmsg,
- rtnl.RTM_DELTFILTER: tcmsg,
- rtnl.RTM_GETTFILTER: tcmsg}
-
- def fix_message(self, msg):
- # FIXME: pls do something with it
- try:
- msg['event'] = rtnl.RTM_VALUES[msg['header']['type']]
- except:
- pass
-
-
-class IPRSocketMixin(object):
-
- def __init__(self, fileno=None):
- super(IPRSocketMixin, self).__init__(NETLINK_ROUTE, fileno=fileno)
- self.marshal = MarshalRtnl()
- self.ancient = ANCIENT
- self._s_channel = None
- self._sproxy = NetlinkProxy(policy='return', nl=self)
- self._sproxy.pmap = {rtnl.RTM_NEWLINK: proxy_newlink,
- rtnl.RTM_SETLINK: proxy_setlink,
- rtnl.RTM_DELLINK: proxy_dellink}
- self._rproxy = NetlinkProxy(policy='forward', nl=self)
- self._rproxy.pmap = {rtnl.RTM_NEWLINK: proxy_linkinfo}
-
- def bind(self, groups=rtnl.RTNL_GROUPS, async=False):
- super(IPRSocketMixin, self).bind(groups, async=async)
-
- ##
- # proxy-ng protocol
- #
- def sendto(self, data, address):
- ret = self._sproxy.handle(data)
- if ret is not None:
- if ret['verdict'] == 'forward':
- return self._sendto(ret['data'], address)
- elif ret['verdict'] in ('return', 'error'):
- if self._s_channel is not None:
- return self._s_channel.send(ret['data'])
- else:
- msgs = self.marshal.parse(ret['data'])
- for msg in msgs:
- seq = msg['header']['sequence_number']
- if seq in self.backlog:
- self.backlog[seq].append(msg)
- else:
- self.backlog[seq] = [msg]
- return len(ret['data'])
- else:
- ValueError('Incorrect verdict')
-
- return self._sendto(data, address)
-
- def recv(self, bufsize, flags=0):
- data = self._recv(bufsize, flags)
- ret = self._rproxy.handle(data)
- if ret is not None:
- if ret['verdict'] in ('forward', 'error'):
- return ret['data']
- else:
- ValueError('Incorrect verdict')
-
- return data
-
-
-class IPRSocket(IPRSocketMixin, NetlinkSocket):
- '''
- The simplest class, that connects together the netlink parser and
- a generic Python socket implementation. Provides method get() to
- receive the next message from netlink socket and parse it. It is
- just simple socket-like class, it implements no buffering or
- like that. It spawns no additional threads, leaving this up to
- developers.
-
- Please note, that netlink is an asynchronous protocol with
- non-guaranteed delivery. You should be fast enough to get all the
- messages in time. If the message flow rate is higher than the
- speed you parse them with, exceeding messages will be dropped.
-
- *Usage*
-
- Threadless RT netlink monitoring with blocking I/O calls:
-
- >>> from pyroute2 import IPRSocket
- >>> from pprint import pprint
- >>> s = IPRSocket()
- >>> s.bind()
- >>> pprint(s.get())
- [{'attrs': [('RTA_TABLE', 254),
- ('RTA_DST', '2a00:1450:4009:808::1002'),
- ('RTA_GATEWAY', 'fe80:52:0:2282::1fe'),
- ('RTA_OIF', 2),
- ('RTA_PRIORITY', 0),
- ('RTA_CACHEINFO', {'rta_clntref': 0,
- 'rta_error': 0,
- 'rta_expires': 0,
- 'rta_id': 0,
- 'rta_lastuse': 5926,
- 'rta_ts': 0,
- 'rta_tsage': 0,
- 'rta_used': 1})],
- 'dst_len': 128,
- 'event': 'RTM_DELROUTE',
- 'family': 10,
- 'flags': 512,
- 'header': {'error': None,
- 'flags': 0,
- 'length': 128,
- 'pid': 0,
- 'sequence_number': 0,
- 'type': 25},
- 'proto': 9,
- 'scope': 0,
- 'src_len': 0,
- 'table': 254,
- 'tos': 0,
- 'type': 1}]
- >>>
- '''
- pass
diff --git a/node-admin/scripts/pyroute2/netlink/rtnl/iw_event.py b/node-admin/scripts/pyroute2/netlink/rtnl/iw_event.py
deleted file mode 100644
index 5a4e4ae5375..00000000000
--- a/node-admin/scripts/pyroute2/netlink/rtnl/iw_event.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-from pyroute2.netlink import nla
-
-
-class iw_event(nla):
-
- nla_map = ((0x8B00, 'SIOCSIWCOMMIT', 'hex'),
- (0x8B01, 'SIOCGIWNAME', 'hex'),
- # Basic operations
- (0x8B02, 'SIOCSIWNWID', 'hex'),
- (0x8B03, 'SIOCGIWNWID', 'hex'),
- (0x8B04, 'SIOCSIWFREQ', 'hex'),
- (0x8B05, 'SIOCGIWFREQ', 'hex'),
- (0x8B06, 'SIOCSIWMODE', 'hex'),
- (0x8B07, 'SIOCGIWMODE', 'hex'),
- (0x8B08, 'SIOCSIWSENS', 'hex'),
- (0x8B09, 'SIOCGIWSENS', 'hex'),
- # Informative stuff
- (0x8B0A, 'SIOCSIWRANGE', 'hex'),
- (0x8B0B, 'SIOCGIWRANGE', 'hex'),
- (0x8B0C, 'SIOCSIWPRIV', 'hex'),
- (0x8B0D, 'SIOCGIWPRIV', 'hex'),
- (0x8B0E, 'SIOCSIWSTATS', 'hex'),
- (0x8B0F, 'SIOCGIWSTATS', 'hex'),
- # Spy support (statistics per MAC address -
- # used for Mobile IP support)
- (0x8B10, 'SIOCSIWSPY', 'hex'),
- (0x8B11, 'SIOCGIWSPY', 'hex'),
- (0x8B12, 'SIOCSIWTHRSPY', 'hex'),
- (0x8B13, 'SIOCGIWTHRSPY', 'hex'),
- # Access Point manipulation
- (0x8B14, 'SIOCSIWAP', 'hex'),
- (0x8B15, 'SIOCGIWAP', 'hex'),
- (0x8B17, 'SIOCGIWAPLIST', 'hex'),
- (0x8B18, 'SIOCSIWSCAN', 'hex'),
- (0x8B19, 'SIOCGIWSCAN', 'hex'),
- # 802.11 specific support
- (0x8B1A, 'SIOCSIWESSID', 'hex'),
- (0x8B1B, 'SIOCGIWESSID', 'hex'),
- (0x8B1C, 'SIOCSIWNICKN', 'hex'),
- (0x8B1D, 'SIOCGIWNICKN', 'hex'),
- # Other parameters useful in 802.11 and
- # some other devices
- (0x8B20, 'SIOCSIWRATE', 'hex'),
- (0x8B21, 'SIOCGIWRATE', 'hex'),
- (0x8B22, 'SIOCSIWRTS', 'hex'),
- (0x8B23, 'SIOCGIWRTS', 'hex'),
- (0x8B24, 'SIOCSIWFRAG', 'hex'),
- (0x8B25, 'SIOCGIWFRAG', 'hex'),
- (0x8B26, 'SIOCSIWTXPOW', 'hex'),
- (0x8B27, 'SIOCGIWTXPOW', 'hex'),
- (0x8B28, 'SIOCSIWRETRY', 'hex'),
- (0x8B29, 'SIOCGIWRETRY', 'hex'),
- # Encoding stuff (scrambling, hardware security, WEP...)
- (0x8B2A, 'SIOCSIWENCODE', 'hex'),
- (0x8B2B, 'SIOCGIWENCODE', 'hex'),
- # Power saving stuff (power management, unicast
- # and multicast)
- (0x8B2C, 'SIOCSIWPOWER', 'hex'),
- (0x8B2D, 'SIOCGIWPOWER', 'hex'),
- # WPA : Generic IEEE 802.11 informatiom element
- # (e.g., for WPA/RSN/WMM).
- (0x8B30, 'SIOCSIWGENIE', 'hex'),
- (0x8B31, 'SIOCGIWGENIE', 'hex'),
- # WPA : IEEE 802.11 MLME requests
- (0x8B16, 'SIOCSIWMLME', 'hex'),
- # WPA : Authentication mode parameters
- (0x8B32, 'SIOCSIWAUTH', 'hex'),
- (0x8B33, 'SIOCGIWAUTH', 'hex'),
- # WPA : Extended version of encoding configuration
- (0x8B34, 'SIOCSIWENCODEEXT', 'hex'),
- (0x8B35, 'SIOCGIWENCODEEXT', 'hex'),
- # WPA2 : PMKSA cache management
- (0x8B36, 'SIOCSIWPMKSA', 'hex'),
- # Events s.str.
- (0x8C00, 'IWEVTXDROP', 'hex'),
- (0x8C01, 'IWEVQUAL', 'hex'),
- (0x8C02, 'IWEVCUSTOM', 'hex'),
- (0x8C03, 'IWEVREGISTERED', 'hex'),
- (0x8C04, 'IWEVEXPIRED', 'hex'),
- (0x8C05, 'IWEVGENIE', 'hex'),
- (0x8C06, 'IWEVMICHAELMICFAILURE', 'hex'),
- (0x8C07, 'IWEVASSOCREQIE', 'hex'),
- (0x8C08, 'IWEVASSOCRESPIE', 'hex'),
- (0x8C09, 'IWEVPMKIDCAND', 'hex'))
diff --git a/node-admin/scripts/pyroute2/netlink/rtnl/ndmsg.py b/node-admin/scripts/pyroute2/netlink/rtnl/ndmsg.py
deleted file mode 100644
index f7dcf836453..00000000000
--- a/node-admin/scripts/pyroute2/netlink/rtnl/ndmsg.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-
-from pyroute2.netlink import nlmsg
-from pyroute2.netlink import nla
-
-
-class ndmsg(nlmsg):
- '''
- ARP cache update message
-
- C structure::
-
- struct ndmsg {
- unsigned char ndm_family;
- int ndm_ifindex; /* Interface index */
- __u16 ndm_state; /* State */
- __u8 ndm_flags; /* Flags */
- __u8 ndm_type;
- };
-
- Cache info structure::
-
- struct nda_cacheinfo {
- __u32 ndm_confirmed;
- __u32 ndm_used;
- __u32 ndm_updated;
- __u32 ndm_refcnt;
- };
- '''
- fields = (('family', 'B'),
- ('__pad', '3x'),
- ('ifindex', 'i'),
- ('state', 'H'),
- ('flags', 'B'),
- ('ndm_type', 'B'))
-
- # Please note, that nla_map creates implicit
- # enumeration. In this case it will be:
- #
- # NDA_UNSPEC = 0
- # NDA_DST = 1
- # NDA_LLADDR = 2
- # NDA_CACHEINFO = 3
- # NDA_PROBES = 4
- # ...
- #
- nla_map = (('NDA_UNSPEC', 'none'),
- ('NDA_DST', 'ipaddr'),
- ('NDA_LLADDR', 'l2addr'),
- ('NDA_CACHEINFO', 'cacheinfo'),
- ('NDA_PROBES', 'uint32'),
- ('NDA_VLAN', 'uint16'),
- ('NDA_PORT', 'be16'),
- ('NDA_VNI', 'be32'),
- ('NDA_IFINDEX', 'uint32'))
-
- class cacheinfo(nla):
- fields = (('ndm_confirmed', 'I'),
- ('ndm_used', 'I'),
- ('ndm_updated', 'I'),
- ('ndm_refcnt', 'I'))
diff --git a/node-admin/scripts/pyroute2/netlink/rtnl/req.py b/node-admin/scripts/pyroute2/netlink/rtnl/req.py
deleted file mode 100644
index 268fd7ff604..00000000000
--- a/node-admin/scripts/pyroute2/netlink/rtnl/req.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-from socket import AF_INET6
-from pyroute2.common import basestring
-from pyroute2.netlink.rtnl.ifinfmsg import ifinfmsg
-from pyroute2.netlink.rtnl.rtmsg import rtmsg
-
-
-class IPRequest(dict):
-
- def __init__(self, obj=None):
- dict.__init__(self)
- if obj is not None:
- self.update(obj)
-
- def update(self, obj):
- for key in obj:
- if obj[key] is not None:
- self[key] = obj[key]
-
-
-class IPRouteRequest(IPRequest):
- '''
- Utility class, that converts human-readable dictionary
- into RTNL route request.
- '''
-
- def __setitem__(self, key, value):
- # fix family
- if isinstance(value, basestring) and value.find(':') >= 0:
- self['family'] = AF_INET6
- # work on the rest
- if key == 'dst':
- if value != 'default':
- value = value.split('/')
- if len(value) == 1:
- dst = value[0]
- mask = 0
- elif len(value) == 2:
- dst = value[0]
- mask = int(value[1])
- else:
- raise ValueError('wrong destination')
- dict.__setitem__(self, 'dst', dst)
- dict.__setitem__(self, 'dst_len', mask)
- elif key == 'metrics':
- ret = {'attrs': []}
- for name in value:
- rtax = rtmsg.metrics.name2nla(name)
- ret['attrs'].append([rtax, value[name]])
- dict.__setitem__(self, 'metrics', ret)
- else:
- dict.__setitem__(self, key, value)
-
-
-class CBRequest(IPRequest):
- '''
- FIXME
- '''
- commands = None
- msg = None
-
- def __init__(self, *argv, **kwarg):
- self['commands'] = {'attrs': []}
-
- def __setitem__(self, key, value):
- if value is None:
- return
- if key in self.commands:
- self['commands']['attrs'].\
- append([self.msg.name2nla(key), value])
- else:
- dict.__setitem__(self, key, value)
-
-
-class IPLinkRequest(IPRequest):
- '''
- Utility class, that converts human-readable dictionary
- into RTNL link request.
- '''
- blacklist = ['carrier',
- 'carrier_changes']
-
- def __init__(self, *argv, **kwarg):
- self.deferred = []
- IPRequest.__init__(self, *argv, **kwarg)
- if 'index' not in self:
- self['index'] = 0
-
- def __setitem__(self, key, value):
- # ignore blacklisted attributes
- if key in self.blacklist:
- return
-
- # there must be no "None" values in the request
- if value is None:
- return
-
- # all the values must be in ascii
- try:
- if isinstance(value, unicode):
- value = value.encode('ascii')
- except NameError:
- pass
-
- # set up specific keys
- if key == 'kind':
- self['IFLA_LINKINFO'] = {'attrs': []}
- linkinfo = self['IFLA_LINKINFO']['attrs']
- linkinfo.append(['IFLA_INFO_KIND', value])
- if value in ('vlan', 'bond', 'tuntap', 'veth',
- 'vxlan', 'macvlan', 'macvtap', 'gre'):
- linkinfo.append(['IFLA_INFO_DATA', {'attrs': []}])
- elif key == 'vlan_id':
- nla = ['IFLA_VLAN_ID', value]
- # FIXME: we need to replace, not add
- self.defer_nla(nla, ('IFLA_LINKINFO', 'IFLA_INFO_DATA'),
- lambda x: x.get('kind', None) == 'vlan')
- elif key == 'gid':
- nla = ['IFTUN_UID', value]
- self.defer_nla(nla, ('IFLA_LINKINFO', 'IFLA_INFO_DATA'),
- lambda x: x.get('kind', None) == 'tuntap')
- elif key == 'uid':
- nla = ['IFTUN_UID', value]
- self.defer_nla(nla, ('IFLA_LINKINFO', 'IFLA_INFO_DATA'),
- lambda x: x.get('kind', None) == 'tuntap')
- elif key == 'mode':
- nla = ['IFTUN_MODE', value]
- self.defer_nla(nla, ('IFLA_LINKINFO', 'IFLA_INFO_DATA'),
- lambda x: x.get('kind', None) == 'tuntap')
- nla = ['IFLA_BOND_MODE', value]
- self.defer_nla(nla, ('IFLA_LINKINFO', 'IFLA_INFO_DATA'),
- lambda x: x.get('kind', None) == 'bond')
- elif key == 'ifr':
- nla = ['IFTUN_IFR', value]
- self.defer_nla(nla, ('IFLA_LINKINFO', 'IFLA_INFO_DATA'),
- lambda x: x.get('kind', None) == 'tuntap')
- elif key.startswith('macvtap'):
- nla = [ifinfmsg.name2nla(key), value]
- self.defer_nla(nla, ('IFLA_LINKINFO', 'IFLA_INFO_DATA'),
- lambda x: x.get('kind', None) == 'macvtap')
- elif key.startswith('macvlan'):
- nla = [ifinfmsg.name2nla(key), value]
- self.defer_nla(nla, ('IFLA_LINKINFO', 'IFLA_INFO_DATA'),
- lambda x: x.get('kind', None) == 'macvlan')
- elif key.startswith('gre'):
- nla = [ifinfmsg.name2nla(key), value]
- self.defer_nla(nla, ('IFLA_LINKINFO', 'IFLA_INFO_DATA'),
- lambda x: x.get('kind', None) == 'gre')
- elif key.startswith('vxlan'):
- nla = [ifinfmsg.name2nla(key), value]
- self.defer_nla(nla, ('IFLA_LINKINFO', 'IFLA_INFO_DATA'),
- lambda x: x.get('kind', None) == 'vxlan')
- elif key == 'peer':
- nla = ['VETH_INFO_PEER', {'attrs': [['IFLA_IFNAME', value]]}]
- self.defer_nla(nla, ('IFLA_LINKINFO', 'IFLA_INFO_DATA'),
- lambda x: x.get('kind', None) == 'veth')
- dict.__setitem__(self, key, value)
- if self.deferred:
- self.flush_deferred()
-
- def flush_deferred(self):
- deferred = []
- for nla, path, predicate in self.deferred:
- if predicate(self):
- self.append_nla(nla, path)
- else:
- deferred.append((nla, path, predicate))
- self.deferred = deferred
-
- def append_nla(self, nla, path):
- pwd = self
- for step in path:
- if step in pwd:
- pwd = pwd[step]
- else:
- pwd = [x[1] for x in pwd['attrs']
- if x[0] == step][0]['attrs']
- pwd.append(nla)
-
- def defer_nla(self, nla, path, predicate):
- self.deferred.append((nla, path, predicate))
- self.flush_deferred()
diff --git a/node-admin/scripts/pyroute2/netlink/rtnl/rtmsg.py b/node-admin/scripts/pyroute2/netlink/rtnl/rtmsg.py
deleted file mode 100644
index 4983f0a405c..00000000000
--- a/node-admin/scripts/pyroute2/netlink/rtnl/rtmsg.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-
-from pyroute2.netlink import nlmsg
-from pyroute2.netlink import nla
-
-
-class rtmsg(nlmsg):
- '''
- Route message
-
- C structure::
-
- struct rtmsg {
- unsigned char rtm_family; /* Address family of route */
- unsigned char rtm_dst_len; /* Length of destination */
- unsigned char rtm_src_len; /* Length of source */
- unsigned char rtm_tos; /* TOS filter */
-
- unsigned char rtm_table; /* Routing table ID */
- unsigned char rtm_protocol; /* Routing protocol; see below */
- unsigned char rtm_scope; /* See below */
- unsigned char rtm_type; /* See below */
-
- unsigned int rtm_flags;
- };
- '''
- prefix = 'RTA_'
-
- fields = (('family', 'B'),
- ('dst_len', 'B'),
- ('src_len', 'B'),
- ('tos', 'B'),
- ('table', 'B'),
- ('proto', 'B'),
- ('scope', 'B'),
- ('type', 'B'),
- ('flags', 'I'))
-
- nla_map = (('RTA_UNSPEC', 'none'),
- ('RTA_DST', 'ipaddr'),
- ('RTA_SRC', 'ipaddr'),
- ('RTA_IIF', 'uint32'),
- ('RTA_OIF', 'uint32'),
- ('RTA_GATEWAY', 'ipaddr'),
- ('RTA_PRIORITY', 'uint32'),
- ('RTA_PREFSRC', 'ipaddr'),
- ('RTA_METRICS', 'metrics'),
- ('RTA_MULTIPATH', 'hex'),
- ('RTA_PROTOINFO', 'uint32'),
- ('RTA_FLOW', 'hex'),
- ('RTA_CACHEINFO', 'cacheinfo'),
- ('RTA_SESSION', 'hex'),
- ('RTA_MP_ALGO', 'hex'),
- ('RTA_TABLE', 'uint32'),
- ('RTA_MARK', 'uint32'),
- ('RTA_MFC_STATS', 'rta_mfc_stats'))
-
- class rta_mfc_stats(nla):
- fields = (('mfcs_packets', 'uint64'),
- ('mfcs_bytes', 'uint64'),
- ('mfcs_wrong_if', 'uint64'))
-
- class metrics(nla):
- prefix = 'RTAX_'
- nla_map = (('RTAX_UNSPEC', 'none'),
- ('RTAX_LOCK', 'uint32'),
- ('RTAX_MTU', 'uint32'),
- ('RTAX_WINDOW', 'uint32'),
- ('RTAX_RTT', 'uint32'),
- ('RTAX_RTTVAR', 'uint32'),
- ('RTAX_SSTHRESH', 'uint32'),
- ('RTAX_CWND', 'uint32'),
- ('RTAX_ADVMSS', 'uint32'),
- ('RTAX_REORDERING', 'uint32'),
- ('RTAX_HOPLIMIT', 'uint32'),
- ('RTAX_INITCWND', 'uint32'),
- ('RTAX_FEATURES', 'uint32'),
- ('RTAX_RTO_MIN', 'uint32'),
- ('RTAX_INITRWND', 'uint32'),
- ('RTAX_QUICKACK', 'uint32'))
-
- class cacheinfo(nla):
- fields = (('rta_clntref', 'I'),
- ('rta_lastuse', 'I'),
- ('rta_expires', 'i'),
- ('rta_error', 'I'),
- ('rta_used', 'I'),
- ('rta_id', 'I'),
- ('rta_ts', 'I'),
- ('rta_tsage', 'I'))
diff --git a/node-admin/scripts/pyroute2/netlink/rtnl/tcmsg.py b/node-admin/scripts/pyroute2/netlink/rtnl/tcmsg.py
deleted file mode 100644
index 32b6a762b5b..00000000000
--- a/node-admin/scripts/pyroute2/netlink/rtnl/tcmsg.py
+++ /dev/null
@@ -1,917 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-import re
-import os
-import struct
-
-from pyroute2.common import size_suffixes
-from pyroute2.common import time_suffixes
-from pyroute2.common import rate_suffixes
-from pyroute2.common import basestring
-from pyroute2.netlink import nlmsg
-from pyroute2.netlink import nla
-
-
-TCA_ACT_MAX_PRIO = 32
-
-LINKLAYER_UNSPEC = 0
-LINKLAYER_ETHERNET = 1
-LINKLAYER_ATM = 2
-
-ATM_CELL_SIZE = 53
-ATM_CELL_PAYLOAD = 48
-
-TC_RED_ECN = 1
-TC_RED_HARDDROP = 2
-TC_RED_ADAPTATIVE = 4
-
-TIME_UNITS_PER_SEC = 1000000
-
-_psched = open('/proc/net/psched', 'r')
-[_t2us,
- _us2t,
- _clock_res,
- _wee] = [int(i, 16) for i in _psched.read().split()]
-_clock_factor = float(_clock_res) / TIME_UNITS_PER_SEC
-_tick_in_usec = float(_t2us) / _us2t * _clock_factor
-_first_letter = re.compile('[^0-9]+')
-_psched.close()
-
-
-def _get_hz():
- if _clock_res == 1000000:
- return _wee
- else:
- return os.environ.get('HZ', 1000)
-
-
-def _get_by_suffix(value, default, func):
- if not isinstance(value, basestring):
- return value
- pos = _first_letter.search(value)
- if pos is None:
- suffix = default
- else:
- pos = pos.start()
- value, suffix = value[:pos], value[pos:]
- value = int(value)
- return func(value, suffix)
-
-
-def _get_size(size):
- return _get_by_suffix(size, 'b',
- lambda x, y: x * size_suffixes[y])
-
-
-def _get_time(lat):
- return _get_by_suffix(lat, 'ms',
- lambda x, y: (x * TIME_UNITS_PER_SEC) /
- time_suffixes[y])
-
-
-def _get_rate(rate):
- return _get_by_suffix(rate, 'bit',
- lambda x, y: (x * rate_suffixes[y]) / 8)
-
-
-def _time2tick(time):
- # The current code is ported from tc utility
- return int(time) * _tick_in_usec
-
-
-def _calc_xmittime(rate, size):
- # The current code is ported from tc utility
- return int(_time2tick(TIME_UNITS_PER_SEC * (float(size) / rate)))
-
-
-def _percent2u32(pct):
- '''xlate a percentage to an uint32 value
- 0% -> 0
- 100% -> 2**32 - 1'''
- return int((2**32 - 1)*pct/100)
-
-
-def _red_eval_ewma(qmin, burst, avpkt):
- # The current code is ported from tc utility
- wlog = 1
- W = 0.5
- a = float(burst) + 1 - float(qmin) / avpkt
- assert a < 1
-
- while wlog < 32:
- wlog += 1
- W /= 2
- if (a <= (1 - pow(1 - W, burst)) / W):
- return wlog
- return -1
-
-
-def _red_eval_P(qmin, qmax, probability):
- # The current code is ported from tc utility
- i = qmax - qmin
- assert i > 0
- assert i < 32
-
- probability /= i
- while i < 32:
- i += 1
- if probability > 1:
- break
- probability *= 2
- return i
-
-
-def _get_rate_parameters(kwarg):
- # rate and burst are required
- rate = _get_rate(kwarg['rate'])
- burst = kwarg['burst']
-
- # if peak, mtu is required
- peak = _get_rate(kwarg.get('peak', 0))
- mtu = kwarg.get('mtu', 0)
- if peak:
- assert mtu
-
- # limit OR latency is required
- limit = kwarg.get('limit', None)
- latency = _get_time(kwarg.get('latency', None))
- assert limit is not None or latency is not None
-
- # calculate limit from latency
- if limit is None:
- rate_limit = rate * float(latency) /\
- TIME_UNITS_PER_SEC + burst
- if peak:
- peak_limit = peak * float(latency) /\
- TIME_UNITS_PER_SEC + mtu
- if rate_limit > peak_limit:
- rate_limit = peak_limit
- limit = rate_limit
-
- return {'rate': int(rate),
- 'mtu': mtu,
- 'buffer': _calc_xmittime(rate, burst),
- 'limit': int(limit)}
-
-
-def get_tbf_parameters(kwarg):
- parms = _get_rate_parameters(kwarg)
- # fill parameters
- return {'attrs': [['TCA_TBF_PARMS', parms],
- ['TCA_TBF_RTAB', True]]}
-
-
-def _get_filter_police_parameter(kwarg):
- # if no limit specified, set it to zero to make
- # the next call happy
- kwarg['limit'] = kwarg.get('limit', 0)
- tbfp = _get_rate_parameters(kwarg)
- # create an alias -- while TBF uses 'buffer', rate
- # policy uses 'burst'
- tbfp['burst'] = tbfp['buffer']
- # action resolver
- actions = nla_plus_police.police.police_tbf.actions
- tbfp['action'] = actions[kwarg.get('action', 'reclassify')]
- police = [['TCA_POLICE_TBF', tbfp],
- ['TCA_POLICE_RATE', True]]
- return police
-
-
-def get_u32_parameters(kwarg):
- ret = {'attrs': []}
-
- if kwarg.get('rate'):
- ret['attrs'].append([
- 'TCA_U32_POLICE',
- {'attrs': _get_filter_police_parameter(kwarg)}
- ])
-
- ret['attrs'].append(['TCA_U32_CLASSID', kwarg['target']])
- ret['attrs'].append(['TCA_U32_SEL', {'keys': kwarg['keys']}])
-
- return ret
-
-
-def get_fw_parameters(kwarg):
- ret = {'attrs': []}
- attrs_map = (
- ('classid', 'TCA_FW_CLASSID'),
- ('act', 'TCA_FW_ACT'),
- # ('police', 'TCA_FW_POLICE'),
- # Handled in _get_filter_police_parameter
- ('indev', 'TCA_FW_INDEV'),
- ('mask', 'TCA_FW_MASK'),
- )
-
- if kwarg.get('rate'):
- ret['attrs'].append([
- 'TCA_FW_POLICE',
- {'attrs': _get_filter_police_parameter(kwarg)}
- ])
-
- for k, v in attrs_map:
- r = kwarg.get(k, None)
- if r is not None:
- ret['attrs'].append([v, r])
-
- return ret
-
-
-def get_sfq_parameters(kwarg):
- kwarg['quantum'] = _get_size(kwarg.get('quantum', 0))
- kwarg['perturb_period'] = kwarg.get('perturb', 0) or \
- kwarg.get('perturb_period', 0)
- limit = kwarg['limit'] = kwarg.get('limit', 0) or \
- kwarg.get('redflowlimit', 0)
- qth_min = kwarg.get('min', 0)
- qth_max = kwarg.get('max', 0)
- avpkt = kwarg.get('avpkt', 1000)
- probability = kwarg.get('probability', 0.02)
- ecn = kwarg.get('ecn', False)
- harddrop = kwarg.get('harddrop', False)
- kwarg['flags'] = kwarg.get('flags', 0)
- if ecn:
- kwarg['flags'] |= TC_RED_ECN
- if harddrop:
- kwarg['flags'] |= TC_RED_HARDDROP
- if kwarg.get('redflowlimit'):
- qth_max = qth_max or limit / 4
- qth_min = qth_min or qth_max / 3
- kwarg['burst'] = kwarg['burst'] or \
- (2 * qth_min + qth_max) / (3 * avpkt)
- assert limit > qth_max
- assert qth_max > qth_min
- kwarg['qth_min'] = qth_min
- kwarg['qth_max'] = qth_max
- kwarg['Wlog'] = _red_eval_ewma(qth_min, kwarg['burst'], avpkt)
- kwarg['Plog'] = _red_eval_P(qth_min, qth_max, probability)
- assert kwarg['Wlog'] >= 0
- assert kwarg['Plog'] >= 0
- kwarg['max_P'] = int(probability * pow(2, 23))
-
- return kwarg
-
-
-def get_htb_class_parameters(kwarg):
- #
- prio = kwarg.get('prio', 0)
- mtu = kwarg.get('mtu', 1600)
- mpu = kwarg.get('mpu', 0)
- overhead = kwarg.get('overhead', 0)
- quantum = kwarg.get('quantum', 0)
- #
- rate = _get_rate(kwarg.get('rate', None))
- ceil = _get_rate(kwarg.get('ceil', 0)) or rate
-
- burst = kwarg.get('burst', None) or \
- kwarg.get('maxburst', None) or \
- kwarg.get('buffer', None)
-
- if rate is not None:
- if burst is None:
- burst = rate / _get_hz() + mtu
- burst = _calc_xmittime(rate, burst)
-
- cburst = kwarg.get('cburst', None) or \
- kwarg.get('cmaxburst', None) or \
- kwarg.get('cbuffer', None)
-
- if ceil is not None:
- if cburst is None:
- cburst = ceil / _get_hz() + mtu
- cburst = _calc_xmittime(ceil, cburst)
-
- return {'attrs': [['TCA_HTB_PARMS', {'buffer': burst,
- 'cbuffer': cburst,
- 'quantum': quantum,
- 'prio': prio,
- 'rate': rate,
- 'ceil': ceil,
- 'ceil_overhead': overhead,
- 'rate_overhead': overhead,
- 'rate_mpu': mpu,
- 'ceil_mpu': mpu}],
- ['TCA_HTB_RTAB', True],
- ['TCA_HTB_CTAB', True]]}
-
-
-def get_htb_parameters(kwarg):
- rate2quantum = kwarg.get('r2q', 0xa)
- version = kwarg.get('version', 3)
- defcls = kwarg.get('default', 0x10)
-
- return {'attrs': [['TCA_HTB_INIT', {'debug': 0,
- 'defcls': defcls,
- 'direct_pkts': 0,
- 'rate2quantum': rate2quantum,
- 'version': version}]]}
-
-
-def get_netem_parameters(kwarg):
- delay = _time2tick(kwarg.get('delay', 0)) # in microsecond
- limit = kwarg.get('limit', 1000) # fifo limit (packets) see netem.c:230
- loss = _percent2u32(kwarg.get('loss', 0)) # int percentage
- gap = kwarg.get('gap', 0)
- duplicate = kwarg.get('duplicate', 0)
- jitter = _time2tick(kwarg.get('jitter', 0)) # in microsecond
-
- opts = {
- 'delay': delay,
- 'limit': limit,
- 'loss': loss,
- 'gap': gap,
- 'duplicate': duplicate,
- 'jitter': jitter,
- 'attrs': []
- }
-
- # correlation (delay, loss, duplicate)
- delay_corr = _percent2u32(kwarg.get('delay_corr', 0))
- loss_corr = _percent2u32(kwarg.get('loss_corr', 0))
- dup_corr = _percent2u32(kwarg.get('dup_corr', 0))
- if delay_corr or loss_corr or dup_corr:
- # delay_corr requires that both jitter and delay are != 0
- if delay_corr and not (delay and jitter):
- raise Exception('delay correlation requires delay'
- ' and jitter to be set')
- # loss correlation and loss
- if loss_corr and not loss:
- raise Exception('loss correlation requires loss to be set')
- # duplicate correlation and duplicate
- if dup_corr and not duplicate:
- raise Exception('duplicate correlation requires '
- 'duplicate to be set')
-
- opts['attrs'].append(['TCA_NETEM_CORR', {'delay_corr': delay_corr,
- 'loss_corr': loss_corr,
- 'dup_corr': dup_corr}])
-
- # reorder (probability, correlation)
- prob_reorder = _percent2u32(kwarg.get('prob_reorder', 0))
- corr_reorder = _percent2u32(kwarg.get('corr_reorder', 0))
- if prob_reorder != 0:
- # gap defaults to 1 if equal to 0
- if gap == 0:
- opts['gap'] = gap = 1
- opts['attrs'].append(['TCA_NETEM_REORDER',
- {'prob_reorder': prob_reorder,
- 'corr_reorder': corr_reorder}])
- else:
- if gap != 0:
- raise Exception('gap can only be set when prob_reorder is set')
- elif corr_reorder != 0:
- raise Exception('corr_reorder can only be set when '
- 'prob_reorder is set')
-
- # corrupt (probability, correlation)
- prob_corrupt = _percent2u32(kwarg.get('prob_corrupt', 0))
- corr_corrupt = _percent2u32(kwarg.get('corr_corrupt', 0))
- if prob_corrupt:
- opts['attrs'].append(['TCA_NETEM_CORRUPT',
- {'prob_corrupt': prob_corrupt,
- 'corr_corrupt': corr_corrupt}])
- elif corr_corrupt != 0:
- raise Exception('corr_corrupt can only be set when '
- 'prob_corrupt is set')
-
- # TODO
- # delay distribution (dist_size, dist_data)
- return opts
-
-
-class nla_plus_rtab(nla):
- class parms(nla):
- def adjust_size(self, size, mpu, linklayer):
- # The current code is ported from tc utility
- if size < mpu:
- size = mpu
-
- if linklayer == LINKLAYER_ATM:
- cells = size / ATM_CELL_PAYLOAD
- if size % ATM_CELL_PAYLOAD > 0:
- cells += 1
- size = cells * ATM_CELL_SIZE
-
- return size
-
- def calc_rtab(self, kind):
- # The current code is ported from tc utility
- rtab = []
- mtu = self.get('mtu', 0) or 1600
- cell_log = self['%s_cell_log' % (kind)]
- mpu = self['%s_mpu' % (kind)]
- rate = self.get(kind, 'rate')
-
- # calculate cell_log
- if cell_log == 0:
- while (mtu >> cell_log) > 255:
- cell_log += 1
-
- # fill up the table
- for i in range(256):
- size = self.adjust_size((i + 1) << cell_log,
- mpu,
- LINKLAYER_ETHERNET)
- rtab.append(_calc_xmittime(rate, size))
-
- self['%s_cell_align' % (kind)] = -1
- self['%s_cell_log' % (kind)] = cell_log
- return rtab
-
- def encode(self):
- self.rtab = None
- self.ptab = None
- if self.get('rate', False):
- self.rtab = self.calc_rtab('rate')
- if self.get('peak', False):
- self.ptab = self.calc_rtab('peak')
- if self.get('ceil', False):
- self.ctab = self.calc_rtab('ceil')
- nla.encode(self)
-
- class rtab(nla):
- fields = (('value', 's'), )
-
- def encode(self):
- parms = self.parent.get_encoded('TCA_TBF_PARMS') or \
- self.parent.get_encoded('TCA_HTB_PARMS') or \
- self.parent.get_encoded('TCA_POLICE_TBF')
- if parms is not None:
- self.value = getattr(parms, self.__class__.__name__)
- self['value'] = struct.pack('I' * 256,
- *(int(x) for x in self.value))
- nla.encode(self)
-
- def decode(self):
- nla.decode(self)
- parms = self.parent.get_attr('TCA_TBF_PARMS') or \
- self.parent.get_attr('TCA_HTB_PARMS') or \
- self.parent.get_attr('TCA_POLICE_TBF')
- if parms is not None:
- rtab = struct.unpack('I' * (len(self['value']) / 4),
- self['value'])
- self.value = rtab
- setattr(parms, self.__class__.__name__, rtab)
-
- class ptab(rtab):
- pass
-
- class ctab(rtab):
- pass
-
-
-class nla_plus_stats2(object):
- class stats2(nla):
- nla_map = (('TCA_STATS_UNSPEC', 'none'),
- ('TCA_STATS_BASIC', 'basic'),
- ('TCA_STATS_RATE_EST', 'rate_est'),
- ('TCA_STATS_QUEUE', 'queue'),
- ('TCA_STATS_APP', 'hex'))
-
- class basic(nla):
- fields = (('bytes', 'Q'),
- ('packets', 'Q'))
-
- class rate_est(nla):
- fields = (('bps', 'I'),
- ('pps', 'I'))
-
- class queue(nla):
- fields = (('qlen', 'I'),
- ('backlog', 'I'),
- ('drops', 'I'),
- ('requeues', 'I'),
- ('overlimits', 'I'))
-
- class stats2_hfsc(stats2):
- nla_map = (('TCA_STATS_UNSPEC', 'none'),
- ('TCA_STATS_BASIC', 'basic'),
- ('TCA_STATS_RATE_EST', 'rate_est'),
- ('TCA_STATS_QUEUE', 'queue'),
- ('TCA_STATS_APP', 'stats_app_hfsc'))
-
- class stats_app_hfsc(nla):
- fields = (('work', 'Q'), # total work done
- ('rtwork', 'Q'), # total work done by real-time criteria
- ('period', 'I'), # current period
- ('level', 'I')) # class level in hierarchy
-
-
-class nla_plus_police(object):
- class police(nla_plus_rtab):
- nla_map = (('TCA_POLICE_UNSPEC', 'none'),
- ('TCA_POLICE_TBF', 'police_tbf'),
- ('TCA_POLICE_RATE', 'rtab'),
- ('TCA_POLICE_PEAKRATE', 'ptab'),
- ('TCA_POLICE_AVRATE', 'uint32'),
- ('TCA_POLICE_RESULT', 'uint32'))
-
- class police_tbf(nla_plus_rtab.parms):
- fields = (('index', 'I'),
- ('action', 'i'),
- ('limit', 'I'),
- ('burst', 'I'),
- ('mtu', 'I'),
- ('rate_cell_log', 'B'),
- ('rate___reserved', 'B'),
- ('rate_overhead', 'H'),
- ('rate_cell_align', 'h'),
- ('rate_mpu', 'H'),
- ('rate', 'I'),
- ('peak_cell_log', 'B'),
- ('peak___reserved', 'B'),
- ('peak_overhead', 'H'),
- ('peak_cell_align', 'h'),
- ('peak_mpu', 'H'),
- ('peak', 'I'),
- ('refcnt', 'i'),
- ('bindcnt', 'i'),
- ('capab', 'I'))
-
- actions = {'unspec': -1, # TC_POLICE_UNSPEC
- 'ok': 0, # TC_POLICE_OK
- 'reclassify': 1, # TC_POLICE_RECLASSIFY
- 'shot': 2, # TC_POLICE_SHOT
- 'drop': 2, # TC_POLICE_SHOT
- 'pipe': 3} # TC_POLICE_PIPE
-
-
-class tcmsg(nlmsg, nla_plus_stats2):
-
- prefix = 'TCA_'
-
- fields = (('family', 'B'),
- ('pad1', 'B'),
- ('pad2', 'H'),
- ('index', 'i'),
- ('handle', 'I'),
- ('parent', 'I'),
- ('info', 'I'))
-
- nla_map = (('TCA_UNSPEC', 'none'),
- ('TCA_KIND', 'asciiz'),
- ('TCA_OPTIONS', 'get_options'),
- ('TCA_STATS', 'stats'),
- ('TCA_XSTATS', 'get_xstats'),
- ('TCA_RATE', 'hex'),
- ('TCA_FCNT', 'hex'),
- ('TCA_STATS2', 'get_stats2'),
- ('TCA_STAB', 'hex'))
-
- class stats(nla):
- fields = (('bytes', 'Q'),
- ('packets', 'I'),
- ('drop', 'I'),
- ('overlimits', 'I'),
- ('bps', 'I'),
- ('pps', 'I'),
- ('qlen', 'I'),
- ('backlog', 'I'))
-
- def get_stats2(self, *argv, **kwarg):
- kind = self.get_attr('TCA_KIND')
- if kind == 'hfsc':
- return self.stats2_hfsc
- return self.stats2
-
- def get_xstats(self, *argv, **kwarg):
- kind = self.get_attr('TCA_KIND')
- if kind == 'htb':
- return self.xstats_htb
- return self.hex
-
- class xstats_htb(nla):
- fields = (('lends', 'I'),
- ('borrows', 'I'),
- ('giants', 'I'),
- ('tokens', 'I'),
- ('ctokens', 'I'))
-
- def get_options(self, *argv, **kwarg):
- kind = self.get_attr('TCA_KIND')
- if kind == 'ingress':
- return self.options_ingress
- elif kind == 'pfifo_fast':
- return self.options_pfifo_fast
- elif kind == 'tbf':
- return self.options_tbf
- elif kind == 'sfq':
- if kwarg.get('length', 0) >= self.options_sfq_v1.get_size():
- return self.options_sfq_v1
- else:
- return self.options_sfq_v0
- elif kind == 'hfsc':
- return self.options_hfsc
- elif kind == 'htb':
- return self.options_htb
- elif kind == 'netem':
- return self.options_netem
- elif kind == 'u32':
- return self.options_u32
- elif kind == 'fw':
- return self.options_fw
- return self.hex
-
- class options_ingress(nla):
- fields = (('value', 'I'), )
-
- class options_hfsc(nla):
- nla_map = (('TCA_HFSC_UNSPEC', 'hfsc_qopt'),
- ('TCA_HFSC_RSC', 'hfsc_curve'), # real-time curve
- ('TCA_HFSC_FSC', 'hfsc_curve'), # link-share curve
- ('TCA_HFSC_USC', 'hfsc_curve')) # upper-limit curve
-
- class hfsc_qopt(nla):
- fields = (('defcls', 'H'),) # default class
-
- class hfsc_curve(nla):
- fields = (('m1', 'I'), # slope of the first segment in bps
- ('d', 'I'), # x-projection of the first segment in us
- ('m2', 'I')) # slope of the second segment in bps
-
- class options_htb(nla_plus_rtab):
- nla_map = (('TCA_HTB_UNSPEC', 'none'),
- ('TCA_HTB_PARMS', 'htb_parms'),
- ('TCA_HTB_INIT', 'htb_glob'),
- ('TCA_HTB_CTAB', 'ctab'),
- ('TCA_HTB_RTAB', 'rtab'))
-
- class htb_glob(nla):
- fields = (('version', 'I'),
- ('rate2quantum', 'I'),
- ('defcls', 'I'),
- ('debug', 'I'),
- ('direct_pkts', 'I'))
-
- class htb_parms(nla_plus_rtab.parms):
- fields = (('rate_cell_log', 'B'),
- ('rate___reserved', 'B'),
- ('rate_overhead', 'H'),
- ('rate_cell_align', 'h'),
- ('rate_mpu', 'H'),
- ('rate', 'I'),
- ('ceil_cell_log', 'B'),
- ('ceil___reserved', 'B'),
- ('ceil_overhead', 'H'),
- ('ceil_cell_align', 'h'),
- ('ceil_mpu', 'H'),
- ('ceil', 'I'),
- ('buffer', 'I'),
- ('cbuffer', 'I'),
- ('quantum', 'I'),
- ('level', 'I'),
- ('prio', 'I'))
-
- class options_netem(nla):
- nla_map = (('TCA_NETEM_UNSPEC', 'none'),
- ('TCA_NETEM_CORR', 'netem_corr'),
- ('TCA_NETEM_DELAY_DIST', 'none'),
- ('TCA_NETEM_REORDER', 'netem_reorder'),
- ('TCA_NETEM_CORRUPT', 'netem_corrupt'),
- ('TCA_NETEM_LOSS', 'none'),
- ('TCA_NETEM_RATE', 'none'))
-
- fields = (('delay', 'I'),
- ('limit', 'I'),
- ('loss', 'I'),
- ('gap', 'I'),
- ('duplicate', 'I'),
- ('jitter', 'I'))
-
- class netem_corr(nla):
- '''correlation'''
- fields = (('delay_corr', 'I'),
- ('loss_corr', 'I'),
- ('dup_corr', 'I'))
-
- class netem_reorder(nla):
- '''reorder has probability and correlation'''
- fields = (('prob_reorder', 'I'),
- ('corr_reorder', 'I'))
-
- class netem_corrupt(nla):
- '''corruption has probability and correlation'''
- fields = (('prob_corrupt', 'I'),
- ('corr_corrupt', 'I'))
-
- class options_fw(nla, nla_plus_police):
- nla_map = (('TCA_FW_UNSPEC', 'none'),
- ('TCA_FW_CLASSID', 'uint32'),
- ('TCA_FW_POLICE', 'police'), # TODO string?
- ('TCA_FW_INDEV', 'hex'), # TODO string
- ('TCA_FW_ACT', 'hex'), # TODO
- ('TCA_FW_MASK', 'uint32'))
-
- class options_u32(nla, nla_plus_police):
- nla_map = (('TCA_U32_UNSPEC', 'none'),
- ('TCA_U32_CLASSID', 'uint32'),
- ('TCA_U32_HASH', 'uint32'),
- ('TCA_U32_LINK', 'hex'),
- ('TCA_U32_DIVISOR', 'uint32'),
- ('TCA_U32_SEL', 'u32_sel'),
- ('TCA_U32_POLICE', 'police'),
- ('TCA_U32_ACT', 'tca_act_prio'),
- ('TCA_U32_INDEV', 'hex'),
- ('TCA_U32_PCNT', 'u32_pcnt'),
- ('TCA_U32_MARK', 'u32_mark'))
-
- class tca_act_prio(nla):
- nla_map = tuple([('TCA_ACT_PRIO_%i' % x, 'tca_act') for x
- in range(TCA_ACT_MAX_PRIO)])
-
- class tca_act(nla, nla_plus_police, nla_plus_stats2):
- nla_map = (('TCA_ACT_UNSPEC', 'none'),
- ('TCA_ACT_KIND', 'asciiz'),
- ('TCA_ACT_OPTIONS', 'police'),
- ('TCA_ACT_INDEX', 'hex'),
- ('TCA_ACT_STATS', 'stats2'))
-
- class u32_sel(nla):
- fields = (('flags', 'B'),
- ('offshift', 'B'),
- ('nkeys', 'B'),
- ('__align', 'B'),
- ('offmask', '>H'),
- ('off', 'H'),
- ('offoff', 'h'),
- ('hoff', 'h'),
- ('hmask', '>I'))
-
- class u32_key(nlmsg):
- header = None
- fields = (('key_mask', '>I'),
- ('key_val', '>I'),
- ('key_off', 'i'),
- ('key_offmask', 'i'))
-
- def encode(self):
- '''
- Key sample::
-
- 'keys': ['0x0006/0x00ff+8',
- '0x0000/0xffc0+2',
- '0x5/0xf+0',
- '0x10/0xff+33']
-
- => 00060000/00ff0000 + 8
- 05000000/0f00ffc0 + 0
- 00100000/00ff0000 + 32
- '''
-
- def cut_field(key, separator):
- '''
- split a field from the end of the string
- '''
- field = '0'
- pos = key.find(separator)
- new_key = key
- if pos > 0:
- field = key[pos + 1:]
- new_key = key[:pos]
- return (new_key, field)
-
- # 'header' array to pack keys to
- header = [(0, 0) for i in range(256)]
-
- keys = []
- # iterate keys and pack them to the 'header'
- for key in self['keys']:
- # TODO tags: filter
- (key, nh) = cut_field(key, '@') # FIXME: do not ignore nh
- (key, offset) = cut_field(key, '+')
- offset = int(offset, 0)
- # a little trick: if you provide /00ff+8, that
- # really means /ff+9, so we should take it into
- # account
- (key, mask) = cut_field(key, '/')
- if mask[:2] == '0x':
- mask = mask[2:]
- while True:
- if mask[:2] == '00':
- offset += 1
- mask = mask[2:]
- else:
- break
- mask = '0x' + mask
- mask = int(mask, 0)
- value = int(key, 0)
- bits = 24
- if mask == 0 and value == 0:
- key = self.u32_key(self.buf)
- key['key_off'] = offset
- key['key_mask'] = mask
- key['key_val'] = value
- keys.append(key)
- for bmask in struct.unpack('4B', struct.pack('>I', mask)):
- if bmask > 0:
- bvalue = (value & (bmask << bits)) >> bits
- header[offset] = (bvalue, bmask)
- offset += 1
- bits -= 8
-
- # recalculate keys from 'header'
- key = None
- value = 0
- mask = 0
- for offset in range(256):
- (bvalue, bmask) = header[offset]
- if bmask > 0 and key is None:
- key = self.u32_key(self.buf)
- key['key_off'] = offset
- key['key_mask'] = 0
- key['key_val'] = 0
- bits = 24
- if key is not None and bits >= 0:
- key['key_mask'] |= bmask << bits
- key['key_val'] |= bvalue << bits
- bits -= 8
- if (bits < 0 or offset == 255):
- keys.append(key)
- key = None
-
- assert keys
- self['nkeys'] = len(keys)
- # FIXME: do not hardcode flags :)
- self['flags'] = 1
- start = self.buf.tell()
-
- nla.encode(self)
- for key in keys:
- key.encode()
- self.update_length(start)
-
- def decode(self):
- nla.decode(self)
- self['keys'] = []
- nkeys = self['nkeys']
- while nkeys:
- key = self.u32_key(self.buf)
- key.decode()
- self['keys'].append(key)
- nkeys -= 1
-
- class u32_mark(nla):
- fields = (('val', 'I'),
- ('mask', 'I'),
- ('success', 'I'))
-
- class u32_pcnt(nla):
- fields = (('rcnt', 'Q'),
- ('rhit', 'Q'),
- ('kcnts', 'Q'))
-
- class options_pfifo_fast(nla):
- fields = (('bands', 'i'),
- ('priomap', '16B'))
-
- class options_tbf(nla_plus_rtab):
- nla_map = (('TCA_TBF_UNSPEC', 'none'),
- ('TCA_TBF_PARMS', 'tbf_parms'),
- ('TCA_TBF_RTAB', 'rtab'),
- ('TCA_TBF_PTAB', 'ptab'))
-
- class tbf_parms(nla_plus_rtab.parms):
- fields = (('rate_cell_log', 'B'),
- ('rate___reserved', 'B'),
- ('rate_overhead', 'H'),
- ('rate_cell_align', 'h'),
- ('rate_mpu', 'H'),
- ('rate', 'I'),
- ('peak_cell_log', 'B'),
- ('peak___reserved', 'B'),
- ('peak_overhead', 'H'),
- ('peak_cell_align', 'h'),
- ('peak_mpu', 'H'),
- ('peak', 'I'),
- ('limit', 'I'),
- ('buffer', 'I'),
- ('mtu', 'I'))
-
- class options_sfq_v0(nla):
- fields = (('quantum', 'I'),
- ('perturb_period', 'i'),
- ('limit', 'I'),
- ('divisor', 'I'),
- ('flows', 'I'))
-
- class options_sfq_v1(nla):
- fields = (('quantum', 'I'),
- ('perturb_period', 'i'),
- ('limit_v0', 'I'),
- ('divisor', 'I'),
- ('flows', 'I'),
- ('depth', 'I'),
- ('headdrop', 'I'),
- ('limit_v1', 'I'),
- ('qth_min', 'I'),
- ('qth_max', 'I'),
- ('Wlog', 'B'),
- ('Plog', 'B'),
- ('Scell_log', 'B'),
- ('flags', 'B'),
- ('max_P', 'I'),
- ('prob_drop', 'I'),
- ('forced_drop', 'I'),
- ('prob_mark', 'I'),
- ('forced_mark', 'I'),
- ('prob_mark_head', 'I'),
- ('forced_mark_head', 'I'))
diff --git a/node-admin/scripts/pyroute2/netlink/taskstats/__init__.py b/node-admin/scripts/pyroute2/netlink/taskstats/__init__.py
deleted file mode 100644
index 86a8d20464c..00000000000
--- a/node-admin/scripts/pyroute2/netlink/taskstats/__init__.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-TaskStats module
-================
-
-All that you should know about TaskStats, is that you should not
-use it. But if you have to, ok::
-
- import os
- from pyroute2 import TaskStats
- ts = TaskStats()
- ts.get_pid_stat(os.getpid())
-
-It is not implemented normally yet, but some methods are already
-usable.
-'''
-
-from pyroute2.netlink import NLM_F_REQUEST
-from pyroute2.netlink import nla
-from pyroute2.netlink import genlmsg
-from pyroute2.netlink.generic import GenericNetlinkSocket
-
-TASKSTATS_CMD_UNSPEC = 0 # Reserved
-TASKSTATS_CMD_GET = 1 # user->kernel request/get-response
-TASKSTATS_CMD_NEW = 2
-
-
-class tcmd(genlmsg):
- nla_map = (('TASKSTATS_CMD_ATTR_UNSPEC', 'none'),
- ('TASKSTATS_CMD_ATTR_PID', 'uint32'),
- ('TASKSTATS_CMD_ATTR_TGID', 'uint32'),
- ('TASKSTATS_CMD_ATTR_REGISTER_CPUMASK', 'asciiz'),
- ('TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK', 'asciiz'))
-
-
-class tstats(nla):
- pack = "struct"
- fields = (('version', 'H'), # 2
- ('ac_exitcode', 'I'), # 4
- ('ac_flag', 'B'), # 1
- ('ac_nice', 'B'), # 1 --- 10
- ('cpu_count', 'Q'), # 8
- ('cpu_delay_total', 'Q'), # 8
- ('blkio_count', 'Q'), # 8
- ('blkio_delay_total', 'Q'), # 8
- ('swapin_count', 'Q'), # 8
- ('swapin_delay_total', 'Q'), # 8
- ('cpu_run_real_total', 'Q'), # 8
- ('cpu_run_virtual_total', 'Q'), # 8
- ('ac_comm', '32s'), # 32 +++ 112
- ('ac_sched', 'B'), # 1
- ('__pad', '3x'), # 1 --- 8 (!)
- ('ac_uid', 'I'), # 4 +++ 120
- ('ac_gid', 'I'), # 4
- ('ac_pid', 'I'), # 4
- ('ac_ppid', 'I'), # 4
- ('ac_btime', 'I'), # 4 +++ 136
- ('ac_etime', 'Q'), # 8 +++ 144
- ('ac_utime', 'Q'), # 8
- ('ac_stime', 'Q'), # 8
- ('ac_minflt', 'Q'), # 8
- ('ac_majflt', 'Q'), # 8
- ('coremem', 'Q'), # 8
- ('virtmem', 'Q'), # 8
- ('hiwater_rss', 'Q'), # 8
- ('hiwater_vm', 'Q'), # 8
- ('read_char', 'Q'), # 8
- ('write_char', 'Q'), # 8
- ('read_syscalls', 'Q'), # 8
- ('write_syscalls', 'Q'), # 8
- ('read_bytes', 'Q'), # ...
- ('write_bytes', 'Q'),
- ('cancelled_write_bytes', 'Q'),
- ('nvcsw', 'Q'),
- ('nivcsw', 'Q'),
- ('ac_utimescaled', 'Q'),
- ('ac_stimescaled', 'Q'),
- ('cpu_scaled_run_real_total', 'Q'))
-
- def decode(self):
- nla.decode(self)
- self['ac_comm'] = self['ac_comm'][:self['ac_comm'].find('\0')]
-
-
-class taskstatsmsg(genlmsg):
-
- nla_map = (('TASKSTATS_TYPE_UNSPEC', 'none'),
- ('TASKSTATS_TYPE_PID', 'uint32'),
- ('TASKSTATS_TYPE_TGID', 'uint32'),
- ('TASKSTATS_TYPE_STATS', 'stats'),
- ('TASKSTATS_TYPE_AGGR_PID', 'aggr_pid'),
- ('TASKSTATS_TYPE_AGGR_TGID', 'aggr_tgid'))
-
- class stats(tstats):
- pass # FIXME: optimize me!
-
- class aggr_id(nla):
- nla_map = (('TASKSTATS_TYPE_UNSPEC', 'none'),
- ('TASKSTATS_TYPE_PID', 'uint32'),
- ('TASKSTATS_TYPE_TGID', 'uint32'),
- ('TASKSTATS_TYPE_STATS', 'stats'))
-
- class stats(tstats):
- pass
-
- class aggr_pid(aggr_id):
- pass
-
- class aggr_tgid(aggr_id):
- pass
-
-
-class TaskStats(GenericNetlinkSocket):
-
- def __init__(self):
- GenericNetlinkSocket.__init__(self)
-
- def bind(self):
- GenericNetlinkSocket.bind(self, 'TASKSTATS', taskstatsmsg)
-
- def get_pid_stat(self, pid):
- '''
- Get taskstats for a process. Pid should be an integer.
- '''
- msg = tcmd()
- msg['cmd'] = TASKSTATS_CMD_GET
- msg['version'] = 1
- msg['attrs'].append(['TASKSTATS_CMD_ATTR_PID', pid])
- return self.nlm_request(msg,
- self.prid,
- msg_flags=NLM_F_REQUEST)
-
- def _register_mask(self, cmd, mask):
- msg = tcmd()
- msg['cmd'] = TASKSTATS_CMD_GET
- msg['version'] = 1
- msg['attrs'].append([cmd, mask])
- # there is no response to this request
- self.put(msg,
- self.prid,
- msg_flags=NLM_F_REQUEST)
-
- def register_mask(self, mask):
- '''
- Start the accounting for a processors by a mask. Mask is
- a string, e.g.::
- 0,1 -- first two CPUs
- 0-4,6-10 -- CPUs from 0 to 4 and from 6 to 10
-
- When the accounting is turned on, on can receive messages
- with get() routine.
-
- Though the kernel has a procedure, that cleans up accounting,
- when it is not used, it is recommended to run deregister_mask()
- before process exit.
- '''
- self.monitor(True)
- self._register_mask('TASKSTATS_CMD_ATTR_REGISTER_CPUMASK',
- mask)
-
- def deregister_mask(self, mask):
- '''
- Stop the accounting.
- '''
- self.monitor(False)
- self._register_mask('TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK',
- mask)
diff --git a/node-admin/scripts/pyroute2/netns/__init__.py b/node-admin/scripts/pyroute2/netns/__init__.py
deleted file mode 100644
index 696ff3a14a6..00000000000
--- a/node-admin/scripts/pyroute2/netns/__init__.py
+++ /dev/null
@@ -1,123 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-Network namespaces management
-=============================
-
-Pyroute2 provides basic namespaces management support. The
-`netns` module contains several tools for that.
-
-Please be aware, that in order to run system calls the
-library uses `ctypes` module. It can fail on platforms
-where SELinux is enforced. If the Python interpreter,
-loading this module, dumps the core, one can check the
-SELinux state with `getenforce` command.
-
-'''
-
-import os
-import errno
-import ctypes
-import sys
-
-if sys.maxsize > 2**32:
- __NR_setns = 308
-else:
- __NR_setns = 346
-
-CLONE_NEWNET = 0x40000000
-MNT_DETACH = 0x00000002
-MS_BIND = 4096
-MS_REC = 16384
-MS_SHARED = 1 << 20
-NETNS_RUN_DIR = '/var/run/netns'
-
-
-def listnetns():
- '''
- List available network namespaces.
- '''
- try:
- return os.listdir(NETNS_RUN_DIR)
- except OSError as e:
- if e.errno == errno.ENOENT:
- return []
- else:
- raise
-
-
-def create(netns, libc=None):
- '''
- Create a network namespace.
- '''
- libc = libc or ctypes.CDLL('libc.so.6', use_errno=True)
- # FIXME validate and prepare NETNS_RUN_DIR
-
- netnspath = '%s/%s' % (NETNS_RUN_DIR, netns)
- netnspath = netnspath.encode('ascii')
- netnsdir = NETNS_RUN_DIR.encode('ascii')
-
- # init netnsdir
- try:
- os.mkdir(netnsdir)
- except OSError as e:
- if e.errno != errno.EEXIST:
- raise
-
- # this code is ported from iproute2
- done = False
- while libc.mount(b'', netnsdir, b'none', MS_SHARED | MS_REC, None) != 0:
- if done:
- raise OSError(ctypes.get_errno(), 'share rundir failed', netns)
- if libc.mount(netnsdir, netnsdir, b'none', MS_BIND, None) != 0:
- raise OSError(ctypes.get_errno(), 'mount rundir failed', netns)
- done = True
-
- # create mountpoint
- os.close(os.open(netnspath, os.O_RDONLY | os.O_CREAT | os.O_EXCL, 0))
-
- # unshare
- if libc.unshare(CLONE_NEWNET) < 0:
- raise OSError(ctypes.get_errno(), 'unshare failed', netns)
-
- # bind the namespace
- if libc.mount(b'/proc/self/ns/net', netnspath, b'none', MS_BIND, None) < 0:
- raise OSError(ctypes.get_errno(), 'mount failed', netns)
-
-
-def remove(netns, libc=None):
- '''
- Remove a network namespace.
- '''
- libc = libc or ctypes.CDLL('libc.so.6', use_errno=True)
- netnspath = '%s/%s' % (NETNS_RUN_DIR, netns)
- netnspath = netnspath.encode('ascii')
- libc.umount2(netnspath, MNT_DETACH)
- os.unlink(netnspath)
-
-
-def setns(netns, flags=os.O_CREAT, libc=None):
- '''
- Set netns for the current process.
-
- The flags semantics is the same as for the `open(2)`
- call:
-
- - O_CREAT -- create netns, if doesn't exist
- - O_CREAT | O_EXCL -- create only if doesn't exist
- '''
- libc = libc or ctypes.CDLL('libc.so.6', use_errno=True)
- netnspath = '%s/%s' % (NETNS_RUN_DIR, netns)
- netnspath = netnspath.encode('ascii')
-
- if netns in listnetns():
- if flags & (os.O_CREAT | os.O_EXCL) == (os.O_CREAT | os.O_EXCL):
- raise OSError(errno.EEXIST, 'netns exists', netns)
- else:
- if flags & os.O_CREAT:
- create(netns, libc=libc)
-
- nsfd = os.open(netnspath, os.O_RDONLY)
- ret = libc.syscall(__NR_setns, nsfd, CLONE_NEWNET)
- if ret != 0:
- raise OSError(ctypes.get_errno(), 'failed to open netns', netns)
- return nsfd
diff --git a/node-admin/scripts/pyroute2/netns/nslink.py b/node-admin/scripts/pyroute2/netns/nslink.py
deleted file mode 100644
index 67d5fff0921..00000000000
--- a/node-admin/scripts/pyroute2/netns/nslink.py
+++ /dev/null
@@ -1,310 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-NetNS
-=====
-
-A NetNS object is IPRoute-like. It runs in the main network
-namespace, but also creates a proxy process running in
-the required netns. All the netlink requests are done via
-that proxy process.
-
-NetNS supports standard IPRoute API, so can be used instead
-of IPRoute, e.g., in IPDB::
-
- # start the main network settings database:
- ipdb_main = IPDB()
- # start the same for a netns:
- ipdb_test = IPDB(nl=NetNS('test'))
-
- # create VETH
- ipdb_main.create(ifname='v0p0', kind='veth', peer='v0p1').commit()
-
- # move peer VETH into the netns
- with ipdb_main.interfaces.v0p1 as veth:
- veth.net_ns_fd = 'test'
-
- # please keep in mind, that netns move clears all the settings
- # on a VETH interface pair, so one should run netns assignment
- # as a separate operation only
-
- # assign addresses
- # please notice, that `v0p1` is already in the `test` netns,
- # so should be accessed via `ipdb_test`
- with ipdb_main.interfaces.v0p0 as veth:
- veth.add_ip('172.16.200.1/24')
- veth.up()
- with ipdb_test.interfaces.v0p1 as veth:
- veth.add_ip('172.16.200.2/24')
- veth.up()
-
-Please review also the test code, under `tests/test_netns.py` for
-more examples.
-
-By default, NetNS creates requested netns, if it doesn't exist,
-or uses existing one. To control this behaviour, one can use flags
-as for `open(2)` system call::
-
- # create a new netns or fail, if it already exists
- netns = NetNS('test', flags=os.O_CREAT | os.O_EXIST)
-
- # create a new netns or use existing one
- netns = NetNS('test', flags=os.O_CREAT)
-
- # the same as above, the default behaviour
- netns = NetNS('test')
-
-To remove a network namespace::
-
- from pyroute2 import NetNS
- netns = NetNS('test')
- netns.close()
- netns.remove()
-
-One should stop it first with `close()`, and only after that
-run `remove()`.
-
-'''
-
-import os
-import errno
-import atexit
-import select
-import struct
-import threading
-import traceback
-from socket import SOL_SOCKET
-from socket import SO_RCVBUF
-from pyroute2.config import MpPipe
-from pyroute2.config import MpProcess
-from pyroute2.iproute import IPRoute
-from pyroute2.netlink.nlsocket import NetlinkMixin
-from pyroute2.netlink.rtnl.iprsocket import MarshalRtnl
-from pyroute2.iproute import IPRouteMixin
-from pyroute2.netns import setns
-from pyroute2.netns import remove
-
-
-def NetNServer(netns, rcvch, cmdch, flags=os.O_CREAT):
- '''
- The netns server supposed to be started automatically by NetNS.
- It has two communication channels: one simplex to forward incoming
- netlink packets, `rcvch`, and other synchronous duplex to get
- commands and send back responses, `cmdch`.
-
- Channels should support standard socket API, should be compatible
- with poll/select and should be able to transparently pickle objects.
- NetNS uses `multiprocessing.Pipe` for this purpose, but it can be
- any other implementation with compatible API.
-
- The first parameter, `netns`, is a netns name. Depending on the
- `flags`, the netns can be created automatically. The `flags` semantics
- is exactly the same as for `open(2)` system call.
-
- ...
-
- The server workflow is simple. The startup sequence::
-
- 1. Create or open a netns.
-
- 2. Start `IPRoute` instance. It will be used only on the low level,
- the `IPRoute` will not parse any packet.
-
- 3. Start poll/select loop on `cmdch` and `IPRoute`.
-
- On the startup, the server sends via `cmdch` the status packet. It can be
- `None` if all is OK, or some exception.
-
- Further data handling, depending on the channel, server side::
-
- 1. `IPRoute`: read an incoming netlink packet and send it unmodified
- to the peer via `rcvch`. The peer, polling `rcvch`, can handle
- the packet on its side.
-
- 2. `cmdch`: read tuple (cmd, argv, kwarg). If the `cmd` starts with
- "send", then take `argv[0]` as a packet buffer, treat it as one
- netlink packet and substitute PID field (offset 12, uint32) with
- its own. Strictly speaking, it is not mandatory for modern netlink
- implementations, but it is required by the protocol standard.
-
- '''
- try:
- nsfd = setns(netns, flags)
- except OSError as e:
- cmdch.send(e)
- return e.errno
- except Exception as e:
- cmdch.send(OSError(errno.ECOMM, str(e), netns))
- return 255
-
- #
- try:
- ipr = IPRoute()
- rcvch_lock = ipr._sproxy.lock
- ipr._s_channel = rcvch
- poll = select.poll()
- poll.register(ipr, select.POLLIN | select.POLLPRI)
- poll.register(cmdch, select.POLLIN | select.POLLPRI)
- except Exception as e:
- cmdch.send(e)
- return 255
-
- # all is OK so far
- cmdch.send(None)
- # 8<-------------------------------------------------------------
- while True:
- events = poll.poll()
- for (fd, event) in events:
- if fd == ipr.fileno():
- bufsize = ipr.getsockopt(SOL_SOCKET, SO_RCVBUF) // 2
- with rcvch_lock:
- rcvch.send(ipr.recv(bufsize))
- elif fd == cmdch.fileno():
- try:
- cmdline = cmdch.recv()
- if cmdline is None:
- poll.unregister(ipr)
- poll.unregister(cmdch)
- ipr.close()
- os.close(nsfd)
- return
- (cmd, argv, kwarg) = cmdline
- if cmd[:4] == 'send':
- # Achtung
- #
- # It's a hack, but we just have to do it: one
- # must use actual pid in netlink messages
- #
- # FIXME: there can be several messages in one
- # call buffer; but right now we can ignore it
- msg = argv[0][:12]
- msg += struct.pack("I", os.getpid())
- msg += argv[0][16:]
- argv = list(argv)
- argv[0] = msg
- cmdch.send(getattr(ipr, cmd)(*argv, **kwarg))
- except Exception as e:
- e.tb = traceback.format_exc()
- cmdch.send(e)
-
-
-class NetNSProxy(object):
-
- netns = 'default'
- flags = os.O_CREAT
-
- def __init__(self, *argv, **kwarg):
- self.cmdlock = threading.Lock()
- self.rcvch, rcvch = MpPipe()
- self.cmdch, cmdch = MpPipe()
- self.server = MpProcess(target=NetNServer,
- args=(self.netns, rcvch, cmdch, self.flags))
- self.server.start()
- error = self.cmdch.recv()
- if error is not None:
- self.server.join()
- raise error
- else:
- atexit.register(self.close)
-
- def recv(self, bufsize, flags=0):
- return self.rcvch.recv()
-
- def close(self):
- self.cmdch.send(None)
- self.server.join()
-
- def proxy(self, cmd, *argv, **kwarg):
- with self.cmdlock:
- self.cmdch.send((cmd, argv, kwarg))
- response = self.cmdch.recv()
- if isinstance(response, Exception):
- raise response
- return response
-
- def fileno(self):
- return self.rcvch.fileno()
-
- def bind(self, *argv, **kwarg):
- if 'async' in kwarg:
- kwarg['async'] = False
- return self.proxy('bind', *argv, **kwarg)
-
- def send(self, *argv, **kwarg):
- return self.proxy('send', *argv, **kwarg)
-
- def sendto(self, *argv, **kwarg):
- return self.proxy('sendto', *argv, **kwarg)
-
- def getsockopt(self, *argv, **kwarg):
- return self.proxy('getsockopt', *argv, **kwarg)
-
- def setsockopt(self, *argv, **kwarg):
- return self.proxy('setsockopt', *argv, **kwarg)
-
-
-class NetNSocket(NetlinkMixin, NetNSProxy):
-
- def bind(self, *argv, **kwarg):
- return NetNSProxy.bind(self, *argv, **kwarg)
-
- def close(self):
- NetNSProxy.close(self)
-
- def _sendto(self, *argv, **kwarg):
- return NetNSProxy.sendto(self, *argv, **kwarg)
-
- def _recv(self, *argv, **kwarg):
- return NetNSProxy.recv(self, *argv, **kwarg)
-
-
-class NetNS(IPRouteMixin, NetNSocket):
- '''
- NetNS is the IPRoute API with network namespace support.
-
- **Why not IPRoute?**
-
- The task to run netlink commands in some network namespace, being in
- another network namespace, requires the architecture, that differs
- too much from a simple Netlink socket.
-
- NetNS starts a proxy process in a network namespace and uses
- `multiprocessing` communication channels between the main and the proxy
- processes to route all `recv()` and `sendto()` requests/responses.
-
- **Any specific API calls?**
-
- Nope. `NetNS` supports all the same, that `IPRoute` does, in the same
- way. It provides full `socket`-compatible API and can be used in
- poll/select as well.
-
- The only difference is the `close()` call. In the case of `NetNS` it
- is **mandatory** to close the socket before exit.
-
- **NetNS and IPDB**
-
- It is possible to run IPDB with NetNS::
-
- from pyroute2 import NetNS
- from pyroute2 import IPDB
-
- ip = IPDB(nl=NetNS('somenetns'))
- ...
- ip.release()
-
- Do not forget to call `release()` when the work is done. It will shut
- down `NetNS` instance as well.
- '''
- def __init__(self, netns, flags=os.O_CREAT):
- self.netns = netns
- self.flags = flags
- super(NetNS, self).__init__()
- self.marshal = MarshalRtnl()
-
- def post_init(self):
- pass
-
- def remove(self):
- '''
- Try to remove this network namespace from the system.
- '''
- remove(self.netns)
diff --git a/node-admin/scripts/pyroute2/netns/process/__init__.py b/node-admin/scripts/pyroute2/netns/process/__init__.py
deleted file mode 100644
index a211a3993f6..00000000000
--- a/node-admin/scripts/pyroute2/netns/process/__init__.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-import types
-import subprocess
-
-
-class MetaPopen(type):
- '''
- API definition for NSPopen.
-
- All this stuff is required to make `help()` function happy.
- '''
- def __init__(cls, *argv, **kwarg):
- super(MetaPopen, cls).__init__(*argv, **kwarg)
- # copy docstrings and create proxy slots
- cls.api = {}
- for attr_name in dir(subprocess.Popen):
- attr = getattr(subprocess.Popen, attr_name)
- cls.api[attr_name] = {}
- cls.api[attr_name]['callable'] = \
- isinstance(attr, (types.MethodType, types.FunctionType))
- cls.api[attr_name]['doc'] = attr.__doc__ \
- if hasattr(attr, '__doc__') else None
-
- def __dir__(cls):
- return list(cls.api.keys()) + ['release']
-
- def __getattribute__(cls, key):
- try:
- return type.__getattribute__(cls, key)
- except AttributeError:
- attr = getattr(subprocess.Popen, key)
- if isinstance(attr, (types.MethodType, types.FunctionType)):
- def proxy(*argv, **kwarg):
- return attr(*argv, **kwarg)
- proxy.__doc__ = attr.__doc__
- proxy.__objclass__ = cls
- return proxy
- else:
- return attr
diff --git a/node-admin/scripts/pyroute2/netns/process/base_p2.py b/node-admin/scripts/pyroute2/netns/process/base_p2.py
deleted file mode 100644
index 402329846c0..00000000000
--- a/node-admin/scripts/pyroute2/netns/process/base_p2.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-from pyroute2.netns.process import MetaPopen
-
-
-class NSPopenBase(object):
-
- __metaclass__ = MetaPopen
diff --git a/node-admin/scripts/pyroute2/netns/process/base_p3.py b/node-admin/scripts/pyroute2/netns/process/base_p3.py
deleted file mode 100644
index 1356958e24a..00000000000
--- a/node-admin/scripts/pyroute2/netns/process/base_p3.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-from pyroute2.netns.process import MetaPopen
-
-
-class NSPopenBase(object, metaclass=MetaPopen):
-
- pass
diff --git a/node-admin/scripts/pyroute2/netns/process/proxy.py b/node-admin/scripts/pyroute2/netns/process/proxy.py
deleted file mode 100644
index 11695ac3d67..00000000000
--- a/node-admin/scripts/pyroute2/netns/process/proxy.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-NSPopen
-=======
-
-The `NSPopen` class has nothing to do with netlink at
-all, but it is required to have a reasonable network
-namespace support.
-
-'''
-
-
-import types
-import atexit
-import threading
-import subprocess
-from pyroute2.netns import setns
-from pyroute2.config import MpQueue
-from pyroute2.config import MpProcess
-try:
- from pyroute2.netns.process.base_p3 import NSPopenBase
-except Exception:
- from pyroute2.netns.process.base_p2 import NSPopenBase
-
-
-def _handle(result):
- if result['code'] == 500:
- raise result['data']
- elif result['code'] == 200:
- return result['data']
- else:
- raise TypeError('unsupported return code')
-
-
-def NSPopenServer(nsname, flags, channel_in, channel_out, argv, kwarg):
- # set netns
- try:
- setns(nsname, flags=flags)
- except Exception as e:
- channel_out.put(e)
- return
- # create the Popen object
- child = subprocess.Popen(*argv, **kwarg)
- # send the API map
- channel_out.put(None)
-
- while True:
- # synchronous mode
- # 1. get the command from the API
- call = channel_in.get()
- # 2. stop?
- if call['name'] == 'release':
- break
- # 3. run the call
- try:
- attr = getattr(child, call['name'])
- if isinstance(attr, types.MethodType):
- result = attr(*call['argv'], **call['kwarg'])
- else:
- result = attr
- channel_out.put({'code': 200, 'data': result})
- except Exception as e:
- channel_out.put({'code': 500, 'data': e})
- child.wait()
-
-
-class NSPopen(NSPopenBase):
- '''
- A proxy class to run `Popen()` object in some network namespace.
-
- Sample to run `ip ad` command in `nsname` network namespace::
-
- nsp = NSPopen('nsname', ['ip', 'ad'], stdout=subprocess.PIPE)
- print(nsp.communicate())
- nsp.wait()
- nsp.release()
-
- The only difference in the `release()` call. It explicitly ends
- the proxy process and releases all the resources.
- '''
-
- def __init__(self, nsname, *argv, **kwarg):
- '''
- The only differences from the `subprocess.Popen` init are:
- * `nsname` -- network namespace name
- * `flags` keyword argument
-
- All other arguments are passed directly to `subprocess.Popen`.
-
- Flags usage samples. Create a network namespace, if it doesn't
- exist yet::
-
- import os
- nsp = NSPopen('nsname', ['command'], flags=os.O_CREAT)
-
- Create a network namespace only if it doesn't exist, otherwise
- fail and raise an exception::
-
- import os
- nsp = NSPopen('nsname', ['command'], flags=os.O_CREAT | os.O_EXCL)
- '''
- # create a child
- self.nsname = nsname
- if 'flags' in kwarg:
- self.flags = kwarg.pop('flags')
- else:
- self.flags = 0
- self.channel_out = MpQueue()
- self.channel_in = MpQueue()
- self.lock = threading.Lock()
- self.released = False
- self.server = MpProcess(target=NSPopenServer,
- args=(self.nsname,
- self.flags,
- self.channel_out,
- self.channel_in,
- argv, kwarg))
- # start the child and check the status
- self.server.start()
- response = self.channel_in.get()
- if isinstance(response, Exception):
- self.server.join()
- raise response
- else:
- atexit.register(self.release)
-
- def release(self):
- '''
- Explicitly stop the proxy process and release all the
- resources. The `NSPopen` object can not be used after
- the `release()` call.
- '''
- with self.lock:
- if self.released:
- return
- self.released = True
- self.channel_out.put({'name': 'release'})
- self.channel_out.close()
- self.channel_in.close()
- self.server.join()
-
- def __dir__(self):
- return list(self.api.keys()) + ['release']
-
- def __getattribute__(self, key):
- try:
- return object.__getattribute__(self, key)
- except AttributeError:
- with self.lock:
- if self.released:
- raise RuntimeError('the object is released')
-
- if self.api.get(key) and self.api[key]['callable']:
- def proxy(*argv, **kwarg):
- self.channel_out.put({'name': key,
- 'argv': argv,
- 'kwarg': kwarg})
- return _handle(self.channel_in.get())
- proxy.__doc__ = self.api[key]['doc']
- return proxy
- else:
- self.channel_out.put({'name': key})
- return _handle(self.channel_in.get())
diff --git a/node-admin/scripts/pyroute2/protocols/__init__.py b/node-admin/scripts/pyroute2/protocols/__init__.py
deleted file mode 100644
index 25cf566af48..00000000000
--- a/node-admin/scripts/pyroute2/protocols/__init__.py
+++ /dev/null
@@ -1,234 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-import struct
-from socket import inet_ntop
-from socket import inet_pton
-from socket import AF_INET
-from pyroute2.common import basestring
-
-#
-# IEEE = 802.3 Ethernet magic constants. The frame sizes omit
-# the preamble and FCS/CRC (frame check sequence).
-#
-
-ETH_ALEN = 6 # Octets in one ethernet addr
-ETH_HLEN = 14 # Total octets in header.
-ETH_ZLEN = 60 # Min. octets in frame sans FCS
-ETH_DATA_LEN = 1500 # Max. octets in payload
-ETH_FRAME_LEN = 1514 # Max. octets in frame sans FCS
-ETH_FCS_LEN = 4 # Octets in the FCS
-
-#
-# These are the defined Ethernet Protocol ID's.
-#
-
-ETH_P_LOOP = 0x0060 # Ethernet Loopback packet
-ETH_P_PUP = 0x0200 # Xerox PUP packet
-ETH_P_PUPAT = 0x0201 # Xerox PUP Addr Trans packet
-ETH_P_IP = 0x0800 # Internet Protocol packet
-ETH_P_X25 = 0x0805 # CCITT X.25
-ETH_P_ARP = 0x0806 # Address Resolution packet
-ETH_P_BPQ = 0x08FF # G8BPQ AX.25 Ethernet Packet
-# ^^^ [ NOT AN OFFICIALLY REGISTERED ID ]
-ETH_P_IEEEPUP = 0x0a00 # Xerox IEEE802.3 PUP packet
-ETH_P_IEEEPUPAT = 0x0a01 # Xerox IEEE802.3 PUP Addr Trans packet
-ETH_P_DEC = 0x6000 # DEC Assigned proto
-ETH_P_DNA_DL = 0x6001 # DEC DNA Dump/Load
-ETH_P_DNA_RC = 0x6002 # DEC DNA Remote Console
-ETH_P_DNA_RT = 0x6003 # DEC DNA Routing
-ETH_P_LAT = 0x6004 # DEC LAT
-ETH_P_DIAG = 0x6005 # DEC Diagnostics
-ETH_P_CUST = 0x6006 # DEC Customer use
-ETH_P_SCA = 0x6007 # DEC Systems Comms Arch
-ETH_P_TEB = 0x6558 # Trans Ether Bridging
-ETH_P_RARP = 0x8035 # Reverse Addr Res packet
-ETH_P_ATALK = 0x809B # Appletalk DDP
-ETH_P_AARP = 0x80F3 # Appletalk AARP
-ETH_P_8021Q = 0x8100 # = 802.1Q VLAN Extended Header
-ETH_P_IPX = 0x8137 # IPX over DIX
-ETH_P_IPV6 = 0x86DD # IPv6 over bluebook
-ETH_P_PAUSE = 0x8808 # IEEE Pause frames. See = 802.3 = 31B
-ETH_P_SLOW = 0x8809 # Slow Protocol. See = 802.3ad = 43B
-ETH_P_WCCP = 0x883E # Web-cache coordination protocol
-# defined in draft-wilson-wrec-wccp-v2-00.txt
-ETH_P_PPP_DISC = 0x8863 # PPPoE discovery messages
-ETH_P_PPP_SES = 0x8864 # PPPoE session messages
-ETH_P_MPLS_UC = 0x8847 # MPLS Unicast traffic
-ETH_P_MPLS_MC = 0x8848 # MPLS Multicast traffic
-ETH_P_ATMMPOA = 0x884c # MultiProtocol Over ATM
-ETH_P_LINK_CTL = 0x886c # HPNA, wlan link local tunnel
-ETH_P_ATMFATE = 0x8884 # Frame-based ATM Transport over Ethernet
-
-ETH_P_PAE = 0x888E # Port Access Entity (IEEE = 802.1X)
-ETH_P_AOE = 0x88A2 # ATA over Ethernet
-ETH_P_8021AD = 0x88A8 # = 802.1ad Service VLAN
-ETH_P_802_EX1 = 0x88B5 # = 802.1 Local Experimental = 1.
-ETH_P_TIPC = 0x88CA # TIPC
-ETH_P_8021AH = 0x88E7 # = 802.1ah Backbone Service Tag
-ETH_P_1588 = 0x88F7 # IEEE = 1588 Timesync
-ETH_P_FCOE = 0x8906 # Fibre Channel over Ethernet
-ETH_P_TDLS = 0x890D # TDLS
-ETH_P_FIP = 0x8914 # FCoE Initialization Protocol
-ETH_P_QINQ1 = 0x9100 # deprecated QinQ VLAN
-# ^^^ [ NOT AN OFFICIALLY REGISTERED ID ]
-ETH_P_QINQ2 = 0x9200 # deprecated QinQ VLAN
-# ^^^ [ NOT AN OFFICIALLY REGISTERED ID ]
-ETH_P_QINQ3 = 0x9300 # deprecated QinQ VLAN
-# ^^^ [ NOT AN OFFICIALLY REGISTERED ID ]
-ETH_P_EDSA = 0xDADA # Ethertype DSA
-# ^^^ [ NOT AN OFFICIALLY REGISTERED ID ]
-ETH_P_AF_IUCV = 0xFBFB # IBM af_iucv
-# ^^^ [ NOT AN OFFICIALLY REGISTERED ID ]
-
-#
-# Non DIX types. Won't clash for = 1500 types.
-#
-
-ETH_P_802_3 = 0x0001 # Dummy type for = 802.3 frames
-ETH_P_AX25 = 0x0002 # Dummy protocol id for AX.25
-ETH_P_ALL = 0x0003 # Every packet (be careful!!!)
-ETH_P_802_2 = 0x0004 # = 802.2 frames
-ETH_P_SNAP = 0x0005 # Internal only
-ETH_P_DDCMP = 0x0006 # DEC DDCMP: Internal only
-ETH_P_WAN_PPP = 0x0007 # Dummy type for WAN PPP frames*/
-ETH_P_PPP_MP = 0x0008 # Dummy type for PPP MP frames
-ETH_P_LOCALTALK = 0x0009 # Localtalk pseudo type
-ETH_P_CAN = 0x000C # Controller Area Network
-ETH_P_PPPTALK = 0x0010 # Dummy type for Atalk over PPP*/
-ETH_P_TR_802_2 = 0x0011 # = 802.2 frames
-ETH_P_MOBITEX = 0x0015 # Mobitex (kaz@cafe.net)
-ETH_P_CONTROL = 0x0016 # Card specific control frames
-ETH_P_IRDA = 0x0017 # Linux-IrDA
-ETH_P_ECONET = 0x0018 # Acorn Econet
-ETH_P_HDLC = 0x0019 # HDLC frames
-ETH_P_ARCNET = 0x001A # = 1A for ArcNet :-)
-ETH_P_DSA = 0x001B # Distributed Switch Arch.
-ETH_P_TRAILER = 0x001C # Trailer switch tagging
-ETH_P_PHONET = 0x00F5 # Nokia Phonet frames
-ETH_P_IEEE802154 = 0x00F6 # IEEE802.15.4 frame
-ETH_P_CAIF = 0x00F7 # ST-Ericsson CAIF protocol
-
-
-class msg(dict):
- buf = None
- data_len = None
- fields = ()
- _fields_names = ()
- types = {'uint8': 'B',
- 'uint16': 'H',
- 'uint32': 'I',
- 'be16': '>H',
- 'ip4addr': {'format': '4s',
- 'decode': lambda x: inet_ntop(AF_INET, x),
- 'encode': lambda x: [inet_pton(AF_INET, x)]},
- 'l2addr': {'format': '6B',
- 'decode': lambda x: ':'.join(['%x' % i for i in x]),
- 'encode': lambda x: [int(i, 16) for i in
- x.split(':')]},
- 'l2paddr': {'format': '6B10s',
- 'decode': lambda x: ':'.join(['%x' % i for i in
- x[:6]]),
- 'encode': lambda x: [int(i, 16) for i in
- x.split(':')] + [10 * b'\x00']}}
-
- def __init__(self, content=None, buf=b'', offset=0, value=None):
- content = content or {}
- dict.__init__(self, content)
- self.buf = buf
- self.offset = offset
- self.value = value
- self._register_fields()
-
- def _register_fields(self):
- self._fields_names = tuple([x[0] for x in self.fields])
-
- def _get_routine(self, mode, fmt):
- fmt = self.types.get(fmt, fmt)
- if isinstance(fmt, dict):
- return (fmt['format'],
- fmt.get(mode, lambda x: x))
- else:
- return (fmt, lambda x: x)
-
- def reset(self):
- self.buf = b''
-
- def decode(self):
- self._register_fields()
- for field in self.fields:
- name, sfmt = field[:2]
- fmt, routine = self._get_routine('decode', sfmt)
- size = struct.calcsize(fmt)
- value = struct.unpack(fmt, self.buf[self.offset:
- self.offset + size])
- if len(value) == 1:
- value = value[0]
- if isinstance(value, basestring) and sfmt[-1] == 's':
- value = value[:value.find(b'\x00')]
- self[name] = routine(value)
- self.offset += size
- return self
-
- def encode(self):
- self._register_fields()
- for field in self.fields:
- name, fmt = field[:2]
- default = b'\x00' if len(field) <= 2 else field[2]
- fmt, routine = self._get_routine('encode', fmt)
- # special case: string
- if fmt == 'string':
- self.buf += routine(self[name])[0]
- else:
- size = struct.calcsize(fmt)
- if self[name] is None:
- if not isinstance(default, basestring):
- self.buf += struct.pack(fmt, default)
- else:
- self.buf += default * (size // len(default))
- else:
- value = routine(self[name])
- if not isinstance(value, (set, tuple, list)):
- value = [value]
- self.buf += struct.pack(fmt, *value)
- return self
-
- def __getitem__(self, key):
- try:
- return dict.__getitem__(self, key)
- except KeyError:
- if key in self._fields_names:
- return None
- raise
-
-
-class ethmsg(msg):
- fields = (('dst', 'l2addr'),
- ('src', 'l2addr'),
- ('type', 'be16'))
-
-
-class ip4msg(msg):
- fields = (('verlen', 'uint8', 0x45),
- ('dsf', 'uint8'),
- ('len', 'be16'),
- ('id', 'be16'),
- ('flags', 'uint16'),
- ('ttl', 'uint8', 128),
- ('proto', 'uint8'),
- ('csum', 'be16'),
- ('src', 'ip4addr'),
- ('dst', 'ip4addr'))
-
-
-class udp4_pseudo_header(msg):
- fields = (('src', 'ip4addr'),
- ('dst', 'ip4addr'),
- ('pad', 'uint8'),
- ('proto', 'uint8', 17),
- ('len', 'be16'))
-
-
-class udpmsg(msg):
- fields = (('sport', 'be16'),
- ('dport', 'be16'),
- ('len', 'be16'),
- ('csum', 'be16'))
diff --git a/node-admin/scripts/pyroute2/protocols/rawsocket.py b/node-admin/scripts/pyroute2/protocols/rawsocket.py
deleted file mode 100644
index 73348a07407..00000000000
--- a/node-admin/scripts/pyroute2/protocols/rawsocket.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-import struct
-from ctypes import Structure
-from ctypes import addressof
-from ctypes import string_at
-from ctypes import sizeof
-from ctypes import c_ushort
-from ctypes import c_ubyte
-from ctypes import c_uint
-from ctypes import c_void_p
-from socket import socket
-from socket import htons
-from socket import AF_PACKET
-from socket import SOCK_RAW
-from socket import SOL_SOCKET
-from pyroute2 import IPRoute
-
-ETH_P_ALL = 3
-SO_ATTACH_FILTER = 26
-
-
-class sock_filter(Structure):
- _fields_ = [('code', c_ushort), # u16
- ('jt', c_ubyte), # u8
- ('jf', c_ubyte), # u8
- ('k', c_uint)] # u32
-
-
-class sock_fprog(Structure):
- _fields_ = [('len', c_ushort),
- ('filter', c_void_p)]
-
-
-def compile_bpf(code):
- ProgramType = sock_filter * len(code)
- program = ProgramType(*[sock_filter(*line) for line in code])
- sfp = sock_fprog(len(code), addressof(program[0]))
- return string_at(addressof(sfp), sizeof(sfp)), program
-
-
-class RawSocket(socket):
-
- fprog = None
-
- def __init__(self, ifname, bpf=None):
- self.ifname = ifname
- # lookup the interface details
- with IPRoute() as ip:
- for link in ip.get_links():
- if link.get_attr('IFLA_IFNAME') == ifname:
- break
- else:
- raise IOError(2, 'Link not found')
- self.l2addr = link.get_attr('IFLA_ADDRESS')
- self.ifindex = link['index']
- # bring up the socket
- socket.__init__(self, AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
- socket.bind(self, (self.ifname, ETH_P_ALL))
- if bpf:
- fstring, self.fprog = compile_bpf(bpf)
- socket.setsockopt(self, SOL_SOCKET, SO_ATTACH_FILTER, fstring)
-
- def csum(self, data):
- if len(data) % 2:
- data += b'\x00'
- csum = sum([struct.unpack('>H', data[x*2:x*2+2])[0] for x
- in range(len(data)//2)])
- csum = (csum >> 16) + (csum & 0xffff)
- csum += csum >> 16
- return ~csum & 0xffff
diff --git a/node-admin/scripts/pyroute2/proxy.py b/node-admin/scripts/pyroute2/proxy.py
deleted file mode 100644
index bfdab39907d..00000000000
--- a/node-admin/scripts/pyroute2/proxy.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# By Peter V. Saveliev https://pypi.python.org/pypi/pyroute2. Dual licensed under the Apache 2 and GPLv2+ see https://github.com/svinota/pyroute2 for License details.
-'''
-Netlink proxy engine
-'''
-import errno
-import struct
-import logging
-import traceback
-import threading
-
-
-class NetlinkProxy(object):
- '''
- Proxy schemes::
-
- User -> NetlinkProxy -> Kernel
- |
- <---------+
-
- User <- NetlinkProxy <- Kernel
-
- '''
-
- def __init__(self, policy='forward', nl=None, lock=None):
- self.nl = nl
- self.lock = lock or threading.Lock()
- self.pmap = {}
- self.policy = policy
-
- def handle(self, data):
- #
- # match the packet
- #
- ptype = struct.unpack('H', data[4:6])[0]
- plugin = self.pmap.get(ptype, None)
- if plugin is not None:
- with self.lock:
- try:
- ret = plugin(data, self.nl)
- if ret is None:
- msg = struct.pack('IHH', 40, 2, 0)
- msg += data[8:16]
- msg += struct.pack('I', 0)
- # nlmsgerr struct alignment
- msg += b'\0' * 20
- return {'verdict': self.policy,
- 'data': msg}
- else:
- return ret
-
- except Exception as e:
- logging.error(traceback.format_exc())
- # errmsg
- if isinstance(e, (OSError, IOError)):
- code = e.errno
- else:
- code = errno.ECOMM
- msg = struct.pack('HH', 2, 0)
- msg += data[8:16]
- msg += struct.pack('I', code)
- msg += data
- msg = struct.pack('I', len(msg) + 4) + msg
- return {'verdict': 'error',
- 'data': msg}
- return None