libnl 3.7.0
ctrl.c
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
29static struct nl_cache_ops genl_ctrl_ops;
30
31static 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
37static 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
48static 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
53static 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
58static 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
95errout:
96 return err;
97}
98
99static 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]));
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);
181errout:
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 */
197static 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 */
231static 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
290out_cb_free:
291 nl_cb_put(cb);
292out_msg_free:
293 nlmsg_free(msg);
294out_fam_free:
295 genl_family_put(ret);
296 ret = NULL;
297out:
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 */
327int 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 */
348struct 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 */
381struct 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 */
423int 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);
436errout:
437 return err;
438}
439
440static 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 */
465int 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);
480errout:
481 return err;
482}
483
484/** @} */
485
486/** @cond SKIP */
487static 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
513static struct genl_ops genl_ops = {
514 .o_cmds = genl_cmds,
515 .o_ncmds = ARRAY_SIZE(genl_cmds),
516};
517
518extern struct nl_object_ops genl_family_ops;
519
520static 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
530static void __init ctrl_init(void)
531{
532 genl_register(&genl_ctrl_ops);
533}
534
535static void __exit ctrl_exit(void)
536{
537 genl_unregister(&genl_ctrl_ops);
538}
539/** @endcond */
540
541/** @} */
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:702
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:652
int nla_put_string(struct nl_msg *msg, int attrtype, const char *str)
Add string attribute to netlink message.
Definition: attr.c:782
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:1016
char * nla_get_string(const struct nlattr *nla)
Return payload of string attribute.
Definition: attr.c:793
#define nla_for_each_nested(pos, nla, rem)
Iterate over a stream of nested attributes.
Definition: attr.h:324
@ NLA_STRING
NUL terminated character string.
Definition: attr.h:39
@ NLA_U16
16 bit integer
Definition: attr.h:36
@ NLA_NESTED
Nested attributes.
Definition: attr.h:42
@ NLA_U32
32 bit integer
Definition: attr.h:37
int nl_cache_alloc_and_fill(struct nl_cache_ops *ops, struct nl_sock *sock, struct nl_cache **result)
Allocate new cache and fill it.
Definition: cache.c:228
int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, void *arg)
Set up a callback.
Definition: handlers.c:287
struct nl_cb * nl_cb_clone(struct nl_cb *orig)
Clone an existing callback handle.
Definition: handlers.c:224
@ NL_STOP
Stop parsing altogether and discard remaining messages.
Definition: handlers.h:62
@ NL_SKIP
Skip this message.
Definition: handlers.h:60
@ NL_CB_VALID
Message is valid.
Definition: handlers.h:89
@ NL_CB_CUSTOM
Customized handler specified by the user.
Definition: handlers.h:77
int genl_ctrl_resolve(struct nl_sock *sk, const char *name)
Resolve Generic Netlink family name to numeric identifier.
Definition: ctrl.c:423
int genl_ctrl_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
Allocate a new controller cache.
Definition: ctrl.c:327
struct genl_family * genl_ctrl_search_by_name(struct nl_cache *cache, const char *name)
Search controller cache for a family name match.
Definition: ctrl.c:381
struct genl_family * genl_ctrl_search(struct nl_cache *cache, int id)
Search controller cache for a numeric address match.
Definition: ctrl.c:348
int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name, const char *grp_name)
Resolve Generic Netlink family group name.
Definition: ctrl.c:465
void genl_family_set_name(struct genl_family *family, const char *name)
Set human readable name.
Definition: family.c:257
void genl_family_set_version(struct genl_family *family, uint8_t version)
Set interface version.
Definition: family.c:287
struct genl_family * genl_family_alloc(void)
Allocate new Generic Netlink family object.
Definition: family.c:180
void genl_family_put(struct genl_family *family)
Release reference on Generic Netlink family object.
Definition: family.c:194
unsigned int genl_family_get_id(struct genl_family *family)
Return numeric identifier.
Definition: family.c:212
void genl_family_set_id(struct genl_family *family, unsigned int id)
Set the numeric identifier.
Definition: family.c:225
int genl_register(struct nl_cache_ops *ops)
Register Generic Netlink family backed cache.
Definition: mngt.c:241
void genl_unregister(struct nl_cache_ops *ops)
Unregister cache based Generic Netlink family.
Definition: mngt.c:278
void * genlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seq, int family, int hdrlen, int flags, uint8_t cmd, uint8_t version)
Add Generic Netlink headers to Netlink message.
Definition: genl.c:343
int genl_send_simple(struct nl_sock *sk, int family, int cmd, int version, int flags)
Send a Generic Netlink message consisting only of a header.
Definition: genl.c:79
int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
Parse Generic Netlink message including attributes.
Definition: genl.c:186
#define NL_AUTO_PORT
Will cause the netlink port to be set to the port assigned to the netlink icoket ust before sending t...
Definition: msg.h:29
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
Definition: msg.c:536
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition: msg.c:558
struct nl_msg * nlmsg_alloc(void)
Allocate a new netlink message with the default maximum payload size.
Definition: msg.c:294
#define NL_AUTO_SEQ
May be used to refer to a sequence number which should be automatically set just before sending the m...
Definition: msg.h:40
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition: object.c:203
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
Definition: nl.c:1241
int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
Receive a set of messages from a netlink socket.
Definition: nl.c:1071
Definition of a Generic Netlink command.
Definition: mngt.h:82
int c_id
Numeric command identifier (required)
Definition: mngt.h:84
Informative structure passed on to message parser callbacks.
Definition: mngt.h:32
struct nlmsghdr * nlh
Pointer to Netlink message header.
Definition: mngt.h:37
struct nlattr ** attrs
Pointer to array of parsed attributes.
Definition: mngt.h:46
Definition of a Generic Netlink family.
Definition: mngt.h:127
struct genl_cmd * o_cmds
Optional array defining the available Generic Netlink commands.
Definition: mngt.h:144
Attribute validation policy.
Definition: attr.h:63
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:65