2004-08-31 Dan Williams <dcbw@redhat.com>

* Remove 'debug' extern global from all files since we now
		use syslog()

	* src/NetworkManager.[ch]
		- Break out routine that get the net.interface property from HAL,
			removing that logic from nm_create_device_and_add_to_list()
		- (nm_create_device_and_add_to_list): make this a bit more general so
			it doesn't do the talking to HAL.  Also add arguments to facilitate
			the create of test devices.
		- (nm_data_mark_state_changed): rename from nm_data_set_state_modified()
		- (nm_data_new, main, nm_print_usage): add new argument "--enable-test-devices"
			which makes NetworkManager listen for dbus commands to create test
			devices, which have no backing hardware.  Use when you're on a plane
			for example, and/or forgot your wireless card at home.  Test devices
			_cannot_ be created unless NM is started with --enable-test-devices.

	* src/NetworkManagerDbus.[ch]
		- New "getLinkActive" method for devices
		- New "setLinkActive" method for devices (only works on test devices)
		- New "createTestDevice" method on NetworkManager object to create a test
			device of a specified type (ie wired, wireless).  UDI is created from
			scratch, as is the interface name.  Only works when NM is started with
			--enable-test-devices switch.
		- New "removeTestDevice" method on NetworkManager object which removes a
			test device.  Only works when NM is started with --enable-test-devices

	* src/NetworkManagerDevice.[ch]
		- Logic to facilitate test devices.  Add variables to NMDevice struct to indicate
			whether a device is a test device or not, and what its link status is.
		- Deal with test devices in most functions.  For those that work directly on hardware
			special-case test devices.
		- (nm_device_new): don't create a test device if test devices weren't enabled on the
			command-line.
		- (nm_device_update_link_active): split out logic for wired and wireless device link
			checking to separate functions to facilitate test device link checking.
		- (nm_device_set_enc_key): Since some drivers for wireless cards are daft and
			don't make a distinction between System Authentication and Encryption
			(namely Cisco aironet), we use Open System auth when setting a WEP key
			on the card.  We don't deal with Shared Key auth yet.
		- (nm_device_activation_worker): split the activation cancel check logic out into
			a separate routine nm_device_activation_cancel_if_needed()
		- (nm_device_activation_signal_cancel): rename from nm_device_activation_cancel()
		- (nm_device_fake_ap_list): Test wireless devices obviously cannot scan, so create
			a list of fake access points that they can "see"
		- (nm_device_is_test_device): return whether or not a device is a test device

	* src/NetworkManagerPolicy.c
		- (nm_policy_get_best_device): attempt to deal with wireless network selection,
			previously if you "locked"/forced NM to use a wireless device but then
			selected a wireless network for NM to use, it would switch to a wired device.
			So, if the active device is wireless and it has a "forced" best AP, use it
			if the "forced" best AP is still valid
		- (nm_state_modification_monitor): deal with NULL best devices, for example
			there were no usable network devices, or the last one was removed

	* src/backends/NetworkManager*.c
		- Deal with test devices, mostly just return success for operations like getting
			a DHCP address

	* test/nmtestdevices.c
		- Test tool to create/remove/link-switch test devices


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@112 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams
2004-08-31 16:09:15 +00:00
parent 3e02531372
commit 4de66efbd4
15 changed files with 989 additions and 242 deletions

View File

