]>
Commit | Line | Data |
---|---|---|
3ebebc5e MW |
1 | /** |
2 | * @file child_sa.c | |
3 | * | |
4 | * @brief Implementation of child_sa_t. | |
5 | * | |
6 | */ | |
7 | ||
8 | /* | |
1396815a | 9 | * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger |
c71d53ba MW |
10 | * Copyright (C) 2005-2006 Martin Willi |
11 | * Copyright (C) 2005 Jan Hutter | |
3ebebc5e MW |
12 | * Hochschule fuer Technik Rapperswil |
13 | * | |
14 | * This program is free software; you can redistribute it and/or modify it | |
15 | * under the terms of the GNU General Public License as published by the | |
16 | * Free Software Foundation; either version 2 of the License, or (at your | |
17 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
18 | * | |
19 | * This program is distributed in the hope that it will be useful, but | |
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
21 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
22 | * for more details. | |
23 | */ | |
24 | ||
60356f33 | 25 | #define _GNU_SOURCE |
b92eef28 | 26 | #include "child_sa.h" |
3ebebc5e | 27 | |
a095243f | 28 | #include <stdio.h> |
4c23a8c9 | 29 | #include <string.h> |
60356f33 | 30 | #include <printf.h> |
4c23a8c9 | 31 | |
aeda79ff MW |
32 | #include <daemon.h> |
33 | ||
60356f33 MW |
34 | ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DELETING, |
35 | "CREATED", | |
36 | "ROUTED", | |
37 | "INSTALLED", | |
38 | "REKEYING", | |
39 | "DELETING", | |
40 | ); | |
bcb95ced | 41 | |
16b9a73c | 42 | typedef struct sa_policy_t sa_policy_t; |
5d187bd2 MW |
43 | |
44 | /** | |
45 | * Struct used to store information for a policy. This | |
46 | * is needed since we must provide all this information | |
47 | * for deleting a policy... | |
48 | */ | |
16b9a73c | 49 | struct sa_policy_t { |
92ee45a0 MW |
50 | /** |
51 | * Traffic selector for us | |
52 | */ | |
53 | traffic_selector_t *my_ts; | |
5d187bd2 MW |
54 | |
55 | /** | |
92ee45a0 | 56 | * Traffic selector for other |
5d187bd2 | 57 | */ |
92ee45a0 | 58 | traffic_selector_t *other_ts; |
5d187bd2 MW |
59 | }; |
60 | ||
3ebebc5e MW |
61 | typedef struct private_child_sa_t private_child_sa_t; |
62 | ||
63 | /** | |
fff4ee8a | 64 | * Private data of a child_sa_t \ 1bject. |
3ebebc5e MW |
65 | */ |
66 | struct private_child_sa_t { | |
67 | /** | |
144f676c | 68 | * Public interface of child_sa_t. |
3ebebc5e MW |
69 | */ |
70 | child_sa_t public; | |
71 | ||
9be547c0 MW |
72 | /** |
73 | * Name of the policy used by this CHILD_SA | |
74 | */ | |
75 | char *name; | |
76 | ||
8d77edde MW |
77 | struct { |
78 | /** address of peer */ | |
79 | host_t *addr; | |
d7934d0c MW |
80 | /** id of peer */ |
81 | identification_t *id; | |
8d77edde MW |
82 | /** actual used SPI, 0 if unused */ |
83 | u_int32_t spi; | |
84 | } me, other; | |
aeda79ff | 85 | |
3efbf983 MW |
86 | /** |
87 | * Allocated SPI for a ESP proposal candidates | |
88 | */ | |
89 | u_int32_t alloc_esp_spi; | |
90 | ||
91 | /** | |
92 | * Allocated SPI for a AH proposal candidates | |
93 | */ | |
94 | u_int32_t alloc_ah_spi; | |
95 | ||
aeda79ff | 96 | /** |
8d77edde | 97 | * Protocol used to protect this SA, ESP|AH |
aeda79ff | 98 | */ |
8d77edde | 99 | protocol_id_t protocol; |
30b5b412 MW |
100 | |
101 | /** | |
8d77edde | 102 | * List containing sa_policy_t objects |
5d187bd2 | 103 | */ |
8d77edde | 104 | linked_list_t *policies; |
5d187bd2 | 105 | |
8dfbe71b MW |
106 | /** |
107 | * Seperate list for local traffic selectors | |
108 | */ | |
109 | linked_list_t *my_ts; | |
110 | ||
111 | /** | |
112 | * Seperate list for remote traffic selectors | |
113 | */ | |
114 | linked_list_t *other_ts; | |
115 | ||
5d187bd2 | 116 | /** |
8d77edde | 117 | * reqid used for this child_sa |
5d187bd2 | 118 | */ |
8d77edde | 119 | u_int32_t reqid; |
5d187bd2 | 120 | |
c0593835 MW |
121 | /** |
122 | * encryption algorithm used for this SA | |
123 | */ | |
124 | algorithm_t encryption; | |
125 | ||
126 | /** | |
127 | * integrity protection algorithm used for this SA | |
128 | */ | |
129 | algorithm_t integrity; | |
130 | ||
a2a3fb3e MW |
131 | /** |
132 | * time, on which SA was installed | |
133 | */ | |
134 | time_t install_time; | |
135 | ||
5d187bd2 | 136 | /** |
8d77edde | 137 | * Lifetime before rekeying |
5d187bd2 | 138 | */ |
8d77edde | 139 | u_int32_t soft_lifetime; |
30b5b412 | 140 | |
a527a426 | 141 | /** |
8d77edde | 142 | * Lifetime before delete |
a527a426 | 143 | */ |
8d77edde | 144 | u_int32_t hard_lifetime; |
a527a426 | 145 | |
bcb95ced MW |
146 | /** |
147 | * state of the CHILD_SA | |
148 | */ | |
149 | child_sa_state_t state; | |
150 | ||
695723d4 | 151 | /** |
abba7ecb | 152 | * transaction which is rekeying this CHILD_SA |
695723d4 | 153 | */ |
382b4817 | 154 | transaction_t *rekeying_transaction; |
1396815a MW |
155 | |
156 | /** | |
d7934d0c | 157 | * Updown script |
1396815a | 158 | */ |
d7934d0c | 159 | char *script; |
1239c6f4 | 160 | |
fff4ee8a AS |
161 | /** |
162 | * Allow host access | |
163 | */ | |
164 | bool hostaccess; | |
165 | ||
1239c6f4 | 166 | /** |
d7934d0c | 167 | * Specifies if NAT traversal is used |
1239c6f4 | 168 | */ |
d7934d0c | 169 | bool use_natt; |
3ebebc5e MW |
170 | }; |
171 | ||
9be547c0 MW |
172 | /** |
173 | * Implementation of child_sa_t.get_name. | |
174 | */ | |
175 | static char *get_name(private_child_sa_t *this) | |
176 | { | |
177 | return this->name; | |
178 | } | |
179 | ||
180 | /** | |
181 | * Implementation of child_sa_t.set_name. | |
182 | */ | |
183 | static void set_name(private_child_sa_t *this, char* name) | |
184 | { | |
a095243f MW |
185 | char buffer[64]; |
186 | ||
187 | if (snprintf(buffer, sizeof(buffer), "%s[%d]", | |
188 | name, this->reqid - REQID_START) > 0) | |
189 | { | |
190 | free(this->name); | |
191 | this->name = strdup(buffer); | |
192 | } | |
9be547c0 MW |
193 | } |
194 | ||
32b6500f MW |
195 | /** |
196 | * Implements child_sa_t.get_reqid | |
197 | */ | |
198 | static u_int32_t get_reqid(private_child_sa_t *this) | |
199 | { | |
200 | return this->reqid; | |
201 | } | |
8d77edde MW |
202 | |
203 | /** | |
204 | * Implements child_sa_t.get_spi | |
205 | */ | |
206 | u_int32_t get_spi(private_child_sa_t *this, bool inbound) | |
207 | { | |
208 | if (inbound) | |
209 | { | |
210 | return this->me.spi; | |
211 | } | |
212 | return this->other.spi; | |
213 | } | |
214 | ||
215 | /** | |
216 | * Implements child_sa_t.get_protocol | |
217 | */ | |
218 | protocol_id_t get_protocol(private_child_sa_t *this) | |
219 | { | |
220 | return this->protocol; | |
221 | } | |
32b6500f | 222 | |
bcb95ced MW |
223 | /** |
224 | * Implements child_sa_t.get_state | |
225 | */ | |
226 | static child_sa_state_t get_state(private_child_sa_t *this) | |
227 | { | |
228 | return this->state; | |
229 | } | |
230 | ||
d7934d0c MW |
231 | /** |
232 | * Run the up/down script | |
233 | */ | |
234 | static void updown(private_child_sa_t *this, bool up) | |
235 | { | |
191a26a6 | 236 | sa_policy_t *policy; |
d7934d0c MW |
237 | iterator_t *iterator; |
238 | ||
239 | if (this->script == NULL) | |
240 | { | |
241 | return; | |
242 | } | |
243 | ||
244 | iterator = this->policies->create_iterator(this->policies, TRUE); | |
191a26a6 | 245 | while (iterator->iterate(iterator, (void**)&policy)) |
d7934d0c | 246 | { |
d7934d0c MW |
247 | char command[1024]; |
248 | char *ifname = NULL; | |
d7934d0c MW |
249 | char *my_client, *other_client, *my_client_mask, *other_client_mask; |
250 | char *pos; | |
251 | FILE *shell; | |
252 | ||
d7934d0c | 253 | /* get subnet/bits from string */ |
60356f33 | 254 | asprintf(&my_client, "%R", policy->my_ts); |
d7934d0c MW |
255 | pos = strchr(my_client, '/'); |
256 | *pos = '\0'; | |
257 | my_client_mask = pos + 1; | |
258 | pos = strchr(my_client_mask, '['); | |
259 | if (pos) | |
260 | { | |
261 | *pos = '\0'; | |
262 | } | |
60356f33 | 263 | asprintf(&other_client, "%R", policy->other_ts); |
d7934d0c MW |
264 | pos = strchr(other_client, '/'); |
265 | *pos = '\0'; | |
266 | other_client_mask = pos + 1; | |
267 | pos = strchr(other_client_mask, '['); | |
268 | if (pos) | |
269 | { | |
270 | *pos = '\0'; | |
271 | } | |
272 | ||
273 | charon->socket->is_local_address(charon->socket, this->me.addr, &ifname); | |
274 | ||
275 | /* build the command with all env variables. | |
276 | * TODO: PLUTO_MY_SRCIP, PLUTO_PEER_CA and PLUTO_NEXT_HOP | |
277 | * are currently missing */ | |
278 | snprintf(command, sizeof(command), | |
279 | "2>&1 " | |
280 | "PLUTO_VERSION='1.1' " | |
281 | "PLUTO_VERB='%s%s%s' " | |
282 | "PLUTO_CONNECTION='%s' " | |
283 | "PLUTO_INTERFACE='%s' " | |
284 | "PLUTO_REQID='%u' " | |
47f50278 MW |
285 | "PLUTO_ME='%H' " |
286 | "PLUTO_MY_ID='%D' " | |
d7934d0c MW |
287 | "PLUTO_MY_CLIENT='%s/%s' " |
288 | "PLUTO_MY_CLIENT_NET='%s' " | |
289 | "PLUTO_MY_CLIENT_MASK='%s' " | |
290 | "PLUTO_MY_PORT='%u' " | |
291 | "PLUTO_MY_PROTOCOL='%u' " | |
47f50278 MW |
292 | "PLUTO_PEER='%H' " |
293 | "PLUTO_PEER_ID='%D' " | |
d7934d0c MW |
294 | "PLUTO_PEER_CLIENT='%s/%s' " |
295 | "PLUTO_PEER_CLIENT_NET='%s' " | |
296 | "PLUTO_PEER_CLIENT_MASK='%s' " | |
297 | "PLUTO_PEER_PORT='%u' " | |
298 | "PLUTO_PEER_PROTOCOL='%u' " | |
fff4ee8a | 299 | "%s" |
d7934d0c MW |
300 | "%s", |
301 | up ? "up" : "down", | |
60356f33 MW |
302 | policy->my_ts->is_host(policy->my_ts, |
303 | this->me.addr) ? "-host" : "-client", | |
d7934d0c MW |
304 | this->me.addr->get_family(this->me.addr) == AF_INET ? "" : "-ipv6", |
305 | this->name, | |
306 | ifname, | |
307 | this->reqid, | |
47f50278 MW |
308 | this->me.addr, |
309 | this->me.id, | |
d7934d0c MW |
310 | my_client, my_client_mask, |
311 | my_client, my_client_mask, | |
312 | policy->my_ts->get_from_port(policy->my_ts), | |
313 | policy->my_ts->get_protocol(policy->my_ts), | |
47f50278 MW |
314 | this->other.addr, |
315 | this->other.id, | |
d7934d0c MW |
316 | other_client, other_client_mask, |
317 | other_client, other_client_mask, | |
318 | policy->other_ts->get_from_port(policy->other_ts), | |
319 | policy->other_ts->get_protocol(policy->other_ts), | |
fff4ee8a | 320 | this->hostaccess? "PLUTO_HOST_ACCESS='1' " : "", |
d7934d0c MW |
321 | this->script); |
322 | free(ifname); | |
323 | free(my_client); | |
324 | free(other_client); | |
325 | ||
326 | shell = popen(command, "r"); | |
327 | ||
328 | if (shell == NULL) | |
329 | { | |
b83806d8 | 330 | DBG1(DBG_CHD, "could not execute updown script '%s'", this->script); |
d7934d0c MW |
331 | return; |
332 | } | |
333 | ||
334 | while (TRUE) | |
335 | { | |
336 | char resp[128]; | |
337 | ||
338 | if (fgets(resp, sizeof(resp), shell) == NULL) | |
339 | { | |
340 | if (ferror(shell)) | |
341 | { | |
b83806d8 | 342 | DBG1(DBG_CHD, "error reading output from updown script"); |
d7934d0c MW |
343 | return; |
344 | } | |
345 | else | |
346 | { | |
347 | break; | |
348 | } | |
349 | } | |
350 | else | |
351 | { | |
352 | char *e = resp + strlen(resp); | |
353 | if (e > resp && e[-1] == '\n') | |
354 | { /* trim trailing '\n' */ | |
355 | e[-1] = '\0'; | |
356 | } | |
b83806d8 | 357 | DBG1(DBG_CHD, "updown: %s", resp); |
d7934d0c MW |
358 | } |
359 | } | |
360 | pclose(shell); | |
361 | } | |
362 | iterator->destroy(iterator); | |
363 | } | |
364 | ||
bcb95ced MW |
365 | /** |
366 | * Implements child_sa_t.set_state | |
367 | */ | |
368 | static void set_state(private_child_sa_t *this, child_sa_state_t state) | |
369 | { | |
370 | this->state = state; | |
d7934d0c MW |
371 | if (state == CHILD_INSTALLED) |
372 | { | |
373 | updown(this, TRUE); | |
374 | } | |
bcb95ced MW |
375 | } |
376 | ||
1396815a MW |
377 | /** |
378 | * Allocate SPI for a single proposal | |
379 | */ | |
380 | static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal) | |
381 | { | |
382 | protocol_id_t protocol = proposal->get_protocol(proposal); | |
383 | ||
384 | if (protocol == PROTO_AH) | |
385 | { | |
386 | /* get a new spi for AH, if not already done */ | |
387 | if (this->alloc_ah_spi == 0) | |
388 | { | |
389 | if (charon->kernel_interface->get_spi( | |
390 | charon->kernel_interface, | |
391 | this->other.addr, this->me.addr, | |
392 | PROTO_AH, this->reqid, | |
393 | &this->alloc_ah_spi) != SUCCESS) | |
394 | { | |
395 | return FAILED; | |
396 | } | |
397 | } | |
398 | proposal->set_spi(proposal, this->alloc_ah_spi); | |
399 | } | |
400 | if (protocol == PROTO_ESP) | |
401 | { | |
402 | /* get a new spi for ESP, if not already done */ | |
403 | if (this->alloc_esp_spi == 0) | |
404 | { | |
405 | if (charon->kernel_interface->get_spi( | |
406 | charon->kernel_interface, | |
407 | this->other.addr, this->me.addr, | |
408 | PROTO_ESP, this->reqid, | |
409 | &this->alloc_esp_spi) != SUCCESS) | |
410 | { | |
411 | return FAILED; | |
412 | } | |
413 | } | |
414 | proposal->set_spi(proposal, this->alloc_esp_spi); | |
415 | } | |
416 | return SUCCESS; | |
417 | } | |
418 | ||
419 | ||
3ebebc5e | 420 | /** |
30b5b412 | 421 | * Implements child_sa_t.alloc |
3ebebc5e | 422 | */ |
30b5b412 | 423 | static status_t alloc(private_child_sa_t *this, linked_list_t *proposals) |
3ebebc5e | 424 | { |
30b5b412 MW |
425 | iterator_t *iterator; |
426 | proposal_t *proposal; | |
30b5b412 | 427 | |
3efbf983 | 428 | /* iterator through proposals to update spis */ |
30b5b412 | 429 | iterator = proposals->create_iterator(proposals, TRUE); |
191a26a6 | 430 | while(iterator->iterate(iterator, (void**)&proposal)) |
30b5b412 | 431 | { |
1396815a | 432 | if (alloc_proposal(this, proposal) != SUCCESS) |
3efbf983 | 433 | { |
1396815a MW |
434 | iterator->destroy(iterator); |
435 | return FAILED; | |
3efbf983 | 436 | } |
30b5b412 MW |
437 | } |
438 | iterator->destroy(iterator); | |
439 | return SUCCESS; | |
3ebebc5e MW |
440 | } |
441 | ||
30b5b412 | 442 | static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus, bool mine) |
3ebebc5e | 443 | { |
30b5b412 | 444 | u_int32_t spi; |
5c131a01 MW |
445 | algorithm_t *enc_algo, *int_algo; |
446 | algorithm_t enc_algo_none = {ENCR_UNDEFINED, 0}; | |
447 | algorithm_t int_algo_none = {AUTH_UNDEFINED, 0}; | |
30b5b412 MW |
448 | host_t *src; |
449 | host_t *dst; | |
1396815a | 450 | natt_conf_t *natt; |
30b5b412 | 451 | status_t status; |
aeda79ff | 452 | |
8d77edde MW |
453 | this->protocol = proposal->get_protocol(proposal); |
454 | ||
455 | /* now we have to decide which spi to use. Use self allocated, if "mine", | |
3efbf983 MW |
456 | * or the one in the proposal, if not "mine" (others). Additionally, |
457 | * source and dest host switch depending on the role */ | |
8d77edde | 458 | if (mine) |
aeda79ff | 459 | { |
3efbf983 MW |
460 | /* if we have allocated SPIs for AH and ESP, we must delete the unused |
461 | * one. */ | |
462 | if (this->protocol == PROTO_ESP) | |
463 | { | |
464 | this->me.spi = this->alloc_esp_spi; | |
465 | if (this->alloc_ah_spi) | |
466 | { | |
467 | charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr, | |
468 | this->alloc_ah_spi, PROTO_AH); | |
469 | } | |
470 | } | |
471 | else | |
472 | { | |
473 | this->me.spi = this->alloc_ah_spi; | |
474 | if (this->alloc_esp_spi) | |
475 | { | |
476 | charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr, | |
477 | this->alloc_esp_spi, PROTO_ESP); | |
478 | } | |
479 | } | |
8d77edde | 480 | spi = this->me.spi; |
3efbf983 MW |
481 | dst = this->me.addr; |
482 | src = this->other.addr; | |
aeda79ff | 483 | } |
8d77edde MW |
484 | else |
485 | { | |
3efbf983 MW |
486 | this->other.spi = proposal->get_spi(proposal); |
487 | spi = this->other.spi; | |
488 | src = this->me.addr; | |
489 | dst = this->other.addr; | |
8d77edde MW |
490 | } |
491 | ||
b83806d8 | 492 | DBG2(DBG_CHD, "adding %s %N SA", mine ? "inbound" : "outbound", |
60356f33 | 493 | protocol_id_names, this->protocol); |
5c131a01 MW |
494 | |
495 | /* select encryption algo */ | |
496 | if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_algo)) | |
8d77edde | 497 | { |
b83806d8 | 498 | DBG2(DBG_CHD, " using %N for encryption", |
60356f33 | 499 | encryption_algorithm_names, enc_algo->algorithm); |
8d77edde MW |
500 | } |
501 | else | |
502 | { | |
5c131a01 | 503 | enc_algo = &enc_algo_none; |
8d77edde MW |
504 | } |
505 | ||
5c131a01 MW |
506 | /* select integrity algo */ |
507 | if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_algo)) | |
8d77edde | 508 | { |
b83806d8 | 509 | DBG2(DBG_CHD, " using %N for integrity", |
60356f33 | 510 | integrity_algorithm_names, int_algo->algorithm); |
8d77edde MW |
511 | } |
512 | else | |
513 | { | |
5c131a01 | 514 | int_algo = &int_algo_none; |
8d77edde MW |
515 | } |
516 | ||
1396815a MW |
517 | /* setup nat-t */ |
518 | if (this->use_natt) | |
519 | { | |
520 | natt = alloca(sizeof(natt_conf_t)); | |
521 | natt->sport = src->get_port(src); | |
522 | natt->dport = dst->get_port(dst); | |
523 | } | |
524 | else | |
525 | { | |
526 | natt = NULL; | |
527 | } | |
528 | ||
529 | ||
5c131a01 | 530 | /* send SA down to the kernel */ |
b83806d8 | 531 | DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst); |
8d77edde | 532 | status = charon->kernel_interface->add_sa(charon->kernel_interface, |
1396815a MW |
533 | src, dst, |
534 | spi, this->protocol, | |
535 | this->reqid, | |
698d7749 | 536 | mine ? this->soft_lifetime : 0, |
1396815a MW |
537 | this->hard_lifetime, |
538 | enc_algo, int_algo, | |
539 | prf_plus, natt, mine); | |
a2a3fb3e | 540 | |
c0593835 MW |
541 | this->encryption = *enc_algo; |
542 | this->integrity = *int_algo; | |
a2a3fb3e | 543 | this->install_time = time(NULL); |
abba7ecb | 544 | |
8d77edde | 545 | return status; |
30b5b412 MW |
546 | } |
547 | ||
548 | static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus) | |
549 | { | |
891dfaf9 | 550 | u_int32_t outbound_spi, inbound_spi; |
30b5b412 | 551 | |
891dfaf9 MW |
552 | /* backup outbound spi, as alloc overwrites it */ |
553 | outbound_spi = proposal->get_spi(proposal); | |
30b5b412 | 554 | |
891dfaf9 | 555 | /* get SPIs inbound SAs */ |
1396815a | 556 | if (alloc_proposal(this, proposal) != SUCCESS) |
30b5b412 | 557 | { |
30b5b412 MW |
558 | return FAILED; |
559 | } | |
891dfaf9 | 560 | inbound_spi = proposal->get_spi(proposal); |
30b5b412 | 561 | |
891dfaf9 | 562 | /* install inbound SAs */ |
30b5b412 MW |
563 | if (install(this, proposal, prf_plus, TRUE) != SUCCESS) |
564 | { | |
565 | return FAILED; | |
566 | } | |
a527a426 | 567 | |
891dfaf9 MW |
568 | /* install outbound SAs, restore spi*/ |
569 | proposal->set_spi(proposal, outbound_spi); | |
570 | if (install(this, proposal, prf_plus, FALSE) != SUCCESS) | |
571 | { | |
572 | return FAILED; | |
573 | } | |
574 | proposal->set_spi(proposal, inbound_spi); | |
575 | ||
30b5b412 MW |
576 | return SUCCESS; |
577 | } | |
578 | ||
579 | static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus) | |
580 | { | |
891dfaf9 MW |
581 | u_int32_t inbound_spi; |
582 | ||
583 | /* backup received spi, as install() overwrites it */ | |
584 | inbound_spi = proposal->get_spi(proposal); | |
585 | ||
586 | /* install outbound SAs */ | |
587 | if (install(this, proposal, prf_plus, FALSE) != SUCCESS) | |
30b5b412 MW |
588 | { |
589 | return FAILED; | |
590 | } | |
891dfaf9 MW |
591 | |
592 | /* restore spi */ | |
593 | proposal->set_spi(proposal, inbound_spi); | |
594 | /* install inbound SAs */ | |
595 | if (install(this, proposal, prf_plus, TRUE) != SUCCESS) | |
30b5b412 MW |
596 | { |
597 | return FAILED; | |
598 | } | |
a527a426 MW |
599 | |
600 | return SUCCESS; | |
601 | } | |
602 | ||
5d187bd2 | 603 | static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list) |
a527a426 | 604 | { |
5d187bd2 MW |
605 | iterator_t *my_iter, *other_iter; |
606 | traffic_selector_t *my_ts, *other_ts; | |
a095243f MW |
607 | /* use low prio for ROUTED policies */ |
608 | bool high_prio = (this->state != CHILD_CREATED); | |
a527a426 | 609 | |
5d187bd2 MW |
610 | /* iterate over both lists */ |
611 | my_iter = my_ts_list->create_iterator(my_ts_list, TRUE); | |
612 | other_iter = other_ts_list->create_iterator(other_ts_list, TRUE); | |
191a26a6 | 613 | while (my_iter->iterate(my_iter, (void**)&my_ts)) |
a527a426 | 614 | { |
5d187bd2 | 615 | other_iter->reset(other_iter); |
191a26a6 | 616 | while (other_iter->iterate(other_iter, (void**)&other_ts)) |
5d187bd2 MW |
617 | { |
618 | /* set up policies for every entry in my_ts_list to every entry in other_ts_list */ | |
5d187bd2 | 619 | status_t status; |
92ee45a0 | 620 | sa_policy_t *policy; |
5d187bd2 | 621 | |
92ee45a0 MW |
622 | if (my_ts->get_type(my_ts) != other_ts->get_type(other_ts)) |
623 | { | |
b83806d8 | 624 | DBG2(DBG_CHD, |
60356f33 | 625 | "CHILD_SA policy uses two different IP families, ignored"); |
92ee45a0 MW |
626 | continue; |
627 | } | |
628 | ||
5f0eb96f MW |
629 | /* only set up policies if protocol matches, or if one is zero (any) */ |
630 | if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts) && | |
631 | my_ts->get_protocol(my_ts) && other_ts->get_protocol(other_ts)) | |
5d187bd2 | 632 | { |
b83806d8 | 633 | DBG2(DBG_CHD, |
60356f33 | 634 | "CHILD_SA policy uses two different protocols, ignored"); |
5d187bd2 MW |
635 | continue; |
636 | } | |
5d187bd2 | 637 | |
5d187bd2 MW |
638 | /* install 3 policies: out, in and forward */ |
639 | status = charon->kernel_interface->add_policy(charon->kernel_interface, | |
92ee45a0 | 640 | this->me.addr, this->other.addr, my_ts, other_ts, |
a095243f | 641 | POLICY_OUT, this->protocol, this->reqid, high_prio, FALSE); |
92ee45a0 | 642 | |
5d187bd2 | 643 | status |= charon->kernel_interface->add_policy(charon->kernel_interface, |
92ee45a0 | 644 | this->other.addr, this->me.addr, other_ts, my_ts, |
a095243f | 645 | POLICY_IN, this->protocol, this->reqid, high_prio, FALSE); |
92ee45a0 | 646 | |
5d187bd2 | 647 | status |= charon->kernel_interface->add_policy(charon->kernel_interface, |
92ee45a0 | 648 | this->other.addr, this->me.addr, other_ts, my_ts, |
a095243f | 649 | POLICY_FWD, this->protocol, this->reqid, high_prio, FALSE); |
5d187bd2 MW |
650 | |
651 | if (status != SUCCESS) | |
652 | { | |
653 | my_iter->destroy(my_iter); | |
654 | other_iter->destroy(other_iter); | |
5d187bd2 MW |
655 | return status; |
656 | } | |
657 | ||
92ee45a0 MW |
658 | /* store policy to delete/update them later */ |
659 | policy = malloc_thing(sa_policy_t); | |
660 | policy->my_ts = my_ts->clone(my_ts); | |
661 | policy->other_ts = other_ts->clone(other_ts); | |
662 | this->policies->insert_last(this->policies, (void*)policy); | |
8dfbe71b MW |
663 | /* add to separate list to query them via get_*_traffic_selectors() */ |
664 | this->my_ts->insert_last(this->my_ts, (void*)policy->my_ts); | |
665 | this->other_ts->insert_last(this->other_ts, (void*)policy->other_ts); | |
5d187bd2 MW |
666 | } |
667 | } | |
5d187bd2 MW |
668 | my_iter->destroy(my_iter); |
669 | other_iter->destroy(other_iter); | |
45f76a7d MW |
670 | |
671 | /* switch to routed state if no SAD entry set up */ | |
672 | if (this->state == CHILD_CREATED) | |
673 | { | |
674 | this->state = CHILD_ROUTED; | |
675 | } | |
676 | ||
5d187bd2 | 677 | return SUCCESS; |
30b5b412 MW |
678 | } |
679 | ||
8dfbe71b MW |
680 | /** |
681 | * Implementation of child_sa_t.get_my_traffic_selectors. | |
682 | */ | |
683 | static linked_list_t *get_my_traffic_selectors(private_child_sa_t *this) | |
684 | { | |
685 | return this->my_ts; | |
686 | } | |
687 | ||
688 | /** | |
689 | * Implementation of child_sa_t.get_my_traffic_selectors. | |
690 | */ | |
691 | static linked_list_t *get_other_traffic_selectors(private_child_sa_t *this) | |
692 | { | |
693 | return this->other_ts; | |
694 | } | |
695 | ||
695723d4 | 696 | /** |
abba7ecb MW |
697 | * Implementation of child_sa_t.set_rekeying_transaction. |
698 | */ | |
382b4817 | 699 | static void set_rekeying_transaction(private_child_sa_t *this, transaction_t *transaction) |
abba7ecb MW |
700 | { |
701 | this->rekeying_transaction = transaction; | |
abba7ecb MW |
702 | } |
703 | ||
704 | /** | |
705 | * Implementation of child_sa_t.get_rekeying_transaction. | |
695723d4 | 706 | */ |
382b4817 | 707 | static transaction_t* get_rekeying_transaction(private_child_sa_t *this) |
695723d4 | 708 | { |
abba7ecb MW |
709 | return this->rekeying_transaction; |
710 | } | |
711 | ||
2f89902d MW |
712 | /** |
713 | * Implementation of child_sa_t.get_use_time | |
714 | */ | |
715 | static status_t get_use_time(private_child_sa_t *this, bool inbound, time_t *use_time) | |
716 | { | |
92ee45a0 MW |
717 | iterator_t *iterator; |
718 | sa_policy_t *policy; | |
fe04e93a | 719 | status_t status = FAILED; |
2f89902d MW |
720 | |
721 | *use_time = UNDEFINED_TIME; | |
92ee45a0 MW |
722 | |
723 | iterator = this->policies->create_iterator(this->policies, TRUE); | |
724 | while (iterator->iterate(iterator, (void**)&policy)) | |
aeeb4f4f | 725 | { |
92ee45a0 MW |
726 | if (inbound) |
727 | { | |
728 | time_t in = UNDEFINED_TIME, fwd = UNDEFINED_TIME; | |
729 | ||
730 | status = charon->kernel_interface->query_policy( | |
731 | charon->kernel_interface, | |
732 | policy->other_ts, policy->my_ts, | |
733 | POLICY_IN, (u_int32_t*)&in); | |
734 | status |= charon->kernel_interface->query_policy( | |
735 | charon->kernel_interface, | |
736 | policy->other_ts, policy->my_ts, | |
737 | POLICY_FWD, (u_int32_t*)&fwd); | |
738 | *use_time = max(in, fwd); | |
739 | } | |
740 | else | |
741 | { | |
742 | status = charon->kernel_interface->query_policy( | |
743 | charon->kernel_interface, | |
744 | policy->my_ts, policy->other_ts, | |
745 | POLICY_OUT, (u_int32_t*)use_time); | |
746 | } | |
aeeb4f4f | 747 | } |
92ee45a0 | 748 | iterator->destroy(iterator); |
aeeb4f4f | 749 | return status; |
2f89902d MW |
750 | } |
751 | ||
5f0eb96f | 752 | /** |
60356f33 | 753 | * output handler in printf() |
5f0eb96f | 754 | */ |
60356f33 MW |
755 | static int print(FILE *stream, const struct printf_info *info, |
756 | const void *const *args) | |
5f0eb96f | 757 | { |
60356f33 | 758 | private_child_sa_t *this = *((private_child_sa_t**)(args[0])); |
5f0eb96f | 759 | iterator_t *iterator; |
60356f33 MW |
760 | sa_policy_t *policy; |
761 | u_int32_t now, rekeying, use; | |
92ee45a0 | 762 | status_t status; |
e706c7f1 | 763 | size_t written = 0; |
5f0eb96f | 764 | |
60356f33 | 765 | if (this == NULL) |
5f0eb96f | 766 | { |
60356f33 | 767 | return fprintf(stream, "(null)"); |
5f0eb96f | 768 | } |
60356f33 | 769 | |
92ee45a0 MW |
770 | now = (u_int32_t)time(NULL); |
771 | ||
efa0ed68 | 772 | written += fprintf(stream, "%12s: %N, reqid: %d", this->name, |
e706c7f1 | 773 | child_sa_state_names, this->state, this->reqid); |
60356f33 | 774 | |
45f76a7d | 775 | if (this->state == CHILD_INSTALLED) |
c0593835 | 776 | { |
efa0ed68 | 777 | written += fprintf(stream, ", %N SPIs: 0x%0x_i 0x%0x_o", |
e706c7f1 MW |
778 | protocol_id_names, this->protocol, |
779 | htonl(this->me.spi), htonl(this->other.spi)); | |
45f76a7d | 780 | |
60356f33 | 781 | if (info->alt) |
45f76a7d | 782 | { |
efa0ed68 | 783 | written += fprintf(stream, "\n%12s: ", this->name); |
60356f33 MW |
784 | |
785 | if (this->protocol == PROTO_ESP) | |
45f76a7d | 786 | { |
e706c7f1 MW |
787 | written += fprintf(stream, "%N", encryption_algorithm_names, |
788 | this->encryption.algorithm); | |
60356f33 MW |
789 | |
790 | if (this->encryption.key_size) | |
791 | { | |
e706c7f1 | 792 | written += fprintf(stream, "-%d", this->encryption.key_size); |
60356f33 | 793 | } |
e706c7f1 | 794 | written += fprintf(stream, "/"); |
60356f33 MW |
795 | } |
796 | ||
e706c7f1 MW |
797 | written += fprintf(stream, "%N", integrity_algorithm_names, |
798 | this->integrity.algorithm); | |
60356f33 MW |
799 | if (this->integrity.key_size) |
800 | { | |
e706c7f1 | 801 | written += fprintf(stream, "-%d", this->integrity.key_size); |
60356f33 | 802 | } |
efa0ed68 | 803 | written += fprintf(stream, ", rekeying "); |
60356f33 MW |
804 | |
805 | /* calculate rekey times */ | |
806 | if (this->soft_lifetime) | |
807 | { | |
808 | rekeying = this->soft_lifetime - (now - this->install_time); | |
efa0ed68 | 809 | written += fprintf(stream, "in %ds", rekeying); |
45f76a7d MW |
810 | } |
811 | else | |
812 | { | |
e706c7f1 | 813 | written += fprintf(stream, "disabled"); |
45f76a7d MW |
814 | } |
815 | } | |
c0593835 | 816 | } |
5f0eb96f | 817 | iterator = this->policies->create_iterator(this->policies, TRUE); |
60356f33 | 818 | while (iterator->iterate(iterator, (void**)&policy)) |
5f0eb96f | 819 | { |
efa0ed68 | 820 | written += fprintf(stream, "\n%12s: %R===%R, last use: ", |
e706c7f1 | 821 | this->name, policy->my_ts, policy->other_ts); |
5f0eb96f | 822 | |
92ee45a0 MW |
823 | /* query policy times */ |
824 | status = charon->kernel_interface->query_policy(charon->kernel_interface, | |
60356f33 MW |
825 | policy->other_ts, policy->my_ts, POLICY_IN, &use); |
826 | if (status == SUCCESS && use) | |
827 | { | |
efa0ed68 | 828 | written += fprintf(stream, "%ds_in ", now - use); |
60356f33 MW |
829 | } |
830 | else | |
5f0eb96f | 831 | { |
efa0ed68 | 832 | written += fprintf(stream, "no_in "); |
5f0eb96f | 833 | } |
92ee45a0 | 834 | status = charon->kernel_interface->query_policy(charon->kernel_interface, |
e706c7f1 | 835 | policy->my_ts, policy->other_ts, POLICY_OUT, &use); |
60356f33 MW |
836 | if (status == SUCCESS && use) |
837 | { | |
efa0ed68 | 838 | written += fprintf(stream, "%ds_out ", now - use); |
60356f33 MW |
839 | } |
840 | else | |
5f0eb96f | 841 | { |
efa0ed68 | 842 | written += fprintf(stream, "no_out "); |
5f0eb96f | 843 | } |
92ee45a0 | 844 | status = charon->kernel_interface->query_policy(charon->kernel_interface, |
60356f33 MW |
845 | policy->other_ts, policy->my_ts, POLICY_FWD, &use); |
846 | if (status == SUCCESS && use) | |
5f0eb96f | 847 | { |
efa0ed68 | 848 | written += fprintf(stream, "%ds_fwd", now - use); |
60356f33 MW |
849 | } |
850 | else | |
851 | { | |
efa0ed68 | 852 | written += fprintf(stream, "no_fwd"); |
5f0eb96f | 853 | } |
5f0eb96f MW |
854 | } |
855 | iterator->destroy(iterator); | |
e706c7f1 | 856 | return written; |
60356f33 MW |
857 | } |
858 | ||
60356f33 MW |
859 | /** |
860 | * register printf() handlers | |
861 | */ | |
862 | static void __attribute__ ((constructor))print_register() | |
863 | { | |
db7ef624 | 864 | register_printf_function(PRINTF_CHILD_SA, print, arginfo_ptr); |
5f0eb96f MW |
865 | } |
866 | ||
1396815a MW |
867 | /** |
868 | * Update the host adress/port of a SA | |
869 | */ | |
870 | static status_t update_sa_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other, | |
871 | int my_changes, int other_changes, bool mine) | |
872 | { | |
873 | host_t *src, *dst, *new_src, *new_dst; | |
874 | int src_changes, dst_changes; | |
875 | status_t status; | |
876 | u_int32_t spi; | |
877 | ||
878 | if (mine) | |
1396815a MW |
879 | { |
880 | src = this->other.addr; | |
881 | dst = this->me.addr; | |
882 | new_src = new_other; | |
883 | new_dst = new_me; | |
884 | src_changes = other_changes; | |
885 | dst_changes = my_changes; | |
886 | spi = this->other.spi; | |
887 | } | |
abba7ecb MW |
888 | else |
889 | { | |
890 | src = this->me.addr; | |
891 | dst = this->other.addr; | |
892 | new_src = new_me; | |
893 | new_dst = new_other; | |
894 | src_changes = my_changes; | |
895 | dst_changes = other_changes; | |
896 | spi = this->me.spi; | |
897 | } | |
1396815a | 898 | |
b83806d8 | 899 | DBG2(DBG_CHD, "updating %N SA 0x%x, from %#H..#H to %#H..%#H", |
60356f33 | 900 | protocol_id_names, this->protocol, ntohl(spi), src, dst, new_src, new_dst); |
1396815a | 901 | |
92ee45a0 MW |
902 | status = charon->kernel_interface->update_sa(charon->kernel_interface, |
903 | dst, spi, this->protocol, | |
904 | new_src, new_dst, | |
905 | src_changes, dst_changes); | |
1396815a MW |
906 | |
907 | if (status != SUCCESS) | |
908 | { | |
909 | return FAILED; | |
910 | } | |
911 | return SUCCESS; | |
912 | } | |
913 | ||
914 | /** | |
915 | * Update the host adress/port of a policy | |
916 | */ | |
917 | static status_t update_policy_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other) | |
918 | { | |
919 | iterator_t *iterator; | |
920 | sa_policy_t *policy; | |
921 | status_t status; | |
a095243f | 922 | /* we always use high priorities, as hosts getting updated are INSTALLED */ |
1396815a MW |
923 | |
924 | iterator = this->policies->create_iterator(this->policies, TRUE); | |
925 | while (iterator->iterate(iterator, (void**)&policy)) | |
926 | { | |
1396815a MW |
927 | status = charon->kernel_interface->add_policy( |
928 | charon->kernel_interface, | |
929 | new_me, new_other, | |
92ee45a0 | 930 | policy->my_ts, policy->other_ts, |
a095243f | 931 | POLICY_OUT, this->protocol, this->reqid, TRUE, TRUE); |
1396815a MW |
932 | |
933 | status |= charon->kernel_interface->add_policy( | |
934 | charon->kernel_interface, | |
935 | new_other, new_me, | |
92ee45a0 | 936 | policy->other_ts, policy->my_ts, |
a095243f | 937 | POLICY_IN, this->protocol, this->reqid, TRUE, TRUE); |
1396815a MW |
938 | |
939 | status |= charon->kernel_interface->add_policy( | |
940 | charon->kernel_interface, | |
941 | new_other, new_me, | |
92ee45a0 | 942 | policy->other_ts, policy->my_ts, |
a095243f | 943 | POLICY_FWD, this->protocol, this->reqid, TRUE, TRUE); |
aeeb4f4f | 944 | |
1396815a MW |
945 | if (status != SUCCESS) |
946 | { | |
947 | iterator->destroy(iterator); | |
948 | return FAILED; | |
949 | } | |
950 | } | |
951 | iterator->destroy(iterator); | |
92ee45a0 | 952 | |
698d7749 | 953 | return SUCCESS; |
1396815a MW |
954 | } |
955 | ||
956 | /** | |
957 | * Implementation of child_sa_t.update_hosts. | |
958 | */ | |
959 | static status_t update_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other, | |
92ee45a0 | 960 | host_diff_t my_changes, host_diff_t other_changes) |
1396815a | 961 | { |
abba7ecb | 962 | if (!my_changes && !other_changes) |
1396815a MW |
963 | { |
964 | return SUCCESS; | |
965 | } | |
966 | ||
967 | /* update our (initator) SAs */ | |
968 | if (update_sa_hosts(this, new_me, new_other, my_changes, other_changes, TRUE) != SUCCESS) | |
969 | { | |
970 | return FAILED; | |
971 | } | |
972 | ||
973 | /* update his (responder) SAs */ | |
974 | if (update_sa_hosts(this, new_me, new_other, my_changes, other_changes, FALSE) != SUCCESS) | |
975 | { | |
976 | return FAILED; | |
977 | } | |
978 | ||
979 | /* update policies */ | |
980 | if (my_changes & HOST_DIFF_ADDR || other_changes & HOST_DIFF_ADDR) | |
981 | { | |
982 | if (update_policy_hosts(this, new_me, new_other) != SUCCESS) | |
983 | { | |
984 | return FAILED; | |
985 | } | |
986 | } | |
987 | ||
988 | /* update hosts */ | |
989 | if (my_changes) | |
990 | { | |
991 | this->me.addr->destroy(this->me.addr); | |
992 | this->me.addr = new_me->clone(new_me); | |
993 | } | |
994 | ||
995 | if (other_changes) | |
996 | { | |
997 | this->other.addr->destroy(this->other.addr); | |
998 | this->other.addr = new_other->clone(new_other); | |
999 | } | |
1000 | ||
1001 | return SUCCESS; | |
1002 | } | |
1003 | ||
30b5b412 MW |
1004 | /** |
1005 | * Implementation of child_sa_t.destroy. | |
1006 | */ | |
1007 | static void destroy(private_child_sa_t *this) | |
1008 | { | |
16b9a73c | 1009 | sa_policy_t *policy; |
5d187bd2 | 1010 | |
d7934d0c MW |
1011 | if (this->state == CHILD_DELETING || this->state == CHILD_INSTALLED) |
1012 | { | |
1013 | updown(this, FALSE); | |
1014 | } | |
1015 | ||
5d187bd2 | 1016 | /* delete SAs in the kernel, if they are set up */ |
3efbf983 | 1017 | if (this->me.spi) |
5d187bd2 MW |
1018 | { |
1019 | charon->kernel_interface->del_sa(charon->kernel_interface, | |
695723d4 | 1020 | this->me.addr, this->me.spi, this->protocol); |
3efbf983 MW |
1021 | } |
1022 | if (this->alloc_esp_spi && this->alloc_esp_spi != this->me.spi) | |
1023 | { | |
1024 | charon->kernel_interface->del_sa(charon->kernel_interface, | |
1025 | this->me.addr, this->alloc_esp_spi, PROTO_ESP); | |
1026 | } | |
1027 | if (this->alloc_ah_spi && this->alloc_ah_spi != this->me.spi) | |
1028 | { | |
1029 | charon->kernel_interface->del_sa(charon->kernel_interface, | |
1030 | this->me.addr, this->alloc_ah_spi, PROTO_AH); | |
1031 | } | |
1032 | if (this->other.spi) | |
1033 | { | |
5d187bd2 | 1034 | charon->kernel_interface->del_sa(charon->kernel_interface, |
695723d4 MW |
1035 | this->other.addr, this->other.spi, this->protocol); |
1036 | } | |
1037 | ||
1038 | /* delete all policies in the kernel */ | |
1039 | while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS) | |
1040 | { | |
aeeb4f4f MW |
1041 | /* let rekeyed policies, as they are used by another child_sa */ |
1042 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
92ee45a0 MW |
1043 | policy->my_ts, policy->other_ts, |
1044 | POLICY_OUT); | |
aeeb4f4f MW |
1045 | |
1046 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
92ee45a0 MW |
1047 | policy->other_ts, policy->my_ts, |
1048 | POLICY_IN); | |
aeeb4f4f MW |
1049 | |
1050 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
92ee45a0 MW |
1051 | policy->other_ts, policy->my_ts, |
1052 | POLICY_FWD); | |
1053 | policy->my_ts->destroy(policy->my_ts); | |
1054 | policy->other_ts->destroy(policy->other_ts); | |
695723d4 | 1055 | free(policy); |
5d187bd2 | 1056 | } |
695723d4 | 1057 | this->policies->destroy(this->policies); |
abba7ecb | 1058 | |
8dfbe71b MW |
1059 | this->my_ts->destroy(this->my_ts); |
1060 | this->other_ts->destroy(this->other_ts); | |
abba7ecb MW |
1061 | this->me.addr->destroy(this->me.addr); |
1062 | this->other.addr->destroy(this->other.addr); | |
d7934d0c MW |
1063 | this->me.id->destroy(this->me.id); |
1064 | this->other.id->destroy(this->other.id); | |
9be547c0 | 1065 | free(this->name); |
d7934d0c | 1066 | free(this->script); |
5113680f | 1067 | free(this); |
30b5b412 MW |
1068 | } |
1069 | ||
1070 | /* | |
1071 | * Described in header. | |
1072 | */ | |
d7934d0c MW |
1073 | child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other, |
1074 | identification_t *my_id, identification_t *other_id, | |
1396815a | 1075 | u_int32_t soft_lifetime, u_int32_t hard_lifetime, |
fff4ee8a | 1076 | char *script, bool hostaccess, bool use_natt) |
30b5b412 | 1077 | { |
1396815a | 1078 | static u_int32_t reqid = REQID_START; |
5113680f | 1079 | private_child_sa_t *this = malloc_thing(private_child_sa_t); |
30b5b412 MW |
1080 | |
1081 | /* public functions */ | |
9be547c0 MW |
1082 | this->public.get_name = (char*(*)(child_sa_t*))get_name; |
1083 | this->public.set_name = (void(*)(child_sa_t*,char*))set_name; | |
32b6500f | 1084 | this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid; |
8d77edde MW |
1085 | this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi; |
1086 | this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol; | |
30b5b412 MW |
1087 | this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc; |
1088 | this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add; | |
1089 | this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update; | |
92ee45a0 | 1090 | this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_diff_t,host_diff_t))update_hosts; |
5d187bd2 | 1091 | this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies; |
8dfbe71b MW |
1092 | this->public.get_my_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_my_traffic_selectors; |
1093 | this->public.get_other_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_other_traffic_selectors; | |
2f89902d | 1094 | this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time; |
382b4817 MW |
1095 | this->public.set_rekeying_transaction = (void (*)(child_sa_t*,transaction_t*))set_rekeying_transaction; |
1096 | this->public.get_rekeying_transaction = (transaction_t* (*)(child_sa_t*))get_rekeying_transaction; | |
bcb95ced MW |
1097 | this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state; |
1098 | this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state; | |
30b5b412 MW |
1099 | this->public.destroy = (void(*)(child_sa_t*))destroy; |
1100 | ||
1101 | /* private data */ | |
9be547c0 | 1102 | this->name = strdup("(uninitialized)"); |
abba7ecb MW |
1103 | this->me.addr = me->clone(me); |
1104 | this->other.addr = other->clone(other); | |
d7934d0c MW |
1105 | this->me.id = my_id->clone(my_id); |
1106 | this->other.id = other_id->clone(other_id); | |
8d77edde MW |
1107 | this->me.spi = 0; |
1108 | this->other.spi = 0; | |
3efbf983 MW |
1109 | this->alloc_ah_spi = 0; |
1110 | this->alloc_esp_spi = 0; | |
d7934d0c | 1111 | this->script = script ? strdup(script) : NULL; |
fff4ee8a | 1112 | this->hostaccess = hostaccess; |
1396815a | 1113 | this->use_natt = use_natt; |
8d77edde MW |
1114 | this->soft_lifetime = soft_lifetime; |
1115 | this->hard_lifetime = hard_lifetime; | |
bcb95ced | 1116 | this->state = CHILD_CREATED; |
50f98119 MW |
1117 | /* reuse old reqid if we are rekeying an existing CHILD_SA */ |
1118 | this->reqid = rekey ? rekey : ++reqid; | |
c0593835 MW |
1119 | this->encryption.algorithm = ENCR_UNDEFINED; |
1120 | this->encryption.key_size = 0; | |
1121 | this->integrity.algorithm = AUTH_UNDEFINED; | |
1122 | this->encryption.key_size = 0; | |
5d187bd2 | 1123 | this->policies = linked_list_create(); |
8dfbe71b MW |
1124 | this->my_ts = linked_list_create(); |
1125 | this->other_ts = linked_list_create(); | |
8d77edde | 1126 | this->protocol = PROTO_NONE; |
abba7ecb | 1127 | this->rekeying_transaction = NULL; |
3ebebc5e | 1128 | |
1396815a | 1129 | return &this->public; |
3ebebc5e | 1130 | } |