Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/task_manager_v1.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2007-2019 Tobias Brunner
! 3: * Copyright (C) 2007-2011 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 "task_manager_v1.h"
! 18:
! 19: #include <math.h>
! 20:
! 21: #include <daemon.h>
! 22: #include <sa/ikev1/tasks/main_mode.h>
! 23: #include <sa/ikev1/tasks/aggressive_mode.h>
! 24: #include <sa/ikev1/tasks/quick_mode.h>
! 25: #include <sa/ikev1/tasks/quick_delete.h>
! 26: #include <sa/ikev1/tasks/xauth.h>
! 27: #include <sa/ikev1/tasks/mode_config.h>
! 28: #include <sa/ikev1/tasks/informational.h>
! 29: #include <sa/ikev1/tasks/isakmp_natd.h>
! 30: #include <sa/ikev1/tasks/isakmp_vendor.h>
! 31: #include <sa/ikev1/tasks/isakmp_cert_pre.h>
! 32: #include <sa/ikev1/tasks/isakmp_cert_post.h>
! 33: #include <sa/ikev1/tasks/isakmp_delete.h>
! 34: #include <sa/ikev1/tasks/isakmp_dpd.h>
! 35:
! 36: #include <processing/jobs/retransmit_job.h>
! 37: #include <processing/jobs/delete_ike_sa_job.h>
! 38: #include <processing/jobs/dpd_timeout_job.h>
! 39: #include <processing/jobs/process_message_job.h>
! 40:
! 41: #include <collections/array.h>
! 42:
! 43: /**
! 44: * Number of old messages hashes we keep for retransmission.
! 45: *
! 46: * In Main Mode, we must ignore messages from a previous message pair if
! 47: * we already continued to the next. Otherwise a late retransmission
! 48: * could be considered as a reply to the newer request.
! 49: */
! 50: #define MAX_OLD_HASHES 2
! 51:
! 52: /**
! 53: * First sequence number of responding packets.
! 54: *
! 55: * To distinguish retransmission jobs for initiating and responding packets,
! 56: * we split up the sequence counter and use the upper half for responding.
! 57: */
! 58: #define RESPONDING_SEQ INT_MAX
! 59:
! 60: typedef struct exchange_t exchange_t;
! 61:
! 62: /**
! 63: * An exchange in the air, used do detect and handle retransmission
! 64: */
! 65: struct exchange_t {
! 66:
! 67: /**
! 68: * Message ID used for this transaction
! 69: */
! 70: uint32_t mid;
! 71:
! 72: /**
! 73: * generated packet for retransmission
! 74: */
! 75: packet_t *packet;
! 76: };
! 77:
! 78: typedef struct private_task_manager_t private_task_manager_t;
! 79:
! 80: /**
! 81: * private data of the task manager
! 82: */
! 83: struct private_task_manager_t {
! 84:
! 85: /**
! 86: * public functions
! 87: */
! 88: task_manager_v1_t public;
! 89:
! 90: /**
! 91: * associated IKE_SA we are serving
! 92: */
! 93: ike_sa_t *ike_sa;
! 94:
! 95: /**
! 96: * RNG to create message IDs
! 97: */
! 98: rng_t *rng;
! 99:
! 100: /**
! 101: * Exchange we are currently handling as responder
! 102: */
! 103: struct {
! 104: /**
! 105: * Message ID of the last response
! 106: */
! 107: uint32_t mid;
! 108:
! 109: /**
! 110: * Hash of a previously received message
! 111: */
! 112: uint32_t hash;
! 113:
! 114: /**
! 115: * packet(s) for retransmission
! 116: */
! 117: array_t *packets;
! 118:
! 119: /**
! 120: * Sequence number of the last sent message
! 121: */
! 122: uint32_t seqnr;
! 123:
! 124: /**
! 125: * how many times we have retransmitted so far
! 126: */
! 127: u_int retransmitted;
! 128:
! 129: } responding;
! 130:
! 131: /**
! 132: * Exchange we are currently handling as initiator
! 133: */
! 134: struct {
! 135: /**
! 136: * Message ID of the exchange
! 137: */
! 138: uint32_t mid;
! 139:
! 140: /**
! 141: * Hashes of old responses we can ignore
! 142: */
! 143: uint32_t old_hashes[MAX_OLD_HASHES];
! 144:
! 145: /**
! 146: * Position in old hash array
! 147: */
! 148: int old_hash_pos;
! 149:
! 150: /**
! 151: * Sequence number of the last sent message
! 152: */
! 153: uint32_t seqnr;
! 154:
! 155: /**
! 156: * how many times we have retransmitted so far
! 157: */
! 158: u_int retransmitted;
! 159:
! 160: /**
! 161: * packet(s) for retransmission
! 162: */
! 163: array_t *packets;
! 164:
! 165: /**
! 166: * type of the initiated exchange
! 167: */
! 168: exchange_type_t type;
! 169:
! 170: } initiating;
! 171:
! 172: /**
! 173: * Message we are currently defragmenting, if any (only one at a time)
! 174: */
! 175: message_t *defrag;
! 176:
! 177: /**
! 178: * List of queued tasks not yet in action
! 179: */
! 180: linked_list_t *queued_tasks;
! 181:
! 182: /**
! 183: * List of active tasks, initiated by ourselves
! 184: */
! 185: linked_list_t *active_tasks;
! 186:
! 187: /**
! 188: * List of tasks initiated by peer
! 189: */
! 190: linked_list_t *passive_tasks;
! 191:
! 192: /**
! 193: * Queued messages not yet ready to process
! 194: */
! 195: message_t *queued;
! 196:
! 197: /**
! 198: * Number of times we retransmit messages before giving up
! 199: */
! 200: u_int retransmit_tries;
! 201:
! 202: /**
! 203: * Retransmission timeout
! 204: */
! 205: double retransmit_timeout;
! 206:
! 207: /**
! 208: * Base to calculate retransmission timeout
! 209: */
! 210: double retransmit_base;
! 211:
! 212: /**
! 213: * Jitter to apply to calculated retransmit timeout (in percent)
! 214: */
! 215: u_int retransmit_jitter;
! 216:
! 217: /**
! 218: * Limit retransmit timeout to this value
! 219: */
! 220: uint32_t retransmit_limit;
! 221:
! 222: /**
! 223: * Sequence number for sending DPD requests
! 224: */
! 225: uint32_t dpd_send;
! 226:
! 227: /**
! 228: * Sequence number for received DPD requests
! 229: */
! 230: uint32_t dpd_recv;
! 231: };
! 232:
! 233: /**
! 234: * Reset retransmission packet list
! 235: */
! 236: static void clear_packets(array_t *array)
! 237: {
! 238: packet_t *packet;
! 239:
! 240: while (array_remove(array, ARRAY_TAIL, &packet))
! 241: {
! 242: packet->destroy(packet);
! 243: }
! 244: }
! 245:
! 246: METHOD(task_manager_t, flush_queue, void,
! 247: private_task_manager_t *this, task_queue_t queue)
! 248: {
! 249: linked_list_t *list;
! 250: task_t *task;
! 251:
! 252: if (this->queued)
! 253: {
! 254: this->queued->destroy(this->queued);
! 255: this->queued = NULL;
! 256: }
! 257: switch (queue)
! 258: {
! 259: case TASK_QUEUE_ACTIVE:
! 260: list = this->active_tasks;
! 261: /* cancel pending retransmits */
! 262: this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
! 263: clear_packets(this->initiating.packets);
! 264: break;
! 265: case TASK_QUEUE_PASSIVE:
! 266: list = this->passive_tasks;
! 267: break;
! 268: case TASK_QUEUE_QUEUED:
! 269: list = this->queued_tasks;
! 270: break;
! 271: default:
! 272: return;
! 273: }
! 274: while (list->remove_last(list, (void**)&task) == SUCCESS)
! 275: {
! 276: task->destroy(task);
! 277: }
! 278: }
! 279:
! 280: METHOD(task_manager_t, flush, void,
! 281: private_task_manager_t *this)
! 282: {
! 283: flush_queue(this, TASK_QUEUE_QUEUED);
! 284: flush_queue(this, TASK_QUEUE_PASSIVE);
! 285: flush_queue(this, TASK_QUEUE_ACTIVE);
! 286: }
! 287:
! 288: /**
! 289: * move a task of a specific type from the queue to the active list
! 290: */
! 291: static bool activate_task(private_task_manager_t *this, task_type_t type)
! 292: {
! 293: enumerator_t *enumerator;
! 294: task_t *task;
! 295: bool found = FALSE;
! 296:
! 297: enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
! 298: while (enumerator->enumerate(enumerator, (void**)&task))
! 299: {
! 300: if (task->get_type(task) == type)
! 301: {
! 302: DBG2(DBG_IKE, " activating %N task", task_type_names, type);
! 303: this->queued_tasks->remove_at(this->queued_tasks, enumerator);
! 304: this->active_tasks->insert_last(this->active_tasks, task);
! 305: found = TRUE;
! 306: break;
! 307: }
! 308: }
! 309: enumerator->destroy(enumerator);
! 310: return found;
! 311: }
! 312:
! 313: /**
! 314: * Send packets in the given array (they get cloned)
! 315: */
! 316: static void send_packets(private_task_manager_t *this, array_t *packets)
! 317: {
! 318: enumerator_t *enumerator;
! 319: packet_t *packet;
! 320:
! 321: enumerator = array_create_enumerator(packets);
! 322: while (enumerator->enumerate(enumerator, &packet))
! 323: {
! 324: charon->sender->send(charon->sender, packet->clone(packet));
! 325: }
! 326: enumerator->destroy(enumerator);
! 327: }
! 328:
! 329: /**
! 330: * Generates the given message and stores packet(s) in the given array
! 331: */
! 332: static bool generate_message(private_task_manager_t *this, message_t *message,
! 333: array_t **packets)
! 334: {
! 335: enumerator_t *fragments;
! 336: packet_t *fragment;
! 337:
! 338: if (this->ike_sa->generate_message_fragmented(this->ike_sa, message,
! 339: &fragments) != SUCCESS)
! 340: {
! 341: return FALSE;
! 342: }
! 343: while (fragments->enumerate(fragments, &fragment))
! 344: {
! 345: array_insert_create(packets, ARRAY_TAIL, fragment);
! 346: }
! 347: fragments->destroy(fragments);
! 348: return TRUE;
! 349: }
! 350:
! 351: /**
! 352: * Retransmit a packet (or its fragments)
! 353: */
! 354: static status_t retransmit_packet(private_task_manager_t *this, uint32_t seqnr,
! 355: u_int mid, u_int retransmitted, array_t *packets)
! 356: {
! 357: packet_t *packet;
! 358: uint32_t t, max_jitter;
! 359:
! 360: array_get(packets, 0, &packet);
! 361: if (retransmitted > this->retransmit_tries)
! 362: {
! 363: DBG1(DBG_IKE, "giving up after %u retransmits", retransmitted - 1);
! 364: charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_TIMEOUT, packet);
! 365: return DESTROY_ME;
! 366: }
! 367: t = (uint32_t)(this->retransmit_timeout * 1000.0 *
! 368: pow(this->retransmit_base, retransmitted));
! 369: if (this->retransmit_limit)
! 370: {
! 371: t = min(t, this->retransmit_limit);
! 372: }
! 373: if (this->retransmit_jitter)
! 374: {
! 375: max_jitter = (t / 100.0) * this->retransmit_jitter;
! 376: t -= max_jitter * (random() / (RAND_MAX + 1.0));
! 377: }
! 378: if (retransmitted)
! 379: {
! 380: DBG1(DBG_IKE, "sending retransmit %u of %s message ID %u, seq %u",
! 381: retransmitted, seqnr < RESPONDING_SEQ ? "request" : "response",
! 382: mid, seqnr < RESPONDING_SEQ ? seqnr : seqnr - RESPONDING_SEQ);
! 383: charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet,
! 384: retransmitted);
! 385: }
! 386: send_packets(this, packets);
! 387: lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
! 388: retransmit_job_create(seqnr, this->ike_sa->get_id(this->ike_sa)), t);
! 389: return SUCCESS;
! 390: }
! 391:
! 392: METHOD(task_manager_t, retransmit, status_t,
! 393: private_task_manager_t *this, uint32_t seqnr)
! 394: {
! 395: status_t status = SUCCESS;
! 396:
! 397: if (seqnr == this->initiating.seqnr &&
! 398: array_count(this->initiating.packets))
! 399: {
! 400: status = retransmit_packet(this, seqnr, this->initiating.mid,
! 401: this->initiating.retransmitted, this->initiating.packets);
! 402: if (status == SUCCESS)
! 403: {
! 404: this->initiating.retransmitted++;
! 405: }
! 406: }
! 407: if (seqnr == this->responding.seqnr &&
! 408: array_count(this->responding.packets))
! 409: {
! 410: status = retransmit_packet(this, seqnr, this->responding.mid,
! 411: this->responding.retransmitted, this->responding.packets);
! 412: if (status == SUCCESS)
! 413: {
! 414: this->responding.retransmitted++;
! 415: }
! 416: }
! 417: return status;
! 418: }
! 419:
! 420: /**
! 421: * Check if we have to wait for a mode config before starting a quick mode
! 422: */
! 423: static bool mode_config_expected(private_task_manager_t *this)
! 424: {
! 425: enumerator_t *enumerator;
! 426: peer_cfg_t *peer_cfg;
! 427: char *pool;
! 428: bool local;
! 429: host_t *host;
! 430:
! 431: peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
! 432: if (peer_cfg)
! 433: {
! 434: if (peer_cfg->use_pull_mode(peer_cfg))
! 435: {
! 436: enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
! 437: if (!enumerator->enumerate(enumerator, &pool))
! 438: { /* no pool configured */
! 439: enumerator->destroy(enumerator);
! 440: return FALSE;
! 441: }
! 442: enumerator->destroy(enumerator);
! 443:
! 444: local = FALSE;
! 445: }
! 446: else
! 447: {
! 448: enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
! 449: if (!enumerator->enumerate(enumerator, &host))
! 450: { /* not requesting a vip */
! 451: enumerator->destroy(enumerator);
! 452: return FALSE;
! 453: }
! 454: enumerator->destroy(enumerator);
! 455:
! 456: local = TRUE;
! 457: }
! 458: enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
! 459: local);
! 460: if (!enumerator->enumerate(enumerator, &host))
! 461: { /* expecting a VIP exchange, but no VIP assigned yet */
! 462: enumerator->destroy(enumerator);
! 463: return TRUE;
! 464: }
! 465: enumerator->destroy(enumerator);
! 466: }
! 467: return FALSE;
! 468: }
! 469:
! 470: METHOD(task_manager_t, initiate, status_t,
! 471: private_task_manager_t *this)
! 472: {
! 473: enumerator_t *enumerator;
! 474: task_t *task;
! 475: message_t *message;
! 476: host_t *me, *other;
! 477: exchange_type_t exchange = EXCHANGE_TYPE_UNDEFINED;
! 478: bool new_mid = FALSE, expect_response = FALSE, cancelled = FALSE, keep = FALSE;
! 479:
! 480: if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED &&
! 481: this->initiating.type != INFORMATIONAL_V1)
! 482: {
! 483: DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
! 484: exchange_type_names, this->initiating.type);
! 485: /* do not initiate if we already have a message in the air */
! 486: return SUCCESS;
! 487: }
! 488:
! 489: if (this->active_tasks->get_count(this->active_tasks) == 0)
! 490: {
! 491: DBG2(DBG_IKE, "activating new tasks");
! 492: switch (this->ike_sa->get_state(this->ike_sa))
! 493: {
! 494: case IKE_CREATED:
! 495: activate_task(this, TASK_ISAKMP_VENDOR);
! 496: activate_task(this, TASK_ISAKMP_CERT_PRE);
! 497: if (activate_task(this, TASK_MAIN_MODE))
! 498: {
! 499: exchange = ID_PROT;
! 500: }
! 501: else if (activate_task(this, TASK_AGGRESSIVE_MODE))
! 502: {
! 503: exchange = AGGRESSIVE;
! 504: }
! 505: activate_task(this, TASK_ISAKMP_CERT_POST);
! 506: activate_task(this, TASK_ISAKMP_NATD);
! 507: break;
! 508: case IKE_CONNECTING:
! 509: if (activate_task(this, TASK_ISAKMP_DELETE))
! 510: {
! 511: exchange = INFORMATIONAL_V1;
! 512: new_mid = TRUE;
! 513: break;
! 514: }
! 515: if (activate_task(this, TASK_XAUTH))
! 516: {
! 517: exchange = TRANSACTION;
! 518: new_mid = TRUE;
! 519: break;
! 520: }
! 521: if (activate_task(this, TASK_INFORMATIONAL))
! 522: {
! 523: exchange = INFORMATIONAL_V1;
! 524: new_mid = TRUE;
! 525: break;
! 526: }
! 527: break;
! 528: case IKE_ESTABLISHED:
! 529: if (activate_task(this, TASK_MODE_CONFIG))
! 530: {
! 531: exchange = TRANSACTION;
! 532: new_mid = TRUE;
! 533: break;
! 534: }
! 535: if (activate_task(this, TASK_QUICK_DELETE))
! 536: {
! 537: exchange = INFORMATIONAL_V1;
! 538: new_mid = TRUE;
! 539: break;
! 540: }
! 541: if (activate_task(this, TASK_ISAKMP_DELETE))
! 542: {
! 543: exchange = INFORMATIONAL_V1;
! 544: new_mid = TRUE;
! 545: break;
! 546: }
! 547: if (activate_task(this, TASK_ISAKMP_DPD))
! 548: {
! 549: exchange = INFORMATIONAL_V1;
! 550: new_mid = TRUE;
! 551: break;
! 552: }
! 553: if (!mode_config_expected(this) &&
! 554: activate_task(this, TASK_QUICK_MODE))
! 555: {
! 556: exchange = QUICK_MODE;
! 557: new_mid = TRUE;
! 558: break;
! 559: }
! 560: if (activate_task(this, TASK_INFORMATIONAL))
! 561: {
! 562: exchange = INFORMATIONAL_V1;
! 563: new_mid = TRUE;
! 564: break;
! 565: }
! 566: break;
! 567: case IKE_REKEYING:
! 568: if (activate_task(this, TASK_ISAKMP_DELETE))
! 569: {
! 570: exchange = INFORMATIONAL_V1;
! 571: new_mid = TRUE;
! 572: break;
! 573: }
! 574: if (activate_task(this, TASK_ISAKMP_DPD))
! 575: {
! 576: exchange = INFORMATIONAL_V1;
! 577: new_mid = TRUE;
! 578: break;
! 579: }
! 580: break;
! 581: default:
! 582: break;
! 583: }
! 584: }
! 585: else
! 586: {
! 587: DBG2(DBG_IKE, "reinitiating already active tasks");
! 588: enumerator = this->active_tasks->create_enumerator(this->active_tasks);
! 589: while (enumerator->enumerate(enumerator, (void**)&task))
! 590: {
! 591: DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
! 592: switch (task->get_type(task))
! 593: {
! 594: case TASK_MAIN_MODE:
! 595: exchange = ID_PROT;
! 596: break;
! 597: case TASK_AGGRESSIVE_MODE:
! 598: exchange = AGGRESSIVE;
! 599: break;
! 600: case TASK_QUICK_MODE:
! 601: exchange = QUICK_MODE;
! 602: break;
! 603: case TASK_XAUTH:
! 604: exchange = TRANSACTION;
! 605: new_mid = TRUE;
! 606: break;
! 607: default:
! 608: continue;
! 609: }
! 610: break;
! 611: }
! 612: enumerator->destroy(enumerator);
! 613: }
! 614:
! 615: if (exchange == EXCHANGE_TYPE_UNDEFINED)
! 616: {
! 617: DBG2(DBG_IKE, "nothing to initiate");
! 618: /* nothing to do yet... */
! 619: return SUCCESS;
! 620: }
! 621:
! 622: me = this->ike_sa->get_my_host(this->ike_sa);
! 623: other = this->ike_sa->get_other_host(this->ike_sa);
! 624:
! 625: if (new_mid)
! 626: {
! 627: if (!this->rng->get_bytes(this->rng, sizeof(this->initiating.mid),
! 628: (void*)&this->initiating.mid))
! 629: {
! 630: DBG1(DBG_IKE, "failed to allocate message ID, destroying IKE_SA");
! 631: flush(this);
! 632: return DESTROY_ME;
! 633: }
! 634: }
! 635: message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
! 636: message->set_message_id(message, this->initiating.mid);
! 637: message->set_source(message, me->clone(me));
! 638: message->set_destination(message, other->clone(other));
! 639: message->set_exchange_type(message, exchange);
! 640: this->initiating.type = exchange;
! 641: this->initiating.retransmitted = 0;
! 642:
! 643: enumerator = this->active_tasks->create_enumerator(this->active_tasks);
! 644: while (enumerator->enumerate(enumerator, (void*)&task))
! 645: {
! 646: switch (task->build(task, message))
! 647: {
! 648: case SUCCESS:
! 649: /* task completed, remove it */
! 650: this->active_tasks->remove_at(this->active_tasks, enumerator);
! 651: if (task->get_type(task) == TASK_AGGRESSIVE_MODE ||
! 652: task->get_type(task) == TASK_QUICK_MODE)
! 653: { /* last message of three message exchange */
! 654: keep = TRUE;
! 655: }
! 656: task->destroy(task);
! 657: continue;
! 658: case NEED_MORE:
! 659: expect_response = TRUE;
! 660: /* processed, but task needs another exchange */
! 661: continue;
! 662: case ALREADY_DONE:
! 663: cancelled = TRUE;
! 664: break;
! 665: case FAILED:
! 666: default:
! 667: if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
! 668: {
! 669: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 670: }
! 671: /* FALL */
! 672: case DESTROY_ME:
! 673: /* critical failure, destroy IKE_SA */
! 674: enumerator->destroy(enumerator);
! 675: message->destroy(message);
! 676: flush(this);
! 677: return DESTROY_ME;
! 678: }
! 679: break;
! 680: }
! 681: enumerator->destroy(enumerator);
! 682:
! 683: if (this->active_tasks->get_count(this->active_tasks) == 0 &&
! 684: (exchange == QUICK_MODE || exchange == AGGRESSIVE))
! 685: { /* tasks completed, no exchange active anymore */
! 686: this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
! 687: }
! 688: if (cancelled)
! 689: {
! 690: message->destroy(message);
! 691: return initiate(this);
! 692: }
! 693:
! 694: clear_packets(this->initiating.packets);
! 695: if (!generate_message(this, message, &this->initiating.packets))
! 696: {
! 697: /* message generation failed. There is nothing more to do than to
! 698: * close the SA */
! 699: message->destroy(message);
! 700: flush(this);
! 701: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 702: return DESTROY_ME;
! 703: }
! 704:
! 705: this->initiating.seqnr++;
! 706: if (expect_response)
! 707: {
! 708: message->destroy(message);
! 709: return retransmit(this, this->initiating.seqnr);
! 710: }
! 711: send_packets(this, this->initiating.packets);
! 712: if (!keep)
! 713: {
! 714: clear_packets(this->initiating.packets);
! 715: }
! 716: message->destroy(message);
! 717:
! 718: if (exchange == INFORMATIONAL_V1)
! 719: {
! 720: switch (this->ike_sa->get_state(this->ike_sa))
! 721: {
! 722: case IKE_CONNECTING:
! 723: /* close after sending an INFORMATIONAL when unestablished */
! 724: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 725: return FAILED;
! 726: case IKE_DELETING:
! 727: /* close after sending a DELETE */
! 728: return DESTROY_ME;
! 729: default:
! 730: break;
! 731: }
! 732: }
! 733: return initiate(this);
! 734: }
! 735:
! 736: /**
! 737: * build a response depending on the "passive" task list
! 738: */
! 739: static status_t build_response(private_task_manager_t *this, message_t *request)
! 740: {
! 741: enumerator_t *enumerator;
! 742: task_t *task;
! 743: message_t *message;
! 744: host_t *me, *other;
! 745: bool delete = FALSE, cancelled = FALSE, expect_request = FALSE;
! 746:
! 747: me = request->get_destination(request);
! 748: other = request->get_source(request);
! 749:
! 750: message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
! 751: message->set_exchange_type(message, request->get_exchange_type(request));
! 752: /* send response along the path the request came in */
! 753: message->set_source(message, me->clone(me));
! 754: message->set_destination(message, other->clone(other));
! 755: message->set_message_id(message, request->get_message_id(request));
! 756: message->set_request(message, FALSE);
! 757:
! 758: this->responding.mid = request->get_message_id(request);
! 759: this->responding.retransmitted = 0;
! 760: this->responding.seqnr++;
! 761:
! 762: enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
! 763: while (enumerator->enumerate(enumerator, (void*)&task))
! 764: {
! 765: switch (task->build(task, message))
! 766: {
! 767: case SUCCESS:
! 768: /* task completed, remove it */
! 769: this->passive_tasks->remove_at(this->passive_tasks, enumerator);
! 770: task->destroy(task);
! 771: continue;
! 772: case NEED_MORE:
! 773: /* processed, but task needs another exchange */
! 774: if (task->get_type(task) == TASK_QUICK_MODE ||
! 775: task->get_type(task) == TASK_AGGRESSIVE_MODE)
! 776: { /* we rely on initiator retransmission, except for
! 777: * three-message exchanges */
! 778: expect_request = TRUE;
! 779: }
! 780: continue;
! 781: case ALREADY_DONE:
! 782: cancelled = TRUE;
! 783: break;
! 784: case INVALID_ARG:
! 785: if (task->get_type(task) == TASK_QUICK_MODE)
! 786: { /* not responsible for this exchange */
! 787: continue;
! 788: }
! 789: /* FALL */
! 790: case FAILED:
! 791: default:
! 792: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 793: /* FALL */
! 794: case DESTROY_ME:
! 795: /* destroy IKE_SA, but SEND response first */
! 796: delete = TRUE;
! 797: break;
! 798: }
! 799: break;
! 800: }
! 801: enumerator->destroy(enumerator);
! 802:
! 803: clear_packets(this->responding.packets);
! 804: if (cancelled)
! 805: {
! 806: message->destroy(message);
! 807: return initiate(this);
! 808: }
! 809: if (!generate_message(this, message, &this->responding.packets))
! 810: {
! 811: message->destroy(message);
! 812: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 813: return DESTROY_ME;
! 814: }
! 815: message->destroy(message);
! 816:
! 817: if (expect_request && !delete)
! 818: {
! 819: return retransmit(this, this->responding.seqnr);
! 820: }
! 821: send_packets(this, this->responding.packets);
! 822: if (delete)
! 823: {
! 824: return DESTROY_ME;
! 825: }
! 826: return SUCCESS;
! 827: }
! 828:
! 829: /**
! 830: * Send a notify in a separate INFORMATIONAL exchange back to the sender.
! 831: * The notify protocol_id is set to ISAKMP
! 832: */
! 833: static void send_notify(private_task_manager_t *this, message_t *request,
! 834: notify_type_t type)
! 835: {
! 836: message_t *response;
! 837: array_t *packets = NULL;
! 838: host_t *me, *other;
! 839: uint32_t mid;
! 840:
! 841: if (request->get_exchange_type(request) == INFORMATIONAL_V1)
! 842: { /* don't respond to INFORMATIONAL requests to avoid a notify war */
! 843: DBG1(DBG_IKE, "ignore malformed INFORMATIONAL request");
! 844: return;
! 845: }
! 846: if (!this->rng->get_bytes(this->rng, sizeof(mid), (void*)&mid))
! 847: {
! 848: DBG1(DBG_IKE, "failed to allocate message ID");
! 849: return;
! 850: }
! 851: response = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
! 852: response->set_exchange_type(response, INFORMATIONAL_V1);
! 853: response->set_request(response, TRUE);
! 854: response->set_message_id(response, mid);
! 855: response->add_payload(response, (payload_t*)
! 856: notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
! 857: PROTO_IKE, type));
! 858:
! 859: me = this->ike_sa->get_my_host(this->ike_sa);
! 860: if (me->is_anyaddr(me))
! 861: {
! 862: me = request->get_destination(request);
! 863: this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
! 864: }
! 865: other = this->ike_sa->get_other_host(this->ike_sa);
! 866: if (other->is_anyaddr(other))
! 867: {
! 868: other = request->get_source(request);
! 869: this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
! 870: }
! 871: response->set_source(response, me->clone(me));
! 872: response->set_destination(response, other->clone(other));
! 873: if (generate_message(this, response, &packets))
! 874: {
! 875: send_packets(this, packets);
! 876: }
! 877: clear_packets(packets);
! 878: array_destroy(packets);
! 879: response->destroy(response);
! 880: }
! 881:
! 882: /**
! 883: * Process a DPD request/response
! 884: */
! 885: static bool process_dpd(private_task_manager_t *this, message_t *message)
! 886: {
! 887: notify_payload_t *notify;
! 888: notify_type_t type;
! 889: uint32_t seq;
! 890: chunk_t data;
! 891:
! 892: type = DPD_R_U_THERE;
! 893: notify = message->get_notify(message, type);
! 894: if (!notify)
! 895: {
! 896: type = DPD_R_U_THERE_ACK;
! 897: notify = message->get_notify(message, type);
! 898: }
! 899: if (!notify)
! 900: {
! 901: return FALSE;
! 902: }
! 903: data = notify->get_notification_data(notify);
! 904: if (data.len != 4)
! 905: {
! 906: return FALSE;
! 907: }
! 908: seq = untoh32(data.ptr);
! 909:
! 910: if (type == DPD_R_U_THERE)
! 911: {
! 912: if (this->dpd_recv == 0 || seq == this->dpd_recv)
! 913: { /* check sequence validity */
! 914: this->dpd_recv = seq + 1;
! 915: this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
! 916: time_monotonic(NULL));
! 917: }
! 918: /* but respond anyway */
! 919: this->ike_sa->queue_task(this->ike_sa,
! 920: &isakmp_dpd_create(this->ike_sa, DPD_R_U_THERE_ACK, seq)->task);
! 921: }
! 922: else /* DPD_R_U_THERE_ACK */
! 923: {
! 924: if (seq == this->dpd_send)
! 925: {
! 926: this->dpd_send++;
! 927: this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
! 928: time_monotonic(NULL));
! 929: }
! 930: else
! 931: {
! 932: DBG1(DBG_IKE, "received invalid DPD sequence number %u "
! 933: "(expected %u), ignored", seq, this->dpd_send);
! 934: }
! 935: }
! 936: return TRUE;
! 937: }
! 938:
! 939: /**
! 940: * Check if we already have a quick mode task queued for the exchange with the
! 941: * given message ID
! 942: */
! 943: static bool have_quick_mode_task(private_task_manager_t *this, uint32_t mid)
! 944: {
! 945: enumerator_t *enumerator;
! 946: quick_mode_t *qm;
! 947: task_t *task;
! 948: bool found = FALSE;
! 949:
! 950: enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
! 951: while (enumerator->enumerate(enumerator, &task))
! 952: {
! 953: if (task->get_type(task) == TASK_QUICK_MODE)
! 954: {
! 955: qm = (quick_mode_t*)task;
! 956: if (qm->get_mid(qm) == mid)
! 957: {
! 958: found = TRUE;
! 959: break;
! 960: }
! 961: }
! 962: }
! 963: enumerator->destroy(enumerator);
! 964: return found;
! 965: }
! 966:
! 967: /**
! 968: * Check if we still have a specific task queued
! 969: */
! 970: static bool have_task_queued(private_task_manager_t *this, task_type_t type)
! 971: {
! 972: enumerator_t *enumerator;
! 973: task_t *task;
! 974: bool found = FALSE;
! 975:
! 976: enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
! 977: while (enumerator->enumerate(enumerator, &task))
! 978: {
! 979: if (task->get_type(task) == type)
! 980: {
! 981: found = TRUE;
! 982: break;
! 983: }
! 984: }
! 985: enumerator->destroy(enumerator);
! 986: return found;
! 987: }
! 988:
! 989: /**
! 990: * handle an incoming request message
! 991: */
! 992: static status_t process_request(private_task_manager_t *this,
! 993: message_t *message)
! 994: {
! 995: enumerator_t *enumerator;
! 996: task_t *task = NULL;
! 997: bool send_response = FALSE, dpd = FALSE;
! 998:
! 999: if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
! 1000: message->get_exchange_type(message) == QUICK_MODE ||
! 1001: this->passive_tasks->get_count(this->passive_tasks) == 0)
! 1002: { /* create tasks depending on request type, if not already some queued */
! 1003: switch (message->get_exchange_type(message))
! 1004: {
! 1005: case ID_PROT:
! 1006: task = (task_t *)isakmp_vendor_create(this->ike_sa, FALSE);
! 1007: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1008: task = (task_t*)isakmp_cert_pre_create(this->ike_sa, FALSE);
! 1009: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1010: task = (task_t *)main_mode_create(this->ike_sa, FALSE);
! 1011: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1012: task = (task_t*)isakmp_cert_post_create(this->ike_sa, FALSE);
! 1013: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1014: task = (task_t *)isakmp_natd_create(this->ike_sa, FALSE);
! 1015: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1016: break;
! 1017: case AGGRESSIVE:
! 1018: task = (task_t *)isakmp_vendor_create(this->ike_sa, FALSE);
! 1019: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1020: task = (task_t*)isakmp_cert_pre_create(this->ike_sa, FALSE);
! 1021: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1022: task = (task_t *)aggressive_mode_create(this->ike_sa, FALSE);
! 1023: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1024: task = (task_t*)isakmp_cert_post_create(this->ike_sa, FALSE);
! 1025: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1026: task = (task_t *)isakmp_natd_create(this->ike_sa, FALSE);
! 1027: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1028: break;
! 1029: case QUICK_MODE:
! 1030: if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
! 1031: {
! 1032: DBG1(DBG_IKE, "received quick mode request for "
! 1033: "unestablished IKE_SA, ignored");
! 1034: return FAILED;
! 1035: }
! 1036: if (have_quick_mode_task(this, message->get_message_id(message)))
! 1037: {
! 1038: break;
! 1039: }
! 1040: task = (task_t *)quick_mode_create(this->ike_sa, NULL,
! 1041: NULL, NULL);
! 1042: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1043: break;
! 1044: case INFORMATIONAL_V1:
! 1045: if (process_dpd(this, message))
! 1046: {
! 1047: dpd = TRUE;
! 1048: }
! 1049: else
! 1050: {
! 1051: task = (task_t *)informational_create(this->ike_sa, NULL);
! 1052: this->passive_tasks->insert_first(this->passive_tasks, task);
! 1053: }
! 1054: break;
! 1055: case TRANSACTION:
! 1056: if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
! 1057: {
! 1058: task = (task_t *)mode_config_create(this->ike_sa,
! 1059: FALSE, TRUE);
! 1060: }
! 1061: else
! 1062: {
! 1063: task = (task_t *)xauth_create(this->ike_sa, FALSE);
! 1064: }
! 1065: this->passive_tasks->insert_last(this->passive_tasks, task);
! 1066: break;
! 1067: default:
! 1068: return FAILED;
! 1069: }
! 1070: }
! 1071: if (dpd)
! 1072: {
! 1073: return initiate(this);
! 1074: }
! 1075: this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND, time_monotonic(NULL));
! 1076:
! 1077: /* let the tasks process the message */
! 1078: enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
! 1079: while (enumerator->enumerate(enumerator, (void*)&task))
! 1080: {
! 1081: switch (task->process(task, message))
! 1082: {
! 1083: case SUCCESS:
! 1084: /* task completed, remove it */
! 1085: this->passive_tasks->remove_at(this->passive_tasks, enumerator);
! 1086: task->destroy(task);
! 1087: continue;
! 1088: case NEED_MORE:
! 1089: /* processed, but task needs at least another call to build() */
! 1090: send_response = TRUE;
! 1091: continue;
! 1092: case ALREADY_DONE:
! 1093: send_response = FALSE;
! 1094: break;
! 1095: case INVALID_ARG:
! 1096: if (task->get_type(task) == TASK_QUICK_MODE)
! 1097: { /* not responsible for this exchange */
! 1098: continue;
! 1099: }
! 1100: /* FALL */
! 1101: case FAILED:
! 1102: default:
! 1103: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 1104: /* FALL */
! 1105: case DESTROY_ME:
! 1106: /* critical failure, destroy IKE_SA */
! 1107: this->passive_tasks->remove_at(this->passive_tasks, enumerator);
! 1108: enumerator->destroy(enumerator);
! 1109: task->destroy(task);
! 1110: return DESTROY_ME;
! 1111: }
! 1112: break;
! 1113: }
! 1114: enumerator->destroy(enumerator);
! 1115:
! 1116: if (send_response)
! 1117: {
! 1118: if (build_response(this, message) != SUCCESS)
! 1119: {
! 1120: return DESTROY_ME;
! 1121: }
! 1122: }
! 1123: else
! 1124: {
! 1125: if (this->responding.retransmitted > 1)
! 1126: {
! 1127: packet_t *packet = NULL;
! 1128: array_get(this->responding.packets, 0, &packet);
! 1129: charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_CLEARED,
! 1130: packet);
! 1131: }
! 1132: /* We don't send a response, so don't retransmit one if we get
! 1133: * the same message again. */
! 1134: clear_packets(this->responding.packets);
! 1135: }
! 1136: if (this->queued &&
! 1137: this->queued->get_exchange_type(this->queued) == INFORMATIONAL_V1)
! 1138: {
! 1139: message_t *queued;
! 1140: status_t status;
! 1141:
! 1142: queued = this->queued;
! 1143: this->queued = NULL;
! 1144: status = this->public.task_manager.process_message(
! 1145: &this->public.task_manager, queued);
! 1146: queued->destroy(queued);
! 1147: if (status == DESTROY_ME)
! 1148: {
! 1149: return status;
! 1150: }
! 1151: }
! 1152: if (this->passive_tasks->get_count(this->passive_tasks) == 0 &&
! 1153: this->queued_tasks->get_count(this->queued_tasks) > 0)
! 1154: {
! 1155: /* passive tasks completed, check if an active task has been queued,
! 1156: * such as XAUTH or modeconfig push */
! 1157: return initiate(this);
! 1158: }
! 1159: return SUCCESS;
! 1160: }
! 1161:
! 1162: /**
! 1163: * handle an incoming response message
! 1164: */
! 1165: static status_t process_response(private_task_manager_t *this,
! 1166: message_t *message)
! 1167: {
! 1168: enumerator_t *enumerator;
! 1169: message_t *queued;
! 1170: status_t status;
! 1171: task_t *task;
! 1172:
! 1173: if (message->get_exchange_type(message) != this->initiating.type)
! 1174: {
! 1175: /* Windows server sends a fourth quick mode message having an initial
! 1176: * contact notify. Ignore this message for compatibility. */
! 1177: if (this->initiating.type == EXCHANGE_TYPE_UNDEFINED &&
! 1178: message->get_exchange_type(message) == QUICK_MODE &&
! 1179: message->get_notify(message, INITIAL_CONTACT))
! 1180: {
! 1181: DBG1(DBG_IKE, "ignoring fourth Quick Mode message");
! 1182: return SUCCESS;
! 1183: }
! 1184: DBG1(DBG_IKE, "received %N response, but expected %N",
! 1185: exchange_type_names, message->get_exchange_type(message),
! 1186: exchange_type_names, this->initiating.type);
! 1187: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 1188: return DESTROY_ME;
! 1189: }
! 1190:
! 1191: enumerator = this->active_tasks->create_enumerator(this->active_tasks);
! 1192: while (enumerator->enumerate(enumerator, (void*)&task))
! 1193: {
! 1194: switch (task->process(task, message))
! 1195: {
! 1196: case SUCCESS:
! 1197: /* task completed, remove it */
! 1198: this->active_tasks->remove_at(this->active_tasks, enumerator);
! 1199: task->destroy(task);
! 1200: continue;
! 1201: case NEED_MORE:
! 1202: /* processed, but task needs another exchange */
! 1203: continue;
! 1204: case ALREADY_DONE:
! 1205: break;
! 1206: case FAILED:
! 1207: default:
! 1208: charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
! 1209: /* FALL */
! 1210: case DESTROY_ME:
! 1211: /* critical failure, destroy IKE_SA */
! 1212: this->active_tasks->remove_at(this->active_tasks, enumerator);
! 1213: enumerator->destroy(enumerator);
! 1214: task->destroy(task);
! 1215: return DESTROY_ME;
! 1216: }
! 1217: break;
! 1218: }
! 1219: enumerator->destroy(enumerator);
! 1220:
! 1221: if (this->initiating.retransmitted > 1)
! 1222: {
! 1223: packet_t *packet = NULL;
! 1224: array_get(this->initiating.packets, 0, &packet);
! 1225: charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_CLEARED, packet);
! 1226: }
! 1227: this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
! 1228: clear_packets(this->initiating.packets);
! 1229:
! 1230: if (this->queued && !this->active_tasks->get_count(this->active_tasks) &&
! 1231: this->queued->get_exchange_type(this->queued) == TRANSACTION)
! 1232: {
! 1233: queued = this->queued;
! 1234: this->queued = NULL;
! 1235: status = this->public.task_manager.process_message(
! 1236: &this->public.task_manager, queued);
! 1237: queued->destroy(queued);
! 1238: if (status == DESTROY_ME)
! 1239: {
! 1240: return status;
! 1241: }
! 1242: }
! 1243:
! 1244: return initiate(this);
! 1245: }
! 1246:
! 1247: static status_t handle_fragment(private_task_manager_t *this, message_t *msg)
! 1248: {
! 1249: status_t status;
! 1250:
! 1251: if (!this->defrag)
! 1252: {
! 1253: this->defrag = message_create_defrag(msg);
! 1254: if (!this->defrag)
! 1255: {
! 1256: return FAILED;
! 1257: }
! 1258: }
! 1259: status = this->defrag->add_fragment(this->defrag, msg);
! 1260: if (status == SUCCESS)
! 1261: {
! 1262: lib->processor->queue_job(lib->processor,
! 1263: (job_t*)process_message_job_create(this->defrag));
! 1264: this->defrag = NULL;
! 1265: /* do not process the last fragment */
! 1266: status = NEED_MORE;
! 1267: }
! 1268: return status;
! 1269: }
! 1270:
! 1271: /**
! 1272: * Parse the given message and verify that it is valid.
! 1273: */
! 1274: static status_t parse_message(private_task_manager_t *this, message_t *msg)
! 1275: {
! 1276: status_t status;
! 1277:
! 1278: status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
! 1279:
! 1280: if (status != SUCCESS)
! 1281: {
! 1282: switch (status)
! 1283: {
! 1284: case NOT_SUPPORTED:
! 1285: DBG1(DBG_IKE, "unsupported exchange type");
! 1286: send_notify(this, msg, INVALID_EXCHANGE_TYPE);
! 1287: break;
! 1288: case PARSE_ERROR:
! 1289: DBG1(DBG_IKE, "message parsing failed");
! 1290: send_notify(this, msg, PAYLOAD_MALFORMED);
! 1291: break;
! 1292: case VERIFY_ERROR:
! 1293: DBG1(DBG_IKE, "message verification failed");
! 1294: send_notify(this, msg, PAYLOAD_MALFORMED);
! 1295: break;
! 1296: case FAILED:
! 1297: DBG1(DBG_IKE, "integrity check failed");
! 1298: send_notify(this, msg, INVALID_HASH_INFORMATION);
! 1299: break;
! 1300: case INVALID_STATE:
! 1301: DBG1(DBG_IKE, "found encrypted message, but no keys available");
! 1302: send_notify(this, msg, PAYLOAD_MALFORMED);
! 1303: default:
! 1304: break;
! 1305: }
! 1306: DBG1(DBG_IKE, "%N %s with message ID %u processing failed",
! 1307: exchange_type_names, msg->get_exchange_type(msg),
! 1308: msg->get_request(msg) ? "request" : "response",
! 1309: msg->get_message_id(msg));
! 1310:
! 1311: charon->bus->alert(charon->bus, ALERT_PARSE_ERROR_BODY, msg, status);
! 1312:
! 1313: if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED)
! 1314: { /* invalid initiation attempt, close SA */
! 1315: return DESTROY_ME;
! 1316: }
! 1317: }
! 1318:
! 1319: if (msg->get_first_payload_type(msg) == PLV1_FRAGMENT)
! 1320: {
! 1321: return handle_fragment(this, msg);
! 1322: }
! 1323: return status;
! 1324: }
! 1325:
! 1326: /**
! 1327: * Queue the given message if possible
! 1328: */
! 1329: static status_t queue_message(private_task_manager_t *this, message_t *msg)
! 1330: {
! 1331: if (this->queued)
! 1332: {
! 1333: DBG1(DBG_IKE, "ignoring %N request, queue full",
! 1334: exchange_type_names, msg->get_exchange_type(msg));
! 1335: return FAILED;
! 1336: }
! 1337: this->queued = message_create_from_packet(msg->get_packet(msg));
! 1338: if (this->queued->parse_header(this->queued) != SUCCESS)
! 1339: {
! 1340: this->queued->destroy(this->queued);
! 1341: this->queued = NULL;
! 1342: return FAILED;
! 1343: }
! 1344: DBG1(DBG_IKE, "queueing %N request as tasks still active",
! 1345: exchange_type_names, msg->get_exchange_type(msg));
! 1346: return SUCCESS;
! 1347: }
! 1348:
! 1349: METHOD(task_manager_t, process_message, status_t,
! 1350: private_task_manager_t *this, message_t *msg)
! 1351: {
! 1352: uint32_t hash, mid, i;
! 1353: host_t *me, *other;
! 1354: status_t status;
! 1355:
! 1356: /* TODO-IKEv1: update hosts more selectively */
! 1357: me = msg->get_destination(msg);
! 1358: other = msg->get_source(msg);
! 1359: mid = msg->get_message_id(msg);
! 1360: hash = chunk_hash(msg->get_packet_data(msg));
! 1361: for (i = 0; i < MAX_OLD_HASHES; i++)
! 1362: {
! 1363: if (this->initiating.old_hashes[i] == hash)
! 1364: {
! 1365: if (array_count(this->initiating.packets) &&
! 1366: i == (this->initiating.old_hash_pos % MAX_OLD_HASHES) &&
! 1367: (msg->get_exchange_type(msg) == QUICK_MODE ||
! 1368: msg->get_exchange_type(msg) == AGGRESSIVE))
! 1369: {
! 1370: DBG1(DBG_IKE, "received retransmit of response with ID %u, "
! 1371: "resending last request", mid);
! 1372: send_packets(this, this->initiating.packets);
! 1373: return SUCCESS;
! 1374: }
! 1375: DBG1(DBG_IKE, "received retransmit of response with ID %u, "
! 1376: "but next request already sent", mid);
! 1377: return SUCCESS;
! 1378: }
! 1379: }
! 1380:
! 1381: if ((mid && mid == this->initiating.mid) ||
! 1382: (this->initiating.mid == 0 &&
! 1383: msg->get_exchange_type(msg) == this->initiating.type &&
! 1384: this->active_tasks->get_count(this->active_tasks)))
! 1385: {
! 1386: msg->set_request(msg, FALSE);
! 1387: charon->bus->message(charon->bus, msg, TRUE, FALSE);
! 1388: status = parse_message(this, msg);
! 1389: if (status == NEED_MORE)
! 1390: {
! 1391: return SUCCESS;
! 1392: }
! 1393: if (status != SUCCESS)
! 1394: {
! 1395: return status;
! 1396: }
! 1397: this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
! 1398: time_monotonic(NULL));
! 1399: this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
! 1400: charon->bus->message(charon->bus, msg, TRUE, TRUE);
! 1401: if (process_response(this, msg) != SUCCESS)
! 1402: {
! 1403: flush(this);
! 1404: return DESTROY_ME;
! 1405: }
! 1406: this->initiating.old_hashes[(++this->initiating.old_hash_pos) %
! 1407: MAX_OLD_HASHES] = hash;
! 1408: }
! 1409: else
! 1410: {
! 1411: if (hash == this->responding.hash)
! 1412: {
! 1413: if (array_count(this->responding.packets))
! 1414: {
! 1415: DBG1(DBG_IKE, "received retransmit of request with ID %u, "
! 1416: "retransmitting response", mid);
! 1417: send_packets(this, this->responding.packets);
! 1418: }
! 1419: else if (array_count(this->initiating.packets) &&
! 1420: this->initiating.type == INFORMATIONAL_V1)
! 1421: {
! 1422: DBG1(DBG_IKE, "received retransmit of DPD request, "
! 1423: "retransmitting response");
! 1424: send_packets(this, this->initiating.packets);
! 1425: }
! 1426: else
! 1427: {
! 1428: DBG1(DBG_IKE, "received retransmit of request with ID %u, "
! 1429: "but no response to retransmit", mid);
! 1430: }
! 1431: charon->bus->alert(charon->bus, ALERT_RETRANSMIT_RECEIVE, msg);
! 1432: return SUCCESS;
! 1433: }
! 1434:
! 1435: /* reject Main/Aggressive Modes once established */
! 1436: if (msg->get_exchange_type(msg) == ID_PROT ||
! 1437: msg->get_exchange_type(msg) == AGGRESSIVE)
! 1438: {
! 1439: if (this->ike_sa->get_state(this->ike_sa) != IKE_CREATED &&
! 1440: this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING &&
! 1441: msg->get_first_payload_type(msg) != PLV1_FRAGMENT)
! 1442: {
! 1443: DBG1(DBG_IKE, "ignoring %N in established IKE_SA state",
! 1444: exchange_type_names, msg->get_exchange_type(msg));
! 1445: return FAILED;
! 1446: }
! 1447: }
! 1448:
! 1449: /* drop XAuth/Mode Config/Quick Mode messages until we received the last
! 1450: * Aggressive Mode message. since Informational messages are not
! 1451: * retransmitted we queue them. */
! 1452: if (have_task_queued(this, TASK_AGGRESSIVE_MODE))
! 1453: {
! 1454: if (msg->get_exchange_type(msg) == INFORMATIONAL_V1)
! 1455: {
! 1456: return queue_message(this, msg);
! 1457: }
! 1458: else if (msg->get_exchange_type(msg) != AGGRESSIVE)
! 1459: {
! 1460: DBG1(DBG_IKE, "ignoring %N request while phase 1 is incomplete",
! 1461: exchange_type_names, msg->get_exchange_type(msg));
! 1462: return FAILED;
! 1463: }
! 1464: }
! 1465:
! 1466: /* queue XAuth/Mode Config messages unless the Main Mode exchange we
! 1467: * initiated is complete */
! 1468: if (msg->get_exchange_type(msg) == TRANSACTION &&
! 1469: this->active_tasks->get_count(this->active_tasks))
! 1470: {
! 1471: return queue_message(this, msg);
! 1472: }
! 1473:
! 1474: /* some peers send INITIAL_CONTACT notifies during XAuth, cache it */
! 1475: if (have_task_queued(this, TASK_XAUTH) &&
! 1476: msg->get_exchange_type(msg) == INFORMATIONAL_V1)
! 1477: {
! 1478: return queue_message(this, msg);
! 1479: }
! 1480:
! 1481: msg->set_request(msg, TRUE);
! 1482: charon->bus->message(charon->bus, msg, TRUE, FALSE);
! 1483: status = parse_message(this, msg);
! 1484: if (status == NEED_MORE)
! 1485: {
! 1486: return SUCCESS;
! 1487: }
! 1488: if (status != SUCCESS)
! 1489: {
! 1490: return status;
! 1491: }
! 1492: /* if this IKE_SA is virgin, we check for a config */
! 1493: if (this->ike_sa->get_ike_cfg(this->ike_sa) == NULL)
! 1494: {
! 1495: ike_sa_id_t *ike_sa_id;
! 1496: ike_cfg_t *ike_cfg;
! 1497: job_t *job;
! 1498:
! 1499: ike_cfg = charon->backends->get_ike_cfg(charon->backends,
! 1500: me, other, IKEV1);
! 1501: if (ike_cfg == NULL)
! 1502: {
! 1503: /* no config found for these hosts, destroy */
! 1504: DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
! 1505: me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
! 1506: send_notify(this, msg, NO_PROPOSAL_CHOSEN);
! 1507: return DESTROY_ME;
! 1508: }
! 1509: this->ike_sa->set_ike_cfg(this->ike_sa, ike_cfg);
! 1510: ike_cfg->destroy(ike_cfg);
! 1511: /* add a timeout if peer does not establish it completely */
! 1512: ike_sa_id = this->ike_sa->get_id(this->ike_sa);
! 1513: job = (job_t*)delete_ike_sa_job_create(ike_sa_id, FALSE);
! 1514: lib->scheduler->schedule_job(lib->scheduler, job,
! 1515: lib->settings->get_int(lib->settings,
! 1516: "%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
! 1517: lib->ns));
! 1518: }
! 1519: this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
! 1520: charon->bus->message(charon->bus, msg, TRUE, TRUE);
! 1521: if (process_request(this, msg) != SUCCESS)
! 1522: {
! 1523: flush(this);
! 1524: return DESTROY_ME;
! 1525: }
! 1526: this->responding.hash = hash;
! 1527: }
! 1528: return SUCCESS;
! 1529: }
! 1530:
! 1531: /**
! 1532: * Check if a given task has been queued already
! 1533: */
! 1534: static bool has_queued(private_task_manager_t *this, task_type_t type)
! 1535: {
! 1536: enumerator_t *enumerator;
! 1537: bool found = FALSE;
! 1538: task_t *task;
! 1539:
! 1540: enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
! 1541: while (enumerator->enumerate(enumerator, &task))
! 1542: {
! 1543: if (task->get_type(task) == type)
! 1544: {
! 1545: found = TRUE;
! 1546: break;
! 1547: }
! 1548: }
! 1549: enumerator->destroy(enumerator);
! 1550: return found;
! 1551: }
! 1552:
! 1553: METHOD(task_manager_t, queue_task_delayed, void,
! 1554: private_task_manager_t *this, task_t *task, uint32_t delay)
! 1555: {
! 1556: task_type_t type = task->get_type(task);
! 1557:
! 1558: switch (type)
! 1559: {
! 1560: case TASK_MODE_CONFIG:
! 1561: case TASK_XAUTH:
! 1562: if (has_queued(this, type))
! 1563: {
! 1564: task->destroy(task);
! 1565: return;
! 1566: }
! 1567: break;
! 1568: default:
! 1569: break;
! 1570: }
! 1571: DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
! 1572: this->queued_tasks->insert_last(this->queued_tasks, task);
! 1573: }
! 1574:
! 1575: METHOD(task_manager_t, queue_task, void,
! 1576: private_task_manager_t *this, task_t *task)
! 1577: {
! 1578: queue_task_delayed(this, task, 0);
! 1579: }
! 1580:
! 1581: METHOD(task_manager_t, queue_ike, void,
! 1582: private_task_manager_t *this)
! 1583: {
! 1584: peer_cfg_t *peer_cfg;
! 1585:
! 1586: if (!has_queued(this, TASK_ISAKMP_VENDOR))
! 1587: {
! 1588: queue_task(this, (task_t*)isakmp_vendor_create(this->ike_sa, TRUE));
! 1589: }
! 1590: if (!has_queued(this, TASK_ISAKMP_CERT_PRE))
! 1591: {
! 1592: queue_task(this, (task_t*)isakmp_cert_pre_create(this->ike_sa, TRUE));
! 1593: }
! 1594: peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
! 1595: if (peer_cfg->use_aggressive(peer_cfg))
! 1596: {
! 1597: if (!has_queued(this, TASK_AGGRESSIVE_MODE))
! 1598: {
! 1599: queue_task(this, (task_t*)aggressive_mode_create(this->ike_sa, TRUE));
! 1600: }
! 1601: }
! 1602: else
! 1603: {
! 1604: if (!has_queued(this, TASK_MAIN_MODE))
! 1605: {
! 1606: queue_task(this, (task_t*)main_mode_create(this->ike_sa, TRUE));
! 1607: }
! 1608: }
! 1609: if (!has_queued(this, TASK_ISAKMP_CERT_POST))
! 1610: {
! 1611: queue_task(this, (task_t*)isakmp_cert_post_create(this->ike_sa, TRUE));
! 1612: }
! 1613: if (!has_queued(this, TASK_ISAKMP_NATD))
! 1614: {
! 1615: queue_task(this, (task_t*)isakmp_natd_create(this->ike_sa, TRUE));
! 1616: }
! 1617: }
! 1618:
! 1619: METHOD(task_manager_t, queue_ike_reauth, void,
! 1620: private_task_manager_t *this)
! 1621: {
! 1622: enumerator_t *enumerator;
! 1623: child_sa_t *child_sa;
! 1624: ike_sa_t *new;
! 1625: host_t *host;
! 1626:
! 1627: new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
! 1628: this->ike_sa->get_version(this->ike_sa), TRUE);
! 1629: if (!new)
! 1630: { /* shouldn't happen */
! 1631: return;
! 1632: }
! 1633:
! 1634: new->set_peer_cfg(new, this->ike_sa->get_peer_cfg(this->ike_sa));
! 1635: host = this->ike_sa->get_other_host(this->ike_sa);
! 1636: new->set_other_host(new, host->clone(host));
! 1637: host = this->ike_sa->get_my_host(this->ike_sa);
! 1638: new->set_my_host(new, host->clone(host));
! 1639: enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
! 1640: while (enumerator->enumerate(enumerator, &host))
! 1641: {
! 1642: new->add_virtual_ip(new, TRUE, host);
! 1643: }
! 1644: enumerator->destroy(enumerator);
! 1645:
! 1646: charon->bus->children_migrate(charon->bus, new->get_id(new),
! 1647: new->get_unique_id(new));
! 1648: enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
! 1649: while (enumerator->enumerate(enumerator, &child_sa))
! 1650: {
! 1651: this->ike_sa->remove_child_sa(this->ike_sa, enumerator);
! 1652: new->add_child_sa(new, child_sa);
! 1653: }
! 1654: enumerator->destroy(enumerator);
! 1655: charon->bus->set_sa(charon->bus, new);
! 1656: charon->bus->children_migrate(charon->bus, NULL, 0);
! 1657: charon->bus->set_sa(charon->bus, this->ike_sa);
! 1658:
! 1659: if (!new->get_child_count(new))
! 1660: { /* check if a Quick Mode task is queued (UNITY_LOAD_BALANCE case) */
! 1661: task_t *task;
! 1662:
! 1663: enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
! 1664: while (enumerator->enumerate(enumerator, &task))
! 1665: {
! 1666: if (task->get_type(task) == TASK_QUICK_MODE)
! 1667: {
! 1668: this->queued_tasks->remove_at(this->queued_tasks, enumerator);
! 1669: task->migrate(task, new);
! 1670: new->queue_task(new, task);
! 1671: }
! 1672: }
! 1673: enumerator->destroy(enumerator);
! 1674: }
! 1675:
! 1676: if (new->initiate(new, NULL, 0, NULL, NULL) != DESTROY_ME)
! 1677: {
! 1678: charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
! 1679: this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
! 1680: }
! 1681: else
! 1682: {
! 1683: charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
! 1684: DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
! 1685: }
! 1686: charon->bus->set_sa(charon->bus, this->ike_sa);
! 1687: }
! 1688:
! 1689: METHOD(task_manager_t, queue_ike_rekey, void,
! 1690: private_task_manager_t *this)
! 1691: {
! 1692: queue_ike_reauth(this);
! 1693: }
! 1694:
! 1695: METHOD(task_manager_t, queue_ike_delete, void,
! 1696: private_task_manager_t *this)
! 1697: {
! 1698: enumerator_t *enumerator;
! 1699: child_sa_t *child_sa;
! 1700:
! 1701: /* cancel any currently active task to get the DELETE done quickly */
! 1702: flush_queue(this, TASK_QUEUE_ACTIVE);
! 1703:
! 1704: enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
! 1705: while (enumerator->enumerate(enumerator, &child_sa))
! 1706: {
! 1707: queue_task(this, (task_t*)
! 1708: quick_delete_create(this->ike_sa, child_sa->get_protocol(child_sa),
! 1709: child_sa->get_spi(child_sa, TRUE), FALSE, FALSE));
! 1710: }
! 1711: enumerator->destroy(enumerator);
! 1712:
! 1713: queue_task(this, (task_t*)isakmp_delete_create(this->ike_sa, TRUE));
! 1714: }
! 1715:
! 1716: METHOD(task_manager_t, queue_mobike, void,
! 1717: private_task_manager_t *this, bool roam, bool address)
! 1718: {
! 1719: /* Not supported in IKEv1 */
! 1720: }
! 1721:
! 1722: METHOD(task_manager_t, queue_child, void,
! 1723: private_task_manager_t *this, child_cfg_t *cfg, uint32_t reqid,
! 1724: traffic_selector_t *tsi, traffic_selector_t *tsr)
! 1725: {
! 1726: quick_mode_t *task;
! 1727:
! 1728: task = quick_mode_create(this->ike_sa, cfg, tsi, tsr);
! 1729: task->use_reqid(task, reqid);
! 1730:
! 1731: queue_task(this, &task->task);
! 1732: }
! 1733:
! 1734: /**
! 1735: * Check if two CHILD_SAs have the same traffic selector
! 1736: */
! 1737: static bool have_equal_ts(child_sa_t *child1, child_sa_t *child2, bool local)
! 1738: {
! 1739: enumerator_t *e1, *e2;
! 1740: traffic_selector_t *ts1, *ts2;
! 1741: bool equal = FALSE;
! 1742:
! 1743: e1 = child1->create_ts_enumerator(child1, local);
! 1744: e2 = child2->create_ts_enumerator(child2, local);
! 1745: if (e1->enumerate(e1, &ts1) && e2->enumerate(e2, &ts2))
! 1746: {
! 1747: equal = ts1->equals(ts1, ts2);
! 1748: }
! 1749: e2->destroy(e2);
! 1750: e1->destroy(e1);
! 1751:
! 1752: return equal;
! 1753: }
! 1754:
! 1755: /*
! 1756: * Described in header
! 1757: */
! 1758: bool ikev1_child_sa_is_redundant(ike_sa_t *ike_sa, child_sa_t *child_sa,
! 1759: bool (*cmp)(child_sa_t*,child_sa_t*))
! 1760: {
! 1761: enumerator_t *enumerator;
! 1762: child_sa_t *current;
! 1763: bool redundant = FALSE;
! 1764:
! 1765: enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
! 1766: while (enumerator->enumerate(enumerator, ¤t))
! 1767: {
! 1768: if (current != child_sa &&
! 1769: current->get_state(current) == CHILD_INSTALLED &&
! 1770: streq(current->get_name(current), child_sa->get_name(child_sa)) &&
! 1771: have_equal_ts(current, child_sa, TRUE) &&
! 1772: have_equal_ts(current, child_sa, FALSE) &&
! 1773: (!cmp || cmp(child_sa, current)))
! 1774: {
! 1775: DBG1(DBG_IKE, "detected redundant CHILD_SA %s{%d}",
! 1776: child_sa->get_name(child_sa),
! 1777: child_sa->get_unique_id(child_sa));
! 1778: redundant = TRUE;
! 1779: break;
! 1780: }
! 1781: }
! 1782: enumerator->destroy(enumerator);
! 1783:
! 1784: return redundant;
! 1785: }
! 1786:
! 1787: /**
! 1788: * Compare the rekey times of two CHILD_SAs, a CHILD_SA is redundant if it is
! 1789: * rekeyed sooner than another.
! 1790: */
! 1791: static bool is_rekeyed_sooner(child_sa_t *is_redundant, child_sa_t *other)
! 1792: {
! 1793: return other->get_lifetime(other, FALSE) >
! 1794: is_redundant->get_lifetime(is_redundant, FALSE);
! 1795: }
! 1796:
! 1797: /**
! 1798: * Get the first traffic selector of a CHILD_SA, local or remote
! 1799: */
! 1800: static traffic_selector_t* get_first_ts(child_sa_t *child_sa, bool local)
! 1801: {
! 1802: traffic_selector_t *ts = NULL;
! 1803: enumerator_t *enumerator;
! 1804:
! 1805: enumerator = child_sa->create_ts_enumerator(child_sa, local);
! 1806: enumerator->enumerate(enumerator, &ts);
! 1807: enumerator->destroy(enumerator);
! 1808:
! 1809: return ts;
! 1810: }
! 1811:
! 1812: METHOD(task_manager_t, queue_child_rekey, void,
! 1813: private_task_manager_t *this, protocol_id_t protocol, uint32_t spi)
! 1814: {
! 1815: child_sa_t *child_sa;
! 1816: child_cfg_t *cfg;
! 1817: quick_mode_t *task;
! 1818:
! 1819: child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, TRUE);
! 1820: if (!child_sa)
! 1821: {
! 1822: child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, FALSE);
! 1823: }
! 1824: if (child_sa && child_sa->get_state(child_sa) == CHILD_INSTALLED)
! 1825: {
! 1826: if (ikev1_child_sa_is_redundant(this->ike_sa, child_sa,
! 1827: is_rekeyed_sooner))
! 1828: {
! 1829: child_sa->set_state(child_sa, CHILD_REKEYED);
! 1830: if (lib->settings->get_bool(lib->settings, "%s.delete_rekeyed",
! 1831: FALSE, lib->ns))
! 1832: {
! 1833: queue_task(this, (task_t*)quick_delete_create(this->ike_sa,
! 1834: protocol, spi, FALSE, FALSE));
! 1835: }
! 1836: }
! 1837: else
! 1838: {
! 1839: child_sa->set_state(child_sa, CHILD_REKEYING);
! 1840: cfg = child_sa->get_config(child_sa);
! 1841: task = quick_mode_create(this->ike_sa, cfg->get_ref(cfg),
! 1842: get_first_ts(child_sa, TRUE), get_first_ts(child_sa, FALSE));
! 1843: task->use_reqid(task, child_sa->get_reqid(child_sa));
! 1844: task->use_marks(task, child_sa->get_mark(child_sa, TRUE).value,
! 1845: child_sa->get_mark(child_sa, FALSE).value);
! 1846: task->use_if_ids(task, child_sa->get_if_id(child_sa, TRUE),
! 1847: child_sa->get_if_id(child_sa, FALSE));
! 1848: task->rekey(task, child_sa->get_spi(child_sa, TRUE));
! 1849:
! 1850: queue_task(this, &task->task);
! 1851: }
! 1852: }
! 1853: }
! 1854:
! 1855: METHOD(task_manager_t, queue_child_delete, void,
! 1856: private_task_manager_t *this, protocol_id_t protocol, uint32_t spi,
! 1857: bool expired)
! 1858: {
! 1859: queue_task(this, (task_t*)quick_delete_create(this->ike_sa, protocol,
! 1860: spi, FALSE, expired));
! 1861: }
! 1862:
! 1863: METHOD(task_manager_t, queue_dpd, void,
! 1864: private_task_manager_t *this)
! 1865: {
! 1866: peer_cfg_t *peer_cfg;
! 1867: uint32_t t, retransmit;
! 1868:
! 1869: queue_task(this, (task_t*)isakmp_dpd_create(this->ike_sa, DPD_R_U_THERE,
! 1870: this->dpd_send));
! 1871: peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
! 1872:
! 1873: /* compute timeout in milliseconds */
! 1874: t = 1000 * peer_cfg->get_dpd_timeout(peer_cfg);
! 1875: if (t == 0)
! 1876: {
! 1877: /* use the same timeout as a retransmitting IKE message would have */
! 1878: for (retransmit = 0; retransmit <= this->retransmit_tries; retransmit++)
! 1879: {
! 1880: t += (uint32_t)(this->retransmit_timeout * 1000.0 *
! 1881: pow(this->retransmit_base, retransmit));
! 1882: }
! 1883: }
! 1884: /* compensate for the already elapsed dpd delay */
! 1885: t -= 1000 * peer_cfg->get_dpd(peer_cfg);
! 1886:
! 1887: /* schedule DPD timeout job */
! 1888: lib->scheduler->schedule_job_ms(lib->scheduler,
! 1889: (job_t*)dpd_timeout_job_create(this->ike_sa->get_id(this->ike_sa)), t);
! 1890: }
! 1891:
! 1892: METHOD(task_manager_t, adopt_tasks, void,
! 1893: private_task_manager_t *this, task_manager_t *other_public)
! 1894: {
! 1895: private_task_manager_t *other = (private_task_manager_t*)other_public;
! 1896: task_t *task;
! 1897:
! 1898: /* move queued tasks from other to this */
! 1899: while (other->queued_tasks->remove_last(other->queued_tasks,
! 1900: (void**)&task) == SUCCESS)
! 1901: {
! 1902: DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
! 1903: task->migrate(task, this->ike_sa);
! 1904: this->queued_tasks->insert_first(this->queued_tasks, task);
! 1905: }
! 1906: }
! 1907:
! 1908: METHOD(task_manager_t, busy, bool,
! 1909: private_task_manager_t *this)
! 1910: {
! 1911: return (this->active_tasks->get_count(this->active_tasks) > 0);
! 1912: }
! 1913:
! 1914: METHOD(task_manager_t, incr_mid, void,
! 1915: private_task_manager_t *this, bool initiate)
! 1916: {
! 1917: }
! 1918:
! 1919: METHOD(task_manager_t, get_mid, uint32_t,
! 1920: private_task_manager_t *this, bool initiate)
! 1921: {
! 1922: return initiate ? this->initiating.mid : this->responding.mid;
! 1923: }
! 1924:
! 1925: METHOD(task_manager_t, reset, void,
! 1926: private_task_manager_t *this, uint32_t initiate, uint32_t respond)
! 1927: {
! 1928: enumerator_t *enumerator;
! 1929: task_t *task;
! 1930:
! 1931: /* reset message counters and retransmit packets */
! 1932: clear_packets(this->responding.packets);
! 1933: clear_packets(this->initiating.packets);
! 1934: this->responding.seqnr = RESPONDING_SEQ;
! 1935: this->responding.retransmitted = 0;
! 1936: this->initiating.mid = 0;
! 1937: this->initiating.seqnr = 0;
! 1938: this->initiating.retransmitted = 0;
! 1939: this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
! 1940: DESTROY_IF(this->defrag);
! 1941: this->defrag = NULL;
! 1942: if (initiate != UINT_MAX)
! 1943: {
! 1944: this->dpd_send = initiate;
! 1945: }
! 1946: if (respond != UINT_MAX)
! 1947: {
! 1948: this->dpd_recv = respond;
! 1949: }
! 1950:
! 1951: /* reset queued tasks */
! 1952: enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
! 1953: while (enumerator->enumerate(enumerator, &task))
! 1954: {
! 1955: task->migrate(task, this->ike_sa);
! 1956: }
! 1957: enumerator->destroy(enumerator);
! 1958:
! 1959: /* reset active tasks */
! 1960: while (this->active_tasks->remove_last(this->active_tasks,
! 1961: (void**)&task) == SUCCESS)
! 1962: {
! 1963: task->migrate(task, this->ike_sa);
! 1964: this->queued_tasks->insert_first(this->queued_tasks, task);
! 1965: }
! 1966: }
! 1967:
! 1968: /**
! 1969: * Data for a task queue enumerator
! 1970: */
! 1971: typedef struct {
! 1972: enumerator_t public;
! 1973: task_queue_t queue;
! 1974: enumerator_t *inner;
! 1975: } task_enumerator_t;
! 1976:
! 1977: METHOD(enumerator_t, task_enumerator_destroy, void,
! 1978: task_enumerator_t *this)
! 1979: {
! 1980: this->inner->destroy(this->inner);
! 1981: free(this);
! 1982: }
! 1983:
! 1984: METHOD(enumerator_t, task_enumerator_enumerate, bool,
! 1985: task_enumerator_t *this, va_list args)
! 1986: {
! 1987: task_t **task;
! 1988:
! 1989: VA_ARGS_VGET(args, task);
! 1990: return this->inner->enumerate(this->inner, task);
! 1991: }
! 1992:
! 1993: METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
! 1994: private_task_manager_t *this, task_queue_t queue)
! 1995: {
! 1996: task_enumerator_t *enumerator;
! 1997:
! 1998: INIT(enumerator,
! 1999: .public = {
! 2000: .enumerate = enumerator_enumerate_default,
! 2001: .venumerate = _task_enumerator_enumerate,
! 2002: .destroy = _task_enumerator_destroy,
! 2003: },
! 2004: .queue = queue,
! 2005: );
! 2006: switch (queue)
! 2007: {
! 2008: case TASK_QUEUE_ACTIVE:
! 2009: enumerator->inner = this->active_tasks->create_enumerator(
! 2010: this->active_tasks);
! 2011: break;
! 2012: case TASK_QUEUE_PASSIVE:
! 2013: enumerator->inner = this->passive_tasks->create_enumerator(
! 2014: this->passive_tasks);
! 2015: break;
! 2016: case TASK_QUEUE_QUEUED:
! 2017: enumerator->inner = this->queued_tasks->create_enumerator(
! 2018: this->queued_tasks);
! 2019: break;
! 2020: default:
! 2021: enumerator->inner = enumerator_create_empty();
! 2022: break;
! 2023: }
! 2024: return &enumerator->public;
! 2025: }
! 2026:
! 2027: METHOD(task_manager_t, remove_task, void,
! 2028: private_task_manager_t *this, enumerator_t *enumerator_public)
! 2029: {
! 2030: task_enumerator_t *enumerator = (task_enumerator_t*)enumerator_public;
! 2031:
! 2032: switch (enumerator->queue)
! 2033: {
! 2034: case TASK_QUEUE_ACTIVE:
! 2035: this->active_tasks->remove_at(this->active_tasks,
! 2036: enumerator->inner);
! 2037: break;
! 2038: case TASK_QUEUE_PASSIVE:
! 2039: this->passive_tasks->remove_at(this->passive_tasks,
! 2040: enumerator->inner);
! 2041: break;
! 2042: case TASK_QUEUE_QUEUED:
! 2043: this->queued_tasks->remove_at(this->queued_tasks,
! 2044: enumerator->inner);
! 2045: break;
! 2046: default:
! 2047: break;
! 2048: }
! 2049: }
! 2050:
! 2051: METHOD(task_manager_t, destroy, void,
! 2052: private_task_manager_t *this)
! 2053: {
! 2054: flush(this);
! 2055:
! 2056: this->active_tasks->destroy(this->active_tasks);
! 2057: this->queued_tasks->destroy(this->queued_tasks);
! 2058: this->passive_tasks->destroy(this->passive_tasks);
! 2059: DESTROY_IF(this->defrag);
! 2060:
! 2061: DESTROY_IF(this->queued);
! 2062: clear_packets(this->responding.packets);
! 2063: array_destroy(this->responding.packets);
! 2064: clear_packets(this->initiating.packets);
! 2065: array_destroy(this->initiating.packets);
! 2066: DESTROY_IF(this->rng);
! 2067: free(this);
! 2068: }
! 2069:
! 2070: /*
! 2071: * see header file
! 2072: */
! 2073: task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
! 2074: {
! 2075: private_task_manager_t *this;
! 2076:
! 2077: INIT(this,
! 2078: .public = {
! 2079: .task_manager = {
! 2080: .process_message = _process_message,
! 2081: .queue_task = _queue_task,
! 2082: .queue_task_delayed = _queue_task_delayed,
! 2083: .queue_ike = _queue_ike,
! 2084: .queue_ike_rekey = _queue_ike_rekey,
! 2085: .queue_ike_reauth = _queue_ike_reauth,
! 2086: .queue_ike_delete = _queue_ike_delete,
! 2087: .queue_mobike = _queue_mobike,
! 2088: .queue_child = _queue_child,
! 2089: .queue_child_rekey = _queue_child_rekey,
! 2090: .queue_child_delete = _queue_child_delete,
! 2091: .queue_dpd = _queue_dpd,
! 2092: .initiate = _initiate,
! 2093: .retransmit = _retransmit,
! 2094: .incr_mid = _incr_mid,
! 2095: .get_mid = _get_mid,
! 2096: .reset = _reset,
! 2097: .adopt_tasks = _adopt_tasks,
! 2098: .busy = _busy,
! 2099: .create_task_enumerator = _create_task_enumerator,
! 2100: .remove_task = _remove_task,
! 2101: .flush = _flush,
! 2102: .flush_queue = _flush_queue,
! 2103: .destroy = _destroy,
! 2104: },
! 2105: },
! 2106: .initiating = {
! 2107: .type = EXCHANGE_TYPE_UNDEFINED,
! 2108: },
! 2109: .responding = {
! 2110: .seqnr = RESPONDING_SEQ,
! 2111: },
! 2112: .ike_sa = ike_sa,
! 2113: .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
! 2114: .queued_tasks = linked_list_create(),
! 2115: .active_tasks = linked_list_create(),
! 2116: .passive_tasks = linked_list_create(),
! 2117: .retransmit_tries = lib->settings->get_int(lib->settings,
! 2118: "%s.retransmit_tries", RETRANSMIT_TRIES, lib->ns),
! 2119: .retransmit_timeout = lib->settings->get_double(lib->settings,
! 2120: "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, lib->ns),
! 2121: .retransmit_base = lib->settings->get_double(lib->settings,
! 2122: "%s.retransmit_base", RETRANSMIT_BASE, lib->ns),
! 2123: .retransmit_jitter = min(lib->settings->get_int(lib->settings,
! 2124: "%s.retransmit_jitter", 0, lib->ns), RETRANSMIT_JITTER_MAX),
! 2125: .retransmit_limit = lib->settings->get_int(lib->settings,
! 2126: "%s.retransmit_limit", 0, lib->ns) * 1000,
! 2127: );
! 2128:
! 2129: if (!this->rng)
! 2130: {
! 2131: DBG1(DBG_IKE, "no RNG found, unable to create IKE_SA");
! 2132: destroy(this);
! 2133: return NULL;
! 2134: }
! 2135: if (!this->rng->get_bytes(this->rng, sizeof(this->dpd_send),
! 2136: (void*)&this->dpd_send))
! 2137: {
! 2138: DBG1(DBG_IKE, "failed to allocate message ID, unable to create IKE_SA");
! 2139: destroy(this);
! 2140: return NULL;
! 2141: }
! 2142: this->dpd_send &= 0x7FFFFFFF;
! 2143:
! 2144: return &this->public;
! 2145: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>