From f4540f0412ec4293eb0f18c7dacd86427af2f230 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 27 Jun 2007 16:18:52 +0000 Subject: [PATCH] 2007-06-27 Dan Williams * Make SSIDs GByteArrays everywhere * Rename "essid" -> "ssid" everywhere that's appropriate * Refcount activation_ap member of the 802.11 wireless device class git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2620 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 6 + introspection/nm-access-point.xml | 2 +- libnm-glib/libnm-glib-test.c | 55 +++- libnm-glib/nm-access-point.c | 6 +- libnm-glib/nm-access-point.h | 16 +- libnm-glib/nm-object.c | 24 ++ libnm-glib/nm-object.h | 4 + src/NetworkManagerAP.c | 127 +++++----- src/NetworkManagerAP.h | 10 +- src/NetworkManagerAPList.c | 92 +++---- src/NetworkManagerAPList.h | 10 +- src/NetworkManagerPolicy.c | 67 +++-- src/NetworkManagerUtils.c | 54 ++++ src/NetworkManagerUtils.h | 5 + src/backends/NetworkManagerSuSE.c | 12 +- src/nm-dbus-nmi.c | 66 +++-- src/nm-device-802-11-wireless.c | 401 +++++++++++++++++------------- src/nm-device-802-11-wireless.h | 10 +- src/nm-device.c | 2 +- test/nm-tool.c | 50 +++- utils/nm-utils.c | 86 +++---- utils/nm-utils.h | 2 +- 22 files changed, 685 insertions(+), 422 deletions(-) diff --git a/ChangeLog b/ChangeLog index 69cc0e0b59..48866ed642 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2007-06-27 Dan Williams + + * Make SSIDs GByteArrays everywhere + * Rename "essid" -> "ssid" everywhere that's appropriate + * Refcount activation_ap member of the 802.11 wireless device class + 2007-06-27 Tambet Ingo * libnm-glib/nm-object.[ch]: Add these to the SVN, oops. diff --git a/introspection/nm-access-point.xml b/introspection/nm-access-point.xml index aee3eee4e3..a01f77d64b 100644 --- a/introspection/nm-access-point.xml +++ b/introspection/nm-access-point.xml @@ -4,7 +4,7 @@ - + diff --git a/libnm-glib/libnm-glib-test.c b/libnm-glib/libnm-glib-test.c index c0b08acb1e..5740b6321b 100644 --- a/libnm-glib/libnm-glib-test.c +++ b/libnm-glib/libnm-glib-test.c @@ -3,12 +3,57 @@ #include #include #include +#include +#include #include "nm-client.h" #include "nm-device.h" #include "nm-device-802-3-ethernet.h" #include "nm-device-802-11-wireless.h" + +/* Shamelessly ripped from the Linux kernel ieee80211 stack */ +static gboolean +nm_utils_is_empty_ssid (const char * ssid, int len) +{ + /* Single white space is for Linksys APs */ + if (len == 1 && ssid[0] == ' ') + return TRUE; + + /* Otherwise, if the entire ssid is 0, we assume it is hidden */ + while (len--) { + if (ssid[len] != '\0') + return FALSE; + } + return TRUE; +} + +static const char * +nm_utils_escape_ssid (const char * ssid, guint32 len) +{ + static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; + const char *s = ssid; + char *d = escaped; + + if (nm_utils_is_empty_ssid (ssid, len)) { + memcpy (escaped, "", sizeof ("")); + return escaped; + } + + len = MIN (len, (guint32) IW_ESSID_MAX_SIZE); + while (len--) { + if (*s == '\0') { + *d++ = '\\'; + *d++ = '0'; + s++; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return escaped; +} + static gboolean test_wireless_enabled (NMClient *client) { @@ -120,11 +165,13 @@ dump_ip4_config (NMIP4Config *cfg) static void dump_access_point (NMAccessPoint *ap) { - char *str; + GByteArray * ssid; + char * str; - str = nm_access_point_get_essid (ap); - g_print ("\tEssid: %s\n", str); - g_free (str); + ssid = nm_access_point_get_ssid (ap); + g_print ("\tSsid: %s\n", + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); + g_byte_array_free (ssid, TRUE); str = nm_access_point_get_hw_address (ap); g_print ("\tMAC Address: %s\n", str); diff --git a/libnm-glib/nm-access-point.c b/libnm-glib/nm-access-point.c index 7a1024c90a..926641b03e 100644 --- a/libnm-glib/nm-access-point.c +++ b/libnm-glib/nm-access-point.c @@ -117,12 +117,12 @@ nm_access_point_is_encrypted (NMAccessPoint *ap) return nm_object_get_boolean_property (NM_OBJECT (ap), NM_DBUS_INTERFACE_ACCESS_POINT, "Encrypted"); } -char * -nm_access_point_get_essid (NMAccessPoint *ap) +GByteArray * +nm_access_point_get_ssid (NMAccessPoint *ap) { g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NULL); - return nm_object_get_string_property (NM_OBJECT (ap), NM_DBUS_INTERFACE_ACCESS_POINT, "Essid"); + return nm_object_get_byte_array_property (NM_OBJECT (ap), NM_DBUS_INTERFACE_ACCESS_POINT, "Ssid"); } gdouble diff --git a/libnm-glib/nm-access-point.h b/libnm-glib/nm-access-point.h index 362ad15681..0ce4a040e8 100644 --- a/libnm-glib/nm-access-point.h +++ b/libnm-glib/nm-access-point.h @@ -27,13 +27,13 @@ GType nm_access_point_get_type (void); NMAccessPoint *nm_access_point_new (DBusGConnection *connection, const char *path); -guint32 nm_access_point_get_capabilities (NMAccessPoint *ap); -gboolean nm_access_point_is_encrypted (NMAccessPoint *ap); -char *nm_access_point_get_essid (NMAccessPoint *ap); -gdouble nm_access_point_get_frequency (NMAccessPoint *ap); -char *nm_access_point_get_hw_address (NMAccessPoint *ap); -int nm_access_point_get_mode (NMAccessPoint *ap); -guint32 nm_access_point_get_rate (NMAccessPoint *ap); -int nm_access_point_get_strength (NMAccessPoint *ap); +guint32 nm_access_point_get_capabilities (NMAccessPoint *ap); +gboolean nm_access_point_is_encrypted (NMAccessPoint *ap); +GByteArray * nm_access_point_get_ssid (NMAccessPoint *ap); +gdouble nm_access_point_get_frequency (NMAccessPoint *ap); +char * nm_access_point_get_hw_address (NMAccessPoint *ap); +int nm_access_point_get_mode (NMAccessPoint *ap); +guint32 nm_access_point_get_rate (NMAccessPoint *ap); +int nm_access_point_get_strength (NMAccessPoint *ap); #endif /* NM_ACCESS_POINT_H */ diff --git a/libnm-glib/nm-object.c b/libnm-glib/nm-object.c index 7df34b2d34..03b77bd242 100644 --- a/libnm-glib/nm-object.c +++ b/libnm-glib/nm-object.c @@ -301,3 +301,27 @@ nm_object_get_double_property (NMObject *object, return d; } + +GByteArray * +nm_object_get_byte_array_property (NMObject *object, + const char *interface, + const char *prop_name) +{ + GByteArray * array = NULL; + GValue value = {0,}; + + if (nm_object_get_property (object, interface, prop_name, &value)) { + GArray * tmp = g_value_get_boxed (&value); + int i; + unsigned char byte; + + array = g_byte_array_sized_new (tmp->len); + for (i = 0; i < tmp->len; i++) { + byte = g_array_index (tmp, unsigned char, i); + g_byte_array_append (array, &byte, 1); + } + } + + return array; +} + diff --git a/libnm-glib/nm-object.h b/libnm-glib/nm-object.h index f20d75f215..8369538265 100644 --- a/libnm-glib/nm-object.h +++ b/libnm-glib/nm-object.h @@ -64,5 +64,9 @@ gdouble nm_object_get_double_property (NMObject *object, const char *interface, const char *prop_name); +GByteArray *nm_object_get_byte_array_property (NMObject *object, + const char *interface, + const char *prop_name); + #endif /* NM_OBJECT_H */ diff --git a/src/NetworkManagerAP.c b/src/NetworkManagerAP.c index 2a39256cdb..403ddae88c 100644 --- a/src/NetworkManagerAP.c +++ b/src/NetworkManagerAP.c @@ -30,7 +30,7 @@ #include "nm-access-point-glue.h" /* This is a controlled list. Want to add to it? Stop. Ask first. */ -static const char * default_essid_list[] = +static const char * default_ssid_list[] = { "linksys", "linksys-a", @@ -49,8 +49,7 @@ typedef struct char *dbus_path; /* Scanned or cached values */ - char * essid; - char * orig_essid; + GByteArray * ssid; struct ether_addr address; int mode; /* from IW_MODE_* in wireless.h */ gint8 strength; @@ -93,16 +92,16 @@ enum { PROP_0, PROP_CAPABILITIES, PROP_ENCRYPTED, - PROP_ESSID, + PROP_SSID, PROP_FREQUENCY, PROP_HW_ADDRESS, PROP_MODE, PROP_RATE, PROP_STRENGTH, - LAST_PROP }; + static void nm_ap_init (NMAccessPoint *ap) { @@ -121,8 +120,7 @@ finalize (GObject *object) NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); g_free (priv->dbus_path); - g_free (priv->essid); - g_free (priv->orig_essid); + g_byte_array_free (priv->ssid, TRUE); g_slist_foreach (priv->user_addresses, (GFunc)g_free, NULL); g_slist_free (priv->user_addresses); @@ -137,28 +135,28 @@ set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); - const char *essid; + GArray * ssid; int mode; switch (prop_id) { case PROP_CAPABILITIES: priv->capabilities = g_value_get_uint (value); break; - case PROP_ESSID: - essid = g_value_get_string (value); - - if (priv->essid) { - g_free (priv->essid); - g_free (priv->orig_essid); - priv->essid = NULL; - priv->orig_essid = NULL; + case PROP_SSID: + ssid = g_value_get_boxed (value); + if (priv->ssid) { + g_byte_array_free (priv->ssid, TRUE); + priv->ssid = NULL; } - - if (essid) { - priv->orig_essid = g_strdup (essid); - priv->essid = nm_utils_essid_to_utf8 (essid); + if (ssid) { + int i; + unsigned char byte; + priv->ssid = g_byte_array_sized_new (ssid->len); + for (i = 0; i < ssid->len; i++) { + byte = g_array_index (ssid, unsigned char, i); + g_byte_array_append (priv->ssid, &byte, 1); + } } - break; case PROP_FREQUENCY: priv->freq = g_value_get_double (value); @@ -189,6 +187,8 @@ get_property (GObject *object, guint prop_id, { NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); char hw_addr_buf[20]; + GArray * ssid; + int i; switch (prop_id) { case PROP_CAPABILITIES: @@ -197,8 +197,12 @@ get_property (GObject *object, guint prop_id, case PROP_ENCRYPTED: g_value_set_boolean (value, !(priv->capabilities & NM_802_11_CAP_PROTO_NONE)); break; - case PROP_ESSID: - g_value_set_string (value, priv->essid); + case PROP_SSID: + ssid = g_array_sized_new (FALSE, TRUE, sizeof (unsigned char), priv->ssid->len); + for (i = 0; i < priv->ssid->len; i++) + g_array_append_val (ssid, priv->ssid->data[i]); + g_value_set_boxed (value, ssid); + g_array_free (ssid, TRUE); break; case PROP_FREQUENCY: g_value_set_double (value, priv->freq); @@ -273,12 +277,12 @@ nm_ap_class_init (NMAccessPointClass *ap_class) G_PARAM_READABLE)); g_object_class_install_property - (object_class, PROP_ESSID, - g_param_spec_string (NM_AP_ESSID, - "ESSID", - "ESSID", - NULL, - G_PARAM_READWRITE)); + (object_class, PROP_SSID, + g_param_spec_boxed (NM_AP_SSID, + "SSID", + "SSID", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_FREQUENCY, @@ -381,10 +385,11 @@ nm_ap_new_from_ap (NMAccessPoint *src_ap) src_priv = NM_AP_GET_PRIVATE (src_ap); new_priv = NM_AP_GET_PRIVATE (new_ap); - if (src_priv->essid && (strlen (src_priv->essid) > 0)) - { - new_priv->essid = g_strdup (src_priv->essid); - new_priv->orig_essid = g_strdup (src_priv->orig_essid); + if (src_priv->ssid) { + new_priv->ssid = g_byte_array_sized_new (src_priv->ssid->len); + g_byte_array_append (new_priv->ssid, + src_priv->ssid->data, + src_priv->ssid->len); } memcpy (&new_priv->address, &src_priv->address, sizeof (struct ether_addr)); new_priv->mode = src_priv->mode; @@ -416,21 +421,18 @@ foreach_property_cb (gpointer key, gpointer value, gpointer user_data) GArray *array = g_value_get_boxed (variant); if (!strcmp (key, "ssid")) { - char ssid[33]; - int ssid_len = sizeof (ssid); + guint32 len = MIN (IW_ESSID_MAX_SIZE, array->len); + GByteArray * ssid; - if (array->len < sizeof (ssid)) - ssid_len = array->len; - if (ssid_len <= 0) - return; /* Stupid ieee80211 layer uses */ - if (((ssid_len == 8) || (ssid_len == 9)) + if (((len == 8) || (len == 9)) && (memcmp (array->data, "", 8) == 0)) return; - memset (&ssid, 0, sizeof (ssid)); - memcpy (&ssid, array->data, ssid_len); - ssid[32] = '\0'; - nm_ap_set_essid (ap, ssid); + + ssid = g_byte_array_sized_new (len); + g_byte_array_append (ssid, array->data, len); + nm_ap_set_ssid (ap, ssid); + g_byte_array_free (ssid, TRUE); } else if (!strcmp (key, "bssid")) { struct ether_addr addr; @@ -496,7 +498,7 @@ nm_ap_new_from_properties (GHashTable *properties) g_get_current_time (&cur_time); nm_ap_set_last_seen (ap, cur_time.tv_sec); - if (!nm_ap_get_essid (ap)) + if (!nm_ap_get_ssid (ap)) nm_ap_set_broadcast (ap, FALSE); return ap; @@ -542,28 +544,21 @@ void nm_ap_set_timestamp_via_timestamp (NMAccessPoint *ap, const GTimeVal *times } /* - * Get/set functions for essid + * Get/set functions for ssid * */ -const char * nm_ap_get_essid (const NMAccessPoint *ap) +const GByteArray * nm_ap_get_ssid (const NMAccessPoint *ap) { g_return_val_if_fail (NM_IS_AP (ap), NULL); - return NM_AP_GET_PRIVATE (ap)->essid; + return NM_AP_GET_PRIVATE (ap)->ssid; } -const char * nm_ap_get_orig_essid (const NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NULL); - - return NM_AP_GET_PRIVATE (ap)->orig_essid; -} - -void nm_ap_set_essid (NMAccessPoint *ap, const char * essid) +void nm_ap_set_ssid (NMAccessPoint *ap, const GByteArray * ssid) { g_return_if_fail (NM_IS_AP (ap)); - g_object_set (ap, NM_AP_ESSID, essid, NULL); + g_object_set (ap, NM_AP_SSID, ssid, NULL); } @@ -926,18 +921,20 @@ void nm_ap_set_user_addresses (NMAccessPoint *ap, GSList *list) } -gboolean nm_ap_has_manufacturer_default_essid (NMAccessPoint *ap) +gboolean nm_ap_has_manufacturer_default_ssid (NMAccessPoint *ap) { - const char **default_essid = default_essid_list; - const char *this_essid; + const char **default_ssid = default_ssid_list; + const GByteArray * this_ssid; g_return_val_if_fail (NM_IS_AP (ap), FALSE); - this_essid = NM_AP_GET_PRIVATE (ap)->essid; + this_ssid = NM_AP_GET_PRIVATE (ap)->ssid; - while (*default_essid) - { - if (!strcmp (*(default_essid++), this_essid)) - return TRUE; + while (*default_ssid) { + if (this_ssid->len == strlen (*default_ssid)) { + if (!memcmp (*default_ssid, this_ssid->data, this_ssid->len)) + return TRUE; + } + default_ssid++; } return FALSE; diff --git a/src/NetworkManagerAP.h b/src/NetworkManagerAP.h index a89af93575..73d8860e49 100644 --- a/src/NetworkManagerAP.h +++ b/src/NetworkManagerAP.h @@ -38,7 +38,7 @@ #define NM_AP_CAPABILITIES "capabilities" #define NM_AP_ENCRYPTED "encrypted" -#define NM_AP_ESSID "essid" +#define NM_AP_SSID "ssid" #define NM_AP_FREQUENCY "frequency" #define NM_AP_HW_ADDRESS "hw-address" #define NM_AP_MODE "mode" @@ -67,10 +67,8 @@ const GTimeVal * nm_ap_get_timestamp (const NMAccessPoint *ap); void nm_ap_set_timestamp (NMAccessPoint *ap, glong sec, glong usec); void nm_ap_set_timestamp_via_timestamp (NMAccessPoint *ap, const GTimeVal *timestamp); -const char * nm_ap_get_essid (const NMAccessPoint *ap); -void nm_ap_set_essid (NMAccessPoint *ap, const char *essid); -/* Get essid in original over-the-air form */ -const char * nm_ap_get_orig_essid (const NMAccessPoint *ap); +const GByteArray * nm_ap_get_ssid (const NMAccessPoint * ap); +void nm_ap_set_ssid (NMAccessPoint * ap, const GByteArray * ssid); guint32 nm_ap_get_capabilities (NMAccessPoint *ap); void nm_ap_set_capabilities (NMAccessPoint *ap, guint32 capabilities); @@ -125,6 +123,6 @@ void nm_ap_add_capabilities_for_wep (NMAccessPoint *ap); * This is not intended to return true for all APs with manufacturer defaults. It is intended to return true for * only the MOST COMMON manufacturing defaults. */ -gboolean nm_ap_has_manufacturer_default_essid (NMAccessPoint *ap); +gboolean nm_ap_has_manufacturer_default_ssid (NMAccessPoint *ap); #endif /* NM_ACCESS_POINT_H */ diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c index 55803a51d7..bb4f0f198a 100644 --- a/src/NetworkManagerAPList.c +++ b/src/NetworkManagerAPList.c @@ -158,22 +158,23 @@ void nm_ap_list_remove_ap (NMAccessPointList *list, NMAccessPoint *ap) /* - * nm_ap_list_remove_ap_by_essid + * nm_ap_list_remove_ap_by_ssid * - * Helper to remove an AP from an AP list by the AP's ESSID. + * Helper to remove an AP from an AP list by the AP's SSID. * */ -void nm_ap_list_remove_ap_by_essid (NMAccessPointList *list, const char *network) +void +nm_ap_list_remove_ap_by_ssid (NMAccessPointList *list, const GByteArray * ssid) { - GSList *elt = NULL; + GSList * elt = NULL; g_return_if_fail (list != NULL); - g_return_if_fail (network != NULL); + g_return_if_fail (ssid != NULL); for (elt = list->ap_list; elt; elt = g_slist_next (elt)) { NMAccessPoint * list_ap = (NMAccessPoint *) elt->data; - if (nm_null_safe_strcmp (nm_ap_get_essid (list_ap), network) == 0) { + if (nm_utils_same_ssid (nm_ap_get_ssid (list_ap), ssid)) { list->ap_list = g_slist_remove_link (list->ap_list, elt); g_object_unref (list_ap); g_slist_free (elt); @@ -182,10 +183,10 @@ void nm_ap_list_remove_ap_by_essid (NMAccessPointList *list, const char *network } } -/* nm_ap_list_remove_duplicate_essids +/* nm_ap_list_remove_duplicate_ssids * */ -void nm_ap_list_remove_duplicate_essids (NMAccessPointList *list) +void nm_ap_list_remove_duplicate_ssids (NMAccessPointList *list) { NMAccessPoint *removal_ap; NMAccessPoint *list_ap_max; @@ -201,12 +202,14 @@ void nm_ap_list_remove_duplicate_essids (NMAccessPointList *list) for (elt_i = list->ap_list; elt_i; elt_i = g_slist_next (elt_i)) { NMAccessPoint * list_ap_i = (NMAccessPoint *) elt_i->data; + const GByteArray * list_ap_i_ssid = nm_ap_get_ssid (list_ap_i); gboolean found = FALSE; for (elt_j = list->ap_list; elt_j < elt_i; elt_j = g_slist_next (elt_j)) { - NMAccessPoint *list_ap_j = (NMAccessPoint *) elt_j->data; + NMAccessPoint * list_ap_j = (NMAccessPoint *) elt_j->data; + const GByteArray * list_ap_j_ssid = nm_ap_get_ssid (list_ap_j); - if ((found = (nm_null_safe_strcmp (nm_ap_get_essid (list_ap_i), nm_ap_get_essid (list_ap_j)) == 0))) + if ((found = nm_utils_same_ssid (list_ap_i_ssid, list_ap_j_ssid))) break; } @@ -219,9 +222,10 @@ void nm_ap_list_remove_duplicate_essids (NMAccessPointList *list) for (elt_j = g_slist_next (elt_i); elt_j; elt_j = g_slist_next (elt_j)) { NMAccessPoint *list_ap_j = (NMAccessPoint *) elt_j->data; + const GByteArray * list_ap_j_ssid = nm_ap_get_ssid (list_ap_j); strengthj = nm_ap_get_strength (list_ap_j); - if (nm_null_safe_strcmp (nm_ap_get_essid (list_ap_i), nm_ap_get_essid (list_ap_j)) == 0) { + if (nm_utils_same_ssid (list_ap_i_ssid, list_ap_j_ssid)) { if (strengthj > max_strength) { removal_list = g_slist_append (removal_list, list_ap_max); list_ap_max = list_ap_j; @@ -242,38 +246,35 @@ void nm_ap_list_remove_duplicate_essids (NMAccessPointList *list) /* - * nm_ap_list_get_ap_by_essid + * nm_ap_list_get_ap_by_ssid * * Search through an access point list and return the access point - * that has a given essid. + * that has a given SSID. * */ -NMAccessPoint *nm_ap_list_get_ap_by_essid (NMAccessPointList *list, const char *network) +NMAccessPoint * +nm_ap_list_get_ap_by_ssid (NMAccessPointList *list, const GByteArray * ssid) { NMAccessPoint *ap; NMAccessPoint *found_ap = NULL; NMAPListIter *iter; - if (!network) - return (NULL); - - if (!list) - return (NULL); + if (!ssid || !list) + return NULL; if (!(iter = nm_ap_list_iter_new (list))) - return (NULL); + return NULL; - while ((ap = nm_ap_list_iter_next (iter))) - { - if (nm_ap_get_essid (ap) && (nm_null_safe_strcmp (nm_ap_get_essid (ap), network) == 0)) - { + while ((ap = nm_ap_list_iter_next (iter))) { + const GByteArray * ap_ssid = nm_ap_get_ssid (ap); + if (ap_ssid && nm_utils_same_ssid (ap_ssid, ssid)) { found_ap = ap; break; } } nm_ap_list_iter_free (iter); - return (found_ap); + return found_ap; } @@ -362,7 +363,7 @@ void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *sou { NMAccessPoint *src_ap = NULL; - if ((src_ap = nm_ap_list_get_ap_by_essid (source, nm_ap_get_essid (dest_ap)))) + if ((src_ap = nm_ap_list_get_ap_by_ssid (source, nm_ap_get_ssid (dest_ap)))) { nm_ap_set_invalid (dest_ap, nm_ap_get_invalid (src_ap)); nm_ap_set_security (dest_ap, nm_ap_get_security (src_ap)); @@ -374,45 +375,45 @@ void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *sou /* - * nm_ap_list_copy_one_essid_by_address + * nm_ap_list_copy_one_ssid_by_address * - * If the access point doesn't have an ESSID, search through a list of access points + * If the access point doesn't have an SSID, search through a list of access points * and find one (if any) that has the MAC address of the access point we're looking for. - * If one is found, copy the essid over to the original access point. + * If one is found, copy the SSID over to the original access point. * */ void -nm_ap_list_copy_one_essid_by_address (NMAccessPoint *ap, - NMAccessPointList *search_list) +nm_ap_list_copy_one_ssid_by_address (NMAccessPoint *ap, + NMAccessPointList *search_list) { - NMAccessPoint *found_ap; - const char *essid; + NMAccessPoint * found_ap; + const GByteArray * ssid; g_return_if_fail (ap != NULL); - /* Ignore APs that already have an ESSID */ - if (!search_list || nm_ap_get_essid (ap)) + /* Ignore APs that already have an SSID */ + if (!search_list || nm_ap_get_ssid (ap)) return; found_ap = nm_ap_list_get_ap_by_address (search_list, nm_ap_get_address (ap)); - essid = found_ap ? nm_ap_get_essid (found_ap) : NULL; + ssid = found_ap ? nm_ap_get_ssid (found_ap) : NULL; - if (essid) - nm_ap_set_essid (ap, essid); + if (ssid) + nm_ap_set_ssid (ap, ssid); } /* - * nm_ap_list_copy_essids_by_address + * nm_ap_list_copy_ssids_by_address * - * For each blank-essid access point in the destination list, try to find + * For each blank-SSID access point in the destination list, try to find * an access point in the source list that has the same MAC address, and if - * its found, copy the source access point's essid to the dest access point. + * its found, copy the source access point's SSID to the dest access point. * */ void -nm_ap_list_copy_essids_by_address (NMAccessPointList *dest, - NMAccessPointList *source) +nm_ap_list_copy_ssids_by_address (NMAccessPointList *dest, + NMAccessPointList *source) { NMAPListIter *iter; NMAccessPoint *dest_ap; @@ -424,7 +425,7 @@ nm_ap_list_copy_essids_by_address (NMAccessPointList *dest, return; while ((dest_ap = nm_ap_list_iter_next (iter))) - nm_ap_list_copy_one_essid_by_address (dest_ap, source); + nm_ap_list_copy_one_ssid_by_address (dest_ap, source); nm_ap_list_iter_free (iter); } @@ -532,6 +533,7 @@ void nm_ap_list_print_members (NMAccessPointList *list, const char *name) const struct ether_addr * eth_addr = nm_ap_get_address (ap); char addr[ETH_ALEN]; double freq = nm_ap_get_freq (ap); + const GByteArray * ssid = nm_ap_get_ssid (ap); if (security) key = nm_ap_security_get_key (security); @@ -541,7 +543,7 @@ void nm_ap_list_print_members (NMAccessPointList *list, const char *name) nm_info ("%d)\t'%s' (%p) stamp=%ld enc=%d addr=" MAC_FMT " strength=%d " "freq=[%f/%d] rate=%d inval=%d mode=%d seen=%ld", i, - nm_ap_get_essid (ap), + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", ap, timestamp->tv_sec, nm_ap_get_encrypted (ap), diff --git a/src/NetworkManagerAPList.h b/src/NetworkManagerAPList.h index d3b0e43201..dc1be7dec8 100644 --- a/src/NetworkManagerAPList.h +++ b/src/NetworkManagerAPList.h @@ -39,15 +39,15 @@ gboolean nm_ap_list_is_empty (NMAccessPointList *list); void nm_ap_list_append_ap (NMAccessPointList *list, NMAccessPoint *ap); void nm_ap_list_remove_ap (NMAccessPointList *list, NMAccessPoint *ap); -void nm_ap_list_remove_ap_by_essid (NMAccessPointList *list, const char *network); -void nm_ap_list_remove_duplicate_essids (NMAccessPointList *list); +void nm_ap_list_remove_ap_by_ssid (NMAccessPointList *list, const GByteArray * ssid); +void nm_ap_list_remove_duplicate_ssids (NMAccessPointList *list); -NMAccessPoint * nm_ap_list_get_ap_by_essid (NMAccessPointList *list, const char *network); +NMAccessPoint * nm_ap_list_get_ap_by_ssid (NMAccessPointList *list, const GByteArray * ssid); NMAccessPoint * nm_ap_list_get_ap_by_address (NMAccessPointList *list, const struct ether_addr *addr); void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *source); -void nm_ap_list_copy_essids_by_address (NMAccessPointList *dest, NMAccessPointList *source); -void nm_ap_list_copy_one_essid_by_address (NMAccessPoint *ap, NMAccessPointList *search_list); +void nm_ap_list_copy_ssids_by_address (NMAccessPointList *dest, NMAccessPointList *source); +void nm_ap_list_copy_one_ssid_by_address (NMAccessPoint *ap, NMAccessPointList *search_list); NMNetworkType nm_ap_list_get_type (NMAccessPointList *list); diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index 7588eff0c1..88c402465f 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -148,10 +148,14 @@ static NMDevice * nm_policy_auto_get_best_device (NMPolicy *policy, NMAccessPoin highest_priority_dev = NM_DEVICE (best_wireless_dev); } -#if 0 - nm_info ("AUTO: Best wired device = %s, best wireless device = %s (%s)", best_wired_dev ? nm_device_get_iface (best_wired_dev) : "(null)", - best_wireless_dev ? nm_device_get_iface (best_wireless_dev) : "(null)", (best_wireless_dev && *ap) ? nm_ap_get_essid (*ap) : "null" ); -#endif + if (FALSE) { + const GByteArray * ssid = (best_wireless_dev && *ap) ? nm_ap_get_ssid (*ap) : NULL; + + nm_info ("AUTO: Best wired device = %s, best wireless device = %s (%s)", + best_wired_dev ? nm_device_get_iface (NM_DEVICE (best_wired_dev)) : "(null)", + best_wireless_dev ? nm_device_get_iface (NM_DEVICE (best_wireless_dev)) : "(null)", + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "null" ); + } return highest_priority_dev; } @@ -161,28 +165,28 @@ create_connection (NMDevice *device, NMAccessPoint *ap) { NMConnection *connection = NULL; NMSetting *setting = NULL; - + if (NM_IS_DEVICE_802_3_ETHERNET (device)) { nm_info ("Will activate connection '%s'.", nm_device_get_iface (device)); setting = nm_setting_wired_new (); } else if (NM_IS_DEVICE_802_11_WIRELESS (device) && ap) { NMSettingWireless *wireless; - const char *ssid; + const GByteArray * ssid = nm_ap_get_ssid (ap); nm_info ("Will activate connection '%s/%s'.", nm_device_get_iface (device), - nm_ap_get_essid (ap)); + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); setting = nm_setting_wireless_new (); wireless = (NMSettingWireless *) setting; - ssid = nm_ap_get_essid (ap); - wireless->ssid = g_byte_array_sized_new (strlen (ssid)); - g_byte_array_append (wireless->ssid, (guint8 *) ssid, strlen (ssid)); + wireless->ssid = g_byte_array_sized_new (ssid->len); + g_byte_array_append (wireless->ssid, ssid->data, ssid->len); wireless->mode = g_strdup ("infrastructure"); - } else + } else { nm_warning ("Unhandled device type '%s'", G_OBJECT_CLASS_NAME (device)); + } if (setting) { NMSettingInfo *info; @@ -216,7 +220,7 @@ nm_policy_device_change_check (gpointer user_data) NMPolicy *policy = (NMPolicy *) user_data; GSList *iter; NMAccessPoint * ap = NULL; - NMDevice * new_dev; + NMDevice * new_dev = NULL; NMDevice * old_dev = NULL; gboolean do_switch = FALSE; @@ -309,9 +313,9 @@ nm_policy_device_change_check (gpointer user_data) /* Only switch if the old device's wireless config is invalid */ if (NM_IS_DEVICE_802_11_WIRELESS (new_dev)) { NMAccessPoint *old_ap = nm_device_802_11_wireless_get_activation_ap (NM_DEVICE_802_11_WIRELESS (old_dev)); - const char * old_essid = nm_ap_get_essid (old_ap); + const GByteArray * old_ssid = nm_ap_get_ssid (old_ap); int old_mode = nm_ap_get_mode (old_ap); - const char * new_essid = nm_ap_get_essid (ap); + const GByteArray * new_ssid = nm_ap_get_ssid (ap); gboolean same_request = FALSE; /* Schedule new activation if the currently associated @@ -319,23 +323,32 @@ nm_policy_device_change_check (gpointer user_data) * link to the old access point. We don't switch away * from Ad-Hoc APs either. */ - gboolean same_essid = (nm_null_safe_strcmp (old_essid, new_essid) == 0); + gboolean same_ssid = nm_utils_same_ssid (old_ssid, new_ssid); - /* If the "best" AP's essid is the same as the current activation - * request's essid, but the current activation request isn't + /* If the "best" AP's SSID is the same as the current activation + * request's SSID, but the current activation request isn't * done yet, don't switch. This prevents multiple requests for the * AP's password on startup. */ - if ((old_dev == new_dev) && nm_device_is_activating (new_dev) && same_essid) + if ((old_dev == new_dev) && nm_device_is_activating (new_dev) && same_ssid) same_request = TRUE; - if (!same_request && (!same_essid || !old_has_link) && (old_mode != IW_MODE_ADHOC)) { + if (!same_request && (!same_ssid || !old_has_link) && (old_mode != IW_MODE_ADHOC)) { + char * new_esc_ssid; + char * old_esc_ssid; + + new_esc_ssid = g_strdup (new_ssid ? nm_utils_escape_ssid (new_ssid->data, new_ssid->len) : "(none)"); + old_esc_ssid = g_strdup (old_ssid ? nm_utils_escape_ssid (old_ssid->data, old_ssid->len) : "(none)"); nm_info ("SWITCH: found better connection '%s/%s'" " than current connection '%s/%s'. " "same_ssid=%d, have_link=%d", - nm_device_get_iface (new_dev), new_essid, - nm_device_get_iface (old_dev), old_essid, - same_essid, old_has_link); + nm_device_get_iface (new_dev), + new_esc_ssid, + nm_device_get_iface (old_dev), + old_esc_ssid, + same_ssid, old_has_link); + g_free (new_esc_ssid); + g_free (old_esc_ssid); do_switch = TRUE; } } else if (NM_IS_DEVICE_802_3_ETHERNET (new_dev)) { @@ -346,7 +359,7 @@ nm_policy_device_change_check (gpointer user_data) } } - if (do_switch) { + if (do_switch && new_dev) { NMConnection *connection; connection = create_connection (new_dev, ap); @@ -446,11 +459,11 @@ nm_policy_device_list_update_from_allowed_list (gpointer user_data) wdev = NM_DEVICE_802_11_WIRELESS (dev); if (nm_device_get_capabilities (dev) & NM_DEVICE_CAP_WIRELESS_SCAN) { /* Once we have the list, copy in any relevant information from our - * Allowed list and fill in the ESSID of base stations that aren't - * broadcasting their ESSID, if we have their MAC address in our + * Allowed list and fill in the SSID of base stations that aren't + * broadcasting their SSID, if we have their MAC address in our * allowed list. */ - nm_ap_list_copy_essids_by_address (nm_device_802_11_wireless_ap_list_get (wdev), + nm_ap_list_copy_ssids_by_address (nm_device_802_11_wireless_ap_list_get (wdev), data->allowed_ap_list); nm_ap_list_copy_properties (nm_device_802_11_wireless_ap_list_get (wdev), data->allowed_ap_list); @@ -458,7 +471,7 @@ nm_policy_device_list_update_from_allowed_list (gpointer user_data) nm_device_802_11_wireless_copy_allowed_to_dev_list (wdev, data->allowed_ap_list); } - nm_ap_list_remove_duplicate_essids (nm_device_802_11_wireless_ap_list_get (wdev)); + nm_ap_list_remove_duplicate_ssids (nm_device_802_11_wireless_ap_list_get (wdev)); } schedule_change_check ((gpointer) global_policy); diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 76d4e9f603..de8e9346c5 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -582,3 +582,57 @@ int nm_utils_ip4_netmask_to_prefix (guint32 ip4_netmask) return (32 - (i-1)); } +/* Shamelessly ripped from the Linux kernel ieee80211 stack */ +gboolean +nm_utils_is_empty_ssid (const char * ssid, int len) +{ + /* Single white space is for Linksys APs */ + if (len == 1 && ssid[0] == ' ') + return TRUE; + + /* Otherwise, if the entire ssid is 0, we assume it is hidden */ + while (len--) { + if (ssid[len] != '\0') + return FALSE; + } + return TRUE; +} + +const char * +nm_utils_escape_ssid (const char * ssid, guint32 len) +{ + static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; + const char *s = ssid; + char *d = escaped; + + if (nm_utils_is_empty_ssid (ssid, len)) { + memcpy (escaped, "", sizeof ("")); + return escaped; + } + + len = MIN (len, (guint32) IW_ESSID_MAX_SIZE); + while (len--) { + if (*s == '\0') { + *d++ = '\\'; + *d++ = '0'; + s++; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return escaped; +} + +gboolean +nm_utils_same_ssid (const GByteArray * ssid1, const GByteArray * ssid2) +{ + if (ssid1 == ssid2) + return TRUE; + if ((ssid1 && !ssid2) || (!ssid1 && ssid2)) + return FALSE; + if (ssid1->len != ssid2->len) + return FALSE; + + return memcmp (ssid1->data, ssid2->data, ssid1->len) == 0 ? TRUE : FALSE; +} diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index bdbb8b9a31..64b78c49e3 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -106,4 +106,9 @@ struct nl_addr * nm_utils_ip4_addr_to_nl_addr (guint32 ip4_addr); int nm_utils_ip4_netmask_to_prefix (guint32 ip4_netmask); +gboolean nm_utils_is_empty_ssid (const char * ssid, int len); +const char * nm_utils_escape_ssid (const char *ssid, guint32 len); + +gboolean nm_utils_same_ssid (const GByteArray * ssid1, const GByteArray * ssid2); + #endif diff --git a/src/backends/NetworkManagerSuSE.c b/src/backends/NetworkManagerSuSE.c index 8c052411fd..4f518a10b0 100644 --- a/src/backends/NetworkManagerSuSE.c +++ b/src/backends/NetworkManagerSuSE.c @@ -393,9 +393,14 @@ found: NMAccessPoint * list_ap; char * key; char * mode; + GByteArray * ssid; ap = nm_ap_new (); - nm_ap_set_essid (ap, buf); + + ssid = g_byte_array_sized_new (strlen (buf)); + g_byte_array_append (ssid, buf, strlen (buf)); + nm_ap_set_ssid (ap, ssid); + nm_ap_set_timestamp (ap, time (NULL), 0); nm_ap_set_fallback (ap, TRUE); @@ -495,9 +500,9 @@ found: g_object_unref (G_OBJECT (security)); } - if ((list_ap = nm_ap_list_get_ap_by_essid (app_data->allowed_ap_list, buf))) + if ((list_ap = nm_ap_list_get_ap_by_ssid (app_data->allowed_ap_list, ssid))) { - nm_ap_set_essid (list_ap, nm_ap_get_essid (ap)); + nm_ap_set_ssid (list_ap, nm_ap_get_ssid (ap)); nm_ap_set_timestamp_via_timestamp (list_ap, nm_ap_get_timestamp (ap)); nm_ap_set_fallback (list_ap, TRUE); nm_ap_set_security (list_ap, nm_ap_get_security (ap)); @@ -507,6 +512,7 @@ found: /* New AP, just add it to the list */ nm_ap_list_append_ap (app_data->allowed_ap_list, ap); } + g_byte_array_free (ssid, TRUE); g_object_unref (ap); nm_debug ("Adding '%s' to the list of trusted networks", buf); diff --git a/src/nm-dbus-nmi.c b/src/nm-dbus-nmi.c index 5f73a64fe1..528fe3b444 100644 --- a/src/nm-dbus-nmi.c +++ b/src/nm-dbus-nmi.c @@ -68,6 +68,7 @@ nm_dbus_get_user_key_for_network_cb (DBusPendingCall *pcall, NMAccessPoint * ap; NMAPSecurity * security; DBusMessageIter iter; + const GByteArray * ssid; g_return_if_fail (pcall != NULL); g_return_if_fail (info != NULL); @@ -80,6 +81,7 @@ nm_dbus_get_user_key_for_network_cb (DBusPendingCall *pcall, ap = nm_device_802_11_wireless_get_activation_ap (NM_DEVICE_802_11_WIRELESS (dev)); g_assert (ap); + ssid = nm_ap_get_ssid (ap); nm_dbus_send_with_callback_replied (pcall, __func__); @@ -99,7 +101,7 @@ nm_dbus_get_user_key_for_network_cb (DBusPendingCall *pcall, nm_info ("Activation (%s) New wireless user key request for network" " '%s' was canceled.", nm_device_get_iface (dev), - nm_ap_get_essid (ap)); + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); } else { nm_warning ("dbus returned an error.\n (%s) %s\n", err.name, @@ -121,7 +123,7 @@ nm_dbus_get_user_key_for_network_cb (DBusPendingCall *pcall, nm_info ("Activation (%s) New wireless user key for network '%s' received.", nm_device_get_iface (dev), - nm_ap_get_essid (ap)); + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); dbus_message_iter_init (reply, &iter); if ((security = nm_ap_security_new_deserialize (&iter))) { @@ -157,7 +159,7 @@ nm_dbus_get_user_key_for_network (NMDevice *dev, gint32 attempt = 1; char * dev_path; const char * net_path; - const char * essid; + const GByteArray * ssid; g_return_if_fail (NM_IS_DEVICE (dev)); g_return_if_fail (req != NULL); @@ -172,10 +174,10 @@ nm_dbus_get_user_key_for_network (NMDevice *dev, ap = nm_device_802_11_wireless_get_activation_ap (NM_DEVICE_802_11_WIRELESS (dev)); g_assert (ap); - essid = nm_ap_get_essid (ap); + ssid = nm_ap_get_ssid (ap); nm_info ("Activation (%s) New wireless user key requested for network '%s'.", nm_device_get_iface (dev), - essid); + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, @@ -189,9 +191,14 @@ nm_dbus_get_user_key_for_network (NMDevice *dev, dev_path = nm_dbus_get_object_path_for_device (dev); net_path = nm_ap_get_dbus_path (ap); if (dev_path && strlen (dev_path) && net_path && strlen (net_path)) { + char buf[IW_ESSID_MAX_SIZE + 1]; + char * ptr = &buf[0]; + + memset (buf, 0, sizeof (buf)); + memcpy (buf, ssid->data, MIN (ssid->len, sizeof (buf) - 1)); dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_OBJECT_PATH, &net_path, - DBUS_TYPE_STRING, &essid, + DBUS_TYPE_STRING, &ptr, DBUS_TYPE_INT32, &attempt, DBUS_TYPE_BOOLEAN, &new_key, DBUS_TYPE_INVALID); @@ -283,11 +290,13 @@ nm_dbus_update_network_info (NMAccessPoint *ap, DBusConnection * dbus_connection; DBusMessage * message; gboolean fallback; - const char * essid; + const GByteArray * ssid; gchar * char_bssid; NMAPSecurity * security; const struct ether_addr *addr; DBusMessageIter iter; + char buf[IW_ESSID_MAX_SIZE + 1]; + char * ptr = &buf[0]; g_return_if_fail (ap != NULL); @@ -298,8 +307,6 @@ nm_dbus_update_network_info (NMAccessPoint *ap, goto out; } - essid = nm_ap_get_essid (ap); - message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, @@ -312,7 +319,10 @@ nm_dbus_update_network_info (NMAccessPoint *ap, dbus_message_iter_init_append (message, &iter); /* First argument: ESSID (STRING) */ - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &essid); + ssid = nm_ap_get_ssid (ap); + memset (buf, 0, sizeof (buf)); + memcpy (buf, ssid->data, MIN (ssid->len, IW_ESSID_MAX_SIZE)); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &ptr); /* Second argument: Automatic or user-driven connection? (BOOLEAN) */ dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &automatic); @@ -404,13 +414,15 @@ static void nm_dbus_get_network_data_cb (DBusPendingCall *pcall, void *user_data DBusMessage * reply = NULL; DBusMessageIter iter; DBusMessageIter subiter; - const char * essid = NULL; + const char * tmp_ssid = NULL; + guint32 tmp_ssid_len; gint timestamp_secs = -1; gboolean fallback = FALSE; GSList * addr_list = NULL; NMAPSecurity * security; NMAccessPoint * ap; NMAccessPoint * list_ap; + GByteArray * ssid; g_return_if_fail (pcall != NULL); g_return_if_fail (cb_data != NULL); @@ -425,19 +437,23 @@ static void nm_dbus_get_network_data_cb (DBusPendingCall *pcall, void *user_data if (!(reply = dbus_pending_call_steal_reply (pcall))) goto out; - if (dbus_message_is_error (reply, "BadNetworkData")) - { - nm_ap_list_remove_ap_by_essid (cb_data->list, cb_data->network); + if (dbus_message_is_error (reply, "BadNetworkData")) { + guint32 rmv_len = strlen (cb_data->network); + GByteArray * rmv_ssid; + + rmv_ssid = g_byte_array_sized_new (rmv_len); + g_byte_array_append (rmv_ssid, cb_data->network, rmv_len); + nm_ap_list_remove_ap_by_ssid (cb_data->list, rmv_ssid); + g_byte_array_free (rmv_ssid, TRUE); goto out; } - if (message_is_error (reply)) - { + if (message_is_error (reply)) { DBusError err; dbus_error_init (&err); dbus_set_error_from_message (&err, reply); - nm_warning ("nm_dbus_get_network_data_cb(): dbus returned an error.\n (%s) %s\n", err.name, err.message); + nm_warning ("dbus returned an error.\n (%s) %s\n", err.name, err.message); dbus_error_free (&err); goto out; } @@ -447,10 +463,10 @@ static void nm_dbus_get_network_data_cb (DBusPendingCall *pcall, void *user_data /* First arg: ESSID (STRING) */ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) { - nm_warning ("a message argument (essid) was invalid."); + nm_warning ("a message argument (SSID) was invalid."); goto out; } - dbus_message_iter_get_basic (&iter, &essid); + dbus_message_iter_get_basic (&iter, &tmp_ssid); /* Second arg: Timestamp (INT32) */ if (!dbus_message_iter_next (&iter) @@ -505,7 +521,12 @@ static void nm_dbus_get_network_data_cb (DBusPendingCall *pcall, void *user_data /* Construct the new access point */ ap = nm_ap_new (); - nm_ap_set_essid (ap, essid); + + tmp_ssid_len = MIN (strlen (tmp_ssid), IW_ESSID_MAX_SIZE); + ssid = g_byte_array_sized_new (tmp_ssid_len); + g_byte_array_append (ssid, tmp_ssid, tmp_ssid_len); + nm_ap_set_ssid (ap, ssid); + nm_ap_set_security (ap, security); nm_ap_add_capabilities_from_security (ap, security); g_object_unref (G_OBJECT (security)); /* set_security copies the object */ @@ -515,9 +536,9 @@ static void nm_dbus_get_network_data_cb (DBusPendingCall *pcall, void *user_data nm_ap_set_fallback (ap, fallback); nm_ap_set_user_addresses (ap, addr_list); - if ((list_ap = nm_ap_list_get_ap_by_essid (cb_data->list, essid))) + if ((list_ap = nm_ap_list_get_ap_by_ssid (cb_data->list, ssid))) { - nm_ap_set_essid (list_ap, nm_ap_get_essid (ap)); + nm_ap_set_ssid (list_ap, nm_ap_get_ssid (ap)); nm_ap_set_timestamp_via_timestamp (list_ap, nm_ap_get_timestamp (ap)); nm_ap_set_fallback (list_ap, nm_ap_get_fallback (ap)); nm_ap_set_security (list_ap, nm_ap_get_security (ap)); @@ -528,6 +549,7 @@ static void nm_dbus_get_network_data_cb (DBusPendingCall *pcall, void *user_data /* New AP, just add it to the list */ nm_ap_list_append_ap (cb_data->list, ap); } + g_byte_array_free (ssid, TRUE); g_object_unref (ap); /* Ensure all devices get new information copied into their device lists */ diff --git a/src/nm-device-802-11-wireless.c b/src/nm-device-802-11-wireless.c index b11fb3ee96..66bf8b362a 100644 --- a/src/nm-device-802-11-wireless.c +++ b/src/nm-device-802-11-wireless.c @@ -109,7 +109,7 @@ struct _NMDevice80211WirelessPrivate struct ether_addr hw_addr; - char * cur_essid; + GByteArray * ssid; gint8 invalid_strength_counter; iwqual max_qual; iwqual avg_qual; @@ -212,19 +212,19 @@ nm_device_802_11_wireless_update_bssid (NMDevice80211Wireless *self, { struct ether_addr new_bssid; const struct ether_addr *old_bssid; - const char * new_essid; - const char * old_essid; + const GByteArray * new_ssid; + const GByteArray * old_ssid; /* Get the current BSSID. If it is valid but does not match the stored value, - * and the ESSID is the same as what we think its supposed to be, update it. */ + * and the SSID is the same as what we think its supposed to be, update it. */ nm_device_802_11_wireless_get_bssid (self, &new_bssid); old_bssid = nm_ap_get_address (ap); - new_essid = nm_device_802_11_wireless_get_essid (self); - old_essid = nm_ap_get_essid (ap); + new_ssid = nm_device_802_11_wireless_get_ssid (self); + old_ssid = nm_ap_get_ssid (ap); if ( nm_ethernet_address_is_valid (&new_bssid) && nm_ethernet_address_is_valid (old_bssid) && !nm_ethernet_addresses_are_equal (&new_bssid, old_bssid) - && !nm_null_safe_strcmp (old_essid, new_essid)) + && nm_utils_same_ssid (old_ssid, new_ssid)) { gboolean automatic; gchar new_addr[20]; @@ -234,7 +234,10 @@ nm_device_802_11_wireless_update_bssid (NMDevice80211Wireless *self, memset (old_addr, '\0', sizeof (old_addr)); iw_ether_ntop (&new_bssid, new_addr); iw_ether_ntop (old_bssid, old_addr); - nm_debug ("Roamed from BSSID %s to %s on wireless network '%s'", old_addr, new_addr, nm_ap_get_essid (ap)); + nm_debug ("Roamed from BSSID %s to %s on wireless network '%s'", + old_addr, + new_addr, + nm_utils_escape_ssid (old_ssid->data, old_ssid->len)); nm_ap_set_address (ap, &new_bssid); @@ -623,12 +626,18 @@ static void real_deactivate_quickly (NMDevice *dev) { NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (dev); + NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self); cleanup_association_attempt (self, TRUE); /* Clean up stuff, don't leave the card associated */ - nm_device_802_11_wireless_set_essid (self, ""); + nm_device_802_11_wireless_set_ssid (self, NULL); nm_device_802_11_wireless_disable_encryption (self); + + if (priv->activation_ap) { + g_object_unref (priv->activation_ap); + priv->activation_ap = NULL; + } } static void @@ -717,11 +726,10 @@ link_to_specific_ap (NMDevice80211Wireless *self, if (is_associated (self)) { - const char * dev_essid = nm_device_802_11_wireless_get_essid (self); - const char * ap_essid = nm_ap_get_essid (ap); + const GByteArray * dev_ssid = nm_device_802_11_wireless_get_ssid (self); + const GByteArray * ap_ssid = nm_ap_get_ssid (ap); - if (dev_essid && ap_essid && !strcmp (dev_essid, ap_essid)) - { + if (dev_ssid && ap_ssid && nm_utils_same_ssid (dev_ssid, ap_ssid)) { self->priv->failed_link_count = 0; have_link = TRUE; } @@ -743,7 +751,7 @@ get_ap_blacklisted (NMAccessPoint *ap, GSList *addrs) { gboolean blacklisted; - blacklisted = nm_ap_has_manufacturer_default_essid (ap); + blacklisted = nm_ap_has_manufacturer_default_ssid (ap); if (blacklisted) { GSList *elt; @@ -794,7 +802,7 @@ get_best_fallback_ap (NMDevice80211Wireless *self) while ((allowed_ap = nm_ap_list_iter_next (iter))) { - const char * essid; + const GByteArray * ssid; GSList * user_addrs; const GTimeVal * curtime; gboolean blacklisted; @@ -812,8 +820,8 @@ get_best_fallback_ap (NMDevice80211Wireless *self) continue; /* No fallback to networks on the invalid list -- we probably already tried them and failed */ - essid = nm_ap_get_essid (allowed_ap); - if (nm_ap_list_get_ap_by_essid (app_data->invalid_ap_list, essid)) + ssid = nm_ap_get_ssid (allowed_ap); + if (nm_ap_list_get_ap_by_ssid (app_data->invalid_ap_list, ssid)) continue; curtime = nm_ap_get_timestamp (allowed_ap); @@ -825,10 +833,13 @@ get_best_fallback_ap (NMDevice80211Wireless *self) } nm_ap_list_iter_free (iter); - if (best_ap) - { + if (best_ap) { + const GByteArray * ssid; + nm_ap_set_broadcast (best_ap, FALSE); - nm_info ("Attempting to fallback to wireless network '%s'", nm_ap_get_essid (best_ap)); + ssid = nm_ap_get_ssid (best_ap); + nm_info ("Attempting to fallback to wireless network '%s'", + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); } return best_ap; @@ -871,11 +882,9 @@ nm_device_802_11_wireless_get_best_ap (NMDevice80211Wireless *self) /* We prefer the currently selected access point if its user-chosen or if there * is still a hardware link to it. */ - if ((req = nm_device_get_act_request (NM_DEVICE (self)))) - { - if ((cur_ap = nm_device_802_11_wireless_get_activation_ap (self))) - { - const char * essid = nm_ap_get_essid (cur_ap); + if ((req = nm_device_get_act_request (NM_DEVICE (self)))) { + if ((cur_ap = nm_device_802_11_wireless_get_activation_ap (self))) { + const GByteArray * ssid = nm_ap_get_ssid (cur_ap); gboolean keep = FALSE; if (nm_ap_get_user_created (cur_ap)) @@ -887,8 +896,8 @@ nm_device_802_11_wireless_get_best_ap (NMDevice80211Wireless *self) /* Only keep if its not in the invalid list and its _is_ in our scanned list */ if ( keep - && !nm_ap_list_get_ap_by_essid (app_data->invalid_ap_list, essid) - && nm_device_802_11_wireless_ap_list_get_ap_by_essid (self, essid)) + && !nm_ap_list_get_ap_by_ssid (app_data->invalid_ap_list, ssid) + && nm_device_802_11_wireless_ap_list_get_ap_by_ssid (self, ssid)) { return (NMAccessPoint *) g_object_ref (cur_ap); } @@ -897,16 +906,15 @@ nm_device_802_11_wireless_get_best_ap (NMDevice80211Wireless *self) if (!(iter = nm_ap_list_iter_new (ap_list))) return NULL; - while ((scan_ap = nm_ap_list_iter_next (iter))) - { + while ((scan_ap = nm_ap_list_iter_next (iter))) { NMAccessPoint *tmp_ap; - const char * ap_essid = nm_ap_get_essid (scan_ap); + const GByteArray * ap_ssid = nm_ap_get_ssid (scan_ap); /* Access points in the "invalid" list cannot be used */ - if (nm_ap_list_get_ap_by_essid (app_data->invalid_ap_list, ap_essid)) + if (nm_ap_list_get_ap_by_ssid (app_data->invalid_ap_list, ap_ssid)) continue; - if ((tmp_ap = nm_ap_list_get_ap_by_essid (app_data->allowed_ap_list, ap_essid))) + if ((tmp_ap = nm_ap_list_get_ap_by_ssid (app_data->allowed_ap_list, ap_ssid))) { const GTimeVal * curtime = nm_ap_get_timestamp (tmp_ap); gboolean blacklisted; @@ -918,8 +926,7 @@ nm_device_802_11_wireless_get_best_ap (NMDevice80211Wireless *self) g_slist_foreach (user_addrs, (GFunc) g_free, NULL); g_slist_free (user_addrs); - if (!blacklisted && (curtime->tv_sec > best_timestamp.tv_sec)) - { + if (!blacklisted && (curtime->tv_sec > best_timestamp.tv_sec)) { best_timestamp = *nm_ap_get_timestamp (tmp_ap); best_ap = scan_ap; nm_ap_set_security (best_ap, nm_ap_get_security (tmp_ap)); @@ -930,7 +937,6 @@ nm_device_802_11_wireless_get_best_ap (NMDevice80211Wireless *self) if (!best_ap) best_ap = get_best_fallback_ap (self); - if (best_ap) g_object_ref (best_ap); @@ -942,36 +948,28 @@ nm_device_802_11_wireless_set_activation_ap (NMDevice80211Wireless *self, GByteArray *ssid, NMAPSecurity *security) { + NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self); NMAccessPoint *ap = NULL; NMData * app_data; NMAccessPointList * dev_ap_list; - char *essid; app_data = nm_device_get_app_data (NM_DEVICE (self)); g_assert (app_data); - /* FIXME: handle essid everywhere as GByteArray */ - { - essid = g_new (char, ssid->len + 1); - memcpy (essid, ssid->data, ssid->len); - essid[ssid->len] = '\0'; - } - - nm_debug ("Forcing AP '%s'", essid); + nm_debug ("Forcing AP '%s'", nm_utils_escape_ssid (ssid->data, ssid->len)); /* Find the AP in our card's scan list first. * If its not there, create an entirely new AP. */ dev_ap_list = nm_device_802_11_wireless_ap_list_get (self); - if (!(ap = nm_ap_list_get_ap_by_essid (dev_ap_list, essid))) - { + if (!(ap = nm_ap_list_get_ap_by_ssid (dev_ap_list, ssid))) { /* We need security information from the user if the network they * request isn't in our scan list. */ - if (!security) - { + if (!security) { nm_warning ("%s: tried to manually connect to network '%s' without " - "providing security information!", __func__, essid); + "providing security information!", __func__, + nm_utils_escape_ssid (ssid->data, ssid->len)); return FALSE; } @@ -979,7 +977,7 @@ nm_device_802_11_wireless_set_activation_ap (NMDevice80211Wireless *self, * "fake" access point and add it to the scan list. */ ap = nm_ap_new (); - nm_ap_set_essid (ap, essid); + nm_ap_set_ssid (ap, ssid); nm_ap_set_artificial (ap, TRUE); nm_ap_set_broadcast (ap, FALSE); /* Ensure the AP has some capabilities. They will get overwritten @@ -994,7 +992,8 @@ nm_device_802_11_wireless_set_activation_ap (NMDevice80211Wireless *self, /* If the AP is in the ignore list, we have to remove it since * the User Knows What's Best. */ - nm_ap_list_remove_ap_by_essid (app_data->invalid_ap_list, nm_ap_get_essid (ap)); + nm_ap_list_remove_ap_by_ssid (app_data->invalid_ap_list, + nm_ap_get_ssid (ap)); /* If we didn't get any security info, make some up. */ if (!security) @@ -1002,13 +1001,17 @@ nm_device_802_11_wireless_set_activation_ap (NMDevice80211Wireless *self, nm_ap_get_encrypted (ap)); } - g_free (essid); - g_assert (security); nm_ap_set_security (ap, security); nm_ap_add_capabilities_from_security (ap, security); - NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self)->activation_ap = ap; + if (priv->activation_ap) { + g_object_unref (priv->activation_ap); + priv->activation_ap = NULL; + } + + g_object_ref (ap); + priv->activation_ap = ap; return TRUE; } @@ -1034,22 +1037,22 @@ nm_device_802_11_wireless_ap_list_clear (NMDevice80211Wireless *self) /* - * nm_device_ap_list_get_ap_by_essid + * nm_device_ap_list_get_ap_by_ssid * - * Get the access point for a specific essid + * Get the access point for a specific SSID * */ NMAccessPoint * -nm_device_802_11_wireless_ap_list_get_ap_by_essid (NMDevice80211Wireless *self, - const char *essid) +nm_device_802_11_wireless_ap_list_get_ap_by_ssid (NMDevice80211Wireless *self, + const GByteArray * ssid) { g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (essid != NULL, NULL); + g_return_val_if_fail (ssid != NULL, NULL); if (!self->priv->ap_list) return NULL; - return nm_ap_list_get_ap_by_essid (self->priv->ap_list, essid); + return nm_ap_list_get_ap_by_ssid (self->priv->ap_list, ssid); } @@ -1141,7 +1144,7 @@ impl_device_get_active_networks (NMDevice80211Wireless *device, NMAccessPoint *ap; while ((ap = nm_ap_list_iter_next (list_iter))) { - if (nm_ap_get_essid (ap)) + if (nm_ap_get_ssid (ap)) g_ptr_array_add (*networks, g_strdup (nm_ap_get_dbus_path (ap))); } nm_ap_list_iter_free (list_iter); @@ -1394,109 +1397,129 @@ max_qual->updated); /* - * nm_device_get_essid + * nm_device_802_11_wireless_get_ssid * - * If a device is wireless, return the essid that it is attempting + * If a device is wireless, return the ssid that it is attempting * to use. - * - * Returns: allocated string containing essid. Must be freed by caller. - * */ -const char * -nm_device_802_11_wireless_get_essid (NMDevice80211Wireless *self) +const GByteArray * +nm_device_802_11_wireless_get_ssid (NMDevice80211Wireless *self) { - NMSock * sk; - int err; - const char * iface; + NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self); + const char * iface; + int err, sk; + struct iwreq wrq; + char ssid[IW_ESSID_MAX_SIZE + 1]; + guint32 len; g_return_val_if_fail (self != NULL, NULL); iface = nm_device_get_iface (NM_DEVICE (self)); - if ((sk = nm_dev_sock_open (iface, DEV_WIRELESS, __FUNCTION__, NULL))) - { - wireless_config info; - - nm_ioctl_info ("%s: About to GET 'basic config' for ESSID.", iface); - - err = iw_get_basic_config (nm_dev_sock_get_fd (sk), iface, &info); - if (err >= 0) - { - if (self->priv->cur_essid) - g_free (self->priv->cur_essid); - self->priv->cur_essid = g_strdup (info.essid); - } - else - { - nm_warning ("error getting ESSID for device %s: %s", - iface, strerror (errno)); - } - - nm_dev_sock_close (sk); + sk = socket (AF_INET, SOCK_DGRAM, 0); + if (!sk) { + nm_error ("Couldn't create socket: %d.", errno); + return NULL; } - return self->priv->cur_essid; + wrq.u.essid.pointer = (caddr_t) &ssid; + wrq.u.essid.length = sizeof (ssid); + wrq.u.essid.flags = 0; + if (iw_get_ext (sk, iface, SIOCGIWESSID, &wrq) < 0) { + nm_error ("Couldn't get SSID: %d", errno); + goto out; + } + + if (priv->ssid) { + g_byte_array_free (priv->ssid, TRUE); + priv->ssid = NULL; + } + + len = wrq.u.essid.length; + if (!nm_utils_is_empty_ssid (ssid, len)) { + /* Some drivers include nul termination in the SSID, so let's + * remove it here before further processing. WE-21 changes this + * to explicitly require the length _not_ to include nul + * termination. */ + if (len > 0 && ssid[len - 1] == '\0' && priv->we_version < 21) + len--; + + priv->ssid = g_byte_array_sized_new (len); + g_byte_array_append (priv->ssid, ssid, len); + } + +out: + close (sk); + return self->priv->ssid; } /* - * nm_device_802_11_wireless_set_essid + * nm_device_802_11_wireless_set_ssid * - * If a device is wireless, set the essid that it should use. + * If a device is wireless, set the SSID that it should use. */ void -nm_device_802_11_wireless_set_essid (NMDevice80211Wireless *self, - const char *essid) +nm_device_802_11_wireless_set_ssid (NMDevice80211Wireless *self, + const GByteArray * ssid) { - NMSock* sk; - int err; - struct iwreq wreq; - char * safe_essid; - const char * iface; - const char * driver; - gint len = 0; + NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self); + int sk, err; + struct iwreq wrq; + const char * iface; + const char * driver; + guint32 len = 0; + char buf[IW_ESSID_MAX_SIZE + 1]; g_return_if_fail (self != NULL); - safe_essid = g_malloc0 (IW_ESSID_MAX_SIZE + 1); - - if (essid) - { - len = MIN(IW_ESSID_MAX_SIZE, strlen (essid)); - if (len <= 0) - len = 0; - strncpy (safe_essid, essid, len); + sk = socket (AF_INET, SOCK_DGRAM, 0); + if (!sk) { + nm_error ("Couldn't create socket: %d.", errno); + return; } iface = nm_device_get_iface (NM_DEVICE (self)); - if ((sk = nm_dev_sock_open (iface, DEV_WIRELESS, __FUNCTION__, NULL))) - { - wreq.u.essid.pointer = (caddr_t) safe_essid; - wreq.u.essid.length = len + 1; - wreq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable ESSID, 0=disable/any */ - nm_ioctl_info ("%s: About to SET IWESSID.", iface); - - if ((err = iw_set_ext (nm_dev_sock_get_fd (sk), iface, SIOCSIWESSID, &wreq)) == -1) - { - if (errno != ENODEV) - { - nm_warning ("error setting ESSID to '%s' for device %s: %s", - safe_essid, iface, strerror (errno)); - } - } - - nm_dev_sock_close (sk); - - /* Orinoco cards seem to need extra time here to not screw - * up the firmware, which reboots when you set the ESSID. - * Unfortunately, there's no way to know when the card is back up - * again. Sigh... - */ - driver = nm_device_get_driver (NM_DEVICE (self)); - if (!driver || !strcmp (driver, "orinoco")) - sleep (2); + memset (buf, 0, sizeof (buf)); + if (ssid) { + len = ssid->len; + memcpy (buf, ssid->data, MIN (sizeof (buf) - 1, len)); } - g_free (safe_essid); + wrq.u.essid.pointer = (caddr_t) buf; + + if (priv->we_version < 21) { + /* For historic reasons, set SSID length to include one extra + * character, C string nul termination, even though SSID is + * really an octet string that should not be presented as a C + * string. Some Linux drivers decrement the length by one and + * can thus end up missing the last octet of the SSID if the + * length is not incremented here. WE-21 changes this to + * explicitly require the length _not_ to include nul + * termination. */ + if (len) + len++; + } + wrq.u.essid.length = len; + wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */ + + if (iw_get_ext (sk, iface, SIOCSIWESSID, &wrq) < 0) { + if (errno != ENODEV) { + nm_warning ("error setting SSID to '%s' for device %s: %s", + nm_utils_escape_ssid (ssid->data, ssid->len), + iface, strerror (errno)); + } + } + + /* Orinoco cards seem to need extra time here to not screw + * up the firmware, which reboots when you set the SSID. + * Unfortunately, there's no way to know when the card is back up + * again. Sigh... + */ + driver = nm_device_get_driver (NM_DEVICE (self)); + if (!driver || !strcmp (driver, "orinoco")) + sleep (2); + + close (sk); } @@ -1744,16 +1767,20 @@ ap_need_key (NMDevice80211Wireless *self, NMAccessPoint *ap, gboolean *ask_user) { - const char * essid; + const GByteArray * ssid; gboolean need_key = FALSE; NMAPSecurity * security; const char * iface; int we_cipher; + const char * esc_ssid = NULL; g_return_val_if_fail (ap != NULL, FALSE); g_return_val_if_fail (ask_user != NULL, FALSE); - essid = nm_ap_get_essid (ap); + ssid = nm_ap_get_ssid (ap); + if (ssid) + esc_ssid = nm_utils_escape_ssid (ssid->data, ssid->len); + security = nm_ap_get_security (ap); g_assert (security); we_cipher = nm_ap_security_get_we_cipher (security); @@ -1763,7 +1790,7 @@ ap_need_key (NMDevice80211Wireless *self, if (!nm_ap_get_encrypted (ap)) { nm_info ("Activation (%s/wireless): access point '%s' is unencrypted, no key needed.", - iface, essid ? essid : "(null)"); + iface, esc_ssid ? esc_ssid : "(null)"); /* If the user-specified security info doesn't overlap the * scanned access point's info, create new info from the scanned @@ -1781,7 +1808,7 @@ ap_need_key (NMDevice80211Wireless *self, { nm_info ("Activation (%s/wireless): access point '%s' " "is encrypted, but NO valid key exists. New key needed.", - iface, essid ? essid : "(null)"); + iface, esc_ssid ? esc_ssid : "(null)"); need_key = TRUE; /* If the user-specified security info doesn't overlap the @@ -1795,7 +1822,7 @@ ap_need_key (NMDevice80211Wireless *self, { nm_info ("Activation (%s/wireless): access point '%s' " "is encrypted, and a key exists. No new key needed.", - iface, essid ? essid : "(null)"); + iface, esc_ssid ? esc_ssid : "(null)"); } } @@ -1876,8 +1903,7 @@ ap_is_auth_required (NMAccessPoint *ap, gboolean *has_key) static void merge_scanned_ap (NMDevice80211Wireless *dev, NMAccessPoint *merge_ap) -{ - +{ NMAccessPointList *list; NMAccessPoint *list_ap = NULL; const struct ether_addr *merge_bssid; @@ -1885,16 +1911,16 @@ merge_scanned_ap (NMDevice80211Wireless *dev, list = nm_device_802_11_wireless_ap_list_get (dev); merge_bssid = nm_ap_get_address (merge_ap); - if (nm_ethernet_address_is_valid (merge_bssid) && (list_ap = nm_ap_list_get_ap_by_address (list, merge_bssid))) - { + if ( nm_ethernet_address_is_valid (merge_bssid) + && (list_ap = nm_ap_list_get_ap_by_address (list, merge_bssid))) { /* First, we check for an address match. If the merge AP has a valid * BSSID and the same address as a list AP, then the merge AP and * the list AP must be the same physical AP. The list AP properties must * be from a previous scan so the time_last_seen's are not equal. Update * encryption, authentication method, strength, and the time_last_seen. */ - const char *devlist_essid = nm_ap_get_essid (list_ap); - const char *merge_essid = nm_ap_get_essid (merge_ap); + const GByteArray * devlist_ssid = nm_ap_get_ssid (list_ap); + const GByteArray * merge_ssid = nm_ap_get_ssid (merge_ap); const glong merge_ap_seen = nm_ap_get_last_seen (merge_ap); nm_ap_set_capabilities (list_ap, nm_ap_get_capabilities (merge_ap)); @@ -1908,16 +1934,16 @@ merge_scanned_ap (NMDevice80211Wireless *dev, nm_ap_set_artificial (list_ap, FALSE); /* Did the AP's name change? */ - if (!devlist_essid || !merge_essid || nm_null_safe_strcmp (devlist_essid, merge_essid)) { + if ( !devlist_ssid + || !merge_ssid + || !nm_utils_same_ssid (devlist_ssid, merge_ssid)) { network_removed (dev, list_ap); - nm_ap_set_essid (list_ap, merge_essid); + nm_ap_set_ssid (list_ap, merge_ssid); network_added (dev, list_ap); } - } - else if ((list_ap = nm_ap_list_get_ap_by_essid (list, nm_ap_get_essid (merge_ap)))) - { - /* Second, we check for an ESSID match. In this case, - * a list AP has the same non-NULL ESSID as the merge AP. Update the + } else if ((list_ap = nm_ap_list_get_ap_by_ssid (list, nm_ap_get_ssid (merge_ap)))) { + /* Second, we check for an SSID match. In this case, + * a list AP has the same non-NULL SSID as the merge AP. Update the * encryption and authentication method. Update the strength and address * except when the time_last_seen of the list AP is the same as the * time_last_seen of the merge AP and the strength of the list AP is greater @@ -1932,8 +1958,7 @@ merge_scanned_ap (NMDevice80211Wireless *dev, nm_ap_set_capabilities (list_ap, nm_ap_get_capabilities (merge_ap)); if (!((list_ap_seen == merge_ap_seen) - && (nm_ap_get_strength (list_ap) >= merge_ap_strength))) - { + && (nm_ap_get_strength (list_ap) >= merge_ap_strength))) { nm_ap_set_strength (list_ap, merge_ap_strength); nm_ap_set_address (list_ap, nm_ap_get_address (merge_ap)); } @@ -1980,14 +2005,14 @@ cull_scan_list (NMDevice80211Wireless * self) const glong ap_time = nm_ap_get_last_seen (outdated_ap); gboolean keep_around = FALSE; guint prune_interval_s; - const char * ssid; + const GByteArray * ssid; + const GByteArray * cur_ssid; /* Don't ever prune the AP we're currently associated with */ - ssid = nm_ap_get_essid (outdated_ap); - if (ssid && cur_ap) { - if (nm_null_safe_strcmp (nm_ap_get_essid (cur_ap), ssid) == 0) - keep_around = TRUE; - } + ssid = nm_ap_get_ssid (outdated_ap); + cur_ssid = cur_ap ? nm_ap_get_ssid (cur_ap) : NULL; + if (ssid && nm_utils_same_ssid (cur_ssid, ssid)) + keep_around = TRUE; prune_interval_s = SCAN_INTERVAL_MAX * 3; @@ -2065,12 +2090,12 @@ supplicant_iface_scanned_ap_cb (NMSupplicantInterface * iface, set_ap_strength_from_properties (self, ap, properties); - /* If the AP is not broadcasting its ESSID, try to fill it in here from our - * allowed list where we cache known MAC->ESSID associations. + /* If the AP is not broadcasting its SSID, try to fill it in here from our + * allowed list where we cache known MAC->SSID associations. */ - if (!nm_ap_get_essid (ap)) { + if (!nm_ap_get_ssid (ap)) { nm_ap_set_broadcast (ap, FALSE); - nm_ap_list_copy_one_essid_by_address (ap, app_data->allowed_ap_list); + nm_ap_list_copy_one_ssid_by_address (ap, app_data->allowed_ap_list); } /* Add the AP to the device's AP list */ @@ -2297,11 +2322,12 @@ supplicant_iface_connection_state_cb_handler (gpointer user_data) */ if (nm_device_get_state (dev) == NM_DEVICE_STATE_CONFIG) { NMAccessPoint *ap = nm_device_802_11_wireless_get_activation_ap (self); + const GByteArray * ssid = nm_ap_get_ssid (ap); nm_info ("Activation (%s/wireless) Stage 2 of 5 (Device Configure) " "successful. Connected to wireless network '%s'.", nm_device_get_iface (dev), - nm_ap_get_essid (ap) ? nm_ap_get_essid (ap) : "(none)"); + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); nm_device_activate_schedule_stage3_ip_config_start (dev); } } else if (new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED) { @@ -2595,9 +2621,9 @@ static NMSupplicantConfig * build_supplicant_config (NMDevice80211Wireless *self) { NMSupplicantConfig * config = NULL; - NMAccessPoint * ap = NULL; - const char * essid; - gboolean is_adhoc; + NMAccessPoint * ap = NULL; + const GByteArray * ssid; + gboolean is_adhoc; g_return_val_if_fail (self != NULL, NULL); @@ -2614,8 +2640,12 @@ build_supplicant_config (NMDevice80211Wireless *self) nm_supplicant_config_set_ap_scan (config, 2); } - essid = nm_ap_get_orig_essid (ap); - nm_supplicant_config_add_option (config, "ssid", essid, -1); + ssid = nm_ap_get_ssid (ap); + if (!ssid) { + nm_warning ("can't add null ssid to config."); + goto error; + } + nm_supplicant_config_add_option (config, "ssid", ssid->data, ssid->len); /* For non-broadcast networks, we need to set "scan_ssid 1" to scan with probe request frames. * However, don't try to probe Ad-Hoc networks. @@ -2838,9 +2868,12 @@ real_act_stage4_ip_config_timeout (NMDevice *dev, */ if (!ap_is_auth_required (ap, &has_key) && has_key) { + const GByteArray * ssid = nm_ap_get_ssid (ap); + /* Activation failed, we must have bad encryption key */ nm_debug ("Activation (%s/wireless): could not get IP configuration info for '%s', asking for new key.", - nm_device_get_iface (dev), nm_ap_get_essid (ap) ? nm_ap_get_essid (ap) : "(none)"); + nm_device_get_iface (dev), + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH); nm_dbus_get_user_key_for_network (dev, nm_device_get_act_request (dev), TRUE); ret = NM_ACT_STAGE_RETURN_POSTPONE; @@ -2884,7 +2917,7 @@ activation_success_handler (NMDevice *dev) if (!automatic && (nm_ap_get_mode (ap) == IW_MODE_ADHOC) && nm_ap_get_user_created (ap)) { NMAccessPointList *ap_list = nm_device_802_11_wireless_ap_list_get (self); - if (!nm_ap_list_get_ap_by_essid (ap_list, nm_ap_get_essid (ap))) + if (!nm_ap_list_get_ap_by_ssid (ap_list, nm_ap_get_ssid (ap))) nm_ap_list_append_ap (ap_list, ap); } @@ -2902,6 +2935,7 @@ activation_failure_handler (NMDevice *dev) NMData * app_data; NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (dev); NMAccessPoint * ap; + const GByteArray * ssid; app_data = nm_device_get_app_data (dev); g_assert (app_data); @@ -2929,8 +2963,10 @@ activation_failure_handler (NMDevice *dev) } } - nm_info ("Activation (%s) failed for access point (%s)", nm_device_get_iface (dev), - ap ? nm_ap_get_essid (ap) : "(none)"); + ssid = nm_ap_get_ssid (ap); + nm_info ("Activation (%s) failed for access point (%s)", + nm_device_get_iface (dev), + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); } static void @@ -3124,6 +3160,9 @@ nm_device_802_11_wireless_class_init (NMDevice80211WirelessClass *klass) static void state_changed_cb (NMDevice *device, NMDeviceState state, gpointer user_data) { + NMDevice80211Wireless *self = NM_DEVICE_802_11_WIRELESS (device); + NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self); + switch (state) { case NM_DEVICE_STATE_ACTIVATED: activation_success_handler (device); @@ -3132,7 +3171,11 @@ state_changed_cb (NMDevice *device, NMDeviceState state, gpointer user_data) activation_failure_handler (device); break; case NM_DEVICE_STATE_DISCONNECTED: - NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (device)->activation_ap = NULL; + if (priv->activation_ap) { +nm_info ("%s(): clearing activation AP", __func__); + g_object_unref (priv->activation_ap); + priv->activation_ap = NULL; + } default: break; } diff --git a/src/nm-device-802-11-wireless.h b/src/nm-device-802-11-wireless.h index d7f657302b..052e092387 100644 --- a/src/nm-device-802-11-wireless.h +++ b/src/nm-device-802-11-wireless.h @@ -83,8 +83,8 @@ NMDevice80211Wireless *nm_device_802_11_wireless_new (const char *iface, gboolean test_dev, NMData *app_data); -void nm_device_802_11_wireless_set_essid (NMDevice80211Wireless *self, - const char *essid); +void nm_device_802_11_wireless_set_ssid (NMDevice80211Wireless *self, + const GByteArray * ssid); void nm_device_802_11_wireless_get_address (NMDevice80211Wireless *dev, struct ether_addr *addr); @@ -92,7 +92,7 @@ void nm_device_802_11_wireless_get_address (NMDevice80211Wireless *dev, void nm_device_802_11_wireless_get_bssid (NMDevice80211Wireless *dev, struct ether_addr *bssid); -const char * nm_device_802_11_wireless_get_essid (NMDevice80211Wireless *self); +const GByteArray * nm_device_802_11_wireless_get_ssid (NMDevice80211Wireless *self); gboolean nm_device_802_11_wireless_set_mode (NMDevice80211Wireless *self, const int mode); @@ -114,8 +114,8 @@ NMAccessPoint * nm_device_802_11_wireless_ap_list_get_ap_by_obj_path (NMDevice80 NMAccessPoint * nm_device_802_11_wireless_ap_list_get_ap_by_bssid (NMDevice80211Wireless *dev, const struct ether_addr *bssid); -NMAccessPoint * nm_device_802_11_wireless_ap_list_get_ap_by_essid (NMDevice80211Wireless *dev, - const char *essid); +NMAccessPoint * nm_device_802_11_wireless_ap_list_get_ap_by_ssid (NMDevice80211Wireless *dev, + const GByteArray * ssid); int nm_device_802_11_wireless_get_mode (NMDevice80211Wireless *self); diff --git a/src/nm-device.c b/src/nm-device.c index ab0d22f2c8..396beadebc 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -432,7 +432,7 @@ real_act_stage2_config (NMDevice *dev) * nm_device_activate_stage2_device_config * * Determine device parameters and set those on the device, ie - * for wireless devices, set essid, keys, etc. + * for wireless devices, set SSID, keys, etc. * */ static gboolean diff --git a/test/nm-tool.c b/test/nm-tool.c index 01892f8e2e..88158c56db 100644 --- a/test/nm-tool.c +++ b/test/nm-tool.c @@ -37,6 +37,47 @@ #include #include +/* Shamelessly ripped from the Linux kernel ieee80211 stack */ +static gboolean +nm_utils_is_empty_ssid (const char * ssid, int len) +{ + /* Single white space is for Linksys APs */ + if (len == 1 && ssid[0] == ' ') + return TRUE; + + /* Otherwise, if the entire ssid is 0, we assume it is hidden */ + while (len--) { + if (ssid[len] != '\0') + return FALSE; + } + return TRUE; +} + +static const char * +nm_utils_escape_ssid (const char * ssid, guint32 len) +{ + static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; + const char *s = ssid; + char *d = escaped; + + if (nm_utils_is_empty_ssid (ssid, len)) { + memcpy (escaped, "", sizeof ("")); + return escaped; + } + + len = MIN (len, (guint32) IW_ESSID_MAX_SIZE); + while (len--) { + if (*s == '\0') { + *d++ = '\\'; + *d++ = '0'; + s++; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return escaped; +} static gboolean @@ -107,7 +148,7 @@ detail_network (gpointer data, gpointer user_data) GString *str; gboolean active = FALSE; guint32 capabilities; - char *essid; + GByteArray * ssid; char *tmp; capabilities = nm_access_point_get_capabilities (ap); @@ -142,9 +183,10 @@ detail_network (gpointer data, gpointer user_data) /* FIXME: broadcast/hidden */ - essid = nm_access_point_get_essid (ap); - tmp = g_strdup_printf (" %s%s", active ? "*" : "", essid); - g_free (essid); + ssid = nm_access_point_get_ssid (ap); + tmp = g_strdup_printf (" %s%s", active ? "*" : "", + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); + g_byte_array_free (ssid, TRUE); print_string (tmp, str->str); diff --git a/utils/nm-utils.c b/utils/nm-utils.c index beff79e739..98b6bbb626 100644 --- a/utils/nm-utils.c +++ b/utils/nm-utils.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -299,55 +301,53 @@ get_encodings_for_lang (const char *lang, char * -nm_utils_essid_to_utf8 (const char *orig_essid) +nm_utils_ssid_to_utf8 (const char *ssid, guint32 len) { - char *new_essid = NULL; + char * new_ssid = NULL; + char buf[IW_ESSID_MAX_SIZE + 1]; + guint32 buf_len = MIN (sizeof (buf) - 1, len); + char * lang; + char *e1 = NULL, *e2 = NULL, *e3 = NULL; - g_return_val_if_fail (orig_essid != NULL, NULL); + g_return_val_if_fail (ssid != NULL, NULL); - if (g_utf8_validate (orig_essid, -1, NULL)) - new_essid = g_strdup (orig_essid); - else - { - char * lang; - char *e1 = NULL, *e2 = NULL, *e3 = NULL; + memset (buf, 0, sizeof (buf)); + memcpy (buf, ssid, buf_len); - /* Even if the local encoding is UTF-8, LANG may give - * us a clue as to what encoding ESSIDs are more likely to be in. - */ - g_get_charset ((const char **)(&e1)); - if ((lang = getenv ("LANG"))) - { - char * dot; - - lang = g_ascii_strdown (lang, -1); - if ((dot = strchr (lang, '.'))) - *dot = '\0'; - - get_encodings_for_lang (lang, &e1, &e2, &e3); - g_free (lang); - } - - new_essid = g_convert (orig_essid, -1, "UTF-8", e1, NULL, NULL, NULL); - if (!new_essid && e2) - { - new_essid = g_convert (orig_essid, -1, "UTF-8", e2, - NULL, NULL, NULL); - } - if (!new_essid && e3) - { - new_essid = g_convert (orig_essid, -1, "UTF-8", e3, - NULL, NULL, NULL); - } - - if (!new_essid) - { - new_essid = g_convert_with_fallback (orig_essid, -1, "UTF-8", e1, - "?", NULL, NULL, NULL); - } + if (g_utf8_validate (buf, buf_len, NULL)) { + new_ssid = g_strdup (buf); + goto out; } - return new_essid; + /* Even if the local encoding is UTF-8, LANG may give + * us a clue as to what encoding SSIDs are more likely to be in. + */ + g_get_charset ((const char **)(&e1)); + if ((lang = getenv ("LANG"))) { + char * dot; + + lang = g_ascii_strdown (lang, -1); + if ((dot = strchr (lang, '.'))) + *dot = '\0'; + + get_encodings_for_lang (lang, &e1, &e2, &e3); + g_free (lang); + } + + new_ssid = g_convert (buf, buf_len, "UTF-8", e1, NULL, NULL, NULL); + if (!new_ssid && e2) { + new_ssid = g_convert (buf, buf_len, "UTF-8", e2, NULL, NULL, NULL); + } + if (!new_ssid && e3) { + new_ssid = g_convert (buf, buf_len, "UTF-8", e3, NULL, NULL, NULL); + } + if (!new_ssid) { + new_ssid = g_convert_with_fallback (buf, buf_len, "UTF-8", e1, + "?", NULL, NULL, NULL); + } + +out: + return new_ssid; } diff --git a/utils/nm-utils.h b/utils/nm-utils.h index 47050bb8a1..d43526c752 100644 --- a/utils/nm-utils.h +++ b/utils/nm-utils.h @@ -129,7 +129,7 @@ G_STMT_START \ gchar *nm_dbus_escape_object_path (const gchar *utf8_string); gchar *nm_dbus_unescape_object_path (const gchar *object_path); -char *nm_utils_essid_to_utf8 (const char *orig_essid); +char *nm_utils_ssid_to_utf8 (const char *ssid, guint32 len); /* #define DBUS_PENDING_CALL_DEBUG */