summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/nm-device.c5
-rw-r--r--src/devices/nm-device.h3
-rw-r--r--src/devices/ovs/nm-device-ovs-bridge.c3
-rw-r--r--src/devices/ovs/nm-device-ovs-port.c3
-rw-r--r--src/devices/wifi/nm-iwd-manager.c2
-rw-r--r--src/nm-connectivity.c95
-rw-r--r--src/nm-manager.c16
-rw-r--r--src/platform/nm-netlink.h4
-rw-r--r--src/ppp/nm-ppp-manager.c6
9 files changed, 87 insertions, 50 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 5a5cb50e..19e43762 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -10225,6 +10225,8 @@ _cleanup_ip_pre (NMDevice *self, int addr_family, CleanupType cleanup_type)
 		arp_cleanup (self);
 		dnsmasq_cleanup (self);
 		ipv4ll_cleanup (self);
+		g_slist_free_full (priv->acd.dad_list, (GDestroyNotify) nm_acd_manager_destroy);
+		priv->acd.dad_list = NULL;
 	} else {
 		g_slist_free_full (priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref);
 		priv->dad6_failed_addrs = NULL;
@@ -15393,9 +15395,6 @@ dispose (GObject *object)
 	g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self);
 	g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self);
 
-	g_slist_free_full (priv->acd.dad_list, (GDestroyNotify) nm_acd_manager_destroy);
-	priv->acd.dad_list = NULL;
-
 	arp_cleanup (self);
 
 	nm_clear_g_signal_handler (nm_config_get (), &priv->config_changed_id);
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index 010a0521..d145f8fc 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -120,7 +120,8 @@ nm_device_state_reason_check (NMDeviceStateReason reason)
 #define NM_DEVICE_PARENT           "parent"
 
 /* the "slaves" property is internal in the parent class, but exposed
- * by the derived classes NMDeviceBond, NMDeviceBridge and NMDeviceTeam. */
+ * by the derived classes NMDeviceBond, NMDeviceBridge, NMDeviceTeam,
+ * NMDeviceOvsBridge and NMDeviceOvsPort. */
 #define NM_DEVICE_SLAVES           "slaves"         /* partially internal */
 
 #define NM_DEVICE_TYPE_DESC        "type-desc"      /* Internal only */