@@ -47,42 +47,66 @@
*/
static GMainLoop *loop = NULL;
static NMData *nm_data = NULL;
gboolean debug = TRUE;
extern gboolean allowed_ap_worker_exit;
static void nm_data_free (NMData *data);
/*
* nm_get_device_interface_from_hal
*
* Queries HAL for the "net.interface" property of a device and returns
* it if successful.
*
*/
static char *nm_get_device_interface_from_hal (LibHalContext *ctx, const char *udi)
{
char *iface = NULL;
if (hal_device_property_exists (ctx, udi, "net.interface"))
{
char *temp = hal_device_get_property_string (ctx, udi, "net.interface");
iface = g_strdup (temp);
hal_free_string (temp);
}
return (iface);
}
/*
* nm_create_device_and_add_to_list
*
* Create a new NLM device and add it to our device list.
* Create a new network device and add it to our device list.
*
* Returns: newly allocated device on success
* NULL on failure
*/
NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi)
NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi, const char *iface,
gboolean test_device, NMDeviceType test_device_type)
{
NMDevice *dev = NULL;
gboolean success = FALSE;
g_return_val_if_fail (data != NULL, NULL);
g_return_val_if_fail (udi != NULL, NULL);
g_return_val_if_fail (iface != NULL, NULL);
if (hal_device_property_exists (data->hal_ctx, udi, "net.interface"))
/* If we are called to create a test devices, but test devices weren't enabled
* on the command-line, don't create the device.
*/
if (!data->enable_test_devices && test_device)
{
gchar *iface_name = hal_device_get_property_string (data->hal_ctx, udi, "net.interface");
/* Make sure the device is not already in the device list */
if ((dev = nm_get_device_by_iface (data, iface_name)))
{
hal_free_string (iface_name);
syslog (LOG_ERR, "nm_create_device_and_add_to_list(): attempt to create a test device,"
" but test devices were not enabled on the command line. Will not create the device.\n");
return (NULL);
}
if ((dev = nm_device_new (iface_name, data)))
{
/* Make sure the device is not already in the device list */
if ((dev = nm_get_device_by_iface (data, iface)))
return (NULL);
if ((dev = nm_device_new (iface, test_device, test_device_type, data)))
{
/* Build up the device structure */
nm_device_set_udi (dev, udi);
@@ -96,26 +120,20 @@ NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi)
data->dev_list = g_slist_append (data->dev_list, dev);
nm_device_deactivate (dev, TRUE);
success = TRUE;
nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__);
} else syslog( LOG_ERR, "nm_create_device_and_add_to_list() could not acquire device list mutex." );
} else syslog( LOG_ERR, "nm_create_device_and_add_to_list() could not allocate device data." );
hal_free_string (iface_name);
if (success)
{
nm_data_set_state_modified (data, TRUE);
nm_data_mark_state_changed (data);
nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_LIST_CHANGE);
}
else
{
/* If we couldn't add the device to our list, free its data. */
syslog( LOG_ERR, "nm_create_device_and_add_to_list() could not acquire device list mutex." );
nm_device_unref (dev);
dev = NULL;
}
}
} else syslog( LOG_ERR, "nm_create_device_and_add_to_list() could not allocate device data." );
return (dev);
}
@@ -159,14 +177,14 @@ void nm_remove_device_from_list (NMData *data, const char *udi)
data->user_device = NULL;
}
nm_device_activation_cancel (dev);
nm_device_activation_signal_cancel (dev);
nm_device_unref (dev);
/* Remove the device entry from the device list and free its data */
data->dev_list = g_slist_remove_link (data->dev_list, element);
nm_device_unref (element->data);
g_slist_free (element);
nm_data_set_state_modified (data, TRUE);
nm_data_mark_state_changed (data);
nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_LIST_CHANGE);
break;
@@ -195,6 +213,7 @@ static void nm_hal_mainloop_integration (LibHalContext *ctx, DBusConnection * db
static void nm_hal_device_added (LibHalContext *ctx, const char *udi)
{
NMData *data = (NMData *)hal_ctx_get_user_data (ctx);
char *iface = NULL;
g_return_if_fail (data != NULL);
@@ -204,7 +223,11 @@ static void nm_hal_device_added (LibHalContext *ctx, const char *udi)
* so this call will fail, and it will actually be added when hal sets the device's
* capabilities a bit later on.
*/
nm_create_device_and_add_to_list (data, udi);
if ((iface = nm_get_device_interface_from_hal (data->hal_ctx, udi)))
{
nm_create_device_and_add_to_list (data, udi, iface, FALSE, DEVICE_TYPE_DONT_KNOW);
g_free (iface);
}
}
@@ -237,7 +260,15 @@ static void nm_hal_device_new_capability (LibHalContext *ctx, const char *udi, c
syslog( LOG_DEBUG, "nm_hal_device_new_capability() called with udi = %s, capability = %s", udi, capability );
if (capability && (strcmp (capability, "net.ethernet") == 0))
nm_create_device_and_add_to_list (data, udi);
{
char *iface;
if ((iface = nm_get_device_interface_from_hal (data->hal_ctx, udi)))
{
nm_create_device_and_add_to_list (data, udi, iface, FALSE, DEVICE_TYPE_DONT_KNOW);
g_free (iface);
}
}
}
@@ -282,7 +313,15 @@ static void nm_add_initial_devices (NMData *data)
if (net_devices)
{
for (i = 0; i < num_net_devices; i++)
nm_create_device_and_add_to_list (data, net_devices[i]);
{
char *iface;
if ((iface = nm_get_device_interface_from_hal (data->hal_ctx, net_devices[i])))
{
nm_create_device_and_add_to_list (data, net_devices[i], iface, FALSE, DEVICE_TYPE_DONT_KNOW);
g_free (iface);
}
}
}
hal_free_string_array (net_devices);
@@ -382,7 +421,7 @@ static LibHalFunctions hal_functions =
* Create data structure used in callbacks from libhal.
*
*/
static NMData *nm_data_new (void)
static NMData *nm_data_new (gboolean enable_test_devices)
{
NMData *data;
@@ -417,6 +456,7 @@ static NMData *nm_data_new (void)
}
data->state_modified = TRUE;
data->enable_test_devices = enable_test_devices;
return (data);
}
@@ -450,17 +490,17 @@ static void nm_data_free (NMData *data)
/*
* nm_data_set_state_modified
* nm_data_mark_state_changed
*
* Locked function to protect state modification changes.
* Notify our timeout that the networking state has changed in some way.
*
*/
void nm_data_set_state_modified (NMData *data, gboolean modified)
void nm_data_mark_state_changed (NMData *data)
{
g_return_if_fail (data != NULL);
g_mutex_lock (data->state_modified_mutex);
data->state_modified = modified;
data->state_modified = TRUE;
g_mutex_unlock (data->state_modified_mutex);
}
@@ -477,6 +517,7 @@ static void nm_print_usage (void)
fprintf (stderr,
"\n"
" --no-daemon Don't become a daemon\n"
" --enable-test-devices Allow dummy devices to be created via DBUS methods [DEBUG]\n"
" --help Show this information and exit\n"
"\n"
"NetworkManager monitors all network connections and automatically\n"
@@ -498,6 +539,7 @@ int main( int argc, char *argv[] )
guint policy_source;
guint wireless_scan_source;
gboolean become_daemon = TRUE;
gboolean enable_test_devices = FALSE;
/* Parse options */
while (1)
@@ -508,6 +550,7 @@ int main( int argc, char *argv[] )
static struct option options[] = {
{"no-daemon", 0, NULL, 0},
{"enable-test-devices", 0, NULL, 0},
{"help", 0, NULL, 0},
{NULL, 0, NULL, 0}
};
@@ -527,6 +570,8 @@ int main( int argc, char *argv[] )
}
else if (strcmp (opt, "no-daemon") == 0)
become_daemon = FALSE;
else if (strcmp (opt, "enable-test-devices") == 0)
enable_test_devices = TRUE;
break;
default:
@@ -554,7 +599,7 @@ int main( int argc, char *argv[] )
nm_system_load_device_modules ();
/* Initialize our instance data */
nm_data = nm_data_new ();
nm_data = nm_data_new (enable_test_devices);
if (!nm_data)
{
syslog( LOG_CRIT, "nm_data_new() failed... Not enough memory?");

View File

@@ -28,11 +28,12 @@
#include <hal/libhal.h>
#include "NetworkManagerAP.h"
struct NMData
typedef struct NMData
{
LibHalContext *hal_ctx;
DBusConnection *dbus_connection;
gboolean info_daemon_avail;
gboolean enable_test_devices;
GSList *dev_list;
GMutex *dev_list_mutex;
@@ -50,10 +51,24 @@ struct NMData
struct NMAccessPointList *trusted_ap_list;
struct NMAccessPointList *preferred_ap_list;
struct NMAccessPointList *invalid_ap_list;
};
} NMData;
typedef struct NMData NMData;
/*
* Types of NetworkManager devices
*/
typedef enum NMDeviceType
{
DEVICE_TYPE_DONT_KNOW = 0,
DEVICE_TYPE_WIRED_ETHERNET,
DEVICE_TYPE_WIRELESS_ETHERNET
} NMDeviceType;
void nm_data_set_state_modified (NMData *data, gboolean modified);
struct NMDevice *nm_create_device_and_add_to_list (NMData *data, const char *udi, const char *iface,
gboolean test_device, NMDeviceType test_device_type);
void nm_remove_device_from_list (NMData *data, const char *udi);
void nm_data_mark_state_changed (NMData *data);
#endif

View File

