stroke: Allow specifying the ipsec.secrets location in strongswan.conf
[strongswan.git] / src / libcharon / bus / bus.c
1 /*
2 * Copyright (C) 2011-2014 Tobias Brunner
3 * Copyright (C) 2006 Martin Willi
4 * 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 /**
211 * Unregister a logger from all log groups (destroys the log_entry_t)
212 */
213 static inline void unregister_logger(private_bus_t *this, logger_t *logger)
214 {
215 enumerator_t *enumerator;
216 linked_list_t *loggers;
217 log_entry_t *entry, *found = NULL;
218
219 loggers = this->loggers[DBG_MAX];
220 enumerator = loggers->create_enumerator(loggers);
221 while (enumerator->enumerate(enumerator, &entry))
222 {
223 if (entry->logger == logger)
224 {
225 loggers->remove_at(loggers, enumerator);
226 found = entry;
227 break;
228 }
229 }
230 enumerator->destroy(enumerator);
231
232 if (found)
233 {
234 level_t level = LEVEL_SILENT, vlevel = LEVEL_SILENT;
235 debug_t group;
236
237 for (group = 0; group < DBG_MAX; group++)
238 {
239 if (found->levels[group] > LEVEL_SILENT)
240 {
241 loggers = this->loggers[group];
242 loggers->remove(loggers, found, NULL);
243
244 if (loggers->get_first(loggers, (void**)&entry) == SUCCESS)
245 {
246 if (entry->logger->log)
247 {
248 level = entry->levels[group];
249 }
250 if (entry->logger->vlog)
251 {
252 vlevel = entry->levels[group];
253 }
254 }
255 set_level(&this->max_level[group], level);
256 set_level(&this->max_vlevel[group], vlevel);
257 }
258 }
259 free(found);
260 }
261 }
262
263 METHOD(bus_t, add_logger, void,
264 private_bus_t *this, logger_t *logger)
265 {
266 log_entry_t *entry;
267 debug_t group;
268
269 INIT(entry,
270 .logger = logger,
271 );
272
273 this->log_lock->write_lock(this->log_lock);
274 unregister_logger(this, logger);
275 for (group = 0; group < DBG_MAX; group++)
276 {
277 entry->levels[group] = logger->get_level(logger, group);
278 if (entry->levels[group] > LEVEL_SILENT)
279 {
280 register_logger(this, group, entry);
281 }
282 }
283 this->loggers[DBG_MAX]->insert_last(this->loggers[DBG_MAX], entry);
284 this->log_lock->unlock(this->log_lock);
285 }
286
287 METHOD(bus_t, remove_logger, void,
288 private_bus_t *this, logger_t *logger)
289 {
290 this->log_lock->write_lock(this->log_lock);
291 unregister_logger(this, logger);
292 this->log_lock->unlock(this->log_lock);
293 }
294
295 METHOD(bus_t, set_sa, void,
296 private_bus_t *this, ike_sa_t *ike_sa)
297 {
298 this->thread_sa->set(this->thread_sa, ike_sa);
299 }
300
301 METHOD(bus_t, get_sa, ike_sa_t*,
302 private_bus_t *this)
303 {
304 return this->thread_sa->get(this->thread_sa);
305 }
306
307 /**
308 * data associated to a signal, passed to callback
309 */
310 typedef struct {
311 /** associated IKE_SA */
312 ike_sa_t *ike_sa;
313 /** invoking thread */
314 long thread;
315 /** debug group */
316 debug_t group;
317 /** debug level */
318 level_t level;
319 /** message/fmt */
320 char *message;
321 /** argument list if message is a format string for vlog() */
322 va_list args;
323 } log_data_t;
324
325 /**
326 * logger->log() invocation as a invoke_function callback
327 */
328 static void log_cb(log_entry_t *entry, log_data_t *data)
329 {
330 if (entry->logger->log && entry->levels[data->group] >= data->level)
331 {
332 entry->logger->log(entry->logger, data->group, data->level,
333 data->thread, data->ike_sa, data->message);
334 }
335 }
336
337 /**
338 * logger->vlog() invocation as a invoke_function callback
339 */
340 static void vlog_cb(log_entry_t *entry, log_data_t *data)
341 {
342 if (entry->logger->vlog && entry->levels[data->group] >= data->level)
343 {
344 va_list copy;
345
346 va_copy(copy, data->args);
347 entry->logger->vlog(entry->logger, data->group, data->level,
348 data->thread, data->ike_sa, data->message, copy);
349 va_end(copy);
350 }
351 }
352
353 METHOD(bus_t, vlog, void,
354 private_bus_t *this, debug_t group, level_t level,
355 char* format, va_list args)
356 {
357 linked_list_t *loggers;
358 log_data_t data;
359
360 /* NOTE: This is not 100% thread-safe and done here only because it is
361 * performance critical. We therefore ignore the following two issues for
362 * this particular case: 1) We might miss some log messages if another
363 * thread concurrently increases the log level or registers a new logger.
364 * 2) We might have to acquire the read lock below even if it wouldn't be
365 * necessary anymore due to another thread concurrently unregistering a
366 * logger or reducing the level. */
367 if (skip_level(&this->max_level[group], level) &&
368 skip_level(&this->max_vlevel[group], level))
369 {
370 return;
371 }
372
373 this->log_lock->read_lock(this->log_lock);
374 loggers = this->loggers[group];
375
376 if (this->max_level[group] >= level)
377 {
378 char buf[1024];
379 ssize_t len;
380
381 data.ike_sa = this->thread_sa->get(this->thread_sa);
382 data.thread = thread_current_id();
383 data.group = group;
384 data.level = level;
385 data.message = buf;
386
387 va_copy(data.args, args);
388 len = vsnprintf(data.message, sizeof(buf), format, data.args);
389 va_end(data.args);
390 if (len >= sizeof(buf))
391 {
392 len++;
393 data.message = malloc(len);
394 va_copy(data.args, args);
395 len = vsnprintf(data.message, len, format, data.args);
396 va_end(data.args);
397 }
398 if (len > 0)
399 {
400 loggers->invoke_function(loggers, (linked_list_invoke_t)log_cb,
401 &data);
402 }
403 if (data.message != buf)
404 {
405 free(data.message);
406 }
407 }
408 if (this->max_vlevel[group] >= level)
409 {
410 data.ike_sa = this->thread_sa->get(this->thread_sa);
411 data.thread = thread_current_id();
412 data.group = group;
413 data.level = level;
414 data.message = format;
415
416 va_copy(data.args, args);
417 loggers->invoke_function(loggers, (linked_list_invoke_t)vlog_cb, &data);
418 va_end(data.args);
419 }
420
421 this->log_lock->unlock(this->log_lock);
422 }
423
424 METHOD(bus_t, log_, void,
425 private_bus_t *this, debug_t group, level_t level, char* format, ...)
426 {
427 va_list args;
428
429 va_start(args, format);
430 vlog(this, group, level, format, args);
431 va_end(args);
432 }
433
434 /**
435 * unregister a listener
436 */
437 static inline void unregister_listener(private_bus_t *this, entry_t *entry,
438 enumerator_t *enumerator)
439 {
440 this->listeners->remove_at(this->listeners, enumerator);
441 free(entry);
442 }
443
444 METHOD(bus_t, alert, void,
445 private_bus_t *this, alert_t alert, ...)
446 {
447 enumerator_t *enumerator;
448 ike_sa_t *ike_sa;
449 entry_t *entry;
450 va_list args;
451 bool keep;
452
453 ike_sa = this->thread_sa->get(this->thread_sa);
454
455 this->mutex->lock(this->mutex);
456 enumerator = this->listeners->create_enumerator(this->listeners);
457 while (enumerator->enumerate(enumerator, &entry))
458 {
459 if (entry->calling || !entry->listener->alert)
460 {
461 continue;
462 }
463 entry->calling++;
464 va_start(args, alert);
465 keep = entry->listener->alert(entry->listener, ike_sa, alert, args);
466 va_end(args);
467 entry->calling--;
468 if (!keep)
469 {
470 unregister_listener(this, entry, enumerator);
471 }
472 }
473 enumerator->destroy(enumerator);
474 this->mutex->unlock(this->mutex);
475 }
476
477 METHOD(bus_t, ike_state_change, void,
478 private_bus_t *this, ike_sa_t *ike_sa, ike_sa_state_t state)
479 {
480 enumerator_t *enumerator;
481 entry_t *entry;
482 bool keep;
483
484 this->mutex->lock(this->mutex);
485 enumerator = this->listeners->create_enumerator(this->listeners);
486 while (enumerator->enumerate(enumerator, &entry))
487 {
488 if (entry->calling || !entry->listener->ike_state_change)
489 {
490 continue;
491 }
492 entry->calling++;
493 keep = entry->listener->ike_state_change(entry->listener, ike_sa, state);
494 entry->calling--;
495 if (!keep)
496 {
497 unregister_listener(this, entry, enumerator);
498 }
499 }
500 enumerator->destroy(enumerator);
501 this->mutex->unlock(this->mutex);
502 }
503
504 METHOD(bus_t, child_state_change, void,
505 private_bus_t *this, child_sa_t *child_sa, child_sa_state_t state)
506 {
507 enumerator_t *enumerator;
508 ike_sa_t *ike_sa;
509 entry_t *entry;
510 bool keep;
511
512 ike_sa = this->thread_sa->get(this->thread_sa);
513
514 this->mutex->lock(this->mutex);
515 enumerator = this->listeners->create_enumerator(this->listeners);
516 while (enumerator->enumerate(enumerator, &entry))
517 {
518 if (entry->calling || !entry->listener->child_state_change)
519 {
520 continue;
521 }
522 entry->calling++;
523 keep = entry->listener->child_state_change(entry->listener, ike_sa,
524 child_sa, state);
525 entry->calling--;
526 if (!keep)
527 {
528 unregister_listener(this, entry, enumerator);
529 }
530 }
531 enumerator->destroy(enumerator);
532 this->mutex->unlock(this->mutex);
533 }
534
535 METHOD(bus_t, message, void,
536 private_bus_t *this, message_t *message, bool incoming, bool plain)
537 {
538 enumerator_t *enumerator;
539 ike_sa_t *ike_sa;
540 entry_t *entry;
541 bool keep;
542
543 ike_sa = this->thread_sa->get(this->thread_sa);
544
545 this->mutex->lock(this->mutex);
546 enumerator = this->listeners->create_enumerator(this->listeners);
547 while (enumerator->enumerate(enumerator, &entry))
548 {
549 if (entry->calling || !entry->listener->message)
550 {
551 continue;
552 }
553 entry->calling++;
554 keep = entry->listener->message(entry->listener, ike_sa,
555 message, incoming, plain);
556 entry->calling--;
557 if (!keep)
558 {
559 unregister_listener(this, entry, enumerator);
560 }
561 }
562 enumerator->destroy(enumerator);
563 this->mutex->unlock(this->mutex);
564 }
565
566 METHOD(bus_t, ike_keys, void,
567 private_bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
568 chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
569 ike_sa_t *rekey, shared_key_t *shared)
570 {
571 enumerator_t *enumerator;
572 entry_t *entry;
573 bool keep;
574
575 this->mutex->lock(this->mutex);
576 enumerator = this->listeners->create_enumerator(this->listeners);
577 while (enumerator->enumerate(enumerator, &entry))
578 {
579 if (entry->calling || !entry->listener->ike_keys)
580 {
581 continue;
582 }
583 entry->calling++;
584 keep = entry->listener->ike_keys(entry->listener, ike_sa, dh, dh_other,
585 nonce_i, nonce_r, rekey, shared);
586 entry->calling--;
587 if (!keep)
588 {
589 unregister_listener(this, entry, enumerator);
590 }
591 }
592 enumerator->destroy(enumerator);
593 this->mutex->unlock(this->mutex);
594 }
595
596 METHOD(bus_t, child_keys, void,
597 private_bus_t *this, child_sa_t *child_sa, bool initiator,
598 diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
599 {
600 enumerator_t *enumerator;
601 ike_sa_t *ike_sa;
602 entry_t *entry;
603 bool keep;
604
605 ike_sa = this->thread_sa->get(this->thread_sa);
606
607 this->mutex->lock(this->mutex);
608 enumerator = this->listeners->create_enumerator(this->listeners);
609 while (enumerator->enumerate(enumerator, &entry))
610 {
611 if (entry->calling || !entry->listener->child_keys)
612 {
613 continue;
614 }
615 entry->calling++;
616 keep = entry->listener->child_keys(entry->listener, ike_sa,
617 child_sa, initiator, dh, nonce_i, nonce_r);
618 entry->calling--;
619 if (!keep)
620 {
621 unregister_listener(this, entry, enumerator);
622 }
623 }
624 enumerator->destroy(enumerator);
625 this->mutex->unlock(this->mutex);
626 }
627
628 METHOD(bus_t, child_updown, void,
629 private_bus_t *this, child_sa_t *child_sa, bool up)
630 {
631 enumerator_t *enumerator;
632 ike_sa_t *ike_sa;
633 entry_t *entry;
634 bool keep;
635
636 ike_sa = this->thread_sa->get(this->thread_sa);
637
638 this->mutex->lock(this->mutex);
639 enumerator = this->listeners->create_enumerator(this->listeners);
640 while (enumerator->enumerate(enumerator, &entry))
641 {
642 if (entry->calling || !entry->listener->child_updown)
643 {
644 continue;
645 }
646 entry->calling++;
647 keep = entry->listener->child_updown(entry->listener,
648 ike_sa, child_sa, up);
649 entry->calling--;
650 if (!keep)
651 {
652 unregister_listener(this, entry, enumerator);
653 }
654 }
655 enumerator->destroy(enumerator);
656 this->mutex->unlock(this->mutex);
657 }
658
659 METHOD(bus_t, child_rekey, void,
660 private_bus_t *this, child_sa_t *old, child_sa_t *new)
661 {
662 enumerator_t *enumerator;
663 ike_sa_t *ike_sa;
664 entry_t *entry;
665 bool keep;
666
667 ike_sa = this->thread_sa->get(this->thread_sa);
668
669 this->mutex->lock(this->mutex);
670 enumerator = this->listeners->create_enumerator(this->listeners);
671 while (enumerator->enumerate(enumerator, &entry))
672 {
673 if (entry->calling || !entry->listener->child_rekey)
674 {
675 continue;
676 }
677 entry->calling++;
678 keep = entry->listener->child_rekey(entry->listener, ike_sa,
679 old, new);
680 entry->calling--;
681 if (!keep)
682 {
683 unregister_listener(this, entry, enumerator);
684 }
685 }
686 enumerator->destroy(enumerator);
687 this->mutex->unlock(this->mutex);
688 }
689
690 METHOD(bus_t, ike_updown, void,
691 private_bus_t *this, ike_sa_t *ike_sa, bool up)
692 {
693 enumerator_t *enumerator;
694 entry_t *entry;
695 bool keep;
696
697 this->mutex->lock(this->mutex);
698 enumerator = this->listeners->create_enumerator(this->listeners);
699 while (enumerator->enumerate(enumerator, &entry))
700 {
701 if (entry->calling || !entry->listener->ike_updown)
702 {
703 continue;
704 }
705 entry->calling++;
706 keep = entry->listener->ike_updown(entry->listener, ike_sa, up);
707 entry->calling--;
708 if (!keep)
709 {
710 unregister_listener(this, entry, enumerator);
711 }
712 }
713 enumerator->destroy(enumerator);
714 this->mutex->unlock(this->mutex);
715
716 /* a down event for IKE_SA implicitly downs all CHILD_SAs */
717 if (!up)
718 {
719 enumerator_t *enumerator;
720 child_sa_t *child_sa;
721
722 enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
723 while (enumerator->enumerate(enumerator, (void**)&child_sa))
724 {
725 child_updown(this, child_sa, FALSE);
726 }
727 enumerator->destroy(enumerator);
728 }
729 }
730
731 METHOD(bus_t, ike_rekey, void,
732 private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
733 {
734 enumerator_t *enumerator;
735 entry_t *entry;
736 bool keep;
737
738 this->mutex->lock(this->mutex);
739 enumerator = this->listeners->create_enumerator(this->listeners);
740 while (enumerator->enumerate(enumerator, &entry))
741 {
742 if (entry->calling || !entry->listener->ike_rekey)
743 {
744 continue;
745 }
746 entry->calling++;
747 keep = entry->listener->ike_rekey(entry->listener, old, new);
748 entry->calling--;
749 if (!keep)
750 {
751 unregister_listener(this, entry, enumerator);
752 }
753 }
754 enumerator->destroy(enumerator);
755 this->mutex->unlock(this->mutex);
756 }
757
758 METHOD(bus_t, ike_reestablish_pre, void,
759 private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
760 {
761 enumerator_t *enumerator;
762 entry_t *entry;
763 bool keep;
764
765 this->mutex->lock(this->mutex);
766 enumerator = this->listeners->create_enumerator(this->listeners);
767 while (enumerator->enumerate(enumerator, &entry))
768 {
769 if (entry->calling || !entry->listener->ike_reestablish_pre)
770 {
771 continue;
772 }
773 entry->calling++;
774 keep = entry->listener->ike_reestablish_pre(entry->listener, old, new);
775 entry->calling--;
776 if (!keep)
777 {
778 unregister_listener(this, entry, enumerator);
779 }
780 }
781 enumerator->destroy(enumerator);
782 this->mutex->unlock(this->mutex);
783 }
784
785 METHOD(bus_t, ike_reestablish_post, void,
786 private_bus_t *this, ike_sa_t *old, ike_sa_t *new, bool initiated)
787 {
788 enumerator_t *enumerator;
789 entry_t *entry;
790 bool keep;
791
792 this->mutex->lock(this->mutex);
793 enumerator = this->listeners->create_enumerator(this->listeners);
794 while (enumerator->enumerate(enumerator, &entry))
795 {
796 if (entry->calling || !entry->listener->ike_reestablish_post)
797 {
798 continue;
799 }
800 entry->calling++;
801 keep = entry->listener->ike_reestablish_post(entry->listener, old, new,
802 initiated);
803 entry->calling--;
804 if (!keep)
805 {
806 unregister_listener(this, entry, enumerator);
807 }
808 }
809 enumerator->destroy(enumerator);
810 this->mutex->unlock(this->mutex);
811 }
812
813 METHOD(bus_t, authorize, bool,
814 private_bus_t *this, bool final)
815 {
816 enumerator_t *enumerator;
817 ike_sa_t *ike_sa;
818 entry_t *entry;
819 bool keep, success = TRUE;
820
821 ike_sa = this->thread_sa->get(this->thread_sa);
822
823 this->mutex->lock(this->mutex);
824 enumerator = this->listeners->create_enumerator(this->listeners);
825 while (enumerator->enumerate(enumerator, &entry))
826 {
827 if (entry->calling || !entry->listener->authorize)
828 {
829 continue;
830 }
831 entry->calling++;
832 keep = entry->listener->authorize(entry->listener, ike_sa,
833 final, &success);
834 entry->calling--;
835 if (!keep)
836 {
837 unregister_listener(this, entry, enumerator);
838 }
839 if (!success)
840 {
841 break;
842 }
843 }
844 enumerator->destroy(enumerator);
845 this->mutex->unlock(this->mutex);
846 if (!success)
847 {
848 alert(this, ALERT_AUTHORIZATION_FAILED);
849 }
850 return success;
851 }
852
853 METHOD(bus_t, narrow, void,
854 private_bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
855 linked_list_t *local, linked_list_t *remote)
856 {
857 enumerator_t *enumerator;
858 ike_sa_t *ike_sa;
859 entry_t *entry;
860 bool keep;
861
862 ike_sa = this->thread_sa->get(this->thread_sa);
863
864 this->mutex->lock(this->mutex);
865 enumerator = this->listeners->create_enumerator(this->listeners);
866 while (enumerator->enumerate(enumerator, &entry))
867 {
868 if (entry->calling || !entry->listener->narrow)
869 {
870 continue;
871 }
872 entry->calling++;
873 keep = entry->listener->narrow(entry->listener, ike_sa, child_sa,
874 type, local, remote);
875 entry->calling--;
876 if (!keep)
877 {
878 unregister_listener(this, entry, enumerator);
879 }
880 }
881 enumerator->destroy(enumerator);
882 this->mutex->unlock(this->mutex);
883 }
884
885 METHOD(bus_t, assign_vips, void,
886 private_bus_t *this, ike_sa_t *ike_sa, bool assign)
887 {
888 enumerator_t *enumerator;
889 entry_t *entry;
890 bool keep;
891
892 this->mutex->lock(this->mutex);
893 enumerator = this->listeners->create_enumerator(this->listeners);
894 while (enumerator->enumerate(enumerator, &entry))
895 {
896 if (entry->calling || !entry->listener->assign_vips)
897 {
898 continue;
899 }
900 entry->calling++;
901 keep = entry->listener->assign_vips(entry->listener, ike_sa, assign);
902 entry->calling--;
903 if (!keep)
904 {
905 unregister_listener(this, entry, enumerator);
906 }
907 }
908 enumerator->destroy(enumerator);
909 this->mutex->unlock(this->mutex);
910 }
911
912 METHOD(bus_t, handle_vips, void,
913 private_bus_t *this, ike_sa_t *ike_sa, bool handle)
914 {
915 enumerator_t *enumerator;
916 entry_t *entry;
917 bool keep;
918
919 this->mutex->lock(this->mutex);
920 enumerator = this->listeners->create_enumerator(this->listeners);
921 while (enumerator->enumerate(enumerator, &entry))
922 {
923 if (entry->calling || !entry->listener->handle_vips)
924 {
925 continue;
926 }
927 entry->calling++;
928 keep = entry->listener->handle_vips(entry->listener, ike_sa, handle);
929 entry->calling--;
930 if (!keep)
931 {
932 unregister_listener(this, entry, enumerator);
933 }
934 }
935 enumerator->destroy(enumerator);
936 this->mutex->unlock(this->mutex);
937 }
938
939 /**
940 * Credential manager hook function to forward bus alerts
941 */
942 static void hook_creds(private_bus_t *this, credential_hook_type_t type,
943 certificate_t *cert)
944 {
945 switch (type)
946 {
947 case CRED_HOOK_EXPIRED:
948 return alert(this, ALERT_CERT_EXPIRED, cert);
949 case CRED_HOOK_REVOKED:
950 return alert(this, ALERT_CERT_REVOKED, cert);
951 case CRED_HOOK_VALIDATION_FAILED:
952 return alert(this, ALERT_CERT_VALIDATION_FAILED, cert);
953 case CRED_HOOK_NO_ISSUER:
954 return alert(this, ALERT_CERT_NO_ISSUER, cert);
955 case CRED_HOOK_UNTRUSTED_ROOT:
956 return alert(this, ALERT_CERT_UNTRUSTED_ROOT, cert);
957 case CRED_HOOK_EXCEEDED_PATH_LEN:
958 return alert(this, ALERT_CERT_EXCEEDED_PATH_LEN, cert);
959 case CRED_HOOK_POLICY_VIOLATION:
960 return alert(this, ALERT_CERT_POLICY_VIOLATION, cert);
961 }
962 }
963
964 METHOD(bus_t, destroy, void,
965 private_bus_t *this)
966 {
967 debug_t group;
968
969 lib->credmgr->set_hook(lib->credmgr, NULL, NULL);
970 for (group = 0; group < DBG_MAX; group++)
971 {
972 this->loggers[group]->destroy(this->loggers[group]);
973 }
974 this->loggers[DBG_MAX]->destroy_function(this->loggers[DBG_MAX],
975 (void*)free);
976 this->listeners->destroy_function(this->listeners, (void*)free);
977 this->thread_sa->destroy(this->thread_sa);
978 this->log_lock->destroy(this->log_lock);
979 this->mutex->destroy(this->mutex);
980 free(this);
981 }
982
983 /*
984 * Described in header.
985 */
986 bus_t *bus_create()
987 {
988 private_bus_t *this;
989 debug_t group;
990
991 INIT(this,
992 .public = {
993 .add_listener = _add_listener,
994 .remove_listener = _remove_listener,
995 .add_logger = _add_logger,
996 .remove_logger = _remove_logger,
997 .set_sa = _set_sa,
998 .get_sa = _get_sa,
999 .log = _log_,
1000 .vlog = _vlog,
1001 .alert = _alert,
1002 .ike_state_change = _ike_state_change,
1003 .child_state_change = _child_state_change,
1004 .message = _message,
1005 .ike_keys = _ike_keys,
1006 .child_keys = _child_keys,
1007 .ike_updown = _ike_updown,
1008 .ike_rekey = _ike_rekey,
1009 .ike_reestablish_pre = _ike_reestablish_pre,
1010 .ike_reestablish_post = _ike_reestablish_post,
1011 .child_updown = _child_updown,
1012 .child_rekey = _child_rekey,
1013 .authorize = _authorize,
1014 .narrow = _narrow,
1015 .assign_vips = _assign_vips,
1016 .handle_vips = _handle_vips,
1017 .destroy = _destroy,
1018 },
1019 .listeners = linked_list_create(),
1020 .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
1021 .log_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
1022 .thread_sa = thread_value_create(NULL),
1023 );
1024
1025 for (group = 0; group <= DBG_MAX; group++)
1026 {
1027 this->loggers[group] = linked_list_create();
1028 this->max_level[group] = LEVEL_SILENT;
1029 this->max_vlevel[group] = LEVEL_SILENT;
1030 }
1031
1032 lib->credmgr->set_hook(lib->credmgr, (credential_hook_t)hook_creds, this);
1033
1034 return &this->public;
1035 }