/build/buildd/libnl-1.0~pre6/lib/fib_lookup/lookup.c

00001 /*
00002  * lib/fib_lookup/lookup.c      FIB Lookup
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  * @defgroup fib_lookup FIB Lookup
00014  * @brief
00015  * @{
00016  */
00017 
00018 #include <netlink-local.h>
00019 #include <netlink/netlink.h>
00020 #include <netlink/attr.h>
00021 #include <netlink/utils.h>
00022 #include <netlink/object.h>
00023 #include <netlink/route/rtnl.h>
00024 #include <netlink/route/route.h>
00025 #include <netlink/fib_lookup/request.h>
00026 #include <netlink/fib_lookup/lookup.h>
00027 
00028 /** @cond SKIP */
00029 static struct nl_cache_ops fib_lookup_ops;
00030 
00031 /* not exported so far */
00032 struct fib_result_nl {
00033         uint32_t        fl_addr;   /* To be looked up*/ 
00034         uint32_t        fl_fwmark; 
00035         unsigned char   fl_tos;
00036         unsigned char   fl_scope;
00037         unsigned char   tb_id_in;
00038 
00039         unsigned char   tb_id;      /* Results */
00040         unsigned char   prefixlen;
00041         unsigned char   nh_sel;
00042         unsigned char   type;
00043         unsigned char   scope;
00044         int             err;      
00045 };
00046 /** @endcond */
00047 
00048 static void result_free_data(struct nl_object *obj)
00049 {
00050         struct flnl_result *res = nl_object_priv(obj);
00051 
00052         if (res && res->fr_req)
00053                 flnl_request_put(res->fr_req);
00054 }
00055 
00056 static int result_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *n,
00057                              void *arg)
00058 {
00059         struct flnl_result *res;
00060         struct fib_result_nl *fr;
00061         struct nl_parser_param *pp = arg;
00062         struct nl_addr *addr;
00063         int err = -EINVAL;
00064 
00065         res = flnl_result_alloc();
00066         if (!res)
00067                 goto errout;
00068 
00069         res->ce_msgtype = n->nlmsg_type;
00070 
00071         res->fr_req = flnl_request_alloc();
00072         if (!res->fr_req)
00073                 goto errout;
00074 
00075         fr = nlmsg_data(n);
00076         addr = nl_addr_build(AF_INET, &fr->fl_addr, 4);
00077         if (!addr)
00078                 goto errout;
00079         err = flnl_request_set_addr(res->fr_req, addr);
00080         nl_addr_put(addr);
00081         if (err < 0)
00082                 goto errout;
00083 
00084         flnl_request_set_fwmark(res->fr_req, fr->fl_fwmark);
00085         flnl_request_set_tos(res->fr_req, fr->fl_tos);
00086         flnl_request_set_scope(res->fr_req, fr->fl_scope);
00087         flnl_request_set_table(res->fr_req, fr->tb_id_in);
00088 
00089         res->fr_table_id = fr->tb_id;
00090         res->fr_prefixlen = fr->prefixlen;
00091         res->fr_nh_sel = fr->nh_sel;
00092         res->fr_type = fr->type;
00093         res->fr_scope = fr->scope;
00094         res->fr_error = fr->err;
00095 
00096         err = pp->pp_cb((struct nl_object *) res, pp);
00097         if (err < 0)
00098                 goto errout;
00099 
00100         /* REAL HACK, fib_lookup doesn't support ACK nor does it
00101          * send a DONE message, enforce end of message stream
00102          * after just the first message */
00103         return NL_EXIT;
00104 
00105 errout:
00106         flnl_result_put(res);
00107         return err;
00108 }
00109 
00110 static int result_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
00111 {
00112         struct flnl_result *res = (struct flnl_result *) obj;
00113         char buf[128];
00114         int line = 1;
00115 
00116         dp_dump(p, "table %s prefixlen %u next-hop-selector %u\n",
00117                 rtnl_route_table2str(res->fr_table_id, buf, sizeof(buf)),
00118                 res->fr_prefixlen, res->fr_nh_sel);
00119         dp_dump_line(p, line++, "type %s ",
00120                      nl_rtntype2str(res->fr_type, buf, sizeof(buf)));
00121         dp_dump(p, "scope %s error %s (%d)\n",
00122                 rtnl_scope2str(res->fr_scope, buf, sizeof(buf)),
00123                 strerror(-res->fr_error), res->fr_error);
00124 
00125         return line;
00126 }
00127 
00128 static int result_dump_full(struct nl_object *obj, struct nl_dump_params *p)
00129 {
00130         return result_dump_brief(obj, p);
00131 }
00132 
00133 static int result_filter(struct nl_object *obj, struct nl_object *filter)
00134 {
00135         struct flnl_result *o = (struct flnl_result *) obj;
00136         struct flnl_result *f = (struct flnl_result *) filter;
00137 
00138         if (o->fr_req && f->fr_req)
00139                 return flnl_request_cmp(o->fr_req, f->fr_req);
00140 
00141         return 1;
00142 }
00143 
00144 /**
00145  * @name FIB Result Allocation/Freeage
00146  * @{
00147  */
00148 
00149 /**
00150  * Allocate and initialize new lookup result object.
00151  * @note Free the memory after usage using flnl_result_put() or
00152  *       flnl_result_free().
00153  * @return Newly allocated lookup result object or NULL if an error occured.
00154  */
00155 struct flnl_result *flnl_result_alloc(void)
00156 {
00157         return (struct flnl_result *) nl_object_alloc_from_ops(&fib_lookup_ops);
00158 }
00159 
00160 /**
00161  * Allocate lookup result cache.
00162  *
00163  * Allocates a new lookup result cache and initializes it properly.
00164  *
00165  * @note Free the memory after usage using nl_cache_destroy_and_free().
00166  * @return Newly allocated cache or NULL if an error occured.
00167  */
00168 struct nl_cache *flnl_result_alloc_cache(void)
00169 {
00170         return nl_cache_alloc_from_ops(&fib_lookup_ops);
00171 }
00172 
00173 /**
00174  * Give back reference on lookup result object.
00175  * @arg res             lookup result object to be given back.
00176  *
00177  * Decrements the reference counter and frees the object if the
00178  * last reference has been released.
00179  */
00180 void flnl_result_put(struct flnl_result *res)
00181 {
00182         nl_object_put((struct nl_object *) res);
00183 }
00184 
00185 /**
00186  * Free lookup result object.
00187  * @arg res             lookup result object to be freed.
00188  *
00189  * @note Always use flnl_result_put() unless you're absolutely sure
00190  *       that no other user may have a reference on this object.
00191  */
00192 void flnl_result_free(struct flnl_result *res)
00193 {
00194         nl_object_free((struct nl_object *) res);
00195 }
00196 
00197 /** @} */
00198 
00199 /**
00200  * @name Lookup
00201  * @{
00202  */
00203 
00204 /**
00205  * Builds a netlink request message to do a lookup
00206  * @arg req             Requested match.
00207  * @arg flags           additional netlink message flags
00208  *
00209  * Builds a new netlink message requesting a change of link attributes.
00210  * The netlink message header isn't fully equipped with all relevant
00211  * fields and must be sent out via nl_send_auto_complete() or
00212  * supplemented as needed.
00213  * \a old must point to a link currently configured in the kernel
00214  * and \a tmpl must contain the attributes to be changed set via
00215  * \c rtnl_link_set_* functions.
00216  *
00217  * @return New netlink message
00218  * @note Not all attributes can be changed, see
00219  *       \ref link_changeable "Changeable Attributes" for more details.
00220  */
00221 struct nl_msg *flnl_lookup_build_request(struct flnl_request *req, int flags)
00222 {
00223         struct nl_msg *msg;
00224         struct nl_addr *addr;
00225         uint64_t fwmark;
00226         int tos, scope, table;
00227         struct fib_result_nl fr = {0};
00228 
00229         fwmark = flnl_request_get_fwmark(req);
00230         tos = flnl_request_get_tos(req);
00231         scope = flnl_request_get_scope(req);
00232         table = flnl_request_get_table(req);
00233 
00234         fr.fl_fwmark = fwmark != UINT_LEAST64_MAX ? fwmark : 0;
00235         fr.fl_tos = tos >= 0 ? tos : 0;
00236         fr.fl_scope = scope >= 0 ? scope : RT_SCOPE_UNIVERSE;
00237         fr.tb_id_in = table >= 0 ? table : RT_TABLE_UNSPEC;
00238 
00239         addr = flnl_request_get_addr(req);
00240         if (!addr) {
00241                 nl_error(EINVAL, "Request must specify the address");
00242                 return NULL;
00243         }
00244 
00245         fr.fl_addr = *(uint32_t *) nl_addr_get_binary_addr(addr);
00246 
00247         msg = nlmsg_build_simple(0, flags);
00248         if (!msg)
00249                 goto errout;
00250 
00251         if (nlmsg_append(msg, &fr, sizeof(fr), 1) < 0)
00252                 goto errout;
00253 
00254         return msg;
00255 
00256 errout:
00257         nlmsg_free(msg);
00258         return NULL;
00259 }
00260 
00261 /**
00262  * Perform FIB Lookup
00263  * @arg handle          Netlink handle.
00264  * @arg req             Lookup request object.
00265  * @arg cache           Cache for result.
00266  *
00267  * Builds a netlink message to request a FIB lookup, waits for the
00268  * reply and adds the result to the specified cache.
00269  *
00270  * @return 0 on success or a negative error code.
00271  */
00272 int flnl_lookup(struct nl_handle *handle, struct flnl_request *req,
00273                 struct nl_cache *cache)
00274 {
00275         struct nl_msg *msg;
00276         int err;
00277 
00278         msg = flnl_lookup_build_request(req, 0);
00279         if (!msg)
00280                 return nl_errno(ENOMEM);
00281 
00282         err = nl_send_auto_complete(handle, msg);
00283         nlmsg_free(msg);
00284         if (err < 0)
00285                 return err;
00286 
00287         return nl_cache_pickup(handle, cache);
00288 }
00289 
00290 /** @} */
00291 
00292 /**
00293  * @name Attribute Access
00294  * @{
00295  */
00296 
00297 int flnl_result_get_table_id(struct flnl_result *res)
00298 {
00299         return res->fr_table_id;
00300 }
00301 
00302 int flnl_result_get_prefixlen(struct flnl_result *res)
00303 {
00304         return res->fr_prefixlen;
00305 }
00306 
00307 int flnl_result_get_nexthop_sel(struct flnl_result *res)
00308 {
00309         return res->fr_nh_sel;
00310 }
00311 
00312 int flnl_result_get_type(struct flnl_result *res)
00313 {
00314         return res->fr_type;
00315 }
00316 
00317 int flnl_result_get_scope(struct flnl_result *res)
00318 {
00319         return res->fr_scope;
00320 }
00321 
00322 int flnl_result_get_error(struct flnl_result *res)
00323 {
00324         return res->fr_error;
00325 }
00326 
00327 /** @} */
00328 
00329 static struct nl_cache_ops fib_lookup_ops = {
00330         .co_name                = "fib_lookup/fib_lookup",
00331         .co_size                = sizeof(struct flnl_result),
00332         .co_hdrsize             = sizeof(struct fib_result_nl),
00333         .co_msgtypes            = {
00334                                         { 0, "any" },
00335                                         { -1, NULL },
00336                                   },
00337         .co_protocol            = NETLINK_FIB_LOOKUP,
00338         .co_msg_parser          = result_msg_parser,
00339         .co_free_data           = result_free_data,
00340         .co_dump[NL_DUMP_BRIEF] = result_dump_brief,
00341         .co_dump[NL_DUMP_FULL]  = result_dump_full,
00342         .co_filter              = result_filter,
00343 };
00344 
00345 static void __init fib_lookup_init(void)
00346 {
00347         nl_cache_mngt_register(&fib_lookup_ops);
00348 }
00349 
00350 static void __exit fib_lookup_exit(void)
00351 {
00352         nl_cache_mngt_unregister(&fib_lookup_ops);
00353 }
00354 
00355 /** @} */

Generated on Fri Apr 27 14:14:07 2007 for libnl by  doxygen 1.5.1