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**)&current))
                    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>