Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/informational.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2011 Martin Willi
! 3: * Copyright (C) 2011 revosec AG
! 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 "informational.h"
! 17:
! 18: #include <daemon.h>
! 19: #include <sa/ikev1/tasks/isakmp_delete.h>
! 20: #include <sa/ikev1/tasks/quick_delete.h>
! 21:
! 22: #include <encoding/payloads/delete_payload.h>
! 23:
! 24: typedef struct private_informational_t private_informational_t;
! 25:
! 26: /**
! 27: * Private members of a informational_t task.
! 28: */
! 29: struct private_informational_t {
! 30:
! 31: /**
! 32: * Public methods and task_t interface.
! 33: */
! 34: informational_t public;
! 35:
! 36: /**
! 37: * Assigned IKE_SA.
! 38: */
! 39: ike_sa_t *ike_sa;
! 40:
! 41: /**
! 42: * Notify payload to send
! 43: */
! 44: notify_payload_t *notify;
! 45:
! 46: /**
! 47: * Delete subtask
! 48: */
! 49: task_t *del;
! 50: };
! 51:
! 52: /**
! 53: * Cancel active quick mode after receiving an error
! 54: */
! 55: static void cancel_quick_mode(private_informational_t *this)
! 56: {
! 57: enumerator_t *enumerator;
! 58: task_t *task;
! 59:
! 60: enumerator = this->ike_sa->create_task_enumerator(this->ike_sa,
! 61: TASK_QUEUE_ACTIVE);
! 62: while (enumerator->enumerate(enumerator, &task))
! 63: {
! 64: if (task->get_type(task) == TASK_QUICK_MODE)
! 65: {
! 66: this->ike_sa->flush_queue(this->ike_sa, TASK_QUEUE_ACTIVE);
! 67: break;
! 68: }
! 69: }
! 70: enumerator->destroy(enumerator);
! 71: }
! 72:
! 73: METHOD(task_t, build_i, status_t,
! 74: private_informational_t *this, message_t *message)
! 75: {
! 76: message->add_payload(message, &this->notify->payload_interface);
! 77: this->notify = NULL;
! 78: return SUCCESS;
! 79: }
! 80:
! 81: METHOD(task_t, process_r, status_t,
! 82: private_informational_t *this, message_t *message)
! 83: {
! 84: enumerator_t *enumerator;
! 85: delete_payload_t *delete;
! 86: notify_payload_t *notify;
! 87: notify_type_t type;
! 88: payload_t *payload;
! 89: status_t status = SUCCESS;
! 90:
! 91: enumerator = message->create_payload_enumerator(message);
! 92: while (enumerator->enumerate(enumerator, &payload))
! 93: {
! 94: switch (payload->get_type(payload))
! 95: {
! 96: case PLV1_NOTIFY:
! 97: notify = (notify_payload_t*)payload;
! 98: type = notify->get_notify_type(notify);
! 99:
! 100: if (type == INITIAL_CONTACT_IKEV1)
! 101: {
! 102: this->ike_sa->set_condition(this->ike_sa,
! 103: COND_INIT_CONTACT_SEEN, TRUE);
! 104: }
! 105: else if (type == UNITY_LOAD_BALANCE)
! 106: {
! 107: host_t *redirect, *me;
! 108: chunk_t data;
! 109:
! 110: data = notify->get_notification_data(notify);
! 111: redirect = host_create_from_chunk(AF_INET, data,
! 112: IKEV2_UDP_PORT);
! 113: if (redirect)
! 114: { /* treat the redirect as reauthentication */
! 115: DBG1(DBG_IKE, "received %N notify, redirected to %H",
! 116: notify_type_names, type, redirect);
! 117: /* Cisco boxes reject the first message from 4500 */
! 118: me = this->ike_sa->get_my_host(this->ike_sa);
! 119: me->set_port(me, charon->socket->get_port(
! 120: charon->socket, FALSE));
! 121: this->ike_sa->set_other_host(this->ike_sa, redirect);
! 122: status = this->ike_sa->reauth(this->ike_sa);
! 123: enumerator->destroy(enumerator);
! 124: return status;
! 125: }
! 126: else
! 127: {
! 128: DBG1(DBG_IKE, "received %N notify, invalid address");
! 129: }
! 130: }
! 131: else if (type < 16384)
! 132: {
! 133: DBG1(DBG_IKE, "received %N error notify",
! 134: notify_type_names, type);
! 135: if (this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING)
! 136: { /* only critical during main mode */
! 137: status = FAILED;
! 138: }
! 139: switch (type)
! 140: {
! 141: case INVALID_ID_INFORMATION:
! 142: case NO_PROPOSAL_CHOSEN:
! 143: cancel_quick_mode(this);
! 144: break;
! 145: default:
! 146: break;
! 147: }
! 148: break;
! 149: }
! 150: else
! 151: {
! 152: DBG1(DBG_IKE, "received %N notify",
! 153: notify_type_names, type);
! 154: }
! 155: continue;
! 156: case PLV1_DELETE:
! 157: if (!this->del)
! 158: {
! 159: delete = (delete_payload_t*)payload;
! 160: if (delete->get_protocol_id(delete) == PROTO_IKE)
! 161: {
! 162: this->del = (task_t*)isakmp_delete_create(this->ike_sa,
! 163: FALSE);
! 164: }
! 165: else
! 166: {
! 167: this->del = (task_t*)quick_delete_create(this->ike_sa,
! 168: PROTO_NONE, 0, FALSE, FALSE);
! 169: }
! 170: }
! 171: break;
! 172: default:
! 173: continue;
! 174: }
! 175: break;
! 176: }
! 177: enumerator->destroy(enumerator);
! 178:
! 179: if (this->del && status == SUCCESS)
! 180: {
! 181: return this->del->process(this->del, message);
! 182: }
! 183: return status;
! 184: }
! 185:
! 186: METHOD(task_t, build_r, status_t,
! 187: private_informational_t *this, message_t *message)
! 188: {
! 189: if (this->del)
! 190: {
! 191: return this->del->build(this->del, message);
! 192: }
! 193: return FAILED;
! 194: }
! 195:
! 196: METHOD(task_t, process_i, status_t,
! 197: private_informational_t *this, message_t *message)
! 198: {
! 199: return FAILED;
! 200: }
! 201:
! 202: METHOD(task_t, get_type, task_type_t,
! 203: private_informational_t *this)
! 204: {
! 205: return TASK_INFORMATIONAL;
! 206: }
! 207:
! 208: METHOD(task_t, migrate, void,
! 209: private_informational_t *this, ike_sa_t *ike_sa)
! 210: {
! 211: this->ike_sa = ike_sa;
! 212: }
! 213:
! 214: METHOD(task_t, destroy, void,
! 215: private_informational_t *this)
! 216: {
! 217: DESTROY_IF(this->notify);
! 218: DESTROY_IF(this->del);
! 219: free(this);
! 220: }
! 221:
! 222: /*
! 223: * Described in header.
! 224: */
! 225: informational_t *informational_create(ike_sa_t *ike_sa, notify_payload_t *notify)
! 226: {
! 227: private_informational_t *this;
! 228:
! 229: INIT(this,
! 230: .public = {
! 231: .task = {
! 232: .get_type = _get_type,
! 233: .migrate = _migrate,
! 234: .destroy = _destroy,
! 235: },
! 236: },
! 237: .ike_sa = ike_sa,
! 238: .notify = notify,
! 239: );
! 240:
! 241: if (notify)
! 242: {
! 243: this->public.task.build = _build_i;
! 244: this->public.task.process = _process_i;
! 245: }
! 246: else
! 247: {
! 248: this->public.task.build = _build_r;
! 249: this->public.task.process = _process_r;
! 250: }
! 251:
! 252: return &this->public;
! 253: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>