summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Niemueller <tim@niemueller.de>2006-08-19 15:13:02 +0000
committerTim Niemueller <tim@niemueller.de>2006-08-19 15:13:02 +0000
commit6a72c7ff0d988b40e031aa8ec2e655e51d2805d0 (patch)
treee07a04e6e2937eb0f6514bd341085b91d5268fa8
parent160f524eab0e5c8ae49ca30bdc4befad10e19b68 (diff)
downloadNetworkManager-6a72c7ff0d988b40e031aa8ec2e655e51d2805d0.tar.gz
2006-08-19 Tim Niemueller <tim@niemueller.de>
* src/dialup/manager/*: Added new dialup manager, full ability to start and control connections git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/branches/SoC_2006@1972 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
-rw-r--r--src/dialup/manager/.cvsignore2
-rw-r--r--src/dialup/manager/Makefile.am42
-rw-r--r--src/dialup/manager/nm-dbus-dialup.c672
-rw-r--r--src/dialup/manager/nm-dbus-dialup.h40
-rw-r--r--src/dialup/manager/nm-dialup-act-request.c245
-rw-r--r--src/dialup/manager/nm-dialup-act-request.h61
-rw-r--r--src/dialup/manager/nm-dialup-connection.c227
-rw-r--r--src/dialup/manager/nm-dialup-connection.h44
-rw-r--r--src/dialup/manager/nm-dialup-manager.c640
-rw-r--r--src/dialup/manager/nm-dialup-manager.h56
-rw-r--r--src/dialup/manager/nm-dialup-service.c1087
-rw-r--r--src/dialup/manager/nm-dialup-service.h61
12 files changed, 3177 insertions, 0 deletions
diff --git a/src/dialup/manager/.cvsignore b/src/dialup/manager/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/src/dialup/manager/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/src/dialup/manager/Makefile.am b/src/dialup/manager/Makefile.am
new file mode 100644
index 0000000000..d7295aaec4
--- /dev/null
+++ b/src/dialup/manager/Makefile.am
@@ -0,0 +1,42 @@
+INCLUDES = -I${top_srcdir} \
+ -I${top_srcdir}/include \
+ -I${top_srcdir}/utils \
+ -I${top_srcdir}/src \
+ -I${top_srcdir}/src/named-manager
+
+
+noinst_LTLIBRARIES = libdialup-manager.la
+
+libdialup_manager_la_SOURCES = \
+ nm-dialup-manager.h \
+ nm-dialup-manager.c \
+ nm-dialup-connection.h \
+ nm-dialup-connection.c \
+ nm-dbus-dialup.h \
+ nm-dbus-dialup.c \
+ nm-dialup-service.h \
+ nm-dialup-service.c \
+ nm-dialup-act-request.h \
+ nm-dialup-act-request.c
+
+libdialup_manager_la_LIBADD = $(DBUS_LIBS) $(GTHREAD_LIBS)
+
+AM_CPPFLAGS = \
+ $(DBUS_CFLAGS) \
+ $(GTHREAD_CFLAGS) \
+ $(HAL_CFLAGS) \
+ -Wall \
+ -DDBUS_API_SUBJECT_TO_CHANGE \
+ -DG_DISABLE_DEPRECATED \
+ -DBINDIR=\"$(bindir)\" \
+ -DPREFIX=\""$(prefix)"\" \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ -DVERSION="\"$(VERSION)\"" \
+ -DLIBDIR=\""$(libdir)"\" \
+ -DLIBEXECDIR=\""$(libexecdir)"\" \
+ -DLOCALSTATEDIR=\""$(localstatedir)"\" \
+ -DDATADIR=\"$(datadir)\" \
+ -fPIC
+
+CLEANFILES = *~
+
diff --git a/src/dialup/manager/nm-dbus-dialup.c b/src/dialup/manager/nm-dbus-dialup.c
new file mode 100644
index 0000000000..50c5c47aa0
--- /dev/null
+++ b/src/dialup/manager/nm-dbus-dialup.c
@@ -0,0 +1,672 @@
+/* NetworkManager -- Network link manager
+ *
+ * Tim Niemueller [www.niemueller.de]
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2005 Red Hat, Inc.
+ * (C) Copyright 2006 Tim Niemueller
+ */
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include "NetworkManagerMain.h"
+#include "nm-device.h"
+#include "NetworkManagerDbus.h"
+#include "NetworkManagerUtils.h"
+#include "NetworkManagerDialup.h"
+#include "nm-dbus-dialup.h"
+#include "nm-dialup-manager.h"
+#include "nm-dialup-connection.h"
+#include "nm-dialup-service.h"
+#include "nm-dialup-act-request.h"
+#include "nm-utils.h"
+
+
+/*
+ * nm_dbus_dialup_signal_dialup_connection_update
+ *
+ * Notifies the bus that a Dialup connection's properties have changed.
+ *
+ */
+void nm_dbus_dialup_signal_dialup_connection_update (DBusConnection *con, NMDialupConnection *dialup, const char *signal)
+{
+ DBusMessage *message;
+ const char *dialup_name;
+
+ g_return_if_fail (con != NULL);
+ g_return_if_fail (dialup != NULL);
+
+ if (!(message = dbus_message_new_signal (NM_DBUS_PATH_DIALUP, NM_DBUS_INTERFACE_DIALUP, signal)))
+ {
+ nm_warning ("Not enough memory for new dbus message!");
+ return;
+ }
+
+ dialup_name = nm_dialup_connection_get_name (dialup);
+
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &dialup_name, DBUS_TYPE_INVALID);
+ if (!dbus_connection_send (con, message, NULL))
+ nm_warning ("Could not raise the %s signal!", signal);
+
+ dbus_message_unref (message);
+}
+
+/*
+ * nm_dbus_dialup_signal_dialup_connection_state_change
+ *
+ * Notifies the bus that a dialup connection's state has changed.
+ */
+void nm_dbus_dialup_signal_dialup_connection_state_change (DBusConnection *con, NMDialupConnection *dialup, NMDialupActStage new_stage)
+{
+ DBusMessage * message;
+ const char * dialup_name;
+ dbus_uint32_t int_stage = (dbus_uint32_t) new_stage;
+
+ g_return_if_fail (con != NULL);
+ g_return_if_fail (dialup != NULL);
+
+ if (!(message = dbus_message_new_signal (NM_DBUS_PATH_DIALUP, NM_DBUS_INTERFACE_DIALUP, "DialupConnectionStateChange")))
+ {
+ nm_warning ("Not enough memory for new dbus message!");
+ return;
+ }
+
+ dialup_name = nm_dialup_connection_get_name (dialup);
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &dialup_name, DBUS_TYPE_UINT32, &int_stage, DBUS_TYPE_INVALID);
+ if (!dbus_connection_send (con, message, NULL))
+ nm_warning ("Could not raise the DialupConnectionStateChange signal!");
+
+ dbus_message_unref (message);
+}
+
+
+/*
+ * nnm_dbus_dialup_signal_dialup_failure
+ *
+ * Proxy a Dialup Failure message from the dialup daemon to the bus.
+ *
+ */
+void nm_dbus_dialup_signal_dialup_failed (DBusConnection *con, const char *signal, NMDialupConnection *dialup, const char *error_msg)
+{
+ DBusMessage *message;
+ const char *dialup_name;
+
+ g_return_if_fail (con != NULL);
+ g_return_if_fail (signal != NULL);
+ g_return_if_fail (dialup != NULL);
+ g_return_if_fail (error_msg != NULL);
+
+ if (!(message = dbus_message_new_signal (NM_DBUS_PATH_DIALUP, NM_DBUS_INTERFACE_DIALUP, signal)))
+ {
+ nm_warning ("Not enough memory for new dbus message!");
+ return;
+ }
+
+ dialup_name = nm_dialup_connection_get_name (dialup);
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &dialup_name, DBUS_TYPE_STRING, &error_msg, DBUS_TYPE_INVALID);
+ if (!dbus_connection_send (con, message, NULL))
+ nm_warning ("Could not raise the %s signal!", signal);
+
+ dbus_message_unref (message);
+}
+
+
+/*
+ * nm_dbus_dialup_get_dialup_data
+ *
+ * Get dialup specific data from NMI for a dialup connection
+ *
+ * NOTE: caller MUST free returned value using g_strfreev()
+ *
+ */
+static char ** nm_dbus_dialup_get_dialup_data (DBusConnection *connection, NMDialupConnection *dialup, int *num_items)
+{
+ DBusMessage *message;
+ DBusError error;
+ DBusMessage *reply;
+ char **data_items = NULL;
+ const char *dialup_name;
+
+ g_return_val_if_fail (connection != NULL, NULL);
+ g_return_val_if_fail (dialup != NULL, NULL);
+ g_return_val_if_fail (num_items != NULL, NULL);
+
+ *num_items = -1;
+
+ if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getDialupConnectionDialupData")))
+ {
+ nm_warning ("nm_dbus_dialup_get_dialup_data(): Couldn't allocate the dbus message");
+ return (NULL);
+ }
+
+ dialup_name = nm_dialup_connection_get_name (dialup);
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &dialup_name, DBUS_TYPE_INVALID);
+
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
+ dbus_message_unref (message);
+ if (dbus_error_is_set (&error))
+ nm_warning ("nm_dbus_dialup_get_dialup_data(): %s raised %s", error.name, error.message);
+ else if (!reply)
+ nm_info ("nm_dbus_dialup_get_dialup_data(): reply was NULL.");
+ else
+ {
+ DBusMessageIter iter, array_iter;
+ GArray *buffer;
+
+ dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_recurse (&iter, &array_iter);
+
+ buffer = g_array_new (TRUE, TRUE, sizeof (gchar *));
+
+ if (buffer == NULL)
+ return NULL;
+
+ while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING)
+ {
+ const char *value;
+ char *str;
+
+ dbus_message_iter_get_basic (&array_iter, &value);
+ str = g_strdup (value);
+
+ if (str == NULL)
+ {
+ g_array_free (buffer, TRUE);
+ return NULL;
+ }
+
+ g_array_append_val (buffer, str);
+
+ dbus_message_iter_next (&array_iter);
+ }
+ data_items = (gchar **)(buffer->data);
+ *num_items = buffer->len;
+ g_array_free (buffer, FALSE);
+ }
+
+ if (reply)
+ dbus_message_unref (reply);
+
+ return (data_items);
+}
+
+
+
+typedef struct UpdateOneDialupCBData
+{
+ NMData * data;
+ char * dialup;
+} UpdateOneDialupCBData;
+
+
+static void free_update_one_dialup_cb_data (UpdateOneDialupCBData *data)
+{
+ if (data)
+ g_free (data->dialup);
+ g_free (data);
+}
+
+/*
+ * nm_dbus_dialup_update_one_connection_cb
+ *
+ * Retrieve and add to our dialup Manager one dialup connection from NMI.
+ *
+ */
+static void nm_dbus_dialup_update_one_connection_cb (DBusPendingCall *pcall, void *user_data)
+{
+ UpdateOneDialupCBData * cb_data = (UpdateOneDialupCBData *) user_data;
+ DBusMessage * reply;
+ const char * con_name = NULL;
+ const char * service_name = NULL;
+ const char * user_name = NULL;
+
+ g_return_if_fail (pcall != NULL);
+ g_return_if_fail (cb_data != NULL);
+ g_return_if_fail (cb_data->data != NULL);
+ g_return_if_fail (cb_data->data->dialup_manager != NULL);
+
+ dbus_pending_call_ref (pcall);
+
+ if (!dbus_pending_call_get_completed (pcall))
+ goto out;
+
+ if (!(reply = dbus_pending_call_steal_reply (pcall)))
+ goto out;
+
+ if (dbus_message_is_error (reply, "BadDialupConnectionData"))
+ {
+ NMDialupConnection *dialup;
+
+ /* Bad dialup, remove it from our dialup connection list */
+ if ((dialup = nm_dialup_manager_find_connection_by_name (cb_data->data->dialup_manager, cb_data->dialup)))
+ {
+ nm_dialup_connection_ref (dialup);
+ nm_dialup_manager_remove_connection (cb_data->data->dialup_manager, dialup);
+ nm_dbus_dialup_signal_dialup_connection_update (cb_data->data->dbus_connection, dialup, "DialupConnectionRemoved");
+ nm_dialup_connection_unref (dialup);
+ }
+ goto out;
+ }
+
+ if (dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_STRING, &con_name,
+ DBUS_TYPE_STRING, &service_name,
+ DBUS_TYPE_STRING, &user_name,
+ DBUS_TYPE_INVALID))
+ {
+ NMDialupConnection * dialup;
+ gboolean new = TRUE;
+
+ // nm_info ("Updating connectoin %s/%s/%s", con_name, service_name, user_name);
+
+ if ((dialup = nm_dialup_manager_find_connection_by_name (cb_data->data->dialup_manager, con_name)))
+ {
+ const char *dialup_service_name = nm_dialup_connection_get_service_name (dialup);
+
+ /* If all attributes of the existing connection are the same as the one we get from NMI,
+ * don't do anything.
+ */
+ if (strcmp (dialup_service_name, service_name) || strcmp (nm_dialup_connection_get_user_name (dialup), user_name))
+ nm_dialup_manager_remove_connection (cb_data->data->dialup_manager, dialup);
+ else
+ new = FALSE;
+ }
+
+ if (new)
+ dialup = nm_dialup_manager_add_connection (cb_data->data->dialup_manager, con_name, service_name, user_name);
+
+ if (dialup)
+ nm_dbus_dialup_signal_dialup_connection_update (cb_data->data->dbus_connection, dialup, new ? "DialupConnectionAdded" : "DialupConnectionUpdate");
+
+ }
+ dbus_message_unref (reply);
+
+out:
+ dbus_pending_call_unref (pcall);
+}
+
+
+/*
+ * nm_dbus_dialup_connections_update_cb
+ *
+ * Async callback from nnm_dbus_dialup_connections_update
+ *
+ */
+static void nm_dbus_dialup_connections_update_cb (DBusPendingCall *pcall, void *user_data)
+{
+ NMData * data = (NMData *) user_data;
+ DBusMessage * reply;
+ DBusMessageIter iter, array_iter;
+ GSList * remove_list = NULL;
+ GSList * elt;
+
+ g_return_if_fail (pcall);
+ g_return_if_fail (data != NULL);
+
+ dbus_pending_call_ref (pcall);
+
+ if (!dbus_pending_call_get_completed (pcall))
+ goto out;
+
+ if (!(reply = dbus_pending_call_steal_reply (pcall)))
+ goto out;
+
+ if (message_is_error (reply))
+ goto out;
+
+ remove_list = nm_dialup_manager_dialup_connection_list_copy (data->dialup_manager);
+
+ dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_recurse (&iter, &array_iter);
+ while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING)
+ {
+ DBusMessage * message;
+ const char * con_name;
+ NMDialupConnection * dialup;
+
+ dbus_message_iter_get_basic (&array_iter, &con_name);
+
+ /* If the connection already exists, remove it from the remove list */
+ if ((dialup = nm_dialup_manager_find_connection_by_name (data->dialup_manager, con_name)))
+ {
+ remove_list = g_slist_remove (remove_list, dialup);
+ }
+
+ if ((message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getDialupConnectionProperties")))
+ {
+ DBusPendingCall * dialup_pcall = NULL;
+
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &con_name, DBUS_TYPE_INVALID);
+ dbus_connection_send_with_reply (data->dbus_connection, message, &dialup_pcall, -1);
+ dbus_message_unref (message);
+ if (dialup_pcall)
+ {
+ UpdateOneDialupCBData * dialup_cb_data = g_malloc0 (sizeof (UpdateOneDialupCBData));
+
+ dialup_cb_data->data = data;
+ dialup_cb_data->dialup = g_strdup (con_name);
+ dbus_pending_call_set_notify (dialup_pcall, nm_dbus_dialup_update_one_connection_cb, dialup_cb_data, (DBusFreeFunction) free_update_one_dialup_cb_data);
+ }
+ }
+ dbus_message_iter_next (&array_iter);
+ }
+ dbus_message_unref (reply);
+
+ /* dialup connections left in the remove list aren't known by NMI, therefore we delete them */
+ for (elt = remove_list; elt; elt = g_slist_next (elt))
+ {
+ nm_dialup_manager_remove_connection (data->dialup_manager, elt->data);
+ nm_dialup_connection_unref (elt->data);
+ }
+
+ g_slist_free (remove_list);
+
+out:
+ dbus_pending_call_unref (pcall);
+}
+
+
+/*
+ * nm_dbus_dialup_update_one_dialup_connection
+ *
+ * Update one dialup connection
+ *
+ */
+void nm_dbus_dialup_update_one_dialup_connection (DBusConnection *connection, const char *dialup, NMData *data)
+{
+ DBusMessage * message;
+ DBusPendingCall * pcall = NULL;
+
+ g_return_if_fail (connection != NULL);
+ g_return_if_fail (dialup != NULL);
+ g_return_if_fail (data != NULL);
+
+ if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getDialupConnectionProperties")))
+ {
+ nm_warning ("nm_dbus_update_one_dialup_connection(): Couldn't allocate the dbus message");
+ return;
+ }
+
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &dialup, DBUS_TYPE_INVALID);
+ dbus_connection_send_with_reply (connection, message, &pcall, -1);
+ dbus_message_unref (message);
+ if (pcall)
+ {
+ UpdateOneDialupCBData * cb_data = g_malloc0 (sizeof (UpdateOneDialupCBData));
+
+ cb_data->data = data;
+ cb_data->dialup = g_strdup (dialup);
+ dbus_pending_call_set_notify (pcall, nm_dbus_dialup_update_one_connection_cb, cb_data, (DBusFreeFunction) free_update_one_dialup_cb_data);
+ }
+}
+
+
+/*
+ * nm_dbus_dialup_connections_update_from_nmi
+ *
+ * Update dialup connections from NetworkManagerInfo.
+ *
+ */
+static gboolean nm_dbus_dialup_connections_update_from_nmi (NMData *data)
+{
+ DBusMessage * message;
+ DBusPendingCall * pcall;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+ g_return_val_if_fail (data->dbus_connection != NULL, FALSE);
+ g_return_val_if_fail (data->dialup_manager != NULL, FALSE);
+
+ if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getDialupConnections")))
+ {
+ nm_warning ("nm_dbus_dialup_connections_update (): Couldn't allocate the dbus message");
+ return FALSE;
+ }
+
+ dbus_connection_send_with_reply (data->dbus_connection, message, &pcall, -1);
+ dbus_message_unref (message);
+ if (pcall)
+ {
+ dbus_pending_call_set_notify (pcall, nm_dbus_dialup_connections_update_cb, data, NULL);
+ dbus_pending_call_block (pcall);
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * nm_dbus_dialup_schedule_dialup_connections_update
+ *
+ * Schedule an update of dialup connections in the main thread
+ *
+ */
+void nm_dbus_dialup_schedule_dialup_connections_update (NMData *app_data)
+{
+ GSource *source = NULL;
+
+ g_return_if_fail (app_data != NULL);
+ g_return_if_fail (app_data->main_context != NULL);
+
+ source = g_idle_source_new ();
+ /* We want this idle source to run before any other idle source */
+ g_source_set_priority (source, G_PRIORITY_HIGH_IDLE);
+ g_source_set_callback (source, (GSourceFunc) nm_dbus_dialup_connections_update_from_nmi, app_data, NULL);
+ g_source_attach (source, app_data->main_context);
+ g_source_unref (source);
+}
+
+
+/*
+ * nm_dbus_dialup_get_dialup_connections
+ *
+ * Returns a string array of dialup connection names.
+ *
+ */
+static DBusMessage *nm_dbus_dialup_get_dialup_connections (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+{
+ DBusMessage *reply = NULL;
+ char **dialup_names = NULL;
+ int num_names;
+
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (data->data != NULL, NULL);
+ g_return_val_if_fail (connection != NULL, NULL);
+ g_return_val_if_fail (message != NULL, NULL);
+
+ if (!data->data->dialup_manager)
+ {
+ reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_DIALUP, "NoDialupConnections", "There are no available dialup connections.");
+ goto out;
+ }
+
+ dialup_names = nm_dialup_manager_get_connection_names (data->data->dialup_manager);
+ num_names = dialup_names ? g_strv_length (dialup_names) : 0;
+ if (num_names == 0)
+ {
+ reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_DIALUP, "NoDialupConnections", "There are no available dialup connections.");
+ goto out;
+ }
+
+ if (!(reply = dbus_message_new_method_return (message)))
+ goto out;
+
+ dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &dialup_names, num_names, DBUS_TYPE_INVALID);
+
+out:
+ if (dialup_names)
+ g_strfreev (dialup_names);
+
+ return (reply);
+}
+
+
+/*
+ * nm_dbus_dialup_get_dialup_connection_properties
+ *
+ * Grab properties of a dialup connection
+ *
+ */
+static DBusMessage *nm_dbus_dialup_get_dialup_connection_properties (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+{
+ DBusMessage * reply = NULL;
+ DBusError error;
+ const char * name;
+ gboolean good = FALSE;
+ NMDialupManager * manager;
+ NMDialupConnection * dialup;
+
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (data->data != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL);
+ g_return_val_if_fail (message != NULL, NULL);
+
+ /* Check for no dialup Manager */
+ if (!(manager = data->data->dialup_manager))
+ return nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_DIALUP, "NoDialupConnections", "There are no available dialup connections.");
+
+ if (!(reply = dbus_message_new_method_return (message)))
+ return NULL;
+
+ dbus_error_init (&error);
+ if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
+ {
+ if ((dialup = nm_dialup_manager_find_connection_by_name (manager, name)))
+ {
+ const char * user_name;
+ const char * service_name;
+ NMDialupService * service;
+
+ user_name = nm_dialup_connection_get_user_name (dialup);
+ service_name = nm_dialup_connection_get_service_name (dialup);
+ if ((service = nm_dialup_manager_find_service_by_name (data->data->dialup_manager, service_name)))
+ {
+ NMDialupActRequest * req = nm_dialup_manager_get_dialup_act_request (manager);
+ dbus_uint32_t stage = (dbus_uint32_t) NM_DIALUP_ACT_STAGE_DISCONNECTED;
+
+ if (req && (nm_dialup_act_request_get_connection (req) == dialup))
+ stage = nm_dialup_act_request_get_stage (req);
+
+ dbus_message_append_args (reply, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &user_name,
+ DBUS_TYPE_STRING, &service_name, DBUS_TYPE_UINT32, &stage, DBUS_TYPE_INVALID);
+ good = TRUE;
+ }
+ }
+ }
+
+ if (!good)
+ reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_DIALUP, "InvalidDialupConnection", "No dialup connection with that name was found.");
+
+ return reply;
+}
+
+
+/*
+ * nm_dbus_dialup_activate_connection
+ *
+ * Activate a specific dialup connection.
+ *
+ */
+static DBusMessage *nm_dbus_dialup_activate_connection (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+{
+ DBusError error;
+ const char * name;
+ char ** passwords;
+ int num_passwords;
+ NMDialupConnection * dialup;
+
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (data->data != NULL, NULL);
+ g_return_val_if_fail (connection != NULL, NULL);
+ g_return_val_if_fail (message != NULL, NULL);
+
+ dbus_error_init (&error);
+
+ if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &passwords, &num_passwords, DBUS_TYPE_INVALID))
+ {
+ if ((dialup = nm_dialup_manager_find_connection_by_name (data->data->dialup_manager, name)))
+ {
+ int item_count = -1;
+ char **items;
+ if ((items = nm_dbus_dialup_get_dialup_data (connection, dialup, &item_count)))
+ {
+ char * joined_string = g_strjoinv (" :: ", items);
+ nm_info ("Will activate dialup connection '%s', service '%s', user_name '%s', dialup_data '%s'.",
+ name, nm_dialup_connection_get_service_name (dialup), nm_dialup_connection_get_user_name (dialup), joined_string);
+ nm_dialup_manager_activate_dialup_connection (data->data->dialup_manager, dialup, passwords, num_passwords, items, item_count);
+
+ g_free (joined_string);
+ g_strfreev (items);
+ }
+ } else {
+ nm_warning ("nm_dbus_dialup_activate_connection(): cannot find dialup connection '%s'", name);
+ }
+ } else {
+ nm_warning ("nm_dbus_dialup_activate_connection(): syntax error in method arguments");
+ }
+
+ return NULL;
+}
+
+
+/*
+ * nm_dbus_dialup_deactivate_connection
+ *
+ * Deactivate the active dialup connection, if any.
+ *
+ */
+static DBusMessage *nm_dbus_dialup_deactivate_connection (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+{
+ NMDialupActRequest *req;
+ NMDialupConnection *dialup;
+
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (data->data != NULL, NULL);
+ g_return_val_if_fail (connection != NULL, NULL);
+ g_return_val_if_fail (message != NULL, NULL);
+
+ if (!(req = nm_dialup_manager_get_dialup_act_request (data->data->dialup_manager)))
+ return NULL;
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_info ("Will deactivate the dialup connection '%s', service '%s'.", nm_dialup_connection_get_name (dialup),
+ nm_dialup_connection_get_service_name (dialup));
+ nm_dialup_manager_deactivate_dialup_connection (data->data->dialup_manager);
+
+ return NULL;
+}
+
+
+/*
+ * nm_dbus_dialup_methods_setup
+ *
+ * Register handlers for dbus methods on the
+ * org.freedesktop.NetworkManager.DialupConnections object.
+ *
+ */
+NMDbusMethodList *nm_dbus_dialup_methods_setup (void)
+{
+ NMDbusMethodList *list = nm_dbus_method_list_new (NULL);
+
+ nm_dbus_method_list_add_method (list, "getDialupConnections", nm_dbus_dialup_get_dialup_connections);
+ nm_dbus_method_list_add_method (list, "getDialupConnectionProperties", nm_dbus_dialup_get_dialup_connection_properties);
+ nm_dbus_method_list_add_method (list, "activateDialupConnection", nm_dbus_dialup_activate_connection);
+ nm_dbus_method_list_add_method (list, "deactivateDialupConnection", nm_dbus_dialup_deactivate_connection);
+
+ return (list);
+}
diff --git a/src/dialup/manager/nm-dbus-dialup.h b/src/dialup/manager/nm-dbus-dialup.h
new file mode 100644
index 0000000000..1d08b60ea9
--- /dev/null
+++ b/src/dialup/manager/nm-dbus-dialup.h
@@ -0,0 +1,40 @@
+/* NetworkManager -- Network link manager
+ *
+ * Tim Niemueller [www.niemueller.de]
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2005 Red Hat, Inc.
+ * (C) Copyright 2006 Tim Niemueller
+ */
+
+#ifndef NM_DBUS_DIALUP_H
+#define NM_DBUS_DIALUP_H
+
+#include "NetworkManagerDbusUtils.h"
+#include "nm-dialup-manager.h"
+#include "nm-dialup-connection.h"
+
+void nm_dbus_dialup_schedule_dialup_connections_update (NMData *app_data);
+void nm_dbus_dialup_update_one_dialup_connection (DBusConnection *connection, const char *dialup, NMData *data);
+
+void nm_dbus_dialup_signal_dialup_connection_update (DBusConnection *con, NMDialupConnection *dialup, const char *signal);
+void nm_dbus_dialup_signal_dialup_failed (DBusConnection *con, const char *signal, NMDialupConnection *dialup, const char *error_msg);
+void nm_dbus_dialup_signal_dialup_connection_state_change (DBusConnection *con, NMDialupConnection *dialup, NMDialupActStage new_stage);
+
+NMDbusMethodList * nm_dbus_dialup_methods_setup (void);
+
+#endif
diff --git a/src/dialup/manager/nm-dialup-act-request.c b/src/dialup/manager/nm-dialup-act-request.c
new file mode 100644
index 0000000000..96a8416875
--- /dev/null
+++ b/src/dialup/manager/nm-dialup-act-request.c
@@ -0,0 +1,245 @@
+/* NetworkManager -- Network link manager
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2005 Red Hat, Inc.
+ */
+
+
+#include <glib.h>
+#include <string.h>
+#include "nm-dialup-act-request.h"
+#include "nm-dbus-dialup.h"
+
+
+struct NMDialupActRequest
+{
+ guint refcount;
+ NMDialupActStage stage;
+
+ NMDialupManager * manager;
+ NMDialupService * service;
+ NMDialupConnection * dialup;
+
+ char ** password_items;
+ int password_count;
+ char ** data_items;
+ int data_count;
+
+ guint daemon_wait_count;
+ guint callback_id;
+ gboolean canceled;
+};
+
+
+NMDialupActRequest *nm_dialup_act_request_new (NMDialupManager *manager, NMDialupService *service, NMDialupConnection *dialup,
+ char **password_items, int password_count,
+ char **data_items, int data_count)
+{
+ NMDialupActRequest *req;
+
+ g_return_val_if_fail (manager != NULL, NULL);
+ g_return_val_if_fail (service != NULL, NULL);
+ g_return_val_if_fail (dialup != NULL, NULL);
+ g_return_val_if_fail (password_items != NULL, NULL);
+ g_return_val_if_fail (data_items != NULL, NULL);
+
+ req = g_malloc0 (sizeof (NMDialupActRequest));
+ req->refcount = 1;
+ req->stage = NM_DIALUP_ACT_STAGE_PREPARE;
+
+ req->manager = manager;
+ nm_dialup_service_ref (service);
+ req->service = service;
+ nm_dialup_connection_ref (dialup);
+ req->dialup = dialup;
+
+ req->password_items = g_strdupv (password_items);
+ req->password_count = password_count;
+ req->data_items = g_strdupv (data_items);
+ req->data_count = data_count;
+
+ return req;
+}
+
+
+void nm_dialup_act_request_ref (NMDialupActRequest *req)
+{
+ g_return_if_fail (req != NULL);
+
+ req->refcount++;
+}
+
+
+void nm_dialup_act_request_unref (NMDialupActRequest *req)
+{
+ g_return_if_fail (req != NULL);
+
+ req->refcount--;
+ if (req->refcount == 0)
+ {
+ nm_dialup_service_unref (req->service);
+ nm_dialup_connection_unref (req->dialup);
+
+ g_strfreev (req->password_items);
+ g_strfreev (req->data_items);
+
+ memset (req, 0, sizeof (NMDialupActRequest));
+ g_free (req);
+ }
+}
+
+gboolean nm_dialup_act_request_is_activating (NMDialupActRequest *req)
+{
+ gboolean activating = FALSE;
+
+ g_return_val_if_fail (req != NULL, FALSE);
+
+ switch (req->stage)
+ {
+ case NM_DIALUP_ACT_STAGE_PREPARE:
+ case NM_DIALUP_ACT_STAGE_CONNECT:
+ case NM_DIALUP_ACT_STAGE_IP_CONFIG_GET:
+ activating = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ return activating;
+}
+
+gboolean nm_dialup_act_request_is_activated (NMDialupActRequest *req)
+{
+ g_return_val_if_fail (req != NULL, FALSE);
+
+ return (req->stage == NM_DIALUP_ACT_STAGE_ACTIVATED) ? TRUE : FALSE;
+}
+
+gboolean nm_dialup_act_request_is_failed (NMDialupActRequest *req)
+{
+ g_return_val_if_fail (req != NULL, FALSE);
+
+ return (req->stage == NM_DIALUP_ACT_STAGE_FAILED) ? TRUE : FALSE;
+}
+
+NMDialupManager *nm_dialup_act_request_get_manager (NMDialupActRequest *req)
+{
+ g_return_val_if_fail (req != NULL, NULL);
+
+ return req->manager;
+}
+
+NMDialupService * nm_dialup_act_request_get_service (NMDialupActRequest *req)
+{
+ g_return_val_if_fail (req != NULL, NULL);
+
+ return req->service;
+}
+
+
+NMDialupConnection * nm_dialup_act_request_get_connection (NMDialupActRequest *req)
+{
+ g_return_val_if_fail (req != NULL, NULL);
+
+ return req->dialup;
+}
+
+const char ** nm_dialup_act_request_get_password_items (NMDialupActRequest *req, guint *count)
+{
+ g_return_val_if_fail (req != NULL, NULL);
+ g_return_val_if_fail (count != NULL, NULL);
+
+ *count = req->password_count;
+ return (const char **) (req->password_items);
+}
+
+const char ** nm_dialup_act_request_get_data_items (NMDialupActRequest *req, guint *count)
+{
+ g_return_val_if_fail (req != NULL, NULL);
+ g_return_val_if_fail (count != NULL, NULL);
+
+ *count = req->data_count;
+ return (const char **) (req->data_items);
+}
+
+void nm_dialup_act_request_cancel (NMDialupActRequest *req)
+{
+ g_return_if_fail (req != NULL);
+
+ req->canceled = TRUE;
+}
+
+gboolean nm_dialup_act_request_should_cancel (NMDialupActRequest *req)
+{
+ g_return_val_if_fail (req != NULL, FALSE);
+
+ return req->canceled;
+}
+
+NMDialupActStage nm_dialup_act_request_get_stage (NMDialupActRequest *req)
+{
+ g_return_val_if_fail (req != NULL, NM_DIALUP_ACT_STAGE_UNKNOWN);
+
+ return req->stage;
+}
+
+void nm_dialup_act_request_set_stage (NMDialupActRequest *req, NMDialupActStage stage)
+{
+ NMDialupActStage old_stage;
+
+ g_return_if_fail (req != NULL);
+
+ old_stage = req->stage;
+ if (old_stage != stage)
+ {
+ DBusConnection *dbus_connection = nm_dialup_service_get_dbus_connection (req->service);
+
+ req->stage = stage;
+ nm_dbus_dialup_signal_dialup_connection_state_change (dbus_connection, req->dialup, req->stage);
+ }
+}
+
+guint nm_dialup_act_request_get_daemon_wait_count (NMDialupActRequest *req)
+{
+ g_return_val_if_fail (req != NULL, 0);
+
+ return req->daemon_wait_count;
+}
+
+void nm_dialup_act_request_set_daemon_wait_count (NMDialupActRequest *req, guint count)
+{
+ g_return_if_fail (req != NULL);
+
+ req->daemon_wait_count = count;
+}
+
+guint nm_dialup_act_request_get_callback_id (NMDialupActRequest *req)
+{
+ g_return_val_if_fail (req != NULL, 0);
+
+ return req->callback_id;
+}
+
+void nm_dialup_act_request_set_callback_id (NMDialupActRequest *req, guint id)
+{
+ g_return_if_fail (req != NULL);
+
+ req->callback_id = id;
+}
+
diff --git a/src/dialup/manager/nm-dialup-act-request.h b/src/dialup/manager/nm-dialup-act-request.h
new file mode 100644
index 0000000000..4396a67274
--- /dev/null
+++ b/src/dialup/manager/nm-dialup-act-request.h
@@ -0,0 +1,61 @@
+/* NetworkManager -- Network link manager
+ *
+ * Tim Niemueller [www.niemueller.de]
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2005 Red Hat, Inc.
+ * (C) Copyright 2006 Tim Niemueller
+ */
+
+#ifndef NM_DIALUP_ACT_REQUEST_H
+#define NM_DIALUP_ACT_REQUEST_H
+
+#include <glib.h>
+#include "NetworkManager.h"
+#include "NetworkManagerMain.h"
+#include "nm-dialup-connection.h"
+#include "nm-dialup-service.h"
+
+NMDialupActRequest * nm_dialup_act_request_new (NMDialupManager *manager, NMDialupService *service, NMDialupConnection *dialup,
+ char **password_items, int password_count, char **data_items, int data_count);
+void nm_dialup_act_request_ref (NMDialupActRequest *req);
+void nm_dialup_act_request_unref (NMDialupActRequest *req);
+
+gboolean nm_dialup_act_request_is_activating (NMDialupActRequest *req);
+gboolean nm_dialup_act_request_is_activated (NMDialupActRequest *req);
+gboolean nm_dialup_act_request_is_failed (NMDialupActRequest *req);
+
+NMDialupManager * nm_dialup_act_request_get_manager (NMDialupActRequest *req);
+NMDialupService * nm_dialup_act_request_get_service (NMDialupActRequest *req);
+NMDialupConnection * nm_dialup_act_request_get_connection (NMDialupActRequest *req);
+
+const char ** nm_dialup_act_request_get_password_items (NMDialupActRequest *req, guint *count);
+const char ** nm_dialup_act_request_get_data_items (NMDialupActRequest *req, guint *count);
+
+void nm_dialup_act_request_cancel (NMDialupActRequest *req);
+gboolean nm_dialup_act_request_should_cancel (NMDialupActRequest *req);
+
+NMDialupActStage nm_dialup_act_request_get_stage (NMDialupActRequest *req);
+void nm_dialup_act_request_set_stage (NMDialupActRequest *req, NMDialupActStage stage);
+
+guint nm_dialup_act_request_get_daemon_wait_count (NMDialupActRequest *req);
+void nm_dialup_act_request_set_daemon_wait_count (NMDialupActRequest *req, guint count);
+
+guint nm_dialup_act_request_get_callback_id (NMDialupActRequest *req);
+void nm_dialup_act_request_set_callback_id (NMDialupActRequest *req, guint timeout);
+
+#endif
diff --git a/src/dialup/manager/nm-dialup-connection.c b/src/dialup/manager/nm-dialup-connection.c
new file mode 100644
index 0000000000..195744893d
--- /dev/null
+++ b/src/dialup/manager/nm-dialup-connection.c
@@ -0,0 +1,227 @@
+/* nm-dialup-connection.c - handle a single dialup connection within NetworkManager's framework
+ *
+ * Copyright (C) 2006 Tim Niemueller
+ * based on work Copyright (C) 2005 Dan Williams
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <glib.h>
+#include <string.h>
+#include "nm-dialup-connection.h"
+#include "nm-dbus-dialup.h"
+#include "NetworkManagerSystem.h"
+
+
+struct NMDialupConnection
+{
+ int refcount;
+
+ /* Won't change over life of object */
+ char * name;
+ char * user_name;
+ char * service_name;
+
+ NMNamedManager *named_manager;
+ DBusConnection *dbus_connection;
+
+ /* Change when connection is activated/deactivated */
+ NMIP4Config * ip4_config;
+ char * dialup_iface;
+};
+
+
+static void nm_dialup_connection_set_dialup_iface (NMDialupConnection *con, const char *dialup_iface);
+static void nm_dialup_connection_set_ip4_config (NMDialupConnection *con, NMIP4Config *ip4_config);
+
+NMDialupConnection *
+nm_dialup_connection_new (const char *name, const char *user_name, const char *service_name,
+ NMNamedManager *named_manager, DBusConnection *dbus_connection)
+{
+ NMDialupConnection *connection;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (user_name != NULL, NULL);
+ g_return_val_if_fail (service_name != NULL, NULL);
+ g_return_val_if_fail (named_manager != NULL, NULL);
+ g_return_val_if_fail (dbus_connection != NULL, NULL);
+
+ connection = g_malloc0 (sizeof (NMDialupConnection));
+ connection->refcount = 1;
+
+ connection->name = g_strdup (name);
+ connection->user_name = g_strdup (user_name);
+ connection->service_name = g_strdup (service_name);
+
+ g_object_ref (named_manager);
+ connection->named_manager = named_manager;
+
+ connection->dbus_connection = dbus_connection;
+
+ return connection;
+}
+
+
+void
+nm_dialup_connection_ref (NMDialupConnection *connection)
+{
+ g_return_if_fail (connection != NULL);
+
+ connection->refcount++;
+}
+
+
+void
+nm_dialup_connection_unref (NMDialupConnection *connection)
+{
+ g_return_if_fail (connection != NULL);
+
+ connection->refcount--;
+ if (connection->refcount <= 0)
+ {
+ g_free (connection->name);
+ g_free (connection->user_name);
+ g_free (connection->service_name);
+
+ if (connection->ip4_config)
+ nm_ip4_config_unref (connection->ip4_config);
+ g_free (connection->dialup_iface);
+
+ g_object_unref (connection->named_manager);
+
+ memset (connection, 0, sizeof (NMDialupConnection));
+ g_free (connection);
+ }
+}
+
+
+void
+nm_dialup_connection_activate (NMDialupConnection *connection)
+{
+ g_return_if_fail (connection != NULL);
+
+ /* Nothing done here yet */
+}
+
+
+gboolean
+nm_dialup_connection_set_config (NMDialupConnection *connection, const char *dialup_iface, NMIP4Config *ip4_config)
+{
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (connection != NULL, FALSE);
+ g_return_val_if_fail (ip4_config != NULL, FALSE);
+
+ if (dialup_iface != NULL && strlen (dialup_iface))
+ nm_dialup_connection_set_dialup_iface (connection, dialup_iface);
+ nm_dialup_connection_set_ip4_config (connection, ip4_config);
+
+ // m_system_dialup_device_set_from_ip4_config (connection->named_manager,
+ // connection->dialup_iface, connection->ip4_config);
+ success = TRUE;
+
+ return success;
+}
+
+
+void
+nm_dialup_connection_deactivate (NMDialupConnection *connection)
+{
+ g_return_if_fail (connection != NULL);
+
+ if (connection->dialup_iface)
+ {
+ nm_system_device_set_up_down_with_iface (connection->dialup_iface, FALSE);
+ nm_system_device_flush_routes_with_iface (connection->dialup_iface);
+ nm_system_device_flush_addresses_with_iface (connection->dialup_iface);
+ }
+
+ if (connection->ip4_config)
+ {
+ /* Remove attributes of the dialup's IP4 Config */
+ //nm_system_dialup_device_unset_from_ip4_config (connection->named_manager, connection->parent_dev,
+ // connection->dialup_iface, connection->ip4_config);
+
+ /* Reset routes, nameservers, and domains of the currently active device */
+ //nm_system_device_set_from_ip4_config (connection->parent_dev);
+ }
+
+ nm_dialup_connection_set_ip4_config (connection, NULL);
+ nm_dialup_connection_set_dialup_iface (connection, NULL);
+}
+
+
+const char *
+nm_dialup_connection_get_name (NMDialupConnection *connection)
+{
+ g_return_val_if_fail (connection != NULL, NULL);
+
+ return connection->name;
+}
+
+
+const char *
+nm_dialup_connection_get_user_name (NMDialupConnection *connection)
+{
+ g_return_val_if_fail (connection != NULL, NULL);
+
+ return connection->user_name;
+}
+
+
+const char *
+nm_dialup_connection_get_service_name (NMDialupConnection *connection)
+{
+ g_return_val_if_fail (connection != NULL, NULL);
+
+ return connection->service_name;
+}
+
+
+static void
+nm_dialup_connection_set_dialup_iface (NMDialupConnection *con, const char *dialup_iface)
+{
+ g_return_if_fail (con != NULL);
+
+ if (con->dialup_iface)
+ {
+ g_free (con->dialup_iface);
+ con->dialup_iface = NULL;
+ }
+
+ if (dialup_iface)
+ con->dialup_iface = g_strdup (dialup_iface);
+}
+
+
+static void
+nm_dialup_connection_set_ip4_config (NMDialupConnection *con, NMIP4Config *ip4_config)
+{
+ g_return_if_fail (con != NULL);
+
+ if (con->ip4_config)
+ {
+ nm_ip4_config_unref (con->ip4_config);
+ con->ip4_config = NULL;
+ }
+
+ if (ip4_config)
+ {
+ nm_ip4_config_ref (ip4_config);
+ con->ip4_config = ip4_config;
+ }
+}
diff --git a/src/dialup/manager/nm-dialup-connection.h b/src/dialup/manager/nm-dialup-connection.h
new file mode 100644
index 0000000000..cdf49d6c73
--- /dev/null
+++ b/src/dialup/manager/nm-dialup-connection.h
@@ -0,0 +1,44 @@
+/* nm-dialup-connection.h - handle a single dialup connection within NetworkManager's framework
+ *
+ * Copyright (C) 2006 Tim Niemueller
+ * base on work Copyright (C) 2005 Dan Williams
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#ifndef NM_DIALUP_CONNECTION_H
+#define NM_DIALUP_CONNECTION_H
+
+#include "nm-device.h"
+#include "nm-named-manager.h"
+
+typedef struct NMDialupConnection NMDialupConnection;
+
+
+NMDialupConnection * nm_dialup_connection_new (const char *name, const char *user_name, const char *service_name,
+ NMNamedManager *named_manager, DBusConnection *dbus_connection);
+void nm_dialup_connection_ref (NMDialupConnection *con);
+void nm_dialup_connection_unref (NMDialupConnection *con);
+
+const char * nm_dialup_connection_get_name (NMDialupConnection *con);
+const char * nm_dialup_connection_get_user_name (NMDialupConnection *con);
+const char * nm_dialup_connection_get_service_name (NMDialupConnection *con);
+
+void nm_dialup_connection_activate (NMDialupConnection *con);
+void nm_dialup_connection_deactivate (NMDialupConnection *con);
+
+gboolean nm_dialup_connection_set_config (NMDialupConnection *con, const char *dialup_iface, NMIP4Config *ip4_config);
+
+#endif /* NM_DIALUP_CONNECTION_H */
diff --git a/src/dialup/manager/nm-dialup-manager.c b/src/dialup/manager/nm-dialup-manager.c
new file mode 100644
index 0000000000..39afc598c2
--- /dev/null
+++ b/src/dialup/manager/nm-dialup-manager.c
@@ -0,0 +1,640 @@
+/* nm-dialup-manager.c - handle dialup connections within NetworkManager's framework
+ *
+ * Copyright (C) 2006 Tim Niemueller
+ * based on work Copyright (C) 2005 Dan Williams
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+#include <dbus/dbus.h>
+#include "nm-dialup-manager.h"
+#include "NetworkManager.h"
+#include "NetworkManagerMain.h"
+#include "NetworkManagerDbus.h"
+#include "NetworkManagerSystem.h"
+#include "nm-dialup-act-request.h"
+#include "nm-dialup-connection.h"
+#include "nm-dbus-dialup.h"
+#include "nm-utils.h"
+
+#define DIALUP_SERVICE_FILE_PATH SYSCONFDIR"/NetworkManager/dialup"
+
+
+
+struct NMDialupManager
+{
+ NMData * app_data;
+ GHashTable * service_table;
+ GSList * connections;
+
+ NMDialupActRequest * act_req;
+};
+
+static void nm_dialup_manager_load_services (NMDialupManager *manager, GHashTable *table);
+
+/*
+ * nm_dialup_manager_new
+ *
+ * Create a new dialup manager instance.
+ *
+ */
+NMDialupManager *
+nm_dialup_manager_new (NMData *app_data)
+{
+ NMDialupManager * manager;
+
+ g_return_val_if_fail (app_data != NULL, NULL);
+
+ manager = g_malloc0 (sizeof (NMDialupManager));
+ manager->app_data = app_data;
+
+ manager->service_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) nm_dialup_service_unref);
+ nm_dialup_manager_load_services (manager, manager->service_table);
+
+ return manager;
+}
+
+
+/*
+ * nm_dialup_manager_dispose
+ *
+ * Release the dialup manager and all its data.
+ *
+ */
+void
+nm_dialup_manager_dispose (NMDialupManager *manager)
+{
+ g_return_if_fail (manager != NULL);
+
+ if (manager->act_req)
+ nm_dialup_manager_deactivate_dialup_connection (manager);
+
+ g_slist_foreach (manager->connections, (GFunc) nm_dialup_connection_unref, NULL);
+ g_slist_free (manager->connections);
+
+ g_hash_table_destroy (manager->service_table);
+
+ memset (manager, 0, sizeof (NMDialupManager));
+ g_free (manager);
+}
+
+
+/*
+ * nm_dialup_manager_find_connection_by_name
+ *
+ * Return the NMDialupConnection object associated with a particular name.
+ *
+ */
+NMDialupConnection *
+nm_dialup_manager_find_connection_by_name (NMDialupManager *manager, const char *con_name)
+{
+ NMDialupConnection *con = NULL;
+ GSList *elt;
+
+ g_return_val_if_fail (manager != NULL, NULL);
+ g_return_val_if_fail (con_name != NULL, NULL);
+
+ for (elt = manager->connections; elt; elt = g_slist_next (elt))
+ {
+ if ((con = (NMDialupConnection *)(elt->data)))
+ {
+ const char *search_name = nm_dialup_connection_get_name (con);
+ if (search_name && (strcmp (con_name, search_name) == 0))
+ break;
+ }
+ con = NULL;
+ }
+
+ return con;
+}
+
+
+NMDialupService *
+nm_dialup_manager_find_service_by_name (NMDialupManager *manager, const char *service_name)
+{
+ g_return_val_if_fail (manager != NULL, NULL);
+ g_return_val_if_fail (service_name != NULL, NULL);
+
+ return (NMDialupService *) g_hash_table_lookup (manager->service_table, service_name);
+}
+
+
+/*
+ * nm_dialup_manager_dialup_connection_list_copy
+ *
+ * Make a shallow copy of the Dialup connection list, should
+ * only be used by nm-dbus-dialup.c
+ *
+ */
+GSList *
+nm_dialup_manager_dialup_connection_list_copy (NMDialupManager *manager)
+{
+ GSList * list;
+ GSList * elt;
+
+ g_return_val_if_fail (manager != NULL, NULL);
+
+ list = g_slist_copy (manager->connections);
+ for (elt = list; elt; elt = g_slist_next (elt))
+ nm_dialup_connection_ref (elt->data);
+
+ return list;
+}
+
+
+/*
+ * nm_dialup_manager_add_connection
+ *
+ * Add a new dialup connection if none already exits, otherwise update the existing one.
+ *
+ */
+NMDialupConnection *
+nm_dialup_manager_add_connection (NMDialupManager *manager, const char *name, const char *service_name, const char *user_name)
+{
+ NMDialupConnection * connection = NULL;
+ NMDialupService * service;
+
+ g_return_val_if_fail (manager != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (service_name != NULL, NULL);
+ g_return_val_if_fail (user_name != NULL, NULL);
+
+ /* Verify that the service name we are adding is in our allowed list */
+ if (!(service = nm_dialup_manager_find_service_by_name (manager, service_name)))
+ {
+ nm_info ("Could not find service %s by name", service_name);
+ return NULL;
+ }
+
+ if ((connection = nm_dialup_connection_new (name, user_name, service_name, manager->app_data->named_manager,
+ manager->app_data->dbus_connection)))
+ {
+ GSList *elt;
+
+ /* Remove the existing connection if found */
+ for (elt = manager->connections; elt; elt = g_slist_next (elt))
+ {
+ NMDialupConnection *con = (NMDialupConnection *)(elt->data);
+
+ if (con && nm_dialup_connection_get_name (con) && (strcmp (nm_dialup_connection_get_name (con), name) == 0))
+ {
+ manager->connections = g_slist_remove_link (manager->connections, elt);
+ nm_dialup_connection_unref (con);
+ g_slist_free (elt);
+ }
+ }
+
+ /* Add in the updated connection */
+ manager->connections = g_slist_append (manager->connections, connection);
+ }
+ else
+ {
+ nm_info ("Could not create new connection, constructor failed");
+ }
+
+ return connection;
+}
+
+
+/*
+ * nm_dialup_manager_remove_connection
+ *
+ * Remove a dialup connection.
+ *
+ */
+void
+nm_dialup_manager_remove_connection (NMDialupManager *manager, NMDialupConnection *dialup)
+{
+ g_return_if_fail (manager != NULL);
+ g_return_if_fail (dialup != NULL);
+
+ /* If this Dialup is currently active, kill it */
+ if (manager->act_req && (nm_dialup_act_request_get_connection (manager->act_req) == dialup))
+ {
+ NMDialupService * service = nm_dialup_act_request_get_service (manager->act_req);
+ NMDialupConnection * v = nm_dialup_act_request_get_connection (manager->act_req);
+
+ nm_dialup_connection_deactivate (v);
+ nm_dialup_service_stop_connection (service, manager->act_req);
+
+ nm_dialup_act_request_unref (manager->act_req);
+ manager->act_req = NULL;
+ }
+
+ manager->connections = g_slist_remove (manager->connections, dialup);
+ nm_dialup_connection_unref (dialup);
+}
+
+
+/*
+ * nm_dialup_manager_get_connection_names
+ *
+ * Return an array of strings of all the dialup Connection names
+ * we know about.
+ *
+ */
+char **
+nm_dialup_manager_get_connection_names (NMDialupManager *manager)
+{
+ char **names = NULL;
+ GSList *elt;
+ int i;
+
+ g_return_val_if_fail (manager != NULL, NULL);
+
+ names = g_malloc0 ((g_slist_length (manager->connections) + 1) * sizeof (char *));
+ for (elt = manager->connections, i = 0; elt; elt = g_slist_next (elt), i++)
+ {
+ NMDialupConnection *dialup_con = (NMDialupConnection *)(elt->data);
+ if (dialup_con)
+ names[i] = g_strdup (nm_dialup_connection_get_name (dialup_con));
+ }
+
+ return names;
+}
+
+
+/*
+ * nm_dialup_manager_get_dialup_act_request
+ *
+ * Return the dialup activation request, if any.
+ *
+ */
+NMDialupActRequest *
+nm_dialup_manager_get_dialup_act_request (NMDialupManager *manager)
+{
+ g_return_val_if_fail (manager != NULL, NULL);
+
+ return manager->act_req;
+}
+
+
+static inline gboolean
+same_service_name (NMDialupService *service, NMDialupConnection *dialup)
+{
+ g_return_val_if_fail (service != NULL, FALSE);
+ g_return_val_if_fail (dialup != NULL, FALSE);
+
+ return (!strcmp (nm_dialup_service_get_service_name (service), nm_dialup_connection_get_service_name (dialup)));
+}
+
+
+/*
+ * nm_dialup_manager_process_signal
+ *
+ * Possibly process a signal from the bus, if it comes from the currently
+ * active dialup daemon, if any. Return TRUE if processed, FALSE if not.
+ *
+ */
+gboolean
+nm_dialup_manager_process_signal (NMDialupManager *manager, DBusMessage *message)
+{
+ const char * service_name;
+ NMDialupService * service;
+ gboolean handled = FALSE;
+
+ g_return_val_if_fail (manager != NULL, FALSE);
+ g_return_val_if_fail (message != NULL, FALSE);
+
+ service_name = dbus_message_get_interface (message);
+ if ((service = nm_dialup_manager_find_service_by_name (manager, service_name)))
+ {
+ nm_dialup_service_process_signal (service, manager->act_req, message);
+ handled = TRUE;
+ }
+
+ return handled;
+}
+
+
+/*
+ * nm_dialup_manager_process_name_owner_changed
+ *
+ * Respond to "service created"/"service deleted" signals from dbus for our active dialup daemon.
+ *
+ */
+gboolean
+nm_dialup_manager_process_name_owner_changed (NMDialupManager *manager,
+ const char *changed_service_name,
+ const char *old_owner, const char *new_owner)
+{
+ NMDialupService * service;
+ gboolean handled = FALSE;
+
+ g_return_val_if_fail (manager != NULL, FALSE);
+ g_return_val_if_fail (changed_service_name != NULL, FALSE);
+
+ if ((service = nm_dialup_manager_find_service_by_name (manager, changed_service_name)))
+ {
+ nm_dialup_service_name_owner_changed (service, manager->act_req, old_owner, new_owner);
+ handled = TRUE;
+ }
+
+ return handled;
+}
+
+
+/*
+ * nm_dialup_manager_activate_dialup_connection
+ *
+ * Signal the dialup service daemon to activate a particular dialup connection,
+ * launching that daemon if necessary.
+ *
+ */
+void
+nm_dialup_manager_activate_dialup_connection (NMDialupManager *manager,
+ NMDialupConnection *dialup,
+ char **password_items, int password_count,
+ char **data_items, int data_count)
+{
+ NMDevice * old_dev;
+ NMDialupActRequest * req;
+ NMDialupService * service;
+ const char * service_name;
+
+ g_return_if_fail (manager != NULL);
+ g_return_if_fail (dialup != NULL);
+ g_return_if_fail (password_items != NULL);
+ g_return_if_fail (data_items != NULL);
+
+ if (nm_dialup_manager_get_dialup_act_request (manager))
+ nm_dialup_manager_deactivate_dialup_connection (manager);
+
+ service_name = nm_dialup_connection_get_service_name (dialup);
+ if (!(service = nm_dialup_manager_find_service_by_name (manager, service_name)))
+ return;
+
+ req = nm_dialup_act_request_new (manager, service, dialup, password_items, password_count, data_items, data_count);
+ manager->act_req = req;
+
+ if ((old_dev = nm_get_active_device (manager->app_data)))
+ nm_device_deactivate (old_dev);
+
+ nm_dialup_service_start_connection (service, req);
+}
+
+
+/*
+ * nm_dialup_manager_deactivate_dialup_connection
+ *
+ * Signal the dialup service daemon to deactivate a particular dialup connection.
+ *
+ */
+void
+nm_dialup_manager_deactivate_dialup_connection (NMDialupManager *manager)
+{
+ NMDialupService * service;
+ NMDialupConnection * dialup;
+
+ g_return_if_fail (manager != NULL);
+
+ if (!manager->act_req)
+ return;
+
+ if (nm_dialup_act_request_is_activating (manager->act_req)
+ || nm_dialup_act_request_is_activated (manager->act_req)
+ || nm_dialup_act_request_is_failed (manager->act_req))
+ {
+ if (nm_dialup_act_request_is_activated (manager->act_req))
+ {
+ dialup = nm_dialup_act_request_get_connection (manager->act_req);
+ g_assert (dialup);
+ nm_dialup_connection_deactivate (dialup);
+ }
+
+ service = nm_dialup_act_request_get_service (manager->act_req);
+ g_assert (service);
+ nm_dialup_service_stop_connection (service, manager->act_req);
+ }
+
+ nm_dialup_act_request_unref (manager->act_req);
+ manager->act_req = NULL;
+
+ // Signal that we are disconnected
+ nm_schedule_state_change_signal_broadcast (manager->app_data);
+}
+
+
+static gboolean
+nm_dialup_manager_dialup_activation_failed (gpointer user_data)
+{
+ NMDialupActRequest * req = (NMDialupActRequest *) user_data;
+ NMDialupManager * manager;
+
+ g_assert (req);
+
+ manager = nm_dialup_act_request_get_manager (req);
+ g_assert (manager);
+
+ if (manager->act_req == req)
+ nm_dialup_manager_deactivate_dialup_connection (manager);
+
+ return FALSE;
+}
+
+
+void
+nm_dialup_manager_schedule_dialup_activation_failed (NMDialupManager *manager, NMDialupActRequest *req)
+{
+ GSource * source = NULL;
+
+ g_return_if_fail (manager != NULL);
+ g_return_if_fail (req != NULL);
+
+ source = g_idle_source_new ();
+ g_source_set_callback (source, (GSourceFunc) nm_dialup_manager_dialup_activation_failed, req, NULL);
+ g_source_attach (source, manager->app_data->main_context);
+ g_source_unref (source);
+}
+
+
+static gboolean
+nm_dialup_manager_dialup_connection_died (gpointer user_data)
+{
+ NMDialupActRequest * req = (NMDialupActRequest *) user_data;
+ NMDialupManager * manager;
+
+ g_assert (req);
+
+ manager = nm_dialup_act_request_get_manager (req);
+ g_assert (manager);
+
+ if (manager->act_req == req)
+ nm_dialup_manager_deactivate_dialup_connection (manager);
+
+ return FALSE;
+}
+
+
+void
+nm_dialup_manager_schedule_dialup_connection_died (NMDialupManager *manager, NMDialupActRequest *req)
+{
+ GSource * source = NULL;
+
+ g_return_if_fail (manager != NULL);
+ g_return_if_fail (req != NULL);
+
+ source = g_idle_source_new ();
+ g_source_set_callback (source, (GSourceFunc) nm_dialup_manager_dialup_connection_died, req, NULL);
+ g_source_attach (source, manager->app_data->main_context);
+ g_source_unref (source);
+}
+
+gboolean
+nm_dialup_manager_is_connecting (NMDialupManager *manager)
+{
+ if (!manager->act_req)
+ return FALSE;
+ else
+ return nm_dialup_act_request_is_activating (manager->act_req);
+}
+
+
+gboolean
+nm_dialup_manager_is_connected (NMDialupManager *manager)
+{
+ if (!manager->act_req)
+ return FALSE;
+ else
+ return nm_dialup_act_request_is_activated (manager->act_req);
+}
+
+
+/*********************************************************************/
+
+static void
+nm_dialup_manager_load_services (NMDialupManager *manager, GHashTable *table)
+{
+ GSList *list = NULL;
+ GDir *dialup_dir;
+
+ g_return_if_fail (manager != NULL);
+ g_return_if_fail (table != NULL);
+
+ /* Load allowed service names */
+ if ((dialup_dir = g_dir_open (DIALUP_SERVICE_FILE_PATH, 0, NULL)))
+ {
+ const char *file_name;
+
+ while ((file_name = g_dir_read_name (dialup_dir)))
+ {
+ char *file_path = g_strdup_printf (DIALUP_SERVICE_FILE_PATH"/%s", file_name);
+ char *contents;
+
+ if (g_file_get_contents (file_path, &contents, NULL, NULL) && (contents != NULL))
+ {
+ char **split_contents = g_strsplit (contents, "\n", 0);
+
+ if (split_contents)
+ {
+ int i, len;
+ NMDialupService * service = nm_dialup_service_new (manager, manager->app_data);
+ gboolean have_name = FALSE;
+ gboolean have_service = FALSE;
+ gboolean have_program = FALSE;
+
+ len = g_strv_length (split_contents);
+ for (i = 0; i < len; i++)
+ {
+ char *line = split_contents[i];
+
+#define NAME_TAG "name="
+#define SERVICE_TAG "service="
+#define PROGRAM_TAG "program="
+
+ if (!line || !strlen (line)) continue;
+
+ /* Comment lines begin with # */
+ if (line[0] == '#') continue;
+
+ if ((strncmp (line, NAME_TAG, strlen (NAME_TAG)) == 0) && !have_name)
+ {
+ char * name = g_strdup (line+strlen (NAME_TAG));
+ GSList * dup_elt;
+ gboolean found = FALSE;
+
+ for (dup_elt = list; dup_elt; dup_elt = g_slist_next (dup_elt))
+ {
+ NMDialupService *dup_svc = (NMDialupService *)(dup_elt->data);
+ if (dup_svc && nm_dialup_service_get_name (dup_svc) && !strcmp (nm_dialup_service_get_name (dup_svc), name))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ nm_dialup_service_set_name (service, (const char *)name);
+ g_free (name);
+ have_name = TRUE;
+ }
+ else if ((strncmp (line, SERVICE_TAG, strlen (SERVICE_TAG)) == 0) && !have_service)
+ {
+ char *service_name = g_strdup (line+strlen (SERVICE_TAG));
+
+ /* Deny the load if the service name is NetworkManager or NetworkManagerInfo. */
+ if (strcmp (service_name, NM_DBUS_SERVICE) && strcmp (service_name, NM_DBUS_SERVICE))
+ nm_dialup_service_set_service_name (service, (const char *)service_name);
+ else
+ nm_warning ("dialup service name matched NetworkManager or NetworkManagerInfo service names, "
+ "which is not allowed and might be malicious.");
+ g_free (service_name);
+ have_service = TRUE;
+ }
+ else if ((strncmp (line, PROGRAM_TAG, strlen (PROGRAM_TAG)) == 0) && !have_program)
+ {
+ gboolean program_ok = FALSE;
+ if ((strlen (line) >= strlen (PROGRAM_TAG) + 1))
+ {
+ if ((*(line+strlen (PROGRAM_TAG)) == '/') && (*(line+strlen (line)-1) != '/'))
+ {
+ nm_dialup_service_set_program (service, (const char *)(line+strlen (PROGRAM_TAG)));
+ program_ok = TRUE;
+ }
+ }
+ if (!program_ok)
+ nm_warning ("WARNING: dialup program '%s' invalid in file '%s'", line, file_path);
+ have_program = TRUE;
+ }
+ }
+ g_strfreev (split_contents);
+
+ if (nm_dialup_service_get_name (service) &&
+ nm_dialup_service_get_service_name (service) &&
+ nm_dialup_service_get_program (service) &&
+ ! g_hash_table_lookup(table, (char *) nm_dialup_service_get_service_name (service))
+ )
+
+ {
+ nm_info ("Adding dialup service '%s' with name '%s' and program '%s'",
+ nm_dialup_service_get_service_name (service),
+ nm_dialup_service_get_name (service),
+ nm_dialup_service_get_program (service));
+ g_hash_table_insert (table, (char *) nm_dialup_service_get_service_name (service), service);
+ }
+ else
+ nm_dialup_service_unref (service);
+ }
+ g_free (contents);
+ }
+ g_free (file_path);
+ }
+
+ g_dir_close (dialup_dir);
+ }
+}
diff --git a/src/dialup/manager/nm-dialup-manager.h b/src/dialup/manager/nm-dialup-manager.h
new file mode 100644
index 0000000000..fceb1ebbd1
--- /dev/null
+++ b/src/dialup/manager/nm-dialup-manager.h
@@ -0,0 +1,56 @@
+/* nm-dialup-manager.h - handle dialup connections within NetworkManager's framework
+ *
+ * Copyright (C) 2006 Tim Niemueller
+ * based on work Copyright (C) 2005 Dan Williams
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#ifndef NM_DIALUP_MANAGER_H
+#define NM_DIALUP_MANAGER_H
+
+#include <dbus/dbus.h>
+#include "NetworkManagerMain.h"
+#include "nm-dialup-connection.h"
+#include "nm-dialup-service.h"
+
+
+NMDialupManager * nm_dialup_manager_new (NMData *app_data);
+NMDialupConnection * nm_dialup_manager_add_connection (NMDialupManager *manager, const char *name, const char *service_name, const char *user_name);
+void nm_dialup_manager_remove_connection (NMDialupManager *manager, NMDialupConnection *dialup);
+char ** nm_dialup_manager_get_connection_names (NMDialupManager *manager);
+void nm_dialup_manager_dispose (NMDialupManager *manager);
+
+NMDialupActRequest * nm_dialup_manager_get_dialup_act_request (NMDialupManager *manager);
+
+GSList * nm_dialup_manager_dialup_connection_list_copy (NMDialupManager *manager);
+
+void nm_dialup_manager_activate_dialup_connection (NMDialupManager *manager, NMDialupConnection *dialup, char **password_items,
+ int password_count, char **data_items, int data_count );
+void nm_dialup_manager_deactivate_dialup_connection (NMDialupManager *manager);
+
+NMDialupConnection * nm_dialup_manager_find_connection_by_name (NMDialupManager *manager, const char *con_name);
+NMDialupService * nm_dialup_manager_find_service_by_name (NMDialupManager *manager, const char *service_name);
+
+gboolean nm_dialup_manager_process_signal (NMDialupManager *manager, DBusMessage *signal);
+gboolean nm_dialup_manager_process_name_owner_changed (NMDialupManager *manager, const char *service, const char *old_owner, const char *new_owner);
+
+void nm_dialup_manager_schedule_dialup_activation_failed(NMDialupManager *manager, NMDialupActRequest *req);
+void nm_dialup_manager_schedule_dialup_connection_died (NMDialupManager *manager, NMDialupActRequest *req);
+
+gboolean nm_dialup_manager_is_connecting (NMDialupManager *manager);
+gboolean nm_dialup_manager_is_connected (NMDialupManager *manager);
+
+#endif /* NM_DIALUP_MANAGER_H */
diff --git a/src/dialup/manager/nm-dialup-service.c b/src/dialup/manager/nm-dialup-service.c
new file mode 100644
index 0000000000..fd81b38420
--- /dev/null
+++ b/src/dialup/manager/nm-dialup-service.c
@@ -0,0 +1,1087 @@
+/* NetworkManager -- Network link manager
+ *
+ * Tim Niemueller [www.niemueller.de]
+ * based on work by Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2005 Red Hat, Inc.
+ * (C) Copyright 2006 Tim Niemueller
+ */
+
+#include <glib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <dbus/dbus.h>
+#include "NetworkManagerDbus.h"
+#include "NetworkManagerMain.h"
+#include "nm-dbus-dialup.h"
+#include "nm-dialup-service.h"
+#include "nm-dialup-act-request.h"
+#include "nm-utils.h"
+
+/* define this for getting dialup debug messages */
+#undef NM_DEBUG_DIALUP_CONFIG
+
+struct NMDialupService
+{
+ int refcount;
+ NMDialupManager * manager;
+ NMData * app_data;
+ gboolean watch_active;
+
+ char * name;
+ char * service;
+ char * program;
+ NMDialupState state;
+};
+
+
+static void nm_dialup_service_add_watch (NMDialupService *service);
+static void nm_dialup_service_remove_watch (NMDialupService *service);
+static void nm_dialup_service_stop_connection_internal (NMDialupService *service);
+#ifdef NM_DEBUG_DIALUP_CONFIG
+static void print_dialup_config (guint32 ip4_dialup_gateway,
+ const char *dev,
+ guint32 ip4_address,
+ guint32 ip4_ptp_address,
+ gint32 ip4_netmask,
+ guint32 *ip4_dns,
+ guint32 ip4_dns_len,
+ guint32 *ip4_nbns);
+#endif
+
+static void nm_dialup_service_schedule_stage1_daemon_exec (NMDialupService *service, NMDialupActRequest *req);
+static void nm_dialup_service_schedule_stage3_connect (NMDialupService *service, NMDialupActRequest *req);
+static void nm_dialup_service_schedule_stage2_daemon_wait (NMDialupService *service, NMDialupActRequest *req);
+static void nm_dialup_service_schedule_stage4_ip_config_get_timeout (NMDialupService *service, NMDialupActRequest *req);
+static void nm_dialup_service_cancel_callback (NMDialupService *service, NMDialupActRequest *req);
+
+
+/*
+ * nm_dialup_service_new
+ *
+ * Create a new DialupService object
+ *
+ */
+NMDialupService *nm_dialup_service_new (NMDialupManager *manager, NMData *app_data)
+{
+ NMDialupService *service = g_malloc0 (sizeof (NMDialupService));
+
+ service->refcount = 1;
+ service->state = NM_DIALUP_STATE_SHUTDOWN;
+ service->app_data = app_data;
+ service->manager = manager;
+
+ return service;
+}
+
+void nm_dialup_service_ref (NMDialupService *service)
+{
+ g_return_if_fail (service != NULL);
+
+ service->refcount++;
+}
+
+
+void nm_dialup_service_unref (NMDialupService *service)
+{
+ g_return_if_fail (service != NULL);
+
+ service->refcount--;
+ if (service->refcount <= 0)
+ {
+ g_free (service->name);
+ g_free (service->service);
+ g_free (service->program);
+ memset (service, 0, sizeof (NMDialupService));
+ g_free (service);
+ }
+}
+
+
+const char *nm_dialup_service_get_name (NMDialupService *service)
+{
+ g_return_val_if_fail (service != NULL, NULL);
+
+ return service->name;
+}
+
+
+void nm_dialup_service_set_name (NMDialupService *service, const char *name)
+{
+ g_return_if_fail (service != NULL);
+
+ if (service->name)
+ g_free (service->name);
+ service->name = g_strdup (name);
+}
+
+
+const char *nm_dialup_service_get_service_name (NMDialupService *service)
+{
+ g_return_val_if_fail (service != NULL, NULL);
+
+ return service->service;
+}
+
+
+void nm_dialup_service_set_service_name (NMDialupService *service, const char *name)
+{
+ g_return_if_fail (service != NULL);
+
+ if (service->service)
+ g_free (service->service);
+ service->service = g_strdup (name);
+
+ /* If the Dialup daemon is currently running, tell it to stop */
+ if (!dbus_bus_name_has_owner (service->app_data->dbus_connection, service->service, NULL))
+ nm_dialup_service_stop_connection_internal (service);
+}
+
+
+const char *nm_dialup_service_get_program (NMDialupService *service)
+{
+ g_return_val_if_fail (service != NULL, NULL);
+
+ return service->program;
+}
+
+
+void nm_dialup_service_set_program (NMDialupService *service, const char *program)
+{
+ g_return_if_fail (service != NULL);
+
+ if (service->program)
+ g_free (service->program);
+ service->program = g_strdup (program);
+}
+
+
+NMDialupState nm_dialup_service_get_state (NMDialupService *service)
+{
+ g_return_val_if_fail (service != NULL, NM_DIALUP_STATE_UNKNOWN);
+
+ return service->state;
+}
+
+
+static void nm_dialup_service_set_state (NMDialupService *service, const NMDialupState state)
+{
+ g_return_if_fail (service != NULL);
+
+ service->state = state;
+}
+
+
+DBusConnection *nm_dialup_service_get_dbus_connection (NMDialupService *service)
+{
+ g_return_val_if_fail (service != NULL, NULL);
+
+ return service->app_data->dbus_connection;
+}
+
+
+/*
+ * construct_op_from_service_name
+ *
+ * Construct an object path from a dbus service name by replacing
+ * all "." in the service with "/" and prepending a "/" to the
+ * object path.
+ *
+ */
+static char *construct_op_from_service_name (const char *service_name)
+{
+ char **split = NULL;
+ char *temp1;
+ char *temp2;
+
+ g_return_val_if_fail (service_name != NULL, NULL);
+
+ if (!(split = g_strsplit (service_name, ".", 0)))
+ return NULL;
+
+ temp1 = g_strjoinv ("/", split);
+ g_strfreev (split);
+ temp2 = g_strdup_printf ("/%s", temp1);
+ g_free (temp1);
+
+ return temp2;
+}
+
+
+/*
+ * nm_dialup_service_act_request_failed
+ *
+ * Clean up after an activation request and tell the dialup manager that it
+ * has failed.
+ *
+ */
+static void nm_dialup_service_act_request_failed (NMDialupService *service,
+ NMDialupActRequest *req)
+{
+ NMDialupConnection *dialup;
+
+ g_return_if_fail (service != NULL);
+ g_return_if_fail (req != NULL);
+
+ /* Sanity checks */
+ if (nm_dialup_act_request_get_service (req) != service)
+ return;
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_dialup_service_cancel_callback (service, req);
+
+ nm_dialup_act_request_set_stage (req, NM_DIALUP_ACT_STAGE_FAILED);
+ nm_info ("Dialup Activation (%s) failed.", nm_dialup_connection_get_name (dialup));
+
+ nm_dialup_act_request_unref (req);
+ nm_dialup_manager_schedule_dialup_activation_failed (service->manager, req);
+
+ // Signal that we are not connected
+ nm_schedule_state_change_signal_broadcast (service->app_data);
+}
+
+
+static void nm_dialup_service_activation_success (NMDialupService *service, NMDialupActRequest *req)
+{
+ NMDialupConnection * dialup = NULL;
+
+ g_assert (service != NULL);
+ g_assert (req != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_dialup_service_cancel_callback (service, req);
+
+ nm_dialup_act_request_set_stage (req, NM_DIALUP_ACT_STAGE_ACTIVATED);
+ nm_info ("Dialup Activation (%s) successful.", nm_dialup_connection_get_name (dialup));
+
+ // Signal that we are connected
+ nm_schedule_state_change_signal_broadcast (service->app_data);
+}
+
+
+/*
+ * nm_dialup_service_start_connection
+ *
+ * Kick off the dialup connection process.
+ *
+ */
+void nm_dialup_service_start_connection (NMDialupService *service, NMDialupActRequest *req)
+{
+ g_return_if_fail (service != NULL);
+ g_return_if_fail (req != NULL);
+
+ nm_dialup_act_request_set_stage (req, NM_DIALUP_ACT_STAGE_PREPARE);
+ nm_dialup_service_add_watch (service);
+
+ /* Start the daemon if it's not already running */
+ nm_dialup_act_request_ref (req);
+
+ // Signal that we are connecting
+ nm_schedule_state_change_signal_broadcast (service->app_data);
+
+ if (!dbus_bus_name_has_owner (service->app_data->dbus_connection, service->service, NULL))
+ nm_dialup_service_schedule_stage1_daemon_exec (service, req);
+ else
+ nm_dialup_service_schedule_stage2_daemon_wait (service, req);
+}
+
+
+/*
+ * nm_dialup_service_stage_1_daemon_exec
+ *
+ * Execute the dialup service daemon.
+ *
+ */
+static gboolean nm_dialup_service_stage1_daemon_exec (gpointer user_data)
+{
+ NMDialupActRequest * req = (NMDialupActRequest *) user_data;
+ NMDialupService * service;
+ NMDialupConnection * dialup = NULL;
+ GPtrArray * dialup_argv;
+ GError * error = NULL;
+ GPid pid;
+
+ g_assert (req != NULL);
+
+ service = nm_dialup_act_request_get_service (req);
+ g_assert (service != NULL);
+ g_assert (service->program != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_dialup_act_request_set_callback_id (req, 0);
+
+ dialup_argv = g_ptr_array_new ();
+ g_ptr_array_add (dialup_argv, service->program);
+ g_ptr_array_add (dialup_argv, NULL);
+
+ if (!g_spawn_async (NULL, (char **) dialup_argv->pdata, NULL, 0, NULL, NULL, &pid, &error))
+ {
+ g_ptr_array_free (dialup_argv, TRUE);
+ nm_warning ("(Dialup Service %s): could not launch the dialup service. error: '%s'.", service->service, error->message);
+ g_error_free (error);
+ nm_dialup_service_act_request_failed (service, req);
+ goto out;
+ }
+ g_ptr_array_free (dialup_argv, TRUE);
+ nm_info ("Dialup Activation (%s) Stage 1 of 4 (Connection Prepare) ran dialup service daemon %s (PID %d)",
+ nm_dialup_connection_get_name (dialup), service->service, pid);
+ nm_info ("Dialup Activation (%s) Stage 1 of 4 (Connection Prepare) complete.",
+ nm_dialup_connection_get_name (dialup));
+
+ nm_dialup_service_schedule_stage2_daemon_wait (service, req);
+
+out:
+ return FALSE;
+}
+
+
+static void nm_dialup_service_schedule_stage1_daemon_exec (NMDialupService *service, NMDialupActRequest *req)
+{
+ GSource * source = NULL;
+ NMDialupConnection * dialup = NULL;
+ guint id;
+
+ g_assert (service != NULL);
+ g_assert (req != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_dialup_act_request_set_stage (req, NM_DIALUP_ACT_STAGE_PREPARE);
+ nm_dialup_service_set_state (service, NM_DIALUP_STATE_SHUTDOWN);
+
+ source = g_idle_source_new ();
+ g_source_set_callback (source, (GSourceFunc) nm_dialup_service_stage1_daemon_exec, req, NULL);
+ id = g_source_attach (source, service->app_data->main_context);
+ nm_dialup_act_request_set_callback_id (req, id);
+ g_source_unref (source);
+ nm_info ("Dialup Activation (%s) Stage 1 of 4 (Connection Prepare) scheduled...", nm_dialup_connection_get_name (dialup));
+}
+
+
+/*
+ * nm_dialup_service_stage2_daemon_wait
+ *
+ * Wait until the dialup daemon has become active.
+ *
+ */
+static gboolean nm_dialup_service_stage2_daemon_wait (gpointer user_data)
+{
+ NMDialupActRequest * req = (NMDialupActRequest *) user_data;
+ NMDialupService * service;
+ NMDialupConnection * dialup = NULL;
+ gboolean service_exists = FALSE;
+
+ g_assert (req != NULL);
+
+ service = nm_dialup_act_request_get_service (req);
+ g_assert (service != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_dialup_act_request_set_callback_id (req, 0);
+
+ nm_info ("Dialup Activation (%s) Stage 2 of 4 (Connection Prepare Wait) "
+ "waiting...", nm_dialup_connection_get_name (dialup));
+
+ service_exists = dbus_bus_name_has_owner (service->app_data->dbus_connection,
+ service->service, NULL);
+ if (service_exists && (service->state == NM_DIALUP_STATE_STOPPED))
+ {
+ nm_info ("Dialup Activation (%s) Stage 2 of 4 (Connection Prepare Wait) "
+ "complete.", nm_dialup_connection_get_name (dialup));
+ nm_dialup_service_schedule_stage3_connect (service, req);
+ }
+ else if (nm_dialup_act_request_get_daemon_wait_count (req) > 10)
+ {
+ /* We only wait 2s (10 * 200 milliseconds) for the service to
+ * become available.
+ */
+ nm_dialup_service_act_request_failed (service, req);
+ }
+ else
+ nm_dialup_service_schedule_stage2_daemon_wait (service, req);
+
+ return FALSE;
+}
+
+
+static void nm_dialup_service_schedule_stage2_daemon_wait (NMDialupService *service, NMDialupActRequest *req)
+{
+ GSource * source = NULL;
+ NMDialupConnection * dialup = NULL;
+ guint id;
+
+ g_assert (service != NULL);
+ g_assert (req != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_dialup_act_request_set_stage (req, NM_DIALUP_ACT_STAGE_PREPARE);
+
+ nm_dialup_act_request_set_daemon_wait_count (req, nm_dialup_act_request_get_daemon_wait_count (req) + 1);
+
+ source = g_timeout_source_new (200);
+ g_source_set_callback (source, (GSourceFunc) nm_dialup_service_stage2_daemon_wait, req, NULL);
+ id = g_source_attach (source, service->app_data->main_context);
+ nm_dialup_act_request_set_callback_id (req, id);
+ g_source_unref (source);
+ nm_info ("Dialup Activation (%s) Stage 2 of 4 (Connection Prepare Wait) scheduled...", nm_dialup_connection_get_name (dialup));
+}
+
+
+static void nm_dialup_service_stage3_connect_cb (DBusPendingCall *pcall, void *user_data)
+{
+ DBusMessage * reply;
+ NMDialupActRequest * req = (NMDialupActRequest *) user_data;
+ NMDialupService * service;
+ NMDialupConnection * dialup;
+
+ g_assert (pcall != NULL);
+ g_assert (req != NULL);
+
+ service = nm_dialup_act_request_get_service (req);
+ g_assert (service != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_info ("Dialup Activation (%s) Stage 3 of 4 (Connect) reply received.",
+ nm_dialup_connection_get_name (dialup));
+
+ if (!(reply = dbus_pending_call_steal_reply (pcall)))
+ {
+ nm_warning ("(Dialup Service %s): could not obtain dialup service's reply.",
+ service->service);
+ nm_dialup_service_act_request_failed (service, req);
+ goto out;
+ }
+
+ if (message_is_error (reply))
+ {
+ const char *member = dbus_message_get_member (reply);
+ char *message;
+
+ if (!dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &message, NULL))
+ message = (char *) "";
+
+ nm_warning ("(Dialup Service %s): could not start the dialup '%s'. dbus says: '%s' '%s'.",
+ service->service, nm_dialup_connection_get_name (dialup), member, message);
+ nm_dialup_service_act_request_failed (service, req);
+ }
+ else
+ {
+ nm_dialup_act_request_set_stage (req, NM_DIALUP_ACT_STAGE_IP_CONFIG_GET);
+ nm_dialup_service_schedule_stage4_ip_config_get_timeout (service, req);
+ nm_info ("Dialup Activation (%s) Stage 3 of 4 (Connect) complete, "
+ "waiting for IP configuration...", nm_dialup_connection_get_name (dialup));
+ }
+
+ dbus_message_unref (reply);
+
+out:
+ dbus_pending_call_unref (pcall);
+}
+
+
+static char **
+sanitize_dbus_string_array (char **in_array, dbus_uint32_t *in_num)
+{
+ char ** out_array;
+
+ g_return_val_if_fail (in_num != NULL, NULL);
+
+ if (in_array)
+ return in_array;
+
+ out_array = g_malloc0 (sizeof (char *));
+ out_array[0] = g_strdup ("");
+ *in_num = 1;
+ return out_array;
+}
+
+
+static gboolean nm_dialup_service_stage3_connect (gpointer user_data)
+{
+ NMDialupActRequest * req = (NMDialupActRequest *) user_data;
+ NMDialupService * service;
+ NMDialupConnection * dialup;
+ char * op;
+ const char * name;
+ const char * user_name;
+ char ** password_items;
+ dbus_uint32_t password_count;
+ char ** data_items;
+ dbus_uint32_t data_count;
+ DBusMessage * message;
+ DBusPendingCall * pcall = NULL;
+
+ g_assert (req != NULL);
+
+ service = nm_dialup_act_request_get_service (req);
+ g_assert (service != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup != NULL);
+
+ nm_dialup_act_request_set_callback_id (req, 0);
+
+ /* Send the start dialup request to the daemon */
+ op = construct_op_from_service_name (service->service);
+ message = dbus_message_new_method_call (service->service, op, service->service, "startConnection");
+ g_free (op);
+ if (!message)
+ {
+ nm_warning ("(Dialup Service %s): couldn't allocate dbus message.", service->service);
+ nm_dialup_service_act_request_failed (service, req);
+ return FALSE;
+ }
+
+ name = nm_dialup_connection_get_name (dialup);
+ user_name = nm_dialup_connection_get_user_name (dialup);
+ password_items = (char **) nm_dialup_act_request_get_password_items (req, &password_count);
+ data_items = (char **) nm_dialup_act_request_get_data_items (req, &data_count);
+
+ /* Ensure that data_items are safe to put through dbus */
+ data_items = sanitize_dbus_string_array (data_items, &data_count);
+
+ nm_info ("Dialup Activation (%s) Stage 3 of 4 (Connect) sending connect request.",
+ nm_dialup_connection_get_name (dialup));
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &password_items, password_count,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &data_items, data_count,
+ DBUS_TYPE_INVALID);
+
+ dbus_connection_send_with_reply (service->app_data->dbus_connection, message, &pcall, -1);
+ if (pcall)
+ {
+ dbus_pending_call_set_notify (pcall, nm_dialup_service_stage3_connect_cb, req, NULL);
+ nm_info ("Dialup Activation (%s) Stage 3 of 4 (Connect) request sent,"
+ " waiting for reply...", nm_dialup_connection_get_name (dialup));
+ }
+ else
+ nm_dialup_service_act_request_failed (service, req);
+ dbus_message_unref (message);
+
+ return FALSE;
+}
+
+
+static void nm_dialup_service_schedule_stage3_connect (NMDialupService *service, NMDialupActRequest *req)
+{
+ GSource * source = NULL;
+ NMDialupConnection * dialup = NULL;
+ guint id;
+
+ g_assert (service != NULL);
+ g_assert (req != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_dialup_act_request_set_stage (req, NM_DIALUP_ACT_STAGE_CONNECT);
+
+ source = g_idle_source_new ();
+ g_source_set_callback (source, (GSourceFunc) nm_dialup_service_stage3_connect, req, NULL);
+ id = g_source_attach (source, service->app_data->main_context);
+ nm_dialup_act_request_set_callback_id (req, id);
+ g_source_unref (source);
+ nm_info ("Dialup Activation (%s) Stage 3 of 4 (Connect) scheduled...", nm_dialup_connection_get_name (dialup));
+}
+
+
+static gboolean nm_dialup_service_stage4_ip_config_get_timeout (gpointer *user_data)
+{
+ NMDialupActRequest * req = (NMDialupActRequest *) user_data;
+ NMDialupService * service;
+ NMDialupConnection * dialup;
+
+ g_assert (req != NULL);
+
+ service = nm_dialup_act_request_get_service (req);
+ g_assert (service != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup != NULL);
+
+ nm_dialup_act_request_set_callback_id (req, 0);
+
+ /* If the activation request's state is still IP_CONFIG_GET and we're
+ * in this timeout, cancel activation because it's taken too long.
+ */
+ if (nm_dialup_act_request_get_stage (req) == NM_DIALUP_ACT_STAGE_IP_CONFIG_GET)
+ {
+ nm_info ("Dialup Activation (%s) Stage 4 of 4 (IP Config Get) timeout exceeded.", nm_dialup_connection_get_name (dialup));
+ nm_dialup_service_act_request_failed (service, req);
+ }
+
+ return FALSE;
+}
+
+
+static void nm_dialup_service_schedule_stage4_ip_config_get_timeout (NMDialupService *service, NMDialupActRequest *req)
+{
+ GSource * source = NULL;
+ NMDialupConnection * dialup = NULL;
+ guint id;
+
+ g_assert (service != NULL);
+ g_assert (req != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_dialup_act_request_set_stage (req, NM_DIALUP_ACT_STAGE_IP_CONFIG_GET);
+
+ /* 20 second timeout waiting for IP config signal from dialup service */
+ source = g_timeout_source_new (20000);
+ g_source_set_callback (source, (GSourceFunc) nm_dialup_service_stage4_ip_config_get_timeout, req, NULL);
+ id = g_source_attach (source, service->app_data->main_context);
+ nm_dialup_act_request_set_callback_id (req, id);
+ g_source_unref (source);
+ nm_info ("Dialup Activation (%s) Stage 4 of 4 (IP Config Get) timeout scheduled...", nm_dialup_connection_get_name (dialup));
+}
+
+
+static void nm_dialup_service_cancel_callback (NMDialupService *service, NMDialupActRequest *req)
+{
+ guint id;
+
+ g_return_if_fail (service != NULL);
+ g_return_if_fail (req != NULL);
+
+ if ((id = nm_dialup_act_request_get_callback_id (req)) != 0)
+ {
+ g_source_destroy (g_main_context_find_source_by_id (service->app_data->main_context, id));
+ nm_dialup_act_request_set_callback_id (req, 0);
+ }
+}
+
+
+static gboolean
+get_dbus_guint32_helper (DBusMessageIter *iter,
+ guint32 *num,
+ char *desc)
+{
+ if (!dbus_message_iter_next (iter)
+ || (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT32))
+ {
+ nm_warning ("Error: couldn't get %s from dialup IP Config message.", desc);
+ return FALSE;
+ }
+ dbus_message_iter_get_basic (iter, num);
+ return TRUE;
+}
+
+/*
+static gboolean
+get_dbus_string_helper (DBusMessageIter *iter,
+ char **str,
+ char *desc)
+{
+ if (!dbus_message_iter_next (iter)
+ || (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRING))
+ {
+ nm_warning ("Error: couldn't get %s from dialup IP Config message.", desc);
+ return FALSE;
+ }
+ dbus_message_iter_get_basic (iter, str);
+ return TRUE;
+}
+*/
+
+/*
+ * nm_dialup_service_stage4_ip_config_get
+ *
+ * Configure a device with IPv4 config info in response the the dialup daemon.
+ *
+ */
+static void
+nm_dialup_service_stage4_ip_config_get (NMDialupService *service,
+ NMDialupActRequest *req,
+ DBusMessage *message)
+{
+ NMDialupConnection * dialup;
+ guint32 num;
+ char * dev;
+ gboolean success = FALSE;
+ DBusMessageIter iter;
+ DBusMessageIter subiter;
+ NMIP4Config * config;
+
+ g_return_if_fail (service != NULL);
+ g_return_if_fail (message != NULL);
+ g_return_if_fail (req != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_info ("Dialup Activation (%s) Stage 4 of 4 (IP Config Get) reply received.",
+ nm_dialup_connection_get_name (dialup));
+
+ config = nm_ip4_config_new ();
+ nm_ip4_config_set_secondary (config, TRUE);
+
+ dbus_message_iter_init (message, &iter);
+
+ /* First arg: device (STRING) */
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
+ {
+ nm_warning ("Error: couldn't get dialup device from dialup IP config message.");
+ goto out;
+ }
+ dbus_message_iter_get_basic (&iter, &dev);
+
+ /* Second arg: IP4 dialup gateway address (UINT32) */
+ if (!get_dbus_guint32_helper (&iter, &num, "IP4 gateway"))
+ goto out;
+ nm_ip4_config_set_gateway (config, num);
+
+ /* Third arg: IP4 dialup Local Address (UINT32) */
+ if (!get_dbus_guint32_helper (&iter, &num, "IP4 dialup Local Address"))
+ goto out;
+ nm_ip4_config_set_address (config, num);
+
+ /* Fourth arg: IP4 dialup Point-to-Point Address (UINT32) */
+ if (!get_dbus_guint32_helper (&iter, &num, "IP4 dialup PtP Address"))
+ goto out;
+ nm_ip4_config_set_ptp_address (config, num);
+
+ /* Fifth arg: IP4 dialup Local Netmask (UINT32) */
+ if (!get_dbus_guint32_helper (&iter, &num, "IP4 dialup Local Netmask"))
+ goto out;
+ /* If no netmask, default to Class C address */
+ nm_ip4_config_set_netmask (config, num ? num : 0x00FF);
+
+ /* Sixth arg: IP4 DNS Server Addresses (ARRAY, UINT32) */
+ if ( !dbus_message_iter_next (&iter)
+ || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY))
+ {
+ nm_warning ("Error: couldn't get IP4 DNS Server Addresses"
+ " from dialup IP Config message.");
+ goto out;
+ }
+ dbus_message_iter_recurse (&iter, &subiter);
+ while (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_UINT32)
+ {
+ dbus_message_iter_get_basic (&subiter, &num);
+ if (num)
+ nm_ip4_config_add_nameserver (config, num);
+ dbus_message_iter_next (&subiter);
+ }
+
+ /* Seventh arg: IP4 NBNS Server Addresses (ARRAY, UINT32) */
+ if ( !dbus_message_iter_next (&iter)
+ || (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY))
+ {
+ nm_warning ("Error: couldn't get IP4 NBNS Server Addresses"
+ " from dialup IP Config message.");
+ goto out;
+ }
+ dbus_message_iter_recurse (&iter, &subiter);
+ while (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_UINT32)
+ {
+ dbus_message_iter_get_basic (&subiter, &num);
+ /* We don't do anything with these yet */
+ dbus_message_iter_next (&subiter);
+ }
+
+ /* Ninth arg: DNS Domain (STRING)
+ if (!get_dbus_string_helper (&iter, &str, "DNS Domain"))
+ goto out;
+ if (strlen (str))
+ nm_ip4_config_add_domain (config, str);
+ */
+
+
+#ifdef NM_DEBUG_DIALUP_CONFIG
+ print_dialup_config (ip4_dialup_gateway,
+ dev,
+ ip4_address,
+ ip4_ptp_address,
+ ip4_netmask,
+ ip4_dns,
+ ip4_dns_len,
+ ip4_nbns,
+ ip4_nbns_len);
+#endif
+
+ if (nm_dialup_connection_set_config (dialup, dev, config))
+ {
+ nm_info ("Dialup Activation (%s) Stage 4 of 4 (IP Config Get) complete.",
+ nm_dialup_connection_get_name (dialup));
+ success = TRUE;
+ nm_dialup_service_activation_success (service, req);
+ }
+
+out:
+ if (!success)
+ {
+ nm_ip4_config_unref (config);
+ nm_warning ("(Dialup Service %s): did not receive valid IP config information.", service->service);
+ nm_dialup_service_act_request_failed (service, req);
+ }
+}
+
+
+static void nm_dialup_service_stop_connection_internal (NMDialupService *service)
+{
+ DBusMessage * message;
+ char * op;
+
+ g_return_if_fail (service != NULL);
+
+ /* Construct a new method call with the correct service and object path */
+ op = construct_op_from_service_name (service->service);
+ if ((message = dbus_message_new_method_call (service->service, op, service->service, "stopConnection")))
+ {
+ dbus_connection_send (service->app_data->dbus_connection, message, NULL);
+ dbus_message_unref (message);
+ }
+ else
+ nm_warning ("(Dialup Service %s): couldn't allocate dbus message.", service->service);
+
+ g_free (op);
+}
+
+
+void nm_dialup_service_stop_connection (NMDialupService *service, NMDialupActRequest *req)
+{
+ NMDialupConnection *dialup;
+
+ g_return_if_fail (service != NULL);
+ g_return_if_fail (req != NULL);
+
+ dialup = nm_dialup_act_request_get_connection (req);
+ g_assert (dialup);
+
+ nm_dialup_service_cancel_callback (service, req);
+ nm_dialup_act_request_set_stage (req, NM_DIALUP_ACT_STAGE_DISCONNECTED);
+
+ /* Ensure we can stop the connection in this state */
+ if ((service->state != NM_DIALUP_STATE_STARTED) && (service->state != NM_DIALUP_STATE_STARTING))
+ {
+ nm_warning ("(Dialup Service %s): could not stop connection '%s' because service was %d.",
+ service->service, nm_dialup_connection_get_name (dialup), service->state);
+ return;
+ }
+
+ nm_dialup_service_stop_connection_internal (service);
+ nm_dialup_service_set_state (service, NM_DIALUP_STATE_STOPPED);
+}
+
+
+static void nm_dialup_service_add_watch (NMDialupService *service)
+{
+ char * match_string = NULL;
+
+ g_return_if_fail (service != NULL);
+
+ if (service->watch_active)
+ return;
+
+ /* Add a dbus filter for this connection's service name so its signals
+ * get delivered to us.
+ */
+ match_string = g_strdup_printf ("type='signal',"
+ "interface='%s',"
+ "sender='%s'", service->service, service->service);
+ dbus_bus_add_match (service->app_data->dbus_connection, match_string, NULL);
+ g_free (match_string);
+ service->watch_active = TRUE;
+}
+
+
+static void nm_dialup_service_remove_watch (NMDialupService *service)
+{
+ char * match_string = NULL;
+
+ g_return_if_fail (service != NULL);
+
+ if (!service->watch_active)
+ return;
+
+ match_string = g_strdup_printf ("type='signal',"
+ "interface='%s',"
+ "sender='%s'", service->service, service->service);
+ dbus_bus_remove_match (service->app_data->dbus_connection, match_string, NULL);
+ g_free (match_string);
+ service->watch_active = FALSE;
+}
+
+
+static inline gboolean same_service_name (NMDialupService *service, NMDialupConnection *dialup)
+{
+ g_return_val_if_fail (service != NULL, FALSE);
+ g_return_val_if_fail (dialup != NULL, FALSE);
+
+ return (!strcmp (nm_dialup_service_get_service_name (service), nm_dialup_connection_get_service_name (dialup)));
+}
+
+
+gboolean nm_dialup_service_name_owner_changed (NMDialupService *service, NMDialupActRequest *req, const char *old, const char *new)
+{
+ NMDialupConnection * dialup;
+ gboolean valid_dialup = FALSE;
+ gboolean old_owner_good = (old && strlen (old));
+ gboolean new_owner_good = (new && strlen (new));
+
+ g_return_val_if_fail (service != NULL, FALSE);
+
+ if (req && (dialup = nm_dialup_act_request_get_connection (req)))
+ valid_dialup = same_service_name (service, dialup);
+
+ if (!old_owner_good && new_owner_good)
+ {
+ /* dialup service started. */
+ nm_dialup_service_add_watch (service);
+ nm_dialup_service_set_state (service, NM_DIALUP_STATE_INIT);
+ }
+ else if (old_owner_good && !new_owner_good)
+ {
+ /* dialup service went away. */
+ nm_dialup_service_set_state (service, NM_DIALUP_STATE_SHUTDOWN);
+ nm_dialup_service_remove_watch (service);
+
+ if (valid_dialup)
+ {
+ nm_dialup_act_request_unref (req);
+ nm_dialup_manager_schedule_dialup_connection_died (service->manager, req);
+ }
+ }
+
+ return TRUE;
+}
+
+
+gboolean nm_dialup_service_process_signal (NMDialupService *service, NMDialupActRequest *req, DBusMessage *message)
+{
+ NMDialupConnection * dialup = NULL;
+ gboolean valid_dialup = FALSE;
+
+ g_return_val_if_fail (service != NULL, FALSE);
+ g_return_val_if_fail (message != NULL, FALSE);
+
+ if (req && (dialup = nm_dialup_act_request_get_connection (req)))
+ valid_dialup = same_service_name (service, dialup);
+
+ if ( dbus_message_is_signal (message, service->service, NM_DBUS_DIALUP_SIGNAL_LOGIN_FAILED)
+ || dbus_message_is_signal (message, service->service, NM_DBUS_DIALUP_SIGNAL_LAUNCH_FAILED)
+ || dbus_message_is_signal (message, service->service, NM_DBUS_DIALUP_SIGNAL_CONNECT_FAILED)
+ || dbus_message_is_signal (message, service->service, NM_DBUS_DIALUP_SIGNAL_DIALUP_CONFIG_BAD)
+ || dbus_message_is_signal (message, service->service, NM_DBUS_DIALUP_SIGNAL_IP_CONFIG_BAD))
+ {
+ const char * member = dbus_message_get_member (message);
+ char * error_msg;
+
+ if (valid_dialup)
+ {
+ if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &error_msg, DBUS_TYPE_INVALID))
+ error_msg = (char *) "";
+ nm_warning ("Dialup failed for service '%s', signal '%s', with message '%s'.", service->service, member, error_msg);
+ nm_dbus_dialup_signal_dialup_failed (service->app_data->dbus_connection, member, dialup, error_msg);
+ /* Don't deal with dialup Connection stopping here, we'll do that when we get the STOPPED or STOPPING signal below */
+ }
+ }
+ else if (dbus_message_is_signal (message, service->service, NM_DBUS_DIALUP_SIGNAL_STATE_CHANGE))
+ {
+ dbus_uint32_t old_state_int;
+ dbus_uint32_t new_state_int;
+
+ if (dbus_message_get_args (message, NULL, DBUS_TYPE_UINT32, &old_state_int, DBUS_TYPE_UINT32, &new_state_int, DBUS_TYPE_INVALID))
+ {
+ NMDialupState old_state = (NMDialupState) old_state_int;
+ NMDialupState new_state = (NMDialupState) new_state_int;
+
+ nm_info ("Dialup service '%s' signaled state change %d -> %d.", service->service, old_state, new_state);
+ nm_dialup_service_set_state (service, new_state);
+
+ /* If the dialup daemon state is now stopped and it was starting, clear the active connection */
+ if (((new_state == NM_DIALUP_STATE_STOPPED) || (new_state == NM_DIALUP_STATE_SHUTDOWN) || (new_state == NM_DIALUP_STATE_STOPPING))
+ && ((old_state == NM_DIALUP_STATE_STARTED) || (old_state == NM_DIALUP_STATE_STARTING))
+ && valid_dialup)
+ {
+ nm_dialup_act_request_unref (req);
+ nm_dialup_manager_schedule_dialup_connection_died (service->manager, req);
+ }
+ }
+ }
+ else if (valid_dialup && dbus_message_is_signal (message, service->service, NM_DBUS_DIALUP_SIGNAL_IP4_CONFIG))
+ nm_dialup_service_stage4_ip_config_get (service, req, message);
+
+ return TRUE;
+}
+
+#ifdef NM_DEBUG_DIALUP_CONFIG
+/*
+ * Prints config returned from the service daemo
+ */
+static void print_dialup_config (guint32 ip4_dialup_gateway,
+ const char *dev,
+ guint32 ip4_address,
+ guint32 ip4_ptp_address,
+ guint32 ip4_netmask,
+ guint32 *ip4_dns,
+ guint32 ip4_dns_len,
+ guint32 *ip4_nbns,
+ guint32 ip4_nbns_len)
+{
+ struct in_addr temp_addr;
+ guint32 i;
+
+ temp_addr.s_addr = ip4_dialup_gateway;
+ nm_info ("Dialup Gateway: %s", inet_ntoa (temp_addr));
+ nm_info ("Device: %s", dev);
+ temp_addr.s_addr = ip4_address;
+ nm_info ("Internal IP4 Address: %s", inet_ntoa (temp_addr));
+ temp_addr.s_addr = ip4_netmask;
+ nm_info ("Internal IP4 Netmask: %s", inet_ntoa (temp_addr));
+ temp_addr.s_addr = ip4_ptp_address;
+ nm_info ("Internal IP4 Point-to-Point Address: %s", inet_ntoa (temp_addr));
+ nm_info ("Maximum Segment Size (MSS): %d", mss);
+
+ for (i = 0; i < ip4_dns_len; i++)
+ {
+ if (ip4_dns[i] != 0)
+ {
+ temp_addr.s_addr = ip4_dns[i];
+ nm_info ("Internal IP4 DNS: %s", inet_ntoa (temp_addr));
+ }
+ }
+
+ for (i = 0; i < ip4_nbns_len; i++)
+ {
+ if (ip4_nbns[i] != 0)
+ {
+ temp_addr.s_addr = ip4_nbns[i];
+ nm_info ("Internal IP4 NBNS: %s", inet_ntoa (temp_addr));
+ }
+ }
+}
+
+#endif
diff --git a/src/dialup/manager/nm-dialup-service.h b/src/dialup/manager/nm-dialup-service.h
new file mode 100644
index 0000000000..b3e723019b
--- /dev/null
+++ b/src/dialup/manager/nm-dialup-service.h
@@ -0,0 +1,61 @@
+/* NetworkManager -- Network link manager
+ *
+ * Tim Niemueller [www.niemueller.de]
+ * based on work by Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2005 Red Hat, Inc.
+ * (C) Copyright 2006 Tim Niemueller
+ */
+
+#ifndef NM_DIALUP_SERVICE_H
+#define NM_DIALUP_SERVICE_H
+
+
+#include <dbus/dbus.h>
+#include "NetworkManager.h"
+#include "NetworkManagerDialup.h"
+#include "NetworkManagerMain.h"
+#include "nm-dialup-connection.h"
+
+typedef struct NMDialupService NMDialupService;
+
+
+NMDialupService * nm_dialup_service_new (NMDialupManager *manager, NMData *app_data);
+
+void nm_dialup_service_ref (NMDialupService *service);
+void nm_dialup_service_unref (NMDialupService *service);
+
+const char * nm_dialup_service_get_name (NMDialupService *service);
+void nm_dialup_service_set_name (NMDialupService *service, const char *name);
+
+const char * nm_dialup_service_get_service_name (NMDialupService *service);
+void nm_dialup_service_set_service_name (NMDialupService *service, const char *name);
+
+const char * nm_dialup_service_get_program (NMDialupService *service);
+void nm_dialup_service_set_program (NMDialupService *service, const char *program);
+
+DBusConnection* nm_dialup_service_get_dbus_connection (NMDialupService *service);
+
+NMDialupState nm_dialup_service_get_state (NMDialupService *service);
+
+gboolean nm_dialup_service_name_owner_changed (NMDialupService *service, NMDialupActRequest *req, const char *old, const char *new);
+gboolean nm_dialup_service_process_signal (NMDialupService *service, NMDialupActRequest *req, DBusMessage *message);
+
+void nm_dialup_service_start_connection (NMDialupService *service, NMDialupActRequest *req);
+void nm_dialup_service_stop_connection (NMDialupService *service, NMDialupActRequest *req);
+
+#endif