diff --git a/src/devices/ovs/nm-device-ovs-bridge.c b/src/devices/ovs/nm-device-ovs-bridge.c
index 5244ca8b..2e4d1cbd 100644
--- a/src/devices/ovs/nm-device-ovs-bridge.c
+++ b/src/devices/ovs/nm-device-ovs-bridge.c
@@ -134,6 +134,9 @@ nm_device_ovs_bridge_init (NMDeviceOvsBridge *self)
 static const NMDBusInterfaceInfoExtended interface_info_device_ovs_bridge = {
 	.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (
 		NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE,
+		.properties = NM_DEFINE_GDBUS_PROPERTY_INFOS (
+			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Slaves", "ao", NM_DEVICE_SLAVES),
+		),
 		.signals = NM_DEFINE_GDBUS_SIGNAL_INFOS (
 			&nm_signal_info_property_changed_legacy,
 		),
diff --git a/src/devices/ovs/nm-device-ovs-port.c b/src/devices/ovs/nm-device-ovs-port.c
index 91cf4f4d..a9a2b24a 100644
--- a/src/devices/ovs/nm-device-ovs-port.c
+++ b/src/devices/ovs/nm-device-ovs-port.c
@@ -180,6 +180,9 @@ nm_device_ovs_port_init (NMDeviceOvsPort *self)
 static const NMDBusInterfaceInfoExtended interface_info_device_ovs_port = {
 	.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (
 		NM_DBUS_INTERFACE_DEVICE_OVS_PORT,
+		.properties = NM_DEFINE_GDBUS_PROPERTY_INFOS (
+			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Slaves", "ao", NM_DEVICE_SLAVES),
+		),
 		.signals = NM_DEFINE_GDBUS_SIGNAL_INFOS (
 			&nm_signal_info_property_changed_legacy,
 		),
diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c
index 0f95fa08..d6511296 100644
--- a/src/devices/wifi/nm-iwd-manager.c
+++ b/src/devices/wifi/nm-iwd-manager.c
@@ -586,7 +586,7 @@ prepare_object_manager (NMIwdManager *self)
 	NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
 
 	g_dbus_object_manager_client_new_for_bus (NM_IWD_BUS_TYPE,
-	                                          G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START,
+	                                          G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
 	                                          NM_IWD_SERVICE, "/",
 	                                          NULL, NULL, NULL,
 	                                          priv->cancellable,
diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c
index 389e72ad..1ce6d3cf 100644
--- a/src/nm-connectivity.c
+++ b/src/nm-connectivity.c
@@ -195,7 +195,7 @@ cb_data_free (NMConnectivityCheckHandle *cb_data,
 		 * the easy handle "at any moment"; specifically not from the
 		 * write function. Thus here we just dissociate the cb_data from
 		 * the easy handle and the easy handle will be cleaned up when the
-		 * message goes to CURLMSG_DONE in curl_check_connectivity(). */
+		 * message goes to CURLMSG_DONE in _con_curl_check_connectivity(). */
 		curl_easy_setopt (cb_data->concheck.curl_ehandle, CURLOPT_WRITEFUNCTION, NULL);
 		curl_easy_setopt (cb_data->concheck.curl_ehandle, CURLOPT_WRITEDATA, NULL);
 		curl_easy_setopt (cb_data->concheck.curl_ehandle, CURLOPT_HEADERFUNCTION, NULL);
@@ -234,8 +234,8 @@ _check_handle_get_response (NMConnectivityCheckHandle *cb_data)
 	return cb_data->concheck.response ?: NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE;
 }
 
-static void
-curl_check_connectivity (CURLM *mhandle, int sockfd, int ev_bitmask)
+static gboolean
+_con_curl_check_connectivity (CURLM *mhandle, int sockfd, int ev_bitmask)
 {
 	NMConnectivityCheckHandle *cb_data;
 	CURLMsg *msg;
@@ -244,10 +244,13 @@ curl_check_connectivity (CURLM *mhandle, int sockfd, int ev_bitmask)
 	long response_code;
 	CURLMcode ret;
 	int running_handles;
+	gboolean success = TRUE;
 
 	ret = curl_multi_socket_action (mhandle, sockfd, ev_bitmask, &running_handles);
-	if (ret != CURLM_OK)
-		_LOGE ("connectivity check failed: %d", ret);
+	if (ret != CURLM_OK) {
+		_LOGD ("connectivity check failed: %d", ret);
+		success = FALSE;
+	}
 
 	while ((msg = curl_multi_info_read (mhandle, &m_left))) {
 
@@ -257,7 +260,8 @@ curl_check_connectivity (CURLM *mhandle, int sockfd, int ev_bitmask)
 		/* Here we have completed a session. Check easy session result. */
 		eret = curl_easy_getinfo (msg->easy_handle, CURLINFO_PRIVATE, (char **) &cb_data);
 		if (eret != CURLE_OK) {
-			_LOGE ("curl cannot extract cb_data for easy handle, skipping msg");
+			_LOGD ("curl cannot extract cb_data for easy handle, skipping msg");
+			success = FALSE;
 			continue;
 		}
 
@@ -286,16 +290,22 @@ curl_check_connectivity (CURLM *mhandle, int sockfd, int ev_bitmask)
 			              "unexpected short response");
 		}
 	}
+
+	/* if we return a failure, we don't know what went wrong. It's likely serious, because
+	 * a failure here is not expected. Return FALSE, so that we stop polling the file descriptor.
+	 * Worst case, this leaves the pending connectivity check unhandled, until our regular
+	 * time-out kicks in. */
+	return success;
 }
 
 static gboolean
-curl_timeout_cb (gpointer user_data)
+_con_curl_timeout_cb (gpointer user_data)
 {
 	gs_unref_object NMConnectivity *self = g_object_ref (NM_CONNECTIVITY (user_data));
 	NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
 
 	priv->concheck.curl_timer = 0;
-	curl_check_connectivity (priv->concheck.curl_mhandle, CURL_SOCKET_TIMEOUT, 0);
+	_con_curl_check_connectivity (priv->concheck.curl_mhandle, CURL_SOCKET_TIMEOUT, 0);
 	return G_SOURCE_REMOVE;
 }
 
@@ -307,17 +317,34 @@ multi_timer_cb (CURLM *multi, long timeout_ms, void *userdata)
 
 	nm_clear_g_source (&priv->concheck.curl_timer);
 	if (timeout_ms != -1)
-		priv->concheck.curl_timer = g_timeout_add (timeout_ms, curl_timeout_cb, self);
+		priv->concheck.curl_timer = g_timeout_add (timeout_ms, _con_curl_timeout_cb, self);
 	return 0;
 }
 
+typedef struct {
+	NMConnectivity *self;
+	GIOChannel *ch;
+
+	/* this is a very simplistic weak-pointer. If ConCurlSockData gets
+	 * destroyed, it will set *destroy_notify to TRUE.
+	 *
+	 * _con_curl_socketevent_cb() uses this to detect whether it can
+	 * safely access @fdp after _con_curl_check_connectivity(). */
+	gboolean *destroy_notify;
+
+	guint ev;
+} ConCurlSockData;
+
 static gboolean
-curl_socketevent_cb (GIOChannel *ch, GIOCondition condition, gpointer user_data)
+_con_curl_socketevent_cb (GIOChannel *ch, GIOCondition condition, gpointer user_data)
 {
-	gs_unref_object NMConnectivity *self = g_object_ref (NM_CONNECTIVITY (user_data));
+	ConCurlSockData *fdp = user_data;
+	gs_unref_object NMConnectivity *self = g_object_ref (fdp->self);
 	NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
 	int fd = g_io_channel_unix_get_fd (ch);
 	int action = 0;
+	gboolean fdp_destroyed = FALSE;
+	gboolean success;
 
 	if (condition & G_IO_IN)
 		action |= CURL_CSELECT_IN;
@@ -326,35 +353,49 @@ curl_socketevent_cb (GIOChannel *ch, GIOCondition condition, gpointer user_data)
 	if (condition & G_IO_ERR)
 		action |= CURL_CSELECT_ERR;
 
-	curl_check_connectivity (priv->concheck.curl_mhandle, fd, action);
-	return G_SOURCE_CONTINUE;
-}
+	nm_assert (!fdp->destroy_notify);
+	fdp->destroy_notify = &fdp_destroyed;
 
-typedef struct {
-	GIOChannel *ch;
-	guint ev;
-} CurlSockData;
+	success = _con_curl_check_connectivity (priv->concheck.curl_mhandle, fd, action);
+
+	if (fdp_destroyed) {
+		/* hups. fdp got invalidated during _con_curl_check_connectivity(). That's fine,
+		 * just don't touch it. */
+	} else {
+		nm_assert (fdp->destroy_notify == &fdp_destroyed);
+		fdp->destroy_notify = NULL;
+		if (!success)
+			fdp->ev = 0;
+	}
+
+	return success ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE;
+}
 
 static int
-multi_socket_cb (CURL *e_handle, curl_socket_t s, int what, void *userdata, void *socketp)
+multi_socket_cb (CURL *e_handle, curl_socket_t fd, int what, void *userdata, void *socketp)
 {
 	NMConnectivity *self = NM_CONNECTIVITY (userdata);
 	NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
-	CurlSockData *fdp = socketp;
+	ConCurlSockData *fdp = socketp;
 	GIOCondition condition = 0;
 
+	(void) _NM_ENSURE_TYPE (int, fd);
+
 	if (what == CURL_POLL_REMOVE) {
 		if (fdp) {
-			curl_multi_assign (priv->concheck.curl_mhandle, s, NULL);
+			if (fdp->destroy_notify)
+				*fdp->destroy_notify = TRUE;
+			curl_multi_assign (priv->concheck.curl_mhandle, fd, NULL);
 			nm_clear_g_source (&fdp->ev);
 			g_io_channel_unref (fdp->ch);
-			g_slice_free (CurlSockData, fdp);
+			g_slice_free (ConCurlSockData, fdp);
 		}
 	} else {
 		if (!fdp) {
-			fdp = g_slice_new0 (CurlSockData);
-			fdp->ch = g_io_channel_unix_new (s);
-			curl_multi_assign (priv->concheck.curl_mhandle, s, fdp);
+			fdp = g_slice_new0 (ConCurlSockData);
+			fdp->self = self;
+			fdp->ch = g_io_channel_unix_new (fd);
+			curl_multi_assign (priv->concheck.curl_mhandle, fd, fdp);
 		} else
 			nm_clear_g_source (&fdp->ev);
 
@@ -366,7 +407,7 @@ multi_socket_cb (CURL *e_handle, curl_socket_t s, int what, void *userdata, void
 			condition = G_IO_IN | G_IO_OUT;
 
 		if (condition)
-			fdp->ev = g_io_add_watch (fdp->ch, condition, curl_socketevent_cb, self);
+			fdp->ev = g_io_add_watch (fdp->ch, condition, _con_curl_socketevent_cb, fdp);
 	}
 
 	return CURLM_OK;
@@ -576,7 +617,7 @@ update_config (NMConnectivity *self, NMConfigData *config_data)
 		} else if (strcasecmp (scheme, "https") == 0) {
 			_LOGW ("use of HTTPS for connectivity checking is not reliable and is discouraged (URI: %s)", uri);
 		} else if (strcasecmp (scheme, "http") != 0) {
-			_LOGE ("scheme of '%s' uri does't use a scheme that is allowed for connectivity check.", uri);
+			_LOGE ("scheme of '%s' uri doesn't use a scheme that is allowed for connectivity check.", uri);
 			uri = NULL;
 		}
 
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 0fea13de..289dcf83 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -4611,21 +4611,7 @@ validate_activation_request (NMManager *self,
 		}
 	}
 
-	if (is_vpn && device) {
-		/* VPN's are treated specially. Maybe the should accept a device as well,
-		 * however, later on during activation, we don't handle the device.
-		 *
-		 * Maybe we should, and maybe it makes sense to specify a device
-		 * when activating a VPN. But for now, just error out.  */
-		g_set_error_literal (error,
-		                     NM_MANAGER_ERROR,
-		                     NM_MANAGER_ERROR_UNKNOWN_DEVICE,
-		                     "Cannot specify device when activating VPN");
-		return NULL;
-	}
-
-	nm_assert (   ( is_vpn && !device)
-	           || (!is_vpn && NM_IS_DEVICE (device)));
+	nm_assert (is_vpn || NM_IS_DEVICE (device));
 
 	*out_device = device;
 	*out_is_vpn = is_vpn;
diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h
index b938fa4a..185269ba 100644
--- a/src/platform/nm-netlink.h
+++ b/src/platform/nm-netlink.h
@@ -225,8 +225,8 @@ nla_put_string (struct nl_msg *msg, int attrtype, const char *str)
 
 #define NLA_PUT_TYPE(msg, type, attrtype, value) \
 	do { \
-		type __tmp = value; \
-		NLA_PUT(msg, attrtype, sizeof(type), &__tmp); \
+		type __nla_tmp = value; \
+		NLA_PUT(msg, attrtype, sizeof(type), &__nla_tmp); \
 	} while(0)
 
 #define NLA_PUT_U8(msg, attrtype, value) \
diff --git a/src/ppp/nm-ppp-manager.c b/src/ppp/nm-ppp-manager.c
index fc658bec..5e893c85 100644
--- a/src/ppp/nm-ppp-manager.c
+++ b/src/ppp/nm-ppp-manager.c
@@ -809,7 +809,11 @@ create_pppd_cmd_line (NMPPPManager *self,
 
 	g_return_val_if_fail (setting != NULL, NULL);
 
-	pppd_binary = nm_utils_find_helper ("pppd", NULL, err);
+#ifndef PPPD_PATH
+#define PPPD_PATH NULL
+#endif
+
+	pppd_binary = nm_utils_find_helper ("pppd", PPPD_PATH, err);
 	if (!pppd_binary)
 		return NULL;