libnl 1.1.4
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-2006 Thomas Graf <tgraf@suug.ch>
10 */
11
12/**
13 * @ingroup genl_mngt
14 * @defgroup ctrl Controller
15 * @brief
16 *
17 * @{
18 */
19
20#include <netlink-generic.h>
21#include <netlink/netlink.h>
22#include <netlink/genl/genl.h>
23#include <netlink/genl/family.h>
24#include <netlink/genl/mngt.h>
25#include <netlink/genl/ctrl.h>
26#include <netlink/utils.h>
27
28/** @cond SKIP */
29#define CTRL_VERSION 0x0001
30
31static struct nl_cache_ops genl_ctrl_ops;
32/** @endcond */
33
34static int ctrl_request_update(struct nl_cache *c, struct nl_handle *h)
35{
36 return genl_send_simple(h, GENL_ID_CTRL, CTRL_CMD_GETFAMILY,
37 CTRL_VERSION, NLM_F_DUMP);
38}
39
40static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
41 [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
42 [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING,
43 .maxlen = GENL_NAMSIZ },
44 [CTRL_ATTR_VERSION] = { .type = NLA_U32 },
45 [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 },
46 [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 },
47 [CTRL_ATTR_OPS] = { .type = NLA_NESTED },
48};
49
50static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = {
51 [CTRL_ATTR_OP_ID] = { .type = NLA_U32 },
52 [CTRL_ATTR_OP_FLAGS] = { .type = NLA_U32 },
53};
54
55static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd,
56 struct genl_info *info, void *arg)
57{
58 struct genl_family *family;
59 struct nl_parser_param *pp = arg;
60 int err;
61
62 family = genl_family_alloc();
63 if (family == NULL) {
64 err = nl_errno(ENOMEM);
65 goto errout;
66 }
67
68 if (info->attrs[CTRL_ATTR_FAMILY_NAME] == NULL) {
69 err = nl_error(EINVAL, "Missing family name TLV");
70 goto errout;
71 }
72
73 if (info->attrs[CTRL_ATTR_FAMILY_ID] == NULL) {
74 err = nl_error(EINVAL, "Missing family id TLV");
75 goto errout;
76 }
77
78 family->ce_msgtype = info->nlh->nlmsg_type;
79 genl_family_set_id(family,
80 nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]));
81 genl_family_set_name(family,
82 nla_get_string(info->attrs[CTRL_ATTR_FAMILY_NAME]));
83
84 if (info->attrs[CTRL_ATTR_VERSION]) {
85 uint32_t version = nla_get_u32(info->attrs[CTRL_ATTR_VERSION]);
86 genl_family_set_version(family, version);
87 }
88
89 if (info->attrs[CTRL_ATTR_HDRSIZE]) {
90 uint32_t hdrsize = nla_get_u32(info->attrs[CTRL_ATTR_HDRSIZE]);
91 genl_family_set_hdrsize(family, hdrsize);
92 }
93
94 if (info->attrs[CTRL_ATTR_MAXATTR]) {
95 uint32_t maxattr = nla_get_u32(info->attrs[CTRL_ATTR_MAXATTR]);
96 genl_family_set_maxattr(family, maxattr);
97 }
98
99 if (info->attrs[CTRL_ATTR_OPS]) {
100 struct nlattr *nla, *nla_ops;
101 int remaining;
102
103 nla_ops = info->attrs[CTRL_ATTR_OPS];
104 nla_for_each_nested(nla, nla_ops, remaining) {
105 struct nlattr *tb[CTRL_ATTR_OP_MAX+1];
106 int flags = 0, id;
107
108 err = nla_parse_nested(tb, CTRL_ATTR_OP_MAX, nla,
109 family_op_policy);
110 if (err < 0)
111 goto errout;
112
113 if (tb[CTRL_ATTR_OP_ID] == NULL) {
114 err = nl_errno(EINVAL);
115 goto errout;
116 }
117
118 id = nla_get_u32(tb[CTRL_ATTR_OP_ID]);
119
120 if (tb[CTRL_ATTR_OP_FLAGS])
121 flags = nla_get_u32(tb[CTRL_ATTR_OP_FLAGS]);
122
123 err = genl_family_add_op(family, id, flags);
124 if (err < 0)
125 goto errout;
126
127 }
128 }
129
130 err = pp->pp_cb((struct nl_object *) family, pp);
131 if (err < 0)
132 goto errout;
133
134 err = P_ACCEPT;
135
136errout:
137 genl_family_put(family);
138 return err;
139}
140
141/**
142 * @name Cache Management
143 * @{
144 */
145
146struct nl_cache *genl_ctrl_alloc_cache(struct nl_handle *handle)
147{
148 struct nl_cache * cache;
149
150 cache = nl_cache_alloc(&genl_ctrl_ops);
151 if (cache == NULL)
152 return NULL;
153
154 if (handle && nl_cache_refill(handle, cache) < 0) {
155 nl_cache_free(cache);
156 return NULL;
157 }
158
159 return cache;
160}
161
162/**
163 * Look up generic netlink family by id in the provided cache.
164 * @arg cache Generic netlink family cache.
165 * @arg id Family identifier.
166 *
167 * Searches through the cache looking for a registered family
168 * matching the specified identifier. The caller will own a
169 * reference on the returned object which needs to be given
170 * back after usage using genl_family_put().
171 *
172 * @return Generic netlink family object or NULL if no match was found.
173 */
174struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id)
175{
176 struct genl_family *fam;
177
178 if (cache->c_ops != &genl_ctrl_ops)
179 BUG();
180
181 nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
182 if (fam->gf_id == id) {
183 nl_object_get((struct nl_object *) fam);
184 return fam;
185 }
186 }
187
188 return NULL;
189}
190
191/**
192 * @name Resolver
193 * @{
194 */
195
196/**
197 * Look up generic netlink family by family name in the provided cache.
198 * @arg cache Generic netlink family cache.
199 * @arg name Family name.
200 *
201 * Searches through the cache looking for a registered family
202 * matching the specified name. The caller will own a reference
203 * on the returned object which needs to be given back after
204 * usage using genl_family_put().
205 *
206 * @return Generic netlink family object or NULL if no match was found.
207 */
208struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache,
209 const char *name)
210{
211 struct genl_family *fam;
212
213 if (cache->c_ops != &genl_ctrl_ops)
214 BUG();
215
216 nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
217 if (!strcmp(name, fam->gf_name)) {
218 nl_object_get((struct nl_object *) fam);
219 return fam;
220 }
221 }
222
223 return NULL;
224}
225
226/** @} */
227
228/**
229 * Resolve generic netlink family name to its identifier
230 * @arg handle Netlink Handle
231 * @arg name Name of generic netlink family
232 *
233 * Resolves the generic netlink family name to its identifer and returns
234 * it.
235 *
236 * @return A positive identifier or a negative error code.
237 */
238int genl_ctrl_resolve(struct nl_handle *handle, const char *name)
239{
240 struct nl_cache *cache;
241 struct genl_family *family;
242 int err;
243
244 cache = genl_ctrl_alloc_cache(handle);
245 if (cache == NULL)
246 return nl_get_errno();
247
248 family = genl_ctrl_search_by_name(cache, name);
249 if (family == NULL) {
250 err = nl_error(ENOENT, "Generic Netlink Family not found");
251 goto errout;
252 }
253
254 err = genl_family_get_id(family);
255 genl_family_put(family);
256errout:
257 nl_cache_free(cache);
258
259 return err;
260}
261
262/** @} */
263
264static struct genl_cmd genl_cmds[] = {
265 {
266 .c_id = CTRL_CMD_NEWFAMILY,
267 .c_name = "NEWFAMILY" ,
268 .c_maxattr = CTRL_ATTR_MAX,
269 .c_attr_policy = ctrl_policy,
270 .c_msg_parser = ctrl_msg_parser,
271 },
272 {
273 .c_id = CTRL_CMD_DELFAMILY,
274 .c_name = "DELFAMILY" ,
275 },
276 {
277 .c_id = CTRL_CMD_GETFAMILY,
278 .c_name = "GETFAMILY" ,
279 },
280 {
281 .c_id = CTRL_CMD_NEWOPS,
282 .c_name = "NEWOPS" ,
283 },
284 {
285 .c_id = CTRL_CMD_DELOPS,
286 .c_name = "DELOPS" ,
287 },
288};
289
290static struct genl_ops genl_ops = {
291 .o_cmds = genl_cmds,
292 .o_ncmds = ARRAY_SIZE(genl_cmds),
293};
294
295/** @cond SKIP */
296extern struct nl_object_ops genl_family_ops;
297/** @endcond */
298
299static struct nl_cache_ops genl_ctrl_ops = {
300 .co_name = "genl/family",
301 .co_hdrsize = GENL_HDRSIZE(0),
302 .co_msgtypes = GENL_FAMILY(GENL_ID_CTRL, "nlctrl"),
303 .co_genl = &genl_ops,
304 .co_protocol = NETLINK_GENERIC,
305 .co_request_update = ctrl_request_update,
306 .co_obj_ops = &genl_family_ops,
307};
308
309static void __init ctrl_init(void)
310{
311 genl_register(&genl_ctrl_ops);
312}
313
314static void __exit ctrl_exit(void)
315{
316 genl_unregister(&genl_ctrl_ops);
317}
318
319/** @} */
uint16_t nla_get_u16(struct nlattr *nla)
Return payload of u16 attribute.
Definition: attr.c:702
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
parse nested attributes
Definition: attr.c:307
uint32_t nla_get_u32(struct nlattr *nla)
Return payload of u32 attribute.
Definition: attr.c:693
#define nla_for_each_nested(pos, nla, rem)
iterate over a stream of nested attributes
Definition: attr.h:276
char * nla_get_string(struct nlattr *nla)
return payload of string attribute
Definition: attr.c:733
@ NLA_STRING
character string
Definition: attr.h:41
@ NLA_U16
16bit integer
Definition: attr.h:38
@ NLA_NESTED
nested attributes
Definition: attr.h:44
@ NLA_U32
32bit integer
Definition: attr.h:39
void nl_cache_free(struct nl_cache *cache)
Free a cache.
Definition: cache.c:277
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate an empty cache.
Definition: cache.c:170
int nl_cache_refill(struct nl_handle *handle, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
Definition: cache.c:680
int genl_ctrl_resolve(struct nl_handle *handle, const char *name)
Resolve generic netlink family name to its identifier.
Definition: ctrl.c:238
struct genl_family * genl_ctrl_search_by_name(struct nl_cache *cache, const char *name)
Look up generic netlink family by family name in the provided cache.
Definition: ctrl.c:208
struct genl_family * genl_ctrl_search(struct nl_cache *cache, int id)
Look up generic netlink family by id in the provided cache.
Definition: ctrl.c:174
int genl_register(struct nl_cache_ops *ops)
Register generic netlink operations.
Definition: mngt.c:172
void genl_unregister(struct nl_cache_ops *ops)
Unregister generic netlink operations.
Definition: mngt.c:214
int genl_send_simple(struct nl_handle *handle, int family, int cmd, int version, int flags)
Send trivial generic netlink message.
Definition: genl.c:128
#define NLM_F_DUMP
Dump all entries.
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition: object.c:167
Generic Netlink Command.
Definition: mngt.h:30
int c_id
Unique command identifier.
Definition: mngt.h:32
Generic Netlink Operations.
Definition: mngt.h:58
Cache Operations.
Definition: cache-api.h:164
Object Operations.
Definition: object-api.h:255
attribute validation policy
Definition: attr.h:73
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:75