]>
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) | |
20dfbcad TB |
262 | { /* register IKE_SA before calling inherit_post() so no scheduled |
263 | * jobs are lost */ | |
264 | charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, | |
79b526de | 265 | ike_sa); |
713a1122 MW |
266 | ike_sa->inherit_pre(ike_sa, old_sa); |
267 | ike_sa->inherit_post(ike_sa, old_sa); | |
34d240a6 MW |
268 | charon->ike_sa_manager->checkin_and_destroy( |
269 | charon->ike_sa_manager, old_sa); | |
270 | old_sa = NULL; | |
271 | } | |
34347094 TE |
272 | if (other) |
273 | { | |
274 | ike_sa->set_other_host(ike_sa, other); | |
275 | other = NULL; | |
276 | } | |
34d240a6 | 277 | ike_sa->set_state(ike_sa, IKE_CONNECTING); |
c3f1839a | 278 | ike_sa->set_proposal(ike_sa, proposal); |
aa334daa MW |
279 | this->cache->cache(this->cache, ike_sa, message); |
280 | message = NULL; | |
34d240a6 MW |
281 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
282 | } | |
283 | else | |
765935c8 | 284 | { |
d8748966 | 285 | DBG1(DBG_IKE, "HA keymat derivation failed"); |
34d240a6 | 286 | ike_sa->destroy(ike_sa); |
765935c8 | 287 | } |
c94fe198 | 288 | charon->bus->set_sa(charon->bus, NULL); |
765935c8 | 289 | proposal->destroy(proposal); |
34d240a6 MW |
290 | } |
291 | if (old_sa) | |
292 | { | |
293 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, old_sa); | |
765935c8 | 294 | } |
34347094 | 295 | DESTROY_IF(other); |
aa334daa | 296 | DESTROY_IF(message); |
765935c8 MW |
297 | } |
298 | ||
299 | /** | |
d6879ef9 | 300 | * Apply all set conditions to the IKE_SA |
765935c8 | 301 | */ |
d6879ef9 | 302 | static void set_conditions(ike_sa_t *ike_sa, ike_condition_t conditions) |
765935c8 | 303 | { |
d6879ef9 TE |
304 | ike_condition_t i; |
305 | ||
306 | for (i = 0; i < sizeof(i) * 8; ++i) | |
307 | { | |
308 | ike_condition_t cond = (1 << i); | |
309 | ||
310 | ike_sa->set_condition(ike_sa, cond, (conditions & cond) != 0); | |
311 | } | |
765935c8 MW |
312 | } |
313 | ||
314 | /** | |
d6879ef9 | 315 | * Apply all enabled extensions to the IKE_SA |
765935c8 | 316 | */ |
d6879ef9 | 317 | static void set_extensions(ike_sa_t *ike_sa, ike_extension_t extensions) |
765935c8 | 318 | { |
d6879ef9 TE |
319 | ike_extension_t i; |
320 | ||
321 | for (i = 0; i < sizeof(i) * 8; ++i) | |
765935c8 | 322 | { |
d6879ef9 TE |
323 | ike_extension_t ext = (1 << i); |
324 | ||
325 | if (extensions & ext) | |
326 | { | |
327 | ike_sa->enable_extension(ike_sa, ext); | |
328 | } | |
765935c8 MW |
329 | } |
330 | } | |
331 | ||
332 | /** | |
333 | * Process messages of type IKE_UPDATE | |
334 | */ | |
d8748966 MW |
335 | static void process_ike_update(private_ha_dispatcher_t *this, |
336 | ha_message_t *message) | |
765935c8 | 337 | { |
d8748966 MW |
338 | ha_message_attribute_t attribute; |
339 | ha_message_value_t value; | |
765935c8 MW |
340 | enumerator_t *enumerator; |
341 | ike_sa_t *ike_sa = NULL; | |
342 | peer_cfg_t *peer_cfg = NULL; | |
fa4f71c8 | 343 | auth_cfg_t *auth; |
d2e8f20d | 344 | bool received_vip = FALSE, first_local_vip = TRUE, first_peer_addr = TRUE; |
765935c8 MW |
345 | |
346 | enumerator = message->create_attribute_enumerator(message); | |
347 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
348 | { | |
d8748966 | 349 | if (attribute != HA_IKE_ID && ike_sa == NULL) |
765935c8 | 350 | { |
34d240a6 | 351 | /* must be first attribute */ |
765935c8 MW |
352 | break; |
353 | } | |
354 | switch (attribute) | |
355 | { | |
d8748966 | 356 | case HA_IKE_ID: |
34d240a6 MW |
357 | ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, |
358 | value.ike_sa_id); | |
190edaf5 | 359 | break; |
d8748966 | 360 | case HA_LOCAL_ID: |
765935c8 MW |
361 | ike_sa->set_my_id(ike_sa, value.id->clone(value.id)); |
362 | break; | |
d8748966 | 363 | case HA_REMOTE_ID: |
765935c8 MW |
364 | ike_sa->set_other_id(ike_sa, value.id->clone(value.id)); |
365 | break; | |
fa4f71c8 MW |
366 | case HA_REMOTE_EAP_ID: |
367 | auth = auth_cfg_create(); | |
368 | auth->add(auth, AUTH_RULE_EAP_IDENTITY, value.id->clone(value.id)); | |
369 | ike_sa->add_auth_cfg(ike_sa, FALSE, auth); | |
370 | break; | |
d8748966 | 371 | case HA_LOCAL_ADDR: |
765935c8 MW |
372 | ike_sa->set_my_host(ike_sa, value.host->clone(value.host)); |
373 | break; | |
d8748966 | 374 | case HA_REMOTE_ADDR: |
765935c8 MW |
375 | ike_sa->set_other_host(ike_sa, value.host->clone(value.host)); |
376 | break; | |
d8748966 | 377 | case HA_LOCAL_VIP: |
d2e8f20d TB |
378 | if (first_local_vip) |
379 | { | |
380 | ike_sa->clear_virtual_ips(ike_sa, TRUE); | |
381 | first_local_vip = FALSE; | |
382 | } | |
101d26ba | 383 | ike_sa->add_virtual_ip(ike_sa, TRUE, value.host); |
80624c79 | 384 | break; |
d8748966 | 385 | case HA_REMOTE_VIP: |
d2e8f20d TB |
386 | if (!received_vip) |
387 | { | |
388 | ike_sa->clear_virtual_ips(ike_sa, FALSE); | |
389 | } | |
101d26ba | 390 | ike_sa->add_virtual_ip(ike_sa, FALSE, value.host); |
98d03438 | 391 | received_vip = TRUE; |
765935c8 | 392 | break; |
94bbc602 | 393 | case HA_PEER_ADDR: |
cd6b5bf8 TB |
394 | if (first_peer_addr) |
395 | { | |
396 | ike_sa->clear_peer_addresses(ike_sa); | |
397 | first_peer_addr = FALSE; | |
398 | } | |
94bbc602 | 399 | ike_sa->add_peer_address(ike_sa, value.host->clone(value.host)); |
190edaf5 | 400 | break; |
d8748966 | 401 | case HA_CONFIG_NAME: |
765935c8 MW |
402 | peer_cfg = charon->backends->get_peer_cfg_by_name( |
403 | charon->backends, value.str); | |
34d240a6 MW |
404 | if (peer_cfg) |
405 | { | |
406 | ike_sa->set_peer_cfg(ike_sa, peer_cfg); | |
407 | peer_cfg->destroy(peer_cfg); | |
408 | } | |
409 | else | |
410 | { | |
d8748966 | 411 | DBG1(DBG_IKE, "HA is missing nodes peer configuration"); |
438318c6 MW |
412 | charon->ike_sa_manager->checkin_and_destroy( |
413 | charon->ike_sa_manager, ike_sa); | |
414 | ike_sa = NULL; | |
34d240a6 | 415 | } |
190edaf5 | 416 | break; |
d8748966 | 417 | case HA_EXTENSIONS: |
d6879ef9 | 418 | set_extensions(ike_sa, value.u32); |
26d08a24 | 419 | break; |
d8748966 | 420 | case HA_CONDITIONS: |
d6879ef9 | 421 | set_conditions(ike_sa, value.u32); |
190edaf5 | 422 | break; |
765935c8 MW |
423 | default: |
424 | break; | |
425 | } | |
426 | } | |
427 | enumerator->destroy(enumerator); | |
428 | ||
34d240a6 | 429 | if (ike_sa) |
765935c8 | 430 | { |
34d240a6 MW |
431 | if (ike_sa->get_state(ike_sa) == IKE_CONNECTING && |
432 | ike_sa->get_peer_cfg(ike_sa)) | |
433 | { | |
aa334daa MW |
434 | DBG1(DBG_CFG, "installed HA passive IKE_SA '%s' %H[%Y]...%H[%Y]", |
435 | ike_sa->get_name(ike_sa), | |
436 | ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa), | |
437 | ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa)); | |
34d240a6 MW |
438 | ike_sa->set_state(ike_sa, IKE_PASSIVE); |
439 | } | |
98d03438 MW |
440 | if (received_vip) |
441 | { | |
497ce2cf | 442 | enumerator_t *pools, *vips; |
98d03438 MW |
443 | host_t *vip; |
444 | char *pool; | |
445 | ||
446 | peer_cfg = ike_sa->get_peer_cfg(ike_sa); | |
101d26ba | 447 | if (peer_cfg) |
98d03438 | 448 | { |
497ce2cf MW |
449 | pools = peer_cfg->create_pool_enumerator(peer_cfg); |
450 | while (pools->enumerate(pools, &pool)) | |
98d03438 | 451 | { |
497ce2cf MW |
452 | vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE); |
453 | while (vips->enumerate(vips, &vip)) | |
101d26ba MW |
454 | { |
455 | this->attr->reserve(this->attr, pool, vip); | |
456 | } | |
497ce2cf | 457 | vips->destroy(vips); |
98d03438 | 458 | } |
497ce2cf | 459 | pools->destroy(pools); |
98d03438 MW |
460 | } |
461 | } | |
e1c7e1bc | 462 | #ifdef USE_IKEV1 |
aa3b53e7 MW |
463 | if (ike_sa->get_version(ike_sa) == IKEV1) |
464 | { | |
465 | lib->processor->queue_job(lib->processor, (job_t*) | |
466 | adopt_children_job_create(ike_sa->get_id(ike_sa))); | |
467 | } | |
e1c7e1bc | 468 | #endif /* USE_IKEV1 */ |
aa334daa | 469 | this->cache->cache(this->cache, ike_sa, message); |
34d240a6 | 470 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
765935c8 | 471 | } |
aa334daa MW |
472 | else |
473 | { | |
474 | DBG1(DBG_CFG, "passive HA IKE_SA to update not found"); | |
475 | message->destroy(message); | |
476 | } | |
765935c8 MW |
477 | } |
478 | ||
ad2488fc MW |
479 | /** |
480 | * Process messages of type IKE_MID_INITIATOR/RESPONDER | |
481 | */ | |
482 | static void process_ike_mid(private_ha_dispatcher_t *this, | |
483 | ha_message_t *message, bool initiator) | |
484 | { | |
485 | ha_message_attribute_t attribute; | |
486 | ha_message_value_t value; | |
487 | enumerator_t *enumerator; | |
488 | ike_sa_t *ike_sa = NULL; | |
b12c53ce | 489 | uint32_t mid = 0; |
ad2488fc MW |
490 | |
491 | enumerator = message->create_attribute_enumerator(message); | |
492 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
493 | { | |
494 | switch (attribute) | |
495 | { | |
496 | case HA_IKE_ID: | |
497 | ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, | |
498 | value.ike_sa_id); | |
499 | break; | |
500 | case HA_MID: | |
501 | mid = value.u32; | |
502 | break; | |
503 | default: | |
504 | break; | |
505 | } | |
506 | } | |
507 | enumerator->destroy(enumerator); | |
508 | ||
509 | if (ike_sa) | |
510 | { | |
511 | if (mid) | |
512 | { | |
513 | ike_sa->set_message_id(ike_sa, initiator, mid); | |
514 | } | |
aa334daa | 515 | this->cache->cache(this->cache, ike_sa, message); |
ad2488fc MW |
516 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
517 | } | |
aa334daa MW |
518 | else |
519 | { | |
520 | message->destroy(message); | |
521 | } | |
ad2488fc MW |
522 | } |
523 | ||
c8531b7e MW |
524 | /** |
525 | * Process messages of type IKE_IV | |
526 | */ | |
527 | static void process_ike_iv(private_ha_dispatcher_t *this, ha_message_t *message) | |
528 | { | |
529 | ha_message_attribute_t attribute; | |
530 | ha_message_value_t value; | |
531 | enumerator_t *enumerator; | |
532 | ike_sa_t *ike_sa = NULL; | |
533 | chunk_t iv = chunk_empty; | |
534 | ||
535 | enumerator = message->create_attribute_enumerator(message); | |
536 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
537 | { | |
538 | switch (attribute) | |
539 | { | |
540 | case HA_IKE_ID: | |
541 | ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, | |
542 | value.ike_sa_id); | |
543 | break; | |
544 | case HA_IV: | |
545 | iv = value.chunk; | |
546 | break; | |
547 | default: | |
548 | break; | |
549 | } | |
550 | } | |
551 | enumerator->destroy(enumerator); | |
552 | ||
553 | if (ike_sa) | |
554 | { | |
555 | if (ike_sa->get_version(ike_sa) == IKEV1) | |
556 | { | |
557 | if (iv.len) | |
558 | { | |
559 | keymat_v1_t *keymat; | |
560 | ||
561 | keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); | |
e185612d MW |
562 | if (keymat->update_iv(keymat, 0, iv)) |
563 | { | |
564 | keymat->confirm_iv(keymat, 0); | |
565 | } | |
c8531b7e MW |
566 | } |
567 | } | |
568 | this->cache->cache(this->cache, ike_sa, message); | |
569 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); | |
570 | } | |
571 | else | |
572 | { | |
573 | message->destroy(message); | |
574 | } | |
575 | } | |
576 | ||
765935c8 MW |
577 | /** |
578 | * Process messages of type IKE_DELETE | |
579 | */ | |
d8748966 MW |
580 | static void process_ike_delete(private_ha_dispatcher_t *this, |
581 | ha_message_t *message) | |
765935c8 | 582 | { |
d8748966 MW |
583 | ha_message_attribute_t attribute; |
584 | ha_message_value_t value; | |
765935c8 | 585 | enumerator_t *enumerator; |
aa334daa | 586 | ike_sa_t *ike_sa = NULL; |
765935c8 MW |
587 | |
588 | enumerator = message->create_attribute_enumerator(message); | |
589 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
590 | { | |
591 | switch (attribute) | |
592 | { | |
d8748966 | 593 | case HA_IKE_ID: |
34d240a6 MW |
594 | ike_sa = charon->ike_sa_manager->checkout( |
595 | charon->ike_sa_manager, value.ike_sa_id); | |
765935c8 MW |
596 | break; |
597 | default: | |
190edaf5 MW |
598 | break; |
599 | } | |
600 | } | |
601 | enumerator->destroy(enumerator); | |
aa334daa MW |
602 | if (ike_sa) |
603 | { | |
604 | this->cache->cache(this->cache, ike_sa, message); | |
605 | charon->ike_sa_manager->checkin_and_destroy( | |
606 | charon->ike_sa_manager, ike_sa); | |
607 | } | |
608 | else | |
609 | { | |
610 | message->destroy(message); | |
611 | } | |
190edaf5 MW |
612 | } |
613 | ||
c94fe198 | 614 | /** |
34d240a6 | 615 | * Lookup a child cfg from the peer cfg by name |
c94fe198 | 616 | */ |
34d240a6 | 617 | static child_cfg_t* find_child_cfg(ike_sa_t *ike_sa, char *name) |
c94fe198 MW |
618 | { |
619 | peer_cfg_t *peer_cfg; | |
620 | child_cfg_t *current, *found = NULL; | |
621 | enumerator_t *enumerator; | |
622 | ||
34d240a6 | 623 | peer_cfg = ike_sa->get_peer_cfg(ike_sa); |
c94fe198 MW |
624 | if (peer_cfg) |
625 | { | |
626 | enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); | |
627 | while (enumerator->enumerate(enumerator, ¤t)) | |
628 | { | |
629 | if (streq(current->get_name(current), name)) | |
630 | { | |
631 | found = current; | |
c94fe198 MW |
632 | break; |
633 | } | |
634 | } | |
635 | enumerator->destroy(enumerator); | |
c94fe198 MW |
636 | } |
637 | return found; | |
638 | } | |
639 | ||
7999be5b MW |
640 | /** |
641 | * Process messages of type CHILD_ADD | |
642 | */ | |
d8748966 MW |
643 | static void process_child_add(private_ha_dispatcher_t *this, |
644 | ha_message_t *message) | |
7999be5b | 645 | { |
d8748966 MW |
646 | ha_message_attribute_t attribute; |
647 | ha_message_value_t value; | |
c94fe198 MW |
648 | enumerator_t *enumerator; |
649 | ike_sa_t *ike_sa = NULL; | |
14041845 | 650 | char *config_name = ""; |
c94fe198 MW |
651 | child_cfg_t *config = NULL; |
652 | child_sa_t *child_sa; | |
653 | proposal_t *proposal; | |
6bc6f67b | 654 | bool initiator = FALSE, failed = FALSE, ok = FALSE; |
b12c53ce AS |
655 | uint32_t inbound_spi = 0, outbound_spi = 0; |
656 | uint16_t inbound_cpi = 0, outbound_cpi = 0; | |
657 | uint8_t mode = MODE_TUNNEL, ipcomp = 0; | |
658 | uint16_t encr = 0, integ = 0, len = 0, dh_grp = 0; | |
659 | uint16_t esn = NO_EXT_SEQ_NUMBERS; | |
08e266a1 | 660 | u_int seg_i, seg_o; |
c94fe198 MW |
661 | chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty; |
662 | chunk_t encr_i, integ_i, encr_r, integ_r; | |
663 | linked_list_t *local_ts, *remote_ts; | |
8bcd9bd1 | 664 | diffie_hellman_t *dh = NULL; |
c94fe198 MW |
665 | |
666 | enumerator = message->create_attribute_enumerator(message); | |
667 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
668 | { | |
669 | switch (attribute) | |
670 | { | |
d8748966 | 671 | case HA_IKE_ID: |
34d240a6 MW |
672 | ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, |
673 | value.ike_sa_id); | |
c94fe198 | 674 | break; |
d8748966 | 675 | case HA_CONFIG_NAME: |
34d240a6 | 676 | config_name = value.str; |
c94fe198 | 677 | break; |
3e6736f6 MW |
678 | case HA_INITIATOR: |
679 | initiator = value.u8; | |
680 | break; | |
d8748966 | 681 | case HA_INBOUND_SPI: |
c94fe198 MW |
682 | inbound_spi = value.u32; |
683 | break; | |
d8748966 | 684 | case HA_OUTBOUND_SPI: |
c94fe198 MW |
685 | outbound_spi = value.u32; |
686 | break; | |
d8748966 | 687 | case HA_INBOUND_CPI: |
c94fe198 MW |
688 | inbound_cpi = value.u32; |
689 | break; | |
d8748966 | 690 | case HA_OUTBOUND_CPI: |
c94fe198 MW |
691 | outbound_cpi = value.u32; |
692 | break; | |
d8748966 | 693 | case HA_IPSEC_MODE: |
c94fe198 MW |
694 | mode = value.u8; |
695 | break; | |
d8748966 | 696 | case HA_IPCOMP: |
c94fe198 MW |
697 | ipcomp = value.u8; |
698 | break; | |
d8748966 | 699 | case HA_ALG_ENCR: |
c94fe198 MW |
700 | encr = value.u16; |
701 | break; | |
d8748966 | 702 | case HA_ALG_ENCR_LEN: |
c94fe198 MW |
703 | len = value.u16; |
704 | break; | |
d8748966 | 705 | case HA_ALG_INTEG: |
c94fe198 MW |
706 | integ = value.u16; |
707 | break; | |
b5c2ed50 TB |
708 | case HA_ALG_DH: |
709 | dh_grp = value.u16; | |
710 | break; | |
98788537 MW |
711 | case HA_ESN: |
712 | esn = value.u16; | |
713 | break; | |
d8748966 | 714 | case HA_NONCE_I: |
c94fe198 MW |
715 | nonce_i = value.chunk; |
716 | break; | |
d8748966 | 717 | case HA_NONCE_R: |
c94fe198 MW |
718 | nonce_r = value.chunk; |
719 | break; | |
d8748966 | 720 | case HA_SECRET: |
c94fe198 MW |
721 | secret = value.chunk; |
722 | break; | |
723 | default: | |
724 | break; | |
725 | } | |
726 | } | |
727 | enumerator->destroy(enumerator); | |
728 | ||
34d240a6 | 729 | if (!ike_sa) |
c94fe198 | 730 | { |
d8748966 | 731 | DBG1(DBG_CHD, "IKE_SA for HA CHILD_SA not found"); |
aa334daa | 732 | message->destroy(message); |
c94fe198 MW |
733 | return; |
734 | } | |
34d240a6 MW |
735 | config = find_child_cfg(ike_sa, config_name); |
736 | if (!config) | |
c94fe198 | 737 | { |
d8748966 | 738 | DBG1(DBG_CHD, "HA is missing nodes child configuration"); |
34d240a6 | 739 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
aa334daa | 740 | message->destroy(message); |
c94fe198 MW |
741 | return; |
742 | } | |
34d240a6 | 743 | |
fafa7698 TB |
744 | child_sa_create_t data = { |
745 | .encap = ike_sa->has_condition(ike_sa, COND_NAT_ANY), | |
746 | }; | |
c94fe198 | 747 | child_sa = child_sa_create(ike_sa->get_my_host(ike_sa), |
fafa7698 | 748 | ike_sa->get_other_host(ike_sa), config, &data); |
c94fe198 MW |
749 | child_sa->set_mode(child_sa, mode); |
750 | child_sa->set_protocol(child_sa, PROTO_ESP); | |
751 | child_sa->set_ipcomp(child_sa, ipcomp); | |
752 | ||
bb162175 | 753 | proposal = proposal_create(PROTO_ESP, 0); |
c94fe198 MW |
754 | if (integ) |
755 | { | |
756 | proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0); | |
757 | } | |
758 | if (encr) | |
759 | { | |
760 | proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len); | |
761 | } | |
b5c2ed50 TB |
762 | if (dh_grp) |
763 | { | |
764 | proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, dh_grp, 0); | |
765 | } | |
98788537 | 766 | proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0); |
8bcd9bd1 MW |
767 | if (secret.len) |
768 | { | |
769 | dh = ha_diffie_hellman_create(secret, chunk_empty); | |
770 | } | |
6bc6f67b MW |
771 | if (ike_sa->get_version(ike_sa) == IKEV2) |
772 | { | |
773 | keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa); | |
c94fe198 | 774 | |
8bcd9bd1 MW |
775 | ok = keymat_v2->derive_child_keys(keymat_v2, proposal, dh, |
776 | nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r); | |
777 | } | |
778 | if (ike_sa->get_version(ike_sa) == IKEV1) | |
779 | { | |
780 | keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); | |
b12c53ce | 781 | uint32_t spi_i, spi_r; |
8bcd9bd1 MW |
782 | |
783 | spi_i = initiator ? inbound_spi : outbound_spi; | |
784 | spi_r = initiator ? outbound_spi : inbound_spi; | |
c94fe198 | 785 | |
8bcd9bd1 MW |
786 | ok = keymat_v1->derive_child_keys(keymat_v1, proposal, dh, spi_i, spi_r, |
787 | nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r); | |
6bc6f67b | 788 | } |
8bcd9bd1 | 789 | DESTROY_IF(dh); |
6bc6f67b | 790 | if (!ok) |
c94fe198 | 791 | { |
d8748966 | 792 | DBG1(DBG_CHD, "HA CHILD_SA key derivation failed"); |
c94fe198 MW |
793 | child_sa->destroy(child_sa); |
794 | proposal->destroy(proposal); | |
34d240a6 | 795 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
c94fe198 MW |
796 | return; |
797 | } | |
798 | child_sa->set_proposal(child_sa, proposal); | |
799 | child_sa->set_state(child_sa, CHILD_INSTALLING); | |
800 | proposal->destroy(proposal); | |
7999be5b | 801 | |
14041845 MW |
802 | /* TODO: Change CHILD_SA API to avoid cloning twice */ |
803 | local_ts = linked_list_create(); | |
804 | remote_ts = linked_list_create(); | |
805 | enumerator = message->create_attribute_enumerator(message); | |
806 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
807 | { | |
808 | switch (attribute) | |
809 | { | |
810 | case HA_LOCAL_TS: | |
811 | local_ts->insert_last(local_ts, value.ts->clone(value.ts)); | |
812 | break; | |
813 | case HA_REMOTE_TS: | |
814 | remote_ts->insert_last(remote_ts, value.ts->clone(value.ts)); | |
815 | break; | |
816 | default: | |
817 | break; | |
818 | } | |
819 | } | |
820 | enumerator->destroy(enumerator); | |
821 | ||
4989aba8 TB |
822 | child_sa->set_policies(child_sa, local_ts, remote_ts); |
823 | ||
c94fe198 MW |
824 | if (initiator) |
825 | { | |
14041845 | 826 | if (child_sa->install(child_sa, encr_r, integ_r, inbound_spi, |
4989aba8 | 827 | inbound_cpi, initiator, TRUE, TRUE) != SUCCESS || |
14041845 | 828 | child_sa->install(child_sa, encr_i, integ_i, outbound_spi, |
4989aba8 | 829 | outbound_cpi, initiator, FALSE, TRUE) != SUCCESS) |
c94fe198 MW |
830 | { |
831 | failed = TRUE; | |
832 | } | |
833 | } | |
834 | else | |
835 | { | |
14041845 | 836 | if (child_sa->install(child_sa, encr_i, integ_i, inbound_spi, |
4989aba8 | 837 | inbound_cpi, initiator, TRUE, TRUE) != SUCCESS || |
14041845 | 838 | child_sa->install(child_sa, encr_r, integ_r, outbound_spi, |
4989aba8 | 839 | outbound_cpi, initiator, FALSE, TRUE) != SUCCESS) |
c94fe198 MW |
840 | { |
841 | failed = TRUE; | |
842 | } | |
843 | } | |
844 | chunk_clear(&encr_i); | |
845 | chunk_clear(&integ_i); | |
846 | chunk_clear(&encr_r); | |
847 | chunk_clear(&integ_r); | |
848 | ||
849 | if (failed) | |
850 | { | |
d8748966 | 851 | DBG1(DBG_CHD, "HA CHILD_SA installation failed"); |
c94fe198 | 852 | child_sa->destroy(child_sa); |
14041845 MW |
853 | local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy)); |
854 | remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy)); | |
34d240a6 | 855 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
aa334daa | 856 | message->destroy(message); |
c94fe198 MW |
857 | return; |
858 | } | |
859 | ||
08e266a1 MW |
860 | seg_i = this->kernel->get_segment_spi(this->kernel, |
861 | ike_sa->get_my_host(ike_sa), inbound_spi); | |
862 | seg_o = this->kernel->get_segment_spi(this->kernel, | |
863 | ike_sa->get_other_host(ike_sa), outbound_spi); | |
864 | ||
ebeb8c87 | 865 | DBG1(DBG_CFG, "installed HA CHILD_SA %s{%d} %#R === %#R " |
08e266a1 | 866 | "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa), |
246c969d | 867 | child_sa->get_unique_id(child_sa), local_ts, remote_ts, |
08e266a1 MW |
868 | seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "", |
869 | seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : ""); | |
4989aba8 | 870 | child_sa->install_policies(child_sa); |
c94fe198 MW |
871 | local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy)); |
872 | remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy)); | |
873 | ||
874 | child_sa->set_state(child_sa, CHILD_INSTALLED); | |
875 | ike_sa->add_child_sa(ike_sa, child_sa); | |
aa334daa | 876 | message->destroy(message); |
34d240a6 | 877 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
7999be5b MW |
878 | } |
879 | ||
880 | /** | |
881 | * Process messages of type CHILD_DELETE | |
882 | */ | |
d8748966 MW |
883 | static void process_child_delete(private_ha_dispatcher_t *this, |
884 | ha_message_t *message) | |
7999be5b | 885 | { |
d8748966 MW |
886 | ha_message_attribute_t attribute; |
887 | ha_message_value_t value; | |
c94fe198 MW |
888 | enumerator_t *enumerator; |
889 | ike_sa_t *ike_sa = NULL; | |
aa334daa | 890 | child_sa_t *child_sa; |
b12c53ce | 891 | uint32_t spi = 0; |
7999be5b | 892 | |
c94fe198 MW |
893 | enumerator = message->create_attribute_enumerator(message); |
894 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
895 | { | |
896 | switch (attribute) | |
897 | { | |
d8748966 | 898 | case HA_IKE_ID: |
34d240a6 MW |
899 | ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, |
900 | value.ike_sa_id); | |
c94fe198 | 901 | break; |
d8748966 | 902 | case HA_INBOUND_SPI: |
aa334daa | 903 | spi = value.u32; |
c94fe198 MW |
904 | break; |
905 | default: | |
906 | break; | |
907 | } | |
c94fe198 | 908 | } |
aa334daa MW |
909 | enumerator->destroy(enumerator); |
910 | ||
34d240a6 MW |
911 | if (ike_sa) |
912 | { | |
aa334daa MW |
913 | child_sa = ike_sa->get_child_sa(ike_sa, PROTO_ESP, spi, TRUE); |
914 | if (child_sa) | |
915 | { | |
916 | ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, spi); | |
917 | } | |
34d240a6 MW |
918 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); |
919 | } | |
aa334daa | 920 | message->destroy(message); |
7999be5b MW |
921 | } |
922 | ||
37459ea9 MW |
923 | /** |
924 | * Process messages of type SEGMENT_TAKE/DROP | |
925 | */ | |
d8748966 MW |
926 | static void process_segment(private_ha_dispatcher_t *this, |
927 | ha_message_t *message, bool take) | |
37459ea9 | 928 | { |
d8748966 MW |
929 | ha_message_attribute_t attribute; |
930 | ha_message_value_t value; | |
37459ea9 MW |
931 | enumerator_t *enumerator; |
932 | ||
933 | enumerator = message->create_attribute_enumerator(message); | |
934 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
935 | { | |
936 | switch (attribute) | |
937 | { | |
d8748966 | 938 | case HA_SEGMENT: |
37459ea9 MW |
939 | if (take) |
940 | { | |
1466af85 | 941 | DBG1(DBG_CFG, "remote node takes segment %d", value.u16); |
37459ea9 MW |
942 | this->segments->deactivate(this->segments, value.u16, FALSE); |
943 | } | |
944 | else | |
945 | { | |
1466af85 | 946 | DBG1(DBG_CFG, "remote node drops segment %d", value.u16); |
37459ea9 MW |
947 | this->segments->activate(this->segments, value.u16, FALSE); |
948 | } | |
949 | break; | |
950 | default: | |
951 | break; | |
952 | } | |
953 | } | |
954 | enumerator->destroy(enumerator); | |
aa334daa | 955 | message->destroy(message); |
37459ea9 MW |
956 | } |
957 | ||
3912fdb1 MW |
958 | /** |
959 | * Process messages of type STATUS | |
960 | */ | |
d8748966 MW |
961 | static void process_status(private_ha_dispatcher_t *this, |
962 | ha_message_t *message) | |
3912fdb1 | 963 | { |
d8748966 MW |
964 | ha_message_attribute_t attribute; |
965 | ha_message_value_t value; | |
3912fdb1 MW |
966 | enumerator_t *enumerator; |
967 | segment_mask_t mask = 0; | |
968 | ||
969 | enumerator = message->create_attribute_enumerator(message); | |
970 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
971 | { | |
972 | switch (attribute) | |
973 | { | |
d8748966 | 974 | case HA_SEGMENT: |
3912fdb1 MW |
975 | mask |= SEGMENTS_BIT(value.u16); |
976 | break; | |
977 | default: | |
978 | break; | |
979 | } | |
980 | } | |
981 | enumerator->destroy(enumerator); | |
982 | ||
983 | this->segments->handle_status(this->segments, mask); | |
aa334daa | 984 | message->destroy(message); |
3912fdb1 MW |
985 | } |
986 | ||
c866a427 MW |
987 | /** |
988 | * Process messages of type RESYNC | |
989 | */ | |
990 | static void process_resync(private_ha_dispatcher_t *this, | |
991 | ha_message_t *message) | |
992 | { | |
993 | ha_message_attribute_t attribute; | |
994 | ha_message_value_t value; | |
995 | enumerator_t *enumerator; | |
996 | ||
997 | enumerator = message->create_attribute_enumerator(message); | |
998 | while (enumerator->enumerate(enumerator, &attribute, &value)) | |
999 | { | |
1000 | switch (attribute) | |
1001 | { | |
1002 | case HA_SEGMENT: | |
aa334daa | 1003 | this->cache->resync(this->cache, value.u16); |
c866a427 MW |
1004 | break; |
1005 | default: | |
1006 | break; | |
1007 | } | |
1008 | } | |
1009 | enumerator->destroy(enumerator); | |
aa334daa | 1010 | message->destroy(message); |
c866a427 MW |
1011 | } |
1012 | ||
190edaf5 MW |
1013 | /** |
1014 | * Dispatcher job function | |
1015 | */ | |
d8748966 | 1016 | static job_requeue_t dispatch(private_ha_dispatcher_t *this) |
190edaf5 | 1017 | { |
d8748966 | 1018 | ha_message_t *message; |
2031002d | 1019 | ha_message_type_t type; |
190edaf5 MW |
1020 | |
1021 | message = this->socket->pull(this->socket); | |
2031002d MW |
1022 | type = message->get_type(message); |
1023 | if (type != HA_STATUS) | |
1024 | { | |
1025 | DBG2(DBG_CFG, "received HA %N message", ha_message_type_names, | |
1026 | message->get_type(message)); | |
1027 | } | |
1028 | switch (type) | |
190edaf5 | 1029 | { |
d8748966 | 1030 | case HA_IKE_ADD: |
190edaf5 MW |
1031 | process_ike_add(this, message); |
1032 | break; | |
d8748966 | 1033 | case HA_IKE_UPDATE: |
765935c8 | 1034 | process_ike_update(this, message); |
190edaf5 | 1035 | break; |
ad2488fc MW |
1036 | case HA_IKE_MID_INITIATOR: |
1037 | process_ike_mid(this, message, TRUE); | |
1038 | break; | |
1039 | case HA_IKE_MID_RESPONDER: | |
1040 | process_ike_mid(this, message, FALSE); | |
1041 | break; | |
c8531b7e MW |
1042 | case HA_IKE_IV: |
1043 | process_ike_iv(this, message); | |
1044 | break; | |
d8748966 | 1045 | case HA_IKE_DELETE: |
765935c8 | 1046 | process_ike_delete(this, message); |
190edaf5 | 1047 | break; |
d8748966 | 1048 | case HA_CHILD_ADD: |
7999be5b | 1049 | process_child_add(this, message); |
190edaf5 | 1050 | break; |
d8748966 | 1051 | case HA_CHILD_DELETE: |
7999be5b | 1052 | process_child_delete(this, message); |
190edaf5 | 1053 | break; |
d8748966 | 1054 | case HA_SEGMENT_DROP: |
37459ea9 MW |
1055 | process_segment(this, message, FALSE); |
1056 | break; | |
d8748966 | 1057 | case HA_SEGMENT_TAKE: |
37459ea9 MW |
1058 | process_segment(this, message, TRUE); |
1059 | break; | |
d8748966 | 1060 | case HA_STATUS: |
3912fdb1 MW |
1061 | process_status(this, message); |
1062 | break; | |
c866a427 MW |
1063 | case HA_RESYNC: |
1064 | process_resync(this, message); | |
1065 | break; | |
190edaf5 | 1066 | default: |
2031002d | 1067 | DBG1(DBG_CFG, "received unknown HA message type %d", type); |
aa334daa | 1068 | message->destroy(message); |
190edaf5 MW |
1069 | break; |
1070 | } | |
190edaf5 MW |
1071 | return JOB_REQUEUE_DIRECT; |
1072 | } | |
1073 | ||
00c1bd06 MW |
1074 | METHOD(ha_dispatcher_t, destroy, void, |
1075 | private_ha_dispatcher_t *this) | |
190edaf5 | 1076 | { |
190edaf5 MW |
1077 | free(this); |
1078 | } | |
1079 | ||
1080 | /** | |
1081 | * See header | |
1082 | */ | |
d8748966 | 1083 | ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket, |
98d03438 MW |
1084 | ha_segments_t *segments, ha_cache_t *cache, |
1085 | ha_kernel_t *kernel, ha_attribute_t *attr) | |
190edaf5 | 1086 | { |
00c1bd06 | 1087 | private_ha_dispatcher_t *this; |
190edaf5 | 1088 | |
190edaf5 | 1089 | |
00c1bd06 MW |
1090 | INIT(this, |
1091 | .public = { | |
1092 | .destroy = _destroy, | |
1093 | }, | |
1094 | .socket = socket, | |
1095 | .segments = segments, | |
aa334daa | 1096 | .cache = cache, |
08e266a1 | 1097 | .kernel = kernel, |
98d03438 | 1098 | .attr = attr, |
00c1bd06 | 1099 | ); |
26d77eb3 TB |
1100 | lib->processor->queue_job(lib->processor, |
1101 | (job_t*)callback_job_create_with_prio((callback_job_cb_t)dispatch, this, | |
1102 | NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); | |
190edaf5 MW |
1103 | |
1104 | return &this->public; | |
1105 | } |