# python-networkmanager - Easy communication with NetworkManager # Copyright (C) 2011-2021 Dennis Kaarsemaker # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgement in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. # NetworkManager - a library to make interacting with the NetworkManager daemon # easier. # # (C)2011-2021 Dennis Kaarsemaker # License: zlib import contextlib import copy import dbus import dbus.service import six import socket import struct import time import warnings import xml.etree.ElementTree as ET class ObjectVanished(Exception): def __init__(self, obj): self.obj = obj super(ObjectVanished, self).__init__(obj.object_path) class SignalDispatcher(object): def __init__(self): self.handlers = {} self.args = {} self.interfaces = set() self.setup = False def setup_signals(self): if not self.setup: bus = dbus.SystemBus() for interface in self.interfaces: bus.add_signal_receiver(self.handle_signal, dbus_interface=interface, interface_keyword='interface', member_keyword='signal', path_keyword='path') self.setup = True self.listen_for_restarts() def listen_for_restarts(self): # If we have a mainloop, listen for disconnections if not NMDbusInterface.last_disconnect and dbus.get_default_main_loop(): dbus.SystemBus().add_signal_receiver(self.handle_restart, 'NameOwnerChanged', 'org.freedesktop.DBus') NMDbusInterface.last_disconnect = 1 def add_signal_receiver(self, interface, signal, obj, func, args, kwargs): self.setup_signals() key = (interface, signal) if key not in self.handlers: self.handlers[key] = [] self.handlers[key].append((obj, func, args, kwargs)) def handle_signal(self, *args, **kwargs): key = (kwargs['interface'], kwargs['signal']) skwargs = {} sargs = [] if key not in self.handlers: return try: sender = fixups.base_to_python(kwargs['path']) for arg, (name, signature) in zip(args, self.args[key]): if name: skwargs[name] = fixups.to_python(type(sender).__name__, kwargs['signal'], name, arg, signature) else: # Older NetworkManager versions don't supply attribute names. Hope for the best. sargs.append(fixups.to_python(type(sender).__name__, kwargs['signal'], None, arg, signature)) except dbus.exceptions.DBusException: # This happens if the sender went away. Tough luck, no signal for you. return to_delete = [] for pos, (match, receiver, rargs, rkwargs) in enumerate(self.handlers[key]): try: match == sender except ObjectVanished: to_delete.append(pos) continue if match == sender: rkwargs['interface'] = kwargs['interface'] rkwargs['signal'] = kwargs['signal'] rkwargs.update(skwargs) receiver(sender, *(sargs + rargs), **rkwargs) for pos in reversed(to_delete): self.handlers[key].pop(pos) def handle_restart(self, name, old, new): if not str(new) or str(name) != 'org.freedesktop.NetworkManager': return NMDbusInterface.last_disconnect = time.time() time.sleep(1) # Give NetworkManager a bit of time to start and rediscover itself. for key in self.handlers: val, self.handlers[key] = self.handlers[key], [] for obj, func, args, kwargs in val: with contextlib.suppress(ObjectVanished): # This resets the object path if needed obj.proxy self.add_signal_receiver(key[0], key[1], obj, func, args, kwargs) SignalDispatcher = SignalDispatcher() # We completely dynamically generate all classes using introspection data. As # this is done at import time, use a special dbus connection that does not get # in the way of setting a mainloop and doing async stuff later. init_bus = dbus.SystemBus(private=True) xml_cache = {} class NMDbusInterfaceType(type): """Metaclass that generates our classes based on introspection data""" dbus_service = 'org.freedesktop.NetworkManager' def __new__(cls, name, bases, attrs): attrs['dbus_service'] = cls.dbus_service attrs['properties'] = [] attrs['introspection_data'] = None attrs['signals'] = [] # Derive the interface name from the name of the class, but let classes # override it if needed if 'interface_names' not in attrs and 'NMDbusInterface' not in name: attrs['interface_names'] = [f'org.freedesktop.NetworkManager.{name}'] for base in bases: if hasattr(base, 'interface_names'): attrs['interface_names'] = [ f'{base.interface_names[0]}.{name}' ] + base.interface_names break else: for base in bases: if hasattr(base, 'interface_names'): attrs['interface_names'] += base.interface_names break if 'interface_names' in attrs: SignalDispatcher.interfaces.update(attrs['interface_names']) # If we know where to find this object, let's introspect it and # generate properties and methods if 'object_path' in attrs and attrs['object_path']: proxy = init_bus.get_object(cls.dbus_service, attrs['object_path']) attrs['introspection_data'] = proxy.Introspect(dbus_interface='org.freedesktop.DBus.Introspectable') root = ET.fromstring(attrs['introspection_data']) for element in root: if element.tag == 'interface' and element.attrib['name'] in attrs['interface_names']: for item in element: if item.tag == 'property': attrs[item.attrib['name']] = cls.make_property( name, element.attrib['name'], item.attrib ) attrs['properties'].append(item.attrib['name']) elif item.tag == 'method': aname = item.attrib['name'] if aname in attrs: aname = f'_{aname}' attrs[aname] = cls.make_method( name, element.attrib['name'], item.attrib, list(item), ) elif item.tag == 'signal': SignalDispatcher.args[(element.attrib['name'], item.attrib['name'])] = [ (arg.attrib.get('name', None), arg.attrib['type']) for arg in item] attrs['On' + item.attrib['name']] = cls.make_signal( name, element.attrib['name'], item.attrib ) attrs['signals'].append(item.attrib['name']) return super(NMDbusInterfaceType, cls).__new__(cls, name, bases, attrs) @staticmethod def make_property(cls, interface, attrib): name = attrib['name'] def get_func(self): try: data = self.proxy.Get(interface, name, dbus_interface='org.freedesktop.DBus.Properties') except dbus.exceptions.DBusException as e: if e.get_dbus_name() == 'org.freedesktop.DBus.Error.UnknownMethod': raise ObjectVanished(self) raise return fixups.to_python(cls, 'Get', name, data, attrib['type']) if attrib['access'] == 'read': return property(get_func) def set_func(self, value): value = fixups.to_dbus(cls, 'Set', name, value, attrib['type']) try: return self.proxy.Set(interface, name, value, dbus_interface='org.freedesktop.DBus.Properties') except dbus.exceptions.DBusException as e: if e.get_dbus_name() == 'org.freedesktop.DBus.Error.UnknownMethod': raise ObjectVanished(self) raise return property(get_func, set_func) @staticmethod def make_method(cls, interface, attrib, args): name = attrib['name'] outargs = [x for x in args if x.tag == 'arg' and x.attrib['direction'] == 'out'] outargstr = ', '.join([x.attrib['name'] for x in outargs]) or 'ret' args = [x for x in args if x.tag == 'arg' and x.attrib['direction'] == 'in'] argstr = ', '.join([x.attrib['name'] for x in args]) ret = {} code = "def %s(self%s):\n" % (name, f', {argstr}' if argstr else '') for arg in args: argname = arg.attrib['name'] signature = arg.attrib['type'] code += " %s = fixups.to_dbus('%s', '%s', '%s', %s, '%s')\n" % ( argname, cls, name, argname, argname, signature) code += " try:\n" code += " %s = dbus.Interface(self.proxy, '%s').%s(%s)\n" % (outargstr, interface, name, argstr) code += " except dbus.exceptions.DBusException as e:\n" code += " if e.get_dbus_name() == 'org.freedesktop.DBus.Error.UnknownMethod':\n" code += " raise ObjectVanished(self)\n" code += " raise\n" for arg in outargs: argname = arg.attrib['name'] signature = arg.attrib['type'] code += " %s = fixups.to_python('%s', '%s', '%s', %s, '%s')\n" % ( argname, cls, name, argname, argname, signature) code += f" return ({outargstr})" exec(code, globals(), ret) return ret[name] @staticmethod def make_signal(cls, interface, attrib): name = attrib['name'] ret = {} code = f"def On{name}(self, func, *args, **kwargs):" code += f" SignalDispatcher.add_signal_receiver('{interface}', '{name}', self, func, list(args), kwargs)" exec(code, globals(), ret) return ret[f'On{name}'] @six.add_metaclass(NMDbusInterfaceType) class NMDbusInterface(object): object_path = None last_disconnect = 0 is_transient = False def __new__(cls, object_path=None): # If we didn't introspect this one at definition time, let's do it now. if object_path and not cls.introspection_data: proxy = dbus.SystemBus().get_object(cls.dbus_service, object_path) cls.introspection_data = proxy.Introspect(dbus_interface='org.freedesktop.DBus.Introspectable') root = ET.fromstring(cls.introspection_data) for element in root: if element.tag == 'interface' and element.attrib['name'] in cls.interface_names: for item in element: if item.tag == 'property': setattr(cls, item.attrib['name'], type(cls).make_property(cls.__name__, element.attrib['name'], item.attrib)) cls.properties.append(item.attrib['name']) elif item.tag == 'method': aname = item.attrib['name'] if hasattr(cls, aname): aname = f'_{aname}' setattr(cls, aname, type(cls).make_method(cls.__name__, element.attrib['name'], item.attrib, list(item))) elif item.tag == 'signal': SignalDispatcher.args[(element.attrib['name'], item.attrib['name'])] = [ (arg.attrib.get('name', None), arg.attrib['type']) for arg in item] setattr(cls, 'On' + item.attrib['name'], type(cls).make_signal(cls.__name__, element.attrib['name'], item.attrib)) cls.signals.append(item.attrib['name']) SignalDispatcher.listen_for_restarts() return super(NMDbusInterface, cls).__new__(cls) def __init__(self, object_path=None): if isinstance(object_path, NMDbusInterface): object_path = object_path.object_path self.object_path = self.object_path or object_path self._proxy = None def __eq__(self, other): return isinstance(other, NMDbusInterface) and self.object_path and other.object_path == self.object_path @property def proxy(self): if not self._proxy: self._proxy = dbus.SystemBus().get_object(self.dbus_service, self.object_path, follow_name_owner_changes=True) self._proxy.created = time.time() elif self._proxy.created < self.last_disconnect: if self.is_transient: raise ObjectVanished(self) obj = type(self)(self.object_path) if obj.object_path != self.object_path: self.object_path = obj.object_path self._proxy = dbus.SystemBus().get_object(self.dbus_service, self.object_path) self._proxy.created = time.time() return self._proxy # Backwards compatibility interface def connect_to_signal(self, signal, handler, *args, **kwargs): return getattr(self, f'On{signal}')(handler, *args, **kwargs) class TransientNMDbusInterface(NMDbusInterface): is_transient = True class NetworkManager(NMDbusInterface): interface_names = ['org.freedesktop.NetworkManager'] object_path = '/org/freedesktop/NetworkManager' # noop method for backward compatibility. It is no longer necessary to call # this but let's not break code that does so. def auto_reconnect(self): pass class Statistics(NMDbusInterface): object_path = '/org/freedesktop/NetworkManager/Statistics' class Settings(NMDbusInterface): object_path = '/org/freedesktop/NetworkManager/Settings' class AgentManager(NMDbusInterface): object_path = '/org/freedesktop/NetworkManager/AgentManager' class Connection(NMDbusInterface): interface_names = ['org.freedesktop.NetworkManager.Settings.Connection'] has_secrets = ['802-1x', '802-11-wireless-security', 'cdma', 'gsm', 'pppoe', 'vpn'] def __init__(self, object_path): super(Connection, self).__init__(object_path) self.uuid = self.GetSettings()['connection']['uuid'] def GetSecrets(self, name=None): settings = self.GetSettings() if name is None: name = settings['connection']['type'] name = settings[name].get('security', name) try: return self._GetSecrets(name) except dbus.exceptions.DBusException as e: if e.get_dbus_name() != 'org.freedesktop.NetworkManager.AgentManager.NoSecrets': raise return {key: {} for key in settings} @staticmethod def all(): return Settings.ListConnections() def __eq__(self, other): return isinstance(other, type(self)) and self.uuid == other.uuid class ActiveConnection(TransientNMDbusInterface): interface_names = ['org.freedesktop.NetworkManager.Connection.Active'] def __new__(cls, object_path): if cls == ActiveConnection: # Automatically turn this into a VPNConnection if needed obj = dbus.SystemBus().get_object(cls.dbus_service, object_path) if obj.Get('org.freedesktop.NetworkManager.Connection.Active', 'Vpn', dbus_interface='org.freedesktop.DBus.Properties'): return VPNConnection.__new__(VPNConnection, object_path) return super(ActiveConnection, cls).__new__(cls, object_path) def __eq__(self, other): return isinstance(other, type(self)) and self.Uuid == other.Uuid class VPNConnection(ActiveConnection): interface_names = ['org.freedesktop.NetworkManager.VPN.Connection'] class Device(NMDbusInterface): interface_names = ['org.freedesktop.NetworkManager.Device', 'org.freedesktop.NetworkManager.Device.Statistics'] def __new__(cls, object_path): if cls == Device: # Automatically specialize the device with contextlib.suppress(ObjectVanished): obj = dbus.SystemBus().get_object(cls.dbus_service, object_path) cls = device_class(obj.Get('org.freedesktop.NetworkManager.Device', 'DeviceType', dbus_interface='org.freedesktop.DBus.Properties')) return cls.__new__(cls, object_path) return super(Device, cls).__new__(cls, object_path) @staticmethod def all(): return NetworkManager.Devices def __eq__(self, other): return isinstance(other, type(self)) and self.IpInterface == other.IpInterface # Backwards compatibility method. Devices now auto-specialize, so this is # no longer needed. But code may use it. def SpecificDevice(self): return self def device_class(typ): return { NM_DEVICE_TYPE_ADSL: Adsl, NM_DEVICE_TYPE_BOND: Bond, NM_DEVICE_TYPE_BRIDGE: Bridge, NM_DEVICE_TYPE_BT: Bluetooth, NM_DEVICE_TYPE_ETHERNET: Wired, NM_DEVICE_TYPE_GENERIC: Generic, NM_DEVICE_TYPE_INFINIBAND: Infiniband, NM_DEVICE_TYPE_IP_TUNNEL: IPTunnel, NM_DEVICE_TYPE_MACVLAN: Macvlan, NM_DEVICE_TYPE_MODEM: Modem, NM_DEVICE_TYPE_OLPC_MESH: OlpcMesh, NM_DEVICE_TYPE_TEAM: Team, NM_DEVICE_TYPE_TUN: Tun, NM_DEVICE_TYPE_VETH: Veth, NM_DEVICE_TYPE_VLAN: Vlan, NM_DEVICE_TYPE_VXLAN: Vxlan, NM_DEVICE_TYPE_WIFI: Wireless, NM_DEVICE_TYPE_WIMAX: Wimax, NM_DEVICE_TYPE_MACSEC: MacSec, NM_DEVICE_TYPE_DUMMY: Dummy, NM_DEVICE_TYPE_PPP: PPP, NM_DEVICE_TYPE_OVS_INTERFACE: OvsIf, NM_DEVICE_TYPE_OVS_PORT: OvsPort, NM_DEVICE_TYPE_OVS_BRIDGE: OvsBridge, NM_DEVICE_TYPE_WPAN: Wpan, NM_DEVICE_TYPE_6LOWPAN: SixLoWpan, NM_DEVICE_TYPE_WIREGUARD: WireGuard, NM_DEVICE_TYPE_VRF: Vrf, NM_DEVICE_TYPE_WIFI_P2P: WifiP2p, }[typ] class Adsl(Device): pass class Bluetooth(Device): pass class Bond(Device): pass class Bridge(Device): pass class Generic(Device): pass class Infiniband(Device): pass class IPTunnel(Device): pass class Macvlan(Device): pass class Modem(Device): pass class OlpcMesh(Device): pass class Team(Device): pass class Tun(Device): pass class Veth(Device): pass class Vlan(Device): pass class Vxlan(Device): pass class Wimax(Device): pass class Wired(Device): pass class Wireless(Device): pass class MacSec(Device): pass class Dummy(Device): pass class PPP(Device): pass class OvsIf(Device): pass class OvsPort(Device): pass class OvsBridge(Device): pass class Wpan(Device): pass class SixLoWpan(Device): pass class WireGuard(Device): pass class WifiP2p(Device): pass class Vrf(Device): pass class NSP(TransientNMDbusInterface): interface_names = ['org.freedesktop.NetworkManager.Wimax.NSP'] class AccessPoint(NMDbusInterface): @staticmethod def all(): for device in Device.all(): if isinstance(device, Wireless): yield from device.AccessPoints def __eq__(self, other): return isinstance(other, type(self)) and self.HwAddress == other.HwAddress class IP4Config(TransientNMDbusInterface): pass class IP6Config(TransientNMDbusInterface): pass class DHCP4Config(TransientNMDbusInterface): pass class DHCP6Config(TransientNMDbusInterface): pass # Evil hack to work around not being able to specify a method name in the # dbus.service.method decorator. class SecretAgentType(type(dbus.service.Object)): def __new__(cls, name, bases, attrs): if bases != (dbus.service.Object,): attrs['GetSecretsImpl'] = attrs.pop('GetSecrets') return super(SecretAgentType, cls).__new__(cls, name, bases, attrs) @six.add_metaclass(SecretAgentType) class SecretAgent(dbus.service.Object): object_path = '/org/freedesktop/NetworkManager/SecretAgent' interface_name = 'org.freedesktop.NetworkManager.SecretAgent' def __init__(self, identifier): self.identifier = identifier dbus.service.Object.__init__(self, dbus.SystemBus(), self.object_path) AgentManager.Register(self.identifier) @dbus.service.method(dbus_interface=interface_name, in_signature='a{sa{sv}}osasu', out_signature='a{sa{sv}}') def GetSecrets(self, connection, connection_path, setting_name, hints, flags): settings = fixups.to_python('SecretAgent', 'GetSecrets', 'connection', connection, 'a{sa{sv}}') connection = fixups.to_python('SecretAgent', 'GetSecrets', 'connection_path', connection_path, 'o') setting_name = fixups.to_python('SecretAgent', 'GetSecrets', 'setting_name', setting_name, 's') hints = fixups.to_python('SecretAgent', 'GetSecrets', 'hints', hints, 'as') return self.GetSecretsImpl(settings, connection, setting_name, hints, flags) # These two are interfaces that must be provided to NetworkManager. Keep them # as comments for documentation purposes. # # class PPP(NMDbusInterface): pass # class VPNPlugin(NMDbusInterface): # interface_names = ['org.freedesktop.NetworkManager.VPN.Plugin'] def const(prefix, val): prefix = f'NM_{prefix.upper()}_' for key, vval in globals().items(): if 'REASON' in key and 'REASON' not in prefix: continue if key.startswith(prefix) and val == vval: return key.replace(prefix, '').lower() raise ValueError("No constant found for %s* with value %d", (prefix, val)) # Several fixer methods to make the data easier to handle in python # - SSID sent/returned as bytes (only encoding tried is utf-8) # - IP, Mac address and route metric encoding/decoding class fixups(object): @staticmethod def to_dbus(cls, method, arg, val, signature): if arg in 'connection' 'properties' and signature == 'a{sa{sv}}': settings = copy.deepcopy(val) for key in settings: if 'mac-address' in settings[key]: settings[key]['mac-address'] = fixups.mac_to_dbus(settings[key]['mac-address']) if 'cloned-mac-address' in settings[key]: settings[key]['cloned-mac-address'] = fixups.mac_to_dbus(settings[key]['cloned-mac-address']) if 'bssid' in settings[key]: settings[key]['bssid'] = fixups.mac_to_dbus(settings[key]['bssid']) for cert in ['ca-cert', 'client-cert', 'phase2-ca-cert', 'phase2-client-cert', 'private-key']: if cert in settings[key]: settings[key][cert] = fixups.cert_to_dbus(settings[key][cert]) if 'routing-rules' in settings[key]: for rule in settings[key]['routing-rules']: for p in rule: rule[p] = dbus.Int32(rule[p]) if p == 'family' else dbus.UInt32(rule[p]) settings[key]['routing-rules'] = dbus.Array( settings[key]['routing-rules'], signature=dbus.Signature('a{sv}')) if 'ssid' in settings.get('802-11-wireless', {}): settings['802-11-wireless']['ssid'] = fixups.ssid_to_dbus(settings['802-11-wireless']['ssid']) with contextlib.suppress(KeyError): val['ipv4']['addresses'] = [fixups.addrconf_to_python(addr, socket.AF_INET) for addr in val['ipv4']['addresses']] val['ipv4']['routes'] = [fixups.route_to_python(route, socket.AF_INET) for route in val['ipv4']['routes']] val['ipv4']['dns'] = [fixups.addr_to_python(addr, socket.AF_INET) for addr in val['ipv4']['dns']] val['ipv6']['addresses'] = [fixups.addrconf_to_python(addr, socket.AF_INET6) for addr in val['ipv6']['addresses']] val['ipv6']['routes'] = [fixups.route_to_python(route, socket.AF_INET6) for route in val['ipv6']['routes']] val['ipv6']['dns'] = [fixups.addr_to_python(addr, socket.AF_INET6) for addr in val['ipv6']['dns']] # Get rid of empty arrays/dicts. dbus barfs on them (can't guess # signatures), and if they were to get through, NetworkManager # ignores them anyway. for key in list(settings.keys()): if isinstance(settings[key], dict): for key2 in list(settings[key].keys()): if settings[key][key2] in ({}, []): del settings[key][key2] if settings[key] in ({}, []): del settings[key] val = settings return fixups.base_to_dbus(val) @staticmethod def base_to_dbus(val): if isinstance(val, NMDbusInterface): return val.object_path if hasattr(val.__class__, 'mro'): for cls in val.__class__.mro(): if cls.__module__ in ('dbus', '_dbus_bindings'): return val if hasattr(val, '__iter__') and not isinstance(val, six.string_types): if hasattr(val, 'items'): return dict([(x, fixups.base_to_dbus(y)) for x, y in val.items()]) else: return [fixups.base_to_dbus(x) for x in val] return val @staticmethod def to_python(cls, method, arg, val, signature): val = fixups.base_to_python(val) cls_af = {'IP4Config': socket.AF_INET, 'IP6Config': socket.AF_INET6}.get(cls, socket.AF_INET) if method == 'Get': if arg == 'Ip4Address': return fixups.addr_to_python(val, socket.AF_INET) if arg == 'Ip6Address': return fixups.addr_to_python(val, socket.AF_INET6) if arg == 'Ssid': return fixups.ssid_to_python(val) if arg == 'Strength': return fixups.strength_to_python(val) if arg == 'Addresses': return [fixups.addrconf_to_python(addr, cls_af) for addr in val] if arg == 'Routes': return [fixups.route_to_python(route, cls_af) for route in val] if arg in ('Nameservers', 'WinsServers'): return [fixups.addr_to_python(addr, cls_af) for addr in val] if arg == 'Options': for key in val: if key.startswith('requested_'): val[key] = bool(int(val[key])) elif val[key].isdigit(): val[key] = int(val[key]) elif key in ('domain_name_servers', 'ntp_servers', 'routers'): val[key] = val[key].split() return val if method == 'GetSettings': if 'ssid' in val.get('802-11-wireless', {}): val['802-11-wireless']['ssid'] = fixups.ssid_to_python(val['802-11-wireless']['ssid']) for key in val: val_ = val[key] if 'mac-address' in val_: val_['mac-address'] = fixups.mac_to_python(val_['mac-address']) if 'cloned-mac-address' in val_: val_['cloned-mac-address'] = fixups.mac_to_python(val_['cloned-mac-address']) if 'bssid' in val_: val_['bssid'] = fixups.mac_to_python(val_['bssid']) if 'ipv4' in val: if 'addresses' in val['ipv4']: val['ipv4']['addresses'] = [fixups.addrconf_to_python(addr, socket.AF_INET) for addr in val['ipv4']['addresses']] if 'routes' in val['ipv4']: val['ipv4']['routes'] = [fixups.route_to_python(route, socket.AF_INET) for route in val['ipv4']['routes']] if 'dns' in val['ipv4']: val['ipv4']['dns'] = [fixups.addr_to_python(addr, socket.AF_INET) for addr in val['ipv4']['dns']] if 'ipv6' in val: if 'addresses' in val['ipv6']: val['ipv6']['addresses'] = [fixups.addrconf_to_python(addr, socket.AF_INET6) for addr in val['ipv6']['addresses']] if 'routes' in val['ipv6']: val['ipv6']['routes'] = [fixups.route_to_python(route, socket.AF_INET6) for route in val['ipv6']['routes']] if 'dns' in val['ipv6']: val['ipv6']['dns'] = [fixups.addr_to_python(addr, socket.AF_INET6) for addr in val['ipv6']['dns']] return val if method == 'PropertiesChanged': for prop in val: val[prop] = fixups.to_python(cls, 'Get', prop, val[prop], None) return val @staticmethod def base_to_python(val): if isinstance(val, dbus.ByteArray): return "".join([str(x) for x in val]) if isinstance(val, (dbus.Array, list, tuple)): return [fixups.base_to_python(x) for x in val] if isinstance(val, (dbus.Dictionary, dict)): return dict([(fixups.base_to_python(x), fixups.base_to_python(y)) for x, y in val.items()]) if isinstance(val, dbus.ObjectPath): for obj in (NetworkManager, Settings, AgentManager): if val == obj.object_path: return obj if val.startswith('/org/freedesktop/NetworkManager/'): classname = val.split('/')[4] classname = { 'Settings': 'Connection', 'Devices': 'Device', }.get(classname, classname) return globals()[classname](val) if val == '/': return None if isinstance(val, (dbus.Signature, dbus.String)): return six.text_type(val) if isinstance(val, dbus.Boolean): return bool(val) if isinstance(val, (dbus.Int16, dbus.UInt16, dbus.Int32, dbus.UInt32, dbus.Int64, dbus.UInt64)): return int(val) return six.int2byte(int(val)) if isinstance(val, dbus.Byte) else val @staticmethod def ssid_to_python(ssid): try: return bytes().join(ssid).decode('utf-8') except UnicodeDecodeError: ssid = bytes().join(ssid).decode('utf-8', 'replace') warnings.warn(f"Unable to decode ssid {ssid} properly", UnicodeWarning) return ssid @staticmethod def ssid_to_dbus(ssid): if isinstance(ssid, six.text_type): ssid = ssid.encode('utf-8') return [dbus.Byte(x) for x in ssid] @staticmethod def strength_to_python(strength): return struct.unpack('B', strength)[0] @staticmethod def mac_to_python(mac): return "%02X:%02X:%02X:%02X:%02X:%02X" % tuple(ord(x) for x in mac) @staticmethod def mac_to_dbus(mac): return [dbus.Byte(int(x, 16)) for x in mac.split(':')] @staticmethod def addrconf_to_python(addrconf, family): addr, netmask, gateway = addrconf return [ fixups.addr_to_python(addr, family), netmask, fixups.addr_to_python(gateway, family) ] @staticmethod def addrconf_to_dbus(addrconf, family): addr, netmask, gateway = addrconf if family == socket.AF_INET: return [ fixups.addr_to_dbus(addr, family), fixups.mask_to_dbus(netmask), fixups.addr_to_dbus(gateway, family) ] else: return dbus.Struct( ( fixups.addr_to_dbus(addr, family), fixups.mask_to_dbus(netmask), fixups.addr_to_dbus(gateway, family) ), signature='ayuay' ) @staticmethod def addr_to_python(addr, family): if family == socket.AF_INET: return socket.inet_ntop(family, struct.pack('I', addr)) else: return socket.inet_ntop(family, b''.join(addr)) @staticmethod def addr_to_dbus(addr, family): if family == socket.AF_INET: return dbus.UInt32(struct.unpack('I', socket.inet_pton(family, addr))[0]) else: return dbus.ByteArray(socket.inet_pton(family, addr)) @staticmethod def mask_to_dbus(mask): return dbus.UInt32(mask) @staticmethod def route_to_python(route, family): addr, netmask, gateway, metric = route return [ fixups.addr_to_python(addr, family), netmask, fixups.addr_to_python(gateway, family), metric ] @staticmethod def route_to_dbus(route, family): addr, netmask, gateway, metric = route return [ fixups.addr_to_dbus(addr, family), fixups.mask_to_dbus(netmask), fixups.addr_to_dbus(gateway, family), metric ] @staticmethod def cert_to_dbus(cert): if not isinstance(cert, bytes): if not cert.startswith('file://'): cert = f'file://{cert}' cert = cert.encode('utf-8') + b'\0' return [dbus.Byte(x) for x in cert] # Turn NetworkManager and Settings into singleton objects NetworkManager = NetworkManager() Settings = Settings() AgentManager = AgentManager() init_bus.close() del init_bus del xml_cache # Constants below are generated with makeconstants.py. Do not edit manually. NM_CAPABILITY_TEAM = 1 NM_CAPABILITY_OVS = 2 NM_STATE_UNKNOWN = 0 NM_STATE_ASLEEP = 10 NM_STATE_DISCONNECTED = 20 NM_STATE_DISCONNECTING = 30 NM_STATE_CONNECTING = 40 NM_STATE_CONNECTED_LOCAL = 50 NM_STATE_CONNECTED_SITE = 60 NM_STATE_CONNECTED_GLOBAL = 70 NM_CONNECTIVITY_UNKNOWN = 0 NM_CONNECTIVITY_NONE = 1 NM_CONNECTIVITY_PORTAL = 2 NM_CONNECTIVITY_LIMITED = 3 NM_CONNECTIVITY_FULL = 4 NM_DEVICE_TYPE_UNKNOWN = 0 NM_DEVICE_TYPE_ETHERNET = 1 NM_DEVICE_TYPE_WIFI = 2 NM_DEVICE_TYPE_UNUSED1 = 3 NM_DEVICE_TYPE_UNUSED2 = 4 NM_DEVICE_TYPE_BT = 5 NM_DEVICE_TYPE_OLPC_MESH = 6 NM_DEVICE_TYPE_WIMAX = 7 NM_DEVICE_TYPE_MODEM = 8 NM_DEVICE_TYPE_INFINIBAND = 9 NM_DEVICE_TYPE_BOND = 10 NM_DEVICE_TYPE_VLAN = 11 NM_DEVICE_TYPE_ADSL = 12 NM_DEVICE_TYPE_BRIDGE = 13 NM_DEVICE_TYPE_GENERIC = 14 NM_DEVICE_TYPE_TEAM = 15 NM_DEVICE_TYPE_TUN = 16 NM_DEVICE_TYPE_IP_TUNNEL = 17 NM_DEVICE_TYPE_MACVLAN = 18 NM_DEVICE_TYPE_VXLAN = 19 NM_DEVICE_TYPE_VETH = 20 NM_DEVICE_TYPE_MACSEC = 21 NM_DEVICE_TYPE_DUMMY = 22 NM_DEVICE_TYPE_PPP = 23 NM_DEVICE_TYPE_OVS_INTERFACE = 24 NM_DEVICE_TYPE_OVS_PORT = 25 NM_DEVICE_TYPE_OVS_BRIDGE = 26 NM_DEVICE_TYPE_WPAN = 27 NM_DEVICE_TYPE_6LOWPAN = 28 NM_DEVICE_TYPE_WIREGUARD = 29 NM_DEVICE_TYPE_WIFI_P2P = 30 NM_DEVICE_TYPE_VRF = 31 NM_DEVICE_CAP_NONE = 0 NM_DEVICE_CAP_NM_SUPPORTED = 1 NM_DEVICE_CAP_CARRIER_DETECT = 2 NM_DEVICE_CAP_IS_SOFTWARE = 4 NM_DEVICE_CAP_SRIOV = 8 NM_WIFI_DEVICE_CAP_NONE = 0 NM_WIFI_DEVICE_CAP_CIPHER_WEP40 = 1 NM_WIFI_DEVICE_CAP_CIPHER_WEP104 = 2 NM_WIFI_DEVICE_CAP_CIPHER_TKIP = 4 NM_WIFI_DEVICE_CAP_CIPHER_CCMP = 8 NM_WIFI_DEVICE_CAP_WPA = 16 NM_WIFI_DEVICE_CAP_RSN = 32 NM_WIFI_DEVICE_CAP_AP = 64 NM_WIFI_DEVICE_CAP_ADHOC = 128 NM_WIFI_DEVICE_CAP_FREQ_VALID = 256 NM_WIFI_DEVICE_CAP_FREQ_2GHZ = 512 NM_WIFI_DEVICE_CAP_FREQ_5GHZ = 1024 NM_WIFI_DEVICE_CAP_MESH = 4096 NM_WIFI_DEVICE_CAP_IBSS_RSN = 8192 NM_802_11_AP_FLAGS_NONE = 0 NM_802_11_AP_FLAGS_PRIVACY = 1 NM_802_11_AP_FLAGS_WPS = 2 NM_802_11_AP_FLAGS_WPS_PBC = 4 NM_802_11_AP_FLAGS_WPS_PIN = 8 NM_802_11_AP_SEC_NONE = 0 NM_802_11_AP_SEC_PAIR_WEP40 = 1 NM_802_11_AP_SEC_PAIR_WEP104 = 2 NM_802_11_AP_SEC_PAIR_TKIP = 4 NM_802_11_AP_SEC_PAIR_CCMP = 8 NM_802_11_AP_SEC_GROUP_WEP40 = 16 NM_802_11_AP_SEC_GROUP_WEP104 = 32 NM_802_11_AP_SEC_GROUP_TKIP = 64 NM_802_11_AP_SEC_GROUP_CCMP = 128 NM_802_11_AP_SEC_KEY_MGMT_PSK = 256 NM_802_11_AP_SEC_KEY_MGMT_802_1X = 512 NM_802_11_AP_SEC_KEY_MGMT_SAE = 1024 NM_802_11_AP_SEC_KEY_MGMT_OWE = 2048 NM_802_11_AP_SEC_KEY_MGMT_OWE_TM = 4096 NM_802_11_MODE_UNKNOWN = 0 NM_802_11_MODE_ADHOC = 1 NM_802_11_MODE_INFRA = 2 NM_802_11_MODE_AP = 3 NM_802_11_MODE_MESH = 4 NM_BT_CAPABILITY_NONE = 0 NM_BT_CAPABILITY_DUN = 1 NM_BT_CAPABILITY_NAP = 2 NM_DEVICE_MODEM_CAPABILITY_NONE = 0 NM_DEVICE_MODEM_CAPABILITY_POTS = 1 NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO = 2 NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS = 4 NM_DEVICE_MODEM_CAPABILITY_LTE = 8 NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN = 0 NM_WIMAX_NSP_NETWORK_TYPE_HOME = 1 NM_WIMAX_NSP_NETWORK_TYPE_PARTNER = 2 NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER = 3 NM_DEVICE_STATE_UNKNOWN = 0 NM_DEVICE_STATE_UNMANAGED = 10 NM_DEVICE_STATE_UNAVAILABLE = 20 NM_DEVICE_STATE_DISCONNECTED = 30 NM_DEVICE_STATE_PREPARE = 40 NM_DEVICE_STATE_CONFIG = 50 NM_DEVICE_STATE_NEED_AUTH = 60 NM_DEVICE_STATE_IP_CONFIG = 70 NM_DEVICE_STATE_IP_CHECK = 80 NM_DEVICE_STATE_SECONDARIES = 90 NM_DEVICE_STATE_ACTIVATED = 100 NM_DEVICE_STATE_DEACTIVATING = 110 NM_DEVICE_STATE_FAILED = 120 NM_DEVICE_STATE_REASON_NONE = 0 NM_DEVICE_STATE_REASON_UNKNOWN = 1 NM_DEVICE_STATE_REASON_NOW_MANAGED = 2 NM_DEVICE_STATE_REASON_NOW_UNMANAGED = 3 NM_DEVICE_STATE_REASON_CONFIG_FAILED = 4 NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE = 5 NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED = 6 NM_DEVICE_STATE_REASON_NO_SECRETS = 7 NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8 NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED = 9 NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED = 10 NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT = 11 NM_DEVICE_STATE_REASON_PPP_START_FAILED = 12 NM_DEVICE_STATE_REASON_PPP_DISCONNECT = 13 NM_DEVICE_STATE_REASON_PPP_FAILED = 14 NM_DEVICE_STATE_REASON_DHCP_START_FAILED = 15 NM_DEVICE_STATE_REASON_DHCP_ERROR = 16 NM_DEVICE_STATE_REASON_DHCP_FAILED = 17 NM_DEVICE_STATE_REASON_SHARED_START_FAILED = 18 NM_DEVICE_STATE_REASON_SHARED_FAILED = 19 NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED = 20 NM_DEVICE_STATE_REASON_AUTOIP_ERROR = 21 NM_DEVICE_STATE_REASON_AUTOIP_FAILED = 22 NM_DEVICE_STATE_REASON_MODEM_BUSY = 23 NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE = 24 NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER = 25 NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT = 26 NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED = 27 NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED = 28 NM_DEVICE_STATE_REASON_GSM_APN_FAILED = 29 NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING = 30 NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED = 31 NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT = 32 NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED = 33 NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED = 34 NM_DEVICE_STATE_REASON_FIRMWARE_MISSING = 35 NM_DEVICE_STATE_REASON_REMOVED = 36 NM_DEVICE_STATE_REASON_SLEEPING = 37 NM_DEVICE_STATE_REASON_CONNECTION_REMOVED = 38 NM_DEVICE_STATE_REASON_USER_REQUESTED = 39 NM_DEVICE_STATE_REASON_CARRIER = 40 NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED = 41 NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE = 42 NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND = 43 NM_DEVICE_STATE_REASON_BT_FAILED = 44 NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED = 45 NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED = 46 NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED = 47 NM_DEVICE_STATE_REASON_GSM_SIM_WRONG = 48 NM_DEVICE_STATE_REASON_INFINIBAND_MODE = 49 NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED = 50 NM_DEVICE_STATE_REASON_BR2684_FAILED = 51 NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE = 52 NM_DEVICE_STATE_REASON_SSID_NOT_FOUND = 53 NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED = 54 NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED = 55 NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED = 56 NM_DEVICE_STATE_REASON_MODEM_FAILED = 57 NM_DEVICE_STATE_REASON_MODEM_AVAILABLE = 58 NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT = 59 NM_DEVICE_STATE_REASON_NEW_ACTIVATION = 60 NM_DEVICE_STATE_REASON_PARENT_CHANGED = 61 NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED = 62 NM_DEVICE_STATE_REASON_OVSDB_FAILED = 63 NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE = 64 NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED = 65 NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED = 66 NM_DEVICE_STATE_REASON_PEER_NOT_FOUND = 67 NM_METERED_UNKNOWN = 0 NM_METERED_YES = 1 NM_METERED_NO = 2 NM_METERED_GUESS_YES = 3 NM_METERED_GUESS_NO = 4 NM_CONNECTION_MULTI_CONNECT_DEFAULT = 0 NM_CONNECTION_MULTI_CONNECT_SINGLE = 1 NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE = 2 NM_CONNECTION_MULTI_CONNECT_MULTIPLE = 3 NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0 NM_ACTIVE_CONNECTION_STATE_ACTIVATING = 1 NM_ACTIVE_CONNECTION_STATE_ACTIVATED = 2 NM_ACTIVE_CONNECTION_STATE_DEACTIVATING = 3 NM_ACTIVE_CONNECTION_STATE_DEACTIVATED = 4 NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN = 0 NM_ACTIVE_CONNECTION_STATE_REASON_NONE = 1 NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED = 2 NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED = 3 NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED = 4 NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID = 5 NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT = 6 NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT = 7 NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED = 8 NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS = 9 NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED = 10 NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED = 11 NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED = 12 NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED = 13 NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED = 14 NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE = 0 NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION = 1 NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW = 2 NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED = 4 NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE = 8 NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM = 2147483648 NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS = 1073741824 NM_IP_TUNNEL_MODE_UNKNOWN = 0 NM_IP_TUNNEL_MODE_IPIP = 1 NM_IP_TUNNEL_MODE_GRE = 2 NM_IP_TUNNEL_MODE_SIT = 3 NM_IP_TUNNEL_MODE_ISATAP = 4 NM_IP_TUNNEL_MODE_VTI = 5 NM_IP_TUNNEL_MODE_IP6IP6 = 6 NM_IP_TUNNEL_MODE_IPIP6 = 7 NM_IP_TUNNEL_MODE_IP6GRE = 8 NM_IP_TUNNEL_MODE_VTI6 = 9 NM_IP_TUNNEL_MODE_GRETAP = 10 NM_IP_TUNNEL_MODE_IP6GRETAP = 11 NM_CHECKPOINT_CREATE_FLAG_NONE = 0 NM_CHECKPOINT_CREATE_FLAG_DESTROY_ALL = 1 NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS = 2 NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES = 4 NM_CHECKPOINT_CREATE_FLAG_ALLOW_OVERLAPPING = 8 NM_ROLLBACK_RESULT_OK = 0 NM_ROLLBACK_RESULT_ERR_NO_DEVICE = 1 NM_ROLLBACK_RESULT_ERR_DEVICE_UNMANAGED = 2 NM_ROLLBACK_RESULT_ERR_FAILED = 3 NM_SETTINGS_CONNECTION_FLAG_NONE = 0 NM_SETTINGS_CONNECTION_FLAG_UNSAVED = 1 NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED = 2 NM_SETTINGS_CONNECTION_FLAG_VOLATILE = 4 NM_SETTINGS_CONNECTION_FLAG_EXTERNAL = 8 NM_ACTIVATION_STATE_FLAG_NONE = 0 NM_ACTIVATION_STATE_FLAG_IS_MASTER = 1 NM_ACTIVATION_STATE_FLAG_IS_SLAVE = 2 NM_ACTIVATION_STATE_FLAG_LAYER2_READY = 4 NM_ACTIVATION_STATE_FLAG_IP4_READY = 8 NM_ACTIVATION_STATE_FLAG_IP6_READY = 16 NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES = 32 NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY = 64 NM_ACTIVATION_STATE_FLAG_EXTERNAL = 128 NM_SETTINGS_ADD_CONNECTION2_FLAG_NONE = 0 NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK = 1 NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY = 2 NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT = 32 NM_SETTINGS_UPDATE2_FLAG_NONE = 0 NM_SETTINGS_UPDATE2_FLAG_TO_DISK = 1 NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY = 2 NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED = 4 NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY = 8 NM_SETTINGS_UPDATE2_FLAG_VOLATILE = 16 NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT = 32 NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY = 64 NM_TERNARY_DEFAULT = -1 NM_TERNARY_FALSE = 0 NM_TERNARY_TRUE = 1 NM_MANAGER_RELOAD_FLAG_NONE = 0 NM_MANAGER_RELOAD_FLAG_CONF = 1 NM_MANAGER_RELOAD_FLAG_DNS_RC = 2 NM_MANAGER_RELOAD_FLAG_DNS_FULL = 4 NM_MANAGER_RELOAD_FLAG_ALL = 7 NM_DEVICE_INTERFACE_FLAG_NONE = 0 NM_DEVICE_INTERFACE_FLAG_UP = 1 NM_DEVICE_INTERFACE_FLAG_LOWER_UP = 2 NM_DEVICE_INTERFACE_FLAG_CARRIER = 65536 NM_CLIENT_PERMISSION_NONE = 0 NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK = 1 NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI = 2 NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN = 3 NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX = 4 NM_CLIENT_PERMISSION_SLEEP_WAKE = 5 NM_CLIENT_PERMISSION_NETWORK_CONTROL = 6 NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED = 7 NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN = 8 NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM = 9 NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN = 10 NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME = 11 NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS = 12 NM_CLIENT_PERMISSION_RELOAD = 13 NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK = 14 NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS = 15 NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK = 16 NM_CLIENT_PERMISSION_WIFI_SCAN = 17 NM_CLIENT_PERMISSION_LAST = 17 NM_CLIENT_PERMISSION_RESULT_UNKNOWN = 0 NM_CLIENT_PERMISSION_RESULT_YES = 1 NM_CLIENT_PERMISSION_RESULT_AUTH = 2 NM_CLIENT_PERMISSION_RESULT_NO = 3 NM_VPN_SERVICE_STATE_UNKNOWN = 0 NM_VPN_SERVICE_STATE_INIT = 1 NM_VPN_SERVICE_STATE_SHUTDOWN = 2 NM_VPN_SERVICE_STATE_STARTING = 3 NM_VPN_SERVICE_STATE_STARTED = 4 NM_VPN_SERVICE_STATE_STOPPING = 5 NM_VPN_SERVICE_STATE_STOPPED = 6 NM_VPN_CONNECTION_STATE_UNKNOWN = 0 NM_VPN_CONNECTION_STATE_PREPARE = 1 NM_VPN_CONNECTION_STATE_NEED_AUTH = 2 NM_VPN_CONNECTION_STATE_CONNECT = 3 NM_VPN_CONNECTION_STATE_IP_CONFIG_GET = 4 NM_VPN_CONNECTION_STATE_ACTIVATED = 5 NM_VPN_CONNECTION_STATE_FAILED = 6 NM_VPN_CONNECTION_STATE_DISCONNECTED = 7 NM_VPN_CONNECTION_STATE_REASON_UNKNOWN = 0 NM_VPN_CONNECTION_STATE_REASON_NONE = 1 NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED = 2 NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED = 3 NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED = 4 NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID = 5 NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT = 6 NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT = 7 NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED = 8 NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS = 9 NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED = 10 NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED = 11 NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED = 0 NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED = 1 NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG = 2 NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED = 0 NM_SECRET_AGENT_ERROR_INVALID_CONNECTION = 1 NM_SECRET_AGENT_ERROR_USER_CANCELED = 2 NM_SECRET_AGENT_ERROR_AGENT_CANCELED = 3 NM_SECRET_AGENT_ERROR_INTERNAL_ERROR = 4 NM_SECRET_AGENT_ERROR_NO_SECRETS = 5