@@ -23,8 +23,6 @@
#include "NetworkManagerUtils.h"
#include "NetworkManagerWireless.h"
extern gboolean debug;
/*
* Encapsulates Access Point information
@@ -32,7 +30,7 @@ extern gboolean debug;
struct NMAccessPoint
{
guint refcount;
gchar *essid;
char *essid;
struct ether_addr *address;
guint8 quality;
double freq;

View File

@@ -26,7 +26,6 @@
#include "NetworkManagerUtils.h"
#include "NetworkManagerDbus.h"
extern gboolean debug;
struct NMAccessPointList
{

View File

@@ -26,7 +26,6 @@
#include <stdarg.h>
#include <iwlib.h>
extern gboolean debug;
#include "NetworkManager.h"
#include "NetworkManagerUtils.h"
@@ -36,6 +35,8 @@ extern gboolean debug;
#include "NetworkManagerAPList.h"
static int test_dev_num = 0;
/*
* nm_dbus_create_error_message
*
@@ -242,7 +243,7 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB
data->user_device = dev;
nm_unlock_mutex (data->user_device_mutex, __FUNCTION__);
nm_data_set_state_modified (data, TRUE);
nm_data_mark_state_changed (data);
}
return (reply_message);
@@ -827,7 +828,7 @@ static DBusHandlerResult nm_dbus_nmi_filter (DBusConnection *connection, DBusMes
{
data->update_ap_lists = TRUE;
data->info_daemon_avail = TRUE;
nm_data_set_state_modified (data, TRUE);
nm_data_mark_state_changed (data);
}
/* Don't set handled = TRUE since other filter functions on this dbus connection
* may want to know about service signals.
@@ -844,7 +845,7 @@ static DBusHandlerResult nm_dbus_nmi_filter (DBusConnection *connection, DBusMes
{
data->update_ap_lists = TRUE;
data->info_daemon_avail = FALSE;
nm_data_set_state_modified (data, TRUE);
nm_data_mark_state_changed (data);
}
/* Don't set handled = TRUE since other filter functions on this dbus connection
* may want to know about service signals.
@@ -873,7 +874,7 @@ static DBusHandlerResult nm_dbus_nmi_filter (DBusConnection *connection, DBusMes
{
syslog( LOG_DEBUG, "updating active device's best ap");
nm_device_update_best_ap (data->active_device);
nm_data_set_state_modified (data, TRUE);
nm_data_mark_state_changed (data);
syslog( LOG_DEBUG, "Device's best ap now '%s'", nm_ap_get_essid (nm_device_get_best_ap (data->active_device)));
}
handled = TRUE;
@@ -1068,6 +1069,27 @@ static DBusMessage *nm_dbus_devices_handle_request (DBusConnection *connection,
"The device cannot see any wireless networks."));
}
}
else if (strcmp ("getLinkActive", request) == 0)
dbus_message_append_args (reply_message, DBUS_TYPE_BOOLEAN, nm_device_get_link_active (dev), DBUS_TYPE_INVALID);
else if (strcmp ("setLinkActive", request) == 0)
{
/* Can only set link status for active devices */
if (nm_device_is_test_device (dev))
{
DBusError error;
gboolean link;
dbus_error_init (&error);
if (dbus_message_get_args (message, &error, DBUS_TYPE_BOOLEAN, &link, DBUS_TYPE_INVALID))
{
nm_device_set_link_active (dev, link);
nm_data_mark_state_changed (data);
}
}
else
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NotTestDevice",
"Only test devices can have their link status set manually.");
}
else
{
/* Must destroy the allocated message */
@@ -1127,7 +1149,7 @@ static DBusHandlerResult nm_dbus_nm_message_handler (DBusConnection *connection,
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);
nm_data_mark_state_changed (data);
}
dbus_free (network);
}
@@ -1140,8 +1162,7 @@ static DBusHandlerResult nm_dbus_nm_message_handler (DBusConnection *connection,
}
else if (strcmp ("status", method) == 0)
{
reply_message = dbus_message_new_method_return (message);
if (reply_message)
if ((reply_message = dbus_message_new_method_return (message)))
{
if (data->active_device && nm_device_activating (data->active_device))
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, "connecting", DBUS_TYPE_INVALID);
@@ -1151,6 +1172,64 @@ static DBusHandlerResult nm_dbus_nm_message_handler (DBusConnection *connection,
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, "disconnected", DBUS_TYPE_INVALID);
}
}
else if (strcmp ("createTestDevice", method) == 0)
{
DBusError error;
NMDeviceType type;
dbus_error_init (&error);
if ( dbus_message_get_args (message, &error, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID)
&& ((type == DEVICE_TYPE_WIRED_ETHERNET) || (type == DEVICE_TYPE_WIRELESS_ETHERNET)))
{
char *interface = g_strdup_printf ("test%d", test_dev_num);
char *udi = g_strdup_printf ("/test-devices/%s", interface);
NMDevice *dev = NULL;
dev = nm_create_device_and_add_to_list (data, udi, interface, TRUE, type);
test_dev_num++;
if ((reply_message = dbus_message_new_method_return (message)))
{
char *dev_path = g_strdup_printf ("%s/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev));
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, dev_path, DBUS_TYPE_INVALID);
g_free (dev_path);
}
g_free (interface);
g_free (udi);
}
else
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "BadType",
"The test device type was invalid.");
}
else if (strcmp ("removeTestDevice", method) == 0)
{
DBusError error;
char *dev_path;
dbus_error_init (&error);
if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev_path, DBUS_TYPE_INVALID))
{
NMDevice *dev;
if ((dev = nm_dbus_get_device_from_object_path (data, dev_path)))
{
if (nm_device_is_test_device (dev))
nm_remove_device_from_list (data, nm_device_get_udi (dev));
else
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NotTestDevice",
"Only test devices can be removed via dbus calls.");
}
else
{
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound",
"The requested network device does not exist.");
}
}
else
{
reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceBad",
"The device ID was bad.");
}
}
else
handled = FALSE;

View File

