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