diff --git a/include/gsupplicant_interface.h b/include/gsupplicant_interface.h index 1a9b27f..382b8b4 100644 --- a/include/gsupplicant_interface.h +++ b/include/gsupplicant_interface.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2015-2020 Jolla Ltd. - * Copyright (C) 2015-2020 Slava Monich + * Copyright (C) 2023 Slava Monich * * You may use this file under the terms of BSD license as follows: * @@ -104,7 +104,14 @@ typedef struct gsupplicant_interface_caps { #define GSUPPLICANT_INTERFACE_CAPS_MODES_P2P (0x00000008) gint max_scan_ssid; - guint caps_reserved[2]; + guint group_mgmt; /* Used since 1.0.27 */ + +#define GSUPPLICANT_INTERFACE_CAPS_GROUP_MGMT_BIP (0x00000001) +#define GSUPPLICANT_INTERFACE_CAPS_GROUP_MGMT_BIP_GMAC_128 (0x00000002) +#define GSUPPLICANT_INTERFACE_CAPS_GROUP_MGMT_BIP_GMAC_256 (0x00000004) +#define GSUPPLICANT_INTERFACE_CAPS_GROUP_MGMT_BIP_CMAC_256 (0x00000008) + + guint caps_reserved; } GSupplicantInterfaceCaps; typedef struct gsupplicant_signal_poll { diff --git a/include/gsupplicant_types.h b/include/gsupplicant_types.h index 557d222..8d67851 100644 --- a/include/gsupplicant_types.h +++ b/include/gsupplicant_types.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2015-2020 Jolla Ltd. - * Copyright (C) 2015-2020 Slava Monich + * Copyright (C) 2023 Slava Monich * * You may use this file under the terms of BSD license as follows: * @@ -52,7 +52,10 @@ typedef enum gsupplicant_cipher { GSUPPLICANT_CIPHER_TKIP = (0x00000004), GSUPPLICANT_CIPHER_WEP104 = (0x00000008), GSUPPLICANT_CIPHER_WEP40 = (0x00000010), - GSUPPLICANT_CIPHER_AES128_CMAC = (0x00000020) + GSUPPLICANT_CIPHER_AES128_CMAC = (0x00000020), + GSUPPLICANT_CIPHER_CCMP_256 = (0x00000040), /* Since 1.0.27 */ + GSUPPLICANT_CIPHER_GCMP = (0x00000080), /* Since 1.0.27 */ + GSUPPLICANT_CIPHER_GCMP_256 = (0x00000100) /* Since 1.0.27 */ } GSUPPLICANT_CIPHER; typedef enum gsupplicant_keymgmt { @@ -66,7 +69,11 @@ typedef enum gsupplicant_keymgmt { GSUPPLICANT_KEYMGMT_WPA_EAP_SHA256 = (0x00000040), GSUPPLICANT_KEYMGMT_IEEE8021X = (0x00000080), GSUPPLICANT_KEYMGMT_WPA_NONE = (0x00000100), - GSUPPLICANT_KEYMGMT_WPS = (0x00000200) + GSUPPLICANT_KEYMGMT_WPS = (0x00000200), + GSUPPLICANT_KEYMGMT_SAE = (0x00000400), /* Since 1.0.27 */ + GSUPPLICANT_KEYMGMT_SAE_EXT_KEY = (0x00000800), /* Since 1.0.27 */ + GSUPPLICANT_KEYMGMT_FT_SAE = (0x00001000), /* Since 1.0.27 */ + GSUPPLICANT_KEYMGMT_FT_SAE_EXT_KEY = (0x00002000) /* Since 1.0.27 */ } GSUPPLICANT_KEYMGMT; typedef enum gsupplicant_protocol { diff --git a/src/gsupplicant.c b/src/gsupplicant.c index fcb673e..82fa99e 100644 --- a/src/gsupplicant.c +++ b/src/gsupplicant.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2015-2021 Jolla Ltd. - * Copyright (C) 2015-2021 Slava Monich + * Copyright (C) 2023 Slava Monich * * You may use this file under the terms of BSD license as follows: * @@ -177,7 +177,10 @@ static const GSupNameIntPair gsupplicant_cipher_suites [] = { { "tkip", GSUPPLICANT_CIPHER_TKIP }, { "wep104", GSUPPLICANT_CIPHER_WEP104 }, { "wep40", GSUPPLICANT_CIPHER_WEP40 }, - { "aes128cmac", GSUPPLICANT_CIPHER_AES128_CMAC } + { "aes128cmac", GSUPPLICANT_CIPHER_AES128_CMAC }, + { "ccmp-256", GSUPPLICANT_CIPHER_CCMP_256 }, + { "gcmp", GSUPPLICANT_CIPHER_GCMP }, + { "gcmp-256", GSUPPLICANT_CIPHER_GCMP_256 } }; static const GSupNameIntPair gsupplicant_keymgmt_suites [] = { @@ -190,7 +193,11 @@ static const GSupNameIntPair gsupplicant_keymgmt_suites [] = { { "wpa-eap-sha256", GSUPPLICANT_KEYMGMT_WPA_EAP_SHA256 }, { "ieee8021x", GSUPPLICANT_KEYMGMT_IEEE8021X }, { "wpa-none", GSUPPLICANT_KEYMGMT_WPA_NONE }, - { "wps", GSUPPLICANT_KEYMGMT_WPS } + { "wps", GSUPPLICANT_KEYMGMT_WPS }, + { "sae", GSUPPLICANT_KEYMGMT_SAE }, + { "sae-ext-key", GSUPPLICANT_KEYMGMT_SAE_EXT_KEY }, + { "ft-sae", GSUPPLICANT_KEYMGMT_FT_SAE }, + { "ft-sae-ext-key", GSUPPLICANT_KEYMGMT_FT_SAE_EXT_KEY } }; /*==========================================================================* @@ -890,6 +897,37 @@ gsupplicant_keymgmt_suite_name( gsupplicant_keymgmt_suites, G_N_ELEMENTS(gsupplicant_keymgmt_suites)); } +/*==========================================================================* + * Internal API + *==========================================================================*/ + +GSUPPLICANT_CIPHER +gsupplicant_parse_cipher_value( + const char* name, + GVariant* value) +{ + return gsupplicant_parse_bit_value(name, value, + gsupplicant_cipher_suites, G_N_ELEMENTS(gsupplicant_cipher_suites)); +} + +GSUPPLICANT_CIPHER +gsupplicant_parse_cipher_list( + const char* name, + GVariant* value) +{ + return gsupplicant_parse_bits_array(0, name, value, + gsupplicant_cipher_suites, G_N_ELEMENTS(gsupplicant_cipher_suites)); +} + +GSUPPLICANT_KEYMGMT +gsupplicant_parse_keymgmt_list( + const char* name, + GVariant* value) +{ + return gsupplicant_parse_bits_array(0, name, value, + gsupplicant_keymgmt_suites, G_N_ELEMENTS(gsupplicant_keymgmt_suites)); +} + /*==========================================================================* * Internals *==========================================================================*/ diff --git a/src/gsupplicant_bss.c b/src/gsupplicant_bss.c index 9c175fd..ad38337 100644 --- a/src/gsupplicant_bss.c +++ b/src/gsupplicant_bss.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2015-2021 Jolla Ltd. - * Copyright (C) 2015-2021 Slava Monich + * Copyright (C) 2023 Slava Monich * * You may use this file under the terms of BSD license as follows: * @@ -34,6 +34,7 @@ #include "gsupplicant_bss.h" #include "gsupplicant_interface.h" +#include "gsupplicant_p.h" #include "gsupplicant_util_p.h" #include "gsupplicant_dbus.h" #include "gsupplicant_log.h" @@ -481,37 +482,11 @@ gsupplicant_bss_parse_wpa( { GSupplicantBSSWPA* wpa = data; if (!g_strcmp0(name, "KeyMgmt")) { - static const GSupNameIntPair keymgmt_map [] = { - { "wpa-psk", GSUPPLICANT_KEYMGMT_WPA_PSK }, - { "wpa-eap", GSUPPLICANT_KEYMGMT_WPA_EAP }, - { "wpa-none", GSUPPLICANT_KEYMGMT_WPA_NONE } - }; - wpa->keymgmt = gsupplicant_parse_bits_array(0, name, value, - keymgmt_map, G_N_ELEMENTS(keymgmt_map)); + wpa->keymgmt = gsupplicant_parse_keymgmt_list(name, value); } else if (!g_strcmp0(name, "Pairwise")) { - static const GSupNameIntPair pairwise_map [] = { - { "ccmp", GSUPPLICANT_CIPHER_CCMP }, - { "tkip", GSUPPLICANT_CIPHER_TKIP } - }; - wpa->pairwise = gsupplicant_parse_bits_array(0, name, value, - pairwise_map, G_N_ELEMENTS(pairwise_map)); + wpa->pairwise = gsupplicant_parse_cipher_list(name, value); } else if (!g_strcmp0(name, "Group")) { - static const GSupNameIntPair group_map [] = { - { "ccmp", GSUPPLICANT_CIPHER_CCMP }, - { "tkip", GSUPPLICANT_CIPHER_TKIP }, - { "wep104", GSUPPLICANT_CIPHER_WEP104 }, - { "wep40", GSUPPLICANT_CIPHER_WEP40 } - }; - GASSERT(g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)); - if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { - const char* str = g_variant_get_string(value, NULL); - const GSupNameIntPair* pair = gsupplicant_name_int_find_name(str, - group_map, G_N_ELEMENTS(group_map)); - if (pair) { - GVERBOSE(" %s: %s", name, str); - wpa->group = pair->value; - } - } + wpa->group = gsupplicant_parse_cipher_value(name, value); } else { GWARN("Unexpected WPA dictionary key %s", name); } @@ -553,54 +528,13 @@ gsupplicant_bss_parse_rsn( { GSupplicantBSSRSN* rsn = data; if (!g_strcmp0(name, "KeyMgmt")) { - static const GSupNameIntPair keymgmt_map [] = { - { "wpa-psk", GSUPPLICANT_KEYMGMT_WPA_PSK }, - { "wpa-eap", GSUPPLICANT_KEYMGMT_WPA_EAP }, - { "wpa-ft-psk", GSUPPLICANT_KEYMGMT_WPA_FT_PSK }, - { "wpa-ft-eap", GSUPPLICANT_KEYMGMT_WPA_FT_EAP }, - { "wpa-psk-sha256", GSUPPLICANT_KEYMGMT_WPA_PSK_SHA256 }, - { "wpa-eap-sha256", GSUPPLICANT_KEYMGMT_WPA_EAP_SHA256 }, - }; - rsn->keymgmt = gsupplicant_parse_bits_array(0, name, value, - keymgmt_map, G_N_ELEMENTS(keymgmt_map)); + rsn->keymgmt = gsupplicant_parse_keymgmt_list(name, value); } else if (!g_strcmp0(name, "Pairwise")) { - static const GSupNameIntPair pairwise_map [] = { - { "ccmp", GSUPPLICANT_CIPHER_CCMP }, - { "tkip", GSUPPLICANT_CIPHER_TKIP } - }; - rsn->pairwise = gsupplicant_parse_bits_array(0, name, value, - pairwise_map, G_N_ELEMENTS(pairwise_map)); + rsn->pairwise = gsupplicant_parse_cipher_list(name, value); } else if (!g_strcmp0(name, "Group")) { - static const GSupNameIntPair group_map [] = { - { "ccmp", GSUPPLICANT_CIPHER_CCMP }, - { "tkip", GSUPPLICANT_CIPHER_TKIP }, - { "wep104", GSUPPLICANT_CIPHER_WEP104 }, - { "wep40", GSUPPLICANT_CIPHER_WEP40 } - }; - GASSERT(g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)); - if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { - const char* str = g_variant_get_string(value, NULL); - const GSupNameIntPair* pair = gsupplicant_name_int_find_name(str, - group_map, G_N_ELEMENTS(group_map)); - if (pair) { - GVERBOSE(" %s: %s", name, str); - rsn->group = pair->value; - } - } + rsn->group = gsupplicant_parse_cipher_value(name, value); } else if (!g_strcmp0(name, "MgmtGroup")) { - static const GSupNameIntPair mgmt_group_map [] = { - { "aes128cmac", GSUPPLICANT_CIPHER_AES128_CMAC } - }; - GASSERT(g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)); - if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { - const char* str = g_variant_get_string(value, NULL); - const GSupNameIntPair* pair = gsupplicant_name_int_find_name(str, - mgmt_group_map, G_N_ELEMENTS(mgmt_group_map)); - if (pair) { - GVERBOSE(" %s: %s", name, str); - rsn->mgmt_group = pair->value; - } - } + rsn->mgmt_group = gsupplicant_parse_cipher_value(name, value); } else { GWARN("Unexpected RSN dictionary key %s", name); } diff --git a/src/gsupplicant_interface.c b/src/gsupplicant_interface.c index 389aedd..80022d5 100644 --- a/src/gsupplicant_interface.c +++ b/src/gsupplicant_interface.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2015-2021 Jolla Ltd. - * Copyright (C) 2015-2021 Slava Monich + * Copyright (C) 2023 Slava Monich * * You may use this file under the terms of BSD license as follows: * @@ -36,6 +36,7 @@ #include "gsupplicant_network.h" #include "gsupplicant_bss.h" #include "gsupplicant.h" +#include "gsupplicant_p.h" #include "gsupplicant_util_p.h" #include "gsupplicant_dbus.h" #include "gsupplicant_log.h" @@ -1460,37 +1461,11 @@ gsupplicant_interface_parse_cap( { GSupplicantInterfaceCaps* caps = data; if (!g_strcmp0(name, "Pairwise")) { - static const GSupNameIntPair pairwise_map [] = { - { "ccmp", GSUPPLICANT_CIPHER_CCMP }, - { "tkip", GSUPPLICANT_CIPHER_TKIP }, - { "none", GSUPPLICANT_CIPHER_NONE } - }; - caps->pairwise = gsupplicant_parse_bits_array(0, name, value, - pairwise_map, G_N_ELEMENTS(pairwise_map)); + caps->pairwise = gsupplicant_parse_cipher_list(name, value); } else if (!g_strcmp0(name, "Group")) { - static const GSupNameIntPair group_map [] = { - { "ccmp", GSUPPLICANT_CIPHER_CCMP }, - { "tkip", GSUPPLICANT_CIPHER_TKIP }, - { "wep104", GSUPPLICANT_CIPHER_WEP104 }, - { "wep40", GSUPPLICANT_CIPHER_WEP40 } - }; - caps->group = gsupplicant_parse_bits_array(0, name, value, - group_map, G_N_ELEMENTS(group_map)); + caps->group = gsupplicant_parse_cipher_list(name, value); } else if (!g_strcmp0(name, "KeyMgmt")) { - static const GSupNameIntPair keymgmt_map [] = { - { "wpa-psk", GSUPPLICANT_KEYMGMT_WPA_PSK }, - { "wpa-ft-psk", GSUPPLICANT_KEYMGMT_WPA_FT_PSK }, - { "wpa-psk-sha256", GSUPPLICANT_KEYMGMT_WPA_PSK_SHA256 }, - { "wpa-eap", GSUPPLICANT_KEYMGMT_WPA_EAP }, - { "wpa-ft-eap", GSUPPLICANT_KEYMGMT_WPA_FT_EAP }, - { "wpa-eap-sha256", GSUPPLICANT_KEYMGMT_WPA_EAP_SHA256 }, - { "ieee8021x", GSUPPLICANT_KEYMGMT_IEEE8021X }, - { "wpa-none", GSUPPLICANT_KEYMGMT_WPA_NONE }, - { "wps", GSUPPLICANT_KEYMGMT_WPS }, - { "none", GSUPPLICANT_KEYMGMT_NONE } - }; - caps->keymgmt = gsupplicant_parse_bits_array(0, name, value, - keymgmt_map, G_N_ELEMENTS(keymgmt_map)); + caps->keymgmt = gsupplicant_parse_keymgmt_list(name, value); } else if (!g_strcmp0(name, "Protocol")) { static const GSupNameIntPair protocol_map [] = { { "rsn", GSUPPLICANT_PROTOCOL_RSN }, @@ -1516,7 +1491,7 @@ gsupplicant_interface_parse_cap( scan_map, G_N_ELEMENTS(scan_map)); } else if (!g_strcmp0(name, "Modes")) { static const GSupNameIntPair modes_map [] = { - { "infrastructure", GSUPPLICANT_INTERFACE_CAPS_MODES_INFRA}, + { "infrastructure", GSUPPLICANT_INTERFACE_CAPS_MODES_INFRA }, { "ad-hoc", GSUPPLICANT_INTERFACE_CAPS_MODES_AD_HOC }, { "ap", GSUPPLICANT_INTERFACE_CAPS_MODES_AP }, { "p2p", GSUPPLICANT_INTERFACE_CAPS_MODES_P2P } @@ -1526,6 +1501,15 @@ gsupplicant_interface_parse_cap( } else if (!g_strcmp0(name, "MaxScanSSID")) { caps->max_scan_ssid = g_variant_get_int32(value); GVERBOSE(" %s: %d", name, caps->max_scan_ssid); + } else if (!g_strcmp0(name, "GroupMgmt")) { + static const GSupNameIntPair group_mgmt_map [] = { + {"aes-128-cmac",GSUPPLICANT_INTERFACE_CAPS_GROUP_MGMT_BIP }, + {"bip-gmac-128",GSUPPLICANT_INTERFACE_CAPS_GROUP_MGMT_BIP_GMAC_128}, + {"bip-gmac-256",GSUPPLICANT_INTERFACE_CAPS_GROUP_MGMT_BIP_GMAC_256}, + {"bip-cmac-256",GSUPPLICANT_INTERFACE_CAPS_GROUP_MGMT_BIP_CMAC_256} + }; + caps->group_mgmt = gsupplicant_parse_bits_array(0, name, value, + group_mgmt_map, G_N_ELEMENTS(group_mgmt_map)); } else { GWARN("Unexpected interface capability key %s", name); } diff --git a/src/gsupplicant_p.h b/src/gsupplicant_p.h new file mode 100644 index 0000000..2280b25 --- /dev/null +++ b/src/gsupplicant_p.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2023 Slava Monich + * + * You may use this file under the terms of BSD license as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GSUPPLICANT_PRIVATE_H +#define GSUPPLICANT_PRIVATE_H + +#include "gsupplicant_types_p.h" + +GSUPPLICANT_CIPHER +gsupplicant_parse_cipher_value( + const char* name, + GVariant* value) /* G_VARIANT_TYPE_STRING */ + GSUPPLICANT_INTERNAL; + +GSUPPLICANT_CIPHER +gsupplicant_parse_cipher_list( + const char* name, + GVariant* value) /* G_VARIANT_TYPE_STRING_ARRAY */ + GSUPPLICANT_INTERNAL; + +GSUPPLICANT_KEYMGMT +gsupplicant_parse_keymgmt_list( + const char* name, + GVariant* value) /* G_VARIANT_TYPE_STRING_ARRAY */ + GSUPPLICANT_INTERNAL; + +#endif /* GSUPPLICANT_PRIVATE_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/gsupplicant_util.c b/src/gsupplicant_util.c index 2fcd9e8..9acd27d 100644 --- a/src/gsupplicant_util.c +++ b/src/gsupplicant_util.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2015-2021 Jolla Ltd. - * Copyright (C) 2015-2021 Slava Monich + * Copyright (C) 2023 Slava Monich * * You may use this file under the terms of BSD license as follows: * @@ -159,6 +159,32 @@ gsupplicant_name_int_concat( return buf ? g_string_free(buf, FALSE) : NULL; } +guint32 +gsupplicant_parse_bit_value( + const char* name, + GVariant* value, + const GSupNameIntPair* map, + gsize count) +{ + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + const char* str = g_variant_get_string(value, NULL); + const GSupNameIntPair* pair = gsupplicant_name_int_find_name(str, + map, count); + if (pair) { + GVERBOSE(" %s: %s", name, str); + return pair->value; + } else if (!str[0]) { + /* Don't complain about empty strings, just return zero */ + GVERBOSE(" %s: ", name); + } else { + GWARN("Unexpected %s value %s", name, str); + } + } else { + GWARN("Unexpected value type for %s", name); + } + return 0; +} + guint32 gsupplicant_parse_bits_array( guint32 mask, @@ -167,7 +193,7 @@ gsupplicant_parse_bits_array( const GSupNameIntPair* map, gsize count) { - if (g_variant_is_of_type(value, G_VARIANT_TYPE("as"))) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING_ARRAY)) { GVariantIter it; char* str = NULL; #if GUTIL_LOG_VERBOSE diff --git a/src/gsupplicant_util_p.h b/src/gsupplicant_util_p.h index 62e55ef..5404f60 100644 --- a/src/gsupplicant_util_p.h +++ b/src/gsupplicant_util_p.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2015-2021 Jolla Ltd. - * Copyright (C) 2015-2021 Slava Monich + * Copyright (C) 2023 Slava Monich * * You may use this file under the terms of BSD license as follows: * @@ -49,6 +49,14 @@ void GVariant* value, void* data); +guint32 +gsupplicant_parse_bit_value( + const char* name, + GVariant* value, + const GSupNameIntPair* map, + gsize count) + GSUPPLICANT_INTERNAL; + guint32 gsupplicant_parse_bits_array( guint32 mask, diff --git a/test/test_util/test_util.c b/test/test_util/test_util.c index d1f0577..8cd7d98 100644 --- a/test/test_util/test_util.c +++ b/test/test_util/test_util.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2017-2021 Jolla Ltd. - * Copyright (C) 2017-2021 Slava Monich + * Copyright (C) 2023 Slava Monich * * You may use this file under the terms of BSD license as follows: * @@ -205,6 +205,7 @@ test_util_parse_bits_array( { GVariantBuilder builder; GVariant* var; + g_variant_builder_init(&builder, G_VARIANT_TYPE("ai")); g_variant_builder_add_value(&builder, g_variant_new_int32(0)); var = g_variant_ref_sink(g_variant_builder_end(&builder)); @@ -218,8 +219,45 @@ test_util_parse_bits_array( g_variant_builder_add_value(&builder, g_variant_new_string("unknown")); var = g_variant_ref_sink(g_variant_builder_end(&builder)); - g_assert(gsupplicant_parse_bits_array(0, "test", var, - test_map, G_N_ELEMENTS(test_map)) == BIT_FOO); + g_assert_cmpuint(gsupplicant_parse_bits_array(0, "test", var, + test_map, G_N_ELEMENTS(test_map)), == ,BIT_FOO); + g_variant_unref(var); +} + +/*==========================================================================* + * parse_bit_value + *==========================================================================*/ + +static +void +test_util_parse_bit_value( + void) +{ + GVariant* var; + + /* Unexpected type */ + var = g_variant_ref_sink(g_variant_new_int32(0)); + g_assert(!gsupplicant_parse_bit_value("test", var, + test_map, G_N_ELEMENTS(test_map))); + g_variant_unref(var); + + /* Unexpected value */ + var = g_variant_new_string("unknown"); + g_assert(!gsupplicant_parse_bit_value("test", var, + test_map, G_N_ELEMENTS(test_map))); + g_variant_unref(var); + + /* Empty string */ + var = g_variant_new_string(""); + g_assert(!gsupplicant_parse_bit_value("test", var, NULL, 0)); + g_assert(gsupplicant_parse_bit_value("test", var, test_map, + G_N_ELEMENTS(test_map))); /* This map contains empty string */ + g_variant_unref(var); + + /* Success */ + var = g_variant_new_string(test_map->name); + g_assert_cmpuint(gsupplicant_parse_bit_value("test", var, + test_map, G_N_ELEMENTS(test_map)), == ,test_map->value); g_variant_unref(var); } @@ -394,6 +432,7 @@ test_util_dict_parse( g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); gsupplicant_dict_add_boolean(&builder, "true", TRUE); gsupplicant_dict_add_uint32(&builder, "one", 1); + gsupplicant_dict_add_value(&builder, "two", g_variant_new_uint32(2)); gsupplicant_dict_add_string0(&builder, NULL, NULL); gsupplicant_dict_add_string0(&builder, NULL, "ignored"); gsupplicant_dict_add_string0(&builder, "string", NULL); @@ -409,13 +448,16 @@ test_util_dict_parse( gsupplicant_dict_add_bytes0(&builder, "bytes", test_bytes); dict = g_variant_ref_sink(g_variant_builder_end(&builder)); GDEBUG_("%u", (guint)g_variant_n_children(dict)); - g_assert(g_variant_n_children(dict) == 5); + g_assert_cmpuint(g_variant_n_children(dict), == ,6); g_assert(!gsupplicant_dict_parse(NULL, test_util_dict_cb, values)); g_assert(!g_hash_table_size(values)); - g_assert(gsupplicant_dict_parse(dict, test_util_dict_cb, values) == 5); + g_assert(gsupplicant_dict_parse(dict, test_util_dict_cb, values) == 6); g_assert(g_variant_get_boolean(g_hash_table_lookup(values, "true"))); - g_assert(g_variant_get_uint32(g_hash_table_lookup(values, "one")) == 1); + g_assert_cmpuint(g_variant_get_uint32(g_hash_table_lookup(values, + "one")), == ,1); + g_assert_cmpuint(g_variant_get_uint32(g_hash_table_lookup(values, + "two")), == ,2); g_assert(!g_strcmp0(g_variant_get_string(g_hash_table_lookup(values, "string"), NULL), "string")); g_assert(!g_strcmp0(g_variant_get_string(g_hash_table_lookup(values, @@ -562,6 +604,7 @@ int main(int argc, char* argv[]) g_test_init(&argc, &argv, NULL); g_test_add_func(TEST_PREFIX "name_int", test_util_name_int); g_test_add_func(TEST_PREFIX "parse_bits_array", test_util_parse_bits_array); + g_test_add_func(TEST_PREFIX "parse_bit_value", test_util_parse_bit_value); g_test_add_func(TEST_PREFIX "format_bytes", test_util_format_bytes); g_test_add_func(TEST_PREFIX "cancel_later", test_util_cancel_later); g_test_add_func(TEST_PREFIX "abs_path", test_util_abs_path);