@@ -94,6 +94,9 @@ struct NMDevice
gboolean activating;
gboolean just_activated;
gboolean quit_activation;
gboolean test_device;
gboolean test_device_up;
};
/******************************************************/
@@ -112,6 +115,12 @@ static gboolean nm_device_test_wireless_extensions (NMDevice *dev)
g_return_val_if_fail (dev != NULL, FALSE);
/* We obviously cannot probe test devices (since they don't
* actually exist in hardware).
*/
if (dev->test_device)
return (FALSE);
iwlib_socket = iw_sockets_open ();
error = iw_get_stats (iwlib_socket, nm_device_get_iface (dev), &stats, NULL, FALSE);
close (iwlib_socket);
@@ -133,6 +142,11 @@ static gboolean nm_device_supports_wireless_scan (NMDevice *dev)
wireless_scan_head scan_data;
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (dev->type == DEVICE_TYPE_WIRELESS_ETHERNET, FALSE);
/* A test wireless device can always scan (we generate fake scan data for it) */
if (dev->test_device)
return (TRUE);
iwlib_socket = iw_sockets_open ();
error = iw_scan (iwlib_socket, nm_device_get_iface (dev), WIRELESS_EXT, &scan_data);
@@ -223,16 +237,32 @@ NMDevice *nm_get_device_by_iface (NMData *data, const char *iface)
/*
* nm_device_new
*
* Creates and initializes the structure representation of an NM device.
* Creates and initializes the structure representation of an NM device. For test
* devices, a device type other than DEVICE_TYPE_DONT_KNOW must be specified, this
* argument is ignored for real hardware devices since they are auto-probed.
*
*/
NMDevice *nm_device_new (const char *iface, NMData *app_data)
NMDevice *nm_device_new (const char *iface, gboolean test_dev, NMDeviceType test_dev_type, NMData *app_data)
{
NMDevice *dev;
g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (strlen (iface) > 0, NULL);
/* Test devices must have a valid type specified */
if (test_dev && !(test_dev_type != DEVICE_TYPE_DONT_KNOW))
return (NULL);
/* Another check to make sure we don't create a test device unless
* test devices were enabled on the command line.
*/
if (app_data && !app_data->enable_test_devices && test_dev)
{
syslog (LOG_ERR, "nm_device_new(): attempt to create a test device, but test devices were not enabled"
" on the command line. Will not create the device.\n");
return (NULL);
}
dev = g_new0 (NMDevice, 1);
if (!dev)
{
@@ -243,6 +273,14 @@ NMDevice *nm_device_new (const char *iface, NMData *app_data)
dev->refcount = 1;
dev->app_data = app_data;
dev->iface = g_strdup (iface);
dev->test_device = test_dev;
/* Real hardware devices are probed for their type, test devices must have
* their type specified.
*/
if (test_dev)
dev->type = test_dev_type;
else
dev->type = nm_device_test_wireless_extensions (dev) ?
DEVICE_TYPE_WIRELESS_ETHERNET : DEVICE_TYPE_WIRED_ETHERNET;
@@ -409,6 +447,86 @@ gboolean nm_device_get_supports_wireless_scan (NMDevice *dev)
}
/*
* nm_device_wireless_link_active
*
* Gets the link state of a wireless device
*
*/
static gboolean nm_device_wireless_link_active (NMDevice *dev)
{
struct iwreq wrq;
int iwlib_socket;
gboolean link = FALSE;
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (dev->app_data != NULL, FALSE);
/* Since non-active wireless cards are supposed to be powered off anyway,
* only scan for active/pending device and clear ap_list and best_ap for
* devices that aren't active/pending.
*/
if (dev != dev->app_data->active_device)
{
nm_ap_list_unref (dev->options.wireless.ap_list);
dev->options.wireless.ap_list = NULL;
if (dev->options.wireless.best_ap)
nm_ap_unref (dev->options.wireless.best_ap);
return (FALSE);
}
/* Test devices have their link state set through DBUS */
if (dev->test_device)
return (nm_device_get_link_active (dev));
/* FIXME
* For wireless cards, the best indicator of a "link" at this time
* seems to be whether the card has a valid access point MAC address.
* Is there a better way?
*/
iwlib_socket = iw_sockets_open ();
if (iw_get_ext (iwlib_socket, nm_device_get_iface (dev), SIOCGIWAP, &wrq) >= 0)
{
if ( nm_ethernet_address_is_valid ((struct ether_addr *)(&(wrq.u.ap_addr.sa_data)))
&& (nm_device_get_best_ap (dev) && !nm_device_need_ap_switch (dev)))
link = TRUE;
}
close (iwlib_socket);
return (link);
}
/*
* nm_device_wired_link_active
*
* Return the link state of a wired device. We usually just grab the HAL
* net.ethernet.link property, but on card insertion we need to check the MII
* registers of the card to get a more accurate response, since HAL may not
* have received a netlink socket link event for the device yet, and therefore
* will return FALSE when the device really does have a link.
*
*/
static gboolean nm_device_wired_link_active (NMDevice *dev, gboolean check_mii)
{
gboolean link = FALSE;
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (dev->app_data != NULL, FALSE);
/* Test devices have their link state set through DBUS */
if (dev->test_device)
return (nm_device_get_link_active (dev));
if (check_mii)
link = mii_get_link (dev);
else if (hal_device_property_exists (dev->app_data->hal_ctx, nm_device_get_udi (dev), "net.ethernet.link"))
link = hal_device_get_property_bool (dev->app_data->hal_ctx, nm_device_get_udi (dev), "net.ethernet.link");
return (link);
}
/*
* nm_device_update_link_active
*
@@ -417,69 +535,30 @@ gboolean nm_device_get_supports_wireless_scan (NMDevice *dev)
*/
void nm_device_update_link_active (NMDevice *dev, gboolean check_mii)
{
gboolean link_active = FALSE;
gboolean link = FALSE;
g_return_if_fail (dev != NULL);
g_return_if_fail (dev->app_data != NULL);
/* FIXME
* For wireless cards, the best indicator of a "link" at this time
* seems to be whether the card has a valid access point MAC address.
* Is there a better way?
*/
switch (nm_device_get_type (dev))
{
case DEVICE_TYPE_WIRELESS_ETHERNET:
{
struct iwreq wrq;
int iwlib_socket;
NMData *data = (NMData *)dev->app_data;
/* Since non-active wireless cards are supposed to be powered off anyway,
* only scan for active/pending device and clear ap_list and best_ap for
* devices that aren't active/pending.
*/
if (dev == data->active_device)
{
iwlib_socket = iw_sockets_open ();
if (iw_get_ext (iwlib_socket, nm_device_get_iface (dev), SIOCGIWAP, &wrq) >= 0)
{
if (nm_ethernet_address_is_valid ((struct ether_addr *)(&(wrq.u.ap_addr.sa_data))))
if (nm_device_get_best_ap (dev) && !nm_device_need_ap_switch (dev))
link_active = TRUE;
}
close (iwlib_socket);
}
else
{
nm_ap_list_unref (dev->options.wireless.ap_list);
dev->options.wireless.ap_list = NULL;
if (dev->options.wireless.best_ap)
nm_ap_unref (dev->options.wireless.best_ap);
}
link = nm_device_wireless_link_active (dev);
break;
}
case DEVICE_TYPE_WIRED_ETHERNET:
{
if (check_mii)
link_active = mii_get_link (dev);
else
if (hal_device_property_exists (dev->app_data->hal_ctx, nm_device_get_udi (dev), "net.ethernet.link"))
link_active = hal_device_get_property_bool (dev->app_data->hal_ctx, nm_device_get_udi (dev), "net.ethernet.link");
break;
}
link = nm_device_wired_link_active (dev, check_mii);
default:
link_active = nm_device_get_link_active (dev); /* Can't get link info for this device, so don't change link status */
link = nm_device_get_link_active (dev); /* Can't get link info for this device, so don't change link status */
break;
}
/* Update device link status and global state variable if the status changed */
if (link_active != nm_device_get_link_active (dev))
if (link != nm_device_get_link_active (dev))
{
nm_device_set_link_active (dev, link_active);
nm_data_set_state_modified (dev->app_data, TRUE);
nm_device_set_link_active (dev, link);
nm_data_mark_state_changed (dev->app_data);
}
}
@@ -503,6 +582,17 @@ char * nm_device_get_essid (NMDevice *dev)
g_return_val_if_fail (dev != NULL, NULL);
g_return_val_if_fail (nm_device_is_wireless (dev), NULL);
/* Test devices return the essid of their "best" access point
* or if there is none, the contents of the cur_essid field.
*/
if (dev->test_device)
{
if (nm_device_get_best_ap (dev))
return (nm_ap_get_essid (nm_device_get_best_ap (dev)));
else
return (dev->options.wireless.cur_essid);
}
iwlib_socket = iw_sockets_open ();
if (iwlib_socket >= 0)
{
@@ -541,6 +631,15 @@ void nm_device_set_essid (NMDevice *dev, const char *essid)
g_return_if_fail (dev != NULL);
g_return_if_fail (nm_device_is_wireless (dev));
/* Test devices directly set cur_essid */
if (dev->test_device)
{
if (dev->options.wireless.cur_essid)
g_free (dev->options.wireless.cur_essid);
dev->options.wireless.cur_essid = g_strdup (essid);
return;
}
/* Make sure the essid we get passed is a valid size */
if (!essid)
safe_essid[0] = '\0';
@@ -581,7 +680,19 @@ void nm_device_get_ap_address (NMDevice *dev, struct ether_addr *addr)
g_return_if_fail (addr != NULL);
g_return_if_fail (nm_device_is_wireless (dev));
/* Do we have a valid MAC address? */
/* Test devices return an invalid address when there's no link,
* and a made-up address when there is a link.
*/
if (dev->test_device)
{
struct ether_addr good_addr = { {0x70, 0x37, 0x03, 0x70, 0x37, 0x03} };
struct ether_addr bad_addr = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
gboolean link = nm_device_get_link_active (dev);
memcpy ((link ? &good_addr : &bad_addr), &(wrq.u.ap_addr.sa_data), sizeof (struct ether_addr));
return;
}
iwlib_socket = iw_sockets_open ();
if (iw_get_ext (iwlib_socket, nm_device_get_iface (dev), SIOCGIWAP, &wrq) >= 0)
memcpy (addr, &(wrq.u.ap_addr.sa_data), sizeof (struct ether_addr));
@@ -612,6 +723,10 @@ void nm_device_set_enc_key (NMDevice *dev, const char *key)
g_return_if_fail (dev != NULL);
g_return_if_fail (nm_device_is_wireless (dev));
/* Test devices just ignore encryption keys */
if (dev->test_device)
return;
/* Make sure the essid we get passed is a valid size */
if (!key)
safe_key[0] = '\0';
@@ -625,12 +740,18 @@ void nm_device_set_enc_key (NMDevice *dev, const char *key)
if (iwlib_socket >= 0)
{
wreq.u.data.pointer = (caddr_t) NULL;
wreq.u.data.flags = IW_ENCODE_ENABLED;
wreq.u.data.length = 0;
wreq.u.data.flags = IW_ENCODE_ENABLED;
/* Unfortunately, some drivers (Cisco) don't make a distinction between
* Open System authentication mode and whether or not to use WEP. You
* DON'T have to use WEP when using Open System, but these cards force
* it. Therefore, we have to set Open System mode when using WEP.
*/
if (strlen (safe_key) == 0)
{
wreq.u.data.flags = IW_ENCODE_OPEN | IW_ENCODE_NOKEY; /* Disable WEP */
wreq.u.data.flags |= IW_ENCODE_DISABLED | IW_ENCODE_NOKEY;
set_key = TRUE;
}
else
@@ -640,6 +761,7 @@ void nm_device_set_enc_key (NMDevice *dev, const char *key)
keylen = iw_in_key_full(iwlib_socket, nm_device_get_iface (dev), safe_key, &parsed_key[0], &wreq.u.data.flags);
if (keylen > 0)
{
wreq.u.data.flags |= IW_ENCODE_OPEN; // FIXME: what about restricted/Shared Key?
wreq.u.data.pointer = (caddr_t) &parsed_key;
wreq.u.data.length = keylen;
set_key = TRUE;
@@ -697,6 +819,13 @@ void nm_device_update_ip4_address (NMDevice *dev)
g_return_if_fail (dev->app_data != NULL);
g_return_if_fail (nm_device_get_iface (dev) != NULL);
/* Test devices get a nice, bogus IP address */
if (dev->test_device)
{
dev->ip4_address = 0x07030703;
return;
}
socket = nm_get_network_control_socket ();
if (socket < 0)
return;
@@ -747,6 +876,13 @@ static void nm_device_set_up_down (NMDevice *dev, gboolean up)
g_return_if_fail (dev != NULL);
/* Test devices do whatever we tell them to do */
if (dev->test_device)
{
dev->test_device_up = up;
return;
}
iface_fd = nm_get_network_control_socket ();
if (iface_fd < 0)
return;
@@ -801,6 +937,9 @@ gboolean nm_device_is_up (NMDevice *dev)
g_return_val_if_fail (dev != NULL, FALSE);
if (dev->test_device)
return (dev->test_device_up);
iface_fd = nm_get_network_control_socket ();
if (iface_fd < 0)
return (FALSE);
@@ -914,6 +1053,32 @@ static gboolean nm_device_activate_wireless (NMDevice *dev)
return (success);
}
/*
* nm_device_activation_cancel_if_needed
*
* Check whether we should stop activation, and if so clean up flags
* and other random things.
*
*/
gboolean nm_device_activation_cancel_if_needed (NMDevice *dev)
{
g_return_val_if_fail (dev != NULL, TRUE);
/* If we were told to quit activation, stop the thread and return */
if (dev->quit_activation)
{
syslog (LOG_DEBUG, "nm_device_activation_worker(%s): activation canceled.", nm_device_get_iface (dev));
dev->activating = FALSE;
dev->just_activated = FALSE;
nm_device_unref (dev);
return (TRUE);
}
return (FALSE);
}
/*
* nm_device_activation_worker
*
@@ -961,8 +1126,7 @@ fprintf( stderr, "(!switch (%d) || !enc_source (%d)) && is_enc (%d)\n",
*/
if (nm_ap_get_enc_key_source (best_ap) && !nm_ap_get_enc_method_good (best_ap))
{
fprintf (stderr, "trying encryption method\n");
/* Try another method, since the one set before obviously didn't work */
/* Try another method, since the one set in a previous iteration obviously didn't work */
switch (nm_ap_get_enc_method (best_ap))
{
case (NM_AP_ENC_METHOD_UNKNOWN):
@@ -984,27 +1148,21 @@ fprintf (stderr, "trying encryption method\n");
if (ask_for_key)
{
fprintf( stderr, "asking for key\n");
dev->options.wireless.user_key_received = FALSE;
nm_dbus_get_user_key_for_network (dev->app_data->dbus_connection, dev, best_ap);
/* Wait for the key to come back */
syslog (LOG_DEBUG, "nm_device_activation_worker(%s): asking for user key.", nm_device_get_iface (dev));
while (!dev->options.wireless.user_key_received && !dev->quit_activation)
g_usleep (G_USEC_PER_SEC / 2);
syslog (LOG_DEBUG, "nm_device_activation_worker(%s): user key received!", nm_device_get_iface (dev));
syslog (LOG_DEBUG, "nm_device_activation_worker(%s): user key received.", nm_device_get_iface (dev));
}
/* If we were told to quit activation, stop the thread and return */
if (dev->quit_activation)
{
syslog (LOG_DEBUG, "nm_device_activation_worker(%s): activation canceled 1", nm_device_get_iface (dev));
dev->activating = FALSE;
dev->just_activated = FALSE;
nm_device_unref (dev);
if (nm_device_activation_cancel_if_needed (dev))
return (NULL);
}
}
nm_device_activate_wireless (dev);
}
@@ -1015,15 +1173,9 @@ fprintf (stderr, "sleeping due to no access point\n");
}
/* If we were told to quit activation, stop the thread and return */
if (dev->quit_activation)
{
syslog (LOG_DEBUG, "nm_device_activation_worker(%s): activation canceled 1.5", nm_device_get_iface (dev));
dev->activating = FALSE;
dev->just_activated = FALSE;
nm_device_unref (dev);
if (nm_device_activation_cancel_if_needed (dev))
return (NULL);
}
}
/* Since we've got a link, the encryption method must be good */
nm_ap_set_enc_method_good (nm_device_get_best_ap (dev), TRUE);
@@ -1070,28 +1222,16 @@ fprintf (stderr, "sleeping due to no access point\n");
sethostname (hostname, strlen (hostname));
/* If we were told to quit activation, stop the thread and return */
if (dev->quit_activation)
{
syslog (LOG_DEBUG, "nm_device_activation_worker(%s): activation canceled 2", nm_device_get_iface (dev));
dev->activating = FALSE;
dev->just_activated = FALSE;
nm_device_unref (dev);
if (nm_device_activation_cancel_if_needed (dev))
return (NULL);
}
/* Make system aware of any new DNS settings from resolv.conf */
nm_system_update_dns ();
}
/* If we were told to quit activation, stop the thread and return */
if (dev->quit_activation)
{
syslog (LOG_DEBUG, "nm_device_activation_worker(%s): activation canceled 3", nm_device_get_iface (dev));
dev->activating = FALSE;
dev->just_activated = FALSE;
nm_device_unref (dev);
if (nm_device_activation_cancel_if_needed (dev))
return (NULL);
}
dev->just_activated = TRUE;
syslog (LOG_DEBUG, "nm_device_activation_worker(%s): device activated", nm_device_get_iface (dev));
@@ -1119,7 +1259,7 @@ gboolean nm_device_just_activated (NMDevice *dev)
dev->just_activated = FALSE;
return (TRUE);
}
else
return (FALSE);
}
@@ -1139,17 +1279,20 @@ gboolean nm_device_activating (NMDevice *dev)
/*
* nm_device_activation_cancel
* nm_device_activation_signal_cancel
*
* Signal activation worker that it should stop and die.
*
*/
void nm_device_activation_cancel (NMDevice *dev)
void nm_device_activation_signal_cancel (NMDevice *dev)
{
g_return_if_fail (dev != NULL);
syslog (LOG_DEBUG, "nm_device_activation_cancel(%s): canceled", nm_device_get_iface (dev));
if (dev->activating)
{
syslog (LOG_DEBUG, "nm_device_activation_signal_cancel(%s): canceled", nm_device_get_iface (dev));
dev->quit_activation = TRUE;
}
}
@@ -1164,7 +1307,7 @@ gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added)
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (dev->app_data != NULL, FALSE);
nm_device_activation_cancel (dev);
nm_device_activation_signal_cancel (dev);
/* Take out any entries in the routing table and any IP address the old device had. */
nm_system_device_flush_routes (dev);
@@ -1235,12 +1378,12 @@ fprintf( stderr, "Got user key\n");
/*
* nm_device_ap_list_add
* nm_device_ap_list_add_ap
*
* Add an access point to the devices internal AP list.
*
*/
void nm_device_ap_list_add (NMDevice *dev, NMAccessPoint *ap)
static void nm_device_ap_list_add_ap (NMDevice *dev, NMAccessPoint *ap)
{
g_return_if_fail (dev != NULL);
g_return_if_fail (ap != NULL);
@@ -1545,6 +1688,10 @@ static void nm_device_do_normal_scan (NMDevice *dev)
g_return_if_fail (dev != NULL);
g_return_if_fail (dev->app_data != NULL);
/* Test devices shouldn't get here since we fake the AP list earlier */
g_return_if_fail (!dev->test_device);
data = (NMData *)dev->app_data;
/* Device must be up before we can scan */
@@ -1637,7 +1784,7 @@ static void nm_device_do_normal_scan (NMDevice *dev)
}
/* Add the AP to the device's AP list */
nm_device_ap_list_add (dev, nm_ap);
nm_device_ap_list_add_ap (dev, nm_ap);
}
tmp_ap = tmp_ap->next;
}
@@ -1678,6 +1825,9 @@ static void nm_device_do_pseudo_scan (NMDevice *dev)
g_return_if_fail (dev != NULL);
g_return_if_fail (dev->app_data != NULL);
/* Test devices shouldn't get here since we fake the AP list earlier */
g_return_if_fail (!dev->test_device);
nm_device_ref (dev);
if (!(list = nm_device_ap_list_get (dev)))
@@ -1726,7 +1876,7 @@ static void nm_device_do_pseudo_scan (NMDevice *dev)
syslog(LOG_INFO, "%s: setting AP '%s' best", nm_device_get_iface (dev), nm_ap_get_essid (ap));
nm_device_set_best_ap (dev, ap);
nm_data_set_state_modified (dev->app_data, TRUE);
nm_data_mark_state_changed (dev->app_data);
break;
}
}
@@ -1736,6 +1886,78 @@ static void nm_device_do_pseudo_scan (NMDevice *dev)
}
/*
* nm_device_fake_ap_list
*
* Fake the access point list, used for test devices.
*
*/
static void nm_device_fake_ap_list (NMDevice *dev)
{
#define NUM_FAKE_APS 4
int i;
NMAccessPointList *old_ap_list = nm_device_ap_list_get (dev);
char *fake_essids[NUM_FAKE_APS] = { "green", "bay", "packers", "rule" };
struct ether_addr fake_addrs[NUM_FAKE_APS] = {{{0x70, 0x37, 0x03, 0x70, 0x37, 0x03}},
{{0x12, 0x34, 0x56, 0x78, 0x90, 0xab}},
{{0xcd, 0xef, 0x12, 0x34, 0x56, 0x78}},
{{0x90, 0xab, 0xcd, 0xef, 0x12, 0x34}} };
guint8 fake_qualities[NUM_FAKE_APS] = { 150, 26, 200, 100 };
double fake_freqs[NUM_FAKE_APS] = { 3.1416, 4.1416, 5.1415, 6.1415 };
gboolean fake_enc[NUM_FAKE_APS] = { FALSE, TRUE, FALSE, TRUE };
g_return_if_fail (dev != NULL);
g_return_if_fail (dev->app_data != NULL);
dev->options.wireless.ap_list = nm_ap_list_new (NETWORK_TYPE_DEVICE);
for (i = 0; i < NUM_FAKE_APS; i++)
{
NMAccessPoint *nm_ap = nm_ap_new ();
NMAccessPoint *list_ap;
/* Copy over info from scan to local structure */
nm_ap_set_essid (nm_ap, fake_essids[i]);
if (fake_enc[i])
{
nm_ap_set_encrypted (nm_ap, FALSE);
nm_ap_set_enc_method (nm_ap, NM_AP_ENC_METHOD_NONE);
}
else
{
nm_ap_set_encrypted (nm_ap, TRUE);
nm_ap_set_enc_method (nm_ap, NM_AP_ENC_METHOD_UNKNOWN);
}
nm_ap_set_address (nm_ap, (const struct ether_addr *)(&fake_addrs[i]));
nm_ap_set_quality (nm_ap, fake_qualities[i]);
nm_ap_set_freq (nm_ap, fake_freqs[i]);
/* Merge settings from Preferred/Allowed networks, mainly Keys */
list_ap = nm_ap_list_get_ap_by_essid (dev->app_data->trusted_ap_list, nm_ap_get_essid (nm_ap));
if (!list_ap)
list_ap = nm_ap_list_get_ap_by_essid (dev->app_data->preferred_ap_list, nm_ap_get_essid (nm_ap));
if (list_ap)
{
nm_ap_set_timestamp (nm_ap, nm_ap_get_timestamp (list_ap));
nm_ap_set_enc_key_source (nm_ap, nm_ap_get_enc_key_source (list_ap));
}
/* Add the AP to the device's AP list */
nm_device_ap_list_add_ap (dev, nm_ap);
}
if (dev == dev->app_data->active_device)
nm_ap_list_diff (dev->app_data, dev, old_ap_list, nm_device_ap_list_get (dev));
if (old_ap_list)
nm_ap_list_unref (old_ap_list);
}
/*
* nm_device_do_wireless_scan
*
@@ -1751,6 +1973,14 @@ void nm_device_do_wireless_scan (NMDevice *dev)
if (!nm_try_acquire_mutex (dev->options.wireless.scan_mutex, __FUNCTION__))
return;
/* Compose a fake list of access points */
if (dev->test_device)
{
nm_device_fake_ap_list (dev);
nm_unlock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__);
return;
}
if (nm_device_get_supports_wireless_scan (dev))
nm_device_do_normal_scan (dev);
else
@@ -1859,3 +2089,19 @@ static gboolean mii_get_link (NMDevice *dev)
/****************************************/
/* End Code ripped from HAL */
/****************************************/
/****************************************/
/* Test device routes */
/****************************************/
/*
* nm_device_is_test_device
*
*/
gboolean nm_device_is_test_device (NMDevice *dev)
{
g_return_val_if_fail (dev != NULL, FALSE);
return (dev->test_device);
}

