1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
35 /**
36 * @ingroup xfrmnl
37 * @defgroup XFRM Address Selector
38 *
39 * Abstract data type representing XFRM SA/SP selector properties
40 *
41 * @{
42 *
43 * Header
44 * ------
45 * ~~~~{.c}
46 * #include <netlink/xfrm/selector.h>
47 * ~~~~
48 */
49
50 #include <netlink/xfrm/selector.h>
51 #include <netlink-private/netlink.h>
52
sel_destroy(struct xfrmnl_sel * sel)53 static void sel_destroy(struct xfrmnl_sel* sel)
54 {
55 if (!sel)
56 return;
57
58 if (sel->refcnt != 1)
59 {
60 fprintf(stderr, "BUG: %s:%d\n", __FILE__, __LINE__);
61 assert(0);
62 }
63
64 nl_addr_put (sel->daddr);
65 nl_addr_put (sel->saddr);
66 free(sel);
67 }
68
69 /**
70 * @name Creating Selector
71 * @{
72 */
73
74 /**
75 * Allocate new selector object.
76 * @return Newly allocated selector object or NULL
77 */
xfrmnl_sel_alloc()78 struct xfrmnl_sel* xfrmnl_sel_alloc()
79 {
80 struct xfrmnl_sel* sel;
81
82 sel = calloc(1, sizeof(struct xfrmnl_sel));
83 if (!sel)
84 return NULL;
85
86 sel->refcnt = 1;
87
88 return sel;
89 }
90
91 /**
92 * Clone existing selector object.
93 * @arg sel Selector object.
94 * @return Newly allocated selector object being a duplicate of the
95 * specified selector object or NULL if a failure occured.
96 */
xfrmnl_sel_clone(struct xfrmnl_sel * sel)97 struct xfrmnl_sel* xfrmnl_sel_clone(struct xfrmnl_sel* sel)
98 {
99 struct xfrmnl_sel* new;
100
101 new = xfrmnl_sel_alloc();
102 if (!new)
103 return NULL;
104
105 memcpy(new, sel, sizeof(struct xfrmnl_sel));
106 new->daddr = nl_addr_clone(sel->daddr);
107 new->saddr = nl_addr_clone(sel->saddr);
108
109 return new;
110 }
111
112 /** @} */
113
114 /**
115 * @name Managing Usage References
116 * @{
117 */
118
xfrmnl_sel_get(struct xfrmnl_sel * sel)119 struct xfrmnl_sel* xfrmnl_sel_get(struct xfrmnl_sel* sel)
120 {
121 sel->refcnt++;
122
123 return sel;
124 }
125
xfrmnl_sel_put(struct xfrmnl_sel * sel)126 void xfrmnl_sel_put(struct xfrmnl_sel* sel)
127 {
128 if (!sel)
129 return;
130
131 if (sel->refcnt == 1)
132 sel_destroy(sel);
133 else
134 sel->refcnt--;
135 }
136
137 /**
138 * Check whether an selector object is shared.
139 * @arg addr Selector object.
140 * @return Non-zero if the selector object is shared, otherwise 0.
141 */
xfrmnl_sel_shared(struct xfrmnl_sel * sel)142 int xfrmnl_sel_shared(struct xfrmnl_sel* sel)
143 {
144 return sel->refcnt > 1;
145 }
146
147 /** @} */
148
149 /**
150 * @name Miscellaneous
151 * @{
152 */
153
154 /**
155 * Compares two selector objects.
156 * @arg a A selector object.
157 * @arg b Another selector object.
158 *
159 * @return Non zero if difference is found, 0 otherwise if both
160 * the objects are identical.
161 */
xfrmnl_sel_cmp(struct xfrmnl_sel * a,struct xfrmnl_sel * b)162 int xfrmnl_sel_cmp(struct xfrmnl_sel* a, struct xfrmnl_sel* b)
163 {
164 /* Check for any differences */
165 if ((nl_addr_cmp_prefix (a->daddr, b->daddr) != 0) ||
166 (nl_addr_cmp_prefix (a->saddr, b->saddr) != 0) ||
167 ((a->sport & a->sport_mask) != (b->sport & b->sport_mask)) ||
168 ((a->dport & a->dport_mask) != (b->dport & b->dport_mask)) ||
169 (a->family != b->family) ||
170 (a->proto && (a->proto != b->proto)) ||
171 (a->ifindex && a->ifindex != b->ifindex) ||
172 (a->user != b->user))
173 return 1;
174
175 /* The objects are identical */
176 return 0;
177 }
178
xfrmnl_sel_dump(struct xfrmnl_sel * sel,struct nl_dump_params * p)179 void xfrmnl_sel_dump(struct xfrmnl_sel* sel, struct nl_dump_params *p)
180 {
181 char dst[INET6_ADDRSTRLEN+5], src[INET6_ADDRSTRLEN+5];
182 char buf [128];
183
184 nl_dump_line(p, "\t\tsrc %s dst %s family: %s\n", nl_addr2str(sel->saddr, src, sizeof(src)),
185 nl_addr2str (sel->daddr, dst, sizeof (dst)), nl_af2str (sel->family, buf, 128));
186 nl_dump_line (p, "\t\tsrc port/mask: %d/%d dst port/mask: %d/%d\n",
187 sel->dport, sel->dport_mask, sel->sport, sel->sport_mask);
188 nl_dump_line (p, "\t\tprotocol: %s ifindex: %u user: %u\n",
189 nl_ip_proto2str (sel->proto, buf, sizeof(buf)), sel->ifindex, sel->user);
190
191 return;
192 }
193
194
195 /** @} */
196
197 /**
198 * @name Attributes
199 * @{
200 */
xfrmnl_sel_get_daddr(struct xfrmnl_sel * sel)201 struct nl_addr* xfrmnl_sel_get_daddr (struct xfrmnl_sel* sel)
202 {
203 return sel->daddr;
204 }
205
xfrmnl_sel_set_daddr(struct xfrmnl_sel * sel,struct nl_addr * addr)206 int xfrmnl_sel_set_daddr (struct xfrmnl_sel* sel, struct nl_addr* addr)
207 {
208 /* Increment reference counter on this to keep this address
209 * object around while selector in use */
210 nl_addr_get(addr);
211
212 sel->daddr = addr;
213
214 return 0;
215 }
216
xfrmnl_sel_get_saddr(struct xfrmnl_sel * sel)217 struct nl_addr* xfrmnl_sel_get_saddr (struct xfrmnl_sel* sel)
218 {
219 return sel->saddr;
220 }
221
xfrmnl_sel_set_saddr(struct xfrmnl_sel * sel,struct nl_addr * addr)222 int xfrmnl_sel_set_saddr (struct xfrmnl_sel* sel, struct nl_addr* addr)
223 {
224 /* Increment reference counter on this to keep this address
225 * object around while selector in use */
226 nl_addr_get(addr);
227
228 sel->saddr = addr;
229
230 return 0;
231 }
232
xfrmnl_sel_get_dport(struct xfrmnl_sel * sel)233 int xfrmnl_sel_get_dport (struct xfrmnl_sel* sel)
234 {
235 return sel->dport;
236 }
237
xfrmnl_sel_set_dport(struct xfrmnl_sel * sel,unsigned int dport)238 int xfrmnl_sel_set_dport (struct xfrmnl_sel* sel, unsigned int dport)
239 {
240 sel->dport = dport;
241
242 return 0;
243 }
244
xfrmnl_sel_get_dportmask(struct xfrmnl_sel * sel)245 int xfrmnl_sel_get_dportmask (struct xfrmnl_sel* sel)
246 {
247 return sel->dport_mask;
248 }
249
xfrmnl_sel_set_dportmask(struct xfrmnl_sel * sel,unsigned int dport_mask)250 int xfrmnl_sel_set_dportmask (struct xfrmnl_sel* sel, unsigned int dport_mask)
251 {
252 sel->dport_mask = dport_mask;
253
254 return 0;
255 }
256
xfrmnl_sel_get_sport(struct xfrmnl_sel * sel)257 int xfrmnl_sel_get_sport (struct xfrmnl_sel* sel)
258 {
259 return sel->sport;
260 }
261
xfrmnl_sel_set_sport(struct xfrmnl_sel * sel,unsigned int sport)262 int xfrmnl_sel_set_sport (struct xfrmnl_sel* sel, unsigned int sport)
263 {
264 sel->sport = sport;
265
266 return 0;
267 }
268
xfrmnl_sel_get_sportmask(struct xfrmnl_sel * sel)269 int xfrmnl_sel_get_sportmask (struct xfrmnl_sel* sel)
270 {
271 return sel->sport_mask;
272 }
273
xfrmnl_sel_set_sportmask(struct xfrmnl_sel * sel,unsigned int sport_mask)274 int xfrmnl_sel_set_sportmask (struct xfrmnl_sel* sel, unsigned int sport_mask)
275 {
276 sel->sport_mask = sport_mask;
277
278 return 0;
279 }
280
xfrmnl_sel_get_family(struct xfrmnl_sel * sel)281 int xfrmnl_sel_get_family(struct xfrmnl_sel *sel)
282 {
283 return sel->family;
284 }
285
xfrmnl_sel_set_family(struct xfrmnl_sel * sel,unsigned int family)286 int xfrmnl_sel_set_family(struct xfrmnl_sel *sel, unsigned int family)
287 {
288 sel->family = family;
289
290 return 0;
291 }
292
xfrmnl_sel_get_prefixlen_d(struct xfrmnl_sel * sel)293 int xfrmnl_sel_get_prefixlen_d (struct xfrmnl_sel* sel)
294 {
295 return sel->prefixlen_d;
296 }
297
xfrmnl_sel_set_prefixlen_d(struct xfrmnl_sel * sel,unsigned int prefixlen)298 int xfrmnl_sel_set_prefixlen_d (struct xfrmnl_sel* sel, unsigned int prefixlen)
299 {
300 sel->prefixlen_d = prefixlen;
301
302 return 0;
303 }
304
xfrmnl_sel_get_prefixlen_s(struct xfrmnl_sel * sel)305 int xfrmnl_sel_get_prefixlen_s (struct xfrmnl_sel* sel)
306 {
307 return sel->prefixlen_s;
308 }
309
xfrmnl_sel_set_prefixlen_s(struct xfrmnl_sel * sel,unsigned int prefixlen)310 int xfrmnl_sel_set_prefixlen_s (struct xfrmnl_sel* sel, unsigned int prefixlen)
311 {
312 sel->prefixlen_s = prefixlen;
313
314 return 0;
315 }
316
xfrmnl_sel_get_proto(struct xfrmnl_sel * sel)317 int xfrmnl_sel_get_proto (struct xfrmnl_sel* sel)
318 {
319 return sel->proto;
320 }
321
xfrmnl_sel_set_proto(struct xfrmnl_sel * sel,unsigned int protocol)322 int xfrmnl_sel_set_proto (struct xfrmnl_sel* sel, unsigned int protocol)
323 {
324 sel->proto = protocol;
325
326 return 0;
327 }
328
xfrmnl_sel_get_ifindex(struct xfrmnl_sel * sel)329 int xfrmnl_sel_get_ifindex (struct xfrmnl_sel* sel)
330 {
331 return sel->ifindex;
332 }
333
xfrmnl_sel_set_ifindex(struct xfrmnl_sel * sel,unsigned int ifindex)334 int xfrmnl_sel_set_ifindex (struct xfrmnl_sel* sel, unsigned int ifindex)
335 {
336 sel->ifindex = ifindex;
337
338 return 0;
339 }
340
xfrmnl_sel_get_userid(struct xfrmnl_sel * sel)341 int xfrmnl_sel_get_userid (struct xfrmnl_sel* sel)
342 {
343 return sel->user;
344 }
345
xfrmnl_sel_set_userid(struct xfrmnl_sel * sel,unsigned int userid)346 int xfrmnl_sel_set_userid (struct xfrmnl_sel* sel, unsigned int userid)
347 {
348 sel->user = userid;
349 return 0;
350 }
351
352
353 /** @} */
354