Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/sa_payload.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2012-2020 Tobias Brunner
        !             3:  * Copyright (C) 2005-2010 Martin Willi
        !             4:  * Copyright (C) 2005 Jan Hutter
        !             5:  * HSR Hochschule fuer Technik Rapperswil
        !             6:  *
        !             7:  * This program is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2 of the License, or (at your
        !            10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            11:  *
        !            12:  * This program is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            15:  * for more details.
        !            16:  */
        !            17: 
        !            18: #include <stddef.h>
        !            19: 
        !            20: #include "sa_payload.h"
        !            21: 
        !            22: #include <encoding/payloads/encodings.h>
        !            23: #include <collections/linked_list.h>
        !            24: #include <daemon.h>
        !            25: 
        !            26: /* IKEv1 situation */
        !            27: #define SIT_IDENTITY_ONLY 1
        !            28: 
        !            29: typedef struct private_sa_payload_t private_sa_payload_t;
        !            30: 
        !            31: /**
        !            32:  * Private data of an sa_payload_t object.
        !            33:  */
        !            34: struct private_sa_payload_t {
        !            35: 
        !            36:        /**
        !            37:         * Public sa_payload_t interface.
        !            38:         */
        !            39:        sa_payload_t public;
        !            40: 
        !            41:        /**
        !            42:         * Next payload type.
        !            43:         */
        !            44:        uint8_t  next_payload;
        !            45: 
        !            46:        /**
        !            47:         * Critical flag.
        !            48:         */
        !            49:        bool critical;
        !            50: 
        !            51:        /**
        !            52:         * Reserved bits
        !            53:         */
        !            54:        bool reserved[8];
        !            55: 
        !            56:        /**
        !            57:         * Length of this payload.
        !            58:         */
        !            59:        uint16_t payload_length;
        !            60: 
        !            61:        /**
        !            62:         * Proposals in this payload are stored in a linked_list_t.
        !            63:         */
        !            64:        linked_list_t *proposals;
        !            65: 
        !            66:        /**
        !            67:         * Type of this payload, V1 or V2
        !            68:         */
        !            69:        payload_type_t type;
        !            70: 
        !            71:        /**
        !            72:         * IKEv1 DOI
        !            73:         */
        !            74:        uint32_t doi;
        !            75: 
        !            76:        /**
        !            77:         * IKEv1 situation
        !            78:         */
        !            79:        uint32_t situation;
        !            80: };
        !            81: 
        !            82: /**
        !            83:  * Encoding rules for IKEv1 SA payload
        !            84:  */
        !            85: static encoding_rule_t encodings_v1[] = {
        !            86:        /* 1 Byte next payload type, stored in the field next_payload */
        !            87:        { U_INT_8,                      offsetof(private_sa_payload_t, next_payload)    },
        !            88:        /* 8 reserved bits */
        !            89:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[0])                     },
        !            90:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[1])                     },
        !            91:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[2])                     },
        !            92:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[3])                     },
        !            93:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[4])                     },
        !            94:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[5])                     },
        !            95:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[6])                     },
        !            96:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[7])                     },
        !            97:        /* Length of the whole SA payload*/
        !            98:        { PAYLOAD_LENGTH,       offsetof(private_sa_payload_t, payload_length)  },
        !            99:        /* DOI*/
        !           100:        { U_INT_32,                     offsetof(private_sa_payload_t, doi)                             },
        !           101:        /* Situation*/
        !           102:        { U_INT_32,                     offsetof(private_sa_payload_t, situation)               },
        !           103:        /* Proposals are stored in a proposal substructure list */
        !           104:        { PAYLOAD_LIST + PLV1_PROPOSAL_SUBSTRUCTURE,
        !           105:                                                offsetof(private_sa_payload_t, proposals)               },
        !           106: };
        !           107: 
        !           108: /*
        !           109:                            1                   2                   3
        !           110:        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        !           111:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           112:       ! Next Payload  !    RESERVED   !         Payload Length        !
        !           113:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           114:       !                           DOI                                 !
        !           115:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           116:       !                           Situation                           !
        !           117:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           118:       !                                                               !
        !           119:       ~                          <Proposals>                          ~
        !           120:       !                                                               !
        !           121:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           122: */
        !           123: 
        !           124: /**
        !           125:  * Encoding rules for IKEv2 SA payload
        !           126:  */
        !           127: static encoding_rule_t encodings_v2[] = {
        !           128:        /* 1 Byte next payload type, stored in the field next_payload */
        !           129:        { U_INT_8,                      offsetof(private_sa_payload_t, next_payload)            },
        !           130:        /* the critical bit */
        !           131:        { FLAG,                         offsetof(private_sa_payload_t, critical)                        },
        !           132:        /* 7 Bit reserved bits */
        !           133:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[0])                     },
        !           134:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[1])                     },
        !           135:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[2])                     },
        !           136:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[3])                     },
        !           137:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[4])                     },
        !           138:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[5])                     },
        !           139:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[6])                     },
        !           140:        /* Length of the whole SA payload*/
        !           141:        { PAYLOAD_LENGTH,       offsetof(private_sa_payload_t, payload_length)          },
        !           142:        /* Proposals are stored in a proposal substructure list */
        !           143:        { PAYLOAD_LIST + PLV2_PROPOSAL_SUBSTRUCTURE,
        !           144:                                                offsetof(private_sa_payload_t, proposals)                       },
        !           145: };
        !           146: 
        !           147: /*
        !           148:                            1                   2                   3
        !           149:        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        !           150:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           151:       ! Next Payload  !C!  RESERVED   !         Payload Length        !
        !           152:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           153:       !                                                               !
        !           154:       ~                          <Proposals>                          ~
        !           155:       !                                                               !
        !           156:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           157: */
        !           158: 
        !           159: METHOD(payload_t, verify, status_t,
        !           160:        private_sa_payload_t *this)
        !           161: {
        !           162:        int expected_number = 0, current_number;
        !           163:        status_t status = SUCCESS;
        !           164:        enumerator_t *enumerator;
        !           165:        proposal_substructure_t *substruct;
        !           166: 
        !           167:        if (this->type == PLV2_SECURITY_ASSOCIATION)
        !           168:        {
        !           169:                expected_number = 1;
        !           170:        }
        !           171: 
        !           172:        /* check proposal numbering */
        !           173:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           174:        while (enumerator->enumerate(enumerator, (void**)&substruct))
        !           175:        {
        !           176:                current_number = substruct->get_proposal_number(substruct);
        !           177:                if (current_number < expected_number)
        !           178:                {
        !           179:                        DBG1(DBG_ENC, "proposal number smaller than previous");
        !           180:                        status = FAILED;
        !           181:                        break;
        !           182:                }
        !           183: 
        !           184:                status = substruct->payload_interface.verify(&substruct->payload_interface);
        !           185:                if (status != SUCCESS)
        !           186:                {
        !           187:                        DBG1(DBG_ENC, "PROPOSAL_SUBSTRUCTURE verification failed");
        !           188:                        break;
        !           189:                }
        !           190:                expected_number = current_number;
        !           191:        }
        !           192:        enumerator->destroy(enumerator);
        !           193:        return status;
        !           194: }
        !           195: 
        !           196: METHOD(payload_t, get_encoding_rules, int,
        !           197:        private_sa_payload_t *this, encoding_rule_t **rules)
        !           198: {
        !           199:        if (this->type == PLV1_SECURITY_ASSOCIATION)
        !           200:        {
        !           201:                *rules = encodings_v1;
        !           202:                return countof(encodings_v1);
        !           203:        }
        !           204:        *rules = encodings_v2;
        !           205:        return countof(encodings_v2);
        !           206: }
        !           207: 
        !           208: METHOD(payload_t, get_header_length, int,
        !           209:        private_sa_payload_t *this)
        !           210: {
        !           211:        if (this->type == PLV1_SECURITY_ASSOCIATION)
        !           212:        {
        !           213:                return 12;
        !           214:        }
        !           215:        return 4;
        !           216: }
        !           217: 
        !           218: METHOD(payload_t, get_type, payload_type_t,
        !           219:        private_sa_payload_t *this)
        !           220: {
        !           221:        return this->type;
        !           222: }
        !           223: 
        !           224: METHOD(payload_t, get_next_type, payload_type_t,
        !           225:        private_sa_payload_t *this)
        !           226: {
        !           227:        return this->next_payload;
        !           228: }
        !           229: 
        !           230: METHOD(payload_t, set_next_type, void,
        !           231:        private_sa_payload_t *this,payload_type_t type)
        !           232: {
        !           233:        this->next_payload = type;
        !           234: }
        !           235: 
        !           236: /**
        !           237:  * recompute length of the payload.
        !           238:  */
        !           239: static void compute_length(private_sa_payload_t *this)
        !           240: {
        !           241:        enumerator_t *enumerator;
        !           242:        payload_t *current;
        !           243: 
        !           244:        this->payload_length = get_header_length(this);
        !           245: 
        !           246:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           247:        while (enumerator->enumerate(enumerator, (void **)&current))
        !           248:        {
        !           249:                this->payload_length += current->get_length(current);
        !           250:        }
        !           251:        enumerator->destroy(enumerator);
        !           252: }
        !           253: 
        !           254: METHOD(payload_t, get_length, size_t,
        !           255:        private_sa_payload_t *this)
        !           256: {
        !           257:        return this->payload_length;
        !           258: }
        !           259: 
        !           260: /**
        !           261:  * Create a transform substructure from a proposal, add to payload
        !           262:  */
        !           263: static void add_proposal_v2(private_sa_payload_t *this, proposal_t *proposal)
        !           264: {
        !           265:        proposal_substructure_t *substruct, *last;
        !           266:        u_int count;
        !           267: 
        !           268:        substruct = proposal_substructure_create_from_proposal_v2(proposal);
        !           269:        count = this->proposals->get_count(this->proposals);
        !           270:        if (count > 0)
        !           271:        {
        !           272:                this->proposals->get_last(this->proposals, (void**)&last);
        !           273:                /* last transform is now not anymore last one */
        !           274:                last->set_is_last_proposal(last, FALSE);
        !           275:        }
        !           276:        substruct->set_is_last_proposal(substruct, TRUE);
        !           277:        if (proposal->get_number(proposal))
        !           278:        {       /* use the selected proposals number, if any */
        !           279:                substruct->set_proposal_number(substruct, proposal->get_number(proposal));
        !           280:        }
        !           281:        else
        !           282:        {
        !           283:                substruct->set_proposal_number(substruct, count + 1);
        !           284:        }
        !           285:        this->proposals->insert_last(this->proposals, substruct);
        !           286:        compute_length(this);
        !           287: }
        !           288: 
        !           289: METHOD(sa_payload_t, get_proposals, linked_list_t*,
        !           290:        private_sa_payload_t *this)
        !           291: {
        !           292:        int struct_number = 0;
        !           293:        int ignore_struct_number = 0;
        !           294:        enumerator_t *enumerator;
        !           295:        proposal_substructure_t *substruct;
        !           296:        linked_list_t *substructs, *list;
        !           297: 
        !           298:        if (this->type == PLV1_SECURITY_ASSOCIATION)
        !           299:        {       /* IKEv1 proposals may start with 0 or 1 (or any other number really) */
        !           300:                struct_number = ignore_struct_number = -1;
        !           301:        }
        !           302: 
        !           303:        /* we do not support proposals split up to two proposal substructures, as
        !           304:         * AH+ESP bundles are not supported in RFC4301 anymore.
        !           305:         * To handle such structures safely, we just skip proposals with multiple
        !           306:         * protocols.
        !           307:         */
        !           308:        substructs = linked_list_create();
        !           309:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           310:        while (enumerator->enumerate(enumerator, &substruct))
        !           311:        {
        !           312:                int current_number = substruct->get_proposal_number(substruct);
        !           313: 
        !           314:                /* check if a proposal has a single protocol */
        !           315:                if (current_number == struct_number)
        !           316:                {
        !           317:                        if (ignore_struct_number < struct_number)
        !           318:                        {       /* remove an already added substruct, if first of series */
        !           319:                                substructs->remove_last(substructs, (void**)&substruct);
        !           320:                                ignore_struct_number = struct_number;
        !           321:                        }
        !           322:                        continue;
        !           323:                }
        !           324:                /* for IKEv1 the numbers don't have to be consecutive, for IKEv2 they do
        !           325:                 * but since we don't really care for the actual number we accept them
        !           326:                 * anyway. we already verified that they increase monotonically. */
        !           327:                struct_number = current_number;
        !           328:                substructs->insert_last(substructs, substruct);
        !           329:        }
        !           330:        enumerator->destroy(enumerator);
        !           331: 
        !           332:        /* generate proposals from substructs */
        !           333:        list = linked_list_create();
        !           334:        enumerator = substructs->create_enumerator(substructs);
        !           335:        while (enumerator->enumerate(enumerator, &substruct))
        !           336:        {
        !           337:                substruct->get_proposals(substruct, list);
        !           338:        }
        !           339:        enumerator->destroy(enumerator);
        !           340:        substructs->destroy(substructs);
        !           341:        return list;
        !           342: }
        !           343: 
        !           344: METHOD(sa_payload_t, get_ipcomp_proposals, linked_list_t*,
        !           345:        private_sa_payload_t *this, uint16_t *cpi)
        !           346: {
        !           347:        int current_proposal = -1, unsupported_proposal = -1;
        !           348:        enumerator_t *enumerator;
        !           349:        proposal_substructure_t *substruct, *espah = NULL, *ipcomp = NULL;
        !           350:        linked_list_t *list;
        !           351: 
        !           352:        /* we currently only support the combination ESP|AH+IPComp, find the first */
        !           353:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           354:        while (enumerator->enumerate(enumerator, &substruct))
        !           355:        {
        !           356:                uint8_t proposal_number = substruct->get_proposal_number(substruct);
        !           357:                uint8_t protocol_id = substruct->get_protocol_id(substruct);
        !           358: 
        !           359:                if (proposal_number == unsupported_proposal)
        !           360:                {
        !           361:                        continue;
        !           362:                }
        !           363:                if (protocol_id != PROTO_ESP && protocol_id != PROTO_AH &&
        !           364:                        protocol_id != PROTO_IPCOMP)
        !           365:                {       /* unsupported combination */
        !           366:                        espah = ipcomp = NULL;
        !           367:                        unsupported_proposal = current_proposal;
        !           368:                        continue;
        !           369:                }
        !           370:                if (proposal_number != current_proposal)
        !           371:                {       /* start of a new proposal */
        !           372:                        if (espah && ipcomp && ipcomp->get_cpi(ipcomp, NULL))
        !           373:                        {       /* previous proposal is valid */
        !           374:                                break;
        !           375:                        }
        !           376:                        espah = ipcomp = NULL;
        !           377:                        current_proposal = proposal_number;
        !           378:                }
        !           379:                switch (protocol_id)
        !           380:                {
        !           381:                        case PROTO_ESP:
        !           382:                        case PROTO_AH:
        !           383:                                espah = substruct;
        !           384:                                break;
        !           385:                        case PROTO_IPCOMP:
        !           386:                                ipcomp = substruct;
        !           387:                                break;
        !           388:                }
        !           389:        }
        !           390:        enumerator->destroy(enumerator);
        !           391: 
        !           392:        list = linked_list_create();
        !           393:        if (espah && ipcomp && ipcomp->get_cpi(ipcomp, cpi))
        !           394:        {
        !           395:                espah->get_proposals(espah, list);
        !           396:        }
        !           397:        return list;
        !           398: }
        !           399: 
        !           400: METHOD(sa_payload_t, create_substructure_enumerator, enumerator_t*,
        !           401:        private_sa_payload_t *this)
        !           402: {
        !           403:        return this->proposals->create_enumerator(this->proposals);
        !           404: }
        !           405: 
        !           406: METHOD(sa_payload_t, get_lifetime, uint32_t,
        !           407:        private_sa_payload_t *this, proposal_t *proposal)
        !           408: {
        !           409:        proposal_substructure_t *substruct;
        !           410:        enumerator_t *enumerator;
        !           411:        uint8_t number = proposal->get_number(proposal);
        !           412:        uint32_t lifetime = 0;
        !           413: 
        !           414:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           415:        while (enumerator->enumerate(enumerator, &substruct))
        !           416:        {
        !           417:                if (substruct->get_proposal_number(substruct) == number)
        !           418:                {
        !           419:                        lifetime = substruct->get_lifetime(substruct,
        !           420:                                                                        proposal->get_transform_number(proposal));
        !           421:                        break;
        !           422:                }
        !           423:        }
        !           424:        enumerator->destroy(enumerator);
        !           425: 
        !           426:        return lifetime;
        !           427: }
        !           428: 
        !           429: METHOD(sa_payload_t, get_lifebytes, uint64_t,
        !           430:        private_sa_payload_t *this, proposal_t *proposal)
        !           431: {
        !           432:        proposal_substructure_t *substruct;
        !           433:        enumerator_t *enumerator;
        !           434:        uint8_t number = proposal->get_number(proposal);
        !           435:        uint64_t lifebytes = 0;
        !           436: 
        !           437:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           438:        while (enumerator->enumerate(enumerator, &substruct))
        !           439:        {
        !           440:                if (substruct->get_proposal_number(substruct) == number)
        !           441:                {
        !           442:                        lifebytes = substruct->get_lifebytes(substruct,
        !           443:                                                                        proposal->get_transform_number(proposal));
        !           444:                        break;
        !           445:                }
        !           446:        }
        !           447:        enumerator->destroy(enumerator);
        !           448: 
        !           449:        return lifebytes;
        !           450: }
        !           451: 
        !           452: METHOD(sa_payload_t, get_auth_method, auth_method_t,
        !           453:        private_sa_payload_t *this)
        !           454: {
        !           455:        proposal_substructure_t *substruct;
        !           456:        enumerator_t *enumerator;
        !           457:        auth_method_t method = AUTH_NONE;
        !           458: 
        !           459:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           460:        if (enumerator->enumerate(enumerator, &substruct))
        !           461:        {
        !           462:                method = substruct->get_auth_method(substruct);
        !           463:        }
        !           464:        enumerator->destroy(enumerator);
        !           465: 
        !           466:        return method;
        !           467: }
        !           468: 
        !           469: METHOD(sa_payload_t, get_encap_mode, ipsec_mode_t,
        !           470:        private_sa_payload_t *this, bool *udp)
        !           471: {
        !           472:        proposal_substructure_t *substruct;
        !           473:        enumerator_t *enumerator;
        !           474:        ipsec_mode_t mode = MODE_NONE;
        !           475: 
        !           476:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           477:        if (enumerator->enumerate(enumerator, &substruct))
        !           478:        {
        !           479:                mode = substruct->get_encap_mode(substruct, udp);
        !           480:        }
        !           481:        enumerator->destroy(enumerator);
        !           482: 
        !           483:        return mode;
        !           484: }
        !           485: 
        !           486: METHOD2(payload_t, sa_payload_t, destroy, void,
        !           487:        private_sa_payload_t *this)
        !           488: {
        !           489:        this->proposals->destroy_offset(this->proposals,
        !           490:                                                                        offsetof(payload_t, destroy));
        !           491:        free(this);
        !           492: }
        !           493: 
        !           494: /*
        !           495:  * Described in header.
        !           496:  */
        !           497: sa_payload_t *sa_payload_create(payload_type_t type)
        !           498: {
        !           499:        private_sa_payload_t *this;
        !           500: 
        !           501:        INIT(this,
        !           502:                .public = {
        !           503:                        .payload_interface = {
        !           504:                                .verify = _verify,
        !           505:                                .get_encoding_rules = _get_encoding_rules,
        !           506:                                .get_header_length = _get_header_length,
        !           507:                                .get_length = _get_length,
        !           508:                                .get_next_type = _get_next_type,
        !           509:                                .set_next_type = _set_next_type,
        !           510:                                .get_type = _get_type,
        !           511:                                .destroy = _destroy,
        !           512:                        },
        !           513:                        .get_proposals = _get_proposals,
        !           514:                        .get_ipcomp_proposals = _get_ipcomp_proposals,
        !           515:                        .create_substructure_enumerator = _create_substructure_enumerator,
        !           516:                        .get_lifetime = _get_lifetime,
        !           517:                        .get_lifebytes = _get_lifebytes,
        !           518:                        .get_auth_method = _get_auth_method,
        !           519:                        .get_encap_mode = _get_encap_mode,
        !           520:                        .destroy = _destroy,
        !           521:                },
        !           522:                .next_payload = PL_NONE,
        !           523:                .proposals = linked_list_create(),
        !           524:                .type = type,
        !           525:                /* for IKEv1 only */
        !           526:                .doi = IKEV1_DOI_IPSEC,
        !           527:                .situation = SIT_IDENTITY_ONLY,
        !           528:        );
        !           529: 
        !           530:        compute_length(this);
        !           531: 
        !           532:        return &this->public;
        !           533: }
        !           534: 
        !           535: /*
        !           536:  * Described in header.
        !           537:  */
        !           538: sa_payload_t *sa_payload_create_from_proposals_v2(linked_list_t *proposals)
        !           539: {
        !           540:        private_sa_payload_t *this;
        !           541:        enumerator_t *enumerator;
        !           542:        proposal_t *proposal;
        !           543: 
        !           544:        this = (private_sa_payload_t*)sa_payload_create(PLV2_SECURITY_ASSOCIATION);
        !           545:        enumerator = proposals->create_enumerator(proposals);
        !           546:        while (enumerator->enumerate(enumerator, &proposal))
        !           547:        {
        !           548:                add_proposal_v2(this, proposal);
        !           549:        }
        !           550:        enumerator->destroy(enumerator);
        !           551: 
        !           552:        return &this->public;
        !           553: }
        !           554: 
        !           555: /*
        !           556:  * Described in header.
        !           557:  */
        !           558: sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal)
        !           559: {
        !           560:        private_sa_payload_t *this;
        !           561: 
        !           562:        this = (private_sa_payload_t*)sa_payload_create(PLV2_SECURITY_ASSOCIATION);
        !           563:        add_proposal_v2(this, proposal);
        !           564: 
        !           565:        return &this->public;
        !           566: 
        !           567: }
        !           568: 
        !           569: /*
        !           570:  * Described in header.
        !           571:  */
        !           572: sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
        !           573:                                                                uint32_t lifetime, uint64_t lifebytes,
        !           574:                                                                auth_method_t auth, ipsec_mode_t mode,
        !           575:                                                                encap_t udp, uint16_t cpi)
        !           576: {
        !           577:        proposal_substructure_t *substruct;
        !           578:        private_sa_payload_t *this;
        !           579: 
        !           580:        this = (private_sa_payload_t*)sa_payload_create(PLV1_SECURITY_ASSOCIATION);
        !           581: 
        !           582:        if (!proposals || !proposals->get_count(proposals))
        !           583:        {
        !           584:                return &this->public;
        !           585:        }
        !           586: 
        !           587:        /* IKEv1 encodes multiple proposals in a single substructure
        !           588:         * TODO-IKEv1: Encode ESP+AH proposals in two substructs with same num */
        !           589:        substruct = proposal_substructure_create_from_proposals_v1(proposals,
        !           590:                                                                                lifetime, lifebytes, auth, mode, udp);
        !           591:        this->proposals->insert_last(this->proposals, substruct);
        !           592:        substruct->set_is_last_proposal(substruct, FALSE);
        !           593:        if (cpi)
        !           594:        {
        !           595:                uint8_t proposal_number = substruct->get_proposal_number(substruct);
        !           596: 
        !           597:                substruct = proposal_substructure_create_for_ipcomp_v1(lifetime,
        !           598:                                        lifebytes, cpi, mode, udp, proposal_number);
        !           599:                this->proposals->insert_last(this->proposals, substruct);
        !           600:                substruct->set_is_last_proposal(substruct, FALSE);
        !           601:                /* add the proposals again without IPComp */
        !           602:                substruct = proposal_substructure_create_from_proposals_v1(proposals,
        !           603:                                                                                lifetime, lifebytes, auth, mode, udp);
        !           604:                substruct->set_proposal_number(substruct, proposal_number + 1);
        !           605:                this->proposals->insert_last(this->proposals, substruct);
        !           606:        }
        !           607:        substruct->set_is_last_proposal(substruct, TRUE);
        !           608:        compute_length(this);
        !           609: 
        !           610:        return &this->public;
        !           611: }
        !           612: 
        !           613: /*
        !           614:  * Described in header.
        !           615:  */
        !           616: sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
        !           617:                                                                uint32_t lifetime, uint64_t lifebytes,
        !           618:                                                                auth_method_t auth, ipsec_mode_t mode,
        !           619:                                                                encap_t udp, uint16_t cpi)
        !           620: {
        !           621:        private_sa_payload_t *this;
        !           622:        linked_list_t *proposals;
        !           623: 
        !           624:        proposals = linked_list_create();
        !           625:        proposals->insert_last(proposals, proposal);
        !           626:        this = (private_sa_payload_t*)sa_payload_create_from_proposals_v1(proposals,
        !           627:                                                                        lifetime, lifebytes, auth, mode, udp, cpi);
        !           628:        proposals->destroy(proposals);
        !           629:        return &this->public;
        !           630: }

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