View File

@@ -25,21 +25,10 @@
#include <net/ethernet.h>
#include "NetworkManager.h"
/*
* Types of NetworkManager devices
*/
enum NMDeviceType
{
DEVICE_TYPE_DONT_KNOW = 0,
DEVICE_TYPE_WIRED_ETHERNET,
DEVICE_TYPE_WIRELESS_ETHERNET
};
typedef struct NMDevice NMDevice;
typedef enum NMDeviceType NMDeviceType;
NMDevice * nm_device_new (const char *iface, NMData *app_data);
NMDevice * nm_device_new (const char *iface, gboolean test_device,
NMDeviceType test_dev_type, NMData *app_data);
void nm_device_ref (NMDevice *dev);
void nm_device_unref (NMDevice *dev);
@@ -86,7 +75,7 @@ char * nm_device_get_path_for_ap (NMDevice *dev, NMAccessPoint *ap);
void nm_device_set_enc_key (NMDevice *dev, const char *key);
gboolean nm_device_activation_begin (NMDevice *dev);
void nm_device_activation_cancel (NMDevice *dev);
void nm_device_activation_signal_cancel (NMDevice *dev);
gboolean nm_device_just_activated (NMDevice *dev);
gboolean nm_device_activating (NMDevice *dev);
gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added);
@@ -98,7 +87,6 @@ void nm_device_bring_up (NMDevice *dev);
void nm_device_bring_down (NMDevice *dev);
gboolean nm_device_is_up (NMDevice *dev);
void nm_device_ap_list_add (NMDevice *dev, NMAccessPoint *ap);
void nm_device_ap_list_clear (NMDevice *dev);
struct NMAccessPointList *nm_device_ap_list_get (NMDevice *dev);
NMAccessPoint *nm_device_ap_list_get_ap_by_essid (NMDevice *dev, const char *essid);
@@ -106,4 +94,7 @@ NMAccessPoint *nm_device_ap_list_get_ap_by_essid (NMDevice *dev, const char *ess
NMDevice * nm_get_device_by_udi (NMData *data, const char *udi);
NMDevice * nm_get_device_by_iface (NMData *data, const char *iface);
/* Test device routines */
gboolean nm_device_is_test_device (NMDevice *dev);
#endif

View File

@@ -36,7 +36,6 @@
#include "NetworkManagerDbus.h"
gboolean allowed_ap_worker_exit = FALSE;
extern gboolean debug;
/*
@@ -173,7 +172,9 @@ static NMDevice * nm_policy_get_best_device (NMData *data)
nm_unlock_mutex (data->user_device_mutex, __FUNCTION__);
}
/* Determine whether we need to clear the active device and unlock it. */
/* Determine whether we need to clear the active device and unlock it.
* This occurs if the best device is removed, for example.
*/
if (!best_dev && data->active_device_locked)
{
switch (nm_device_get_type (data->active_device))
@@ -198,6 +199,22 @@ static NMDevice * nm_policy_get_best_device (NMData *data)
}
}
/* Or, if the current active device is wireless and its "best" access
* point is locked, use that device still. This happens when the user
* forces a specific wireless network choice. The "best" ap will have
* already been set and locked by the dbus message handler, so we just
* need to test for a locked "best" ap.
*/
if (data->active_device && nm_device_is_wireless (data->active_device))
{
/* Give ourselves a chance to clear the "best" access point if
* its gone out of range and no longer in the device's ap list.
*/
nm_device_update_best_ap (data->active_device);
if (nm_device_get_best_ap_frozen (data->active_device))
best_dev = data->active_device;
}
/* Fall back to automatic device picking */
if (!best_dev)
{
@@ -276,8 +293,6 @@ gboolean nm_state_modification_monitor (gpointer user_data)
|| ( best_dev && nm_device_is_wireless (best_dev) && !nm_device_activating (best_dev)
&& (nm_device_need_ap_switch (best_dev) || (nm_device_get_ip4_address (best_dev) == 0))))
{
syslog (LOG_INFO, "nm_state_modification_monitor(): beginning activation for device '%s'", best_dev ? nm_device_get_iface (best_dev) : "(null)");
/* Deactivate the old device */
if (data->active_device)
{
@@ -286,11 +301,15 @@ gboolean nm_state_modification_monitor (gpointer user_data)
data->active_device = NULL;
}
if (best_dev)
{
/* Begin activation on the new device */
syslog (LOG_INFO, "nm_state_modification_monitor(): beginning activation for device '%s'", nm_device_get_iface (best_dev));
nm_device_ref (best_dev);
data->active_device = best_dev;
nm_device_activation_begin (data->active_device);
}
}
nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__);
}

