• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
4  */
5 
6 /**
7  * @ingroup genl
8  * @defgroup genl_ctrl Controller (Resolver)
9  *
10  * Resolves Generic Netlink family names to numeric identifiers.
11  *
12  * The controller is a component in the kernel that resolves Generic Netlink
13  * family names to their numeric identifiers. This module provides functions
14  * to query the controller to access the resolving functionality.
15  * @{
16  */
17 
18 #include <netlink-private/genl.h>
19 #include <netlink/netlink.h>
20 #include <netlink/genl/genl.h>
21 #include <netlink/genl/family.h>
22 #include <netlink/genl/mngt.h>
23 #include <netlink/genl/ctrl.h>
24 #include <netlink/utils.h>
25 
26 /** @cond SKIP */
27 #define CTRL_VERSION		0x0001
28 
29 static struct nl_cache_ops genl_ctrl_ops;
30 
ctrl_request_update(struct nl_cache * c,struct nl_sock * h)31 static int ctrl_request_update(struct nl_cache *c, struct nl_sock *h)
32 {
33 	return genl_send_simple(h, GENL_ID_CTRL, CTRL_CMD_GETFAMILY,
34 				CTRL_VERSION, NLM_F_DUMP);
35 }
36 
37 static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
38 	[CTRL_ATTR_FAMILY_ID]	= { .type = NLA_U16 },
39 	[CTRL_ATTR_FAMILY_NAME]	= { .type = NLA_STRING,
40 				    .maxlen = GENL_NAMSIZ },
41 	[CTRL_ATTR_VERSION]	= { .type = NLA_U32 },
42 	[CTRL_ATTR_HDRSIZE]	= { .type = NLA_U32 },
43 	[CTRL_ATTR_MAXATTR]	= { .type = NLA_U32 },
44 	[CTRL_ATTR_OPS]		= { .type = NLA_NESTED },
45 	[CTRL_ATTR_MCAST_GROUPS] = { .type = NLA_NESTED },
46 };
47 
48 static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = {
49 	[CTRL_ATTR_OP_ID]	= { .type = NLA_U32 },
50 	[CTRL_ATTR_OP_FLAGS]	= { .type = NLA_U32 },
51 };
52 
53 static struct nla_policy family_grp_policy[CTRL_ATTR_MCAST_GRP_MAX+1] = {
54 	[CTRL_ATTR_MCAST_GRP_NAME] = { .type = NLA_STRING },
55 	[CTRL_ATTR_MCAST_GRP_ID]   = { .type = NLA_U32 },
56 };
57 
parse_mcast_grps(struct genl_family * family,struct nlattr * grp_attr)58 static int parse_mcast_grps(struct genl_family *family, struct nlattr *grp_attr)
59 {
60 	struct nlattr *nla;
61 	int remaining, err;
62 
63 	if (!grp_attr)
64 		BUG();
65 
66 	nla_for_each_nested(nla, grp_attr, remaining) {
67 		struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1];
68 		int id;
69 		const char * name;
70 
71 		err = nla_parse_nested(tb, CTRL_ATTR_MCAST_GRP_MAX, nla,
72 				       family_grp_policy);
73 		if (err < 0)
74 			goto errout;
75 
76 		if (tb[CTRL_ATTR_MCAST_GRP_ID] == NULL) {
77 			err = -NLE_MISSING_ATTR;
78 			goto errout;
79 		}
80 		id = nla_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]);
81 
82 		if (tb[CTRL_ATTR_MCAST_GRP_NAME] == NULL) {
83 			err = -NLE_MISSING_ATTR;
84 			goto errout;
85 		}
86 		name = nla_get_string(tb[CTRL_ATTR_MCAST_GRP_NAME]);
87 
88 		err = genl_family_add_grp(family, id, name);
89 		if (err < 0)
90 			goto errout;
91 	}
92 
93 	err = 0;
94 
95 errout:
96 	return err;
97 }
98 
ctrl_msg_parser(struct nl_cache_ops * ops,struct genl_cmd * cmd,struct genl_info * info,void * arg)99 static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd,
100 			   struct genl_info *info, void *arg)
101 {
102 	struct genl_family *family;
103 	struct nl_parser_param *pp = arg;
104 	int err;
105 
106 	family = genl_family_alloc();
107 	if (family == NULL) {
108 		err = -NLE_NOMEM;
109 		goto errout;
110 	}
111 
112 	if (info->attrs[CTRL_ATTR_FAMILY_NAME] == NULL) {
113 		err = -NLE_MISSING_ATTR;
114 		goto errout;
115 	}
116 
117 	if (info->attrs[CTRL_ATTR_FAMILY_ID] == NULL) {
118 		err = -NLE_MISSING_ATTR;
119 		goto errout;
120 	}
121 
122 	family->ce_msgtype = info->nlh->nlmsg_type;
123 	genl_family_set_id(family,
124 			   nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]));
125 	genl_family_set_name(family,
126 		     nla_get_string(info->attrs[CTRL_ATTR_FAMILY_NAME]));
127 
128 	if (info->attrs[CTRL_ATTR_VERSION]) {
129 		uint32_t version = nla_get_u32(info->attrs[CTRL_ATTR_VERSION]);
130 		genl_family_set_version(family, version);
131 	}
132 
133 	if (info->attrs[CTRL_ATTR_HDRSIZE]) {
134 		uint32_t hdrsize = nla_get_u32(info->attrs[CTRL_ATTR_HDRSIZE]);
135 		genl_family_set_hdrsize(family, hdrsize);
136 	}
137 
138 	if (info->attrs[CTRL_ATTR_MAXATTR]) {
139 		uint32_t maxattr = nla_get_u32(info->attrs[CTRL_ATTR_MAXATTR]);
140 		genl_family_set_maxattr(family, maxattr);
141 	}
142 
143 	if (info->attrs[CTRL_ATTR_OPS]) {
144 		struct nlattr *nla, *nla_ops;
145 		int remaining;
146 
147 		nla_ops = info->attrs[CTRL_ATTR_OPS];
148 		nla_for_each_nested(nla, nla_ops, remaining) {
149 			struct nlattr *tb[CTRL_ATTR_OP_MAX+1];
150 			int flags = 0, id;
151 
152 			err = nla_parse_nested(tb, CTRL_ATTR_OP_MAX, nla,
153 					       family_op_policy);
154 			if (err < 0)
155 				goto errout;
156 
157 			if (tb[CTRL_ATTR_OP_ID] == NULL) {
158 				err = -NLE_MISSING_ATTR;
159 				goto errout;
160 			}
161 
162 			id = nla_get_u32(tb[CTRL_ATTR_OP_ID]);
163 
164 			if (tb[CTRL_ATTR_OP_FLAGS])
165 				flags = nla_get_u32(tb[CTRL_ATTR_OP_FLAGS]);
166 
167 			err = genl_family_add_op(family, id, flags);
168 			if (err < 0)
169 				goto errout;
170 
171 		}
172 	}
173 
174 	if (info->attrs[CTRL_ATTR_MCAST_GROUPS]) {
175 		err = parse_mcast_grps(family, info->attrs[CTRL_ATTR_MCAST_GROUPS]);
176 		if (err < 0)
177 			goto errout;
178 	}
179 
180 	err = pp->pp_cb((struct nl_object *) family, pp);
181 errout:
182 	genl_family_put(family);
183 	return err;
184 }
185 
186 /**
187  * process responses from from the query sent by genl_ctrl_probe_by_name
188  * @arg nl_msg		Returned message.
189  * @arg name		genl_family structure to fill out.
190  *
191  * Process returned messages, filling out the missing informatino in the
192  * genl_family structure
193  *
194  * @return Indicator to keep processing frames or not
195  *
196  */
probe_response(struct nl_msg * msg,void * arg)197 static int probe_response(struct nl_msg *msg, void *arg)
198 {
199 	struct nlattr *tb[CTRL_ATTR_MAX+1];
200 	struct nlmsghdr *nlh = nlmsg_hdr(msg);
201 	struct genl_family *ret = (struct genl_family *)arg;
202 
203 	if (genlmsg_parse(nlh, 0, tb, CTRL_ATTR_MAX, ctrl_policy))
204 		return NL_SKIP;
205 
206 	if (tb[CTRL_ATTR_FAMILY_ID])
207 		genl_family_set_id(ret, nla_get_u16(tb[CTRL_ATTR_FAMILY_ID]));
208 
209 	if (tb[CTRL_ATTR_MCAST_GROUPS])
210 		if (parse_mcast_grps(ret, tb[CTRL_ATTR_MCAST_GROUPS]) < 0)
211 			return NL_SKIP;
212 
213 	return NL_STOP;
214 }
215 
216 /**
217  * Look up generic netlink family by family name querying the kernel directly
218  * @arg sk		Socket.
219  * @arg name		Family name.
220  *
221  * Directly query's the kernel for a given family name.  The caller will own a
222  * reference on the returned object which needsd to be given back after usage
223  * using genl_family_put.
224  *
225  * Note: This API call differs from genl_ctrl_search_by_name in that it querys
226  * the kernel directly, alowing for module autoload to take place to resolve the
227  * family request. Using an nl_cache prevents that operation
228  *
229  * @return Generic netlink family object or NULL if no match was found.
230  */
genl_ctrl_probe_by_name(struct nl_sock * sk,const char * name)231 static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk,
232 						   const char *name)
233 {
234 	struct nl_msg *msg;
235 	struct genl_family *ret;
236 	struct nl_cb *cb, *orig;
237 	int rc;
238 
239 	ret = genl_family_alloc();
240 	if (!ret)
241 		goto out;
242 
243 	genl_family_set_name(ret, name);
244 
245 	msg = nlmsg_alloc();
246 	if (!msg)
247 		goto out_fam_free;
248 
249 	if (!(orig = nl_socket_get_cb(sk)))
250 		goto out_msg_free;
251 
252 	cb = nl_cb_clone(orig);
253 	nl_cb_put(orig);
254 	if (!cb)
255 		goto out_msg_free;
256 
257 	if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL,
258 			0, 0, CTRL_CMD_GETFAMILY, 1)) {
259 		BUG();
260 		goto out_cb_free;
261 	}
262 
263 	if (nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name) < 0)
264 		goto out_cb_free;
265 
266 	rc = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response,
267 		       (void *) ret);
268 	if (rc < 0)
269 		goto out_cb_free;
270 
271 	rc = nl_send_auto_complete(sk, msg);
272 	if (rc < 0)
273 		goto out_cb_free;
274 
275 	rc = nl_recvmsgs(sk, cb);
276 	if (rc < 0)
277 		goto out_cb_free;
278 
279 	/* If search was successful, request may be ACKed after data */
280 	rc = wait_for_ack(sk);
281 	if (rc < 0)
282 		goto out_cb_free;
283 
284 	if (genl_family_get_id(ret) != 0) {
285 		nlmsg_free(msg);
286 		nl_cb_put(cb);
287 		return ret;
288 	}
289 
290 out_cb_free:
291 	nl_cb_put(cb);
292 out_msg_free:
293 	nlmsg_free(msg);
294 out_fam_free:
295 	genl_family_put(ret);
296 	ret = NULL;
297 out:
298 	return ret;
299 }
300 
301 
302 /** @endcond */
303 
304 /**
305  * @name Controller Cache
306  *
307  * The controller cache allows to keep a local copy of the list of all
308  * kernel side registered Generic Netlink families to quickly resolve
309  * multiple Generic Netlink family names without requiring to communicate
310  * with the kernel for each resolving iteration.
311  *
312  * @{
313  */
314 
315 /**
316  * Allocate a new controller cache
317  * @arg sk		Generic Netlink socket
318  * @arg result		Pointer to store resulting cache
319  *
320  * Allocates a new cache mirroring the state of the controller and stores it
321  * in \c *result. The allocated cache will contain a list of all currently
322  * registered kernel side Generic Netlink families. The cache is meant to be
323  * used to resolve family names locally.
324  *
325  * @return 0 on success or a negative error code.
326  */
genl_ctrl_alloc_cache(struct nl_sock * sk,struct nl_cache ** result)327 int genl_ctrl_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
328 {
329 	return nl_cache_alloc_and_fill(&genl_ctrl_ops, sk, result);
330 }
331 
332 /**
333  * Search controller cache for a numeric address match
334  * @arg cache		Controller cache
335  * @arg id		Numeric family identifier.
336  *
337  * Searches a previously allocated controller cache and looks for an entry
338  * that matches the specified numeric family identifier \c id.  If a match
339  * is found successfully, the reference count of the matching object is
340  * increased by one before the objet is returned.
341  *
342  * @see genl_ctrl_alloc_cache()
343  * @see genl_ctrl_search_by_name()
344  * @see genl_family_put()
345  *
346  * @return Generic Netlink family object or NULL if no match was found.
347  */
genl_ctrl_search(struct nl_cache * cache,int id)348 struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id)
349 {
350 	struct genl_family *fam;
351 
352 	if (cache->c_ops != &genl_ctrl_ops)
353 		BUG();
354 
355 	nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
356 		if (fam->gf_id == id) {
357 			nl_object_get((struct nl_object *) fam);
358 			return fam;
359 		}
360 	}
361 
362 	return NULL;
363 }
364 
365 /**
366  * Search controller cache for a family name match
367  * @arg cache		Controller cache
368  * @arg name		Name of Generic Netlink family
369  *
370  * Searches a previously allocated controller cache and looks for an entry
371  * that matches the specified family \c name. If a match is found successfully,
372  * the reference count of the matching object is increased by one before the
373  * objet is returned.
374  *
375  * @see genl_ctrl_alloc_cache()
376  * @see genl_ctrl_search()
377  * @see genl_family_put()
378  *
379  * @return Generic Netlink family object or NULL if no match was found.
380  */
genl_ctrl_search_by_name(struct nl_cache * cache,const char * name)381 struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache,
382 					     const char *name)
383 {
384 	struct genl_family *fam;
385 
386 	if (cache->c_ops != &genl_ctrl_ops)
387 		BUG();
388 
389 	nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
390 		if (!strcmp(name, fam->gf_name)) {
391 			nl_object_get((struct nl_object *) fam);
392 			return fam;
393 		}
394 	}
395 
396 	return NULL;
397 }
398 
399 /** @} */
400 
401 /**
402  * @name Direct Resolvers
403  *
404  * These functions communicate directly with the kernel and do not require
405  * a cache to be kept up to date.
406  *
407  * @{
408  */
409 
410 /**
411  * Resolve Generic Netlink family name to numeric identifier
412  * @arg sk		Generic Netlink socket.
413  * @arg name		Name of Generic Netlink family
414  *
415  * Resolves the Generic Netlink family name to the corresponding numeric
416  * family identifier. This function queries the kernel directly, use
417  * genl_ctrl_search_by_name() if you need to resolve multiple names.
418  *
419  * @see genl_ctrl_search_by_name()
420  *
421  * @return The numeric family identifier or a negative error code.
422  */
genl_ctrl_resolve(struct nl_sock * sk,const char * name)423 int genl_ctrl_resolve(struct nl_sock *sk, const char *name)
424 {
425 	struct genl_family *family;
426 	int err;
427 
428 	family = genl_ctrl_probe_by_name(sk, name);
429 	if (family == NULL) {
430 		err = -NLE_OBJ_NOTFOUND;
431 		goto errout;
432 	}
433 
434 	err = genl_family_get_id(family);
435 	genl_family_put(family);
436 errout:
437 	return err;
438 }
439 
genl_ctrl_grp_by_name(const struct genl_family * family,const char * grp_name)440 static int genl_ctrl_grp_by_name(const struct genl_family *family,
441 				 const char *grp_name)
442 {
443 	struct genl_family_grp *grp;
444 
445 	nl_list_for_each_entry(grp, &family->gf_mc_grps, list) {
446 		if (!strcmp(grp->name, grp_name)) {
447 			return grp->id;
448 		}
449 	}
450 
451 	return -NLE_OBJ_NOTFOUND;
452 }
453 
454 /**
455  * Resolve Generic Netlink family group name
456  * @arg sk		Generic Netlink socket
457  * @arg family_name	Name of Generic Netlink family
458  * @arg grp_name	Name of group to resolve
459  *
460  * Looks up the family object and resolves the group name to the numeric
461  * group identifier.
462  *
463  * @return Numeric group identifier or a negative error code.
464  */
genl_ctrl_resolve_grp(struct nl_sock * sk,const char * family_name,const char * grp_name)465 int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name,
466 			  const char *grp_name)
467 {
468 
469 	struct genl_family *family;
470 	int err;
471 
472 	family = genl_ctrl_probe_by_name(sk, family_name);
473 	if (family == NULL) {
474 		err = -NLE_OBJ_NOTFOUND;
475 		goto errout;
476 	}
477 
478 	err = genl_ctrl_grp_by_name(family, grp_name);
479 	genl_family_put(family);
480 errout:
481 	return err;
482 }
483 
484 /** @} */
485 
486 /** @cond SKIP */
487 static struct genl_cmd genl_cmds[] = {
488 	{
489 		.c_id		= CTRL_CMD_NEWFAMILY,
490 		.c_name		= "NEWFAMILY" ,
491 		.c_maxattr	= CTRL_ATTR_MAX,
492 		.c_attr_policy	= ctrl_policy,
493 		.c_msg_parser	= ctrl_msg_parser,
494 	},
495 	{
496 		.c_id		= CTRL_CMD_DELFAMILY,
497 		.c_name		= "DELFAMILY" ,
498 	},
499 	{
500 		.c_id		= CTRL_CMD_GETFAMILY,
501 		.c_name		= "GETFAMILY" ,
502 	},
503 	{
504 		.c_id		= CTRL_CMD_NEWOPS,
505 		.c_name		= "NEWOPS" ,
506 	},
507 	{
508 		.c_id		= CTRL_CMD_DELOPS,
509 		.c_name		= "DELOPS" ,
510 	},
511 };
512 
513 static struct genl_ops genl_ops = {
514 	.o_cmds			= genl_cmds,
515 	.o_ncmds		= ARRAY_SIZE(genl_cmds),
516 };
517 
518 extern struct nl_object_ops genl_family_ops;
519 
520 static struct nl_cache_ops genl_ctrl_ops = {
521 	.co_name		= "genl/family",
522 	.co_hdrsize		= GENL_HDRSIZE(0),
523 	.co_msgtypes		= GENL_FAMILY(GENL_ID_CTRL, "nlctrl"),
524 	.co_genl		= &genl_ops,
525 	.co_protocol		= NETLINK_GENERIC,
526 	.co_request_update      = ctrl_request_update,
527 	.co_obj_ops		= &genl_family_ops,
528 };
529 
ctrl_init(void)530 static void __init ctrl_init(void)
531 {
532 	genl_register(&genl_ctrl_ops);
533 }
534 
ctrl_exit(void)535 static void __exit ctrl_exit(void)
536 {
537 	genl_unregister(&genl_ctrl_ops);
538 }
539 /** @endcond */
540 
541 /** @} */
542