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