2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2007 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 #include "child_create.h"
23 #include <crypto/diffie_hellman.h>
24 #include <encoding/payloads/sa_payload.h>
25 #include <encoding/payloads/ke_payload.h>
26 #include <encoding/payloads/ts_payload.h>
27 #include <encoding/payloads/nonce_payload.h>
28 #include <encoding/payloads/notify_payload.h>
29 #include <processing/jobs/delete_ike_sa_job.h>
32 typedef struct private_child_create_t private_child_create_t
;
35 * Private members of a child_create_t task.
37 struct private_child_create_t
{
40 * Public methods and task_t interface.
42 child_create_t
public;
50 * Are we the initiator?
60 * nonce chosen by peer
65 * config to create the CHILD_SA from
70 * list of proposal candidates
72 linked_list_t
*proposals
;
75 * selected proposal to use for CHILD_SA
80 * traffic selectors for initiators side
85 * traffic selectors for responders side
90 * optional diffie hellman exchange
95 * group used for DH exchange
97 diffie_hellman_group_t dh_group
;
100 * mode the new CHILD_SA uses (transport/tunnel/beet)
105 * IPComp transform to use
107 ipcomp_transform_t ipcomp
;
110 * IPComp transform proposed or accepted by the other peer
112 ipcomp_transform_t ipcomp_received
;
115 * Other Compression Parameter Index (CPI)
120 * reqid to use if we are rekeying
125 * CHILD_SA which gets established
127 child_sa_t
*child_sa
;
130 * successfully established the CHILD?
136 * get the nonce from a message
138 static status_t
get_nonce(message_t
*message
, chunk_t
*nonce
)
140 nonce_payload_t
*payload
;
142 payload
= (nonce_payload_t
*)message
->get_payload(message
, NONCE
);
147 *nonce
= payload
->get_nonce(payload
);
152 * generate a new nonce to include in a CREATE_CHILD_SA message
154 static status_t
generate_nonce(chunk_t
*nonce
)
158 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
161 DBG1(DBG_IKE
, "error generating nonce value, no RNG found");
164 rng
->allocate_bytes(rng
, NONCE_SIZE
, nonce
);
170 * Check a list of traffic selectors if any selector belongs to host
172 static bool ts_list_is_host(linked_list_t
*list
, host_t
*host
)
174 traffic_selector_t
*ts
;
176 iterator_t
*iterator
= list
->create_iterator(list
, TRUE
);
178 while (is_host
&& iterator
->iterate(iterator
, (void**)&ts
))
180 is_host
= is_host
&& ts
->is_host(ts
, host
);
182 iterator
->destroy(iterator
);
187 * Install a CHILD_SA for usage, return value:
188 * - FAILED: no acceptable proposal
189 * - INVALID_ARG: diffie hellman group inacceptable
190 * - NOT_FOUND: TS inacceptable
192 static status_t
select_and_install(private_child_create_t
*this, bool no_dh
)
194 prf_plus_t
*prf_plus
;
196 chunk_t nonce_i
, nonce_r
, secret
, seed
;
197 linked_list_t
*my_ts
, *other_ts
;
198 host_t
*me
, *other
, *other_vip
, *my_vip
;
200 if (this->proposals
== NULL
)
202 DBG1(DBG_IKE
, "SA payload missing in message");
205 if (this->tsi
== NULL
|| this->tsr
== NULL
)
207 DBG1(DBG_IKE
, "TS payloads missing in message");
213 nonce_i
= this->my_nonce
;
214 nonce_r
= this->other_nonce
;
216 other_ts
= this->tsr
;
220 nonce_r
= this->my_nonce
;
221 nonce_i
= this->other_nonce
;
223 other_ts
= this->tsi
;
226 me
= this->ike_sa
->get_my_host(this->ike_sa
);
227 other
= this->ike_sa
->get_other_host(this->ike_sa
);
228 my_vip
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
229 other_vip
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
231 this->proposal
= this->config
->select_proposal(this->config
, this->proposals
,
233 if (this->proposal
== NULL
)
235 DBG1(DBG_IKE
, "no acceptable proposal found");
239 if (!this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
243 if (this->proposal
->get_algorithm(this->proposal
, DIFFIE_HELLMAN_GROUP
,
246 DBG1(DBG_IKE
, "DH group %N inacceptable, requesting %N",
247 diffie_hellman_group_names
, this->dh_group
,
248 diffie_hellman_group_names
, group
);
249 this->dh_group
= group
;
254 DBG1(DBG_IKE
, "no acceptable proposal found");
263 if (other_vip
== NULL
)
268 my_ts
= this->config
->get_traffic_selectors(this->config
, TRUE
, my_ts
,
270 other_ts
= this->config
->get_traffic_selectors(this->config
, FALSE
, other_ts
,
273 if (my_ts
->get_count(my_ts
) == 0 || other_ts
->get_count(other_ts
) == 0)
275 my_ts
->destroy_offset(my_ts
, offsetof(traffic_selector_t
, destroy
));
276 other_ts
->destroy_offset(other_ts
, offsetof(traffic_selector_t
, destroy
));
277 DBG1(DBG_IKE
, "no acceptable traffic selectors found");
281 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
282 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
286 this->tsr
= other_ts
;
291 this->tsi
= other_ts
;
294 if (!this->initiator
)
296 /* check if requested mode is acceptable, downgrade if required */
300 if (!ts_list_is_host(this->tsi
, other
) ||
301 !ts_list_is_host(this->tsr
, me
))
303 this->mode
= MODE_TUNNEL
;
304 DBG1(DBG_IKE
, "not using tranport mode, not host-to-host");
306 else if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
308 this->mode
= MODE_TUNNEL
;
309 DBG1(DBG_IKE
, "not using tranport mode, connection NATed");
313 if (!ts_list_is_host(this->tsi
, NULL
) ||
314 !ts_list_is_host(this->tsr
, NULL
))
316 this->mode
= MODE_TUNNEL
;
317 DBG1(DBG_IKE
, "not using BEET mode, not host-to-host");
327 if (this->dh
->get_shared_secret(this->dh
, &secret
) != SUCCESS
)
329 DBG1(DBG_IKE
, "DH exchange incomplete");
332 DBG3(DBG_IKE
, "DH secret %B", &secret
);
333 seed
= chunk_cata("mcc", secret
, nonce_i
, nonce_r
);
337 seed
= chunk_cata("cc", nonce_i
, nonce_r
);
340 if (this->ipcomp
!= IPCOMP_NONE
)
342 this->child_sa
->activate_ipcomp(this->child_sa
, this->ipcomp
,
346 status
= this->child_sa
->add_policies(this->child_sa
, my_ts
, other_ts
,
347 this->mode
, this->proposal
->get_protocol(this->proposal
));
348 if (status
!= SUCCESS
)
350 DBG1(DBG_IKE
, "unable to install IPsec policies (SPD) in kernel");
354 prf_plus
= prf_plus_create(this->ike_sa
->get_child_prf(this->ike_sa
), seed
);
357 status
= this->child_sa
->update(this->child_sa
, this->proposal
,
358 this->mode
, prf_plus
);
362 status
= this->child_sa
->add(this->child_sa
, this->proposal
,
363 this->mode
, prf_plus
);
365 prf_plus
->destroy(prf_plus
);
367 if (status
!= SUCCESS
)
369 DBG1(DBG_IKE
, "unable to install IPsec SA (SAD) in kernel");
372 /* add to IKE_SA, and remove from task */
373 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLED
);
374 this->ike_sa
->add_child_sa(this->ike_sa
, this->child_sa
);
375 this->established
= TRUE
;
380 * build the payloads for the message
382 static void build_payloads(private_child_create_t
*this, message_t
*message
)
384 sa_payload_t
*sa_payload
;
385 nonce_payload_t
*nonce_payload
;
386 ke_payload_t
*ke_payload
;
387 ts_payload_t
*ts_payload
;
392 sa_payload
= sa_payload_create_from_proposal_list(this->proposals
);
396 sa_payload
= sa_payload_create_from_proposal(this->proposal
);
398 message
->add_payload(message
, (payload_t
*)sa_payload
);
400 /* add nonce payload if not in IKE_AUTH */
401 if (message
->get_exchange_type(message
) == CREATE_CHILD_SA
)
403 nonce_payload
= nonce_payload_create();
404 nonce_payload
->set_nonce(nonce_payload
, this->my_nonce
);
405 message
->add_payload(message
, (payload_t
*)nonce_payload
);
408 /* diffie hellman exchange, if PFS enabled */
411 ke_payload
= ke_payload_create_from_diffie_hellman(this->dh
);
412 message
->add_payload(message
, (payload_t
*)ke_payload
);
415 /* add TSi/TSr payloads */
416 ts_payload
= ts_payload_create_from_traffic_selectors(TRUE
, this->tsi
);
417 message
->add_payload(message
, (payload_t
*)ts_payload
);
418 ts_payload
= ts_payload_create_from_traffic_selectors(FALSE
, this->tsr
);
419 message
->add_payload(message
, (payload_t
*)ts_payload
);
421 /* add a notify if we are not in tunnel mode */
425 message
->add_notify(message
, FALSE
, USE_TRANSPORT_MODE
, chunk_empty
);
428 message
->add_notify(message
, FALSE
, USE_BEET_MODE
, chunk_empty
);
436 * Adds an IPCOMP_SUPPORTED notify to the message, if possible
438 static void build_ipcomp_supported_notify(private_child_create_t
*this,
444 if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
446 DBG1(DBG_IKE
, "IPComp is not supported if either peer is natted, "
448 this->ipcomp
= IPCOMP_NONE
;
452 cpi
= this->child_sa
->allocate_cpi(this->child_sa
);
456 message
->add_notify(message
, FALSE
, IPCOMP_SUPPORTED
,
457 chunk_cata("cc", chunk_from_thing(cpi
), chunk_from_thing(tid
)));
461 DBG1(DBG_IKE
, "unable to allocate a CPI from kernel, IPComp disabled");
462 this->ipcomp
= IPCOMP_NONE
;
467 * Read payloads from message
469 static void process_payloads(private_child_create_t
*this, message_t
*message
)
471 iterator_t
*iterator
;
473 sa_payload_t
*sa_payload
;
474 ke_payload_t
*ke_payload
;
475 ts_payload_t
*ts_payload
;
476 notify_payload_t
*notify_payload
;
478 /* defaults to TUNNEL mode */
479 this->mode
= MODE_TUNNEL
;
481 iterator
= message
->get_payload_iterator(message
);
482 while (iterator
->iterate(iterator
, (void**)&payload
))
484 switch (payload
->get_type(payload
))
486 case SECURITY_ASSOCIATION
:
487 sa_payload
= (sa_payload_t
*)payload
;
488 this->proposals
= sa_payload
->get_proposals(sa_payload
);
491 ke_payload
= (ke_payload_t
*)payload
;
492 if (!this->initiator
)
494 this->dh_group
= ke_payload
->get_dh_group_number(ke_payload
);
495 this->dh
= lib
->crypto
->create_dh(lib
->crypto
, this->dh_group
);
499 this->dh
->set_other_public_value(this->dh
,
500 ke_payload
->get_key_exchange_data(ke_payload
));
503 case TRAFFIC_SELECTOR_INITIATOR
:
504 ts_payload
= (ts_payload_t
*)payload
;
505 this->tsi
= ts_payload
->get_traffic_selectors(ts_payload
);
507 case TRAFFIC_SELECTOR_RESPONDER
:
508 ts_payload
= (ts_payload_t
*)payload
;
509 this->tsr
= ts_payload
->get_traffic_selectors(ts_payload
);
512 notify_payload
= (notify_payload_t
*)payload
;
513 switch (notify_payload
->get_notify_type(notify_payload
))
515 case USE_TRANSPORT_MODE
:
516 this->mode
= MODE_TRANSPORT
;
519 this->mode
= MODE_BEET
;
521 case IPCOMP_SUPPORTED
:
523 chunk_t data
= notify_payload
->get_notification_data(notify_payload
);
524 u_int16_t cpi
= *(u_int16_t
*)data
.ptr
;
525 ipcomp_transform_t ipcomp
= (ipcomp_transform_t
)(*(data
.ptr
+ 2));
529 this->other_cpi
= cpi
;
530 this->ipcomp_received
= ipcomp
;
535 DBG1(DBG_IKE
, "received IPCOMP_SUPPORTED notify with a transform"
536 " ID we don't support %N", ipcomp_transform_names
, ipcomp
);
548 iterator
->destroy(iterator
);
552 * Implementation of task_t.build for initiator
554 static status_t
build_i(private_child_create_t
*this, message_t
*message
)
556 host_t
*me
, *other
, *vip
;
557 bool propose_all
= FALSE
;
558 peer_cfg_t
*peer_cfg
;
560 switch (message
->get_exchange_type(message
))
563 return get_nonce(message
, &this->my_nonce
);
564 case CREATE_CHILD_SA
:
565 if (generate_nonce(&this->my_nonce
) != SUCCESS
)
567 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
570 if (this->dh_group
== MODP_NONE
)
572 this->dh_group
= this->config
->get_dh_group(this->config
);
576 if (!message
->get_payload(message
, ID_INITIATOR
))
578 /* send only in the first request, not in subsequent EAP */
588 DBG0(DBG_IKE
, "establishing CHILD_SA %s{%d}",
589 this->config
->get_name(this->config
), this->reqid
);
593 DBG0(DBG_IKE
, "establishing CHILD_SA %s",
594 this->config
->get_name(this->config
));
597 /* reuse virtual IP if we already have one */
598 me
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
601 me
= this->ike_sa
->get_my_host(this->ike_sa
);
603 other
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
606 other
= this->ike_sa
->get_other_host(this->ike_sa
);
609 /* check if we want a virtual IP, but don't have one */
612 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
613 vip
= peer_cfg
->get_virtual_ip(peer_cfg
);
621 { /* propose a 0.0.0.0/0 subnet when we use virtual ip */
622 this->tsi
= this->config
->get_traffic_selectors(this->config
, TRUE
,
626 { /* but shorten a 0.0.0.0/0 subnet for host2host/we already have a vip */
627 this->tsi
= this->config
->get_traffic_selectors(this->config
, TRUE
,
630 this->tsr
= this->config
->get_traffic_selectors(this->config
, FALSE
,
633 this->proposals
= this->config
->get_proposals(this->config
,
634 this->dh_group
== MODP_NONE
);
635 this->mode
= this->config
->get_mode(this->config
);
637 this->child_sa
= child_sa_create(this->ike_sa
->get_my_host(this->ike_sa
),
638 this->ike_sa
->get_other_host(this->ike_sa
), this->config
, this->reqid
,
639 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
641 if (this->child_sa
->alloc(this->child_sa
, this->proposals
) != SUCCESS
)
643 DBG1(DBG_IKE
, "unable to allocate SPIs from kernel");
647 if (this->dh_group
!= MODP_NONE
)
649 this->dh
= lib
->crypto
->create_dh(lib
->crypto
, this->dh_group
);
652 if (this->config
->use_ipcomp(this->config
)) {
653 /* IPCOMP_DEFLATE is the only transform we support at the moment */
654 this->ipcomp
= IPCOMP_DEFLATE
;
655 build_ipcomp_supported_notify(this, message
);
658 build_payloads(this, message
);
660 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
661 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
662 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
665 this->proposals
= NULL
;
671 * Implementation of task_t.process for initiator
673 static status_t
process_r(private_child_create_t
*this, message_t
*message
)
675 peer_cfg_t
*peer_cfg
;
677 switch (message
->get_exchange_type(message
))
680 return get_nonce(message
, &this->other_nonce
);
681 case CREATE_CHILD_SA
:
682 get_nonce(message
, &this->other_nonce
);
685 if (message
->get_payload(message
, ID_INITIATOR
) == NULL
)
687 /* wait until extensible authentication completed, if used */
694 process_payloads(this, message
);
696 if (this->tsi
== NULL
|| this->tsr
== NULL
)
698 DBG1(DBG_IKE
, "TS payload missing in message");
702 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
707 me
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
710 me
= this->ike_sa
->get_my_host(this->ike_sa
);
712 other
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
715 other
= this->ike_sa
->get_other_host(this->ike_sa
);
718 this->config
= peer_cfg
->select_child_cfg(peer_cfg
, this->tsr
,
719 this->tsi
, me
, other
);
725 * handle CHILD_SA setup failure
727 static void handle_child_sa_failure(private_child_create_t
*this,
730 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
731 lib
->settings
->get_bool(lib
->settings
,
732 "charon.close_ike_on_child_failure", FALSE
))
734 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
736 DBG1(DBG_IKE
, "closing IKE_SA due CHILD_SA setup failure");
737 charon
->scheduler
->schedule_job(charon
->scheduler
, (job_t
*)
738 delete_ike_sa_job_create(this->ike_sa
->get_id(this->ike_sa
), TRUE
),
744 * Implementation of task_t.build for responder
746 static status_t
build_r(private_child_create_t
*this, message_t
*message
)
749 iterator_t
*iterator
;
752 switch (message
->get_exchange_type(message
))
755 return get_nonce(message
, &this->my_nonce
);
756 case CREATE_CHILD_SA
:
757 if (generate_nonce(&this->my_nonce
) != SUCCESS
)
759 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
,
766 if (message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
))
768 /* wait until extensible authentication completed, if used */
775 if (this->ike_sa
->get_state(this->ike_sa
) == IKE_REKEYING
)
777 DBG1(DBG_IKE
, "unable to create CHILD_SA while rekeying IKE_SA");
778 message
->add_notify(message
, TRUE
, NO_ADDITIONAL_SAS
, chunk_empty
);
782 if (this->config
== NULL
)
784 DBG1(DBG_IKE
, "traffic selectors %#R=== %#R inacceptable",
785 this->tsr
, this->tsi
);
786 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
787 handle_child_sa_failure(this, message
);
791 /* check if ike_config_t included non-critical error notifies */
792 iterator
= message
->get_payload_iterator(message
);
793 while (iterator
->iterate(iterator
, (void**)&payload
))
795 if (payload
->get_type(payload
) == NOTIFY
)
797 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
799 switch (notify
->get_notify_type(notify
))
801 case INTERNAL_ADDRESS_FAILURE
:
802 case FAILED_CP_REQUIRED
:
804 DBG1(DBG_IKE
,"configuration payload negotation "
805 "failed, no CHILD_SA built");
806 iterator
->destroy(iterator
);
807 handle_child_sa_failure(this, message
);
815 iterator
->destroy(iterator
);
817 this->child_sa
= child_sa_create(this->ike_sa
->get_my_host(this->ike_sa
),
818 this->ike_sa
->get_other_host(this->ike_sa
), this->config
, this->reqid
,
819 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
821 if (this->config
->use_ipcomp(this->config
) &&
822 this->ipcomp_received
!= IPCOMP_NONE
)
824 this->ipcomp
= this->ipcomp_received
;
825 build_ipcomp_supported_notify(this, message
);
827 else if (this->ipcomp_received
!= IPCOMP_NONE
)
829 DBG1(DBG_IKE
, "received %N notify but IPComp is disabled, ignoring",
830 notify_type_names
, IPCOMP_SUPPORTED
);
833 switch (select_and_install(this, no_dh
))
838 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
839 handle_child_sa_failure(this, message
);
843 u_int16_t group
= htons(this->dh_group
);
844 message
->add_notify(message
, FALSE
, INVALID_KE_PAYLOAD
,
845 chunk_from_thing(group
));
846 handle_child_sa_failure(this, message
);
851 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
852 handle_child_sa_failure(this, message
);
856 build_payloads(this, message
);
858 DBG0(DBG_IKE
, "CHILD_SA %s{%d} established "
859 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
860 this->child_sa
->get_name(this->child_sa
),
861 this->child_sa
->get_reqid(this->child_sa
),
862 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
863 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
864 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
865 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
871 * Implementation of task_t.process for initiator
873 static status_t
process_i(private_child_create_t
*this, message_t
*message
)
875 iterator_t
*iterator
;
879 switch (message
->get_exchange_type(message
))
882 return get_nonce(message
, &this->other_nonce
);
883 case CREATE_CHILD_SA
:
884 get_nonce(message
, &this->other_nonce
);
888 if (message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
))
890 /* wait until extensible authentication completed, if used */
897 /* check for erronous notifies */
898 iterator
= message
->get_payload_iterator(message
);
899 while (iterator
->iterate(iterator
, (void**)&payload
))
901 if (payload
->get_type(payload
) == NOTIFY
)
903 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
904 notify_type_t type
= notify
->get_notify_type(notify
);
908 /* handle notify errors related to CHILD_SA only */
909 case NO_PROPOSAL_CHOSEN
:
910 case SINGLE_PAIR_REQUIRED
:
911 case NO_ADDITIONAL_SAS
:
912 case INTERNAL_ADDRESS_FAILURE
:
913 case FAILED_CP_REQUIRED
:
914 case TS_UNACCEPTABLE
:
915 case INVALID_SELECTORS
:
917 DBG1(DBG_IKE
, "received %N notify, no CHILD_SA built",
918 notify_type_names
, type
);
919 iterator
->destroy(iterator
);
920 handle_child_sa_failure(this, message
);
921 /* an error in CHILD_SA creation is not critical */
924 case INVALID_KE_PAYLOAD
:
927 diffie_hellman_group_t bad_group
;
929 bad_group
= this->dh_group
;
930 data
= notify
->get_notification_data(notify
);
931 this->dh_group
= ntohs(*((u_int16_t
*)data
.ptr
));
932 DBG1(DBG_IKE
, "peer didn't accept DH group %N, "
933 "it requested %N", diffie_hellman_group_names
,
934 bad_group
, diffie_hellman_group_names
, this->dh_group
);
936 this->public.task
.migrate(&this->public.task
, this->ike_sa
);
937 iterator
->destroy(iterator
);
945 iterator
->destroy(iterator
);
947 process_payloads(this, message
);
949 if (this->ipcomp
== IPCOMP_NONE
&& this->ipcomp_received
!= IPCOMP_NONE
)
951 DBG1(DBG_IKE
, "received an IPCOMP_SUPPORTED notify without requesting"
952 " one, no CHILD_SA built");
953 handle_child_sa_failure(this, message
);
956 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp_received
== IPCOMP_NONE
)
958 DBG1(DBG_IKE
, "peer didn't accept our proposed IPComp transforms, "
959 "IPComp is disabled");
960 this->ipcomp
= IPCOMP_NONE
;
962 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp
!= this->ipcomp_received
)
964 DBG1(DBG_IKE
, "received an IPCOMP_SUPPORTED notify we didn't propose, "
965 "no CHILD_SA built");
966 handle_child_sa_failure(this, message
);
970 if (select_and_install(this, no_dh
) == SUCCESS
)
972 DBG0(DBG_IKE
, "CHILD_SA %s{%d} established "
973 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
974 this->child_sa
->get_name(this->child_sa
),
975 this->child_sa
->get_reqid(this->child_sa
),
976 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
977 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
978 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
979 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
983 handle_child_sa_failure(this, message
);
989 * Implementation of task_t.get_type
991 static task_type_t
get_type(private_child_create_t
*this)
997 * Implementation of child_create_t.use_reqid
999 static void use_reqid(private_child_create_t
*this, u_int32_t reqid
)
1001 this->reqid
= reqid
;
1005 * Implementation of child_create_t.get_child
1007 static child_sa_t
* get_child(private_child_create_t
*this)
1009 return this->child_sa
;
1013 * Implementation of child_create_t.get_lower_nonce
1015 static chunk_t
get_lower_nonce(private_child_create_t
*this)
1017 if (memcmp(this->my_nonce
.ptr
, this->other_nonce
.ptr
,
1018 min(this->my_nonce
.len
, this->other_nonce
.len
)) < 0)
1020 return this->my_nonce
;
1024 return this->other_nonce
;
1029 * Implementation of task_t.migrate
1031 static void migrate(private_child_create_t
*this, ike_sa_t
*ike_sa
)
1033 chunk_free(&this->my_nonce
);
1034 chunk_free(&this->other_nonce
);
1037 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1041 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1043 DESTROY_IF(this->child_sa
);
1044 DESTROY_IF(this->proposal
);
1045 DESTROY_IF(this->dh
);
1046 if (this->proposals
)
1048 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1051 this->ike_sa
= ike_sa
;
1052 this->proposals
= NULL
;
1056 this->child_sa
= NULL
;
1057 this->mode
= MODE_TUNNEL
;
1058 this->ipcomp
= IPCOMP_NONE
;
1059 this->ipcomp_received
= IPCOMP_NONE
;
1060 this->other_cpi
= 0;
1062 this->established
= FALSE
;
1066 * Implementation of task_t.destroy
1068 static void destroy(private_child_create_t
*this)
1070 chunk_free(&this->my_nonce
);
1071 chunk_free(&this->other_nonce
);
1074 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1078 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1080 if (!this->established
)
1082 DESTROY_IF(this->child_sa
);
1084 DESTROY_IF(this->proposal
);
1085 DESTROY_IF(this->dh
);
1086 if (this->proposals
)
1088 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1091 DESTROY_IF(this->config
);
1096 * Described in header.
1098 child_create_t
*child_create_create(ike_sa_t
*ike_sa
, child_cfg_t
*config
)
1100 private_child_create_t
*this = malloc_thing(private_child_create_t
);
1102 this->public.get_child
= (child_sa_t
*(*)(child_create_t
*))get_child
;
1103 this->public.get_lower_nonce
= (chunk_t(*)(child_create_t
*))get_lower_nonce
;
1104 this->public.use_reqid
= (void(*)(child_create_t
*,u_int32_t
))use_reqid
;
1105 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
1106 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
1107 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
1110 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
1111 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
1112 this->initiator
= TRUE
;
1113 config
->get_ref(config
);
1117 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
1118 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
1119 this->initiator
= FALSE
;
1122 this->ike_sa
= ike_sa
;
1123 this->config
= config
;
1124 this->my_nonce
= chunk_empty
;
1125 this->other_nonce
= chunk_empty
;
1126 this->proposals
= NULL
;
1127 this->proposal
= NULL
;
1131 this->dh_group
= MODP_NONE
;
1132 this->child_sa
= NULL
;
1133 this->mode
= MODE_TUNNEL
;
1134 this->ipcomp
= IPCOMP_NONE
;
1135 this->ipcomp_received
= IPCOMP_NONE
;
1136 this->other_cpi
= 0;
1138 this->established
= FALSE
;
1140 return &this->public;