1/*
2 * lib/fib_lookup/request.c	FIB Lookup Request
3 *
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
7 *	of the License.
8 *
9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
10 */
11
12/**
13 * @ingroup fib_lookup
14 * @defgroup flreq Request
15 * @brief
16 * @{
17 */
18
19#include <netlink-local.h>
20#include <netlink/netlink.h>
21#include <netlink/attr.h>
22#include <netlink/utils.h>
23#include <netlink/object.h>
24#include <netlink/fib_lookup/request.h>
25
26static struct nl_object_ops request_obj_ops;
27
28/** @cond SKIP */
29#define REQUEST_ATTR_ADDR	0x01
30#define REQUEST_ATTR_FWMARK	0x02
31#define REQUEST_ATTR_TOS	0x04
32#define REQUEST_ATTR_SCOPE	0x08
33#define REQUEST_ATTR_TABLE	0x10
34/** @endcond */
35
36static void request_free_data(struct nl_object *obj)
37{
38	struct flnl_request *req = REQUEST_CAST(obj);
39
40	if (req)
41		nl_addr_put(req->lr_addr);
42}
43
44static int request_clone(struct nl_object *_dst, struct nl_object *_src)
45{
46	struct flnl_request *dst = nl_object_priv(_dst);
47	struct flnl_request *src = nl_object_priv(_src);
48
49	if (src->lr_addr)
50		if (!(dst->lr_addr = nl_addr_clone(src->lr_addr)))
51			return -NLE_NOMEM;
52
53	return 0;
54}
55
56static int request_compare(struct nl_object *_a, struct nl_object *_b,
57			   uint32_t attrs, int flags)
58{
59	struct flnl_request *a = (struct flnl_request *) _a;
60	struct flnl_request *b = (struct flnl_request *) _b;
61	int diff = 0;
62
63#define REQ_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, REQUEST_ATTR_##ATTR, a, b, EXPR)
64
65	diff |= REQ_DIFF(FWMARK,	a->lr_fwmark != b->lr_fwmark);
66	diff |= REQ_DIFF(TOS,		a->lr_tos != b->lr_tos);
67	diff |= REQ_DIFF(SCOPE,		a->lr_scope != b->lr_scope);
68	diff |= REQ_DIFF(TABLE,		a->lr_table != b->lr_table);
69	diff |= REQ_DIFF(ADDR,		nl_addr_cmp(a->lr_addr, b->lr_addr));
70
71#undef REQ_DIFF
72
73	return diff;
74}
75
76
77/**
78 * @name Lookup Request Creation/Deletion
79 * @{
80 */
81
82struct flnl_request *flnl_request_alloc(void)
83{
84	return REQUEST_CAST(nl_object_alloc(&request_obj_ops));
85}
86
87/** @} */
88
89/**
90 * @name Attributes
91 * @{
92 */
93
94void flnl_request_set_fwmark(struct flnl_request *req, uint64_t fwmark)
95{
96	req->lr_fwmark = fwmark;
97	req->ce_mask |= REQUEST_ATTR_FWMARK;
98}
99
100uint64_t flnl_request_get_fwmark(struct flnl_request *req)
101{
102	if (req->ce_mask & REQUEST_ATTR_FWMARK)
103		return req->lr_fwmark;
104	else
105		return UINT_LEAST64_MAX;
106}
107
108void flnl_request_set_tos(struct flnl_request *req, int tos)
109{
110	req->lr_tos = tos;
111	req->ce_mask |= REQUEST_ATTR_TOS;
112}
113
114int flnl_request_get_tos(struct flnl_request *req)
115{
116	if (req->ce_mask & REQUEST_ATTR_TOS)
117		return req->lr_tos;
118	else
119		return -1;
120}
121
122void flnl_request_set_scope(struct flnl_request *req, int scope)
123{
124	req->lr_scope = scope;
125	req->ce_mask |= REQUEST_ATTR_SCOPE;
126}
127
128int flnl_request_get_scope(struct flnl_request *req)
129{
130	if (req->ce_mask & REQUEST_ATTR_SCOPE)
131		return req->lr_scope;
132	else
133		return -1;
134}
135
136void flnl_request_set_table(struct flnl_request *req, int table)
137{
138	req->lr_table = table;
139	req->ce_mask |= REQUEST_ATTR_TABLE;
140}
141
142int flnl_request_get_table(struct flnl_request *req)
143{
144	if (req->ce_mask & REQUEST_ATTR_TABLE)
145		return req->lr_table;
146	else
147		return -1;
148}
149
150int flnl_request_set_addr(struct flnl_request *req, struct nl_addr *addr)
151{
152	if (addr->a_family != AF_INET)
153		return -NLE_AF_NOSUPPORT;
154
155	if (req->lr_addr)
156		nl_addr_put(req->lr_addr);
157
158	nl_addr_get(addr);
159	req->lr_addr = addr;
160
161	req->ce_mask |= REQUEST_ATTR_ADDR;
162
163	return 0;
164}
165
166struct nl_addr *flnl_request_get_addr(struct flnl_request *req)
167{
168	if (req->ce_mask & REQUEST_ATTR_ADDR)
169		return req->lr_addr;
170	else
171		return NULL;
172}
173
174/** @} */
175
176static struct nl_object_ops request_obj_ops = {
177	.oo_name		= "fib_lookup/request",
178	.oo_size		= sizeof(struct flnl_request),
179	.oo_free_data		= request_free_data,
180	.oo_clone		= request_clone,
181	.oo_compare		= request_compare,
182	.oo_id_attrs		= ~0,
183};
184
185/** @} */
186