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