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