gsupplicant: Creating an helper function to compute bss security
[platform/upstream/connman.git] / gsupplicant / supplicant.c
index 3e61f74..8d87dae 100644 (file)
@@ -188,6 +188,7 @@ struct g_supplicant_bss {
        dbus_bool_t privacy;
        dbus_bool_t psk;
        dbus_bool_t ieee8021x;
+       unsigned int wps_capabilities;
 };
 
 struct _GSupplicantNetwork {
@@ -203,6 +204,7 @@ struct _GSupplicantNetwork {
        GSupplicantMode mode;
        GSupplicantSecurity security;
        dbus_bool_t wps;
+       unsigned int wps_capabilities;
        GHashTable *bss_table;
        GHashTable *config_table;
 };
@@ -859,6 +861,39 @@ dbus_bool_t g_supplicant_network_get_wps(GSupplicantNetwork *network)
        return network->wps;
 }
 
+dbus_bool_t g_supplicant_network_is_wps_active(GSupplicantNetwork *network)
+{
+       if (network == NULL)
+               return FALSE;
+
+       if (network->wps_capabilities & G_SUPPLICANT_WPS_CONFIGURED)
+               return TRUE;
+
+       return FALSE;
+}
+
+dbus_bool_t g_supplicant_network_is_wps_pbc(GSupplicantNetwork *network)
+{
+       if (network == NULL)
+               return FALSE;
+
+       if (network->wps_capabilities & G_SUPPLICANT_WPS_PBC)
+               return TRUE;
+
+       return FALSE;
+}
+
+dbus_bool_t g_supplicant_network_is_wps_advertizing(GSupplicantNetwork *network)
+{
+       if (network == NULL)
+               return FALSE;
+
+       if (network->wps_capabilities & G_SUPPLICANT_WPS_REGISTRAR)
+               return TRUE;
+
+       return FALSE;
+}
+
 static void merge_network(GSupplicantNetwork *network)
 {
        GString *str;
@@ -1061,7 +1096,7 @@ static char *create_group(struct g_supplicant_bss *bss)
        return g_string_free(str, FALSE);
 }
 
-static void add_bss_to_network(struct g_supplicant_bss *bss)
+static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
 {
        GSupplicantInterface *interface = bss->interface;
        GSupplicantNetwork *network;
@@ -1097,9 +1132,12 @@ static void add_bss_to_network(struct g_supplicant_bss *bss)
        network->best_bss = bss;
 
        network->wps = FALSE;
-       if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0)
+       if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
                network->wps = TRUE;
 
+               network->wps_capabilities |= bss->wps_capabilities;
+       }
+
        network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
                                                        NULL, remove_bss);
 
@@ -1248,13 +1286,19 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
        const unsigned char WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
        unsigned char *ie, *ie_end;
        DBusMessageIter array;
+       unsigned int value;
        int ie_len;
 
 #define WMM_WPA1_WPS_INFO 221
 #define WPS_INFO_MIN_LEN  6
 #define WPS_VERSION_TLV   0x104A
 #define WPS_STATE_TLV     0x1044
+#define WPS_METHODS_TLV   0x1012
+#define WPS_REGISTRAR_TLV 0x1041
 #define WPS_VERSION       0x10
+#define WPS_PBC           0x04
+#define WPS_PIN           0x00
+#define WPS_CONFIGURED    0x02
 
        dbus_message_iter_recurse(iter, &array);
        dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
@@ -1271,14 +1315,49 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 
                SUPPLICANT_DBG("IE: match WPS_OUI");
 
