Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_me.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2007-2008 Tobias Brunner
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15:
! 16: #include "ike_me.h"
! 17:
! 18: #include <string.h>
! 19:
! 20: #include <daemon.h>
! 21: #include <config/peer_cfg.h>
! 22: #include <encoding/payloads/id_payload.h>
! 23: #include <encoding/payloads/notify_payload.h>
! 24: #include <encoding/payloads/endpoint_notify.h>
! 25: #include <processing/jobs/mediation_job.h>
! 26:
! 27: #define ME_CONNECTID_LEN 4
! 28: #define ME_CONNECTKEY_LEN 16
! 29:
! 30: typedef struct private_ike_me_t private_ike_me_t;
! 31:
! 32: /**
! 33: * Private members of a ike_me_t task.
! 34: */
! 35: struct private_ike_me_t {
! 36:
! 37: /**
! 38: * Public methods and task_t interface.
! 39: */
! 40: ike_me_t public;
! 41:
! 42: /**
! 43: * Assigned IKE_SA.
! 44: */
! 45: ike_sa_t *ike_sa;
! 46:
! 47: /**
! 48: * Are we the initiator?
! 49: */
! 50: bool initiator;
! 51:
! 52: /**
! 53: * Is this a mediation connection?
! 54: */
! 55: bool mediation;
! 56:
! 57: /**
! 58: * Is this the response from another peer?
! 59: */
! 60: bool response;
! 61:
! 62: /**
! 63: * Gathered endpoints
! 64: */
! 65: linked_list_t *local_endpoints;
! 66:
! 67: /**
! 68: * Parsed endpoints
! 69: */
! 70: linked_list_t *remote_endpoints;
! 71:
! 72: /**
! 73: * Did the peer request a callback?
! 74: */
! 75: bool callback;
! 76:
! 77: /**
! 78: * Did the connect fail?
! 79: */
! 80: bool failed;
! 81:
! 82: /**
! 83: * Was there anything wrong with the payloads?
! 84: */
! 85: bool invalid_syntax;
! 86:
! 87: /**
! 88: * The requested peer
! 89: */
! 90: identification_t *peer_id;
! 91: /**
! 92: * Received ID used for connectivity checks
! 93: */
! 94: chunk_t connect_id;
! 95:
! 96: /**
! 97: * Received key used for connectivity checks
! 98: */
! 99: chunk_t connect_key;
! 100:
! 101: /**
! 102: * Peer config of the mediated connection
! 103: */
! 104: peer_cfg_t *mediated_cfg;
! 105:
! 106: };
! 107:
! 108: /**
! 109: * Adds a list of endpoints as notifies to a given message
! 110: */
! 111: static void add_endpoints_to_message(message_t *message, linked_list_t *endpoints)
! 112: {
! 113: enumerator_t *enumerator;
! 114: endpoint_notify_t *endpoint;
! 115:
! 116: enumerator = endpoints->create_enumerator(endpoints);
! 117: while (enumerator->enumerate(enumerator, (void**)&endpoint))
! 118: {
! 119: message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
! 120: }
! 121: enumerator->destroy(enumerator);
! 122: }
! 123:
! 124: /**
! 125: * Gathers endpoints and adds them to the current message
! 126: */
! 127: static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message)
! 128: {
! 129: enumerator_t *enumerator;
! 130: host_t *addr, *host;
! 131: uint16_t port;
! 132:
! 133: /* get the port that is used to communicate with the ms */
! 134: host = this->ike_sa->get_my_host(this->ike_sa);
! 135: port = host->get_port(host);
! 136:
! 137: enumerator = charon->kernel->create_address_enumerator(charon->kernel,
! 138: ADDR_TYPE_REGULAR);
! 139: while (enumerator->enumerate(enumerator, (void**)&addr))
! 140: {
! 141: host = addr->clone(addr);
! 142: host->set_port(host, port);
! 143:
! 144: this->local_endpoints->insert_last(this->local_endpoints,
! 145: endpoint_notify_create_from_host(HOST, host, NULL));
! 146:
! 147: host->destroy(host);
! 148: }
! 149: enumerator->destroy(enumerator);
! 150:
! 151: host = this->ike_sa->get_server_reflexive_host(this->ike_sa);
! 152: if (host)
! 153: {
! 154: this->local_endpoints->insert_last(this->local_endpoints,
! 155: endpoint_notify_create_from_host(SERVER_REFLEXIVE, host,
! 156: this->ike_sa->get_my_host(this->ike_sa)));
! 157: }
! 158:
! 159: add_endpoints_to_message(message, this->local_endpoints);
! 160: }
! 161:
! 162: /**
! 163: * read notifys from message and evaluate them
! 164: */
! 165: static void process_payloads(private_ike_me_t *this, message_t *message)
! 166: {
! 167: enumerator_t *enumerator;
! 168: payload_t *payload;
! 169:
! 170: enumerator = message->create_payload_enumerator(message);
! 171: while (enumerator->enumerate(enumerator, &payload))
! 172: {
! 173: if (payload->get_type(payload) != PLV2_NOTIFY)
! 174: {
! 175: continue;
! 176: }
! 177:
! 178: notify_payload_t *notify = (notify_payload_t*)payload;
! 179:
! 180: switch (notify->get_notify_type(notify))
! 181: {
! 182: case ME_CONNECT_FAILED:
! 183: {
! 184: DBG2(DBG_IKE, "received ME_CONNECT_FAILED notify");
! 185: this->failed = TRUE;
! 186: break;
! 187: }
! 188: case ME_MEDIATION:
! 189: {
! 190: DBG2(DBG_IKE, "received ME_MEDIATION notify");
! 191: this->mediation = TRUE;
! 192: break;
! 193: }
! 194: case ME_ENDPOINT:
! 195: {
! 196: endpoint_notify_t *endpoint;
! 197: endpoint = endpoint_notify_create_from_payload(notify);
! 198: if (!endpoint)
! 199: {
! 200: DBG1(DBG_IKE, "received invalid ME_ENDPOINT notify");
! 201: break;
! 202: }
! 203: DBG1(DBG_IKE, "received %N ME_ENDPOINT %#H",
! 204: me_endpoint_type_names, endpoint->get_type(endpoint),
! 205: endpoint->get_host(endpoint));
! 206:
! 207: this->remote_endpoints->insert_last(this->remote_endpoints,
! 208: endpoint);
! 209: break;
! 210: }
! 211: case ME_CALLBACK:
! 212: {
! 213: DBG2(DBG_IKE, "received ME_CALLBACK notify");
! 214: this->callback = TRUE;
! 215: break;
! 216: }
! 217: case ME_CONNECTID:
! 218: {
! 219: chunk_free(&this->connect_id);
! 220: this->connect_id = chunk_clone(notify->get_notification_data(notify));
! 221: DBG2(DBG_IKE, "received ME_CONNECTID %#B", &this->connect_id);
! 222: break;
! 223: }
! 224: case ME_CONNECTKEY:
! 225: {
! 226: chunk_free(&this->connect_key);
! 227: this->connect_key = chunk_clone(notify->get_notification_data(notify));
! 228: DBG4(DBG_IKE, "received ME_CONNECTKEY %#B", &this->connect_key);
! 229: break;
! 230: }
! 231: case ME_RESPONSE:
! 232: {
! 233: DBG2(DBG_IKE, "received ME_RESPONSE notify");
! 234: this->response = TRUE;
! 235: break;
! 236: }
! 237: default:
! 238: break;
! 239: }
! 240: }
! 241: enumerator->destroy(enumerator);
! 242: }
! 243:
! 244: METHOD(task_t, build_i, status_t,
! 245: private_ike_me_t *this, message_t *message)
! 246: {
! 247: switch(message->get_exchange_type(message))
! 248: {
! 249: case IKE_SA_INIT:
! 250: {
! 251: peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
! 252: if (peer_cfg->is_mediation(peer_cfg))
! 253: {
! 254: DBG2(DBG_IKE, "adding ME_MEDIATION");
! 255: message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty);
! 256: }
! 257: else
! 258: {
! 259: return SUCCESS;
! 260: }
! 261: break;
! 262: }
! 263: case IKE_AUTH:
! 264: {
! 265: if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
! 266: {
! 267: endpoint_notify_t *endpoint;
! 268: endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE,
! 269: NULL, NULL);
! 270: message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
! 271: endpoint->destroy(endpoint);
! 272: }
! 273: break;
! 274: }
! 275: case ME_CONNECT:
! 276: {
! 277: rng_t *rng;
! 278: id_payload_t *id_payload;
! 279: id_payload = id_payload_create_from_identification(PLV2_ID_PEER,
! 280: this->peer_id);
! 281: message->add_payload(message, (payload_t*)id_payload);
! 282:
! 283: rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
! 284: if (!rng)
! 285: {
! 286: DBG1(DBG_IKE, "unable to generate connect ID for ME_CONNECT");
! 287: return FAILED;
! 288: }
! 289: if (!this->response)
! 290: {
! 291: /* only the initiator creates a connect ID. the responder
! 292: * returns the connect ID that it received from the initiator */
! 293: if (!rng->allocate_bytes(rng, ME_CONNECTID_LEN,
! 294: &this->connect_id))
! 295: {
! 296: DBG1(DBG_IKE, "unable to generate ID for ME_CONNECT");
! 297: rng->destroy(rng);
! 298: return FAILED;
! 299: }
! 300: }
! 301: if (!rng->allocate_bytes(rng, ME_CONNECTKEY_LEN,
! 302: &this->connect_key))
! 303: {
! 304: DBG1(DBG_IKE, "unable to generate connect key for ME_CONNECT");
! 305: rng->destroy(rng);
! 306: return FAILED;
! 307: }
! 308: rng->destroy(rng);
! 309:
! 310: message->add_notify(message, FALSE, ME_CONNECTID, this->connect_id);
! 311: message->add_notify(message, FALSE, ME_CONNECTKEY, this->connect_key);
! 312:
! 313: if (this->response)
! 314: {
! 315: message->add_notify(message, FALSE, ME_RESPONSE, chunk_empty);
! 316: }
! 317: else
! 318: {
! 319: /* FIXME: should we make this configurable? */
! 320: message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty);
! 321: }
! 322:
! 323: gather_and_add_endpoints(this, message);
! 324:
! 325: break;
! 326: }
! 327: default:
! 328: break;
! 329: }
! 330: return NEED_MORE;
! 331: }
! 332:
! 333: METHOD(task_t, process_r, status_t,
! 334: private_ike_me_t *this, message_t *message)
! 335: {
! 336: switch(message->get_exchange_type(message))
! 337: {
! 338: case ME_CONNECT:
! 339: {
! 340: id_payload_t *id_payload;
! 341: id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_PEER);
! 342: if (!id_payload)
! 343: {
! 344: DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload"
! 345: ", aborting");
! 346: break;
! 347: }
! 348: this->peer_id = id_payload->get_identification(id_payload);
! 349:
! 350: process_payloads(this, message);
! 351:
! 352: if (this->callback)
! 353: {
! 354: DBG1(DBG_IKE, "received ME_CALLBACK for '%Y'", this->peer_id);
! 355: break;
! 356: }
! 357:
! 358: if (!this->connect_id.ptr)
! 359: {
! 360: DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify"
! 361: ", aborting");
! 362: this->invalid_syntax = TRUE;
! 363: break;
! 364: }
! 365:
! 366: if (!this->connect_key.ptr)
! 367: {
! 368: DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY "
! 369: "notify, aborting");
! 370: this->invalid_syntax = TRUE;
! 371: break;
! 372: }
! 373:
! 374: if (!this->remote_endpoints->get_count(this->remote_endpoints))
! 375: {
! 376: DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT "
! 377: "payloads, aborting");
! 378: this->invalid_syntax = TRUE;
! 379: break;
! 380: }
! 381:
! 382: DBG1(DBG_IKE, "received ME_CONNECT");
! 383: break;
! 384: }
! 385: default:
! 386: break;
! 387: }
! 388: return NEED_MORE;
! 389: }
! 390:
! 391: METHOD(task_t, build_r, status_t,
! 392: private_ike_me_t *this, message_t *message)
! 393: {
! 394: switch(message->get_exchange_type(message))
! 395: {
! 396: case ME_CONNECT:
! 397: {
! 398: if (this->invalid_syntax)
! 399: {
! 400: message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
! 401: break;
! 402: }
! 403:
! 404: if (this->callback)
! 405: {
! 406: /* we got a callback from the mediation server, initiate the
! 407: * queued mediated connection */
! 408: charon->connect_manager->check_and_initiate(
! 409: charon->connect_manager,
! 410: this->ike_sa->get_id(this->ike_sa),
! 411: this->ike_sa->get_my_id(this->ike_sa), this->peer_id);
! 412: return SUCCESS;
! 413: }
! 414:
! 415: if (this->response)
! 416: {
! 417: /* FIXME: handle result of set_responder_data
! 418: * as initiator, upon receiving a response from another peer,
! 419: * update the checklist and start sending checks */
! 420: charon->connect_manager->set_responder_data(
! 421: charon->connect_manager,
! 422: this->connect_id, this->connect_key,
! 423: this->remote_endpoints);
! 424: }
! 425: else
! 426: {
! 427: /* FIXME: handle result of set_initiator_data
! 428: * as responder, create a checklist with the initiator's data */
! 429: charon->connect_manager->set_initiator_data(
! 430: charon->connect_manager,
! 431: this->peer_id, this->ike_sa->get_my_id(this->ike_sa),
! 432: this->connect_id, this->connect_key,
! 433: this->remote_endpoints, FALSE);
! 434: if (this->ike_sa->respond(this->ike_sa, this->peer_id,
! 435: this->connect_id) != SUCCESS)
! 436: {
! 437: return FAILED;
! 438: }
! 439: }
! 440: break;
! 441: }
! 442: default:
! 443: break;
! 444: }
! 445: return SUCCESS;
! 446: }
! 447:
! 448: METHOD(task_t, process_i, status_t,
! 449: private_ike_me_t *this, message_t *message)
! 450: {
! 451: switch(message->get_exchange_type(message))
! 452: {
! 453: case IKE_SA_INIT:
! 454: {
! 455: process_payloads(this, message);
! 456: if (!this->mediation)
! 457: {
! 458: DBG1(DBG_IKE, "server did not return a ME_MEDIATION, aborting");
! 459: return FAILED;
! 460: }
! 461: /* if we are on a mediation connection we switch to port 4500 even
! 462: * if no NAT is detected. */
! 463: this->ike_sa->float_ports(this->ike_sa);
! 464: return NEED_MORE;
! 465: }
! 466: case IKE_AUTH:
! 467: {
! 468: process_payloads(this, message);
! 469: /* FIXME: we should update the server reflexive endpoint somehow,
! 470: * if mobike notices a change */
! 471: endpoint_notify_t *reflexive;
! 472: if (this->remote_endpoints->get_first(this->remote_endpoints,
! 473: (void**)&reflexive) == SUCCESS &&
! 474: reflexive->get_type(reflexive) == SERVER_REFLEXIVE)
! 475: { /* FIXME: should we accept this endpoint even if we did not send
! 476: * a request? */
! 477: host_t *endpoint = reflexive->get_host(reflexive);
! 478: endpoint = endpoint->clone(endpoint);
! 479: this->ike_sa->set_server_reflexive_host(this->ike_sa, endpoint);
! 480: }
! 481: break;
! 482: }
! 483: case ME_CONNECT:
! 484: {
! 485: process_payloads(this, message);
! 486:
! 487: if (this->failed)
! 488: {
! 489: DBG1(DBG_IKE, "peer '%Y' is not online", this->peer_id);
! 490: /* FIXME: notify the mediated connection (job?) */
! 491: }
! 492: else
! 493: {
! 494: if (this->response)
! 495: {
! 496: /* FIXME: handle result of set_responder_data. */
! 497: /* as responder, we update the checklist and start sending
! 498: * checks */
! 499: charon->connect_manager->set_responder_data(
! 500: charon->connect_manager, this->connect_id,
! 501: this->connect_key, this->local_endpoints);
! 502: }
! 503: else
! 504: {
! 505: /* FIXME: handle result of set_initiator_data */
! 506: /* as initiator, we create a checklist and set the
! 507: * initiator's data */
! 508: charon->connect_manager->set_initiator_data(
! 509: charon->connect_manager,
! 510: this->ike_sa->get_my_id(this->ike_sa),
! 511: this->peer_id, this->connect_id, this->connect_key,
! 512: this->local_endpoints, TRUE);
! 513: /* FIXME: also start a timer for the whole transaction
! 514: * (maybe within the connect_manager?) */
! 515: }
! 516: }
! 517: break;
! 518: }
! 519: default:
! 520: break;
! 521: }
! 522: return SUCCESS;
! 523: }
! 524:
! 525: /**
! 526: * For mediation server
! 527: */
! 528: METHOD(task_t, build_i_ms, status_t,
! 529: private_ike_me_t *this, message_t *message)
! 530: {
! 531: switch(message->get_exchange_type(message))
! 532: {
! 533: case ME_CONNECT:
! 534: {
! 535: id_payload_t *id_payload;
! 536: id_payload = id_payload_create_from_identification(PLV2_ID_PEER,
! 537: this->peer_id);
! 538: message->add_payload(message, (payload_t*)id_payload);
! 539:
! 540: if (this->callback)
! 541: {
! 542: message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty);
! 543: }
! 544: else
! 545: {
! 546: if (this->response)
! 547: {
! 548: message->add_notify(message, FALSE, ME_RESPONSE,
! 549: chunk_empty);
! 550: }
! 551: message->add_notify(message, FALSE, ME_CONNECTID,
! 552: this->connect_id);
! 553: message->add_notify(message, FALSE, ME_CONNECTKEY,
! 554: this->connect_key);
! 555: add_endpoints_to_message(message, this->remote_endpoints);
! 556: }
! 557: break;
! 558: }
! 559: default:
! 560: break;
! 561: }
! 562: return NEED_MORE;
! 563: }
! 564:
! 565: /**
! 566: * For mediation server
! 567: */
! 568: METHOD(task_t, process_r_ms, status_t,
! 569: private_ike_me_t *this, message_t *message)
! 570: {
! 571: switch(message->get_exchange_type(message))
! 572: {
! 573: case IKE_SA_INIT:
! 574: {
! 575: /* FIXME: we should check for SA* and TS* payloads. if there are
! 576: * any, send NO_ADDITIONAL_SAS back and delete this SA */
! 577: process_payloads(this, message);
! 578: return this->mediation ? NEED_MORE : SUCCESS;
! 579: }
! 580: case IKE_AUTH:
! 581: {
! 582: /* FIXME: we should check whether the current peer_config is
! 583: * configured as mediation connection */
! 584: process_payloads(this, message);
! 585: break;
! 586: }
! 587: case CREATE_CHILD_SA:
! 588: {
! 589: /* FIXME: if this is not to rekey the IKE SA we have to return a
! 590: * NO_ADDITIONAL_SAS and then delete the SA */
! 591: break;
! 592: }
! 593: case ME_CONNECT:
! 594: {
! 595: id_payload_t *id_payload;
! 596: id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_PEER);
! 597: if (!id_payload)
! 598: {
! 599: DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload"
! 600: ", aborting");
! 601: this->invalid_syntax = TRUE;
! 602: break;
! 603: }
! 604: this->peer_id = id_payload->get_identification(id_payload);
! 605:
! 606: process_payloads(this, message);
! 607:
! 608: if (!this->connect_id.ptr)
! 609: {
! 610: DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify"
! 611: ", aborting");
! 612: this->invalid_syntax = TRUE;
! 613: break;
! 614: }
! 615:
! 616: if (!this->connect_key.ptr)
! 617: {
! 618: DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY notify"
! 619: ", aborting");
! 620: this->invalid_syntax = TRUE;
! 621: break;
! 622: }
! 623:
! 624: if (!this->remote_endpoints->get_count(this->remote_endpoints))
! 625: {
! 626: DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT "
! 627: "payloads, aborting");
! 628: this->invalid_syntax = TRUE;
! 629: break;
! 630: }
! 631: break;
! 632: }
! 633: default:
! 634: break;
! 635: }
! 636: return NEED_MORE;
! 637: }
! 638:
! 639: /**
! 640: * For mediation server
! 641: */
! 642: METHOD(task_t, build_r_ms, status_t,
! 643: private_ike_me_t *this, message_t *message)
! 644: {
! 645: switch(message->get_exchange_type(message))
! 646: {
! 647: case IKE_SA_INIT:
! 648: {
! 649: message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty);
! 650: return NEED_MORE;
! 651: }
! 652: case IKE_AUTH:
! 653: {
! 654: endpoint_notify_t *endpoint;
! 655: if (this->remote_endpoints->get_first(this->remote_endpoints,
! 656: (void**)&endpoint) == SUCCESS &&
! 657: endpoint->get_type(endpoint) == SERVER_REFLEXIVE)
! 658: {
! 659: host_t *host = this->ike_sa->get_other_host(this->ike_sa);
! 660: DBG2(DBG_IKE, "received request for a server reflexive "
! 661: "endpoint sending: %#H", host);
! 662: endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE,
! 663: host, NULL);
! 664: message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
! 665: endpoint->destroy(endpoint);
! 666: }
! 667: this->ike_sa->act_as_mediation_server(this->ike_sa);
! 668: break;
! 669: }
! 670: case ME_CONNECT:
! 671: {
! 672: if (this->invalid_syntax)
! 673: {
! 674: message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
! 675: break;
! 676: }
! 677:
! 678: ike_sa_id_t *peer_sa;
! 679: if (this->callback)
! 680: {
! 681: peer_sa = charon->mediation_manager->check_and_register(
! 682: charon->mediation_manager, this->peer_id,
! 683: this->ike_sa->get_other_id(this->ike_sa));
! 684: }
! 685: else
! 686: {
! 687: peer_sa = charon->mediation_manager->check(
! 688: charon->mediation_manager, this->peer_id);
! 689: }
! 690:
! 691: if (!peer_sa)
! 692: {
! 693: /* the peer is not online */
! 694: message->add_notify(message, TRUE, ME_CONNECT_FAILED,
! 695: chunk_empty);
! 696: break;
! 697: }
! 698:
! 699: job_t *job = (job_t*)mediation_job_create(this->peer_id,
! 700: this->ike_sa->get_other_id(this->ike_sa), this->connect_id,
! 701: this->connect_key, this->remote_endpoints, this->response);
! 702: lib->processor->queue_job(lib->processor, job);
! 703: break;
! 704: }
! 705: default:
! 706: break;
! 707: }
! 708: return SUCCESS;
! 709: }
! 710:
! 711: /**
! 712: * For mediation server
! 713: */
! 714: METHOD(task_t, process_i_ms, status_t,
! 715: private_ike_me_t *this, message_t *message)
! 716: {
! 717: /* FIXME: theoretically we should be prepared to receive a ME_CONNECT_FAILED
! 718: * here if the responding peer is not able to proceed. in this case we shall
! 719: * notify the initiating peer with a ME_CONNECT request containing only a
! 720: * ME_CONNECT_FAILED */
! 721: return SUCCESS;
! 722: }
! 723:
! 724: METHOD(ike_me_t, me_connect, void,
! 725: private_ike_me_t *this, identification_t *peer_id)
! 726: {
! 727: this->peer_id = peer_id->clone(peer_id);
! 728: }
! 729:
! 730: METHOD(ike_me_t, me_respond, void,
! 731: private_ike_me_t *this, identification_t *peer_id, chunk_t connect_id)
! 732: {
! 733: this->peer_id = peer_id->clone(peer_id);
! 734: this->connect_id = chunk_clone(connect_id);
! 735: this->response = TRUE;
! 736: }
! 737:
! 738: METHOD(ike_me_t, me_callback, void,
! 739: private_ike_me_t *this, identification_t *peer_id)
! 740: {
! 741: this->peer_id = peer_id->clone(peer_id);
! 742: this->callback = TRUE;
! 743: }
! 744:
! 745: METHOD(ike_me_t, relay, void,
! 746: private_ike_me_t *this, identification_t *requester, chunk_t connect_id,
! 747: chunk_t connect_key, linked_list_t *endpoints, bool response)
! 748: {
! 749: this->peer_id = requester->clone(requester);
! 750: this->connect_id = chunk_clone(connect_id);
! 751: this->connect_key = chunk_clone(connect_key);
! 752:
! 753: this->remote_endpoints->destroy_offset(this->remote_endpoints,
! 754: offsetof(endpoint_notify_t, destroy));
! 755: this->remote_endpoints = endpoints->clone_offset(endpoints,
! 756: offsetof(endpoint_notify_t, clone));
! 757:
! 758: this->response = response;
! 759: }
! 760:
! 761: METHOD(task_t, get_type, task_type_t,
! 762: private_ike_me_t *this)
! 763: {
! 764: return TASK_IKE_ME;
! 765: }
! 766:
! 767: METHOD(task_t, migrate, void,
! 768: private_ike_me_t *this, ike_sa_t *ike_sa)
! 769: {
! 770: this->ike_sa = ike_sa;
! 771: }
! 772:
! 773: METHOD(task_t, destroy, void,
! 774: private_ike_me_t *this)
! 775: {
! 776: DESTROY_IF(this->peer_id);
! 777:
! 778: chunk_free(&this->connect_id);
! 779: chunk_free(&this->connect_key);
! 780:
! 781: this->local_endpoints->destroy_offset(this->local_endpoints,
! 782: offsetof(endpoint_notify_t, destroy));
! 783: this->remote_endpoints->destroy_offset(this->remote_endpoints,
! 784: offsetof(endpoint_notify_t, destroy));
! 785:
! 786: DESTROY_IF(this->mediated_cfg);
! 787: free(this);
! 788: }
! 789:
! 790: /*
! 791: * Described in header.
! 792: */
! 793: ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator)
! 794: {
! 795: private_ike_me_t *this;
! 796:
! 797: INIT(this,
! 798: .public = {
! 799: .task = {
! 800: .get_type = _get_type,
! 801: .migrate = _migrate,
! 802: .destroy = _destroy,
! 803: },
! 804: .connect = _me_connect,
! 805: .respond = _me_respond,
! 806: .callback = _me_callback,
! 807: .relay = _relay,
! 808: },
! 809: .ike_sa = ike_sa,
! 810: .initiator = initiator,
! 811: .local_endpoints = linked_list_create(),
! 812: .remote_endpoints = linked_list_create(),
! 813: );
! 814:
! 815: if (ike_sa->has_condition(ike_sa, COND_ORIGINAL_INITIATOR))
! 816: {
! 817: if (initiator)
! 818: {
! 819: this->public.task.build = _build_i;
! 820: this->public.task.process = _process_i;
! 821: }
! 822: else
! 823: {
! 824: this->public.task.build = _build_r;
! 825: this->public.task.process = _process_r;
! 826: }
! 827: }
! 828: else
! 829: {
! 830: /* mediation server */
! 831: if (initiator)
! 832: {
! 833: this->public.task.build = _build_i_ms;
! 834: this->public.task.process = _process_i_ms;
! 835: }
! 836: else
! 837: {
! 838: this->public.task.build = _build_r_ms;
! 839: this->public.task.process = _process_r_ms;
! 840: }
! 841: }
! 842:
! 843: return &this->public;
! 844: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>