Annotation of embedaddon/strongswan/src/libipsec/ipsec_sa.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2012 Tobias Brunner
! 3: * Copyright (C) 2012 Giuliano Grassi
! 4: * Copyright (C) 2012 Ralf Sager
! 5: * HSR Hochschule fuer Technik Rapperswil
! 6: *
! 7: * This program is free software; you can redistribute it and/or modify it
! 8: * under the terms of the GNU General Public License as published by the
! 9: * Free Software Foundation; either version 2 of the License, or (at your
! 10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 11: *
! 12: * This program is distributed in the hope that it will be useful, but
! 13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 15: * for more details.
! 16: */
! 17:
! 18: #include "ipsec.h"
! 19: #include "ipsec_sa.h"
! 20:
! 21: #include <library.h>
! 22: #include <utils/debug.h>
! 23:
! 24: typedef struct private_ipsec_sa_t private_ipsec_sa_t;
! 25:
! 26: /**
! 27: * Private additions to ipsec_sa_t.
! 28: */
! 29: struct private_ipsec_sa_t {
! 30:
! 31: /**
! 32: * Public members
! 33: */
! 34: ipsec_sa_t public;
! 35:
! 36: /**
! 37: * SPI of this SA
! 38: */
! 39: uint32_t spi;
! 40:
! 41: /**
! 42: * Source address
! 43: */
! 44: host_t *src;
! 45:
! 46: /**
! 47: * Destination address
! 48: */
! 49: host_t *dst;
! 50:
! 51: /**
! 52: * Protocol
! 53: */
! 54: uint8_t protocol;
! 55:
! 56: /**
! 57: * Reqid of this SA
! 58: */
! 59: uint32_t reqid;
! 60:
! 61: /**
! 62: * Lifetime configuration
! 63: */
! 64: lifetime_cfg_t lifetime;
! 65:
! 66: /**
! 67: * IPsec mode
! 68: */
! 69: ipsec_mode_t mode;
! 70:
! 71: /**
! 72: * TRUE if extended sequence numbers are used
! 73: */
! 74: bool esn;
! 75:
! 76: /**
! 77: * TRUE if this is an inbound SA
! 78: */
! 79: bool inbound;
! 80:
! 81: /**
! 82: * ESP context
! 83: */
! 84: esp_context_t *esp_context;
! 85:
! 86: /**
! 87: * Usage statistics
! 88: */
! 89: struct {
! 90: /** last time of use */
! 91: time_t time;
! 92: /** number of packets processed */
! 93: uint64_t packets;
! 94: /** number of bytes processed */
! 95: uint64_t bytes;
! 96: } use;
! 97:
! 98: /**
! 99: * Has the SA soft-expired?
! 100: */
! 101: bool soft_expired;
! 102:
! 103: /**
! 104: * Has the SA hard-expired?
! 105: */
! 106: bool hard_expired;
! 107: };
! 108:
! 109: METHOD(ipsec_sa_t, get_source, host_t*,
! 110: private_ipsec_sa_t *this)
! 111: {
! 112: return this->src;
! 113: }
! 114:
! 115: METHOD(ipsec_sa_t, get_destination, host_t*,
! 116: private_ipsec_sa_t *this)
! 117: {
! 118: return this->dst;
! 119: }
! 120:
! 121: METHOD(ipsec_sa_t, set_source, void,
! 122: private_ipsec_sa_t *this, host_t *addr)
! 123: {
! 124: this->src->destroy(this->src);
! 125: this->src = addr->clone(addr);
! 126: }
! 127:
! 128: METHOD(ipsec_sa_t, set_destination, void,
! 129: private_ipsec_sa_t *this, host_t *addr)
! 130: {
! 131: this->dst->destroy(this->dst);
! 132: this->dst = addr->clone(addr);
! 133: }
! 134:
! 135: METHOD(ipsec_sa_t, get_spi, uint32_t,
! 136: private_ipsec_sa_t *this)
! 137: {
! 138: return this->spi;
! 139: }
! 140:
! 141: METHOD(ipsec_sa_t, get_reqid, uint32_t,
! 142: private_ipsec_sa_t *this)
! 143: {
! 144: return this->reqid;
! 145: }
! 146:
! 147: METHOD(ipsec_sa_t, get_protocol, uint8_t,
! 148: private_ipsec_sa_t *this)
! 149: {
! 150: return this->protocol;
! 151: }
! 152:
! 153: METHOD(ipsec_sa_t, get_lifetime, lifetime_cfg_t*,
! 154: private_ipsec_sa_t *this)
! 155: {
! 156: return &this->lifetime;
! 157: }
! 158:
! 159: METHOD(ipsec_sa_t, is_inbound, bool,
! 160: private_ipsec_sa_t *this)
! 161: {
! 162: return this->inbound;
! 163: }
! 164:
! 165: METHOD(ipsec_sa_t, get_esp_context, esp_context_t*,
! 166: private_ipsec_sa_t *this)
! 167: {
! 168: return this->esp_context;
! 169: }
! 170:
! 171: METHOD(ipsec_sa_t, get_usestats, void,
! 172: private_ipsec_sa_t *this, uint64_t *bytes, uint64_t *packets,
! 173: time_t *time)
! 174: {
! 175: if (bytes)
! 176: {
! 177: *bytes = this->use.bytes;
! 178: }
! 179: if (packets)
! 180: {
! 181: *packets = this->use.packets;
! 182: }
! 183: if (time)
! 184: {
! 185: *time = this->use.time;
! 186: }
! 187: }
! 188:
! 189: METHOD(ipsec_sa_t, expire, void,
! 190: private_ipsec_sa_t *this, bool hard)
! 191: {
! 192: if (hard)
! 193: {
! 194: if (!this->hard_expired)
! 195: {
! 196: this->hard_expired = TRUE;
! 197: ipsec->events->expire(ipsec->events, this->protocol, this->spi,
! 198: this->dst, TRUE);
! 199: }
! 200: }
! 201: else
! 202: {
! 203: if (!this->hard_expired && !this->soft_expired)
! 204: {
! 205: this->soft_expired = TRUE;
! 206: ipsec->events->expire(ipsec->events, this->protocol, this->spi,
! 207: this->dst, FALSE);
! 208: }
! 209: }
! 210: }
! 211:
! 212: METHOD(ipsec_sa_t, update_usestats, void,
! 213: private_ipsec_sa_t *this, uint32_t bytes)
! 214: {
! 215: this->use.time = time_monotonic(NULL);
! 216: this->use.packets++;
! 217: this->use.bytes += bytes;
! 218:
! 219: if (this->lifetime.packets.life &&
! 220: this->use.packets >= this->lifetime.packets.life)
! 221: {
! 222: return expire(this, TRUE);
! 223: }
! 224: if (this->lifetime.bytes.life &&
! 225: this->use.bytes >= this->lifetime.bytes.life)
! 226: {
! 227: return expire(this, TRUE);
! 228: }
! 229: if (this->lifetime.packets.rekey &&
! 230: this->use.packets >= this->lifetime.packets.rekey)
! 231: {
! 232: return expire(this, FALSE);
! 233: }
! 234: if (this->lifetime.bytes.rekey &&
! 235: this->use.bytes >= this->lifetime.bytes.rekey)
! 236: {
! 237: return expire(this, FALSE);
! 238: }
! 239: }
! 240:
! 241: METHOD(ipsec_sa_t, match_by_spi_dst, bool,
! 242: private_ipsec_sa_t *this, uint32_t spi, host_t *dst)
! 243: {
! 244: return this->spi == spi && this->dst->ip_equals(this->dst, dst) &&
! 245: !this->hard_expired;
! 246: }
! 247:
! 248: METHOD(ipsec_sa_t, match_by_spi_src_dst, bool,
! 249: private_ipsec_sa_t *this, uint32_t spi, host_t *src, host_t *dst)
! 250: {
! 251: return this->spi == spi && this->src->ip_equals(this->src, src) &&
! 252: this->dst->ip_equals(this->dst, dst);
! 253: }
! 254:
! 255: METHOD(ipsec_sa_t, match_by_reqid, bool,
! 256: private_ipsec_sa_t *this, uint32_t reqid, bool inbound)
! 257: {
! 258: return this->reqid == reqid && this->inbound == inbound &&
! 259: !this->hard_expired;
! 260: }
! 261:
! 262: METHOD(ipsec_sa_t, destroy, void,
! 263: private_ipsec_sa_t *this)
! 264: {
! 265: this->src->destroy(this->src);
! 266: this->dst->destroy(this->dst);
! 267: DESTROY_IF(this->esp_context);
! 268: free(this);
! 269: }
! 270:
! 271: /**
! 272: * Described in header.
! 273: */
! 274: ipsec_sa_t *ipsec_sa_create(uint32_t spi, host_t *src, host_t *dst,
! 275: uint8_t protocol, uint32_t reqid, mark_t mark, uint32_t tfc,
! 276: lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
! 277: uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
! 278: uint16_t ipcomp, uint16_t cpi, bool encap, bool esn, bool inbound)
! 279: {
! 280: private_ipsec_sa_t *this;
! 281:
! 282: if (protocol != IPPROTO_ESP)
! 283: {
! 284: DBG1(DBG_ESP, " IPsec SA: protocol not supported");
! 285: return NULL;
! 286: }
! 287: if (!encap)
! 288: {
! 289: DBG1(DBG_ESP, " IPsec SA: only UDP encapsulation is supported");
! 290: return NULL;
! 291: }
! 292: if (esn)
! 293: {
! 294: DBG1(DBG_ESP, " IPsec SA: ESN not supported");
! 295: return NULL;
! 296: }
! 297: if (ipcomp != IPCOMP_NONE)
! 298: {
! 299: DBG1(DBG_ESP, " IPsec SA: compression not supported");
! 300: return NULL;
! 301: }
! 302: if (mode != MODE_TUNNEL)
! 303: {
! 304: DBG1(DBG_ESP, " IPsec SA: unsupported mode");
! 305: return NULL;
! 306: }
! 307:
! 308: INIT(this,
! 309: .public = {
! 310: .destroy = _destroy,
! 311: .get_source = _get_source,
! 312: .get_destination = _get_destination,
! 313: .set_source = _set_source,
! 314: .set_destination = _set_destination,
! 315: .get_spi = _get_spi,
! 316: .get_reqid = _get_reqid,
! 317: .get_protocol = _get_protocol,
! 318: .get_lifetime = _get_lifetime,
! 319: .is_inbound = _is_inbound,
! 320: .match_by_spi_dst = _match_by_spi_dst,
! 321: .match_by_spi_src_dst = _match_by_spi_src_dst,
! 322: .match_by_reqid = _match_by_reqid,
! 323: .get_esp_context = _get_esp_context,
! 324: .get_usestats = _get_usestats,
! 325: .update_usestats = _update_usestats,
! 326: .expire = _expire,
! 327: },
! 328: .spi = spi,
! 329: .src = src->clone(src),
! 330: .dst = dst->clone(dst),
! 331: .lifetime = *lifetime,
! 332: .protocol = protocol,
! 333: .reqid = reqid,
! 334: .mode = mode,
! 335: .esn = esn,
! 336: .inbound = inbound,
! 337: );
! 338:
! 339: this->esp_context = esp_context_create(enc_alg, enc_key, int_alg, int_key,
! 340: inbound);
! 341: if (!this->esp_context)
! 342: {
! 343: destroy(this);
! 344: return NULL;
! 345: }
! 346: return &this->public;
! 347: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>