2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 typedef struct private_ha_child_t private_ha_child_t
;
21 * Private data of an ha_child_t object.
23 struct private_ha_child_t
{
26 * Public ha_child_t interface.
31 * socket we use for syncing
36 * tunnel securing sync messages
43 ha_segments_t
*segments
;
51 METHOD(listener_t
, child_keys
, bool,
52 private_ha_child_t
*this, ike_sa_t
*ike_sa
, child_sa_t
*child_sa
,
53 bool initiator
, diffie_hellman_t
*dh
, chunk_t nonce_i
, chunk_t nonce_r
)
59 linked_list_t
*local_ts
, *remote_ts
;
60 enumerator_t
*enumerator
;
61 traffic_selector_t
*ts
;
64 if (this->tunnel
&& this->tunnel
->is_sa(this->tunnel
, ike_sa
))
65 { /* do not sync SA between nodes */
69 m
= ha_message_create(HA_CHILD_ADD
);
71 m
->add_attribute(m
, HA_IKE_ID
, ike_sa
->get_id(ike_sa
));
72 m
->add_attribute(m
, HA_INITIATOR
, (u_int8_t
)initiator
);
73 m
->add_attribute(m
, HA_INBOUND_SPI
, child_sa
->get_spi(child_sa
, TRUE
));
74 m
->add_attribute(m
, HA_OUTBOUND_SPI
, child_sa
->get_spi(child_sa
, FALSE
));
75 m
->add_attribute(m
, HA_INBOUND_CPI
, child_sa
->get_cpi(child_sa
, TRUE
));
76 m
->add_attribute(m
, HA_OUTBOUND_CPI
, child_sa
->get_cpi(child_sa
, FALSE
));
77 m
->add_attribute(m
, HA_IPSEC_MODE
, child_sa
->get_mode(child_sa
));
78 m
->add_attribute(m
, HA_IPCOMP
, child_sa
->get_ipcomp(child_sa
));
79 m
->add_attribute(m
, HA_CONFIG_NAME
, child_sa
->get_name(child_sa
));
81 proposal
= child_sa
->get_proposal(child_sa
);
82 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
, &alg
, &len
))
84 m
->add_attribute(m
, HA_ALG_ENCR
, alg
);
87 m
->add_attribute(m
, HA_ALG_ENCR_LEN
, len
);
90 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
, &alg
, NULL
))
92 m
->add_attribute(m
, HA_ALG_INTEG
, alg
);
94 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, &alg
, NULL
))
96 m
->add_attribute(m
, HA_ALG_DH
, alg
);
98 if (proposal
->get_algorithm(proposal
, EXTENDED_SEQUENCE_NUMBERS
, &alg
, NULL
))
100 m
->add_attribute(m
, HA_ESN
, alg
);
102 m
->add_attribute(m
, HA_NONCE_I
, nonce_i
);
103 m
->add_attribute(m
, HA_NONCE_R
, nonce_r
);
104 if (dh
&& dh
->get_shared_secret(dh
, &secret
))
106 m
->add_attribute(m
, HA_SECRET
, secret
);
107 chunk_clear(&secret
);
110 local_ts
= linked_list_create();
111 remote_ts
= linked_list_create();
113 enumerator
= child_sa
->create_ts_enumerator(child_sa
, TRUE
);
114 while (enumerator
->enumerate(enumerator
, &ts
))
116 m
->add_attribute(m
, HA_LOCAL_TS
, ts
);
117 local_ts
->insert_last(local_ts
, ts
);
119 enumerator
->destroy(enumerator
);
121 enumerator
= child_sa
->create_ts_enumerator(child_sa
, FALSE
);
122 while (enumerator
->enumerate(enumerator
, &ts
))
124 m
->add_attribute(m
, HA_REMOTE_TS
, ts
);
125 remote_ts
->insert_last(remote_ts
, ts
);
127 enumerator
->destroy(enumerator
);
129 seg_i
= this->kernel
->get_segment_spi(this->kernel
,
130 ike_sa
->get_my_host(ike_sa
), child_sa
->get_spi(child_sa
, TRUE
));
131 seg_o
= this->kernel
->get_segment_spi(this->kernel
,
132 ike_sa
->get_other_host(ike_sa
), child_sa
->get_spi(child_sa
, FALSE
));
133 DBG1(DBG_CFG
, "handling HA CHILD_SA %s{%d} %#R === %#R "
134 "(segment in: %d%s, out: %d%s)", child_sa
->get_name(child_sa
),
135 child_sa
->get_unique_id(child_sa
), local_ts
, remote_ts
,
136 seg_i
, this->segments
->is_active(this->segments
, seg_i
) ?
"*" : "",
137 seg_o
, this->segments
->is_active(this->segments
, seg_o
) ?
"*" : "");
139 local_ts
->destroy(local_ts
);
140 remote_ts
->destroy(remote_ts
);
142 this->socket
->push(this->socket
, m
);
148 METHOD(listener_t
, child_state_change
, bool,
149 private_ha_child_t
*this, ike_sa_t
*ike_sa
,
150 child_sa_t
*child_sa
, child_sa_state_t state
)
153 ike_sa
->get_state(ike_sa
) == IKE_PASSIVE
||
154 ike_sa
->get_state(ike_sa
) == IKE_DESTROYING
)
155 { /* only sync active IKE_SAs */
158 if (this->tunnel
&& this->tunnel
->is_sa(this->tunnel
, ike_sa
))
159 { /* do not sync SA between nodes */
164 if (state
== CHILD_DESTROYING
)
168 m
= ha_message_create(HA_CHILD_DELETE
);
170 m
->add_attribute(m
, HA_IKE_ID
, ike_sa
->get_id(ike_sa
));
171 m
->add_attribute(m
, HA_INBOUND_SPI
,
172 child_sa
->get_spi(child_sa
, TRUE
));
173 this->socket
->push(this->socket
, m
);
179 METHOD(ha_child_t
, destroy
, void,
180 private_ha_child_t
*this)
188 ha_child_t
*ha_child_create(ha_socket_t
*socket
, ha_tunnel_t
*tunnel
,
189 ha_segments_t
*segments
, ha_kernel_t
*kernel
)
191 private_ha_child_t
*this;
196 .child_keys
= _child_keys
,
197 .child_state_change
= _child_state_change
,
203 .segments
= segments
,
207 return &this->public;