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 = obj_ops(obj);
00136
00137 if (obj->ce_refcnt > 0)
00138 NL_DBG(1, "Warning: Freeing object in use...\n");
00139
00140 if (obj->ce_cache)
00141 nl_cache_remove(obj);
00142
00143 if (ops->oo_free_data)
00144 ops->oo_free_data(obj);
00145
00146 free(obj);
00147
00148 NL_DBG(4, "Freed object %p\n", obj);
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 void nl_object_get(struct nl_object *obj)
00163 {
00164 obj->ce_refcnt++;
00165 NL_DBG(4, "New reference to object %p, total %d\n",
00166 obj, obj->ce_refcnt);
00167 }
00168
00169
00170
00171
00172
00173 void nl_object_put(struct nl_object *obj)
00174 {
00175 if (!obj)
00176 return;
00177
00178 obj->ce_refcnt--;
00179 NL_DBG(4, "Returned object reference %p, %d remaining\n",
00180 obj, obj->ce_refcnt);
00181
00182 if (obj->ce_refcnt < 0)
00183 BUG();
00184
00185 if (obj->ce_refcnt <= 0)
00186 nl_object_free(obj);
00187 }
00188
00189
00190
00191
00192
00193
00194 int nl_object_shared(struct nl_object *obj)
00195 {
00196 return obj->ce_refcnt > 1;
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 void nl_object_mark(struct nl_object *obj)
00211 {
00212 obj->ce_flags |= NL_OBJ_MARK;
00213 }
00214
00215
00216
00217
00218
00219 void nl_object_unmark(struct nl_object *obj)
00220 {
00221 obj->ce_flags &= ~NL_OBJ_MARK;
00222 }
00223
00224
00225
00226
00227
00228
00229 int nl_object_is_marked(struct nl_object *obj)
00230 {
00231 return (obj->ce_flags & NL_OBJ_MARK);
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
00247 {
00248 dump_from_ops(obj, params);
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 int nl_object_identical(struct nl_object *a, struct nl_object *b)
00259 {
00260 struct nl_object_ops *ops = obj_ops(a);
00261 int req_attrs;
00262
00263
00264 if (ops != obj_ops(b))
00265 return 0;
00266
00267 req_attrs = ops->oo_id_attrs;
00268
00269
00270
00271 if ((a->ce_mask & req_attrs) != req_attrs ||
00272 (b->ce_mask & req_attrs) != req_attrs)
00273 return 0;
00274
00275
00276 if (ops->oo_compare == NULL)
00277 return 0;
00278
00279 return !(ops->oo_compare(a, b, req_attrs, 0));
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
00295 {
00296 struct nl_object_ops *ops = obj_ops(a);
00297
00298 if (ops != obj_ops(b) || ops->oo_compare == NULL)
00299 return UINT_MAX;
00300
00301 return ops->oo_compare(a, b, ~0, 0);
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
00314 {
00315 struct nl_object_ops *ops = obj_ops(obj);
00316
00317 if (ops != obj_ops(filter) || ops->oo_compare == NULL)
00318 return 0;
00319
00320 return !(ops->oo_compare(obj, filter, filter->ce_mask,
00321 LOOSE_FLAG_COMPARISON));
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 char *nl_object_attrs2str(struct nl_object *obj, uint32_t attrs,
00337 char *buf, size_t len)
00338 {
00339 struct nl_object_ops *ops = obj_ops(obj);
00340
00341 if (ops->oo_attrs2str != NULL)
00342 return ops->oo_attrs2str(attrs, buf, len);
00343 else {
00344 memset(buf, 0, len);
00345 return buf;
00346 }
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len)
00358 {
00359 return nl_object_attrs2str(obj, obj->ce_mask, buf, len);
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369 int nl_object_get_refcnt(struct nl_object *obj)
00370 {
00371 return obj->ce_refcnt;
00372 }
00373
00374 struct nl_cache *nl_object_get_cache(struct nl_object *obj)
00375 {
00376 return obj->ce_cache;
00377 }
00378
00379 void *nl_object_priv(struct nl_object *obj)
00380 {
00381 return obj;
00382 }
00383
00384
00385
00386