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