NetworkManager/info-daemon/NetworkManagerInfoDbus.c
Dan Williams f39b3344c1 2004-10-08 Dan Williams <dcbw@redhat.com>
* info-daemon/NetworkManagerInfo.[ch]
	  info-dameon/NetworkManagerInfoDbus.[ch]
	  info-daemon/NetworkManagerInfoPassphraseDialog.[ch]
		- Preserve original label text in the passphrase dialog so that
			it actually gets updated with the new network name the next
			time around.  Previously, we were overwriting it so you'd get
			the wrong network name to enter a key for
		- Add a "Key Type" combo to the passphrase dialog, user selects
			encryption key type now, type is stored in GConf too
		- Adjust NM<->NMI DBUS protocol to pass the key type back to NM too

	* src/NetworkManagerAP.[ch]
		- Remove all the encyption method magic.  It's now set by the user
			and NetworkManager retrieves the type of encryption key from
			NetworkManagerInfo

	* src/NetworkManagerAPList.[ch]
	  src/NetworkManagerDbus.[ch]
		- Adjust to new way of setting encryption key and method
		- Pull encryption method down from NMI along with key

	* src/NetworkManagerDevice.[ch]
		- Removed encryption method fallback magic as the method is now
			determined by the user.  This greatly simplifies the connection
			logic.
		- More robust connection/link logic.  Besides removing the encryption
			method fallback magic, check whether or not the card is receiving
			invalidly encrypted packets, which usually indicates that we have
			a bad WEP key set.
		- Don't blindly forge ahead when DHCP fails (still not completely fixed)

	* test/nminfotest.c
		- Test out new "Key Type" stuff in the NMI passphrase dialog


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@195 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2004-10-08 05:22:17 +00:00

639 lines
19 KiB
C

