^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * NETLINK Generic Netlink Family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Authors: Jamal Hadi Salim
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Thomas Graf <tgraf@suug.ch>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Johannes Berg <johannes@sipsolutions.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/bitmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/rwsem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/idr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static DECLARE_RWSEM(cb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) atomic_t genl_sk_destructing_cnt = ATOMIC_INIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) DECLARE_WAIT_QUEUE_HEAD(genl_sk_destructing_waitq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) void genl_lock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) mutex_lock(&genl_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) EXPORT_SYMBOL(genl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) void genl_unlock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) mutex_unlock(&genl_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) EXPORT_SYMBOL(genl_unlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #ifdef CONFIG_LOCKDEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) bool lockdep_genl_is_held(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return lockdep_is_held(&genl_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) EXPORT_SYMBOL(lockdep_genl_is_held);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static void genl_lock_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) down_write(&cb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) genl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static void genl_unlock_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) genl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) up_write(&cb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static DEFINE_IDR(genl_fam_idr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Bitmap of multicast groups that are currently in use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * To avoid an allocation at boot of just one unsigned long,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * declare it global instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * Bit 0 is marked as already used since group 0 is invalid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * Bit 1 is marked as already used since the drop-monitor code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * abuses the API and thinks it can statically use group 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * That group will typically conflict with other groups that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * any proper users use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * Bit 16 is marked as used since it's used for generic netlink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * and the code no longer marks pre-reserved IDs as used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * Bit 17 is marked as already used since the VFS quota code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * also abused this API and relied on family == group ID, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * cater to that by giving it a static family and group ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * Bit 18 is marked as already used since the PMCRAID driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * did the same thing as the VFS quota code (maybe copied?)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) BIT(GENL_ID_VFS_DQUOT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) BIT(GENL_ID_PMCRAID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static unsigned long *mc_groups = &mc_group_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static unsigned long mc_groups_longs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static int genl_ctrl_event(int event, const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) const struct genl_multicast_group *grp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int grp_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static const struct genl_family *genl_family_find_byid(unsigned int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return idr_find(&genl_fam_idr, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static const struct genl_family *genl_family_find_byname(char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) const struct genl_family *family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) idr_for_each_entry(&genl_fam_idr, family, id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (strcmp(family->name, name) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int genl_get_cmd_cnt(const struct genl_family *family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return family->n_ops + family->n_small_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static void genl_op_from_full(const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned int i, struct genl_ops *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *op = family->ops[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (!op->maxattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) op->maxattr = family->maxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (!op->policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) op->policy = family->policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int genl_get_cmd_full(u32 cmd, const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct genl_ops *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) for (i = 0; i < family->n_ops; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (family->ops[i].cmd == cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) genl_op_from_full(family, i, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static void genl_op_from_small(const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int i, struct genl_ops *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) memset(op, 0, sizeof(*op));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) op->doit = family->small_ops[i].doit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) op->dumpit = family->small_ops[i].dumpit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) op->cmd = family->small_ops[i].cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) op->internal_flags = family->small_ops[i].internal_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) op->flags = family->small_ops[i].flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) op->validate = family->small_ops[i].validate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) op->maxattr = family->maxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) op->policy = family->policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static int genl_get_cmd_small(u32 cmd, const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct genl_ops *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) for (i = 0; i < family->n_small_ops; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (family->small_ops[i].cmd == cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) genl_op_from_small(family, i, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static int genl_get_cmd(u32 cmd, const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct genl_ops *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (!genl_get_cmd_full(cmd, family, op))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return genl_get_cmd_small(cmd, family, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static void genl_get_cmd_by_index(unsigned int i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct genl_ops *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (i < family->n_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) genl_op_from_full(family, i, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) else if (i < family->n_ops + family->n_small_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) genl_op_from_small(family, i - family->n_ops, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) WARN_ON_ONCE(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int genl_allocate_reserve_groups(int n_groups, int *first_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned long *new_groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) bool fits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (start == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) id = find_first_zero_bit(mc_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) mc_groups_longs *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) BITS_PER_LONG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) id = find_next_zero_bit(mc_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) mc_groups_longs * BITS_PER_LONG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) fits = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) for (i = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) i < min_t(int, id + n_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) mc_groups_longs * BITS_PER_LONG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (test_bit(i, mc_groups)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) start = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) fits = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (id + n_groups > mc_groups_longs * BITS_PER_LONG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned long new_longs = mc_groups_longs +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) BITS_TO_LONGS(n_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) size_t nlen = new_longs * sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (mc_groups == &mc_group_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) new_groups = kzalloc(nlen, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (!new_groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) mc_groups = new_groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) *mc_groups = mc_group_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) new_groups = krealloc(mc_groups, nlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (!new_groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) mc_groups = new_groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) for (i = 0; i < BITS_TO_LONGS(n_groups); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) mc_groups[mc_groups_longs + i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) mc_groups_longs = new_longs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) } while (!fits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) for (i = id; i < id + n_groups; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) set_bit(i, mc_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) *first_id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static struct genl_family genl_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int genl_validate_assign_mc_groups(struct genl_family *family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) int first_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int n_groups = family->n_mcgrps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) int err = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) bool groups_allocated = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (!n_groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) for (i = 0; i < n_groups; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) const struct genl_multicast_group *grp = &family->mcgrps[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (WARN_ON(grp->name[0] == '\0'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (WARN_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* special-case our own group and hacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (family == &genl_ctrl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) first_id = GENL_ID_CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) BUG_ON(n_groups != 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) } else if (strcmp(family->name, "NET_DM") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) first_id = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) BUG_ON(n_groups != 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) } else if (family->id == GENL_ID_VFS_DQUOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) first_id = GENL_ID_VFS_DQUOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) BUG_ON(n_groups != 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) } else if (family->id == GENL_ID_PMCRAID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) first_id = GENL_ID_PMCRAID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) BUG_ON(n_groups != 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) groups_allocated = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) err = genl_allocate_reserve_groups(n_groups, &first_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) family->mcgrp_offset = first_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /* if still initializing, can't and don't need to realloc bitmaps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (!init_net.genl_sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (family->netnsok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) netlink_table_grab();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) for_each_net_rcu(net) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) err = __netlink_change_ngroups(net->genl_sock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) mc_groups_longs * BITS_PER_LONG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * No need to roll back, can only fail if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * memory allocation fails and then the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * number of _possible_ groups has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * increased on some sockets which is ok.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) netlink_table_ungrab();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) err = netlink_change_ngroups(init_net.genl_sock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) mc_groups_longs * BITS_PER_LONG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (groups_allocated && err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) for (i = 0; i < family->n_mcgrps; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) clear_bit(family->mcgrp_offset + i, mc_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static void genl_unregister_mc_groups(const struct genl_family *family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) netlink_table_grab();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) for_each_net_rcu(net) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) for (i = 0; i < family->n_mcgrps; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) __netlink_clear_multicast_users(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) net->genl_sock, family->mcgrp_offset + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) netlink_table_ungrab();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) for (i = 0; i < family->n_mcgrps; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) int grp_id = family->mcgrp_offset + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (grp_id != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) clear_bit(grp_id, mc_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) &family->mcgrps[i], grp_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static int genl_validate_ops(const struct genl_family *family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (WARN_ON(family->n_ops && !family->ops) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) WARN_ON(family->n_small_ops && !family->small_ops))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) for (i = 0; i < genl_get_cmd_cnt(family); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct genl_ops op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) genl_get_cmd_by_index(i, family, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (op.dumpit == NULL && op.doit == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) for (j = i + 1; j < genl_get_cmd_cnt(family); j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct genl_ops op2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) genl_get_cmd_by_index(j, family, &op2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (op.cmd == op2.cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * genl_register_family - register a generic netlink family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * @family: generic netlink family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * Registers the specified family after validating it first. Only one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * family may be registered with the same family name or identifier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * The family's ops, multicast groups and module pointer must already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * be assigned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * Return 0 on success or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) int genl_register_family(struct genl_family *family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int start = GENL_START_ALLOC, end = GENL_MAX_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) err = genl_validate_ops(family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) genl_lock_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (genl_family_find_byname(family->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) err = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) goto errout_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * Sadly, a few cases need to be special-cased
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * due to them having previously abused the API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * and having used their family ID also as their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * multicast group ID, so we use reserved IDs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * for both to be sure we can do that mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (family == &genl_ctrl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /* and this needs to be special for initial family lookups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) start = end = GENL_ID_CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) } else if (strcmp(family->name, "pmcraid") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) start = end = GENL_ID_PMCRAID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) } else if (strcmp(family->name, "VFS_DQUOT") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) start = end = GENL_ID_VFS_DQUOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) family->id = idr_alloc_cyclic(&genl_fam_idr, family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) start, end + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (family->id < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) err = family->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) goto errout_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) err = genl_validate_assign_mc_groups(family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) goto errout_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) genl_unlock_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /* send all events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) genl_ctrl_event(CTRL_CMD_NEWFAMILY, family, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) for (i = 0; i < family->n_mcgrps; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) genl_ctrl_event(CTRL_CMD_NEWMCAST_GRP, family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) &family->mcgrps[i], family->mcgrp_offset + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) errout_remove:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) idr_remove(&genl_fam_idr, family->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) errout_locked:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) genl_unlock_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) EXPORT_SYMBOL(genl_register_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * genl_unregister_family - unregister generic netlink family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * @family: generic netlink family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * Unregisters the specified family.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * Returns 0 on success or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) int genl_unregister_family(const struct genl_family *family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) genl_lock_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (!genl_family_find_byid(family->id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) genl_unlock_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) genl_unregister_mc_groups(family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) idr_remove(&genl_fam_idr, family->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) up_write(&cb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) wait_event(genl_sk_destructing_waitq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) atomic_read(&genl_sk_destructing_cnt) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) genl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) EXPORT_SYMBOL(genl_unregister_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * genlmsg_put - Add generic netlink header to netlink message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * @skb: socket buffer holding the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * @portid: netlink portid the message is addressed to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * @seq: sequence number (usually the one of the sender)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * @family: generic netlink family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * @flags: netlink message flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * @cmd: generic netlink command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * Returns pointer to user specific header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) const struct genl_family *family, int flags, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct nlmsghdr *nlh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct genlmsghdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) nlh = nlmsg_put(skb, portid, seq, family->id, GENL_HDRLEN +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) family->hdrsize, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (nlh == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) hdr = nlmsg_data(nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) hdr->cmd = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) hdr->version = family->version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) hdr->reserved = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return (char *) hdr + GENL_HDRLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) EXPORT_SYMBOL(genlmsg_put);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static struct genl_dumpit_info *genl_dumpit_info_alloc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return kmalloc(sizeof(struct genl_dumpit_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static void genl_dumpit_info_free(const struct genl_dumpit_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) kfree(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static struct nlattr **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) genl_family_rcv_msg_attrs_parse(const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct nlmsghdr *nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct netlink_ext_ack *extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) const struct genl_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) int hdrlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) enum genl_validate_flags no_strict_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) enum netlink_validation validate = ops->validate & no_strict_flag ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) NL_VALIDATE_LIBERAL :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) NL_VALIDATE_STRICT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) struct nlattr **attrbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (!ops->maxattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) attrbuf = kmalloc_array(ops->maxattr + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) sizeof(struct nlattr *), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (!attrbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) err = __nlmsg_parse(nlh, hdrlen, attrbuf, ops->maxattr, ops->policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) validate, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) kfree(attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return attrbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static void genl_family_rcv_msg_attrs_free(struct nlattr **attrbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) kfree(attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct genl_start_context {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) const struct genl_family *family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) struct nlmsghdr *nlh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) struct netlink_ext_ack *extack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) const struct genl_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) int hdrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static int genl_start(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) struct genl_start_context *ctx = cb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) const struct genl_ops *ops = ctx->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) struct genl_dumpit_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) struct nlattr **attrs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (ops->validate & GENL_DONT_VALIDATE_DUMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) goto no_attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (ctx->nlh->nlmsg_len < nlmsg_msg_size(ctx->hdrlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) attrs = genl_family_rcv_msg_attrs_parse(ctx->family, ctx->nlh, ctx->extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) ops, ctx->hdrlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) GENL_DONT_VALIDATE_DUMP_STRICT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (IS_ERR(attrs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return PTR_ERR(attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) no_attrs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) info = genl_dumpit_info_alloc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (!info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) genl_family_rcv_msg_attrs_free(attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) info->family = ctx->family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) info->op = *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) info->attrs = attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) cb->data = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (ops->start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (!ctx->family->parallel_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) genl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) rc = ops->start(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (!ctx->family->parallel_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) genl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) genl_family_rcv_msg_attrs_free(info->attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) genl_dumpit_info_free(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) cb->data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) const struct genl_ops *ops = &genl_dumpit_info(cb)->op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) genl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) rc = ops->dumpit(skb, cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) genl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) static int genl_lock_done(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) const struct genl_dumpit_info *info = genl_dumpit_info(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) const struct genl_ops *ops = &info->op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (ops->done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) genl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) rc = ops->done(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) genl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) genl_family_rcv_msg_attrs_free(info->attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) genl_dumpit_info_free(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) static int genl_parallel_done(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) const struct genl_dumpit_info *info = genl_dumpit_info(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) const struct genl_ops *ops = &info->op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (ops->done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) rc = ops->done(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) genl_family_rcv_msg_attrs_free(info->attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) genl_dumpit_info_free(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) struct nlmsghdr *nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct netlink_ext_ack *extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) const struct genl_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) int hdrlen, struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct genl_start_context ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (!ops->dumpit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) ctx.family = family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) ctx.nlh = nlh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) ctx.extack = extack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) ctx.ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) ctx.hdrlen = hdrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (!family->parallel_ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) struct netlink_dump_control c = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) .module = family->module,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) .data = &ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) .start = genl_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) .dump = genl_lock_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) .done = genl_lock_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) genl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) err = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) genl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct netlink_dump_control c = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) .module = family->module,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) .data = &ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) .start = genl_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) .dump = ops->dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) .done = genl_parallel_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) err = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) static int genl_family_rcv_msg_doit(const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct nlmsghdr *nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) struct netlink_ext_ack *extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) const struct genl_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) int hdrlen, struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct nlattr **attrbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) struct genl_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (!ops->doit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) attrbuf = genl_family_rcv_msg_attrs_parse(family, nlh, extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) ops, hdrlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) GENL_DONT_VALIDATE_STRICT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (IS_ERR(attrbuf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return PTR_ERR(attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) info.snd_seq = nlh->nlmsg_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) info.snd_portid = NETLINK_CB(skb).portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) info.nlhdr = nlh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) info.genlhdr = nlmsg_data(nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) info.attrs = attrbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) info.extack = extack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) genl_info_net_set(&info, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) memset(&info.user_ptr, 0, sizeof(info.user_ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (family->pre_doit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) err = family->pre_doit(ops, skb, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) err = ops->doit(skb, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (family->post_doit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) family->post_doit(ops, skb, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) genl_family_rcv_msg_attrs_free(attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static int genl_family_rcv_msg(const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) struct nlmsghdr *nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) struct genlmsghdr *hdr = nlmsg_data(nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) struct genl_ops op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) int hdrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) /* this family doesn't exist in this netns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (!family->netnsok && !net_eq(net, &init_net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) hdrlen = GENL_HDRLEN + family->hdrsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (genl_get_cmd(hdr->cmd, family, &op))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if ((op.flags & GENL_ADMIN_PERM) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) !netlink_capable(skb, CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if ((op.flags & GENL_UNS_ADMIN_PERM) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return genl_family_rcv_msg_dumpit(family, skb, nlh, extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) &op, hdrlen, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return genl_family_rcv_msg_doit(family, skb, nlh, extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) &op, hdrlen, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) const struct genl_family *family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) family = genl_family_find_byid(nlh->nlmsg_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (family == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (!family->parallel_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) genl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) err = genl_family_rcv_msg(family, skb, nlh, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (!family->parallel_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) genl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) static void genl_rcv(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) down_read(&cb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) netlink_rcv_skb(skb, &genl_rcv_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) up_read(&cb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) /**************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * Controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) **************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static struct genl_family genl_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static int ctrl_fill_info(const struct genl_family *family, u32 portid, u32 seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) u32 flags, struct sk_buff *skb, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) hdr = genlmsg_put(skb, portid, seq, &genl_ctrl, flags, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (hdr == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (nla_put_string(skb, CTRL_ATTR_FAMILY_NAME, family->name) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, family->id) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) nla_put_u32(skb, CTRL_ATTR_VERSION, family->version) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) nla_put_u32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) nla_put_u32(skb, CTRL_ATTR_MAXATTR, family->maxattr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (genl_get_cmd_cnt(family)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) struct nlattr *nla_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) nla_ops = nla_nest_start_noflag(skb, CTRL_ATTR_OPS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (nla_ops == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) for (i = 0; i < genl_get_cmd_cnt(family); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) struct nlattr *nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) struct genl_ops op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) u32 op_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) genl_get_cmd_by_index(i, family, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) op_flags = op.flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (op.dumpit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) op_flags |= GENL_CMD_CAP_DUMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (op.doit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) op_flags |= GENL_CMD_CAP_DO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (op.policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) op_flags |= GENL_CMD_CAP_HASPOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) nest = nla_nest_start_noflag(skb, i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (nest == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (nla_put_u32(skb, CTRL_ATTR_OP_ID, op.cmd) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) nla_put_u32(skb, CTRL_ATTR_OP_FLAGS, op_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) nla_nest_end(skb, nla_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (family->n_mcgrps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct nlattr *nla_grps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) nla_grps = nla_nest_start_noflag(skb, CTRL_ATTR_MCAST_GROUPS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (nla_grps == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) for (i = 0; i < family->n_mcgrps; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) struct nlattr *nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) const struct genl_multicast_group *grp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) grp = &family->mcgrps[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) nest = nla_nest_start_noflag(skb, i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (nest == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) family->mcgrp_offset + i) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) grp->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) nla_nest_end(skb, nla_grps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static int ctrl_fill_mcgrp_info(const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) const struct genl_multicast_group *grp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) int grp_id, u32 portid, u32 seq, u32 flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) struct sk_buff *skb, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct nlattr *nla_grps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct nlattr *nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) hdr = genlmsg_put(skb, portid, seq, &genl_ctrl, flags, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (hdr == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (nla_put_string(skb, CTRL_ATTR_FAMILY_NAME, family->name) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, family->id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) nla_grps = nla_nest_start_noflag(skb, CTRL_ATTR_MCAST_GROUPS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (nla_grps == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) nest = nla_nest_start_noflag(skb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (nest == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID, grp_id) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) grp->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) nla_nest_end(skb, nla_grps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) int n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct genl_family *rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) int fams_to_skip = cb->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) unsigned int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) idr_for_each_entry(&genl_fam_idr, rt, id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (!rt->netnsok && !net_eq(net, &init_net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (n++ < fams_to_skip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) cb->nlh->nlmsg_seq, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) skb, CTRL_CMD_NEWFAMILY) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) n--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) cb->args[0] = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) static struct sk_buff *ctrl_build_family_msg(const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) u32 portid, int seq, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return ERR_PTR(-ENOBUFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) err = ctrl_fill_info(family, portid, seq, 0, skb, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) nlmsg_free(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) static struct sk_buff *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) ctrl_build_mcgrp_msg(const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) const struct genl_multicast_group *grp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) int grp_id, u32 portid, int seq, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return ERR_PTR(-ENOBUFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) err = ctrl_fill_mcgrp_info(family, grp, grp_id, portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) seq, 0, skb, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) nlmsg_free(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) static const struct nla_policy ctrl_policy_family[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) .len = GENL_NAMSIZ - 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) const struct genl_family *res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) int err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (info->attrs[CTRL_ATTR_FAMILY_ID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) u16 id = nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) res = genl_family_find_byid(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (info->attrs[CTRL_ATTR_FAMILY_NAME]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) res = genl_family_find_byname(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) #ifdef CONFIG_MODULES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (res == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) genl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) up_read(&cb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) request_module("net-pf-%d-proto-%d-family-%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) PF_NETLINK, NETLINK_GENERIC, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) down_read(&cb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) genl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) res = genl_family_find_byname(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (res == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (!res->netnsok && !net_eq(genl_info_net(info), &init_net)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /* family doesn't exist here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) msg = ctrl_build_family_msg(res, info->snd_portid, info->snd_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) CTRL_CMD_NEWFAMILY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (IS_ERR(msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) return PTR_ERR(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) static int genl_ctrl_event(int event, const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) const struct genl_multicast_group *grp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) int grp_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /* genl is still initialising */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (!init_net.genl_sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) case CTRL_CMD_NEWFAMILY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) case CTRL_CMD_DELFAMILY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) WARN_ON(grp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) msg = ctrl_build_family_msg(family, 0, 0, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) case CTRL_CMD_NEWMCAST_GRP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) case CTRL_CMD_DELMCAST_GRP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) BUG_ON(!grp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) msg = ctrl_build_mcgrp_msg(family, grp, grp_id, 0, 0, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (IS_ERR(msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) return PTR_ERR(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (!family->netnsok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) genlmsg_multicast_netns(&genl_ctrl, &init_net, msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) genlmsg_multicast_allns(&genl_ctrl, msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 0, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) struct ctrl_dump_policy_ctx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) struct netlink_policy_dump_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) const struct genl_family *rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) unsigned int opidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) u32 op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) u16 fam_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) u8 policies:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) single_op:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static const struct nla_policy ctrl_policy_policy[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) .len = GENL_NAMSIZ - 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) [CTRL_ATTR_OP] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) static int ctrl_dumppolicy_start(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) const struct genl_dumpit_info *info = genl_dumpit_info(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct nlattr **tb = info->attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) const struct genl_family *rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct genl_ops op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (!tb[CTRL_ATTR_FAMILY_ID] && !tb[CTRL_ATTR_FAMILY_NAME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (tb[CTRL_ATTR_FAMILY_ID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) ctx->fam_id = nla_get_u16(tb[CTRL_ATTR_FAMILY_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) rt = genl_family_find_byname(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) nla_data(tb[CTRL_ATTR_FAMILY_NAME]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) if (!rt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) ctx->fam_id = rt->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) rt = genl_family_find_byid(ctx->fam_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (!rt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) ctx->rt = rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (tb[CTRL_ATTR_OP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) ctx->single_op = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) ctx->op = nla_get_u32(tb[CTRL_ATTR_OP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) err = genl_get_cmd(ctx->op, rt, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) NL_SET_BAD_ATTR(cb->extack, tb[CTRL_ATTR_OP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (!op.policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) return netlink_policy_dump_add_policy(&ctx->state, op.policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) op.maxattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) for (i = 0; i < genl_get_cmd_cnt(rt); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) genl_get_cmd_by_index(i, rt, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (op.policy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) err = netlink_policy_dump_add_policy(&ctx->state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) op.policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) op.maxattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) if (!ctx->state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) static void *ctrl_dumppolicy_prep(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) cb->nlh->nlmsg_seq, &genl_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) NLM_F_MULTI, CTRL_CMD_GETPOLICY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, ctx->fam_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) static int ctrl_dumppolicy_put_op(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) struct netlink_callback *cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) struct genl_ops *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) struct nlattr *nest_pol, *nest_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) /* skip if we have nothing to show */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (!op->policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (!op->doit &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) (!op->dumpit || op->validate & GENL_DONT_VALIDATE_DUMP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) hdr = ctrl_dumppolicy_prep(skb, cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) nest_pol = nla_nest_start(skb, CTRL_ATTR_OP_POLICY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) if (!nest_pol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) nest_op = nla_nest_start(skb, op->cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) if (!nest_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) /* for now both do/dump are always the same */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) idx = netlink_policy_dump_get_policy_idx(ctx->state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) op->policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) op->maxattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if (op->doit && nla_put_u32(skb, CTRL_ATTR_POLICY_DO, idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (op->dumpit && !(op->validate & GENL_DONT_VALIDATE_DUMP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) nla_put_u32(skb, CTRL_ATTR_POLICY_DUMP, idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) nla_nest_end(skb, nest_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) nla_nest_end(skb, nest_pol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (!ctx->policies) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) while (ctx->opidx < genl_get_cmd_cnt(ctx->rt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) struct genl_ops op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (ctx->single_op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) err = genl_get_cmd(ctx->op, ctx->rt, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (WARN_ON(err))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) /* break out of the loop after this one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) ctx->opidx = genl_get_cmd_cnt(ctx->rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) genl_get_cmd_by_index(ctx->opidx, ctx->rt, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (ctrl_dumppolicy_put_op(skb, cb, &op))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) ctx->opidx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) /* completed with the per-op policy index list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) ctx->policies = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) while (netlink_policy_dump_loop(ctx->state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) struct nlattr *nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) hdr = ctrl_dumppolicy_prep(skb, cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) nest = nla_nest_start(skb, CTRL_ATTR_POLICY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (!nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (netlink_policy_dump_write(skb, ctx->state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) static int ctrl_dumppolicy_done(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) netlink_policy_dump_free(ctx->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) static const struct genl_ops genl_ctrl_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) .cmd = CTRL_CMD_GETFAMILY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) .policy = ctrl_policy_family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) .maxattr = ARRAY_SIZE(ctrl_policy_family) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) .doit = ctrl_getfamily,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) .dumpit = ctrl_dumpfamily,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) .cmd = CTRL_CMD_GETPOLICY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) .policy = ctrl_policy_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) .maxattr = ARRAY_SIZE(ctrl_policy_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) .start = ctrl_dumppolicy_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) .dumpit = ctrl_dumppolicy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) .done = ctrl_dumppolicy_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) static const struct genl_multicast_group genl_ctrl_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) { .name = "notify", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) static struct genl_family genl_ctrl __ro_after_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) .module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) .ops = genl_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) .n_ops = ARRAY_SIZE(genl_ctrl_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) .mcgrps = genl_ctrl_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) .n_mcgrps = ARRAY_SIZE(genl_ctrl_groups),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) .id = GENL_ID_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) .name = "nlctrl",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) .version = 0x2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) .netnsok = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) static int __net_init genl_pernet_init(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) struct netlink_kernel_cfg cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) .input = genl_rcv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) .flags = NL_CFG_F_NONROOT_RECV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) /* we'll bump the group number right afterwards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC, &cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (!net->genl_sock && net_eq(net, &init_net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) panic("GENL: Cannot initialize generic netlink\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) if (!net->genl_sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) static void __net_exit genl_pernet_exit(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) netlink_kernel_release(net->genl_sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) net->genl_sock = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) static struct pernet_operations genl_pernet_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) .init = genl_pernet_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) .exit = genl_pernet_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) static int __init genl_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) err = genl_register_family(&genl_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) goto problem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) err = register_pernet_subsys(&genl_pernet_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) goto problem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) problem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) panic("GENL: Cannot register controller: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) core_initcall(genl_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) gfp_t flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) struct sk_buff *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) struct net *net, *prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) bool delivered = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) for_each_net_rcu(net) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) if (prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) tmp = skb_clone(skb, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) if (!tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) err = nlmsg_multicast(prev->genl_sock, tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) portid, group, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) delivered = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) else if (err != -ESRCH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) prev = net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) err = nlmsg_multicast(prev->genl_sock, skb, portid, group, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) delivered = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) else if (err != -ESRCH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) return delivered ? 0 : -ESRCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) int genlmsg_multicast_allns(const struct genl_family *family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) struct sk_buff *skb, u32 portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) unsigned int group, gfp_t flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) if (WARN_ON_ONCE(group >= family->n_mcgrps))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) group = family->mcgrp_offset + group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) return genlmsg_mcast(skb, portid, group, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) EXPORT_SYMBOL(genlmsg_multicast_allns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) void genl_notify(const struct genl_family *family, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) struct genl_info *info, u32 group, gfp_t flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) struct net *net = genl_info_net(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) struct sock *sk = net->genl_sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) int report = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (info->nlhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) report = nlmsg_report(info->nlhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (WARN_ON_ONCE(group >= family->n_mcgrps))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) group = family->mcgrp_offset + group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) nlmsg_notify(sk, skb, info->snd_portid, group, report, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) EXPORT_SYMBOL(genl_notify);