View File

@@ -28,8 +28,6 @@
#include "NetworkManager.h"
#include "NetworkManagerUtils.h"
extern gboolean debug;
/*#define LOCKING_DEBUG */

View File

@@ -33,7 +33,6 @@
#include "NetworkManagerPolicy.h"
#include "NetworkManagerUtils.h"
extern gboolean debug;
static char *
nm_md5 (const char *buf, size_t len)

View File

@@ -47,6 +47,13 @@ gboolean nm_system_device_run_dhcp (NMDevice *dev)
g_return_val_if_fail (dev != NULL, FALSE);
/* Fake it for a test device */
if (nm_device_is_test_device (dev))
{
g_usleep (2000);
return (TRUE);
}
/* Unfortunately, dhclient can take a long time to get a dhcp address
* (for example, bad WEP key so it can't actually talk to the AP).
*/
@@ -74,6 +81,10 @@ void nm_system_device_stop_dhcp (NMDevice *dev)
g_return_if_fail (dev != NULL);
/* Not really applicable for test devices */
if (nm_device_is_test_device (dev))
return;
/* Find and kill the previous dhclient process for this device */
snprintf (buf, 500, "/var/run/dhclient-%s.pid", nm_device_get_iface (dev));
pidfile = fopen (buf, "r");
@@ -107,6 +118,10 @@ void nm_system_device_flush_routes (NMDevice *dev)
g_return_if_fail (dev != NULL);
/* Not really applicable for test devices */
if (nm_device_is_test_device (dev))
return;
/* Remove routing table entries */
snprintf (buf, 100, "/sbin/ip route flush dev %s", nm_device_get_iface (dev));
nm_spawn_process (buf);
@@ -125,7 +140,11 @@ void nm_system_device_flush_addresses (NMDevice *dev)
g_return_if_fail (dev != NULL);
/* Remove routing table entries */
/* Not really applicable for test devices */
if (nm_device_is_test_device (dev))
return;
/* Remove all IP addresses for a device */
snprintf (buf, 100, "/sbin/ip address flush dev %s", nm_device_get_iface (dev));
nm_spawn_process (buf);
}

