xref: /aosp_15_r20/external/libnl/lib/fib_lookup/request.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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