summary refs log tree commit diff
path: root/tools
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2016-01-20 16:26:51 +0100
committerMichael Biebl <biebl@debian.org>2016-01-20 16:26:51 +0100
commit494f296a3baab08522617b24b1f126d8f9a17502 (patch)
treec8ef32fb0dd1c4ff35a0b38e787abb58692de0cd /tools
parent54f6333410ffd570e62717d9e77c5c987175e397 (diff)
Imported Upstream version 1.1.90 upstream/1.1.90
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile.in18
-rwxr-xr-xtools/check-exports.sh4
-rwxr-xr-xtools/test-networkmanager-service.py203
3 files changed, 151 insertions, 74 deletions
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 4236d5f2..0c4078a3 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -146,7 +146,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CKDB_PATH = @CKDB_PATH@
 CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
 CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
 CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
@@ -158,8 +157,6 @@ CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DBUS_CFLAGS = @DBUS_CFLAGS@
-DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
-DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
 DBUS_LIBS = @DBUS_LIBS@
 DBUS_SYS_DIR = @DBUS_SYS_DIR@
 DEFS = @DEFS@
@@ -169,6 +166,7 @@ DHCPCD_PATH = @DHCPCD_PATH@
 DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
+DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@
 DSYMUTIL = @DSYMUTIL@
 DUMPBIN = @DUMPBIN@
 ECHO_C = @ECHO_C@
@@ -223,16 +221,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
 INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
 INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
 IPTABLES_PATH = @IPTABLES_PATH@
-IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@
-IWMX_SDK_LIBS = @IWMX_SDK_LIBS@
 KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
 LCOV = @LCOV@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@
+LIBAUDIT_LIBS = @LIBAUDIT_LIBS@
 LIBDL = @LIBDL@
-LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
-LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
-LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
@@ -269,6 +264,8 @@ NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
+NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@
+NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
 NM_MICRO_VERSION = @NM_MICRO_VERSION@
 NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -297,7 +294,6 @@ POLKIT_LIBS = @POLKIT_LIBS@
 POSUB = @POSUB@
 PPPD_PATH = @PPPD_PATH@
 PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
-PPPOE_PATH = @PPPOE_PATH@
 QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
@@ -312,6 +308,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@
 SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@
 SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@
 SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
+SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@
+SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@
 SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
 SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
@@ -372,6 +370,7 @@ mkdir_p = @mkdir_p@
 nmbinary = @nmbinary@
 nmconfdir = @nmconfdir@
 nmdatadir = @nmdatadir@
+nmlibdir = @nmlibdir@
 nmrundir = @nmrundir@
 nmstatedir = @nmstatedir@
 oldincludedir = @oldincludedir@
@@ -379,6 +378,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
diff --git a/tools/check-exports.sh b/tools/check-exports.sh
index da62a74f..b645d379 100755
--- a/tools/check-exports.sh
+++ b/tools/check-exports.sh
@@ -18,9 +18,7 @@ get_syms() {
 }
 
 get_syms_from_def() {
-    # be strict and only parse entries that start with one \t and end with a ';'
-    sed -n 's/^\t\([_a-zA-Z0-9]\+\);$/\1/p' "$1" |
-    grep '^\*$' -v |
+    sed -n 's/^\t\(\([_a-zA-Z0-9]\+\)\|#\s*\([_a-zA-Z0-9]\+@@\?[_a-zA-Z0-9]\+\)\);$/\2\3/p' "$1" |
     sort
 }
 
diff --git a/tools/test-networkmanager-service.py b/tools/test-networkmanager-service.py
index 6035fecd..6335fd80 100755
--- a/tools/test-networkmanager-service.py
+++ b/tools/test-networkmanager-service.py
@@ -9,6 +9,8 @@ import dbus
 import dbus.service
 import dbus.mainloop.glib
 import random
+import collections
+import uuid
 
 mainloop = GLib.MainLoop()
 
