libnl  3.5.0
ae.c
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 
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 
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 
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 
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 
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 
285 int xfrmnl_ae_str2flag(const char *name)
286 {
287  return __str2flags(name, ae_flags, ARRAY_SIZE(ae_flags));
288 }
289 /** @} */
290 
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 
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 
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 
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 
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 
457 struct xfrmnl_ae* xfrmnl_ae_alloc(void)
458 {
459  return (struct xfrmnl_ae*) nl_object_alloc(&xfrm_ae_obj_ops);
460 }
461 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
Definition: nl.c:1248
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
Definition: addr.c:494
Dump object briefly on one line.
Definition: types.h:22
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition: msg.c:565
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
parse attributes of a netlink message
Definition: msg.c:215
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
Definition: addr.c:586
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
Definition: msg.c:107
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
Definition: object.c:55
Attribute validation policy.
Definition: attr.h:69
struct nl_addr * nl_addr_build(int family, const void *buf, size_t size)
Allocate abstract address based on a binary address.
Definition: addr.c:218
int nl_pickup(struct nl_sock *sk, int(*parser)(struct nl_cache_ops *, struct sockaddr_nl *, struct nlmsghdr *, struct nl_parser_param *), struct nl_object **result)
Pickup netlink answer, parse is and return object.
Definition: nl.c:1179
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
Definition: addr.c:524
Dump all attributes but no statistics.
Definition: types.h:23
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition: attr.h:165
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:121
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:236
uint16_t minlen
Minimal length of payload required.
Definition: attr.h:74
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
Definition: msg.c:449
int nl_wait_for_ack(struct nl_sock *sk)
Wait for ACK.
Definition: nl.c:1113
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition: object.c:216
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition: addr.c:540
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
Definition: msg.c:348
32 bit integer
Definition: attr.h:43
Dumping parameters.
Definition: types.h:33
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:962
int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg)
Finalize and transmit Netlink message.
Definition: nl.c:517
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
Definition: addr.c:954
Dump all attributes including statistics.
Definition: types.h:24
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
Definition: addr.c:942
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition: addr.c:1000
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.
Definition: addr.c:894