Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/mode_config.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2011 Martin Willi
                      3:  * Copyright (C) 2011 revosec AG
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "mode_config.h"
                     17: 
                     18: #include <daemon.h>
                     19: #include <encoding/payloads/cp_payload.h>
                     20: 
                     21: typedef struct private_mode_config_t private_mode_config_t;
                     22: 
                     23: /**
                     24:  * Private members of a mode_config_t task.
                     25:  */
                     26: struct private_mode_config_t {
                     27: 
                     28:        /**
                     29:         * Public methods and task_t interface.
                     30:         */
                     31:        mode_config_t public;
                     32: 
                     33:        /**
                     34:         * Assigned IKE_SA.
                     35:         */
                     36:        ike_sa_t *ike_sa;
                     37: 
                     38:        /**
                     39:         * Are we the initiator?
                     40:         */
                     41:        bool initiator;
                     42: 
                     43:        /**
                     44:         * Use pull (CFG_REQUEST/RESPONSE) or push (CFG_SET/ACK)?
                     45:         */
                     46:        bool pull;
                     47: 
                     48:        /**
                     49:         * Received list of virtual IPs, host_t*
                     50:         */
                     51:        linked_list_t *vips;
                     52: 
                     53:        /**
                     54:         * Requested/received list of attributes, entry_t
                     55:         */
                     56:        linked_list_t *attributes;
                     57: 
                     58:        /**
                     59:         * Identifier to include in response
                     60:         */
                     61:        uint16_t identifier;
                     62: };
                     63: 
                     64: /**
                     65:  * Entry for a attribute and associated handler
                     66:  */
                     67: typedef struct {
                     68:        /** attribute type */
                     69:        configuration_attribute_type_t type;
                     70:        /** handler for this attribute */
                     71:        attribute_handler_t *handler;
                     72: } entry_t;
                     73: 
                     74: /**
                     75:  * build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
                     76:  */
                     77: static configuration_attribute_t *build_vip(host_t *vip)
                     78: {
                     79:        configuration_attribute_type_t type = INTERNAL_IP4_ADDRESS;
                     80:        chunk_t chunk;
                     81: 
                     82:        if (vip->get_family(vip) == AF_INET6)
                     83:        {
                     84:                type = INTERNAL_IP6_ADDRESS;
                     85:        }
                     86:        if (vip->is_anyaddr(vip))
                     87:        {
                     88:                chunk = chunk_empty;
                     89:        }
                     90:        else
                     91:        {
                     92:                chunk = vip->get_address(vip);
                     93:        }
                     94:        return configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE,
                     95:                                                                                                type, chunk);
                     96: }
                     97: 
                     98: /**
                     99:  * Handle a received attribute as initiator
                    100:  */
                    101: static void handle_attribute(private_mode_config_t *this,
                    102:                                                         configuration_attribute_t *ca)
                    103: {
                    104:        attribute_handler_t *handler = NULL;
                    105:        enumerator_t *enumerator;
                    106:        entry_t *entry;
                    107: 
                    108:        /* find the handler which requested this attribute */
                    109:        enumerator = this->attributes->create_enumerator(this->attributes);
                    110:        while (enumerator->enumerate(enumerator, &entry))
                    111:        {
                    112:                if (entry->type == ca->get_type(ca))
                    113:                {
                    114:                        handler = entry->handler;
                    115:                        this->attributes->remove_at(this->attributes, enumerator);
                    116:                        free(entry);
                    117:                        break;
                    118:                }
                    119:        }
                    120:        enumerator->destroy(enumerator);
                    121: 
                    122:        /* and pass it to the handle function */
                    123:        handler = charon->attributes->handle(charon->attributes,
                    124:                                        this->ike_sa, handler, ca->get_type(ca), ca->get_chunk(ca));
                    125:        this->ike_sa->add_configuration_attribute(this->ike_sa,
                    126:                                                        handler, ca->get_type(ca), ca->get_chunk(ca));
                    127: }
                    128: 
                    129: /**
                    130:  * process a single configuration attribute
                    131:  */
                    132: static void process_attribute(private_mode_config_t *this,
                    133:                                                          configuration_attribute_t *ca)
                    134: {
                    135:        host_t *ip;
                    136:        chunk_t addr;
                    137:        int family = AF_INET6;
                    138: 
                    139:        switch (ca->get_type(ca))
                    140:        {
                    141:                case INTERNAL_IP4_ADDRESS:
                    142:                        family = AF_INET;
                    143:                        /* fall */
                    144:                case INTERNAL_IP6_ADDRESS:
                    145:                {
                    146:                        addr = ca->get_chunk(ca);
                    147:                        if (addr.len == 0)
                    148:                        {
                    149:                                ip = host_create_any(family);
                    150:                        }
                    151:                        else
                    152:                        {
                    153:                                /* skip prefix byte in IPv6 payload sent by older releases */
                    154:                                if (family == AF_INET6 && addr.len == 17)
                    155:                                {
                    156:                                        addr.len--;
                    157:                                }
                    158:                                ip = host_create_from_chunk(family, addr, 0);
                    159:                        }
                    160:                        if (ip)
                    161:                        {
                    162:                                this->vips->insert_last(this->vips, ip);
                    163:                        }
                    164:                        break;
                    165:                }
                    166:                default:
                    167:                {
                    168:                        if (this->initiator == this->pull)
                    169:                        {
                    170:                                handle_attribute(this, ca);
                    171:                        }
                    172:                }
                    173:        }
                    174: }
                    175: 
                    176: /**
                    177:  * Check if config allows push mode when acting as task responder
                    178:  */
                    179: static bool accept_push(private_mode_config_t *this)
                    180: {
                    181:        enumerator_t *enumerator;
                    182:        peer_cfg_t *config;
                    183:        bool vip;
                    184:        host_t *host;
                    185: 
                    186:        config = this->ike_sa->get_peer_cfg(this->ike_sa);
                    187:        enumerator = config->create_virtual_ip_enumerator(config);
                    188:        vip = enumerator->enumerate(enumerator, &host);
                    189:        enumerator->destroy(enumerator);
                    190: 
                    191:        return vip && !config->use_pull_mode(config);
                    192: }
                    193: 
                    194: /**
                    195:  * Scan for configuration payloads and attributes
                    196:  */
                    197: static void process_payloads(private_mode_config_t *this, message_t *message)
                    198: {
                    199:        enumerator_t *enumerator, *attributes;
                    200:        payload_t *payload;
                    201: 
                    202:        enumerator = message->create_payload_enumerator(message);
                    203:        while (enumerator->enumerate(enumerator, &payload))
                    204:        {
                    205:                if (payload->get_type(payload) == PLV1_CONFIGURATION)
                    206:                {
                    207:                        cp_payload_t *cp = (cp_payload_t*)payload;
                    208:                        configuration_attribute_t *ca;
                    209: 
                    210:                        switch (cp->get_type(cp))
                    211:                        {
                    212:                                case CFG_SET:
                    213:                                        /* when acting as a responder, we detect the mode using
                    214:                                         * the type of configuration payload. But we should double
                    215:                                         * check the peer is allowed to use push mode on us. */
                    216:                                        if (!this->initiator && accept_push(this))
                    217:                                        {
                    218:                                                this->pull = FALSE;
                    219:                                        }
                    220:                                        /* FALL */
                    221:                                case CFG_REQUEST:
                    222:                                        this->identifier = cp->get_identifier(cp);
                    223:                                        /* FALL */
                    224:                                case CFG_REPLY:
                    225:                                        attributes = cp->create_attribute_enumerator(cp);
                    226:                                        while (attributes->enumerate(attributes, &ca))
                    227:                                        {
                    228:                                                DBG2(DBG_IKE, "processing %N attribute",
                    229:                                                         configuration_attribute_type_names, ca->get_type(ca));
                    230:                                                process_attribute(this, ca);
                    231:                                        }
                    232:                                        attributes->destroy(attributes);
                    233:                                        break;
                    234:                                case CFG_ACK:
                    235:                                        break;
                    236:                                default:
                    237:                                        DBG1(DBG_IKE, "ignoring %N config payload",
                    238:                                                 config_type_names, cp->get_type(cp));
                    239:                                        break;
                    240:                        }
                    241:                }
                    242:        }
                    243:        enumerator->destroy(enumerator);
                    244: }
                    245: 
                    246: /**
                    247:  * Add an attribute to a configuration payload, and store it in task
                    248:  */
                    249: static void add_attribute(private_mode_config_t *this, cp_payload_t *cp,
                    250:                                                  configuration_attribute_type_t type, chunk_t data,
                    251:                                                  attribute_handler_t *handler)
                    252: {
                    253:        entry_t *entry;
                    254: 
                    255:        cp->add_attribute(cp,
                    256:                        configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE,
                    257:                                                                                                 type, data));
                    258:        INIT(entry,
                    259:                .type = type,
                    260:                .handler = handler,
                    261:        );
                    262:        this->attributes->insert_last(this->attributes, entry);
                    263: }
                    264: 
                    265: /**
                    266:  * Build a CFG_REQUEST as initiator
                    267:  */
                    268: static status_t build_request(private_mode_config_t *this, message_t *message)
                    269: {
                    270:        cp_payload_t *cp;
                    271:        enumerator_t *enumerator;
                    272:        attribute_handler_t *handler;
                    273:        peer_cfg_t *config;
                    274:        configuration_attribute_type_t type;
                    275:        chunk_t data;
                    276:        linked_list_t *vips;
                    277:        host_t *host;
                    278: 
                    279:        cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
                    280: 
                    281:        vips = linked_list_create();
                    282: 
                    283:        /* reuse virtual IP if we already have one */
                    284:        enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
                    285:        while (enumerator->enumerate(enumerator, &host))
                    286:        {
                    287:                vips->insert_last(vips, host);
                    288:        }
                    289:        enumerator->destroy(enumerator);
                    290: 
                    291:        if (vips->get_count(vips) == 0)
                    292:        {
                    293:                config = this->ike_sa->get_peer_cfg(this->ike_sa);
                    294:                enumerator = config->create_virtual_ip_enumerator(config);
                    295:                while (enumerator->enumerate(enumerator, &host))
                    296:                {
                    297:                        vips->insert_last(vips, host);
                    298:                }
                    299:                enumerator->destroy(enumerator);
                    300:        }
                    301: 
                    302:        if (vips->get_count(vips))
                    303:        {
                    304:                enumerator = vips->create_enumerator(vips);
                    305:                while (enumerator->enumerate(enumerator, &host))
                    306:                {
                    307:                        cp->add_attribute(cp, build_vip(host));
                    308:                }
                    309:                enumerator->destroy(enumerator);
                    310:        }
                    311: 
                    312:        enumerator = charon->attributes->create_initiator_enumerator(
                    313:                                                                                charon->attributes, this->ike_sa, vips);
                    314:        while (enumerator->enumerate(enumerator, &handler, &type, &data))
                    315:        {
                    316:                add_attribute(this, cp, type, data, handler);
                    317:        }
                    318:        enumerator->destroy(enumerator);
                    319: 
                    320:        vips->destroy(vips);
                    321: 
                    322:        message->add_payload(message, (payload_t*)cp);
                    323: 
                    324:        return NEED_MORE;
                    325: }
                    326: 
                    327: /**
                    328:  * Build a CFG_SET as initiator
                    329:  */
                    330: static status_t build_set(private_mode_config_t *this, message_t *message)
                    331: {
                    332:        enumerator_t *enumerator;
                    333:        configuration_attribute_type_t type;
                    334:        chunk_t value;
                    335:        cp_payload_t *cp;
                    336:        peer_cfg_t *config;
                    337:        identification_t *id;
                    338:        linked_list_t *pools, *migrated, *vips;
                    339:        host_t *any4, *any6, *found;
                    340:        char *name;
                    341: 
                    342:        cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_SET);
                    343: 
                    344:        id = this->ike_sa->get_other_eap_id(this->ike_sa);
                    345:        config = this->ike_sa->get_peer_cfg(this->ike_sa);
                    346: 
                    347:        /* if we migrated virtual IPs during reauthentication, reassign them */
                    348:        migrated = linked_list_create_from_enumerator(
                    349:                                                this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
                    350:                                                                                                                                   FALSE));
                    351:        vips = migrated->clone_offset(migrated, offsetof(host_t, clone));
                    352:        migrated->destroy(migrated);
                    353:        this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE);
                    354: 
                    355:        /* in push mode, we ask each configured pool for an address */
                    356:        if (!vips->get_count(vips))
                    357:        {
                    358:                any4 = host_create_any(AF_INET);
                    359:                any6 = host_create_any(AF_INET6);
                    360:                enumerator = config->create_pool_enumerator(config);
                    361:                while (enumerator->enumerate(enumerator, &name))
                    362:                {
                    363:                        pools = linked_list_create_with_items(name, NULL);
                    364:                        /* try IPv4, then IPv6 */
                    365:                        found = charon->attributes->acquire_address(charon->attributes,
                    366:                                                                                                        pools, this->ike_sa, any4);
                    367:                        if (!found)
                    368:                        {
                    369:                                found = charon->attributes->acquire_address(charon->attributes,
                    370:                                                                                                        pools, this->ike_sa, any6);
                    371:                        }
                    372:                        pools->destroy(pools);
                    373:                        if (found)
                    374:                        {
                    375:                                vips->insert_last(vips, found);
                    376:                        }
                    377:                }
                    378:                enumerator->destroy(enumerator);
                    379:                any4->destroy(any4);
                    380:                any6->destroy(any6);
                    381:        }
                    382: 
                    383:        enumerator = vips->create_enumerator(vips);
                    384:        while (enumerator->enumerate(enumerator, &found))
                    385:        {
                    386:                DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
                    387:                this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
                    388:                cp->add_attribute(cp, build_vip(found));
                    389:                this->vips->insert_last(this->vips, found);
                    390:                vips->remove_at(vips, enumerator);
                    391:        }
                    392:        enumerator->destroy(enumerator);
                    393:        vips->destroy(vips);
                    394: 
                    395:        charon->bus->assign_vips(charon->bus, this->ike_sa, TRUE);
                    396: 
                    397:        /* query registered providers for additional attributes to include */
                    398:        pools = linked_list_create_from_enumerator(
                    399:                                                                        config->create_pool_enumerator(config));
                    400:        enumerator = charon->attributes->create_responder_enumerator(
                    401:                                                charon->attributes, pools, this->ike_sa, this->vips);
                    402:        while (enumerator->enumerate(enumerator, &type, &value))
                    403:        {
                    404:                add_attribute(this, cp, type, value, NULL);
                    405:        }
                    406:        enumerator->destroy(enumerator);
                    407:        pools->destroy(pools);
                    408: 
                    409:        message->add_payload(message, (payload_t*)cp);
                    410: 
                    411:        return SUCCESS;
                    412: }
                    413: 
                    414: METHOD(task_t, build_i, status_t,
                    415:        private_mode_config_t *this, message_t *message)
                    416: {
                    417:        if (this->pull)
                    418:        {
                    419:                return build_request(this, message);
                    420:        }
                    421:        return build_set(this, message);
                    422: }
                    423: 
                    424: /**
                    425:  * Store received virtual IPs to the IKE_SA, install them
                    426:  */
                    427: static void install_vips(private_mode_config_t *this)
                    428: {
                    429:        enumerator_t *enumerator;
                    430:        host_t *host;
                    431: 
                    432:        this->ike_sa->clear_virtual_ips(this->ike_sa, TRUE);
                    433: 
                    434:        enumerator = this->vips->create_enumerator(this->vips);
                    435:        while (enumerator->enumerate(enumerator, &host))
                    436:        {
                    437:                if (!host->is_anyaddr(host))
                    438:                {
                    439:                        this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
                    440:                }
                    441:        }
                    442:        enumerator->destroy(enumerator);
                    443: 
                    444:        charon->bus->handle_vips(charon->bus, this->ike_sa, TRUE);
                    445: }
                    446: 
                    447: METHOD(task_t, process_r, status_t,
                    448:        private_mode_config_t *this, message_t *message)
                    449: {
                    450:        process_payloads(this, message);
                    451: 
                    452:        if (!this->pull)
                    453:        {
                    454:                install_vips(this);
                    455:        }
                    456:        return NEED_MORE;
                    457: }
                    458: 
                    459: /**
                    460:  * Assign a migrated virtual IP
                    461:  */
                    462: static host_t *assign_migrated_vip(linked_list_t *migrated, host_t *requested)
                    463: {
                    464:        enumerator_t *enumerator;
                    465:        host_t *found = NULL, *vip;
                    466: 
                    467:        enumerator = migrated->create_enumerator(migrated);
                    468:        while (enumerator->enumerate(enumerator, &vip))
                    469:        {
                    470:                if (vip->ip_equals(vip, requested) ||
                    471:                   (requested->is_anyaddr(requested) &&
                    472:                        requested->get_family(requested) == vip->get_family(vip)))
                    473:                {
                    474:                        migrated->remove_at(migrated, enumerator);
                    475:                        found = vip;
                    476:                        break;
                    477:                }
                    478:        }
                    479:        enumerator->destroy(enumerator);
                    480:        return found;
                    481: }
                    482: 
                    483: /**
                    484:  * Build CFG_REPLY message after receiving CFG_REQUEST
                    485:  */
                    486: static status_t build_reply(private_mode_config_t *this, message_t *message)
                    487: {
                    488:        enumerator_t *enumerator;
                    489:        configuration_attribute_type_t type;
                    490:        chunk_t value;
                    491:        cp_payload_t *cp;
                    492:        peer_cfg_t *config;
                    493:        identification_t *id;
                    494:        linked_list_t *vips, *pools, *migrated;
                    495:        host_t *requested, *found;
                    496: 
                    497:        cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
                    498: 
                    499:        id = this->ike_sa->get_other_eap_id(this->ike_sa);
                    500:        config = this->ike_sa->get_peer_cfg(this->ike_sa);
                    501:        pools = linked_list_create_from_enumerator(
                    502:                                                                        config->create_pool_enumerator(config));
                    503:        /* if we migrated virtual IPs during reauthentication, reassign them */
                    504:        vips = linked_list_create_from_enumerator(
                    505:                                                this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
                    506:                                                                                                                                   FALSE));
                    507:        migrated = vips->clone_offset(vips, offsetof(host_t, clone));
                    508:        vips->destroy(vips);
                    509:        this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE);
                    510: 
                    511:        vips = linked_list_create();
                    512:        enumerator = this->vips->create_enumerator(this->vips);
                    513:        while (enumerator->enumerate(enumerator, &requested))
                    514:        {
                    515:                DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
                    516: 
                    517:                found = assign_migrated_vip(migrated, requested);
                    518:                if (!found)
                    519:                {
                    520:                        found = charon->attributes->acquire_address(charon->attributes,
                    521:                                                                                        pools, this->ike_sa, requested);
                    522:                }
                    523:                if (found)
                    524:                {
                    525:                        DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
                    526:                        this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
                    527:                        cp->add_attribute(cp, build_vip(found));
                    528:                        vips->insert_last(vips, found);
                    529:                }
                    530:                else
                    531:                {
                    532:                        DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
                    533:                                 requested, id);
                    534:                }
                    535:        }
                    536:        enumerator->destroy(enumerator);
                    537: 
                    538:        charon->bus->assign_vips(charon->bus, this->ike_sa, TRUE);
                    539: 
                    540:        /* query registered providers for additional attributes to include */
                    541:        enumerator = charon->attributes->create_responder_enumerator(
                    542:                                                                charon->attributes, pools, this->ike_sa, vips);
                    543:        while (enumerator->enumerate(enumerator, &type, &value))
                    544:        {
                    545:                cp->add_attribute(cp,
                    546:                        configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE,
                    547:                                                                                                 type, value));
                    548:        }
                    549:        enumerator->destroy(enumerator);
                    550:        /* if a client did not re-request all addresses, release them */
                    551:        enumerator = migrated->create_enumerator(migrated);
                    552:        while (enumerator->enumerate(enumerator, &found))
                    553:        {
                    554:                charon->attributes->release_address(charon->attributes,
                    555:                                                                                        pools, found, this->ike_sa);
                    556:        }
                    557:        enumerator->destroy(enumerator);
                    558:        migrated->destroy_offset(migrated, offsetof(host_t, destroy));
                    559:        vips->destroy_offset(vips, offsetof(host_t, destroy));
                    560:        pools->destroy(pools);
                    561: 
                    562:        cp->set_identifier(cp, this->identifier);
                    563:        message->add_payload(message, (payload_t*)cp);
                    564: 
                    565:        return SUCCESS;
                    566: }
                    567: 
                    568: /**
                    569:  * Build CFG_ACK for a received CFG_SET
                    570:  */
                    571: static status_t build_ack(private_mode_config_t *this, message_t *message)
                    572: {
                    573:        cp_payload_t *cp;
                    574:        enumerator_t *enumerator;
                    575:        host_t *host;
                    576:        configuration_attribute_type_t type;
                    577:        entry_t *entry;
                    578: 
                    579:        cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_ACK);
                    580: 
                    581:        /* return empty attributes for installed IPs */
                    582: 
                    583:        enumerator = this->vips->create_enumerator(this->vips);
                    584:        while (enumerator->enumerate(enumerator, &host))
                    585:        {
                    586:                if (host->get_family(host) == AF_INET6)
                    587:                {
                    588:                        type = INTERNAL_IP6_ADDRESS;
                    589:                }
                    590:                else
                    591:                {
                    592:                        type = INTERNAL_IP4_ADDRESS;
                    593:                }
                    594:                cp->add_attribute(cp, configuration_attribute_create_chunk(
                    595:                                                                PLV1_CONFIGURATION_ATTRIBUTE, type, chunk_empty));
                    596:        }
                    597:        enumerator->destroy(enumerator);
                    598: 
                    599:        enumerator = this->attributes->create_enumerator(this->attributes);
                    600:        while (enumerator->enumerate(enumerator, &entry))
                    601:        {
                    602:                cp->add_attribute(cp,
                    603:                        configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE,
                    604:                                                                                                 entry->type, chunk_empty));
                    605:        }
                    606:        enumerator->destroy(enumerator);
                    607: 
                    608:        cp->set_identifier(cp, this->identifier);
                    609:        message->add_payload(message, (payload_t*)cp);
                    610: 
                    611:        return SUCCESS;
                    612: }
                    613: 
                    614: METHOD(task_t, build_r, status_t,
                    615:        private_mode_config_t *this, message_t *message)
                    616: {
                    617:        if (this->pull)
                    618:        {
                    619:                return build_reply(this, message);
                    620:        }
                    621:        return build_ack(this, message);
                    622: }
                    623: 
                    624: METHOD(task_t, process_i, status_t,
                    625:        private_mode_config_t *this, message_t *message)
                    626: {
                    627:        process_payloads(this, message);
                    628: 
                    629:        if (this->pull)
                    630:        {
                    631:                install_vips(this);
                    632:        }
                    633:        return SUCCESS;
                    634: }
                    635: 
                    636: METHOD(task_t, get_type, task_type_t,
                    637:        private_mode_config_t *this)
                    638: {
                    639:        return TASK_MODE_CONFIG;
                    640: }
                    641: 
                    642: METHOD(task_t, migrate, void,
                    643:        private_mode_config_t *this, ike_sa_t *ike_sa)
                    644: {
                    645:        this->ike_sa = ike_sa;
                    646:        this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
                    647:        this->vips = linked_list_create();
                    648:        this->attributes->destroy_function(this->attributes, free);
                    649:        this->attributes = linked_list_create();
                    650: }
                    651: 
                    652: METHOD(task_t, destroy, void,
                    653:        private_mode_config_t *this)
                    654: {
                    655:        this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
                    656:        this->attributes->destroy_function(this->attributes, free);
                    657:        free(this);
                    658: }
                    659: 
                    660: /*
                    661:  * Described in header.
                    662:  */
                    663: mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator, bool pull)
                    664: {
                    665:        private_mode_config_t *this;
                    666: 
                    667:        INIT(this,
                    668:                .public = {
                    669:                        .task = {
                    670:                                .get_type = _get_type,
                    671:                                .migrate = _migrate,
                    672:                                .destroy = _destroy,
                    673:                        },
                    674:                },
                    675:                .initiator = initiator,
                    676:                .pull = initiator ? pull : TRUE,
                    677:                .ike_sa = ike_sa,
                    678:                .attributes = linked_list_create(),
                    679:                .vips = linked_list_create(),
                    680:        );
                    681: 
                    682:        if (initiator)
                    683:        {
                    684:                this->public.task.build = _build_i;
                    685:                this->public.task.process = _process_i;
                    686:        }
                    687:        else
                    688:        {
                    689:                this->public.task.build = _build_r;
                    690:                this->public.task.process = _process_r;
                    691:        }
                    692: 
                    693:        return &this->public;
                    694: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>