]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/sa/child_sa.c
cirrus: Explicitly install tpm2-tss-sys package on Alpine
[thirdparty/strongswan.git] / src / libcharon / sa / child_sa.c
CommitLineData
3ebebc5e 1/*
13771206 2 * Copyright (C) 2006-2023 Tobias Brunner
1003cf23 3 * Copyright (C) 2016 Andreas Steffen
a985db3f 4 * Copyright (C) 2005-2008 Martin Willi
d4aad554 5 * Copyright (C) 2006 Daniel Roethlisberger
c71d53ba 6 * Copyright (C) 2005 Jan Hutter
19ef2aec
TB
7 *
8 * Copyright (C) secunet Security Networks AG
3ebebc5e
MW
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * for more details.
19 */
20
60356f33 21#define _GNU_SOURCE
b92eef28 22#include "child_sa.h"
3ebebc5e 23
a095243f 24#include <stdio.h>
4c23a8c9 25#include <string.h>
e13389a7 26#include <time.h>
4c23a8c9 27
aeda79ff 28#include <daemon.h>
2745ae26 29#include <collections/array.h>
aeda79ff 30
a985db3f 31ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
60356f33
MW
32 "CREATED",
33 "ROUTED",
ea625fab 34 "INSTALLING",
60356f33 35 "INSTALLED",
ad3af574 36 "UPDATING",
60356f33 37 "REKEYING",
70728eb1 38 "REKEYED",
013857ad 39 "RETRYING",
60356f33 40 "DELETING",
16898026 41 "DELETED",
a985db3f 42 "DESTROYING",
60356f33 43);
bcb95ced 44
2c116ef5 45ENUM_FLAGS(child_sa_outbound_state_names, CHILD_OUTBOUND_REGISTERED, CHILD_OUTBOUND_POLICIES,
927103ec 46 "NONE",
afbea8ce 47 "REGISTERED",
2c116ef5
TB
48 "SA",
49 "POLICIES",
afbea8ce
TB
50);
51
3ebebc5e
MW
52typedef struct private_child_sa_t private_child_sa_t;
53
54/**
7b8bae99 55 * Private data of a child_sa_t object.
3ebebc5e
MW
56 */
57struct private_child_sa_t {
58 /**
144f676c 59 * Public interface of child_sa_t.
3ebebc5e
MW
60 */
61 child_sa_t public;
7daf5226 62
80853d84
MW
63 /**
64 * address of us
65 */
66 host_t *my_addr;
7daf5226 67
3efbf983 68 /**
80853d84 69 * address of remote
3efbf983 70 */
80853d84 71 host_t *other_addr;
7daf5226 72
3efbf983 73 /**
80853d84 74 * our actually used SPI, 0 if unused
3efbf983 75 */
b12c53ce 76 uint32_t my_spi;
7daf5226 77
aeda79ff 78 /**
80853d84 79 * others used SPI, 0 if unused
aeda79ff 80 */
b12c53ce 81 uint32_t other_spi;
7daf5226 82
8dfbe71b 83 /**
80853d84 84 * our Compression Parameter Index (CPI) used, 0 if unused
8dfbe71b 85 */
b12c53ce 86 uint16_t my_cpi;
7daf5226 87
8dfbe71b 88 /**
80853d84 89 * others Compression Parameter Index (CPI) used, 0 if unused
8dfbe71b 90 */
b12c53ce 91 uint16_t other_cpi;
7daf5226 92
5d187bd2 93 /**
2745ae26 94 * Array for local traffic selectors
5d187bd2 95 */
2745ae26 96 array_t *my_ts;
7daf5226 97
80853d84 98 /**
2745ae26 99 * Array for remote traffic selectors
80853d84 100 */
2745ae26 101 array_t *other_ts;
7daf5226 102
8a3a389e
TB
103 /**
104 * Outbound encryption key cached during a rekeying
105 */
106 chunk_t encr_r;
107
108 /**
109 * Outbound integrity key cached during a rekeying
110 */
111 chunk_t integ_r;
112
639af09b
TB
113 /**
114 * Whether the registered outbound SA was created as initiator
115 */
116 bool initiator;
117
8a3a389e
TB
118 /**
119 * Whether the outbound SA has only been registered yet during a rekeying
120 */
afbea8ce 121 child_sa_outbound_state_t outbound_state;
8a3a389e 122
9118fd39
TB
123 /**
124 * Whether the inbound SA has been installed
125 */
126 bool inbound_installed;
127
8a3a389e
TB
128 /**
129 * Whether the peer supports TFCv3
130 */
131 bool tfcv3;
132
cad13450
TB
133 /**
134 * The outbound SPI of the CHILD_SA that replaced this one during a rekeying
135 */
136 uint32_t rekey_spi;
137
c0593835 138 /**
80853d84 139 * Protocol used to protect this SA, ESP|AH
c0593835 140 */
80853d84 141 protocol_id_t protocol;
7daf5226 142
3c7e72f5 143 /**
80853d84 144 * reqid used for this child_sa
3c7e72f5 145 */
b12c53ce 146 uint32_t reqid;
7daf5226 147
0da97f50
MW
148 /**
149 * Did we allocate/confirm and must release the reqid?
150 */
151 bool reqid_allocated;
152
3665adef
TB
153 /**
154 * Is the reqid statically configured
155 */
156 bool static_reqid;
157
ad1b5345 158 /**
4ec397b8
MW
159 * Unique CHILD_SA identifier
160 */
b12c53ce 161 uint32_t unique_id;
4ec397b8 162
ad1b5345 163 /**
b3ab7a48 164 * Whether FWD policies in the outbound direction should be installed
ad1b5345
TB
165 */
166 bool policies_fwd_out;
167
a6014d99
TB
168 /**
169 * Inbound interface ID
170 */
171 uint32_t if_id_in;
172
173 /**
174 * Outbound interface ID
175 */
176 uint32_t if_id_out;
177
ee26c537
AS
178 /**
179 * inbound mark used for this child_sa
180 */
181 mark_t mark_in;
182
183 /**
184 * outbound mark used for this child_sa
185 */
186 mark_t mark_out;
187
139d6558
TB
188 /**
189 * Security label
190 */
191 sec_label_t *label;
192
a2a3fb3e 193 /**
6e10aead 194 * absolute time when rekeying is scheduled
a2a3fb3e 195 */
6e10aead 196 time_t rekey_time;
7daf5226 197
e70d5576 198 /**
6e10aead 199 * absolute time when the SA expires
e70d5576 200 */
6e10aead 201 time_t expire_time;
7daf5226 202
763e0353
MW
203 /**
204 * absolute time when SA has been installed
205 */
206 time_t install_time;
207
bcb95ced
MW
208 /**
209 * state of the CHILD_SA
210 */
211 child_sa_state_t state;
fff4ee8a 212
c8f7a114
TB
213 /**
214 * TRUE if this CHILD_SA is used to install trap policies
215 */
216 bool trap;
217
1239c6f4 218 /**
fc2d1c42 219 * Specifies if UDP encapsulation is enabled (NAT traversal)
1239c6f4 220 */
fc2d1c42 221 bool encap;
7daf5226 222
d4aad554
TB
223 /**
224 * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
225 */
226 ipcomp_transform_t ipcomp;
7daf5226 227
7652be89
MW
228 /**
229 * mode this SA uses, tunnel/transport
230 */
a341a68f 231 ipsec_mode_t mode;
7daf5226 232
4c401ea2
MW
233 /**
234 * Action to enforce if peer closes the CHILD_SA
235 */
236 action_t close_action;
237
238 /**
239 * Action to enforce if peer is considered dead
240 */
241 action_t dpd_action;
242
80853d84 243 /**
7b3814f7
MW
244 * selected proposal
245 */
246 proposal_t *proposal;
7daf5226 247
c60c7694 248 /**
e0fe7651 249 * config used to create this child
c60c7694 250 */
e0fe7651 251 child_cfg_t *config;
3f720dc7
AS
252
253 /**
254 * time of last use in seconds (inbound)
255 */
c99458e9 256 time_t my_usetime;
3f720dc7
AS
257
258 /**
259 * time of last use in seconds (outbound)
260 */
c99458e9 261 time_t other_usetime;
3f720dc7
AS
262
263 /**
264 * last number of inbound bytes
265 */
b12c53ce 266 uint64_t my_usebytes;
3f720dc7
AS
267
268 /**
269 * last number of outbound bytes
270 */
b12c53ce 271 uint64_t other_usebytes;
7eeeb1c7
MW
272
273 /**
274 * last number of inbound packets
275 */
b12c53ce 276 uint64_t my_usepackets;
7eeeb1c7
MW
277
278 /**
ba5b5f03 279 * last number of outbound packets
7eeeb1c7 280 */
b12c53ce 281 uint64_t other_usepackets;
3ebebc5e
MW
282};
283
9f166d9a 284/**
ea43f8ff 285 * Convert an IKEv2 specific protocol identifier to the IP protocol identifier
9f166d9a 286 */
b12c53ce 287static inline uint8_t proto_ike2ip(protocol_id_t protocol)
9f166d9a
TB
288{
289 switch (protocol)
290 {
291 case PROTO_ESP:
292 return IPPROTO_ESP;
293 case PROTO_AH:
294 return IPPROTO_AH;
295 default:
296 return protocol;
297 }
298}
299
ea43f8ff
TB
300/**
301 * Returns the mark to use on the inbound SA
302 */
303static inline mark_t mark_in_sa(private_child_sa_t *this)
304{
305 if (this->config->has_option(this->config, OPT_MARK_IN_SA))
306 {
307 return this->mark_in;
308 }
309 return (mark_t){};
310}
311
139d6558
TB
312/**
313 * Possible uses for security labels
314 */
315typedef enum {
316 LABEL_USE_REQID,
317 LABEL_USE_POLICY,
318 LABEL_USE_SA,
319} label_use_t;
320
321/**
322 * Returns the security label for either policies, SAs or reqids.
323 */
324static inline sec_label_t *label_for(private_child_sa_t *this, label_use_t use)
325{
326 /* For SELinux we use the configured label for policies and reqid but the
327 * negotiated one for the SAs. That's because the label on the policies is
328 * usually a generic one that matches specific labels on flows, which will
329 * trigger an acquire if no matching SA with that label exists yet.
330 * When that SA is later installed, we want to avoid having to install
331 * policies in the kernel that will never get used, so we use the configured
332 * label again.
333 * Note that while the labels don't have to be equal, they are both either
334 * NULL or defined.
335 */
336 if (this->config->get_label_mode(this->config) == SEC_LABEL_MODE_SELINUX)
337 {
338 switch (use)
339 {
340 case LABEL_USE_REQID:
341 case LABEL_USE_POLICY:
342 return this->config->get_label(this->config);
343 case LABEL_USE_SA:
344 return this->label;
345 }
346 }
347 /* for the simple label mode we don't pass labels to the kernel, so we don't
348 * use it to acquire unique reqids either */
349 return NULL;
350}
351
9d941742
TB
352METHOD(child_sa_t, get_name, char*,
353 private_child_sa_t *this)
9be547c0 354{
e0fe7651 355 return this->config->get_name(this->config);
9be547c0
MW
356}
357
b12c53ce 358METHOD(child_sa_t, get_reqid, uint32_t,
9d941742 359 private_child_sa_t *this)
32b6500f
MW
360{
361 return this->reqid;
362}
3aaf7908 363
ff269f7f
TB
364METHOD(child_sa_t, get_reqid_ref, uint32_t,
365 private_child_sa_t *this)
366{
367 if ((this->reqid_allocated || (!this->static_reqid && this->reqid)) &&
368 charon->kernel->ref_reqid(charon->kernel, this->reqid) == SUCCESS)
369 {
370 return this->reqid;
371 }
372 return 0;
373}
374
b12c53ce 375METHOD(child_sa_t, get_unique_id, uint32_t,
4ec397b8
MW
376 private_child_sa_t *this)
377{
378 return this->unique_id;
379}
380
9d941742
TB
381METHOD(child_sa_t, get_config, child_cfg_t*,
382 private_child_sa_t *this)
3aaf7908
MW
383{
384 return this->config;
385}
386
9d941742
TB
387METHOD(child_sa_t, set_state, void,
388 private_child_sa_t *this, child_sa_state_t state)
3aaf7908 389{
859dae25
TB
390 if (this->state != state)
391 {
392 DBG2(DBG_CHD, "CHILD_SA %s{%d} state change: %N => %N",
393 get_name(this), this->unique_id,
394 child_sa_state_names, this->state,
395 child_sa_state_names, state);
396 charon->bus->child_state_change(charon->bus, &this->public, state);
397 this->state = state;
398 }
3aaf7908
MW
399}
400
9d941742
TB
401METHOD(child_sa_t, get_state, child_sa_state_t,
402 private_child_sa_t *this)
3aaf7908
MW
403{
404 return this->state;
405}
406
afbea8ce
TB
407METHOD(child_sa_t, get_outbound_state, child_sa_outbound_state_t,
408 private_child_sa_t *this)
409{
410 return this->outbound_state;
411}
412
b12c53ce 413METHOD(child_sa_t, get_spi, uint32_t,
9d941742 414 private_child_sa_t *this, bool inbound)
8d77edde 415{
80853d84 416 return inbound ? this->my_spi : this->other_spi;
8d77edde
MW
417}
418
b12c53ce 419METHOD(child_sa_t, get_cpi, uint16_t,
9d941742 420 private_child_sa_t *this, bool inbound)
66da78b4 421{
80853d84 422 return inbound ? this->my_cpi : this->other_cpi;
66da78b4
AS
423}
424
9d941742
TB
425METHOD(child_sa_t, get_protocol, protocol_id_t,
426 private_child_sa_t *this)
8d77edde
MW
427{
428 return this->protocol;
429}
32b6500f 430
9d941742
TB
431METHOD(child_sa_t, set_protocol, void,
432 private_child_sa_t *this, protocol_id_t protocol)
3aaf7908
MW
433{
434 this->protocol = protocol;
435}
436
9d941742
TB
437METHOD(child_sa_t, get_mode, ipsec_mode_t,
438 private_child_sa_t *this)
80853d84
MW
439{
440 return this->mode;
441}
442
9d941742
TB
443METHOD(child_sa_t, set_mode, void,
444 private_child_sa_t *this, ipsec_mode_t mode)
3aaf7908
MW
445{
446 this->mode = mode;
447}
448
9d941742
TB
449METHOD(child_sa_t, has_encap, bool,
450 private_child_sa_t *this)
82d20c05
MW
451{
452 return this->encap;
453}
454
9d941742
TB
455METHOD(child_sa_t, get_ipcomp, ipcomp_transform_t,
456 private_child_sa_t *this)
82d20c05
MW
457{
458 return this->ipcomp;
459}
460
9d941742
TB
461METHOD(child_sa_t, set_ipcomp, void,
462 private_child_sa_t *this, ipcomp_transform_t ipcomp)
bcb95ced 463{
3aaf7908 464 this->ipcomp = ipcomp;
bcb95ced
MW
465}
466
9d941742
TB
467METHOD(child_sa_t, set_close_action, void,
468 private_child_sa_t *this, action_t action)
4c401ea2
MW
469{
470 this->close_action = action;
471}
472
9d941742
TB
473METHOD(child_sa_t, get_close_action, action_t,
474 private_child_sa_t *this)
4c401ea2
MW
475{
476 return this->close_action;
477}
478
9d941742
TB
479METHOD(child_sa_t, set_dpd_action, void,
480 private_child_sa_t *this, action_t action)
4c401ea2
MW
481{
482 this->dpd_action = action;
483}
484
9d941742
TB
485METHOD(child_sa_t, get_dpd_action, action_t,
486 private_child_sa_t *this)
4c401ea2
MW
487{
488 return this->dpd_action;
489}
490
9d941742
TB
491METHOD(child_sa_t, get_proposal, proposal_t*,
492 private_child_sa_t *this)
c60c7694 493{
3aaf7908
MW
494 return this->proposal;
495}
496
9d941742
TB
497METHOD(child_sa_t, set_proposal, void,
498 private_child_sa_t *this, proposal_t *proposal)
3aaf7908 499{
a2cb2c9c 500 this->proposal = proposal->clone(proposal, 0);
3aaf7908
MW
501}
502
553bb787
MW
503METHOD(child_sa_t, create_ts_enumerator, enumerator_t*,
504 private_child_sa_t *this, bool local)
3aaf7908 505{
553bb787
MW
506 if (local)
507 {
2745ae26 508 return array_create_enumerator(this->my_ts);
553bb787 509 }
2745ae26 510 return array_create_enumerator(this->other_ts);
c60c7694
MW
511}
512
1df106bf
MW
513typedef struct policy_enumerator_t policy_enumerator_t;
514
515/**
516 * Private policy enumerator
517 */
518struct policy_enumerator_t {
519 /** implements enumerator_t */
520 enumerator_t public;
521 /** enumerator over own TS */
522 enumerator_t *mine;
523 /** enumerator over others TS */
524 enumerator_t *other;
2745ae26
MW
525 /** array of others TS, to recreate enumerator */
526 array_t *array;
6df2837a
MW
527 /** currently enumerating TS for "me" side */
528 traffic_selector_t *ts;
1df106bf
MW
529};
530
9d941742 531METHOD(enumerator_t, policy_enumerate, bool,
95a63bf2 532 policy_enumerator_t *this, va_list args)
1df106bf 533{
95a63bf2
TB
534 traffic_selector_t *other_ts, **my_out, **other_out;
535
536 VA_ARGS_VGET(args, my_out, other_out);
7daf5226 537
6df2837a 538 while (this->ts || this->mine->enumerate(this->mine, &this->ts))
1df106bf 539 {
6df2837a
MW
540 if (!this->other->enumerate(this->other, &other_ts))
541 { /* end of others list, restart with new of mine */
542 this->other->destroy(this->other);
2745ae26 543 this->other = array_create_enumerator(this->array);
6df2837a
MW
544 this->ts = NULL;
545 continue;
546 }
547 if (this->ts->get_type(this->ts) != other_ts->get_type(other_ts))
548 { /* family mismatch */
549 continue;
550 }
551 if (this->ts->get_protocol(this->ts) &&
552 other_ts->get_protocol(other_ts) &&
553 this->ts->get_protocol(this->ts) != other_ts->get_protocol(other_ts))
554 { /* protocol mismatch */
555 continue;
1df106bf 556 }
a6e0f14f
TB
557 if (my_out)
558 {
559 *my_out = this->ts;
560 }
561 if (other_out)
562 {
563 *other_out = other_ts;
564 }
6df2837a 565 return TRUE;
1df106bf
MW
566 }
567 return FALSE;
568}
569
9d941742
TB
570METHOD(enumerator_t, policy_destroy, void,
571 policy_enumerator_t *this)
1df106bf
MW
572{
573 this->mine->destroy(this->mine);
574 this->other->destroy(this->other);
575 free(this);
576}
577
8f4cfe96
TB
578/**
579 * Create an enumerator over two lists of traffic selectors, returning all the
580 * pairs of traffic selectors from the first and second list.
581 */
582static enumerator_t *create_policy_enumerator_internal(array_t *my_ts,
583 array_t *other_ts)
1df106bf 584{
9d941742 585 policy_enumerator_t *e;
7daf5226 586
9d941742
TB
587 INIT(e,
588 .public = {
95a63bf2
TB
589 .enumerate = enumerator_enumerate_default,
590 .venumerate = _policy_enumerate,
9d941742
TB
591 .destroy = _policy_destroy,
592 },
8f4cfe96
TB
593 .mine = array_create_enumerator(my_ts),
594 .other = array_create_enumerator(other_ts),
595 .array = other_ts,
9d941742
TB
596 .ts = NULL,
597 );
7daf5226 598
1df106bf
MW
599 return &e->public;
600}
601
8f4cfe96
TB
602METHOD(child_sa_t, create_policy_enumerator, enumerator_t*,
603 private_child_sa_t *this)
604{
605 return create_policy_enumerator_internal(this->my_ts, this->other_ts);
606}
607
dd83c6d4
TB
608/**
609 * update the cached usebytes
610 * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs
611 * are available, and NOT_SUPPORTED if the kernel interface does not support
99dd4291 612 * querying the usebytes.
dd83c6d4 613 */
c3a78360 614static status_t update_usebytes(private_child_sa_t *this, bool inbound)
dd83c6d4
TB
615{
616 status_t status = FAILED;
b12c53ce 617 uint64_t bytes, packets;
c99458e9 618 time_t time;
7daf5226 619
dd83c6d4
TB
620 if (inbound)
621 {
9118fd39 622 if (this->my_spi && this->inbound_installed)
dd83c6d4 623 {
89da06ac
TB
624 kernel_ipsec_sa_id_t id = {
625 .src = this->other_addr,
626 .dst = this->my_addr,
627 .spi = this->my_spi,
628 .proto = proto_ike2ip(this->protocol),
ea43f8ff 629 .mark = mark_in_sa(this),
a6014d99 630 .if_id = this->if_id_in,
89da06ac
TB
631 };
632 kernel_ipsec_query_sa_t query = {};
633
634 status = charon->kernel->query_sa(charon->kernel, &id, &query,
635 &bytes, &packets, &time);
dd83c6d4
TB
636 if (status == SUCCESS)
637 {
638 if (bytes > this->my_usebytes)
639 {
640 this->my_usebytes = bytes;
7eeeb1c7 641 this->my_usepackets = packets;
5c12700f
MW
642 if (time)
643 {
644 this->my_usetime = time;
645 }
dd83c6d4 646 }
1042b919
TE
647 else
648 {
649 status = FAILED;
650 }
dd83c6d4
TB
651 }
652 }
653 }
654 else
655 {
2c116ef5 656 if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
dd83c6d4 657 {
89da06ac
TB
658 kernel_ipsec_sa_id_t id = {
659 .src = this->my_addr,
660 .dst = this->other_addr,
661 .spi = this->other_spi,
662 .proto = proto_ike2ip(this->protocol),
663 .mark = this->mark_out,
a6014d99 664 .if_id = this->if_id_out,
89da06ac
TB
665 };
666 kernel_ipsec_query_sa_t query = {};
667
668 status = charon->kernel->query_sa(charon->kernel, &id, &query,
669 &bytes, &packets, &time);
dd83c6d4
TB
670 if (status == SUCCESS)
671 {
672 if (bytes > this->other_usebytes)
673 {
674 this->other_usebytes = bytes;
7eeeb1c7 675 this->other_usepackets = packets;
5c12700f
MW
676 if (time)
677 {
678 this->other_usetime = time;
679 }
dd83c6d4 680 }
1042b919
TE
681 else
682 {
683 status = FAILED;
684 }
dd83c6d4
TB
685 }
686 }
687 }
688 return status;
689}
690
a3ce4bc2 691/**
c3a78360 692 * updates the cached usetime
a3ce4bc2 693 */
5c12700f 694static bool update_usetime(private_child_sa_t *this, bool inbound)
a3ce4bc2 695{
1df106bf 696 enumerator_t *enumerator;
6e10aead 697 traffic_selector_t *my_ts, *other_ts;
d7083b65 698 time_t last_use = 0;
7daf5226 699
1df106bf
MW
700 enumerator = create_policy_enumerator(this);
701 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
a3ce4bc2 702 {
d7083b65 703 time_t in, out, fwd;
7daf5226 704
dd83c6d4 705 if (inbound)
a3ce4bc2 706 {
89da06ac
TB
707 kernel_ipsec_policy_id_t id = {
708 .dir = POLICY_IN,
709 .src_ts = other_ts,
710 .dst_ts = my_ts,
711 .mark = this->mark_in,
a6014d99 712 .if_id = this->if_id_in,
139d6558 713 .label = label_for(this, LABEL_USE_POLICY),
89da06ac
TB
714 };
715 kernel_ipsec_query_policy_t query = {};
716
717 if (charon->kernel->query_policy(charon->kernel, &id, &query,
718 &in) == SUCCESS)
6e10aead
MW
719 {
720 last_use = max(last_use, in);
721 }
ce42db09 722 if (this->mode != MODE_TRANSPORT)
6e10aead 723 {
89da06ac
TB
724 id.dir = POLICY_FWD;
725 if (charon->kernel->query_policy(charon->kernel, &id, &query,
726 &fwd) == SUCCESS)
d487b4b7
AS
727 {
728 last_use = max(last_use, fwd);
729 }
6e10aead 730 }
a3ce4bc2 731 }
6e10aead 732 else
a3ce4bc2 733 {
89da06ac
TB
734 kernel_ipsec_policy_id_t id = {
735 .dir = POLICY_OUT,
736 .src_ts = my_ts,
737 .dst_ts = other_ts,
738 .mark = this->mark_out,
a6014d99 739 .if_id = this->if_id_out,
c26e4330 740 .interface = this->config->get_interface(this->config),
139d6558 741 .label = label_for(this, LABEL_USE_POLICY),
89da06ac
TB
742 };
743 kernel_ipsec_query_policy_t query = {};
744
745 if (charon->kernel->query_policy(charon->kernel, &id, &query,
746 &out) == SUCCESS)
6e10aead
MW
747 {
748 last_use = max(last_use, out);
749 }
a3ce4bc2
MW
750 }
751 }
1df106bf 752 enumerator->destroy(enumerator);
99dd4291
AS
753
754 if (last_use == 0)
755 {
5c12700f 756 return FALSE;
99dd4291 757 }
3f720dc7
AS
758 if (inbound)
759 {
760 this->my_usetime = last_use;
761 }
762 else
763 {
764 this->other_usetime = last_use;
765 }
5c12700f 766 return TRUE;
6e10aead
MW
767}
768
9d941742 769METHOD(child_sa_t, get_usestats, void,
d954a208 770 private_child_sa_t *this, bool inbound,
b12c53ce 771 time_t *time, uint64_t *bytes, uint64_t *packets)
2ad51539 772{
6301b880
TB
773 status_t status = NOT_SUPPORTED;
774 bool sa_use_time;
775
776 sa_use_time = charon->kernel->get_features(charon->kernel) & KERNEL_SA_USE_TIME;
777
778 if (bytes || packets || sa_use_time)
99dd4291 779 {
6301b880
TB
780 status = update_usebytes(this, inbound);
781 }
782 if (time && !sa_use_time && status != FAILED)
783 { /* query policies only if last use time is not available from SAs and
784 * there was either traffic or querying the SA wasn't supported */
785 update_usetime(this, inbound);
c3a78360
TB
786 }
787 if (time)
788 {
789 *time = inbound ? this->my_usetime : this->other_usetime;
790 }
791 if (bytes)
792 {
793 *bytes = inbound ? this->my_usebytes : this->other_usebytes;
794 }
d954a208
MW
795 if (packets)
796 {
797 *packets = inbound ? this->my_usepackets : this->other_usepackets;
798 }
2ad51539
AS
799}
800
79f39ecf
MW
801METHOD(child_sa_t, get_mark, mark_t,
802 private_child_sa_t *this, bool inbound)
803{
a6014d99
TB
804 return inbound ? this->mark_in : this->mark_out;
805}
806
807METHOD(child_sa_t, get_if_id, uint32_t,
808 private_child_sa_t *this, bool inbound)
809{
810 return inbound ? this->if_id_in : this->if_id_out;
79f39ecf
MW
811}
812
139d6558
TB
813METHOD(child_sa_t, get_label, sec_label_t*,
814 private_child_sa_t *this)
815{
816 return this->label ?: this->config->get_label(this->config);
817}
818
9d941742
TB
819METHOD(child_sa_t, get_lifetime, time_t,
820 private_child_sa_t *this, bool hard)
6e10aead 821{
80853d84 822 return hard ? this->expire_time : this->rekey_time;
a3ce4bc2
MW
823}
824
763e0353
MW
825METHOD(child_sa_t, get_installtime, time_t,
826 private_child_sa_t *this)
827{
828 return this->install_time;
829}
830
b12c53ce 831METHOD(child_sa_t, alloc_spi, uint32_t,
9d941742 832 private_child_sa_t *this, protocol_id_t protocol)
1396815a 833{
8394ea2a
TB
834 if (charon->kernel->get_spi(charon->kernel, this->other_addr, this->my_addr,
835 proto_ike2ip(protocol), &this->my_spi) == SUCCESS)
64e8ca28 836 {
21b096f3
MW
837 /* if we allocate a SPI, but then are unable to establish the SA, we
838 * need to know the protocol family to delete the partial SA */
839 this->protocol = protocol;
64e8ca28 840 return this->my_spi;
1396815a 841 }
3aaf7908 842 return 0;
1396815a
MW
843}
844
b12c53ce 845METHOD(child_sa_t, alloc_cpi, uint16_t,
9d941742 846 private_child_sa_t *this)
3ebebc5e 847{
8394ea2a
TB
848 if (charon->kernel->get_cpi(charon->kernel, this->other_addr, this->my_addr,
849 &this->my_cpi) == SUCCESS)
30b5b412 850 {
3aaf7908 851 return this->my_cpi;
30b5b412 852 }
3aaf7908 853 return 0;
3ebebc5e
MW
854}
855
13771206
TB
856/**
857 * Allocate a reqid for the given local and remote traffic selector lists.
858 * On success, release the previously allocated reqid.
859 */
860static status_t alloc_reqid_lists(private_child_sa_t *this,
861 linked_list_t *my_ts, linked_list_t *other_ts,
862 uint32_t *reqid)
863{
864 uint32_t existing_reqid = *reqid;
865 status_t status;
866
867 status = charon->kernel->alloc_reqid(
868 charon->kernel, my_ts, other_ts,
869 this->mark_in, this->mark_out, this->if_id_in,
870 this->if_id_out, label_for(this, LABEL_USE_REQID),
871 reqid);
872
873 if (status == SUCCESS && existing_reqid)
874 {
875 if (charon->kernel->release_reqid(charon->kernel,
876 existing_reqid) != SUCCESS)
877 {
878 DBG1(DBG_CHD, "releasing previous reqid %u failed", existing_reqid);
879 }
880 }
881 return status;
882}
883
884/**
885 * Allocate a reqid for the given local and remote traffic selectors.
886 */
887static status_t alloc_reqid(private_child_sa_t *this, array_t *my_ts,
888 array_t *other_ts, uint32_t *reqid)
889{
890 linked_list_t *my_ts_list, *other_ts_list;
891 status_t status;
892
893 my_ts_list = linked_list_create_from_enumerator(array_create_enumerator(my_ts));
894 other_ts_list = linked_list_create_from_enumerator(array_create_enumerator(other_ts));
895 status = alloc_reqid_lists(this, my_ts_list, other_ts_list, reqid);
896 my_ts_list->destroy(my_ts_list);
897 other_ts_list->destroy(other_ts_list);
898 return status;
899}
900
8a3a389e
TB
901/**
902 * Install the given SA in the kernel
903 */
904static status_t install_internal(private_child_sa_t *this, chunk_t encr,
905 chunk_t integ, uint32_t spi, uint16_t cpi, bool initiator, bool inbound,
906 bool tfcv3)
3ebebc5e 907{
b12c53ce
AS
908 uint16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
909 uint16_t esn = NO_EXT_SEQ_NUMBERS;
4989aba8 910 linked_list_t *my_ts, *other_ts, *src_ts, *dst_ts;
cb123493 911 time_t now;
89da06ac
TB
912 kernel_ipsec_sa_id_t id;
913 kernel_ipsec_add_sa_t sa;
cb123493 914 lifetime_cfg_t *lifetime;
b12c53ce 915 uint32_t tfc = 0;
e517b4b1 916 host_t *src, *dst;
30b5b412 917 status_t status;
acad5e9f 918 bool update = FALSE;
7daf5226 919
4989aba8
TB
920 /* BEET requires the bound address from the traffic selectors */
921 my_ts = linked_list_create_from_enumerator(
922 array_create_enumerator(this->my_ts));
923 other_ts = linked_list_create_from_enumerator(
924 array_create_enumerator(this->other_ts));
925
80853d84
MW
926 /* now we have to decide which spi to use. Use self allocated, if "in",
927 * or the one in the proposal, if not "in" (others). Additionally,
3efbf983 928 * source and dest host switch depending on the role */
3aaf7908 929 if (inbound)
aeda79ff 930 {
80853d84
MW
931 dst = this->my_addr;
932 src = this->other_addr;
acad5e9f
MW
933 if (this->my_spi == spi)
934 { /* alloc_spi has been called, do an SA update */
935 update = TRUE;
936 }
3aaf7908
MW
937 this->my_spi = spi;
938 this->my_cpi = cpi;
4989aba8
TB
939 dst_ts = my_ts;
940 src_ts = other_ts;
9118fd39 941 this->inbound_installed = TRUE;
aeda79ff 942 }
8d77edde
MW
943 else
944 {
80853d84
MW
945 src = this->my_addr;
946 dst = this->other_addr;
3aaf7908
MW
947 this->other_spi = spi;
948 this->other_cpi = cpi;
4989aba8
TB
949 src_ts = my_ts;
950 dst_ts = other_ts;
37788b1d 951
55df72e6
MW
952 if (tfcv3)
953 {
954 tfc = this->config->get_tfc(this->config);
955 }
2c116ef5 956 this->outbound_state |= CHILD_OUTBOUND_SA;
8d77edde 957 }
7daf5226 958
3aaf7908 959 DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
60356f33 960 protocol_id_names, this->protocol);
7daf5226 961
5c131a01 962 /* send SA down to the kernel */
b83806d8 963 DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
7daf5226 964
3aaf7908
MW
965 this->proposal->get_algorithm(this->proposal, ENCRYPTION_ALGORITHM,
966 &enc_alg, &size);
967 this->proposal->get_algorithm(this->proposal, INTEGRITY_ALGORITHM,
968 &int_alg, &size);
bd01b9d8
MW
969 this->proposal->get_algorithm(this->proposal, EXTENDED_SEQUENCE_NUMBERS,
970 &esn, NULL);
7daf5226 971
7637633b
TB
972 if (int_alg == AUTH_HMAC_SHA2_256_128 &&
973 this->config->has_option(this->config, OPT_SHA256_96))
974 {
975 DBG2(DBG_CHD, " using %N with 96-bit truncation",
976 integrity_algorithm_names, int_alg);
977 int_alg = AUTH_HMAC_SHA2_256_96;
978 }
979
3665adef 980 if (!this->reqid_allocated && !this->static_reqid)
0da97f50 981 {
13771206 982 status = alloc_reqid_lists(this, my_ts, other_ts, &this->reqid);
0da97f50
MW
983 if (status != SUCCESS)
984 {
4989aba8
TB
985 my_ts->destroy(my_ts);
986 other_ts->destroy(other_ts);
0da97f50
MW
987 return status;
988 }
989 this->reqid_allocated = TRUE;
990 }
991
b1df6312 992 lifetime = this->config->get_lifetime(this->config, TRUE);
7daf5226 993
6180a558 994 now = time_monotonic(NULL);
e75f4237 995 if (lifetime->time.rekey)
37974979 996 {
106b938b
MW
997 if (this->rekey_time)
998 {
999 this->rekey_time = min(this->rekey_time, now + lifetime->time.rekey);
1000 }
1001 else
1002 {
1003 this->rekey_time = now + lifetime->time.rekey;
1004 }
37974979 1005 }
e75f4237 1006 if (lifetime->time.life)
37974979 1007 {
e75f4237 1008 this->expire_time = now + lifetime->time.life;
cb123493 1009 }
7daf5226 1010
e75f4237 1011 if (!lifetime->time.jitter && !inbound)
cb123493 1012 { /* avoid triggering multiple rekey events */
e75f4237 1013 lifetime->time.rekey = 0;
37974979 1014 }
7daf5226 1015
89da06ac
TB
1016 id = (kernel_ipsec_sa_id_t){
1017 .src = src,
1018 .dst = dst,
1019 .spi = spi,
1020 .proto = proto_ike2ip(this->protocol),
ea43f8ff 1021 .mark = inbound ? mark_in_sa(this) : this->mark_out,
a6014d99 1022 .if_id = inbound ? this->if_id_in : this->if_id_out,
89da06ac
TB
1023 };
1024 sa = (kernel_ipsec_add_sa_t){
1025 .reqid = this->reqid,
1026 .mode = this->mode,
1027 .src_ts = src_ts,
1028 .dst_ts = dst_ts,
c26e4330 1029 .interface = inbound ? NULL : this->config->get_interface(this->config),
89da06ac
TB
1030 .lifetime = lifetime,
1031 .enc_alg = enc_alg,
1032 .enc_key = encr,
1033 .int_alg = int_alg,
1034 .int_key = integ,
1035 .replay_window = this->config->get_replay_window(this->config),
1036 .tfc = tfc,
1037 .ipcomp = this->ipcomp,
1038 .cpi = cpi,
1039 .encap = this->encap,
8ced1570 1040 .hw_offload = this->config->get_hw_offload(this->config),
f59450fd 1041 .mark = this->config->get_set_mark(this->config, inbound),
89da06ac 1042 .esn = esn,
dc8b015d
TB
1043 .copy_df = !this->config->has_option(this->config, OPT_NO_COPY_DF),
1044 .copy_ecn = !this->config->has_option(this->config, OPT_NO_COPY_ECN),
c993eaf9 1045 .copy_dscp = this->config->get_copy_dscp(this->config),
139d6558 1046 .label = label_for(this, LABEL_USE_SA),
89da06ac
TB
1047 .initiator = initiator,
1048 .inbound = inbound,
1049 .update = update,
1050 };
1051
902dc29f
MW
1052 if (sa.mark.value == MARK_SAME)
1053 {
1054 sa.mark.value = inbound ? this->mark_in.value : this->mark_out.value;
1055 }
1056
89da06ac 1057 status = charon->kernel->add_sa(charon->kernel, &id, &sa);
7daf5226 1058
4989aba8
TB
1059 my_ts->destroy(my_ts);
1060 other_ts->destroy(other_ts);
cb123493 1061 free(lifetime);
7daf5226 1062
8d77edde 1063 return status;
30b5b412
MW
1064}
1065
8a3a389e
TB
1066METHOD(child_sa_t, install, status_t,
1067 private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
1068 uint16_t cpi, bool initiator, bool inbound, bool tfcv3)
1069{
1070 return install_internal(this, encr, integ, spi, cpi, initiator, inbound,
1071 tfcv3);
1072}
1073
7452adfa
MW
1074/**
1075 * Check kernel interface if policy updates are required
1076 */
1077static bool require_policy_update()
1078{
1079 kernel_feature_t f;
1080
8394ea2a 1081 f = charon->kernel->get_features(charon->kernel);
7452adfa
MW
1082 return !(f & KERNEL_NO_POLICY_UPDATES);
1083}
1084
a6e0f14f
TB
1085/**
1086 * Prepare SA config to install/delete policies
1087 */
1088static void prepare_sa_cfg(private_child_sa_t *this, ipsec_sa_cfg_t *my_sa,
1089 ipsec_sa_cfg_t *other_sa)
1090{
1091 enumerator_t *enumerator;
1092
1093 *my_sa = (ipsec_sa_cfg_t){
1094 .mode = this->mode,
1095 .reqid = this->reqid,
1096 .ipcomp = {
1097 .transform = this->ipcomp,
1098 },
1099 };
1100 *other_sa = *my_sa;
1101
1102 my_sa->ipcomp.cpi = this->my_cpi;
1103 other_sa->ipcomp.cpi = this->other_cpi;
1104
1105 if (this->protocol == PROTO_ESP)
1106 {
1107 my_sa->esp.use = TRUE;
1108 my_sa->esp.spi = this->my_spi;
1109 other_sa->esp.use = TRUE;
1110 other_sa->esp.spi = this->other_spi;
1111 }
1112 else
1113 {
1114 my_sa->ah.use = TRUE;
1115 my_sa->ah.spi = this->my_spi;
1116 other_sa->ah.use = TRUE;
1117 other_sa->ah.spi = this->other_spi;
1118 }
1119
1120 enumerator = create_policy_enumerator(this);
1121 while (enumerator->enumerate(enumerator, NULL, NULL))
1122 {
1123 my_sa->policy_count++;
1124 other_sa->policy_count++;
1125 }
1126 enumerator->destroy(enumerator);
1127}
1128
f1c1965d 1129/**
db82c0f5 1130 * Install inbound policies: in, fwd
f1c1965d 1131 */
29ef4cf5 1132static status_t install_policies_inbound(private_child_sa_t *this,
f1c1965d
TB
1133 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1134 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
7f57c4f9
AS
1135 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1136 policy_priority_t priority, uint32_t manual_prio)
f1c1965d 1137{
29ef4cf5 1138 kernel_ipsec_policy_id_t in_id = {
89da06ac
TB
1139 .dir = POLICY_IN,
1140 .src_ts = other_ts,
1141 .dst_ts = my_ts,
1142 .mark = this->mark_in,
a6014d99 1143 .if_id = this->if_id_in,
139d6558 1144 .label = label_for(this, LABEL_USE_POLICY),
89da06ac 1145 };
29ef4cf5 1146 kernel_ipsec_manage_policy_t in_policy = {
89da06ac
TB
1147 .type = type,
1148 .prio = priority,
7f57c4f9 1149 .manual_prio = manual_prio,
46cfebe4 1150 .hw_offload = this->config->get_hw_offload(this->config),
89da06ac
TB
1151 .src = other_addr,
1152 .dst = my_addr,
1153 .sa = my_sa,
1154 };
f1c1965d 1155 status_t status = SUCCESS;
89da06ac 1156
89da06ac 1157 status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
f1c1965d
TB
1158 if (this->mode != MODE_TRANSPORT)
1159 {
89da06ac
TB
1160 in_id.dir = POLICY_FWD;
1161 status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
29ef4cf5
TB
1162 }
1163 return status;
1164}
9c126352 1165
29ef4cf5 1166/**
db82c0f5 1167 * Install outbound policies: out, [fwd]
29ef4cf5
TB
1168 */
1169static status_t install_policies_outbound(private_child_sa_t *this,
1170 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1171 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1172 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1173 policy_priority_t priority, uint32_t manual_prio)
1174{
1175 kernel_ipsec_policy_id_t out_id = {
1176 .dir = POLICY_OUT,
1177 .src_ts = my_ts,
1178 .dst_ts = other_ts,
1179 .mark = this->mark_out,
a6014d99 1180 .if_id = this->if_id_out,
29ef4cf5 1181 .interface = this->config->get_interface(this->config),
139d6558 1182 .label = label_for(this, LABEL_USE_POLICY),
29ef4cf5
TB
1183 };
1184 kernel_ipsec_manage_policy_t out_policy = {
1185 .type = type,
1186 .prio = priority,
1187 .manual_prio = manual_prio,
46cfebe4 1188 .hw_offload = this->config->get_hw_offload(this->config),
29ef4cf5
TB
1189 .src = my_addr,
1190 .dst = other_addr,
1191 .sa = other_sa,
1192 };
8f4cfe96 1193 uint32_t reqid = other_sa->reqid;
29ef4cf5
TB
1194 status_t status = SUCCESS;
1195
1196 status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
1197
1198 if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
1199 {
9c126352
TB
1200 /* install an "outbound" FWD policy in case there is a drop policy
1201 * matching outbound forwarded traffic, to allow another tunnel to use
1202 * the reversed subnets and do the same we don't set a reqid (this also
1203 * allows the kernel backend to distinguish between the two types of
979f4651
TB
1204 * FWD policies). To avoid problems with symmetrically overlapping
1205 * policies of two SAs we install them with reduced priority. As they
1206 * basically act as bypass policies for drop policies we use a higher
1207 * priority than is used for them. */
29ef4cf5
TB
1208 out_id.dir = POLICY_FWD;
1209 other_sa->reqid = 0;
1210 if (priority == POLICY_PRIORITY_DEFAULT)
979f4651 1211 {
29ef4cf5 1212 out_policy.prio = POLICY_PRIORITY_ROUTED;
979f4651 1213 }
29ef4cf5
TB
1214 status |= charon->kernel->add_policy(charon->kernel, &out_id,
1215 &out_policy);
1216 /* reset the reqid for any other further policies */
8f4cfe96 1217 other_sa->reqid = reqid;
f1c1965d
TB
1218 }
1219 return status;
1220}
1221
1222/**
29ef4cf5 1223 * Install all policies
f1c1965d 1224 */
29ef4cf5
TB
1225static status_t install_policies_internal(private_child_sa_t *this,
1226 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1227 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1228 ipsec_sa_cfg_t *other_sa, policy_type_t type,
529ffc2f 1229 policy_priority_t priority, uint32_t manual_prio, bool outbound)
29ef4cf5
TB
1230{
1231 status_t status = SUCCESS;
1232
1233 status |= install_policies_inbound(this, my_addr, other_addr, my_ts,
529ffc2f
TB
1234 other_ts, my_sa, other_sa, type, priority, manual_prio);
1235 if (outbound)
1236 {
1237 status |= install_policies_outbound(this, my_addr, other_addr, my_ts,
1238 other_ts, my_sa, other_sa, type, priority, manual_prio);
1239 }
29ef4cf5
TB
1240 return status;
1241}
1242
1243/**
1244 * Delete inbound policies: in, fwd
1245 */
1246static void del_policies_inbound(private_child_sa_t *this,
a6e0f14f
TB
1247 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1248 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
7f57c4f9
AS
1249 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1250 policy_priority_t priority, uint32_t manual_prio)
f1c1965d 1251{
29ef4cf5 1252 kernel_ipsec_policy_id_t in_id = {
89da06ac
TB
1253 .dir = POLICY_IN,
1254 .src_ts = other_ts,
1255 .dst_ts = my_ts,
1256 .mark = this->mark_in,
a6014d99 1257 .if_id = this->if_id_in,
139d6558 1258 .label = label_for(this, LABEL_USE_POLICY),
89da06ac 1259 };
29ef4cf5 1260 kernel_ipsec_manage_policy_t in_policy = {
89da06ac
TB
1261 .type = type,
1262 .prio = priority,
7f57c4f9 1263 .manual_prio = manual_prio,
46cfebe4 1264 .hw_offload = this->config->get_hw_offload(this->config),
89da06ac
TB
1265 .src = other_addr,
1266 .dst = my_addr,
1267 .sa = my_sa,
1268 };
a6e0f14f 1269
89da06ac 1270 charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
29ef4cf5 1271
f1c1965d
TB
1272 if (this->mode != MODE_TRANSPORT)
1273 {
89da06ac
TB
1274 in_id.dir = POLICY_FWD;
1275 charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
29ef4cf5
TB
1276 }
1277}
1278
1279/**
1280 * Delete outbound policies: out, [fwd]
1281 */
1282static void del_policies_outbound(private_child_sa_t *this,
1283 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1284 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1285 ipsec_sa_cfg_t *other_sa, policy_type_t type,
1286 policy_priority_t priority, uint32_t manual_prio)
1287{
1288 kernel_ipsec_policy_id_t out_id = {
1289 .dir = POLICY_OUT,
1290 .src_ts = my_ts,
1291 .dst_ts = other_ts,
1292 .mark = this->mark_out,
a6014d99 1293 .if_id = this->if_id_out,
29ef4cf5 1294 .interface = this->config->get_interface(this->config),
139d6558 1295 .label = label_for(this, LABEL_USE_POLICY),
29ef4cf5
TB
1296 };
1297 kernel_ipsec_manage_policy_t out_policy = {
1298 .type = type,
1299 .prio = priority,
1300 .manual_prio = manual_prio,
46cfebe4 1301 .hw_offload = this->config->get_hw_offload(this->config),
29ef4cf5
TB
1302 .src = my_addr,
1303 .dst = other_addr,
1304 .sa = other_sa,
1305 };
8f4cfe96 1306 uint32_t reqid = other_sa->reqid;
29ef4cf5
TB
1307
1308 charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
9c126352 1309
29ef4cf5
TB
1310 if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
1311 {
1312 out_id.dir = POLICY_FWD;
1313 other_sa->reqid = 0;
1314 if (priority == POLICY_PRIORITY_DEFAULT)
979f4651 1315 {
29ef4cf5 1316 out_policy.prio = POLICY_PRIORITY_ROUTED;
979f4651 1317 }
29ef4cf5 1318 charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
8f4cfe96 1319 other_sa->reqid = reqid;
f1c1965d
TB
1320 }
1321}
1322
29ef4cf5
TB
1323/**
1324 * Delete in- and outbound policies
1325 */
1326static void del_policies_internal(private_child_sa_t *this,
1327 host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
1328 traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
1329 ipsec_sa_cfg_t *other_sa, policy_type_t type,
529ffc2f 1330 policy_priority_t priority, uint32_t manual_prio, bool outbound)
29ef4cf5 1331{
529ffc2f
TB
1332 if (outbound)
1333 {
1334 del_policies_outbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
1335 other_sa, type, priority, manual_prio);
1336 }
29ef4cf5 1337 del_policies_inbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
529ffc2f 1338 other_sa, type, priority, manual_prio);
29ef4cf5
TB
1339}
1340
4989aba8 1341METHOD(child_sa_t, set_policies, void,
9d941742
TB
1342 private_child_sa_t *this, linked_list_t *my_ts_list,
1343 linked_list_t *other_ts_list)
a527a426 1344{
1df106bf 1345 enumerator_t *enumerator;
5d187bd2 1346 traffic_selector_t *my_ts, *other_ts;
7daf5226 1347
4989aba8 1348 if (array_count(this->my_ts))
0da97f50 1349 {
4989aba8
TB
1350 array_destroy_offset(this->my_ts,
1351 offsetof(traffic_selector_t, destroy));
1352 this->my_ts = array_create(0, 0);
0da97f50 1353 }
1df106bf
MW
1354 enumerator = my_ts_list->create_enumerator(my_ts_list);
1355 while (enumerator->enumerate(enumerator, &my_ts))
a527a426 1356 {
2745ae26 1357 array_insert(this->my_ts, ARRAY_TAIL, my_ts->clone(my_ts));
1df106bf
MW
1358 }
1359 enumerator->destroy(enumerator);
5499473c
MW
1360 array_sort(this->my_ts, (void*)traffic_selector_cmp, NULL);
1361
4989aba8
TB
1362 if (array_count(this->other_ts))
1363 {
1364 array_destroy_offset(this->other_ts,
1365 offsetof(traffic_selector_t, destroy));
1366 this->other_ts = array_create(0, 0);
1367 }
1df106bf
MW
1368 enumerator = other_ts_list->create_enumerator(other_ts_list);
1369 while (enumerator->enumerate(enumerator, &other_ts))
1370 {
2745ae26 1371 array_insert(this->other_ts, ARRAY_TAIL, other_ts->clone(other_ts));
1df106bf
MW
1372 }
1373 enumerator->destroy(enumerator);
5499473c 1374 array_sort(this->other_ts, (void*)traffic_selector_cmp, NULL);
4989aba8
TB
1375}
1376
1377METHOD(child_sa_t, install_policies, status_t,
1378 private_child_sa_t *this)
1379{
1380 enumerator_t *enumerator;
4989aba8
TB
1381 traffic_selector_t *my_ts, *other_ts;
1382 status_t status = SUCCESS;
2c116ef5 1383 bool install_outbound = FALSE;
4989aba8
TB
1384
1385 if (!this->reqid_allocated && !this->static_reqid)
1386 {
8f4cfe96 1387 status = alloc_reqid(this, this->my_ts, this->other_ts, &this->reqid);
4989aba8
TB
1388 if (status != SUCCESS)
1389 {
1390 return status;
1391 }
1392 this->reqid_allocated = TRUE;
1393 }
7daf5226 1394
2c116ef5
TB
1395 if (!(this->outbound_state & CHILD_OUTBOUND_REGISTERED))
1396 {
1397 install_outbound = TRUE;
1398 this->outbound_state |= CHILD_OUTBOUND_POLICIES;
1399 }
1400
749ac175 1401 if (!this->config->has_option(this->config, OPT_NO_POLICIES))
1df106bf 1402 {
fbedc6a4 1403 policy_priority_t priority;
a6e0f14f 1404 ipsec_sa_cfg_t my_sa, other_sa;
7f57c4f9 1405 uint32_t manual_prio;
a6e0f14f
TB
1406
1407 prepare_sa_cfg(this, &my_sa, &other_sa);
7f57c4f9 1408 manual_prio = this->config->get_manual_prio(this->config);
71b6d2ff 1409
c8f7a114
TB
1410 /* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
1411 * entry) we install a trap policy */
1412 this->trap = this->state == CHILD_CREATED;
1413 priority = this->trap ? POLICY_PRIORITY_ROUTED
1414 : POLICY_PRIORITY_DEFAULT;
fbedc6a4 1415
d487b4b7
AS
1416 /* enumerate pairs of traffic selectors */
1417 enumerator = create_policy_enumerator(this);
1418 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1419 {
529ffc2f 1420 status |= install_policies_internal(this, this->my_addr,
f1c1965d 1421 this->other_addr, my_ts, other_ts,
529ffc2f
TB
1422 &my_sa, &other_sa, POLICY_IPSEC, priority,
1423 manual_prio, install_outbound);
d487b4b7
AS
1424 if (status != SUCCESS)
1425 {
1426 break;
1427 }
5d187bd2 1428 }
d487b4b7 1429 enumerator->destroy(enumerator);
5d187bd2 1430 }
7daf5226 1431
c8f7a114
TB
1432 if (status == SUCCESS && this->trap)
1433 {
3aaf7908 1434 set_state(this, CHILD_ROUTED);
45f76a7d 1435 }
1df106bf 1436 return status;
30b5b412
MW
1437}
1438
139d6558
TB
1439/**
1440 * Check if we can install the outbound SA immediately.
1441 *
1442 * If the kernel supports installing SPIs with policies, we can do so as it
1443 * will only be used once we update the policies.
1444 *
1445 * However, if we use labels with SELinux, we can't as we don't set SPIs
1446 * on the policy in order to match SAs with other labels that match the generic
1447 * label that's used on the policies.
1448 */
1449static bool install_outbound_immediately(private_child_sa_t *this)
1450{
1451 if (charon->kernel->get_features(charon->kernel) & KERNEL_POLICY_SPI)
1452 {
1453 if (this->config->get_label_mode(this->config) == SEC_LABEL_MODE_SELINUX)
1454 {
1455 return !this->label;
1456 }
1457 return TRUE;
1458 }
1459 return FALSE;
1460}
1461
a146b4c9 1462METHOD(child_sa_t, register_outbound, status_t,
8a3a389e 1463 private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
639af09b 1464 uint16_t cpi, bool initiator, bool tfcv3)
8a3a389e 1465{
a146b4c9
TB
1466 status_t status;
1467
139d6558 1468 if (install_outbound_immediately(this))
a146b4c9 1469 {
639af09b 1470 status = install_internal(this, encr, integ, spi, cpi, initiator, FALSE,
a146b4c9
TB
1471 tfcv3);
1472 }
1473 else
1474 {
1475 DBG2(DBG_CHD, "registering outbound %N SA", protocol_id_names,
1476 this->protocol);
1477 DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), this->my_addr,
1478 this->other_addr);
1479
1480 this->other_spi = spi;
1481 this->other_cpi = cpi;
1482 this->encr_r = chunk_clone(encr);
1483 this->integ_r = chunk_clone(integ);
639af09b 1484 this->initiator = initiator;
a146b4c9
TB
1485 this->tfcv3 = tfcv3;
1486 status = SUCCESS;
1487 }
2c116ef5 1488 this->outbound_state |= CHILD_OUTBOUND_REGISTERED;
a146b4c9 1489 return status;
8a3a389e
TB
1490}
1491
1492METHOD(child_sa_t, install_outbound, status_t,
1493 private_child_sa_t *this)
1494{
1495 enumerator_t *enumerator;
1496 traffic_selector_t *my_ts, *other_ts;
2c116ef5 1497 status_t status = SUCCESS;
8a3a389e 1498
a146b4c9
TB
1499 if (!(this->outbound_state & CHILD_OUTBOUND_SA))
1500 {
1501 status = install_internal(this, this->encr_r, this->integ_r,
639af09b
TB
1502 this->other_spi, this->other_cpi,
1503 this->initiator, FALSE, this->tfcv3);
a146b4c9
TB
1504 chunk_clear(&this->encr_r);
1505 chunk_clear(&this->integ_r);
1506 }
2c116ef5 1507 this->outbound_state &= ~CHILD_OUTBOUND_REGISTERED;
8a3a389e
TB
1508 if (status != SUCCESS)
1509 {
1510 return status;
1511 }
a146b4c9
TB
1512 if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
1513 !(this->outbound_state & CHILD_OUTBOUND_POLICIES))
8a3a389e
TB
1514 {
1515 ipsec_sa_cfg_t my_sa, other_sa;
1516 uint32_t manual_prio;
1517
1518 prepare_sa_cfg(this, &my_sa, &other_sa);
1519 manual_prio = this->config->get_manual_prio(this->config);
1520
1521 enumerator = create_policy_enumerator(this);
1522 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1523 {
8a3a389e
TB
1524 status |= install_policies_outbound(this, this->my_addr,
1525 this->other_addr, my_ts, other_ts,
1526 &my_sa, &other_sa, POLICY_IPSEC,
1527 POLICY_PRIORITY_DEFAULT, manual_prio);
1528 if (status != SUCCESS)
1529 {
1530 break;
1531 }
1532 }
1533 enumerator->destroy(enumerator);
1534 }
a146b4c9 1535 this->outbound_state |= CHILD_OUTBOUND_POLICIES;
8a3a389e
TB
1536 return status;
1537}
1538
c5fed4cd
TB
1539METHOD(child_sa_t, remove_outbound, void,
1540 private_child_sa_t *this)
1541{
1542 enumerator_t *enumerator;
1543 traffic_selector_t *my_ts, *other_ts;
1544
2c116ef5 1545 if (!(this->outbound_state & CHILD_OUTBOUND_SA))
c5fed4cd 1546 {
2c116ef5
TB
1547 if (this->outbound_state & CHILD_OUTBOUND_REGISTERED)
1548 {
c5fed4cd
TB
1549 chunk_clear(&this->encr_r);
1550 chunk_clear(&this->integ_r);
afbea8ce 1551 this->outbound_state = CHILD_OUTBOUND_NONE;
2c116ef5
TB
1552 }
1553 return;
c5fed4cd
TB
1554 }
1555
2c116ef5
TB
1556 if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
1557 (this->outbound_state & CHILD_OUTBOUND_POLICIES))
c5fed4cd
TB
1558 {
1559 ipsec_sa_cfg_t my_sa, other_sa;
1560 uint32_t manual_prio;
1561
1562 prepare_sa_cfg(this, &my_sa, &other_sa);
1563 manual_prio = this->config->get_manual_prio(this->config);
1564
1565 enumerator = create_policy_enumerator(this);
1566 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1567 {
1568 del_policies_outbound(this, this->my_addr, this->other_addr,
1569 my_ts, other_ts, &my_sa, &other_sa,
1570 POLICY_IPSEC, POLICY_PRIORITY_DEFAULT,
1571 manual_prio);
c5fed4cd
TB
1572 }
1573 enumerator->destroy(enumerator);
1574 }
1575
1576 kernel_ipsec_sa_id_t id = {
1577 .src = this->my_addr,
1578 .dst = this->other_addr,
1579 .spi = this->other_spi,
1580 .proto = proto_ike2ip(this->protocol),
1581 .mark = this->mark_out,
a6014d99 1582 .if_id = this->if_id_out,
c5fed4cd
TB
1583 };
1584 kernel_ipsec_del_sa_t sa = {
1585 .cpi = this->other_cpi,
1586 };
1587 charon->kernel->del_sa(charon->kernel, &id, &sa);
afbea8ce 1588 this->outbound_state = CHILD_OUTBOUND_NONE;
c5fed4cd
TB
1589}
1590
cad13450
TB
1591METHOD(child_sa_t, set_rekey_spi, void,
1592 private_child_sa_t *this, uint32_t spi)
1593{
1594 this->rekey_spi = spi;
1595}
1596
1597METHOD(child_sa_t, get_rekey_spi, uint32_t,
1598 private_child_sa_t *this)
1599{
1600 return this->rekey_spi;
1601}
1602
8a2e4d4a
TB
1603CALLBACK(reinstall_vip, void,
1604 host_t *vip, va_list args)
101d26ba 1605{
8a2e4d4a 1606 host_t *me;
b185cdd1
MW
1607 char *iface;
1608
8a2e4d4a 1609 VA_ARGS_VGET(args, me);
8394ea2a 1610 if (charon->kernel->get_interface(charon->kernel, me, &iface))
b185cdd1 1611 {
8394ea2a
TB
1612 charon->kernel->del_ip(charon->kernel, vip, -1, TRUE);
1613 charon->kernel->add_ip(charon->kernel, vip, -1, iface);
b185cdd1
MW
1614 free(iface);
1615 }
101d26ba
MW
1616}
1617
35ef1b03
TB
1618/**
1619 * Update addresses and encap state of IPsec SAs in the kernel
1620 */
1621static status_t update_sas(private_child_sa_t *this, host_t *me, host_t *other,
8f4cfe96 1622 bool encap, uint32_t reqid)
35ef1b03
TB
1623{
1624 /* update our (initiator) SA */
9118fd39 1625 if (this->my_spi && this->inbound_installed)
35ef1b03
TB
1626 {
1627 kernel_ipsec_sa_id_t id = {
1628 .src = this->other_addr,
1629 .dst = this->my_addr,
1630 .spi = this->my_spi,
1631 .proto = proto_ike2ip(this->protocol),
1632 .mark = mark_in_sa(this),
a6014d99 1633 .if_id = this->if_id_in,
35ef1b03
TB
1634 };
1635 kernel_ipsec_update_sa_t sa = {
1636 .cpi = this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
1637 .new_src = other,
1638 .new_dst = me,
1639 .encap = this->encap,
1640 .new_encap = encap,
8f4cfe96 1641 .new_reqid = reqid,
35ef1b03
TB
1642 };
1643 if (charon->kernel->update_sa(charon->kernel, &id,
1644 &sa) == NOT_SUPPORTED)
1645 {
1646 return NOT_SUPPORTED;
1647 }
1648 }
1649
1650 /* update his (responder) SA */
ca79bd54 1651 if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
35ef1b03
TB
1652 {
1653 kernel_ipsec_sa_id_t id = {
1654 .src = this->my_addr,
1655 .dst = this->other_addr,
1656 .spi = this->other_spi,
1657 .proto = proto_ike2ip(this->protocol),
1658 .mark = this->mark_out,
a6014d99 1659 .if_id = this->if_id_out,
35ef1b03
TB
1660 };
1661 kernel_ipsec_update_sa_t sa = {
1662 .cpi = this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
1663 .new_src = me,
1664 .new_dst = other,
1665 .encap = this->encap,
1666 .new_encap = encap,
8f4cfe96 1667 .new_reqid = reqid,
35ef1b03
TB
1668 };
1669 if (charon->kernel->update_sa(charon->kernel, &id,
1670 &sa) == NOT_SUPPORTED)
1671 {
1672 return NOT_SUPPORTED;
1673 }
1674 }
1675 /* we currently ignore the actual return values above */
1676 return SUCCESS;
1677}
1678
8f4cfe96
TB
1679/**
1680 * Fill the second list with copies of the given traffic selectors updating
1681 * dynamic traffic selectors based on the given addresses.
1682 */
1683static void update_ts(host_t *old_host, host_t *new_host, array_t *old_list,
1684 array_t *new_list)
1685{
1686 enumerator_t *enumerator;
1687 traffic_selector_t *old_ts, *new_ts;
1688
1689 enumerator = array_create_enumerator(old_list);
1690 while (enumerator->enumerate(enumerator, &old_ts))
1691 {
1692 new_ts = old_ts->clone(old_ts);
1693 if (new_ts->is_host(new_ts, old_host))
1694 {
1695 new_ts->set_address(new_ts, new_host);
1696 }
1697 array_insert(new_list, ARRAY_TAIL, new_ts);
1698 }
1699 enumerator->destroy(enumerator);
1700 array_sort(new_list, (void*)traffic_selector_cmp, NULL);
1701}
1702
9d941742 1703METHOD(child_sa_t, update, status_t,
35ef1b03 1704 private_child_sa_t *this, host_t *me, host_t *other, linked_list_t *vips,
101d26ba 1705 bool encap)
1396815a 1706{
ad3af574 1707 child_sa_state_t old;
08c6ed9f 1708 bool transport_proxy_mode;
7daf5226 1709
2b3100b5 1710 /* anything changed at all? */
dd83c6d4 1711 if (me->equals(me, this->my_addr) &&
80853d84 1712 other->equals(other, this->other_addr) && this->encap == encap)
1396815a
MW
1713 {
1714 return SUCCESS;
1715 }
7daf5226 1716
ad3af574
MW
1717 old = this->state;
1718 set_state(this, CHILD_UPDATING);
749ac175
TB
1719 transport_proxy_mode = this->mode == MODE_TRANSPORT &&
1720 this->config->has_option(this->config,
1721 OPT_PROXY_MODE);
7daf5226 1722
35ef1b03 1723 if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
29b491ed
TB
1724 require_policy_update() && array_count(this->my_ts) &&
1725 array_count(this->other_ts))
ea625fab 1726 {
35ef1b03
TB
1727 ipsec_sa_cfg_t my_sa, other_sa;
1728 enumerator_t *enumerator;
1729 traffic_selector_t *my_ts, *other_ts;
8f4cfe96 1730 array_t *new_my_ts = NULL, *new_other_ts = NULL;
9619b1e7 1731 policy_priority_t priority;
8f4cfe96 1732 uint32_t manual_prio, new_reqid = 0;
35ef1b03 1733 status_t state;
529ffc2f 1734 bool outbound;
35ef1b03
TB
1735
1736 prepare_sa_cfg(this, &my_sa, &other_sa);
1737 manual_prio = this->config->get_manual_prio(this->config);
9619b1e7
TB
1738 priority = this->trap ? POLICY_PRIORITY_ROUTED
1739 : POLICY_PRIORITY_DEFAULT;
1740 outbound = (this->outbound_state & CHILD_OUTBOUND_POLICIES) || this->trap;
7daf5226 1741
35ef1b03
TB
1742 enumerator = create_policy_enumerator(this);
1743 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
7a915d62 1744 {
8f4cfe96
TB
1745 if (!new_my_ts && !me->ip_equals(me, this->my_addr) &&
1746 my_ts->is_host(my_ts, this->my_addr))
1747 {
1748 new_my_ts = array_create(0, 0);
1749 }
1750 if (!new_other_ts && !other->ip_equals(other, this->other_addr) &&
1751 other_ts->is_host(other_ts, this->other_addr))
1752 {
1753 new_other_ts = array_create(0, 0);
1754 }
35ef1b03 1755 /* install drop policy to avoid traffic leaks, acquires etc. */
529ffc2f
TB
1756 if (outbound)
1757 {
1758 install_policies_outbound(this, this->my_addr, this->other_addr,
1759 my_ts, other_ts, &my_sa, &other_sa, POLICY_DROP,
1760 POLICY_PRIORITY_DEFAULT, manual_prio);
1761 }
35ef1b03
TB
1762 /* remove old policies */
1763 del_policies_internal(this, this->my_addr, this->other_addr,
1764 my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC,
9619b1e7 1765 priority, manual_prio, outbound);
7a915d62 1766 }
35ef1b03 1767 enumerator->destroy(enumerator);
7daf5226 1768
8f4cfe96
TB
1769 if (new_my_ts)
1770 {
1771 update_ts(this->my_addr, me, this->my_ts, new_my_ts);
1772 }
1773 if (new_other_ts)
1774 {
1775 update_ts(this->other_addr, other, this->other_ts, new_other_ts);
1776 }
1777 if (this->reqid_allocated && (new_my_ts || new_other_ts))
1778 {
1779 /* if we allocated a reqid with the previous TS, we have to get a
1780 * new one that matches the updated TS */
1781 if (alloc_reqid(this, new_my_ts ?: this->my_ts,
1782 new_other_ts ?: this->other_ts, &new_reqid) != SUCCESS)
1783 {
1784 DBG1(DBG_CHD, "allocating new reqid for updated SA failed");
1785 }
1786 }
1787
35ef1b03 1788 /* update the IPsec SAs */
8f4cfe96
TB
1789 state = update_sas(this, me, other, encap, new_reqid);
1790
1791 /* install new/updated policies only if we were able to update the
1792 * SAs, otherwise we reinstall the old policies further below */
1793 if (state != NOT_SUPPORTED)
1794 {
1795 /* we reinstall the virtual IP to handle interface roaming
1796 * correctly */
1797 if (vips)
1798 {
1799 vips->invoke_function(vips, reinstall_vip, me);
1800 }
1801 if (new_reqid)
1802 {
1803 my_sa.reqid = other_sa.reqid = new_reqid;
1804 }
1805 enumerator = create_policy_enumerator_internal(
1806 new_my_ts ?: this->my_ts,
1807 new_other_ts ?: this->other_ts);
1808 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1809 {
1810 install_policies_internal(this, me, other, my_ts, other_ts,
1811 &my_sa, &other_sa, POLICY_IPSEC,
1812 priority, manual_prio, outbound);
1813 }
1814 enumerator->destroy(enumerator);
1815 if (new_reqid)
1816 {
1817 my_sa.reqid = other_sa.reqid = this->reqid;
1818 }
1819 }
7daf5226 1820
35ef1b03
TB
1821 enumerator = create_policy_enumerator(this);
1822 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1823 {
35ef1b03
TB
1824 /* reinstall the previous policies if we can't update the SAs */
1825 if (state == NOT_SUPPORTED)
1826 {
1827 install_policies_internal(this, this->my_addr, this->other_addr,
529ffc2f 1828 my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC,
9619b1e7 1829 priority, manual_prio, outbound);
35ef1b03 1830 }
35ef1b03 1831 /* remove the drop policy */
529ffc2f
TB
1832 if (outbound)
1833 {
1834 del_policies_outbound(this, this->my_addr, this->other_addr,
8f4cfe96 1835 my_ts, other_ts, &my_sa, &other_sa, POLICY_DROP,
8e31d657 1836 POLICY_PRIORITY_DEFAULT, manual_prio);
529ffc2f 1837 }
35ef1b03
TB
1838 }
1839 enumerator->destroy(enumerator);
1840
1841 if (state == NOT_SUPPORTED)
1842 {
8f4cfe96
TB
1843 if (new_reqid &&
1844 charon->kernel->release_reqid(charon->kernel,
02180ae2 1845 new_reqid) != SUCCESS)
8f4cfe96
TB
1846 {
1847 DBG1(DBG_CHD, "releasing reqid %u failed", new_reqid);
1848 }
1849 array_destroy_offset(new_my_ts,
1850 offsetof(traffic_selector_t, destroy));
1851 array_destroy_offset(new_other_ts,
1852 offsetof(traffic_selector_t, destroy));
35ef1b03
TB
1853 set_state(this, old);
1854 return NOT_SUPPORTED;
1855 }
1856
8f4cfe96
TB
1857 if (new_reqid)
1858 {
1859 if (charon->kernel->release_reqid(charon->kernel,
02180ae2 1860 this->reqid) != SUCCESS)
8f4cfe96
TB
1861 {
1862 DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid);
1863 }
1864 DBG1(DBG_CHD, "replaced reqid %u with reqid %u for updated "
1865 "CHILD_SA %s{%d}", this->reqid, new_reqid, get_name(this),
1866 this->unique_id);
1867 this->reqid = new_reqid;
1868 }
1869 if (new_my_ts)
1870 {
1871 array_destroy_offset(this->my_ts,
1872 offsetof(traffic_selector_t, destroy));
1873 this->my_ts = new_my_ts;
1874 }
1875 if (new_other_ts)
1876 {
1877 array_destroy_offset(this->other_ts,
1878 offsetof(traffic_selector_t, destroy));
1879 this->other_ts = new_other_ts;
1880 }
35ef1b03
TB
1881 }
1882 else if (!transport_proxy_mode)
1883 {
8f4cfe96 1884 if (update_sas(this, me, other, encap, 0) == NOT_SUPPORTED)
35ef1b03
TB
1885 {
1886 set_state(this, old);
1887 return NOT_SUPPORTED;
1396815a
MW
1888 }
1889 }
7a915d62 1890
08c6ed9f
AS
1891 if (!transport_proxy_mode)
1892 {
1893 /* apply hosts */
1894 if (!me->equals(me, this->my_addr))
1895 {
1896 this->my_addr->destroy(this->my_addr);
1897 this->my_addr = me->clone(me);
1898 }
1899 if (!other->equals(other, this->other_addr))
1900 {
1901 this->other_addr->destroy(this->other_addr);
1902 this->other_addr = other->clone(other);
1903 }
1904 }
1905
ea625fab 1906 this->encap = encap;
ad3af574 1907 set_state(this, old);
7a915d62 1908
1396815a
MW
1909 return SUCCESS;
1910}
1911
9d941742
TB
1912METHOD(child_sa_t, destroy, void,
1913 private_child_sa_t *this)
30b5b412 1914{
1df106bf
MW
1915 enumerator_t *enumerator;
1916 traffic_selector_t *my_ts, *other_ts;
fbedc6a4
TB
1917 policy_priority_t priority;
1918
c8f7a114 1919 priority = this->trap ? POLICY_PRIORITY_ROUTED : POLICY_PRIORITY_DEFAULT;
7daf5226 1920
a985db3f 1921 set_state(this, CHILD_DESTROYING);
7daf5226 1922
749ac175 1923 if (!this->config->has_option(this->config, OPT_NO_POLICIES))
695723d4 1924 {
a6e0f14f 1925 ipsec_sa_cfg_t my_sa, other_sa;
7f57c4f9 1926 uint32_t manual_prio;
c5fed4cd 1927 bool del_outbound;
a6e0f14f
TB
1928
1929 prepare_sa_cfg(this, &my_sa, &other_sa);
7f57c4f9 1930 manual_prio = this->config->get_manual_prio(this->config);
2c116ef5
TB
1931 del_outbound = (this->outbound_state & CHILD_OUTBOUND_POLICIES) ||
1932 this->trap;
a6e0f14f 1933
d487b4b7
AS
1934 /* delete all policies in the kernel */
1935 enumerator = create_policy_enumerator(this);
1936 while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
1937 {
529ffc2f
TB
1938 del_policies_internal(this, this->my_addr,
1939 this->other_addr, my_ts, other_ts, &my_sa, &other_sa,
1940 POLICY_IPSEC, priority, manual_prio, del_outbound);
d487b4b7
AS
1941 }
1942 enumerator->destroy(enumerator);
5d187bd2 1943 }
7daf5226 1944
bb87e63c
TB
1945 /* delete SAs in the kernel, if they are set up, inbound is always deleted
1946 * to remove allocated SPIs */
1947 if (this->my_spi)
46188b0e 1948 {
89da06ac
TB
1949 kernel_ipsec_sa_id_t id = {
1950 .src = this->other_addr,
1951 .dst = this->my_addr,
1952 .spi = this->my_spi,
1953 .proto = proto_ike2ip(this->protocol),
ea43f8ff 1954 .mark = mark_in_sa(this),
a6014d99 1955 .if_id = this->if_id_in,
89da06ac
TB
1956 };
1957 kernel_ipsec_del_sa_t sa = {
1958 .cpi = this->my_cpi,
1959 };
1960 charon->kernel->del_sa(charon->kernel, &id, &sa);
46188b0e 1961 }
2c116ef5 1962 if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
46188b0e 1963 {
89da06ac
TB
1964 kernel_ipsec_sa_id_t id = {
1965 .src = this->my_addr,
1966 .dst = this->other_addr,
1967 .spi = this->other_spi,
1968 .proto = proto_ike2ip(this->protocol),
1969 .mark = this->mark_out,
a6014d99 1970 .if_id = this->if_id_out,
89da06ac
TB
1971 };
1972 kernel_ipsec_del_sa_t sa = {
1973 .cpi = this->other_cpi,
1974 };
1975 charon->kernel->del_sa(charon->kernel, &id, &sa);
46188b0e
TB
1976 }
1977
13771206 1978 if (this->reqid_allocated || (!this->static_reqid && this->reqid))
0da97f50 1979 {
8394ea2a 1980 if (charon->kernel->release_reqid(charon->kernel,
02180ae2 1981 this->reqid) != SUCCESS)
0da97f50
MW
1982 {
1983 DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid);
1984 }
1985 }
1986
2745ae26
MW
1987 array_destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
1988 array_destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
80853d84
MW
1989 this->my_addr->destroy(this->my_addr);
1990 this->other_addr->destroy(this->other_addr);
1991 DESTROY_IF(this->proposal);
139d6558 1992 DESTROY_IF(this->label);
e0fe7651 1993 this->config->destroy(this->config);
8a3a389e
TB
1994 chunk_clear(&this->encr_r);
1995 chunk_clear(&this->integ_r);
5113680f 1996 free(this);
30b5b412
MW
1997}
1998
c6f1d0de
MW
1999/**
2000 * Get proxy address for one side, if any
2001 */
2002static host_t* get_proxy_addr(child_cfg_t *config, host_t *ike, bool local)
2003{
2004 host_t *host = NULL;
b12c53ce 2005 uint8_t mask;
c6f1d0de
MW
2006 enumerator_t *enumerator;
2007 linked_list_t *ts_list, *list;
2008 traffic_selector_t *ts;
2009
2010 list = linked_list_create_with_items(ike, NULL);
84cdfbc9 2011 ts_list = config->get_traffic_selectors(config, local, NULL, list, FALSE);
c6f1d0de
MW
2012 list->destroy(list);
2013
2014 enumerator = ts_list->create_enumerator(ts_list);
2015 while (enumerator->enumerate(enumerator, &ts))
2016 {
2017 if (ts->is_host(ts, NULL) && ts->to_subnet(ts, &host, &mask))
2018 {
2019 DBG1(DBG_CHD, "%s address: %H is a transport mode proxy for %H",
2020 local ? "my" : "other", ike, host);
2021 break;
2022 }
2023 }
2024 enumerator->destroy(enumerator);
2025 ts_list->destroy_offset(ts_list, offsetof(traffic_selector_t, destroy));
2026
2027 if (!host)
2028 {
2029 host = ike->clone(ike);
2030 }
2031 return host;
2032}
2033
fafa7698
TB
2034/*
2035 * Described in header
30b5b412 2036 */
fafa7698
TB
2037child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
2038 child_sa_create_t *data)
30b5b412 2039{
9d941742 2040 private_child_sa_t *this;
dde40bcb 2041 static refcount_t unique_id = 0;
9d941742
TB
2042
2043 INIT(this,
2044 .public = {
2045 .get_name = _get_name,
2046 .get_reqid = _get_reqid,
ff269f7f 2047 .get_reqid_ref = _get_reqid_ref,
4ec397b8 2048 .get_unique_id = _get_unique_id,
9d941742
TB
2049 .get_config = _get_config,
2050 .get_state = _get_state,
2051 .set_state = _set_state,
afbea8ce 2052 .get_outbound_state = _get_outbound_state,
9d941742
TB
2053 .get_spi = _get_spi,
2054 .get_cpi = _get_cpi,
2055 .get_protocol = _get_protocol,
2056 .set_protocol = _set_protocol,
2057 .get_mode = _get_mode,
2058 .set_mode = _set_mode,
2059 .get_proposal = _get_proposal,
2060 .set_proposal = _set_proposal,
2061 .get_lifetime = _get_lifetime,
763e0353 2062 .get_installtime = _get_installtime,
9d941742 2063 .get_usestats = _get_usestats,
79f39ecf 2064 .get_mark = _get_mark,
a6014d99 2065 .get_if_id = _get_if_id,
139d6558 2066 .get_label = _get_label,
9d941742
TB
2067 .has_encap = _has_encap,
2068 .get_ipcomp = _get_ipcomp,
2069 .set_ipcomp = _set_ipcomp,
2070 .get_close_action = _get_close_action,
2071 .set_close_action = _set_close_action,
2072 .get_dpd_action = _get_dpd_action,
2073 .set_dpd_action = _set_dpd_action,
2074 .alloc_spi = _alloc_spi,
2075 .alloc_cpi = _alloc_cpi,
2076 .install = _install,
8a3a389e
TB
2077 .register_outbound = _register_outbound,
2078 .install_outbound = _install_outbound,
c5fed4cd 2079 .remove_outbound = _remove_outbound,
cad13450
TB
2080 .set_rekey_spi = _set_rekey_spi,
2081 .get_rekey_spi = _get_rekey_spi,
9d941742 2082 .update = _update,
4989aba8
TB
2083 .set_policies = _set_policies,
2084 .install_policies = _install_policies,
553bb787 2085 .create_ts_enumerator = _create_ts_enumerator,
9d941742
TB
2086 .create_policy_enumerator = _create_policy_enumerator,
2087 .destroy = _destroy,
2088 },
fafa7698 2089 .encap = data->encap,
9d941742
TB
2090 .ipcomp = IPCOMP_NONE,
2091 .state = CHILD_CREATED,
2745ae26
MW
2092 .my_ts = array_create(0, 0),
2093 .other_ts = array_create(0, 0),
9d941742
TB
2094 .protocol = PROTO_NONE,
2095 .mode = MODE_TUNNEL,
2096 .close_action = config->get_close_action(config),
2097 .dpd_action = config->get_dpd_action(config),
2098 .reqid = config->get_reqid(config),
4aac88fa 2099 .unique_id = ref_get_nonzero(&unique_id),
9d941742
TB
2100 .mark_in = config->get_mark(config, TRUE),
2101 .mark_out = config->get_mark(config, FALSE),
fafa7698
TB
2102 .if_id_in = config->get_if_id(config, TRUE) ?: data->if_id_in_def,
2103 .if_id_out = config->get_if_id(config, FALSE) ?: data->if_id_out_def,
139d6558 2104 .label = data->label ? data->label->clone(data->label) : NULL,
763e0353 2105 .install_time = time_monotonic(NULL),
749ac175 2106 .policies_fwd_out = config->has_option(config, OPT_FWD_OUT_POLICIES),
9d941742
TB
2107 );
2108
e0fe7651
MW
2109 this->config = config;
2110 config->get_ref(config);
ee26c537 2111
fafa7698 2112 if (data->mark_in)
85b23888 2113 {
fafa7698 2114 this->mark_in.value = data->mark_in;
85b23888 2115 }
fafa7698 2116 if (data->mark_out)
85b23888 2117 {
fafa7698 2118 this->mark_out.value = data->mark_out;
85b23888 2119 }
fafa7698 2120 if (data->if_id_in)
a6014d99 2121 {
fafa7698 2122 this->if_id_in = data->if_id_in;
a6014d99 2123 }
fafa7698 2124 if (data->if_id_out)
a6014d99 2125 {
fafa7698 2126 this->if_id_out = data->if_id_out;
a6014d99 2127 }
32e5c492 2128
9347f724 2129 allocate_unique_if_ids(&this->if_id_in, &this->if_id_out);
dde40bcb 2130 allocate_unique_marks(&this->mark_in.value, &this->mark_out.value);
a6014d99 2131
71a66a62
RB
2132 if (!this->reqid)
2133 {
c9998e5f
TB
2134 /* reuse old reqid if we are rekeying an existing CHILD_SA and when
2135 * initiating a trap policy. While the reqid cache would find the same
2136 * reqid for our selectors, this does not work in a special case: If an
2137 * SA is triggered by a trap policy, but the negotiated TS get
2138 * narrowed, we still must reuse the same reqid to successfully
2139 * replace the temporary SA on the kernel level. Rekeying such an SA
2140 * requires an explicit reqid, as the cache currently knows the original
2141 * selectors only for that reqid. */
13771206
TB
2142 if (data->reqid &&
2143 charon->kernel->ref_reqid(charon->kernel, data->reqid) == SUCCESS)
2144 {
2145 this->reqid = data->reqid;
2146 }
71a66a62 2147 }
3665adef
TB
2148 else
2149 {
2150 this->static_reqid = TRUE;
2151 }
7daf5226 2152
dd83c6d4 2153 /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
d487b4b7 2154 if (config->get_mode(config) == MODE_TRANSPORT &&
749ac175 2155 config->has_option(config, OPT_PROXY_MODE))
d487b4b7 2156 {
d487b4b7 2157 this->mode = MODE_TRANSPORT;
7daf5226 2158
c6f1d0de
MW
2159 this->my_addr = get_proxy_addr(config, me, TRUE);
2160 this->other_addr = get_proxy_addr(config, other, FALSE);
2161 }
2162 else
2163 {
2164 this->my_addr = me->clone(me);
2165 this->other_addr = other->clone(other);
d487b4b7 2166 }
1396815a 2167 return &this->public;
3ebebc5e 2168}