@@ -83,32 +85,42 @@ def to_path(src):
     return dbus.ObjectPath("/")
 
 class ExportedObj(dbus.service.Object):
+
+    DBusInterface = collections.namedtuple('DBusInterface', ['dbus_iface', 'get_props_func', 'prop_changed_func'])
+
     def __init__(self, bus, object_path):
         dbus.service.Object.__init__(self, bus, object_path)
         self._bus = bus
         self.path = object_path
         self.__dbus_ifaces = {}
 
-    def add_dbus_interface(self, dbus_iface, get_props_func):
-        self.__dbus_ifaces[dbus_iface] = get_props_func
+    def add_dbus_interface(self, dbus_iface, get_props_func, prop_changed_func):
+        self.__dbus_ifaces[dbus_iface] = ExportedObj.DBusInterface(dbus_iface, get_props_func, prop_changed_func)
+
+    def __dbus_interface_get(self, dbus_iface):
+        if dbus_iface not in self.__dbus_ifaces:
+            raise UnknownInterfaceException()
+        return self.__dbus_ifaces[dbus_iface]
+
+    def _dbus_property_get(self, dbus_iface, propname = None):
+        props = self.__dbus_interface_get(dbus_iface).get_props_func()
+        if propname is None:
+            return props
+        if propname not in props:
+            raise UnknownPropertyException()
+        return props[propname]
 
-    def _get_dbus_properties(self, iface):
-        return self.__dbus_ifaces[iface]()
+    def _dbus_property_notify(self, dbus_iface, propname):
+        prop = self._dbus_property_get(dbus_iface, propname)
+        self.__dbus_interface_get(dbus_iface).prop_changed_func(self, { propname: prop })
 
     @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='s', out_signature='a{sv}')
-    def GetAll(self, iface):
-        if iface not in self.__dbus_ifaces.keys():
-            raise UnknownInterfaceException()
-        return self._get_dbus_properties(iface)
+    def GetAll(self, dbus_iface):
+        return self._dbus_property_get(dbus_iface)
 
     @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v')
-    def Get(self, iface, name):
-        if iface not in self.__dbus_ifaces.keys():
-            raise UnknownInterfaceException()
-        props = self._get_dbus_properties(iface)
-        if not name in props.keys():
-            raise UnknownPropertyException()
-        return props[name]
+    def Get(self, dbus_iface, name):
+        return self._dbus_property_get(dbus_iface, name)
 
 ###################################################################
 IFACE_DEVICE = 'org.freedesktop.NetworkManager.Device'
@@ -137,7 +149,7 @@ class Device(ExportedObj):
         object_path = "/org/freedesktop/NetworkManager/Devices/%d" % Device.counter
         Device.counter = Device.counter + 1
         ExportedObj.__init__(self, bus, object_path)
-        self.add_dbus_interface(IFACE_DEVICE, self.__get_props)
+        self.add_dbus_interface(IFACE_DEVICE, self.__get_props, Device.PropertiesChanged)
 
         self.iface = iface
         self.udi = "/sys/devices/virtual/%s" % iface
@@ -180,9 +192,7 @@ class Device(ExportedObj):
         pass
 
     def __notify(self, propname):
-        props = self._get_dbus_properties(IFACE_DEVICE)
-        changed = { propname: props[propname] }
-        Device.PropertiesChanged(self, changed)
+        self._dbus_property_notify(IFACE_DEVICE, propname)
 
     @dbus.service.signal(IFACE_DEVICE, signature='a{sv}')
     def PropertiesChanged(self, changed):
@@ -207,14 +217,19 @@ PE_HW_ADDRESS = "HwAddress"
 PE_PERM_HW_ADDRESS = "PermHwAddress"
 PE_SPEED = "Speed"
 PE_CARRIER = "Carrier"
+PE_S390_SUBCHANNELS = "S390Subchannels"
 
 class WiredDevice(Device):
-    def __init__(self, bus, iface):
+    def __init__(self, bus, iface, mac, subchannels):
         Device.__init__(self, bus, iface, NM_DEVICE_TYPE_ETHERNET)
