summary refs log tree commit diff
path: root/src/ppp-manager/nm-ppp-manager.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2011-04-21 10:42:53 +0200
committerMichael Biebl <biebl@debian.org>2011-04-21 10:42:53 +0200
commit8baa1aca8dfd35e3190d7d5655eb83b5b901e263 (patch)
treea9ac1e67d0c22a48330c76f08fc5291f85307055 /src/ppp-manager/nm-ppp-manager.c
parentf75dd6fd1975146623052b843b182dc32c3fbe46 (diff)
Imported Upstream version 0.8.4.0 upstream/0.8.4.0
Diffstat (limited to 'src/ppp-manager/nm-ppp-manager.c')
-rw-r--r--src/ppp-manager/nm-ppp-manager.c259
1 files changed, 126 insertions, 133 deletions
diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
index 41b5ef1a..1258b8f6 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -66,10 +66,14 @@ static gboolean impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
 
 #include "nm-ppp-manager-glue.h"
 
+static void _ppp_cleanup  (NMPPPManager *manager);
+
 #define NM_PPPD_PLUGIN PLUGINDIR "/nm-pppd-plugin.so"
 #define PPP_MANAGER_SECRET_TRIES "ppp-manager-secret-tries"
 
 typedef struct {
+	gboolean disposed;
+
 	GPid pid;
 	NMDBusManager *dbus_manager;
 	char *dbus_path;
@@ -78,7 +82,6 @@ typedef struct {
 
 	NMActRequest *act_req;
 	DBusGMethodInvocation *pending_secrets_context;
-	guint32 secrets_id;
 
 	guint32 ppp_watch_id;
 	guint32 ppp_timeout_handler;
@@ -164,11 +167,19 @@ dispose (GObject *object)
 {
 	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (object);
 
-	nm_ppp_manager_stop (NM_PPP_MANAGER (object));
+	if (priv->disposed == FALSE) {
+		priv->disposed = TRUE;
+
+		_ppp_cleanup (NM_PPP_MANAGER (object));
 
-	if (priv->act_req)
-		g_object_unref (priv->act_req);
-	g_object_unref (priv->dbus_manager);
+		if (priv->act_req) {
+			g_object_unref (priv->act_req);
+			priv->act_req = NULL;
+		}
+
+		g_object_unref (priv->dbus_manager);
+		priv->dbus_manager = NULL;
+	}
 
 	G_OBJECT_CLASS (nm_ppp_manager_parent_class)->dispose (object);
 }
@@ -192,7 +203,8 @@ set_property (GObject *object, guint prop_id,
 
 	switch (prop_id) {
 	case PROP_PARENT_IFACE:
-		g_free (priv->parent_iface);
+		if (priv->parent_iface)
+			g_free (priv->parent_iface);
 		priv->parent_iface = g_value_dup_string (value);
 		break;
 	default:
@@ -315,9 +327,12 @@ monitor_stats (NMPPPManager *manager)
 	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
 
 	priv->monitor_fd = socket (AF_INET, SOCK_DGRAM, 0);
-	if (priv->monitor_fd > 0)
+	if (priv->monitor_fd > 0) {
+		g_warn_if_fail (priv->monitor_id == 0);
+		if (priv->monitor_id)
+			g_source_remove (priv->monitor_id);
 		priv->monitor_id = g_timeout_add_seconds (5, monitor_cb, manager);
-	else
+	} else
 		nm_log_warn (LOGD_PPP, "could not monitor PPP stats: %s", strerror (errno));
 }
 
@@ -335,147 +350,87 @@ remove_timeout_handler (NMPPPManager *manager)
 }
 
 static void
-cancel_get_secrets (NMPPPManager *self)
-{
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
-
-	if (priv->secrets_id) {
-		nm_act_request_cancel_secrets (priv->act_req, priv->secrets_id);
-		priv->secrets_id = 0;
-	}
-}
-
-static gboolean
-extract_details_from_connection (NMConnection *connection,
-                                 const char **username,
-                                 const char **password,
-                                 GError **error)
-{
-	NMSettingConnection *s_con;
-	NMSetting *setting;
-	const char *connection_type;
-
-	g_return_val_if_fail (connection != NULL, FALSE);
-	g_return_val_if_fail (username != NULL, FALSE);
-	g_return_val_if_fail (password != NULL, FALSE);
-
-	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
-	g_assert (s_con);
-
-	connection_type = nm_setting_connection_get_connection_type (s_con);
-	g_assert (connection_type);
-
-	setting = nm_connection_get_setting_by_name (connection, connection_type);
-	if (!setting) {
-		g_set_error_literal (error, NM_PPP_MANAGER_ERROR, NM_PPP_MANAGER_ERROR_UNKOWN,
-		                     "Missing type-specific setting; no secrets could be found.");
-		return FALSE;
-	}
-
-	/* FIXME: push this down to the settings and keep PPP manager generic */
-	if (NM_IS_SETTING_PPPOE (setting)) {
-		*username = nm_setting_pppoe_get_username (NM_SETTING_PPPOE (setting));
-		*password = nm_setting_pppoe_get_password (NM_SETTING_PPPOE (setting));
-	} else if (NM_IS_SETTING_GSM (setting)) {
-		*username = nm_setting_gsm_get_username (NM_SETTING_GSM (setting));
-		*password = nm_setting_gsm_get_password (NM_SETTING_GSM (setting));
-	} else if (NM_IS_SETTING_CDMA (setting)) {
-		*username = nm_setting_cdma_get_username (NM_SETTING_CDMA (setting));
-		*password = nm_setting_cdma_get_password (NM_SETTING_CDMA (setting));
-	}
-
-	return TRUE;
-}
-
-static void
-ppp_secrets_cb (NMActRequest *req,
-                guint32 call_id,
-                NMConnection *connection,
-                GError *error,
-                gpointer user_data)
-{
-	NMPPPManager *self = NM_PPP_MANAGER (user_data);
-	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
-	const char *username = NULL;
-	const char *password = NULL;
-	GError *local = NULL;
-
-	g_return_if_fail (priv->pending_secrets_context != NULL);
-	g_return_if_fail (req == priv->act_req);
-	g_return_if_fail (call_id == priv->secrets_id);
-
-	if (error) {
-		nm_log_warn (LOGD_PPP, "%s", error->message);
-		dbus_g_method_return_error (priv->pending_secrets_context, error);
-		goto out;
-	}
-
-	if (!extract_details_from_connection (connection, &username, &password, &local)) {
-		nm_log_warn (LOGD_PPP, "%s", local->message);
-		dbus_g_method_return_error (priv->pending_secrets_context, local);
-		g_clear_error (&local);
-		goto out;
-	}
-
-	/* This is sort of a hack but...
-	 * pppd plugin only ever needs username and password. Passing the full
-	 * connection there would mean some bloat: the plugin would need to link
-	 * against libnm-util just to parse this. So instead, let's just send what
-	 * it needs.
-	 */
-	dbus_g_method_return (priv->pending_secrets_context, username, password);
-
-out:
-	priv->pending_secrets_context = NULL;
-	priv->secrets_id = 0;
-}
-
-static void
 impl_ppp_manager_need_secrets (NMPPPManager *manager,
                                DBusGMethodInvocation *context)
 {
 	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
 	NMConnection *connection;
+	NMSettingConnection *s_con;
+	const char *connection_type;
 	const char *setting_name;
-	const char *username = NULL;
-	const char *password = NULL;
 	guint32 tries;
 	GPtrArray *hints = NULL;
-	GError *error = NULL;
-	NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION;
+	const char *hint1 = NULL, *hint2 = NULL;
 
 	connection = nm_act_request_get_connection (priv->act_req);
 
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
+
+	connection_type = nm_setting_connection_get_connection_type (s_con);
+	g_assert (connection_type);
+
 	nm_connection_clear_secrets (connection);
 	setting_name = nm_connection_need_secrets (connection, &hints);
 	if (!setting_name) {
-		/* Use existing secrets from the connection */
-		if (extract_details_from_connection (connection, &username, &password, &error)) {
-			/* Send existing secrets to the PPP plugin */
+		NMSetting *setting;
+
+		setting = nm_connection_get_setting_by_name (connection, connection_type);
+		if (setting) {
+			const char *username = NULL;
+			const char *password = NULL;
+
+			/* FIXME: push this down to the settings and keep PPP manager generic */
+			if (NM_IS_SETTING_PPPOE (setting)) {
+				username = nm_setting_pppoe_get_username (NM_SETTING_PPPOE (setting));
+				password = nm_setting_pppoe_get_password (NM_SETTING_PPPOE (setting));
+			} else if (NM_IS_SETTING_GSM (setting)) {
+				username = nm_setting_gsm_get_username (NM_SETTING_GSM (setting));
+				password = nm_setting_gsm_get_password (NM_SETTING_GSM (setting));
+			} else if (NM_IS_SETTING_CDMA (setting)) {
+				username = nm_setting_cdma_get_username (NM_SETTING_CDMA (setting));
+				password = nm_setting_cdma_get_password (NM_SETTING_CDMA (setting));
+			}
+
+			/* If secrets are not required, send the existing username and password
+			 * back to the PPP plugin immediately.
+			 */
 			priv->pending_secrets_context = context;
-			ppp_secrets_cb (priv->act_req, priv->secrets_id, connection, NULL, manager);
+			nm_ppp_manager_update_secrets (manager,
+			                               priv->parent_iface,
+			                               username ? username : "",
+			                               password ? password : "",
+			                               NULL);
 		} else {
-			nm_log_warn (LOGD_PPP, "%s", error->message);
-			dbus_g_method_return_error (priv->pending_secrets_context, error);
-			g_clear_error (&error);
+			GError *err = NULL;
+
+			g_set_error (&err, NM_PPP_MANAGER_ERROR, NM_PPP_MANAGER_ERROR_UNKOWN,
+			             "Missing type-specific setting; no secrets could be found.");
+			nm_log_warn (LOGD_PPP, "%s", err->message);
+			dbus_g_method_return_error (context, err);
 		}
 		return;
 	}
 
-	/* Only ask for completely new secrets after retrying them once; some devices
-	 * appear to ask a few times when they actually don't even care what you
-	 * pass back.
-	 */
+	/* Extract hints */
+	if (hints) {
+		if (hints->len > 0)
+			hint1 = g_ptr_array_index (hints, 0);
+		if (hints->len > 1)
+			hint2 = g_ptr_array_index (hints, 1);
+	}
+
 	tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), PPP_MANAGER_SECRET_TRIES));
-	if (tries > 1)
-		flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW;
-
-	priv->secrets_id = nm_act_request_get_secrets (priv->act_req,
-	                                               setting_name,
-	                                               flags,
-	                                               hints ? g_ptr_array_index (hints, 0) : NULL,
-	                                               ppp_secrets_cb,
-	                                               manager);
+	/* Only ask for completely new secrets after retrying them once; some PPP
+	 * servers (T-Mobile USA) appear to ask a few times when they actually don't
+	 * even care what you pass back.
+	 */
+	nm_act_request_get_secrets (priv->act_req,
+	                            setting_name,
+	                            tries > 1 ? TRUE : FALSE,
+	                            SECRETS_CALLER_PPP,
+	                            hint1,
+	                            hint2);
 	g_object_set_data (G_OBJECT (connection), PPP_MANAGER_SECRET_TRIES, GUINT_TO_POINTER (++tries));
 	priv->pending_secrets_context = context;
 
@@ -766,7 +721,7 @@ pppd_timed_out (gpointer data)
 	NMPPPManager *manager = NM_PPP_MANAGER (data);
 
 	nm_log_warn (LOGD_PPP, "pppd timed out or didn't initialize our dbus module");
-	nm_ppp_manager_stop (manager);
+	_ppp_cleanup (manager);
 
 	g_signal_emit (manager, signals[STATE_CHANGED], 0, NM_PPP_STATUS_DEAD);
 
@@ -1027,6 +982,46 @@ nm_ppp_manager_start (NMPPPManager *manager,
 	return priv->pid > 0;
 }
 
+void
+nm_ppp_manager_update_secrets (NMPPPManager *manager,
+                               const char *device,
+                               const char *username,
+                               const char *password,
+                               const char *error_message)
+{
+	NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+
+	g_return_if_fail (NM_IS_PPP_MANAGER (manager));
+	g_return_if_fail (device != NULL);
+	g_return_if_fail (priv->pending_secrets_context != NULL);
+
+	if (error_message) {
+		g_return_if_fail (username == NULL);
+		g_return_if_fail (password == NULL);
+	} else {
+		g_return_if_fail (username != NULL);
+		g_return_if_fail (password != NULL);
+	}
+
+	if (error_message) {
+		GError *err = NULL;
+
+		g_set_error (&err, NM_PPP_MANAGER_ERROR, NM_PPP_MANAGER_ERROR_UNKOWN, "%s", error_message);
+		nm_log_warn (LOGD_PPP, "%s", error_message);
+		dbus_g_method_return_error (priv->pending_secrets_context, err);
+		g_error_free (err);
+	} else {
+		/* This is sort of a hack but...
+		   pppd plugin only ever needs username and password.
+		   Passing the full connection there would mean some bloat:
+		   the plugin would need to link against libnm-util just to parse this.
+		   So instead, let's just send what it needs */
+
+		dbus_g_method_return (priv->pending_secrets_context, username, password);
+	}
+	priv->pending_secrets_context = NULL;
+}
+
 static gboolean
 ensure_killed (gpointer data)
 {
@@ -1043,8 +1038,8 @@ ensure_killed (gpointer data)
 	return FALSE;
 }
 
-void
-nm_ppp_manager_stop (NMPPPManager *manager)
+static void
+_ppp_cleanup (NMPPPManager *manager)
 {
 	NMPPPManagerPrivate *priv;
 
@@ -1052,8 +1047,6 @@ nm_ppp_manager_stop (NMPPPManager *manager)
 
 	priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
 
-	cancel_get_secrets (manager);
-
 	if (priv->monitor_id) {
 		g_source_remove (priv->monitor_id);
 		priv->monitor_id = 0;