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);