summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2011-03-10 22:27:10 -0600
committerDan Williams <dcbw@redhat.com>2011-03-10 22:27:10 -0600
commit3320764e1e3eb6e7ffa845c1181aecec301623a8 (patch)
treef2e4310db7ac1df29d906041501c64f9de6b2383
parentfbf118e58e47c41d63910dbe979325eb6d31e49f (diff)
downloadNetworkManager-3320764e1e3eb6e7ffa845c1181aecec301623a8.tar.gz
libnm-glib: add nm_device_filter_connections()
-rw-r--r--libnm-glib/libnm-glib.ver1
-rw-r--r--libnm-glib/nm-device-bt.c87
-rw-r--r--libnm-glib/nm-device-ethernet.c69
-rw-r--r--libnm-glib/nm-device-modem.c55
-rw-r--r--libnm-glib/nm-device-wifi.c98
-rw-r--r--libnm-glib/nm-device-wimax.c49
-rw-r--r--libnm-glib/nm-device.c27
-rw-r--r--libnm-glib/nm-device.h6
8 files changed, 380 insertions, 12 deletions
diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver
index 56445a1474..ef37364dc0 100644
--- a/libnm-glib/libnm-glib.ver
+++ b/libnm-glib/libnm-glib.ver
@@ -68,6 +68,7 @@ global:
nm_device_ethernet_get_speed;
nm_device_ethernet_get_type;
nm_device_ethernet_new;
+ nm_device_filter_connections;
nm_device_get_capabilities;
nm_device_get_dhcp4_config;
nm_device_get_dhcp6_config;
diff --git a/libnm-glib/nm-device-bt.c b/libnm-glib/nm-device-bt.c
index fcad9d5b6c..1209f61aaf 100644
--- a/libnm-glib/nm-device-bt.c
+++ b/libnm-glib/nm-device-bt.c
@@ -21,6 +21,13 @@
* Copyright (C) 2007 - 2011 Red Hat, Inc.
*/
+#include <config.h>
+#include <string.h>
+#include <netinet/ether.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-bluetooth.h>
+
#include "nm-device-bt.h"
#include "nm-device-private.h"
#include "nm-object-private.h"
@@ -156,6 +163,78 @@ nm_device_bt_get_capabilities (NMDeviceBt *device)
return priv->bt_capabilities;
}
+static NMBluetoothCapabilities
+get_connection_bt_type (NMConnection *connection)
+{
+ NMSettingBluetooth *s_bt;
+ const char *bt_type;
+
+ s_bt = (NMSettingBluetooth *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH);
+ if (!s_bt)
+ return NM_BT_CAPABILITY_NONE;
+
+ bt_type = nm_setting_bluetooth_get_connection_type (s_bt);
+ g_assert (bt_type);
+
+ if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN))
+ return NM_BT_CAPABILITY_DUN;
+ else if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU))
+ return NM_BT_CAPABILITY_NAP;
+
+ return NM_BT_CAPABILITY_NONE;
+}
+
+static GSList *
+filter_connections (NMDevice *device, const GSList *connections)
+{
+ GSList *filtered = NULL;
+ const GSList *iter;
+
+ for (iter = connections; iter; iter = g_slist_next (iter)) {
+ NMConnection *candidate = NM_CONNECTION (iter->data);
+ NMSettingConnection *s_con;
+ NMSettingBluetooth *s_bt;
+ const char *ctype;
+ const GByteArray *mac;
+ const char *hw_str;
+ struct ether_addr *hw_mac;
+ NMBluetoothCapabilities dev_caps;
+ NMBluetoothCapabilities bt_type;
+
+ s_con = (NMSettingConnection *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_CONNECTION);
+ g_assert (s_con);
+
+ ctype = nm_setting_connection_get_connection_type (s_con);
+ if (strcmp (ctype, NM_SETTING_BLUETOOTH_SETTING_NAME) != 0)
+ continue;
+
+ s_bt = (NMSettingBluetooth *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_BLUETOOTH);
+ if (!s_bt)
+ continue;
+
+ /* Check BT address */
+ hw_str = nm_device_bt_get_hw_address (NM_DEVICE_BT (device));
+ if (hw_str) {
+ hw_mac = ether_aton (hw_str);
+ mac = nm_setting_bluetooth_get_bdaddr (s_bt);
+ if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN))
+ continue;
+ }
+
+ dev_caps = nm_device_bt_get_capabilities (NM_DEVICE_BT (device));
+ bt_type = get_connection_bt_type (candidate);
+ if (!(bt_type & dev_caps))
+ continue;
+
+ /* Connection applies to this device */
+ filtered = g_slist_prepend (filtered, candidate);
+ }
+
+ return g_slist_reverse (filtered);
+}
+
+/************************************************************/
+
static void
nm_device_bt_init (NMDeviceBt *device)
{
@@ -253,17 +332,19 @@ get_property (GObject *object,
}
static void
-nm_device_bt_class_init (NMDeviceBtClass *device_class)
+nm_device_bt_class_init (NMDeviceBtClass *bt_class)
{
- GObjectClass *object_class = G_OBJECT_CLASS (device_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (bt_class);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (bt_class);
- g_type_class_add_private (device_class, sizeof (NMDeviceBtPrivate));
+ g_type_class_add_private (bt_class, sizeof (NMDeviceBtPrivate));
/* virtual methods */
object_class->constructor = constructor;
object_class->dispose = dispose;
object_class->finalize = finalize;
object_class->get_property = get_property;
+ device_class->filter_connections = filter_connections;
/* properties */
diff --git a/libnm-glib/nm-device-ethernet.c b/libnm-glib/nm-device-ethernet.c
index e7a1fe2504..6584a3f96c 100644
--- a/libnm-glib/nm-device-ethernet.c
+++ b/libnm-glib/nm-device-ethernet.c
@@ -21,6 +21,14 @@
* Copyright (C) 2007 - 2011 Red Hat, Inc.
*/
+#include <config.h>
+#include <string.h>
+#include <netinet/ether.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-pppoe.h>
+
#include "nm-device-ethernet.h"
#include "nm-device-private.h"
#include "nm-object-private.h"
@@ -186,6 +194,59 @@ nm_device_ethernet_get_carrier (NMDeviceEthernet *device)
return priv->carrier;
}
+static GSList *
+filter_connections (NMDevice *device, const GSList *connections)
+{
+ GSList *filtered = NULL;
+ const GSList *iter;
+
+ for (iter = connections; iter; iter = g_slist_next (iter)) {
+ NMConnection *candidate = NM_CONNECTION (iter->data);
+ NMSettingConnection *s_con;
+ NMSettingWired *s_wired;
+ const char *ctype;
+ gboolean is_pppoe = FALSE;
+
+ s_con = (NMSettingConnection *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_CONNECTION);
+ g_assert (s_con);
+
+ ctype = nm_setting_connection_get_connection_type (s_con);
+ if (!strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME))
+ is_pppoe = TRUE;
+ else if (strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME) != 0)
+ continue;
+
+ s_wired = (NMSettingWired *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_WIRED);
+ /* Wired setting optional for PPPoE */
+ if (!is_pppoe && !s_wired)
+ continue;
+
+ if (s_wired) {
+ const GByteArray *mac;
+ const char *perm_str;
+ struct ether_addr *perm_mac;
+
+ /* FIXME: filter using s390 subchannels when they are exported over the bus */
+
+ /* Check MAC address */
+ perm_str = nm_device_ethernet_get_permanent_hw_address (NM_DEVICE_ETHERNET (device));
+ if (perm_str) {
+ perm_mac = ether_aton (perm_str);
+ mac = nm_setting_wired_get_mac_address (s_wired);
+ if (mac && perm_mac && memcmp (mac->data, perm_mac->ether_addr_octet, ETH_ALEN))
+ continue;
+ }
+ }
+
+ /* Connection applies to this device */
+ filtered = g_slist_prepend (filtered, candidate);
+ }
+
+ return g_slist_reverse (filtered);
+}
+
+/***********************************************************/
+
static void
nm_device_ethernet_init (NMDeviceEthernet *device)
{
@@ -298,17 +359,19 @@ get_property (GObject *object,
}
static void
-nm_device_ethernet_class_init (NMDeviceEthernetClass *device_class)
+nm_device_ethernet_class_init (NMDeviceEthernetClass *eth_class)
{
- GObjectClass *object_class = G_OBJECT_CLASS (device_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (eth_class);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (eth_class);
- g_type_class_add_private (device_class, sizeof (NMDeviceEthernetPrivate));
+ g_type_class_add_private (eth_class, sizeof (NMDeviceEthernetPrivate));
/* virtual methods */
object_class->constructor = constructor;
object_class->dispose = dispose;
object_class->finalize = finalize;
object_class->get_property = get_property;
+ device_class->filter_connections = filter_connections;
/* properties */
diff --git a/libnm-glib/nm-device-modem.c b/libnm-glib/nm-device-modem.c
index a871e8ff1e..fba0b003a1 100644
--- a/libnm-glib/nm-device-modem.c
+++ b/libnm-glib/nm-device-modem.c
@@ -21,6 +21,13 @@
* Copyright (C) 2008 Novell, Inc.
*/
+#include <config.h>
+#include <string.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-gsm.h>
+#include <nm-setting-cdma.h>
+
#include "nm-device-modem.h"
#include "nm-device-private.h"
#include "nm-object-private.h"
@@ -110,6 +117,46 @@ nm_device_modem_get_current_capabilities (NMDeviceModem *self)
return priv->current_caps;
}
+static GSList *
+filter_connections (NMDevice *device, const GSList *connections)
+{
+ GSList *filtered = NULL;
+ const GSList *iter;
+
+ for (iter = connections; iter; iter = g_slist_next (iter)) {
+ NMConnection *candidate = NM_CONNECTION (iter->data);
+ NMSettingConnection *s_con;
+ NMSettingGsm *s_gsm;
+ NMSettingCdma *s_cdma;
+ const char *ctype;
+ NMDeviceModemCapabilities current_caps;
+
+ s_con = (NMSettingConnection *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_CONNECTION);
+ g_assert (s_con);
+
+ ctype = nm_setting_connection_get_connection_type (s_con);
+ if ( strcmp (ctype, NM_SETTING_GSM_SETTING_NAME) != 0
+ && strcmp (ctype, NM_SETTING_CDMA_SETTING_NAME) != 0)
+ continue;
+
+ s_gsm = (NMSettingGsm *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_GSM);
+ s_cdma = (NMSettingCdma *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_CDMA);
+ if (!s_cdma && !s_gsm)
+ continue;
+
+ current_caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device));
+ if ( (s_gsm && (current_caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS))
+ || (s_cdma && (current_caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO))) {
+ /* Connection applies to this device */
+ filtered = g_slist_prepend (filtered, candidate);
+ }
+ }
+
+ return g_slist_reverse (filtered);
+}
+
+/*******************************************************************/
+
static void
register_for_property_changed (NMDeviceModem *device)
{
@@ -194,16 +241,18 @@ dispose (GObject *object)
}
static void
-nm_device_modem_class_init (NMDeviceModemClass *device_class)
+nm_device_modem_class_init (NMDeviceModemClass *modem_class)
{
- GObjectClass *object_class = G_OBJECT_CLASS (device_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (modem_class);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (modem_class);
- g_type_class_add_private (device_class, sizeof (NMDeviceModemPrivate));
+ g_type_class_add_private (modem_class, sizeof (NMDeviceModemPrivate));
/* virtual methods */
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->dispose = dispose;
+ device_class->filter_connections = filter_connections;
/**
* NMDeviceModem:modem-capabilities:
diff --git a/libnm-glib/nm-device-wifi.c b/libnm-glib/nm-device-wifi.c
index f8a891c1e7..c0a366dd93 100644
--- a/libnm-glib/nm-device-wifi.c
+++ b/libnm-glib/nm-device-wifi.c
@@ -21,7 +21,13 @@
* Copyright (C) 2007 - 2011 Red Hat, Inc.
*/
+#include <config.h>
#include <string.h>
+#include <netinet/ether.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-wireless.h>
+#include <nm-setting-wireless-security.h>
#include "nm-device-wifi.h"
#include "nm-device-private.h"
@@ -477,6 +483,90 @@ _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device,
clean_up_aps (device, TRUE);
}
+#define WPA_CAPS (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | \
+ NM_WIFI_DEVICE_CAP_CIPHER_CCMP | \
+ NM_WIFI_DEVICE_CAP_WPA | \
+ NM_WIFI_DEVICE_CAP_RSN)
+
+#define RSN_CAPS (NM_WIFI_DEVICE_CAP_CIPHER_CCMP | NM_WIFI_DEVICE_CAP_RSN)
+
+static gboolean
+has_proto (NMSettingWirelessSecurity *s_wsec, const char *proto)
+{
+ int i;
+
+ for (i = 0; i < nm_setting_wireless_security_get_num_protos (s_wsec); i++) {
+ if (g_strcmp0 (proto, nm_setting_wireless_security_get_proto (s_wsec, i)) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static GSList *
+filter_connections (NMDevice *device, const GSList *connections)
+{
+ GSList *filtered = NULL;
+ const GSList *iter;
+
+ for (iter = connections; iter; iter = g_slist_next (iter)) {
+ NMConnection *candidate = NM_CONNECTION (iter->data);
+ NMSettingConnection *s_con;
+ NMSettingWireless *s_wifi;
+ NMSettingWirelessSecurity *s_wsec;
+ const char *ctype;
+ const GByteArray *mac;
+ const char *hw_str;
+ struct ether_addr *hw_mac;
+ NMDeviceWifiCapabilities wifi_caps;
+ const char *key_mgmt;
+
+ s_con = (NMSettingConnection *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_CONNECTION);
+ g_assert (s_con);
+
+ ctype = nm_setting_connection_get_connection_type (s_con);
+ if (strcmp (ctype, NM_SETTING_WIRELESS_SETTING_NAME) != 0)
+ continue;
+
+ s_wifi = (NMSettingWireless *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_WIRELESS);
+ if (!s_wifi)
+ continue;
+
+ /* Check MAC address */
+ hw_str = nm_device_wifi_get_permanent_hw_address (NM_DEVICE_WIFI (device));
+ if (hw_str) {
+ hw_mac = ether_aton (hw_str);
+ mac = nm_setting_wireless_get_mac_address (s_wifi);
+ if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN))
+ continue;
+ }
+
+ /* Check device capabilities; we assume all devices can do WEP at least */
+ wifi_caps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (device));
+
+ s_wsec = (NMSettingWirelessSecurity *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_WIRELESS_SECURITY);
+ if (s_wsec) {
+ /* Connection has security, verify it against the device's capabilities */
+ key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
+ if ( !g_strcmp0 (key_mgmt, "wpa-none")
+ || !g_strcmp0 (key_mgmt, "wpa-psk")
+ || !g_strcmp0 (key_mgmt, "wpa-eap")) {
+
+ /* Is device only WEP capable? */
+ if (!(wifi_caps & WPA_CAPS))
+ continue;
+
+ /* Make sure WPA2/RSN-only connections don't get chosen for WPA-only cards */
+ if (has_proto (s_wsec, "rsn") && !has_proto (s_wsec, "wpa") && !(wifi_caps & RSN_CAPS))
+ continue;
+ }
+ }
+
+ /* Connection applies to this device */
+ filtered = g_slist_prepend (filtered, candidate);
+ }
+
+ return g_slist_reverse (filtered);
+}
/**************************************************************/
@@ -683,17 +773,19 @@ finalize (GObject *object)
}
static void
-nm_device_wifi_class_init (NMDeviceWifiClass *device_class)
+nm_device_wifi_class_init (NMDeviceWifiClass *wifi_class)
{
- GObjectClass *object_class = G_OBJECT_CLASS (device_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (wifi_class);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (wifi_class);
- g_type_class_add_private (device_class, sizeof (NMDeviceWifiPrivate));
+ g_type_class_add_private (wifi_class, sizeof (NMDeviceWifiPrivate));
/* virtual methods */
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
+ device_class->filter_connections = filter_connections;
/* properties */
diff --git a/libnm-glib/nm-device-wimax.c b/libnm-glib/nm-device-wimax.c
index 6c9bd6cfd2..fdd34c2a52 100644
--- a/libnm-glib/nm-device-wimax.c
+++ b/libnm-glib/nm-device-wimax.c
@@ -21,7 +21,12 @@
* Copyright (C) 2009 Novell, Inc.
*/
+#include <config.h>
#include <string.h>
+#include <netinet/ether.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-wimax.h>
#include "nm-device-wimax.h"
#include "nm-object-private.h"
@@ -474,6 +479,48 @@ nm_device_wimax_get_bsid (NMDeviceWimax *self)
return priv->bsid;
}
+static GSList *
+filter_connections (NMDevice *device, const GSList *connections)
+{
+ GSList *filtered = NULL;
+ const GSList *iter;
+
+ for (iter = connections; iter; iter = g_slist_next (iter)) {
+ NMConnection *candidate = NM_CONNECTION (iter->data);
+ NMSettingConnection *s_con;
+ NMSettingWimax *s_wimax;
+ const char *ctype;
+ const GByteArray *mac;
+ const char *hw_str;
+ struct ether_addr *hw_mac;
+
+ s_con = (NMSettingConnection *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_CONNECTION);
+ g_assert (s_con);
+
+ ctype = nm_setting_connection_get_connection_type (s_con);
+ if (strcmp (ctype, NM_SETTING_WIMAX_SETTING_NAME) != 0)
+ continue;
+
+ s_wimax = (NMSettingWimax *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_WIMAX);
+ if (!s_wimax)
+ continue;
+
+ /* Check MAC address */
+ hw_str = nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device));
+ if (hw_str) {
+ hw_mac = ether_aton (hw_str);
+ mac = nm_setting_wimax_get_mac_address (s_wimax);
+ if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN))
+ continue;
+ }
+
+ /* Connection applies to this device */
+ filtered = g_slist_prepend (filtered, candidate);
+ }
+
+ return g_slist_reverse (filtered);
+}
+
/**************************************************************/
static void
@@ -710,6 +757,7 @@ static void
nm_device_wimax_class_init (NMDeviceWimaxClass *wimax_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (wimax_class);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (wimax_class);
g_type_class_add_private (wimax_class, sizeof (NMDeviceWimaxPrivate));
@@ -717,6 +765,7 @@ nm_device_wimax_class_init (NMDeviceWimaxClass *wimax_class)
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->dispose = dispose;
+ device_class->filter_connections = filter_connections;
/* properties */
diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c
index bbc5416c90..3d640cee34 100644
--- a/libnm-glib/nm-device.c
+++ b/libnm-glib/nm-device.c
@@ -1395,3 +1395,30 @@ nm_device_disconnect (NMDevice *device,
info);
}
+/**
+ * nm_device_filter_connections:
+ * @device: an #NMDevice to filter connections for
+ * @connections: a list of #NMConnection objects to filter
+ *
+ * Filters a given list of connections for a given #NMDevice object and return
+ * connections which may be activated with the device. For example if @device
+ * is a WiFi device that supports only WEP encryption, the returned list will
+ * contain any WiFi connections in @connections that allow connection to
+ * unencrypted or WEP-enabled SSIDs. The returned list will not contain
+ * Ethernet, Bluetooth, WiFi WPA connections, or any other connection that is
+ * incompatible with the device.
+ *
+ * Returns: (transfer container) (element-type NetworkManager.Connection): a
+ * list of #NMConnection objects that could be activated with the given @device.
+ * The elements of the list are owned by their creator and should not be freed
+ * by the caller, but the returned list itself is owned by the caller and should
+ * be freed with g_slist_free() when it is no longer required.
+ **/
+GSList *
+nm_device_filter_connections (NMDevice *device, const GSList *connections)
+{
+ if (NM_DEVICE_GET_CLASS (device)->filter_connections)
+ return NM_DEVICE_GET_CLASS (device)->filter_connections (device, connections);
+ return NULL;
+}
+
diff --git a/libnm-glib/nm-device.h b/libnm-glib/nm-device.h
index 0c330e0b1a..0b641587ac 100644
--- a/libnm-glib/nm-device.h
+++ b/libnm-glib/nm-device.h
@@ -73,6 +73,9 @@ typedef struct {
NMDeviceState old_state,
NMDeviceStateReason reason);
+ GSList * (*filter_connections) (NMDevice *device,
+ const GSList *connections);
+
/* Padding for future expansion */
void (*_reserved1) (void);
void (*_reserved2) (void);
@@ -108,6 +111,9 @@ void nm_device_disconnect (NMDevice *device,
NMDeviceDeactivateFn callback,
gpointer user_data);
+GSList * nm_device_filter_connections (NMDevice *device,
+ const GSList *connections);
+
G_END_DECLS
#endif /* NM_DEVICE_H */