/* NetworkManagerInfo -- Manage allowed access points and provide a UI
* for WEP key entry
*
* 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 2004 Red Hat, Inc.
*/
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <stdio.h>
#include <string.h>
#include <libgnomevfs/gnome-vfs-utils.h>
#include "NetworkManagerInfo.h"
#include "NetworkManagerInfoDbus.h"
#include "NetworkManagerInfoPassphraseDialog.h"
#define NM_DBUS_SERVICE "org.freedesktop.NetworkManager"
#define NM_DBUS_PATH "/org/freedesktop/NetworkManager"
#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager"
#define NM_DBUS_PATH_DEVICES "/org/freedesktop/NetworkManager/Devices"
#define NM_DBUS_INTERFACE_DEVICES "org.freedesktop.NetworkManager.Devices"
#define NMI_DBUS_SERVICE "org.freedesktop.NetworkManagerInfo"
#define NMI_DBUS_PATH "/org/freedesktop/NetworkManagerInfo"
#define NMI_DBUS_INTERFACE "org.freedesktop.NetworkManagerInfo"
/*
* nmi_network_type_valid
*
* Helper to validate network types NMI can deal with
*
*/
inline gboolean nmi_network_type_valid (NMINetworkType type)
{
return ((type == NETWORK_TYPE_ALLOWED));
}
/*
* nmi_dbus_create_error_message
*
* Make a DBus error message
*
*/
static DBusMessage *nmi_dbus_create_error_message (DBusMessage *message, const char *exception_namespace,
const char *exception, const char *format, ...)
{
DBusMessage *reply_message;
va_list args;
char error_text[512];
va_start (args, format);
vsnprintf (error_text, 512, format, args);
va_end (args);
char *exception_text = g_strdup_printf ("%s.%s", exception_namespace, exception);
reply_message = dbus_message_new_error (message, exception_text, error_text);
g_free (exception_text);
return (reply_message);
}
/*
* nmi_dbus_get_key_for_network
*
* Throw up the user key dialog
*
*/
static void nmi_dbus_get_key_for_network (NMIAppInfo *info, DBusMessage *message)
{
DBusError error;
char *device = NULL;
char *network = NULL;
dbus_error_init (&error);
if (dbus_message_get_args (message, &error,
DBUS_TYPE_STRING, &device,
DBUS_TYPE_STRING, &network,
DBUS_TYPE_INVALID))
{
nmi_passphrase_dialog_show (device, network, info);
dbus_free (device);
dbus_free (network);
}
}
/*
* nmi_dbus_dbus_return_user_key
*
* Alert NetworkManager of the new user key
*
*/
void nmi_dbus_return_user_key (DBusConnection *connection, const char *device,
const char *network, const char *passphrase, const char *key_type_string)
{
DBusMessage *message;
g_return_if_fail (connection != NULL);
g_return_if_fail (device != NULL);
g_return_if_fail (network != NULL);
g_return_if_fail (passphrase != NULL);
if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "setKeyForNetwork")))
{
syslog (LOG_ERR, "nmi_dbus_return_user_key(): Couldn't allocate the dbus message");
return;
}
/* Add network name and passphrase */
if (dbus_message_append_args (message, DBUS_TYPE_STRING, device,
DBUS_TYPE_STRING, network,
DBUS_TYPE_STRING, passphrase,
DBUS_TYPE_STRING, key_type_string,
DBUS_TYPE_INVALID))
{
if (!dbus_connection_send (connection, message, NULL))
syslog (LOG_ERR, "nmi_dbus_return_user_key(): dbus could not send the message");
}
dbus_message_unref (message);
}
/*
* nmi_dbus_signal_update_network
*
* Signal NetworkManager that it needs to update info associated with a particular
* allowed/ignored network.
*
*/
void nmi_dbus_signal_update_network (DBusConnection *connection, const char *network, NMINetworkType type)
{
DBusMessage *message;
g_return_if_fail (connection != NULL);
g_return_if_fail (network != NULL);
if (type != NETWORK_TYPE_ALLOWED)
return;
message = dbus_message_new_signal (NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "WirelessNetworkUpdate");
if (!message)
{
syslog (LOG_ERR, "nmi_dbus_signal_update_network(): Not enough memory for new dbus message!");
return;
}
dbus_message_append_args (message, DBUS_TYPE_STRING, network, DBUS_TYPE_INVALID);
if (!dbus_connection_send (connection, message, NULL))
syslog (LOG_WARNING, "nmi_dbus_signal_update_network(): Could not raise the 'WirelessNetworkUpdate' signal!");
dbus_message_unref (message);
}
/*
* nmi_dbus_get_networks
*
* Grab a list of access points from GConf and return it in the form
* of a string array in a dbus message.
*
*/
static DBusMessage *nmi_dbus_get_networks (NMIAppInfo *info, DBusMessage *message)
{
GSList *dir_list = NULL;
GSList *element = NULL;
DBusError error;
DBusMessage *reply_message = NULL;
DBusMessageIter iter;
DBusMessageIter iter_array;
NMINetworkType type;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
dbus_error_init (&error);
if (!dbus_message_get_args (message, &error, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID))
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments",
"NetworkManagerInfo::getNetworks called with invalid arguments.");
return (reply_message);
}
if (!nmi_network_type_valid (type))
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments",
"NetworkManagerInfo::getNetworks called with an invalid network type %d.", type);
return (reply_message);
}
/* List all allowed access points that gconf knows about */
element = dir_list = gconf_client_all_dirs (info->gconf_client, NMI_GCONF_WIRELESS_NETWORKS_PATH, NULL);
if (!dir_list)
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "NoNetworks",
"There were are no wireless networks stored.");
}
else
{
gboolean value_added = FALSE;
reply_message = dbus_message_new_method_return (message);
dbus_message_iter_init (reply_message, &iter);
dbus_message_iter_append_array (&iter, &iter_array, DBUS_TYPE_STRING);
/* Append the essid of every allowed or ignored access point we know of
* to a string array in the dbus message.
*/
while (element)
{
char key[100];
GConfValue *value;
g_snprintf (&key[0], 99, "%s/essid", (char *)(element->data));
value = gconf_client_get (info->gconf_client, key, NULL);
if (value && gconf_value_get_string (value))
{
dbus_message_iter_append_string (&iter_array, gconf_value_get_string (value));
value_added = TRUE;
gconf_value_free (value);
}
g_free (element->data);
element = element->next;
}
g_slist_free (dir_list);
/* Make sure that there's at least one array element if all the gconf calls failed */
if (!value_added)
{
dbus_message_unref (reply_message);
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "NoNetworks",
"There were are no wireless networks stored.");
}
}
return (reply_message);
}
/*
* nmi_dbus_get_network_timestamp
*
* If the specified network exists, get its timestamp from gconf
* and pass it back as a dbus message.
*
*/
static DBusMessage *nmi_dbus_get_network_timestamp (NMIAppInfo *info, DBusMessage *message)
{
DBusMessage *reply_message = NULL;
gchar *key = NULL;
char *network = NULL;
GConfValue *value;
DBusError error;
NMINetworkType type;
char *escaped_network;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
dbus_error_init (&error);
if ( !dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID)
|| !nmi_network_type_valid (type)
|| (strlen (network) <= 0))
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments",
"NetworkManagerInfo::getNetworkTimestamp called with invalid arguments.");
return (reply_message);
}
/* Grab timestamp key for our access point from GConf */
escaped_network = gnome_vfs_escape_string (network);
key = g_strdup_printf ("%s/%s/timestamp", NMI_GCONF_WIRELESS_NETWORKS_PATH, escaped_network);
g_free (escaped_network);
value = gconf_client_get (info->gconf_client, key, NULL);
g_free (key);
if (value)
{
reply_message = dbus_message_new_method_return (message);
dbus_message_append_args (reply_message, DBUS_TYPE_INT32, gconf_value_get_int (value), DBUS_TYPE_INVALID);
gconf_value_free (value);
}
else
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "BadNetworkData",
"NetworkManagerInfo::getNetworkTimestamp could not access data for network '%s'", network);
}
dbus_free (network);
return (reply_message);
}
/*
* nmi_dbus_get_network_essid
*
* If the specified network exists, get its essid from gconf
* and pass it back as a dbus message.
*
*/
static DBusMessage *nmi_dbus_get_network_essid (NMIAppInfo *info, DBusMessage *message)
{
DBusMessage *reply_message = NULL;
gchar *key = NULL;
char *network = NULL;
GConfValue *value;
DBusError error;
NMINetworkType type;
char *escaped_network;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
dbus_error_init (&error);
if ( !dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID)
|| !nmi_network_type_valid (type)
|| (strlen (network) <= 0))
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments",
"NetworkManagerInfo::getNetworkEssid called with invalid arguments.");
return (reply_message);
}
/* Grab essid key for our access point from GConf */
escaped_network = gnome_vfs_escape_string (network);
key = g_strdup_printf ("%s/%s/essid", NMI_GCONF_WIRELESS_NETWORKS_PATH, escaped_network);
g_free (escaped_network);
value = gconf_client_get (info->gconf_client, key, NULL);
g_free (key);
if (value)
{
reply_message = dbus_message_new_method_return (message);
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, gconf_value_get_string (value), DBUS_TYPE_INVALID);
gconf_value_free (value);
}
else
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "BadNetworkData",
"NetworkManagerInfo::getNetworkEssid could not access data for network '%s'", network);
}
dbus_free (network);
return (reply_message);
}
/*
* nmi_dbus_get_network_key
*
* If the specified network exists, get its key and key type from gconf
* and pass it back as a dbus message.
*
*/
static DBusMessage *nmi_dbus_get_network_key (NMIAppInfo *info, DBusMessage *message)
{
DBusMessage *reply_message = NULL;
gchar *key = NULL;
char *network = NULL;
GConfValue *key_value;
GConfValue *key_type_value;
DBusError error;
NMINetworkType type;
char *escaped_network;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
dbus_error_init (&error);
if ( !dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID)
|| !nmi_network_type_valid (type)
|| (strlen (network) <= 0))
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments",
"NetworkManagerInfo::getNetworkKey called with invalid arguments.");
return (reply_message);
}
/* Grab user-key key for our access point from GConf */
escaped_network = gnome_vfs_escape_string (network);
key = g_strdup_printf ("%s/%s/key", NMI_GCONF_WIRELESS_NETWORKS_PATH, escaped_network);
key_value = gconf_client_get (info->gconf_client, key, NULL);
g_free (key);
key = g_strdup_printf ("%s/%s/key_type", NMI_GCONF_WIRELESS_NETWORKS_PATH, escaped_network);
key_type_value = gconf_client_get (info->gconf_client, key, NULL);
g_free (key);
g_free (escaped_network);
/* We don't error out if no key was found in gconf, we return blank key */
reply_message = dbus_message_new_method_return (message);
if (key_value && key_type_value)
{
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, gconf_value_get_string (key_value),
DBUS_TYPE_STRING, gconf_value_get_string (key_type_value), DBUS_TYPE_INVALID);
}
else
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, "", DBUS_TYPE_STRING, "", DBUS_TYPE_INVALID);
if (key_value)
gconf_value_free (key_value);
if (key_type_value)
gconf_value_free (key_type_value);
return (reply_message);
}
/*
* nmi_dbus_get_network_trusted
*
* If the specified network exists, get its "trusted" value
* from gconf and pass it back.
*
*/
static DBusMessage *nmi_dbus_get_network_trusted (NMIAppInfo *info, DBusMessage *message)
{
DBusMessage *reply_message = NULL;
gchar *key = NULL;
char *network = NULL;
GConfValue *value;
DBusError error;
NMINetworkType type;
char *escaped_network;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
dbus_error_init (&error);
if ( !dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID)
|| !nmi_network_type_valid (type)
|| (strlen (network) <= 0))
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments",
"NetworkManagerInfo::getNetworkTrusted called with invalid arguments.");
return (reply_message);
}
/* Grab user-key key for our access point from GConf */
escaped_network = gnome_vfs_escape_string (network);
key = g_strdup_printf ("%s/%s/trusted", NMI_GCONF_WIRELESS_NETWORKS_PATH, escaped_network);
g_free (escaped_network);
value = gconf_client_get (info->gconf_client, key, NULL);
g_free (key);
/* We don't error out if no key was found in gconf, we return blank key */
reply_message = dbus_message_new_method_return (message);
if (value)
{
dbus_message_append_args (reply_message, DBUS_TYPE_BOOLEAN, gconf_value_get_bool (value), DBUS_TYPE_INVALID);
gconf_value_free (value);
}
else
dbus_message_append_args (reply_message, DBUS_TYPE_BOOLEAN, FALSE, DBUS_TYPE_INVALID);
return (reply_message);
}
/*
* nmi_dbus_nmi_message_handler
*
* Responds to requests for our services
*
*/
static DBusHandlerResult nmi_dbus_nmi_message_handler (DBusConnection *connection, DBusMessage *message, void *user_data)
{
const char *method;
const char *path;
NMIAppInfo *info = (NMIAppInfo *)user_data;
DBusMessage *reply_message = NULL;
g_return_val_if_fail (info != NULL, DBUS_HANDLER_RESULT_HANDLED);
method = dbus_message_get_member (message);
path = dbus_message_get_path (message);
/* syslog (LOG_WARNING, "nmi_dbus_nmi_message_handler() got method %s for path %s", method, path);*/
if (strcmp ("getKeyForNetwork", method) == 0)
{
GtkWidget *dialog = glade_xml_get_widget (info->passphrase_dialog, "passphrase_dialog");
if (!GTK_WIDGET_VISIBLE (dialog))
nmi_dbus_get_key_for_network (info, message);
}
else if (strcmp ("cancelGetKeyForNetwork", method) == 0)
{
GtkWidget *dialog = glade_xml_get_widget (info->passphrase_dialog, "passphrase_dialog");
if (GTK_WIDGET_VISIBLE (dialog))
nmi_passphrase_dialog_cancel (info);
}
else if (strcmp ("getNetworks", method) == 0)
reply_message = nmi_dbus_get_networks (info, message);
else if (strcmp ("getNetworkTimestamp", method) == 0)
reply_message = nmi_dbus_get_network_timestamp (info, message);
else if (strcmp ("getNetworkEssid", method) == 0)
reply_message = nmi_dbus_get_network_essid (info, message);
else if (strcmp ("getNetworkKey", method) == 0)
reply_message = nmi_dbus_get_network_key (info, message);
else if (strcmp ("getNetworkTrusted", method) == 0)
reply_message = nmi_dbus_get_network_trusted (info, message);
else
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "UnknownMethod",
"NetworkManagerInfo knows nothing about the method %s for object %s", method, path);
}
if (reply_message)
{
dbus_connection_send (connection, reply_message, NULL);
dbus_message_unref (reply_message);
}
return (DBUS_HANDLER_RESULT_HANDLED);
}
/*
* nmi_dbus_nmi_unregister_handler
*
* Nothing happens here.
*
*/
void nmi_dbus_nmi_unregister_handler (DBusConnection *connection, void *user_data)
{
/* do nothing */
}
static DBusHandlerResult nmi_dbus_filter (DBusConnection *connection, DBusMessage *message, void *user_data)
{
char *ap_path;
char *dev_path;
DBusError error;
gboolean handled = FALSE;
NMIAppInfo *info = (NMIAppInfo *) user_data;
gboolean appeared = FALSE;
gboolean disappeared = FALSE;
g_return_val_if_fail (info != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkAppeared"))
appeared = TRUE;
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkDisappeared"))
disappeared = TRUE;
if (appeared || disappeared)
{
dbus_error_init (&error);
if (dbus_message_get_args (message, &error,
DBUS_TYPE_STRING, &dev_path,
DBUS_TYPE_STRING, &ap_path,
DBUS_TYPE_INVALID))
{
#if 0
if (appeared)
nmi_new_networks_dialog_add_network (ap_path, info);
else if (disappeared)
nmi_new_networks_dialog_add_network (ap_path, info);
#endif
dbus_free (dev_path);
dbus_free (ap_path);
handled = TRUE;
}
}
return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
}
/*
* nmi_dbus_service_init
*
* Connect to the system messagebus and register ourselves as a service.
*
*/
int nmi_dbus_service_init (DBusConnection *dbus_connection, NMIAppInfo *info)
{
DBusError dbus_error;
DBusObjectPathVTable nmi_vtable = { &nmi_dbus_nmi_unregister_handler, &nmi_dbus_nmi_message_handler, NULL, NULL, NULL, NULL };
dbus_error_init (&dbus_error);
dbus_bus_acquire_service (dbus_connection, NMI_DBUS_SERVICE, 0, &dbus_error);
if (dbus_error_is_set (&dbus_error))
{
syslog (LOG_ERR, "nmi_dbus_service_init() could not acquire its service. dbus_bus_acquire_service() says: '%s'", dbus_error.message);
dbus_error_free (&dbus_error);
return (-1);
}
if (!dbus_connection_register_object_path (dbus_connection, NMI_DBUS_PATH, &nmi_vtable, info))
{
syslog (LOG_ERR, "nmi_dbus_service_init() could not register a handler for NetworkManagerInfo. Not enough memory?");
return (-1);
}
if (!dbus_connection_add_filter (dbus_connection, nmi_dbus_filter, info, NULL))
return (-1);
dbus_error_init (&dbus_error);
dbus_bus_add_match (dbus_connection,
"type='signal',"
"interface='" NM_DBUS_INTERFACE "',"
"sender='" NM_DBUS_SERVICE "',"
"path='" NM_DBUS_PATH "'", &dbus_error);
if (dbus_error_is_set (&dbus_error))
{
dbus_error_free (&dbus_error);
return (-1);
}
return (0);
}