summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-07-07 12:55:50 +0200
committerThomas Haller <thaller@redhat.com>2022-07-19 12:33:50 +0200
commit3b58404712425093b40d36fe52cd6935d8bb94f6 (patch)
treeb26d39c7a8470e22a8300532db5edf5e18b8a77c
parent9ef02ef7d0e8252a656650bc1426caafec6d906f (diff)
downloadNetworkManager-3b58404712425093b40d36fe52cd6935d8bb94f6.tar.gz
platform: add NMPGenlFamilyType enum for generic netlink types
The genl types that we care about are well known. Add an enum for them, so we can do a lookup by index. To kernel, the corresponding names (like "wireguard") are also well known. However, the family-id, that we need when using genl are allocated dynamically. So we need to lookup the family-id, and by having an enum for the genl type, we can do so generically.
-rw-r--r--src/core/platform/tests/test-platform-general.c60
-rw-r--r--src/libnm-platform/nm-platform.c70
-rw-r--r--src/libnm-platform/nm-platform.h19
3 files changed, 149 insertions, 0 deletions
diff --git a/src/core/platform/tests/test-platform-general.c b/src/core/platform/tests/test-platform-general.c
index 908ad4dd3e..c18886c96e 100644
--- a/src/core/platform/tests/test-platform-general.c
+++ b/src/core/platform/tests/test-platform-general.c
@@ -788,6 +788,64 @@ test_route_type_is_nodev(void)
/*****************************************************************************/
+static void
+test_nmp_genl_family_type_from_name(void)
+{
+ int n_run;
+ int i;
+
+ for (i = 0; i < (int) _NMP_GENL_FAMILY_TYPE_NUM; i++) {
+ const char *name = nmp_genl_family_infos[i].name;
+
+ g_assert(name);
+ if (i > 0)
+ g_assert_cmpint(strcmp(nmp_genl_family_infos[i - 1].name, name), <, 0);
+ }
+
+ g_assert_cmpint(nmp_genl_family_type_from_name("ethtool"), ==, NMP_GENL_FAMILY_TYPE_ETHTOOL);
+ g_assert_cmpint(nmp_genl_family_type_from_name("mptcp_pm"), ==, NMP_GENL_FAMILY_TYPE_MPTCP_PM);
+ g_assert_cmpint(nmp_genl_family_type_from_name("nl80211"), ==, NMP_GENL_FAMILY_TYPE_NL80211);
+ g_assert_cmpint(nmp_genl_family_type_from_name("nl802154"), ==, NMP_GENL_FAMILY_TYPE_NL802154);
+ g_assert_cmpint(nmp_genl_family_type_from_name("wireguard"),
+ ==,
+ NMP_GENL_FAMILY_TYPE_WIREGUARD);
+
+ g_assert_cmpint(nmp_genl_family_type_from_name(NULL), ==, _NMP_GENL_FAMILY_TYPE_NONE);
+ g_assert_cmpint(nmp_genl_family_type_from_name("a"), ==, _NMP_GENL_FAMILY_TYPE_NONE);
+ g_assert_cmpint(nmp_genl_family_type_from_name("wireguara"), ==, _NMP_GENL_FAMILY_TYPE_NONE);
+ g_assert_cmpint(nmp_genl_family_type_from_name("wireguarb"), ==, _NMP_GENL_FAMILY_TYPE_NONE);
+ g_assert_cmpint(nmp_genl_family_type_from_name(""), ==, _NMP_GENL_FAMILY_TYPE_NONE);
+ g_assert_cmpint(nmp_genl_family_type_from_name("z"), ==, _NMP_GENL_FAMILY_TYPE_NONE);
+
+ for (n_run = 0; n_run < 20; n_run++) {
+ for (i = 0; i < (int) _NMP_GENL_FAMILY_TYPE_NUM; i++) {
+ const char *cname = nmp_genl_family_infos[i].name;
+ const int ch_idx = nmtst_get_rand_uint() % strlen(cname);
+ char name[200];
+ char ch;
+ gsize l;
+
+ l = g_strlcpy(name, cname, sizeof(name));
+ g_assert_cmpint(l, <, sizeof(name));
+
+ if (n_run == 0) {
+ g_assert_cmpint(nmp_genl_family_type_from_name(cname), ==, i);
+ g_assert_cmpint(nmp_genl_family_type_from_name(name), ==, i);
+ }
+
+ /* randomly change one character in the name. Such a name becomes invalid.
+ * There are no two valid names which only differ by one characters. */
+ do {
+ ch = nmtst_get_rand_uint() % 256;
+ } while (cname[ch_idx] == ch);
+ name[ch_idx] = ch;
+ g_assert_cmpint(nmp_genl_family_type_from_name(name), ==, _NMP_GENL_FAMILY_TYPE_NONE);
+ }
+ }
+}
+
+/*****************************************************************************/
+
NMTST_DEFINE();
int
@@ -808,6 +866,8 @@ main(int argc, char **argv)
GINT_TO_POINTER(2),
test_platform_ip_address_pretty_sort_cmp);
g_test_add_func("/general/test_route_type_is_nodev", test_route_type_is_nodev);
+ g_test_add_func("/nm-platform/test_nmp_genl_family_type_from_name",
+ test_nmp_genl_family_type_from_name);
return g_test_run();
}
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 50204abc5f..ab21f3f289 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -395,6 +395,76 @@ _nm_platform_kernel_support_init(NMPlatformKernelSupportType type, int value)
/*****************************************************************************/
+const NMPGenlFamilyInfo nmp_genl_family_infos[_NMP_GENL_FAMILY_TYPE_NUM] = {
+ [NMP_GENL_FAMILY_TYPE_ETHTOOL] =
+ {
+ .name = "ethtool",
+ },
+ [NMP_GENL_FAMILY_TYPE_MPTCP_PM] =
+ {
+ .name = "mptcp_pm",
+ },
+ [NMP_GENL_FAMILY_TYPE_NL80211] =
+ {
+ .name = "nl80211",
+ },
+ [NMP_GENL_FAMILY_TYPE_NL802154] =
+ {
+ .name = "nl802154",
+ },
+ [NMP_GENL_FAMILY_TYPE_WIREGUARD] =
+ {
+ .name = "wireguard",
+ },
+};
+
+NMPGenlFamilyType
+nmp_genl_family_type_from_name(const char *name)
+{
+ int imin, imax, imid;
+
+ if (NM_MORE_ASSERT_ONCE(50)) {
+ int i;
+
+ for (i = 0; i < (int) G_N_ELEMENTS(nmp_genl_family_infos); i++) {
+ nm_assert(nmp_genl_family_infos[i].name);
+ if (i > 0)
+ nm_assert(strcmp(nmp_genl_family_infos[i - 1].name, nmp_genl_family_infos[i].name)
+ < 0);
+ }
+ }
+
+ if (!name)
+ goto out;
+
+ imin = 0;
+ imax = G_N_ELEMENTS(nmp_genl_family_infos) - 1;
+ imid = imax / 2;
+
+ while (TRUE) {
+ int c;
+
+ c = strcmp(nmp_genl_family_infos[imid].name, name);
+ if (c == 0)
+ return (NMPGenlFamilyType) imid;
+
+ if (c < 0)
+ imin = imid + 1;
+ else
+ imax = imid - 1;
+
+ if (imin > imax)
+ break;
+
+ imid = (imax + imin) / 2;
+ }
+
+out:
+ return _NMP_GENL_FAMILY_TYPE_NONE;
+}
+
+/*****************************************************************************/
+
/**
* nm_platform_process_events:
* @self: platform instance
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index b921a2f562..e940f43b60 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -1103,6 +1103,25 @@ nm_platform_kernel_support_get(NMPlatformKernelSupportType type)
return nm_platform_kernel_support_get_full(type, TRUE) != NM_OPTION_BOOL_FALSE;
}
+typedef enum {
+ NMP_GENL_FAMILY_TYPE_ETHTOOL,
+ NMP_GENL_FAMILY_TYPE_MPTCP_PM,
+ NMP_GENL_FAMILY_TYPE_NL80211,
+ NMP_GENL_FAMILY_TYPE_NL802154,
+ NMP_GENL_FAMILY_TYPE_WIREGUARD,
+
+ _NMP_GENL_FAMILY_TYPE_NUM,
+ _NMP_GENL_FAMILY_TYPE_NONE = _NMP_GENL_FAMILY_TYPE_NUM,
+} NMPGenlFamilyType;
+
+typedef struct {
+ const char *name;
+} NMPGenlFamilyInfo;
+
+extern const NMPGenlFamilyInfo nmp_genl_family_infos[_NMP_GENL_FAMILY_TYPE_NUM];
+
+NMPGenlFamilyType nmp_genl_family_type_from_name(const char *name);
+
/*****************************************************************************/
struct _NMPlatformPrivate;