summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/bluetooth/nm-device-bt.c3
-rw-r--r--src/devices/nm-device.c160
-rw-r--r--src/devices/nm-device.h33
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c8
-rw-r--r--src/devices/wifi/nm-device-wifi.c3
-rw-r--r--src/devices/wwan/nm-device-modem.c3
-rw-r--r--src/devices/wwan/nm-modem-ofono.c189
-rw-r--r--src/dnsmasq/nm-dnsmasq-manager.c3
-rw-r--r--src/nm-checkpoint-manager.c26
-rw-r--r--src/nm-manager.c24
-rw-r--r--src/nm-manager.h1
-rw-r--r--src/nm-policy.c131
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c8
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c5
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected9
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c58
16 files changed, 347 insertions, 317 deletions
diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c
index 0d46be8f..977c1e1a 100644
--- a/src/devices/bluetooth/nm-device-bt.c
+++ b/src/devices/bluetooth/nm-device-bt.c
@@ -491,8 +491,7 @@ modem_prepare_result (NMModem *modem,
 			 * the device to be auto-activated anymore, which would risk locking
 			 * the SIM if the incorrect PIN continues to be used.
 			 */
-			_LOGI (LOGD_MB, "disabling autoconnect due to failed SIM PIN");
-			nm_device_set_autoconnect_intern (device, FALSE);
+			nm_device_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_WRONG_PIN);
 		}
 
 		nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index e979b875..6a1a10f4 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -354,6 +354,8 @@ typedef struct _NMDevicePrivate {
 	bool            v4_route_table_initalized:1;
 	bool            v6_route_table_initalized:1;
 
+	NMDeviceAutoconnectBlockedFlags autoconnect_blocked_flags:4;
+
 	/* Generic DHCP stuff */
 	char *          dhcp_anycast_address;
 
@@ -466,10 +468,6 @@ typedef struct _NMDevicePrivate {
 
 	gboolean needs_ip6_subnet;
 
-	/* allow autoconnect feature */
-	bool autoconnect_intern:1;
-	bool autoconnect_user:1;
-
 	/* master interface for bridge/bond/team slave */
 	NMDevice *      master;
 	bool            is_enslaved;
@@ -533,9 +531,6 @@ static NMActStageReturn linklocal6_start (NMDevice *self);
 
 static void _carrier_wait_check_queued_act_request (NMDevice *self);
 
-static void nm_device_set_autoconnect_both (NMDevice *self, gboolean autoconnect);
-static void nm_device_set_autoconnect_full (NMDevice *self, int autoconnect_intern, int autoconnect_user);
-
 static const char *_activation_func_to_string (ActivationHandleFunc func);
 static void activation_source_handle_cb (NMDevice *self, int addr_family);
 
@@ -3392,8 +3387,6 @@ realize_start_setup (NMDevice *self,
 	if (real_rate)
 		priv->stats.timeout_id = g_timeout_add (real_rate, _stats_timeout_cb, self);
 
-	nm_device_set_autoconnect_full (self, !!DEFAULT_AUTOCONNECT, TRUE);
-
 	klass->realize_start_notify (self, plink);
 
 	nm_assert (!nm_device_get_unmanaged_mask (self, NM_UNMANAGED_USER_EXPLICIT));
@@ -3593,8 +3586,6 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
 	priv->real = FALSE;
 	_notify (self, PROP_REAL);
 
-	nm_device_set_autoconnect_both (self, FALSE);
-
 	g_object_thaw_notify (G_OBJECT (self));
 
 	nm_device_set_unmanaged_flags (self,
@@ -4219,62 +4210,55 @@ nm_device_set_enabled (NMDevice *self, gboolean enabled)
 		NM_DEVICE_GET_CLASS (self)->set_enabled (self, enabled);
 }
 
-/**
- * nm_device_get_autoconnect:
- * @self: the #NMDevice
- *
- * Returns: %TRUE if the device allows autoconnect connections, or %FALSE if the
- * device is explicitly blocking all autoconnect connections.  Does not take
- * into account transient conditions like companion devices that may wish to
- * block the device.
- */
-gboolean
-nm_device_get_autoconnect (NMDevice *self)
+NM_UTILS_FLAGS2STR_DEFINE_STATIC (_autoconnect_blocked_flags_to_string, NMDeviceAutoconnectBlockedFlags,
+	NM_UTILS_FLAGS2STR (NM_DEVICE_AUTOCONNECT_BLOCKED_NONE,              "none"),
+	NM_UTILS_FLAGS2STR (NM_DEVICE_AUTOCONNECT_BLOCKED_USER,              "user"),
+	NM_UTILS_FLAGS2STR (NM_DEVICE_AUTOCONNECT_BLOCKED_WRONG_PIN,         "wrong-pin"),
+	NM_UTILS_FLAGS2STR (NM_DEVICE_AUTOCONNECT_BLOCKED_MANUAL_DISCONNECT, "manual-disconnect"),
+);
+
+NMDeviceAutoconnectBlockedFlags
+nm_device_autoconnect_blocked_get (NMDevice *self, NMDeviceAutoconnectBlockedFlags mask)
 {
 	NMDevicePrivate *priv;
 
 	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
 
+	if (mask == 0)
+		mask = NM_DEVICE_AUTOCONNECT_BLOCKED_ALL;
+
 	priv = NM_DEVICE_GET_PRIVATE (self);
-	return priv->autoconnect_intern && priv->autoconnect_user;
+	return priv->autoconnect_blocked_flags & mask;
 }
 
-static void
-nm_device_set_autoconnect_full (NMDevice *self, int autoconnect_intern, int autoconnect_user)
+void
+nm_device_autoconnect_blocked_set_full (NMDevice *self, NMDeviceAutoconnectBlockedFlags mask, NMDeviceAutoconnectBlockedFlags value)
 {
 	NMDevicePrivate *priv;
-	gboolean old_value;
+	gboolean changed;
+	char buf1[128], buf2[128];
 
 	g_return_if_fail (NM_IS_DEVICE (self));
+	nm_assert (mask);
+	nm_assert (!NM_FLAGS_ANY (mask, ~NM_DEVICE_AUTOCONNECT_BLOCKED_ALL));
+	nm_assert (!NM_FLAGS_ANY (value, ~mask));
 
 	priv = NM_DEVICE_GET_PRIVATE (self);
 
-	old_value = nm_device_get_autoconnect (self);
-	if (autoconnect_intern != -1)
-		priv->autoconnect_intern = autoconnect_intern;
-	if (autoconnect_user != -1)
-		priv->autoconnect_user = autoconnect_user;
-	if (old_value != nm_device_get_autoconnect (self))
-		_notify (self, PROP_AUTOCONNECT);
-}
+	value = (priv->autoconnect_blocked_flags & ~mask) | (mask & value);
+	if (value == priv->autoconnect_blocked_flags)
+		return;
 
-void
-nm_device_set_autoconnect_intern (NMDevice *self, gboolean autoconnect)
-{
-	nm_device_set_autoconnect_full (self, !!autoconnect, -1);
-}
+	changed = ((!value) != (!priv->autoconnect_blocked_flags));
 
-static void
-nm_device_set_autoconnect_both (NMDevice *self, gboolean autoconnect)
-{
-	autoconnect = !!autoconnect;
-	nm_device_set_autoconnect_full (self, autoconnect, autoconnect);
-}
+	_LOGT (LOGD_DEVICE, "autoconnect-blocked: set \"%s\" (was \"%s\")",
+	       _autoconnect_blocked_flags_to_string (value, buf1, sizeof (buf1)),
+	       _autoconnect_blocked_flags_to_string (priv->autoconnect_blocked_flags, buf2, sizeof (buf2)));
 
-static gboolean
-get_autoconnect_allowed (NMDevice *self)
-{
-	return TRUE;
+	priv->autoconnect_blocked_flags = value;
+	nm_assert (priv->autoconnect_blocked_flags == value);
+	if (changed)
+		_notify (self, PROP_AUTOCONNECT);
 }
 
 static gboolean
@@ -4303,14 +4287,23 @@ nm_device_autoconnect_allowed (NMDevice *self)
 	GValue instance = G_VALUE_INIT;
 	GValue retval = G_VALUE_INIT;
 
-	if (   !nm_device_get_autoconnect (self)
-	    || !klass->get_autoconnect_allowed (self))
+	if (nm_device_autoconnect_blocked_get (self, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
 		return FALSE;
 
-	/* Unrealized devices can always autoconnect. */
-	if (nm_device_is_real (self) && priv->state < NM_DEVICE_STATE_DISCONNECTED)
+	if (   klass->get_autoconnect_allowed
+	    && !klass->get_autoconnect_allowed (self))
 		return FALSE;
 
+	if (!nm_device_get_enabled (self))
+		return FALSE;
+
+	if (nm_device_is_real (self)) {
+		if (priv->state < NM_DEVICE_STATE_DISCONNECTED)
+			return FALSE;
+	} else {
+		/* Unrealized devices can always autoconnect. */
+	}
+
 	/* The 'autoconnect-allowed' signal is emitted on a device to allow
 	 * other listeners to block autoconnect on the device if they wish.
 	 * This is mainly used by the OLPC Mesh devices to block autoconnect
@@ -4337,15 +4330,8 @@ can_auto_connect (NMDevice *self,
                   NMConnection *connection,
                   char **specific_object)
 {
-	NMSettingConnection *s_con;
-
 	nm_assert (!specific_object || !*specific_object);
-
-	s_con = nm_connection_get_setting_connection (connection);
-	if (!nm_setting_connection_get_autoconnect (s_con))
-		return FALSE;
-
-	return nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL);
+	return TRUE;
 }
 
 /**
@@ -4372,11 +4358,24 @@ nm_device_can_auto_connect (NMDevice *self,
 {
 	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
-	g_return_val_if_fail (specific_object && !*specific_object, FALSE);
+	g_return_val_if_fail (!specific_object || !*specific_object, FALSE);
 
-	if (nm_device_autoconnect_allowed (self))
-		return NM_DEVICE_GET_CLASS (self)->can_auto_connect (self, connection, specific_object);
-	return FALSE;
+	/* the caller must ensure that nm_device_autoconnect_allowed() returns
+	 * TRUE as well. This is done, because nm_device_can_auto_connect()
+	 * has only one caller, and it iterates over a list of available
+	 * connections.
+	 *
+	 * Hence, we don't need to re-check nm_device_autoconnect_allowed()
+	 * over and over again. The caller is supposed to do that. */
+	nm_assert (nm_device_autoconnect_allowed (self));
+
+	if (!nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL))
+		return FALSE;
+
+	if (!NM_DEVICE_GET_CLASS (self)->can_auto_connect (self, connection, specific_object))
+		return FALSE;
+
+	return TRUE;
 }
 
 static gboolean
@@ -4975,7 +4974,7 @@ static void
 activation_source_schedule (NMDevice *self, ActivationHandleFunc func, int addr_family)
 {
 	ActivationHandleData *act_data;
-	GSourceFunc source_func;
+	GSourceFunc source_func = NULL;
 	guint new_id = 0;
 
 	act_data = activation_source_get_by_family (self, addr_family, &source_func);
@@ -5396,8 +5395,8 @@ ipv4_manual_method_apply (NMDevice *self, NMIP4Config **configs, gboolean succes
 		nm_device_activate_schedule_ip4_config_result (self, empty);
 		g_object_unref (empty);
 	} else {
-		nm_device_queue_state (self, NM_DEVICE_STATE_FAILED,
-		                       NM_DEVICE_STATE_REASON_CONFIG_FAILED);
+		nm_device_ip_method_failed (self, AF_INET,
+		                            NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
 	}
 }
 
@@ -5977,8 +5976,8 @@ dhcp4_dad_cb (NMDevice *self, NMIP4Config **configs, gboolean success)
 	if (success)
 		nm_device_activate_schedule_ip4_config_result (self, configs[1]);
 	else {
-		nm_device_state_changed (self, NM_DEVICE_STATE_FAILED,
-		                         NM_DEVICE_STATE_REASON_CONFIG_FAILED);
+		nm_device_ip_method_failed (self, AF_INET,
+		                            NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
 	}
 }
 
@@ -9732,7 +9731,7 @@ disconnect_cb (NMDevice *self,
 		nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, NULL, subject, local->message);
 		g_dbus_method_invocation_take_error (context, local);
 	} else {
-		nm_device_set_autoconnect_intern (self, FALSE);
+		nm_device_autoconnect_blocked_set (self, NM_DEVICE_AUTOCONNECT_BLOCKED_MANUAL_DISCONNECT);
 
 		nm_device_state_changed (self,
 		                         NM_DEVICE_STATE_DEACTIVATING,
@@ -12988,10 +12987,10 @@ _set_state_full (NMDevice *self,
 		break;
 	}
 
-	/* Reset autoconnect flag when the device is activating or connected. */
+	/* Reset intern autoconnect flags when the device is activating or connected. */
 	if (   state >= NM_DEVICE_STATE_PREPARE
 	    && state <= NM_DEVICE_STATE_ACTIVATED)
-		nm_device_set_autoconnect_intern  (self, TRUE);
+		nm_device_autoconnect_blocked_unset (self, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERNAL);
 
 	_notify (self, PROP_STATE);
 	_notify (self, PROP_STATE_REASON);
@@ -14116,6 +14115,10 @@ nm_device_init (NMDevice *self)
 
 	priv->netns = g_object_ref (NM_NETNS_GET);
 
+	priv->autoconnect_blocked_flags = DEFAULT_AUTOCONNECT
+	                                  ? NM_DEVICE_AUTOCONNECT_BLOCKED_NONE
+	                                  : NM_DEVICE_AUTOCONNECT_BLOCKED_USER;
+
 	priv->auth_retries = NM_DEVICE_AUTH_RETRIES_UNSET;
 	priv->type = NM_DEVICE_TYPE_UNKNOWN;
 	priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED;
@@ -14402,7 +14405,10 @@ set_property (GObject *object, guint prop_id,
 		}
 		break;
 	case PROP_AUTOCONNECT:
-		nm_device_set_autoconnect_both (self, g_value_get_boolean (value));
+		if (g_value_get_boolean (value))
+			nm_device_autoconnect_blocked_unset (self, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL);
+		else
+			nm_device_autoconnect_blocked_set (self, NM_DEVICE_AUTOCONNECT_BLOCKED_USER);
 		break;
 	case PROP_FIRMWARE_MISSING:
 		/* construct-only */
@@ -14539,7 +14545,10 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_boolean (value, nm_device_get_state (self) > NM_DEVICE_STATE_UNMANAGED);
 		break;
 	case PROP_AUTOCONNECT:
-		g_value_set_boolean (value, nm_device_get_autoconnect (self));
+		g_value_set_boolean (value,
+		                     nm_device_autoconnect_blocked_get (self, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL)
+		                       ? FALSE
+		                       : TRUE);
 		break;
 	case PROP_FIRMWARE_MISSING:
 		g_value_set_boolean (value, priv->firmware_missing);
@@ -14668,7 +14677,6 @@ nm_device_class_init (NMDeviceClass *klass)
 	klass->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout;
 
 	klass->get_type_description = get_type_description;
-	klass->get_autoconnect_allowed = get_autoconnect_allowed;
 	klass->can_auto_connect = can_auto_connect;
 	klass->check_connection_compatible = check_connection_compatible;
 	klass->check_connection_available = check_connection_available;
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index 350a17b2..bd8104b4 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -663,8 +663,37 @@ gboolean nm_device_unrealize          (NMDevice *device,
 void nm_device_update_from_platform_link (NMDevice *self,
                                           const NMPlatformLink *plink);
 
-gboolean nm_device_get_autoconnect (NMDevice *device);
-void nm_device_set_autoconnect_intern (NMDevice *device, gboolean autoconnect);
+typedef enum {
+	NM_DEVICE_AUTOCONNECT_BLOCKED_NONE                  = 0,
+
+	NM_DEVICE_AUTOCONNECT_BLOCKED_USER                  = (1LL <<  0),
+
+	NM_DEVICE_AUTOCONNECT_BLOCKED_WRONG_PIN             = (1LL <<  1),
+	NM_DEVICE_AUTOCONNECT_BLOCKED_MANUAL_DISCONNECT     = (1LL <<  2),
+
+	_NM_DEVICE_AUTOCONNECT_BLOCKED_LAST,
+
+	NM_DEVICE_AUTOCONNECT_BLOCKED_ALL                   = (((_NM_DEVICE_AUTOCONNECT_BLOCKED_LAST - 1) << 1) - 1),
+
+	NM_DEVICE_AUTOCONNECT_BLOCKED_INTERNAL              = NM_DEVICE_AUTOCONNECT_BLOCKED_ALL & ~NM_DEVICE_AUTOCONNECT_BLOCKED_USER,
+} NMDeviceAutoconnectBlockedFlags;
+
+NMDeviceAutoconnectBlockedFlags nm_device_autoconnect_blocked_get (NMDevice *device, NMDeviceAutoconnectBlockedFlags mask);
+
+void nm_device_autoconnect_blocked_set_full (NMDevice *device, NMDeviceAutoconnectBlockedFlags mask, NMDeviceAutoconnectBlockedFlags values);
+
+static inline void
+nm_device_autoconnect_blocked_set (NMDevice *device, NMDeviceAutoconnectBlockedFlags mask)
+{
+	nm_device_autoconnect_blocked_set_full (device, mask, mask);
+}
+
+static inline void
+nm_device_autoconnect_blocked_unset (NMDevice *device, NMDeviceAutoconnectBlockedFlags mask)
+{
+	nm_device_autoconnect_blocked_set_full (device, mask, NM_DEVICE_AUTOCONNECT_BLOCKED_NONE);
+}
+
 void nm_device_emit_recheck_auto_activate (NMDevice *device);
 
 NMDeviceSysIfaceState nm_device_sys_iface_state_get (NMDevice *device);
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index ac78757d..3a4a027a 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -107,12 +107,8 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 }
 
 static gboolean
-can_auto_connect (NMDevice *device,
-                  NMConnection *connection,
-                  char **specific_object)
+get_autoconnect_allowed (NMDevice *device)
 {
-	nm_assert (!specific_object || !*specific_object);
-
 	return FALSE;
 }
 
@@ -517,7 +513,7 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
 	object_class->dispose = dispose;
 
 	parent_class->check_connection_compatible = check_connection_compatible;
-	parent_class->can_auto_connect = can_auto_connect;
+	parent_class->get_autoconnect_allowed = get_autoconnect_allowed;
 	parent_class->complete_connection = complete_connection;
 	parent_class->is_available = is_available;
 	parent_class->act_stage1_prepare = act_stage1_prepare;
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 8bfddbd9..5e92f47b 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -997,9 +997,6 @@ get_autoconnect_allowed (NMDevice *device)
 {
 	NMDeviceWifiPrivate *priv;
 
-	if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->get_autoconnect_allowed (device))
-		return FALSE;
-
 	priv = NM_DEVICE_WIFI_GET_PRIVATE (NM_DEVICE_WIFI (device));
 	return !priv->requested_scan;
 }
diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c
index 22fb8c67..b79d145d 100644
--- a/src/devices/wwan/nm-device-modem.c
+++ b/src/devices/wwan/nm-device-modem.c
@@ -132,8 +132,7 @@ modem_prepare_result (NMModem *modem,
 			 * the device to be auto-activated anymore, which would risk locking
 			 * the SIM if the incorrect PIN continues to be used.
 			 */
-			nm_device_set_autoconnect_intern (device, FALSE);
-			_LOGI (LOGD_MB, "disabling autoconnect due to failed SIM PIN");
+			nm_device_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_WRONG_PIN);
 		}
 
 		nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c
index 8b3fc2e8..811c3afb 100644
--- a/src/devices/wwan/nm-modem-ofono.c
+++ b/src/devices/wwan/nm-modem-ofono.c
@@ -829,12 +829,13 @@ context_property_changed (GDBusProxy *proxy,
 	NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self);
 	NMPlatformIP4Address addr;
 	gboolean ret = FALSE;
-	GVariant *v_dict;
-	const gchar *s, *addr_s;
+	gs_unref_variant GVariant *v_dict = NULL;
+	const char *interface;
+	const gchar *s;
 	const gchar **array, **iter;
 	guint32 address_network, gateway_network;
 	guint32 ip4_route_table, ip4_route_metric;
-	guint prefix = 0;
+	int ifindex;
 
 	_LOGD ("PropertyChanged: %s", property);
 
@@ -855,141 +856,109 @@ context_property_changed (GDBusProxy *proxy,
 
 	_LOGI ("IPv4 static Settings:");
 
-	if (g_variant_lookup (v_dict, "Interface", "&s", &s)) {
-		if (s && strlen (s)) {
-			_LOGD ("Interface: %s", s);
-			g_object_set (self,
-			              NM_MODEM_DATA_PORT, g_strdup (s),
-			              NM_MODEM_IP4_METHOD, NM_MODEM_IP_METHOD_STATIC,
-			              NULL);
-		} else {
-			_LOGW ("Settings 'Interface'; empty");
-			goto out;
-		}
-
-	} else {
+	if (!g_variant_lookup (v_dict, "Interface", "&s", &interface)) {
 		_LOGW ("Settings 'Interface' missing");
 		goto out;
 	}
+	if (!interface || !interface[0]) {
+		_LOGW ("Settings 'Interface'; empty");
+		goto out;
+	}
+
+	ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, interface);
+	if (ifindex <= 0) {
+		_LOGW ("Interface \"%s\" not found", interface);
+		goto out;
+	}
+
+	_LOGD ("Interface: %s", interface);
+	g_object_set (self,
+	              NM_MODEM_DATA_PORT, interface,
+	              NM_MODEM_IP4_METHOD, NM_MODEM_IP_METHOD_STATIC,
+	              NULL);
 
 	/* TODO: verify handling of ip4_config; check other places it's used... */
 	g_clear_object (&priv->ip4_config);
 
-	memset (&addr, 0, sizeof (addr));
 
-	/*
-	 * TODO:
-	 *
-	 * NM 1.2 changed the NMIP4Config constructor to take an ifindex
-	 * ( vs. void pre 1.2 ), to tie config instance to a specific
-	 * platform interface.
-	 *
-	 * This doesn't work for ofono, as the devices are created
-	 * dynamically ( eg. ril_0, ril_1 ) in NMModemManager.  The
-	 * device created doesn't really map directly to a platform
-	 * link.  The closest would be one of the devices owned by
-	 * rild ( eg. ccmin0 ), which is passed to us above as
-	 * 'Interface'.
-	 *
-	 * This needs discussion with upstream.
-	 *
-	 * FIXME: it is no longer allowed to omit the ifindex for NMIP4Config instances.
-	 * This is broken.
-	 */
 	priv->ip4_config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET),
-	                                      0);
-
-	/* TODO: simply if/else error logic! */
+	                                      ifindex);
 
-	if (g_variant_lookup (v_dict, "Address", "&s", &addr_s)) {
-		_LOGD ("Address: %s", addr_s);
-
-		if (   addr_s
-		    && nm_utils_parse_inaddr_bin (AF_INET, addr_s, &address_network)) {
-			addr.address = address_network;
-			addr.addr_source = NM_IP_CONFIG_SOURCE_WWAN;
-		} else {
-			_LOGW ("can't convert 'Address' %s to addr", s);
-			goto out;
-		}
-
-	} else {
+	if (!g_variant_lookup (v_dict, "Address", "&s", &s)) {
 		_LOGW ("Settings 'Address' missing");
 		goto out;
 	}
+	if (   !s
+	    || !nm_utils_parse_inaddr_bin (AF_INET, s, &address_network)) {
+		_LOGW ("can't convert 'Address' %s to addr", s ?: "");
+		goto out;
+	}
+	memset (&addr, 0, sizeof (addr));
+	addr.ifindex = ifindex;
+	addr.address = address_network;
+	addr.addr_source = NM_IP_CONFIG_SOURCE_WWAN;
 
-	if (g_variant_lookup (v_dict, "Netmask", "&s", &s)) {
-		_LOGD ("Netmask: %s", s);
-
-		if (   s
-		    && nm_utils_parse_inaddr_bin (AF_INET, s, &address_network)) {
-			prefix = nm_utils_ip4_netmask_to_prefix (address_network);
-			if (prefix > 0)
-				addr.plen = prefix;
-		} else {
-			_LOGW ("invalid 'Netmask': %s", s);
-			goto out;
-		}
-	} else {
+	if (!g_variant_lookup (v_dict, "Netmask", "&s", &s)) {
 		_LOGW ("Settings 'Netmask' missing");
 		goto out;
 	}
+	if (   !s
+	    || !nm_utils_parse_inaddr_bin (AF_INET, s, &address_network)) {
+		_LOGW ("invalid 'Netmask': %s", s ?: "");
+		goto out;
+	}
+	addr.plen = nm_utils_ip4_netmask_to_prefix (address_network);
 
-	_LOGI ("Address: %s/%d", addr_s, prefix);
-
+	_LOGI ("Address: %s", nm_platform_ip4_address_to_string (&addr, NULL, 0));
 	nm_ip4_config_add_address (priv->ip4_config, &addr);
 
-	if (   g_variant_lookup (v_dict, "Gateway", "&s", &s)
-	    && s) {
-
-		if (!nm_utils_parse_inaddr_bin (AF_INET, s, &gateway_network)) {
-			_LOGW ("invalid 'Gateway': %s", s);
-			goto out;
-		}
-
-		nm_modem_get_route_parameters (NM_MODEM (self),
-		                               &ip4_route_table,
-		                               &ip4_route_metric,
-		                               NULL,
-		                               NULL);
-		{
-			const NMPlatformIP4Route r = {
-				.rt_source = NM_IP_CONFIG_SOURCE_WWAN,
-				.gateway = gateway_network,
-				.table_coerced = nm_platform_route_table_coerce (ip4_route_table),
-				.metric = ip4_route_metric,
-			};
-
-			_LOGI ("Gateway: %s", s);
-			nm_ip4_config_add_route (priv->ip4_config, &r, NULL);
-		}
-	} else {
+	if (   !g_variant_lookup (v_dict, "Gateway", "&s", &s)
+	    || !s) {
 		_LOGW ("Settings 'Gateway' missing");
 		goto out;
 	}
+	if (!nm_utils_parse_inaddr_bin (AF_INET, s, &gateway_network)) {
+		_LOGW ("invalid 'Gateway': %s", s);
+		goto out;
+	}
+	nm_modem_get_route_parameters (NM_MODEM (self),
+	                               &ip4_route_table,
+	                               &ip4_route_metric,
+	                               NULL,
+	                               NULL);
+	{
+		const NMPlatformIP4Route r = {
+			.rt_source = NM_IP_CONFIG_SOURCE_WWAN,
+			.gateway = gateway_network,
+			.table_coerced = nm_platform_route_table_coerce (ip4_route_table),
+			.metric = ip4_route_metric,
+		};
+
+		_LOGI ("Gateway: %s", s);
+		nm_ip4_config_add_route (priv->ip4_config, &r, NULL);
+	}
 
-	if (g_variant_lookup (v_dict, "DomainNameServers", "^a&s", &array)) {
-		if (array) {
-			for (iter = array; *iter; iter++) {
-				if (   nm_utils_parse_inaddr_bin (AF_INET, *iter, &address_network)
-				    && address_network) {
-					_LOGI ("DNS: %s", *iter);
-					nm_ip4_config_add_nameserver (priv->ip4_config, address_network);
-				} else {
-					_LOGW ("invalid NameServer: %s", *iter);
-				}
+	if (!g_variant_lookup (v_dict, "DomainNameServers", "^a&s", &array)) {
+		_LOGW ("Settings 'DomainNameServers' missing");
+		goto out;
+	}
+	if (array) {
+		for (iter = array; *iter; iter++) {
+			if (   nm_utils_parse_inaddr_bin (AF_INET, *iter, &address_network)
+			    && address_network) {
+				_LOGI ("DNS: %s", *iter);
+				nm_ip4_config_add_nameserver (priv->ip4_config, address_network);
+			} else {
+				_LOGW ("invalid NameServer: %s", *iter);
 			}
+		}
 
-			if (iter == array) {
-				_LOGW ("Settings: 'DomainNameServers': none specified");
-				g_free (array);
-				goto out;
-			}
+		if (iter == array) {
+			_LOGW ("Settings: 'DomainNameServers': none specified");
 			g_free (array);
+			goto out;
 		}
-	} else {
-		_LOGW ("Settings 'DomainNameServers' missing");
-		goto out;
+		g_free (array);
 	}
 
 	if (g_variant_lookup (v_dict, "MessageProxy", "&s", &s)) {
diff --git a/src/dnsmasq/nm-dnsmasq-manager.c b/src/dnsmasq/nm-dnsmasq-manager.c
index 4ac1e7c3..323ef781 100644
--- a/src/dnsmasq/nm-dnsmasq-manager.c
+++ b/src/dnsmasq/nm-dnsmasq-manager.c
@@ -175,7 +175,8 @@ create_dm_cmd_line (const char *iface,
 	cmd = nm_cmd_line_new ();
 	nm_cmd_line_add_string (cmd, dm_binary);
 
-	if (getenv ("NM_DNSMASQ_DEBUG")) {
+	if (   nm_logging_enabled (LOGL_TRACE, LOGD_SHARING)
+	    || getenv ("NM_DNSMASQ_DEBUG")) {
 		nm_cmd_line_add_string (cmd, "--log-dhcp");
 		nm_cmd_line_add_string (cmd, "--log-queries");
 	}
diff --git a/src/nm-checkpoint-manager.c b/src/nm-checkpoint-manager.c
index 033c11cc..6da220c4 100644
--- a/src/nm-checkpoint-manager.c
+++ b/src/nm-checkpoint-manager.c
@@ -153,7 +153,23 @@ nm_checkpoint_manager_create (NMCheckpointManager *self,
 	manager = GET_MANAGER (self);
 
 	if (!device_paths || !device_paths[0]) {
-		device_paths_free = nm_manager_get_device_paths (manager);
+		const char *device_path;
+		const GSList *iter;
+		GPtrArray *paths;
+
+		paths = g_ptr_array_new ();
+		for (iter = nm_manager_get_devices (manager);
+		     iter;
+		     iter = g_slist_next (iter)) {
+			device = NM_DEVICE (iter->data);
+			if (!nm_device_is_real (device))
+				continue;
+			device_path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (device));
+			if (device_path)
+				g_ptr_array_add (paths, (gpointer) device_path);
+		}
+		g_ptr_array_add (paths, NULL);
+		device_paths_free = (const char **) g_ptr_array_free (paths, FALSE);
 		device_paths = (const char *const *) device_paths_free;
 	} else if (NM_FLAGS_HAS (flags, NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES)) {
 		g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_INVALID_ARGUMENTS,
@@ -175,10 +191,12 @@ nm_checkpoint_manager_create (NMCheckpointManager *self,
 	if (!NM_FLAGS_HAS (flags, NM_CHECKPOINT_CREATE_FLAG_DESTROY_ALL)) {
 		for (i = 0; i < devices->len; i++) {
 			device = devices->pdata[i];
-			if (find_checkpoint_for_device (self, device)) {
+			checkpoint = find_checkpoint_for_device (self, device);
+			if (checkpoint) {
 				g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_INVALID_ARGUMENTS,
-				             "a checkpoint for device '%s' already exists",
-				             nm_device_get_iface (device));
+				             "device '%s' is already included in checkpoint %s",
+				             nm_device_get_iface (device),
+				             nm_exported_object_get_path (NM_EXPORTED_OBJECT (checkpoint)));
 				return NULL;
 			}
 		}
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 3b2b4861..2766e86a 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -2589,28 +2589,6 @@ nm_manager_get_devices (NMManager *manager)
 	return NM_MANAGER_GET_PRIVATE (manager)->devices;
 }
 
-const char **
-nm_manager_get_device_paths (NMManager *self)
-{
-	const GSList *devices, *iter;
-	GPtrArray *paths;
-	const char *path;
-
-	g_return_val_if_fail (NM_IS_MANAGER (self), NULL);
-	devices = NM_MANAGER_GET_PRIVATE (self)->devices;
-	paths = g_ptr_array_new ();
-
-	for (iter = devices; iter; iter = g_slist_next (iter)) {
-		path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (iter->data));
-		if (path)
-			g_ptr_array_add (paths, (gpointer) path);
-	}
-
-	g_ptr_array_add (paths, NULL);
-
-	return (const char **) g_ptr_array_free (paths, FALSE);
-}
-
 static NMDevice *
 nm_manager_get_best_device_for_connection (NMManager *self,
                                            NMConnection *connection,
@@ -4623,8 +4601,6 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed)
 					nm_device_set_enabled (device, enabled);
 			}
 
-			nm_device_set_autoconnect_intern (device, TRUE);
-
 			nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, FALSE, NM_DEVICE_STATE_REASON_NOW_MANAGED);
 		}
 	}
diff --git a/src/nm-manager.h b/src/nm-manager.h
index 622edb5b..418c5ea9 100644
--- a/src/nm-manager.h
+++ b/src/nm-manager.h
@@ -95,7 +95,6 @@ void          nm_manager_write_device_state (NMManager *manager);
 /* Device handling */
 
 const GSList *      nm_manager_get_devices             (NMManager *manager);
-const char **       nm_manager_get_device_paths        (NMManager *self);
 
 NMDevice *          nm_manager_get_device_by_ifindex   (NMManager *manager,
                                                         int ifindex);
diff --git a/src/nm-policy.c b/src/nm-policy.c
index 3cfb1f7c..e56fce0b 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -1159,8 +1159,7 @@ activate_data_free (ActivateData *data)
 	nm_device_remove_pending_action (data->device, NM_PENDING_ACTION_AUTOACTIVATE, TRUE);
 	priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, data);
 
-	if (data->autoactivate_id)
-		g_source_remove (data->autoactivate_id);
+	nm_clear_g_source (&data->autoactivate_id);
 	g_object_unref (data->device);
 
 	g_slice_free (ActivateData, data);
@@ -1214,6 +1213,9 @@ auto_activate_device (NMPolicy *self,
 	gs_free char *specific_object = NULL;
 	gs_free NMSettingsConnection **connections = NULL;
 	guint i, len;
+	GError *error = NULL;
+	NMAuthSubject *subject;
+	NMActiveConnection *ac;
 
 	nm_assert (NM_IS_POLICY (self));
 	nm_assert (NM_IS_DEVICE (device));
@@ -1227,6 +1229,9 @@ auto_activate_device (NMPolicy *self,
 	if (nm_device_get_act_request (device))
 		return;
 
+	if (!nm_device_autoconnect_allowed (device))
+		return;
+
 	connections = nm_manager_get_activatable_connections (priv->manager, &len, TRUE);
 	if (!connections[0])
 		return;
@@ -1258,46 +1263,43 @@ auto_activate_device (NMPolicy *self,
 		}
 	}
 
-	if (best_connection) {
-		GError *error = NULL;
-		NMAuthSubject *subject;
-		NMActiveConnection *ac;
-
-		_LOGI (LOGD_DEVICE, "auto-activating connection '%s'",
-		       nm_settings_connection_get_id (best_connection));
-		subject = nm_auth_subject_new_internal ();
-		ac = nm_manager_activate_connection (priv->manager,
-		                                     best_connection,
-		                                     NULL,
-		                                     specific_object,
-		                                     device,
-		                                     subject,
-		                                     NM_ACTIVATION_TYPE_MANAGED,
-		                                     &error);
-		if (!ac) {
-			_LOGI (LOGD_DEVICE, "connection '%s' auto-activation failed: (%d) %s",
-			       nm_settings_connection_get_id (best_connection),
-			       error->code,
-			       error->message);
-			g_error_free (error);
-			nm_settings_connection_autoconnect_blocked_reason_set (best_connection,
-			                                                       NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED);
-			schedule_activate_check (self, device);
-			return;
-		}
+	if (!best_connection)
+		return;
 
-		/* Subscribe to AC state-changed signal to detect when the
-		 * activation fails in early stages without changing device
-		 * state.
-		 */
-		if (nm_g_hash_table_add (priv->pending_active_connections, ac)) {
-			g_signal_connect (ac, NM_ACTIVE_CONNECTION_STATE_CHANGED,
-			                  G_CALLBACK (pending_ac_state_changed), g_object_ref (self));
-			g_object_weak_ref (G_OBJECT (ac), (GWeakNotify) pending_ac_gone, self);
-		}
+	_LOGI (LOGD_DEVICE, "auto-activating connection '%s'",
+	       nm_settings_connection_get_id (best_connection));
+	subject = nm_auth_subject_new_internal ();
+	ac = nm_manager_activate_connection (priv->manager,
+	                                     best_connection,
+	                                     NULL,
+	                                     specific_object,
+	                                     device,
+	                                     subject,
+	                                     NM_ACTIVATION_TYPE_MANAGED,
+	                                     &error);
+	if (!ac) {
+		_LOGI (LOGD_DEVICE, "connection '%s' auto-activation failed: (%d) %s",
+		       nm_settings_connection_get_id (best_connection),
+		       error->code,
+		       error->message);
+		g_error_free (error);
+		nm_settings_connection_autoconnect_blocked_reason_set (best_connection,
+		                                                       NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED);
+		schedule_activate_check (self, device);
+		return;
+	}
 
-		g_object_unref (subject);
+	/* Subscribe to AC state-changed signal to detect when the
+	 * activation fails in early stages without changing device
+	 * state.
+	 */
+	if (nm_g_hash_table_add (priv->pending_active_connections, ac)) {
+		g_signal_connect (ac, NM_ACTIVE_CONNECTION_STATE_CHANGED,
+		                  G_CALLBACK (pending_ac_state_changed), g_object_ref (self));
+		g_object_weak_ref (G_OBJECT (ac), (GWeakNotify) pending_ac_gone, self);
 	}
+
+	g_object_unref (subject);
 }
 
 static gboolean
@@ -1465,34 +1467,6 @@ reset_autoconnect_for_failed_secrets (NMPolicy *self)
 }
 
 static void
-block_autoconnect_for_device (NMPolicy *self, NMDevice *device)
-{
-	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
-	gs_free NMSettingsConnection **connections = NULL;
-	guint i;
-
-	_LOGD (LOGD_DEVICE, "blocking autoconnect for all connections on %s",
-	       nm_device_get_iface (device));
-
-	/* NMDevice keeps its own autoconnect-able-ness state; we only need to
-	 * explicitly block connections for software devices, where the NMDevice
-	 * might be destroyed and recreated later.
-	 */
-	if (!nm_device_is_software (device))
-		return;
-
-	connections = nm_settings_get_connections_sorted (priv->settings, NULL);
-	for (i = 0; connections[i]; i++) {
-		NMSettingsConnection *connection = connections[i];
-
-		if (nm_device_check_connection_compatible (device, NM_CONNECTION (connection))) {
-			nm_settings_connection_autoconnect_blocked_reason_set (connection,
-			                                                       NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST);
-		}
-	}
-}
-
-static void
 sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
 {
 	NMPolicyPrivate *priv = user_data;
@@ -1517,9 +1491,6 @@ schedule_activate_check (NMPolicy *self, NMDevice *device)
 	if (nm_manager_get_state (priv->manager) == NM_STATE_ASLEEP)
 		return;
 
-	if (!nm_device_get_enabled (device))
-		return;
-
 	if (!nm_device_autoconnect_allowed (device))
 		return;
 
@@ -1845,17 +1816,12 @@ device_state_changed (NMDevice *device,
 		break;
 	case NM_DEVICE_STATE_DEACTIVATING:
 		if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_USER_REQUESTED) {
-			if (!nm_device_get_autoconnect (device)) {
-				/* The device was disconnected; block all connections on it */
-				block_autoconnect_for_device (self, device);
-			} else {
-				if (connection) {
-					/* The connection was deactivated, so block just this connection */
-					_LOGD (LOGD_DEVICE, "blocking autoconnect of connection '%s' by user request",
-					       nm_settings_connection_get_id (connection));
-					nm_settings_connection_autoconnect_blocked_reason_set (connection,
-					                                                       NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST);
-				}
+			if (connection) {
+				/* The connection was deactivated, so block just this connection */
+				_LOGD (LOGD_DEVICE, "blocking autoconnect of connection '%s' by user request",
+				       nm_settings_connection_get_id (connection));
+				nm_settings_connection_autoconnect_blocked_reason_set (connection,
+				                                                       NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST);
 			}
 		}
 		ip6_remove_device_prefix_delegations (self, device);
@@ -1999,8 +1965,7 @@ device_autoconnect_changed (NMDevice *device,
 	NMPolicyPrivate *priv = user_data;
 	NMPolicy *self = _PRIV_TO_SELF (priv);
 
-	if (nm_device_autoconnect_allowed (device))
-		schedule_activate_check (self, device);
+	schedule_activate_check (self, device);
 }
 
 static void
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
index 4754bea5..66add713 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
@@ -5261,8 +5261,12 @@ connection_from_file_full (const char *filename,
 		else if (!strcasecmp (devtype, TYPE_TEAM_PORT)) {
 			gs_free char *device = NULL;
 
+			type = svGetValueStr_cp (parsed, "TYPE");
 			device = svGetValueStr_cp (parsed, "DEVICE");
-			if (device && is_vlan_device (device, parsed))
+
+			if (type) {
+				/* nothing to do */
+			} else if (device && is_vlan_device (device, parsed))
 				type = g_strdup (TYPE_VLAN);
 			else
 				type = g_strdup (TYPE_ETHERNET);
@@ -5273,7 +5277,7 @@ connection_from_file_full (const char *filename,
 		gs_free char *t = NULL;
 
 		/* Team and TeamPort types are also accepted by the mere
-		 * presense of TEAM_CONFIG/TEAM_MASTER. They don't require
+		 * presence of TEAM_CONFIG/TEAM_MASTER. They don't require
 		 * DEVICETYPE. */
 		t = svGetValueStr_cp (parsed, "TEAM_CONFIG");
 		if (t)
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index d16f46be..5c8de7d1 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -1821,7 +1821,10 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
 		} else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) {
 			svSetValueStr (ifcfg, "TEAM_MASTER_UUID", master);
 			svSetValueStr (ifcfg, "TEAM_MASTER", master_iface);
-			svUnsetValue (ifcfg, "TYPE");
+			if (NM_IN_STRSET (type,
+			                  NM_SETTING_WIRED_SETTING_NAME,
+			                  NM_SETTING_VLAN_SETTING_NAME))
+				svUnsetValue (ifcfg, "TYPE");
 		}
 	}
 
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected
new file mode 100644
index 00000000..460278e1
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected
@@ -0,0 +1,9 @@
+CONNECTED_MODE=no
+TYPE=InfiniBand
+TEAM_PORT_CONFIG="{ \"inf1\": { \"prio\": -10, \"sticky\": true } }"
+NAME="Test Write Team Infiniband Port"
+UUID=${UUID}
+DEVICE=inf1
+ONBOOT=yes
+TEAM_MASTER=team0
+DEVICETYPE=TeamPort
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index 52dbd932..5044a2d7 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -8863,6 +8863,63 @@ test_write_team_port (void)
 }
 
 static void
+test_write_team_infiniband_port (void)
+{
+	nmtst_auto_unlinkfile char *testfile = NULL;
+	gs_unref_object NMConnection *connection = NULL;
+	gs_unref_object NMConnection *reread = NULL;
+	NMSettingConnection *s_con;
+	NMSettingTeamPort *s_team_port;
+	NMSettingInfiniband *s_inf;
+	const char *expected_config = "{ \"inf1\": { \"prio\": -10, \"sticky\": true } }";
+	shvarFile *f;
+
+	connection = nm_simple_connection_new ();
+
+	/* Connection setting */
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "Test Write Team Infiniband Port",
+	              NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_a (),
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_INFINIBAND_SETTING_NAME,
+	              NM_SETTING_CONNECTION_MASTER, "team0",
+	              NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_TEAM_SETTING_NAME,
+	              NM_SETTING_CONNECTION_INTERFACE_NAME, "inf1",
+	              NULL);
+
+	/* Team setting */
+	s_team_port = (NMSettingTeamPort *) nm_setting_team_port_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_team_port));
+	g_object_set (s_team_port, NM_SETTING_TEAM_PORT_CONFIG, expected_config, NULL);
+
+	/* Infiniband setting */
+	s_inf = (NMSettingInfiniband *) nm_setting_infiniband_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_inf));
+	g_object_set (s_inf, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL);
+
+	nmtst_assert_connection_verifies (connection);
+
+	_writer_new_connec_exp (connection,
+	                        TEST_SCRATCH_DIR "/network-scripts/",
+	                        TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected",
+	                        &testfile);
+
+	f = _svOpenFile (testfile);
+	_svGetValue_check (f, "TYPE", "InfiniBand");
+	_svGetValue_check (f, "DEVICETYPE", "TeamPort");
+	_svGetValue_check (f, "TEAM_PORT_CONFIG", expected_config);
+	_svGetValue_check (f, "TEAM_MASTER", "team0");
+	svCloseFile (f);
+
+	reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET,
+	                                NULL);
+
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
+}
+
+static void
 test_read_team_port_empty_config (void)
 {
 	NMConnection *connection;
@@ -9821,6 +9878,7 @@ int main (int argc, char **argv)
 	g_test_add_data_func (TPATH "team/read-port-1", TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port-1", test_read_team_port);
 	g_test_add_data_func (TPATH "team/read-port-2", TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port-2", test_read_team_port);
 	g_test_add_func (TPATH "team/write-port", test_write_team_port);
+	g_test_add_func (TPATH "team/write-infiniband-port", test_write_team_infiniband_port);
 	g_test_add_func (TPATH "team/read-port-empty-config", test_read_team_port_empty_config);
 	g_test_add_func (TPATH "team/reread-slave", test_team_reread_slave);