-        self.add_dbus_interface(IFACE_WIRED, self.__get_props)
+        self.add_dbus_interface(IFACE_WIRED, self.__get_props, WiredDevice.PropertiesChanged)
 
-        self.mac = random_mac()
+        if mac is None:
+            self.mac = random_mac()
+        else:
+            self.mac = mac
         self.carrier = False
+        self.s390_subchannels = subchannels
 
     # Properties interface
     def __get_props(self):
@@ -223,12 +238,11 @@ class WiredDevice(Device):
         props[PE_PERM_HW_ADDRESS] = self.mac
         props[PE_SPEED] = dbus.UInt32(100)
         props[PE_CARRIER] = self.carrier
+        props[PE_S390_SUBCHANNELS] = self.s390_subchannels
         return props
 
     def __notify(self, propname):
-        props = self._get_dbus_properties(IFACE_WIRED)
-        changed = { propname: props[propname] }
-        WiredDevice.PropertiesChanged(self, changed)
+        self._dbus_property_notify(IFACE_WIRED, propname)
 
     @dbus.service.signal(IFACE_WIRED, signature='a{sv}')
     def PropertiesChanged(self, changed):
@@ -244,7 +258,7 @@ PV_VLAN_ID = "VlanId"
 class VlanDevice(Device):
     def __init__(self, bus, iface):
         Device.__init__(self, bus, iface, NM_DEVICE_TYPE_VLAN)
-        self.add_dbus_interface(IFACE_VLAN, self.__get_props)
+        self.add_dbus_interface(IFACE_VLAN, self.__get_props, VlanDevice.PropertiesChanged)
 
         self.mac = random_mac()
         self.carrier = False
@@ -282,7 +296,7 @@ class WifiAp(ExportedObj):
         path = "/org/freedesktop/NetworkManager/AccessPoint/%d" % WifiAp.counter
         WifiAp.counter = WifiAp.counter + 1
         ExportedObj.__init__(self, bus, path)
-        self.add_dbus_interface(IFACE_WIFI_AP, self.__get_props)
+        self.add_dbus_interface(IFACE_WIFI_AP, self.__get_props, WifiAp.PropertiesChanged)
 
         self.ssid = ssid
         if mac:
@@ -321,9 +335,7 @@ class WifiAp(ExportedObj):
         return props
 
     def __notify(self, propname):
-        props = self._get_dbus_properties(IFACE_WIFI_AP)
-        changed = { propname: props[propname] }
-        WifiAp.PropertiesChanged(self, changed)
+        self._dbus_property_notify(IFACE_WIFI_AP, propname)
 
     @dbus.service.signal(IFACE_WIFI_AP, signature='a{sv}')
     def PropertiesChanged(self, changed):
@@ -346,7 +358,7 @@ PW_WIRELESS_CAPABILITIES = "WirelessCapabilities"
 class WifiDevice(Device):
     def __init__(self, bus, iface):
         Device.__init__(self, bus, iface, NM_DEVICE_TYPE_WIFI)
-        self.add_dbus_interface(IFACE_WIFI, self.__get_props)
+        self.add_dbus_interface(IFACE_WIFI, self.__get_props, WifiDevice.PropertiesChanged)
 
         self.mac = random_mac()
         self.aps = []
@@ -398,9 +410,7 @@ class WifiDevice(Device):
         return props
 
     def __notify(self, propname):
-        props = self._get_dbus_properties(IFACE_WIFI)
-        changed = { propname: props[propname] }
-        WifiDevice.PropertiesChanged(self, changed)
+        self._dbus_property_notify(IFACE_WIFI, propname)
 
     @dbus.service.signal(IFACE_WIFI, signature='a{sv}')
     def PropertiesChanged(self, changed):
@@ -434,7 +444,7 @@ class WimaxNsp(ExportedObj):
         path = "/org/freedesktop/NetworkManager/Nsp/%d" % WimaxNsp.counter
         WimaxNsp.counter = WimaxNsp.counter + 1
         ExportedObj.__init__(self, bus, path)