View File

@@ -64,6 +64,13 @@ gboolean nm_system_device_run_dhcp (NMDevice *dev)
g_return_val_if_fail (dev != NULL, FALSE);
/* Fake it for a test device */
if (nm_device_is_test_device (dev))
{
g_usleep (2000);
return (TRUE);
}
iface = nm_device_get_iface (dev);
snprintf (buf, 500, "/sbin/dhcpcd %s", iface);
err = nm_spawn_process (buf);
@@ -85,6 +92,10 @@ void nm_system_device_stop_dhcp (NMDevice *dev)
g_return_if_fail (dev != NULL);
/* Not really applicable for test devices */
if (nm_device_is_test_device (dev))
return;
snprintf (buf, 500, "/var/run/dhcpcd-%s.pid", nm_device_get_iface(dev));
pidfile = fopen (buf, "r");
if (pidfile)
@@ -116,11 +127,15 @@ void nm_system_device_flush_routes (NMDevice *dev)
g_return_if_fail (dev != NULL);
/* Not really applicable for test devices */
if (nm_device_is_test_device (dev))
return;
if (nm_system_gentoo_conf_type == GENTOO_CONF_TYPE_IPROUTE) {
snprintf (buf, 100, "/sbin/ip route flush dev %s", nm_device_get_iface (dev));
} else if (nm_system_gentoo_conf_type == GENTOO_CONF_TYPE_IFCONFIG) {
// FIXME: this command still isn't right
snprintf (buf, 100, "/sbin/route del dev%s", nm_device_get_iface (dev));
snprintf (buf, 100, "/sbin/route del dev %s", nm_device_get_iface (dev));
} else {
snprintf (buf, 100, "/bin/false");
}
@@ -139,6 +154,10 @@ void nm_system_device_flush_addresses (NMDevice *dev)
g_return_if_fail (dev != NULL);
/* Not really applicable for test devices */
if (nm_device_is_test_device (dev))
return;
if (nm_system_gentoo_conf_type == GENTOO_CONF_TYPE_IPROUTE) {
snprintf (buf, 100, "/sbin/ip address flush dev %s", nm_device_get_iface (dev));
} else if (nm_system_gentoo_conf_type == GENTOO_CONF_TYPE_IFCONFIG) {

View File

@@ -54,6 +54,13 @@ gboolean nm_system_device_run_dhcp (NMDevice *dev)
g_return_val_if_fail (dev != NULL, FALSE);
/* Fake it for a test device */
if (nm_device_is_test_device (dev))
{
g_usleep (2000);
return (TRUE);
}
/* Unfortunately, dhclient can take a long time to get a dhcp address
* (for example, bad WEP key so it can't actually talk to the AP).
*/
@@ -80,6 +87,10 @@ void nm_system_device_stop_dhcp (NMDevice *dev)
g_return_if_fail (dev != NULL);
/* Not really applicable for test devices */
if (nm_device_is_test_device (dev))
return;
/* Find and kill the previous dhclient process for this device */
snprintf (buf, 500, "/var/run/dhclient-%s.pid", nm_device_get_iface (dev));
pidfile = fopen (buf, "r");
@@ -113,6 +124,10 @@ void nm_system_device_flush_routes (NMDevice *dev)
g_return_if_fail (dev != NULL);
/* Not really applicable for test devices */
if (nm_device_is_test_device (dev))
return;
/* Remove routing table entries */
snprintf (buf, 100, "/sbin/ip route flush dev %s", nm_device_get_iface (dev));
nm_spawn_process (buf);
@@ -131,7 +146,11 @@ void nm_system_device_flush_addresses (NMDevice *dev)
g_return_if_fail (dev != NULL);
/* Remove routing table entries */
/* Not really applicable for test devices */
if (nm_device_is_test_device (dev))
return;
/* Remove all IP addresses for a device */
snprintf (buf, 100, "/sbin/ip address flush dev %s", nm_device_get_iface (dev));
nm_spawn_process (buf);
}
@@ -170,7 +189,7 @@ void nm_system_delete_default_route (void)
*/
void nm_system_kill_all_dhcp_daemons (void)
{
nm_spawn_process ("/usr/bin/killall dhclient");
nm_spawn_process ("/usr/bin/killall -q dhclient");
}
@@ -183,7 +202,8 @@ void nm_system_kill_all_dhcp_daemons (void)
*/
void nm_system_update_dns (void)
{
nm_spawn_process ("/sbin/service nscd restart");
if(nm_spawn_process ("/etc/init.d/nscd status"))
nm_spawn_process ("/etc/init.d/nscd restart");
}

View File

