oops
[libnl.git] / lib / fib_lookup / request.c
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-2006 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 /** @cond SKIP */
27 #define REQUEST_ATTR_ADDR       0x01
28 #define REQUEST_ATTR_FWMARK     0x02
29 #define REQUEST_ATTR_TOS        0x04
30 #define REQUEST_ATTR_SCOPE      0x08
31 #define REQUEST_ATTR_TABLE      0x10
32 /** @endcond */
33
34 /**
35  * @name Lookup Request Creation/Deletion
36  * @{
37  */
38
39 /**
40  * Allocate and initialize new lookup request object.
41  * @note Free the memory after usage using flnl_request_put() or
42  *       flnl_request_free().
43  * @return Newly allocated lookup request object or NULL if an error occured.
44  */
45 struct flnl_request *flnl_request_alloc(void)
46 {
47         struct flnl_request *req;
48
49         req = calloc(1, sizeof(*req));
50         if (req)
51                 req->lr_refcnt = 1;
52         else
53                 nl_errno(ENOMEM);
54
55         return req;
56 }
57
58 /**
59  * Request undestroyable reference of lookup request object.
60  * @arg req             Lookup request object.
61  * @return Lookup request object of which the reference was given.
62  */
63 struct flnl_request *flnl_request_get(struct flnl_request *req)
64 {
65         req->lr_refcnt++;
66
67         return req;
68 }
69
70 /**
71  * Give back reference of lookup request object.
72  * @arg req             Lookup request object to be given back.
73  * 
74  * Decrements the reference counter and destroys the object if the
75  * last reference was given back.
76  */
77 void flnl_request_put(struct flnl_request *req)
78 {
79         if (!req)
80                 return;
81
82         if (req->lr_refcnt <= 1)
83                 flnl_request_free(req);
84         else
85                 req->lr_refcnt--;
86 }
87
88 /**
89  * Free lookup request object.
90  * @arg req             Lookup request object to be freed.
91  */
92 void flnl_request_free(struct flnl_request *req)
93 {
94         if (!req)
95                 return;
96
97         if (req->lr_refcnt != 1)
98                 BUG();
99
100         free(req);
101 }
102
103 /** @} */
104
105 /**
106  * @name Attribute Access
107  * @{
108  */
109
110 /**
111  * Set firewall mark of lookup request object.
112  * @arg req             Lookup request object.
113  * @arg fwmark          Firewall mark.
114  */
115 void flnl_request_set_fwmark(struct flnl_request *req, uint64_t fwmark)
116 {
117         req->lr_fwmark = fwmark;
118         req->lr_mask |= REQUEST_ATTR_FWMARK;
119 }
120
121 /**
122  * Get firewall mark of lookup request object.
123  * @arg req             Lookup request object.
124  * @return Firewall mark or UINT_LEAST64_MAX if not available.
125  */
126 uint64_t flnl_request_get_fwmark(struct flnl_request *req)
127 {
128         if (req->lr_mask & REQUEST_ATTR_FWMARK)
129                 return req->lr_fwmark;
130         else
131                 return UINT_LEAST64_MAX;
132 }
133
134 /**
135  * Set Type of Service of lookup request object.
136  * @arg req             Lookup request object.
137  * @arg tos             Type of Service.
138  */
139 void flnl_request_set_tos(struct flnl_request *req, int tos)
140 {
141         req->lr_tos = tos;
142         req->lr_mask |= REQUEST_ATTR_TOS;
143 }
144
145 /**
146  * Get Type of Service of lookup request object.
147  * @arg req             Lookup request object.
148  * @return Type of Service or -1 if not available.
149  */
150 int flnl_request_get_tos(struct flnl_request *req)
151 {
152         if (req->lr_mask & REQUEST_ATTR_TOS)
153                 return req->lr_tos;
154         else
155                 return -1;
156 }
157
158 /**
159  * Set Scope of lookup request object.
160  * @arg req             Lookup request oject.
161  * @arg scope           Routing scope.
162  */
163 void flnl_request_set_scope(struct flnl_request *req, int scope)
164 {
165         req->lr_scope = scope;
166         req->lr_mask |= REQUEST_ATTR_SCOPE;
167 }
168
169 /**
170  * Get scope of lookup request object.
171  * @arg req             Lookup request object.
172  * @return Scope or -1 if not available.
173  */
174 int flnl_request_get_scope(struct flnl_request *req)
175 {
176         if (req->lr_mask & REQUEST_ATTR_SCOPE)
177                 return req->lr_scope;
178         else
179                 return -1;
180 }
181
182 /**
183  * Set routing table of lookup request object.
184  * @arg req             Lookup request object.
185  * @arg table           Routing table.
186  */
187 void flnl_request_set_table(struct flnl_request *req, int table)
188 {
189         req->lr_table = table;
190         req->lr_mask |= REQUEST_ATTR_TABLE;
191 }
192
193 /**
194  * Get routing table of lookup request object.
195  * @arg req             Lookup request object.
196  * @return Routing table or -1 if not available.
197  */
198 int flnl_request_get_table(struct flnl_request *req)
199 {
200         if (req->lr_mask & REQUEST_ATTR_TABLE)
201                 return req->lr_table;
202         else
203                 return -1;
204 }
205
206 /**
207  * Set destination address of lookup request object.
208  * @arg req             Lookup request object.
209  * @arg addr            IPv4 destination address.
210  */
211 int flnl_request_set_addr(struct flnl_request *req, struct nl_addr *addr)
212 {
213         if (addr->a_family != AF_INET)
214                 return nl_error(EINVAL, "Address must be an IPv4 address");
215
216         if (req->lr_addr)
217                 nl_addr_put(req->lr_addr);
218
219         nl_addr_get(addr);
220         req->lr_addr = addr;
221
222         req->lr_mask |= REQUEST_ATTR_ADDR;
223
224         return 0;
225 }
226
227 /**
228  * Get destination address of lookup request object.
229  * @arg req             Lookup request object.
230  * @return Destination address or NULL if not available.
231  */
232 struct nl_addr *flnl_request_get_addr(struct flnl_request *req)
233 {
234         if (req->lr_mask & REQUEST_ATTR_ADDR)
235                 return req->lr_addr;
236         else
237                 return NULL;
238 }
239
240 /** @} */
241
242 /**
243  * @name Miscellaneous
244  * @{
245  */
246
247 /**
248  * Compares two lookup request objects.
249  * @arg a               Lookup request object.
250  * @arg b               Another lookup request object.
251  *
252  * @return Integer less than, equal to or greather than zero if \c is found,
253  *         respectively to be less than, to, or be greater than \c b.
254  */
255 int flnl_request_cmp(struct flnl_request *a, struct flnl_request *b)
256 {
257 #define REQ(F) (a->lr_mask & REQUEST_ATTR_##F)
258 #define AVAIL(F) (b->lr_mask & REQUEST_ATTR_##F)
259 #define F_CUS(F, EXPR) (REQ(F) && (!AVAIL(F) || (EXPR)))
260 #define F_INT(F, N) (REQ(F) && (!AVAIL(F) || (a->N != b->N)))
261
262         if (F_INT(FWMARK,       lr_fwmark)                              ||
263             F_INT(TOS,          lr_tos)                                 ||
264             F_INT(SCOPE,        lr_scope)                               ||
265             F_INT(TABLE,        lr_table)                               ||
266             F_CUS(ADDR,         nl_addr_cmp(a->lr_addr, b->lr_addr)))
267                 return 0;
268 #undef REQ
269 #undef AVAIL
270 #undef F_CUS
271 #undef F_INT
272         return 1;
273 }
274
275 /** @} */
276
277 /** @} */