]>
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 | ||
32b6500f MW |
122 | /** |
123 | * Implements child_sa_t.get_reqid | |
124 | */ | |
125 | static u_int32_t get_reqid(private_child_sa_t *this) | |
126 | { | |
127 | return this->reqid; | |
128 | } | |
129 | ||
3ebebc5e | 130 | /** |
30b5b412 | 131 | * Implements child_sa_t.alloc |
3ebebc5e | 132 | */ |
30b5b412 | 133 | static status_t alloc(private_child_sa_t *this, linked_list_t *proposals) |
3ebebc5e | 134 | { |
30b5b412 MW |
135 | protocol_id_t protocols[2]; |
136 | iterator_t *iterator; | |
137 | proposal_t *proposal; | |
138 | status_t status; | |
139 | u_int i; | |
140 | ||
141 | /* iterator through proposals */ | |
142 | iterator = proposals->create_iterator(proposals, TRUE); | |
143 | while(iterator->has_next(iterator)) | |
144 | { | |
145 | iterator->current(iterator, (void**)&proposal); | |
146 | proposal->get_protocols(proposal, protocols); | |
147 | ||
148 | /* check all protocols */ | |
149 | for (i = 0; i<2; i++) | |
150 | { | |
151 | switch (protocols[i]) | |
152 | { | |
dec59822 | 153 | case PROTO_AH: |
30b5b412 | 154 | /* do we already have an spi for AH?*/ |
5d187bd2 | 155 | if (this->my_ah_spi == 0) |
30b5b412 MW |
156 | { |
157 | /* nope, get one */ | |
158 | status = charon->kernel_interface->get_spi( | |
159 | charon->kernel_interface, | |
160 | this->me, this->other, | |
dec59822 | 161 | PROTO_AH, FALSE, |
5d187bd2 | 162 | &(this->my_ah_spi)); |
30b5b412 MW |
163 | } |
164 | /* update proposal */ | |
dec59822 | 165 | proposal->set_spi(proposal, PROTO_AH, (u_int64_t)this->my_ah_spi); |
30b5b412 | 166 | break; |
dec59822 | 167 | case PROTO_ESP: |
30b5b412 | 168 | /* do we already have an spi for ESP?*/ |
5d187bd2 | 169 | if (this->my_esp_spi == 0) |
30b5b412 MW |
170 | { |
171 | /* nope, get one */ | |
172 | status = charon->kernel_interface->get_spi( | |
173 | charon->kernel_interface, | |
174 | this->me, this->other, | |
dec59822 | 175 | PROTO_ESP, FALSE, |
5d187bd2 | 176 | &(this->my_esp_spi)); |
30b5b412 MW |
177 | } |
178 | /* update proposal */ | |
dec59822 | 179 | proposal->set_spi(proposal, PROTO_ESP, (u_int64_t)this->my_esp_spi); |
30b5b412 MW |
180 | break; |
181 | default: | |
182 | break; | |
183 | } | |
184 | if (status != SUCCESS) | |
185 | { | |
186 | iterator->destroy(iterator); | |
187 | return FAILED; | |
188 | } | |
189 | } | |
190 | } | |
191 | iterator->destroy(iterator); | |
192 | return SUCCESS; | |
3ebebc5e MW |
193 | } |
194 | ||
30b5b412 | 195 | static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus, bool mine) |
3ebebc5e | 196 | { |
30b5b412 MW |
197 | protocol_id_t protocols[2]; |
198 | u_int32_t spi; | |
199 | encryption_algorithm_t enc_algo; | |
200 | integrity_algorithm_t int_algo; | |
201 | chunk_t enc_key, int_key; | |
202 | algorithm_t *algo; | |
203 | crypter_t *crypter; | |
204 | signer_t *signer; | |
205 | size_t key_size; | |
206 | host_t *src; | |
207 | host_t *dst; | |
208 | status_t status; | |
aeda79ff | 209 | u_int i; |
aeda79ff | 210 | |
30b5b412 MW |
211 | /* we must assign the roles to correctly set up the SAs */ |
212 | if (mine) | |
213 | { | |
214 | src = this->me; | |
215 | dst = this->other; | |
216 | } | |
217 | else | |
218 | { | |
219 | dst = this->me; | |
220 | src = this->other; | |
221 | } | |
222 | ||
223 | proposal->get_protocols(proposal, protocols); | |
224 | /* derive keys in order as protocols appear */ | |
aeda79ff MW |
225 | for (i = 0; i<2; i++) |
226 | { | |
dec59822 | 227 | if (protocols[i] != PROTO_NONE) |
aeda79ff | 228 | { |
aeda79ff | 229 | |
30b5b412 MW |
230 | /* now we have to decide which spi to use. Use self allocated, if "mine", |
231 | * or the one in the proposal, if not "mine" (others). */ | |
232 | if (mine) | |
233 | { | |
dec59822 | 234 | if (protocols[i] == PROTO_AH) |
30b5b412 | 235 | { |
5d187bd2 | 236 | spi = this->my_ah_spi; |
30b5b412 MW |
237 | } |
238 | else | |
239 | { | |
5d187bd2 | 240 | spi = this->my_esp_spi; |
30b5b412 MW |
241 | } |
242 | } | |
243 | else /* use proposals spi */ | |
244 | { | |
245 | spi = proposal->get_spi(proposal, protocols[i]); | |
dec59822 | 246 | if (protocols[i] == PROTO_AH) |
5d187bd2 MW |
247 | { |
248 | this->other_ah_spi = spi; | |
249 | } | |
250 | else | |
251 | { | |
252 | this->other_esp_spi = spi; | |
253 | } | |
30b5b412 MW |
254 | } |
255 | ||
256 | /* derive encryption key first */ | |
257 | if (proposal->get_algorithm(proposal, protocols[i], ENCRYPTION_ALGORITHM, &algo)) | |
aeda79ff | 258 | { |
30b5b412 MW |
259 | enc_algo = algo->algorithm; |
260 | this->logger->log(this->logger, CONTROL|LEVEL1, "%s for %s: using %s %s, ", | |
261 | mapping_find(protocol_id_m, protocols[i]), | |
262 | mine ? "me" : "other", | |
aeda79ff | 263 | mapping_find(transform_type_m, ENCRYPTION_ALGORITHM), |
30b5b412 | 264 | mapping_find(encryption_algorithm_m, enc_algo)); |
aeda79ff | 265 | |
30b5b412 MW |
266 | /* we must create a (unused) crypter, since its the only way to get the size |
267 | * of the key. This is not so nice, since charon must support all algorithms | |
268 | * the kernel supports... | |
269 | * TODO: build something of a encryption algorithm lookup function | |
270 | */ | |
271 | crypter = crypter_create(enc_algo, algo->key_size); | |
272 | key_size = crypter->get_key_size(crypter); | |
273 | crypter->destroy(crypter); | |
274 | prf_plus->allocate_bytes(prf_plus, key_size, &enc_key); | |
16b9a73c | 275 | this->logger->log_chunk(this->logger, PRIVATE, "key:", enc_key); |
30b5b412 MW |
276 | } |
277 | else | |
278 | { | |
279 | enc_algo = ENCR_UNDEFINED; | |
aeda79ff MW |
280 | } |
281 | ||
30b5b412 MW |
282 | /* derive integrity key */ |
283 | if (proposal->get_algorithm(proposal, protocols[i], INTEGRITY_ALGORITHM, &algo)) | |
aeda79ff | 284 | { |
30b5b412 MW |
285 | int_algo = algo->algorithm; |
286 | this->logger->log(this->logger, CONTROL|LEVEL1, "%s for %s: using %s %s,", | |
287 | mapping_find(protocol_id_m, protocols[i]), | |
288 | mine ? "me" : "other", | |
aeda79ff MW |
289 | mapping_find(transform_type_m, INTEGRITY_ALGORITHM), |
290 | mapping_find(integrity_algorithm_m, algo->algorithm)); | |
291 | ||
30b5b412 MW |
292 | signer = signer_create(int_algo); |
293 | key_size = signer->get_key_size(signer); | |
294 | signer->destroy(signer); | |
295 | prf_plus->allocate_bytes(prf_plus, key_size, &int_key); | |
16b9a73c | 296 | this->logger->log_chunk(this->logger, PRIVATE, "key:", int_key); |
30b5b412 MW |
297 | } |
298 | else | |
299 | { | |
300 | int_algo = AUTH_UNDEFINED; | |
301 | } | |
302 | /* send keys down to kernel */ | |
303 | this->logger->log(this->logger, CONTROL|LEVEL1, | |
304 | "installing 0x%.8x for %s, src %s dst %s", | |
305 | ntohl(spi), mapping_find(protocol_id_m, protocols[i]), | |
306 | src->get_address(src), dst->get_address(dst)); | |
307 | status = charon->kernel_interface->add_sa(charon->kernel_interface, | |
308 | src, dst, | |
a527a426 MW |
309 | spi, protocols[i], |
310 | this->reqid, | |
32b6500f | 311 | 5, 30, |
30b5b412 MW |
312 | enc_algo, enc_key, |
313 | int_algo, int_key, mine); | |
314 | /* clean up for next round */ | |
315 | if (enc_algo != ENCR_UNDEFINED) | |
316 | { | |
5113680f | 317 | chunk_free(&enc_key); |
aeda79ff | 318 | } |
30b5b412 MW |
319 | if (int_algo != AUTH_UNDEFINED) |
320 | { | |
5113680f | 321 | chunk_free(&int_key); |
30b5b412 MW |
322 | } |
323 | ||
324 | if (status != SUCCESS) | |
325 | { | |
326 | return FAILED; | |
327 | } | |
aeda79ff MW |
328 | } |
329 | } | |
30b5b412 MW |
330 | return SUCCESS; |
331 | } | |
332 | ||
333 | static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus) | |
334 | { | |
335 | linked_list_t *list; | |
336 | ||
337 | /* install others (initiators) SAs*/ | |
338 | if (install(this, proposal, prf_plus, FALSE) != SUCCESS) | |
339 | { | |
340 | return FAILED; | |
341 | } | |
342 | ||
343 | /* get SPIs for our SAs */ | |
344 | list = linked_list_create(); | |
345 | list->insert_last(list, proposal); | |
346 | if (alloc(this, list) != SUCCESS) | |
347 | { | |
348 | list->destroy(list); | |
349 | return FAILED; | |
350 | } | |
351 | list->destroy(list); | |
352 | ||
353 | /* install our (responders) SAs */ | |
354 | if (install(this, proposal, prf_plus, TRUE) != SUCCESS) | |
355 | { | |
356 | return FAILED; | |
357 | } | |
a527a426 | 358 | |
30b5b412 MW |
359 | return SUCCESS; |
360 | } | |
361 | ||
362 | static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus) | |
363 | { | |
364 | /* install our (initator) SAs */ | |
365 | if (install(this, proposal, prf_plus, TRUE) != SUCCESS) | |
366 | { | |
367 | return FAILED; | |
368 | } | |
369 | /* install his (responder) SAs */ | |
370 | if (install(this, proposal, prf_plus, FALSE) != SUCCESS) | |
371 | { | |
372 | return FAILED; | |
373 | } | |
a527a426 MW |
374 | |
375 | return SUCCESS; | |
376 | } | |
377 | ||
5d187bd2 | 378 | static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list) |
a527a426 | 379 | { |
5d187bd2 MW |
380 | iterator_t *my_iter, *other_iter; |
381 | traffic_selector_t *my_ts, *other_ts; | |
a527a426 | 382 | |
5d187bd2 MW |
383 | /* iterate over both lists */ |
384 | my_iter = my_ts_list->create_iterator(my_ts_list, TRUE); | |
385 | other_iter = other_ts_list->create_iterator(other_ts_list, TRUE); | |
386 | while (my_iter->has_next(my_iter)) | |
a527a426 | 387 | { |
5d187bd2 MW |
388 | my_iter->current(my_iter, (void**)&my_ts); |
389 | other_iter->reset(other_iter); | |
390 | while (other_iter->has_next(other_iter)) | |
391 | { | |
392 | /* set up policies for every entry in my_ts_list to every entry in other_ts_list */ | |
393 | int family; | |
b1953ccd | 394 | chunk_t from_addr; |
5d187bd2 | 395 | u_int16_t from_port, to_port; |
16b9a73c | 396 | sa_policy_t *policy; |
5d187bd2 MW |
397 | status_t status; |
398 | ||
399 | other_iter->current(other_iter, (void**)&other_ts); | |
400 | ||
401 | /* only set up policies if protocol matches */ | |
402 | if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts)) | |
403 | { | |
404 | continue; | |
405 | } | |
5113680f | 406 | policy = malloc_thing(sa_policy_t); |
5d187bd2 MW |
407 | policy->upper_proto = my_ts->get_protocol(my_ts); |
408 | ||
409 | /* calculate net and ports for local side */ | |
410 | family = my_ts->get_type(my_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; | |
411 | from_addr = my_ts->get_from_address(my_ts); | |
5d187bd2 MW |
412 | from_port = my_ts->get_from_port(my_ts); |
413 | to_port = my_ts->get_to_port(my_ts); | |
414 | from_port = (from_port != to_port) ? 0 : from_port; | |
415 | policy->my_net = host_create_from_chunk(family, from_addr, from_port); | |
b1953ccd | 416 | policy->my_net_mask = my_ts->get_netmask(my_ts); |
5113680f | 417 | chunk_free(&from_addr); |
5d187bd2 MW |
418 | |
419 | /* calculate net and ports for remote side */ | |
420 | family = other_ts->get_type(other_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; | |
421 | from_addr = other_ts->get_from_address(other_ts); | |
5d187bd2 MW |
422 | from_port = other_ts->get_from_port(other_ts); |
423 | to_port = other_ts->get_to_port(other_ts); | |
424 | from_port = (from_port != to_port) ? 0 : from_port; | |
425 | policy->other_net = host_create_from_chunk(family, from_addr, from_port); | |
b1953ccd | 426 | policy->other_net_mask = other_ts->get_netmask(other_ts); |
5113680f | 427 | chunk_free(&from_addr); |
a527a426 | 428 | |
5d187bd2 MW |
429 | /* install 3 policies: out, in and forward */ |
430 | status = charon->kernel_interface->add_policy(charon->kernel_interface, | |
431 | this->me, this->other, | |
432 | policy->my_net, policy->other_net, | |
433 | policy->my_net_mask, policy->other_net_mask, | |
434 | XFRM_POLICY_OUT, policy->upper_proto, | |
435 | this->my_ah_spi, this->my_esp_spi, | |
436 | this->reqid); | |
a527a426 | 437 | |
5d187bd2 MW |
438 | status |= charon->kernel_interface->add_policy(charon->kernel_interface, |
439 | this->other, this->me, | |
440 | policy->other_net, policy->my_net, | |
441 | policy->other_net_mask, policy->my_net_mask, | |
442 | XFRM_POLICY_IN, policy->upper_proto, | |
443 | this->my_ah_spi, this->my_esp_spi, | |
444 | this->reqid); | |
a527a426 | 445 | |
5d187bd2 MW |
446 | status |= charon->kernel_interface->add_policy(charon->kernel_interface, |
447 | this->other, this->me, | |
448 | policy->other_net, policy->my_net, | |
449 | policy->other_net_mask, policy->my_net_mask, | |
450 | XFRM_POLICY_FWD, policy->upper_proto, | |
451 | this->my_ah_spi, this->my_esp_spi, | |
452 | this->reqid); | |
453 | ||
454 | if (status != SUCCESS) | |
455 | { | |
456 | my_iter->destroy(my_iter); | |
457 | other_iter->destroy(other_iter); | |
9d7597bb MW |
458 | policy->my_net->destroy(policy->my_net); |
459 | policy->other_net->destroy(policy->other_net); | |
5113680f | 460 | free(policy); |
5d187bd2 MW |
461 | return status; |
462 | } | |
463 | ||
464 | /* add it to the policy list, since we want to know which policies we own */ | |
465 | this->policies->insert_last(this->policies, policy); | |
466 | } | |
467 | } | |
468 | ||
469 | my_iter->destroy(my_iter); | |
470 | other_iter->destroy(other_iter); | |
471 | return SUCCESS; | |
30b5b412 MW |
472 | } |
473 | ||
b92eef28 MW |
474 | /** |
475 | * Implementation of child_sa_t.log_status. | |
476 | */ | |
e168ee17 | 477 | static void log_status(private_child_sa_t *this, logger_t *logger, char* name) |
b92eef28 MW |
478 | { |
479 | iterator_t *iterator; | |
480 | sa_policy_t *policy; | |
481 | struct protoent *proto; | |
108b489f | 482 | char proto_buf[8] = ""; |
b92eef28 MW |
483 | char *proto_name = proto_buf; |
484 | ||
485 | if (logger == NULL) | |
486 | { | |
487 | logger = this->logger; | |
488 | } | |
8b5be79d | 489 | logger->log(logger, CONTROL|LEVEL1, " \"%s\": protected with ESP (0x%x/0x%x), AH (0x%x,0x%x):", |
e168ee17 | 490 | name, |
108b489f MW |
491 | htonl(this->my_esp_spi), htonl(this->other_esp_spi), |
492 | htonl(this->my_ah_spi), htonl(this->other_ah_spi)); | |
b92eef28 MW |
493 | iterator = this->policies->create_iterator(this->policies, TRUE); |
494 | while (iterator->has_next(iterator)) | |
495 | { | |
496 | iterator->current(iterator, (void**)&policy); | |
497 | if (policy->upper_proto) | |
498 | { | |
499 | proto = getprotobynumber(policy->upper_proto); | |
500 | if (proto) | |
501 | { | |
502 | proto_name = proto->p_name; | |
503 | } | |
504 | else | |
505 | { | |
506 | snprintf(proto_buf, sizeof(proto_buf), "<%d>", policy->upper_proto); | |
507 | } | |
508 | } | |
8b5be79d | 509 | logger->log(logger, CONTROL, " \"%s\": %s/%d==%s==%s/%d", |
e168ee17 | 510 | name, |
b92eef28 MW |
511 | policy->my_net->get_address(policy->my_net), policy->my_net_mask, |
512 | proto_name, | |
513 | policy->other_net->get_address(policy->other_net), policy->other_net_mask); | |
514 | } | |
515 | iterator->destroy(iterator); | |
516 | } | |
517 | ||
30b5b412 MW |
518 | /** |
519 | * Implementation of child_sa_t.destroy. | |
520 | */ | |
521 | static void destroy(private_child_sa_t *this) | |
522 | { | |
7881ac14 | 523 | /* delete all policies in the kernel */ |
16b9a73c | 524 | sa_policy_t *policy; |
5d187bd2 MW |
525 | while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS) |
526 | { | |
527 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
528 | this->me, this->other, | |
529 | policy->my_net, policy->other_net, | |
530 | policy->my_net_mask, policy->other_net_mask, | |
531 | XFRM_POLICY_OUT, policy->upper_proto); | |
532 | ||
533 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
534 | this->other, this->me, | |
535 | policy->other_net, policy->my_net, | |
536 | policy->other_net_mask, policy->my_net_mask, | |
537 | XFRM_POLICY_IN, policy->upper_proto); | |
538 | ||
539 | charon->kernel_interface->del_policy(charon->kernel_interface, | |
540 | this->other, this->me, | |
541 | policy->other_net, policy->my_net, | |
542 | policy->other_net_mask, policy->my_net_mask, | |
543 | XFRM_POLICY_FWD, policy->upper_proto); | |
544 | ||
545 | policy->my_net->destroy(policy->my_net); | |
546 | policy->other_net->destroy(policy->other_net); | |
5113680f | 547 | free(policy); |
5d187bd2 MW |
548 | } |
549 | this->policies->destroy(this->policies); | |
550 | ||
551 | /* delete SAs in the kernel, if they are set up */ | |
552 | if (this->my_ah_spi) | |
553 | { | |
554 | charon->kernel_interface->del_sa(charon->kernel_interface, | |
dec59822 | 555 | this->other, this->my_ah_spi, PROTO_AH); |
5d187bd2 | 556 | charon->kernel_interface->del_sa(charon->kernel_interface, |
dec59822 | 557 | this->me, this->other_ah_spi, PROTO_AH); |
5d187bd2 MW |
558 | } |
559 | if (this->my_esp_spi) | |
560 | { | |
561 | charon->kernel_interface->del_sa(charon->kernel_interface, | |
dec59822 | 562 | this->other, this->my_esp_spi, PROTO_ESP); |
5d187bd2 | 563 | charon->kernel_interface->del_sa(charon->kernel_interface, |
dec59822 | 564 | this->me, this->other_esp_spi, PROTO_ESP); |
5d187bd2 | 565 | } |
5113680f | 566 | free(this); |
30b5b412 MW |
567 | } |
568 | ||
569 | /* | |
570 | * Described in header. | |
571 | */ | |
572 | child_sa_t * child_sa_create(host_t *me, host_t* other) | |
573 | { | |
32b6500f | 574 | static u_int32_t reqid = 2000000000; |
5113680f | 575 | private_child_sa_t *this = malloc_thing(private_child_sa_t); |
30b5b412 MW |
576 | |
577 | /* public functions */ | |
32b6500f | 578 | this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid; |
30b5b412 MW |
579 | this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc; |
580 | this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add; | |
581 | this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update; | |
5d187bd2 | 582 | this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies; |
e168ee17 | 583 | this->public.log_status = (void (*)(child_sa_t*, logger_t*, char*))log_status; |
30b5b412 MW |
584 | this->public.destroy = (void(*)(child_sa_t*))destroy; |
585 | ||
586 | /* private data */ | |
5113680f | 587 | this->logger = logger_manager->get_logger(logger_manager, CHILD_SA); |
30b5b412 MW |
588 | this->me = me; |
589 | this->other = other; | |
5d187bd2 MW |
590 | this->my_ah_spi = 0; |
591 | this->my_esp_spi = 0; | |
592 | this->other_ah_spi = 0; | |
593 | this->other_esp_spi = 0; | |
32b6500f | 594 | this->reqid = ++reqid; |
5d187bd2 | 595 | this->policies = linked_list_create(); |
3ebebc5e | 596 | |
3ebebc5e MW |
597 | return (&this->public); |
598 | } |