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