]>
Commit | Line | Data |
---|---|---|
190edaf5 MW |
1 | /* |
2 | * Copyright (C) 2008 Martin Willi | |
1b671669 | 3 | * HSR Hochschule fuer Technik Rapperswil |
190edaf5 MW |
4 | * |
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>. | |
9 | * | |
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 | |
13 | * for more details. | |
190edaf5 MW |
14 | */ |
15 | ||
d8748966 | 16 | #include "ha_dispatcher.h" |
190edaf5 MW |
17 | |
18 | #include <daemon.h> | |
6bc6f67b | 19 | #include <sa/ikev2/keymat_v2.h> |
8bcd9bd1 | 20 | #include <sa/ikev1/keymat_v1.h> |
190edaf5 | 21 | #include <processing/jobs/callback_job.h> |
aa3b53e7 | 22 | #include <processing/jobs/adopt_children_job.h> |
190edaf5 | 23 | |
d8748966 | 24 | typedef struct private_ha_dispatcher_t private_ha_dispatcher_t; |
26451482 | 25 | typedef struct ha_diffie_hellman_t ha_diffie_hellman_t; |
190edaf5 MW |
26 | |
27 | /** | |
d8748966 | 28 | * Private data of an ha_dispatcher_t object. |
190edaf5 | 29 | */ |
d8748966 | 30 | struct private_ha_dispatcher_t { |
190edaf5 MW |
31 | |
32 | /** | |
d8748966 | 33 | * Public ha_dispatcher_t interface. |
190edaf5 | 34 | */ |
d8748966 | 35 | ha_dispatcher_t public; |
190edaf5 MW |
36 | |
37 | /** | |
38 | * socket to pull messages from | |
39 | */ | |
d8748966 | 40 | ha_socket_t *socket; |
190edaf5 | 41 | |
37459ea9 MW |
42 | /** |
43 | * segments to control | |
44 | */ | |
d8748966 | 45 | ha_segments_t *segments; |
37459ea9 | 46 | |
aa334daa MW |
47 | /** |
48 | * Cache for resync | |
49 | */ | |
50 | ha_cache_t *cache; | |
51 | ||
08e266a1 MW |
52 | /** |
53 | * Kernel helper | |
54 | */ | |
55 | ha_kernel_t *kernel; | |
56 | ||
98d03438 MW |
57 | /** |
58 | * HA enabled pool | |
59 | */ | |
60 | ha_attribute_t *attr; | |
190edaf5 MW |
61 | }; |
62 | ||
765935c8 | 63 | /** |
26451482 | 64 | * DH implementation for HA synced DH values |
765935c8 | 65 | */ |
26451482 MW |
66 | struct ha_diffie_hellman_t { |
67 | ||
68 | /** | |
69 | * Implements diffie_hellman_t | |
70 | */ | |
71 | diffie_hellman_t dh; | |
72 | ||
73 | /** | |
74 | * Shared secret | |
75 | */ | |
76 | chunk_t secret; | |
8bcd9bd1 MW |
77 | |
78 | /** | |
79 | * Own public value | |
80 | */ | |
81 | chunk_t pub; | |
26451482 MW |
82 | }; |
83 | ||
bace1d64 | 84 | METHOD(diffie_hellman_t, dh_get_shared_secret, bool, |
26451482 | 85 | ha_diffie_hellman_t *this, chunk_t *secret) |
765935c8 | 86 | { |
26451482 | 87 | *secret = chunk_clone(this->secret); |
bace1d64 | 88 | return TRUE; |
765935c8 MW |
89 | } |
90 | ||
42431690 | 91 | METHOD(diffie_hellman_t, dh_get_my_public_value, bool, |
8bcd9bd1 MW |
92 | ha_diffie_hellman_t *this, chunk_t *value) |
93 | { | |
94 | *value = chunk_clone(this->pub); | |
42431690 | 95 | return TRUE; |
8bcd9bd1 MW |
96 | } |
97 | ||
26451482 MW |
98 | METHOD(diffie_hellman_t, dh_destroy, void, |
99 | ha_diffie_hellman_t *this) | |
100 | { | |
101 | free(this); | |
102 | } | |
103 | ||
104 | /** | |
105 | * Create a HA synced DH implementation | |
106 | */ | |
8bcd9bd1 | 107 | static diffie_hellman_t *ha_diffie_hellman_create(chunk_t secret, chunk_t pub) |
26451482 MW |
108 | { |
109 | ha_diffie_hellman_t *this; | |
110 | ||
111 | INIT(this, | |
112 | .dh = { | |
113 | .get_shared_secret = _dh_get_shared_secret, | |
8bcd9bd1 | 114 | .get_my_public_value = _dh_get_my_public_value, |
26451482 MW |
115 | .destroy = _dh_destroy, |
116 | }, | |
117 | .secret = secret, | |
8bcd9bd1 | 118 | .pub = pub, |
26451482 MW |
119 | ); |
120 | ||
121 | return &this->dh; | |
122 | } | |
123 | ||
190edaf5 MW |
124 | /** |
125 | * Process messages of type IKE_ADD | |
126 | */ | |
d8748966 | 127 | static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message) |
190edaf5 | 128 | { |
d8748966 MW |
129 | ha_message_attribute_t attribute; |
130 | ha_message_value_t value; | |
190edaf5 | 131 | enumerator_t *enumerator; |
d4113a42 | 132 | ike_sa_t *ike_sa = NULL, *old_sa = NULL; |
8bcd9bd1 | 133 | ike_version_t version = IKEV2; |
b12c53ce AS |
134 | uint16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED; |
135 | uint16_t dh_grp = 0; | |
d4113a42 MW |
136 | chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty; |
137 | chunk_t secret = chunk_empty, old_skd = chunk_empty; | |
8bcd9bd1 | 138 | chunk_t dh_local = chunk_empty, dh_remote = chunk_empty, psk = chunk_empty; |
34347094 | 139 | host_t *other = NULL; |
6bc6f67b | 140 | bool ok = FALSE; |
eed20c21 | 141 | auth_method_t method = AUTH_RSA; |
190edaf5 MW |
142 | |
143 | enumerator = message->create_attribute_enumerator(message); | |
144 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
145 | { | |
146 | switch (attribute) | |
147 | { | |
d8748966 | 148 | case HA_IKE_ID: |
17ec1c74 | 149 | ike_sa = ike_sa_create(value.ike_sa_id, |
8bcd9bd1 | 150 | value.ike_sa_id->is_initiator(value.ike_sa_id), version); |
765935c8 | 151 | break; |
d8748966 | 152 | case HA_IKE_REKEY_ID: |
34d240a6 MW |
153 | old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, |
154 | value.ike_sa_id); | |
765935c8 | 155 | break; |
34347094 TE |
156 | case HA_REMOTE_ADDR: |
157 | other = value.host->clone(value.host); | |
158 | break; | |
8bcd9bd1 MW |
159 | case HA_IKE_VERSION: |
160 | version = value.u8; | |
161 | break; | |
d8748966 | 162 | case HA_NONCE_I: |
765935c8 MW |
163 | nonce_i = value.chunk; |
164 | break; | |
d8748966 | 165 | case HA_NONCE_R: |
765935c8 MW |
166 | nonce_r = value.chunk; |
167 | break; | |
d8748966 | 168 | case HA_SECRET: |
765935c8 MW |
169 | secret = value.chunk; |
170 | break; | |
8bcd9bd1 MW |
171 | case HA_LOCAL_DH: |
172 | dh_local = value.chunk; | |
173 | break; | |
174 | case HA_REMOTE_DH: | |
175 | dh_remote = value.chunk; | |
176 | break; | |
177 | case HA_PSK: | |
178 | psk = value.chunk; | |
179 | break; | |
d8748966 | 180 | case HA_OLD_SKD: |
d4113a42 MW |
181 | old_skd = value.chunk; |
182 | break; | |
d8748966 | 183 | case HA_ALG_ENCR: |
765935c8 MW |
184 | encr = value.u16; |
185 | break; | |
d8748966 | 186 | case HA_ALG_ENCR_LEN: |
765935c8 MW |
187 | len = value.u16; |
188 | break; | |
d8748966 | 189 | case HA_ALG_INTEG: |
765935c8 MW |
190 | integ = value.u16; |
191 | break; | |
d8748966 | 192 | case HA_ALG_PRF: |
765935c8 MW |
193 | prf = value.u16; |
194 | break; | |
d8748966 | 195 | case HA_ALG_OLD_PRF: |
d4113a42 MW |
196 | old_prf = value.u16; |
197 | break; | |
f1e90883 TB |
198 | case HA_ALG_DH: |
199 | dh_grp = value.u16; | |
200 | break; | |
eed20c21 TE |
201 | case HA_AUTH_METHOD: |
202 | method = value.u16; | |
765935c8 MW |
203 | default: |
204 | break; | |
205 | } | |
206 | } | |
207 | enumerator->destroy(enumerator); | |
208 | ||
765935c8 MW |
209 | if (ike_sa) |
210 | { | |
211 | proposal_t *proposal; | |
26451482 | 212 | diffie_hellman_t *dh; |
765935c8 | 213 | |
bb162175 | 214 | proposal = proposal_create(PROTO_IKE, 0); |
765935c8 MW |
215 | if (integ) |
216 | { | |
217 | proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0); | |
218 | } | |
219 | if (encr) | |
220 | { | |
221 | proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len); | |
222 | } | |
223 | if (prf) | |
224 | { | |
225 | proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0); | |
226 | } | |
f1e90883 TB |
227 | if (dh_grp) |
228 | { | |
229 | proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, dh_grp, 0); | |
230 | } | |
c94fe198 | 231 | charon->bus->set_sa(charon->bus, ike_sa); |
8bcd9bd1 | 232 | dh = ha_diffie_hellman_create(secret, dh_local); |
6bc6f67b MW |
233 | if (ike_sa->get_version(ike_sa) == IKEV2) |
234 | { | |
235 | keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa); | |
236 | ||
26451482 | 237 | ok = keymat_v2->derive_ike_keys(keymat_v2, proposal, dh, nonce_i, |
6bc6f67b MW |
238 | nonce_r, ike_sa->get_id(ike_sa), old_prf, old_skd); |
239 | } | |
8bcd9bd1 MW |
240 | if (ike_sa->get_version(ike_sa) == IKEV1) |
241 | { | |
242 | keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); | |
243 | shared_key_t *shared = NULL; | |
8bcd9bd1 MW |
244 | |
245 | if (psk.len) | |
246 | { | |
247 | method = AUTH_PSK; | |
248 | shared = shared_key_create(SHARED_IKE, chunk_clone(psk)); | |
249 | } | |
ae926418 MW |
250 | if (keymat_v1->create_hasher(keymat_v1, proposal)) |
251 | { | |
252 | ok = keymat_v1->derive_ike_keys(keymat_v1, proposal, | |
253 | dh, dh_remote, nonce_i, nonce_r, | |
254 | ike_sa->get_id(ike_sa), method, shared); | |
255 | } | |
8bcd9bd1 MW |
256 | DESTROY_IF(shared); |
257 | } | |
26451482 | 258 | dh->destroy(dh); |
6bc6f67b | 259 | if (ok) |
34d240a6 MW |
260 | { |
261 | if (old_sa) | |
262 | { | |
713a1122 MW |
263 | ike_sa->inherit_pre(ike_sa, old_sa); |
264 | ike_sa->inherit_post(ike_sa, old_sa); | |
34d240a6 MW |
265 | charon->ike_sa_manager->checkin_and_destroy( |
266 | charon->ike_sa_manager, old_sa); | |
267 | old_sa = NULL; | |
268 | } | |
34347094 TE |
269 | if (other) |
270 | { | |
271 | ike_sa->set_other_host(ike_sa, other); | |
272 | other = NULL; | |
273 | } | |
34d240a6 | 274 | ike_sa->set_state(ike_sa, IKE_CONNECTING); |
c3f1839a | 275 | ike_sa->set_proposal(ike_sa, proposal); |
aa334daa MW |
276 | this->cache->cache(this->cache, ike_sa, message); |
277 | message = NULL; | |
34d240a6 MW |
278 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
279 | } | |
280 | else | |
765935c8 | 281 | { |
d8748966 | 282 | DBG1(DBG_IKE, "HA keymat derivation failed"); |
34d240a6 | 283 | ike_sa->destroy(ike_sa); |
765935c8 | 284 | } |
c94fe198 | 285 | charon->bus->set_sa(charon->bus, NULL); |
765935c8 | 286 | proposal->destroy(proposal); |
34d240a6 MW |
287 | } |
288 | if (old_sa) | |
289 | { | |
290 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, old_sa); | |
765935c8 | 291 | } |
34347094 | 292 | DESTROY_IF(other); |
aa334daa | 293 | DESTROY_IF(message); |
765935c8 MW |
294 | } |
295 | ||
296 | /** | |
297 | * Apply a condition flag to the IKE_SA if it is in set | |
298 | */ | |
299 | static void set_condition(ike_sa_t *ike_sa, ike_condition_t set, | |
300 | ike_condition_t flag) | |
301 | { | |
302 | ike_sa->set_condition(ike_sa, flag, flag & set); | |
303 | } | |
304 | ||
305 | /** | |
306 | * Apply a extension flag to the IKE_SA if it is in set | |
307 | */ | |
308 | static void set_extension(ike_sa_t *ike_sa, ike_extension_t set, | |
309 | ike_extension_t flag) | |
310 | { | |
311 | if (flag & set) | |
312 | { | |
313 | ike_sa->enable_extension(ike_sa, flag); | |
314 | } | |
315 | } | |
316 | ||
317 | /** | |
318 | * Process messages of type IKE_UPDATE | |
319 | */ | |
d8748966 MW |
320 | static void process_ike_update(private_ha_dispatcher_t *this, |
321 | ha_message_t *message) | |
765935c8 | 322 | { |
d8748966 MW |
323 | ha_message_attribute_t attribute; |
324 | ha_message_value_t value; | |
765935c8 MW |
325 | enumerator_t *enumerator; |
326 | ike_sa_t *ike_sa = NULL; | |
327 | peer_cfg_t *peer_cfg = NULL; | |
fa4f71c8 | 328 | auth_cfg_t *auth; |
d2e8f20d | 329 | bool received_vip = FALSE, first_local_vip = TRUE, first_peer_addr = TRUE; |
765935c8 MW |
330 | |
331 | enumerator = message->create_attribute_enumerator(message); | |
332 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
333 | { | |
d8748966 | 334 | if (attribute != HA_IKE_ID && ike_sa == NULL) |
765935c8 | 335 | { |
34d240a6 | 336 | /* must be first attribute */ |
765935c8 MW |
337 | break; |
338 | } | |
339 | switch (attribute) | |
340 | { | |
d8748966 | 341 | case HA_IKE_ID: |
34d240a6 MW |
342 | ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, |
343 | value.ike_sa_id); | |
190edaf5 | 344 | break; |
d8748966 | 345 | case HA_LOCAL_ID: |
765935c8 MW |
346 | ike_sa->set_my_id(ike_sa, value.id->clone(value.id)); |
347 | break; | |
d8748966 | 348 | case HA_REMOTE_ID: |
765935c8 MW |
349 | ike_sa->set_other_id(ike_sa, value.id->clone(value.id)); |
350 | break; | |
fa4f71c8 MW |
351 | case HA_REMOTE_EAP_ID: |
352 | auth = auth_cfg_create(); | |
353 | auth->add(auth, AUTH_RULE_EAP_IDENTITY, value.id->clone(value.id)); | |
354 | ike_sa->add_auth_cfg(ike_sa, FALSE, auth); | |
355 | break; | |
d8748966 | 356 | case HA_LOCAL_ADDR: |
765935c8 MW |
357 | ike_sa->set_my_host(ike_sa, value.host->clone(value.host)); |
358 | break; | |
d8748966 | 359 | case HA_REMOTE_ADDR: |
765935c8 MW |
360 | ike_sa->set_other_host(ike_sa, value.host->clone(value.host)); |
361 | break; | |
d8748966 | 362 | case HA_LOCAL_VIP: |
d2e8f20d TB |
363 | if (first_local_vip) |
364 | { | |
365 | ike_sa->clear_virtual_ips(ike_sa, TRUE); | |
366 | first_local_vip = FALSE; | |
367 | } | |
101d26ba | 368 | ike_sa->add_virtual_ip(ike_sa, TRUE, value.host); |
80624c79 | 369 | break; |
d8748966 | 370 | case HA_REMOTE_VIP: |
d2e8f20d TB |
371 | if (!received_vip) |
372 | { | |
373 | ike_sa->clear_virtual_ips(ike_sa, FALSE); | |
374 | } | |
101d26ba | 375 | ike_sa->add_virtual_ip(ike_sa, FALSE, value.host); |
98d03438 | 376 | received_vip = TRUE; |
765935c8 | 377 | break; |
94bbc602 | 378 | case HA_PEER_ADDR: |
cd6b5bf8 TB |
379 | if (first_peer_addr) |
380 | { | |
381 | ike_sa->clear_peer_addresses(ike_sa); | |
382 | first_peer_addr = FALSE; | |
383 | } | |
94bbc602 | 384 | ike_sa->add_peer_address(ike_sa, value.host->clone(value.host)); |
190edaf5 | 385 | break; |
d8748966 | 386 | case HA_CONFIG_NAME: |
765935c8 MW |
387 | peer_cfg = charon->backends->get_peer_cfg_by_name( |
388 | charon->backends, value.str); | |
34d240a6 MW |
389 | if (peer_cfg) |
390 | { | |
391 | ike_sa->set_peer_cfg(ike_sa, peer_cfg); | |
392 | peer_cfg->destroy(peer_cfg); | |
393 | } | |
394 | else | |
395 | { | |
d8748966 | 396 | DBG1(DBG_IKE, "HA is missing nodes peer configuration"); |
438318c6 MW |
397 | charon->ike_sa_manager->checkin_and_destroy( |
398 | charon->ike_sa_manager, ike_sa); | |
399 | ike_sa = NULL; | |
34d240a6 | 400 | } |
190edaf5 | 401 | break; |
d8748966 | 402 | case HA_EXTENSIONS: |
26d08a24 MW |
403 | set_extension(ike_sa, value.u32, EXT_NATT); |
404 | set_extension(ike_sa, value.u32, EXT_MOBIKE); | |
405 | set_extension(ike_sa, value.u32, EXT_HASH_AND_URL); | |
f54bcf35 MW |
406 | set_extension(ike_sa, value.u32, EXT_MULTIPLE_AUTH); |
407 | set_extension(ike_sa, value.u32, EXT_STRONGSWAN); | |
408 | set_extension(ike_sa, value.u32, EXT_EAP_ONLY_AUTHENTICATION); | |
409 | set_extension(ike_sa, value.u32, EXT_MS_WINDOWS); | |
868d92a4 MW |
410 | set_extension(ike_sa, value.u32, EXT_XAUTH); |
411 | set_extension(ike_sa, value.u32, EXT_DPD); | |
26d08a24 | 412 | break; |
d8748966 | 413 | case HA_CONDITIONS: |
26d08a24 MW |
414 | set_condition(ike_sa, value.u32, COND_NAT_ANY); |
415 | set_condition(ike_sa, value.u32, COND_NAT_HERE); | |
416 | set_condition(ike_sa, value.u32, COND_NAT_THERE); | |
417 | set_condition(ike_sa, value.u32, COND_NAT_FAKE); | |
418 | set_condition(ike_sa, value.u32, COND_EAP_AUTHENTICATED); | |
419 | set_condition(ike_sa, value.u32, COND_CERTREQ_SEEN); | |
420 | set_condition(ike_sa, value.u32, COND_ORIGINAL_INITIATOR); | |
f54bcf35 | 421 | set_condition(ike_sa, value.u32, COND_STALE); |
868d92a4 MW |
422 | set_condition(ike_sa, value.u32, COND_INIT_CONTACT_SEEN); |
423 | set_condition(ike_sa, value.u32, COND_XAUTH_AUTHENTICATED); | |
190edaf5 | 424 | break; |
765935c8 MW |
425 | default: |
426 | break; | |
427 | } | |
428 | } | |
429 | enumerator->destroy(enumerator); | |
430 | ||
34d240a6 | 431 | if (ike_sa) |
765935c8 | 432 | { |
34d240a6 MW |
433 | if (ike_sa->get_state(ike_sa) == IKE_CONNECTING && |
434 | ike_sa->get_peer_cfg(ike_sa)) | |
435 | { | |
aa334daa MW |
436 | DBG1(DBG_CFG, "installed HA passive IKE_SA '%s' %H[%Y]...%H[%Y]", |
437 | ike_sa->get_name(ike_sa), | |
438 | ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa), | |
439 | ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa)); | |
34d240a6 MW |
440 | ike_sa->set_state(ike_sa, IKE_PASSIVE); |
441 | } | |
98d03438 MW |
442 | if (received_vip) |
443 | { | |
497ce2cf | 444 | enumerator_t *pools, *vips; |
98d03438 MW |
445 | host_t *vip; |
446 | char *pool; | |
447 | ||
448 | peer_cfg = ike_sa->get_peer_cfg(ike_sa); | |
101d26ba | 449 | if (peer_cfg) |
98d03438 | 450 | { |
497ce2cf MW |
451 | pools = peer_cfg->create_pool_enumerator(peer_cfg); |
452 | while (pools->enumerate(pools, &pool)) | |
98d03438 | 453 | { |
497ce2cf MW |
454 | vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE); |
455 | while (vips->enumerate(vips, &vip)) | |
101d26ba MW |
456 | { |
457 | this->attr->reserve(this->attr, pool, vip); | |
458 | } | |
497ce2cf | 459 | vips->destroy(vips); |
98d03438 | 460 | } |
497ce2cf | 461 | pools->destroy(pools); |
98d03438 MW |
462 | } |
463 | } | |
e1c7e1bc | 464 | #ifdef USE_IKEV1 |
aa3b53e7 MW |
465 | if (ike_sa->get_version(ike_sa) == IKEV1) |
466 | { | |
467 | lib->processor->queue_job(lib->processor, (job_t*) | |
468 | adopt_children_job_create(ike_sa->get_id(ike_sa))); | |
469 | } | |
e1c7e1bc | 470 | #endif /* USE_IKEV1 */ |
aa334daa | 471 | this->cache->cache(this->cache, ike_sa, message); |
34d240a6 | 472 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
765935c8 | 473 | } |
aa334daa MW |
474 | else |
475 | { | |
476 | DBG1(DBG_CFG, "passive HA IKE_SA to update not found"); | |
477 | message->destroy(message); | |
478 | } | |
765935c8 MW |
479 | } |
480 | ||
ad2488fc MW |
481 | /** |
482 | * Process messages of type IKE_MID_INITIATOR/RESPONDER | |
483 | */ | |
484 | static void process_ike_mid(private_ha_dispatcher_t *this, | |
485 | ha_message_t *message, bool initiator) | |
486 | { | |
487 | ha_message_attribute_t attribute; | |
488 | ha_message_value_t value; | |
489 | enumerator_t *enumerator; | |
490 | ike_sa_t *ike_sa = NULL; | |
b12c53ce | 491 | uint32_t mid = 0; |
ad2488fc MW |
492 | |
493 | enumerator = message->create_attribute_enumerator(message); | |
494 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
495 | { | |
496 | switch (attribute) | |
497 | { | |
498 | case HA_IKE_ID: | |
499 | ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, | |
500 | value.ike_sa_id); | |
501 | break; | |
502 | case HA_MID: | |
503 | mid = value.u32; | |
504 | break; | |
505 | default: | |
506 | break; | |
507 | } | |
508 | } | |
509 | enumerator->destroy(enumerator); | |
510 | ||
511 | if (ike_sa) | |
512 | { | |
513 | if (mid) | |
514 | { | |
515 | ike_sa->set_message_id(ike_sa, initiator, mid); | |
516 | } | |
aa334daa | 517 | this->cache->cache(this->cache, ike_sa, message); |
ad2488fc MW |
518 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
519 | } | |
aa334daa MW |
520 | else |
521 | { | |
522 | message->destroy(message); | |
523 | } | |
ad2488fc MW |
524 | } |
525 | ||
c8531b7e MW |
526 | /** |
527 | * Process messages of type IKE_IV | |
528 | */ | |
529 | static void process_ike_iv(private_ha_dispatcher_t *this, ha_message_t *message) | |
530 | { | |
531 | ha_message_attribute_t attribute; | |
532 | ha_message_value_t value; | |
533 | enumerator_t *enumerator; | |
534 | ike_sa_t *ike_sa = NULL; | |
535 | chunk_t iv = chunk_empty; | |
536 | ||
537 | enumerator = message->create_attribute_enumerator(message); | |
538 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
539 | { | |
540 | switch (attribute) | |
541 | { | |
542 | case HA_IKE_ID: | |
543 | ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, | |
544 | value.ike_sa_id); | |
545 | break; | |
546 | case HA_IV: | |
547 | iv = value.chunk; | |
548 | break; | |
549 | default: | |
550 | break; | |
551 | } | |
552 | } | |
553 | enumerator->destroy(enumerator); | |
554 | ||
555 | if (ike_sa) | |
556 | { | |
557 | if (ike_sa->get_version(ike_sa) == IKEV1) | |
558 | { | |
559 | if (iv.len) | |
560 | { | |
561 | keymat_v1_t *keymat; | |
562 | ||
563 | keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); | |
e185612d MW |
564 | if (keymat->update_iv(keymat, 0, iv)) |
565 | { | |
566 | keymat->confirm_iv(keymat, 0); | |
567 | } | |
c8531b7e MW |
568 | } |
569 | } | |
570 | this->cache->cache(this->cache, ike_sa, message); | |
571 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); | |
572 | } | |
573 | else | |
574 | { | |
575 | message->destroy(message); | |
576 | } | |
577 | } | |
578 | ||
765935c8 MW |
579 | /** |
580 | * Process messages of type IKE_DELETE | |
581 | */ | |
d8748966 MW |
582 | static void process_ike_delete(private_ha_dispatcher_t *this, |
583 | ha_message_t *message) | |
765935c8 | 584 | { |
d8748966 MW |
585 | ha_message_attribute_t attribute; |
586 | ha_message_value_t value; | |
765935c8 | 587 | enumerator_t *enumerator; |
aa334daa | 588 | ike_sa_t *ike_sa = NULL; |
765935c8 MW |
589 | |
590 | enumerator = message->create_attribute_enumerator(message); | |
591 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
592 | { | |
593 | switch (attribute) | |
594 | { | |
d8748966 | 595 | case HA_IKE_ID: |
34d240a6 MW |
596 | ike_sa = charon->ike_sa_manager->checkout( |
597 | charon->ike_sa_manager, value.ike_sa_id); | |
765935c8 MW |
598 | break; |
599 | default: | |
190edaf5 MW |
600 | break; |
601 | } | |
602 | } | |
603 | enumerator->destroy(enumerator); | |
aa334daa MW |
604 | if (ike_sa) |
605 | { | |
606 | this->cache->cache(this->cache, ike_sa, message); | |
607 | charon->ike_sa_manager->checkin_and_destroy( | |
608 | charon->ike_sa_manager, ike_sa); | |
609 | } | |
610 | else | |
611 | { | |
612 | message->destroy(message); | |
613 | } | |
190edaf5 MW |
614 | } |
615 | ||
c94fe198 | 616 | /** |
34d240a6 | 617 | * Lookup a child cfg from the peer cfg by name |
c94fe198 | 618 | */ |
34d240a6 | 619 | static child_cfg_t* find_child_cfg(ike_sa_t *ike_sa, char *name) |
c94fe198 MW |
620 | { |
621 | peer_cfg_t *peer_cfg; | |
622 | child_cfg_t *current, *found = NULL; | |
623 | enumerator_t *enumerator; | |
624 | ||
34d240a6 | 625 | peer_cfg = ike_sa->get_peer_cfg(ike_sa); |
c94fe198 MW |
626 | if (peer_cfg) |
627 | { | |
628 | enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); | |
629 | while (enumerator->enumerate(enumerator, ¤t)) | |
630 | { | |
631 | if (streq(current->get_name(current), name)) | |
632 | { | |
633 | found = current; | |
c94fe198 MW |
634 | break; |
635 | } | |
636 | } | |
637 | enumerator->destroy(enumerator); | |
c94fe198 MW |
638 | } |
639 | return found; | |
640 | } | |
641 | ||
7999be5b MW |
642 | /** |
643 | * Process messages of type CHILD_ADD | |
644 | */ | |
d8748966 MW |
645 | static void process_child_add(private_ha_dispatcher_t *this, |
646 | ha_message_t *message) | |
7999be5b | 647 | { |
d8748966 MW |
648 | ha_message_attribute_t attribute; |
649 | ha_message_value_t value; | |
c94fe198 MW |
650 | enumerator_t *enumerator; |
651 | ike_sa_t *ike_sa = NULL; | |
14041845 | 652 | char *config_name = ""; |
c94fe198 MW |
653 | child_cfg_t *config = NULL; |
654 | child_sa_t *child_sa; | |
655 | proposal_t *proposal; | |
6bc6f67b | 656 | bool initiator = FALSE, failed = FALSE, ok = FALSE; |
b12c53ce AS |
657 | uint32_t inbound_spi = 0, outbound_spi = 0; |
658 | uint16_t inbound_cpi = 0, outbound_cpi = 0; | |
659 | uint8_t mode = MODE_TUNNEL, ipcomp = 0; | |
660 | uint16_t encr = 0, integ = 0, len = 0, dh_grp = 0; | |
661 | uint16_t esn = NO_EXT_SEQ_NUMBERS; | |
08e266a1 | 662 | u_int seg_i, seg_o; |
c94fe198 MW |
663 | chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty; |
664 | chunk_t encr_i, integ_i, encr_r, integ_r; | |
665 | linked_list_t *local_ts, *remote_ts; | |
8bcd9bd1 | 666 | diffie_hellman_t *dh = NULL; |
c94fe198 MW |
667 | |
668 | enumerator = message->create_attribute_enumerator(message); | |
669 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
670 | { | |
671 | switch (attribute) | |
672 | { | |
d8748966 | 673 | case HA_IKE_ID: |
34d240a6 MW |
674 | ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, |
675 | value.ike_sa_id); | |
c94fe198 | 676 | break; |
d8748966 | 677 | case HA_CONFIG_NAME: |
34d240a6 | 678 | config_name = value.str; |
c94fe198 | 679 | break; |
3e6736f6 MW |
680 | case HA_INITIATOR: |
681 | initiator = value.u8; | |
682 | break; | |
d8748966 | 683 | case HA_INBOUND_SPI: |
c94fe198 MW |
684 | inbound_spi = value.u32; |
685 | break; | |
d8748966 | 686 | case HA_OUTBOUND_SPI: |
c94fe198 MW |
687 | outbound_spi = value.u32; |
688 | break; | |
d8748966 | 689 | case HA_INBOUND_CPI: |
c94fe198 MW |
690 | inbound_cpi = value.u32; |
691 | break; | |
d8748966 | 692 | case HA_OUTBOUND_CPI: |
c94fe198 MW |
693 | outbound_cpi = value.u32; |
694 | break; | |
d8748966 | 695 | case HA_IPSEC_MODE: |
c94fe198 MW |
696 | mode = value.u8; |
697 | break; | |
d8748966 | 698 | case HA_IPCOMP: |
c94fe198 MW |
699 | ipcomp = value.u8; |
700 | break; | |
d8748966 | 701 | case HA_ALG_ENCR: |
c94fe198 MW |
702 | encr = value.u16; |
703 | break; | |
d8748966 | 704 | case HA_ALG_ENCR_LEN: |
c94fe198 MW |
705 | len = value.u16; |
706 | break; | |
d8748966 | 707 | case HA_ALG_INTEG: |
c94fe198 MW |
708 | integ = value.u16; |
709 | break; | |
b5c2ed50 TB |
710 | case HA_ALG_DH: |
711 | dh_grp = value.u16; | |
712 | break; | |
98788537 MW |
713 | case HA_ESN: |
714 | esn = value.u16; | |
715 | break; | |
d8748966 | 716 | case HA_NONCE_I: |
c94fe198 MW |
717 | nonce_i = value.chunk; |
718 | break; | |
d8748966 | 719 | case HA_NONCE_R: |
c94fe198 MW |
720 | nonce_r = value.chunk; |
721 | break; | |
d8748966 | 722 | case HA_SECRET: |
c94fe198 MW |
723 | secret = value.chunk; |
724 | break; | |
725 | default: | |
726 | break; | |
727 | } | |
728 | } | |
729 | enumerator->destroy(enumerator); | |
730 | ||
34d240a6 | 731 | if (!ike_sa) |
c94fe198 | 732 | { |
d8748966 | 733 | DBG1(DBG_CHD, "IKE_SA for HA CHILD_SA not found"); |
aa334daa | 734 | message->destroy(message); |
c94fe198 MW |
735 | return; |
736 | } | |
34d240a6 MW |
737 | config = find_child_cfg(ike_sa, config_name); |
738 | if (!config) | |
c94fe198 | 739 | { |
d8748966 | 740 | DBG1(DBG_CHD, "HA is missing nodes child configuration"); |
34d240a6 | 741 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
aa334daa | 742 | message->destroy(message); |
c94fe198 MW |
743 | return; |
744 | } | |
34d240a6 | 745 | |
c94fe198 MW |
746 | child_sa = child_sa_create(ike_sa->get_my_host(ike_sa), |
747 | ike_sa->get_other_host(ike_sa), config, 0, | |
85b23888 | 748 | ike_sa->has_condition(ike_sa, COND_NAT_ANY), |
a6014d99 | 749 | 0, 0, 0, 0); |
c94fe198 MW |
750 | child_sa->set_mode(child_sa, mode); |
751 | child_sa->set_protocol(child_sa, PROTO_ESP); | |
752 | child_sa->set_ipcomp(child_sa, ipcomp); | |
753 | ||
bb162175 | 754 | proposal = proposal_create(PROTO_ESP, 0); |
c94fe198 MW |
755 | if (integ) |
756 | { | |
757 | proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0); | |
758 | } | |
759 | if (encr) | |
760 | { | |
761 | proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len); | |
762 | } | |
b5c2ed50 TB |
763 | if (dh_grp) |
764 | { | |
765 | proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, dh_grp, 0); | |
766 | } | |
98788537 | 767 | proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0); |
8bcd9bd1 MW |
768 | if (secret.len) |
769 | { | |
770 | dh = ha_diffie_hellman_create(secret, chunk_empty); | |
771 | } | |
6bc6f67b MW |
772 | if (ike_sa->get_version(ike_sa) == IKEV2) |
773 | { | |
774 | keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa); | |
c94fe198 | 775 | |
8bcd9bd1 MW |
776 | ok = keymat_v2->derive_child_keys(keymat_v2, proposal, dh, |
777 | nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r); | |
778 | } | |
779 | if (ike_sa->get_version(ike_sa) == IKEV1) | |
780 | { | |
781 | keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); | |
b12c53ce | 782 | uint32_t spi_i, spi_r; |
8bcd9bd1 MW |
783 | |
784 | spi_i = initiator ? inbound_spi : outbound_spi; | |
785 | spi_r = initiator ? outbound_spi : inbound_spi; | |
c94fe198 | 786 | |
8bcd9bd1 MW |
787 | ok = keymat_v1->derive_child_keys(keymat_v1, proposal, dh, spi_i, spi_r, |
788 | nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r); | |
6bc6f67b | 789 | } |
8bcd9bd1 | 790 | DESTROY_IF(dh); |
6bc6f67b | 791 | if (!ok) |
c94fe198 | 792 | { |
d8748966 | 793 | DBG1(DBG_CHD, "HA CHILD_SA key derivation failed"); |
c94fe198 MW |
794 | child_sa->destroy(child_sa); |
795 | proposal->destroy(proposal); | |
34d240a6 | 796 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
c94fe198 MW |
797 | return; |
798 | } | |
799 | child_sa->set_proposal(child_sa, proposal); | |
800 | child_sa->set_state(child_sa, CHILD_INSTALLING); | |
801 | proposal->destroy(proposal); | |
7999be5b | 802 | |
14041845 MW |
803 | /* TODO: Change CHILD_SA API to avoid cloning twice */ |
804 | local_ts = linked_list_create(); | |
805 | remote_ts = linked_list_create(); | |
806 | enumerator = message->create_attribute_enumerator(message); | |
807 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
808 | { | |
809 | switch (attribute) | |
810 | { | |
811 | case HA_LOCAL_TS: | |
812 | local_ts->insert_last(local_ts, value.ts->clone(value.ts)); | |
813 | break; | |
814 | case HA_REMOTE_TS: | |
815 | remote_ts->insert_last(remote_ts, value.ts->clone(value.ts)); | |
816 | break; | |
817 | default: | |
818 | break; | |
819 | } | |
820 | } | |
821 | enumerator->destroy(enumerator); | |
822 | ||
4989aba8 TB |
823 | child_sa->set_policies(child_sa, local_ts, remote_ts); |
824 | ||
c94fe198 MW |
825 | if (initiator) |
826 | { | |
14041845 | 827 | if (child_sa->install(child_sa, encr_r, integ_r, inbound_spi, |
4989aba8 | 828 | inbound_cpi, initiator, TRUE, TRUE) != SUCCESS || |
14041845 | 829 | child_sa->install(child_sa, encr_i, integ_i, outbound_spi, |
4989aba8 | 830 | outbound_cpi, initiator, FALSE, TRUE) != SUCCESS) |
c94fe198 MW |
831 | { |
832 | failed = TRUE; | |
833 | } | |
834 | } | |
835 | else | |
836 | { | |
14041845 | 837 | if (child_sa->install(child_sa, encr_i, integ_i, inbound_spi, |
4989aba8 | 838 | inbound_cpi, initiator, TRUE, TRUE) != SUCCESS || |
14041845 | 839 | child_sa->install(child_sa, encr_r, integ_r, outbound_spi, |
4989aba8 | 840 | outbound_cpi, initiator, FALSE, TRUE) != SUCCESS) |
c94fe198 MW |
841 | { |
842 | failed = TRUE; | |
843 | } | |
844 | } | |
845 | chunk_clear(&encr_i); | |
846 | chunk_clear(&integ_i); | |
847 | chunk_clear(&encr_r); | |
848 | chunk_clear(&integ_r); | |
849 | ||
850 | if (failed) | |
851 | { | |
d8748966 | 852 | DBG1(DBG_CHD, "HA CHILD_SA installation failed"); |
c94fe198 | 853 | child_sa->destroy(child_sa); |
14041845 MW |
854 | local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy)); |
855 | remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy)); | |
34d240a6 | 856 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
aa334daa | 857 | message->destroy(message); |
c94fe198 MW |
858 | return; |
859 | } | |
860 | ||
08e266a1 MW |
861 | seg_i = this->kernel->get_segment_spi(this->kernel, |
862 | ike_sa->get_my_host(ike_sa), inbound_spi); | |
863 | seg_o = this->kernel->get_segment_spi(this->kernel, | |
864 | ike_sa->get_other_host(ike_sa), outbound_spi); | |
865 | ||
ebeb8c87 | 866 | DBG1(DBG_CFG, "installed HA CHILD_SA %s{%d} %#R === %#R " |
08e266a1 | 867 | "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa), |
246c969d | 868 | child_sa->get_unique_id(child_sa), local_ts, remote_ts, |
08e266a1 MW |
869 | seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "", |
870 | seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : ""); | |
4989aba8 | 871 | child_sa->install_policies(child_sa); |
c94fe198 MW |
872 | local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy)); |
873 | remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy)); | |
874 | ||
875 | child_sa->set_state(child_sa, CHILD_INSTALLED); | |
876 | ike_sa->add_child_sa(ike_sa, child_sa); | |
aa334daa | 877 | message->destroy(message); |
34d240a6 | 878 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
7999be5b MW |
879 | } |
880 | ||
881 | /** | |
882 | * Process messages of type CHILD_DELETE | |
883 | */ | |
d8748966 MW |
884 | static void process_child_delete(private_ha_dispatcher_t *this, |
885 | ha_message_t *message) | |
7999be5b | 886 | { |
d8748966 MW |
887 | ha_message_attribute_t attribute; |
888 | ha_message_value_t value; | |
c94fe198 MW |
889 | enumerator_t *enumerator; |
890 | ike_sa_t *ike_sa = NULL; | |
aa334daa | 891 | child_sa_t *child_sa; |
b12c53ce | 892 | uint32_t spi = 0; |
7999be5b | 893 | |
c94fe198 MW |
894 | enumerator = message->create_attribute_enumerator(message); |
895 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
896 | { | |
897 | switch (attribute) | |
898 | { | |
d8748966 | 899 | case HA_IKE_ID: |
34d240a6 MW |
900 | ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, |
901 | value.ike_sa_id); | |
c94fe198 | 902 | break; |
d8748966 | 903 | case HA_INBOUND_SPI: |
aa334daa | 904 | spi = value.u32; |
c94fe198 MW |
905 | break; |
906 | default: | |
907 | break; | |
908 | } | |
c94fe198 | 909 | } |
aa334daa MW |
910 | enumerator->destroy(enumerator); |
911 | ||
34d240a6 MW |
912 | if (ike_sa) |
913 | { | |
aa334daa MW |
914 | child_sa = ike_sa->get_child_sa(ike_sa, PROTO_ESP, spi, TRUE); |
915 | if (child_sa) | |
916 | { | |
917 | ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, spi); | |
918 | } | |
34d240a6 MW |
919 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
920 | } | |
aa334daa | 921 | message->destroy(message); |
7999be5b MW |
922 | } |
923 | ||
37459ea9 MW |
924 | /** |
925 | * Process messages of type SEGMENT_TAKE/DROP | |
926 | */ | |
d8748966 MW |
927 | static void process_segment(private_ha_dispatcher_t *this, |
928 | ha_message_t *message, bool take) | |
37459ea9 | 929 | { |
d8748966 MW |
930 | ha_message_attribute_t attribute; |
931 | ha_message_value_t value; | |
37459ea9 MW |
932 | enumerator_t *enumerator; |
933 | ||
934 | enumerator = message->create_attribute_enumerator(message); | |
935 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
936 | { | |
937 | switch (attribute) | |
938 | { | |
d8748966 | 939 | case HA_SEGMENT: |
37459ea9 MW |
940 | if (take) |
941 | { | |
1466af85 | 942 | DBG1(DBG_CFG, "remote node takes segment %d", value.u16); |
37459ea9 MW |
943 | this->segments->deactivate(this->segments, value.u16, FALSE); |
944 | } | |
945 | else | |
946 | { | |
1466af85 | 947 | DBG1(DBG_CFG, "remote node drops segment %d", value.u16); |
37459ea9 MW |
948 | this->segments->activate(this->segments, value.u16, FALSE); |
949 | } | |
950 | break; | |
951 | default: | |
952 | break; | |
953 | } | |
954 | } | |
955 | enumerator->destroy(enumerator); | |
aa334daa | 956 | message->destroy(message); |
37459ea9 MW |
957 | } |
958 | ||
3912fdb1 MW |
959 | /** |
960 | * Process messages of type STATUS | |
961 | */ | |
d8748966 MW |
962 | static void process_status(private_ha_dispatcher_t *this, |
963 | ha_message_t *message) | |
3912fdb1 | 964 | { |
d8748966 MW |
965 | ha_message_attribute_t attribute; |
966 | ha_message_value_t value; | |
3912fdb1 MW |
967 | enumerator_t *enumerator; |
968 | segment_mask_t mask = 0; | |
969 | ||
970 | enumerator = message->create_attribute_enumerator(message); | |
971 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
972 | { | |
973 | switch (attribute) | |
974 | { | |
d8748966 | 975 | case HA_SEGMENT: |
3912fdb1 MW |
976 | mask |= SEGMENTS_BIT(value.u16); |
977 | break; | |
978 | default: | |
979 | break; | |
980 | } | |
981 | } | |
982 | enumerator->destroy(enumerator); | |
983 | ||
984 | this->segments->handle_status(this->segments, mask); | |
aa334daa | 985 | message->destroy(message); |
3912fdb1 MW |
986 | } |
987 | ||
c866a427 MW |
988 | /** |
989 | * Process messages of type RESYNC | |
990 | */ | |
991 | static void process_resync(private_ha_dispatcher_t *this, | |
992 | ha_message_t *message) | |
993 | { | |
994 | ha_message_attribute_t attribute; | |
995 | ha_message_value_t value; | |
996 | enumerator_t *enumerator; | |
997 | ||
998 | enumerator = message->create_attribute_enumerator(message); | |
999 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
1000 | { | |
1001 | switch (attribute) | |
1002 | { | |
1003 | case HA_SEGMENT: | |
aa334daa | 1004 | this->cache->resync(this->cache, value.u16); |
c866a427 MW |
1005 | break; |
1006 | default: | |
1007 | break; | |
1008 | } | |
1009 | } | |
1010 | enumerator->destroy(enumerator); | |
aa334daa | 1011 | message->destroy(message); |
c866a427 MW |
1012 | } |
1013 | ||
190edaf5 MW |
1014 | /** |
1015 | * Dispatcher job function | |
1016 | */ | |
d8748966 | 1017 | static job_requeue_t dispatch(private_ha_dispatcher_t *this) |
190edaf5 | 1018 | { |
d8748966 | 1019 | ha_message_t *message; |
2031002d | 1020 | ha_message_type_t type; |
190edaf5 MW |
1021 | |
1022 | message = this->socket->pull(this->socket); | |
2031002d MW |
1023 | type = message->get_type(message); |
1024 | if (type != HA_STATUS) | |
1025 | { | |
1026 | DBG2(DBG_CFG, "received HA %N message", ha_message_type_names, | |
1027 | message->get_type(message)); | |
1028 | } | |
1029 | switch (type) | |
190edaf5 | 1030 | { |
d8748966 | 1031 | case HA_IKE_ADD: |
190edaf5 MW |
1032 | process_ike_add(this, message); |
1033 | break; | |
d8748966 | 1034 | case HA_IKE_UPDATE: |
765935c8 | 1035 | process_ike_update(this, message); |
190edaf5 | 1036 | break; |
ad2488fc MW |
1037 | case HA_IKE_MID_INITIATOR: |
1038 | process_ike_mid(this, message, TRUE); | |
1039 | break; | |
1040 | case HA_IKE_MID_RESPONDER: | |
1041 | process_ike_mid(this, message, FALSE); | |
1042 | break; | |
c8531b7e MW |
1043 | case HA_IKE_IV: |
1044 | process_ike_iv(this, message); | |
1045 | break; | |
d8748966 | 1046 | case HA_IKE_DELETE: |
765935c8 | 1047 | process_ike_delete(this, message); |
190edaf5 | 1048 | break; |
d8748966 | 1049 | case HA_CHILD_ADD: |
7999be5b | 1050 | process_child_add(this, message); |
190edaf5 | 1051 | break; |
d8748966 | 1052 | case HA_CHILD_DELETE: |
7999be5b | 1053 | process_child_delete(this, message); |
190edaf5 | 1054 | break; |
d8748966 | 1055 | case HA_SEGMENT_DROP: |
37459ea9 MW |
1056 | process_segment(this, message, FALSE); |
1057 | break; | |
d8748966 | 1058 | case HA_SEGMENT_TAKE: |
37459ea9 MW |
1059 | process_segment(this, message, TRUE); |
1060 | break; | |
d8748966 | 1061 | case HA_STATUS: |
3912fdb1 MW |
1062 | process_status(this, message); |
1063 | break; | |
c866a427 MW |
1064 | case HA_RESYNC: |
1065 | process_resync(this, message); | |
1066 | break; | |
190edaf5 | 1067 | default: |
2031002d | 1068 | DBG1(DBG_CFG, "received unknown HA message type %d", type); |
aa334daa | 1069 | message->destroy(message); |
190edaf5 MW |
1070 | break; |
1071 | } | |
190edaf5 MW |
1072 | return JOB_REQUEUE_DIRECT; |
1073 | } | |
1074 | ||
00c1bd06 MW |
1075 | METHOD(ha_dispatcher_t, destroy, void, |
1076 | private_ha_dispatcher_t *this) | |
190edaf5 | 1077 | { |
190edaf5 MW |
1078 | free(this); |
1079 | } | |
1080 | ||
1081 | /** | |
1082 | * See header | |
1083 | */ | |
d8748966 | 1084 | ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket, |
98d03438 MW |
1085 | ha_segments_t *segments, ha_cache_t *cache, |
1086 | ha_kernel_t *kernel, ha_attribute_t *attr) | |
190edaf5 | 1087 | { |
00c1bd06 | 1088 | private_ha_dispatcher_t *this; |
190edaf5 | 1089 | |
190edaf5 | 1090 | |
00c1bd06 MW |
1091 | INIT(this, |
1092 | .public = { | |
1093 | .destroy = _destroy, | |
1094 | }, | |
1095 | .socket = socket, | |
1096 | .segments = segments, | |
aa334daa | 1097 | .cache = cache, |
08e266a1 | 1098 | .kernel = kernel, |
98d03438 | 1099 | .attr = attr, |
00c1bd06 | 1100 | ); |
26d77eb3 TB |
1101 | lib->processor->queue_job(lib->processor, |
1102 | (job_t*)callback_job_create_with_prio((callback_job_cb_t)dispatch, this, | |
1103 | NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); | |
190edaf5 MW |
1104 | |
1105 | return &this->public; | |
1106 | } |