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 **)¤t))
! 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>