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