libnl  3.6.0
mngt.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_mngt Family and Command Registration
9  *
10  * Registering Generic Netlink Families and Commands
11  *
12  * @{
13  */
14 
15 #include <netlink-private/genl.h>
16 #include <netlink/netlink.h>
17 #include <netlink/genl/genl.h>
18 #include <netlink/genl/mngt.h>
19 #include <netlink/genl/family.h>
20 #include <netlink/genl/ctrl.h>
21 #include <netlink/utils.h>
22 
23 #include "netlink-private/utils.h"
24 
25 /** @cond SKIP */
26 
27 static NL_LIST_HEAD(genl_ops_list);
28 
29 static struct genl_cmd *lookup_cmd(struct genl_ops *ops, int cmd_id)
30 {
31  struct genl_cmd *cmd;
32  int i;
33 
34  for (i = 0; i < ops->o_ncmds; i++) {
35  cmd = &ops->o_cmds[i];
36  if (cmd->c_id == cmd_id)
37  return cmd;
38  }
39 
40  return NULL;
41 }
42 
43 static int cmd_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *nlh,
44  struct genl_ops *ops, struct nl_cache_ops *cache_ops, void *arg)
45 {
46  _nl_auto_free struct nlattr **tb_free = NULL;
47  int err;
48  struct genlmsghdr *ghdr;
49  struct genl_cmd *cmd;
50  struct nlattr **tb;
51 
52  ghdr = genlmsg_hdr(nlh);
53 
54  if (!(cmd = lookup_cmd(ops, ghdr->cmd)))
55  return -NLE_MSGTYPE_NOSUPPORT;
56 
57  if (cmd->c_msg_parser == NULL)
58  return -NLE_OPNOTSUPP;
59 
60  tb = _nl_malloc_maybe_a (300, (((size_t) cmd->c_maxattr) + 1u) * sizeof (struct nlattr *), &tb_free);
61  if (!tb)
62  return -NLE_NOMEM;
63 
64  err = nlmsg_parse(nlh,
65  GENL_HDRSIZE(ops->o_hdrsize),
66  tb,
67  cmd->c_maxattr,
68  cmd->c_attr_policy);
69  if (err < 0)
70  return err;
71 
72  {
73  struct genl_info info = {
74  .who = who,
75  .nlh = nlh,
76  .genlhdr = ghdr,
77  .userhdr = genlmsg_user_hdr(ghdr),
78  .attrs = tb,
79  };
80 
81  return cmd->c_msg_parser(cache_ops, cmd, &info, arg);
82  }
83 }
84 
85 static int genl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
86  struct nlmsghdr *nlh, struct nl_parser_param *pp)
87 {
88  if (ops->co_genl == NULL)
89  BUG();
90 
91  return cmd_msg_parser(who, nlh, ops->co_genl, ops, pp);
92 }
93 
94 static struct genl_ops *lookup_family(int family)
95 {
96  struct genl_ops *ops;
97 
98  nl_list_for_each_entry(ops, &genl_ops_list, o_list) {
99  if (ops->o_id == family)
100  return ops;
101  }
102 
103  return NULL;
104 }
105 
106 static struct genl_ops *lookup_family_by_name(const char *name)
107 {
108  struct genl_ops *ops;
109 
110  nl_list_for_each_entry(ops, &genl_ops_list, o_list) {
111  if (!strcmp(ops->o_name, name))
112  return ops;
113  }
114 
115  return NULL;
116 }
117 
118 char *genl_op2name(int family, int op, char *buf, size_t len)
119 {
120  struct genl_ops *ops;
121  int i;
122 
123  if ((ops = lookup_family(family))) {
124  for (i = 0; i < ops->o_ncmds; i++) {
125  struct genl_cmd *cmd;
126  cmd = &ops->o_cmds[i];
127 
128  if (cmd->c_id == op) {
129  _nl_strncpy_trunc(buf, cmd->c_name, len);
130  return buf;
131  }
132  }
133  }
134 
135  _nl_strncpy_trunc(buf, "unknown", len);
136  return NULL;
137 }
138 
139 /** @endcond */
140 
141 /**
142  * @name Registration
143  * @{
144  */
145 
146 /**
147  * Register Generic Netlink family and associated commands
148  * @arg ops Generic Netlink family definition
149  *
150  * Registers the specified Generic Netlink family definition together with
151  * all associated commands. After registration, received Generic Netlink
152  * messages can be passed to genl_handle_msg() which will validate the
153  * messages, look for a matching command and call the respective callback
154  * function automatically.
155  *
156  * @note Consider using genl_register() if the family is used to implement a
157  * cacheable type.
158  *
159  * @see genl_unregister_family();
160  * @see genl_register();
161  *
162  * @return 0 on success or a negative error code.
163  */
165 {
166  if (!ops->o_name)
167  return -NLE_INVAL;
168 
169  if (ops->o_cmds && ops->o_ncmds <= 0)
170  return -NLE_INVAL;
171 
172  if (ops->o_id && lookup_family(ops->o_id))
173  return -NLE_EXIST;
174 
175  if (lookup_family_by_name(ops->o_name))
176  return -NLE_EXIST;
177 
178  nl_list_add_tail(&ops->o_list, &genl_ops_list);
179 
180  return 0;
181 }
182 
183 /**
184  * Unregister Generic Netlink family
185  * @arg ops Generic Netlink family definition
186  *
187  * Unregisters a family and all associated commands that were previously
188  * registered using genl_register_family().
189  *
190  * @see genl_register_family()
191  *
192  * @return 0 on success or a negative error code.
193  */
195 {
196  nl_list_del(&ops->o_list);
197 
198  return 0;
199 }
200 
201 /**
202  * Run a received message through the demultiplexer
203  * @arg msg Generic Netlink message
204  * @arg arg Argument passed on to the message handler callback
205  *
206  * @return 0 on success or a negative error code.
207  */
208 int genl_handle_msg(struct nl_msg *msg, void *arg)
209 {
210  struct nlmsghdr *nlh = nlmsg_hdr(msg);
211  struct genl_ops *ops;
212 
213  if (!genlmsg_valid_hdr(nlh, 0))
214  return -NLE_INVAL;
215 
216  if (!(ops = lookup_family(nlh->nlmsg_type)))
217  return -NLE_MSGTYPE_NOSUPPORT;
218 
219  return cmd_msg_parser(nlmsg_get_src(msg), nlh, ops, NULL, arg);
220 }
221 
222 /** @} */
223 
224 /**
225  * @name Registration of Cache Operations
226  * @{
227  */
228 
229 /**
230  * Register Generic Netlink family backed cache
231  * @arg ops Cache operations definition
232  *
233  * Same as genl_register_family() but additionally registers the specified
234  * cache operations using nl_cache_mngt_register() and associates it with
235  * the Generic Netlink family.
236  *
237  * @see genl_register_family()
238  *
239  * @return 0 on success or a negative error code.
240  */
241 int genl_register(struct nl_cache_ops *ops)
242 {
243  int err;
244 
245  if (ops->co_protocol != NETLINK_GENERIC) {
246  err = -NLE_PROTO_MISMATCH;
247  goto errout;
248  }
249 
250  if (ops->co_hdrsize < GENL_HDRSIZE(0)) {
251  err = -NLE_INVAL;
252  goto errout;
253  }
254 
255  if (ops->co_genl == NULL) {
256  err = -NLE_INVAL;
257  goto errout;
258  }
259 
260  ops->co_genl->o_cache_ops = ops;
261  ops->co_genl->o_hdrsize = ops->co_hdrsize - GENL_HDRLEN;
262  ops->co_genl->o_name = ops->co_msgtypes[0].mt_name;
263  ops->co_genl->o_id = ops->co_msgtypes[0].mt_id;
264  ops->co_msg_parser = genl_msg_parser;
265 
266  if ((err = genl_register_family(ops->co_genl)) < 0)
267  goto errout;
268 
269  err = nl_cache_mngt_register(ops);
270 errout:
271  return err;
272 }
273 
274 /**
275  * Unregister cache based Generic Netlink family
276  * @arg ops Cache operations definition
277  */
278 void genl_unregister(struct nl_cache_ops *ops)
279 {
280  if (!ops)
281  return;
282 
284 
285  genl_unregister_family(ops->co_genl);
286 }
287 
288 /** @} */
289 
290 /** @cond SKIP */
291 static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops)
292 {
293  struct genl_family *family;
294 
295  family = genl_ctrl_search_by_name(ctrl, ops->o_name);
296  if (family != NULL) {
297  ops->o_id = genl_family_get_id(family);
298 
299  if (ops->o_cache_ops)
300  ops->o_cache_ops->co_msgtypes[0].mt_id = ops->o_id;
301 
302  genl_family_put(family);
303 
304  return 0;
305  }
306 
307  return -NLE_OBJ_NOTFOUND;
308 }
309 
310 int genl_resolve_id(struct genl_ops *ops)
311 {
312  struct nl_sock *sk;
313  int err = 0;
314 
315  /* Check if resolved already */
316  if (ops->o_id != 0)
317  return 0;
318 
319  if (!ops->o_name)
320  return -NLE_INVAL;
321 
322  if (!(sk = nl_socket_alloc()))
323  return -NLE_NOMEM;
324 
325  if ((err = genl_connect(sk)) < 0)
326  goto errout_free;
327 
328  err = genl_ops_resolve(sk, ops);
329 
330 errout_free:
331  nl_socket_free(sk);
332 
333  return err;
334 }
335 /** @endcond */
336 
337 /**
338  * @name Resolving the name of registered families
339  * @{
340  */
341 
342 /**
343  * Resolve a single Generic Netlink family
344  * @arg sk Generic Netlink socket
345  * @arg ops Generic Netlink family definition
346  *
347  * Resolves the family name to its numeric identifier.
348  *
349  * @return 0 on success or a negative error code.
350  */
351 int genl_ops_resolve(struct nl_sock *sk, struct genl_ops *ops)
352 {
353  struct nl_cache *ctrl;
354  int err;
355 
356  if ((err = genl_ctrl_alloc_cache(sk, &ctrl)) < 0)
357  goto errout;
358 
359  err = __genl_ops_resolve(ctrl, ops);
360 
361  nl_cache_free(ctrl);
362 errout:
363  return err;
364 }
365 
366 /**
367  * Resolve all registered Generic Netlink families
368  * @arg sk Generic Netlink socket
369  *
370  * Walks through all local Generic Netlink families that have been registered
371  * using genl_register() and resolves the name of each family to the
372  * corresponding numeric identifier.
373  *
374  * @see genl_register()
375  * @see genl_ops_resolve()
376  *
377  * @return 0 on success or a negative error code.
378  */
379 int genl_mngt_resolve(struct nl_sock *sk)
380 {
381  struct nl_cache *ctrl;
382  struct genl_ops *ops;
383  int err = 0;
384 
385  if ((err = genl_ctrl_alloc_cache(sk, &ctrl)) < 0)
386  goto errout;
387 
388  nl_list_for_each_entry(ops, &genl_ops_list, o_list) {
389  err = __genl_ops_resolve(ctrl, ops);
390  }
391 
392  nl_cache_free(ctrl);
393 errout:
394  return err;
395 }
396 
397 /** @} */
398 
399 /** @} */
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:281
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:246
void nl_cache_free(struct nl_cache *cache)
Free a cache.
Definition: cache.c:403
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
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
int genl_register(struct nl_cache_ops *ops)
Register Generic Netlink family backed cache.
Definition: mngt.c:241
int genl_mngt_resolve(struct nl_sock *sk)
Resolve all registered Generic Netlink families.
Definition: mngt.c:379
void genl_unregister(struct nl_cache_ops *ops)
Unregister cache based Generic Netlink family.
Definition: mngt.c:278
int genl_ops_resolve(struct nl_sock *sk, struct genl_ops *ops)
Resolve a single Generic Netlink family.
Definition: mngt.c:351
int genl_unregister_family(struct genl_ops *ops)
Unregister Generic Netlink family.
Definition: mngt.c:194
int genl_register_family(struct genl_ops *ops)
Register Generic Netlink family and associated commands.
Definition: mngt.c:164
int genl_handle_msg(struct nl_msg *msg, void *arg)
Run a received message through the demultiplexer.
Definition: mngt.c:208
int genl_connect(struct nl_sock *sk)
Connect a Generic Netlink socket.
Definition: genl.c:39
struct genlmsghdr * genlmsg_hdr(struct nlmsghdr *nlh)
Return pointer to Generic Netlink header.
Definition: genl.c:205
void * genlmsg_user_hdr(const struct genlmsghdr *gnlh)
Return pointer to user header.
Definition: genl.c:237
int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
Validate Generic Netlink message headers.
Definition: genl.c:112
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
parse attributes of a netlink message
Definition: msg.c:208
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
Definition: msg.c:536
void nl_socket_free(struct nl_sock *sk)
Free a netlink socket.
Definition: socket.c:237
struct nl_sock * nl_socket_alloc(void)
Allocate new netlink socket.
Definition: socket.c:199
Definition of a Generic Netlink command.
Definition: mngt.h:82
struct nla_policy * c_attr_policy
Attribute validation policy, enforced before the callback is called.
Definition: mngt.h:98
int c_id
Numeric command identifier (required)
Definition: mngt.h:84
char * c_name
Human readable name (required)
Definition: mngt.h:87
int(* c_msg_parser)(struct nl_cache_ops *, struct genl_cmd *, struct genl_info *, void *)
Called whenever a message for this command is received.
Definition: mngt.h:93
int c_maxattr
Maximum attribute identifier that the command is prepared to handle.
Definition: mngt.h:90
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 sockaddr_nl * who
Socket address of sender.
Definition: mngt.h:34
Definition of a Generic Netlink family.
Definition: mngt.h:127
int o_ncmds
Number of elements in o_cmds array.
Definition: mngt.h:147
unsigned int o_hdrsize
Length of user header.
Definition: mngt.h:129
struct nl_list_head o_list
Used internally to link together all registered operations.
Definition: mngt.h:153
char * o_name
Human readable name, used by genl_ops_resolve() to resolve numeric id.
Definition: mngt.h:135
int o_id
Numeric identifier, automatically filled in by genl_ops_resolve()
Definition: mngt.h:132
struct genl_cmd * o_cmds
Optional array defining the available Generic Netlink commands.
Definition: mngt.h:144
struct nl_cache_ops * o_cache_ops
If registered via genl_register(), will point to the related cache operations.
Definition: mngt.h:141