Annotation of embedaddon/strongswan/src/libcharon/bus/bus.c, revision 1.1.1.2
1.1 misho 1: /*
1.1.1.2 ! misho 2: * Copyright (C) 2011-2020 Tobias Brunner
1.1 misho 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,
1.1.1.2 ! misho 869: private_bus_t *this, ike_sa_t *ike_sa, host_t *local, host_t *remote)
1.1 misho 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++;
1.1.1.2 ! misho 884: keep = entry->listener->ike_update(entry->listener, ike_sa, local,
! 885: remote);
1.1 misho 886: entry->calling--;
887: if (!keep)
888: {
889: unregister_listener(this, entry, enumerator);
890: }
891: }
892: enumerator->destroy(enumerator);
893: this->mutex->unlock(this->mutex);
894: }
895:
896: METHOD(bus_t, ike_reestablish_pre, void,
897: private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
898: {
899: enumerator_t *enumerator;
900: entry_t *entry;
901: bool keep;
902:
903: this->mutex->lock(this->mutex);
904: enumerator = this->listeners->create_enumerator(this->listeners);
905: while (enumerator->enumerate(enumerator, &entry))
906: {
907: if (entry->calling || !entry->listener->ike_reestablish_pre)
908: {
909: continue;
910: }
911: entry->calling++;
912: keep = entry->listener->ike_reestablish_pre(entry->listener, old, new);
913: entry->calling--;
914: if (!keep)
915: {
916: unregister_listener(this, entry, enumerator);
917: }
918: }
919: enumerator->destroy(enumerator);
920: this->mutex->unlock(this->mutex);
921: }
922:
923: METHOD(bus_t, ike_reestablish_post, void,
924: private_bus_t *this, ike_sa_t *old, ike_sa_t *new, bool initiated)
925: {
926: enumerator_t *enumerator;
927: entry_t *entry;
928: bool keep;
929:
930: this->mutex->lock(this->mutex);
931: enumerator = this->listeners->create_enumerator(this->listeners);
932: while (enumerator->enumerate(enumerator, &entry))
933: {
934: if (entry->calling || !entry->listener->ike_reestablish_post)
935: {
936: continue;
937: }
938: entry->calling++;
939: keep = entry->listener->ike_reestablish_post(entry->listener, old, new,
940: initiated);
941: entry->calling--;
942: if (!keep)
943: {
944: unregister_listener(this, entry, enumerator);
945: }
946: }
947: enumerator->destroy(enumerator);
948: this->mutex->unlock(this->mutex);
949: }
950:
951: METHOD(bus_t, authorize, bool,
952: private_bus_t *this, bool final)
953: {
954: enumerator_t *enumerator;
955: ike_sa_t *ike_sa;
956: entry_t *entry;
957: bool keep, success = TRUE;
958:
959: ike_sa = this->thread_sa->get(this->thread_sa);
960:
961: this->mutex->lock(this->mutex);
962: enumerator = this->listeners->create_enumerator(this->listeners);
963: while (enumerator->enumerate(enumerator, &entry))
964: {
965: if (entry->calling || !entry->listener->authorize)
966: {
967: continue;
968: }
969: entry->calling++;
970: keep = entry->listener->authorize(entry->listener, ike_sa,
971: final, &success);
972: entry->calling--;
973: if (!keep)
974: {
975: unregister_listener(this, entry, enumerator);
976: }
977: if (!success)
978: {
979: break;
980: }
981: }
982: enumerator->destroy(enumerator);
983: this->mutex->unlock(this->mutex);
984: if (!success)
985: {
986: alert(this, ALERT_AUTHORIZATION_FAILED);
987: }
988: return success;
989: }
990:
991: METHOD(bus_t, narrow, void,
992: private_bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
993: linked_list_t *local, linked_list_t *remote)
994: {
995: enumerator_t *enumerator;
996: ike_sa_t *ike_sa;
997: entry_t *entry;
998: bool keep;
999:
1000: ike_sa = this->thread_sa->get(this->thread_sa);
1001:
1002: this->mutex->lock(this->mutex);
1003: enumerator = this->listeners->create_enumerator(this->listeners);
1004: while (enumerator->enumerate(enumerator, &entry))
1005: {
1006: if (entry->calling || !entry->listener->narrow)
1007: {
1008: continue;
1009: }
1010: entry->calling++;
1011: keep = entry->listener->narrow(entry->listener, ike_sa, child_sa,
1012: type, local, remote);
1013: entry->calling--;
1014: if (!keep)
1015: {
1016: unregister_listener(this, entry, enumerator);
1017: }
1018: }
1019: enumerator->destroy(enumerator);
1020: this->mutex->unlock(this->mutex);
1021: }
1022:
1023: METHOD(bus_t, assign_vips, void,
1024: private_bus_t *this, ike_sa_t *ike_sa, bool assign)
1025: {
1026: enumerator_t *enumerator;
1027: entry_t *entry;
1028: bool keep;
1029:
1030: this->mutex->lock(this->mutex);
1031: enumerator = this->listeners->create_enumerator(this->listeners);
1032: while (enumerator->enumerate(enumerator, &entry))
1033: {
1034: if (entry->calling || !entry->listener->assign_vips)
1035: {
1036: continue;
1037: }
1038: entry->calling++;
1039: keep = entry->listener->assign_vips(entry->listener, ike_sa, assign);
1040: entry->calling--;
1041: if (!keep)
1042: {
1043: unregister_listener(this, entry, enumerator);
1044: }
1045: }
1046: enumerator->destroy(enumerator);
1047: this->mutex->unlock(this->mutex);
1048: }
1049:
1050: METHOD(bus_t, handle_vips, void,
1051: private_bus_t *this, ike_sa_t *ike_sa, bool handle)
1052: {
1053: enumerator_t *enumerator;
1054: entry_t *entry;
1055: bool keep;
1056:
1057: this->mutex->lock(this->mutex);
1058: enumerator = this->listeners->create_enumerator(this->listeners);
1059: while (enumerator->enumerate(enumerator, &entry))
1060: {
1061: if (entry->calling || !entry->listener->handle_vips)
1062: {
1063: continue;
1064: }
1065: entry->calling++;
1066: keep = entry->listener->handle_vips(entry->listener, ike_sa, handle);
1067: entry->calling--;
1068: if (!keep)
1069: {
1070: unregister_listener(this, entry, enumerator);
1071: }
1072: }
1073: enumerator->destroy(enumerator);
1074: this->mutex->unlock(this->mutex);
1075: }
1076:
1077: /**
1078: * Credential manager hook function to forward bus alerts
1079: */
1080: static void hook_creds(private_bus_t *this, credential_hook_type_t type,
1081: certificate_t *cert)
1082: {
1083: switch (type)
1084: {
1085: case CRED_HOOK_EXPIRED:
1086: return alert(this, ALERT_CERT_EXPIRED, cert);
1087: case CRED_HOOK_REVOKED:
1088: return alert(this, ALERT_CERT_REVOKED, cert);
1089: case CRED_HOOK_VALIDATION_FAILED:
1090: return alert(this, ALERT_CERT_VALIDATION_FAILED, cert);
1091: case CRED_HOOK_NO_ISSUER:
1092: return alert(this, ALERT_CERT_NO_ISSUER, cert);
1093: case CRED_HOOK_UNTRUSTED_ROOT:
1094: return alert(this, ALERT_CERT_UNTRUSTED_ROOT, cert);
1095: case CRED_HOOK_EXCEEDED_PATH_LEN:
1096: return alert(this, ALERT_CERT_EXCEEDED_PATH_LEN, cert);
1097: case CRED_HOOK_POLICY_VIOLATION:
1098: return alert(this, ALERT_CERT_POLICY_VIOLATION, cert);
1099: }
1100: }
1101:
1102: METHOD(bus_t, destroy, void,
1103: private_bus_t *this)
1104: {
1105: debug_t group;
1106:
1107: lib->credmgr->set_hook(lib->credmgr, NULL, NULL);
1108: for (group = 0; group < DBG_MAX; group++)
1109: {
1110: this->loggers[group]->destroy(this->loggers[group]);
1111: }
1112: this->loggers[DBG_MAX]->destroy_function(this->loggers[DBG_MAX],
1113: (void*)free);
1114: this->listeners->destroy_function(this->listeners, (void*)free);
1115: this->thread_sa->destroy(this->thread_sa);
1116: this->log_lock->destroy(this->log_lock);
1117: this->mutex->destroy(this->mutex);
1118: free(this);
1119: }
1120:
1121: /*
1122: * Described in header.
1123: */
1124: bus_t *bus_create()
1125: {
1126: private_bus_t *this;
1127: debug_t group;
1128:
1129: INIT(this,
1130: .public = {
1131: .add_listener = _add_listener,
1132: .remove_listener = _remove_listener,
1133: .add_logger = _add_logger,
1134: .remove_logger = _remove_logger,
1135: .set_sa = _set_sa,
1136: .get_sa = _get_sa,
1137: .log = _log_,
1138: .vlog = _vlog,
1139: .alert = _alert,
1140: .ike_state_change = _ike_state_change,
1141: .child_state_change = _child_state_change,
1142: .message = _message,
1143: .ike_keys = _ike_keys,
1144: .ike_derived_keys = _ike_derived_keys,
1145: .child_keys = _child_keys,
1146: .child_derived_keys = _child_derived_keys,
1147: .ike_updown = _ike_updown,
1148: .ike_rekey = _ike_rekey,
1149: .ike_update = _ike_update,
1150: .ike_reestablish_pre = _ike_reestablish_pre,
1151: .ike_reestablish_post = _ike_reestablish_post,
1152: .child_updown = _child_updown,
1153: .child_rekey = _child_rekey,
1154: .children_migrate = _children_migrate,
1155: .authorize = _authorize,
1156: .narrow = _narrow,
1157: .assign_vips = _assign_vips,
1158: .handle_vips = _handle_vips,
1159: .destroy = _destroy,
1160: },
1161: .listeners = linked_list_create(),
1162: .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
1163: .log_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
1164: .thread_sa = thread_value_create(NULL),
1165: );
1166:
1167: for (group = 0; group <= DBG_MAX; group++)
1168: {
1169: this->loggers[group] = linked_list_create();
1170: this->max_level[group] = LEVEL_SILENT;
1171: this->max_vlevel[group] = LEVEL_SILENT;
1172: }
1173:
1174: lib->credmgr->set_hook(lib->credmgr, (credential_hook_t)hook_creds, this);
1175:
1176: return &this->public;
1177: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>