-               if (get_tlv(&ie[6], ie[1],
-                               WPS_VERSION_TLV) == WPS_VERSION &&
-                       get_tlv(&ie[6], ie[1],
-                               WPS_STATE_TLV) != 0)
+               value = get_tlv(&ie[6], ie[1], WPS_STATE_TLV);
+               if (get_tlv(&ie[6], ie[1], WPS_VERSION_TLV) == WPS_VERSION &&
+                                                               value != 0) {
                        bss->keymgmt |= G_SUPPLICANT_KEYMGMT_WPS;
+
+                       if (value == WPS_CONFIGURED)
+                               bss->wps_capabilities |=
+                                       G_SUPPLICANT_WPS_CONFIGURED;
+               }
+
+               value = get_tlv(&ie[6], ie[1], WPS_METHODS_TLV);
+               if (value != 0) {
+                       if (GUINT16_FROM_BE(value) == WPS_PBC)
+                               bss->wps_capabilities |= G_SUPPLICANT_WPS_PBC;
+                       if (GUINT16_FROM_BE(value) == WPS_PIN)
+                               bss->wps_capabilities |= G_SUPPLICANT_WPS_PIN;
+               } else
+                       bss->wps_capabilities |=
+                               G_SUPPLICANT_WPS_PBC | G_SUPPLICANT_WPS_PIN;
+
+               /* If the AP sends this it means it's advertizing
+                * as a registrar and the WPS process is launched
+                * on its side */
+               if (get_tlv(&ie[6], ie[1], WPS_REGISTRAR_TLV) != 0)
+                       bss->wps_capabilities |= G_SUPPLICANT_WPS_REGISTRAR;
+
+               SUPPLICANT_DBG("WPS Methods 0x%x", bss->wps_capabilities);
        }
 }
 
+static void bss_compute_security(struct g_supplicant_bss *bss)
+{
+       if (bss->ieee8021x == TRUE)
+               bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
+       else if (bss->psk == TRUE)
+               bss->security = G_SUPPLICANT_SECURITY_PSK;
+       else if (bss->privacy == TRUE)
+               bss->security = G_SUPPLICANT_SECURITY_WEP;
+       else
+               bss->security = G_SUPPLICANT_SECURITY_NONE;
+}
+
+
 static void bss_property(const char *key, DBusMessageIter *iter,
                                                        void *user_data)
 {
@@ -1290,16 +1369,9 @@ static void bss_property(const char *key, DBusMessageIter *iter,
        SUPPLICANT_DBG("key %s", key);
 
        if (key == NULL) {
-               if (bss->ieee8021x == TRUE)
-                       bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
-               else if (bss->psk == TRUE)
-                       bss->security = G_SUPPLICANT_SECURITY_PSK;
-               else if (bss->privacy == TRUE)
-                       bss->security = G_SUPPLICANT_SECURITY_WEP;
-               else
-                       bss->security = G_SUPPLICANT_SECURITY_NONE;
+               bss_compute_security(bss);
 
-               add_bss_to_network(bss);
+               add_or_replace_bss_to_network(bss);
                return;
        }
 
@@ -2684,10 +2756,15 @@ static int parse_supplicant_error(DBusMessageIter *iter)
        int err = -ECANCELED;
        char *key;
 
+       /* If the given passphrase is malformed wpa_s returns
+        * "invalid message format" but this error should be interpreted as
+        * invalid-key.
+        */
        while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
                dbus_message_iter_get_basic(iter, &key);
-               if (strncmp(key, "psk", 4) == 0 ||
-                       strncmp(key, "wep_key", 7) == 0) {
+               if (strncmp(key, "psk", 3) == 0 ||
+                               strncmp(key, "wep_key", 7) == 0 ||
+                               strcmp(key, "invalid message format") == 0) {
                        err = -ENOKEY;
                        break;
                }
@@ -3142,6 +3219,10 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
                supplicant_dbus_dict_append_basic(&dict, "frequency",
                                         DBUS_TYPE_UINT32, &ssid->freq);
 
+       if (ssid->bgscan != NULL)
+               supplicant_dbus_dict_append_basic(&dict, "bgscan",
+                                       DBUS_TYPE_STRING, &ssid->bgscan);
+
        add_network_mode(&dict, ssid);
 
        add_network_security(&dict, ssid);
@@ -3479,7 +3560,7 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
                callback_system_killed();
 
        if (interface_table != NULL) {
-               g_hash_table_foreach(interface_table,   
+               g_hash_table_foreach(interface_table,
                                        unregister_remove_interface, NULL);
                g_hash_table_destroy(interface_table);
                interface_table = NULL;