diff options
author | Dan Williams <dcbw@redhat.com> | 2011-03-10 22:27:10 -0600 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2011-03-10 22:27:10 -0600 |
commit | 3320764e1e3eb6e7ffa845c1181aecec301623a8 (patch) | |
tree | f2e4310db7ac1df29d906041501c64f9de6b2383 | |
parent | fbf118e58e47c41d63910dbe979325eb6d31e49f (diff) | |
download | NetworkManager-3320764e1e3eb6e7ffa845c1181aecec301623a8.tar.gz |
libnm-glib: add nm_device_filter_connections()
-rw-r--r-- | libnm-glib/libnm-glib.ver | 1 | ||||
-rw-r--r-- | libnm-glib/nm-device-bt.c | 87 | ||||
-rw-r--r-- | libnm-glib/nm-device-ethernet.c | 69 | ||||
-rw-r--r-- | libnm-glib/nm-device-modem.c | 55 | ||||
-rw-r--r-- | libnm-glib/nm-device-wifi.c | 98 | ||||
-rw-r--r-- | libnm-glib/nm-device-wimax.c | 49 | ||||
-rw-r--r-- | libnm-glib/nm-device.c | 27 | ||||
-rw-r--r-- | libnm-glib/nm-device.h | 6 |
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 */ |