00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 #include <netlink-local.h>
00085 #include <netlink/netlink.h>
00086 #include <netlink/cache.h>
00087 #include <netlink/utils.h>
00088
00089 static int include_cb(struct nl_object *obj, struct nl_parser_param *p)
00090 {
00091 struct nl_cache_assoc *ca = p->pp_arg;
00092
00093 NL_DBG(2, "Including object %p into cache %p\n", obj, ca->ca_cache);
00094 #ifdef NL_DEBUG
00095 if (nl_debug >= 4)
00096 nl_object_dump(obj, &nl_debug_dp);
00097 #endif
00098 return nl_cache_include(ca->ca_cache, obj, ca->ca_change);
00099 }
00100
00101 static int event_input(struct nl_msg *msg, void *arg)
00102 {
00103 struct nl_cache_mngr *mngr = arg;
00104 int protocol = nlmsg_get_proto(msg);
00105 int type = nlmsg_hdr(msg)->nlmsg_type;
00106 struct nl_cache_ops *ops;
00107 int i, n;
00108 struct nl_parser_param p = {
00109 .pp_cb = include_cb,
00110 };
00111
00112 NL_DBG(2, "Cache manager %p, handling new message %p as event\n",
00113 mngr, msg);
00114 #ifdef NL_DEBUG
00115 if (nl_debug >= 4)
00116 nl_msg_dump(msg, stderr);
00117 #endif
00118
00119 if (mngr->cm_protocol != protocol)
00120 BUG();
00121
00122 for (i = 0; i < mngr->cm_nassocs; i++) {
00123 if (mngr->cm_assocs[i].ca_cache) {
00124 ops = mngr->cm_assocs[i].ca_cache->c_ops;
00125 for (n = 0; ops->co_msgtypes[n].mt_id >= 0; n++)
00126 if (ops->co_msgtypes[n].mt_id == type)
00127 goto found;
00128 }
00129 }
00130
00131 return NL_SKIP;
00132
00133 found:
00134 NL_DBG(2, "Associated message %p to cache %p\n",
00135 msg, mngr->cm_assocs[i].ca_cache);
00136 p.pp_arg = &mngr->cm_assocs[i];
00137
00138 return nl_cache_parse(ops, NULL, nlmsg_hdr(msg), &p);
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags,
00150 struct nl_cache_mngr **result)
00151 {
00152 struct nl_cache_mngr *mngr;
00153 int err = -NLE_NOMEM;
00154
00155 if (sk == NULL)
00156 BUG();
00157
00158 mngr = calloc(1, sizeof(*mngr));
00159 if (!mngr)
00160 goto errout;
00161
00162 mngr->cm_handle = sk;
00163 mngr->cm_nassocs = 32;
00164 mngr->cm_protocol = protocol;
00165 mngr->cm_flags = flags;
00166 mngr->cm_assocs = calloc(mngr->cm_nassocs,
00167 sizeof(struct nl_cache_assoc));
00168 if (!mngr->cm_assocs)
00169 goto errout;
00170
00171 nl_socket_modify_cb(mngr->cm_handle, NL_CB_VALID, NL_CB_CUSTOM,
00172 event_input, mngr);
00173
00174
00175 nl_socket_disable_seq_check(mngr->cm_handle);
00176
00177 if ((err = nl_connect(mngr->cm_handle, protocol) < 0))
00178 goto errout;
00179
00180 if ((err = nl_socket_set_nonblocking(mngr->cm_handle) < 0))
00181 goto errout;
00182
00183 NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n",
00184 mngr, protocol, mngr->cm_nassocs);
00185
00186 *result = mngr;
00187 return 0;
00188
00189 errout:
00190 nl_cache_mngr_free(mngr);
00191 return err;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 int nl_cache_mngr_add(struct nl_cache_mngr *mngr, const char *name,
00210 change_func_t cb, struct nl_cache **result)
00211 {
00212 struct nl_cache_ops *ops;
00213 struct nl_cache *cache;
00214 struct nl_af_group *grp;
00215 int err, i;
00216
00217 ops = nl_cache_ops_lookup(name);
00218 if (!ops)
00219 return -NLE_NOCACHE;
00220
00221 if (ops->co_protocol != mngr->cm_protocol)
00222 return -NLE_PROTO_MISMATCH;
00223
00224 if (ops->co_groups == NULL)
00225 return -NLE_OPNOTSUPP;
00226
00227 for (i = 0; i < mngr->cm_nassocs; i++)
00228 if (mngr->cm_assocs[i].ca_cache &&
00229 mngr->cm_assocs[i].ca_cache->c_ops == ops)
00230 return -NLE_EXIST;
00231
00232 retry:
00233 for (i = 0; i < mngr->cm_nassocs; i++)
00234 if (!mngr->cm_assocs[i].ca_cache)
00235 break;
00236
00237 if (i >= mngr->cm_nassocs) {
00238 mngr->cm_nassocs += 16;
00239 mngr->cm_assocs = realloc(mngr->cm_assocs,
00240 mngr->cm_nassocs *
00241 sizeof(struct nl_cache_assoc));
00242 if (mngr->cm_assocs == NULL)
00243 return -NLE_NOMEM;
00244 else {
00245 NL_DBG(1, "Increased capacity of cache manager %p " \
00246 "to %d\n", mngr, mngr->cm_nassocs);
00247 goto retry;
00248 }
00249 }
00250
00251 cache = nl_cache_alloc(ops);
00252 if (!cache)
00253 return -NLE_NOMEM;
00254
00255 for (grp = ops->co_groups; grp->ag_group; grp++) {
00256 err = nl_socket_add_membership(mngr->cm_handle, grp->ag_group);
00257 if (err < 0)
00258 goto errout_free_cache;
00259 }
00260
00261 err = nl_cache_refill(mngr->cm_handle, cache);
00262 if (err < 0)
00263 goto errout_drop_membership;
00264
00265 mngr->cm_assocs[i].ca_cache = cache;
00266 mngr->cm_assocs[i].ca_change = cb;
00267
00268 if (mngr->cm_flags & NL_AUTO_PROVIDE)
00269 nl_cache_mngt_provide(cache);
00270
00271 NL_DBG(1, "Added cache %p <%s> to cache manager %p\n",
00272 cache, nl_cache_name(cache), mngr);
00273
00274 *result = cache;
00275 return 0;
00276
00277 errout_drop_membership:
00278 for (grp = ops->co_groups; grp->ag_group; grp++)
00279 nl_socket_drop_membership(mngr->cm_handle, grp->ag_group);
00280 errout_free_cache:
00281 nl_cache_free(cache);
00282
00283 return err;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 int nl_cache_mngr_get_fd(struct nl_cache_mngr *mngr)
00295 {
00296 return nl_socket_get_fd(mngr->cm_handle);
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout)
00315 {
00316 int ret;
00317 struct pollfd fds = {
00318 .fd = nl_socket_get_fd(mngr->cm_handle),
00319 .events = POLLIN,
00320 };
00321
00322 NL_DBG(3, "Cache manager %p, poll() fd %d\n", mngr, fds.fd);
00323 ret = poll(&fds, 1, timeout);
00324 NL_DBG(3, "Cache manager %p, poll() returned %d\n", mngr, ret);
00325 if (ret < 0)
00326 return -nl_syserr2nlerr(errno);
00327
00328 if (ret == 0)
00329 return 0;
00330
00331 return nl_cache_mngr_data_ready(mngr);
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr)
00346 {
00347 int err;
00348
00349 err = nl_recvmsgs_default(mngr->cm_handle);
00350 if (err < 0)
00351 return err;
00352
00353 return 1;
00354 }
00355
00356
00357
00358
00359
00360
00361
00362 void nl_cache_mngr_free(struct nl_cache_mngr *mngr)
00363 {
00364 int i;
00365
00366 if (!mngr)
00367 return;
00368
00369 if (mngr->cm_handle)
00370 nl_close(mngr->cm_handle);
00371
00372 for (i = 0; i < mngr->cm_nassocs; i++)
00373 if (mngr->cm_assocs[i].ca_cache)
00374 nl_cache_free(mngr->cm_assocs[i].ca_cache);
00375
00376 free(mngr->cm_assocs);
00377 free(mngr);
00378
00379 NL_DBG(1, "Cache manager %p freed\n", mngr);
00380 }
00381
00382