@@ -4,10 +4,13 @@ INCLUDES = \
-DBINDIR=\"$(bindir)\" \
-DDATADIR=\"$(datadir)\"
noinst_PROGRAMS = nmtest nminfotest
noinst_PROGRAMS = nmtest nminfotest nmtestdevices
nmtest_SOURCES = nmclienttest.c
nmtest_LDADD = $(NM_LIBS)
nminfotest_SOURCES = nminfotest.c
nminfotest_LDADD = $(NM_LIBS)
nmtestdevices_SOURCES = nmtestdevices.c
nmtestdevices_LDADD = $(NM_LIBS)

297
test/nmtestdevices.c Normal file
View File

@@ -0,0 +1,297 @@
/* nmtestdevices - Tool to create/delete/modify test devices for NetworkManager
* (use when you are on a plane, don't have a wireless card, etc)
*
* 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 <getopt.h>
/* These MUST correspond to NetworkManager device types */
typedef enum NMDeviceType
{
DEVICE_TYPE_DONT_KNOW = 0,
DEVICE_TYPE_WIRED_ETHERNET,
DEVICE_TYPE_WIRELESS_ETHERNET
} NMDeviceType;
#define NM_DBUS_SERVICE "org.freedesktop.NetworkManager"
#define NM_DBUS_PATH "/org/freedesktop/NetworkManager"
#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager"
#define NM_DBUS_INTERFACE_DEVICES "org.freedesktop.NetworkManager.Devices"
void create_device (DBusConnection *connection, NMDeviceType type)
{
DBusMessage *message;
DBusMessage *reply;
DBusMessageIter iter;
DBusError error;
g_return_if_fail (connection != NULL);
g_return_if_fail (((type == DEVICE_TYPE_WIRED_ETHERNET) || (type == DEVICE_TYPE_WIRELESS_ETHERNET)));
message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "createTestDevice");
if (message == NULL)
{
fprintf (stderr, "Couldn't allocate the dbus message\n");
return;
}
dbus_error_init (&error);
dbus_message_append_args (message, DBUS_TYPE_INT32, type, DBUS_TYPE_INVALID);
reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
if (dbus_error_is_set (&error))
{
fprintf (stderr, "%s raised:\n %s\n\n", error.name, error.message);
dbus_error_free (&error);
dbus_message_unref (message);
return;
}
if (reply == NULL)
{
fprintf( stderr, "dbus reply message was NULL\n" );
dbus_message_unref (message);
return;
}
/* now analyze reply */
dbus_message_iter_init (reply, &iter);
char *string;
string = dbus_message_iter_get_string (&iter);
if (!string)
{
fprintf (stderr, "NetworkManager returned a NULL test device ID, test device could not be created." );
return;
}
fprintf (stderr, "New test device ID: '%s'\n", string );
dbus_free (string);
dbus_message_unref (reply);
dbus_message_unref (message);
}
void remove_device (DBusConnection *connection, char *dev)
{
DBusMessage *message;
DBusMessage *reply;
DBusMessageIter iter;
DBusError error;
g_return_if_fail (connection != NULL);
g_return_if_fail (dev != NULL);
message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "removeTestDevice");
if (message == NULL)
{
fprintf (stderr, "Couldn't allocate the dbus message\n");
return;
}
dbus_error_init (&error);
dbus_message_append_args (message, DBUS_TYPE_STRING, dev, DBUS_TYPE_INVALID);
reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
if (dbus_error_is_set (&error))
{
fprintf (stderr, "%s raised:\n %s\n\n", error.name, error.message);
dbus_error_free (&error);
dbus_message_unref (message);
return;
}
if (reply == NULL)
{
fprintf( stderr, "dbus reply message was NULL\n" );
dbus_message_unref (message);
return;
}
dbus_message_unref (message);
dbus_message_unref (reply);
}
void set_link_active (DBusConnection *connection, char *dev, gboolean active)
{
DBusMessage *message;
DBusMessage *reply;
DBusMessageIter iter;
DBusError error;
g_return_if_fail (connection != NULL);
g_return_if_fail (dev != NULL);
message = dbus_message_new_method_call (NM_DBUS_SERVICE, dev, NM_DBUS_INTERFACE_DEVICES, "setLinkActive");
if (message == NULL)
{
fprintf (stderr, "Couldn't allocate the dbus message\n");
return;
}
dbus_message_append_args (message, DBUS_TYPE_BOOLEAN, active, DBUS_TYPE_INVALID);
dbus_error_init (&error);
reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
if (dbus_error_is_set (&error))
{
fprintf (stderr, "%s raised:\n %s\n\n", error.name, error.message);
dbus_error_free (&error);
dbus_message_unref (message);
return;
}
if (reply == NULL)
{
fprintf( stderr, "dbus reply message was NULL\n" );
dbus_message_unref (message);
return;
}
dbus_message_unref (message);
dbus_message_unref (reply);
}
static void print_usage (void)
{
fprintf (stderr, "\n" "usage : nmtestdevices [options] [--help]\n");
fprintf (stderr,
"\n"
" --create-device <wired | wireless> Creates a test device, returns the new device ID\n"
" --remove-device <ID> Remove a test device (cannot remove real devices)\n"
" --make-link-active <ID> Switch a test device's link ON\n"
" --make-link-inactive <ID> Switch a test device's link OFF\n"
" --help Show this information and exit\n"
"\n"
"This tool allows you to tell NetworkManager to create and manipulate fake 'test' devices. This\n"
"is useful in sitation where you may not have a particular device but still want to test\n"
"NetworkManager out with it (For example, you forgot your wireless card at home and now you're\n"
"taking a trip and want to hack on NM, and you're on a plane so you could use the wireless\n"
"card anyway).\n"
"\n");
}
int main( int argc, char *argv[] )
{
DBusConnection *connection;
DBusError error;
char *dev = NULL;
gboolean create = FALSE;
gboolean remove = FALSE;
gboolean make_link_active = FALSE;
gboolean make_link_inactive = FALSE;
NMDeviceType dev_type = DEVICE_TYPE_DONT_KNOW;
/* Parse options */
while (1)
{
int c;
int option_index = 0;
const char *opt;
static struct option options[] = {
{"create-device", 1, NULL, 0},
{"remove-device", 1, NULL, 0},
{"make-link-active", 1, NULL, 0},
{"make-link-inactive", 1, NULL, 0},
{"help", 0, NULL, 0},
{NULL, 0, NULL, 0}
};
c = getopt_long (argc, argv, "", options, &option_index);
if (c == -1)
break;
switch (c)
{
case 0:
opt = options[option_index].name;
if (strcmp (opt, "help") == 0)
{
print_usage ();
exit (0);
}
else if (strcmp (opt, "create-device") == 0)
{
create = TRUE;
if (optarg)
{
if (strcmp (optarg, "wired") == 0)
dev_type = DEVICE_TYPE_WIRED_ETHERNET;
else if (strcmp (optarg, "wireless") == 0)
dev_type = DEVICE_TYPE_WIRELESS_ETHERNET;
}
}
else if (strcmp (opt, "remove-device") == 0)
{
remove = TRUE;
if (optarg)
dev = g_strdup (optarg);
}
else if (strcmp (opt, "make-link-active") == 0)
{
make_link_active = TRUE;
if (optarg)
dev = g_strdup (optarg);
}
else if (strcmp (opt, "make-link-inactive") == 0)
{
make_link_inactive = TRUE;
if (optarg)
dev = g_strdup (optarg);
}
break;
default:
print_usage ();
exit (1);
break;
}
}
g_type_init ();
dbus_error_init (&error);
connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
if (connection == NULL)
{
fprintf (stderr, "Error connecting to system bus: %s\n", error.message);
dbus_error_free (&error);
return 1;
}
if (create)
create_device (connection, dev_type);
else if (remove)
remove_device (connection, dev);
else if (make_link_active)
set_link_active (connection, dev, TRUE);
else if (make_link_inactive)
set_link_active (connection, dev, FALSE);
return 0;
}