00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <netlink-local.h>
00018 #include <netlink/netlink.h>
00019 #include <netlink/cache.h>
00020 #include <netlink/utils.h>
00021
00022 static struct nl_cache_ops *cache_ops;
00023 static NL_RW_LOCK(cache_ops_lock);
00024
00025
00026
00027
00028
00029
00030 struct nl_cache_ops *__nl_cache_ops_lookup(const char *name)
00031 {
00032 struct nl_cache_ops *ops;
00033
00034 for (ops = cache_ops; ops; ops = ops->co_next)
00035 if (!strcmp(ops->co_name, name))
00036 return ops;
00037
00038 return NULL;
00039 }
00040
00041
00042
00043
00044
00045 void nl_cache_ops_get(struct nl_cache_ops *ops)
00046 {
00047 ops->co_refcnt++;
00048 }
00049
00050
00051
00052
00053
00054 void nl_cache_ops_put(struct nl_cache_ops *ops)
00055 {
00056 ops->co_refcnt--;
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 struct nl_cache_ops *nl_cache_ops_lookup(const char *name)
00069 {
00070 struct nl_cache_ops *ops;
00071
00072 nl_read_lock(&cache_ops_lock);
00073 ops = __nl_cache_ops_lookup(name);
00074 nl_read_unlock(&cache_ops_lock);
00075
00076 return ops;
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 struct nl_cache_ops *nl_cache_ops_lookup_safe(const char *name)
00089 {
00090 struct nl_cache_ops *ops;
00091
00092 nl_write_lock(&cache_ops_lock);
00093 if ((ops = __nl_cache_ops_lookup(name)))
00094 nl_cache_ops_get(ops);
00095 nl_write_unlock(&cache_ops_lock);
00096
00097 return ops;
00098 }
00099
00100 static struct nl_cache_ops *__cache_ops_associate(int protocol, int msgtype)
00101 {
00102 int i;
00103 struct nl_cache_ops *ops;
00104
00105 for (ops = cache_ops; ops; ops = ops->co_next) {
00106 if (ops->co_protocol != protocol)
00107 continue;
00108
00109 for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
00110 if (ops->co_msgtypes[i].mt_id == msgtype)
00111 return ops;
00112 }
00113
00114 return NULL;
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype)
00130 {
00131 struct nl_cache_ops *ops;
00132
00133 nl_read_lock(&cache_ops_lock);
00134 ops = __cache_ops_associate(protocol, msgtype);
00135 nl_read_unlock(&cache_ops_lock);
00136
00137 return ops;
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 struct nl_cache_ops *nl_cache_ops_associate_safe(int protocol, int msgtype)
00154 {
00155 struct nl_cache_ops *ops;
00156
00157 nl_write_lock(&cache_ops_lock);
00158 if ((ops = __cache_ops_associate(protocol, msgtype)))
00159 nl_cache_ops_get(ops);
00160 nl_write_unlock(&cache_ops_lock);
00161
00162 return ops;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 struct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype)
00179 {
00180 int i;
00181
00182 for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
00183 if (ops->co_msgtypes[i].mt_id == msgtype)
00184 return &ops->co_msgtypes[i];
00185
00186 return NULL;
00187 }
00188
00189
00190 static struct nl_cache_ops *cache_ops_lookup_for_obj(struct nl_object_ops *obj_ops)
00191 {
00192 struct nl_cache_ops *ops;
00193
00194 for (ops = cache_ops; ops; ops = ops->co_next)
00195 if (ops->co_obj_ops == obj_ops)
00196 return ops;
00197
00198 return NULL;
00199
00200 }
00201
00202
00203
00204
00205
00206
00207 void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg)
00208 {
00209 struct nl_cache_ops *ops;
00210
00211 nl_read_lock(&cache_ops_lock);
00212 for (ops = cache_ops; ops; ops = ops->co_next)
00213 cb(ops, arg);
00214 nl_read_unlock(&cache_ops_lock);
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 int nl_cache_mngt_register(struct nl_cache_ops *ops)
00227 {
00228 if (!ops->co_name)
00229 return nl_error(EINVAL, "No cache name specified");
00230
00231 if (!ops->co_obj_ops)
00232 return nl_error(EINVAL, "No obj cache ops specified");
00233
00234 nl_write_lock(&cache_ops_lock);
00235 if (__nl_cache_ops_lookup(ops->co_name)) {
00236 nl_write_unlock(&cache_ops_lock);
00237 return nl_error(EEXIST, "Cache operations already exist");
00238 }
00239
00240 ops->co_refcnt = 0;
00241 ops->co_next = cache_ops;
00242 cache_ops = ops;
00243 nl_write_unlock(&cache_ops_lock);
00244
00245 NL_DBG(1, "Registered cache operations %s\n", ops->co_name);
00246
00247 return 0;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
00262 {
00263 struct nl_cache_ops *t, **tp;
00264
00265 nl_write_lock(&cache_ops_lock);
00266
00267 if (ops->co_refcnt > 0) {
00268 nl_write_unlock(&cache_ops_lock);
00269 return nl_error(EBUSY, "Cache operations busy");
00270 }
00271
00272 for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next)
00273 if (t == ops)
00274 break;
00275
00276 if (!t) {
00277 nl_write_unlock(&cache_ops_lock);
00278 return nl_error(ENOENT, "No such cache operations");
00279 }
00280
00281 NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name);
00282
00283 *tp = t->co_next;
00284 nl_write_unlock(&cache_ops_lock);
00285
00286 return 0;
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 void nl_cache_mngt_provide(struct nl_cache *cache)
00305 {
00306 struct nl_cache_ops *ops;
00307
00308 nl_write_lock(&cache_ops_lock);
00309
00310 ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
00311 if (!ops)
00312 BUG();
00313 else {
00314 nl_cache_get(cache);
00315 ops->co_major_cache = cache;
00316 }
00317
00318 nl_write_unlock(&cache_ops_lock);
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 void nl_cache_mngt_unprovide(struct nl_cache *cache)
00330 {
00331 struct nl_cache_ops *ops;
00332
00333 nl_write_lock(&cache_ops_lock);
00334
00335 ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
00336 if (!ops)
00337 BUG();
00338 else if (ops->co_major_cache == cache) {
00339 nl_cache_free(ops->co_major_cache);
00340 ops->co_major_cache = NULL;
00341 }
00342
00343 nl_write_unlock(&cache_ops_lock);
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 struct nl_cache *nl_cache_mngt_require(const char *name)
00357 {
00358 struct nl_cache_ops *ops;
00359
00360 ops = nl_cache_ops_lookup(name);
00361 if (!ops || !ops->co_major_cache) {
00362 fprintf(stderr, "Application BUG: Your application must "
00363 "call nl_cache_mngt_provide() and\nprovide a valid "
00364 "%s cache to be used for internal lookups.\nSee the "
00365 " API documentation for more details.\n", name);
00366
00367 return NULL;
00368 }
00369
00370 return ops->co_major_cache;
00371 }
00372
00373
00374
00375