NetworkManager/src/NetworkManagerDbus.c
Colin Walters 6871fe28bc 2004-08-29 Colin Walters <walters@verbum.org>
* test/nminfotest.c: Include string.h and stdlib.h.
	(get_network_string_property, get_networks_of_type): Return NULL.

	* test/nmclienttest.c (get_device_name, get_active_device): Return
	NULL.

	* src/backends/NetworkManagerRedHat.c (nm_system_device_stop_dhcp): Just
	use strlen, fgets always NULL-terminates the string.

	* src/NetworkManagerDbus.c (nm_dbus_nmi_filter,
	dbus_message_get_member): Remove /* in comment.

	* src/NetworkManagerUtils.c (LOCKING_DEBUG): Ditto.

	* src/NetworkManager.c (quit): Unused, delete.
	(nm_data_free): Cast arg to GFunc.

	* panel-applet/NMWirelessAppletDbus.c: Need to include
	string.h, and dbus-glib-lowlevel.h (the latter is needed
	for dbus_connection_setup_with_g_main at present).
	(nmwa_dbus_update_wireless_network_list): Parenthesize
	assignment in conditional.
	(nmwa_dbus_worker): Return NULL.

	* panel-applet/NMWirelessApplet.c (nmwa_redraw)
	(nmwa_get_menu_pos, nmwa_toplevel_menu_activate)
	(nmwa_menu_add_text_item, nmwa_setup_widgets): Kill unused variables.
	(nmwa_populate_menu): Return NULL on failure, instead of just
	return;

	* initscript/NMLaunchHelper.c (g_timeout_add): Cast arg to GSourceFunc.

	* info-daemon/NetworkManagerInfoNetworksDialog.c (nmi_networks_dialog_init): Kill unused
	variables.

	* info-daemon/NetworkManagerInfo.c (nmi_print_usage): Unused,
	delete.


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@105 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2004-08-29 06:06:51 +00:00

1307 lines
38 KiB
C

/* 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 2004 Red Hat, Inc.
*/
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <dbus/dbus-glib.h>
#include <stdarg.h>
#include <iwlib.h>
extern gboolean debug;
#include "NetworkManager.h"
#include "NetworkManagerUtils.h"
#include "NetworkManagerDevice.h"
#include "NetworkManagerDbus.h"
#include "NetworkManagerAP.h"
#include "NetworkManagerAPList.h"
/*
* nm_dbus_create_error_message
*
* Make a DBus error message
*
*/
static DBusMessage *nm_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);
}
/*
* nm_dbus_get_object_path_from_device
*
* Copies the object path for a device object. Caller must free returned string.
*
*/
static unsigned char * nm_dbus_get_object_path_from_device (NMDevice *dev)
{
g_return_val_if_fail (dev != NULL, NULL);
return (g_strdup_printf ("%s/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev)));
}
/*
* nm_dbus_get_device_from_object_path
*
* Returns the device associated with a dbus object path
*
*/
static NMDevice *nm_dbus_get_device_from_object_path (NMData *data, const char *path)
{
NMDevice *dev = NULL;
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (data != NULL, NULL);
/* FIXME
* This function could be much more efficient, for example we could
* actually _parse_ the object path, but that's a lot more code and
* stupid stuff. The approach below is slower, less efficient, but
* less code and less error-prone.
*/
/* Iterate over device list */
if (nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__))
{
GSList *element = data->dev_list;
char compare_path[100];
while (element)
{
if ((dev = (NMDevice *)(element->data)))
{
snprintf (compare_path, 100, "%s/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev));
/* Compare against our constructed path, but ignore any trailing elements */
if (strncmp (path, compare_path, strlen (compare_path)) == 0)
break;
dev = NULL;
}
element = g_slist_next (element);
}
nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__);
}
return (dev);
}
/*
* nm_dbus_get_ap_from_object_path
*
* Returns the network (ap) associated with a dbus object path
*
*/
static NMAccessPoint *nm_dbus_get_ap_from_object_path (const char *path, NMDevice *dev)
{
NMAccessPoint *ap = NULL;
NMAccessPointList *ap_list;
NMAPListIter *iter;
char compare_path[100];
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (dev != NULL, NULL);
ap_list = nm_device_ap_list_get (dev);
if (!ap_list)
return (NULL);
if (!(iter = nm_ap_list_iter_new (ap_list)))
return (NULL);
while ((ap = nm_ap_list_iter_next (iter)))
{
snprintf (compare_path, 100, "%s/%s/Networks/%s", NM_DBUS_PATH_DEVICES,
nm_device_get_iface (dev), nm_ap_get_essid (ap));
if (strncmp (path, compare_path, strlen (compare_path)) == 0)
break;
}
nm_ap_list_iter_free (iter);
return (ap);
}
/*
* nm_dbus_nm_get_active_device
*
* Returns the object path of the currently active device
*
*/
static DBusMessage *nm_dbus_nm_get_active_device (DBusConnection *connection, DBusMessage *message, NMData *data)
{
DBusMessage *reply_message = NULL;
g_return_val_if_fail (data != NULL, NULL);
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
/* Construct object path of "active" device and return it */
if (data->active_device)
{
char *object_path;
reply_message = dbus_message_new_method_return (message);
if (!reply_message)
return (NULL);
object_path = g_strdup_printf ("%s/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (data->active_device));
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, object_path, DBUS_TYPE_INVALID);
g_free (object_path);
}
else
{
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoActiveDevice",
"There is no currently active device.");
}
return (reply_message);
}
/*
* nm_dbus_nm_set_active_device
*
* Notify the state modification handler that we want to lock to a specific
* device.
*
*/
static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DBusMessage *message, NMData *data)
{
NMDevice *dev = NULL;
DBusMessage *reply_message = NULL;
char *dev_path = NULL;
DBusError error;
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
g_return_val_if_fail (data != NULL, NULL);
dbus_error_init (&error);
if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev_path, DBUS_TYPE_INVALID))
{
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments",
"NetworkManager::setActiveDevice called with invalid arguments.");
return (reply_message);
}
dev = nm_dbus_get_device_from_object_path (data, dev_path);
dbus_free (dev_path);
if (!dev)
{
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound",
"The requested network device does not exist.");
return (reply_message);
}
if (!(reply_message = dbus_message_new_method_return (message)))
return (NULL);
/* Notify the state modification handler that we'd like to lock on a specific device */
if (nm_try_acquire_mutex (data->user_device_mutex, __FUNCTION__))
{
if (data->user_device)
nm_device_unref (data->user_device);
nm_device_ref (dev);
data->user_device = dev;
nm_unlock_mutex (data->user_device_mutex, __FUNCTION__);
nm_data_set_state_modified (data, TRUE);
}
return (reply_message);
}
/*
* nm_dbus_nm_get_devices
*
* Returns a string array of object paths corresponding to the
* devices in the device list.
*
*/
static DBusMessage *nm_dbus_nm_get_devices (DBusConnection *connection, DBusMessage *message, NMData *data)
{
DBusMessage *reply_message = NULL;
DBusMessageIter iter;
DBusMessageIter iter_array;
g_return_val_if_fail (data != NULL, NULL);
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
/* Check for no devices */
if (!data->dev_list)
return (nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoDevices",
"There are no available network devices."));
if (!(reply_message = dbus_message_new_method_return (message)))
return (NULL);
dbus_message_iter_init (reply_message, &iter);
dbus_message_iter_append_array (&iter, &iter_array, DBUS_TYPE_STRING);
/* Iterate over device list and grab index of "active device" */
if (nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__))
{
GSList *element = data->dev_list;
gboolean appended = FALSE;
while (element)
{
NMDevice *dev = (NMDevice *)(element->data);
if (dev)
{
char *object_path = g_strdup_printf ("%s/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev));
dbus_message_iter_append_string (&iter_array, object_path);
g_free (object_path);
appended = TRUE;
}
element = g_slist_next (element);
}
/* If by some chance there is a device list, but it has no devices in it
* (something which should never happen), die.
*/
if (!appended)
g_assert ("Device list existed, but no devices were in it.");
nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__);
}
else
{
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "Retry",
"NetworkManager could not lock device list, try again.");
}
return (reply_message);
}
/*-------------------------------------------------------------*/
/* Handler code */
/*-------------------------------------------------------------*/
/*
* nm_dbus_signal_device_status_change
*
* Notifies the bus that a particular device has had a status change, either
* active or no longer active
*
*/
void nm_dbus_signal_device_status_change (DBusConnection *connection, NMDevice *dev, DeviceStatus status)
{
DBusMessage *message;
unsigned char *dev_path;
unsigned char *signal = NULL;
g_return_if_fail (connection != NULL);
g_return_if_fail (dev != NULL);
if (!(dev_path = nm_dbus_get_object_path_from_device (dev)))
return;
switch (status)
{
case (DEVICE_NO_LONGER_ACTIVE):
signal = "DeviceNoLongerActive";
break;
case (DEVICE_NOW_ACTIVE):
signal = "DeviceNowActive";
break;
case (DEVICE_ACTIVATING):
signal = "DeviceActivating";
break;
case (DEVICE_LIST_CHANGE):
signal = "DevicesChanged";
break;
default:
syslog (LOG_ERR, "nm_dbus_signal_device_status_change(): got a bad signal name");
return;
}
if (!(message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, signal)))
{
syslog (LOG_ERR, "nm_dbus_signal_device_status_change(): Not enough memory for new dbus message!");
g_free (dev_path);
return;
}
dbus_message_append_args (message, DBUS_TYPE_STRING, dev_path, DBUS_TYPE_INVALID);
g_free (dev_path);
if (!dbus_connection_send (connection, message, NULL))
syslog (LOG_WARNING, "nm_dbus_signal_device_status_change(): Could not raise the signal!");
dbus_message_unref (message);
}
/*
* nm_dbus_signal_device_ip4_address_change
*
* Notifies the bus that a particular device's IPv4 address changed.
*
*/
void nm_dbus_signal_device_ip4_address_change (DBusConnection *connection, NMDevice *dev)
{
DBusMessage *message;
unsigned char *dev_path;
g_return_if_fail (connection != NULL);
g_return_if_fail (dev != NULL);
if (!(dev_path = nm_dbus_get_object_path_from_device (dev)))
return;
message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE, "DeviceIP4AddressChange");
if (!message)
{
syslog (LOG_ERR, "nm_dbus_signal_device_ip4_address_change(): Not enough memory for new dbus message!");
g_free (dev_path);
return;
}
dbus_message_append_args (message, DBUS_TYPE_STRING, dev_path, DBUS_TYPE_INVALID);
g_free (dev_path);
if (!dbus_connection_send (connection, message, NULL))
syslog (LOG_WARNING, "nm_dbus_signal_device_ip4_address_change(): Could not raise the IP4AddressChange signal!");
dbus_message_unref (message);
}
/*
* nm_dbus_signal_wireless_network_change
*
* Notifies the bus that a new wireless network has come into range
*
*/
void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap, gboolean gone)
{
DBusMessage *message;
char *dev_path;
char *ap_path;
g_return_if_fail (connection != NULL);
g_return_if_fail (dev != NULL);
g_return_if_fail (ap != NULL);
if (!(dev_path = nm_dbus_get_object_path_from_device (dev)))
return;
if (!(ap_path = nm_device_get_path_for_ap (dev, ap)))
{
g_free (dev_path);
return;
}
message = dbus_message_new_signal (NM_DBUS_PATH, NM_DBUS_INTERFACE,
(gone ? "WirelessNetworkDisappeared" : "WirelessNetworkAppeared"));
if (!message)
{
syslog (LOG_ERR, "nm_dbus_signal_wireless_network_appeared(): Not enough memory for new dbus message!");
g_free (dev_path);
g_free (ap_path);
return;
}
dbus_message_append_args (message,
DBUS_TYPE_STRING, dev_path,
DBUS_TYPE_STRING, ap_path,
DBUS_TYPE_INVALID);
g_free (ap_path);
g_free (dev_path);
if (!dbus_connection_send (connection, message, NULL))
syslog (LOG_WARNING, "nnm_dbus_signal_wireless_network_appeared(): Could not raise the WirelessNetworkAppeared signal!");
dbus_message_unref (message);
}
/*
* nm_dbus_get_user_key_for_network
*
* Asks NetworkManagerInfo for a user-entered WEP key.
*
*/
void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMDevice *dev, NMAccessPoint *ap)
{
DBusMessage *message;
g_return_if_fail (connection != NULL);
g_return_if_fail (dev != NULL);
g_return_if_fail (ap != NULL);
g_return_if_fail (nm_ap_get_essid (ap) != NULL);
message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH,
NMI_DBUS_INTERFACE, "getKeyForNetwork");
if (message == NULL)
{
syslog (LOG_ERR, "nm_dbus_get_user_key_for_network(): Couldn't allocate the dbus message");
return;
}
dbus_message_append_args (message, DBUS_TYPE_STRING, nm_device_get_iface (dev),
DBUS_TYPE_STRING, nm_ap_get_essid (ap),
DBUS_TYPE_INVALID);
fprintf( stderr, "getUserKey\n");
if (!dbus_connection_send (connection, message, NULL))
syslog (LOG_WARNING, "nm_dbus_get_user_key_for_network(): could not send dbus message");
dbus_message_unref (message);
}
/*
* nm_dbus_set_user_key_for_network
*
* In response to a NetworkManagerInfo message, sets the WEP key
* for a particular wireless AP/network
*
*/
static void nm_dbus_set_user_key_for_network (DBusConnection *connection, DBusMessage *message, NMData *data)
{
DBusError error;
char *device;
char *network;
char *passphrase;
g_return_if_fail (data != NULL);
g_return_if_fail (connection != NULL);
g_return_if_fail (message != NULL);
dbus_error_init (&error);
if (dbus_message_get_args (message, &error,
DBUS_TYPE_STRING, &device,
DBUS_TYPE_STRING, &network,
DBUS_TYPE_STRING, &passphrase,
DBUS_TYPE_INVALID))
{
NMDevice *dev;
if ((dev = nm_get_device_by_iface (data, device)))
nm_device_set_user_key_for_network (dev, data->invalid_ap_list, network, passphrase);
dbus_free (device);
dbus_free (network);
dbus_free (passphrase);
}
}
/*
* nm_dbus_cancel_get_user_key_for_network
*
* Sends a user-key cancellation message to NetworkManagerInfo
*
*/
void nm_dbus_cancel_get_user_key_for_network (DBusConnection *connection)
{
DBusMessage *message;
g_return_if_fail (connection != NULL);
message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH,
NMI_DBUS_INTERFACE, "cancelGetKeyForNetwork");
if (message == NULL)
{
syslog (LOG_ERR, "nm_dbus_cancel_get_user_key_for_network(): Couldn't allocate the dbus message");
return;
}
if (!dbus_connection_send (connection, message, NULL))
syslog (LOG_WARNING, "nm_dbus_cancel_get_user_key_for_network(): could not send dbus message");
dbus_message_unref (message);
}
/*
* nm_dbus_get_network_essid
*
* Get a network's essid from NetworkManagerInfo
*
* NOTE: caller MUST free returned value
*
*/
char * nm_dbus_get_network_essid (DBusConnection *connection, NMNetworkType type, const char *network)
{
DBusMessage *message;
DBusError error;
DBusMessage *reply;
char *essid = NULL;
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (network != NULL, NULL);
g_return_val_if_fail (type != NETWORK_TYPE_UNKNOWN, NULL);
message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH,
NMI_DBUS_INTERFACE, "getNetworkEssid");
if (!message)
{
syslog (LOG_ERR, "nm_dbus_get_network_essid(): Couldn't allocate the dbus message");
return (NULL);
}
dbus_message_append_args (message, DBUS_TYPE_STRING, network,
DBUS_TYPE_INT32, (int)type,
DBUS_TYPE_INVALID);
/* Send message and get essid back from NetworkManagerInfo */
dbus_error_init (&error);
reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
if (dbus_error_is_set (&error))
syslog (LOG_ERR, "nm_dbus_get_network_essid(): %s raised %s", error.name, error.message);
else if (!reply)
syslog (LOG_NOTICE, "nm_dbus_get_network_essid(): reply was NULL.");
else
{
char *dbus_string;
dbus_error_init (&error);
if (dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &dbus_string, DBUS_TYPE_INVALID))
{
essid = (dbus_string == NULL ? NULL : strdup (dbus_string));
dbus_free (dbus_string);
}
}
dbus_message_unref (message);
if (reply)
dbus_message_unref (reply);
return (essid);
}
/*
* nm_dbus_get_network_key
*
* Get a network's key from NetworkManagerInfo.
*
* NOTE: caller MUST free returned value
*
*/
char * nm_dbus_get_network_key (DBusConnection *connection, NMNetworkType type, const char *network)
{
DBusMessage *message;
DBusError error;
DBusMessage *reply;
char *key = NULL;
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (network != NULL, NULL);
g_return_val_if_fail (type != NETWORK_TYPE_UNKNOWN, NULL);
message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH,
NMI_DBUS_INTERFACE, "getNetworkKey");
if (!message)
{
syslog (LOG_ERR, "nm_dbus_get_network_key(): Couldn't allocate the dbus message");
return (NULL);
}
dbus_message_append_args (message, DBUS_TYPE_STRING, network,
DBUS_TYPE_INT32, (int)type,
DBUS_TYPE_INVALID);
/* Send message and get key back from NetworkManagerInfo */
dbus_error_init (&error);
reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
if (dbus_error_is_set (&error))
syslog (LOG_ERR, "nm_dbus_get_network_key(): %s raised %s", error.name, error.message);
else if (!reply)
syslog (LOG_NOTICE, "nm_dbus_get_network_key(): reply was NULL.");
else
{
char *dbus_string;
dbus_error_init (&error);
if (dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &dbus_string, DBUS_TYPE_INVALID))
{
key = (dbus_string == NULL ? NULL : strdup (dbus_string));
dbus_free (dbus_string);
}
}
dbus_message_unref (message);
if (reply)
dbus_message_unref (reply);
return (key);
}
/*
* nm_dbus_get_network_timestamp
*
* Get a network's timestamp from NetworkManagerInfo
*
* Returns: NULL on error
* timestamp if no error
*
*/
GTimeVal *nm_dbus_get_network_timestamp (DBusConnection *connection, NMNetworkType type, const char *network)
{
DBusMessage *message;
DBusError error;
DBusMessage *reply;
guint32 timestamp_secs;
GTimeVal *timestamp;
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (network != NULL, NULL);
g_return_val_if_fail (type != NETWORK_TYPE_UNKNOWN, NULL);
message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH,
NMI_DBUS_INTERFACE, "getNetworkTimestamp");
if (!message)
{
syslog (LOG_ERR, "nm_dbus_get_network_timestamp(): Couldn't allocate the dbus message");
return NULL;
}
dbus_message_append_args (message, DBUS_TYPE_STRING, network,
DBUS_TYPE_INT32, (int)type,
DBUS_TYPE_INVALID);
/* Send message and get prio back from NetworkManagerInfo */
dbus_error_init (&error);
reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
if (dbus_error_is_set (&error))
syslog (LOG_ERR, "nm_dbus_get_network_timestamp(): %s raised %s", error.name, error.message);
else if (!reply)
syslog (LOG_NOTICE, "nm_dbus_get_network_timestamp(): reply was NULL.");
else
{
dbus_error_init (&error);
if (!dbus_message_get_args (reply, &error, DBUS_TYPE_INT32, &timestamp_secs, DBUS_TYPE_INVALID))
timestamp_secs = -1;
}
dbus_message_unref (message);
if (reply)
dbus_message_unref (reply);
if (timestamp_secs < 0)
return NULL;
timestamp = g_new0 (GTimeVal, 1);
timestamp->tv_sec = timestamp_secs;
timestamp->tv_usec = 0;
return (timestamp);
}
/*
* nm_dbus_get_networks
*
* Get all networks of a specific type from NetworkManagerInfo
*
* NOTE: caller MUST free returned value using dbus_free_string_array()
*
*/
char ** nm_dbus_get_networks (DBusConnection *connection, NMNetworkType type, int *num_networks)
{
DBusMessage *message;
DBusError error;
DBusMessage *reply;
char **networks = NULL;
*num_networks = 0;
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (type != NETWORK_TYPE_UNKNOWN, NULL);
message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH,
NMI_DBUS_INTERFACE, "getNetworks");
if (!message)
{
syslog (LOG_ERR, "nm_dbus_get_networks(): Couldn't allocate the dbus message");
return (NULL);
}
dbus_message_append_args (message, DBUS_TYPE_INT32, (int)type, DBUS_TYPE_INVALID);
/* Send message and get essid back from NetworkManagerInfo */
dbus_error_init (&error);
reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
if (dbus_error_is_set (&error))
syslog (LOG_ERR, "nm_dbus_get_networks(): %s raised %s", error.name, error.message);
else if (!reply)
syslog (LOG_NOTICE, "nm_dbus_get_networks(): reply was NULL.");
else
{
DBusMessageIter iter;
dbus_message_iter_init (reply, &iter);
dbus_message_iter_get_string_array (&iter, &networks, num_networks);
}
dbus_message_unref (message);
if (reply)
dbus_message_unref (reply);
return (networks);
}
/*
* nm_dbus_nmi_filter
*
* Respond to NetworkManagerInfo signals about changing Allowed Networks
*
*/
static DBusHandlerResult nm_dbus_nmi_filter (DBusConnection *connection, DBusMessage *message, void *user_data)
{
NMData *data = (NMData *)user_data;
const char *object_path;
const char *method;
NMAccessPointList *list = NULL;
gboolean handled = FALSE;
g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
method = dbus_message_get_member (message);
if (!(object_path = dbus_message_get_path (message)))
return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
/* syslog (LOG_DEBUG, "nm_dbus_nmi_filter() got method %s for path %s", method, object_path); */
if ( (strcmp (object_path, NMI_DBUS_PATH) == 0)
&& dbus_message_is_signal (message, NMI_DBUS_INTERFACE, "TrustedNetworkUpdate"))
list = data->trusted_ap_list;
else if ( (strcmp (object_path, NMI_DBUS_PATH) == 0)
&& dbus_message_is_signal (message, NMI_DBUS_INTERFACE, "PreferredNetworkUpdate"))
list = data->preferred_ap_list;
else if (dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, "ServiceCreated"))
{
char *service;
DBusError error;
dbus_error_init (&error);
if ( dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &service, DBUS_TYPE_INVALID)
&& (strcmp (service, NMI_DBUS_SERVICE) == 0))
{
data->update_ap_lists = TRUE;
data->info_daemon_avail = TRUE;
nm_data_set_state_modified (data, TRUE);
}
/* Don't set handled = TRUE since other filter functions on this dbus connection
* may want to know about service signals.
*/
}
else if (dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, "ServiceDeleted"))
{
char *service;
DBusError error;
dbus_error_init (&error);
if ( dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &service, DBUS_TYPE_INVALID)
&& (strcmp (service, NMI_DBUS_SERVICE) == 0))
{
data->update_ap_lists = TRUE;
data->info_daemon_avail = FALSE;
nm_data_set_state_modified (data, TRUE);
}
/* Don't set handled = TRUE since other filter functions on this dbus connection
* may want to know about service signals.
*/
}
if (list)
{
char *network = NULL;
DBusError error;
dbus_error_init (&error);
if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INVALID))
return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
syslog( LOG_DEBUG, "update of network '%s'", network);
nm_ap_list_update_network (list, network, data);
dbus_free (network);
/* Make sure the currently active device updates its "best" ap
* based on the new preferred/trusted network information.
*/
if ( data->active_device
&& nm_device_is_wireless (data->active_device)
&& !nm_device_activating (data->active_device))
{
syslog( LOG_DEBUG, "updating active device's best ap");
nm_device_update_best_ap (data->active_device);
nm_data_set_state_modified (data, TRUE);
syslog( LOG_DEBUG, "Device's best ap now '%s'", nm_ap_get_essid (nm_device_get_best_ap (data->active_device)));
}
handled = TRUE;
}
return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
}
/*
* nm_dbus_devices_handle_networks_request
*
* Converts a property request on a _network_ into a dbus message.
*
*/
static DBusMessage *nm_dbus_devices_handle_networks_request (DBusConnection *connection, DBusMessage *message,
NMData *data, const char *path, const char *request, NMDevice *dev)
{
NMAccessPoint *ap;
DBusMessage *reply_message = NULL;
g_return_val_if_fail (data != NULL, NULL);
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (request != NULL, NULL);
g_return_val_if_fail (dev != NULL, NULL);
if (!(ap = nm_dbus_get_ap_from_object_path (path, dev)))
{
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NetworkNotFound",
"The requested network does not exist for this device.");
return (reply_message);
}
if (!(reply_message = dbus_message_new_method_return (message)))
return (NULL);
if (strcmp ("getName", request) == 0)
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, nm_ap_get_essid (ap), DBUS_TYPE_INVALID);
else if (strcmp ("getAddress", request) == 0)
{
char buf[20];
memset (&buf[0], 0, 20);
iw_ether_ntop((const struct ether_addr *) (nm_ap_get_address (ap)), &buf[0]);
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, &buf[0], DBUS_TYPE_INVALID);
}
else if (strcmp ("getQuality", request) == 0)
dbus_message_append_args (reply_message, DBUS_TYPE_INT32, nm_ap_get_quality (ap), DBUS_TYPE_INVALID);
else if (strcmp ("getFrequency", request) == 0)
dbus_message_append_args (reply_message, DBUS_TYPE_DOUBLE, nm_ap_get_freq (ap), DBUS_TYPE_INVALID);
else if (strcmp ("getRate", request) == 0)
dbus_message_append_args (reply_message, DBUS_TYPE_INT32, nm_ap_get_rate (ap), DBUS_TYPE_INVALID);
else if (strcmp ("getEncrypted", request) == 0)
dbus_message_append_args (reply_message, DBUS_TYPE_BOOLEAN, nm_ap_get_encrypted (ap), DBUS_TYPE_INVALID);
else
{
/* Must destroy the allocated message */
dbus_message_unref (reply_message);
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "UnknownMethod",
"NetworkManager knows nothing about the method %s for object %s", request, path);
}
return (reply_message);
}
/*
* nm_dbus_devices_handle_request
*
* Converts a property request into a dbus message.
*
*/
static DBusMessage *nm_dbus_devices_handle_request (DBusConnection *connection, NMData *data, DBusMessage *message,
const char *path, const char *request)
{
NMDevice *dev;
DBusMessage *reply_message = NULL;
char *object_path;
g_return_val_if_fail (data != NULL, NULL);
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (request != NULL, NULL);
if (!(dev = nm_dbus_get_device_from_object_path (data, path)))
{
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound",
"The requested network device does not exist.");
return (reply_message);
}
/* Test whether or not the _networks_ of a device were queried instead of the device itself */
object_path = g_strdup_printf ("%s/%s/Networks/", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev));
if (strncmp (path, object_path, strlen (object_path)) == 0)
{
free (object_path);
reply_message = nm_dbus_devices_handle_networks_request (connection, message, data, path, request, dev);
return (reply_message);
}
free (object_path);
if (!(reply_message = dbus_message_new_method_return (message)))
return (NULL);
if (strcmp ("getName", request) == 0)
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, nm_device_get_iface (dev), DBUS_TYPE_INVALID);
else if (strcmp ("getType", request) == 0)
dbus_message_append_args (reply_message, DBUS_TYPE_INT32, nm_device_get_type (dev), DBUS_TYPE_INVALID);
else if (strcmp ("getHalUdi", request) == 0)
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, nm_device_get_udi (dev), DBUS_TYPE_INVALID);
else if (strcmp ("getIP4Address", request) == 0)
dbus_message_append_args (reply_message, DBUS_TYPE_UINT32, nm_device_get_ip4_address (dev), DBUS_TYPE_INVALID);
else if (strcmp ("getMaxQuality", request) == 0)
dbus_message_append_args (reply_message, DBUS_TYPE_UINT32, nm_device_get_max_quality (dev), DBUS_TYPE_INVALID);
else if (strcmp ("getActiveNetwork", request) == 0)
{
NMAccessPoint *ap;
gboolean success = FALSE;
/* Only wireless devices have an active network */
if (!nm_device_is_wireless (dev))
{
dbus_message_unref (reply_message);
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotWireless",
"Wired devices cannot have active networks.");
return (reply_message);
}
if ((ap = nm_device_ap_list_get_ap_by_essid (dev, nm_device_get_essid (dev))))
{
if ( (nm_null_safe_strcmp (nm_ap_get_essid (ap), nm_ap_get_essid (nm_device_get_best_ap (dev))) == 0)
&& (object_path = nm_device_get_path_for_ap (dev, ap)))
{
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, object_path, DBUS_TYPE_INVALID);
g_free (object_path);
success = TRUE;
}
}
if (!success)
{
dbus_message_unref (reply_message);
return (nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoActiveNetwork",
"The device is not associated with any networks at this time."));
}
}
else if (strcmp ("getNetworks", request) == 0)
{
DBusMessageIter iter;
DBusMessageIter iter_array;
NMAccessPoint *ap = NULL;
gboolean success = FALSE;
NMAccessPointList *ap_list;
NMAPListIter *list_iter;
/* Only wireless devices have networks */
if (!nm_device_is_wireless (dev))
{
dbus_message_unref (reply_message);
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotWireless",
"Wired devices cannot see wireless networks.");
return (reply_message);
}
dbus_message_iter_init (reply_message, &iter);
dbus_message_iter_append_array (&iter, &iter_array, DBUS_TYPE_STRING);
if ((ap_list = nm_device_ap_list_get (dev)))
{
if ((list_iter = nm_ap_list_iter_new (ap_list)))
{
while ((ap = nm_ap_list_iter_next (list_iter)))
{
object_path = g_strdup_printf ("%s/%s/Networks/%s", NM_DBUS_PATH_DEVICES,
nm_device_get_iface (dev), nm_ap_get_essid (ap));
dbus_message_iter_append_string (&iter_array, object_path);
g_free (object_path);
success = TRUE;
}
nm_ap_list_iter_free (list_iter);
}
}
if (!success)
{
dbus_message_unref (reply_message);
return (nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoNetworks",
"The device cannot see any wireless networks."));
}
}
else
{
/* Must destroy the allocated message */
dbus_message_unref (reply_message);
reply_message = NULL;
}
return (reply_message);
}
/*
* nm_dbus_nm_message_handler
*
* Dispatch messages against our NetworkManager object
*
*/
static DBusHandlerResult nm_dbus_nm_message_handler (DBusConnection *connection, DBusMessage *message, void *user_data)
{
NMData *data = (NMData *)user_data;
const char *method;
const char *path;
DBusMessage *reply_message = NULL;
gboolean handled = TRUE;
g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
method = dbus_message_get_member (message);
path = dbus_message_get_path (message);
/* syslog (LOG_DEBUG, "nm_dbus_nm_message_handler() got method %s for path %s", method, path); */
if (strcmp ("getActiveDevice", method) == 0)
reply_message = nm_dbus_nm_get_active_device (connection, message, data);
else if (strcmp ("getDevices", method) == 0)
reply_message = nm_dbus_nm_get_devices (connection, message, data);
else if (strcmp ("setActiveDevice", method) == 0)
nm_dbus_nm_set_active_device (connection, message, data);
else if (strcmp ("setKeyForNetwork", method) == 0)
nm_dbus_set_user_key_for_network (connection, message, data);
else if (strcmp ("setNetwork", method) == 0)
{
if (data->active_device && nm_device_is_wireless (data->active_device))
{
char *network;
DBusError error;
dbus_error_init (&error);
if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INVALID))
{
NMAccessPoint *ap;
if ((ap = nm_ap_list_get_ap_by_essid (nm_device_ap_list_get (data->active_device), network)))
{
syslog (LOG_DEBUG, "Forcing AP '%s'", nm_ap_get_essid (ap));
nm_device_freeze_best_ap (data->active_device);
nm_device_set_best_ap (data->active_device, ap);
nm_data_set_state_modified (data, TRUE);
}
dbus_free (network);
}
}
else
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "BadDevice",
"A network can only be set when a wireless device is active.");
handled = TRUE;
}
else if (strcmp ("status", method) == 0)
{
reply_message = dbus_message_new_method_return (message);
if (reply_message)
{
if (data->active_device && nm_device_activating (data->active_device))
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, "connecting", DBUS_TYPE_INVALID);
else if (data->active_device)
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, "connected", DBUS_TYPE_INVALID);
else
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, "disconnected", DBUS_TYPE_INVALID);
}
}
else
handled = FALSE;
if (reply_message)
{
dbus_connection_send (connection, reply_message, NULL);
dbus_message_unref (reply_message);
}
return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
}
/*
* nm_dbus_nm_unregister_handler
*
* Nothing happens here.
*
*/
void nm_dbus_nm_unregister_handler (DBusConnection *connection, void *user_data)
{
/* do nothing */
}
/*
* nm_dbus_devices_message_handler
*
* Dispatch messages against individual network devices
*
*/
static DBusHandlerResult nm_dbus_devices_message_handler (DBusConnection *connection, DBusMessage *message, void *user_data)
{
NMData *data = (NMData *)user_data;
gboolean handled = FALSE;
const char *method;
const char *path;
DBusMessage *reply_message = NULL;
g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
method = dbus_message_get_member (message);
path = dbus_message_get_path (message);
/*syslog (LOG_DEBUG, "nm_dbus_devices_message_handler() got method %s for path %s", method, path);*/
if ((reply_message = nm_dbus_devices_handle_request (connection, data, message, path, method)))
{
dbus_connection_send (connection, reply_message, NULL);
dbus_message_unref (reply_message);
handled = TRUE;
}
return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
}
/*
* nm_dbus_devices_unregister_handler
*
* Nothing happens here.
*
*/
void nm_dbus_devices_unregister_handler (DBusConnection *connection, void *user_data)
{
/* do nothing */
}
/*
* nm_dbus_is_info_daemon_running
*
* Ask dbus whether or not the info daemon is providing its dbus service
*
*/
gboolean nm_dbus_is_info_daemon_running (DBusConnection *connection)
{
DBusError error;
g_return_val_if_fail (connection != NULL, FALSE);
dbus_error_init (&error);
return (dbus_bus_service_exists (connection, NMI_DBUS_SERVICE, &error));
}
/*
* nm_dbus_init
*
* Connect to the system messagebus and register ourselves as a service.
*
*/
DBusConnection *nm_dbus_init (NMData *data)
{
DBusError dbus_error;
dbus_bool_t success;
DBusConnection *connection;
DBusObjectPathVTable nm_vtable = { &nm_dbus_nm_unregister_handler, &nm_dbus_nm_message_handler, NULL, NULL, NULL, NULL };
DBusObjectPathVTable devices_vtable = { &nm_dbus_devices_unregister_handler, &nm_dbus_devices_message_handler, NULL, NULL, NULL, NULL };
dbus_connection_set_change_sigpipe (TRUE);
dbus_error_init (&dbus_error);
connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error);
if (connection == NULL)
{
syslog (LOG_ERR, "nm_dbus_init() could not get the system bus. Make sure the message bus daemon is running?");
return (NULL);
}
dbus_connection_set_exit_on_disconnect (connection, FALSE);
dbus_connection_setup_with_g_main (connection, NULL);
success = dbus_connection_register_object_path (connection, NM_DBUS_PATH, &nm_vtable, data);
if (!success)
{
syslog (LOG_ERR, "nm_dbus_init() could not register a handler for NetworkManager. Not enough memory?");
return (NULL);
}
success = dbus_connection_register_fallback (connection, NM_DBUS_PATH_DEVICES, &devices_vtable, data);
if (!success)
{
syslog (LOG_ERR, "nm_dbus_init() could not register a handler for NetworkManager devices. Not enough memory?");
return (NULL);
}
if (!dbus_connection_add_filter (connection, nm_dbus_nmi_filter, data, NULL))
return (NULL);
dbus_bus_add_match (connection,
"type='signal',"
"interface='" NMI_DBUS_INTERFACE "',"
"sender='" NMI_DBUS_SERVICE "',"
"path='" NMI_DBUS_PATH "'",
&dbus_error);
dbus_bus_add_match(connection,
"type='signal',"
"interface='" DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS "',"
"sender='" DBUS_SERVICE_ORG_FREEDESKTOP_DBUS "'",
&dbus_error);
dbus_bus_acquire_service (connection, NM_DBUS_SERVICE, 0, &dbus_error);
if (dbus_error_is_set (&dbus_error))
{
syslog (LOG_ERR, "nm_dbus_init() could not acquire its service. dbus_bus_acquire_service() says: '%s'", dbus_error.message);
return (NULL);
}
return (connection);
}