2 * lib/fib_lookup/lookup.c FIB Lookup
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
13 * @defgroup fib_lookup FIB Lookup
18 #include <netlink-local.h>
19 #include <netlink/netlink.h>
20 #include <netlink/attr.h>
21 #include <netlink/utils.h>
22 #include <netlink/object.h>
23 #include <netlink/route/rtnl.h>
24 #include <netlink/route/route.h>
25 #include <netlink/fib_lookup/request.h>
26 #include <netlink/fib_lookup/lookup.h>
29 static struct nl_cache_ops fib_lookup_ops;
30 static struct nl_object_ops result_obj_ops;
32 /* not exported so far */
33 struct fib_result_nl {
34 uint32_t fl_addr; /* To be looked up*/
37 unsigned char fl_scope;
38 unsigned char tb_id_in;
40 unsigned char tb_id; /* Results */
41 unsigned char prefixlen;
49 static void result_free_data(struct nl_object *obj)
51 struct flnl_result *res = nl_object_priv(obj);
53 if (res && res->fr_req)
54 nl_object_put(OBJ_CAST(res->fr_req));
57 static int result_clone(struct nl_object *_dst, struct nl_object *_src)
59 struct flnl_result *dst = nl_object_priv(_dst);
60 struct flnl_result *src = nl_object_priv(_src);
63 if (!(dst->fr_req = (struct flnl_request *)
64 nl_object_clone(OBJ_CAST(src->fr_req))))
70 static int result_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
71 struct nlmsghdr *n, struct nl_parser_param *pp)
73 struct flnl_result *res;
74 struct fib_result_nl *fr;
78 res = flnl_result_alloc();
82 res->ce_msgtype = n->nlmsg_type;
84 res->fr_req = flnl_request_alloc();
89 addr = nl_addr_build(AF_INET, &fr->fl_addr, 4);
92 err = flnl_request_set_addr(res->fr_req, addr);
97 flnl_request_set_fwmark(res->fr_req, fr->fl_fwmark);
98 flnl_request_set_tos(res->fr_req, fr->fl_tos);
99 flnl_request_set_scope(res->fr_req, fr->fl_scope);
100 flnl_request_set_table(res->fr_req, fr->tb_id_in);
102 res->fr_table_id = fr->tb_id;
103 res->fr_prefixlen = fr->prefixlen;
104 res->fr_nh_sel = fr->nh_sel;
105 res->fr_type = fr->type;
106 res->fr_scope = fr->scope;
107 res->fr_error = fr->err;
109 err = pp->pp_cb((struct nl_object *) res, pp);
113 /* REAL HACK, fib_lookup doesn't support ACK nor does it
114 * send a DONE message, enforce end of message stream
115 * after just the first message */
119 flnl_result_put(res);
123 static void result_dump_line(struct nl_object *obj, struct nl_dump_params *p)
125 struct flnl_result *res = (struct flnl_result *) obj;
128 nl_dump_line(p, "table %s prefixlen %u next-hop-selector %u\n",
129 rtnl_route_table2str(res->fr_table_id, buf, sizeof(buf)),
130 res->fr_prefixlen, res->fr_nh_sel);
131 nl_dump_line(p, "type %s ",
132 nl_rtntype2str(res->fr_type, buf, sizeof(buf)));
133 nl_dump(p, "scope %s error %s (%d)\n",
134 rtnl_scope2str(res->fr_scope, buf, sizeof(buf)),
135 strerror(-res->fr_error), res->fr_error);
138 static void result_dump_details(struct nl_object *obj, struct nl_dump_params *p)
140 result_dump_line(obj, p);
143 static int result_compare(struct nl_object *_a, struct nl_object *_b,
144 uint32_t attrs, int flags)
150 * @name Allocation/Freeing
154 struct flnl_result *flnl_result_alloc(void)
156 return (struct flnl_result *) nl_object_alloc(&result_obj_ops);
159 void flnl_result_put(struct flnl_result *res)
161 nl_object_put((struct nl_object *) res);
167 * @name Cache Management
172 * Allocate lookup result cache.
174 * Allocates a new lookup result cache and initializes it properly.
176 * @note Free the memory after usage using nl_cache_destroy_and_free().
177 * @return Newly allocated cache or NULL if an error occured.
179 struct nl_cache *flnl_result_alloc_cache(void)
181 return nl_cache_alloc(&fib_lookup_ops);
192 * Builds a netlink request message to do a lookup
193 * @arg req Requested match.
194 * @arg flags additional netlink message flags
196 * Builds a new netlink message requesting a change of link attributes.
197 * The netlink message header isn't fully equipped with all relevant
198 * fields and must be sent out via nl_send_auto_complete() or
199 * supplemented as needed.
200 * \a old must point to a link currently configured in the kernel
201 * and \a tmpl must contain the attributes to be changed set via
202 * \c rtnl_link_set_* functions.
204 * @return New netlink message
205 * @note Not all attributes can be changed, see
206 * \ref link_changeable "Changeable Attributes" for more details.
208 int flnl_lookup_build_request(struct flnl_request *req, int flags,
209 struct nl_msg **result)
212 struct nl_addr *addr;
214 int tos, scope, table;
215 struct fib_result_nl fr = {0};
217 fwmark = flnl_request_get_fwmark(req);
218 tos = flnl_request_get_tos(req);
219 scope = flnl_request_get_scope(req);
220 table = flnl_request_get_table(req);
222 fr.fl_fwmark = fwmark != UINT_LEAST64_MAX ? fwmark : 0;
223 fr.fl_tos = tos >= 0 ? tos : 0;
224 fr.fl_scope = scope >= 0 ? scope : RT_SCOPE_UNIVERSE;
225 fr.tb_id_in = table >= 0 ? table : RT_TABLE_UNSPEC;
227 addr = flnl_request_get_addr(req);
229 return -NLE_MISSING_ATTR;
231 fr.fl_addr = *(uint32_t *) nl_addr_get_binary_addr(addr);
233 msg = nlmsg_alloc_simple(0, flags);
237 if (nlmsg_append(msg, &fr, sizeof(fr), NLMSG_ALIGNTO) < 0)
250 * @arg sk Netlink socket.
251 * @arg req Lookup request object.
252 * @arg cache Cache for result.
254 * Builds a netlink message to request a FIB lookup, waits for the
255 * reply and adds the result to the specified cache.
257 * @return 0 on success or a negative error code.
259 int flnl_lookup(struct nl_sock *sk, struct flnl_request *req,
260 struct nl_cache *cache)
265 if ((err = flnl_lookup_build_request(req, 0, &msg)) < 0)
268 err = nl_send_auto_complete(sk, msg);
273 return nl_cache_pickup(sk, cache);
279 * @name Attribute Access
283 int flnl_result_get_table_id(struct flnl_result *res)
285 return res->fr_table_id;
288 int flnl_result_get_prefixlen(struct flnl_result *res)
290 return res->fr_prefixlen;
293 int flnl_result_get_nexthop_sel(struct flnl_result *res)
295 return res->fr_nh_sel;
298 int flnl_result_get_type(struct flnl_result *res)
303 int flnl_result_get_scope(struct flnl_result *res)
305 return res->fr_scope;
308 int flnl_result_get_error(struct flnl_result *res)
310 return res->fr_error;
315 static struct nl_object_ops result_obj_ops = {
316 .oo_name = "fib_lookup/result",
317 .oo_size = sizeof(struct flnl_result),
318 .oo_free_data = result_free_data,
319 .oo_clone = result_clone,
321 [NL_DUMP_LINE] = result_dump_line,
322 [NL_DUMP_DETAILS] = result_dump_details,
324 .oo_compare = result_compare,
327 static struct nl_cache_ops fib_lookup_ops = {
328 .co_name = "fib_lookup/fib_lookup",
329 .co_hdrsize = sizeof(struct fib_result_nl),
331 { 0, NL_ACT_UNSPEC, "any" },
332 END_OF_MSGTYPES_LIST,
334 .co_protocol = NETLINK_FIB_LOOKUP,
335 .co_msg_parser = result_msg_parser,
336 .co_obj_ops = &result_obj_ops,
339 static void __init fib_lookup_init(void)
341 nl_cache_mngt_register(&fib_lookup_ops);
344 static void __exit fib_lookup_exit(void)
346 nl_cache_mngt_unregister(&fib_lookup_ops);