libnl 3.10.0
family.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_ctrl
8 * @defgroup genl_family Generic Netlink Family Object
9 *
10 * Object representing a kernel side registered Generic Netlink family
11 *
12 * @{
13 */
14
15#include "nl-default.h"
16
17#include <netlink/netlink.h>
18#include <netlink/genl/genl.h>
19#include <netlink/genl/family.h>
20#include <netlink/utils.h>
21
22#include "nl-genl.h"
23#include "nl-priv-dynamic-core/object-api.h"
24#include "nl-priv-dynamic-core/nl-core.h"
25
26/** @cond SKIP */
27struct genl_family_op
28{
29 uint32_t o_id;
30 uint32_t o_flags;
31
32 struct nl_list_head o_list;
33};
34
35#define FAMILY_ATTR_ID 0x01
36#define FAMILY_ATTR_NAME 0x02
37#define FAMILY_ATTR_VERSION 0x04
38#define FAMILY_ATTR_HDRSIZE 0x08
39#define FAMILY_ATTR_MAXATTR 0x10
40#define FAMILY_ATTR_OPS 0x20
41
42struct nl_object_ops genl_family_ops;
43
44static void family_constructor(struct nl_object *c)
45{
46 struct genl_family *family = (struct genl_family *) c;
47
48 nl_init_list_head(&family->gf_ops);
49 nl_init_list_head(&family->gf_mc_grps);
50}
51
52static void family_free_data(struct nl_object *c)
53{
54 struct genl_family *family = (struct genl_family *) c;
55 struct genl_family_op *ops, *tmp;
56 struct genl_family_grp *grp, *t_grp;
57
58 if (family == NULL)
59 return;
60
61 nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) {
62 nl_list_del(&ops->o_list);
63 free(ops);
64 }
65
66 nl_list_for_each_entry_safe(grp, t_grp, &family->gf_mc_grps, list) {
67 nl_list_del(&grp->list);
68 free(grp);
69 }
70
71}
72
73static int family_clone(struct nl_object *_dst, struct nl_object *_src)
74{
75 struct genl_family *dst = nl_object_priv(_dst);
76 struct genl_family *src = nl_object_priv(_src);
77 struct genl_family_op *ops;
78 struct genl_family_grp *grp;
79 int err;
80
81 nl_init_list_head(&dst->gf_ops);
82 nl_init_list_head(&dst->gf_mc_grps);
83
84 nl_list_for_each_entry(ops, &src->gf_ops, o_list) {
85 err = genl_family_add_op(dst, ops->o_id, ops->o_flags);
86 if (err < 0)
87 return err;
88 }
89
90 nl_list_for_each_entry(grp, &src->gf_mc_grps, list) {
91 err = genl_family_add_grp(dst, grp->id, grp->name);
92 if (err < 0)
93 return err;
94 }
95
96
97 return 0;
98}
99
100static void family_dump_line(struct nl_object *obj, struct nl_dump_params *p)
101{
102 struct genl_family *family = (struct genl_family *) obj;
103
104 nl_dump(p, "0x%04x %s version %u\n",
105 family->gf_id, family->gf_name, family->gf_version);
106}
107
108static const struct trans_tbl ops_flags[] = {
109 __ADD(GENL_ADMIN_PERM, admin_perm),
110 __ADD(GENL_CMD_CAP_DO, has_doit),
111 __ADD(GENL_CMD_CAP_DUMP, has_dump),
112 __ADD(GENL_CMD_CAP_HASPOL, has_policy),
113};
114
115static char *ops_flags2str(int flags, char *buf, size_t len)
116{
117 return __flags2str(flags, buf, len, ops_flags, ARRAY_SIZE(ops_flags));
118}
119
120static void family_dump_details(struct nl_object *obj, struct nl_dump_params *p)
121{
122 struct genl_family_grp *grp;
123 struct genl_family *family = (struct genl_family *) obj;
124
125 family_dump_line(obj, p);
126 nl_dump_line(p, " hdrsize %u maxattr %u\n",
127 family->gf_hdrsize, family->gf_maxattr);
128
129 if (family->ce_mask & FAMILY_ATTR_OPS) {
130 struct genl_family_op *op;
131 char buf[64];
132
133 nl_list_for_each_entry(op, &family->gf_ops, o_list) {
134 ops_flags2str(op->o_flags, buf, sizeof(buf));
135
136 genl_op2name(family->gf_id, op->o_id, buf, sizeof(buf));
137
138 nl_dump_line(p, " op %s (0x%02x)", buf, op->o_id);
139
140 if (op->o_flags)
141 nl_dump(p, " <%s>",
142 ops_flags2str(op->o_flags, buf,
143 sizeof(buf)));
144
145 nl_dump(p, "\n");
146 }
147 }
148
149 nl_list_for_each_entry(grp, &family->gf_mc_grps, list) {
150 nl_dump_line(p, " grp %s (0x%02x)\n", grp->name, grp->id);
151 }
152
153}
154
155static void family_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
156{
157 family_dump_details(obj, p);
158}
159
160static uint64_t family_compare(struct nl_object *_a, struct nl_object *_b,
161 uint64_t attrs, int flags)
162{
163 struct genl_family *a = (struct genl_family *) _a;
164 struct genl_family *b = (struct genl_family *) _b;
165 uint64_t diff = 0;
166
167#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
168 diff |= _DIFF(FAMILY_ATTR_ID, a->gf_id != b->gf_id);
169 diff |= _DIFF(FAMILY_ATTR_VERSION, a->gf_version != b->gf_version);
170 diff |= _DIFF(FAMILY_ATTR_HDRSIZE, a->gf_hdrsize != b->gf_hdrsize);
171 diff |= _DIFF(FAMILY_ATTR_MAXATTR, a->gf_maxattr != b->gf_maxattr);
172 diff |= _DIFF(FAMILY_ATTR_NAME, strcmp(a->gf_name, b->gf_name));
173#undef _DIFF
174
175 return diff;
176}
177/** @endcond */
178
179/**
180 * @name Object Allocation
181 * @{
182 */
183
184/**
185 * Allocate new Generic Netlink family object
186 *
187 * @return Newly allocated Generic Netlink family object or NULL.
188 */
190{
191 return (struct genl_family *) nl_object_alloc(&genl_family_ops);
192}
193
194/**
195 * Release reference on Generic Netlink family object
196 * @arg family Generic Netlink family object
197 *
198 * Reduces the reference counter of a Generic Netlink family object by one.
199 * The object is freed after the last user has returned its reference.
200 *
201 * @see nl_object_put()
202 */
203void genl_family_put(struct genl_family *family)
204{
205 nl_object_put((struct nl_object *) family);
206}
207
208/** @} */
209
210/**
211 * @name Numeric Identifier
212 * @{
213 */
214
215/**
216 * Return numeric identifier
217 * @arg family Generic Netlink family object
218 *
219 * @return Numeric identifier or 0 if not available.
220 */
221unsigned int genl_family_get_id(struct genl_family *family)
222{
223 if (family->ce_mask & FAMILY_ATTR_ID)
224 return family->gf_id;
225 else
226 return 0;
227}
228
229/**
230 * Set the numeric identifier
231 * @arg family Generic Netlink family object
232 * @arg id New numeric identifier
233 */
234void genl_family_set_id(struct genl_family *family, unsigned int id)
235{
236 family->gf_id = id;
237 family->ce_mask |= FAMILY_ATTR_ID;
238}
239
240/** @} */
241
242/**
243 * @name Human Readable Name
244 * @{
245 */
246
247/**
248 * Return human readable name
249 * @arg family Generic Netlink family object
250 *
251 * @return Name of family or NULL if not available
252 */
254{
255 if (family->ce_mask & FAMILY_ATTR_NAME)
256 return family->gf_name;
257 else
258 return NULL;
259}
260
261/**
262 * Set human readable name
263 * @arg family Generic Netlink family object
264 * @arg name New human readable name
265 */
266void genl_family_set_name(struct genl_family *family, const char *name)
267{
268 _nl_strncpy_trunc(family->gf_name, name, GENL_NAMSIZ);
269 family->ce_mask |= FAMILY_ATTR_NAME;
270}
271
272/**
273 * @name Interface Version
274 * @{
275 */
276
277/**
278 * Return interface version
279 * @arg family Generic Netlink family object
280 *
281 * @return Interface version or 0 if not available.
282 */
284{
285 if (family->ce_mask & FAMILY_ATTR_VERSION)
286 return family->gf_version;
287 else
288 return 0;
289}
290
291/**
292 * Set interface version
293 * @arg family Generic Netlink family object
294 * @arg version New interface version
295 */
296void genl_family_set_version(struct genl_family *family, uint8_t version)
297{
298 family->gf_version = version;
299 family->ce_mask |= FAMILY_ATTR_VERSION;
300}
301
302/** @} */
303
304/**
305 * @name Header Size
306 * @{
307 */
308
309/**
310 * Return user header size expected by kernel component
311 * @arg family Generic Netlink family object
312 *
313 * @return Expected header length or 0 if not available.
314 */
315uint32_t genl_family_get_hdrsize(struct genl_family *family)
316{
317 if (family->ce_mask & FAMILY_ATTR_HDRSIZE)
318 return family->gf_hdrsize;
319 else
320 return 0;
321}
322
323void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize)
324{
325 family->gf_hdrsize = hdrsize;
326 family->ce_mask |= FAMILY_ATTR_HDRSIZE;
327}
328
329/** @} */
330
331/**
332 * @name Maximum Expected Attribute
333 * @{
334 */
335
336uint32_t genl_family_get_maxattr(struct genl_family *family)
337{
338 if (family->ce_mask & FAMILY_ATTR_MAXATTR)
339 return family->gf_maxattr;
340 else
341 return 0;
342}
343
344void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr)
345{
346 family->gf_maxattr = maxattr;
347 family->ce_mask |= FAMILY_ATTR_MAXATTR;
348}
349
350/** @} */
351
352/**
353 * @name Operations
354 * @{
355 */
356
357int genl_family_add_op(struct genl_family *family, int id, int flags)
358{
359 struct genl_family_op *op;
360
361 op = calloc(1, sizeof(*op));
362 if (op == NULL)
363 return -NLE_NOMEM;
364
365 op->o_id = id;
366 op->o_flags = flags;
367
368 nl_list_add_tail(&op->o_list, &family->gf_ops);
369 family->ce_mask |= FAMILY_ATTR_OPS;
370
371 return 0;
372}
373
374int genl_family_add_grp(struct genl_family *family, uint32_t id,
375 const char *name)
376{
377 struct genl_family_grp *grp;
378
379 if ( !name
380 || strlen (name) >= GENL_NAMSIZ)
381 return -NLE_INVAL;
382
383 grp = calloc(1, sizeof(*grp));
384 if (grp == NULL)
385 return -NLE_NOMEM;
386
387 grp->id = id;
388 _nl_strncpy_assert(grp->name, name, GENL_NAMSIZ);
389
390 nl_list_add_tail(&grp->list, &family->gf_mc_grps);
391
392 return 0;
393}
394
395/** @} */
396
397/** @cond SKIP */
398struct nl_object_ops genl_family_ops = {
399 .oo_name = "genl/family",
400 .oo_size = sizeof(struct genl_family),
401 .oo_constructor = family_constructor,
402 .oo_free_data = family_free_data,
403 .oo_clone = family_clone,
404 .oo_dump = {
405 [NL_DUMP_LINE] = family_dump_line,
406 [NL_DUMP_DETAILS] = family_dump_details,
407 [NL_DUMP_STATS] = family_dump_stats,
408 },
409 .oo_compare = family_compare,
410 .oo_id_attrs = FAMILY_ATTR_ID,
411};
412/** @endcond */
413
414/** @} */
void genl_family_set_name(struct genl_family *family, const char *name)
Set human readable name.
Definition family.c:266
void genl_family_set_version(struct genl_family *family, uint8_t version)
Set interface version.
Definition family.c:296
struct genl_family * genl_family_alloc(void)
Allocate new Generic Netlink family object.
Definition family.c:189
void genl_family_put(struct genl_family *family)
Release reference on Generic Netlink family object.
Definition family.c:203
uint8_t genl_family_get_version(struct genl_family *family)
Return interface version.
Definition family.c:283
char * genl_family_get_name(struct genl_family *family)
Return human readable name.
Definition family.c:253
unsigned int genl_family_get_id(struct genl_family *family)
Return numeric identifier.
Definition family.c:221
uint32_t genl_family_get_hdrsize(struct genl_family *family)
Return user header size expected by kernel component.
Definition family.c:315
void genl_family_set_id(struct genl_family *family, unsigned int id)
Set the numeric identifier.
Definition family.c:234
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition object.c:221
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
Definition object.c:55
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
@ NL_DUMP_STATS
Dump all attributes including statistics.
Definition types.h:22
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition types.h:20
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition types.h:21
Dumping parameters.
Definition types.h:32