2 * Copyright (C) 2011-2012 Tobias Brunner
3 * Copyright (C) 2006 Martin Willi
4 * Hochschule fuer Technik Rapperswil
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>.
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
21 #include <threading/thread.h>
22 #include <threading/thread_value.h>
23 #include <threading/mutex.h>
24 #include <threading/rwlock.h>
26 typedef struct private_bus_t private_bus_t
;
29 * Private data of a bus_t object.
31 struct private_bus_t
{
33 * Public part of a bus_t object.
38 * List of registered listeners as entry_t.
40 linked_list_t
*listeners
;
43 * List of registered loggers for each log group as log_entry_t.
44 * Loggers are ordered by descending log level.
45 * The extra list stores all loggers so we can properly unregister them.
47 linked_list_t
*loggers
[DBG_MAX
+ 1];
50 * Maximum log level of any registered logger for each log group.
51 * This allows to check quickly if a log message has to be logged at all.
53 level_t max_level
[DBG_MAX
+ 1];
56 * Mutex for the list of listeners, recursively.
61 * Read-write lock for the list of loggers.
66 * Thread local storage the threads IKE_SA
68 thread_value_t
*thread_sa
;
71 typedef struct entry_t entry_t
;
79 * registered listener interface
84 * are we currently calling this listener
90 typedef struct log_entry_t log_entry_t
;
98 * registered logger interface
103 * registered log levels per group
105 level_t levels
[DBG_MAX
];
109 METHOD(bus_t
, add_listener
, void,
110 private_bus_t
*this, listener_t
*listener
)
115 .listener
= listener
,
118 this->mutex
->lock(this->mutex
);
119 this->listeners
->insert_last(this->listeners
, entry
);
120 this->mutex
->unlock(this->mutex
);
123 METHOD(bus_t
, remove_listener
, void,
124 private_bus_t
*this, listener_t
*listener
)
126 enumerator_t
*enumerator
;
129 this->mutex
->lock(this->mutex
);
130 enumerator
= this->listeners
->create_enumerator(this->listeners
);
131 while (enumerator
->enumerate(enumerator
, &entry
))
133 if (entry
->listener
== listener
)
135 this->listeners
->remove_at(this->listeners
, enumerator
);
140 enumerator
->destroy(enumerator
);
141 this->mutex
->unlock(this->mutex
);
145 * Register a logger on the given log group according to the requested level
147 static inline void register_logger(private_bus_t
*this, debug_t group
,
150 enumerator_t
*enumerator
;
151 linked_list_t
*loggers
;
152 log_entry_t
*current
;
155 loggers
= this->loggers
[group
];
156 level
= entry
->levels
[group
];
158 enumerator
= loggers
->create_enumerator(loggers
);
159 while (enumerator
->enumerate(enumerator
, (void**)¤t
))
161 if (current
->levels
[group
] <= level
)
166 loggers
->insert_before(loggers
, enumerator
, entry
);
167 enumerator
->destroy(enumerator
);
169 this->max_level
[group
] = max(this->max_level
[group
], level
);
173 * Unregister a logger from all log groups (destroys the log_entry_t)
175 static inline void unregister_logger(private_bus_t
*this, logger_t
*logger
)
177 enumerator_t
*enumerator
;
178 linked_list_t
*loggers
;
179 log_entry_t
*entry
, *found
= NULL
;
181 loggers
= this->loggers
[DBG_MAX
];
182 enumerator
= loggers
->create_enumerator(loggers
);
183 while (enumerator
->enumerate(enumerator
, &entry
))
185 if (entry
->logger
== logger
)
187 loggers
->remove_at(loggers
, enumerator
);
192 enumerator
->destroy(enumerator
);
197 for (group
= 0; group
< DBG_MAX
; group
++)
199 if (found
->levels
[group
] > LEVEL_SILENT
)
201 loggers
= this->loggers
[group
];
202 loggers
->remove(loggers
, found
, NULL
);
204 this->max_level
[group
] = LEVEL_SILENT
;
205 if (loggers
->get_first(loggers
, (void**)&entry
) == SUCCESS
)
207 this->max_level
[group
] = entry
->levels
[group
];
215 METHOD(bus_t
, add_logger
, void,
216 private_bus_t
*this, logger_t
*logger
)
225 this->log_lock
->write_lock(this->log_lock
);
226 unregister_logger(this, logger
);
227 for (group
= 0; group
< DBG_MAX
; group
++)
229 entry
->levels
[group
] = logger
->get_level(logger
, group
);
230 if (entry
->levels
[group
] > LEVEL_SILENT
)
232 register_logger(this, group
, entry
);
235 this->loggers
[DBG_MAX
]->insert_last(this->loggers
[DBG_MAX
], entry
);
236 this->log_lock
->unlock(this->log_lock
);
239 METHOD(bus_t
, remove_logger
, void,
240 private_bus_t
*this, logger_t
*logger
)
242 this->log_lock
->write_lock(this->log_lock
);
243 unregister_logger(this, logger
);
244 this->log_lock
->unlock(this->log_lock
);
247 METHOD(bus_t
, set_sa
, void,
248 private_bus_t
*this, ike_sa_t
*ike_sa
)
250 this->thread_sa
->set(this->thread_sa
, ike_sa
);
253 METHOD(bus_t
, get_sa
, ike_sa_t
*,
256 return this->thread_sa
->get(this->thread_sa
);
260 * data associated to a signal, passed to callback
263 /** associated IKE_SA */
265 /** invoking thread */
276 * logger->log() invocation as a invoke_function callback
278 static void log_cb(log_entry_t
*entry
, log_data_t
*data
)
280 if (entry
->levels
[data
->group
] < data
->level
)
284 entry
->logger
->log(entry
->logger
, data
->group
, data
->level
,
285 data
->thread
, data
->ike_sa
, data
->message
);
288 METHOD(bus_t
, vlog
, void,
289 private_bus_t
*this, debug_t group
, level_t level
,
290 char* format
, va_list args
)
292 this->log_lock
->read_lock(this->log_lock
);
293 if (this->max_level
[group
] >= level
)
295 linked_list_t
*loggers
= this->loggers
[group
];
301 data
.ike_sa
= this->thread_sa
->get(this->thread_sa
);
302 data
.thread
= thread_current_id();
308 len
= vsnprintf(data
.message
, sizeof(buf
), format
, copy
);
310 if (len
>= sizeof(buf
))
313 data
.message
= malloc(len
);
314 len
= vsnprintf(data
.message
, len
, format
, args
);
318 loggers
->invoke_function(loggers
, (linked_list_invoke_t
)log_cb
,
321 if (data
.message
!= buf
)
326 this->log_lock
->unlock(this->log_lock
);
329 METHOD(bus_t
, log_
, void,
330 private_bus_t
*this, debug_t group
, level_t level
, char* format
, ...)
334 va_start(args
, format
);
335 vlog(this, group
, level
, format
, args
);
340 * unregister a listener
342 static inline void unregister_listener(private_bus_t
*this, entry_t
*entry
,
343 enumerator_t
*enumerator
)
345 this->listeners
->remove_at(this->listeners
, enumerator
);
349 METHOD(bus_t
, alert
, void,
350 private_bus_t
*this, alert_t alert
, ...)
352 enumerator_t
*enumerator
;
358 ike_sa
= this->thread_sa
->get(this->thread_sa
);
360 this->mutex
->lock(this->mutex
);
361 enumerator
= this->listeners
->create_enumerator(this->listeners
);
362 while (enumerator
->enumerate(enumerator
, &entry
))
364 if (entry
->calling
|| !entry
->listener
->alert
)
369 va_start(args
, alert
);
370 keep
= entry
->listener
->alert(entry
->listener
, ike_sa
, alert
, args
);
375 unregister_listener(this, entry
, enumerator
);
378 enumerator
->destroy(enumerator
);
379 this->mutex
->unlock(this->mutex
);
382 METHOD(bus_t
, ike_state_change
, void,
383 private_bus_t
*this, ike_sa_t
*ike_sa
, ike_sa_state_t state
)
385 enumerator_t
*enumerator
;
389 this->mutex
->lock(this->mutex
);
390 enumerator
= this->listeners
->create_enumerator(this->listeners
);
391 while (enumerator
->enumerate(enumerator
, &entry
))
393 if (entry
->calling
|| !entry
->listener
->ike_state_change
)
398 keep
= entry
->listener
->ike_state_change(entry
->listener
, ike_sa
, state
);
402 unregister_listener(this, entry
, enumerator
);
405 enumerator
->destroy(enumerator
);
406 this->mutex
->unlock(this->mutex
);
409 METHOD(bus_t
, child_state_change
, void,
410 private_bus_t
*this, child_sa_t
*child_sa
, child_sa_state_t state
)
412 enumerator_t
*enumerator
;
417 ike_sa
= this->thread_sa
->get(this->thread_sa
);
419 this->mutex
->lock(this->mutex
);
420 enumerator
= this->listeners
->create_enumerator(this->listeners
);
421 while (enumerator
->enumerate(enumerator
, &entry
))
423 if (entry
->calling
|| !entry
->listener
->child_state_change
)
428 keep
= entry
->listener
->child_state_change(entry
->listener
, ike_sa
,
433 unregister_listener(this, entry
, enumerator
);
436 enumerator
->destroy(enumerator
);
437 this->mutex
->unlock(this->mutex
);
440 METHOD(bus_t
, message
, void,
441 private_bus_t
*this, message_t
*message
, bool incoming
, bool plain
)
443 enumerator_t
*enumerator
;
448 ike_sa
= this->thread_sa
->get(this->thread_sa
);
450 this->mutex
->lock(this->mutex
);
451 enumerator
= this->listeners
->create_enumerator(this->listeners
);
452 while (enumerator
->enumerate(enumerator
, &entry
))
454 if (entry
->calling
|| !entry
->listener
->message
)
459 keep
= entry
->listener
->message(entry
->listener
, ike_sa
,
460 message
, incoming
, plain
);
464 unregister_listener(this, entry
, enumerator
);
467 enumerator
->destroy(enumerator
);
468 this->mutex
->unlock(this->mutex
);
471 METHOD(bus_t
, ike_keys
, void,
472 private_bus_t
*this, ike_sa_t
*ike_sa
, diffie_hellman_t
*dh
,
473 chunk_t dh_other
, chunk_t nonce_i
, chunk_t nonce_r
,
474 ike_sa_t
*rekey
, shared_key_t
*shared
)
476 enumerator_t
*enumerator
;
480 this->mutex
->lock(this->mutex
);
481 enumerator
= this->listeners
->create_enumerator(this->listeners
);
482 while (enumerator
->enumerate(enumerator
, &entry
))
484 if (entry
->calling
|| !entry
->listener
->ike_keys
)
489 keep
= entry
->listener
->ike_keys(entry
->listener
, ike_sa
, dh
, dh_other
,
490 nonce_i
, nonce_r
, rekey
, shared
);
494 unregister_listener(this, entry
, enumerator
);
497 enumerator
->destroy(enumerator
);
498 this->mutex
->unlock(this->mutex
);
501 METHOD(bus_t
, child_keys
, void,
502 private_bus_t
*this, child_sa_t
*child_sa
, bool initiator
,
503 diffie_hellman_t
*dh
, chunk_t nonce_i
, chunk_t nonce_r
)
505 enumerator_t
*enumerator
;
510 ike_sa
= this->thread_sa
->get(this->thread_sa
);
512 this->mutex
->lock(this->mutex
);
513 enumerator
= this->listeners
->create_enumerator(this->listeners
);
514 while (enumerator
->enumerate(enumerator
, &entry
))
516 if (entry
->calling
|| !entry
->listener
->child_keys
)
521 keep
= entry
->listener
->child_keys(entry
->listener
, ike_sa
,
522 child_sa
, initiator
, dh
, nonce_i
, nonce_r
);
526 unregister_listener(this, entry
, enumerator
);
529 enumerator
->destroy(enumerator
);
530 this->mutex
->unlock(this->mutex
);
533 METHOD(bus_t
, child_updown
, void,
534 private_bus_t
*this, child_sa_t
*child_sa
, bool up
)
536 enumerator_t
*enumerator
;
541 ike_sa
= this->thread_sa
->get(this->thread_sa
);
543 this->mutex
->lock(this->mutex
);
544 enumerator
= this->listeners
->create_enumerator(this->listeners
);
545 while (enumerator
->enumerate(enumerator
, &entry
))
547 if (entry
->calling
|| !entry
->listener
->child_updown
)
552 keep
= entry
->listener
->child_updown(entry
->listener
,
553 ike_sa
, child_sa
, up
);
557 unregister_listener(this, entry
, enumerator
);
560 enumerator
->destroy(enumerator
);
561 this->mutex
->unlock(this->mutex
);
564 METHOD(bus_t
, child_rekey
, void,
565 private_bus_t
*this, child_sa_t
*old
, child_sa_t
*new)
567 enumerator_t
*enumerator
;
572 ike_sa
= this->thread_sa
->get(this->thread_sa
);
574 this->mutex
->lock(this->mutex
);
575 enumerator
= this->listeners
->create_enumerator(this->listeners
);
576 while (enumerator
->enumerate(enumerator
, &entry
))
578 if (entry
->calling
|| !entry
->listener
->child_rekey
)
583 keep
= entry
->listener
->child_rekey(entry
->listener
, ike_sa
,
588 unregister_listener(this, entry
, enumerator
);
591 enumerator
->destroy(enumerator
);
592 this->mutex
->unlock(this->mutex
);
595 METHOD(bus_t
, ike_updown
, void,
596 private_bus_t
*this, ike_sa_t
*ike_sa
, bool up
)
598 enumerator_t
*enumerator
;
602 this->mutex
->lock(this->mutex
);
603 enumerator
= this->listeners
->create_enumerator(this->listeners
);
604 while (enumerator
->enumerate(enumerator
, &entry
))
606 if (entry
->calling
|| !entry
->listener
->ike_updown
)
611 keep
= entry
->listener
->ike_updown(entry
->listener
, ike_sa
, up
);
615 unregister_listener(this, entry
, enumerator
);
618 enumerator
->destroy(enumerator
);
619 this->mutex
->unlock(this->mutex
);
621 /* a down event for IKE_SA implicitly downs all CHILD_SAs */
624 enumerator_t
*enumerator
;
625 child_sa_t
*child_sa
;
627 enumerator
= ike_sa
->create_child_sa_enumerator(ike_sa
);
628 while (enumerator
->enumerate(enumerator
, (void**)&child_sa
))
630 child_updown(this, child_sa
, FALSE
);
632 enumerator
->destroy(enumerator
);
636 METHOD(bus_t
, ike_rekey
, void,
637 private_bus_t
*this, ike_sa_t
*old
, ike_sa_t
*new)
639 enumerator_t
*enumerator
;
643 this->mutex
->lock(this->mutex
);
644 enumerator
= this->listeners
->create_enumerator(this->listeners
);
645 while (enumerator
->enumerate(enumerator
, &entry
))
647 if (entry
->calling
|| !entry
->listener
->ike_rekey
)
652 keep
= entry
->listener
->ike_rekey(entry
->listener
, old
, new);
656 unregister_listener(this, entry
, enumerator
);
659 enumerator
->destroy(enumerator
);
660 this->mutex
->unlock(this->mutex
);
663 METHOD(bus_t
, ike_reestablish
, void,
664 private_bus_t
*this, ike_sa_t
*old
, ike_sa_t
*new)
666 enumerator_t
*enumerator
;
670 this->mutex
->lock(this->mutex
);
671 enumerator
= this->listeners
->create_enumerator(this->listeners
);
672 while (enumerator
->enumerate(enumerator
, &entry
))
674 if (entry
->calling
|| !entry
->listener
->ike_reestablish
)
679 keep
= entry
->listener
->ike_reestablish(entry
->listener
, old
, new);
683 unregister_listener(this, entry
, enumerator
);
686 enumerator
->destroy(enumerator
);
687 this->mutex
->unlock(this->mutex
);
690 METHOD(bus_t
, authorize
, bool,
691 private_bus_t
*this, bool final
)
693 enumerator_t
*enumerator
;
696 bool keep
, success
= TRUE
;
698 ike_sa
= this->thread_sa
->get(this->thread_sa
);
700 this->mutex
->lock(this->mutex
);
701 enumerator
= this->listeners
->create_enumerator(this->listeners
);
702 while (enumerator
->enumerate(enumerator
, &entry
))
704 if (entry
->calling
|| !entry
->listener
->authorize
)
709 keep
= entry
->listener
->authorize(entry
->listener
, ike_sa
,
714 unregister_listener(this, entry
, enumerator
);
721 enumerator
->destroy(enumerator
);
722 this->mutex
->unlock(this->mutex
);
725 alert(this, ALERT_AUTHORIZATION_FAILED
);
730 METHOD(bus_t
, narrow
, void,
731 private_bus_t
*this, child_sa_t
*child_sa
, narrow_hook_t type
,
732 linked_list_t
*local
, linked_list_t
*remote
)
734 enumerator_t
*enumerator
;
739 ike_sa
= this->thread_sa
->get(this->thread_sa
);
741 this->mutex
->lock(this->mutex
);
742 enumerator
= this->listeners
->create_enumerator(this->listeners
);
743 while (enumerator
->enumerate(enumerator
, &entry
))
745 if (entry
->calling
|| !entry
->listener
->narrow
)
750 keep
= entry
->listener
->narrow(entry
->listener
, ike_sa
, child_sa
,
751 type
, local
, remote
);
755 unregister_listener(this, entry
, enumerator
);
758 enumerator
->destroy(enumerator
);
759 this->mutex
->unlock(this->mutex
);
762 METHOD(bus_t
, assign_vips
, void,
763 private_bus_t
*this, ike_sa_t
*ike_sa
, bool assign
)
765 enumerator_t
*enumerator
;
769 this->mutex
->lock(this->mutex
);
770 enumerator
= this->listeners
->create_enumerator(this->listeners
);
771 while (enumerator
->enumerate(enumerator
, &entry
))
773 if (entry
->calling
|| !entry
->listener
->assign_vips
)
778 keep
= entry
->listener
->assign_vips(entry
->listener
, ike_sa
, assign
);
782 unregister_listener(this, entry
, enumerator
);
785 enumerator
->destroy(enumerator
);
786 this->mutex
->unlock(this->mutex
);
789 METHOD(bus_t
, destroy
, void,
793 for (group
= 0; group
< DBG_MAX
; group
++)
795 this->loggers
[group
]->destroy(this->loggers
[group
]);
797 this->loggers
[DBG_MAX
]->destroy_function(this->loggers
[DBG_MAX
],
799 this->listeners
->destroy_function(this->listeners
, (void*)free
);
800 this->thread_sa
->destroy(this->thread_sa
);
801 this->log_lock
->destroy(this->log_lock
);
802 this->mutex
->destroy(this->mutex
);
807 * Described in header.
816 .add_listener
= _add_listener
,
817 .remove_listener
= _remove_listener
,
818 .add_logger
= _add_logger
,
819 .remove_logger
= _remove_logger
,
825 .ike_state_change
= _ike_state_change
,
826 .child_state_change
= _child_state_change
,
828 .ike_keys
= _ike_keys
,
829 .child_keys
= _child_keys
,
830 .ike_updown
= _ike_updown
,
831 .ike_rekey
= _ike_rekey
,
832 .ike_reestablish
= _ike_reestablish
,
833 .child_updown
= _child_updown
,
834 .child_rekey
= _child_rekey
,
835 .authorize
= _authorize
,
837 .assign_vips
= _assign_vips
,
840 .listeners
= linked_list_create(),
841 .mutex
= mutex_create(MUTEX_TYPE_RECURSIVE
),
842 .log_lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
843 .thread_sa
= thread_value_create(NULL
),
846 for (group
= 0; group
<= DBG_MAX
; group
++)
848 this->loggers
[group
] = linked_list_create();
849 this->max_level
[group
] = LEVEL_SILENT
;
852 return &this->public;