2 * Copyright (C) 2008 Martin Willi
4 * Copyright (C) secunet Security Networks AG
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 typedef struct private_ha_child_t private_ha_child_t
;
22 * Private data of an ha_child_t object.
24 struct private_ha_child_t
{
27 * Public ha_child_t interface.
32 * socket we use for syncing
37 * tunnel securing sync messages
44 ha_segments_t
*segments
;
52 METHOD(listener_t
, child_keys
, bool,
53 private_ha_child_t
*this, ike_sa_t
*ike_sa
, child_sa_t
*child_sa
,
54 bool initiator
, diffie_hellman_t
*dh
, chunk_t nonce_i
, chunk_t nonce_r
)
60 linked_list_t
*local_ts
, *remote_ts
;
61 enumerator_t
*enumerator
;
62 traffic_selector_t
*ts
;
65 if (this->tunnel
&& this->tunnel
->is_sa(this->tunnel
, ike_sa
))
66 { /* do not sync SA between nodes */
70 m
= ha_message_create(HA_CHILD_ADD
);
72 m
->add_attribute(m
, HA_IKE_ID
, ike_sa
->get_id(ike_sa
));
73 m
->add_attribute(m
, HA_INITIATOR
, (uint8_t)initiator
);
74 m
->add_attribute(m
, HA_INBOUND_SPI
, child_sa
->get_spi(child_sa
, TRUE
));
75 m
->add_attribute(m
, HA_OUTBOUND_SPI
, child_sa
->get_spi(child_sa
, FALSE
));
76 m
->add_attribute(m
, HA_INBOUND_CPI
, child_sa
->get_cpi(child_sa
, TRUE
));
77 m
->add_attribute(m
, HA_OUTBOUND_CPI
, child_sa
->get_cpi(child_sa
, FALSE
));
78 m
->add_attribute(m
, HA_IPSEC_MODE
, child_sa
->get_mode(child_sa
));
79 m
->add_attribute(m
, HA_IPCOMP
, child_sa
->get_ipcomp(child_sa
));
80 m
->add_attribute(m
, HA_CONFIG_NAME
, child_sa
->get_name(child_sa
));
82 proposal
= child_sa
->get_proposal(child_sa
);
83 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
, &alg
, &len
))
85 m
->add_attribute(m
, HA_ALG_ENCR
, alg
);
88 m
->add_attribute(m
, HA_ALG_ENCR_LEN
, len
);
91 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
, &alg
, NULL
))
93 m
->add_attribute(m
, HA_ALG_INTEG
, alg
);
95 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, &alg
, NULL
))
97 m
->add_attribute(m
, HA_ALG_DH
, alg
);
99 if (proposal
->get_algorithm(proposal
, EXTENDED_SEQUENCE_NUMBERS
, &alg
, NULL
))
101 m
->add_attribute(m
, HA_ESN
, alg
);
103 m
->add_attribute(m
, HA_NONCE_I
, nonce_i
);
104 m
->add_attribute(m
, HA_NONCE_R
, nonce_r
);
105 if (dh
&& dh
->get_shared_secret(dh
, &secret
))
107 m
->add_attribute(m
, HA_SECRET
, secret
);
108 chunk_clear(&secret
);
111 local_ts
= linked_list_create();
112 remote_ts
= linked_list_create();
114 enumerator
= child_sa
->create_ts_enumerator(child_sa
, TRUE
);
115 while (enumerator
->enumerate(enumerator
, &ts
))
117 m
->add_attribute(m
, HA_LOCAL_TS
, ts
);
118 local_ts
->insert_last(local_ts
, ts
);
120 enumerator
->destroy(enumerator
);
122 enumerator
= child_sa
->create_ts_enumerator(child_sa
, FALSE
);
123 while (enumerator
->enumerate(enumerator
, &ts
))
125 m
->add_attribute(m
, HA_REMOTE_TS
, ts
);
126 remote_ts
->insert_last(remote_ts
, ts
);
128 enumerator
->destroy(enumerator
);
130 seg_i
= this->kernel
->get_segment_spi(this->kernel
,
131 ike_sa
->get_my_host(ike_sa
), child_sa
->get_spi(child_sa
, TRUE
));
132 seg_o
= this->kernel
->get_segment_spi(this->kernel
,
133 ike_sa
->get_other_host(ike_sa
), child_sa
->get_spi(child_sa
, FALSE
));
134 DBG1(DBG_CFG
, "handling HA CHILD_SA %s{%d} %#R === %#R "
135 "(segment in: %d%s, out: %d%s)", child_sa
->get_name(child_sa
),
136 child_sa
->get_unique_id(child_sa
), local_ts
, remote_ts
,
137 seg_i
, this->segments
->is_active(this->segments
, seg_i
) ? "*" : "",
138 seg_o
, this->segments
->is_active(this->segments
, seg_o
) ? "*" : "");
140 local_ts
->destroy(local_ts
);
141 remote_ts
->destroy(remote_ts
);
143 this->socket
->push(this->socket
, m
);
149 METHOD(listener_t
, child_state_change
, bool,
150 private_ha_child_t
*this, ike_sa_t
*ike_sa
,
151 child_sa_t
*child_sa
, child_sa_state_t state
)
154 ike_sa
->get_state(ike_sa
) == IKE_PASSIVE
||
155 ike_sa
->get_state(ike_sa
) == IKE_DESTROYING
)
156 { /* only sync active IKE_SAs */
159 if (this->tunnel
&& this->tunnel
->is_sa(this->tunnel
, ike_sa
))
160 { /* do not sync SA between nodes */
165 if (state
== CHILD_DESTROYING
)
169 m
= ha_message_create(HA_CHILD_DELETE
);
171 m
->add_attribute(m
, HA_IKE_ID
, ike_sa
->get_id(ike_sa
));
172 m
->add_attribute(m
, HA_INBOUND_SPI
,
173 child_sa
->get_spi(child_sa
, TRUE
));
174 this->socket
->push(this->socket
, m
);
180 METHOD(ha_child_t
, destroy
, void,
181 private_ha_child_t
*this)
189 ha_child_t
*ha_child_create(ha_socket_t
*socket
, ha_tunnel_t
*tunnel
,
190 ha_segments_t
*segments
, ha_kernel_t
*kernel
)
192 private_ha_child_t
*this;
197 .child_keys
= _child_keys
,
198 .child_state_change
= _child_state_change
,
204 .segments
= segments
,
208 return &this->public;