-        self.add_dbus_interface(IFACE_WIMAX_NSP, self.__get_props)
+        self.add_dbus_interface(IFACE_WIMAX_NSP, self.__get_props, WimaxNsp.PropertiesChanged)
 
         self.name = name
         self.strength = random.randint(0, 100)
@@ -459,9 +469,7 @@ class WimaxNsp(ExportedObj):
         return props
 
     def __notify(self, propname):
-        props = self._get_dbus_properties(IFACE_WIMAX_NSP)
-        changed = { propname: props[propname] }
-        WimaxNsp.PropertiesChanged(self, changed)
+        self._dbus_property_notify(IFACE_WIMAX_NSP, propname)
 
     @dbus.service.signal(IFACE_WIMAX_NSP, signature='a{sv}')
     def PropertiesChanged(self, changed):
@@ -485,7 +493,7 @@ PX_ACTIVE_NSP = "ActiveNsp"
 class WimaxDevice(Device):
     def __init__(self, bus, iface):
         Device.__init__(self, bus, iface, NM_DEVICE_TYPE_WIMAX)
-        self.add_dbus_interface(IFACE_WIMAX, self.__get_props)
+        self.add_dbus_interface(IFACE_WIMAX, self.__get_props, WimaxDevice.PropertiesChanged)
 
         self.mac = random_mac()
         self.bsid = random_mac()
@@ -530,9 +538,7 @@ class WimaxDevice(Device):
         return props
 
     def __notify(self, propname):
-        props = self._get_dbus_properties(IFACE_WIMAX)
-        changed = { propname: props[propname] }
-        WimaxDevice.PropertiesChanged(self, changed)
+        self._dbus_property_notify(IFACE_WIMAX, propname)
 
     @dbus.service.signal(IFACE_WIMAX, signature='a{sv}')
     def PropertiesChanged(self, changed):
@@ -577,7 +583,7 @@ class ActiveConnection(ExportedObj):
         object_path = "/org/freedesktop/NetworkManager/ActiveConnection/%d" % ActiveConnection.counter
         ActiveConnection.counter = ActiveConnection.counter + 1
         ExportedObj.__init__(self, bus, object_path)
-        self.add_dbus_interface(IFACE_ACTIVE_CONNECTION, self.__get_props)
+        self.add_dbus_interface(IFACE_ACTIVE_CONNECTION, self.__get_props, ActiveConnection.PropertiesChanged)
 
         self.device = device
         self.conn = connection
@@ -632,6 +638,7 @@ class UnknownConnectionException(dbus.DBusException):
     _dbus_error_name = IFACE_NM + '.UnknownConnection'
 
 PM_DEVICES = 'Devices'
+PM_ALL_DEVICES = 'AllDevices'
 PM_NETWORKING_ENABLED = 'NetworkingEnabled'
 PM_WWAN_ENABLED = 'WwanEnabled'
 PM_WWAN_HARDWARE_ENABLED = 'WwanHardwareEnabled'
@@ -653,7 +660,7 @@ def set_device_ac_cb(device, ac):
 class NetworkManager(ExportedObj):
     def __init__(self, bus, object_path):
         ExportedObj.__init__(self, bus, object_path)
-        self.add_dbus_interface(IFACE_NM, self.__get_props)
+        self.add_dbus_interface(IFACE_NM, self.__get_props, NetworkManager.PropertiesChanged)
 
         self._bus = bus;
         self.devices = []
@@ -674,7 +681,11 @@ class NetworkManager(ExportedObj):
 
     @dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='ao')
     def GetDevices(self):
-        return self._get_dbus_properties(IFACE_NM)[PM_DEVICES]
+        return to_path_array(self.devices)
+
+    @dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='ao')
+    def GetAllDevices(self):
+        return to_path_array(self.devices)
 
     @dbus.service.method(dbus_interface=IFACE_NM, in_signature='s', out_signature='o')
     def GetDeviceByIpIface(self, ip_iface):
