Return to ipsec_sa.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libipsec |
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: }