libnl  3.2.11
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-local.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  */
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(kind);
89  if (!ops)
90  return -NLE_OPNOTSUPP;
91 
92  if (!(*result = nl_object_alloc(ops->co_obj_ops)))
93  return -NLE_NOMEM;
94 
95  return 0;
96 }
97 
100  char data;
101 };
102 
103 /**
104  * Allocate a new object and copy all data from an existing object
105  * @arg obj object to inherite data from
106  * @return The new object or NULL.
107  */
108 struct nl_object *nl_object_clone(struct nl_object *obj)
109 {
110  struct nl_object *new;
111  struct nl_object_ops *ops = obj_ops(obj);
112  int doff = offsetof(struct nl_derived_object, data);
113  int size;
114 
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((void *)new + doff, (void *)obj + doff, size);
129 
130  if (ops->oo_clone) {
131  if (ops->oo_clone(new, obj) < 0) {
132  nl_object_free(new);
133  return NULL;
134  }
135  } else if (size && ops->oo_free_data)
136  BUG();
137 
138  return new;
139 }
140 
141 /**
142  * Free a cacheable object
143  * @arg obj object to free
144  *
145  * @return 0 or a negative error code.
146  */
147 void nl_object_free(struct nl_object *obj)
148 {
149  struct nl_object_ops *ops = obj_ops(obj);
150 
151  if (obj->ce_refcnt > 0)
152  NL_DBG(1, "Warning: Freeing object in use...\n");
153 
154  if (obj->ce_cache)
155  nl_cache_remove(obj);
156 
157  if (ops->oo_free_data)
158  ops->oo_free_data(obj);
159 
160  free(obj);
161 
162  NL_DBG(4, "Freed object %p\n", obj);
163 }
164 
165 /** @} */
166 
167 /**
168  * @name Reference Management
169  * @{
170  */
171 
172 /**
173  * Acquire a reference on a object
174  * @arg obj object to acquire reference from
175  */
176 void nl_object_get(struct nl_object *obj)
177 {
178  obj->ce_refcnt++;
179  NL_DBG(4, "New reference to object %p, total %d\n",
180  obj, obj->ce_refcnt);
181 }
182 
183 /**
184  * Release a reference from an object
185  * @arg obj object to release reference from
186  */
187 void nl_object_put(struct nl_object *obj)
188 {
189  if (!obj)
190  return;
191 
192  obj->ce_refcnt--;
193  NL_DBG(4, "Returned object reference %p, %d remaining\n",
194  obj, obj->ce_refcnt);
195 
196  if (obj->ce_refcnt < 0)
197  BUG();
198 
199  if (obj->ce_refcnt <= 0)
200  nl_object_free(obj);
201 }
202 
203 /**
204  * Check whether this object is used by multiple users
205  * @arg obj object to check
206  * @return true or false
207  */
208 int nl_object_shared(struct nl_object *obj)
209 {
210  return obj->ce_refcnt > 1;
211 }
212 
213 /** @} */
214 
215 /**
216  * @name Marks
217  * @{
218  */
219 
220 /**
221  * Add mark to object
222  * @arg obj Object to mark
223  */
224 void nl_object_mark(struct nl_object *obj)
225 {
226  obj->ce_flags |= NL_OBJ_MARK;
227 }
228 
229 /**
230  * Remove mark from object
231  * @arg obj Object to unmark
232  */
233 void nl_object_unmark(struct nl_object *obj)
234 {
235  obj->ce_flags &= ~NL_OBJ_MARK;
236 }
237 
238 /**
239  * Return true if object is marked
240  * @arg obj Object to check
241  * @return true if object is marked, otherwise false
242  */
244 {
245  return (obj->ce_flags & NL_OBJ_MARK);
246 }
247 
248 /** @} */
249 
250 /**
251  * @name Utillities
252  * @{
253  */
254 
255 /**
256  * Dump this object according to the specified parameters
257  * @arg obj object to dump
258  * @arg params dumping parameters
259  */
260 void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
261 {
262  if (params->dp_buf)
263  memset(params->dp_buf, 0, params->dp_buflen);
264 
265  dump_from_ops(obj, params);
266 }
267 
268 void nl_object_dump_buf(struct nl_object *obj, char *buf, size_t len)
269 {
270  struct nl_dump_params dp = {
271  .dp_buf = buf,
272  .dp_buflen = len,
273  };
274 
275  return nl_object_dump(obj, &dp);
276 }
277 
278 /**
279  * Check if the identifiers of two objects are identical
280  * @arg a an object
281  * @arg b another object of same type
282  *
283  * @return true if both objects have equal identifiers, otherwise false.
284  */
285 int nl_object_identical(struct nl_object *a, struct nl_object *b)
286 {
287  struct nl_object_ops *ops = obj_ops(a);
288  uint32_t req_attrs;
289 
290  /* Both objects must be of same type */
291  if (ops != obj_ops(b))
292  return 0;
293 
294  req_attrs = ops->oo_id_attrs;
295  if (req_attrs == 0xFFFFFFFF)
296  req_attrs = a->ce_mask & b->ce_mask;
297 
298  /* Both objects must provide all required attributes to uniquely
299  * identify an object */
300  if ((a->ce_mask & req_attrs) != req_attrs ||
301  (b->ce_mask & req_attrs) != req_attrs)
302  return 0;
303 
304  /* Can't judge unless we can compare */
305  if (ops->oo_compare == NULL)
306  return 0;
307 
308  return !(ops->oo_compare(a, b, req_attrs, 0));
309 }
310 
311 /**
312  * Compute bitmask representing difference in attribute values
313  * @arg a an object
314  * @arg b another object of same type
315  *
316  * The bitmask returned is specific to an object type, each bit set represents
317  * an attribute which mismatches in either of the two objects. Unavailability
318  * of an attribute in one object and presence in the other is regarded a
319  * mismatch as well.
320  *
321  * @return Bitmask describing differences or 0 if they are completely identical.
322  */
323 uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
324 {
325  struct nl_object_ops *ops = obj_ops(a);
326 
327  if (ops != obj_ops(b) || ops->oo_compare == NULL)
328  return UINT_MAX;
329 
330  return ops->oo_compare(a, b, ~0, 0);
331 }
332 
333 /**
334  * Match a filter against an object
335  * @arg obj object to check
336  * @arg filter object of same type acting as filter
337  *
338  * @return 1 if the object matches the filter or 0
339  * if no filter procedure is available or if the
340  * filter does not match.
341  */
342 int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
343 {
344  struct nl_object_ops *ops = obj_ops(obj);
345 
346  if (ops != obj_ops(filter) || ops->oo_compare == NULL)
347  return 0;
348 
349  return !(ops->oo_compare(obj, filter, filter->ce_mask,
350  LOOSE_COMPARISON));
351 }
352 
353 /**
354  * Convert bitmask of attributes to a character string
355  * @arg obj object of same type as attribute bitmask
356  * @arg attrs bitmask of attribute types
357  * @arg buf destination buffer
358  * @arg len length of destination buffer
359  *
360  * Converts the bitmask of attribute types into a list of attribute
361  * names separated by comas.
362  *
363  * @return destination buffer.
364  */
365 char *nl_object_attrs2str(struct nl_object *obj, uint32_t attrs,
366  char *buf, size_t len)
367 {
368  struct nl_object_ops *ops = obj_ops(obj);
369 
370  if (ops->oo_attrs2str != NULL)
371  return ops->oo_attrs2str(attrs, buf, len);
372  else {
373  memset(buf, 0, len);
374  return buf;
375  }
376 }
377 
378 /**
379  * Return list of attributes present in an object
380  * @arg obj an object
381  * @arg buf destination buffer
382  * @arg len length of destination buffer
383  *
384  * @return destination buffer.
385  */
386 char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len)
387 {
388  return nl_object_attrs2str(obj, obj->ce_mask, buf, len);
389 }
390 
391 /** @} */
392 
393 /**
394  * @name Attributes
395  * @{
396  */
397 
398 /**
399  * Return number of references held
400  * @arg obj object
401  *
402  * @return The number of references held to this object
403  */
405 {
406  return obj->ce_refcnt;
407 }
408 
409 /**
410  * Return cache the object is associated with
411  * @arg obj object
412  *
413  * @note The returned pointer is not protected with a reference counter,
414  * it is your responsibility.
415  *
416  * @return Pointer to cache or NULL if not associated with a cache.
417  */
418 struct nl_cache *nl_object_get_cache(struct nl_object *obj)
419 {
420  return obj->ce_cache;
421 }
422 
423 /**
424  * Return the object's type
425  * @arg obj object
426  *
427  * FIXME: link to list of object types
428  *
429  * @return Name of the object type
430  */
431 const char *nl_object_get_type(const struct nl_object *obj)
432 {
433  if (!obj->ce_ops)
434  BUG();
435 
436  return obj->ce_ops->oo_name;
437 }
438 
439 /**
440  * Return the netlink message type the object was derived from
441  * @arg obj object
442  *
443  * @return Netlink message type or 0.
444  */
445 int nl_object_get_msgtype(const struct nl_object *obj)
446 {
447  return obj->ce_msgtype;
448 }
449 
450 /**
451  * Return object operations structure
452  * @arg obj object
453  *
454  * @return Pointer to the object operations structure
455  */
456 struct nl_object_ops *nl_object_get_ops(const struct nl_object *obj)
457 {
458  return obj->ce_ops;
459 }
460 
461 /** @} */
462 
463 /** @} */