]>
Commit | Line | Data |
---|---|---|
3ebebc5e | 1 | /* |
cb123493 | 2 | * Copyright (C) 2006-2009 Tobias Brunner |
a985db3f | 3 | * Copyright (C) 2005-2008 Martin Willi |
d4aad554 | 4 | * Copyright (C) 2006 Daniel Roethlisberger |
c71d53ba | 5 | * Copyright (C) 2005 Jan Hutter |
3ebebc5e MW |
6 | * Hochschule fuer Technik Rapperswil |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by the | |
10 | * Free Software Foundation; either version 2 of the License, or (at your | |
11 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
15 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | * for more details. | |
17 | */ | |
18 | ||
60356f33 | 19 | #define _GNU_SOURCE |
b92eef28 | 20 | #include "child_sa.h" |
3ebebc5e | 21 | |
a095243f | 22 | #include <stdio.h> |
4c23a8c9 | 23 | #include <string.h> |
e13389a7 | 24 | #include <time.h> |
4c23a8c9 | 25 | |
aeda79ff MW |
26 | #include <daemon.h> |
27 | ||
a985db3f | 28 | ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING, |
60356f33 MW |
29 | "CREATED", |
30 | "ROUTED", | |
ea625fab | 31 | "INSTALLING", |
60356f33 | 32 | "INSTALLED", |
ad3af574 | 33 | "UPDATING", |
60356f33 MW |
34 | "REKEYING", |
35 | "DELETING", | |
a985db3f | 36 | "DESTROYING", |
60356f33 | 37 | ); |
bcb95ced | 38 | |
3ebebc5e MW |
39 | typedef struct private_child_sa_t private_child_sa_t; |
40 | ||
41 | /** | |
7b8bae99 | 42 | * Private data of a child_sa_t object. |
3ebebc5e MW |
43 | */ |
44 | struct private_child_sa_t { | |
45 | /** | |
144f676c | 46 | * Public interface of child_sa_t. |
3ebebc5e MW |
47 | */ |
48 | child_sa_t public; | |
7daf5226 | 49 | |
80853d84 MW |
50 | /** |
51 | * address of us | |
52 | */ | |
53 | host_t *my_addr; | |
7daf5226 | 54 | |
3efbf983 | 55 | /** |
80853d84 | 56 | * address of remote |
3efbf983 | 57 | */ |
80853d84 | 58 | host_t *other_addr; |
7daf5226 | 59 | |
3efbf983 | 60 | /** |
80853d84 | 61 | * our actually used SPI, 0 if unused |
3efbf983 | 62 | */ |
80853d84 | 63 | u_int32_t my_spi; |
7daf5226 | 64 | |
aeda79ff | 65 | /** |
80853d84 | 66 | * others used SPI, 0 if unused |
aeda79ff | 67 | */ |
80853d84 | 68 | u_int32_t other_spi; |
7daf5226 | 69 | |
8dfbe71b | 70 | /** |
80853d84 | 71 | * our Compression Parameter Index (CPI) used, 0 if unused |
8dfbe71b | 72 | */ |
80853d84 | 73 | u_int16_t my_cpi; |
7daf5226 | 74 | |
8dfbe71b | 75 | /** |
80853d84 | 76 | * others Compression Parameter Index (CPI) used, 0 if unused |
8dfbe71b | 77 | */ |
80853d84 | 78 | u_int16_t other_cpi; |
7daf5226 | 79 | |
5d187bd2 | 80 | /** |
80853d84 | 81 | * List for local traffic selectors |
5d187bd2 | 82 | */ |
80853d84 | 83 | linked_list_t *my_ts; |
7daf5226 | 84 | |
80853d84 MW |
85 | /** |
86 | * List for remote traffic selectors | |
87 | */ | |
88 | linked_list_t *other_ts; | |
7daf5226 | 89 | |
c0593835 | 90 | /** |
80853d84 | 91 | * Protocol used to protect this SA, ESP|AH |
c0593835 | 92 | */ |
80853d84 | 93 | protocol_id_t protocol; |
7daf5226 | 94 | |
3c7e72f5 | 95 | /** |
80853d84 | 96 | * reqid used for this child_sa |
3c7e72f5 | 97 | */ |
80853d84 | 98 | u_int32_t reqid; |
7daf5226 | 99 | |
ee26c537 AS |
100 | /** |
101 | * inbound mark used for this child_sa | |
102 | */ | |
103 | mark_t mark_in; | |
104 | ||
105 | /** | |
106 | * outbound mark used for this child_sa | |
107 | */ | |
108 | mark_t mark_out; | |
109 | ||
a2a3fb3e | 110 | /** |
6e10aead | 111 | * absolute time when rekeying is scheduled |
a2a3fb3e | 112 | */ |
6e10aead | 113 | time_t rekey_time; |
7daf5226 | 114 | |
e70d5576 | 115 | /** |
6e10aead | 116 | * absolute time when the SA expires |
e70d5576 | 117 | */ |
6e10aead | 118 | time_t expire_time; |
7daf5226 | 119 | |
bcb95ced MW |
120 | /** |
121 | * state of the CHILD_SA | |
122 | */ | |
123 | child_sa_state_t state; | |
fff4ee8a | 124 | |
1239c6f4 | 125 | /** |
fc2d1c42 | 126 | * Specifies if UDP encapsulation is enabled (NAT traversal) |
1239c6f4 | 127 | */ |
fc2d1c42 | 128 | bool encap; |
7daf5226 | 129 | |
d4aad554 TB |
130 | /** |
131 | * Specifies the IPComp transform used (IPCOMP_NONE if disabled) | |
132 | */ | |
133 | ipcomp_transform_t ipcomp; | |
7daf5226 | 134 | |
7652be89 MW |
135 | /** |
136 | * mode this SA uses, tunnel/transport | |
137 | */ | |
a341a68f | 138 | ipsec_mode_t mode; |
7daf5226 | 139 | |
4c401ea2 MW |
140 | /** |
141 | * Action to enforce if peer closes the CHILD_SA | |
142 | */ | |
143 | action_t close_action; | |
144 | ||
145 | /** | |
146 | * Action to enforce if peer is considered dead | |
147 | */ | |
148 | action_t dpd_action; | |
149 | ||
80853d84 | 150 | /** |
7b3814f7 MW |
151 | * selected proposal |
152 | */ | |
153 | proposal_t *proposal; | |
7daf5226 | 154 | |
c60c7694 | 155 | /** |
e0fe7651 | 156 | * config used to create this child |
c60c7694 | 157 | */ |
e0fe7651 | 158 | child_cfg_t *config; |
3f720dc7 AS |
159 | |
160 | /** | |
161 | * time of last use in seconds (inbound) | |
162 | */ | |
163 | u_int32_t my_usetime; | |
164 | ||
165 | /** | |
166 | * time of last use in seconds (outbound) | |
167 | */ | |
168 | u_int32_t other_usetime; | |
169 | ||
170 | /** | |
171 | * last number of inbound bytes | |
172 | */ | |
173 | u_int64_t my_usebytes; | |
174 | ||
175 | /** | |
176 | * last number of outbound bytes | |
177 | */ | |
178 | u_int64_t other_usebytes; | |
3ebebc5e MW |
179 | }; |
180 | ||
e517b4b1 | 181 | /** |
d487b4b7 | 182 | * Implementation of child_sa_t.get_name |
9be547c0 MW |
183 | */ |
184 | static char *get_name(private_child_sa_t *this) | |
185 | { | |
e0fe7651 | 186 | return this->config->get_name(this->config); |
9be547c0 MW |
187 | } |
188 | ||
32b6500f MW |
189 | /** |
190 | * Implements child_sa_t.get_reqid | |
191 | */ | |
192 | static u_int32_t get_reqid(private_child_sa_t *this) | |
193 | { | |
194 | return this->reqid; | |
195 | } | |
3aaf7908 MW |
196 | |
197 | /** | |
198 | * Implements child_sa_t.get_config | |
199 | */ | |
200 | static child_cfg_t* get_config(private_child_sa_t *this) | |
201 | { | |
202 | return this->config; | |
203 | } | |
204 | ||
205 | /** | |
206 | * Implements child_sa_t.set_state | |
207 | */ | |
208 | static void set_state(private_child_sa_t *this, child_sa_state_t state) | |
209 | { | |
210 | charon->bus->child_state_change(charon->bus, &this->public, state); | |
211 | this->state = state; | |
212 | } | |
213 | ||
214 | /** | |
215 | * Implements child_sa_t.get_state | |
216 | */ | |
217 | static child_sa_state_t get_state(private_child_sa_t *this) | |
218 | { | |
219 | return this->state; | |
220 | } | |
221 | ||
8d77edde MW |
222 | /** |
223 | * Implements child_sa_t.get_spi | |
224 | */ | |
225 | u_int32_t get_spi(private_child_sa_t *this, bool inbound) | |
226 | { | |
80853d84 | 227 | return inbound ? this->my_spi : this->other_spi; |
8d77edde MW |
228 | } |
229 | ||
66da78b4 AS |
230 | /** |
231 | * Implements child_sa_t.get_cpi | |
232 | */ | |
233 | u_int16_t get_cpi(private_child_sa_t *this, bool inbound) | |
234 | { | |
80853d84 | 235 | return inbound ? this->my_cpi : this->other_cpi; |
66da78b4 AS |
236 | } |
237 | ||
8d77edde MW |
238 | /** |
239 | * Implements child_sa_t.get_protocol | |
240 | */ | |
241 | protocol_id_t get_protocol(private_child_sa_t *this) | |
242 | { | |
243 | return this->protocol; | |
244 | } | |
32b6500f | 245 | |
3aaf7908 MW |
246 | /** |
247 | * Implementation of child_sa_t.set_protocol | |
248 | */ | |
249 | static void set_protocol(private_child_sa_t *this, protocol_id_t protocol) | |
250 | { | |
251 | this->protocol = protocol; | |
252 | } | |
253 | ||
80853d84 MW |
254 | /** |
255 | * Implementation of child_sa_t.get_mode | |
256 | */ | |
257 | static ipsec_mode_t get_mode(private_child_sa_t *this) | |
258 | { | |
259 | return this->mode; | |
260 | } | |
261 | ||
3aaf7908 MW |
262 | /** |
263 | * Implementation of child_sa_t.set_mode | |
264 | */ | |
265 | static void set_mode(private_child_sa_t *this, ipsec_mode_t mode) | |
266 | { | |
267 | this->mode = mode; | |
268 | } | |
269 | ||
82d20c05 MW |
270 | /** |
271 | * Implementation of child_sa_t.has_encap | |
272 | */ | |
273 | static bool has_encap(private_child_sa_t *this) | |
274 | { | |
275 | return this->encap; | |
276 | } | |
277 | ||
278 | /** | |
279 | * Implementation of child_sa_t.get_ipcomp | |
280 | */ | |
281 | static ipcomp_transform_t get_ipcomp(private_child_sa_t *this) | |
282 | { | |
283 | return this->ipcomp; | |
284 | } | |
285 | ||
bcb95ced | 286 | /** |
3aaf7908 | 287 | * Implementation of child_sa_t.set_ipcomp. |
bcb95ced | 288 | */ |
3aaf7908 | 289 | static void set_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp) |
bcb95ced | 290 | { |
3aaf7908 | 291 | this->ipcomp = ipcomp; |
bcb95ced MW |
292 | } |
293 | ||
4c401ea2 MW |
294 | /** |
295 | * Implementation of child_sa_t.set_close_action. | |
296 | */ | |
297 | static void set_close_action(private_child_sa_t *this, action_t action) | |
298 | { | |
299 | this->close_action = action; | |
300 | } | |
301 | ||
302 | /** | |
303 | * Implementation of child_sa_t.get_close_action. | |
304 | */ | |
305 | static action_t get_close_action(private_child_sa_t *this) | |
306 | { | |
307 | return this->close_action; | |
308 | } | |
309 | ||
310 | /** | |
311 | * Implementation of child_sa_t.set_dpd_action. | |
312 | */ | |
313 | static void set_dpd_action(private_child_sa_t *this, action_t action) | |
314 | { | |
315 | this->dpd_action = action; | |
316 | } | |
317 | ||
318 | /** | |
319 | * Implementation of child_sa_t.get_dpd_action. | |
320 | */ | |
321 | static action_t get_dpd_action(private_child_sa_t *this) | |
322 | { | |
323 | return this->dpd_action; | |
324 | } | |
325 | ||
c60c7694 | 326 | /** |
3aaf7908 | 327 | * Implementation of child_sa_t.get_proposal |
c60c7694 | 328 | */ |
3aaf7908 | 329 | static proposal_t* get_proposal(private_child_sa_t *this) |
c60c7694 | 330 | { |
3aaf7908 MW |
331 | return this->proposal; |
332 | } | |
333 | ||
334 | /** | |
335 | * Implementation of child_sa_t.set_proposal | |
336 | */ | |
337 | static void set_proposal(private_child_sa_t *this, proposal_t *proposal) | |
338 | { | |
339 | this->proposal = proposal->clone(proposal); | |
340 | } | |
341 | ||
342 | /** | |
343 | * Implementation of child_sa_t.get_traffic_selectors. | |
344 | */ | |
345 | static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local) | |
346 | { | |
347 | return local ? this->my_ts : this->other_ts; | |
c60c7694 MW |
348 | } |
349 | ||
1df106bf MW |
350 | typedef struct policy_enumerator_t policy_enumerator_t; |
351 | ||
352 | /** | |
353 | * Private policy enumerator | |
354 | */ | |
355 | struct policy_enumerator_t { | |
356 | /** implements enumerator_t */ | |
357 | enumerator_t public; | |
358 | /** enumerator over own TS */ | |
359 | enumerator_t *mine; | |
360 | /** enumerator over others TS */ | |
361 | enumerator_t *other; | |
362 | /** list of others TS, to recreate enumerator */ | |
363 | linked_list_t *list; | |
6df2837a MW |
364 | /** currently enumerating TS for "me" side */ |
365 | traffic_selector_t *ts; | |
1df106bf MW |
366 | }; |
367 | ||
368 | /** | |
369 | * enumerator function of create_policy_enumerator() | |
370 | */ | |
371 | static bool policy_enumerate(policy_enumerator_t *this, | |
372 | traffic_selector_t **my_out, traffic_selector_t **other_out) | |
373 | { | |
6df2837a | 374 | traffic_selector_t *other_ts; |
7daf5226 | 375 | |
6df2837a | 376 | while (this->ts || this->mine->enumerate(this->mine, &this->ts)) |
1df106bf | 377 | { |
6df2837a MW |
378 | if (!this->other->enumerate(this->other, &other_ts)) |
379 | { /* end of others list, restart with new of mine */ | |
380 | this->other->destroy(this->other); | |
381 | this->other = this->list->create_enumerator(this->list); | |
382 | this->ts = NULL; | |
383 | continue; | |
384 | } | |
385 | if (this->ts->get_type(this->ts) != other_ts->get_type(other_ts)) | |
386 | { /* family mismatch */ | |
387 | continue; | |
388 | } | |
389 | if (this->ts->get_protocol(this->ts) && | |
390 | other_ts->get_protocol(other_ts) && | |
391 | this->ts->get_protocol(this->ts) != other_ts->get_protocol(other_ts)) | |
392 | { /* protocol mismatch */ | |
393 | continue; | |
1df106bf | 394 | } |
6df2837a MW |
395 | *my_out = this->ts; |
396 | *other_out = other_ts; | |
397 | return TRUE; | |
1df106bf MW |
398 | } |
399 | return FALSE; | |
400 | } | |
401 | ||
402 | /** | |
403 | * destroy function of create_policy_enumerator() | |
404 | */ | |
405 | static void policy_destroy(policy_enumerator_t *this) | |
406 | { | |
407 | this->mine->destroy(this->mine); | |
408 | this->other->destroy(this->other); | |
409 | free(this); | |
410 | } | |
411 | ||
412 | /** | |
413 | * Implementation of child_sa_t.create_policy_enumerator | |
414 | */ | |
415 | static enumerator_t* create_policy_enumerator(private_child_sa_t *this) | |
416 | { | |
417 | policy_enumerator_t *e = malloc_thing(policy_enumerator_t); | |
7daf5226 | 418 | |
1df106bf MW |
419 | e->public.enumerate = (void*)policy_enumerate; |
420 | e->public.destroy = (void*)policy_destroy; | |
421 | e->mine = this->my_ts->create_enumerator(this->my_ts); | |
422 | e->other = this->other_ts->create_enumerator(this->other_ts); | |
423 | e->list = this->other_ts; | |
6df2837a | 424 | e->ts = NULL; |
7daf5226 | 425 | |
1df106bf MW |
426 | return &e->public; |
427 | } | |
428 | ||
dd83c6d4 TB |
429 | /** |
430 | * update the cached usebytes | |
431 | * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs | |
432 | * are available, and NOT_SUPPORTED if the kernel interface does not support | |
99dd4291 | 433 | * querying the usebytes. |
dd83c6d4 | 434 | */ |
c3a78360 | 435 | static status_t update_usebytes(private_child_sa_t *this, bool inbound) |
dd83c6d4 TB |
436 | { |
437 | status_t status = FAILED; | |
438 | u_int64_t bytes; | |
7daf5226 | 439 | |
dd83c6d4 TB |
440 | if (inbound) |
441 | { | |
442 | if (this->my_spi) | |
443 | { | |
ee26c537 | 444 | status = charon->kernel_interface->query_sa(charon->kernel_interface, |
dd83c6d4 | 445 | this->other_addr, this->my_addr, |
ee26c537 AS |
446 | this->my_spi, this->protocol, |
447 | this->mark_in, &bytes); | |
dd83c6d4 TB |
448 | if (status == SUCCESS) |
449 | { | |
450 | if (bytes > this->my_usebytes) | |
451 | { | |
452 | this->my_usebytes = bytes; | |
453 | return SUCCESS; | |
454 | } | |
455 | return FAILED; | |
456 | } | |
457 | } | |
458 | } | |
459 | else | |
460 | { | |
461 | if (this->other_spi) | |
462 | { | |
ee26c537 | 463 | status = charon->kernel_interface->query_sa(charon->kernel_interface, |
dd83c6d4 | 464 | this->my_addr, this->other_addr, |
ee26c537 AS |
465 | this->other_spi, this->protocol, |
466 | this->mark_out, &bytes); | |
dd83c6d4 TB |
467 | if (status == SUCCESS) |
468 | { | |
469 | if (bytes > this->other_usebytes) | |
470 | { | |
471 | this->other_usebytes = bytes; | |
472 | return SUCCESS; | |
473 | } | |
474 | return FAILED; | |
475 | } | |
476 | } | |
477 | } | |
478 | return status; | |
479 | } | |
480 | ||
a3ce4bc2 | 481 | /** |
c3a78360 | 482 | * updates the cached usetime |
a3ce4bc2 | 483 | */ |
c3a78360 | 484 | static void update_usetime(private_child_sa_t *this, bool inbound) |
a3ce4bc2 | 485 | { |
1df106bf | 486 | enumerator_t *enumerator; |
6e10aead MW |
487 | traffic_selector_t *my_ts, *other_ts; |
488 | u_int32_t last_use = 0; | |
7daf5226 | 489 | |
1df106bf MW |
490 | enumerator = create_policy_enumerator(this); |
491 | while (enumerator->enumerate(enumerator, &my_ts, &other_ts)) | |
a3ce4bc2 | 492 | { |
6e10aead | 493 | u_int32_t in, out, fwd; |
7daf5226 | 494 | |
dd83c6d4 | 495 | if (inbound) |
a3ce4bc2 | 496 | { |
6e10aead | 497 | if (charon->kernel_interface->query_policy(charon->kernel_interface, |
ee26c537 | 498 | other_ts, my_ts, POLICY_IN, this->mark_in, &in) == SUCCESS) |
6e10aead MW |
499 | { |
500 | last_use = max(last_use, in); | |
501 | } | |
ce42db09 | 502 | if (this->mode != MODE_TRANSPORT) |
6e10aead | 503 | { |
d487b4b7 | 504 | if (charon->kernel_interface->query_policy(charon->kernel_interface, |
ee26c537 | 505 | other_ts, my_ts, POLICY_FWD, this->mark_in, &fwd) == SUCCESS) |
d487b4b7 AS |
506 | { |
507 | last_use = max(last_use, fwd); | |
508 | } | |
6e10aead | 509 | } |
a3ce4bc2 | 510 | } |
6e10aead | 511 | else |
a3ce4bc2 | 512 | { |
6e10aead | 513 | if (charon->kernel_interface->query_policy(charon->kernel_interface, |
ee26c537 | 514 | my_ts, other_ts, POLICY_OUT, this->mark_out, &out) == SUCCESS) |
6e10aead MW |
515 | { |
516 | last_use = max(last_use, out); | |
517 | } | |
a3ce4bc2 MW |
518 | } |
519 | } | |
1df106bf | 520 | enumerator->destroy(enumerator); |
99dd4291 AS |
521 | |
522 | if (last_use == 0) | |
523 | { | |
524 | return; | |
525 | } | |
3f720dc7 AS |
526 | if (inbound) |
527 | { | |
528 | this->my_usetime = last_use; | |
529 | } | |
530 | else | |
531 | { | |
532 | this->other_usetime = last_use; | |
533 | } | |
6e10aead MW |
534 | } |
535 | ||
2ad51539 | 536 | /** |
c3a78360 | 537 | * Implementation of child_sa_t.get_usestats |
2ad51539 | 538 | */ |
c3a78360 TB |
539 | static void get_usestats(private_child_sa_t *this, bool inbound, |
540 | time_t *time, u_int64_t *bytes) | |
2ad51539 | 541 | { |
c3a78360 | 542 | if (update_usebytes(this, inbound) != FAILED) |
99dd4291 AS |
543 | { |
544 | /* there was traffic since last update or the kernel interface | |
545 | * does not support querying the number of usebytes. | |
546 | */ | |
c3a78360 TB |
547 | update_usetime(this, inbound); |
548 | } | |
549 | if (time) | |
550 | { | |
551 | *time = inbound ? this->my_usetime : this->other_usetime; | |
552 | } | |
553 | if (bytes) | |
554 | { | |
555 | *bytes = inbound ? this->my_usebytes : this->other_usebytes; | |
556 | } | |
2ad51539 AS |
557 | } |
558 | ||
6e10aead MW |
559 | /** |
560 | * Implementation of child_sa_t.get_lifetime | |
561 | */ | |
e3c7e729 | 562 | static time_t get_lifetime(private_child_sa_t *this, bool hard) |
6e10aead | 563 | { |
80853d84 | 564 | return hard ? this->expire_time : this->rekey_time; |
a3ce4bc2 MW |
565 | } |
566 | ||
bcb95ced | 567 | /** |
3aaf7908 | 568 | * Implementation of child_sa_t.alloc_spi |
1396815a | 569 | */ |
3aaf7908 | 570 | static u_int32_t alloc_spi(private_child_sa_t *this, protocol_id_t protocol) |
1396815a | 571 | { |
64e8ca28 MW |
572 | if (charon->kernel_interface->get_spi(charon->kernel_interface, |
573 | this->other_addr, this->my_addr, protocol, | |
3aaf7908 | 574 | this->reqid, &this->my_spi) == SUCCESS) |
64e8ca28 MW |
575 | { |
576 | return this->my_spi; | |
1396815a | 577 | } |
3aaf7908 | 578 | return 0; |
1396815a MW |
579 | } |
580 | ||
3ebebc5e | 581 | /** |
3aaf7908 | 582 | * Implementation of child_sa_t.alloc_cpi |
3ebebc5e | 583 | */ |
3aaf7908 | 584 | static u_int16_t alloc_cpi(private_child_sa_t *this) |
3ebebc5e | 585 | { |
3aaf7908 MW |
586 | if (charon->kernel_interface->get_cpi(charon->kernel_interface, |
587 | this->other_addr, this->my_addr, this->reqid, | |
588 | &this->my_cpi) == SUCCESS) | |
30b5b412 | 589 | { |
3aaf7908 | 590 | return this->my_cpi; |
30b5b412 | 591 | } |
3aaf7908 | 592 | return 0; |
3ebebc5e MW |
593 | } |
594 | ||
80853d84 | 595 | /** |
3aaf7908 | 596 | * Implementation of child_sa_t.install |
80853d84 | 597 | */ |
3aaf7908 | 598 | static status_t install(private_child_sa_t *this, chunk_t encr, chunk_t integ, |
6ec949e0 MW |
599 | u_int32_t spi, u_int16_t cpi, bool inbound, |
600 | linked_list_t *my_ts, linked_list_t *other_ts) | |
3ebebc5e | 601 | { |
80853d84 | 602 | u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size; |
6ec949e0 | 603 | traffic_selector_t *src_ts = NULL, *dst_ts = NULL; |
cb123493 TB |
604 | time_t now; |
605 | lifetime_cfg_t *lifetime; | |
e517b4b1 | 606 | host_t *src, *dst; |
30b5b412 | 607 | status_t status; |
3aaf7908 | 608 | bool update = FALSE; |
7daf5226 | 609 | |
80853d84 MW |
610 | /* now we have to decide which spi to use. Use self allocated, if "in", |
611 | * or the one in the proposal, if not "in" (others). Additionally, | |
3efbf983 | 612 | * source and dest host switch depending on the role */ |
3aaf7908 | 613 | if (inbound) |
aeda79ff | 614 | { |
80853d84 MW |
615 | dst = this->my_addr; |
616 | src = this->other_addr; | |
3aaf7908 MW |
617 | if (this->my_spi == spi) |
618 | { /* alloc_spi has been called, do an SA update */ | |
619 | update = TRUE; | |
620 | } | |
621 | this->my_spi = spi; | |
622 | this->my_cpi = cpi; | |
aeda79ff | 623 | } |
8d77edde MW |
624 | else |
625 | { | |
80853d84 MW |
626 | src = this->my_addr; |
627 | dst = this->other_addr; | |
3aaf7908 MW |
628 | this->other_spi = spi; |
629 | this->other_cpi = cpi; | |
8d77edde | 630 | } |
7daf5226 | 631 | |
3aaf7908 | 632 | DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound", |
60356f33 | 633 | protocol_id_names, this->protocol); |
7daf5226 | 634 | |
5c131a01 | 635 | /* send SA down to the kernel */ |
b83806d8 | 636 | DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst); |
7daf5226 | 637 | |
3aaf7908 MW |
638 | this->proposal->get_algorithm(this->proposal, ENCRYPTION_ALGORITHM, |
639 | &enc_alg, &size); | |
640 | this->proposal->get_algorithm(this->proposal, INTEGRITY_ALGORITHM, | |
641 | &int_alg, &size); | |
7daf5226 | 642 | |
cb123493 | 643 | lifetime = this->config->get_lifetime(this->config); |
7daf5226 | 644 | |
6180a558 | 645 | now = time_monotonic(NULL); |
e75f4237 | 646 | if (lifetime->time.rekey) |
37974979 | 647 | { |
e75f4237 | 648 | this->rekey_time = now + lifetime->time.rekey; |
37974979 | 649 | } |
e75f4237 | 650 | if (lifetime->time.life) |
37974979 | 651 | { |
e75f4237 | 652 | this->expire_time = now + lifetime->time.life; |
cb123493 | 653 | } |
7daf5226 | 654 | |
e75f4237 | 655 | if (!lifetime->time.jitter && !inbound) |
cb123493 | 656 | { /* avoid triggering multiple rekey events */ |
e75f4237 | 657 | lifetime->time.rekey = 0; |
37974979 | 658 | } |
7daf5226 | 659 | |
6ec949e0 MW |
660 | if (this->mode == MODE_BEET) |
661 | { | |
662 | /* BEET requires the bound address from the traffic selectors. | |
663 | * TODO: We add just the first traffic selector for now, as the | |
664 | * kernel accepts a single TS per SA only */ | |
665 | if (inbound) | |
666 | { | |
667 | my_ts->get_first(my_ts, (void**)&dst_ts); | |
668 | other_ts->get_first(other_ts, (void**)&src_ts); | |
669 | } | |
670 | else | |
671 | { | |
672 | my_ts->get_first(my_ts, (void**)&src_ts); | |
673 | other_ts->get_first(other_ts, (void**)&dst_ts); | |
674 | } | |
675 | } | |
676 | ||
cb123493 | 677 | status = charon->kernel_interface->add_sa(charon->kernel_interface, |
ee26c537 AS |
678 | src, dst, spi, this->protocol, this->reqid, |
679 | inbound ? this->mark_in : this->mark_out, | |
680 | lifetime, enc_alg, encr, int_alg, integ, this->mode, | |
681 | this->ipcomp, cpi, this->encap, update, src_ts, dst_ts); | |
7daf5226 | 682 | |
cb123493 | 683 | free(lifetime); |
7daf5226 | 684 | |
8d77edde | 685 | return status; |
30b5b412 MW |
686 | } |
687 | ||
80853d84 MW |
688 | /** |
689 | * Implementation of child_sa_t.add_policies | |
690 | */ | |
7652be89 | 691 | static status_t add_policies(private_child_sa_t *this, |
3aaf7908 | 692 | linked_list_t *my_ts_list, linked_list_t *other_ts_list) |
a527a426 | 693 | { |
1df106bf | 694 | enumerator_t *enumerator; |
5d187bd2 | 695 | traffic_selector_t *my_ts, *other_ts; |
1df106bf | 696 | status_t status = SUCCESS; |
ea625fab | 697 | bool routed = (this->state == CHILD_CREATED); |
7daf5226 | 698 | |
1df106bf MW |
699 | /* apply traffic selectors */ |
700 | enumerator = my_ts_list->create_enumerator(my_ts_list); | |
701 | while (enumerator->enumerate(enumerator, &my_ts)) | |
a527a426 | 702 | { |
1df106bf MW |
703 | this->my_ts->insert_last(this->my_ts, my_ts->clone(my_ts)); |
704 | } | |
705 | enumerator->destroy(enumerator); | |
706 | enumerator = other_ts_list->create_enumerator(other_ts_list); | |
707 | while (enumerator->enumerate(enumerator, &other_ts)) | |
708 | { | |
709 | this->other_ts->insert_last(this->other_ts, other_ts->clone(other_ts)); | |
710 | } | |
711 | enumerator->destroy(enumerator); | |
7daf5226 | 712 | |
d487b4b7 | 713 | if (this->config->install_policy(this->config)) |
1df106bf | 714 | { |
d487b4b7 AS |
715 | /* enumerate pairs of traffic selectors */ |
716 | enumerator = create_policy_enumerator(this); | |
717 | while (enumerator->enumerate(enumerator, &my_ts, &other_ts)) | |
718 | { | |
719 | /* install 3 policies: out, in and forward */ | |
720 | status |= charon->kernel_interface->add_policy(charon->kernel_interface, | |
721 | this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT, | |
ee26c537 AS |
722 | this->other_spi, this->protocol, this->reqid, this->mark_out, |
723 | this->mode, this->ipcomp, this->other_cpi, routed); | |
7daf5226 | 724 | |
d487b4b7 AS |
725 | status |= charon->kernel_interface->add_policy(charon->kernel_interface, |
726 | this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN, | |
ee26c537 AS |
727 | this->my_spi, this->protocol, this->reqid, this->mark_in, |
728 | this->mode, this->ipcomp, this->my_cpi, routed); | |
3aaf7908 | 729 | if (this->mode != MODE_TRANSPORT) |
d487b4b7 AS |
730 | { |
731 | status |= charon->kernel_interface->add_policy(charon->kernel_interface, | |
ea625fab | 732 | this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD, |
ee26c537 AS |
733 | this->my_spi, this->protocol, this->reqid, this->mark_in, |
734 | this->mode, this->ipcomp, this->my_cpi, routed); | |
d487b4b7 | 735 | } |
7daf5226 | 736 | |
d487b4b7 AS |
737 | if (status != SUCCESS) |
738 | { | |
739 | break; | |
740 | } | |
5d187bd2 | 741 | } |
d487b4b7 | 742 | enumerator->destroy(enumerator); |
5d187bd2 | 743 | } |
7daf5226 | 744 | |
3aaf7908 MW |
745 | if (status == SUCCESS && this->state == CHILD_CREATED) |
746 | { /* switch to routed state if no SAD entry set up */ | |
747 | set_state(this, CHILD_ROUTED); | |
45f76a7d | 748 | } |
1df106bf | 749 | return status; |
30b5b412 MW |
750 | } |
751 | ||
8dfbe71b | 752 | /** |
3aaf7908 | 753 | * Implementation of child_sa_t.update. |
8dfbe71b | 754 | */ |
3aaf7908 | 755 | static status_t update(private_child_sa_t *this, host_t *me, host_t *other, |
dd83c6d4 | 756 | host_t *vip, bool encap) |
1396815a | 757 | { |
ad3af574 | 758 | child_sa_state_t old; |
08c6ed9f | 759 | bool transport_proxy_mode; |
7daf5226 | 760 | |
2b3100b5 | 761 | /* anything changed at all? */ |
dd83c6d4 | 762 | if (me->equals(me, this->my_addr) && |
80853d84 | 763 | other->equals(other, this->other_addr) && this->encap == encap) |
1396815a MW |
764 | { |
765 | return SUCCESS; | |
766 | } | |
7daf5226 | 767 | |
ad3af574 MW |
768 | old = this->state; |
769 | set_state(this, CHILD_UPDATING); | |
08c6ed9f AS |
770 | transport_proxy_mode = this->config->use_proxy_mode(this->config) && |
771 | this->mode == MODE_TRANSPORT; | |
7daf5226 | 772 | |
08c6ed9f | 773 | if (!transport_proxy_mode) |
ea625fab | 774 | { |
7a915d62 AS |
775 | /* update our (initator) SA */ |
776 | if (this->my_spi) | |
777 | { | |
778 | if (charon->kernel_interface->update_sa(charon->kernel_interface, | |
779 | this->my_spi, this->protocol, | |
780 | this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0, | |
781 | this->other_addr, this->my_addr, other, me, | |
ee26c537 | 782 | this->encap, encap, this->mark_in) == NOT_SUPPORTED) |
7a915d62 AS |
783 | { |
784 | return NOT_SUPPORTED; | |
785 | } | |
786 | } | |
7daf5226 | 787 | |
7a915d62 AS |
788 | /* update his (responder) SA */ |
789 | if (this->other_spi) | |
790 | { | |
791 | if (charon->kernel_interface->update_sa(charon->kernel_interface, | |
792 | this->other_spi, this->protocol, | |
b9b8a98f | 793 | this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0, |
7a915d62 | 794 | this->my_addr, this->other_addr, me, other, |
ee26c537 | 795 | this->encap, encap, this->mark_out) == NOT_SUPPORTED) |
7a915d62 AS |
796 | { |
797 | return NOT_SUPPORTED; | |
798 | } | |
799 | } | |
ea625fab | 800 | } |
7daf5226 | 801 | |
d487b4b7 | 802 | if (this->config->install_policy(this->config)) |
1396815a | 803 | { |
d487b4b7 AS |
804 | /* update policies */ |
805 | if (!me->ip_equals(me, this->my_addr) || | |
806 | !other->ip_equals(other, this->other_addr)) | |
1396815a | 807 | { |
d487b4b7 AS |
808 | enumerator_t *enumerator; |
809 | traffic_selector_t *my_ts, *other_ts; | |
7daf5226 | 810 | |
d487b4b7 AS |
811 | /* always use high priorities, as hosts getting updated are INSTALLED */ |
812 | enumerator = create_policy_enumerator(this); | |
813 | while (enumerator->enumerate(enumerator, &my_ts, &other_ts)) | |
814 | { | |
815 | /* remove old policies first */ | |
816 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
ee26c537 | 817 | my_ts, other_ts, POLICY_OUT, this->mark_out, FALSE); |
d487b4b7 | 818 | charon->kernel_interface->del_policy(charon->kernel_interface, |
ee26c537 | 819 | other_ts, my_ts, POLICY_IN, this->mark_in, FALSE); |
ce42db09 | 820 | if (this->mode != MODE_TRANSPORT) |
d487b4b7 AS |
821 | { |
822 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
ee26c537 | 823 | other_ts, my_ts, POLICY_FWD, this->mark_in, FALSE); |
d487b4b7 | 824 | } |
7daf5226 | 825 | |
d487b4b7 AS |
826 | /* check whether we have to update a "dynamic" traffic selector */ |
827 | if (!me->ip_equals(me, this->my_addr) && | |
828 | my_ts->is_host(my_ts, this->my_addr)) | |
829 | { | |
830 | my_ts->set_address(my_ts, me); | |
831 | } | |
832 | if (!other->ip_equals(other, this->other_addr) && | |
833 | other_ts->is_host(other_ts, this->other_addr)) | |
834 | { | |
835 | other_ts->set_address(other_ts, other); | |
836 | } | |
7daf5226 | 837 | |
d487b4b7 AS |
838 | /* we reinstall the virtual IP to handle interface roaming |
839 | * correctly */ | |
840 | if (vip) | |
841 | { | |
842 | charon->kernel_interface->del_ip(charon->kernel_interface, vip); | |
843 | charon->kernel_interface->add_ip(charon->kernel_interface, vip, me); | |
844 | } | |
7daf5226 | 845 | |
d487b4b7 AS |
846 | /* reinstall updated policies */ |
847 | charon->kernel_interface->add_policy(charon->kernel_interface, | |
ea625fab | 848 | me, other, my_ts, other_ts, POLICY_OUT, this->other_spi, |
ee26c537 AS |
849 | this->protocol, this->reqid, this->mark_out, this->mode, |
850 | this->ipcomp, this->other_cpi, FALSE); | |
dd83c6d4 | 851 | charon->kernel_interface->add_policy(charon->kernel_interface, |
ea625fab | 852 | other, me, other_ts, my_ts, POLICY_IN, this->my_spi, |
ee26c537 AS |
853 | this->protocol, this->reqid, this->mark_in, this->mode, |
854 | this->ipcomp, this->my_cpi, FALSE); | |
ce42db09 | 855 | if (this->mode != MODE_TRANSPORT) |
d487b4b7 AS |
856 | { |
857 | charon->kernel_interface->add_policy(charon->kernel_interface, | |
ea625fab | 858 | other, me, other_ts, my_ts, POLICY_FWD, this->my_spi, |
ee26c537 AS |
859 | this->protocol, this->reqid, this->mark_in, this->mode, |
860 | this->ipcomp, this->my_cpi, FALSE); | |
d487b4b7 AS |
861 | } |
862 | } | |
863 | enumerator->destroy(enumerator); | |
1396815a MW |
864 | } |
865 | } | |
7a915d62 | 866 | |
08c6ed9f AS |
867 | if (!transport_proxy_mode) |
868 | { | |
869 | /* apply hosts */ | |
870 | if (!me->equals(me, this->my_addr)) | |
871 | { | |
872 | this->my_addr->destroy(this->my_addr); | |
873 | this->my_addr = me->clone(me); | |
874 | } | |
875 | if (!other->equals(other, this->other_addr)) | |
876 | { | |
877 | this->other_addr->destroy(this->other_addr); | |
878 | this->other_addr = other->clone(other); | |
879 | } | |
880 | } | |
881 | ||
ea625fab | 882 | this->encap = encap; |
ad3af574 | 883 | set_state(this, old); |
7a915d62 | 884 | |
1396815a MW |
885 | return SUCCESS; |
886 | } | |
887 | ||
30b5b412 MW |
888 | /** |
889 | * Implementation of child_sa_t.destroy. | |
890 | */ | |
891 | static void destroy(private_child_sa_t *this) | |
892 | { | |
1df106bf MW |
893 | enumerator_t *enumerator; |
894 | traffic_selector_t *my_ts, *other_ts; | |
ea625fab | 895 | bool unrouted = (this->state == CHILD_ROUTED); |
7daf5226 | 896 | |
a985db3f | 897 | set_state(this, CHILD_DESTROYING); |
7daf5226 | 898 | |
5d187bd2 | 899 | /* delete SAs in the kernel, if they are set up */ |
80853d84 | 900 | if (this->my_spi) |
5d187bd2 | 901 | { |
1bc0b4f7 MW |
902 | /* if CHILD was not established, use PROTO_ESP used during alloc_spi(). |
903 | * TODO: For AH support, we have to store protocol specific SPI.s */ | |
904 | if (this->protocol == PROTO_NONE) | |
905 | { | |
906 | this->protocol = PROTO_ESP; | |
907 | } | |
5d187bd2 | 908 | charon->kernel_interface->del_sa(charon->kernel_interface, |
d24a74c5 | 909 | this->other_addr, this->my_addr, this->my_spi, |
ee26c537 | 910 | this->protocol, this->my_cpi, this->mark_in); |
3efbf983 | 911 | } |
80853d84 | 912 | if (this->other_spi) |
3efbf983 | 913 | { |
5d187bd2 | 914 | charon->kernel_interface->del_sa(charon->kernel_interface, |
d24a74c5 | 915 | this->my_addr, this->other_addr, this->other_spi, |
ee26c537 | 916 | this->protocol, this->other_cpi, this->mark_out); |
d4aad554 | 917 | } |
7daf5226 | 918 | |
d487b4b7 | 919 | if (this->config->install_policy(this->config)) |
695723d4 | 920 | { |
d487b4b7 AS |
921 | /* delete all policies in the kernel */ |
922 | enumerator = create_policy_enumerator(this); | |
923 | while (enumerator->enumerate(enumerator, &my_ts, &other_ts)) | |
924 | { | |
925 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
ee26c537 | 926 | my_ts, other_ts, POLICY_OUT, this->mark_out, unrouted); |
d487b4b7 | 927 | charon->kernel_interface->del_policy(charon->kernel_interface, |
ee26c537 | 928 | other_ts, my_ts, POLICY_IN, this->mark_in, unrouted); |
ce42db09 | 929 | if (this->mode != MODE_TRANSPORT) |
d487b4b7 AS |
930 | { |
931 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
ee26c537 | 932 | other_ts, my_ts, POLICY_FWD, this->mark_in, unrouted); |
d487b4b7 AS |
933 | } |
934 | } | |
935 | enumerator->destroy(enumerator); | |
5d187bd2 | 936 | } |
7daf5226 | 937 | |
1df106bf MW |
938 | this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy)); |
939 | this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy)); | |
80853d84 MW |
940 | this->my_addr->destroy(this->my_addr); |
941 | this->other_addr->destroy(this->other_addr); | |
942 | DESTROY_IF(this->proposal); | |
e0fe7651 | 943 | this->config->destroy(this->config); |
5113680f | 944 | free(this); |
30b5b412 MW |
945 | } |
946 | ||
947 | /* | |
948 | * Described in header. | |
949 | */ | |
c60c7694 | 950 | child_sa_t * child_sa_create(host_t *me, host_t* other, |
fc2d1c42 | 951 | child_cfg_t *config, u_int32_t rekey, bool encap) |
30b5b412 | 952 | { |
c60c7694 | 953 | static u_int32_t reqid = 0; |
5113680f | 954 | private_child_sa_t *this = malloc_thing(private_child_sa_t); |
30b5b412 MW |
955 | |
956 | /* public functions */ | |
9be547c0 | 957 | this->public.get_name = (char*(*)(child_sa_t*))get_name; |
32b6500f | 958 | this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid; |
3aaf7908 MW |
959 | this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config; |
960 | this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state; | |
961 | this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state; | |
8d77edde | 962 | this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi; |
66da78b4 | 963 | this->public.get_cpi = (u_int16_t(*)(child_sa_t*, bool))get_cpi; |
8d77edde | 964 | this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol; |
3aaf7908 | 965 | this->public.set_protocol = (void(*)(child_sa_t*, protocol_id_t protocol))set_protocol; |
6e10aead | 966 | this->public.get_mode = (ipsec_mode_t(*)(child_sa_t*))get_mode; |
3aaf7908 MW |
967 | this->public.set_mode = (void(*)(child_sa_t*, ipsec_mode_t mode))set_mode; |
968 | this->public.get_proposal = (proposal_t*(*)(child_sa_t*))get_proposal; | |
969 | this->public.set_proposal = (void(*)(child_sa_t*, proposal_t *proposal))set_proposal; | |
e3c7e729 | 970 | this->public.get_lifetime = (time_t(*)(child_sa_t*, bool))get_lifetime; |
c3a78360 | 971 | this->public.get_usestats = (void(*)(child_sa_t*,bool,time_t*,u_int64_t*))get_usestats; |
3aaf7908 MW |
972 | this->public.has_encap = (bool(*)(child_sa_t*))has_encap; |
973 | this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp; | |
974 | this->public.set_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t))set_ipcomp; | |
4c401ea2 MW |
975 | this->public.get_close_action = (action_t(*)(child_sa_t*))get_close_action; |
976 | this->public.set_close_action = (void(*)(child_sa_t*,action_t))set_close_action; | |
977 | this->public.get_dpd_action = (action_t(*)(child_sa_t*))get_dpd_action; | |
978 | this->public.set_dpd_action = (void(*)(child_sa_t*,action_t))set_dpd_action; | |
3aaf7908 MW |
979 | this->public.alloc_spi = (u_int32_t(*)(child_sa_t*, protocol_id_t protocol))alloc_spi; |
980 | this->public.alloc_cpi = (u_int16_t(*)(child_sa_t*))alloc_cpi; | |
6ec949e0 | 981 | this->public.install = (status_t(*)(child_sa_t*, chunk_t encr, chunk_t integ, u_int32_t spi, u_int16_t cpi, bool inbound, linked_list_t *my_ts_list, linked_list_t *other_ts_list))install; |
3aaf7908 MW |
982 | this->public.update = (status_t (*)(child_sa_t*,host_t*,host_t*,host_t*,bool))update; |
983 | this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies; | |
e0fe7651 | 984 | this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors; |
1df106bf | 985 | this->public.create_policy_enumerator = (enumerator_t*(*)(child_sa_t*))create_policy_enumerator; |
30b5b412 | 986 | this->public.destroy = (void(*)(child_sa_t*))destroy; |
7daf5226 | 987 | |
30b5b412 | 988 | /* private data */ |
80853d84 MW |
989 | this->my_addr = me->clone(me); |
990 | this->other_addr = other->clone(other); | |
991 | this->my_spi = 0; | |
80853d84 | 992 | this->other_spi = 0; |
3aaf7908 | 993 | this->my_cpi = 0; |
80853d84 | 994 | this->other_cpi = 0; |
fc2d1c42 | 995 | this->encap = encap; |
d4aad554 | 996 | this->ipcomp = IPCOMP_NONE; |
bcb95ced | 997 | this->state = CHILD_CREATED; |
3f720dc7 AS |
998 | this->my_usetime = 0; |
999 | this->other_usetime = 0; | |
1000 | this->my_usebytes = 0; | |
1001 | this->other_usebytes = 0; | |
8dfbe71b MW |
1002 | this->my_ts = linked_list_create(); |
1003 | this->other_ts = linked_list_create(); | |
8d77edde | 1004 | this->protocol = PROTO_NONE; |
7652be89 | 1005 | this->mode = MODE_TUNNEL; |
4c401ea2 MW |
1006 | this->close_action = config->get_close_action(config); |
1007 | this->dpd_action = config->get_dpd_action(config); | |
80853d84 | 1008 | this->proposal = NULL; |
37974979 MW |
1009 | this->rekey_time = 0; |
1010 | this->expire_time = 0; | |
e0fe7651 MW |
1011 | this->config = config; |
1012 | config->get_ref(config); | |
71a66a62 | 1013 | this->reqid = config->get_reqid(config); |
ee26c537 AS |
1014 | this->mark_in = config->get_mark(config, TRUE); |
1015 | this->mark_out = config->get_mark(config, FALSE); | |
1016 | ||
71a66a62 RB |
1017 | if (!this->reqid) |
1018 | { | |
1019 | /* reuse old reqid if we are rekeying an existing CHILD_SA */ | |
1020 | this->reqid = rekey ? rekey : ++reqid; | |
1021 | } | |
7daf5226 | 1022 | |
dd83c6d4 | 1023 | /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */ |
d487b4b7 | 1024 | if (config->get_mode(config) == MODE_TRANSPORT && |
323f9f99 | 1025 | config->use_proxy_mode(config)) |
d487b4b7 AS |
1026 | { |
1027 | ts_type_t type; | |
1028 | int family; | |
1029 | chunk_t addr; | |
1030 | host_t *host; | |
1031 | enumerator_t *enumerator; | |
1032 | linked_list_t *my_ts_list, *other_ts_list; | |
1033 | traffic_selector_t *my_ts, *other_ts; | |
7daf5226 | 1034 | |
d487b4b7 | 1035 | this->mode = MODE_TRANSPORT; |
7daf5226 | 1036 | |
d487b4b7 AS |
1037 | my_ts_list = config->get_traffic_selectors(config, TRUE, NULL, me); |
1038 | enumerator = my_ts_list->create_enumerator(my_ts_list); | |
1039 | if (enumerator->enumerate(enumerator, &my_ts)) | |
1040 | { | |
1041 | if (my_ts->is_host(my_ts, NULL) && | |
1042 | !my_ts->is_host(my_ts, this->my_addr)) | |
1043 | { | |
1044 | type = my_ts->get_type(my_ts); | |
1045 | family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6; | |
1046 | addr = my_ts->get_from_address(my_ts); | |
1047 | host = host_create_from_chunk(family, addr, 0); | |
1048 | free(addr.ptr); | |
1049 | DBG1(DBG_CHD, "my address: %H is a transport mode proxy for %H", | |
dd83c6d4 | 1050 | this->my_addr, host); |
d487b4b7 AS |
1051 | this->my_addr->destroy(this->my_addr); |
1052 | this->my_addr = host; | |
1053 | } | |
1054 | } | |
1055 | enumerator->destroy(enumerator); | |
1056 | my_ts_list->destroy_offset(my_ts_list, offsetof(traffic_selector_t, destroy)); | |
7daf5226 | 1057 | |
d487b4b7 AS |
1058 | other_ts_list = config->get_traffic_selectors(config, FALSE, NULL, other); |
1059 | enumerator = other_ts_list->create_enumerator(other_ts_list); | |
1060 | if (enumerator->enumerate(enumerator, &other_ts)) | |
1061 | { | |
1062 | if (other_ts->is_host(other_ts, NULL) && | |
1063 | !other_ts->is_host(other_ts, this->other_addr)) | |
1064 | { | |
1065 | type = other_ts->get_type(other_ts); | |
1066 | family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6; | |
1067 | addr = other_ts->get_from_address(other_ts); | |
1068 | host = host_create_from_chunk(family, addr, 0); | |
1069 | free(addr.ptr); | |
1070 | DBG1(DBG_CHD, "other address: %H is a transport mode proxy for %H", | |
dd83c6d4 | 1071 | this->other_addr, host); |
d487b4b7 AS |
1072 | this->other_addr->destroy(this->other_addr); |
1073 | this->other_addr = host; | |
1074 | } | |
1075 | } | |
1076 | enumerator->destroy(enumerator); | |
1077 | other_ts_list->destroy_offset(other_ts_list, offsetof(traffic_selector_t, destroy)); | |
1078 | } | |
7daf5226 | 1079 | |
1396815a | 1080 | return &this->public; |
3ebebc5e | 1081 | } |