ikev1: Log traffic selectors for missing child configs
[strongswan.git] / src / libcharon / bus / bus.c
1 /*
2 * Copyright (C) 2011-2016 Tobias Brunner
3 * Copyright (C) 2006 Martin Willi
4 * HSR Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "bus.h"
18
19 #include <stdint.h>
20
21 #include <threading/thread.h>
22 #include <threading/thread_value.h>
23 #include <threading/mutex.h>
24 #include <threading/rwlock.h>
25
26 /**
27 * These operations allow us to speed up the log level checks on some platforms.
28 * In particular if acquiring the read lock is expensive even in the absence of
29 * any writers.
30 *
31 * Note that while holding the read/write lock the read does not have to be
32 * atomic as the write lock must be held to set the level.
33 */
34 #ifdef HAVE_GCC_ATOMIC_OPERATIONS
35
36 #define skip_level(ptr, level) (__atomic_load_n(ptr, __ATOMIC_RELAXED) < level)
37 #define set_level(ptr, val) __atomic_store_n(ptr, val, __ATOMIC_RELAXED)
38
39 #elif defined(HAVE_GCC_SYNC_OPERATIONS)
40
41 #define skip_level(ptr, level) (__sync_fetch_and_add(ptr, 0) < level)
42 #define set_level(ptr, val) __sync_bool_compare_and_swap(ptr, *ptr, val)
43
44 #else
45
46 #define skip_level(ptr, level) FALSE
47 #define set_level(ptr, val) ({ *ptr = val; })
48
49 #endif
50
51 typedef struct private_bus_t private_bus_t;
52
53 /**
54 * Private data of a bus_t object.
55 */
56 struct private_bus_t {
57 /**
58 * Public part of a bus_t object.
59 */
60 bus_t public;
61
62 /**
63 * List of registered listeners as entry_t.
64 */
65 linked_list_t *listeners;
66
67 /**
68 * List of registered loggers for each log group as log_entry_t.
69 * Loggers are ordered by descending log level.
70 * The extra list stores all loggers so we can properly unregister them.
71 */
72 linked_list_t *loggers[DBG_MAX + 1];
73
74 /**
75 * Maximum log level of any registered logger for each log group.
76 * This allows to check quickly if a log message has to be logged at all.
77 */
78 level_t max_level[DBG_MAX + 1];
79
80 /**
81 * Same as max level, but for loggers using the vlog() method.
82 */
83 level_t max_vlevel[DBG_MAX + 1];
84
85 /**
86 * Mutex for the list of listeners, recursively.
87 */
88 mutex_t *mutex;
89
90 /**
91 * Read-write lock for the list of loggers.
92 */
93 rwlock_t *log_lock;
94
95 /**
96 * Thread local storage the threads IKE_SA
97 */
98 thread_value_t *thread_sa;
99 };
100
101 typedef struct entry_t entry_t;
102
103 /**
104 * a listener entry
105 */
106 struct entry_t {
107
108 /**
109 * registered listener interface
110 */
111 listener_t *listener;
112
113 /**
114 * are we currently calling this listener
115 */
116 int calling;
117
118 };
119
120 typedef struct log_entry_t log_entry_t;
121
122 /**
123 * a logger entry
124 */
125 struct log_entry_t {
126
127 /**
128 * registered logger interface
129 */
130 logger_t *logger;
131
132 /**
133 * registered log levels per group
134 */
135 level_t levels[DBG_MAX];
136
137 };
138
139 METHOD(bus_t, add_listener, void,
140 private_bus_t *this, listener_t *listener)
141 {
142 entry_t *entry;
143
144 INIT(entry,
145 .listener = listener,
146 );
147
148 this->mutex->lock(this->mutex);
149 this->listeners->insert_last(this->listeners, entry);
150 this->mutex->unlock(this->mutex);
151 }
152
153 METHOD(bus_t, remove_listener, void,
154 private_bus_t *this, listener_t *listener)
155 {
156 enumerator_t *enumerator;
157 entry_t *entry;
158
159 this->mutex->lock(this->mutex);
160 enumerator = this->listeners->create_enumerator(this->listeners);
161 while (enumerator->enumerate(enumerator, &entry))
162 {
163 if (entry->listener == listener)
164 {
165 this->listeners->remove_at(this->listeners, enumerator);
166 free(entry);
167 break;
168 }
169 }
170 enumerator->destroy(enumerator);
171 this->mutex->unlock(this->mutex);
172 }
173
174 /**
175 * Register a logger on the given log group according to the requested level
176 */
177 static inline void register_logger(private_bus_t *this, debug_t group,
178 log_entry_t *entry)
179 {
180 enumerator_t *enumerator;
181 linked_list_t *loggers;
182 log_entry_t *current;
183 level_t level;
184
185 loggers = this->loggers[group];
186 level = entry->levels[group];
187
188 enumerator = loggers->create_enumerator(loggers);
189 while (enumerator->enumerate(enumerator, (void**)&current))
190 {
191 if (current->levels[group] <= level)
192 {
193 break;
194 }
195 }
196 loggers->insert_before(loggers, enumerator, entry);
197 enumerator->destroy(enumerator);
198
199 if (entry->logger->log)
200 {
201 set_level(&this->max_level[group], max(this->max_level[group], level));
202 }
203 if (entry->logger->vlog)
204 {
205 set_level(&this->max_vlevel[group],
206 max(this->max_vlevel[group], level));
207 }
208 }
209
210 CALLBACK(find_max_levels, bool,
211 log_entry_t *entry, va_list args)
212 {
213 level_t *level, *vlevel;
214 debug_t group;
215
216 VA_ARGS_VGET(args, group, level, vlevel);
217 if (entry->logger->log && *level == LEVEL_SILENT)
218 {
219 *level = entry->levels[group];
220 }
221 if (entry->logger->vlog && *vlevel == LEVEL_SILENT)
222 {
223 *vlevel = entry->levels[group];
224 }
225 return *level > LEVEL_SILENT && *vlevel > LEVEL_SILENT;
226 }
227
228 /**
229 * Unregister a logger from all log groups (destroys the log_entry_t)
230 */
231 static inline void unregister_logger(private_bus_t *this, logger_t *logger)
232 {
233 enumerator_t *enumerator;
234 linked_list_t *loggers;
235 log_entry_t *entry, *found = NULL;
236 debug_t group;
237
238 loggers = this->loggers[DBG_MAX];
239 enumerator = loggers->create_enumerator(loggers);
240 while (enumerator->enumerate(enumerator, &entry))
241 {
242 if (entry->logger == logger)
243 {
244 loggers->remove_at(loggers, enumerator);
245 found = entry;
246 break;
247 }
248 }
249 enumerator->destroy(enumerator);
250
251 if (found)
252 {
253 for (group = 0; group < DBG_MAX; group++)
254 {
255 if (found->levels[group] > LEVEL_SILENT)
256 {
257 level_t level = LEVEL_SILENT, vlevel = LEVEL_SILENT;
258
259 loggers = this->loggers[group];
260 loggers->remove(loggers, found, NULL);
261 loggers->find_first(loggers, find_max_levels, NULL, group,
262 &level, &vlevel);
263 set_level(&this->max_level[group], level);
264 set_level(&this->max_vlevel[group], vlevel);
265 }
266 }
267 free(found);
268 }
269 }
270
271 METHOD(bus_t, add_logger, void,
272 private_bus_t *this, logger_t *logger)
273 {
274 log_entry_t *entry;
275 debug_t group;
276
277 INIT(entry,
278 .logger = logger,
279 );
280
281 this->log_lock->write_lock(this->log_lock);
282 unregister_logger(this, logger);
283 for (group = 0; group < DBG_MAX; group++)
284 {
285 entry->levels[group] = logger->get_level(logger, group);
286 if (entry->levels[group] > LEVEL_SILENT)
287 {
288 register_logger(this, group, entry);
289 }
290 }
291 this->loggers[DBG_MAX]->insert_last(this->loggers[DBG_MAX], entry);
292 this->log_lock->unlock(this->log_lock);
293 }
294
295 METHOD(bus_t, remove_logger, void,
296 private_bus_t *this, logger_t *logger)
297 {
298 this->log_lock->write_lock(this->log_lock);
299 unregister_logger(this, logger);
300 this->log_lock->unlock(this->log_lock);
301 }
302
303 METHOD(bus_t, set_sa, void,
304 private_bus_t *this, ike_sa_t *ike_sa)
305 {
306 this->thread_sa->set(this->thread_sa, ike_sa);
307 }
308
309 METHOD(bus_t, get_sa, ike_sa_t*,
310 private_bus_t *this)
311 {
312 return this->thread_sa->get(this->thread_sa);
313 }
314
315 /**
316 * data associated to a signal, passed to callback
317 */
318 typedef struct {
319 /** associated IKE_SA */
320 ike_sa_t *ike_sa;
321 /** invoking thread */
322 long thread;
323 /** debug group */
324 debug_t group;
325 /** debug level */
326 level_t level;
327 /** message/fmt */
328 char *message;
329 /** argument list if message is a format string for vlog() */
330 va_list args;
331 } log_data_t;
332
333 CALLBACK(log_cb, void,
334 log_entry_t *entry, va_list args)
335 {
336 log_data_t *data;
337
338 VA_ARGS_VGET(args, data);
339 if (entry->logger->log && entry->levels[data->group] >= data->level)
340 {
341 entry->logger->log(entry->logger, data->group, data->level,
342 data->thread, data->ike_sa, data->message);
343 }
344 }
345
346 CALLBACK(vlog_cb, void,
347 log_entry_t *entry, va_list args)
348 {
349 log_data_t *data;
350
351 VA_ARGS_VGET(args, data);
352 if (entry->logger->vlog && entry->levels[data->group] >= data->level)
353 {
354 va_list copy;
355
356 va_copy(copy, data->args);
357 entry->logger->vlog(entry->logger, data->group, data->level,
358 data->thread, data->ike_sa, data->message, copy);
359 va_end(copy);
360 }
361 }
362
363 METHOD(bus_t, vlog, void,
364 private_bus_t *this, debug_t group, level_t level,
365 char* format, va_list args)
366 {
367 linked_list_t *loggers;
368 log_data_t data;
369
370 /* NOTE: This is not 100% thread-safe and done here only because it is
371 * performance critical. We therefore ignore the following two issues for
372 * this particular case: 1) We might miss some log messages if another
373 * thread concurrently increases the log level or registers a new logger.
374 * 2) We might have to acquire the read lock below even if it wouldn't be
375 * necessary anymore due to another thread concurrently unregistering a
376 * logger or reducing the level. */
377 if (skip_level(&this->max_level[group], level) &&
378 skip_level(&this->max_vlevel[group], level))
379 {
380 return;
381 }
382
383 this->log_lock->read_lock(this->log_lock);
384 loggers = this->loggers[group];
385
386 if (this->max_level[group] >= level)
387 {
388 char buf[1024];
389 ssize_t len;
390
391 data.ike_sa = this->thread_sa->get(this->thread_sa);
392 data.thread = thread_current_id();
393 data.group = group;
394 data.level = level;
395 data.message = buf;
396
397 va_copy(data.args, args);
398 len = vsnprintf(data.message, sizeof(buf), format, data.args);
399 va_end(data.args);
400 if (len >= sizeof(buf))
401 {
402 len++;
403 data.message = malloc(len);
404 va_copy(data.args, args);
405 len = vsnprintf(data.message, len, format, data.args);
406 va_end(data.args);
407 }
408 if (len > 0)
409 {
410 loggers->invoke_function(loggers, log_cb, &data);
411 }
412 if (data.message != buf)
413 {
414 free(data.message);
415 }
416 }
417 if (this->max_vlevel[group] >= level)
418 {
419 data.ike_sa = this->thread_sa->get(this->thread_sa);
420 data.thread = thread_current_id();
421 data.group = group;
422 data.level = level;
423 data.message = format;
424
425 va_copy(data.args, args);
426 loggers->invoke_function(loggers, vlog_cb, &data);
427 va_end(data.args);
428 }
429
430 this->log_lock->unlock(this->log_lock);
431 }
432
433 METHOD(bus_t, log_, void,
434 private_bus_t *this, debug_t group, level_t level, char* format, ...)
435 {
436 va_list args;
437
438 va_start(args, format);
439 vlog(this, group, level, format, args);
440 va_end(args);
441 }
442
443 /**
444 * unregister a listener
445 */
446 static inline void unregister_listener(private_bus_t *this, entry_t *entry,
447 enumerator_t *enumerator)
448 {
449 this->listeners->remove_at(this->listeners, enumerator);
450 free(entry);
451 }
452
453 METHOD(bus_t, alert, void,
454 private_bus_t *this, alert_t alert, ...)
455 {
456 enumerator_t *enumerator;
457 ike_sa_t *ike_sa;
458 entry_t *entry;
459 va_list args;
460 bool keep;
461
462 ike_sa = this->thread_sa->get(this->thread_sa);
463
464 this->mutex->lock(this->mutex);
465 enumerator = this->listeners->create_enumerator(this->listeners);
466 while (enumerator->enumerate(enumerator, &entry))
467 {
468 if (entry->calling || !entry->listener->alert)
469 {
470 continue;
471 }
472 entry->calling++;
473 va_start(args, alert);
474 keep = entry->listener->alert(entry->listener, ike_sa, alert, args);
475 va_end(args);
476 entry->calling--;
477 if (!keep)
478 {
479 unregister_listener(this, entry, enumerator);
480 }
481 }
482 enumerator->destroy(enumerator);
483 this->mutex->unlock(this->mutex);
484 }
485
486 METHOD(bus_t, ike_state_change, void,
487 private_bus_t *this, ike_sa_t *ike_sa, ike_sa_state_t state)
488 {
489 enumerator_t *enumerator;
490 entry_t *entry;
491 bool keep;
492
493 this->mutex->lock(this->mutex);
494 enumerator = this->listeners->create_enumerator(this->listeners);
495 while (enumerator->enumerate(enumerator, &entry))
496 {
497 if (entry->calling || !entry->listener->ike_state_change)
498 {
499 continue;
500 }
501 entry->calling++;
502 keep = entry->listener->ike_state_change(entry->listener, ike_sa, state);
503 entry->calling--;
504 if (!keep)
505 {
506 unregister_listener(this, entry, enumerator);
507 }
508 }
509 enumerator->destroy(enumerator);
510 this->mutex->unlock(this->mutex);
511 }
512
513 METHOD(bus_t, child_state_change, void,
514 private_bus_t *this, child_sa_t *child_sa, child_sa_state_t state)
515 {
516 enumerator_t *enumerator;
517 ike_sa_t *ike_sa;
518 entry_t *entry;
519 bool keep;
520
521 ike_sa = this->thread_sa->get(this->thread_sa);
522
523 this->mutex->lock(this->mutex);
524 enumerator = this->listeners->create_enumerator(this->listeners);
525 while (enumerator->enumerate(enumerator, &entry))
526 {
527 if (entry->calling || !entry->listener->child_state_change)
528 {
529 continue;
530 }
531 entry->calling++;
532 keep = entry->listener->child_state_change(entry->listener, ike_sa,
533 child_sa, state);
534 entry->calling--;
535 if (!keep)
536 {
537 unregister_listener(this, entry, enumerator);
538 }
539 }
540 enumerator->destroy(enumerator);
541 this->mutex->unlock(this->mutex);
542 }
543
544 METHOD(bus_t, message, void,
545 private_bus_t *this, message_t *message, bool incoming, bool plain)
546 {
547 enumerator_t *enumerator;
548 ike_sa_t *ike_sa;
549 entry_t *entry;
550 bool keep;
551
552 ike_sa = this->thread_sa->get(this->thread_sa);
553
554 this->mutex->lock(this->mutex);
555 enumerator = this->listeners->create_enumerator(this->listeners);
556 while (enumerator->enumerate(enumerator, &entry))
557 {
558 if (entry->calling || !entry->listener->message)
559 {
560 continue;
561 }
562 entry->calling++;
563 keep = entry->listener->message(entry->listener, ike_sa,
564 message, incoming, plain);
565 entry->calling--;
566 if (!keep)
567 {
568 unregister_listener(this, entry, enumerator);
569 }
570 }
571 enumerator->destroy(enumerator);
572 this->mutex->unlock(this->mutex);
573 }
574
575 METHOD(bus_t, ike_keys, void,
576 private_bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
577 chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
578 ike_sa_t *rekey, shared_key_t *shared)
579 {
580 enumerator_t *enumerator;
581 entry_t *entry;
582 bool keep;
583
584 this->mutex->lock(this->mutex);
585 enumerator = this->listeners->create_enumerator(this->listeners);
586 while (enumerator->enumerate(enumerator, &entry))
587 {
588 if (entry->calling || !entry->listener->ike_keys)
589 {
590 continue;
591 }
592 entry->calling++;
593 keep = entry->listener->ike_keys(entry->listener, ike_sa, dh, dh_other,
594 nonce_i, nonce_r, rekey, shared);
595 entry->calling--;
596 if (!keep)
597 {
598 unregister_listener(this, entry, enumerator);
599 }
600 }
601 enumerator->destroy(enumerator);
602 this->mutex->unlock(this->mutex);
603 }
604
605 METHOD(bus_t, ike_derived_keys, void,
606 private_bus_t *this, chunk_t sk_ei, chunk_t sk_er, chunk_t sk_ai,
607 chunk_t sk_ar)
608 {
609 enumerator_t *enumerator;
610 ike_sa_t *ike_sa;
611 entry_t *entry;
612 bool keep;
613
614 ike_sa = this->thread_sa->get(this->thread_sa);
615
616 this->mutex->lock(this->mutex);
617 enumerator = this->listeners->create_enumerator(this->listeners);
618 while (enumerator->enumerate(enumerator, &entry))
619 {
620 if (entry->calling || !entry->listener->ike_derived_keys)
621 {
622 continue;
623 }
624 entry->calling++;
625 keep = entry->listener->ike_derived_keys(entry->listener, ike_sa, sk_ei,
626 sk_er, sk_ai, sk_ar);
627 entry->calling--;
628 if (!keep)
629 {
630 unregister_listener(this, entry, enumerator);
631 }
632 }
633 enumerator->destroy(enumerator);
634 this->mutex->unlock(this->mutex);
635 }
636
637 METHOD(bus_t, child_keys, void,
638 private_bus_t *this, child_sa_t *child_sa, bool initiator,
639 diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
640 {
641 enumerator_t *enumerator;
642 ike_sa_t *ike_sa;
643 entry_t *entry;
644 bool keep;
645
646 ike_sa = this->thread_sa->get(this->thread_sa);
647
648 this->mutex->lock(this->mutex);
649 enumerator = this->listeners->create_enumerator(this->listeners);
650 while (enumerator->enumerate(enumerator, &entry))
651 {
652 if (entry->calling || !entry->listener->child_keys)
653 {
654 continue;
655 }
656 entry->calling++;
657 keep = entry->listener->child_keys(entry->listener, ike_sa,
658 child_sa, initiator, dh, nonce_i, nonce_r);
659 entry->calling--;
660 if (!keep)
661 {
662 unregister_listener(this, entry, enumerator);
663 }
664 }
665 enumerator->destroy(enumerator);
666 this->mutex->unlock(this->mutex);
667 }
668
669 METHOD(bus_t, child_derived_keys, void,
670 private_bus_t *this, child_sa_t *child_sa, bool initiator,
671 chunk_t encr_i, chunk_t encr_r, chunk_t integ_i, chunk_t integ_r)
672 {
673 enumerator_t *enumerator;
674 ike_sa_t *ike_sa;
675 entry_t *entry;
676 bool keep;
677
678 ike_sa = this->thread_sa->get(this->thread_sa);
679
680 this->mutex->lock(this->mutex);
681 enumerator = this->listeners->create_enumerator(this->listeners);
682 while (enumerator->enumerate(enumerator, &entry))
683 {
684 if (entry->calling || !entry->listener->child_derived_keys)
685 {
686 continue;
687 }
688 entry->calling++;
689 keep = entry->listener->child_derived_keys(entry->listener, ike_sa,
690 child_sa, initiator, encr_i, encr_r,
691 integ_i, integ_r);
692 entry->calling--;
693 if (!keep)
694 {
695 unregister_listener(this, entry, enumerator);
696 }
697 }
698 enumerator->destroy(enumerator);
699 this->mutex->unlock(this->mutex);
700 }
701
702 METHOD(bus_t, child_updown, void,
703 private_bus_t *this, child_sa_t *child_sa, bool up)
704 {
705 enumerator_t *enumerator;
706 ike_sa_t *ike_sa;
707 entry_t *entry;
708 bool keep;
709
710 ike_sa = this->thread_sa->get(this->thread_sa);
711
712 this->mutex->lock(this->mutex);
713 enumerator = this->listeners->create_enumerator(this->listeners);
714 while (enumerator->enumerate(enumerator, &entry))
715 {
716 if (entry->calling || !entry->listener->child_updown)
717 {
718 continue;
719 }
720 entry->calling++;
721 keep = entry->listener->child_updown(entry->listener,
722 ike_sa, child_sa, up);
723 entry->calling--;
724 if (!keep)
725 {
726 unregister_listener(this, entry, enumerator);
727 }
728 }
729 enumerator->destroy(enumerator);
730 this->mutex->unlock(this->mutex);
731 }
732
733 METHOD(bus_t, child_rekey, void,
734 private_bus_t *this, child_sa_t *old, child_sa_t *new)
735 {
736 enumerator_t *enumerator;
737 ike_sa_t *ike_sa;
738 entry_t *entry;
739 bool keep;
740
741 ike_sa = this->thread_sa->get(this->thread_sa);
742
743 this->mutex->lock(this->mutex);
744 enumerator = this->listeners->create_enumerator(this->listeners);
745 while (enumerator->enumerate(enumerator, &entry))
746 {
747 if (entry->calling || !entry->listener->child_rekey)
748 {
749 continue;
750 }
751 entry->calling++;
752 keep = entry->listener->child_rekey(entry->listener, ike_sa,
753 old, new);
754 entry->calling--;
755 if (!keep)
756 {
757 unregister_listener(this, entry, enumerator);
758 }
759 }
760 enumerator->destroy(enumerator);
761 this->mutex->unlock(this->mutex);
762 }
763
764 METHOD(bus_t, children_migrate, void,
765 private_bus_t *this, ike_sa_id_t *new, uint32_t unique)
766 {
767 enumerator_t *enumerator;
768 ike_sa_t *ike_sa;
769 entry_t *entry;
770 bool keep;
771
772 ike_sa = this->thread_sa->get(this->thread_sa);
773
774 this->mutex->lock(this->mutex);
775 enumerator = this->listeners->create_enumerator(this->listeners);
776 while (enumerator->enumerate(enumerator, &entry))
777 {
778 if (entry->calling || !entry->listener->children_migrate)
779 {
780 continue;
781 }
782 entry->calling++;
783 keep = entry->listener->children_migrate(entry->listener, ike_sa, new,
784 unique);
785 entry->calling--;
786 if (!keep)
787 {
788 unregister_listener(this, entry, enumerator);
789 }
790 }
791 enumerator->destroy(enumerator);
792 this->mutex->unlock(this->mutex);
793 }
794
795 METHOD(bus_t, ike_updown, void,
796 private_bus_t *this, ike_sa_t *ike_sa, bool up)
797 {
798 enumerator_t *enumerator;
799 entry_t *entry;
800 bool keep;
801
802 this->mutex->lock(this->mutex);
803 enumerator = this->listeners->create_enumerator(this->listeners);
804 while (enumerator->enumerate(enumerator, &entry))
805 {
806 if (entry->calling || !entry->listener->ike_updown)
807 {
808 continue;
809 }
810 entry->calling++;
811 keep = entry->listener->ike_updown(entry->listener, ike_sa, up);
812 entry->calling--;
813 if (!keep)
814 {
815 unregister_listener(this, entry, enumerator);
816 }
817 }
818 enumerator->destroy(enumerator);
819 this->mutex->unlock(this->mutex);
820
821 /* a down event for IKE_SA implicitly downs all CHILD_SAs */
822 if (!up)
823 {
824 enumerator_t *enumerator;
825 child_sa_t *child_sa;
826
827 enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
828 while (enumerator->enumerate(enumerator, (void**)&child_sa))
829 {
830 if (child_sa->get_state(child_sa) != CHILD_REKEYED &&
831 child_sa->get_state(child_sa) != CHILD_DELETED)
832 {
833 child_updown(this, child_sa, FALSE);
834 }
835 }
836 enumerator->destroy(enumerator);
837 }
838 }
839
840 METHOD(bus_t, ike_rekey, void,
841 private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
842 {
843 enumerator_t *enumerator;
844 entry_t *entry;
845 bool keep;
846
847 this->mutex->lock(this->mutex);
848 enumerator = this->listeners->create_enumerator(this->listeners);
849 while (enumerator->enumerate(enumerator, &entry))
850 {
851 if (entry->calling || !entry->listener->ike_rekey)
852 {
853 continue;
854 }
855 entry->calling++;
856 keep = entry->listener->ike_rekey(entry->listener, old, new);
857 entry->calling--;
858 if (!keep)
859 {
860 unregister_listener(this, entry, enumerator);
861 }
862 }
863 enumerator->destroy(enumerator);
864 this->mutex->unlock(this->mutex);
865 }
866
867 METHOD(bus_t, ike_update, void,
868 private_bus_t *this, ike_sa_t *ike_sa, bool local, host_t *new)
869 {
870 enumerator_t *enumerator;
871 entry_t *entry;
872 bool keep;
873
874 this->mutex->lock(this->mutex);
875 enumerator = this->listeners->create_enumerator(this->listeners);
876 while (enumerator->enumerate(enumerator, &entry))
877 {
878 if (entry->calling || !entry->listener->ike_update)
879 {
880 continue;
881 }
882 entry->calling++;
883 keep = entry->listener->ike_update(entry->listener, ike_sa, local, new);
884 entry->calling--;
885 if (!keep)
886 {
887 unregister_listener(this, entry, enumerator);
888 }
889 }
890 enumerator->destroy(enumerator);
891 this->mutex->unlock(this->mutex);
892 }
893
894 METHOD(bus_t, ike_reestablish_pre, void,
895 private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
896 {
897 enumerator_t *enumerator;
898 entry_t *entry;
899 bool keep;
900
901 this->mutex->lock(this->mutex);
902 enumerator = this->listeners->create_enumerator(this->listeners);
903 while (enumerator->enumerate(enumerator, &entry))
904 {
905 if (entry->calling || !entry->listener->ike_reestablish_pre)
906 {
907 continue;
908 }
909 entry->calling++;
910 keep = entry->listener->ike_reestablish_pre(entry->listener, old, new);
911 entry->calling--;
912 if (!keep)
913 {
914 unregister_listener(this, entry, enumerator);
915 }
916 }
917 enumerator->destroy(enumerator);
918 this->mutex->unlock(this->mutex);
919 }
920
921 METHOD(bus_t, ike_reestablish_post, void,
922 private_bus_t *this, ike_sa_t *old, ike_sa_t *new, bool initiated)
923 {
924 enumerator_t *enumerator;
925 entry_t *entry;
926 bool keep;
927
928 this->mutex->lock(this->mutex);
929 enumerator = this->listeners->create_enumerator(this->listeners);
930 while (enumerator->enumerate(enumerator, &entry))
931 {
932 if (entry->calling || !entry->listener->ike_reestablish_post)
933 {
934 continue;
935 }
936 entry->calling++;
937 keep = entry->listener->ike_reestablish_post(entry->listener, old, new,
938 initiated);
939 entry->calling--;
940 if (!keep)
941 {
942 unregister_listener(this, entry, enumerator);
943 }
944 }
945 enumerator->destroy(enumerator);
946 this->mutex->unlock(this->mutex);
947 }
948
949 METHOD(bus_t, authorize, bool,
950 private_bus_t *this, bool final)
951 {
952 enumerator_t *enumerator;
953 ike_sa_t *ike_sa;
954 entry_t *entry;
955 bool keep, success = TRUE;
956
957 ike_sa = this->thread_sa->get(this->thread_sa);
958
959 this->mutex->lock(this->mutex);
960 enumerator = this->listeners->create_enumerator(this->listeners);
961 while (enumerator->enumerate(enumerator, &entry))
962 {
963 if (entry->calling || !entry->listener->authorize)
964 {
965 continue;
966 }
967 entry->calling++;
968 keep = entry->listener->authorize(entry->listener, ike_sa,
969 final, &success);
970 entry->calling--;
971 if (!keep)
972 {
973 unregister_listener(this, entry, enumerator);
974 }
975 if (!success)
976 {
977 break;
978 }
979 }
980 enumerator->destroy(enumerator);
981 this->mutex->unlock(this->mutex);
982 if (!success)
983 {
984 alert(this, ALERT_AUTHORIZATION_FAILED);
985 }
986 return success;
987 }
988
989 METHOD(bus_t, narrow, void,
990 private_bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
991 linked_list_t *local, linked_list_t *remote)
992 {
993 enumerator_t *enumerator;
994 ike_sa_t *ike_sa;
995 entry_t *entry;
996 bool keep;
997
998 ike_sa = this->thread_sa->get(this->thread_sa);
999
1000 this->mutex->lock(this->mutex);
1001 enumerator = this->listeners->create_enumerator(this->listeners);
1002 while (enumerator->enumerate(enumerator, &entry))
1003 {
1004 if (entry->calling || !entry->listener->narrow)
1005 {
1006 continue;
1007 }
1008 entry->calling++;
1009 keep = entry->listener->narrow(entry->listener, ike_sa, child_sa,
1010 type, local, remote);
1011 entry->calling--;
1012 if (!keep)
1013 {
1014 unregister_listener(this, entry, enumerator);
1015 }
1016 }
1017 enumerator->destroy(enumerator);
1018 this->mutex->unlock(this->mutex);
1019 }
1020
1021 METHOD(bus_t, assign_vips, void,
1022 private_bus_t *this, ike_sa_t *ike_sa, bool assign)
1023 {
1024 enumerator_t *enumerator;
1025 entry_t *entry;
1026 bool keep;
1027
1028 this->mutex->lock(this->mutex);
1029 enumerator = this->listeners->create_enumerator(this->listeners);
1030 while (enumerator->enumerate(enumerator, &entry))
1031 {
1032 if (entry->calling || !entry->listener->assign_vips)
1033 {
1034 continue;
1035 }
1036 entry->calling++;
1037 keep = entry->listener->assign_vips(entry->listener, ike_sa, assign);
1038 entry->calling--;
1039 if (!keep)
1040 {
1041 unregister_listener(this, entry, enumerator);
1042 }
1043 }
1044 enumerator->destroy(enumerator);
1045 this->mutex->unlock(this->mutex);
1046 }
1047
1048 METHOD(bus_t, handle_vips, void,
1049 private_bus_t *this, ike_sa_t *ike_sa, bool handle)
1050 {
1051 enumerator_t *enumerator;
1052 entry_t *entry;
1053 bool keep;
1054
1055 this->mutex->lock(this->mutex);
1056 enumerator = this->listeners->create_enumerator(this->listeners);
1057 while (enumerator->enumerate(enumerator, &entry))
1058 {
1059 if (entry->calling || !entry->listener->handle_vips)
1060 {
1061 continue;
1062 }
1063 entry->calling++;
1064 keep = entry->listener->handle_vips(entry->listener, ike_sa, handle);
1065 entry->calling--;
1066 if (!keep)
1067 {
1068 unregister_listener(this, entry, enumerator);
1069 }
1070 }
1071 enumerator->destroy(enumerator);
1072 this->mutex->unlock(this->mutex);
1073 }
1074
1075 /**
1076 * Credential manager hook function to forward bus alerts
1077 */
1078 static void hook_creds(private_bus_t *this, credential_hook_type_t type,
1079 certificate_t *cert)
1080 {
1081 switch (type)
1082 {
1083 case CRED_HOOK_EXPIRED:
1084 return alert(this, ALERT_CERT_EXPIRED, cert);
1085 case CRED_HOOK_REVOKED:
1086 return alert(this, ALERT_CERT_REVOKED, cert);
1087 case CRED_HOOK_VALIDATION_FAILED:
1088 return alert(this, ALERT_CERT_VALIDATION_FAILED, cert);
1089 case CRED_HOOK_NO_ISSUER:
1090 return alert(this, ALERT_CERT_NO_ISSUER, cert);
1091 case CRED_HOOK_UNTRUSTED_ROOT:
1092 return alert(this, ALERT_CERT_UNTRUSTED_ROOT, cert);
1093 case CRED_HOOK_EXCEEDED_PATH_LEN:
1094 return alert(this, ALERT_CERT_EXCEEDED_PATH_LEN, cert);
1095 case CRED_HOOK_POLICY_VIOLATION:
1096 return alert(this, ALERT_CERT_POLICY_VIOLATION, cert);
1097 }
1098 }
1099
1100 METHOD(bus_t, destroy, void,
1101 private_bus_t *this)
1102 {
1103 debug_t group;
1104
1105 lib->credmgr->set_hook(lib->credmgr, NULL, NULL);
1106 for (group = 0; group < DBG_MAX; group++)
1107 {
1108 this->loggers[group]->destroy(this->loggers[group]);
1109 }
1110 this->loggers[DBG_MAX]->destroy_function(this->loggers[DBG_MAX],
1111 (void*)free);
1112 this->listeners->destroy_function(this->listeners, (void*)free);
1113 this->thread_sa->destroy(this->thread_sa);
1114 this->log_lock->destroy(this->log_lock);
1115 this->mutex->destroy(this->mutex);
1116 free(this);
1117 }
1118
1119 /*
1120 * Described in header.
1121 */
1122 bus_t *bus_create()
1123 {
1124 private_bus_t *this;
1125 debug_t group;
1126
1127 INIT(this,
1128 .public = {
1129 .add_listener = _add_listener,
1130 .remove_listener = _remove_listener,
1131 .add_logger = _add_logger,
1132 .remove_logger = _remove_logger,
1133 .set_sa = _set_sa,
1134 .get_sa = _get_sa,
1135 .log = _log_,
1136 .vlog = _vlog,
1137 .alert = _alert,
1138 .ike_state_change = _ike_state_change,
1139 .child_state_change = _child_state_change,
1140 .message = _message,
1141 .ike_keys = _ike_keys,
1142 .ike_derived_keys = _ike_derived_keys,
1143 .child_keys = _child_keys,
1144 .child_derived_keys = _child_derived_keys,
1145 .ike_updown = _ike_updown,
1146 .ike_rekey = _ike_rekey,
1147 .ike_update = _ike_update,
1148 .ike_reestablish_pre = _ike_reestablish_pre,
1149 .ike_reestablish_post = _ike_reestablish_post,
1150 .child_updown = _child_updown,
1151 .child_rekey = _child_rekey,
1152 .children_migrate = _children_migrate,
1153 .authorize = _authorize,
1154 .narrow = _narrow,
1155 .assign_vips = _assign_vips,
1156 .handle_vips = _handle_vips,
1157 .destroy = _destroy,
1158 },
1159 .listeners = linked_list_create(),
1160 .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
1161 .log_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
1162 .thread_sa = thread_value_create(NULL),
1163 );
1164
1165 for (group = 0; group <= DBG_MAX; group++)
1166 {
1167 this->loggers[group] = linked_list_create();
1168 this->max_level[group] = LEVEL_SILENT;
1169 this->max_vlevel[group] = LEVEL_SILENT;
1170 }
1171
1172 lib->credmgr->set_hook(lib->credmgr, (credential_hook_t)hook_creds, this);
1173
1174 return &this->public;
1175 }