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-2006 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;
31 /* not exported so far */
32 struct fib_result_nl {
33 uint32_t fl_addr; /* To be looked up*/
36 unsigned char fl_scope;
37 unsigned char tb_id_in;
39 unsigned char tb_id; /* Results */
40 unsigned char prefixlen;
48 static void result_free_data(struct nl_object *obj)
50 struct flnl_result *res = nl_object_priv(obj);
52 if (res && res->fr_req)
53 flnl_request_put(res->fr_req);
56 static int result_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *n,
59 struct flnl_result *res;
60 struct fib_result_nl *fr;
61 struct nl_parser_param *pp = arg;
65 res = flnl_result_alloc();
69 res->ce_msgtype = n->nlmsg_type;
71 res->fr_req = flnl_request_alloc();
76 addr = nl_addr_build(AF_INET, &fr->fl_addr, 4);
79 err = flnl_request_set_addr(res->fr_req, addr);
84 flnl_request_set_fwmark(res->fr_req, fr->fl_fwmark);
85 flnl_request_set_tos(res->fr_req, fr->fl_tos);
86 flnl_request_set_scope(res->fr_req, fr->fl_scope);
87 flnl_request_set_table(res->fr_req, fr->tb_id_in);
89 res->fr_table_id = fr->tb_id;
90 res->fr_prefixlen = fr->prefixlen;
91 res->fr_nh_sel = fr->nh_sel;
92 res->fr_type = fr->type;
93 res->fr_scope = fr->scope;
94 res->fr_error = fr->err;
96 err = pp->pp_cb((struct nl_object *) res, pp);
100 /* REAL HACK, fib_lookup doesn't support ACK nor does it
101 * send a DONE message, enforce end of message stream
102 * after just the first message */
106 flnl_result_put(res);
110 static int result_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
112 struct flnl_result *res = (struct flnl_result *) obj;
116 dp_dump(p, "table %s prefixlen %u next-hop-selector %u\n",
117 rtnl_route_table2str(res->fr_table_id, buf, sizeof(buf)),
118 res->fr_prefixlen, res->fr_nh_sel);
119 dp_dump_line(p, line++, "type %s ",
120 nl_rtntype2str(res->fr_type, buf, sizeof(buf)));
121 dp_dump(p, "scope %s error %s (%d)\n",
122 rtnl_scope2str(res->fr_scope, buf, sizeof(buf)),
123 strerror(-res->fr_error), res->fr_error);
128 static int result_dump_full(struct nl_object *obj, struct nl_dump_params *p)
130 return result_dump_brief(obj, p);
133 static int result_filter(struct nl_object *obj, struct nl_object *filter)
135 struct flnl_result *o = (struct flnl_result *) obj;
136 struct flnl_result *f = (struct flnl_result *) filter;
138 if (o->fr_req && f->fr_req)
139 return flnl_request_cmp(o->fr_req, f->fr_req);
145 * @name FIB Result Allocation/Freeage
150 * Allocate and initialize new lookup result object.
151 * @note Free the memory after usage using flnl_result_put() or
152 * flnl_result_free().
153 * @return Newly allocated lookup result object or NULL if an error occured.
155 struct flnl_result *flnl_result_alloc(void)
157 return (struct flnl_result *) nl_object_alloc_from_ops(&fib_lookup_ops);
161 * Allocate lookup result cache.
163 * Allocates a new lookup result cache and initializes it properly.
165 * @note Free the memory after usage using nl_cache_destroy_and_free().
166 * @return Newly allocated cache or NULL if an error occured.
168 struct nl_cache *flnl_result_alloc_cache(void)
170 return nl_cache_alloc_from_ops(&fib_lookup_ops);
174 * Give back reference on lookup result object.
175 * @arg res lookup result object to be given back.
177 * Decrements the reference counter and frees the object if the
178 * last reference has been released.
180 void flnl_result_put(struct flnl_result *res)
182 nl_object_put((struct nl_object *) res);
186 * Free lookup result object.
187 * @arg res lookup result object to be freed.
189 * @note Always use flnl_result_put() unless you're absolutely sure
190 * that no other user may have a reference on this object.
192 void flnl_result_free(struct flnl_result *res)
194 nl_object_free((struct nl_object *) res);
205 * Builds a netlink request message to do a lookup
206 * @arg req Requested match.
207 * @arg flags additional netlink message flags
209 * Builds a new netlink message requesting a change of link attributes.
210 * The netlink message header isn't fully equipped with all relevant
211 * fields and must be sent out via nl_send_auto_complete() or
212 * supplemented as needed.
213 * \a old must point to a link currently configured in the kernel
214 * and \a tmpl must contain the attributes to be changed set via
215 * \c rtnl_link_set_* functions.
217 * @return New netlink message
218 * @note Not all attributes can be changed, see
219 * \ref link_changeable "Changeable Attributes" for more details.
221 struct nl_msg *flnl_lookup_build_request(struct flnl_request *req, int flags)
224 struct nl_addr *addr;
226 int tos, scope, table;
227 struct fib_result_nl fr = {0};
229 fwmark = flnl_request_get_fwmark(req);
230 tos = flnl_request_get_tos(req);
231 scope = flnl_request_get_scope(req);
232 table = flnl_request_get_table(req);
234 fr.fl_fwmark = fwmark != UINT_LEAST64_MAX ? fwmark : 0;
235 fr.fl_tos = tos >= 0 ? tos : 0;
236 fr.fl_scope = scope >= 0 ? scope : RT_SCOPE_UNIVERSE;
237 fr.tb_id_in = table >= 0 ? table : RT_TABLE_UNSPEC;
239 addr = flnl_request_get_addr(req);
241 nl_error(EINVAL, "Request must specify the address");
245 fr.fl_addr = *(uint32_t *) nl_addr_get_binary_addr(addr);
247 msg = nlmsg_build_simple(0, flags);
251 if (nlmsg_append(msg, &fr, sizeof(fr), 1) < 0)
263 * @arg handle Netlink handle.
264 * @arg req Lookup request object.
265 * @arg cache Cache for result.
267 * Builds a netlink message to request a FIB lookup, waits for the
268 * reply and adds the result to the specified cache.
270 * @return 0 on success or a negative error code.
272 int flnl_lookup(struct nl_handle *handle, struct flnl_request *req,
273 struct nl_cache *cache)
278 msg = flnl_lookup_build_request(req, 0);
280 return nl_errno(ENOMEM);
282 err = nl_send_auto_complete(handle, msg);
287 return nl_cache_pickup(handle, cache);
293 * @name Attribute Access
297 int flnl_result_get_table_id(struct flnl_result *res)
299 return res->fr_table_id;
302 int flnl_result_get_prefixlen(struct flnl_result *res)
304 return res->fr_prefixlen;
307 int flnl_result_get_nexthop_sel(struct flnl_result *res)
309 return res->fr_nh_sel;
312 int flnl_result_get_type(struct flnl_result *res)
317 int flnl_result_get_scope(struct flnl_result *res)
319 return res->fr_scope;
322 int flnl_result_get_error(struct flnl_result *res)
324 return res->fr_error;
329 static struct nl_cache_ops fib_lookup_ops = {
330 .co_name = "fib_lookup/fib_lookup",
331 .co_size = sizeof(struct flnl_result),
332 .co_hdrsize = sizeof(struct fib_result_nl),
337 .co_protocol = NETLINK_FIB_LOOKUP,
338 .co_msg_parser = result_msg_parser,
339 .co_free_data = result_free_data,
340 .co_dump[NL_DUMP_BRIEF] = result_dump_brief,
341 .co_dump[NL_DUMP_FULL] = result_dump_full,
342 .co_filter = result_filter,
345 static void __init fib_lookup_init(void)
347 nl_cache_mngt_register(&fib_lookup_ops);
350 static void __exit fib_lookup_exit(void)
352 nl_cache_mngt_unregister(&fib_lookup_ops);