Annotation of embedaddon/strongswan/src/libcharon/bus/bus.c, revision 1.1.1.1
1.1 misho 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**)¤t))
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, auth_method_t method)
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: method);
596: entry->calling--;
597: if (!keep)
598: {
599: unregister_listener(this, entry, enumerator);
600: }
601: }
602: enumerator->destroy(enumerator);
603: this->mutex->unlock(this->mutex);
604: }
605:
606: METHOD(bus_t, ike_derived_keys, void,
607: private_bus_t *this, chunk_t sk_ei, chunk_t sk_er, chunk_t sk_ai,
608: chunk_t sk_ar)
609: {
610: enumerator_t *enumerator;
611: ike_sa_t *ike_sa;
612: entry_t *entry;
613: bool keep;
614:
615: ike_sa = this->thread_sa->get(this->thread_sa);
616:
617: this->mutex->lock(this->mutex);
618: enumerator = this->listeners->create_enumerator(this->listeners);
619: while (enumerator->enumerate(enumerator, &entry))
620: {
621: if (entry->calling || !entry->listener->ike_derived_keys)
622: {
623: continue;
624: }
625: entry->calling++;
626: keep = entry->listener->ike_derived_keys(entry->listener, ike_sa, sk_ei,
627: sk_er, sk_ai, sk_ar);
628: entry->calling--;
629: if (!keep)
630: {
631: unregister_listener(this, entry, enumerator);
632: }
633: }
634: enumerator->destroy(enumerator);
635: this->mutex->unlock(this->mutex);
636: }
637:
638: METHOD(bus_t, child_keys, void,
639: private_bus_t *this, child_sa_t *child_sa, bool initiator,
640: diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
641: {
642: enumerator_t *enumerator;
643: ike_sa_t *ike_sa;
644: entry_t *entry;
645: bool keep;
646:
647: ike_sa = this->thread_sa->get(this->thread_sa);
648:
649: this->mutex->lock(this->mutex);
650: enumerator = this->listeners->create_enumerator(this->listeners);
651: while (enumerator->enumerate(enumerator, &entry))
652: {
653: if (entry->calling || !entry->listener->child_keys)
654: {
655: continue;
656: }
657: entry->calling++;
658: keep = entry->listener->child_keys(entry->listener, ike_sa,
659: child_sa, initiator, dh, nonce_i, nonce_r);
660: entry->calling--;
661: if (!keep)
662: {
663: unregister_listener(this, entry, enumerator);
664: }
665: }
666: enumerator->destroy(enumerator);
667: this->mutex->unlock(this->mutex);
668: }
669:
670: METHOD(bus_t, child_derived_keys, void,
671: private_bus_t *this, child_sa_t *child_sa, bool initiator,
672: chunk_t encr_i, chunk_t encr_r, chunk_t integ_i, chunk_t integ_r)
673: {
674: enumerator_t *enumerator;
675: ike_sa_t *ike_sa;
676: entry_t *entry;
677: bool keep;
678:
679: ike_sa = this->thread_sa->get(this->thread_sa);
680:
681: this->mutex->lock(this->mutex);
682: enumerator = this->listeners->create_enumerator(this->listeners);
683: while (enumerator->enumerate(enumerator, &entry))
684: {
685: if (entry->calling || !entry->listener->child_derived_keys)
686: {
687: continue;
688: }
689: entry->calling++;
690: keep = entry->listener->child_derived_keys(entry->listener, ike_sa,
691: child_sa, initiator, encr_i, encr_r,
692: integ_i, integ_r);
693: entry->calling--;
694: if (!keep)
695: {
696: unregister_listener(this, entry, enumerator);
697: }
698: }
699: enumerator->destroy(enumerator);
700: this->mutex->unlock(this->mutex);
701: }
702:
703: METHOD(bus_t, child_updown, void,
704: private_bus_t *this, child_sa_t *child_sa, bool up)
705: {
706: enumerator_t *enumerator;
707: ike_sa_t *ike_sa;
708: entry_t *entry;
709: bool keep;
710:
711: ike_sa = this->thread_sa->get(this->thread_sa);
712:
713: this->mutex->lock(this->mutex);
714: enumerator = this->listeners->create_enumerator(this->listeners);
715: while (enumerator->enumerate(enumerator, &entry))
716: {
717: if (entry->calling || !entry->listener->child_updown)
718: {
719: continue;
720: }
721: entry->calling++;
722: keep = entry->listener->child_updown(entry->listener,
723: ike_sa, child_sa, up);
724: entry->calling--;
725: if (!keep)
726: {
727: unregister_listener(this, entry, enumerator);
728: }
729: }
730: enumerator->destroy(enumerator);
731: this->mutex->unlock(this->mutex);
732: }
733:
734: METHOD(bus_t, child_rekey, void,
735: private_bus_t *this, child_sa_t *old, child_sa_t *new)
736: {
737: enumerator_t *enumerator;
738: ike_sa_t *ike_sa;
739: entry_t *entry;
740: bool keep;
741:
742: ike_sa = this->thread_sa->get(this->thread_sa);
743:
744: this->mutex->lock(this->mutex);
745: enumerator = this->listeners->create_enumerator(this->listeners);
746: while (enumerator->enumerate(enumerator, &entry))
747: {
748: if (entry->calling || !entry->listener->child_rekey)
749: {
750: continue;
751: }
752: entry->calling++;
753: keep = entry->listener->child_rekey(entry->listener, ike_sa,
754: old, new);
755: entry->calling--;
756: if (!keep)
757: {
758: unregister_listener(this, entry, enumerator);
759: }
760: }
761: enumerator->destroy(enumerator);
762: this->mutex->unlock(this->mutex);
763: }
764:
765: METHOD(bus_t, children_migrate, void,
766: private_bus_t *this, ike_sa_id_t *new, uint32_t unique)
767: {
768: enumerator_t *enumerator;
769: ike_sa_t *ike_sa;
770: entry_t *entry;
771: bool keep;
772:
773: ike_sa = this->thread_sa->get(this->thread_sa);
774:
775: this->mutex->lock(this->mutex);
776: enumerator = this->listeners->create_enumerator(this->listeners);
777: while (enumerator->enumerate(enumerator, &entry))
778: {
779: if (entry->calling || !entry->listener->children_migrate)
780: {
781: continue;
782: }
783: entry->calling++;
784: keep = entry->listener->children_migrate(entry->listener, ike_sa, new,
785: unique);
786: entry->calling--;
787: if (!keep)
788: {
789: unregister_listener(this, entry, enumerator);
790: }
791: }
792: enumerator->destroy(enumerator);
793: this->mutex->unlock(this->mutex);
794: }
795:
796: METHOD(bus_t, ike_updown, void,
797: private_bus_t *this, ike_sa_t *ike_sa, bool up)
798: {
799: enumerator_t *enumerator;
800: entry_t *entry;
801: bool keep;
802:
803: this->mutex->lock(this->mutex);
804: enumerator = this->listeners->create_enumerator(this->listeners);
805: while (enumerator->enumerate(enumerator, &entry))
806: {
807: if (entry->calling || !entry->listener->ike_updown)
808: {
809: continue;
810: }
811: entry->calling++;
812: keep = entry->listener->ike_updown(entry->listener, ike_sa, up);
813: entry->calling--;
814: if (!keep)
815: {
816: unregister_listener(this, entry, enumerator);
817: }
818: }
819: enumerator->destroy(enumerator);
820: this->mutex->unlock(this->mutex);
821:
822: /* a down event for IKE_SA implicitly downs all CHILD_SAs */
823: if (!up)
824: {
825: enumerator_t *enumerator;
826: child_sa_t *child_sa;
827:
828: enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
829: while (enumerator->enumerate(enumerator, (void**)&child_sa))
830: {
831: if (child_sa->get_state(child_sa) != CHILD_REKEYED &&
832: child_sa->get_state(child_sa) != CHILD_DELETED)
833: {
834: child_updown(this, child_sa, FALSE);
835: }
836: }
837: enumerator->destroy(enumerator);
838: }
839: }
840:
841: METHOD(bus_t, ike_rekey, void,
842: private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
843: {
844: enumerator_t *enumerator;
845: entry_t *entry;
846: bool keep;
847:
848: this->mutex->lock(this->mutex);
849: enumerator = this->listeners->create_enumerator(this->listeners);
850: while (enumerator->enumerate(enumerator, &entry))
851: {
852: if (entry->calling || !entry->listener->ike_rekey)
853: {
854: continue;
855: }
856: entry->calling++;
857: keep = entry->listener->ike_rekey(entry->listener, old, new);
858: entry->calling--;
859: if (!keep)
860: {
861: unregister_listener(this, entry, enumerator);
862: }
863: }
864: enumerator->destroy(enumerator);
865: this->mutex->unlock(this->mutex);
866: }
867:
868: METHOD(bus_t, ike_update, void,
869: private_bus_t *this, ike_sa_t *ike_sa, bool local, host_t *new)
870: {
871: enumerator_t *enumerator;
872: entry_t *entry;
873: bool keep;
874:
875: this->mutex->lock(this->mutex);
876: enumerator = this->listeners->create_enumerator(this->listeners);
877: while (enumerator->enumerate(enumerator, &entry))
878: {
879: if (entry->calling || !entry->listener->ike_update)
880: {
881: continue;
882: }
883: entry->calling++;
884: keep = entry->listener->ike_update(entry->listener, ike_sa, local, new);
885: entry->calling--;
886: if (!keep)
887: {
888: unregister_listener(this, entry, enumerator);
889: }
890: }
891: enumerator->destroy(enumerator);
892: this->mutex->unlock(this->mutex);
893: }
894:
895: METHOD(bus_t, ike_reestablish_pre, void,
896: private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
897: {
898: enumerator_t *enumerator;
899: entry_t *entry;
900: bool keep;
901:
902: this->mutex->lock(this->mutex);
903: enumerator = this->listeners->create_enumerator(this->listeners);
904: while (enumerator->enumerate(enumerator, &entry))
905: {
906: if (entry->calling || !entry->listener->ike_reestablish_pre)
907: {
908: continue;
909: }
910: entry->calling++;
911: keep = entry->listener->ike_reestablish_pre(entry->listener, old, new);
912: entry->calling--;
913: if (!keep)
914: {
915: unregister_listener(this, entry, enumerator);
916: }
917: }
918: enumerator->destroy(enumerator);
919: this->mutex->unlock(this->mutex);
920: }
921:
922: METHOD(bus_t, ike_reestablish_post, void,
923: private_bus_t *this, ike_sa_t *old, ike_sa_t *new, bool initiated)
924: {
925: enumerator_t *enumerator;
926: entry_t *entry;
927: bool keep;
928:
929: this->mutex->lock(this->mutex);
930: enumerator = this->listeners->create_enumerator(this->listeners);
931: while (enumerator->enumerate(enumerator, &entry))
932: {
933: if (entry->calling || !entry->listener->ike_reestablish_post)
934: {
935: continue;
936: }
937: entry->calling++;
938: keep = entry->listener->ike_reestablish_post(entry->listener, old, new,
939: initiated);
940: entry->calling--;
941: if (!keep)
942: {
943: unregister_listener(this, entry, enumerator);
944: }
945: }
946: enumerator->destroy(enumerator);
947: this->mutex->unlock(this->mutex);
948: }
949:
950: METHOD(bus_t, authorize, bool,
951: private_bus_t *this, bool final)
952: {
953: enumerator_t *enumerator;
954: ike_sa_t *ike_sa;
955: entry_t *entry;
956: bool keep, success = TRUE;
957:
958: ike_sa = this->thread_sa->get(this->thread_sa);
959:
960: this->mutex->lock(this->mutex);
961: enumerator = this->listeners->create_enumerator(this->listeners);
962: while (enumerator->enumerate(enumerator, &entry))
963: {
964: if (entry->calling || !entry->listener->authorize)
965: {
966: continue;
967: }
968: entry->calling++;
969: keep = entry->listener->authorize(entry->listener, ike_sa,
970: final, &success);
971: entry->calling--;
972: if (!keep)
973: {
974: unregister_listener(this, entry, enumerator);
975: }
976: if (!success)
977: {
978: break;
979: }
980: }
981: enumerator->destroy(enumerator);
982: this->mutex->unlock(this->mutex);
983: if (!success)
984: {
985: alert(this, ALERT_AUTHORIZATION_FAILED);
986: }
987: return success;
988: }
989:
990: METHOD(bus_t, narrow, void,
991: private_bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
992: linked_list_t *local, linked_list_t *remote)
993: {
994: enumerator_t *enumerator;
995: ike_sa_t *ike_sa;
996: entry_t *entry;
997: bool keep;
998:
999: ike_sa = this->thread_sa->get(this->thread_sa);
1000:
1001: this->mutex->lock(this->mutex);
1002: enumerator = this->listeners->create_enumerator(this->listeners);
1003: while (enumerator->enumerate(enumerator, &entry))
1004: {
1005: if (entry->calling || !entry->listener->narrow)
1006: {
1007: continue;
1008: }
1009: entry->calling++;
1010: keep = entry->listener->narrow(entry->listener, ike_sa, child_sa,
1011: type, local, remote);
1012: entry->calling--;
1013: if (!keep)
1014: {
1015: unregister_listener(this, entry, enumerator);
1016: }
1017: }
1018: enumerator->destroy(enumerator);
1019: this->mutex->unlock(this->mutex);
1020: }
1021:
1022: METHOD(bus_t, assign_vips, void,
1023: private_bus_t *this, ike_sa_t *ike_sa, bool assign)
1024: {
1025: enumerator_t *enumerator;
1026: entry_t *entry;
1027: bool keep;
1028:
1029: this->mutex->lock(this->mutex);
1030: enumerator = this->listeners->create_enumerator(this->listeners);
1031: while (enumerator->enumerate(enumerator, &entry))
1032: {
1033: if (entry->calling || !entry->listener->assign_vips)
1034: {
1035: continue;
1036: }
1037: entry->calling++;
1038: keep = entry->listener->assign_vips(entry->listener, ike_sa, assign);
1039: entry->calling--;
1040: if (!keep)
1041: {
1042: unregister_listener(this, entry, enumerator);
1043: }
1044: }
1045: enumerator->destroy(enumerator);
1046: this->mutex->unlock(this->mutex);
1047: }
1048:
1049: METHOD(bus_t, handle_vips, void,
1050: private_bus_t *this, ike_sa_t *ike_sa, bool handle)
1051: {
1052: enumerator_t *enumerator;
1053: entry_t *entry;
1054: bool keep;
1055:
1056: this->mutex->lock(this->mutex);
1057: enumerator = this->listeners->create_enumerator(this->listeners);
1058: while (enumerator->enumerate(enumerator, &entry))
1059: {
1060: if (entry->calling || !entry->listener->handle_vips)
1061: {
1062: continue;
1063: }
1064: entry->calling++;
1065: keep = entry->listener->handle_vips(entry->listener, ike_sa, handle);
1066: entry->calling--;
1067: if (!keep)
1068: {
1069: unregister_listener(this, entry, enumerator);
1070: }
1071: }
1072: enumerator->destroy(enumerator);
1073: this->mutex->unlock(this->mutex);
1074: }
1075:
1076: /**
1077: * Credential manager hook function to forward bus alerts
1078: */
1079: static void hook_creds(private_bus_t *this, credential_hook_type_t type,
1080: certificate_t *cert)
1081: {
1082: switch (type)
1083: {
1084: case CRED_HOOK_EXPIRED:
1085: return alert(this, ALERT_CERT_EXPIRED, cert);
1086: case CRED_HOOK_REVOKED:
1087: return alert(this, ALERT_CERT_REVOKED, cert);
1088: case CRED_HOOK_VALIDATION_FAILED:
1089: return alert(this, ALERT_CERT_VALIDATION_FAILED, cert);
1090: case CRED_HOOK_NO_ISSUER:
1091: return alert(this, ALERT_CERT_NO_ISSUER, cert);
1092: case CRED_HOOK_UNTRUSTED_ROOT:
1093: return alert(this, ALERT_CERT_UNTRUSTED_ROOT, cert);
1094: case CRED_HOOK_EXCEEDED_PATH_LEN:
1095: return alert(this, ALERT_CERT_EXCEEDED_PATH_LEN, cert);
1096: case CRED_HOOK_POLICY_VIOLATION:
1097: return alert(this, ALERT_CERT_POLICY_VIOLATION, cert);
1098: }
1099: }
1100:
1101: METHOD(bus_t, destroy, void,
1102: private_bus_t *this)
1103: {
1104: debug_t group;
1105:
1106: lib->credmgr->set_hook(lib->credmgr, NULL, NULL);
1107: for (group = 0; group < DBG_MAX; group++)
1108: {
1109: this->loggers[group]->destroy(this->loggers[group]);
1110: }
1111: this->loggers[DBG_MAX]->destroy_function(this->loggers[DBG_MAX],
1112: (void*)free);
1113: this->listeners->destroy_function(this->listeners, (void*)free);
1114: this->thread_sa->destroy(this->thread_sa);
1115: this->log_lock->destroy(this->log_lock);
1116: this->mutex->destroy(this->mutex);
1117: free(this);
1118: }
1119:
1120: /*
1121: * Described in header.
1122: */
1123: bus_t *bus_create()
1124: {
1125: private_bus_t *this;
1126: debug_t group;
1127:
1128: INIT(this,
1129: .public = {
1130: .add_listener = _add_listener,
1131: .remove_listener = _remove_listener,
1132: .add_logger = _add_logger,
1133: .remove_logger = _remove_logger,
1134: .set_sa = _set_sa,
1135: .get_sa = _get_sa,
1136: .log = _log_,
1137: .vlog = _vlog,
1138: .alert = _alert,
1139: .ike_state_change = _ike_state_change,
1140: .child_state_change = _child_state_change,
1141: .message = _message,
1142: .ike_keys = _ike_keys,
1143: .ike_derived_keys = _ike_derived_keys,
1144: .child_keys = _child_keys,
1145: .child_derived_keys = _child_derived_keys,
1146: .ike_updown = _ike_updown,
1147: .ike_rekey = _ike_rekey,
1148: .ike_update = _ike_update,
1149: .ike_reestablish_pre = _ike_reestablish_pre,
1150: .ike_reestablish_post = _ike_reestablish_post,
1151: .child_updown = _child_updown,
1152: .child_rekey = _child_rekey,
1153: .children_migrate = _children_migrate,
1154: .authorize = _authorize,
1155: .narrow = _narrow,
1156: .assign_vips = _assign_vips,
1157: .handle_vips = _handle_vips,
1158: .destroy = _destroy,
1159: },
1160: .listeners = linked_list_create(),
1161: .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
1162: .log_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
1163: .thread_sa = thread_value_create(NULL),
1164: );
1165:
1166: for (group = 0; group <= DBG_MAX; group++)
1167: {
1168: this->loggers[group] = linked_list_create();
1169: this->max_level[group] = LEVEL_SILENT;
1170: this->max_vlevel[group] = LEVEL_SILENT;
1171: }
1172:
1173: lib->credmgr->set_hook(lib->credmgr, (credential_hook_t)hook_creds, this);
1174:
1175: return &this->public;
1176: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>