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 /**
37  * @ingroup xfrmnl
38  * @defgroup ae Attribute Element
39  * @brief
40  *
41  * The AE interface allows a user to retrieve and update various
42  * Security Association (SA) attributes such as lifetime, replay state etc.
43  *
44  * @par AE Flags
45  * @code
46  * XFRM_AE_UNSPEC
47  * XFRM_AE_RTHR=1
48  * XFRM_AE_RVAL=2
49  * XFRM_AE_LVAL=4
50  * XFRM_AE_ETHR=8
51  * XFRM_AE_CR=16
52  * XFRM_AE_CE=32
53  * XFRM_AE_CU=64
54  * @endcode
55  *
56  * @par AE Identification
57  * An AE is uniquely identified by the attributes listed below, whenever
58  * you refer to an existing AE all of the attributes must be set. There is
59  * no cache support for AE since you can retrieve the AE for any given combination
60  * of attributes mentioned below, but not all at once since they just characterize
61  * an SA.
62  *   - destination address (xfrmnl_ae_set_daddr())
63  *   - SPI (xfrmnl_ae_set_spi)
64  *   - protocol (xfrmnl_ae_set_proto)
65  *   - mark (xfrmnl_ae_set_mark)
66  *
67  * @par Changeable Attributes
68  * \anchor ae_changeable
69  *  - current lifetime (xfrmnl_ae_set_curlifetime())
70  *  - replay properties (xfrmnl_ae_set_replay_maxage(), xfrmnl_ae_set_replay_maxdiff())
71  *  - replay state (xfrmnl_ae_set_replay_state(), xfrmnl_ae_set_replay_state_esn))
72  *
73  * @par Required Caches for Dumping
74  * None
75  *
76  * @par TODO
77  * None
78  *
79  * @par 1) Retrieving AE information for a given SA tuple
80  * @code
81  * // Create a netlink socket and connect it to XFRM subsystem in
82  * the kernel to be able to send/receive info from userspace.
83  * struct nl_sock* sk = nl_socket_alloc ();
84  * nl_connect (sk, NETLINK_XFRM);
85  *
86  * // AEs can then be looked up by the SA tuple, destination address,
87  * SPI, protocol, mark:
88  * struct xfrmnl_ae *ae;
89  * xfrmnl_ae_get_kernel(sk, dst_addr, spi, proto,mark_mask, mark_value, &ae);
90  *
91  * // After successful usage, the object must be freed
92  * xfrmnl_ae_put(ae);
93  * @endcode
94  *
95  * @par 2) Updating AE
96  * @code
97  * // Allocate an empty AE handle to be filled out with the attributes
98  * // of the new AE.
99  * struct xfrmnl_ae *ae = xfrmnl_ae_alloc();
100  *
101  * // Fill out the attributes of the new AE
102  * xfrmnl_ae_set_daddr(ae, dst_addr);
103  * xfrmnl_ae_set_spi(ae, 0xDEADBEEF);
104  * xfrmnl_ae_set_proto(ae, 50);
105  * xfrmnl_ae_set_mark(ae, 0x0);
106  * xfrmnl_ae_set_saddr(ae, src_addr);
107  * xfrmnl_ae_set_curlifetime(ae, 540, 10, 0xAABB1122, 0x0);
108  *
109  * // Build the netlink message and send it to the kernel, the operation will
110  * // block until the operation has been completed. Alternatively, a netlink message
111  * // can be built using xfrmnl_ae_build_get_request () API and be sent using
112  * // nl_send_auto(). Further the result from the kernel can be parsed using
113  * // xfrmnl_ae_parse() API.
114  * xfrmnl_ae_set(sk, ae, NLM_F_REPLACE);
115  *
116  * // Free the memory
117  * xfrmnl_ae_put(ae);
118  * @endcode
119  *
120  * @{
121  */
122 
123 #include <netlink-private/netlink.h>
124 #include <netlink/netlink.h>
125 #include <netlink/cache.h>
126 #include <netlink/object.h>
127 #include <netlink/xfrm/ae.h>
128 #include <linux/xfrm.h>
129 
130 /** @cond SKIP */
131 #define XFRM_AE_ATTR_DADDR          0x01
132 #define XFRM_AE_ATTR_SPI            0x02
133 #define XFRM_AE_ATTR_PROTO          0x04
134 #define XFRM_AE_ATTR_SADDR          0x08
135 #define XFRM_AE_ATTR_FLAGS          0x10
136 #define XFRM_AE_ATTR_REQID          0x20
137 #define XFRM_AE_ATTR_MARK           0x40
138 #define XFRM_AE_ATTR_LIFETIME       0x80
139 #define XFRM_AE_ATTR_REPLAY_MAXAGE  0x100
140 #define XFRM_AE_ATTR_REPLAY_MAXDIFF 0x200
141 #define XFRM_AE_ATTR_REPLAY_STATE   0x400
142 #define XFRM_AE_ATTR_FAMILY         0x800
143 
144 static struct nl_object_ops xfrm_ae_obj_ops;
145 /** @endcond */
146 
147 
xfrm_ae_free_data(struct nl_object * c)148 static void xfrm_ae_free_data(struct nl_object *c)
149 {
150 	struct xfrmnl_ae* ae =   nl_object_priv (c);
151 
152 	if (ae == NULL)
153 		return;
154 
155 	nl_addr_put (ae->sa_id.daddr);
156 	nl_addr_put (ae->saddr);
157 
158 	if (ae->replay_state_esn)
159 		free (ae->replay_state_esn);
160 }
161 
xfrm_ae_clone(struct nl_object * _dst,struct nl_object * _src)162 static int xfrm_ae_clone(struct nl_object *_dst, struct nl_object *_src)
163 {
164 	struct xfrmnl_ae* dst = nl_object_priv(_dst);
165 	struct xfrmnl_ae* src = nl_object_priv(_src);
166 
167 	if (src->sa_id.daddr)
168 		if ((dst->sa_id.daddr = nl_addr_clone (src->sa_id.daddr)) == NULL)
169 			return -NLE_NOMEM;
170 
171 	if (src->saddr)
172 		if ((dst->saddr = nl_addr_clone (src->saddr)) == NULL)
173 			return -NLE_NOMEM;
174 
175 	if (src->replay_state_esn)
176 	{
177 		uint32_t len = sizeof (struct xfrmnl_replay_state_esn) + (sizeof (uint32_t) * src->replay_state_esn->bmp_len);
178 		if ((dst->replay_state_esn = malloc (len)) == NULL)
179 			return -NLE_NOMEM;
180 		memcpy (dst->replay_state_esn, src->replay_state_esn, len);
181 	}
182 
183 	return 0;
184 }
185 
xfrm_ae_compare(struct nl_object * _a,struct nl_object * _b,uint64_t attrs,int flags)186 static uint64_t xfrm_ae_compare(struct nl_object *_a, struct nl_object *_b,
187 				uint64_t attrs, int flags)
188 {
189 	struct xfrmnl_ae* a  =   (struct xfrmnl_ae *) _a;
190 	struct xfrmnl_ae* b  =   (struct xfrmnl_ae *) _b;
191 	uint64_t diff = 0;
192 	int found = 0;
193 
194 #define XFRM_AE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, XFRM_AE_ATTR_##ATTR, a, b, EXPR)
195 	diff |= XFRM_AE_DIFF(DADDR,	nl_addr_cmp(a->sa_id.daddr, b->sa_id.daddr));
196 	diff |= XFRM_AE_DIFF(SPI,	a->sa_id.spi != b->sa_id.spi);
197 	diff |= XFRM_AE_DIFF(PROTO,	a->sa_id.proto != b->sa_id.proto);
198 	diff |= XFRM_AE_DIFF(SADDR,	nl_addr_cmp(a->saddr, b->saddr));
199 	diff |= XFRM_AE_DIFF(FLAGS, a->flags != b->flags);
200 	diff |= XFRM_AE_DIFF(REQID, a->reqid != b->reqid);
201 	diff |= XFRM_AE_DIFF(MARK, (a->mark.v & a->mark.m) != (b->mark.v & b->mark.m));
202 	diff |= XFRM_AE_DIFF(REPLAY_MAXAGE, a->replay_maxage != b->replay_maxage);
203 	diff |= XFRM_AE_DIFF(REPLAY_MAXDIFF, a->replay_maxdiff != b->replay_maxdiff);
204 
205 	/* Compare replay states */
206 	found = AVAILABLE_MISMATCH (a, b, XFRM_AE_ATTR_REPLAY_STATE);
207 	if (found == 0) // attribute exists in both objects
208 	{
209 		if (((a->replay_state_esn != NULL) && (b->replay_state_esn == NULL)) ||
210 			((a->replay_state_esn == NULL) && (b->replay_state_esn != NULL)))
211 			found |= 1;
212 
213 		if (found == 0) // same replay type. compare actual values
214 		{
215 			if (a->replay_state_esn)
216 			{
217 				if (a->replay_state_esn->bmp_len != b->replay_state_esn->bmp_len)
218 					diff |= 1;
219 				else
220 				{
221 					uint32_t len = sizeof (struct xfrmnl_replay_state_esn) + (sizeof (uint32_t) * a->replay_state_esn->bmp_len);
222 					diff |= memcmp (a->replay_state_esn, b->replay_state_esn, len);
223 				}
224 			}
225 			else
226 			{
227 				if ((a->replay_state.oseq != b->replay_state.oseq) ||
228 				    (a->replay_state.seq != b->replay_state.seq) ||
229 				    (a->replay_state.bitmap != b->replay_state.bitmap))
230 					diff |= 1;
231 			}
232 		}
233 	}
234 #undef XFRM_AE_DIFF
235 
236 	return diff;
237 }
238 
239 /**
240  * @name XFRM AE Attribute Translations
241  * @{
242  */
243 static const struct trans_tbl ae_attrs[] =
244 {
245 	__ADD(XFRM_AE_ATTR_DADDR, daddr),
246 	__ADD(XFRM_AE_ATTR_SPI, spi),
247 	__ADD(XFRM_AE_ATTR_PROTO, protocol),
248 	__ADD(XFRM_AE_ATTR_SADDR, saddr),
249 	__ADD(XFRM_AE_ATTR_FLAGS, flags),
250 	__ADD(XFRM_AE_ATTR_REQID, reqid),
251 	__ADD(XFRM_AE_ATTR_MARK, mark),
252 	__ADD(XFRM_AE_ATTR_LIFETIME, cur_lifetime),
253 	__ADD(XFRM_AE_ATTR_REPLAY_MAXAGE, replay_maxage),
254 	__ADD(XFRM_AE_ATTR_REPLAY_MAXDIFF, replay_maxdiff),
255 	__ADD(XFRM_AE_ATTR_REPLAY_STATE, replay_state),
256 };
257 
xfrm_ae_attrs2str(int attrs,char * buf,size_t len)258 static char* xfrm_ae_attrs2str (int attrs, char *buf, size_t len)
259 {
260 	return __flags2str(attrs, buf, len, ae_attrs, ARRAY_SIZE(ae_attrs));
261 }
262 /** @} */
263 
264 /**
265  * @name XFRM AE Flags Translations
266  * @{
267  */
268 
269 static const struct trans_tbl ae_flags[] = {
270 	__ADD(XFRM_AE_UNSPEC, unspecified),
271 	__ADD(XFRM_AE_RTHR, replay threshold),
272 	__ADD(XFRM_AE_RVAL, replay value),
273 	__ADD(XFRM_AE_LVAL, lifetime value),
274 	__ADD(XFRM_AE_ETHR, expiry time threshold),
275 	__ADD(XFRM_AE_CR, replay update event),
276 	__ADD(XFRM_AE_CE, timer expiry event),
277 	__ADD(XFRM_AE_CU, policy update event),
278 };
279 
xfrmnl_ae_flags2str(int flags,char * buf,size_t len)280 char* xfrmnl_ae_flags2str(int flags, char *buf, size_t len)
281 {
282 	return __flags2str (flags, buf, len, ae_flags, ARRAY_SIZE(ae_flags));
283 }
284 
xfrmnl_ae_str2flag(const char * name)285 int xfrmnl_ae_str2flag(const char *name)
286 {
287 	return __str2flags(name, ae_flags, ARRAY_SIZE(ae_flags));
288 }
289 /** @} */
290 
xfrm_ae_dump_line(struct nl_object * a,struct nl_dump_params * p)291 static void xfrm_ae_dump_line(struct nl_object *a, struct nl_dump_params *p)
292 {
293 	char                dst[INET6_ADDRSTRLEN+5], src[INET6_ADDRSTRLEN+5];
294 	struct xfrmnl_ae*   ae  =   (struct xfrmnl_ae *) a;
295 	char                flags[128], buf[128];
296 	time_t              add_time, use_time;
297 	struct tm           *add_time_tm, *use_time_tm;
298 
299 	nl_dump_line(p, "src %s dst %s \n", nl_addr2str(ae->saddr, src, sizeof(src)),
300 				nl_addr2str(ae->sa_id.daddr, dst, sizeof(dst)));
301 
302 	nl_dump_line(p, "\tproto %s spi 0x%x reqid %u ",
303 				nl_ip_proto2str (ae->sa_id.proto, buf, sizeof (buf)),
304 				ae->sa_id.spi, ae->reqid);
305 
306 	xfrmnl_ae_flags2str(ae->flags, flags, sizeof (flags));
307 	nl_dump_line(p, "flags %s(0x%x) mark mask/value 0x%x/0x%x \n", flags,
308 				ae->flags, ae->mark.m, ae->mark.v);
309 
310 	nl_dump_line(p, "\tlifetime current: \n");
311 	nl_dump_line(p, "\t\tbytes %llu packets %llu \n", ae->lifetime_cur.bytes,
312 				ae->lifetime_cur.packets);
313 	if (ae->lifetime_cur.add_time != 0)
314 	{
315 		add_time = ae->lifetime_cur.add_time;
316 		add_time_tm = gmtime (&add_time);
317 		strftime (flags, 128, "%Y-%m-%d %H-%M-%S", add_time_tm);
318 	}
319 	else
320 	{
321 		sprintf (flags, "%s", "-");
322 	}
323 
324 	if (ae->lifetime_cur.use_time != 0)
325 	{
326 		use_time = ae->lifetime_cur.use_time;
327 		use_time_tm = gmtime (&use_time);
328 		strftime (buf, 128, "%Y-%m-%d %H-%M-%S", use_time_tm);
329 	}
330 	else
331 	{
332 		sprintf (buf, "%s", "-");
333 	}
334 	nl_dump_line(p, "\t\tadd_time: %s, use_time: %s\n", flags, buf);
335 
336 	nl_dump_line(p, "\treplay info: \n");
337 	nl_dump_line(p, "\t\tmax age %u max diff %u \n", ae->replay_maxage, ae->replay_maxdiff);
338 
339 	nl_dump_line(p, "\treplay state info: \n");
340 	if (ae->replay_state_esn)
341 	{
342 		nl_dump_line(p, "\t\toseq %u seq %u oseq_hi %u seq_hi %u replay window: %u \n",
343 					ae->replay_state_esn->oseq, ae->replay_state_esn->seq,
344 					ae->replay_state_esn->oseq_hi, ae->replay_state_esn->seq_hi,
345 					ae->replay_state_esn->replay_window);
346 	}
347 	else
348 	{
349 		nl_dump_line(p, "\t\toseq %u seq %u bitmap: %u \n", ae->replay_state.oseq,
350 					ae->replay_state.seq, ae->replay_state.bitmap);
351 	}
352 
353 	nl_dump(p, "\n");
354 }
355 
xfrm_ae_dump_details(struct nl_object * a,struct nl_dump_params * p)356 static void xfrm_ae_dump_details(struct nl_object *a, struct nl_dump_params *p)
357 {
358 	xfrm_ae_dump_line(a, p);
359 }
360 
xfrm_ae_dump_stats(struct nl_object * a,struct nl_dump_params * p)361 static void xfrm_ae_dump_stats(struct nl_object *a, struct nl_dump_params *p)
362 {
363 	xfrm_ae_dump_details(a, p);
364 }
365 
366 
build_xfrm_ae_message(struct xfrmnl_ae * tmpl,int cmd,int flags,struct nl_msg ** result)367 static int build_xfrm_ae_message(struct xfrmnl_ae *tmpl, int cmd, int flags,
368 			   struct nl_msg **result)
369 {
370 	struct nl_msg*          msg;
371 	struct xfrm_aevent_id   ae_id;
372 
373 	if (!(tmpl->ce_mask & XFRM_AE_ATTR_DADDR) ||
374 		!(tmpl->ce_mask & XFRM_AE_ATTR_SPI) ||
375 		!(tmpl->ce_mask & XFRM_AE_ATTR_PROTO))
376 		return -NLE_MISSING_ATTR;
377 
378 	memcpy (&ae_id.sa_id.daddr, nl_addr_get_binary_addr (tmpl->sa_id.daddr), sizeof (uint8_t) * nl_addr_get_len (tmpl->sa_id.daddr));
379 	ae_id.sa_id.spi    = htonl(tmpl->sa_id.spi);
380 	ae_id.sa_id.family = tmpl->sa_id.family;
381 	ae_id.sa_id.proto  = tmpl->sa_id.proto;
382 
383 	if (tmpl->ce_mask & XFRM_AE_ATTR_SADDR)
384 		memcpy (&ae_id.saddr, nl_addr_get_binary_addr (tmpl->saddr), sizeof (uint8_t) * nl_addr_get_len (tmpl->saddr));
385 
386 	if (tmpl->ce_mask & XFRM_AE_ATTR_FLAGS)
387 		ae_id.flags    = tmpl->flags;
388 
389 	if (tmpl->ce_mask & XFRM_AE_ATTR_REQID)
390 		ae_id.reqid    = tmpl->reqid;
391 
392 	msg = nlmsg_alloc_simple(cmd, flags);
393 	if (!msg)
394 		return -NLE_NOMEM;
395 
396 	if (nlmsg_append(msg, &ae_id, sizeof(ae_id), NLMSG_ALIGNTO) < 0)
397 		goto nla_put_failure;
398 
399 	if (tmpl->ce_mask & XFRM_AE_ATTR_MARK)
400 		NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrmnl_mark), &tmpl->mark);
401 
402 	if (tmpl->ce_mask & XFRM_AE_ATTR_LIFETIME)
403 		NLA_PUT (msg, XFRMA_LTIME_VAL, sizeof (struct xfrmnl_lifetime_cur), &tmpl->lifetime_cur);
404 
405 	if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_MAXAGE)
406 		NLA_PUT_U32 (msg, XFRMA_ETIMER_THRESH, tmpl->replay_maxage);
407 
408 	if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_MAXDIFF)
409 		NLA_PUT_U32 (msg, XFRMA_REPLAY_THRESH, tmpl->replay_maxdiff);
410 
411 	if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_STATE) {
412 		if (tmpl->replay_state_esn) {
413 			uint32_t len = sizeof (struct xfrm_replay_state_esn) + (sizeof (uint32_t) * tmpl->replay_state_esn->bmp_len);
414 			NLA_PUT (msg, XFRMA_REPLAY_ESN_VAL, len, tmpl->replay_state_esn);
415 		}
416 		else {
417 			NLA_PUT (msg, XFRMA_REPLAY_VAL, sizeof (struct xfrmnl_replay_state), &tmpl->replay_state);
418 		}
419 	}
420 
421 	*result = msg;
422 	return 0;
423 
424 nla_put_failure:
425 	nlmsg_free(msg);
426 	return -NLE_MSGSIZE;
427 }
428 
429 /**
430  * @name XFRM AE Update
431  * @{
432  */
433 
xfrmnl_ae_set(struct nl_sock * sk,struct xfrmnl_ae * ae,int flags)434 int xfrmnl_ae_set(struct nl_sock* sk, struct xfrmnl_ae* ae, int flags)
435 {
436 	int err;
437 	struct nl_msg *msg;
438 
439 	if ((err = build_xfrm_ae_message(ae, XFRM_MSG_NEWAE, flags|NLM_F_REPLACE, &msg)) < 0)
440 		return err;
441 
442 	err = nl_send_auto_complete(sk, msg);
443 	nlmsg_free(msg);
444 	if (err < 0)
445 		return err;
446 
447 	return nl_wait_for_ack(sk);
448 }
449 
450 /** @} */
451 
452 /**
453  * @name XFRM AE Object Allocation/Freeage
454  * @{
455  */
456 
xfrmnl_ae_alloc(void)457 struct xfrmnl_ae* xfrmnl_ae_alloc(void)
458 {
459 	return (struct xfrmnl_ae*) nl_object_alloc(&xfrm_ae_obj_ops);
460 }
461 
xfrmnl_ae_put(struct xfrmnl_ae * ae)462 void xfrmnl_ae_put(struct xfrmnl_ae* ae)
463 {
464 	nl_object_put((struct nl_object *) ae);
465 }
466 
467 /** @} */
468 
469 static struct nla_policy xfrm_ae_policy[XFRMA_MAX+1] = {
470 	[XFRMA_LTIME_VAL]       = { .minlen = sizeof(struct xfrm_lifetime_cur) },
471 	[XFRMA_REPLAY_VAL]      = { .minlen = sizeof(struct xfrm_replay_state) },
472 	[XFRMA_REPLAY_THRESH]   = { .type = NLA_U32 },
473 	[XFRMA_ETIMER_THRESH]   = { .type = NLA_U32 },
474 	[XFRMA_SRCADDR]         = { .minlen = sizeof(xfrm_address_t) },
475 	[XFRMA_MARK]            = { .minlen = sizeof(struct xfrm_mark) },
476 	[XFRMA_REPLAY_ESN_VAL]  = { .minlen = sizeof(struct xfrm_replay_state_esn) },
477 };
478 
xfrmnl_ae_parse(struct nlmsghdr * n,struct xfrmnl_ae ** result)479 int xfrmnl_ae_parse(struct nlmsghdr *n, struct xfrmnl_ae **result)
480 {
481 	struct xfrmnl_ae*    ae;
482 	struct nlattr           *tb[XFRMA_MAX + 1];
483 	struct xfrm_aevent_id*  ae_id;
484 	int err;
485 
486 	ae = xfrmnl_ae_alloc();
487 	if (!ae) {
488 		err = -NLE_NOMEM;
489 		goto errout;
490 	}
491 
492 	ae->ce_msgtype = n->nlmsg_type;
493 	ae_id = nlmsg_data(n);
494 
495 	err = nlmsg_parse(n, sizeof(struct xfrm_aevent_id), tb, XFRMA_MAX, xfrm_ae_policy);
496 	if (err < 0)
497 		goto errout;
498 
499 	ae->sa_id.daddr = nl_addr_build(ae_id->sa_id.family, &ae_id->sa_id.daddr, sizeof (ae_id->sa_id.daddr));
500 	ae->sa_id.family= ae_id->sa_id.family;
501 	ae->sa_id.spi   = ntohl(ae_id->sa_id.spi);
502 	ae->sa_id.proto = ae_id->sa_id.proto;
503 	ae->saddr       = nl_addr_build(ae_id->sa_id.family, &ae_id->saddr, sizeof (ae_id->saddr));
504 	ae->reqid       = ae_id->reqid;
505 	ae->flags       = ae_id->flags;
506 	ae->ce_mask |= (XFRM_AE_ATTR_DADDR | XFRM_AE_ATTR_FAMILY | XFRM_AE_ATTR_SPI |
507 					XFRM_AE_ATTR_PROTO | XFRM_AE_ATTR_SADDR | XFRM_AE_ATTR_REQID |
508 					XFRM_AE_ATTR_FLAGS);
509 
510 	if (tb[XFRMA_MARK]) {
511 		struct xfrm_mark* m =   nla_data(tb[XFRMA_MARK]);
512 		ae->mark.m  =   m->m;
513 		ae->mark.v  =   m->v;
514 		ae->ce_mask |= XFRM_AE_ATTR_MARK;
515 	}
516 
517 	if (tb[XFRMA_LTIME_VAL]) {
518 		struct xfrm_lifetime_cur* cur =   nla_data(tb[XFRMA_LTIME_VAL]);
519 		ae->lifetime_cur.bytes      =   cur->bytes;
520 		ae->lifetime_cur.packets    =   cur->packets;
521 		ae->lifetime_cur.add_time   =   cur->add_time;
522 		ae->lifetime_cur.use_time   =   cur->use_time;
523 		ae->ce_mask |= XFRM_AE_ATTR_LIFETIME;
524 	}
525 
526 	if (tb[XFRM_AE_ETHR]) {
527 		ae->replay_maxage       =   *(uint32_t*)nla_data(tb[XFRM_AE_ETHR]);
528 		ae->ce_mask |= XFRM_AE_ATTR_REPLAY_MAXAGE;
529 	}
530 
531 	if (tb[XFRM_AE_RTHR]) {
532 		ae->replay_maxdiff      =   *(uint32_t*)nla_data(tb[XFRM_AE_RTHR]);
533 		ae->ce_mask |= XFRM_AE_ATTR_REPLAY_MAXDIFF;
534 	}
535 
536 	if (tb[XFRMA_REPLAY_ESN_VAL]) {
537 		struct xfrm_replay_state_esn* esn =  nla_data (tb[XFRMA_REPLAY_ESN_VAL]);
538 		uint32_t len = sizeof (struct xfrmnl_replay_state_esn) +  (sizeof (uint32_t) * esn->bmp_len);
539 
540 		if ((ae->replay_state_esn = calloc (1, len)) == NULL) {
541 			err = -ENOMEM;
542 			goto errout;
543 		}
544 		ae->replay_state_esn->oseq       =  esn->oseq;
545 		ae->replay_state_esn->seq        =  esn->seq;
546 		ae->replay_state_esn->oseq_hi    =  esn->oseq_hi;
547 		ae->replay_state_esn->seq_hi     =  esn->seq_hi;
548 		ae->replay_state_esn->replay_window   =   esn->replay_window;
549 		ae->replay_state_esn->bmp_len    =   esn->bmp_len;
550 		memcpy (ae->replay_state_esn->bmp, esn->bmp, sizeof (uint32_t) * esn->bmp_len);
551 		ae->ce_mask |= XFRM_AE_ATTR_REPLAY_STATE;
552 	}
553 	else
554 	{
555 		struct xfrm_replay_state* replay_state = nla_data (tb[XFRMA_REPLAY_VAL]);
556 		ae->replay_state.oseq       =   replay_state->oseq;
557 		ae->replay_state.seq        =   replay_state->seq;
558 		ae->replay_state.bitmap     =   replay_state->bitmap;
559 		ae->ce_mask |= XFRM_AE_ATTR_REPLAY_STATE;
560 
561 		ae->replay_state_esn = NULL;
562 	}
563 
564 	*result = ae;
565 	return 0;
566 
567 errout:
568 	xfrmnl_ae_put(ae);
569 	return err;
570 }
571 
xfrm_ae_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * n,struct nl_parser_param * pp)572 static int xfrm_ae_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
573 				struct nlmsghdr *n, struct nl_parser_param *pp)
574 {
575 	struct xfrmnl_ae*    ae;
576 	int err;
577 
578 	if ((err = xfrmnl_ae_parse(n, &ae)) < 0)
579 		return err;
580 
581 	err = pp->pp_cb((struct nl_object *) ae, pp);
582 
583 	xfrmnl_ae_put(ae);
584 	return err;
585 }
586 
587 /**
588  * @name XFRM AE Get
589  * @{
590  */
591 
xfrmnl_ae_build_get_request(struct nl_addr * daddr,unsigned int spi,unsigned int protocol,unsigned int mark_mask,unsigned int mark_value,struct nl_msg ** result)592 int xfrmnl_ae_build_get_request(struct nl_addr* daddr, unsigned int spi, unsigned int protocol,
593                                 unsigned int mark_mask, unsigned int mark_value, struct nl_msg **result)
594 {
595 	struct nl_msg *msg;
596 	struct xfrm_aevent_id   ae_id;
597 	struct xfrmnl_mark   mark;
598 
599 	if (!daddr || !spi)
600 	{
601 		fprintf(stderr, "APPLICATION BUG: %s:%d:%s: A valid destination address, spi must be specified\n",
602 				__FILE__, __LINE__, __func__);
603 		assert(0);
604 		return -NLE_MISSING_ATTR;
605 	}
606 
607 	memset(&ae_id, 0, sizeof(ae_id));
608 	memcpy (&ae_id.sa_id.daddr, nl_addr_get_binary_addr (daddr), sizeof (uint8_t) * nl_addr_get_len (daddr));
609 	ae_id.sa_id.spi    = htonl(spi);
610 	ae_id.sa_id.family = nl_addr_get_family (daddr);
611 	ae_id.sa_id.proto  = protocol;
612 
613 	if (!(msg = nlmsg_alloc_simple(XFRM_MSG_GETAE, 0)))
614 		return -NLE_NOMEM;
615 
616 	if (nlmsg_append(msg, &ae_id, sizeof(ae_id), NLMSG_ALIGNTO) < 0)
617 		goto nla_put_failure;
618 
619 	mark.m  =   mark_mask;
620 	mark.v  =   mark_value;
621 	NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrmnl_mark), &mark);
622 
623 	*result = msg;
624 	return 0;
625 
626 nla_put_failure:
627 	nlmsg_free(msg);
628 	return -NLE_MSGSIZE;
629 }
630 
xfrmnl_ae_get_kernel(struct nl_sock * sock,struct nl_addr * daddr,unsigned int spi,unsigned int protocol,unsigned int mark_mask,unsigned int mark_value,struct xfrmnl_ae ** result)631 int xfrmnl_ae_get_kernel(struct nl_sock* sock, struct nl_addr* daddr, unsigned int spi, unsigned int protocol,
632                          unsigned int mark_mask, unsigned int mark_value, struct xfrmnl_ae** result)
633 {
634 	struct nl_msg *msg = NULL;
635 	struct nl_object *obj;
636 	int err;
637 
638 	if ((err = xfrmnl_ae_build_get_request(daddr, spi, protocol, mark_mask, mark_value, &msg)) < 0)
639 		return err;
640 
641 	err = nl_send_auto(sock, msg);
642 	nlmsg_free(msg);
643 	if (err < 0)
644 		return err;
645 
646 	if ((err = nl_pickup(sock, &xfrm_ae_msg_parser, &obj)) < 0)
647 		return err;
648 
649 	/* We have used xfrm_ae_msg_parser(), object is definitely a xfrm ae */
650 	*result = (struct xfrmnl_ae *) obj;
651 
652 	/* If an object has been returned, we also need to wait for the ACK */
653 	if (err == 0 && obj)
654 		nl_wait_for_ack(sock);
655 
656 	return 0;
657 }
658 
659 /** @} */
660 
661 /**
662  * @name Attributes
663  * @{
664  */
665 
__assign_addr(struct xfrmnl_ae * ae,struct nl_addr ** pos,struct nl_addr * new,int flag,int nocheck)666 static inline int __assign_addr(struct xfrmnl_ae* ae, struct nl_addr **pos,
667 					struct nl_addr *new, int flag, int nocheck)
668 {
669 	if (!nocheck) {
670 		if (ae->ce_mask & XFRM_AE_ATTR_FAMILY) {
671 			if (nl_addr_get_family (new) != ae->sa_id.family)
672 				return -NLE_AF_MISMATCH;
673 		} else {
674 			ae->sa_id.family = nl_addr_get_family (new);
675 			ae->ce_mask |= XFRM_AE_ATTR_FAMILY;
676 		}
677 	}
678 
679 	if (*pos)
680 		nl_addr_put(*pos);
681 
682 	nl_addr_get(new);
683 	*pos = new;
684 
685 	ae->ce_mask |= flag;
686 
687 	return 0;
688 }
689 
690 
xfrmnl_ae_get_daddr(struct xfrmnl_ae * ae)691 struct nl_addr* xfrmnl_ae_get_daddr (struct xfrmnl_ae* ae)
692 {
693 	if (ae->ce_mask & XFRM_AE_ATTR_DADDR)
694 		return ae->sa_id.daddr;
695 	else
696 		return NULL;
697 }
698 
xfrmnl_ae_set_daddr(struct xfrmnl_ae * ae,struct nl_addr * addr)699 int xfrmnl_ae_set_daddr (struct xfrmnl_ae* ae, struct nl_addr* addr)
700 {
701 	return __assign_addr(ae, &ae->sa_id.daddr, addr, XFRM_AE_ATTR_DADDR, 0);
702 }
703 
xfrmnl_ae_get_spi(struct xfrmnl_ae * ae)704 int xfrmnl_ae_get_spi (struct xfrmnl_ae* ae)
705 {
706 	if (ae->ce_mask & XFRM_AE_ATTR_SPI)
707 		return ae->sa_id.spi;
708 	else
709 		return -1;
710 }
711 
xfrmnl_ae_set_spi(struct xfrmnl_ae * ae,unsigned int spi)712 int xfrmnl_ae_set_spi (struct xfrmnl_ae* ae, unsigned int spi)
713 {
714 	ae->sa_id.spi = spi;
715 	ae->ce_mask |= XFRM_AE_ATTR_SPI;
716 
717 	return 0;
718 }
719 
xfrmnl_ae_get_family(struct xfrmnl_ae * ae)720 int xfrmnl_ae_get_family (struct xfrmnl_ae* ae)
721 {
722 	if (ae->ce_mask & XFRM_AE_ATTR_FAMILY)
723 		return ae->sa_id.family;
724 	else
725 		return -1;
726 }
727 
xfrmnl_ae_set_family(struct xfrmnl_ae * ae,unsigned int family)728 int xfrmnl_ae_set_family (struct xfrmnl_ae* ae, unsigned int family)
729 {
730 	ae->sa_id.family = family;
731 	ae->ce_mask |= XFRM_AE_ATTR_FAMILY;
732 
733 	return 0;
734 }
735 
xfrmnl_ae_get_proto(struct xfrmnl_ae * ae)736 int xfrmnl_ae_get_proto (struct xfrmnl_ae* ae)
737 {
738 	if (ae->ce_mask & XFRM_AE_ATTR_PROTO)
739 		return ae->sa_id.proto;
740 	else
741 		return -1;
742 }
743 
xfrmnl_ae_set_proto(struct xfrmnl_ae * ae,unsigned int protocol)744 int xfrmnl_ae_set_proto (struct xfrmnl_ae* ae, unsigned int protocol)
745 {
746 	ae->sa_id.proto = protocol;
747 	ae->ce_mask |= XFRM_AE_ATTR_PROTO;
748 
749 	return 0;
750 }
751 
xfrmnl_ae_get_saddr(struct xfrmnl_ae * ae)752 struct nl_addr* xfrmnl_ae_get_saddr (struct xfrmnl_ae* ae)
753 {
754 	if (ae->ce_mask & XFRM_AE_ATTR_SADDR)
755 		return ae->saddr;
756 	else
757 		return NULL;
758 }
759 
xfrmnl_ae_set_saddr(struct xfrmnl_ae * ae,struct nl_addr * addr)760 int xfrmnl_ae_set_saddr (struct xfrmnl_ae* ae, struct nl_addr* addr)
761 {
762 	return 	__assign_addr(ae, &ae->saddr, addr, XFRM_AE_ATTR_SADDR, 1);
763 }
764 
xfrmnl_ae_get_flags(struct xfrmnl_ae * ae)765 int xfrmnl_ae_get_flags (struct xfrmnl_ae* ae)
766 {
767 	if (ae->ce_mask & XFRM_AE_ATTR_FLAGS)
768 		return ae->flags;
769 	else
770 		return -1;
771 }
772 
xfrmnl_ae_set_flags(struct xfrmnl_ae * ae,unsigned int flags)773 int xfrmnl_ae_set_flags (struct xfrmnl_ae* ae, unsigned int flags)
774 {
775 	ae->flags = flags;
776 	ae->ce_mask |= XFRM_AE_ATTR_FLAGS;
777 
778 	return 0;
779 }
780 
xfrmnl_ae_get_reqid(struct xfrmnl_ae * ae)781 int xfrmnl_ae_get_reqid (struct xfrmnl_ae* ae)
782 {
783 	if (ae->ce_mask & XFRM_AE_ATTR_REQID)
784 		return ae->reqid;
785 	else
786 		return -1;
787 }
788 
xfrmnl_ae_set_reqid(struct xfrmnl_ae * ae,unsigned int reqid)789 int xfrmnl_ae_set_reqid (struct xfrmnl_ae* ae, unsigned int reqid)
790 {
791 	ae->reqid = reqid;
792 	ae->ce_mask |= XFRM_AE_ATTR_REQID;
793 
794 	return 0;
795 }
796 
xfrmnl_ae_get_mark(struct xfrmnl_ae * ae,unsigned int * mark_mask,unsigned int * mark_value)797 int xfrmnl_ae_get_mark (struct xfrmnl_ae* ae, unsigned int* mark_mask, unsigned int* mark_value)
798 {
799 	if (mark_mask == NULL || mark_value == NULL)
800 		return -1;
801 
802 	if (ae->ce_mask & XFRM_AE_ATTR_MARK)
803 	{
804 		*mark_mask  =   ae->mark.m;
805 		*mark_value  =   ae->mark.v;
806 
807 		return 0;
808 	}
809 	else
810 		return -1;
811 }
812 
xfrmnl_ae_set_mark(struct xfrmnl_ae * ae,unsigned int value,unsigned int mask)813 int xfrmnl_ae_set_mark (struct xfrmnl_ae* ae, unsigned int value, unsigned int mask)
814 {
815 	ae->mark.v  = value;
816 	ae->mark.m  = mask;
817 	ae->ce_mask |= XFRM_AE_ATTR_MARK;
818 
819 	return 0;
820 }
821 
xfrmnl_ae_get_curlifetime(struct xfrmnl_ae * ae,unsigned long long int * curr_bytes,unsigned long long int * curr_packets,unsigned long long int * curr_add_time,unsigned long long int * curr_use_time)822 int xfrmnl_ae_get_curlifetime (struct xfrmnl_ae* ae, unsigned long long int* curr_bytes,
823                                unsigned long long int* curr_packets, unsigned long long int* curr_add_time,
824                                unsigned long long int* curr_use_time)
825 {
826 	if (curr_bytes == NULL || curr_packets == NULL || curr_add_time == NULL || curr_use_time == NULL)
827 		return -1;
828 
829 	if (ae->ce_mask & XFRM_AE_ATTR_LIFETIME)
830 	{
831 		*curr_bytes     =   ae->lifetime_cur.bytes;
832 		*curr_packets   =   ae->lifetime_cur.packets;
833 		*curr_add_time  =   ae->lifetime_cur.add_time;
834 		*curr_use_time  =   ae->lifetime_cur.use_time;
835 
836 		return 0;
837 	}
838 	else
839 		return -1;
840 }
841 
xfrmnl_ae_set_curlifetime(struct xfrmnl_ae * ae,unsigned long long int curr_bytes,unsigned long long int curr_packets,unsigned long long int curr_add_time,unsigned long long int curr_use_time)842 int xfrmnl_ae_set_curlifetime (struct xfrmnl_ae* ae, unsigned long long int curr_bytes,
843                                unsigned long long int curr_packets, unsigned long long int curr_add_time,
844                                unsigned long long int curr_use_time)
845 {
846 	ae->lifetime_cur.bytes = curr_bytes;
847 	ae->lifetime_cur.packets = curr_packets;
848 	ae->lifetime_cur.add_time = curr_add_time;
849 	ae->lifetime_cur.use_time = curr_use_time;
850 	ae->ce_mask |= XFRM_AE_ATTR_LIFETIME;
851 
852 	return 0;
853 }
854 
xfrmnl_ae_get_replay_maxage(struct xfrmnl_ae * ae)855 int xfrmnl_ae_get_replay_maxage (struct xfrmnl_ae* ae)
856 {
857 	if (ae->ce_mask & XFRM_AE_ATTR_REPLAY_MAXAGE)
858 		return ae->replay_maxage;
859 	else
860 		return -1;
861 }
862 
xfrmnl_ae_set_replay_maxage(struct xfrmnl_ae * ae,unsigned int replay_maxage)863 int xfrmnl_ae_set_replay_maxage (struct xfrmnl_ae* ae, unsigned int replay_maxage)
864 {
865 	ae->replay_maxage  = replay_maxage;
866 	ae->ce_mask |= XFRM_AE_ATTR_REPLAY_MAXAGE;
867 
868 	return 0;
869 }
870 
xfrmnl_ae_get_replay_maxdiff(struct xfrmnl_ae * ae)871 int xfrmnl_ae_get_replay_maxdiff (struct xfrmnl_ae* ae)
872 {
873 	if (ae->ce_mask & XFRM_AE_ATTR_REPLAY_MAXDIFF)
874 		return ae->replay_maxdiff;
875 	else
876 		return -1;
877 }
878 
xfrmnl_ae_set_replay_maxdiff(struct xfrmnl_ae * ae,unsigned int replay_maxdiff)879 int xfrmnl_ae_set_replay_maxdiff (struct xfrmnl_ae* ae, unsigned int replay_maxdiff)
880 {
881 	ae->replay_maxdiff  = replay_maxdiff;
882 	ae->ce_mask |= XFRM_AE_ATTR_REPLAY_MAXDIFF;
883 
884 	return 0;
885 }
886 
xfrmnl_ae_get_replay_state(struct xfrmnl_ae * ae,unsigned int * oseq,unsigned int * seq,unsigned int * bmp)887 int xfrmnl_ae_get_replay_state (struct xfrmnl_ae* ae, unsigned int* oseq, unsigned int* seq, unsigned int* bmp)
888 {
889 	if (ae->ce_mask & XFRM_AE_ATTR_REPLAY_STATE)
890 	{
891 		if (ae->replay_state_esn == NULL)
892 		{
893 			*oseq   =   ae->replay_state.oseq;
894 			*seq    =   ae->replay_state.seq;
895 			*bmp    =   ae->replay_state.bitmap;
896 
897 			return 0;
898 		}
899 		else
900 		{
901 			return -1;
902 		}
903 	}
904 	else
905 		return -1;
906 }
907 
xfrmnl_ae_set_replay_state(struct xfrmnl_ae * ae,unsigned int oseq,unsigned int seq,unsigned int bitmap)908 int xfrmnl_ae_set_replay_state (struct xfrmnl_ae* ae, unsigned int oseq, unsigned int seq, unsigned int bitmap)
909 {
910 	ae->replay_state.oseq = oseq;
911 	ae->replay_state.seq = seq;
912 	ae->replay_state.bitmap = bitmap;
913 	ae->ce_mask |= XFRM_AE_ATTR_REPLAY_STATE;
914 
915 	return 0;
916 }
917 
xfrmnl_ae_get_replay_state_esn(struct xfrmnl_ae * ae,unsigned int * oseq,unsigned int * seq,unsigned int * oseq_hi,unsigned int * seq_hi,unsigned int * replay_window,unsigned int * bmp_len,unsigned int * bmp)918 int xfrmnl_ae_get_replay_state_esn(struct xfrmnl_ae* ae, unsigned int* oseq, unsigned int* seq, unsigned int* oseq_hi,
919                                    unsigned int* seq_hi, unsigned int* replay_window, unsigned int* bmp_len, unsigned int* bmp)
920 {
921 	if (ae->ce_mask & XFRM_AE_ATTR_REPLAY_STATE)
922 	{
923 		if (ae->replay_state_esn)
924 		{
925 			*oseq   =   ae->replay_state_esn->oseq;
926 			*seq    =   ae->replay_state_esn->seq;
927 			*oseq_hi=   ae->replay_state_esn->oseq_hi;
928 			*seq_hi =   ae->replay_state_esn->seq_hi;
929 			*replay_window  =   ae->replay_state_esn->replay_window;
930 			*bmp_len        =   ae->replay_state_esn->bmp_len; // In number of 32 bit words
931 			memcpy (bmp, ae->replay_state_esn->bmp, ae->replay_state_esn->bmp_len * sizeof (uint32_t));
932 
933 			return 0;
934 		}
935 		else
936 		{
937 			return -1;
938 		}
939 	}
940 	else
941 		return -1;
942 }
943 
xfrmnl_ae_set_replay_state_esn(struct xfrmnl_ae * ae,unsigned int oseq,unsigned int seq,unsigned int oseq_hi,unsigned int seq_hi,unsigned int replay_window,unsigned int bmp_len,unsigned int * bmp)944 int xfrmnl_ae_set_replay_state_esn(struct xfrmnl_ae* ae, unsigned int oseq, unsigned int seq,
945                                    unsigned int oseq_hi, unsigned int seq_hi, unsigned int replay_window,
946                                    unsigned int bmp_len, unsigned int* bmp)
947 {
948 	/* Free the old replay ESN state and allocate new one */
949 	if (ae->replay_state_esn)
950 		free (ae->replay_state_esn);
951 
952 	if ((ae->replay_state_esn = calloc (1, sizeof (struct xfrmnl_replay_state_esn) + sizeof (uint32_t) * bmp_len)) == NULL)
953 		return -1;
954 
955 	ae->replay_state_esn->oseq = oseq;
956 	ae->replay_state_esn->seq = seq;
957 	ae->replay_state_esn->oseq_hi = oseq_hi;
958 	ae->replay_state_esn->seq_hi = seq_hi;
959 	ae->replay_state_esn->replay_window = replay_window;
960 	ae->replay_state_esn->bmp_len = bmp_len; // In number of 32 bit words
961 	memcpy (ae->replay_state_esn->bmp, bmp, bmp_len * sizeof (uint32_t));
962 	ae->ce_mask |= XFRM_AE_ATTR_REPLAY_STATE;
963 
964 	return 0;
965 }
966 
967 /** @} */
968 
969 static struct nl_object_ops xfrm_ae_obj_ops = {
970 	.oo_name        =   "xfrm/ae",
971 	.oo_size        =   sizeof(struct xfrmnl_ae),
972 	.oo_free_data   =   xfrm_ae_free_data,
973 	.oo_clone       =   xfrm_ae_clone,
974 	.oo_dump        =   {
975 	                        [NL_DUMP_LINE]      =   xfrm_ae_dump_line,
976 	                        [NL_DUMP_DETAILS]   =   xfrm_ae_dump_details,
977 	                        [NL_DUMP_STATS]     =   xfrm_ae_dump_stats,
978 	                    },
979 	.oo_compare     =   xfrm_ae_compare,
980 	.oo_attrs2str   =   xfrm_ae_attrs2str,
981 	.oo_id_attrs    =   (XFRM_AE_ATTR_DADDR | XFRM_AE_ATTR_SPI | XFRM_AE_ATTR_PROTO),
982 };
983 
984 /** @} */
985 
986