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 
26 static 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 
request_free_data(struct nl_object * obj)36 static 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 
request_clone(struct nl_object * _dst,struct nl_object * _src)44 static 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 
request_compare(struct nl_object * _a,struct nl_object * _b,uint32_t attrs,int flags)56 static 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 
flnl_request_alloc(void)82 struct 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 
flnl_request_set_fwmark(struct flnl_request * req,uint64_t fwmark)94 void 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 
flnl_request_get_fwmark(struct flnl_request * req)100 uint64_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 
flnl_request_set_tos(struct flnl_request * req,int tos)108 void 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 
flnl_request_get_tos(struct flnl_request * req)114 int 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 
flnl_request_set_scope(struct flnl_request * req,int scope)122 void 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 
flnl_request_get_scope(struct flnl_request * req)128 int 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 
flnl_request_set_table(struct flnl_request * req,int table)136 void 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 
flnl_request_get_table(struct flnl_request * req)142 int 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 
flnl_request_set_addr(struct flnl_request * req,struct nl_addr * addr)150 int 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 
flnl_request_get_addr(struct flnl_request * req)166 struct 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 
176 static 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