@@ -793,6 +804,7 @@ class NetworkManager(ExportedObj):
     def add_device(self, device):
         self.devices.append(device)
         self.__notify(PM_DEVICES)
+        self.__notify(PM_ALL_DEVICES)
         self.DeviceAdded(to_path(device))
 
     @dbus.service.signal(IFACE_NM, signature='o')
@@ -802,12 +814,14 @@ class NetworkManager(ExportedObj):
     def remove_device(self, device):
         self.devices.remove(device)
         self.__notify(PM_DEVICES)
+        self.__notify(PM_ALL_DEVICES)
         self.DeviceRemoved(to_path(device))
 
     ################# D-Bus Properties interface
     def __get_props(self):
         props = {}
         props[PM_DEVICES] = to_path_array(self.devices)
+        props[PM_ALL_DEVICES] = to_path_array(self.devices)
         props[PM_NETWORKING_ENABLED] = True
         props[PM_WWAN_ENABLED] = True
         props[PM_WWAN_HARDWARE_ENABLED] = True
@@ -825,9 +839,7 @@ class NetworkManager(ExportedObj):
         return props
 
     def __notify(self, propname):
-        props = self._get_dbus_properties(IFACE_NM)
-        changed = { propname: props[propname] }
-        NetworkManager.PropertiesChanged(self, changed)
+        self._dbus_property_notify(IFACE_NM, propname)
 
     @dbus.service.signal(IFACE_NM, signature='a{sv}')
     def PropertiesChanged(self, changed):
@@ -838,12 +850,12 @@ class NetworkManager(ExportedObj):
     def Quit(self):
         mainloop.quit()
 
-    @dbus.service.method(IFACE_TEST, in_signature='s', out_signature='o')
-    def AddWiredDevice(self, ifname):
+    @dbus.service.method(IFACE_TEST, in_signature='ssas', out_signature='o')
+    def AddWiredDevice(self, ifname, mac, subchannels):
         for d in self.devices:
             if d.iface == ifname:
                 raise PermissionDeniedException("Device already added")
-        dev = WiredDevice(self._bus, ifname)
+        dev = WiredDevice(self._bus, ifname, mac, subchannels)
         self.add_device(dev)
         return to_path(dev)
 
@@ -907,6 +919,15 @@ class NetworkManager(ExportedObj):
     def AutoRemoveNextConnection(self):
         settings.auto_remove_next_connection()
 
+    @dbus.service.method(dbus_interface=IFACE_TEST, in_signature='a{sa{sv}}b', out_signature='o')
+    def AddConnection(self, connection, verify_connection):
+        return settings.add_connection(connection, verify_connection)
+
+    @dbus.service.method(dbus_interface=IFACE_TEST, in_signature='sa{sa{sv}}b', out_signature='')
+    def UpdateConnection(self, path, connection, verify_connection):
+        return settings.update_connection(connection, path, verify_connection)
+
+
 ###################################################################
 IFACE_CONNECTION = 'org.freedesktop.NetworkManager.Settings.Connection'
 
@@ -923,17 +944,15 @@ class MissingSettingException(dbus.DBusException):
     _dbus_error_name = IFACE_CONNECTION + '.MissingSetting'
 
 class Connection(dbus.service.Object):
-    def __init__(self, bus, object_path, settings, remove_func):
-        dbus.service.Object.__init__(self, bus, object_path)
+    def __init__(self, bus, object_path, settings, remove_func, verify_connection=True):
 
-        if 'connection' not in settings:
-            raise MissingSettingException('connection: setting is required')
-        s_con = settings['connection']
-        if 'type' not in s_con:
-            raise MissingPropertyException('connection.type: property is required')
-        type = s_con['type']
-        if not type in ['802-3-ethernet', '802-11-wireless', 'vlan', 'wimax']:
-            raise InvalidPropertyException('connection.type: unsupported connection type')
+        if self.get_uuid(settings) is None:
+            if 'connection' not in settings:
+                settings['connection'] = { }
+            settings['connection']['uuid'] = uuid.uuid4()
+        self.verify(settings, verify_strict=verify_connection)
+
+        dbus.service.Object.__init__(self, bus, object_path)
 
         self.path = object_path
         self.settings = settings
