libnl 1.1
lib/route/neightbl.c
00001 /*
00002  * lib/route/neightbl.c         neighbour tables
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup rtnl
00014  * @defgroup neightbl Neighbour Tables
00015  * @brief
00016  * @{
00017  */
00018 
00019 #include <netlink-local.h>
00020 #include <netlink/netlink.h>
00021 #include <netlink/utils.h>
00022 #include <netlink/route/rtnl.h>
00023 #include <netlink/route/neightbl.h>
00024 #include <netlink/route/link.h>
00025 
00026 /** @cond SKIP */
00027 #define NEIGHTBL_ATTR_FAMILY       0x001
00028 #define NEIGHTBL_ATTR_STATS        0x002
00029 #define NEIGHTBL_ATTR_NAME        0x004
00030 #define NEIGHTBL_ATTR_THRESH1     0x008
00031 #define NEIGHTBL_ATTR_THRESH2     0x010
00032 #define NEIGHTBL_ATTR_THRESH3     0x020
00033 #define NEIGHTBL_ATTR_CONFIG      0x040
00034 #define NEIGHTBL_ATTR_PARMS       0x080
00035 #define NEIGHTBL_ATTR_GC_INTERVAL  0x100
00036 
00037 #define NEIGHTBLPARM_ATTR_IFINDEX       0x0001
00038 #define NEIGHTBLPARM_ATTR_REFCNT                0x0002
00039 #define NEIGHTBLPARM_ATTR_QUEUE_LEN     0x0004
00040 #define NEIGHTBLPARM_ATTR_APP_PROBES    0x0008
00041 #define NEIGHTBLPARM_ATTR_UCAST_PROBES  0x0010
00042 #define NEIGHTBLPARM_ATTR_MCAST_PROBES  0x0020
00043 #define NEIGHTBLPARM_ATTR_PROXY_QLEN    0x0040
00044 #define NEIGHTBLPARM_ATTR_REACHABLE_TIME        0x0080
00045 #define NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME 0x0100
00046 #define NEIGHTBLPARM_ATTR_RETRANS_TIME  0x0200
00047 #define NEIGHTBLPARM_ATTR_GC_STALETIME  0x0400
00048 #define NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME 0x0800
00049 #define NEIGHTBLPARM_ATTR_ANYCAST_DELAY 0x1000
00050 #define NEIGHTBLPARM_ATTR_PROXY_DELAY   0x2000
00051 #define NEIGHTBLPARM_ATTR_LOCKTIME      0x4000
00052 
00053 static struct nl_cache_ops rtnl_neightbl_ops;
00054 static struct nl_object_ops neightbl_obj_ops;
00055 /** @endcond */
00056 
00057 static int neightbl_compare(struct nl_object *_a, struct nl_object *_b,
00058                         uint32_t attrs, int flags)
00059 {
00060         struct rtnl_neightbl *a = (struct rtnl_neightbl *) _a;
00061         struct rtnl_neightbl *b = (struct rtnl_neightbl *) _b;
00062         int diff = 0;
00063 
00064 #define NT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGHTBL_ATTR_##ATTR, a, b, EXPR)
00065 
00066         diff |= NT_DIFF(FAMILY,         a->nt_family != b->nt_family);
00067         diff |= NT_DIFF(NAME,           strcmp(a->nt_name, b->nt_name));
00068         diff |= NT_DIFF(THRESH1,        a->nt_gc_thresh1 != b->nt_gc_thresh1);
00069         diff |= NT_DIFF(THRESH2,        a->nt_gc_thresh2 != b->nt_gc_thresh2);
00070         diff |= NT_DIFF(THRESH3,        a->nt_gc_thresh3 != b->nt_gc_thresh3);
00071         diff |= NT_DIFF(GC_INTERVAL,    a->nt_gc_interval != b->nt_gc_interval);
00072 
00073 #undef NT_DIFF
00074 
00075         if (!(a->ce_mask & NEIGHTBL_ATTR_PARMS) &&
00076             !(b->ce_mask & NEIGHTBL_ATTR_PARMS))
00077                 return diff;
00078 
00079         /* XXX: FIXME: Compare parameter table */
00080 
00081 
00082 #if 0
00083 #define REQ(F) (fp->ntp_mask & NEIGHTBLPARM_ATTR_##F)
00084 #define AVAIL(F) (op->ntp_mask & NEIGHTBLPARM_ATTR_##F)
00085 #define _C(F, N) (REQ(F) && (!AVAIL(F) || (op->N != fp->N)))
00086         if (_C(IFINDEX,                 ntp_ifindex)                    ||
00087             _C(QUEUE_LEN,               ntp_queue_len)                  ||
00088             _C(APP_PROBES,              ntp_app_probes)                 ||
00089             _C(UCAST_PROBES,            ntp_ucast_probes)               ||
00090             _C(MCAST_PROBES,            ntp_mcast_probes)               ||
00091             _C(PROXY_QLEN,              ntp_proxy_qlen)                 ||
00092             _C(LOCKTIME,                ntp_locktime)                   ||
00093             _C(RETRANS_TIME,            ntp_retrans_time)               ||
00094             _C(BASE_REACHABLE_TIME,     ntp_base_reachable_time)        ||
00095             _C(GC_STALETIME,            ntp_gc_stale_time)              ||
00096             _C(DELAY_PROBE_TIME,        ntp_probe_delay)                ||
00097             _C(ANYCAST_DELAY,           ntp_anycast_delay)              ||
00098             _C(PROXY_DELAY,             ntp_proxy_delay))
00099                 return 0;
00100 #undef REQ
00101 #undef AVAIL
00102 #undef _C
00103 #endif
00104 
00105         return diff;
00106 }
00107 
00108 
00109 static struct nla_policy neightbl_policy[NDTA_MAX+1] = {
00110         [NDTA_NAME]             = { .type = NLA_STRING,
00111                                     .maxlen = NTBLNAMSIZ },
00112         [NDTA_THRESH1]          = { .type = NLA_U32 },
00113         [NDTA_THRESH2]          = { .type = NLA_U32 },
00114         [NDTA_THRESH3]          = { .type = NLA_U32 },
00115         [NDTA_GC_INTERVAL]      = { .type = NLA_U32 },
00116         [NDTA_CONFIG]           = { .minlen = sizeof(struct ndt_config) },
00117         [NDTA_STATS]            = { .minlen = sizeof(struct ndt_stats) },
00118         [NDTA_PARMS]            = { .type = NLA_NESTED },
00119 };
00120 
00121 static int neightbl_msg_parser(struct nl_cache_ops *ops,
00122                                struct sockaddr_nl *who, struct nlmsghdr *n,
00123                                struct nl_parser_param *pp)
00124 {
00125         struct rtnl_neightbl *ntbl;
00126         struct nlattr *tb[NDTA_MAX + 1];
00127         struct rtgenmsg *rtmsg;
00128         int err;
00129 
00130         ntbl = rtnl_neightbl_alloc();
00131         if (!ntbl) {
00132                 err = nl_errno(ENOMEM);
00133                 goto errout;
00134         }
00135 
00136         ntbl->ce_msgtype = n->nlmsg_type;
00137         rtmsg = nlmsg_data(n);
00138         
00139         err = nlmsg_parse(n, sizeof(*rtmsg), tb, NDTA_MAX, neightbl_policy);
00140         if (err < 0)
00141                 goto errout;
00142 
00143         ntbl->nt_family = rtmsg->rtgen_family;
00144 
00145         if (tb[NDTA_NAME] == NULL) {
00146                 err = nl_error(EINVAL, "NDTA_NAME is missing");
00147                 goto errout;
00148         }
00149 
00150         nla_strlcpy(ntbl->nt_name, tb[NDTA_NAME], NTBLNAMSIZ);
00151         ntbl->ce_mask |= NEIGHTBL_ATTR_NAME;
00152 
00153         if (tb[NDTA_THRESH1]) {
00154                 ntbl->nt_gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
00155                 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH1;
00156         }
00157 
00158         if (tb[NDTA_THRESH2]) {
00159                 ntbl->nt_gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
00160                 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH2;
00161         }
00162 
00163         if (tb[NDTA_THRESH3]) {
00164                 ntbl->nt_gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
00165                 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH3;
00166         }
00167 
00168         if (tb[NDTA_GC_INTERVAL]) {
00169                 ntbl->nt_gc_interval = nla_get_u32(tb[NDTA_GC_INTERVAL]);
00170                 ntbl->ce_mask |= NEIGHTBL_ATTR_GC_INTERVAL;
00171         }
00172 
00173         if (tb[NDTA_CONFIG]) {
00174                 nla_memcpy(&ntbl->nt_config, tb[NDTA_CONFIG],
00175                            sizeof(ntbl->nt_config));
00176                 ntbl->ce_mask |= NEIGHTBL_ATTR_CONFIG;
00177         }
00178 
00179         if (tb[NDTA_STATS]) {
00180                 nla_memcpy(&ntbl->nt_stats, tb[NDTA_STATS],
00181                            sizeof(ntbl->nt_stats));
00182                 ntbl->ce_mask |= NEIGHTBL_ATTR_STATS;
00183         }
00184 
00185         if (tb[NDTA_PARMS]) {
00186                 struct nlattr *tbp[NDTPA_MAX + 1];
00187                 struct rtnl_neightbl_parms *p = &ntbl->nt_parms;
00188 
00189                 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS], NULL);
00190                 if (err < 0)
00191                         goto errout;
00192 
00193 #define COPY_ENTRY(name, var) \
00194                 if (tbp[NDTPA_ ##name]) { \
00195                         p->ntp_ ##var = nla_get_u32(tbp[NDTPA_ ##name]); \
00196                         p->ntp_mask |= NEIGHTBLPARM_ATTR_ ##name; \
00197                 }
00198 
00199                 COPY_ENTRY(IFINDEX, ifindex);
00200                 COPY_ENTRY(REFCNT, refcnt);
00201                 COPY_ENTRY(QUEUE_LEN, queue_len);
00202                 COPY_ENTRY(APP_PROBES, app_probes);
00203                 COPY_ENTRY(UCAST_PROBES, ucast_probes);
00204                 COPY_ENTRY(MCAST_PROBES, mcast_probes);
00205                 COPY_ENTRY(PROXY_QLEN, proxy_qlen);
00206                 COPY_ENTRY(PROXY_DELAY, proxy_delay);
00207                 COPY_ENTRY(ANYCAST_DELAY, anycast_delay);
00208                 COPY_ENTRY(LOCKTIME, locktime);
00209                 COPY_ENTRY(REACHABLE_TIME, reachable_time);
00210                 COPY_ENTRY(BASE_REACHABLE_TIME, base_reachable_time);
00211                 COPY_ENTRY(RETRANS_TIME, retrans_time);
00212                 COPY_ENTRY(GC_STALETIME, gc_stale_time);
00213                 COPY_ENTRY(DELAY_PROBE_TIME, probe_delay);
00214 #undef COPY_ENTRY
00215 
00216                 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00217         }
00218 
00219         err = pp->pp_cb((struct nl_object *) ntbl, pp);
00220         if (err < 0)
00221                 goto errout;
00222 
00223         err = P_ACCEPT;
00224 errout:
00225         rtnl_neightbl_put(ntbl);
00226         return err;
00227 }
00228 
00229 static int neightbl_request_update(struct nl_cache *c, struct nl_handle *h)
00230 {
00231         return nl_rtgen_request(h, RTM_GETNEIGHTBL, AF_UNSPEC, NLM_F_DUMP);
00232 }
00233 
00234 
00235 static int neightbl_dump_brief(struct nl_object *arg, struct nl_dump_params *p)
00236 {
00237         int line = 1;
00238         struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg;
00239 
00240         dp_dump(p, "%s", ntbl->nt_name);
00241 
00242         if (ntbl->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) {
00243                 struct nl_cache *link_cache;
00244                 
00245                 link_cache = nl_cache_mngt_require("route/link");
00246 
00247                 if (link_cache) {
00248                         char buf[32];
00249                         dp_dump(p, "<%s> ",
00250                                 rtnl_link_i2name(link_cache,
00251                                                  ntbl->nt_parms.ntp_ifindex,
00252                                                  buf, sizeof(buf)));
00253                 } else
00254                         dp_dump(p, "<%u> ", ntbl->nt_parms.ntp_ifindex);
00255         } else
00256                 dp_dump(p, " ");
00257 
00258         if (ntbl->ce_mask & NEIGHTBL_ATTR_CONFIG)
00259                 dp_dump(p, "entries %u ", ntbl->nt_config.ndtc_entries);
00260 
00261         if (ntbl->ce_mask & NEIGHTBL_ATTR_PARMS) {
00262                 char rt[32], rt2[32];
00263                 struct rtnl_neightbl_parms *pa = &ntbl->nt_parms;
00264 
00265                 dp_dump(p, "reachable-time %s retransmit-time %s",
00266                         nl_msec2str(pa->ntp_reachable_time, rt, sizeof(rt)),
00267                         nl_msec2str(pa->ntp_retrans_time, rt2, sizeof(rt2)));
00268         }
00269 
00270         dp_dump(p, "\n");
00271 
00272         return line;
00273 }
00274 
00275 static int neightbl_dump_full(struct nl_object *arg, struct nl_dump_params *p)
00276 {
00277         char x[32], y[32], z[32];
00278         struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg;
00279 
00280         int line = neightbl_dump_brief(arg, p);
00281 
00282         if (ntbl->ce_mask & NEIGHTBL_ATTR_CONFIG) {
00283                 dp_new_line(p, line++);
00284                 dp_dump(p, "    key-len %u entry-size %u last-flush %s\n",
00285                         ntbl->nt_config.ndtc_key_len,
00286                         ntbl->nt_config.ndtc_entry_size,
00287                         nl_msec2str(ntbl->nt_config.ndtc_last_flush,
00288                                       x, sizeof(x)));
00289 
00290                 dp_new_line(p, line++);
00291                 dp_dump(p, "    gc threshold %u/%u/%u interval %s " \
00292                             "chain-position %u\n",
00293                         ntbl->nt_gc_thresh1, ntbl->nt_gc_thresh2,
00294                         ntbl->nt_gc_thresh3,
00295                         nl_msec2str(ntbl->nt_gc_interval, x, sizeof(x)),
00296                         ntbl->nt_config.ndtc_hash_chain_gc);
00297 
00298                 dp_new_line(p, line++);
00299                 dp_dump(p, "    hash-rand 0x%08X/0x%08X last-rand %s\n",
00300                         ntbl->nt_config.ndtc_hash_rnd,
00301                         ntbl->nt_config.ndtc_hash_mask,
00302                         nl_msec2str(ntbl->nt_config.ndtc_last_rand,
00303                                       x, sizeof(x)));
00304         }
00305 
00306         if (ntbl->ce_mask & NEIGHTBL_ATTR_PARMS) {
00307                 struct rtnl_neightbl_parms *pa = &ntbl->nt_parms;
00308 
00309                 dp_new_line(p, line++);
00310                 dp_dump(p, "    refcnt %u pending-queue-limit %u " \
00311                             "proxy-delayed-queue-limit %u\n",
00312                         pa->ntp_refcnt,
00313                         pa->ntp_queue_len,
00314                         pa->ntp_proxy_qlen);
00315 
00316                 dp_new_line(p, line++);
00317                 dp_dump(p, "    num-userspace-probes %u num-unicast-probes " \
00318                             "%u num-multicast-probes %u\n",
00319                         pa->ntp_app_probes,
00320                         pa->ntp_ucast_probes,
00321                         pa->ntp_mcast_probes);
00322 
00323                 dp_new_line(p, line++);
00324                 dp_dump(p, "    min-age %s base-reachable-time %s " \
00325                             "stale-check-interval %s\n",
00326                         nl_msec2str(pa->ntp_locktime, x, sizeof(x)),
00327                         nl_msec2str(pa->ntp_base_reachable_time,
00328                                       y, sizeof(y)),
00329                         nl_msec2str(pa->ntp_gc_stale_time, z, sizeof(z)));
00330 
00331                 dp_new_line(p, line++);
00332                 dp_dump(p, "    initial-probe-delay %s answer-delay %s " \
00333                             "proxy-answer-delay %s\n",
00334                         nl_msec2str(pa->ntp_probe_delay, x, sizeof(x)),
00335                         nl_msec2str(pa->ntp_anycast_delay, y, sizeof(y)),
00336                         nl_msec2str(pa->ntp_proxy_delay, z, sizeof(z)));
00337         }
00338 
00339         return line;
00340 }
00341 
00342 static int neightbl_dump_stats(struct nl_object *arg, struct nl_dump_params *p)
00343 {
00344         struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg;
00345         int line = neightbl_dump_full(arg, p);
00346 
00347         if (!(ntbl->ce_mask & NEIGHTBL_ATTR_STATS))
00348                 return line;
00349 
00350         dp_new_line(p, line++);
00351         dp_dump(p, "    lookups %lld hits %lld failed %lld " \
00352                     "allocations %lld destroys %lld\n",
00353                 ntbl->nt_stats.ndts_lookups,
00354                 ntbl->nt_stats.ndts_hits,
00355                 ntbl->nt_stats.ndts_res_failed,
00356                 ntbl->nt_stats.ndts_allocs,
00357                 ntbl->nt_stats.ndts_destroys);
00358 
00359         dp_new_line(p, line++);
00360         dp_dump(p, "    hash-grows %lld forced-gc-runs %lld " \
00361                     "periodic-gc-runs %lld\n",
00362                 ntbl->nt_stats.ndts_hash_grows,
00363                 ntbl->nt_stats.ndts_forced_gc_runs,
00364                 ntbl->nt_stats.ndts_periodic_gc_runs);
00365 
00366         dp_dump(p, "    rcv-unicast-probes %lld rcv-multicast-probes %lld\n",
00367                 ntbl->nt_stats.ndts_rcv_probes_ucast,
00368                 ntbl->nt_stats.ndts_rcv_probes_mcast);
00369 
00370         return line;
00371 }
00372 
00373 /**
00374  * @name Allocation/Freeing
00375  * @{
00376  */
00377 
00378 struct rtnl_neightbl *rtnl_neightbl_alloc(void)
00379 {
00380         return (struct rtnl_neightbl *) nl_object_alloc(&neightbl_obj_ops);
00381 }
00382 
00383 void rtnl_neightbl_put(struct rtnl_neightbl *neightbl)
00384 {
00385         nl_object_put((struct nl_object *) neightbl);
00386 }
00387 
00388 /** @} */
00389 
00390 /**
00391  * @name Neighbour Table Cache Management
00392  * @{
00393  */
00394 
00395 /**
00396  * Build a neighbour table cache including all neighbour tables currently configured in the kernel.
00397  * @arg handle          netlink handle
00398  *
00399  * Allocates a new neighbour table cache, initializes it properly and
00400  * updates it to include all neighbour tables currently configured in
00401  * the kernel.
00402  *
00403  * @note The caller is responsible for destroying and freeing the
00404  *       cache after using it.
00405  * @return The new cache or NULL if an error occured.
00406  */
00407 struct nl_cache * rtnl_neightbl_alloc_cache(struct nl_handle *handle)
00408 {
00409         struct nl_cache * cache;
00410         
00411         cache = nl_cache_alloc(&rtnl_neightbl_ops);
00412         if (cache == NULL)
00413                 return NULL;
00414         
00415         if (handle && nl_cache_refill(handle, cache) < 0) {
00416                 nl_cache_free(cache);
00417                 return NULL;
00418         }
00419 
00420         return cache;
00421 }
00422 
00423 /**
00424  * Lookup neighbour table by name and optional interface index
00425  * @arg cache           neighbour table cache
00426  * @arg name            name of table
00427  * @arg ifindex         optional interface index
00428  *
00429  * Looks up the neighbour table matching the specified name and
00430  * optionally the specified ifindex to retrieve device specific
00431  * parameter sets.
00432  *
00433  * @return ptr to neighbour table inside the cache or NULL if no
00434  *         match was found.
00435  */
00436 struct rtnl_neightbl *rtnl_neightbl_get(struct nl_cache *cache,
00437                                         const char *name, int ifindex)
00438 {
00439         struct rtnl_neightbl *nt;
00440 
00441         if (cache->c_ops != &rtnl_neightbl_ops)
00442                 return NULL;
00443 
00444         nl_list_for_each_entry(nt, &cache->c_items, ce_list) {
00445                 if (!strcasecmp(nt->nt_name, name) &&
00446                     ((!ifindex && !nt->nt_parms.ntp_ifindex) ||
00447                      (ifindex && ifindex == nt->nt_parms.ntp_ifindex))) {
00448                         nl_object_get((struct nl_object *) nt);
00449                         return nt;
00450                 }
00451         }
00452 
00453         return NULL;
00454 }
00455 
00456 /** @} */
00457 
00458 /**
00459  * @name Neighbour Table Modifications
00460  * @{
00461  */
00462 
00463 /**
00464  * Builds a netlink change request message to change neighbour table attributes
00465  * @arg old             neighbour table to change
00466  * @arg tmpl            template with requested changes
00467  *
00468  * Builds a new netlink message requesting a change of neighbour table
00469  * attributes. The netlink message header isn't fully equipped with all
00470  * relevant fields and must be sent out via nl_send_auto_complete() or
00471  * supplemented as needed.
00472  * \a old must point to a neighbour table currently configured in the
00473  * kernel and \a tmpl must contain the attributes to be changed set via
00474  * \c rtnl_neightbl_set_* functions.
00475  *
00476  * @return New netlink message
00477  */
00478 struct nl_msg * rtnl_neightbl_build_change_request(struct rtnl_neightbl *old,
00479                                                    struct rtnl_neightbl *tmpl)
00480 {
00481         struct nl_msg *m;
00482         struct ndtmsg ndt = {
00483                 .ndtm_family = old->nt_family,
00484         };
00485 
00486         m = nlmsg_alloc_simple(RTM_SETNEIGHTBL, 0);
00487         nlmsg_append(m, &ndt, sizeof(ndt), NLMSG_ALIGNTO);
00488 
00489         nla_put_string(m, NDTA_NAME, old->nt_name);
00490 
00491         if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH1)
00492                 nla_put_u32(m, NDTA_THRESH1, tmpl->nt_gc_thresh1);
00493 
00494         if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH2)
00495                 nla_put_u32(m, NDTA_THRESH2, tmpl->nt_gc_thresh2);
00496 
00497         if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH2)
00498                 nla_put_u32(m, NDTA_THRESH2, tmpl->nt_gc_thresh2);
00499 
00500         if (tmpl->ce_mask & NEIGHTBL_ATTR_GC_INTERVAL)
00501                 nla_put_u64(m, NDTA_GC_INTERVAL,
00502                                       tmpl->nt_gc_interval);
00503 
00504         if (tmpl->ce_mask & NEIGHTBL_ATTR_PARMS) {
00505                 struct rtnl_neightbl_parms *p = &tmpl->nt_parms;
00506                 struct nl_msg *parms = nlmsg_alloc();
00507 
00508                 if (old->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX)
00509                         nla_put_u32(parms, NDTPA_IFINDEX,
00510                                               old->nt_parms.ntp_ifindex);
00511 
00512 
00513                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_QUEUE_LEN)
00514                         nla_put_u32(parms, NDTPA_QUEUE_LEN, p->ntp_queue_len);
00515 
00516                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_APP_PROBES)
00517                         nla_put_u32(parms, NDTPA_APP_PROBES, p->ntp_app_probes);
00518 
00519                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_UCAST_PROBES)
00520                         nla_put_u32(parms, NDTPA_UCAST_PROBES,
00521                                     p->ntp_ucast_probes);
00522 
00523                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_MCAST_PROBES)
00524                         nla_put_u32(parms, NDTPA_MCAST_PROBES,
00525                                     p->ntp_mcast_probes);
00526 
00527                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_QLEN)
00528                         nla_put_u32(parms, NDTPA_PROXY_QLEN,
00529                                     p->ntp_proxy_qlen);
00530 
00531                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME)
00532                         nla_put_u64(parms, NDTPA_BASE_REACHABLE_TIME,
00533                                     p->ntp_base_reachable_time);
00534 
00535                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_RETRANS_TIME)
00536                         nla_put_u64(parms, NDTPA_RETRANS_TIME,
00537                                     p->ntp_retrans_time);
00538 
00539                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_GC_STALETIME)
00540                         nla_put_u64(parms, NDTPA_GC_STALETIME,
00541                                     p->ntp_gc_stale_time);
00542 
00543                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME)
00544                         nla_put_u64(parms, NDTPA_DELAY_PROBE_TIME,
00545                                     p->ntp_proxy_delay);
00546 
00547                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_ANYCAST_DELAY)
00548                         nla_put_u64(parms, NDTPA_ANYCAST_DELAY,
00549                                     p->ntp_anycast_delay);
00550 
00551                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_DELAY)
00552                         nla_put_u64(parms, NDTPA_PROXY_DELAY,
00553                                               p->ntp_proxy_delay);
00554 
00555                 if (p->ntp_mask & NEIGHTBLPARM_ATTR_LOCKTIME)
00556                         nla_put_u64(parms, NDTPA_LOCKTIME, p->ntp_locktime);
00557 
00558                 nla_put_nested(m, NDTA_PARMS, parms);
00559                 nlmsg_free(parms);
00560         }
00561         
00562         return m;
00563 }
00564 
00565 /**
00566  * Change neighbour table attributes
00567  * @arg handle          netlink handle
00568  * @arg old             neighbour table to be changed
00569  * @arg tmpl            template with requested changes
00570  *
00571  * Builds a new netlink message by calling
00572  * rtnl_neightbl_build_change_request(), sends the request to the
00573  * kernel and waits for the next ACK to be received, i.e. blocks
00574  * until the request has been processed.
00575  *
00576  * @return 0 on success or a negative error code
00577  */
00578 int rtnl_neightbl_change(struct nl_handle *handle, struct rtnl_neightbl *old,
00579                          struct rtnl_neightbl *tmpl)
00580 {
00581         int err;
00582         struct nl_msg *msg;
00583         
00584         msg = rtnl_neightbl_build_change_request(old, tmpl);
00585         err = nl_send_auto_complete(handle, msg);
00586         if (err < 0)
00587                 return err;
00588 
00589         nlmsg_free(msg);
00590         return nl_wait_for_ack(handle);
00591 }
00592 
00593 /** @} */
00594 
00595 /**
00596  * @name Attribute Modification
00597  * @{
00598  */
00599 
00600 void rtnl_neightbl_set_family(struct rtnl_neightbl *ntbl, int family)
00601 {
00602         ntbl->nt_family = family;
00603         ntbl->ce_mask |= NEIGHTBL_ATTR_FAMILY;
00604 }
00605 
00606 void rtnl_neightbl_set_gc_interval(struct rtnl_neightbl *ntbl, uint64_t ms)
00607 {
00608         ntbl->nt_gc_interval = ms;
00609         ntbl->ce_mask |= NEIGHTBL_ATTR_GC_INTERVAL;
00610 }
00611 
00612 void rtnl_neightbl_set_gc_tresh1(struct rtnl_neightbl *ntbl, int thresh)
00613 {
00614         ntbl->nt_gc_thresh1 = thresh;
00615         ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH1;
00616 }
00617 
00618 void rtnl_neightbl_set_gc_tresh2(struct rtnl_neightbl *ntbl, int thresh)
00619 {
00620         ntbl->nt_gc_thresh2 = thresh;
00621         ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH2;
00622 }
00623 
00624 void rtnl_neightbl_set_gc_tresh3(struct rtnl_neightbl *ntbl, int thresh)
00625 {
00626         ntbl->nt_gc_thresh3 = thresh;
00627         ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH3;
00628 }
00629 
00630 void rtnl_neightbl_set_name(struct rtnl_neightbl *ntbl, const char *name)
00631 {
00632         strncpy(ntbl->nt_name, name, sizeof(ntbl->nt_name) - 1);
00633         ntbl->ce_mask |= NEIGHTBL_ATTR_NAME;
00634 }
00635 
00636 void rtnl_neightbl_set_dev(struct rtnl_neightbl *ntbl, int ifindex)
00637 {
00638         ntbl->nt_parms.ntp_ifindex = ifindex;
00639         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_IFINDEX;
00640         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00641 }
00642 
00643 /**
00644  * Set the queue length for pending requests of a neighbour table to the specified value
00645  * @arg ntbl            neighbour table to change
00646  * @arg len             new queue len
00647  */
00648 void rtnl_neightbl_set_queue_len(struct rtnl_neightbl *ntbl, int len)
00649 {
00650         ntbl->nt_parms.ntp_queue_len = len;
00651         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_QUEUE_LEN;
00652         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00653 }
00654 
00655 /**
00656  * Set the queue length for delay proxy arp requests of a neighbour table to the specified value
00657  * @arg ntbl            neighbour table to change
00658  * @arg len             new queue len
00659  */
00660 void rtnl_neightbl_set_proxy_queue_len(struct rtnl_neightbl *ntbl, int len)
00661 {
00662         ntbl->nt_parms.ntp_proxy_qlen = len;
00663         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_PROXY_QLEN;
00664         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00665 }
00666 
00667 /**
00668  * Set the number of application probes of a neighbour table to the specified value
00669  * @arg ntbl            neighbour table to change
00670  * @arg probes          new probes value
00671  */
00672 void rtnl_neightbl_set_app_probes(struct rtnl_neightbl *ntbl, int probes)
00673 {
00674         ntbl->nt_parms.ntp_app_probes = probes;
00675         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_APP_PROBES;
00676         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00677 }
00678 
00679 /**
00680  * Set the number of unicast probes of a neighbour table to the specified value
00681  * @arg ntbl            neighbour table to change
00682  * @arg probes          new probes value
00683  */
00684 void rtnl_neightbl_set_ucast_probes(struct rtnl_neightbl *ntbl, int probes)
00685 {
00686         ntbl->nt_parms.ntp_ucast_probes = probes;
00687         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_UCAST_PROBES;
00688         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00689 }
00690 
00691 /**
00692  * Set the number of multicast probes of a neighbour table to the specified value
00693  * @arg ntbl            neighbour table to change
00694  * @arg probes          new probes value
00695  */
00696 void rtnl_neightbl_set_mcast_probes(struct rtnl_neightbl *ntbl, int probes)
00697 {
00698         ntbl->nt_parms.ntp_mcast_probes = probes;
00699         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_MCAST_PROBES;
00700         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00701 }
00702 
00703 /**
00704  * Set the base reachable time of a neighbour table to the specified value
00705  * @arg ntbl            neighbour table to change
00706  * @arg ms              new base reachable time in milliseconds
00707  */
00708 void rtnl_neightbl_set_base_reachable_time(struct rtnl_neightbl *ntbl,
00709                                            uint64_t ms)
00710 {
00711         ntbl->nt_parms.ntp_base_reachable_time = ms;
00712         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME;
00713         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00714 }
00715 
00716 /**
00717  * Set the retransmit time of a neighbour table to the specified value
00718  * @arg ntbl            neighbour table to change
00719  * @arg ms              new retransmit time
00720  */
00721 void rtnl_neightbl_set_retrans_time(struct rtnl_neightbl *ntbl, uint64_t ms)
00722 {
00723         ntbl->nt_parms.ntp_retrans_time = ms;
00724         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_RETRANS_TIME;
00725         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00726 }
00727 
00728 /**
00729  * Set the gc stale time of a neighbour table to the specified value
00730  * @arg ntbl            neighbour table to change
00731  * @arg ms              new gc stale time in milliseconds
00732  */
00733 void rtnl_neightbl_set_gc_stale_time(struct rtnl_neightbl *ntbl, uint64_t ms)
00734 {
00735         ntbl->nt_parms.ntp_gc_stale_time = ms;
00736         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_GC_STALETIME;
00737         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00738 }
00739 
00740 /**
00741  * Set the first probe delay time of a neighbour table to the specified value
00742  * @arg ntbl            neighbour table to change
00743  * @arg ms              new first probe delay time in milliseconds
00744  */
00745 void rtnl_neightbl_set_delay_probe_time(struct rtnl_neightbl *ntbl, uint64_t ms)
00746 {
00747         ntbl->nt_parms.ntp_probe_delay = ms;
00748         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME;
00749         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00750 }
00751 
00752 /**
00753  * Set the anycast delay of a neighbour table to the specified value
00754  * @arg ntbl            neighbour table to change
00755  * @arg ms              new anycast delay in milliseconds
00756  */
00757 void rtnl_neightbl_set_anycast_delay(struct rtnl_neightbl *ntbl, uint64_t ms)
00758 {
00759         ntbl->nt_parms.ntp_anycast_delay = ms;
00760         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_ANYCAST_DELAY;
00761         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00762 }
00763 
00764 /**
00765  * Set the proxy delay of a neighbour table to the specified value
00766  * @arg ntbl            neighbour table to change
00767  * @arg ms              new proxy delay in milliseconds
00768  */
00769 void rtnl_neightbl_set_proxy_delay(struct rtnl_neightbl *ntbl, uint64_t ms)
00770 {
00771         ntbl->nt_parms.ntp_proxy_delay = ms;
00772         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_PROXY_DELAY;
00773         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00774 }
00775 
00776 /**
00777  * Set the locktime of a neighbour table to the specified value
00778  * @arg ntbl            neighbour table to change
00779  * @arg ms              new locktime in milliseconds
00780  */
00781 void rtnl_neightbl_set_locktime(struct rtnl_neightbl *ntbl, uint64_t ms)
00782 {
00783         ntbl->nt_parms.ntp_locktime = ms;
00784         ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_LOCKTIME;
00785         ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS;
00786 }
00787 
00788 /** @} */
00789 
00790 static struct nl_object_ops neightbl_obj_ops = {
00791         .oo_name                = "route/neightbl",
00792         .oo_size                = sizeof(struct rtnl_neightbl),
00793         .oo_dump[NL_DUMP_BRIEF] = neightbl_dump_brief,
00794         .oo_dump[NL_DUMP_FULL]  = neightbl_dump_full,
00795         .oo_dump[NL_DUMP_STATS] = neightbl_dump_stats,
00796         .oo_compare             = neightbl_compare,
00797 };
00798 
00799 static struct nl_cache_ops rtnl_neightbl_ops = {
00800         .co_name                = "route/neightbl",
00801         .co_hdrsize             = sizeof(struct rtgenmsg),
00802         .co_msgtypes            = {
00803                                         { RTM_NEWNEIGHTBL, NL_ACT_NEW, "new" },
00804                                         { RTM_SETNEIGHTBL, NL_ACT_SET, "set" },
00805                                         { RTM_GETNEIGHTBL, NL_ACT_GET, "get" },
00806                                         END_OF_MSGTYPES_LIST,
00807                                   },
00808         .co_protocol            = NETLINK_ROUTE,
00809         .co_request_update      = neightbl_request_update,
00810         .co_msg_parser          = neightbl_msg_parser,
00811         .co_obj_ops             = &neightbl_obj_ops,
00812 };
00813 
00814 static void __init neightbl_init(void)
00815 {
00816         nl_cache_mngt_register(&rtnl_neightbl_ops);
00817 }
00818 
00819 static void __exit neightbl_exit(void)
00820 {
00821         nl_cache_mngt_unregister(&rtnl_neightbl_ops);
00822 }
00823 
00824 /** @} */