Annotation of embedaddon/strongswan/src/libcharon/bus/bus.c, revision 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>