@@ -942,6 +961,45 @@ class Connection(dbus.service.Object):
         self.props = {}
         self.props['Unsaved'] = False
 
+    def get_uuid(self, settings=None):
+        if settings is None:
+            settings = self.settings
+        if 'connection' in settings:
+            s_con = settings['connection']
+            if 'uuid' in s_con:
+                return s_con['uuid']
+        return None
+
+    def verify(self, settings=None, verify_strict=True):
+        if settings is None:
+            settings = self.settings;
+        if 'connection' not in settings:
+            raise MissingSettingException('connection: setting is required')
+        s_con = settings['connection']
+        if 'type' not in s_con:
+            raise MissingPropertyException('connection.type: property is required')
+        if 'uuid' not in s_con:
+            raise MissingPropertyException('connection.uuid: property is required')
+        if 'id' not in s_con:
+            raise MissingPropertyException('connection.id: property is required')
+
+        if not verify_strict:
+            return;
+        t = s_con['type']
+        if t not in ['802-3-ethernet', '802-11-wireless', 'vlan', 'wimax']:
+            raise InvalidPropertyException('connection.type: unsupported connection type "%s"' % (t))
+
+    def update_connection(self, settings, verify_connection):
+        self.verify(settings, verify_strict=verify_connection)
+
+        old_uuid = self.get_uuid()
+        new_uuid = self.get_uuid(settings)
+        if old_uuid != new_uuid:
+            raise InvalidPropertyException('connection.uuid: cannot change the uuid from %s to %s' % (old_uuid, new_uuid))
+
+        self.settings = settings;
+        self.Updated()
+
     # Properties interface
     @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='s', out_signature='a{sv}')
     def GetAll(self, iface):
@@ -975,6 +1033,10 @@ class Connection(dbus.service.Object):
         self.Removed()
         self.remove_from_connection()
 
+    @dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='a{sa{sv}}', out_signature='')
+    def Update(self, settings):
+        self.update_connection(settings, TRUE)
+
     @dbus.service.signal(IFACE_CONNECTION, signature='')
     def Removed(self):
         pass
@@ -1013,9 +1075,18 @@ class Settings(dbus.service.Object):
 
     @dbus.service.method(dbus_interface=IFACE_SETTINGS, in_signature='a{sa{sv}}', out_signature='o')
     def AddConnection(self, settings):
+        return self.add_connection(settings)
+
+    def add_connection(self, settings, verify_connection=True):
         path = "/org/freedesktop/NetworkManager/Settings/Connection/{0}".format(self.counter)
+        con = Connection(self.bus, path, settings, self.delete_connection, verify_connection)
+
+        uuid = con.get_uuid()
+        if uuid in [c.get_uuid() for c in self.connections.itervalues()]:
+            raise InvalidSettingException('cannot add duplicate connection with uuid %s' % (uuid))
+
         self.counter = self.counter + 1
-        self.connections[path] = Connection(self.bus, path, settings, self.delete_connection)
+        self.connections[path] = con
         self.props['Connections'] = dbus.Array(self.connections.keys(), 'o')
         self.NewConnection(path)
         self.PropertiesChanged({ 'connections': self.props['Connections'] })
@@ -1026,6 +1097,14 @@ class Settings(dbus.service.Object):
 
         return path
 
+    def update_connection(self, connection, path=None, verify_connection=True):
+        if path is None:
+            path = connection.path
+        if path not in self.connections:
+            raise UnknownConnectionException('Connection not found')
+        con = self.connections[path]
+        con.update_connection(connection, verify_connection)
+
     def delete_connection(self, connection):
         del self.connections[connection.path]
         self.props['Connections'] = dbus.Array(self.connections.keys(), 'o')