Annotation of embedaddon/strongswan/src/libcharon/sa/child_sa_manager.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2014 Martin Willi
! 3: * Copyright (C) 2014 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 "child_sa_manager.h"
! 17:
! 18: #include <daemon.h>
! 19: #include <threading/mutex.h>
! 20: #include <collections/hashtable.h>
! 21:
! 22: typedef struct private_child_sa_manager_t private_child_sa_manager_t;
! 23:
! 24: /**
! 25: * Private data of an child_sa_manager_t object.
! 26: */
! 27: struct private_child_sa_manager_t {
! 28:
! 29: /**
! 30: * Public child_sa_manager_t interface.
! 31: */
! 32: child_sa_manager_t public;
! 33:
! 34: /**
! 35: * CHILD_SAs by inbound SPI/dst, child_entry_t => child_entry_t
! 36: */
! 37: hashtable_t *in;
! 38:
! 39: /**
! 40: * CHILD_SAs by outbound SPI/dst, child_entry_t => child_entry_t
! 41: */
! 42: hashtable_t *out;
! 43:
! 44: /**
! 45: * CHILD_SAs by unique ID, child_entry_t => child_entry_t
! 46: */
! 47: hashtable_t *ids;
! 48:
! 49: /**
! 50: * Mutex to access any hashtable
! 51: */
! 52: mutex_t *mutex;
! 53: };
! 54:
! 55: /**
! 56: * Hashtable entry for a known CHILD_SA
! 57: */
! 58: typedef struct {
! 59: /** the associated IKE_SA */
! 60: ike_sa_id_t *ike_id;
! 61: /** unique CHILD_SA identifier */
! 62: uint32_t unique_id;
! 63: /** inbound SPI */
! 64: uint32_t spi_in;
! 65: /** outbound SPI */
! 66: uint32_t spi_out;
! 67: /** inbound host address */
! 68: host_t *host_in;
! 69: /** outbound host address and port */
! 70: host_t *host_out;
! 71: /** IPsec protocol, AH|ESP */
! 72: protocol_id_t proto;
! 73: } child_entry_t;
! 74:
! 75: /**
! 76: * Destroy a CHILD_SA entry
! 77: */
! 78: static void child_entry_destroy(child_entry_t *entry)
! 79: {
! 80: entry->ike_id->destroy(entry->ike_id);
! 81: entry->host_in->destroy(entry->host_in);
! 82: entry->host_out->destroy(entry->host_out);
! 83: free(entry);
! 84: }
! 85:
! 86: /**
! 87: * Hashtable hash function for inbound SAs
! 88: */
! 89: static u_int hash_in(child_entry_t *entry)
! 90: {
! 91: return chunk_hash_inc(chunk_from_thing(entry->spi_in),
! 92: chunk_hash_inc(entry->host_in->get_address(entry->host_in),
! 93: chunk_hash(chunk_from_thing(entry->proto))));
! 94: }
! 95:
! 96: /**
! 97: * Hashtable equals function for inbound SAs
! 98: */
! 99: static bool equals_in(child_entry_t *a, child_entry_t *b)
! 100: {
! 101: return a->spi_in == b->spi_in &&
! 102: a->proto == b->proto &&
! 103: a->host_in->ip_equals(a->host_in, b->host_in);
! 104: }
! 105:
! 106: /**
! 107: * Hashtable hash function for outbound SAs
! 108: */
! 109: static u_int hash_out(child_entry_t *entry)
! 110: {
! 111: return chunk_hash_inc(chunk_from_thing(entry->spi_out),
! 112: chunk_hash_inc(entry->host_out->get_address(entry->host_out),
! 113: chunk_hash(chunk_from_thing(entry->proto))));
! 114: }
! 115:
! 116: /**
! 117: * Hashtable equals function for outbound SAs
! 118: */
! 119: static bool equals_out(child_entry_t *a, child_entry_t *b)
! 120: {
! 121: return a->spi_out == b->spi_out &&
! 122: a->proto == b->proto &&
! 123: a->host_out->ip_equals(a->host_out, b->host_out);
! 124: }
! 125:
! 126: /**
! 127: * Hashtable hash function for SAs by unique ID
! 128: */
! 129: static u_int hash_id(child_entry_t *entry)
! 130: {
! 131: return chunk_hash(chunk_from_thing(entry->unique_id));
! 132: }
! 133:
! 134: /**
! 135: * Hashtable equals function for SAs by unique ID
! 136: */
! 137: static bool equals_id(child_entry_t *a, child_entry_t *b)
! 138: {
! 139: return a->unique_id == b->unique_id;
! 140: }
! 141:
! 142: METHOD(child_sa_manager_t, add, void,
! 143: private_child_sa_manager_t *this, child_sa_t *child_sa, ike_sa_t *ike_sa)
! 144: {
! 145: child_entry_t *entry;
! 146: host_t *in, *out;
! 147: ike_sa_id_t *id;
! 148:
! 149: id = ike_sa->get_id(ike_sa);
! 150: in = ike_sa->get_my_host(ike_sa);
! 151: out = ike_sa->get_other_host(ike_sa);
! 152:
! 153: INIT(entry,
! 154: .ike_id = id->clone(id),
! 155: .unique_id = child_sa->get_unique_id(child_sa),
! 156: .proto = child_sa->get_protocol(child_sa),
! 157: .spi_in = child_sa->get_spi(child_sa, TRUE),
! 158: .spi_out = child_sa->get_spi(child_sa, FALSE),
! 159: .host_in = in->clone(in),
! 160: .host_out = out->clone(out),
! 161: );
! 162:
! 163: this->mutex->lock(this->mutex);
! 164: if (!this->in->get(this->in, entry) &&
! 165: !this->out->get(this->out, entry))
! 166: {
! 167: this->in->put(this->in, entry, entry);
! 168: this->out->put(this->out, entry, entry);
! 169: entry = this->ids->put(this->ids, entry, entry);
! 170: }
! 171: this->mutex->unlock(this->mutex);
! 172:
! 173: if (entry)
! 174: {
! 175: child_entry_destroy(entry);
! 176: }
! 177: }
! 178:
! 179: METHOD(child_sa_manager_t, remove_, void,
! 180: private_child_sa_manager_t *this, child_sa_t *child_sa)
! 181: {
! 182: child_entry_t *entry, key = {
! 183: .unique_id = child_sa->get_unique_id(child_sa),
! 184: };
! 185:
! 186: this->mutex->lock(this->mutex);
! 187: entry = this->ids->remove(this->ids, &key);
! 188: if (entry)
! 189: {
! 190: this->in->remove(this->in, entry);
! 191: this->out->remove(this->out, entry);
! 192: }
! 193: this->mutex->unlock(this->mutex);
! 194:
! 195: if (entry)
! 196: {
! 197: child_entry_destroy(entry);
! 198: }
! 199: }
! 200:
! 201: /**
! 202: * Check out an IKE_SA for a given CHILD_SA
! 203: */
! 204: static ike_sa_t *checkout_ikesa(private_child_sa_manager_t *this,
! 205: ike_sa_id_t *id, uint32_t unique_id, child_sa_t **child_sa)
! 206: {
! 207: enumerator_t *enumerator;
! 208: child_sa_t *current;
! 209: ike_sa_t *ike_sa;
! 210: bool found = FALSE;
! 211:
! 212: ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
! 213: id->destroy(id);
! 214: if (ike_sa)
! 215: {
! 216: enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
! 217: while (enumerator->enumerate(enumerator, ¤t))
! 218: {
! 219: found = current->get_unique_id(current) == unique_id;
! 220: if (found)
! 221: {
! 222: if (child_sa)
! 223: {
! 224: *child_sa = current;
! 225: }
! 226: break;
! 227: }
! 228: }
! 229: enumerator->destroy(enumerator);
! 230:
! 231: if (found)
! 232: {
! 233: return ike_sa;
! 234: }
! 235: charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
! 236: }
! 237: return NULL;
! 238: }
! 239:
! 240: METHOD(child_sa_manager_t, checkout_by_id, ike_sa_t*,
! 241: private_child_sa_manager_t *this, uint32_t unique_id,
! 242: child_sa_t **child_sa)
! 243: {
! 244: ike_sa_id_t *id;
! 245: child_entry_t *entry, key = {
! 246: .unique_id = unique_id,
! 247: };
! 248:
! 249: this->mutex->lock(this->mutex);
! 250: entry = this->ids->get(this->ids, &key);
! 251: if (entry)
! 252: {
! 253: id = entry->ike_id->clone(entry->ike_id);
! 254: }
! 255: this->mutex->unlock(this->mutex);
! 256:
! 257: if (entry)
! 258: {
! 259: return checkout_ikesa(this, id, unique_id, child_sa);
! 260: }
! 261: return NULL;
! 262: }
! 263:
! 264: METHOD(child_sa_manager_t, checkout, ike_sa_t*,
! 265: private_child_sa_manager_t *this, protocol_id_t protocol, uint32_t spi,
! 266: host_t *dst, child_sa_t **child_sa)
! 267: {
! 268: ike_sa_id_t *id;
! 269: uint32_t unique_id;
! 270: child_entry_t *entry, key = {
! 271: .spi_in = spi,
! 272: .spi_out = spi,
! 273: .host_in = dst,
! 274: .host_out = dst,
! 275: .proto = protocol,
! 276: };
! 277:
! 278: this->mutex->lock(this->mutex);
! 279: entry = this->in->get(this->in, &key);
! 280: if (!entry)
! 281: {
! 282: entry = this->out->get(this->out, &key);
! 283: }
! 284: if (entry)
! 285: {
! 286: unique_id = entry->unique_id;
! 287: id = entry->ike_id->clone(entry->ike_id);
! 288: }
! 289: this->mutex->unlock(this->mutex);
! 290:
! 291: if (entry)
! 292: {
! 293: return checkout_ikesa(this, id, unique_id, child_sa);
! 294: }
! 295: return NULL;
! 296: }
! 297:
! 298: METHOD(child_sa_manager_t, destroy, void,
! 299: private_child_sa_manager_t *this)
! 300: {
! 301: this->in->destroy(this->in);
! 302: this->out->destroy(this->out);
! 303: this->ids->destroy(this->ids);
! 304: this->mutex->destroy(this->mutex);
! 305: free(this);
! 306: }
! 307:
! 308: /**
! 309: * See header
! 310: */
! 311: child_sa_manager_t *child_sa_manager_create()
! 312: {
! 313: private_child_sa_manager_t *this;
! 314:
! 315: INIT(this,
! 316: .public = {
! 317: .add = _add,
! 318: .remove = _remove_,
! 319: .checkout = _checkout,
! 320: .checkout_by_id = _checkout_by_id,
! 321: .destroy = _destroy,
! 322: },
! 323: .in = hashtable_create((hashtable_hash_t)hash_in,
! 324: (hashtable_equals_t)equals_in, 8),
! 325: .out = hashtable_create((hashtable_hash_t)hash_out,
! 326: (hashtable_equals_t)equals_out, 8),
! 327: .ids = hashtable_create((hashtable_hash_t)hash_id,
! 328: (hashtable_equals_t)equals_id, 8),
! 329: .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
! 330: );
! 331:
! 332: return &this->public;
! 333: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>