144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/fib_lookup/lookup.c	FIB Lookup
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
544d362409d5469aed47d19e7908d19bd194493aThomas Graf *	modify it under the terms of the GNU Lesser General Public
644d362409d5469aed47d19e7908d19bd194493aThomas Graf *	License as published by the Free Software Foundation version 2.1
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *	of the License.
844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
9054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf
1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
13054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @ingroup rtnl
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup fib_lookup FIB Lookup
1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @brief
1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
1744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1844d362409d5469aed47d19e7908d19bd194493aThomas Graf
19054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink-private/netlink.h>
2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h>
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/attr.h>
2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h>
2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/object.h>
2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/rtnl.h>
2544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/route.h>
2644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/fib_lookup/request.h>
2744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/fib_lookup/lookup.h>
2844d362409d5469aed47d19e7908d19bd194493aThomas Graf
2944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */
3044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops fib_lookup_ops;
3144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops result_obj_ops;
3244d362409d5469aed47d19e7908d19bd194493aThomas Graf
3344d362409d5469aed47d19e7908d19bd194493aThomas Graf/* not exported so far */
3444d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct fib_result_nl {
3544d362409d5469aed47d19e7908d19bd194493aThomas Graf	uint32_t	fl_addr;   /* To be looked up*/
3644d362409d5469aed47d19e7908d19bd194493aThomas Graf	uint32_t	fl_fwmark;
3744d362409d5469aed47d19e7908d19bd194493aThomas Graf	unsigned char	fl_tos;
3844d362409d5469aed47d19e7908d19bd194493aThomas Graf	unsigned char   fl_scope;
3944d362409d5469aed47d19e7908d19bd194493aThomas Graf	unsigned char   tb_id_in;
4044d362409d5469aed47d19e7908d19bd194493aThomas Graf
4144d362409d5469aed47d19e7908d19bd194493aThomas Graf	unsigned char   tb_id;      /* Results */
4244d362409d5469aed47d19e7908d19bd194493aThomas Graf	unsigned char	prefixlen;
4344d362409d5469aed47d19e7908d19bd194493aThomas Graf	unsigned char	nh_sel;
4444d362409d5469aed47d19e7908d19bd194493aThomas Graf	unsigned char	type;
4544d362409d5469aed47d19e7908d19bd194493aThomas Graf	unsigned char	scope;
4644d362409d5469aed47d19e7908d19bd194493aThomas Graf	int             err;
4744d362409d5469aed47d19e7908d19bd194493aThomas Graf};
4844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */
4944d362409d5469aed47d19e7908d19bd194493aThomas Graf
5044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void result_free_data(struct nl_object *obj)
5144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
5244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct flnl_result *res = nl_object_priv(obj);
5344d362409d5469aed47d19e7908d19bd194493aThomas Graf
5444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (res && res->fr_req)
5544d362409d5469aed47d19e7908d19bd194493aThomas Graf		nl_object_put(OBJ_CAST(res->fr_req));
5644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
5744d362409d5469aed47d19e7908d19bd194493aThomas Graf
5844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int result_clone(struct nl_object *_dst, struct nl_object *_src)
5944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
6044d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct flnl_result *dst = nl_object_priv(_dst);
6144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct flnl_result *src = nl_object_priv(_src);
6244d362409d5469aed47d19e7908d19bd194493aThomas Graf
6344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (src->fr_req)
6444d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!(dst->fr_req = (struct flnl_request *)
6544d362409d5469aed47d19e7908d19bd194493aThomas Graf				nl_object_clone(OBJ_CAST(src->fr_req))))
668a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_NOMEM;
6744d362409d5469aed47d19e7908d19bd194493aThomas Graf
6844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
6944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
7044d362409d5469aed47d19e7908d19bd194493aThomas Graf
7144d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int result_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
723040a1d6254465bed9e44e4d1bf279c2c50cd16aThomas Graf			     struct nlmsghdr *n, struct nl_parser_param *pp)
7344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
7444d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct flnl_result *res;
7544d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct fib_result_nl *fr;
7644d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_addr *addr;
778a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	int err = -NLE_INVAL;
7844d362409d5469aed47d19e7908d19bd194493aThomas Graf
7944d362409d5469aed47d19e7908d19bd194493aThomas Graf	res = flnl_result_alloc();
8044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!res)
8144d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
8244d362409d5469aed47d19e7908d19bd194493aThomas Graf
8344d362409d5469aed47d19e7908d19bd194493aThomas Graf	res->ce_msgtype = n->nlmsg_type;
8444d362409d5469aed47d19e7908d19bd194493aThomas Graf
8544d362409d5469aed47d19e7908d19bd194493aThomas Graf	res->fr_req = flnl_request_alloc();
8644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!res->fr_req)
8744d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
8844d362409d5469aed47d19e7908d19bd194493aThomas Graf
8944d362409d5469aed47d19e7908d19bd194493aThomas Graf	fr = nlmsg_data(n);
9044d362409d5469aed47d19e7908d19bd194493aThomas Graf	addr = nl_addr_build(AF_INET, &fr->fl_addr, 4);
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!addr)
9244d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
9344d362409d5469aed47d19e7908d19bd194493aThomas Graf	err = flnl_request_set_addr(res->fr_req, addr);
9444d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_addr_put(addr);
9544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
9644d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
9744d362409d5469aed47d19e7908d19bd194493aThomas Graf
9844d362409d5469aed47d19e7908d19bd194493aThomas Graf	flnl_request_set_fwmark(res->fr_req, fr->fl_fwmark);
9944d362409d5469aed47d19e7908d19bd194493aThomas Graf	flnl_request_set_tos(res->fr_req, fr->fl_tos);
10044d362409d5469aed47d19e7908d19bd194493aThomas Graf	flnl_request_set_scope(res->fr_req, fr->fl_scope);
10144d362409d5469aed47d19e7908d19bd194493aThomas Graf	flnl_request_set_table(res->fr_req, fr->tb_id_in);
10244d362409d5469aed47d19e7908d19bd194493aThomas Graf
10344d362409d5469aed47d19e7908d19bd194493aThomas Graf	res->fr_table_id = fr->tb_id;
10444d362409d5469aed47d19e7908d19bd194493aThomas Graf	res->fr_prefixlen = fr->prefixlen;
10544d362409d5469aed47d19e7908d19bd194493aThomas Graf	res->fr_nh_sel = fr->nh_sel;
10644d362409d5469aed47d19e7908d19bd194493aThomas Graf	res->fr_type = fr->type;
10744d362409d5469aed47d19e7908d19bd194493aThomas Graf	res->fr_scope = fr->scope;
10844d362409d5469aed47d19e7908d19bd194493aThomas Graf	res->fr_error = fr->err;
10944d362409d5469aed47d19e7908d19bd194493aThomas Graf
11044d362409d5469aed47d19e7908d19bd194493aThomas Graf	err = pp->pp_cb((struct nl_object *) res, pp);
11144d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
11244d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
11344d362409d5469aed47d19e7908d19bd194493aThomas Graf
11444d362409d5469aed47d19e7908d19bd194493aThomas Graf	/* REAL HACK, fib_lookup doesn't support ACK nor does it
11544d362409d5469aed47d19e7908d19bd194493aThomas Graf	 * send a DONE message, enforce end of message stream
11644d362409d5469aed47d19e7908d19bd194493aThomas Graf	 * after just the first message */
117155ad439a49df034ec58ee4218834bc5b0120515Thomas Graf	err = NL_STOP;
11844d362409d5469aed47d19e7908d19bd194493aThomas Graf
11944d362409d5469aed47d19e7908d19bd194493aThomas Graferrout:
12044d362409d5469aed47d19e7908d19bd194493aThomas Graf	flnl_result_put(res);
12144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return err;
12244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
12344d362409d5469aed47d19e7908d19bd194493aThomas Graf
124d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void result_dump_line(struct nl_object *obj, struct nl_dump_params *p)
12544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
12644d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct flnl_result *res = (struct flnl_result *) obj;
127054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	char buf[256];
12844d362409d5469aed47d19e7908d19bd194493aThomas Graf
129d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	nl_dump_line(p, "table %s prefixlen %u next-hop-selector %u\n",
13044d362409d5469aed47d19e7908d19bd194493aThomas Graf		rtnl_route_table2str(res->fr_table_id, buf, sizeof(buf)),
13144d362409d5469aed47d19e7908d19bd194493aThomas Graf		res->fr_prefixlen, res->fr_nh_sel);
132d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	nl_dump_line(p, "type %s ",
13344d362409d5469aed47d19e7908d19bd194493aThomas Graf		     nl_rtntype2str(res->fr_type, buf, sizeof(buf)));
134d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	nl_dump(p, "scope %s error %s (%d)\n",
13544d362409d5469aed47d19e7908d19bd194493aThomas Graf		rtnl_scope2str(res->fr_scope, buf, sizeof(buf)),
136054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		strerror_r(-res->fr_error, buf, sizeof(buf)), res->fr_error);
13744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
13844d362409d5469aed47d19e7908d19bd194493aThomas Graf
139d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void result_dump_details(struct nl_object *obj, struct nl_dump_params *p)
14044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
141d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	result_dump_line(obj, p);
14244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
14344d362409d5469aed47d19e7908d19bd194493aThomas Graf
14444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int result_compare(struct nl_object *_a, struct nl_object *_b,
14544d362409d5469aed47d19e7908d19bd194493aThomas Graf			uint32_t attrs, int flags)
14644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
14744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
14844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
14944d362409d5469aed47d19e7908d19bd194493aThomas Graf
15044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
15144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Allocation/Freeing
15244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
15344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
15444d362409d5469aed47d19e7908d19bd194493aThomas Graf
15544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct flnl_result *flnl_result_alloc(void)
15644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
15744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return (struct flnl_result *) nl_object_alloc(&result_obj_ops);
15844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
15944d362409d5469aed47d19e7908d19bd194493aThomas Graf
16044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid flnl_result_put(struct flnl_result *res)
16144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
16244d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_object_put((struct nl_object *) res);
16344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
16444d362409d5469aed47d19e7908d19bd194493aThomas Graf
16544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
16644d362409d5469aed47d19e7908d19bd194493aThomas Graf
16744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
16844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Cache Management
16944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
17044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
17144d362409d5469aed47d19e7908d19bd194493aThomas Graf
17244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
17344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocate lookup result cache.
17444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
17544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocates a new lookup result cache and initializes it properly.
17644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
17744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @note Free the memory after usage using nl_cache_destroy_and_free().
17844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated cache or NULL if an error occured.
17944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
18044d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cache *flnl_result_alloc_cache(void)
18144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
18244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nl_cache_alloc(&fib_lookup_ops);
18344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
18444d362409d5469aed47d19e7908d19bd194493aThomas Graf
18544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
18644d362409d5469aed47d19e7908d19bd194493aThomas Graf
18744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
18844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Lookup
18944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
19044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
19144d362409d5469aed47d19e7908d19bd194493aThomas Graf
19244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
19344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink request message to do a lookup
19444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg req		Requested match.
19544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags		additional netlink message flags
196054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg result		Result pointer
19744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
19844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message requesting a change of link attributes.
19944d362409d5469aed47d19e7908d19bd194493aThomas Graf * The netlink message header isn't fully equipped with all relevant
20044d362409d5469aed47d19e7908d19bd194493aThomas Graf * fields and must be sent out via nl_send_auto_complete() or
20144d362409d5469aed47d19e7908d19bd194493aThomas Graf * supplemented as needed.
20244d362409d5469aed47d19e7908d19bd194493aThomas Graf * \a old must point to a link currently configured in the kernel
20344d362409d5469aed47d19e7908d19bd194493aThomas Graf * and \a tmpl must contain the attributes to be changed set via
20444d362409d5469aed47d19e7908d19bd194493aThomas Graf * \c rtnl_link_set_* functions.
20544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
206054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return 0 on success or a negative error code.
20744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
2088a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint flnl_lookup_build_request(struct flnl_request *req, int flags,
2098a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			      struct nl_msg **result)
21044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
21144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_msg *msg;
21244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_addr *addr;
21344d362409d5469aed47d19e7908d19bd194493aThomas Graf	uint64_t fwmark;
21444d362409d5469aed47d19e7908d19bd194493aThomas Graf	int tos, scope, table;
21544d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct fib_result_nl fr = {0};
21644d362409d5469aed47d19e7908d19bd194493aThomas Graf
21744d362409d5469aed47d19e7908d19bd194493aThomas Graf	fwmark = flnl_request_get_fwmark(req);
21844d362409d5469aed47d19e7908d19bd194493aThomas Graf	tos = flnl_request_get_tos(req);
21944d362409d5469aed47d19e7908d19bd194493aThomas Graf	scope = flnl_request_get_scope(req);
22044d362409d5469aed47d19e7908d19bd194493aThomas Graf	table = flnl_request_get_table(req);
22144d362409d5469aed47d19e7908d19bd194493aThomas Graf
22244d362409d5469aed47d19e7908d19bd194493aThomas Graf	fr.fl_fwmark = fwmark != UINT_LEAST64_MAX ? fwmark : 0;
22344d362409d5469aed47d19e7908d19bd194493aThomas Graf	fr.fl_tos = tos >= 0 ? tos : 0;
22444d362409d5469aed47d19e7908d19bd194493aThomas Graf	fr.fl_scope = scope >= 0 ? scope : RT_SCOPE_UNIVERSE;
22544d362409d5469aed47d19e7908d19bd194493aThomas Graf	fr.tb_id_in = table >= 0 ? table : RT_TABLE_UNSPEC;
22644d362409d5469aed47d19e7908d19bd194493aThomas Graf
22744d362409d5469aed47d19e7908d19bd194493aThomas Graf	addr = flnl_request_get_addr(req);
2288a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	if (!addr)
2298a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_MISSING_ATTR;
23044d362409d5469aed47d19e7908d19bd194493aThomas Graf
23144d362409d5469aed47d19e7908d19bd194493aThomas Graf	fr.fl_addr = *(uint32_t *) nl_addr_get_binary_addr(addr);
23244d362409d5469aed47d19e7908d19bd194493aThomas Graf
23344d362409d5469aed47d19e7908d19bd194493aThomas Graf	msg = nlmsg_alloc_simple(0, flags);
23444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!msg)
2358a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_NOMEM;
23644d362409d5469aed47d19e7908d19bd194493aThomas Graf
23744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (nlmsg_append(msg, &fr, sizeof(fr), NLMSG_ALIGNTO) < 0)
23844d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
23944d362409d5469aed47d19e7908d19bd194493aThomas Graf
2408a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	*result = msg;
2418a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	return 0;
24244d362409d5469aed47d19e7908d19bd194493aThomas Graf
24344d362409d5469aed47d19e7908d19bd194493aThomas Graferrout:
24444d362409d5469aed47d19e7908d19bd194493aThomas Graf	nlmsg_free(msg);
2458a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	return -NLE_MSGSIZE;
24644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
24744d362409d5469aed47d19e7908d19bd194493aThomas Graf
24844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
24944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Perform FIB Lookup
2501155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
25144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg req		Lookup request object.
25244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cache		Cache for result.
25344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
25444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink message to request a FIB lookup, waits for the
25544d362409d5469aed47d19e7908d19bd194493aThomas Graf * reply and adds the result to the specified cache.
25644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
25744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code.
25844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
2591155370f520cb64657e25153255cf7dc1424317fThomas Grafint flnl_lookup(struct nl_sock *sk, struct flnl_request *req,
26044d362409d5469aed47d19e7908d19bd194493aThomas Graf		struct nl_cache *cache)
26144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
26244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_msg *msg;
26344d362409d5469aed47d19e7908d19bd194493aThomas Graf	int err;
26444d362409d5469aed47d19e7908d19bd194493aThomas Graf
2658a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	if ((err = flnl_lookup_build_request(req, 0, &msg)) < 0)
2668a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return err;
26744d362409d5469aed47d19e7908d19bd194493aThomas Graf
2681155370f520cb64657e25153255cf7dc1424317fThomas Graf	err = nl_send_auto_complete(sk, msg);
26944d362409d5469aed47d19e7908d19bd194493aThomas Graf	nlmsg_free(msg);
27044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
27144d362409d5469aed47d19e7908d19bd194493aThomas Graf		return err;
27244d362409d5469aed47d19e7908d19bd194493aThomas Graf
2731155370f520cb64657e25153255cf7dc1424317fThomas Graf	return nl_cache_pickup(sk, cache);
27444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
27544d362409d5469aed47d19e7908d19bd194493aThomas Graf
27644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
27744d362409d5469aed47d19e7908d19bd194493aThomas Graf
27844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
27944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attribute Access
28044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
28144d362409d5469aed47d19e7908d19bd194493aThomas Graf */
28244d362409d5469aed47d19e7908d19bd194493aThomas Graf
28344d362409d5469aed47d19e7908d19bd194493aThomas Grafint flnl_result_get_table_id(struct flnl_result *res)
28444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
28544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return res->fr_table_id;
28644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
28744d362409d5469aed47d19e7908d19bd194493aThomas Graf
28844d362409d5469aed47d19e7908d19bd194493aThomas Grafint flnl_result_get_prefixlen(struct flnl_result *res)
28944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
29044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return res->fr_prefixlen;
29144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
29244d362409d5469aed47d19e7908d19bd194493aThomas Graf
29344d362409d5469aed47d19e7908d19bd194493aThomas Grafint flnl_result_get_nexthop_sel(struct flnl_result *res)
29444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
29544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return res->fr_nh_sel;
29644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
29744d362409d5469aed47d19e7908d19bd194493aThomas Graf
29844d362409d5469aed47d19e7908d19bd194493aThomas Grafint flnl_result_get_type(struct flnl_result *res)
29944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
30044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return res->fr_type;
30144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
30244d362409d5469aed47d19e7908d19bd194493aThomas Graf
30344d362409d5469aed47d19e7908d19bd194493aThomas Grafint flnl_result_get_scope(struct flnl_result *res)
30444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
30544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return res->fr_scope;
30644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
30744d362409d5469aed47d19e7908d19bd194493aThomas Graf
30844d362409d5469aed47d19e7908d19bd194493aThomas Grafint flnl_result_get_error(struct flnl_result *res)
30944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
31044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return res->fr_error;
31144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
31244d362409d5469aed47d19e7908d19bd194493aThomas Graf
31344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
31444d362409d5469aed47d19e7908d19bd194493aThomas Graf
31544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops result_obj_ops = {
31644d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_name		= "fib_lookup/result",
31744d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_size		= sizeof(struct flnl_result),
31844d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_free_data		= result_free_data,
31944d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_clone		= result_clone,
320d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	.oo_dump = {
321d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	    [NL_DUMP_LINE]	= result_dump_line,
322d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	    [NL_DUMP_DETAILS]	= result_dump_details,
323d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	},
32444d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_compare		= result_compare,
32544d362409d5469aed47d19e7908d19bd194493aThomas Graf};
32644d362409d5469aed47d19e7908d19bd194493aThomas Graf
32744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops fib_lookup_ops = {
32844d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_name		= "fib_lookup/fib_lookup",
32944d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_hdrsize		= sizeof(struct fib_result_nl),
33044d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_msgtypes		= {
33144d362409d5469aed47d19e7908d19bd194493aThomas Graf					{ 0, NL_ACT_UNSPEC, "any" },
33244d362409d5469aed47d19e7908d19bd194493aThomas Graf					END_OF_MSGTYPES_LIST,
33344d362409d5469aed47d19e7908d19bd194493aThomas Graf				  },
33444d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_protocol		= NETLINK_FIB_LOOKUP,
33544d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_msg_parser		= result_msg_parser,
33644d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_obj_ops		= &result_obj_ops,
33744d362409d5469aed47d19e7908d19bd194493aThomas Graf};
33844d362409d5469aed47d19e7908d19bd194493aThomas Graf
33944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init fib_lookup_init(void)
34044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
34144d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_cache_mngt_register(&fib_lookup_ops);
34244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
34344d362409d5469aed47d19e7908d19bd194493aThomas Graf
34444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __exit fib_lookup_exit(void)
34544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
34644d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_cache_mngt_unregister(&fib_lookup_ops);
34744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
34844d362409d5469aed47d19e7908d19bd194493aThomas Graf
34944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
350