]>
Commit | Line | Data |
---|---|---|
3ebebc5e MW |
1 | /** |
2 | * @file child_sa.c | |
3 | * | |
4 | * @brief Implementation of child_sa_t. | |
5 | * | |
6 | */ | |
7 | ||
8 | /* | |
9 | * Copyright (C) 2005 Jan Hutter, Martin Willi | |
10 | * Hochschule fuer Technik Rapperswil | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, but | |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
19 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 | * for more details. | |
21 | */ | |
22 | ||
b92eef28 | 23 | #include <netdb.h> |
3ebebc5e | 24 | |
b92eef28 | 25 | #include "child_sa.h" |
3ebebc5e | 26 | |
aeda79ff MW |
27 | #include <daemon.h> |
28 | ||
3ebebc5e | 29 | |
16b9a73c | 30 | typedef struct sa_policy_t sa_policy_t; |
5d187bd2 MW |
31 | |
32 | /** | |
33 | * Struct used to store information for a policy. This | |
34 | * is needed since we must provide all this information | |
35 | * for deleting a policy... | |
36 | */ | |
16b9a73c | 37 | struct sa_policy_t { |
5d187bd2 MW |
38 | |
39 | /** | |
40 | * Network on local side | |
41 | */ | |
42 | host_t *my_net; | |
43 | ||
44 | /** | |
45 | * Network on remote side | |
46 | */ | |
47 | host_t *other_net; | |
48 | ||
49 | /** | |
50 | * Number of bits for local network (subnet size) | |
51 | */ | |
52 | u_int8_t my_net_mask; | |
53 | ||
54 | /** | |
55 | * Number of bits for remote network (subnet size) | |
56 | */ | |
57 | u_int8_t other_net_mask; | |
58 | ||
59 | /** | |
60 | * Protocol for this policy, such as TCP/UDP/ICMP... | |
61 | */ | |
62 | int upper_proto; | |
63 | }; | |
64 | ||
3ebebc5e MW |
65 | typedef struct private_child_sa_t private_child_sa_t; |
66 | ||
67 | /** | |
144f676c | 68 | * Private data of a child_sa_t object. |
3ebebc5e MW |
69 | */ |
70 | struct private_child_sa_t { | |
71 | /** | |
144f676c | 72 | * Public interface of child_sa_t. |
3ebebc5e MW |
73 | */ |
74 | child_sa_t public; | |
75 | ||
76 | /** | |
30b5b412 | 77 | * IP of this peer |
3ebebc5e | 78 | */ |
30b5b412 | 79 | host_t *me; |
aeda79ff MW |
80 | |
81 | /** | |
30b5b412 | 82 | * IP of other peer |
aeda79ff | 83 | */ |
30b5b412 MW |
84 | host_t *other; |
85 | ||
86 | /** | |
5d187bd2 MW |
87 | * Local security parameter index for AH protocol, 0 if not used |
88 | */ | |
89 | u_int32_t my_ah_spi; | |
90 | ||
91 | /** | |
92 | * Local security parameter index for ESP protocol, 0 if not used | |
30b5b412 | 93 | */ |
5d187bd2 | 94 | u_int32_t my_esp_spi; |
30b5b412 MW |
95 | |
96 | /** | |
5d187bd2 | 97 | * Remote security parameter index for AH protocol, 0 if not used |
30b5b412 | 98 | */ |
5d187bd2 MW |
99 | u_int32_t other_ah_spi; |
100 | ||
101 | /** | |
102 | * Remote security parameter index for ESP protocol, 0 if not used | |
103 | */ | |
104 | u_int32_t other_esp_spi; | |
105 | ||
106 | /** | |
107 | * List containing policy_id_t objects | |
108 | */ | |
109 | linked_list_t *policies; | |
30b5b412 | 110 | |
a527a426 MW |
111 | /** |
112 | * reqid used for this child_sa | |
113 | */ | |
114 | u_int32_t reqid; | |
115 | ||
30b5b412 MW |
116 | /** |
117 | * CHILD_SAs own logger | |
118 | */ | |
119 | logger_t *logger; | |
3ebebc5e MW |
120 | }; |
121 | ||
3ebebc5e | 122 | /** |
30b5b412 | 123 | * Implements child_sa_t.alloc |
3ebebc5e | 124 | */ |
30b5b412 | 125 | static status_t alloc(private_child_sa_t *this, linked_list_t *proposals) |
3ebebc5e | 126 | { |
30b5b412 MW |
127 | protocol_id_t protocols[2]; |
128 | iterator_t *iterator; | |
129 | proposal_t *proposal; | |
130 | status_t status; | |
131 | u_int i; | |
132 | ||
133 | /* iterator through proposals */ | |
134 | iterator = proposals->create_iterator(proposals, TRUE); | |
135 | while(iterator->has_next(iterator)) | |
136 | { | |
137 | iterator->current(iterator, (void**)&proposal); | |
138 | proposal->get_protocols(proposal, protocols); | |
139 | ||
140 | /* check all protocols */ | |
141 | for (i = 0; i<2; i++) | |
142 | { | |
143 | switch (protocols[i]) | |
144 | { | |
dec59822 | 145 | case PROTO_AH: |
30b5b412 | 146 | /* do we already have an spi for AH?*/ |
5d187bd2 | 147 | if (this->my_ah_spi == 0) |
30b5b412 MW |
148 | { |
149 | /* nope, get one */ | |
150 | status = charon->kernel_interface->get_spi( | |
151 | charon->kernel_interface, | |
152 | this->me, this->other, | |
dec59822 | 153 | PROTO_AH, FALSE, |
5d187bd2 | 154 | &(this->my_ah_spi)); |
30b5b412 MW |
155 | } |
156 | /* update proposal */ | |
dec59822 | 157 | proposal->set_spi(proposal, PROTO_AH, (u_int64_t)this->my_ah_spi); |
30b5b412 | 158 | break; |
dec59822 | 159 | case PROTO_ESP: |
30b5b412 | 160 | /* do we already have an spi for ESP?*/ |
5d187bd2 | 161 | if (this->my_esp_spi == 0) |
30b5b412 MW |
162 | { |
163 | /* nope, get one */ | |
164 | status = charon->kernel_interface->get_spi( | |
165 | charon->kernel_interface, | |
166 | this->me, this->other, | |
dec59822 | 167 | PROTO_ESP, FALSE, |
5d187bd2 | 168 | &(this->my_esp_spi)); |
30b5b412 MW |
169 | } |
170 | /* update proposal */ | |
dec59822 | 171 | proposal->set_spi(proposal, PROTO_ESP, (u_int64_t)this->my_esp_spi); |
30b5b412 MW |
172 | break; |
173 | default: | |
174 | break; | |
175 | } | |
176 | if (status != SUCCESS) | |
177 | { | |
178 | iterator->destroy(iterator); | |
179 | return FAILED; | |
180 | } | |
181 | } | |
182 | } | |
183 | iterator->destroy(iterator); | |
184 | return SUCCESS; | |
3ebebc5e MW |
185 | } |
186 | ||
30b5b412 | 187 | static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus, bool mine) |
3ebebc5e | 188 | { |
30b5b412 MW |
189 | protocol_id_t protocols[2]; |
190 | u_int32_t spi; | |
191 | encryption_algorithm_t enc_algo; | |
192 | integrity_algorithm_t int_algo; | |
193 | chunk_t enc_key, int_key; | |
194 | algorithm_t *algo; | |
195 | crypter_t *crypter; | |
196 | signer_t *signer; | |
197 | size_t key_size; | |
198 | host_t *src; | |
199 | host_t *dst; | |
200 | status_t status; | |
aeda79ff | 201 | u_int i; |
aeda79ff | 202 | |
30b5b412 MW |
203 | /* we must assign the roles to correctly set up the SAs */ |
204 | if (mine) | |
205 | { | |
206 | src = this->me; | |
207 | dst = this->other; | |
208 | } | |
209 | else | |
210 | { | |
211 | dst = this->me; | |
212 | src = this->other; | |
213 | } | |
214 | ||
215 | proposal->get_protocols(proposal, protocols); | |
216 | /* derive keys in order as protocols appear */ | |
aeda79ff MW |
217 | for (i = 0; i<2; i++) |
218 | { | |
dec59822 | 219 | if (protocols[i] != PROTO_NONE) |
aeda79ff | 220 | { |
aeda79ff | 221 | |
30b5b412 MW |
222 | /* now we have to decide which spi to use. Use self allocated, if "mine", |
223 | * or the one in the proposal, if not "mine" (others). */ | |
224 | if (mine) | |
225 | { | |
dec59822 | 226 | if (protocols[i] == PROTO_AH) |
30b5b412 | 227 | { |
5d187bd2 | 228 | spi = this->my_ah_spi; |
30b5b412 MW |
229 | } |
230 | else | |
231 | { | |
5d187bd2 | 232 | spi = this->my_esp_spi; |
30b5b412 MW |
233 | } |
234 | } | |
235 | else /* use proposals spi */ | |
236 | { | |
237 | spi = proposal->get_spi(proposal, protocols[i]); | |
dec59822 | 238 | if (protocols[i] == PROTO_AH) |
5d187bd2 MW |
239 | { |
240 | this->other_ah_spi = spi; | |
241 | } | |
242 | else | |
243 | { | |
244 | this->other_esp_spi = spi; | |
245 | } | |
30b5b412 MW |
246 | } |
247 | ||
248 | /* derive encryption key first */ | |
249 | if (proposal->get_algorithm(proposal, protocols[i], ENCRYPTION_ALGORITHM, &algo)) | |
aeda79ff | 250 | { |
30b5b412 MW |
251 | enc_algo = algo->algorithm; |
252 | this->logger->log(this->logger, CONTROL|LEVEL1, "%s for %s: using %s %s, ", | |
253 | mapping_find(protocol_id_m, protocols[i]), | |
254 | mine ? "me" : "other", | |
aeda79ff | 255 | mapping_find(transform_type_m, ENCRYPTION_ALGORITHM), |
30b5b412 | 256 | mapping_find(encryption_algorithm_m, enc_algo)); |
aeda79ff | 257 | |
30b5b412 MW |
258 | /* we must create a (unused) crypter, since its the only way to get the size |
259 | * of the key. This is not so nice, since charon must support all algorithms | |
260 | * the kernel supports... | |
261 | * TODO: build something of a encryption algorithm lookup function | |
262 | */ | |
263 | crypter = crypter_create(enc_algo, algo->key_size); | |
264 | key_size = crypter->get_key_size(crypter); | |
265 | crypter->destroy(crypter); | |
266 | prf_plus->allocate_bytes(prf_plus, key_size, &enc_key); | |
16b9a73c | 267 | this->logger->log_chunk(this->logger, PRIVATE, "key:", enc_key); |
30b5b412 MW |
268 | } |
269 | else | |
270 | { | |
271 | enc_algo = ENCR_UNDEFINED; | |
aeda79ff MW |
272 | } |
273 | ||
30b5b412 MW |
274 | /* derive integrity key */ |
275 | if (proposal->get_algorithm(proposal, protocols[i], INTEGRITY_ALGORITHM, &algo)) | |
aeda79ff | 276 | { |
30b5b412 MW |
277 | int_algo = algo->algorithm; |
278 | this->logger->log(this->logger, CONTROL|LEVEL1, "%s for %s: using %s %s,", | |
279 | mapping_find(protocol_id_m, protocols[i]), | |
280 | mine ? "me" : "other", | |
aeda79ff MW |
281 | mapping_find(transform_type_m, INTEGRITY_ALGORITHM), |
282 | mapping_find(integrity_algorithm_m, algo->algorithm)); | |
283 | ||
30b5b412 MW |
284 | signer = signer_create(int_algo); |
285 | key_size = signer->get_key_size(signer); | |
286 | signer->destroy(signer); | |
287 | prf_plus->allocate_bytes(prf_plus, key_size, &int_key); | |
16b9a73c | 288 | this->logger->log_chunk(this->logger, PRIVATE, "key:", int_key); |
30b5b412 MW |
289 | } |
290 | else | |
291 | { | |
292 | int_algo = AUTH_UNDEFINED; | |
293 | } | |
294 | /* send keys down to kernel */ | |
295 | this->logger->log(this->logger, CONTROL|LEVEL1, | |
296 | "installing 0x%.8x for %s, src %s dst %s", | |
297 | ntohl(spi), mapping_find(protocol_id_m, protocols[i]), | |
298 | src->get_address(src), dst->get_address(dst)); | |
299 | status = charon->kernel_interface->add_sa(charon->kernel_interface, | |
300 | src, dst, | |
a527a426 MW |
301 | spi, protocols[i], |
302 | this->reqid, | |
30b5b412 MW |
303 | enc_algo, enc_key, |
304 | int_algo, int_key, mine); | |
305 | /* clean up for next round */ | |
306 | if (enc_algo != ENCR_UNDEFINED) | |
307 | { | |
5113680f | 308 | chunk_free(&enc_key); |
aeda79ff | 309 | } |
30b5b412 MW |
310 | if (int_algo != AUTH_UNDEFINED) |
311 | { | |
5113680f | 312 | chunk_free(&int_key); |
30b5b412 MW |
313 | } |
314 | ||
315 | if (status != SUCCESS) | |
316 | { | |
317 | return FAILED; | |
318 | } | |
319 | ||
a527a426 | 320 | |
aeda79ff MW |
321 | } |
322 | } | |
30b5b412 MW |
323 | return SUCCESS; |
324 | } | |
325 | ||
326 | static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus) | |
327 | { | |
328 | linked_list_t *list; | |
329 | ||
330 | /* install others (initiators) SAs*/ | |
331 | if (install(this, proposal, prf_plus, FALSE) != SUCCESS) | |
332 | { | |
333 | return FAILED; | |
334 | } | |
335 | ||
336 | /* get SPIs for our SAs */ | |
337 | list = linked_list_create(); | |
338 | list->insert_last(list, proposal); | |
339 | if (alloc(this, list) != SUCCESS) | |
340 | { | |
341 | list->destroy(list); | |
342 | return FAILED; | |
343 | } | |
344 | list->destroy(list); | |
345 | ||
346 | /* install our (responders) SAs */ | |
347 | if (install(this, proposal, prf_plus, TRUE) != SUCCESS) | |
348 | { | |
349 | return FAILED; | |
350 | } | |
a527a426 | 351 | |
30b5b412 MW |
352 | return SUCCESS; |
353 | } | |
354 | ||
355 | static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus) | |
356 | { | |
357 | /* install our (initator) SAs */ | |
358 | if (install(this, proposal, prf_plus, TRUE) != SUCCESS) | |
359 | { | |
360 | return FAILED; | |
361 | } | |
362 | /* install his (responder) SAs */ | |
363 | if (install(this, proposal, prf_plus, FALSE) != SUCCESS) | |
364 | { | |
365 | return FAILED; | |
366 | } | |
a527a426 MW |
367 | |
368 | return SUCCESS; | |
369 | } | |
370 | ||
5d187bd2 | 371 | static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list) |
a527a426 | 372 | { |
5d187bd2 MW |
373 | iterator_t *my_iter, *other_iter; |
374 | traffic_selector_t *my_ts, *other_ts; | |
a527a426 | 375 | |
5d187bd2 MW |
376 | /* iterate over both lists */ |
377 | my_iter = my_ts_list->create_iterator(my_ts_list, TRUE); | |
378 | other_iter = other_ts_list->create_iterator(other_ts_list, TRUE); | |
379 | while (my_iter->has_next(my_iter)) | |
a527a426 | 380 | { |
5d187bd2 MW |
381 | my_iter->current(my_iter, (void**)&my_ts); |
382 | other_iter->reset(other_iter); | |
383 | while (other_iter->has_next(other_iter)) | |
384 | { | |
385 | /* set up policies for every entry in my_ts_list to every entry in other_ts_list */ | |
386 | int family; | |
b1953ccd | 387 | chunk_t from_addr; |
5d187bd2 | 388 | u_int16_t from_port, to_port; |
16b9a73c | 389 | sa_policy_t *policy; |
5d187bd2 MW |
390 | status_t status; |
391 | ||
392 | other_iter->current(other_iter, (void**)&other_ts); | |
393 | ||
394 | /* only set up policies if protocol matches */ | |
395 | if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts)) | |
396 | { | |
397 | continue; | |
398 | } | |
5113680f | 399 | policy = malloc_thing(sa_policy_t); |
5d187bd2 MW |
400 | policy->upper_proto = my_ts->get_protocol(my_ts); |
401 | ||
402 | /* calculate net and ports for local side */ | |
403 | family = my_ts->get_type(my_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; | |
404 | from_addr = my_ts->get_from_address(my_ts); | |
5d187bd2 MW |
405 | from_port = my_ts->get_from_port(my_ts); |
406 | to_port = my_ts->get_to_port(my_ts); | |
407 | from_port = (from_port != to_port) ? 0 : from_port; | |
408 | policy->my_net = host_create_from_chunk(family, from_addr, from_port); | |
b1953ccd | 409 | policy->my_net_mask = my_ts->get_netmask(my_ts); |
5113680f | 410 | chunk_free(&from_addr); |
5d187bd2 MW |
411 | |
412 | /* calculate net and ports for remote side */ | |
413 | family = other_ts->get_type(other_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; | |
414 | from_addr = other_ts->get_from_address(other_ts); | |
5d187bd2 MW |
415 | from_port = other_ts->get_from_port(other_ts); |
416 | to_port = other_ts->get_to_port(other_ts); | |
417 | from_port = (from_port != to_port) ? 0 : from_port; | |
418 | policy->other_net = host_create_from_chunk(family, from_addr, from_port); | |
b1953ccd | 419 | policy->other_net_mask = other_ts->get_netmask(other_ts); |
5113680f | 420 | chunk_free(&from_addr); |
a527a426 | 421 | |
5d187bd2 MW |
422 | /* install 3 policies: out, in and forward */ |
423 | status = charon->kernel_interface->add_policy(charon->kernel_interface, | |
424 | this->me, this->other, | |
425 | policy->my_net, policy->other_net, | |
426 | policy->my_net_mask, policy->other_net_mask, | |
427 | XFRM_POLICY_OUT, policy->upper_proto, | |
428 | this->my_ah_spi, this->my_esp_spi, | |
429 | this->reqid); | |
a527a426 | 430 | |
5d187bd2 MW |
431 | status |= charon->kernel_interface->add_policy(charon->kernel_interface, |
432 | this->other, this->me, | |
433 | policy->other_net, policy->my_net, | |
434 | policy->other_net_mask, policy->my_net_mask, | |
435 | XFRM_POLICY_IN, policy->upper_proto, | |
436 | this->my_ah_spi, this->my_esp_spi, | |
437 | this->reqid); | |
a527a426 | 438 | |
5d187bd2 MW |
439 | status |= charon->kernel_interface->add_policy(charon->kernel_interface, |
440 | this->other, this->me, | |
441 | policy->other_net, policy->my_net, | |
442 | policy->other_net_mask, policy->my_net_mask, | |
443 | XFRM_POLICY_FWD, policy->upper_proto, | |
444 | this->my_ah_spi, this->my_esp_spi, | |
445 | this->reqid); | |
446 | ||
447 | if (status != SUCCESS) | |
448 | { | |
449 | my_iter->destroy(my_iter); | |
450 | other_iter->destroy(other_iter); | |
9d7597bb MW |
451 | policy->my_net->destroy(policy->my_net); |
452 | policy->other_net->destroy(policy->other_net); | |
5113680f | 453 | free(policy); |
5d187bd2 MW |
454 | return status; |
455 | } | |
456 | ||
457 | /* add it to the policy list, since we want to know which policies we own */ | |
458 | this->policies->insert_last(this->policies, policy); | |
459 | } | |
460 | } | |
461 | ||
462 | my_iter->destroy(my_iter); | |
463 | other_iter->destroy(other_iter); | |
464 | return SUCCESS; | |
30b5b412 MW |
465 | } |
466 | ||
b92eef28 MW |
467 | /** |
468 | * Implementation of child_sa_t.log_status. | |
469 | */ | |
470 | static void log_status(private_child_sa_t *this, logger_t *logger) | |
471 | { | |
472 | iterator_t *iterator; | |
473 | sa_policy_t *policy; | |
474 | struct protoent *proto; | |
475 | char proto_buf[16] = ""; | |
476 | char *proto_name = proto_buf; | |
477 | ||
478 | if (logger == NULL) | |
479 | { | |
480 | logger = this->logger; | |
481 | } | |
482 | logger->log(logger, CONTROL, " protected with ESP (%x/%x), AH (%x,%x); traffic:", | |
483 | htons(this->my_esp_spi), htons(this->other_esp_spi), | |
484 | htons(this->my_ah_spi), htons(this->other_ah_spi)); | |
485 | iterator = this->policies->create_iterator(this->policies, TRUE); | |
486 | while (iterator->has_next(iterator)) | |
487 | { | |
488 | iterator->current(iterator, (void**)&policy); | |
489 | if (policy->upper_proto) | |
490 | { | |
491 | proto = getprotobynumber(policy->upper_proto); | |
492 | if (proto) | |
493 | { | |
494 | proto_name = proto->p_name; | |
495 | } | |
496 | else | |
497 | { | |
498 | snprintf(proto_buf, sizeof(proto_buf), "<%d>", policy->upper_proto); | |
499 | } | |
500 | } | |
501 | logger->log(logger, CONTROL, " %s/%d===%s===%s/%d", | |
502 | policy->my_net->get_address(policy->my_net), policy->my_net_mask, | |
503 | proto_name, | |
504 | policy->other_net->get_address(policy->other_net), policy->other_net_mask); | |
505 | } | |
506 | iterator->destroy(iterator); | |
507 | } | |
508 | ||
30b5b412 MW |
509 | /** |
510 | * Implementation of child_sa_t.destroy. | |
511 | */ | |
512 | static void destroy(private_child_sa_t *this) | |
513 | { | |
5d187bd2 | 514 | /* delete all policys in the kernel */ |
16b9a73c | 515 | sa_policy_t *policy; |
5d187bd2 MW |
516 | while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS) |
517 | { | |
518 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
519 | this->me, this->other, | |
520 | policy->my_net, policy->other_net, | |
521 | policy->my_net_mask, policy->other_net_mask, | |
522 | XFRM_POLICY_OUT, policy->upper_proto); | |
523 | ||
524 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
525 | this->other, this->me, | |
526 | policy->other_net, policy->my_net, | |
527 | policy->other_net_mask, policy->my_net_mask, | |
528 | XFRM_POLICY_IN, policy->upper_proto); | |
529 | ||
530 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
531 | this->other, this->me, | |
532 | policy->other_net, policy->my_net, | |
533 | policy->other_net_mask, policy->my_net_mask, | |
534 | XFRM_POLICY_FWD, policy->upper_proto); | |
535 | ||
536 | policy->my_net->destroy(policy->my_net); | |
537 | policy->other_net->destroy(policy->other_net); | |
5113680f | 538 | free(policy); |
5d187bd2 MW |
539 | } |
540 | this->policies->destroy(this->policies); | |
541 | ||
542 | /* delete SAs in the kernel, if they are set up */ | |
543 | if (this->my_ah_spi) | |
544 | { | |
545 | charon->kernel_interface->del_sa(charon->kernel_interface, | |
dec59822 | 546 | this->other, this->my_ah_spi, PROTO_AH); |
5d187bd2 | 547 | charon->kernel_interface->del_sa(charon->kernel_interface, |
dec59822 | 548 | this->me, this->other_ah_spi, PROTO_AH); |
5d187bd2 MW |
549 | } |
550 | if (this->my_esp_spi) | |
551 | { | |
552 | charon->kernel_interface->del_sa(charon->kernel_interface, | |
dec59822 | 553 | this->other, this->my_esp_spi, PROTO_ESP); |
5d187bd2 | 554 | charon->kernel_interface->del_sa(charon->kernel_interface, |
dec59822 | 555 | this->me, this->other_esp_spi, PROTO_ESP); |
5d187bd2 | 556 | } |
5113680f | 557 | free(this); |
30b5b412 MW |
558 | } |
559 | ||
560 | /* | |
561 | * Described in header. | |
562 | */ | |
563 | child_sa_t * child_sa_create(host_t *me, host_t* other) | |
564 | { | |
aa5a35a0 | 565 | static u_int32_t reqid = 0xc0000000; |
5113680f | 566 | private_child_sa_t *this = malloc_thing(private_child_sa_t); |
30b5b412 MW |
567 | |
568 | /* public functions */ | |
30b5b412 MW |
569 | this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc; |
570 | this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add; | |
571 | this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update; | |
5d187bd2 | 572 | this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies; |
b92eef28 | 573 | this->public.log_status = (void (*)(child_sa_t*, logger_t*))log_status; |
30b5b412 MW |
574 | this->public.destroy = (void(*)(child_sa_t*))destroy; |
575 | ||
576 | /* private data */ | |
5113680f | 577 | this->logger = logger_manager->get_logger(logger_manager, CHILD_SA); |
30b5b412 MW |
578 | this->me = me; |
579 | this->other = other; | |
5d187bd2 MW |
580 | this->my_ah_spi = 0; |
581 | this->my_esp_spi = 0; | |
582 | this->other_ah_spi = 0; | |
583 | this->other_esp_spi = 0; | |
a527a426 | 584 | this->reqid = reqid++; |
5d187bd2 | 585 | this->policies = linked_list_create(); |
3ebebc5e | 586 | |
3ebebc5e MW |
587 | return (&this->public); |
588 | } |