git: 06cf36516512 - main - netlink: provide genl_unregister_group()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 05 Feb 2025 18:09:21 UTC
The branch main has been updated by glebius:
URL: https://cgit.FreeBSD.org/src/commit/?id=06cf36516512015867ceb56bde7913b1dc51ef3c
commit 06cf36516512015867ceb56bde7913b1dc51ef3c
Author: Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-02-05 18:09:06 +0000
Commit: Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-02-05 18:09:06 +0000
netlink: provide genl_unregister_group()
Cause generic netlink group IDs are dynamic, we go through all sockets
and unsubscribe from the group that goes away. Otherwise they could be
surprisingly find themselves subscribed to a group created later.
---
sys/netlink/netlink_ctl.h | 1 +
sys/netlink/netlink_domain.c | 12 ++++++++++++
sys/netlink/netlink_generic.c | 26 ++++++++++++++++++++++++++
sys/netlink/netlink_var.h | 1 +
4 files changed, 40 insertions(+)
diff --git a/sys/netlink/netlink_ctl.h b/sys/netlink/netlink_ctl.h
index e7566552ea32..7f43e0f2c25e 100644
--- a/sys/netlink/netlink_ctl.h
+++ b/sys/netlink/netlink_ctl.h
@@ -97,6 +97,7 @@ void genl_unregister_family(uint16_t family);
bool genl_register_cmds(uint16_t family, const struct genl_cmd *cmds,
u_int count);
uint32_t genl_register_group(uint16_t family, const char *group_name);
+void genl_unregister_group(uint16_t family, uint32_t group);
typedef void (*genl_family_event_handler_t)(void *arg, const char *family_name,
uint16_t family_id, u_int action);
diff --git a/sys/netlink/netlink_domain.c b/sys/netlink/netlink_domain.c
index e06c0bf1919e..7fabb222665e 100644
--- a/sys/netlink/netlink_domain.c
+++ b/sys/netlink/netlink_domain.c
@@ -250,6 +250,18 @@ nl_send_group(struct nl_writer *nw)
return (true);
}
+void
+nl_clear_group(u_int group)
+{
+ struct nlpcb *nlp;
+
+ NLCTL_WLOCK();
+ CK_LIST_FOREACH(nlp, &V_nl_ctl.ctl_pcb_head, nl_next)
+ if (nlp_memberof_group(nlp, group))
+ nlp_leave_group(nlp, group);
+ NLCTL_WUNLOCK();
+}
+
static uint32_t
nl_find_port(void)
{
diff --git a/sys/netlink/netlink_generic.c b/sys/netlink/netlink_generic.c
index 0714f22382cb..00f47e60f013 100644
--- a/sys/netlink/netlink_generic.c
+++ b/sys/netlink/netlink_generic.c
@@ -497,3 +497,29 @@ genl_register_group(uint16_t family_id, const char *group_name)
return (group_id);
}
+
+void
+genl_unregister_group(uint16_t family_id, uint32_t group_id)
+{
+ struct genl_family *gf;
+ struct genl_group *gg;
+
+ MPASS(group_id > MIN_GROUP_NUM &&
+ group_id < MIN_GROUP_NUM + MAX_GROUPS);
+
+ nl_clear_group(group_id);
+
+ group_id -= MIN_GROUP_NUM;
+
+ GENL_LOCK();
+ gf = genl_family(family_id);
+ gg = &groups[group_id];
+
+ MPASS(gg->group_family == gf);
+ MPASS(gf->family_num_groups > 0);
+
+ gf->family_num_groups--;
+ gg->group_family = NULL;
+ gg->group_name = NULL;
+ GENL_UNLOCK();
+}
diff --git a/sys/netlink/netlink_var.h b/sys/netlink/netlink_var.h
index a59cb2efecd0..23e7395d44c2 100644
--- a/sys/netlink/netlink_var.h
+++ b/sys/netlink/netlink_var.h
@@ -121,6 +121,7 @@ extern struct nl_proto_handler *nl_handlers;
/* netlink_domain.c */
bool nl_send_group(struct nl_writer *);
+void nl_clear_group(u_int);
void nl_osd_register(void);
void nl_osd_unregister(void);
void nl_set_thread_nlp(struct thread *td, struct nlpcb *nlp);