Commit 69d77f6b authored by Dan Williams's avatar Dan Williams
Browse files

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
parent fad78837
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.
2005-10-09 Dan Williams <dcbw@redhat.com>
* test/nmtest.c
......
......@@ -114,21 +114,22 @@ typedef enum NMEncKeyType
NM_ENC_TYPE_NONE,
NM_ENC_TYPE_HEX_KEY,
NM_ENC_TYPE_ASCII_KEY,
NM_ENC_TYPE_128_BIT_PASSPHRASE
/* FIXME: WPA and 802.1x support */
NM_ENC_TYPE_128_BIT_PASSPHRASE,
NM_ENC_TYPE_WPA_PSK_HEX_KEY,
NM_ENC_TYPE_WPA_PSK_PASSPHRASE
/* FIXME: 802.1x support */
} NMEncKeyType;
/*
* Driver support levels
* Device capability bits
*
*/
typedef enum NMDriverSupportLevel
{
NM_DRIVER_UNSUPPORTED = 0,
NM_DRIVER_NO_CARRIER_DETECT,
NM_DRIVER_NO_WIRELESS_SCAN,
NM_DRIVER_FULLY_SUPPORTED
} NMDriverSupportLevel;
#define NM_DEVICE_CAP_NONE 0x0000
#define NM_DEVICE_CAP_NM_SUPPORTED 0x0001
#define NM_DEVICE_CAP_CARRIER_DETECT 0x0002
#define NM_DEVICE_CAP_WIRELESS_SCAN 0x0004
#define NM_DEVICE_CAP_WPA_PSK 0x0008
/*
......@@ -173,7 +174,8 @@ typedef enum NMDeviceAuthMethod
NM_DEVICE_AUTH_METHOD_UNKNOWN = 0,
NM_DEVICE_AUTH_METHOD_NONE,
NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM,
NM_DEVICE_AUTH_METHOD_SHARED_KEY
NM_DEVICE_AUTH_METHOD_SHARED_KEY,
NM_DEVICE_AUTH_METHOD_WPA_PSK
} NMDeviceAuthMethod;
......
......@@ -436,10 +436,12 @@ static void nmwa_dbus_check_drivers (NMWirelessApplet *applet)
}
}
if ( !found
&& ( (network_device_get_driver_support_level (dbus_dev) == NM_DRIVER_NO_CARRIER_DETECT)
|| (network_device_get_driver_support_level (dbus_dev) == NM_DRIVER_NO_WIRELESS_SCAN)))
nmwa_dbus_schedule_driver_notification (applet, dbus_dev);
if (!found)
{
if ((network_device_is_wired (dbus_dev) && !(network_device_get_capabilities (dbus_dev) & NM_DEVICE_CAP_CARRIER_DETECT))
|| (network_device_is_wireless (dbus_dev) && !(network_device_get_capabilities (dbus_dev) & NM_DEVICE_CAP_WIRELESS_SCAN)))
nmwa_dbus_schedule_driver_notification (applet, dbus_dev);
}
}
}
......@@ -669,7 +671,7 @@ static void nmwa_dbus_device_properties_cb (DBusPendingCall *pcall, void *user_d
dbus_int32_t strength = -1;
char * active_network_path = NULL;
dbus_bool_t link_active = FALSE;
dbus_uint32_t driver_support_level = 0;
dbus_uint32_t caps = NM_DEVICE_CAP_NONE;
char ** networks = NULL;
int num_networks = 0;
NMActStage act_stage = NM_ACT_STAGE_UNKNOWN;
......@@ -702,7 +704,7 @@ static void nmwa_dbus_device_properties_cb (DBusPendingCall *pcall, void *user_d
DBUS_TYPE_UINT32, &mode,
DBUS_TYPE_INT32, &strength,
DBUS_TYPE_BOOLEAN,&link_active,
DBUS_TYPE_UINT32, &driver_support_level,
DBUS_TYPE_UINT32, &caps,
DBUS_TYPE_STRING, &active_network_path,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &networks, &num_networks,
DBUS_TYPE_INVALID))
......@@ -714,7 +716,7 @@ static void nmwa_dbus_device_properties_cb (DBusPendingCall *pcall, void *user_d
network_device_set_address (dev, hw_addr);
network_device_set_active (dev, active);
network_device_set_link (dev, link_active);
network_device_set_driver_support_level (dev, driver_support_level);
network_device_set_capabilities (dev, caps);
network_device_set_act_stage (dev, act_stage);
network_device_set_ip4_address (dev, ip4_address);
network_device_set_broadcast (dev, broadcast);
......
......@@ -753,24 +753,20 @@ gboolean nmwa_driver_notify (gpointer user_data)
label = GTK_LABEL (glade_xml_get_widget (cb_data->xml, "driver_sucks_label"));
switch (network_device_get_driver_support_level (dev))
{
case NM_DRIVER_NO_WIRELESS_SCAN:
temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support wireless scanning."),
network_device_get_desc (dev), network_device_get_iface (dev));
label_text = g_strdup_printf (gtk_label_get_label (label), temp);
g_free (temp);
break;
case NM_DRIVER_NO_CARRIER_DETECT:
temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support link detection."),
network_device_get_desc (dev), network_device_get_iface (dev));
label_text = g_strdup_printf (gtk_label_get_label (label), temp);
g_free (temp);
break;
if (network_device_is_wireless (dev) && !(network_device_get_capabilities (dev) & NM_DEVICE_CAP_WIRELESS_SCAN))
{
temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support wireless scanning."),
network_device_get_desc (dev), network_device_get_iface (dev));
label_text = g_strdup_printf (gtk_label_get_label (label), temp);
g_free (temp);
}
default:
break;
if (network_device_is_wired (dev) && !(network_device_get_capabilities (dev) & NM_DEVICE_CAP_CARRIER_DETECT))
{
temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support link detection."),
network_device_get_desc (dev), network_device_get_iface (dev));
label_text = g_strdup_printf (gtk_label_get_label (label), temp);
g_free (temp);
}
if (label_text)
......@@ -1768,6 +1764,10 @@ static void nmwa_menu_add_devices (GtkWidget *menu, NMWirelessApplet *applet)
g_assert (dev);
/* Ignore unsupported devices */
if (!(network_device_get_capabilities (dev) & NM_DEVICE_CAP_NM_SUPPORTED))
continue;
switch (network_device_get_type (dev))
{
case DEVICE_TYPE_WIRELESS_ETHERNET:
......@@ -1790,6 +1790,10 @@ static void nmwa_menu_add_devices (GtkWidget *menu, NMWirelessApplet *applet)
{
gint n_devices = 0;
/* Ignore unsupported devices */
if (!(network_device_get_capabilities (dev) & NM_DEVICE_CAP_NM_SUPPORTED))
continue;
switch (network_device_get_type (dev))
{
case DEVICE_TYPE_WIRED_ETHERNET:
......
......@@ -94,7 +94,7 @@ void wired_menu_item_update (NMWiredMenuItem *item, NetworkDevice *dev, const gi
/* Only dim the item if the device supports carrier detection AND
* we know it doesn't have a link.
*/
if (network_device_get_driver_support_level (dev) != NM_DRIVER_NO_CARRIER_DETECT)
if (network_device_get_capabilities (dev) & NM_DEVICE_CAP_CARRIER_DETECT)
gtk_widget_set_sensitive (GTK_WIDGET (item->check_item), network_device_get_link (dev));
}
......
......@@ -32,25 +32,25 @@
*/
struct NetworkDevice
{
int refcount;
char * iface;
char * desc;
char * nm_path;
NMDeviceType type;
gboolean active;
gboolean link;
NMDriverSupportLevel driver_support_level;
char * addr;
char * ip4addr;
char * broadcast;
char * netmask;
char * udi;
char * route;
char * primary_dns;
char * secondary_dns;
gint strength;
GSList * networks;
NMActStage act_stage;
int refcount;
char * iface;
char * desc;
char * nm_path;
NMDeviceType type;
gboolean active;
gboolean link;
guint32 caps;
char * addr;
char * ip4addr;
char * broadcast;
char * netmask;
char * udi;
char * route;
char * primary_dns;
char * secondary_dns;
gint strength;
GSList * networks;
NMActStage act_stage;
};
......@@ -98,7 +98,7 @@ NetworkDevice *network_device_copy (NetworkDevice *src)
dev->ip4addr = g_strdup (src->ip4addr);
dev->broadcast = g_strdup (src->broadcast);
dev->netmask = g_strdup (src->netmask);
dev->driver_support_level = src->driver_support_level;
dev->caps = src->caps;
dev->iface = g_strdup (src->iface);
dev->desc = g_strdup (src->desc);
dev->route = g_strdup (src->route);
......@@ -533,20 +533,20 @@ void network_device_set_secondary_dns (NetworkDevice *dev, const char *dns)
}
/*
* Accessors for driver support level
* Accessors for device capabilities
*/
NMDriverSupportLevel network_device_get_driver_support_level (NetworkDevice *dev)
guint32 network_device_get_capabilities (NetworkDevice *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->caps;
}
void network_device_set_driver_support_level (NetworkDevice *dev, NMDriverSupportLevel level)
void network_device_set_capabilities (NetworkDevice *dev, guint32 caps)
{
g_return_if_fail (dev != NULL);
dev->driver_support_level = level;
dev->caps = caps;
}
/*
......
......@@ -78,8 +78,8 @@ void network_device_set_primary_dns (NetworkDevice *dev, const char *dns);
const char * network_device_get_secondary_dns (NetworkDevice *dev);
void network_device_set_secondary_dns (NetworkDevice *dev, const char *dns);
NMDriverSupportLevel network_device_get_driver_support_level (NetworkDevice *dev);
void network_device_set_driver_support_level (NetworkDevice *dev, NMDriverSupportLevel level);
guint32 network_device_get_capabilities (NetworkDevice *dev);
void network_device_set_capabilities (NetworkDevice *dev, guint32 caps);
const char * network_device_get_iface (NetworkDevice *dev);
......
......@@ -106,6 +106,11 @@ static GtkTreeModel *create_wireless_adapter_model (NMWirelessApplet *applet)
NetworkDevice *dev = (NetworkDevice *)(element->data);
g_assert (dev);
/* Ignore unsupported devices */
if (!(network_device_get_capabilities (dev) & NM_DEVICE_CAP_NM_SUPPORTED))
continue;
if (network_device_is_wireless (dev))
{
GtkTreeIter iter;
......@@ -260,6 +265,11 @@ static GtkDialog *nmwa_other_network_dialog_init (GladeXML *xml, NMWirelessApple
NetworkDevice *dev = (NetworkDevice *)(element->data);
g_assert (dev);
/* Ignore unsupported devices */
if (!(network_device_get_capabilities (dev) & NM_DEVICE_CAP_NM_SUPPORTED))
continue;
if (network_device_is_wireless (dev))
{
if (!*def_dev)
......
......@@ -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;
}
......@@ -258,6 +292,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
*
......@@ -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;
......@@ -535,6 +584,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