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