libnl 3.7.0
object.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 core_types
8 * @defgroup object Object (Cacheable)
9 *
10 * Generic object data type, for inheritance purposes to implement cacheable
11 * data types.
12 *
13 * Related sections in the development guide:
14 *
15 * @{
16 *
17 * Header
18 * ------
19 * ~~~~{.c}
20 * #include <netlink/object.h>
21 * ~~~~
22 */
23
24#include <netlink-private/netlink.h>
25#include <netlink/netlink.h>
26#include <netlink/cache.h>
27#include <netlink/object.h>
28#include <netlink/utils.h>
29
30static inline struct nl_object_ops *obj_ops(struct nl_object *obj)
31{
32 if (!obj->ce_ops)
33 BUG();
34
35 return obj->ce_ops;
36}
37
38/**
39 * @name Object Creation/Deletion
40 * @{
41 */
42
43/**
44 * Allocate a new object of kind specified by the operations handle
45 * @arg ops cache operations handle
46 * @return The new object or NULL
47 */
48struct nl_object *nl_object_alloc(struct nl_object_ops *ops)
49{
50 struct nl_object *new;
51
52 if (ops->oo_size < sizeof(*new))
53 BUG();
54
55 new = calloc(1, ops->oo_size);
56 if (!new)
57 return NULL;
58
59 new->ce_refcnt = 1;
60 nl_init_list_head(&new->ce_list);
61
62 new->ce_ops = ops;
63 if (ops->oo_constructor)
64 ops->oo_constructor(new);
65
66 NL_DBG(4, "Allocated new object %p\n", new);
67
68 return new;
69}
70
71/**
72 * Allocate new object of kind specified by the name
73 * @arg kind name of object type
74 * @arg result Result pointer
75 *
76 * @return 0 on success or a negative error code.
77 */
78int nl_object_alloc_name(const char *kind, struct nl_object **result)
79{
80 struct nl_cache_ops *ops;
81
82 ops = nl_cache_ops_lookup_safe(kind);
83 if (!ops)
84 return -NLE_OPNOTSUPP;
85
86 *result = nl_object_alloc(ops->co_obj_ops);
88 if (!*result)
89 return -NLE_NOMEM;
90
91 return 0;
92}
93
95 NLHDR_COMMON
96 char data;
97};
98
99/**
100 * Allocate a new object and copy all data from an existing object
101 * @arg obj object to inherite data from
102 * @return The new object or NULL.
103 */
104struct nl_object *nl_object_clone(struct nl_object *obj)
105{
106 struct nl_object *new;
107 struct nl_object_ops *ops;
108 int doff = offsetof(struct nl_derived_object, data);
109 int size;
110
111 if (!obj)
112 return NULL;
113
114 ops = obj_ops(obj);
115 new = nl_object_alloc(ops);
116 if (!new)
117 return NULL;
118
119 size = ops->oo_size - doff;
120 if (size < 0)
121 BUG();
122
123 new->ce_ops = obj->ce_ops;
124 new->ce_msgtype = obj->ce_msgtype;
125 new->ce_mask = obj->ce_mask;
126
127 if (size)
128 memcpy((char *)new + doff, (char *)obj + doff, size);
129
130 /* Note that the base implementation already initializes @new via memcpy().
131 * That means, simple fields don't need to be handled via oo_clone().
132 * However, this is only a shallow-copy, so oo_clone() MUST fix all
133 * pointer values accordingly. */
134
135 if (ops->oo_clone) {
136 if (ops->oo_clone(new, obj) < 0) {
137 nl_object_free(new);
138 return NULL;
139 }
140 } else if (size && ops->oo_free_data)
141 BUG();
142
143 return new;
144}
145
146/**
147 * Merge a cacheable object
148 * @arg dst object to be merged into
149 * @arg src new object to be merged into dst
150 *
151 * @return 0 or a negative error code.
152 */
153int nl_object_update(struct nl_object *dst, struct nl_object *src)
154{
155 struct nl_object_ops *ops = obj_ops(dst);
156
157 if (ops->oo_update)
158 return ops->oo_update(dst, src);
159
160 return -NLE_OPNOTSUPP;
161}
162
163/**
164 * Free a cacheable object
165 * @arg obj object to free
166 *
167 * @return 0 or a negative error code.
168 */
169void nl_object_free(struct nl_object *obj)
170{
171 struct nl_object_ops *ops;
172
173 if (!obj)
174 return;
175
176 ops = obj_ops(obj);
177
178 if (obj->ce_refcnt > 0)
179 NL_DBG(1, "Warning: Freeing object in use...\n");
180
181 if (obj->ce_cache)
182 nl_cache_remove(obj);
183
184 if (ops->oo_free_data)
185 ops->oo_free_data(obj);
186
187 NL_DBG(4, "Freed object %p\n", obj);
188
189 free(obj);
190}
191
192/** @} */
193
194/**
195 * @name Reference Management
196 * @{
197 */
198
199/**
200 * Acquire a reference on a object
201 * @arg obj object to acquire reference from
202 */
203void nl_object_get(struct nl_object *obj)
204{
205 obj->ce_refcnt++;
206 NL_DBG(4, "New reference to object %p, total %d\n",
207 obj, obj->ce_refcnt);
208}
209
210/**
211 * Release a reference from an object
212 * @arg obj object to release reference from
213 */
214void nl_object_put(struct nl_object *obj)
215{
216 if (!obj)
217 return;
218
219 obj->ce_refcnt--;
220 NL_DBG(4, "Returned object reference %p, %d remaining\n",
221 obj, obj->ce_refcnt);
222
223 if (obj->ce_refcnt < 0)
224 BUG();
225
226 if (obj->ce_refcnt <= 0)
227 nl_object_free(obj);
228}
229
230/**
231 * Check whether this object is used by multiple users
232 * @arg obj object to check
233 * @return true or false
234 */
235int nl_object_shared(struct nl_object *obj)
236{
237 return obj->ce_refcnt > 1;
238}
239
240/** @} */
241
242/**
243 * @name Marks
244 * @{
245 */
246
247/**
248 * Add mark to object
249 * @arg obj Object to mark
250 */
251void nl_object_mark(struct nl_object *obj)
252{
253 obj->ce_flags |= NL_OBJ_MARK;
254}
255
256/**
257 * Remove mark from object
258 * @arg obj Object to unmark
259 */
260void nl_object_unmark(struct nl_object *obj)
261{
262 obj->ce_flags &= ~NL_OBJ_MARK;
263}
264
265/**
266 * Return true if object is marked
267 * @arg obj Object to check
268 * @return true if object is marked, otherwise false
269 */
270int nl_object_is_marked(struct nl_object *obj)
271{
272 return (obj->ce_flags & NL_OBJ_MARK);
273}
274
275/** @} */
276
277/**
278 * @name Utillities
279 * @{
280 */
281
282/**
283 * Dump this object according to the specified parameters
284 * @arg obj object to dump
285 * @arg params dumping parameters
286 */
287void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
288{
289 if (params->dp_buf)
290 memset(params->dp_buf, 0, params->dp_buflen);
291
292 dump_from_ops(obj, params);
293}
294
295void nl_object_dump_buf(struct nl_object *obj, char *buf, size_t len)
296{
297 struct nl_dump_params dp = {
298 .dp_buf = buf,
299 .dp_buflen = len,
300 };
301
302 nl_object_dump(obj, &dp);
303}
304
305/**
306 * Check if the identifiers of two objects are identical
307 * @arg a an object
308 * @arg b another object of same type
309 *
310 * @return true if both objects have equal identifiers, otherwise false.
311 */
312int nl_object_identical(struct nl_object *a, struct nl_object *b)
313{
314 struct nl_object_ops *ops;
315 uint64_t req_attrs_a;
316 uint64_t req_attrs_b;
317
318 if (a == b)
319 return 1;
320
321 /* Both objects must be of same type */
322 ops = obj_ops(a);
323 if (ops != obj_ops(b))
324 return 0;
325
326 /* Can't judge unless we can compare */
327 if (ops->oo_compare == NULL)
328 return 0;
329
330 if (ops->oo_id_attrs_get) {
331 req_attrs_a = ops->oo_id_attrs_get(a);
332 req_attrs_b = ops->oo_id_attrs_get(b);
333 } else if (ops->oo_id_attrs) {
334 req_attrs_a = ops->oo_id_attrs;
335 req_attrs_b = req_attrs_a;
336 } else {
337 req_attrs_a = UINT64_MAX;
338 req_attrs_b = req_attrs_a;
339 }
340
341 req_attrs_a &= a->ce_mask;
342 req_attrs_b &= b->ce_mask;
343
344 /* Both objects must provide all required attributes to uniquely
345 * identify an object */
346 if (req_attrs_a != req_attrs_b)
347 return 0;
348
349 return !(ops->oo_compare(a, b, req_attrs_a, ID_COMPARISON));
350}
351
352/**
353 * Compute bitmask representing difference in attribute values
354 * @arg a an object
355 * @arg b another object of same type
356 *
357 * The bitmask returned is specific to an object type, each bit set represents
358 * an attribute which mismatches in either of the two objects. Unavailability
359 * of an attribute in one object and presence in the other is regarded a
360 * mismatch as well.
361 *
362 * @return Bitmask describing differences or 0 if they are completely identical.
363 */
364uint64_t nl_object_diff64(struct nl_object *a, struct nl_object *b)
365{
366 struct nl_object_ops *ops = obj_ops(a);
367
368 if (ops != obj_ops(b) || ops->oo_compare == NULL)
369 return UINT64_MAX;
370
371 return ops->oo_compare(a, b, UINT64_MAX, 0);
372}
373
374/**
375 * Compute 32-bit bitmask representing difference in attribute values
376 * @arg a an object
377 * @arg b another object of same type
378 *
379 * The bitmask returned is specific to an object type, each bit set represents
380 * an attribute which mismatches in either of the two objects. Unavailability
381 * of an attribute in one object and presence in the other is regarded a
382 * mismatch as well.
383 *
384 * @return Bitmask describing differences or 0 if they are completely identical.
385 * 32nd bit indicates if higher bits from the 64-bit compare were
386 * different.
387 */
388uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
389{
390 uint64_t diff;
391
392 diff = nl_object_diff64(a, b);
393
394 return (diff & ~((uint64_t) 0xFFFFFFFF))
395 ? (uint32_t) diff | (1 << 31)
396 : (uint32_t) diff;
397}
398
399/**
400 * Match a filter against an object
401 * @arg obj object to check
402 * @arg filter object of same type acting as filter
403 *
404 * @return 1 if the object matches the filter or 0
405 * if no filter procedure is available or if the
406 * filter does not match.
407 */
408int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
409{
410 struct nl_object_ops *ops = obj_ops(obj);
411
412 if (ops != obj_ops(filter) || ops->oo_compare == NULL)
413 return 0;
414
415 return !(ops->oo_compare(obj, filter, filter->ce_mask,
416 LOOSE_COMPARISON));
417}
418
419/**
420 * Convert bitmask of attributes to a character string
421 * @arg obj object of same type as attribute bitmask
422 * @arg attrs bitmask of attribute types
423 * @arg buf destination buffer
424 * @arg len length of destination buffer
425 *
426 * Converts the bitmask of attribute types into a list of attribute
427 * names separated by comas.
428 *
429 * @return destination buffer.
430 */
431char *nl_object_attrs2str(struct nl_object *obj, uint32_t attrs,
432 char *buf, size_t len)
433{
434 struct nl_object_ops *ops = obj_ops(obj);
435
436 if (ops->oo_attrs2str != NULL)
437 return ops->oo_attrs2str(attrs, buf, len);
438 else {
439 memset(buf, 0, len);
440 return buf;
441 }
442}
443
444/**
445 * Return list of attributes present in an object
446 * @arg obj an object
447 * @arg buf destination buffer
448 * @arg len length of destination buffer
449 *
450 * @return destination buffer.
451 */
452char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len)
453{
454 return nl_object_attrs2str(obj, obj->ce_mask, buf, len);
455}
456
457/**
458 * Generate object hash key
459 * @arg obj the object
460 * @arg hashkey destination buffer to be used for key stream
461 * @arg hashtbl_sz hash table size
462 *
463 * @return hash key in destination buffer
464 */
465void nl_object_keygen(struct nl_object *obj, uint32_t *hashkey,
466 uint32_t hashtbl_sz)
467{
468 struct nl_object_ops *ops = obj_ops(obj);
469
470 if (ops->oo_keygen)
471 ops->oo_keygen(obj, hashkey, hashtbl_sz);
472 else
473 *hashkey = 0;
474
475 return;
476}
477
478/** @} */
479
480/**
481 * @name Attributes
482 * @{
483 */
484
485/**
486 * Return number of references held
487 * @arg obj object
488 *
489 * @return The number of references held to this object
490 */
491int nl_object_get_refcnt(struct nl_object *obj)
492{
493 return obj->ce_refcnt;
494}
495
496/**
497 * Return cache the object is associated with
498 * @arg obj object
499 *
500 * @note The returned pointer is not protected with a reference counter,
501 * it is your responsibility.
502 *
503 * @return Pointer to cache or NULL if not associated with a cache.
504 */
505struct nl_cache *nl_object_get_cache(struct nl_object *obj)
506{
507 return obj->ce_cache;
508}
509
510/**
511 * Return the object's type
512 * @arg obj object
513 *
514 * FIXME: link to list of object types
515 *
516 * @return Name of the object type
517 */
518const char *nl_object_get_type(const struct nl_object *obj)
519{
520 if (!obj->ce_ops)
521 BUG();
522
523 return obj->ce_ops->oo_name;
524}
525
526/**
527 * Return the netlink message type the object was derived from
528 * @arg obj object
529 *
530 * @return Netlink message type or 0.
531 */
532int nl_object_get_msgtype(const struct nl_object *obj)
533{
534 return obj->ce_msgtype;
535}
536
537/**
538 * Return object operations structure
539 * @arg obj object
540 *
541 * @return Pointer to the object operations structure
542 */
543struct nl_object_ops *nl_object_get_ops(const struct nl_object *obj)
544{
545 return obj->ce_ops;
546}
547
548/**
549 * Return object id attribute mask
550 * @arg obj object
551 *
552 * @return object id attribute mask
553 */
554uint32_t nl_object_get_id_attrs(struct nl_object *obj)
555{
556 struct nl_object_ops *ops = obj_ops(obj);
557 uint32_t id_attrs;
558
559 if (!ops)
560 return 0;
561
562 if (ops->oo_id_attrs_get)
563 id_attrs = ops->oo_id_attrs_get(obj);
564 else
565 id_attrs = ops->oo_id_attrs;
566
567 return id_attrs;
568}
569
570/** @} */
571
572/** @} */
struct nl_cache_ops * nl_cache_ops_lookup_safe(const char *name)
Lookup cache operations by name.
Definition: cache_mngt.c:93
void nl_cache_ops_put(struct nl_cache_ops *ops)
Decrement reference counter.
Definition: cache_mngt.c:59
void nl_cache_remove(struct nl_object *obj)
Remove object from cache.
Definition: cache.c:546
int nl_object_alloc_name(const char *kind, struct nl_object **result)
Allocate new object of kind specified by the name.
Definition: object.c:78
struct nl_object_ops * nl_object_get_ops(const struct nl_object *obj)
Return object operations structure.
Definition: object.c:543
uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
Compute 32-bit bitmask representing difference in attribute values.
Definition: object.c:388
void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
Dump this object according to the specified parameters.
Definition: object.c:287
int nl_object_update(struct nl_object *dst, struct nl_object *src)
Merge a cacheable object.
Definition: object.c:153
const char * nl_object_get_type(const struct nl_object *obj)
Return the object's type.
Definition: object.c:518
struct nl_object * nl_object_clone(struct nl_object *obj)
Allocate a new object and copy all data from an existing object.
Definition: object.c:104
int nl_object_get_msgtype(const struct nl_object *obj)
Return the netlink message type the object was derived from.
Definition: object.c:532
char * nl_object_attrs2str(struct nl_object *obj, uint32_t attrs, char *buf, size_t len)
Convert bitmask of attributes to a character string.
Definition: object.c:431
uint64_t nl_object_diff64(struct nl_object *a, struct nl_object *b)
Compute bitmask representing difference in attribute values.
Definition: object.c:364
uint32_t nl_object_get_id_attrs(struct nl_object *obj)
Return object id attribute mask.
Definition: object.c:554
int nl_object_get_refcnt(struct nl_object *obj)
Return number of references held.
Definition: object.c:491
int nl_object_shared(struct nl_object *obj)
Check whether this object is used by multiple users.
Definition: object.c:235
void nl_object_unmark(struct nl_object *obj)
Remove mark from object.
Definition: object.c:260
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition: object.c:214
struct nl_cache * nl_object_get_cache(struct nl_object *obj)
Return cache the object is associated with.
Definition: object.c:505
int nl_object_identical(struct nl_object *a, struct nl_object *b)
Check if the identifiers of two objects are identical.
Definition: object.c:312
char * nl_object_attr_list(struct nl_object *obj, char *buf, size_t len)
Return list of attributes present in an object.
Definition: object.c:452
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition: object.c:203
void nl_object_free(struct nl_object *obj)
Free a cacheable object.
Definition: object.c:169
int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
Match a filter against an object.
Definition: object.c:408
int nl_object_is_marked(struct nl_object *obj)
Return true if object is marked.
Definition: object.c:270
void nl_object_mark(struct nl_object *obj)
Add mark to object.
Definition: object.c:251
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_object_keygen(struct nl_object *obj, uint32_t *hashkey, uint32_t hashtbl_sz)
Generate object hash key.
Definition: object.c:465
Dumping parameters.
Definition: types.h:28
size_t dp_buflen
Length of the buffer dp_buf.
Definition: types.h:87
char * dp_buf
Alternatively the output may be redirected into a buffer.
Definition: types.h:82