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