Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_mobike.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2010-2018 Tobias Brunner
        !             3:  * Copyright (C) 2007 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 "ike_mobike.h"
        !            18: 
        !            19: #include <string.h>
        !            20: 
        !            21: #include <daemon.h>
        !            22: #include <sa/ikev2/tasks/ike_natd.h>
        !            23: #include <encoding/payloads/notify_payload.h>
        !            24: 
        !            25: #define COOKIE2_SIZE 16
        !            26: #define MAX_ADDITIONAL_ADDRS 8
        !            27: 
        !            28: typedef struct private_ike_mobike_t private_ike_mobike_t;
        !            29: 
        !            30: /**
        !            31:  * Private members of a ike_mobike_t task.
        !            32:  */
        !            33: struct private_ike_mobike_t {
        !            34: 
        !            35:        /**
        !            36:         * Public methods and task_t interface.
        !            37:         */
        !            38:        ike_mobike_t public;
        !            39: 
        !            40:        /**
        !            41:         * Assigned IKE_SA.
        !            42:         */
        !            43:        ike_sa_t *ike_sa;
        !            44: 
        !            45:        /**
        !            46:         * Are we the initiator?
        !            47:         */
        !            48:        bool initiator;
        !            49: 
        !            50:        /**
        !            51:         * cookie2 value to verify new addresses
        !            52:         */
        !            53:        chunk_t cookie2;
        !            54: 
        !            55:        /**
        !            56:         * NAT discovery reusing the TASK_IKE_NATD task
        !            57:         */
        !            58:        ike_natd_t *natd;
        !            59: 
        !            60:        /**
        !            61:         * use task to update addresses
        !            62:         */
        !            63:        bool update;
        !            64: 
        !            65:        /**
        !            66:         * do routability check
        !            67:         */
        !            68:        bool check;
        !            69: 
        !            70:        /**
        !            71:         * include address list update
        !            72:         */
        !            73:        bool address;
        !            74: 
        !            75:        /**
        !            76:         * additional addresses got updated
        !            77:         */
        !            78:        bool addresses_updated;
        !            79: };
        !            80: 
        !            81: /**
        !            82:  * Check if a newer MOBIKE update task is queued
        !            83:  */
        !            84: static bool is_newer_update_queued(private_ike_mobike_t *this)
        !            85: {
        !            86:        enumerator_t *enumerator;
        !            87:        private_ike_mobike_t *mobike;
        !            88:        task_t *task;
        !            89:        bool found = FALSE;
        !            90: 
        !            91:        enumerator = this->ike_sa->create_task_enumerator(this->ike_sa,
        !            92:                                                                                                          TASK_QUEUE_QUEUED);
        !            93:        while (enumerator->enumerate(enumerator, &task))
        !            94:        {
        !            95:                if (task->get_type(task) == TASK_IKE_MOBIKE)
        !            96:                {
        !            97:                        mobike = (private_ike_mobike_t*)task;
        !            98:                        /* a queued check or update might invalidate the results of the
        !            99:                         * current task */
        !           100:                        found = mobike->check || mobike->update;
        !           101:                        break;
        !           102:                }
        !           103:        }
        !           104:        enumerator->destroy(enumerator);
        !           105:        return found;
        !           106: }
        !           107: 
        !           108: /**
        !           109:  * read notifys from message and evaluate them
        !           110:  */
        !           111: static void process_payloads(private_ike_mobike_t *this, message_t *message)
        !           112: {
        !           113:        enumerator_t *enumerator;
        !           114:        payload_t *payload;
        !           115:        bool first = TRUE;
        !           116: 
        !           117:        enumerator = message->create_payload_enumerator(message);
        !           118:        while (enumerator->enumerate(enumerator, &payload))
        !           119:        {
        !           120:                int family = AF_INET;
        !           121:                notify_payload_t *notify;
        !           122:                chunk_t data;
        !           123:                host_t *host;
        !           124: 
        !           125:                if (payload->get_type(payload) != PLV2_NOTIFY)
        !           126:                {
        !           127:                        continue;
        !           128:                }
        !           129:                notify = (notify_payload_t*)payload;
        !           130:                switch (notify->get_notify_type(notify))
        !           131:                {
        !           132:                        case MOBIKE_SUPPORTED:
        !           133:                        {
        !           134:                                peer_cfg_t *peer_cfg;
        !           135: 
        !           136:                                peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
        !           137:                                if (!this->initiator &&
        !           138:                                        peer_cfg && !peer_cfg->use_mobike(peer_cfg))
        !           139:                                {
        !           140:                                        DBG1(DBG_IKE, "peer supports MOBIKE, but disabled in config");
        !           141:                                }
        !           142:                                else
        !           143:                                {
        !           144:                                        DBG1(DBG_IKE, "peer supports MOBIKE");
        !           145:                                        this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE);
        !           146:                                }
        !           147:                                break;
        !           148:                        }
        !           149:                        case COOKIE2:
        !           150:                        {
        !           151:                                chunk_free(&this->cookie2);
        !           152:                                this->cookie2 = chunk_clone(notify->get_notification_data(notify));
        !           153:                                break;
        !           154:                        }
        !           155:                        case ADDITIONAL_IP6_ADDRESS:
        !           156:                        {
        !           157:                                family = AF_INET6;
        !           158:                                /* fall through */
        !           159:                        }
        !           160:                        case ADDITIONAL_IP4_ADDRESS:
        !           161:                        {
        !           162:                                if (first)
        !           163:                                {       /* an ADDITIONAL_*_ADDRESS means replace, so flush once */
        !           164:                                        this->ike_sa->clear_peer_addresses(this->ike_sa);
        !           165:                                        first = FALSE;
        !           166:                                        /* add the peer's current address to the list */
        !           167:                                        host = message->get_source(message);
        !           168:                                        this->ike_sa->add_peer_address(this->ike_sa,
        !           169:                                                                                                   host->clone(host));
        !           170:                                }
        !           171:                                data = notify->get_notification_data(notify);
        !           172:                                host = host_create_from_chunk(family, data, 0);
        !           173:                                DBG2(DBG_IKE, "got additional MOBIKE peer address: %H", host);
        !           174:                                this->ike_sa->add_peer_address(this->ike_sa, host);
        !           175:                                this->addresses_updated = TRUE;
        !           176:                                break;
        !           177:                        }
        !           178:                        case UPDATE_SA_ADDRESSES:
        !           179:                        {
        !           180:                                this->update = TRUE;
        !           181:                                break;
        !           182:                        }
        !           183:                        case NO_ADDITIONAL_ADDRESSES:
        !           184:                        {
        !           185:                                this->ike_sa->clear_peer_addresses(this->ike_sa);
        !           186:                                /* add the peer's current address to the list */
        !           187:                                host = message->get_source(message);
        !           188:                                this->ike_sa->add_peer_address(this->ike_sa, host->clone(host));
        !           189:                                this->addresses_updated = TRUE;
        !           190:                                break;
        !           191:                        }
        !           192:                        case NAT_DETECTION_SOURCE_IP:
        !           193:                        case NAT_DETECTION_DESTINATION_IP:
        !           194:                        {
        !           195:                                /* NAT check in this MOBIKE exchange, create subtask for it */
        !           196:                                if (!this->natd)
        !           197:                                {
        !           198:                                        this->natd = ike_natd_create(this->ike_sa, this->initiator);
        !           199:                                }
        !           200:                                break;
        !           201:                        }
        !           202:                        default:
        !           203:                                break;
        !           204:                }
        !           205:        }
        !           206:        enumerator->destroy(enumerator);
        !           207: }
        !           208: 
        !           209: /**
        !           210:  * Add ADDITIONAL_*_ADDRESS notifys depending on our address list
        !           211:  */
        !           212: static void build_address_list(private_ike_mobike_t *this, message_t *message)
        !           213: {
        !           214:        enumerator_t *enumerator;
        !           215:        host_t *host, *me;
        !           216:        notify_type_t type;
        !           217:        int added = 0;
        !           218: 
        !           219:        me = this->ike_sa->get_my_host(this->ike_sa);
        !           220:        enumerator = charon->kernel->create_address_enumerator(charon->kernel,
        !           221:                                                                                                                   ADDR_TYPE_REGULAR);
        !           222:        while (enumerator->enumerate(enumerator, (void**)&host))
        !           223:        {
        !           224:                if (me->ip_equals(me, host))
        !           225:                {       /* "ADDITIONAL" means do not include IKE_SAs host */
        !           226:                        continue;
        !           227:                }
        !           228:                switch (host->get_family(host))
        !           229:                {
        !           230:                        case AF_INET:
        !           231:                                type = ADDITIONAL_IP4_ADDRESS;
        !           232:                                break;
        !           233:                        case AF_INET6:
        !           234:                                type = ADDITIONAL_IP6_ADDRESS;
        !           235:                                break;
        !           236:                        default:
        !           237:                                continue;
        !           238:                }
        !           239:                message->add_notify(message, FALSE, type, host->get_address(host));
        !           240:                if (++added >= MAX_ADDITIONAL_ADDRS)
        !           241:                {       /* limit number of notifys, some implementations do not like too
        !           242:                         * many of them (f.e. strongSwan ;-) */
        !           243:                        break;
        !           244:                }
        !           245:        }
        !           246:        if (!added)
        !           247:        {
        !           248:                message->add_notify(message, FALSE, NO_ADDITIONAL_ADDRESSES, chunk_empty);
        !           249:        }
        !           250:        enumerator->destroy(enumerator);
        !           251: }
        !           252: 
        !           253: /**
        !           254:  * build a cookie and add it to the message
        !           255:  */
        !           256: static bool build_cookie(private_ike_mobike_t *this, message_t *message)
        !           257: {
        !           258:        rng_t *rng;
        !           259: 
        !           260:        chunk_free(&this->cookie2);
        !           261:        rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
        !           262:        if (!rng || !rng->allocate_bytes(rng, COOKIE2_SIZE, &this->cookie2))
        !           263:        {
        !           264:                DESTROY_IF(rng);
        !           265:                return FALSE;
        !           266:        }
        !           267:        message->add_notify(message, FALSE, COOKIE2, this->cookie2);
        !           268:        rng->destroy(rng);
        !           269:        return TRUE;
        !           270: }
        !           271: 
        !           272: /**
        !           273:  * update addresses of associated CHILD_SAs
        !           274:  */
        !           275: static void update_children(private_ike_mobike_t *this)
        !           276: {
        !           277:        enumerator_t *enumerator;
        !           278:        child_sa_t *child_sa;
        !           279:        linked_list_t *vips;
        !           280:        status_t status;
        !           281:        host_t *host;
        !           282: 
        !           283:        vips = linked_list_create();
        !           284: 
        !           285:        enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
        !           286:        while (enumerator->enumerate(enumerator, &host))
        !           287:        {
        !           288:                vips->insert_last(vips, host);
        !           289:        }
        !           290:        enumerator->destroy(enumerator);
        !           291: 
        !           292:        enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
        !           293:        while (enumerator->enumerate(enumerator, (void**)&child_sa))
        !           294:        {
        !           295:                status = child_sa->update(child_sa,
        !           296:                                        this->ike_sa->get_my_host(this->ike_sa),
        !           297:                                        this->ike_sa->get_other_host(this->ike_sa), vips,
        !           298:                                        this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
        !           299:                switch (status)
        !           300:                {
        !           301:                        case NOT_SUPPORTED:
        !           302:                                this->ike_sa->rekey_child_sa(this->ike_sa,
        !           303:                                                                                         child_sa->get_protocol(child_sa),
        !           304:                                                                                         child_sa->get_spi(child_sa, TRUE));
        !           305:                                break;
        !           306:                        case SUCCESS:
        !           307:                                charon->child_sa_manager->remove(charon->child_sa_manager,
        !           308:                                                                                                 child_sa);
        !           309:                                charon->child_sa_manager->add(charon->child_sa_manager,
        !           310:                                                                                          child_sa, this->ike_sa);
        !           311:                                break;
        !           312:                        default:
        !           313:                                break;
        !           314:                }
        !           315:        }
        !           316:        enumerator->destroy(enumerator);
        !           317: 
        !           318:        vips->destroy(vips);
        !           319: }
        !           320: 
        !           321: /**
        !           322:  * Apply the port of the old host, if its ip equals the new, use port otherwise.
        !           323:  */
        !           324: static void apply_port(host_t *host, host_t *old, uint16_t port, bool local)
        !           325: {
        !           326:        if (host->ip_equals(host, old))
        !           327:        {
        !           328:                port = old->get_port(old);
        !           329:        }
        !           330:        else if (local && port == charon->socket->get_port(charon->socket, FALSE))
        !           331:        {
        !           332:                port = charon->socket->get_port(charon->socket, TRUE);
        !           333:        }
        !           334:        else if (!local && port == IKEV2_UDP_PORT)
        !           335:        {
        !           336:                port = IKEV2_NATT_PORT;
        !           337:        }
        !           338:        host->set_port(host, port);
        !           339: }
        !           340: 
        !           341: METHOD(ike_mobike_t, transmit, bool,
        !           342:           private_ike_mobike_t *this, packet_t *packet)
        !           343: {
        !           344:        host_t *me, *other, *me_old, *other_old;
        !           345:        enumerator_t *enumerator;
        !           346:        ike_cfg_t *ike_cfg;
        !           347:        packet_t *copy;
        !           348:        int family = AF_UNSPEC;
        !           349:        bool found = FALSE;
        !           350: 
        !           351:        me_old = this->ike_sa->get_my_host(this->ike_sa);
        !           352:        other_old = this->ike_sa->get_other_host(this->ike_sa);
        !           353:        ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
        !           354: 
        !           355:        if (!this->check)
        !           356:        {
        !           357:                me = charon->kernel->get_source_addr(charon->kernel, other_old, me_old);
        !           358:                if (me)
        !           359:                {
        !           360:                        if (me->ip_equals(me, me_old))
        !           361:                        {
        !           362:                                copy = packet->clone(packet);
        !           363:                                /* hosts might have been updated by a peer's MOBIKE exchange */
        !           364:                                copy->set_source(copy, me_old->clone(me_old));
        !           365:                                copy->set_destination(copy, other_old->clone(other_old));
        !           366:                                charon->sender->send(charon->sender, copy);
        !           367:                                me->destroy(me);
        !           368:                                return TRUE;
        !           369:                        }
        !           370:                        me->destroy(me);
        !           371:                }
        !           372:                this->check = TRUE;
        !           373:        }
        !           374: 
        !           375:        switch (charon->socket->supported_families(charon->socket))
        !           376:        {
        !           377:                case SOCKET_FAMILY_IPV4:
        !           378:                        family = AF_INET;
        !           379:                        break;
        !           380:                case SOCKET_FAMILY_IPV6:
        !           381:                        family = AF_INET6;
        !           382:                        break;
        !           383:                case SOCKET_FAMILY_BOTH:
        !           384:                case SOCKET_FAMILY_NONE:
        !           385:                        break;
        !           386:        }
        !           387: 
        !           388:        enumerator = this->ike_sa->create_peer_address_enumerator(this->ike_sa);
        !           389:        while (enumerator->enumerate(enumerator, (void**)&other))
        !           390:        {
        !           391:                if (family != AF_UNSPEC && other->get_family(other) != family)
        !           392:                {
        !           393:                        continue;
        !           394:                }
        !           395:                me = charon->kernel->get_source_addr(charon->kernel, other, NULL);
        !           396:                if (me)
        !           397:                {
        !           398:                        /* reuse port for an active address, 4500 otherwise */
        !           399:                        apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg), TRUE);
        !           400:                        other = other->clone(other);
        !           401:                        apply_port(other, other_old, ike_cfg->get_other_port(ike_cfg), FALSE);
        !           402:                        DBG1(DBG_IKE, "checking path %#H - %#H", me, other);
        !           403:                        copy = packet->clone(packet);
        !           404:                        copy->set_source(copy, me);
        !           405:                        copy->set_destination(copy, other);
        !           406:                        charon->sender->send(charon->sender, copy);
        !           407:                        found = TRUE;
        !           408:                }
        !           409:        }
        !           410:        enumerator->destroy(enumerator);
        !           411:        return found;
        !           412: }
        !           413: 
        !           414: METHOD(task_t, build_i, status_t,
        !           415:           private_ike_mobike_t *this, message_t *message)
        !           416: {
        !           417:        if (message->get_exchange_type(message) == IKE_AUTH &&
        !           418:                message->get_message_id(message) == 1)
        !           419:        {       /* only in first IKE_AUTH */
        !           420:                message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
        !           421:                build_address_list(this, message);
        !           422:        }
        !           423:        else if (message->get_exchange_type(message) == INFORMATIONAL)
        !           424:        {
        !           425:                host_t *old, *new;
        !           426: 
        !           427:                /* we check if the existing address is still valid */
        !           428:                old = message->get_source(message);
        !           429:                new = charon->kernel->get_source_addr(charon->kernel,
        !           430:                                                                                message->get_destination(message), old);
        !           431:                if (new)
        !           432:                {
        !           433:                        if (!new->ip_equals(new, old))
        !           434:                        {
        !           435:                                new->set_port(new, old->get_port(old));
        !           436:                                message->set_source(message, new);
        !           437:                        }
        !           438:                        else
        !           439:                        {
        !           440:                                new->destroy(new);
        !           441:                        }
        !           442:                }
        !           443:                if (this->update)
        !           444:                {
        !           445:                        message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES,
        !           446:                                                                chunk_empty);
        !           447:                        if (!build_cookie(this, message))
        !           448:                        {
        !           449:                                return FAILED;
        !           450:                        }
        !           451:                        update_children(this);
        !           452:                }
        !           453:                if (this->address && !this->check)
        !           454:                {
        !           455:                        build_address_list(this, message);
        !           456:                }
        !           457:                if (this->natd)
        !           458:                {
        !           459:                        this->natd->task.build(&this->natd->task, message);
        !           460:                }
        !           461:        }
        !           462:        return NEED_MORE;
        !           463: }
        !           464: 
        !           465: METHOD(task_t, process_r, status_t,
        !           466:           private_ike_mobike_t *this, message_t *message)
        !           467: {
        !           468:        if (message->get_exchange_type(message) == IKE_AUTH &&
        !           469:                message->get_message_id(message) == 1)
        !           470:        {       /* only first IKE_AUTH */
        !           471:                process_payloads(this, message);
        !           472:        }
        !           473:        else if (message->get_exchange_type(message) == INFORMATIONAL)
        !           474:        {
        !           475:                process_payloads(this, message);
        !           476:                if (this->update)
        !           477:                {
        !           478:                        host_t *me, *other;
        !           479: 
        !           480:                        me = message->get_destination(message);
        !           481:                        other = message->get_source(message);
        !           482:                        this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
        !           483:                        this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
        !           484:                }
        !           485: 
        !           486:                if (this->natd)
        !           487:                {
        !           488:                        this->natd->task.process(&this->natd->task, message);
        !           489:                }
        !           490:                if (this->addresses_updated && this->ike_sa->has_condition(this->ike_sa,
        !           491:                                                                                                COND_ORIGINAL_INITIATOR))
        !           492:                {
        !           493:                        host_t *other = message->get_source(message);
        !           494:                        host_t *other_old = this->ike_sa->get_other_host(this->ike_sa);
        !           495:                        if (!other->equals(other, other_old))
        !           496:                        {
        !           497:                                DBG1(DBG_IKE, "remote address changed from %H to %H", other_old,
        !           498:                                         other);
        !           499:                                this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
        !           500:                                this->update = TRUE;
        !           501:                        }
        !           502:                }
        !           503:        }
        !           504:        return NEED_MORE;
        !           505: }
        !           506: 
        !           507: METHOD(task_t, build_r, status_t,
        !           508:           private_ike_mobike_t *this, message_t *message)
        !           509: {
        !           510:        if (message->get_exchange_type(message) == IKE_AUTH &&
        !           511:                this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
        !           512:        {
        !           513:                if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
        !           514:                {
        !           515:                        message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
        !           516:                        build_address_list(this, message);
        !           517:                }
        !           518:                return SUCCESS;
        !           519:        }
        !           520:        else if (message->get_exchange_type(message) == INFORMATIONAL)
        !           521:        {
        !           522:                if (this->natd)
        !           523:                {
        !           524:                        this->natd->task.build(&this->natd->task, message);
        !           525:                }
        !           526:                if (this->cookie2.ptr)
        !           527:                {
        !           528:                        message->add_notify(message, FALSE, COOKIE2, this->cookie2);
        !           529:                        chunk_free(&this->cookie2);
        !           530:                }
        !           531:                if (this->update)
        !           532:                {
        !           533:                        update_children(this);
        !           534:                }
        !           535:                return SUCCESS;
        !           536:        }
        !           537:        return NEED_MORE;
        !           538: }
        !           539: 
        !           540: METHOD(task_t, process_i, status_t,
        !           541:           private_ike_mobike_t *this, message_t *message)
        !           542: {
        !           543:        if (message->get_exchange_type(message) == IKE_AUTH &&
        !           544:                this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
        !           545:        {
        !           546:                process_payloads(this, message);
        !           547:                return SUCCESS;
        !           548:        }
        !           549:        else if (message->get_exchange_type(message) == INFORMATIONAL)
        !           550:        {
        !           551:                if (is_newer_update_queued(this))
        !           552:                {
        !           553:                        return SUCCESS;
        !           554:                }
        !           555:                if (this->cookie2.ptr)
        !           556:                {       /* check cookie if we included one */
        !           557:                        chunk_t cookie2;
        !           558: 
        !           559:                        cookie2 = this->cookie2;
        !           560:                        this->cookie2 = chunk_empty;
        !           561:                        process_payloads(this, message);
        !           562:                        if (!chunk_equals_const(cookie2, this->cookie2))
        !           563:                        {
        !           564:                                chunk_free(&cookie2);
        !           565:                                DBG1(DBG_IKE, "COOKIE2 mismatch, closing IKE_SA");
        !           566:                                return FAILED;
        !           567:                        }
        !           568:                        chunk_free(&cookie2);
        !           569:                }
        !           570:                else
        !           571:                {
        !           572:                        process_payloads(this, message);
        !           573:                }
        !           574:                if (this->natd)
        !           575:                {
        !           576:                        this->natd->task.process(&this->natd->task, message);
        !           577:                        if (!this->update && this->natd->has_mapping_changed(this->natd))
        !           578:                        {
        !           579:                                /* force an update if mappings have changed */
        !           580:                                this->update = this->check = TRUE;
        !           581:                                DBG1(DBG_IKE, "detected changes in NAT mappings, "
        !           582:                                         "initiating MOBIKE update");
        !           583:                        }
        !           584:                }
        !           585:                if (this->update)
        !           586:                {
        !           587:                        /* update again, as NAT state may have changed */
        !           588:                        update_children(this);
        !           589:                }
        !           590:                if (this->check)
        !           591:                {
        !           592:                        host_t *me_new, *me_old, *other_new, *other_old;
        !           593: 
        !           594:                        me_new = message->get_destination(message);
        !           595:                        other_new = message->get_source(message);
        !           596:                        me_old = this->ike_sa->get_my_host(this->ike_sa);
        !           597:                        other_old = this->ike_sa->get_other_host(this->ike_sa);
        !           598: 
        !           599:                        if (!me_new->equals(me_new, me_old))
        !           600:                        {
        !           601:                                this->update = TRUE;
        !           602:                                this->ike_sa->set_my_host(this->ike_sa, me_new->clone(me_new));
        !           603:                        }
        !           604:                        if (!other_new->equals(other_new, other_old))
        !           605:                        {
        !           606:                                this->update = TRUE;
        !           607:                                this->ike_sa->set_other_host(this->ike_sa, other_new->clone(other_new));
        !           608:                        }
        !           609:                        if (this->update)
        !           610:                        {
        !           611:                                /* use the same task to ... */
        !           612:                                if (!this->ike_sa->has_condition(this->ike_sa,
        !           613:                                                                                                 COND_ORIGINAL_INITIATOR))
        !           614:                                {       /*... send an updated list of addresses as responder */
        !           615:                                        update_children(this);
        !           616:                                        this->update = FALSE;
        !           617:                                }
        !           618:                                else
        !           619:                                {       /* ... send the update as original initiator */
        !           620:                                        if (this->natd)
        !           621:                                        {
        !           622:                                                this->natd->task.destroy(&this->natd->task);
        !           623:                                        }
        !           624:                                        this->natd = ike_natd_create(this->ike_sa, this->initiator);
        !           625:                                }
        !           626:                                this->check = FALSE;
        !           627:                                return NEED_MORE;
        !           628:                        }
        !           629:                }
        !           630:                return SUCCESS;
        !           631:        }
        !           632:        return NEED_MORE;
        !           633: }
        !           634: 
        !           635: METHOD(ike_mobike_t, addresses, void,
        !           636:           private_ike_mobike_t *this)
        !           637: {
        !           638:        this->address = TRUE;
        !           639: }
        !           640: 
        !           641: METHOD(ike_mobike_t, roam, void,
        !           642:           private_ike_mobike_t *this, bool address)
        !           643: {
        !           644:        this->check = TRUE;
        !           645:        this->address |= address;
        !           646: }
        !           647: 
        !           648: METHOD(ike_mobike_t, dpd, void,
        !           649:           private_ike_mobike_t *this)
        !           650: {
        !           651:        if (!this->natd && this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
        !           652:        {
        !           653:                this->natd = ike_natd_create(this->ike_sa, this->initiator);
        !           654:        }
        !           655: }
        !           656: 
        !           657: METHOD(ike_mobike_t, is_probing, bool,
        !           658:           private_ike_mobike_t *this)
        !           659: {
        !           660:        return this->check;
        !           661: }
        !           662: 
        !           663: METHOD(ike_mobike_t, enable_probing, void,
        !           664:        private_ike_mobike_t *this)
        !           665: {
        !           666:        this->check = TRUE;
        !           667: }
        !           668: 
        !           669: METHOD(task_t, get_type, task_type_t,
        !           670:           private_ike_mobike_t *this)
        !           671: {
        !           672:        return TASK_IKE_MOBIKE;
        !           673: }
        !           674: 
        !           675: METHOD(task_t, migrate, void,
        !           676:           private_ike_mobike_t *this, ike_sa_t *ike_sa)
        !           677: {
        !           678:        chunk_free(&this->cookie2);
        !           679:        this->ike_sa = ike_sa;
        !           680:        if (this->natd)
        !           681:        {
        !           682:                this->natd->task.migrate(&this->natd->task, ike_sa);
        !           683:        }
        !           684: }
        !           685: 
        !           686: METHOD(task_t, destroy, void,
        !           687:           private_ike_mobike_t *this)
        !           688: {
        !           689:        chunk_free(&this->cookie2);
        !           690:        if (this->natd)
        !           691:        {
        !           692:                this->natd->task.destroy(&this->natd->task);
        !           693:        }
        !           694:        free(this);
        !           695: }
        !           696: 
        !           697: /*
        !           698:  * Described in header.
        !           699:  */
        !           700: ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
        !           701: {
        !           702:        private_ike_mobike_t *this;
        !           703: 
        !           704:        INIT(this,
        !           705:                .public = {
        !           706:                        .task = {
        !           707:                                .get_type = _get_type,
        !           708:                                .migrate = _migrate,
        !           709:                                .destroy = _destroy,
        !           710:                        },
        !           711:                        .addresses = _addresses,
        !           712:                        .roam = _roam,
        !           713:                        .dpd = _dpd,
        !           714:                        .transmit = _transmit,
        !           715:                        .is_probing = _is_probing,
        !           716:                        .enable_probing = _enable_probing,
        !           717:                },
        !           718:                .ike_sa = ike_sa,
        !           719:                .initiator = initiator,
        !           720:        );
        !           721: 
        !           722:        if (initiator)
        !           723:        {
        !           724:                this->public.task.build = _build_i;
        !           725:                this->public.task.process = _process_i;
        !           726:        }
        !           727:        else
        !           728:        {
        !           729:                this->public.task.build = _build_r;
        !           730:                this->public.task.process = _process_r;
        !           731:        }
        !           732: 
        !           733:        return &this->public;
        !           734: }

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