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