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