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 * Same as max level, but for loggers using the vlog() method.
58 level_t max_vlevel
[DBG_MAX
+ 1];
61 * Mutex for the list of listeners, recursively.
66 * Read-write lock for the list of loggers.
71 * Thread local storage the threads IKE_SA
73 thread_value_t
*thread_sa
;
76 typedef struct entry_t entry_t
;
84 * registered listener interface
89 * are we currently calling this listener
95 typedef struct log_entry_t log_entry_t
;
103 * registered logger interface
108 * registered log levels per group
110 level_t levels
[DBG_MAX
];
114 METHOD(bus_t
, add_listener
, void,
115 private_bus_t
*this, listener_t
*listener
)
120 .listener
= listener
,
123 this->mutex
->lock(this->mutex
);
124 this->listeners
->insert_last(this->listeners
, entry
);
125 this->mutex
->unlock(this->mutex
);
128 METHOD(bus_t
, remove_listener
, void,
129 private_bus_t
*this, listener_t
*listener
)
131 enumerator_t
*enumerator
;
134 this->mutex
->lock(this->mutex
);
135 enumerator
= this->listeners
->create_enumerator(this->listeners
);
136 while (enumerator
->enumerate(enumerator
, &entry
))
138 if (entry
->listener
== listener
)
140 this->listeners
->remove_at(this->listeners
, enumerator
);
145 enumerator
->destroy(enumerator
);
146 this->mutex
->unlock(this->mutex
);
150 * Register a logger on the given log group according to the requested level
152 static inline void register_logger(private_bus_t
*this, debug_t group
,
155 enumerator_t
*enumerator
;
156 linked_list_t
*loggers
;
157 log_entry_t
*current
;
160 loggers
= this->loggers
[group
];
161 level
= entry
->levels
[group
];
163 enumerator
= loggers
->create_enumerator(loggers
);
164 while (enumerator
->enumerate(enumerator
, (void**)¤t
))
166 if (current
->levels
[group
] <= level
)
171 loggers
->insert_before(loggers
, enumerator
, entry
);
172 enumerator
->destroy(enumerator
);
174 if (entry
->logger
->log
)
176 this->max_level
[group
] = max(this->max_level
[group
], level
);
178 if (entry
->logger
->vlog
)
180 this->max_vlevel
[group
] = max(this->max_vlevel
[group
], level
);
185 * Unregister a logger from all log groups (destroys the log_entry_t)
187 static inline void unregister_logger(private_bus_t
*this, logger_t
*logger
)
189 enumerator_t
*enumerator
;
190 linked_list_t
*loggers
;
191 log_entry_t
*entry
, *found
= NULL
;
193 loggers
= this->loggers
[DBG_MAX
];
194 enumerator
= loggers
->create_enumerator(loggers
);
195 while (enumerator
->enumerate(enumerator
, &entry
))
197 if (entry
->logger
== logger
)
199 loggers
->remove_at(loggers
, enumerator
);
204 enumerator
->destroy(enumerator
);
210 for (group
= 0; group
< DBG_MAX
; group
++)
212 if (found
->levels
[group
] > LEVEL_SILENT
)
214 loggers
= this->loggers
[group
];
215 loggers
->remove(loggers
, found
, NULL
);
217 this->max_level
[group
] = LEVEL_SILENT
;
218 this->max_vlevel
[group
] = LEVEL_SILENT
;
219 if (loggers
->get_first(loggers
, (void**)&entry
) == SUCCESS
)
221 this->max_level
[group
] = entry
->levels
[group
];
222 this->max_vlevel
[group
] = entry
->levels
[group
];
230 METHOD(bus_t
, add_logger
, void,
231 private_bus_t
*this, logger_t
*logger
)
240 this->log_lock
->write_lock(this->log_lock
);
241 unregister_logger(this, logger
);
242 for (group
= 0; group
< DBG_MAX
; group
++)
244 entry
->levels
[group
] = logger
->get_level(logger
, group
);
245 if (entry
->levels
[group
] > LEVEL_SILENT
)
247 register_logger(this, group
, entry
);
250 this->loggers
[DBG_MAX
]->insert_last(this->loggers
[DBG_MAX
], entry
);
251 this->log_lock
->unlock(this->log_lock
);
254 METHOD(bus_t
, remove_logger
, void,
255 private_bus_t
*this, logger_t
*logger
)
257 this->log_lock
->write_lock(this->log_lock
);
258 unregister_logger(this, logger
);
259 this->log_lock
->unlock(this->log_lock
);
262 METHOD(bus_t
, set_sa
, void,
263 private_bus_t
*this, ike_sa_t
*ike_sa
)
265 this->thread_sa
->set(this->thread_sa
, ike_sa
);
268 METHOD(bus_t
, get_sa
, ike_sa_t
*,
271 return this->thread_sa
->get(this->thread_sa
);
275 * data associated to a signal, passed to callback
278 /** associated IKE_SA */
280 /** invoking thread */
288 /** argument list if message is a format string for vlog() */
293 * logger->log() invocation as a invoke_function callback
295 static void log_cb(log_entry_t
*entry
, log_data_t
*data
)
297 if (entry
->logger
->log
&& entry
->levels
[data
->group
] >= data
->level
)
299 entry
->logger
->log(entry
->logger
, data
->group
, data
->level
,
300 data
->thread
, data
->ike_sa
, data
->message
);
305 * logger->vlog() invocation as a invoke_function callback
307 static void vlog_cb(log_entry_t
*entry
, log_data_t
*data
)
309 if (entry
->logger
->vlog
&& entry
->levels
[data
->group
] >= data
->level
)
313 va_copy(copy
, data
->args
);
314 entry
->logger
->vlog(entry
->logger
, data
->group
, data
->level
,
315 data
->thread
, data
->ike_sa
, data
->message
, copy
);
320 METHOD(bus_t
, vlog
, void,
321 private_bus_t
*this, debug_t group
, level_t level
,
322 char* format
, va_list args
)
324 linked_list_t
*loggers
;
327 this->log_lock
->read_lock(this->log_lock
);
328 loggers
= this->loggers
[group
];
330 if (this->max_level
[group
] >= level
)
335 data
.ike_sa
= this->thread_sa
->get(this->thread_sa
);
336 data
.thread
= thread_current_id();
341 va_copy(data
.args
, args
);
342 len
= vsnprintf(data
.message
, sizeof(buf
), format
, data
.args
);
344 if (len
>= sizeof(buf
))
347 data
.message
= malloc(len
);
348 len
= vsnprintf(data
.message
, len
, format
, args
);
352 loggers
->invoke_function(loggers
, (linked_list_invoke_t
)log_cb
,
355 if (data
.message
!= buf
)
360 if (this->max_vlevel
[group
] >= level
)
362 data
.ike_sa
= this->thread_sa
->get(this->thread_sa
);
363 data
.thread
= thread_current_id();
366 data
.message
= format
;
368 va_copy(data
.args
, args
);
369 loggers
->invoke_function(loggers
, (linked_list_invoke_t
)vlog_cb
, &data
);
373 this->log_lock
->unlock(this->log_lock
);
376 METHOD(bus_t
, log_
, void,
377 private_bus_t
*this, debug_t group
, level_t level
, char* format
, ...)
381 va_start(args
, format
);
382 vlog(this, group
, level
, format
, args
);
387 * unregister a listener
389 static inline void unregister_listener(private_bus_t
*this, entry_t
*entry
,
390 enumerator_t
*enumerator
)
392 this->listeners
->remove_at(this->listeners
, enumerator
);
396 METHOD(bus_t
, alert
, void,
397 private_bus_t
*this, alert_t alert
, ...)
399 enumerator_t
*enumerator
;
405 ike_sa
= this->thread_sa
->get(this->thread_sa
);
407 this->mutex
->lock(this->mutex
);
408 enumerator
= this->listeners
->create_enumerator(this->listeners
);
409 while (enumerator
->enumerate(enumerator
, &entry
))
411 if (entry
->calling
|| !entry
->listener
->alert
)
416 va_start(args
, alert
);
417 keep
= entry
->listener
->alert(entry
->listener
, ike_sa
, alert
, args
);
422 unregister_listener(this, entry
, enumerator
);
425 enumerator
->destroy(enumerator
);
426 this->mutex
->unlock(this->mutex
);
429 METHOD(bus_t
, ike_state_change
, void,
430 private_bus_t
*this, ike_sa_t
*ike_sa
, ike_sa_state_t state
)
432 enumerator_t
*enumerator
;
436 this->mutex
->lock(this->mutex
);
437 enumerator
= this->listeners
->create_enumerator(this->listeners
);
438 while (enumerator
->enumerate(enumerator
, &entry
))
440 if (entry
->calling
|| !entry
->listener
->ike_state_change
)
445 keep
= entry
->listener
->ike_state_change(entry
->listener
, ike_sa
, state
);
449 unregister_listener(this, entry
, enumerator
);
452 enumerator
->destroy(enumerator
);
453 this->mutex
->unlock(this->mutex
);
456 METHOD(bus_t
, child_state_change
, void,
457 private_bus_t
*this, child_sa_t
*child_sa
, child_sa_state_t state
)
459 enumerator_t
*enumerator
;
464 ike_sa
= this->thread_sa
->get(this->thread_sa
);
466 this->mutex
->lock(this->mutex
);
467 enumerator
= this->listeners
->create_enumerator(this->listeners
);
468 while (enumerator
->enumerate(enumerator
, &entry
))
470 if (entry
->calling
|| !entry
->listener
->child_state_change
)
475 keep
= entry
->listener
->child_state_change(entry
->listener
, ike_sa
,
480 unregister_listener(this, entry
, enumerator
);
483 enumerator
->destroy(enumerator
);
484 this->mutex
->unlock(this->mutex
);
487 METHOD(bus_t
, message
, void,
488 private_bus_t
*this, message_t
*message
, bool incoming
, bool plain
)
490 enumerator_t
*enumerator
;
495 ike_sa
= this->thread_sa
->get(this->thread_sa
);
497 this->mutex
->lock(this->mutex
);
498 enumerator
= this->listeners
->create_enumerator(this->listeners
);
499 while (enumerator
->enumerate(enumerator
, &entry
))
501 if (entry
->calling
|| !entry
->listener
->message
)
506 keep
= entry
->listener
->message(entry
->listener
, ike_sa
,
507 message
, incoming
, plain
);
511 unregister_listener(this, entry
, enumerator
);
514 enumerator
->destroy(enumerator
);
515 this->mutex
->unlock(this->mutex
);
518 METHOD(bus_t
, ike_keys
, void,
519 private_bus_t
*this, ike_sa_t
*ike_sa
, diffie_hellman_t
*dh
,
520 chunk_t dh_other
, chunk_t nonce_i
, chunk_t nonce_r
,
521 ike_sa_t
*rekey
, shared_key_t
*shared
)
523 enumerator_t
*enumerator
;
527 this->mutex
->lock(this->mutex
);
528 enumerator
= this->listeners
->create_enumerator(this->listeners
);
529 while (enumerator
->enumerate(enumerator
, &entry
))
531 if (entry
->calling
|| !entry
->listener
->ike_keys
)
536 keep
= entry
->listener
->ike_keys(entry
->listener
, ike_sa
, dh
, dh_other
,
537 nonce_i
, nonce_r
, rekey
, shared
);
541 unregister_listener(this, entry
, enumerator
);
544 enumerator
->destroy(enumerator
);
545 this->mutex
->unlock(this->mutex
);
548 METHOD(bus_t
, child_keys
, void,
549 private_bus_t
*this, child_sa_t
*child_sa
, bool initiator
,
550 diffie_hellman_t
*dh
, chunk_t nonce_i
, chunk_t nonce_r
)
552 enumerator_t
*enumerator
;
557 ike_sa
= this->thread_sa
->get(this->thread_sa
);
559 this->mutex
->lock(this->mutex
);
560 enumerator
= this->listeners
->create_enumerator(this->listeners
);
561 while (enumerator
->enumerate(enumerator
, &entry
))
563 if (entry
->calling
|| !entry
->listener
->child_keys
)
568 keep
= entry
->listener
->child_keys(entry
->listener
, ike_sa
,
569 child_sa
, initiator
, dh
, nonce_i
, nonce_r
);
573 unregister_listener(this, entry
, enumerator
);
576 enumerator
->destroy(enumerator
);
577 this->mutex
->unlock(this->mutex
);
580 METHOD(bus_t
, child_updown
, void,
581 private_bus_t
*this, child_sa_t
*child_sa
, bool up
)
583 enumerator_t
*enumerator
;
588 ike_sa
= this->thread_sa
->get(this->thread_sa
);
590 this->mutex
->lock(this->mutex
);
591 enumerator
= this->listeners
->create_enumerator(this->listeners
);
592 while (enumerator
->enumerate(enumerator
, &entry
))
594 if (entry
->calling
|| !entry
->listener
->child_updown
)
599 keep
= entry
->listener
->child_updown(entry
->listener
,
600 ike_sa
, child_sa
, up
);
604 unregister_listener(this, entry
, enumerator
);
607 enumerator
->destroy(enumerator
);
608 this->mutex
->unlock(this->mutex
);
611 METHOD(bus_t
, child_rekey
, void,
612 private_bus_t
*this, child_sa_t
*old
, child_sa_t
*new)
614 enumerator_t
*enumerator
;
619 ike_sa
= this->thread_sa
->get(this->thread_sa
);
621 this->mutex
->lock(this->mutex
);
622 enumerator
= this->listeners
->create_enumerator(this->listeners
);
623 while (enumerator
->enumerate(enumerator
, &entry
))
625 if (entry
->calling
|| !entry
->listener
->child_rekey
)
630 keep
= entry
->listener
->child_rekey(entry
->listener
, ike_sa
,
635 unregister_listener(this, entry
, enumerator
);
638 enumerator
->destroy(enumerator
);
639 this->mutex
->unlock(this->mutex
);
642 METHOD(bus_t
, ike_updown
, void,
643 private_bus_t
*this, ike_sa_t
*ike_sa
, bool up
)
645 enumerator_t
*enumerator
;
649 this->mutex
->lock(this->mutex
);
650 enumerator
= this->listeners
->create_enumerator(this->listeners
);
651 while (enumerator
->enumerate(enumerator
, &entry
))
653 if (entry
->calling
|| !entry
->listener
->ike_updown
)
658 keep
= entry
->listener
->ike_updown(entry
->listener
, ike_sa
, up
);
662 unregister_listener(this, entry
, enumerator
);
665 enumerator
->destroy(enumerator
);
666 this->mutex
->unlock(this->mutex
);
668 /* a down event for IKE_SA implicitly downs all CHILD_SAs */
671 enumerator_t
*enumerator
;
672 child_sa_t
*child_sa
;
674 enumerator
= ike_sa
->create_child_sa_enumerator(ike_sa
);
675 while (enumerator
->enumerate(enumerator
, (void**)&child_sa
))
677 child_updown(this, child_sa
, FALSE
);
679 enumerator
->destroy(enumerator
);
683 METHOD(bus_t
, ike_rekey
, void,
684 private_bus_t
*this, ike_sa_t
*old
, ike_sa_t
*new)
686 enumerator_t
*enumerator
;
690 this->mutex
->lock(this->mutex
);
691 enumerator
= this->listeners
->create_enumerator(this->listeners
);
692 while (enumerator
->enumerate(enumerator
, &entry
))
694 if (entry
->calling
|| !entry
->listener
->ike_rekey
)
699 keep
= entry
->listener
->ike_rekey(entry
->listener
, old
, new);
703 unregister_listener(this, entry
, enumerator
);
706 enumerator
->destroy(enumerator
);
707 this->mutex
->unlock(this->mutex
);
710 METHOD(bus_t
, ike_reestablish
, void,
711 private_bus_t
*this, ike_sa_t
*old
, ike_sa_t
*new)
713 enumerator_t
*enumerator
;
717 this->mutex
->lock(this->mutex
);
718 enumerator
= this->listeners
->create_enumerator(this->listeners
);
719 while (enumerator
->enumerate(enumerator
, &entry
))
721 if (entry
->calling
|| !entry
->listener
->ike_reestablish
)
726 keep
= entry
->listener
->ike_reestablish(entry
->listener
, old
, new);
730 unregister_listener(this, entry
, enumerator
);
733 enumerator
->destroy(enumerator
);
734 this->mutex
->unlock(this->mutex
);
737 METHOD(bus_t
, authorize
, bool,
738 private_bus_t
*this, bool final
)
740 enumerator_t
*enumerator
;
743 bool keep
, success
= TRUE
;
745 ike_sa
= this->thread_sa
->get(this->thread_sa
);
747 this->mutex
->lock(this->mutex
);
748 enumerator
= this->listeners
->create_enumerator(this->listeners
);
749 while (enumerator
->enumerate(enumerator
, &entry
))
751 if (entry
->calling
|| !entry
->listener
->authorize
)
756 keep
= entry
->listener
->authorize(entry
->listener
, ike_sa
,
761 unregister_listener(this, entry
, enumerator
);
768 enumerator
->destroy(enumerator
);
769 this->mutex
->unlock(this->mutex
);
772 alert(this, ALERT_AUTHORIZATION_FAILED
);
777 METHOD(bus_t
, narrow
, void,
778 private_bus_t
*this, child_sa_t
*child_sa
, narrow_hook_t type
,
779 linked_list_t
*local
, linked_list_t
*remote
)
781 enumerator_t
*enumerator
;
786 ike_sa
= this->thread_sa
->get(this->thread_sa
);
788 this->mutex
->lock(this->mutex
);
789 enumerator
= this->listeners
->create_enumerator(this->listeners
);
790 while (enumerator
->enumerate(enumerator
, &entry
))
792 if (entry
->calling
|| !entry
->listener
->narrow
)
797 keep
= entry
->listener
->narrow(entry
->listener
, ike_sa
, child_sa
,
798 type
, local
, remote
);
802 unregister_listener(this, entry
, enumerator
);
805 enumerator
->destroy(enumerator
);
806 this->mutex
->unlock(this->mutex
);
809 METHOD(bus_t
, assign_vips
, void,
810 private_bus_t
*this, ike_sa_t
*ike_sa
, bool assign
)
812 enumerator_t
*enumerator
;
816 this->mutex
->lock(this->mutex
);
817 enumerator
= this->listeners
->create_enumerator(this->listeners
);
818 while (enumerator
->enumerate(enumerator
, &entry
))
820 if (entry
->calling
|| !entry
->listener
->assign_vips
)
825 keep
= entry
->listener
->assign_vips(entry
->listener
, ike_sa
, assign
);
829 unregister_listener(this, entry
, enumerator
);
832 enumerator
->destroy(enumerator
);
833 this->mutex
->unlock(this->mutex
);
836 METHOD(bus_t
, destroy
, void,
840 for (group
= 0; group
< DBG_MAX
; group
++)
842 this->loggers
[group
]->destroy(this->loggers
[group
]);
844 this->loggers
[DBG_MAX
]->destroy_function(this->loggers
[DBG_MAX
],
846 this->listeners
->destroy_function(this->listeners
, (void*)free
);
847 this->thread_sa
->destroy(this->thread_sa
);
848 this->log_lock
->destroy(this->log_lock
);
849 this->mutex
->destroy(this->mutex
);
854 * Described in header.
863 .add_listener
= _add_listener
,
864 .remove_listener
= _remove_listener
,
865 .add_logger
= _add_logger
,
866 .remove_logger
= _remove_logger
,
872 .ike_state_change
= _ike_state_change
,
873 .child_state_change
= _child_state_change
,
875 .ike_keys
= _ike_keys
,
876 .child_keys
= _child_keys
,
877 .ike_updown
= _ike_updown
,
878 .ike_rekey
= _ike_rekey
,
879 .ike_reestablish
= _ike_reestablish
,
880 .child_updown
= _child_updown
,
881 .child_rekey
= _child_rekey
,
882 .authorize
= _authorize
,
884 .assign_vips
= _assign_vips
,
887 .listeners
= linked_list_create(),
888 .mutex
= mutex_create(MUTEX_TYPE_RECURSIVE
),
889 .log_lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
890 .thread_sa
= thread_value_create(NULL
),
893 for (group
= 0; group
<= DBG_MAX
; group
++)
895 this->loggers
[group
] = linked_list_create();
896 this->max_level
[group
] = LEVEL_SILENT
;
897 this->max_vlevel
[group
] = LEVEL_SILENT
;
900 return &this->public;