aboutsummaryrefslogtreecommitdiff
path: root/sys/netlink
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2023-03-27 10:48:24 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2023-03-27 10:48:24 +0000
commit544f1492c026f358507d812b63943eea08d3155d (patch)
tree4c9e8a54246e31ddb8b1700be3cb31a3c0f32d5e /sys/netlink
parente8988d60d24b05e98919e912329880a54cdfdd70 (diff)
downloadsrc-544f1492c026f358507d812b63943eea08d3155d.tar.gz
src-544f1492c026f358507d812b63943eea08d3155d.zip
netlink: ensure genetlink control family always registers under the same ID.
MFC after: 2 weeks
Diffstat (limited to 'sys/netlink')
-rw-r--r--sys/netlink/netlink_generic.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/sys/netlink/netlink_generic.c b/sys/netlink/netlink_generic.c
index a2bd624f99d9..16b49d5aa9ce 100644
--- a/sys/netlink/netlink_generic.c
+++ b/sys/netlink/netlink_generic.c
@@ -47,6 +47,8 @@ __FBSDID("$FreeBSD$");
#include <netlink/netlink_debug.h>
_DECLARE_DEBUG(LOG_DEBUG);
+#define CTRL_FAMILY_NAME "nlctrl"
+
#define MAX_FAMILIES 20
#define MAX_GROUPS 64
@@ -96,6 +98,28 @@ find_family(const char *family_name)
return (NULL);
}
+static struct genl_family *
+find_empty_family_id(const char *family_name)
+{
+ struct genl_family *gf = NULL;
+
+ if (!strcmp(family_name, CTRL_FAMILY_NAME)) {
+ gf = &families[0];
+ gf->family_id = GENL_MIN_ID;
+ } else {
+ /* Index 0 is reserved for the control family */
+ for (int i = 1; i < MAX_FAMILIES; i++) {
+ struct genl_family *gf = &families[i];
+ if (gf->family_name == NULL) {
+ gf->family_id = GENL_MIN_ID + i;
+ break;
+ }
+ }
+ }
+
+ return (gf);
+}
+
uint32_t
genl_register_family(const char *family_name, size_t hdrsize, int family_version,
int max_attr_idx)
@@ -107,21 +131,18 @@ genl_register_family(const char *family_name, size_t hdrsize, int family_version
return (0);
GENL_LOCK();
- for (int i = 0; i < MAX_FAMILIES; i++) {
- struct genl_family *gf = &families[i];
- if (gf->family_name == NULL) {
- gf->family_name = family_name;
- gf->family_version = family_version;
- gf->family_hdrsize = hdrsize;
- gf->family_attr_max = max_attr_idx;
- gf->family_id = i + GENL_MIN_ID;
- NL_LOG(LOG_DEBUG2, "Registered family %s id %d",
- gf->family_name, gf->family_id);
- family_id = gf->family_id;
- nlctrl_notify(gf, CTRL_CMD_NEWFAMILY);
- break;
- }
- }
+
+ struct genl_family *gf = find_empty_family_id(family_name);
+ MPASS(gf != NULL);
+
+ gf->family_name = family_name;
+ gf->family_version = family_version;
+ gf->family_hdrsize = hdrsize;
+ gf->family_attr_max = max_attr_idx;
+ NL_LOG(LOG_DEBUG2, "Registered family %s id %d", gf->family_name, gf->family_id);
+ family_id = gf->family_id;
+ nlctrl_notify(gf, CTRL_CMD_NEWFAMILY);
+
GENL_UNLOCK();
return (family_id);
@@ -377,7 +398,6 @@ enomem:
/* Declare ourself as a user */
-#define CTRL_FAMILY_NAME "nlctrl"
static uint32_t ctrl_family_id;
static uint32_t ctrl_group_id;