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