summaryrefslogtreecommitdiff
path: root/src/NetworkManagerDevice.c
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2005-10-09 04:39:49 +0000
committerDan Williams <dcbw@redhat.com>2005-10-09 04:39:49 +0000
commit69d77f6b56ebddfcfbc1cf0e618d66035d8cf609 (patch)
tree9c9dcf45eaa458d26e085222ffc409a1568eecff /src/NetworkManagerDevice.c
parentfad78837c6a3c0fdd243abc655f214752d73ed22 (diff)
downloadNetworkManager-69d77f6b56ebddfcfbc1cf0e618d66035d8cf609.tar.gz
2005-10-09 Dan Williams <dcbw@redhat.com>
* Replace the "driver support level" stuff with capabilities. The capability field is a bitfield that is more flexible than the old driver support level thing. It's mostly so we can easily figure out what supports WPA and what doesn't, but should be quite useful later. git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@1007 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
Diffstat (limited to 'src/NetworkManagerDevice.c')
-rw-r--r--src/NetworkManagerDevice.c348
1 files changed, 256 insertions, 92 deletions
diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c
index 9c52a21a08..dae40d325e 100644
--- a/src/NetworkManagerDevice.c
+++ b/src/NetworkManagerDevice.c
@@ -52,6 +52,9 @@ static gboolean supports_mii_carrier_detect (NMDevice *dev);
static gboolean supports_ethtool_carrier_detect (NMDevice *dev);
static gboolean nm_device_bring_up_wait (NMDevice *dev, gboolean cancelable);
static gboolean link_to_specific_ap (NMDevice *dev, NMAccessPoint *ap, gboolean default_link);
+static guint32 nm_device_discover_capabilities (NMDevice *dev);
+static gboolean nm_is_driver_supported (NMDevice *dev);
+static guint32 nm_device_wireless_discover_capabilities (NMDevice *dev);
static void nm_device_activate_schedule_stage1_device_prepare (NMActRequest *req);
static void nm_device_activate_schedule_stage2_device_config (NMActRequest *req);
@@ -114,34 +117,65 @@ static gboolean nm_device_test_wireless_extensions (NMDevice *dev)
/*
- * nm_device_supports_wireless_scan
+ * nm_get_device_driver_name
*
- * Test whether a given device is a wireless one or not.
+ * Get the device's driver name from HAL.
*
*/
-static gboolean nm_device_supports_wireless_scan (NMDevice *dev)
+static char *nm_get_device_driver_name (NMDevice *dev)
{
- NMSock *sk;
- int err;
- gboolean can_scan = TRUE;
- 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);
+ char * udi = NULL;
+ char * driver_name = NULL;
+ LibHalContext *ctx = NULL;
- /* A test wireless device can always scan (we generate fake scan data for it) */
- if (dev->test_device)
- return (TRUE);
+ g_return_val_if_fail (dev != NULL, NULL);
+ g_return_val_if_fail (dev->app_data != NULL, NULL);
- if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
+ ctx = dev->app_data->hal_ctx;
+ g_return_val_if_fail (ctx != NULL, NULL);
+
+ if ((udi = nm_device_get_udi (dev)))
{
- err = iw_scan (nm_dev_sock_get_fd (sk), (char *)nm_device_get_iface (dev), WIRELESS_EXT, &scan_data);
- nm_dispose_scan_results (scan_data.result);
- if ((err == -1) && (errno == EOPNOTSUPP))
- can_scan = FALSE;
- nm_dev_sock_close (sk);
+ char *parent_udi = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
+
+ if (parent_udi && libhal_device_property_exists (ctx, parent_udi, "info.linux.driver", NULL))
+ {
+ char *drv = libhal_device_get_property_string (ctx, parent_udi, "info.linux.driver", NULL);
+ driver_name = g_strdup (drv);
+ g_free (drv);
+ }
+ g_free (parent_udi);
}
- return (can_scan);
+
+ return driver_name;
+}
+
+/* Blacklist of unsupported drivers */
+static char * driver_blacklist[] =
+{
+ NULL
+};
+
+
+/*
+ * nm_is_driver_supported
+ *
+ * Check device's driver against a blacklist of unsupported drivers.
+ *
+ */
+static gboolean nm_is_driver_supported (NMDevice *dev)
+{
+ char ** drv = NULL;
+
+ g_return_val_if_fail (dev != NULL, FALSE);
+ g_return_val_if_fail (dev->driver != NULL, FALSE);
+
+ for (drv = &driver_blacklist[0]; *drv; drv++)
+ {
+ if (!strcmp (*drv, dev->driver))
+ return FALSE;
+ }
+ return TRUE;
}
@@ -259,6 +293,64 @@ void nm_device_copy_allowed_to_dev_list (NMDevice *dev, NMAccessPointList *allow
/*
+ * nm_device_wireless_init
+ *
+ * Initialize a new wireless device with wireless-specific settings.
+ *
+ */
+static gboolean nm_device_wireless_init (NMDevice *dev)
+{
+ NMSock *sk;
+ NMDeviceWirelessOptions *opts = &(dev->options.wireless);
+
+ g_return_val_if_fail (dev != NULL, FALSE);
+ g_return_val_if_fail (nm_device_is_wireless (dev), FALSE);
+
+ opts->scan_mutex = g_mutex_new ();
+ opts->ap_list = nm_ap_list_new (NETWORK_TYPE_DEVICE);
+ if (!opts->scan_mutex || !opts->ap_list)
+ return FALSE;
+
+ nm_register_mutex_desc (opts->scan_mutex, "Scan Mutex");
+ nm_wireless_set_scan_interval (dev->app_data, dev, NM_WIRELESS_SCAN_INTERVAL_ACTIVE);
+
+ nm_device_set_mode (dev, NETWORK_MODE_INFRA);
+
+ /* Non-scanning devices show the entire allowed AP list as their
+ * available networks.
+ */
+ if (!(dev->capabilities & NM_DEVICE_CAP_WIRELESS_SCAN))
+ nm_device_copy_allowed_to_dev_list (dev, dev->app_data->allowed_ap_list);
+
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
+ {
+ iwrange range;
+ if (iw_get_range_info (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), &range) >= 0)
+ {
+ int i;
+
+ opts->max_qual.qual = range.max_qual.qual;
+ opts->max_qual.level = range.max_qual.level;
+ opts->max_qual.noise = range.max_qual.noise;
+ opts->max_qual.updated = range.max_qual.updated;
+
+ opts->avg_qual.qual = range.avg_qual.qual;
+ opts->avg_qual.level = range.avg_qual.level;
+ opts->avg_qual.noise = range.avg_qual.noise;
+ opts->avg_qual.updated = range.avg_qual.updated;
+
+ opts->num_freqs = MIN (range.num_frequency, IW_MAX_FREQUENCIES);
+ for (i = 0; i < opts->num_freqs; i++)
+ opts->freqs[i] = iw_freq2float (&(range.freq[i]));
+ }
+ nm_dev_sock_close (sk);
+ }
+
+ return TRUE;
+}
+
+
+/*
* nm_device_new
*
* Creates and initializes the structure representation of an NM device. For test
@@ -296,7 +388,8 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev,
dev->app_data = app_data;
dev->iface = g_strdup (iface);
dev->test_device = test_dev;
- nm_device_set_udi (dev, udi);
+ dev->udi = g_strdup (udi);
+ dev->driver = nm_get_device_driver_name (dev);
dev->use_dhcp = TRUE;
/* Real hardware devices are probed for their type, test devices must have
@@ -318,66 +411,19 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev,
/* Have to bring the device up before checking link status and other stuff */
nm_device_bring_up_wait (dev, 0);
- /* Initialize wireless-specific options */
- if (nm_device_is_wireless (dev))
- {
- NMSock *sk;
- NMDeviceWirelessOptions *opts = &(dev->options.wireless);
-
- nm_device_set_mode (dev, NETWORK_MODE_INFRA);
-
- nm_wireless_set_scan_interval (dev->app_data, dev, NM_WIRELESS_SCAN_INTERVAL_ACTIVE);
-
- opts->scan_mutex = g_mutex_new ();
- opts->ap_list = nm_ap_list_new (NETWORK_TYPE_DEVICE);
- if (!opts->scan_mutex || !opts->ap_list)
- goto err;
-
- nm_register_mutex_desc (opts->scan_mutex, "Scan Mutex");
-
- opts->supports_wireless_scan = nm_device_supports_wireless_scan (dev);
-
- /* Non-scanning devices show the entire allowed AP list as their
- * available networks.
- */
- if (opts->supports_wireless_scan == FALSE)
- nm_device_copy_allowed_to_dev_list (dev, app_data->allowed_ap_list);
-
- if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
- {
- iwrange range;
- if (iw_get_range_info (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), &range) >= 0)
- {
- int i;
-
- opts->max_qual.qual = range.max_qual.qual;
- opts->max_qual.level = range.max_qual.level;
- opts->max_qual.noise = range.max_qual.noise;
- opts->max_qual.updated = range.max_qual.updated;
-
- opts->avg_qual.qual = range.avg_qual.qual;
- opts->avg_qual.level = range.avg_qual.level;
- opts->avg_qual.noise = range.avg_qual.noise;
- opts->avg_qual.updated = range.avg_qual.updated;
+ /* First check for driver support */
+ if (nm_is_driver_supported (dev))
+ dev->capabilities |= NM_DEVICE_CAP_NM_SUPPORTED;
- opts->num_freqs = MIN (range.num_frequency, IW_MAX_FREQUENCIES);
- for (i = 0; i < opts->num_freqs; i++)
- opts->freqs[i] = iw_freq2float (&(range.freq[i]));
- }
- nm_dev_sock_close (sk);
- }
- }
- else if (nm_device_is_wired (dev))
+ /* Then discover devices-specific capabilities */
+ if (dev->capabilities & NM_DEVICE_CAP_NM_SUPPORTED)
{
- if (supports_ethtool_carrier_detect (dev) || supports_mii_carrier_detect (dev))
- dev->options.wired.has_carrier_detect = TRUE;
- }
+ dev->capabilities |= nm_device_discover_capabilities (dev);
- /* Must be called after carrier detect or wireless scan detect. */
- dev->driver_support_level = nm_get_driver_support_level (dev->app_data->hal_ctx, dev);
+ /* Initialize wireless-specific options */
+ if (nm_device_is_wireless (dev) && !nm_device_wireless_init (dev))
+ goto err;
- if (nm_device_get_driver_support_level (dev) != NM_DRIVER_UNSUPPORTED)
- {
nm_device_set_link_active (dev, nm_device_probe_link_state (dev));
nm_device_update_ip4_address (dev);
nm_device_update_hw_address (dev);
@@ -387,6 +433,8 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev,
dev->use_dhcp = nm_system_device_get_use_dhcp (dev);
}
+ nm_print_device_capabilities (dev);
+
dev->worker = g_thread_create (nm_device_worker, dev, TRUE, &error);
if (!dev->worker)
{
@@ -463,6 +511,7 @@ gboolean nm_device_unref (NMDevice *dev)
g_free (dev->udi);
g_free (dev->iface);
+ g_free (dev->driver);
memset (dev, 0, sizeof (NMDevice));
g_free (dev);
deleted = TRUE;
@@ -536,6 +585,105 @@ void nm_device_worker_thread_stop (NMDevice *dev)
/*
+ * nm_device_wireless_discover_capabilities
+ *
+ * Figure out wireless-specific capabilities
+ *
+ */
+static guint32 nm_device_wireless_discover_capabilities (NMDevice *dev)
+{
+ NMSock * sk;
+ int err;
+ wireless_scan_head scan_data;
+ guint32 caps = NM_DEVICE_CAP_NONE;
+
+ g_return_val_if_fail (dev != NULL, NM_DEVICE_CAP_NONE);
+ g_return_val_if_fail (nm_device_is_wireless (dev), NM_DEVICE_CAP_NONE);
+
+ /* A test wireless device can always scan (we generate fake scan data for it) */
+ if (dev->test_device)
+ caps |= NM_DEVICE_CAP_WIRELESS_SCAN;
+ else
+ {
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
+ {
+ err = iw_scan (nm_dev_sock_get_fd (sk), (char *)nm_device_get_iface (dev), WIRELESS_EXT, &scan_data);
+ nm_dispose_scan_results (scan_data.result);
+ if (!((err == -1) && (errno == EOPNOTSUPP)))
+ caps |= NM_DEVICE_CAP_WIRELESS_SCAN;
+ nm_dev_sock_close (sk);
+ }
+ }
+
+ return caps;
+}
+
+
+/*
+ * nm_device_wireless_discover_capabilities
+ *
+ * Figure out wireless-specific capabilities
+ *
+ */
+static guint32 nm_device_wired_discover_capabilities (NMDevice *dev)
+{
+ guint32 caps = NM_DEVICE_CAP_NONE;
+ const char * udi = NULL;
+ char * usb_test = NULL;
+ LibHalContext *ctx = NULL;
+
+ g_return_val_if_fail (dev != NULL, NM_DEVICE_CAP_NONE);
+ g_return_val_if_fail (nm_device_is_wired (dev), NM_DEVICE_CAP_NONE);
+ g_return_val_if_fail (dev->app_data != NULL, NM_DEVICE_CAP_NONE);
+
+ /* cipsec devices are also explicitly unsupported at this time */
+ if (strstr (nm_device_get_iface (dev), "cipsec"))
+ return NM_DEVICE_CAP_NONE;
+
+ /* Ignore Ethernet-over-USB devices too for the moment (Red Hat #135722) */
+ ctx = dev->app_data->hal_ctx;
+ udi = nm_device_get_udi (dev);
+ if ( libhal_device_property_exists (ctx, udi, "usb.interface.class", NULL)
+ && (usb_test = libhal_device_get_property_string (ctx, udi, "usb.interface.class", NULL)))
+ {
+ libhal_free_string (usb_test);
+ return NM_DEVICE_CAP_NONE;
+ }
+
+ if (supports_ethtool_carrier_detect (dev) || supports_mii_carrier_detect (dev))
+ caps |= NM_DEVICE_CAP_CARRIER_DETECT;
+
+ return caps;
+}
+
+
+/*
+ * nm_device_discover_capabilities
+ *
+ * Called only at device initialization time to discover device-specific
+ * capabilities.
+ *
+ */
+static guint32 nm_device_discover_capabilities (NMDevice *dev)
+{
+ guint32 caps = NM_DEVICE_CAP_NONE;
+
+ g_return_val_if_fail (dev != NULL, NM_DEVICE_CAP_NONE);
+
+ /* Don't touch devices that we already don't support */
+ if (!(dev->capabilities & NM_DEVICE_CAP_NM_SUPPORTED))
+ return NM_DEVICE_CAP_NONE;
+
+ if (nm_device_is_wired (dev))
+ caps |= nm_device_wired_discover_capabilities (dev);
+ else if (nm_device_is_wireless (dev))
+ caps |= nm_device_wireless_discover_capabilities (dev);
+
+ return caps;
+}
+
+
+/*
* nm_device_get_app_data
*
*/
@@ -621,6 +769,17 @@ const char * nm_device_get_iface (NMDevice *dev)
/*
+ * Get/set functions for driver
+ */
+const char * nm_device_get_driver (NMDevice *dev)
+{
+ g_return_val_if_fail (dev != NULL, NULL);
+
+ return (dev->driver);
+}
+
+
+/*
* Get/set functions for type
*/
guint nm_device_get_type (NMDevice *dev)
@@ -646,13 +805,13 @@ gboolean nm_device_is_wired (NMDevice *dev)
/*
- * Accessor for driver support level
+ * Accessor for device capabilities
*/
-NMDriverSupportLevel nm_device_get_driver_support_level (NMDevice *dev)
+guint32 nm_device_get_capabilities (NMDevice *dev)
{
- g_return_val_if_fail (dev != NULL, NM_DRIVER_UNSUPPORTED);
+ g_return_val_if_fail (dev != NULL, NM_DEVICE_CAP_NONE);
- return (dev->driver_support_level);
+ return dev->capabilities;
}
@@ -695,7 +854,7 @@ void nm_device_set_link_active (NMDevice *dev, const gboolean link_active)
* must manually choose semi-supported devices.
*
*/
- if (nm_device_is_wired (dev) && (nm_device_get_driver_support_level (dev) == NM_DRIVER_FULLY_SUPPORTED))
+ if (nm_device_is_wired (dev) && (nm_device_get_capabilities (dev) & NM_DEVICE_CAP_CARRIER_DETECT))
{
gboolean do_switch = act_dev ? FALSE : TRUE; /* If no currently active device, switch to this one */
NMActRequest * act_req;
@@ -726,7 +885,7 @@ gboolean nm_device_get_supports_wireless_scan (NMDevice *dev)
if (!nm_device_is_wireless (dev))
return (FALSE);
- return (dev->options.wireless.supports_wireless_scan);
+ return (dev->capabilities & NM_DEVICE_CAP_WIRELESS_SCAN);
}
@@ -740,7 +899,7 @@ gboolean nm_device_get_supports_carrier_detect (NMDevice *dev)
if (!nm_device_is_wired (dev))
return (FALSE);
- return (dev->options.wired.has_carrier_detect);
+ return (dev->capabilities & NM_DEVICE_CAP_CARRIER_DETECT);
}
/*
@@ -866,7 +1025,7 @@ static gboolean nm_device_probe_wired_link_state (NMDevice *dev)
* they never get auto-selected by NM. User has to force them on us,
* so we just hope the user knows whether or not the cable's plugged in.
*/
- if (dev->options.wired.has_carrier_detect != TRUE)
+ if (!(dev->capabilities & NM_DEVICE_CAP_CARRIER_DETECT))
link = TRUE;
return link;
@@ -1850,9 +2009,6 @@ gboolean nm_device_activation_start (NMActRequest *req)
g_return_val_if_fail (!nm_device_is_activating (dev), TRUE); /* Return if activation has already begun */
- if (nm_device_get_driver_support_level (dev) == NM_DRIVER_UNSUPPORTED)
- return FALSE;
-
nm_act_request_ref (req);
dev->act_request = req;
dev->quit_activation = FALSE;
@@ -3212,7 +3368,7 @@ gboolean nm_device_deactivate (NMDevice *dev)
nm_device_deactivate_quickly (dev);
- if (nm_device_get_driver_support_level (dev) == NM_DRIVER_UNSUPPORTED)
+ if (!(nm_device_get_capabilities (dev) & NM_DEVICE_CAP_NM_SUPPORTED))
return TRUE;
/* Remove any device nameservers and domains */
@@ -3971,9 +4127,10 @@ static gboolean nm_completion_scan_has_results (int tries, nm_completion_args ar
*/
static gboolean nm_device_wireless_scan (gpointer user_data)
{
- NMWirelessScanCB *scan_cb = (NMWirelessScanCB *)(user_data);
- NMDevice *dev = NULL;
- NMWirelessScanResults *scan_results = NULL;
+ NMWirelessScanCB * scan_cb = (NMWirelessScanCB *)(user_data);
+ NMDevice * dev = NULL;
+ NMWirelessScanResults * scan_results = NULL;
+ guint32 caps;
g_return_val_if_fail (scan_cb != NULL, FALSE);
@@ -3984,6 +4141,13 @@ static gboolean nm_device_wireless_scan (gpointer user_data)
return FALSE;
}
+ caps = nm_device_get_capabilities (dev);
+ if (!(caps & NM_DEVICE_CAP_NM_SUPPORTED) || !(caps & NM_DEVICE_CAP_WIRELESS_SCAN))
+ {
+ g_free (scan_cb);
+ return FALSE;
+ }
+
/* Reschedule ourselves if all wireless is disabled, we're asleep,
* or we are currently activating.
*/