xref: /aosp_15_r20/external/libnl/lib/genl/mngt.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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