00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <netlink-local.h>
00019 #include <netlink/netlink.h>
00020 #include <netlink/cache.h>
00021 #include <netlink/object.h>
00022 #include <netlink/utils.h>
00023
00024 static inline struct nl_object_ops *obj_ops(struct nl_object *obj)
00025 {
00026 if (!obj->ce_ops)
00027 BUG();
00028
00029 return obj->ce_ops;
00030 }
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 struct nl_object *nl_object_alloc(struct nl_object_ops *ops)
00043 {
00044 struct nl_object *new;
00045
00046 if (ops->oo_size < sizeof(*new))
00047 BUG();
00048
00049 new = calloc(1, ops->oo_size);
00050 if (!new)
00051 return NULL;
00052
00053 new->ce_refcnt = 1;
00054 nl_init_list_head(&new->ce_list);
00055
00056 new->ce_ops = ops;
00057 if (ops->oo_constructor)
00058 ops->oo_constructor(new);
00059
00060 NL_DBG(4, "Allocated new object %p\n", new);
00061
00062 return new;
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072 int nl_object_alloc_name(const char *kind, struct nl_object **result)
00073 {
00074 struct nl_cache_ops *ops;
00075
00076 ops = nl_cache_ops_lookup(kind);
00077 if (!ops)
00078 return -NLE_OPNOTSUPP;
00079
00080 if (!(*result = nl_object_alloc(ops->co_obj_ops)))
00081 return -NLE_NOMEM;
00082
00083 return 0;
00084 }
00085
00086 struct nl_derived_object {
00087 NLHDR_COMMON
00088 char data;
00089 };
00090
00091
00092
00093
00094
00095
00096 struct nl_object *nl_object_clone(struct nl_object *obj)
00097 {
00098 struct nl_object *new;
00099 struct nl_object_ops *ops = obj_ops(obj);
00100 int doff = offsetof(struct nl_derived_object, data);
00101 int size;
00102
00103 new = nl_object_alloc(ops);
00104 if (!new)
00105 return NULL;
00106
00107 size = ops->oo_size - doff;
00108 if (size < 0)
00109 BUG();
00110
00111 new->ce_ops = obj->ce_ops;
00112 new->ce_msgtype = obj->ce_msgtype;
00113 new->ce_mask = obj->ce_mask;
00114
00115 if (size)
00116 memcpy((void *)new + doff, (void *)obj + doff, size);
00117
00118 if (ops->oo_clone) {
00119 if (ops->oo_clone(new, obj) < 0) {
00120 nl_object_free(new);
00121 return NULL;
00122 }
00123 } else if (size && ops->oo_free_data)
00124 BUG();
00125
00126 return new;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 void nl_object_free(struct nl_object *obj)
00136 {
00137 struct nl_object_ops *ops = obj_ops(obj);
00138
00139 if (obj->ce_refcnt > 0)
00140 NL_DBG(1, "Warning: Freeing object in use...\n");
00141
00142 if (obj->ce_cache)
00143 nl_cache_remove(obj);
00144
00145 if (ops->oo_free_data)
00146 ops->oo_free_data(obj);
00147
00148 free(obj);
00149
00150 NL_DBG(4, "Freed object %p\n", obj);
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 void nl_object_get(struct nl_object *obj)
00165 {
00166 obj->ce_refcnt++;
00167 NL_DBG(4, "New reference to object %p, total %d\n",
00168 obj, obj->ce_refcnt);
00169 }
00170
00171
00172
00173
00174
00175 void nl_object_put(struct nl_object *obj)
00176 {
00177 if (!obj)
00178 return;
00179
00180 obj->ce_refcnt--;
00181 NL_DBG(4, "Returned object reference %p, %d remaining\n",
00182 obj, obj->ce_refcnt);
00183
00184 if (obj->ce_refcnt < 0)
00185 BUG();
00186
00187 if (obj->ce_refcnt <= 0)
00188 nl_object_free(obj);
00189 }
00190
00191
00192
00193
00194
00195
00196 int nl_object_shared(struct nl_object *obj)
00197 {
00198 return obj->ce_refcnt > 1;
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 void nl_object_mark(struct nl_object *obj)
00213 {
00214 obj->ce_flags |= NL_OBJ_MARK;
00215 }
00216
00217
00218
00219
00220
00221 void nl_object_unmark(struct nl_object *obj)
00222 {
00223 obj->ce_flags &= ~NL_OBJ_MARK;
00224 }
00225
00226
00227
00228
00229
00230
00231 int nl_object_is_marked(struct nl_object *obj)
00232 {
00233 return (obj->ce_flags & NL_OBJ_MARK);
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
00249 {
00250 dump_from_ops(obj, params);
00251 }
00252
00253 void nl_object_dump_buf(struct nl_object *obj, char *buf, size_t len)
00254 {
00255 struct nl_dump_params dp = {
00256 .dp_buf = buf,
00257 .dp_buflen = len,
00258 };
00259
00260 return nl_object_dump(obj, &dp);
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270 int nl_object_identical(struct nl_object *a, struct nl_object *b)
00271 {
00272 struct nl_object_ops *ops = obj_ops(a);
00273 int req_attrs;
00274
00275
00276 if (ops != obj_ops(b))
00277 return 0;
00278
00279 req_attrs = ops->oo_id_attrs;
00280 if (req_attrs == ~0)
00281 req_attrs = a->ce_mask & b->ce_mask;
00282
00283
00284
00285 if ((a->ce_mask & req_attrs) != req_attrs ||
00286 (b->ce_mask & req_attrs) != req_attrs)
00287 return 0;
00288
00289
00290 if (ops->oo_compare == NULL)
00291 return 0;
00292
00293 return !(ops->oo_compare(a, b, req_attrs, 0));
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
00309 {
00310 struct nl_object_ops *ops = obj_ops(a);
00311
00312 if (ops != obj_ops(b) || ops->oo_compare == NULL)
00313 return UINT_MAX;
00314
00315 return ops->oo_compare(a, b, ~0, 0);
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
00328 {
00329 struct nl_object_ops *ops = obj_ops(obj);
00330
00331 if (ops != obj_ops(filter) || ops->oo_compare == NULL)
00332 return 0;
00333
00334 return !(ops->oo_compare(obj, filter, filter->ce_mask,
00335 LOOSE_COMPARISON));
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 char *nl_object_attrs2str(struct nl_object *obj, uint32_t attrs,
00351 char *buf, size_t len)
00352 {
00353 struct nl_object_ops *ops = obj_ops(obj);
00354
00355 if (ops->oo_attrs2str != NULL)
00356 return ops->oo_attrs2str(attrs, buf, len);
00357 else {
00358 memset(buf, 0, len);
00359 return buf;
00360 }
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len)
00372 {
00373 return nl_object_attrs2str(obj, obj->ce_mask, buf, len);
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383 int nl_object_get_refcnt(struct nl_object *obj)
00384 {
00385 return obj->ce_refcnt;
00386 }
00387
00388 struct nl_cache *nl_object_get_cache(struct nl_object *obj)
00389 {
00390 return obj->ce_cache;
00391 }
00392
00393
00394
00395