Annotation of embedaddon/strongswan/src/libipsec/ipsec_sa.c, revision 1.1.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>