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, ca->ca_change_data);
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, void *data, 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 mngr->cm_assocs[i].ca_change_data = data;
00268
00269 if (mngr->cm_flags & NL_AUTO_PROVIDE)
00270 nl_cache_mngt_provide(cache);
00271
00272 NL_DBG(1, "Added cache %p <%s> to cache manager %p\n",
00273 cache, nl_cache_name(cache), mngr);
00274
00275 *result = cache;
00276 return 0;
00277
00278 errout_drop_membership:
00279 for (grp = ops->co_groups; grp->ag_group; grp++)
00280 nl_socket_drop_membership(mngr->cm_handle, grp->ag_group);
00281 errout_free_cache:
00282 nl_cache_free(cache);
00283
00284 return err;
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 int nl_cache_mngr_get_fd(struct nl_cache_mngr *mngr)
00296 {
00297 return nl_socket_get_fd(mngr->cm_handle);
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout)
00316 {
00317 int ret;
00318 struct pollfd fds = {
00319 .fd = nl_socket_get_fd(mngr->cm_handle),
00320 .events = POLLIN,
00321 };
00322
00323 NL_DBG(3, "Cache manager %p, poll() fd %d\n", mngr, fds.fd);
00324 ret = poll(&fds, 1, timeout);
00325 NL_DBG(3, "Cache manager %p, poll() returned %d\n", mngr, ret);
00326 if (ret < 0)
00327 return -nl_syserr2nlerr(errno);
00328
00329 if (ret == 0)
00330 return 0;
00331
00332 return nl_cache_mngr_data_ready(mngr);
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr)
00347 {
00348 int err;
00349
00350 err = nl_recvmsgs_default(mngr->cm_handle);
00351 if (err < 0)
00352 return err;
00353
00354 return 1;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363 void nl_cache_mngr_free(struct nl_cache_mngr *mngr)
00364 {
00365 int i;
00366
00367 if (!mngr)
00368 return;
00369
00370 if (mngr->cm_handle)
00371 nl_close(mngr->cm_handle);
00372
00373 for (i = 0; i < mngr->cm_nassocs; i++)
00374 if (mngr->cm_assocs[i].ca_cache)
00375 nl_cache_free(mngr->cm_assocs[i].ca_cache);
00376
00377 free(mngr->cm_assocs);
00378 free(mngr);
00379
00380 NL_DBG(1, "Cache manager %p freed\n", mngr);
00381 }
00382
00383