summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-01-04 16:34:44 +0100
committerThomas Haller <thaller@redhat.com>2020-01-04 17:26:36 +0100
commit18d03417d54d2c52b2b1b5fdb2cecc1b935a06ac (patch)
treeb58109c0057bdfecc3dafc9b6a5e47f6bd2ef9a2
parent95241d0f7d40f44b7f7ce0053003dd254828e286 (diff)
downloadNetworkManager-th/supplicant-capabilities.tar.gz
supplicant: add enum for supplicant capabilities (features)th/supplicant-capabilities
We should handle features/capabilities more generically. Add an enum type for that. It will be used next. Also, wpa_supplicant calls this "Capabilities", not features. Use that name.
-rw-r--r--src/supplicant/nm-supplicant-types.h88
-rw-r--r--src/supplicant/tests/test-supplicant-config.c38
2 files changed, 126 insertions, 0 deletions
diff --git a/src/supplicant/nm-supplicant-types.h b/src/supplicant/nm-supplicant-types.h
index 2b3563548b..e5be6c95f6 100644
--- a/src/supplicant/nm-supplicant-types.h
+++ b/src/supplicant/nm-supplicant-types.h
@@ -15,11 +15,99 @@ typedef struct _NMSupplicantInterface NMSupplicantInterface;
typedef struct _NMSupplicantConfig NMSupplicantConfig;
typedef enum {
+ NM_SUPPL_CAP_TYPE_AP = 0,
+ NM_SUPPL_CAP_TYPE_FAST,
+ NM_SUPPL_CAP_TYPE_PMF,
+ NM_SUPPL_CAP_TYPE_FILS,
+ NM_SUPPL_CAP_TYPE_P2P,
+ NM_SUPPL_CAP_TYPE_MESH,
+ NM_SUPPL_CAP_TYPE_WFD,
+ NM_SUPPL_CAP_TYPE_FT,
+ NM_SUPPL_CAP_TYPE_SHA384,
+ _NM_SUPPL_CAP_TYPE_NUM,
+} NMSupplCapType;
+
+#define NM_SUPPL_CAP_MASK_NO(type) ((NMSupplCapMask) (1llu << ((type) * 2u)))
+#define NM_SUPPL_CAP_MASK_YES(type) ((NMSupplCapMask) (2llu << ((type) * 2u)))
+#define NM_SUPPL_CAP_MASK_MASK(type) ((NMSupplCapMask) (3llu << ((type) * 2u)))
+
+typedef enum {
+ NM_SUPPL_CAP_MASK_NONE = 0,
+ NM_SUPPL_CAP_MASK_ALL = ((1llu << (_NM_SUPPL_CAP_TYPE_NUM * 2)) - 1),
+
+/* usually it's bad to use macros to define enum values (because you cannot find them with ctags/cscope
+ * anymore. In this case, still do it because the alternative is ugly too. */
+#define _NM_SUPPL_CAP_MASK_DEFINE(type) \
+ NM_SUPPL_CAP_MASK_##type##_NO = (1llu << ((NM_SUPPL_CAP_TYPE_##type) * 2u)), \
+ NM_SUPPL_CAP_MASK_##type##_YES = (2llu << ((NM_SUPPL_CAP_TYPE_##type) * 2u)), \
+ NM_SUPPL_CAP_MASK_##type##_MASK = (3llu << ((NM_SUPPL_CAP_TYPE_##type) * 2u))
+ _NM_SUPPL_CAP_MASK_DEFINE (AP),
+ _NM_SUPPL_CAP_MASK_DEFINE (FAST),
+ _NM_SUPPL_CAP_MASK_DEFINE (PMF),
+ _NM_SUPPL_CAP_MASK_DEFINE (FILS),
+ _NM_SUPPL_CAP_MASK_DEFINE (P2P),
+ _NM_SUPPL_CAP_MASK_DEFINE (MESH),
+ _NM_SUPPL_CAP_MASK_DEFINE (WFD),
+ _NM_SUPPL_CAP_MASK_DEFINE (FT),
+ _NM_SUPPL_CAP_MASK_DEFINE (SHA384),
+#undef _NM_SUPPL_CAP_MASK_DEFINE
+} NMSupplCapMask;
+
+typedef enum {
NM_SUPPLICANT_FEATURE_UNKNOWN = 0, /* Can't detect whether supported or not */
NM_SUPPLICANT_FEATURE_NO = 1, /* Feature definitely not supported */
NM_SUPPLICANT_FEATURE_YES = 2, /* Feature definitely supported */
} NMSupplicantFeature;
+static inline NMTernary
+nm_supplicant_feature_to_ternary (NMSupplicantFeature value)
+{
+ switch (value) {
+ case NM_SUPPLICANT_FEATURE_NO: return NM_TERNARY_FALSE;
+ case NM_SUPPLICANT_FEATURE_YES: return NM_TERNARY_TRUE;
+ default: return NM_TERNARY_DEFAULT;
+ }
+}
+
+static inline NMSupplCapMask
+NM_SUPPL_CAP_MASK_SET (NMSupplCapMask features, NMSupplCapType type, NMTernary value)
+{
+ nm_assert (_NM_INT_NOT_NEGATIVE (type));
+ nm_assert (type < _NM_SUPPL_CAP_TYPE_NUM);
+ nm_assert (NM_IN_SET (value, NM_TERNARY_DEFAULT,
+ NM_TERNARY_TRUE,
+ NM_TERNARY_FALSE));
+
+ features &= ~NM_SUPPL_CAP_MASK_MASK (type);
+ switch (value) {
+ case NM_TERNARY_FALSE:
+ features |= NM_SUPPL_CAP_MASK_NO (type);
+ break;
+ case NM_TERNARY_TRUE:
+ features |= NM_SUPPL_CAP_MASK_YES (type);
+ break;
+ case NM_TERNARY_DEFAULT:
+ break;
+ }
+
+ return features;
+}
+
+static inline NMTernary
+NM_SUPPL_CAP_MASK_GET (NMSupplCapMask features, NMSupplCapType type)
+{
+ int f;
+
+ nm_assert (_NM_INT_NOT_NEGATIVE (type));
+ nm_assert (type < _NM_SUPPL_CAP_TYPE_NUM);
+
+ f = ((int) (features >> (2 * (int) type))) & 0x3;
+
+ nm_assert (NM_IN_SET (f, 0, 1, 2));
+
+ return (NMTernary) (f - 1);
+}
+
/**
* NMSupplicantError:
* @NM_SUPPLICANT_ERROR_UNKNOWN: unknown or unclassified error
diff --git a/src/supplicant/tests/test-supplicant-config.c b/src/supplicant/tests/test-supplicant-config.c
index 008735b423..7201660743 100644
--- a/src/supplicant/tests/test-supplicant-config.c
+++ b/src/supplicant/tests/test-supplicant-config.c
@@ -621,6 +621,43 @@ test_wifi_eap_fils_disabled (void)
validate_opt ("wifi-eap", config_dict, "bgscan", TYPE_BYTES, bgscan);
}
+/*****************************************************************************/
+
+static void
+test_suppl_cap_mask (void)
+{
+ NMSupplCapType type;
+
+ g_assert_cmpint (NM_SUPPL_CAP_MASK_GET (NM_SUPPL_CAP_MASK_AP_NO, NM_SUPPL_CAP_TYPE_AP), ==, NM_TERNARY_FALSE);
+ g_assert_cmpint (NM_SUPPL_CAP_MASK_GET (NM_SUPPL_CAP_MASK_AP_YES, NM_SUPPL_CAP_TYPE_AP), ==, NM_TERNARY_TRUE);
+ g_assert_cmpint (NM_SUPPL_CAP_MASK_GET (NM_SUPPL_CAP_MASK_NONE, NM_SUPPL_CAP_TYPE_AP), ==, NM_TERNARY_DEFAULT);
+
+ g_assert_cmpint (NM_SUPPL_CAP_MASK_GET (NM_SUPPL_CAP_MASK_FILS_NO, NM_SUPPL_CAP_TYPE_FILS), ==, NM_TERNARY_FALSE);
+ g_assert_cmpint (NM_SUPPL_CAP_MASK_GET (NM_SUPPL_CAP_MASK_FILS_YES, NM_SUPPL_CAP_TYPE_FILS), ==, NM_TERNARY_TRUE);
+ g_assert_cmpint (NM_SUPPL_CAP_MASK_GET (NM_SUPPL_CAP_MASK_NONE, NM_SUPPL_CAP_TYPE_FILS), ==, NM_TERNARY_DEFAULT);
+
+ for (type = 0; type < _NM_SUPPL_CAP_TYPE_NUM; type++) {
+ NMTernary value;
+ NMSupplCapType feature;
+ NMSupplCapType feature2;
+
+ feature = nmtst_get_rand_bool ()
+ ? 0u
+ : nmtst_get_rand_uint64 ();
+
+ value = nmtst_rand_select (NM_TERNARY_DEFAULT,
+ NM_TERNARY_FALSE,
+ NM_TERNARY_TRUE);
+
+ feature2 = NM_SUPPL_CAP_MASK_SET (feature, type, value);
+
+ g_assert_cmpint (NM_SUPPL_CAP_MASK_GET (feature2, type), ==, value);
+ g_assert_cmpint (feature & ~NM_SUPPL_CAP_MASK_MASK (type), ==, feature2 & ~NM_SUPPL_CAP_MASK_MASK (type));
+ }
+}
+
+/*****************************************************************************/
+
NMTST_DEFINE ();
int main (int argc, char **argv)
@@ -634,6 +671,7 @@ int main (int argc, char **argv)
g_test_add_func ("/supplicant-config/wifi-eap/unlocked-bssid", test_wifi_eap_unlocked_bssid);
g_test_add_func ("/supplicant-config/wifi-eap/fils-disabled", test_wifi_eap_fils_disabled);
g_test_add_func ("/supplicant-config/wifi-sae", test_wifi_sae);
+ g_test_add_func ("/supplicant-config/test_suppl_cap_mask", test_suppl_cap_mask);
return g_test_run ();
}