Annotation of embedaddon/strongswan/src/libcharon/sa/child_sa.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * Copyright (C) 2006-2019 Tobias Brunner
                      3:  * Copyright (C) 2016 Andreas Steffen
                      4:  * Copyright (C) 2005-2008 Martin Willi
                      5:  * Copyright (C) 2006 Daniel Roethlisberger
                      6:  * Copyright (C) 2005 Jan Hutter
                      7:  * HSR Hochschule fuer Technik Rapperswil
                      8:  *
                      9:  * This program is free software; you can redistribute it and/or modify it
                     10:  * under the terms of the GNU General Public License as published by the
                     11:  * Free Software Foundation; either version 2 of the License, or (at your
                     12:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     13:  *
                     14:  * This program is distributed in the hope that it will be useful, but
                     15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     16:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     17:  * for more details.
                     18:  */
                     19: 
                     20: #define _GNU_SOURCE
                     21: #include "child_sa.h"
                     22: 
                     23: #include <stdio.h>
                     24: #include <string.h>
                     25: #include <time.h>
                     26: 
                     27: #include <daemon.h>
                     28: #include <collections/array.h>
                     29: 
                     30: ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
                     31:        "CREATED",
                     32:        "ROUTED",
                     33:        "INSTALLING",
                     34:        "INSTALLED",
                     35:        "UPDATING",
                     36:        "REKEYING",
                     37:        "REKEYED",
                     38:        "RETRYING",
                     39:        "DELETING",
                     40:        "DELETED",
                     41:        "DESTROYING",
                     42: );
                     43: 
                     44: ENUM_FLAGS(child_sa_outbound_state_names, CHILD_OUTBOUND_REGISTERED, CHILD_OUTBOUND_POLICIES,
                     45:        "REGISTERED",
                     46:        "SA",
                     47:        "POLICIES",
                     48: );
                     49: 
                     50: typedef struct private_child_sa_t private_child_sa_t;
                     51: 
                     52: /**
                     53:  * Private data of a child_sa_t object.
                     54:  */
                     55: struct private_child_sa_t {
                     56:        /**
                     57:         * Public interface of child_sa_t.
                     58:         */
                     59:        child_sa_t public;
                     60: 
                     61:        /**
                     62:         * address of us
                     63:         */
                     64:        host_t *my_addr;
                     65: 
                     66:        /**
                     67:         * address of remote
                     68:         */
                     69:        host_t *other_addr;
                     70: 
                     71:        /**
                     72:         * our actually used SPI, 0 if unused
                     73:         */
                     74:        uint32_t my_spi;
                     75: 
                     76:        /**
                     77:         * others used SPI, 0 if unused
                     78:         */
                     79:        uint32_t other_spi;
                     80: 
                     81:        /**
                     82:         * our Compression Parameter Index (CPI) used, 0 if unused
                     83:         */
                     84:        uint16_t my_cpi;
                     85: 
                     86:        /**
                     87:         * others Compression Parameter Index (CPI) used, 0 if unused
                     88:         */
                     89:        uint16_t other_cpi;
                     90: 
                     91:        /**
                     92:         * Array for local traffic selectors
                     93:         */
                     94:        array_t *my_ts;
                     95: 
                     96:        /**
                     97:         * Array for remote traffic selectors
                     98:         */
                     99:        array_t *other_ts;
                    100: 
                    101:        /**
                    102:         * Outbound encryption key cached during a rekeying
                    103:         */
                    104:        chunk_t encr_r;
                    105: 
                    106:        /**
                    107:         * Outbound integrity key cached during a rekeying
                    108:         */
                    109:        chunk_t integ_r;
                    110: 
                    111:        /**
                    112:         * Whether the outbound SA has only been registered yet during a rekeying
                    113:         */
                    114:        child_sa_outbound_state_t outbound_state;
                    115: 
                    116:        /**
1.1.1.2 ! misho     117:         * Whether the inbound SA has been installed
        !           118:         */
        !           119:        bool inbound_installed;
        !           120: 
        !           121:        /**
1.1       misho     122:         * Whether the peer supports TFCv3
                    123:         */
                    124:        bool tfcv3;
                    125: 
                    126:        /**
                    127:         * The outbound SPI of the CHILD_SA that replaced this one during a rekeying
                    128:         */
                    129:        uint32_t rekey_spi;
                    130: 
                    131:        /**
                    132:         * Protocol used to protect this SA, ESP|AH
                    133:         */
                    134:        protocol_id_t protocol;
                    135: 
                    136:        /**
                    137:         * reqid used for this child_sa
                    138:         */
                    139:        uint32_t reqid;
                    140: 
                    141:        /**
                    142:         * Did we allocate/confirm and must release the reqid?
                    143:         */
                    144:        bool reqid_allocated;
                    145: 
                    146:        /**
                    147:         * Is the reqid statically configured
                    148:         */
                    149:        bool static_reqid;
                    150: 
                    151:        /**
                    152:         * Unique CHILD_SA identifier
                    153:         */
                    154:        uint32_t unique_id;
                    155: 
                    156:        /**
                    157:         * Whether FWD policies in the outbound direction should be installed
                    158:         */
                    159:        bool policies_fwd_out;
                    160: 
                    161:        /**
                    162:         * Inbound interface ID
                    163:         */
                    164:        uint32_t if_id_in;
                    165: 
                    166:        /**
                    167:         * Outbound interface ID
                    168:         */
                    169:        uint32_t if_id_out;
                    170: 
                    171:        /**
                    172:         * inbound mark used for this child_sa
                    173:         */
                    174:        mark_t mark_in;
                    175: 
                    176:        /**
                    177:         * outbound mark used for this child_sa
                    178:         */
                    179:        mark_t mark_out;
                    180: 
                    181:        /**
                    182:         * absolute time when rekeying is scheduled
                    183:         */
                    184:        time_t rekey_time;
                    185: 
                    186:        /**
                    187:         * absolute time when the SA expires
                    188:         */
                    189:        time_t expire_time;
                    190: 
                    191:        /**
                    192:         * absolute time when SA has been installed
                    193:         */
                    194:        time_t install_time;
                    195: 
                    196:        /**
                    197:         * state of the CHILD_SA
                    198:         */
                    199:        child_sa_state_t state;
                    200: 
                    201:        /**
                    202:         * TRUE if this CHILD_SA is used to install trap policies
                    203:         */
                    204:        bool trap;
                    205: 
                    206:        /**
                    207:         * Specifies if UDP encapsulation is enabled (NAT traversal)
                    208:         */
                    209:        bool encap;
                    210: 
                    211:        /**
                    212:         * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
                    213:         */
                    214:        ipcomp_transform_t ipcomp;
                    215: 
                    216:        /**
                    217:         * mode this SA uses, tunnel/transport
                    218:         */
                    219:        ipsec_mode_t mode;
                    220: 
                    221:        /**
                    222:         * Action to enforce if peer closes the CHILD_SA
                    223:         */
                    224:        action_t close_action;
                    225: 
                    226:        /**
                    227:         * Action to enforce if peer is considered dead
                    228:         */
                    229:        action_t dpd_action;
                    230: 
                    231:        /**
                    232:         * selected proposal
                    233:         */
                    234:        proposal_t *proposal;
                    235: 
                    236:        /**
                    237:         * config used to create this child
                    238:         */
                    239:        child_cfg_t *config;
                    240: 
                    241:        /**
                    242:         * time of last use in seconds (inbound)
                    243:         */
                    244:        time_t my_usetime;
                    245: 
                    246:        /**
                    247:         * time of last use in seconds (outbound)
                    248:         */
                    249:        time_t other_usetime;
                    250: 
                    251:        /**
                    252:         * last number of inbound bytes
                    253:         */
                    254:        uint64_t my_usebytes;
                    255: 
                    256:        /**
                    257:         * last number of outbound bytes
                    258:         */
                    259:        uint64_t other_usebytes;
                    260: 
                    261:        /**
                    262:         * last number of inbound packets
                    263:         */
                    264:        uint64_t my_usepackets;
                    265: 
                    266:        /**
                    267:         * last number of outbound bytes
                    268:         */
                    269:        uint64_t other_usepackets;
                    270: };
                    271: 
                    272: /**
                    273:  * Convert an IKEv2 specific protocol identifier to the IP protocol identifier
                    274:  */
                    275: static inline uint8_t proto_ike2ip(protocol_id_t protocol)
                    276: {
                    277:        switch (protocol)
                    278:        {
                    279:                case PROTO_ESP:
                    280:                        return IPPROTO_ESP;
                    281:                case PROTO_AH:
                    282:                        return IPPROTO_AH;
                    283:                default:
                    284:                        return protocol;
                    285:        }
                    286: }
                    287: 
                    288: /**
                    289:  * Returns the mark to use on the inbound SA
                    290:  */
                    291: static inline mark_t mark_in_sa(private_child_sa_t *this)
                    292: {
                    293:        if (this->config->has_option(this->config, OPT_MARK_IN_SA))
                    294:        {
                    295:                return this->mark_in;
                    296:        }
                    297:        return (mark_t){};
                    298: }
                    299: 
                    300: METHOD(child_sa_t, get_name, char*,
                    301:           private_child_sa_t *this)
                    302: {
                    303:        return this->config->get_name(this->config);
                    304: }
                    305: 
                    306: METHOD(child_sa_t, get_reqid, uint32_t,
                    307:           private_child_sa_t *this)
                    308: {
                    309:        return this->reqid;
                    310: }
                    311: 
                    312: METHOD(child_sa_t, get_unique_id, uint32_t,
                    313:        private_child_sa_t *this)
                    314: {
                    315:        return this->unique_id;
                    316: }
                    317: 
                    318: METHOD(child_sa_t, get_config, child_cfg_t*,
                    319:           private_child_sa_t *this)
                    320: {
                    321:        return this->config;
                    322: }
                    323: 
                    324: METHOD(child_sa_t, set_state, void,
                    325:           private_child_sa_t *this, child_sa_state_t state)
                    326: {
                    327:        if (this->state != state)
                    328:        {
                    329:                DBG2(DBG_CHD, "CHILD_SA %s{%d} state change: %N => %N",
                    330:                         get_name(this), this->unique_id,
                    331:                         child_sa_state_names, this->state,
                    332:                         child_sa_state_names, state);
                    333:                charon->bus->child_state_change(charon->bus, &this->public, state);
                    334:                this->state = state;
                    335:        }
                    336: }
                    337: 
                    338: METHOD(child_sa_t, get_state, child_sa_state_t,
                    339:           private_child_sa_t *this)
                    340: {
                    341:        return this->state;
                    342: }
                    343: 
                    344: METHOD(child_sa_t, get_outbound_state, child_sa_outbound_state_t,
                    345:           private_child_sa_t *this)
                    346: {
                    347:        return this->outbound_state;
                    348: }
                    349: 
                    350: METHOD(child_sa_t, get_spi, uint32_t,
                    351:           private_child_sa_t *this, bool inbound)
                    352: {
                    353:        return inbound ? this->my_spi : this->other_spi;
                    354: }
                    355: 
                    356: METHOD(child_sa_t, get_cpi, uint16_t,
                    357:           private_child_sa_t *this, bool inbound)
                    358: {
                    359:        return inbound ? this->my_cpi : this->other_cpi;
                    360: }
                    361: 
                    362: METHOD(child_sa_t, get_protocol, protocol_id_t,
                    363:           private_child_sa_t *this)
                    364: {
                    365:        return this->protocol;
                    366: }
                    367: 
                    368: METHOD(child_sa_t, set_protocol, void,
                    369:           private_child_sa_t *this, protocol_id_t protocol)
                    370: {
                    371:        this->protocol = protocol;
                    372: }
                    373: 
                    374: METHOD(child_sa_t, get_mode, ipsec_mode_t,
                    375:           private_child_sa_t *this)
                    376: {
                    377:        return this->mode;
                    378: }
                    379: 
                    380: METHOD(child_sa_t, set_mode, void,
                    381:           private_child_sa_t *this, ipsec_mode_t mode)
                    382: {
                    383:        this->mode = mode;
                    384: }
                    385: 
                    386: METHOD(child_sa_t, has_encap, bool,
                    387:           private_child_sa_t *this)
                    388: {
                    389:        return this->encap;
                    390: }
                    391: 
                    392: METHOD(child_sa_t, get_ipcomp, ipcomp_transform_t,
                    393:           private_child_sa_t *this)
                    394: {
                    395:        return this->ipcomp;
                    396: }
                    397: 
                    398: METHOD(child_sa_t, set_ipcomp, void,
                    399:           private_child_sa_t *this, ipcomp_transform_t ipcomp)
                    400: {
                    401:        this->ipcomp = ipcomp;
                    402: }
                    403: 
                    404: METHOD(child_sa_t, set_close_action, void,
                    405:           private_child_sa_t *this, action_t action)
                    406: {
                    407:        this->close_action = action;
                    408: }
                    409: 
                    410: METHOD(child_sa_t, get_close_action, action_t,
                    411:           private_child_sa_t *this)
                    412: {
                    413:        return this->close_action;
                    414: }
                    415: 
                    416: METHOD(child_sa_t, set_dpd_action, void,
                    417:           private_child_sa_t *this, action_t action)
                    418: {
                    419:        this->dpd_action = action;
                    420: }
                    421: 
                    422: METHOD(child_sa_t, get_dpd_action, action_t,
                    423:           private_child_sa_t *this)
                    424: {
                    425:        return this->dpd_action;
                    426: }
                    427: 
                    428: METHOD(child_sa_t, get_proposal, proposal_t*,
                    429:           private_child_sa_t *this)
                    430: {
                    431:        return this->proposal;
                    432: }
                    433: 
                    434: METHOD(child_sa_t, set_proposal, void,
                    435:           private_child_sa_t *this, proposal_t *proposal)
                    436: {
                    437:        this->proposal = proposal->clone(proposal, 0);
                    438: }
                    439: 
                    440: METHOD(child_sa_t, create_ts_enumerator, enumerator_t*,
                    441:        private_child_sa_t *this, bool local)
                    442: {
                    443:        if (local)
                    444:        {
                    445:                return array_create_enumerator(this->my_ts);
                    446:        }
                    447:        return array_create_enumerator(this->other_ts);
                    448: }
                    449: 
                    450: typedef struct policy_enumerator_t policy_enumerator_t;
                    451: 
                    452: /**
                    453:  * Private policy enumerator
                    454:  */
                    455: struct policy_enumerator_t {
                    456:        /** implements enumerator_t */
                    457:        enumerator_t public;
                    458:        /** enumerator over own TS */
                    459:        enumerator_t *mine;
                    460:        /** enumerator over others TS */
                    461:        enumerator_t *other;
                    462:        /** array of others TS, to recreate enumerator */
                    463:        array_t *array;
                    464:        /** currently enumerating TS for "me" side */
                    465:        traffic_selector_t *ts;
                    466: };
                    467: 
                    468: METHOD(enumerator_t, policy_enumerate, bool,
                    469:           policy_enumerator_t *this, va_list args)
                    470: {
                    471:        traffic_selector_t *other_ts, **my_out, **other_out;
                    472: 
                    473:        VA_ARGS_VGET(args, my_out, other_out);
                    474: 
                    475:        while (this->ts || this->mine->enumerate(this->mine, &this->ts))
                    476:        {
                    477:                if (!this->other->enumerate(this->other, &other_ts))
                    478:                {       /* end of others list, restart with new of mine */
                    479:                        this->other->destroy(this->other);
                    480:                        this->other = array_create_enumerator(this->array);
                    481:                        this->ts = NULL;
                    482:                        continue;
                    483:                }
                    484:                if (this->ts->get_type(this->ts) != other_ts->get_type(other_ts))
                    485:                {       /* family mismatch */
                    486:                        continue;
                    487:                }
                    488:                if (this->ts->get_protocol(this->ts) &&
                    489:                        other_ts->get_protocol(other_ts) &&
                    490:                        this->ts->get_protocol(this->ts) != other_ts->get_protocol(other_ts))
                    491:                {       /* protocol mismatch */
                    492:                        continue;
                    493:                }
                    494:                if (my_out)
                    495:                {
                    496:                        *my_out = this->ts;
                    497:                }
                    498:                if (other_out)
                    499:                {
                    500:                        *other_out = other_ts;
                    501:                }
                    502:                return TRUE;
                    503:        }
                    504:        return FALSE;
                    505: }
                    506: 
                    507: METHOD(enumerator_t, policy_destroy, void,
                    508:           policy_enumerator_t *this)
                    509: {
                    510:        this->mine->destroy(this->mine);
                    511:        this->other->destroy(this->other);
                    512:        free(this);
                    513: }
                    514: 
                    515: METHOD(child_sa_t, create_policy_enumerator, enumerator_t*,
                    516:           private_child_sa_t *this)
                    517: {
                    518:        policy_enumerator_t *e;
                    519: 
                    520:        INIT(e,
                    521:                .public = {
                    522:                        .enumerate = enumerator_enumerate_default,
                    523:                        .venumerate = _policy_enumerate,
                    524:                        .destroy = _policy_destroy,
                    525:                },
                    526:                .mine = array_create_enumerator(this->my_ts),
                    527:                .other = array_create_enumerator(this->other_ts),
                    528:                .array = this->other_ts,
                    529:                .ts = NULL,
                    530:        );
                    531: 
                    532:        return &e->public;
                    533: }
                    534: 
                    535: /**
                    536:  * update the cached usebytes
                    537:  * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs
                    538:  * are available, and NOT_SUPPORTED if the kernel interface does not support
                    539:  * querying the usebytes.
                    540:  */
                    541: static status_t update_usebytes(private_child_sa_t *this, bool inbound)
                    542: {
                    543:        status_t status = FAILED;
                    544:        uint64_t bytes, packets;
                    545:        time_t time;
                    546: 
                    547:        if (inbound)
                    548:        {
1.1.1.2 ! misho     549:                if (this->my_spi && this->inbound_installed)
1.1       misho     550:                {
                    551:                        kernel_ipsec_sa_id_t id = {
                    552:                                .src = this->other_addr,
                    553:                                .dst = this->my_addr,
                    554:                                .spi = this->my_spi,
                    555:                                .proto = proto_ike2ip(this->protocol),
                    556:                                .mark = mark_in_sa(this),
                    557:                                .if_id = this->if_id_in,
                    558:                        };
                    559:                        kernel_ipsec_query_sa_t query = {};
                    560: 
                    561:                        status = charon->kernel->query_sa(charon->kernel, &id, &query,
                    562:                                                                                          &bytes, &packets, &time);
                    563:                        if (status == SUCCESS)
                    564:                        {
                    565:                                if (bytes > this->my_usebytes)
                    566:                                {
                    567:                                        this->my_usebytes = bytes;
                    568:                                        this->my_usepackets = packets;
                    569:                                        if (time)
                    570:                                        {
                    571:                                                this->my_usetime = time;
                    572:                                        }
                    573:                                }
                    574:                                else
                    575:                                {
                    576:                                        status = FAILED;
                    577:                                }
                    578:                        }
                    579:                }
                    580:        }
                    581:        else
                    582:        {
                    583:                if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
                    584:                {
                    585:                        kernel_ipsec_sa_id_t id = {
                    586:                                .src = this->my_addr,
                    587:                                .dst = this->other_addr,
                    588:                                .spi = this->other_spi,
                    589:                                .proto = proto_ike2ip(this->protocol),
                    590:                                .mark = this->mark_out,
                    591:                                .if_id = this->if_id_out,
                    592:                        };
                    593:                        kernel_ipsec_query_sa_t query = {};
                    594: 
                    595:                        status = charon->kernel->query_sa(charon->kernel, &id, &query,
                    596:                                                                                          &bytes, &packets, &time);
                    597:                        if (status == SUCCESS)
                    598:                        {
                    599:                                if (bytes > this->other_usebytes)
                    600:                                {
                    601:                                        this->other_usebytes = bytes;
                    602:                                        this->other_usepackets = packets;
                    603:                                        if (time)
                    604:                                        {
                    605:                                                this->other_usetime = time;
                    606:                                        }
                    607:                                }
                    608:                                else
                    609:                                {
                    610:                                        status = FAILED;
                    611:                                }
                    612:                        }
                    613:                }
                    614:        }
                    615:        return status;
                    616: }
                    617: 
                    618: /**
                    619:  * updates the cached usetime
                    620:  */
                    621: static bool update_usetime(private_child_sa_t *this, bool inbound)
                    622: {
                    623:        enumerator_t *enumerator;
                    624:        traffic_selector_t *my_ts, *other_ts;
                    625:        time_t last_use = 0;
                    626: 
                    627:        enumerator = create_policy_enumerator(this);
                    628:        while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
                    629:        {
                    630:                time_t in, out, fwd;
                    631: 
                    632:                if (inbound)
                    633:                {
                    634:                        kernel_ipsec_policy_id_t id = {
                    635:                                .dir = POLICY_IN,
                    636:                                .src_ts = other_ts,
                    637:                                .dst_ts = my_ts,
                    638:                                .mark = this->mark_in,
                    639:                                .if_id = this->if_id_in,
                    640:                        };
                    641:                        kernel_ipsec_query_policy_t query = {};
                    642: 
                    643:                        if (charon->kernel->query_policy(charon->kernel, &id, &query,
                    644:                                                                                         &in) == SUCCESS)
                    645:                        {
                    646:                                last_use = max(last_use, in);
                    647:                        }
                    648:                        if (this->mode != MODE_TRANSPORT)
                    649:                        {
                    650:                                id.dir = POLICY_FWD;
                    651:                                if (charon->kernel->query_policy(charon->kernel, &id, &query,
                    652:                                                                                                 &fwd) == SUCCESS)
                    653:                                {
                    654:                                        last_use = max(last_use, fwd);
                    655:                                }
                    656:                        }
                    657:                }
                    658:                else
                    659:                {
                    660:                        kernel_ipsec_policy_id_t id = {
                    661:                                .dir = POLICY_OUT,
                    662:                                .src_ts = my_ts,
                    663:                                .dst_ts = other_ts,
                    664:                                .mark = this->mark_out,
                    665:                                .if_id = this->if_id_out,
                    666:                                .interface = this->config->get_interface(this->config),
                    667:                        };
                    668:                        kernel_ipsec_query_policy_t query = {};
                    669: 
                    670:                        if (charon->kernel->query_policy(charon->kernel, &id, &query,
                    671:                                                                                         &out) == SUCCESS)
                    672:                        {
                    673:                                last_use = max(last_use, out);
                    674:                        }
                    675:                }
                    676:        }
                    677:        enumerator->destroy(enumerator);
                    678: 
                    679:        if (last_use == 0)
                    680:        {
                    681:                return FALSE;
                    682:        }
                    683:        if (inbound)
                    684:        {
                    685:                this->my_usetime = last_use;
                    686:        }
                    687:        else
                    688:        {
                    689:                this->other_usetime = last_use;
                    690:        }
                    691:        return TRUE;
                    692: }
                    693: 
                    694: METHOD(child_sa_t, get_usestats, void,
                    695:        private_child_sa_t *this, bool inbound,
                    696:        time_t *time, uint64_t *bytes, uint64_t *packets)
                    697: {
                    698:        if ((!bytes && !packets) || update_usebytes(this, inbound) != FAILED)
                    699:        {
                    700:                /* there was traffic since last update or the kernel interface
                    701:                 * does not support querying the number of usebytes.
                    702:                 */
                    703:                if (time)
                    704:                {
                    705:                        if (!update_usetime(this, inbound) && !bytes && !packets)
                    706:                        {
                    707:                                /* if policy query did not yield a usetime, query SAs instead */
                    708:                                update_usebytes(this, inbound);
                    709:                        }
                    710:                }
                    711:        }
                    712:        if (time)
                    713:        {
                    714:                *time = inbound ? this->my_usetime : this->other_usetime;
                    715:        }
                    716:        if (bytes)
                    717:        {
                    718:                *bytes = inbound ? this->my_usebytes : this->other_usebytes;
                    719:        }
                    720:        if (packets)
                    721:        {
                    722:                *packets = inbound ? this->my_usepackets : this->other_usepackets;
                    723:        }
                    724: }
                    725: 
                    726: METHOD(child_sa_t, get_mark, mark_t,
                    727:        private_child_sa_t *this, bool inbound)
                    728: {
                    729:        return inbound ? this->mark_in : this->mark_out;
                    730: }
                    731: 
                    732: METHOD(child_sa_t, get_if_id, uint32_t,
                    733:        private_child_sa_t *this, bool inbound)
                    734: {
                    735:        return inbound ? this->if_id_in : this->if_id_out;
                    736: }
                    737: 
                    738: METHOD(child_sa_t, get_lifetime, time_t,
                    739:           private_child_sa_t *this, bool hard)
                    740: {
                    741:        return hard ? this->expire_time : this->rekey_time;
                    742: }
                    743: 
                    744: METHOD(child_sa_t, get_installtime, time_t,
                    745:        private_child_sa_t *this)
                    746: {
                    747:        return this->install_time;
                    748: }
                    749: 
                    750: METHOD(child_sa_t, alloc_spi, uint32_t,
                    751:           private_child_sa_t *this, protocol_id_t protocol)
                    752: {
                    753:        if (charon->kernel->get_spi(charon->kernel, this->other_addr, this->my_addr,
                    754:                                                        proto_ike2ip(protocol), &this->my_spi) == SUCCESS)
                    755:        {
                    756:                /* if we allocate a SPI, but then are unable to establish the SA, we
                    757:                 * need to know the protocol family to delete the partial SA */
                    758:                this->protocol = protocol;
                    759:                return this->my_spi;
                    760:        }
                    761:        return 0;
                    762: }
                    763: 
                    764: METHOD(child_sa_t, alloc_cpi, uint16_t,
                    765:           private_child_sa_t *this)
                    766: {
                    767:        if (charon->kernel->get_cpi(charon->kernel, this->other_addr, this->my_addr,
                    768:                                                                &this->my_cpi) == SUCCESS)
                    769:        {
                    770:                return this->my_cpi;
                    771:        }
                    772:        return 0;
                    773: }
                    774: 
                    775: /**
                    776:  * Install the given SA in the kernel
                    777:  */
                    778: static status_t install_internal(private_child_sa_t *this, chunk_t encr,
                    779:        chunk_t integ, uint32_t spi, uint16_t cpi, bool initiator, bool inbound,
                    780:        bool tfcv3)
                    781: {
                    782:        uint16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
                    783:        uint16_t esn = NO_EXT_SEQ_NUMBERS;
                    784:        linked_list_t *my_ts, *other_ts, *src_ts, *dst_ts;
                    785:        time_t now;
                    786:        kernel_ipsec_sa_id_t id;
                    787:        kernel_ipsec_add_sa_t sa;
                    788:        lifetime_cfg_t *lifetime;
                    789:        uint32_t tfc = 0;
                    790:        host_t *src, *dst;
                    791:        status_t status;
                    792:        bool update = FALSE;
                    793: 
                    794:        /* BEET requires the bound address from the traffic selectors */
                    795:        my_ts = linked_list_create_from_enumerator(
                    796:                                                                        array_create_enumerator(this->my_ts));
                    797:        other_ts = linked_list_create_from_enumerator(
                    798:                                                                        array_create_enumerator(this->other_ts));
                    799: 
                    800:        /* now we have to decide which spi to use. Use self allocated, if "in",
                    801:         * or the one in the proposal, if not "in" (others). Additionally,
                    802:         * source and dest host switch depending on the role */
                    803:        if (inbound)
                    804:        {
                    805:                dst = this->my_addr;
                    806:                src = this->other_addr;
                    807:                if (this->my_spi == spi)
                    808:                {       /* alloc_spi has been called, do an SA update */
                    809:                        update = TRUE;
                    810:                }
                    811:                this->my_spi = spi;
                    812:                this->my_cpi = cpi;
                    813:                dst_ts = my_ts;
                    814:                src_ts = other_ts;
1.1.1.2 ! misho     815:                this->inbound_installed = TRUE;
1.1       misho     816:        }
                    817:        else
                    818:        {
                    819:                src = this->my_addr;
                    820:                dst = this->other_addr;
                    821:                this->other_spi = spi;
                    822:                this->other_cpi = cpi;
                    823:                src_ts = my_ts;
                    824:                dst_ts = other_ts;
                    825: 
                    826:                if (tfcv3)
                    827:                {
                    828:                        tfc = this->config->get_tfc(this->config);
                    829:                }
                    830:                this->outbound_state |= CHILD_OUTBOUND_SA;
                    831:        }
                    832: 
                    833:        DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
                    834:                 protocol_id_names, this->protocol);
                    835: 
                    836:        /* send SA down to the kernel */
                    837:        DBG2(DBG_CHD, "  SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
                    838: 
                    839:        this->proposal->get_algorithm(this->proposal, ENCRYPTION_ALGORITHM,
                    840:                                                                  &enc_alg, &size);
                    841:        this->proposal->get_algorithm(this->proposal, INTEGRITY_ALGORITHM,
                    842:                                                                  &int_alg, &size);
                    843:        this->proposal->get_algorithm(this->proposal, EXTENDED_SEQUENCE_NUMBERS,
                    844:                                                                  &esn, NULL);
                    845: 
                    846:        if (int_alg == AUTH_HMAC_SHA2_256_128 &&
                    847:                this->config->has_option(this->config, OPT_SHA256_96))
                    848:        {
                    849:                DBG2(DBG_CHD, "  using %N with 96-bit truncation",
                    850:                         integrity_algorithm_names, int_alg);
                    851:                int_alg = AUTH_HMAC_SHA2_256_96;
                    852:        }
                    853: 
                    854:        if (!this->reqid_allocated && !this->static_reqid)
                    855:        {
                    856:                status = charon->kernel->alloc_reqid(charon->kernel, my_ts, other_ts,
                    857:                                                                this->mark_in, this->mark_out, this->if_id_in,
                    858:                                                                this->if_id_out, &this->reqid);
                    859:                if (status != SUCCESS)
                    860:                {
                    861:                        my_ts->destroy(my_ts);
                    862:                        other_ts->destroy(other_ts);
                    863:                        return status;
                    864:                }
                    865:                this->reqid_allocated = TRUE;
                    866:        }
                    867: 
                    868:        lifetime = this->config->get_lifetime(this->config, TRUE);
                    869: 
                    870:        now = time_monotonic(NULL);
                    871:        if (lifetime->time.rekey)
                    872:        {
                    873:                if (this->rekey_time)
                    874:                {
                    875:                        this->rekey_time = min(this->rekey_time, now + lifetime->time.rekey);
                    876:                }
                    877:                else
                    878:                {
                    879:                        this->rekey_time = now + lifetime->time.rekey;
                    880:                }
                    881:        }
                    882:        if (lifetime->time.life)
                    883:        {
                    884:                this->expire_time = now + lifetime->time.life;
                    885:        }
                    886: 
                    887:        if (!lifetime->time.jitter && !inbound)
                    888:        {       /* avoid triggering multiple rekey events */
                    889:                lifetime->time.rekey = 0;
                    890:        }
                    891: 
                    892:        id = (kernel_ipsec_sa_id_t){
                    893:                .src = src,
                    894:                .dst = dst,
                    895:                .spi = spi,
                    896:                .proto = proto_ike2ip(this->protocol),
                    897:                .mark = inbound ? mark_in_sa(this) : this->mark_out,
                    898:                .if_id = inbound ? this->if_id_in : this->if_id_out,
                    899:        };
                    900:        sa = (kernel_ipsec_add_sa_t){
                    901:                .reqid = this->reqid,
                    902:                .mode = this->mode,
                    903:                .src_ts = src_ts,
                    904:                .dst_ts = dst_ts,
                    905:                .interface = inbound ? NULL : this->config->get_interface(this->config),
                    906:                .lifetime = lifetime,
                    907:                .enc_alg = enc_alg,
                    908:                .enc_key = encr,
                    909:                .int_alg = int_alg,
                    910:                .int_key = integ,
                    911:                .replay_window = this->config->get_replay_window(this->config),
                    912:                .tfc = tfc,
                    913:                .ipcomp = this->ipcomp,
                    914:                .cpi = cpi,
                    915:                .encap = this->encap,
                    916:                .hw_offload = this->config->get_hw_offload(this->config),
                    917:                .mark = this->config->get_set_mark(this->config, inbound),
                    918:                .esn = esn,
                    919:                .copy_df = !this->config->has_option(this->config, OPT_NO_COPY_DF),
                    920:                .copy_ecn = !this->config->has_option(this->config, OPT_NO_COPY_ECN),
                    921:                .copy_dscp = this->config->get_copy_dscp(this->config),
                    922:                .initiator = initiator,
                    923:                .inbound = inbound,
                    924:                .update = update,
                    925:        };
                    926: 
                    927:        if (sa.mark.value == MARK_SAME)
                    928:        {
                    929:                sa.mark.value = inbound ? this->mark_in.value : this->mark_out.value;
                    930:        }
                    931: 
                    932:        status = charon->kernel->add_sa(charon->kernel, &id, &sa);
                    933: 
                    934:        my_ts->destroy(my_ts);
                    935:        other_ts->destroy(other_ts);
                    936:        free(lifetime);
                    937: 
                    938:        return status;
                    939: }
                    940: 
                    941: METHOD(child_sa_t, install, status_t,
                    942:        private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
                    943:        uint16_t cpi, bool initiator, bool inbound, bool tfcv3)
                    944: {
                    945:        return install_internal(this, encr, integ, spi, cpi, initiator, inbound,
                    946:                                                        tfcv3);
                    947: }
                    948: 
                    949: /**
                    950:  * Check kernel interface if policy updates are required
                    951:  */
                    952: static bool require_policy_update()
                    953: {
                    954:        kernel_feature_t f;
                    955: 
                    956:        f = charon->kernel->get_features(charon->kernel);
                    957:        return !(f & KERNEL_NO_POLICY_UPDATES);
                    958: }
                    959: 
                    960: /**
                    961:  * Prepare SA config to install/delete policies
                    962:  */
                    963: static void prepare_sa_cfg(private_child_sa_t *this, ipsec_sa_cfg_t *my_sa,
                    964:                                                   ipsec_sa_cfg_t *other_sa)
                    965: {
                    966:        enumerator_t *enumerator;
                    967: 
                    968:        *my_sa = (ipsec_sa_cfg_t){
                    969:                .mode = this->mode,
                    970:                .reqid = this->reqid,
                    971:                .ipcomp = {
                    972:                        .transform = this->ipcomp,
                    973:                },
                    974:        };
                    975:        *other_sa = *my_sa;
                    976: 
                    977:        my_sa->ipcomp.cpi = this->my_cpi;
                    978:        other_sa->ipcomp.cpi = this->other_cpi;
                    979: 
                    980:        if (this->protocol == PROTO_ESP)
                    981:        {
                    982:                my_sa->esp.use = TRUE;
                    983:                my_sa->esp.spi = this->my_spi;
                    984:                other_sa->esp.use = TRUE;
                    985:                other_sa->esp.spi = this->other_spi;
                    986:        }
                    987:        else
                    988:        {
                    989:                my_sa->ah.use = TRUE;
                    990:                my_sa->ah.spi = this->my_spi;
                    991:                other_sa->ah.use = TRUE;
                    992:                other_sa->ah.spi = this->other_spi;
                    993:        }
                    994: 
                    995:        enumerator = create_policy_enumerator(this);
                    996:        while (enumerator->enumerate(enumerator, NULL, NULL))
                    997:        {
                    998:                my_sa->policy_count++;
                    999:                other_sa->policy_count++;
                   1000:        }
                   1001:        enumerator->destroy(enumerator);
                   1002: }
                   1003: 
                   1004: /**
                   1005:  * Install inbound policies: in, fwd
                   1006:  */
                   1007: static status_t install_policies_inbound(private_child_sa_t *this,
                   1008:        host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
                   1009:        traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
                   1010:        ipsec_sa_cfg_t *other_sa, policy_type_t type,
                   1011:        policy_priority_t priority,     uint32_t manual_prio)
                   1012: {
                   1013:        kernel_ipsec_policy_id_t in_id = {
                   1014:                .dir = POLICY_IN,
                   1015:                .src_ts = other_ts,
                   1016:                .dst_ts = my_ts,
                   1017:                .mark = this->mark_in,
                   1018:                .if_id = this->if_id_in,
                   1019:        };
                   1020:        kernel_ipsec_manage_policy_t in_policy = {
                   1021:                .type = type,
                   1022:                .prio = priority,
                   1023:                .manual_prio = manual_prio,
                   1024:                .src = other_addr,
                   1025:                .dst = my_addr,
                   1026:                .sa = my_sa,
                   1027:        };
                   1028:        status_t status = SUCCESS;
                   1029: 
                   1030:        status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
                   1031:        if (this->mode != MODE_TRANSPORT)
                   1032:        {
                   1033:                in_id.dir = POLICY_FWD;
                   1034:                status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
                   1035:        }
                   1036:        return status;
                   1037: }
                   1038: 
                   1039: /**
                   1040:  * Install outbound policies: out, [fwd]
                   1041:  */
                   1042: static status_t install_policies_outbound(private_child_sa_t *this,
                   1043:        host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
                   1044:        traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
                   1045:        ipsec_sa_cfg_t *other_sa, policy_type_t type,
                   1046:        policy_priority_t priority,     uint32_t manual_prio)
                   1047: {
                   1048:        kernel_ipsec_policy_id_t out_id = {
                   1049:                .dir = POLICY_OUT,
                   1050:                .src_ts = my_ts,
                   1051:                .dst_ts = other_ts,
                   1052:                .mark = this->mark_out,
                   1053:                .if_id = this->if_id_out,
                   1054:                .interface = this->config->get_interface(this->config),
                   1055:        };
                   1056:        kernel_ipsec_manage_policy_t out_policy = {
                   1057:                .type = type,
                   1058:                .prio = priority,
                   1059:                .manual_prio = manual_prio,
                   1060:                .src = my_addr,
                   1061:                .dst = other_addr,
                   1062:                .sa = other_sa,
                   1063:        };
                   1064:        status_t status = SUCCESS;
                   1065: 
                   1066:        status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
                   1067: 
                   1068:        if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
                   1069:        {
                   1070:                /* install an "outbound" FWD policy in case there is a drop policy
                   1071:                 * matching outbound forwarded traffic, to allow another tunnel to use
                   1072:                 * the reversed subnets and do the same we don't set a reqid (this also
                   1073:                 * allows the kernel backend to distinguish between the two types of
                   1074:                 * FWD policies). To avoid problems with symmetrically overlapping
                   1075:                 * policies of two SAs we install them with reduced priority.  As they
                   1076:                 * basically act as bypass policies for drop policies we use a higher
                   1077:                 * priority than is used for them. */
                   1078:                out_id.dir = POLICY_FWD;
                   1079:                other_sa->reqid = 0;
                   1080:                if (priority == POLICY_PRIORITY_DEFAULT)
                   1081:                {
                   1082:                        out_policy.prio = POLICY_PRIORITY_ROUTED;
                   1083:                }
                   1084:                status |= charon->kernel->add_policy(charon->kernel, &out_id,
                   1085:                                                                                         &out_policy);
                   1086:                /* reset the reqid for any other further policies */
                   1087:                other_sa->reqid = this->reqid;
                   1088:        }
                   1089:        return status;
                   1090: }
                   1091: 
                   1092: /**
                   1093:  * Install all policies
                   1094:  */
                   1095: static status_t install_policies_internal(private_child_sa_t *this,
                   1096:        host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
                   1097:        traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
                   1098:        ipsec_sa_cfg_t *other_sa, policy_type_t type,
                   1099:        policy_priority_t priority,     uint32_t manual_prio, bool outbound)
                   1100: {
                   1101:        status_t status = SUCCESS;
                   1102: 
                   1103:        status |= install_policies_inbound(this, my_addr, other_addr, my_ts,
                   1104:                                                other_ts, my_sa, other_sa, type, priority, manual_prio);
                   1105:        if (outbound)
                   1106:        {
                   1107:                status |= install_policies_outbound(this, my_addr, other_addr, my_ts,
                   1108:                                                other_ts, my_sa, other_sa, type, priority, manual_prio);
                   1109:        }
                   1110:        return status;
                   1111: }
                   1112: 
                   1113: /**
                   1114:  * Delete inbound policies: in, fwd
                   1115:  */
                   1116: static void del_policies_inbound(private_child_sa_t *this,
                   1117:        host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
                   1118:        traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
                   1119:        ipsec_sa_cfg_t *other_sa, policy_type_t type,
                   1120:        policy_priority_t priority, uint32_t manual_prio)
                   1121: {
                   1122:        kernel_ipsec_policy_id_t in_id = {
                   1123:                .dir = POLICY_IN,
                   1124:                .src_ts = other_ts,
                   1125:                .dst_ts = my_ts,
                   1126:                .mark = this->mark_in,
                   1127:                .if_id = this->if_id_in,
                   1128:        };
                   1129:        kernel_ipsec_manage_policy_t in_policy = {
                   1130:                .type = type,
                   1131:                .prio = priority,
                   1132:                .manual_prio = manual_prio,
                   1133:                .src = other_addr,
                   1134:                .dst = my_addr,
                   1135:                .sa = my_sa,
                   1136:        };
                   1137: 
                   1138:        charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
                   1139: 
                   1140:        if (this->mode != MODE_TRANSPORT)
                   1141:        {
                   1142:                in_id.dir = POLICY_FWD;
                   1143:                charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
                   1144:        }
                   1145: }
                   1146: 
                   1147: /**
                   1148:  * Delete outbound policies: out, [fwd]
                   1149:  */
                   1150: static void del_policies_outbound(private_child_sa_t *this,
                   1151:        host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
                   1152:        traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
                   1153:        ipsec_sa_cfg_t *other_sa, policy_type_t type,
                   1154:        policy_priority_t priority, uint32_t manual_prio)
                   1155: {
                   1156:        kernel_ipsec_policy_id_t out_id = {
                   1157:                .dir = POLICY_OUT,
                   1158:                .src_ts = my_ts,
                   1159:                .dst_ts = other_ts,
                   1160:                .mark = this->mark_out,
                   1161:                .if_id = this->if_id_out,
                   1162:                .interface = this->config->get_interface(this->config),
                   1163:        };
                   1164:        kernel_ipsec_manage_policy_t out_policy = {
                   1165:                .type = type,
                   1166:                .prio = priority,
                   1167:                .manual_prio = manual_prio,
                   1168:                .src = my_addr,
                   1169:                .dst = other_addr,
                   1170:                .sa = other_sa,
                   1171:        };
                   1172: 
                   1173:        charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
                   1174: 
                   1175:        if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
                   1176:        {
                   1177:                out_id.dir = POLICY_FWD;
                   1178:                other_sa->reqid = 0;
                   1179:                if (priority == POLICY_PRIORITY_DEFAULT)
                   1180:                {
                   1181:                        out_policy.prio = POLICY_PRIORITY_ROUTED;
                   1182:                }
                   1183:                charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
                   1184:                other_sa->reqid = this->reqid;
                   1185:        }
                   1186: }
                   1187: 
                   1188: /**
                   1189:  * Delete in- and outbound policies
                   1190:  */
                   1191: static void del_policies_internal(private_child_sa_t *this,
                   1192:        host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
                   1193:        traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
                   1194:        ipsec_sa_cfg_t *other_sa, policy_type_t type,
                   1195:        policy_priority_t priority, uint32_t manual_prio, bool outbound)
                   1196: {
                   1197:        if (outbound)
                   1198:        {
                   1199:                del_policies_outbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
                   1200:                                                other_sa, type, priority, manual_prio);
                   1201:        }
                   1202:        del_policies_inbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
                   1203:                                                other_sa, type, priority, manual_prio);
                   1204: }
                   1205: 
                   1206: METHOD(child_sa_t, set_policies, void,
                   1207:           private_child_sa_t *this, linked_list_t *my_ts_list,
                   1208:           linked_list_t *other_ts_list)
                   1209: {
                   1210:        enumerator_t *enumerator;
                   1211:        traffic_selector_t *my_ts, *other_ts;
                   1212: 
                   1213:        if (array_count(this->my_ts))
                   1214:        {
                   1215:                array_destroy_offset(this->my_ts,
                   1216:                                                         offsetof(traffic_selector_t, destroy));
                   1217:                this->my_ts = array_create(0, 0);
                   1218:        }
                   1219:        enumerator = my_ts_list->create_enumerator(my_ts_list);
                   1220:        while (enumerator->enumerate(enumerator, &my_ts))
                   1221:        {
                   1222:                array_insert(this->my_ts, ARRAY_TAIL, my_ts->clone(my_ts));
                   1223:        }
                   1224:        enumerator->destroy(enumerator);
                   1225:        array_sort(this->my_ts, (void*)traffic_selector_cmp, NULL);
                   1226: 
                   1227:        if (array_count(this->other_ts))
                   1228:        {
                   1229:                array_destroy_offset(this->other_ts,
                   1230:                                                         offsetof(traffic_selector_t, destroy));
                   1231:                this->other_ts = array_create(0, 0);
                   1232:        }
                   1233:        enumerator = other_ts_list->create_enumerator(other_ts_list);
                   1234:        while (enumerator->enumerate(enumerator, &other_ts))
                   1235:        {
                   1236:                array_insert(this->other_ts, ARRAY_TAIL, other_ts->clone(other_ts));
                   1237:        }
                   1238:        enumerator->destroy(enumerator);
                   1239:        array_sort(this->other_ts, (void*)traffic_selector_cmp, NULL);
                   1240: }
                   1241: 
                   1242: METHOD(child_sa_t, install_policies, status_t,
                   1243:           private_child_sa_t *this)
                   1244: {
                   1245:        enumerator_t *enumerator;
                   1246:        linked_list_t *my_ts_list, *other_ts_list;
                   1247:        traffic_selector_t *my_ts, *other_ts;
                   1248:        status_t status = SUCCESS;
                   1249:        bool install_outbound = FALSE;
                   1250: 
                   1251:        if (!this->reqid_allocated && !this->static_reqid)
                   1252:        {
                   1253:                my_ts_list = linked_list_create_from_enumerator(
                   1254:                                                                        array_create_enumerator(this->my_ts));
                   1255:                other_ts_list = linked_list_create_from_enumerator(
                   1256:                                                                        array_create_enumerator(this->other_ts));
                   1257:                status = charon->kernel->alloc_reqid(
                   1258:                                                        charon->kernel, my_ts_list, other_ts_list,
                   1259:                                                        this->mark_in, this->mark_out, this->if_id_in,
                   1260:                                                        this->if_id_out, &this->reqid);
                   1261:                my_ts_list->destroy(my_ts_list);
                   1262:                other_ts_list->destroy(other_ts_list);
                   1263:                if (status != SUCCESS)
                   1264:                {
                   1265:                        return status;
                   1266:                }
                   1267:                this->reqid_allocated = TRUE;
                   1268:        }
                   1269: 
                   1270:        if (!(this->outbound_state & CHILD_OUTBOUND_REGISTERED))
                   1271:        {
                   1272:                install_outbound = TRUE;
                   1273:                this->outbound_state |= CHILD_OUTBOUND_POLICIES;
                   1274:        }
                   1275: 
                   1276:        if (!this->config->has_option(this->config, OPT_NO_POLICIES))
                   1277:        {
                   1278:                policy_priority_t priority;
                   1279:                ipsec_sa_cfg_t my_sa, other_sa;
                   1280:                uint32_t manual_prio;
                   1281: 
                   1282:                prepare_sa_cfg(this, &my_sa, &other_sa);
                   1283:                manual_prio = this->config->get_manual_prio(this->config);
                   1284: 
                   1285:                /* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
                   1286:                 * entry) we install a trap policy */
                   1287:                this->trap = this->state == CHILD_CREATED;
                   1288:                priority = this->trap ? POLICY_PRIORITY_ROUTED
                   1289:                                                          : POLICY_PRIORITY_DEFAULT;
                   1290: 
                   1291:                /* enumerate pairs of traffic selectors */
                   1292:                enumerator = create_policy_enumerator(this);
                   1293:                while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
                   1294:                {
                   1295:                        status |= install_policies_internal(this, this->my_addr,
                   1296:                                                                        this->other_addr, my_ts, other_ts,
                   1297:                                                                        &my_sa, &other_sa, POLICY_IPSEC, priority,
                   1298:                                                                        manual_prio, install_outbound);
                   1299:                        if (status != SUCCESS)
                   1300:                        {
                   1301:                                break;
                   1302:                        }
                   1303:                }
                   1304:                enumerator->destroy(enumerator);
                   1305:        }
                   1306: 
                   1307:        if (status == SUCCESS && this->trap)
                   1308:        {
                   1309:                set_state(this, CHILD_ROUTED);
                   1310:        }
                   1311:        return status;
                   1312: }
                   1313: 
                   1314: METHOD(child_sa_t, register_outbound, status_t,
                   1315:        private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
                   1316:        uint16_t cpi, bool tfcv3)
                   1317: {
                   1318:        status_t status;
                   1319: 
                   1320:        /* if the kernel supports installing SPIs with policies we install the
                   1321:         * SA immediately as it will only be used once we update the policies */
                   1322:        if (charon->kernel->get_features(charon->kernel) & KERNEL_POLICY_SPI)
                   1323:        {
                   1324:                status = install_internal(this, encr, integ, spi, cpi, FALSE, FALSE,
                   1325:                                                                  tfcv3);
                   1326:        }
                   1327:        else
                   1328:        {
                   1329:                DBG2(DBG_CHD, "registering outbound %N SA", protocol_id_names,
                   1330:                         this->protocol);
                   1331:                DBG2(DBG_CHD, "  SPI 0x%.8x, src %H dst %H", ntohl(spi), this->my_addr,
                   1332:                         this->other_addr);
                   1333: 
                   1334:                this->other_spi = spi;
                   1335:                this->other_cpi = cpi;
                   1336:                this->encr_r = chunk_clone(encr);
                   1337:                this->integ_r = chunk_clone(integ);
                   1338:                this->tfcv3 = tfcv3;
                   1339:                status = SUCCESS;
                   1340:        }
                   1341:        this->outbound_state |= CHILD_OUTBOUND_REGISTERED;
                   1342:        return status;
                   1343: }
                   1344: 
                   1345: METHOD(child_sa_t, install_outbound, status_t,
                   1346:        private_child_sa_t *this)
                   1347: {
                   1348:        enumerator_t *enumerator;
                   1349:        traffic_selector_t *my_ts, *other_ts;
                   1350:        status_t status = SUCCESS;
                   1351: 
                   1352:        if (!(this->outbound_state & CHILD_OUTBOUND_SA))
                   1353:        {
                   1354:                status = install_internal(this, this->encr_r, this->integ_r,
                   1355:                                                                  this->other_spi, this->other_cpi, FALSE,
                   1356:                                                                  FALSE, this->tfcv3);
                   1357:                chunk_clear(&this->encr_r);
                   1358:                chunk_clear(&this->integ_r);
                   1359:        }
                   1360:        this->outbound_state &= ~CHILD_OUTBOUND_REGISTERED;
                   1361:        if (status != SUCCESS)
                   1362:        {
                   1363:                return status;
                   1364:        }
                   1365:        if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
                   1366:                !(this->outbound_state & CHILD_OUTBOUND_POLICIES))
                   1367:        {
                   1368:                ipsec_sa_cfg_t my_sa, other_sa;
                   1369:                uint32_t manual_prio;
                   1370: 
                   1371:                prepare_sa_cfg(this, &my_sa, &other_sa);
                   1372:                manual_prio = this->config->get_manual_prio(this->config);
                   1373: 
                   1374:                enumerator = create_policy_enumerator(this);
                   1375:                while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
                   1376:                {
                   1377:                        status |= install_policies_outbound(this, this->my_addr,
                   1378:                                                                        this->other_addr, my_ts, other_ts,
                   1379:                                                                        &my_sa, &other_sa, POLICY_IPSEC,
                   1380:                                                                        POLICY_PRIORITY_DEFAULT, manual_prio);
                   1381:                        if (status != SUCCESS)
                   1382:                        {
                   1383:                                break;
                   1384:                        }
                   1385:                }
                   1386:                enumerator->destroy(enumerator);
                   1387:        }
                   1388:        this->outbound_state |= CHILD_OUTBOUND_POLICIES;
                   1389:        return status;
                   1390: }
                   1391: 
                   1392: METHOD(child_sa_t, remove_outbound, void,
                   1393:        private_child_sa_t *this)
                   1394: {
                   1395:        enumerator_t *enumerator;
                   1396:        traffic_selector_t *my_ts, *other_ts;
                   1397: 
                   1398:        if (!(this->outbound_state & CHILD_OUTBOUND_SA))
                   1399:        {
                   1400:                if (this->outbound_state & CHILD_OUTBOUND_REGISTERED)
                   1401:                {
                   1402:                        chunk_clear(&this->encr_r);
                   1403:                        chunk_clear(&this->integ_r);
                   1404:                        this->outbound_state = CHILD_OUTBOUND_NONE;
                   1405:                }
                   1406:                return;
                   1407:        }
                   1408: 
                   1409:        if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
                   1410:                (this->outbound_state & CHILD_OUTBOUND_POLICIES))
                   1411:        {
                   1412:                ipsec_sa_cfg_t my_sa, other_sa;
                   1413:                uint32_t manual_prio;
                   1414: 
                   1415:                prepare_sa_cfg(this, &my_sa, &other_sa);
                   1416:                manual_prio = this->config->get_manual_prio(this->config);
                   1417: 
                   1418:                enumerator = create_policy_enumerator(this);
                   1419:                while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
                   1420:                {
                   1421:                        del_policies_outbound(this, this->my_addr, this->other_addr,
                   1422:                                                                  my_ts, other_ts, &my_sa, &other_sa,
                   1423:                                                                  POLICY_IPSEC, POLICY_PRIORITY_DEFAULT,
                   1424:                                                                  manual_prio);
                   1425:                }
                   1426:                enumerator->destroy(enumerator);
                   1427:        }
                   1428: 
                   1429:        kernel_ipsec_sa_id_t id = {
                   1430:                .src = this->my_addr,
                   1431:                .dst = this->other_addr,
                   1432:                .spi = this->other_spi,
                   1433:                .proto = proto_ike2ip(this->protocol),
                   1434:                .mark = this->mark_out,
                   1435:                .if_id = this->if_id_out,
                   1436:        };
                   1437:        kernel_ipsec_del_sa_t sa = {
                   1438:                .cpi = this->other_cpi,
                   1439:        };
                   1440:        charon->kernel->del_sa(charon->kernel, &id, &sa);
                   1441:        this->outbound_state = CHILD_OUTBOUND_NONE;
                   1442: }
                   1443: 
                   1444: METHOD(child_sa_t, set_rekey_spi, void,
                   1445:        private_child_sa_t *this, uint32_t spi)
                   1446: {
                   1447:        this->rekey_spi = spi;
                   1448: }
                   1449: 
                   1450: METHOD(child_sa_t, get_rekey_spi, uint32_t,
                   1451:        private_child_sa_t *this)
                   1452: {
                   1453:        return this->rekey_spi;
                   1454: }
                   1455: 
                   1456: CALLBACK(reinstall_vip, void,
                   1457:        host_t *vip, va_list args)
                   1458: {
                   1459:        host_t *me;
                   1460:        char *iface;
                   1461: 
                   1462:        VA_ARGS_VGET(args, me);
                   1463:        if (charon->kernel->get_interface(charon->kernel, me, &iface))
                   1464:        {
                   1465:                charon->kernel->del_ip(charon->kernel, vip, -1, TRUE);
                   1466:                charon->kernel->add_ip(charon->kernel, vip, -1, iface);
                   1467:                free(iface);
                   1468:        }
                   1469: }
                   1470: 
                   1471: /**
                   1472:  * Update addresses and encap state of IPsec SAs in the kernel
                   1473:  */
                   1474: static status_t update_sas(private_child_sa_t *this, host_t *me, host_t *other,
                   1475:                                                   bool encap)
                   1476: {
                   1477:        /* update our (initiator) SA */
1.1.1.2 ! misho    1478:        if (this->my_spi && this->inbound_installed)
1.1       misho    1479:        {
                   1480:                kernel_ipsec_sa_id_t id = {
                   1481:                        .src = this->other_addr,
                   1482:                        .dst = this->my_addr,
                   1483:                        .spi = this->my_spi,
                   1484:                        .proto = proto_ike2ip(this->protocol),
                   1485:                        .mark = mark_in_sa(this),
                   1486:                        .if_id = this->if_id_in,
                   1487:                };
                   1488:                kernel_ipsec_update_sa_t sa = {
                   1489:                        .cpi = this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
                   1490:                        .new_src = other,
                   1491:                        .new_dst = me,
                   1492:                        .encap = this->encap,
                   1493:                        .new_encap = encap,
                   1494:                };
                   1495:                if (charon->kernel->update_sa(charon->kernel, &id,
                   1496:                                                                          &sa) == NOT_SUPPORTED)
                   1497:                {
                   1498:                        return NOT_SUPPORTED;
                   1499:                }
                   1500:        }
                   1501: 
                   1502:        /* update his (responder) SA */
                   1503:        if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
                   1504:        {
                   1505:                kernel_ipsec_sa_id_t id = {
                   1506:                        .src = this->my_addr,
                   1507:                        .dst = this->other_addr,
                   1508:                        .spi = this->other_spi,
                   1509:                        .proto = proto_ike2ip(this->protocol),
                   1510:                        .mark = this->mark_out,
                   1511:                        .if_id = this->if_id_out,
                   1512:                };
                   1513:                kernel_ipsec_update_sa_t sa = {
                   1514:                        .cpi = this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
                   1515:                        .new_src = me,
                   1516:                        .new_dst = other,
                   1517:                        .encap = this->encap,
                   1518:                        .new_encap = encap,
                   1519:                };
                   1520:                if (charon->kernel->update_sa(charon->kernel, &id,
                   1521:                                                                          &sa) == NOT_SUPPORTED)
                   1522:                {
                   1523:                        return NOT_SUPPORTED;
                   1524:                }
                   1525:        }
                   1526:        /* we currently ignore the actual return values above */
                   1527:        return SUCCESS;
                   1528: }
                   1529: 
                   1530: METHOD(child_sa_t, update, status_t,
                   1531:        private_child_sa_t *this, host_t *me, host_t *other, linked_list_t *vips,
                   1532:        bool encap)
                   1533: {
                   1534:        child_sa_state_t old;
                   1535:        bool transport_proxy_mode;
                   1536: 
                   1537:        /* anything changed at all? */
                   1538:        if (me->equals(me, this->my_addr) &&
                   1539:                other->equals(other, this->other_addr) && this->encap == encap)
                   1540:        {
                   1541:                return SUCCESS;
                   1542:        }
                   1543: 
                   1544:        old = this->state;
                   1545:        set_state(this, CHILD_UPDATING);
                   1546:        transport_proxy_mode = this->mode == MODE_TRANSPORT &&
                   1547:                                                   this->config->has_option(this->config,
                   1548:                                                                                                        OPT_PROXY_MODE);
                   1549: 
                   1550:        if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
1.1.1.2 ! misho    1551:                require_policy_update() && array_count(this->my_ts) &&
        !          1552:                array_count(this->other_ts))
1.1       misho    1553:        {
                   1554:                ipsec_sa_cfg_t my_sa, other_sa;
                   1555:                enumerator_t *enumerator;
                   1556:                traffic_selector_t *my_ts, *other_ts;
                   1557:                uint32_t manual_prio;
                   1558:                status_t state;
                   1559:                bool outbound;
                   1560: 
                   1561:                prepare_sa_cfg(this, &my_sa, &other_sa);
                   1562:                manual_prio = this->config->get_manual_prio(this->config);
                   1563:                outbound = (this->outbound_state & CHILD_OUTBOUND_POLICIES);
                   1564: 
                   1565:                enumerator = create_policy_enumerator(this);
                   1566:                while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
                   1567:                {
                   1568:                        /* install drop policy to avoid traffic leaks, acquires etc. */
                   1569:                        if (outbound)
                   1570:                        {
                   1571:                                install_policies_outbound(this, this->my_addr, this->other_addr,
                   1572:                                                        my_ts, other_ts, &my_sa, &other_sa, POLICY_DROP,
                   1573:                                                        POLICY_PRIORITY_DEFAULT, manual_prio);
                   1574:                        }
                   1575:                        /* remove old policies */
                   1576:                        del_policies_internal(this, this->my_addr, this->other_addr,
                   1577:                                                my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC,
                   1578:                                                POLICY_PRIORITY_DEFAULT, manual_prio, outbound);
                   1579:                }
                   1580:                enumerator->destroy(enumerator);
                   1581: 
                   1582:                /* update the IPsec SAs */
                   1583:                state = update_sas(this, me, other, encap);
                   1584: 
                   1585:                enumerator = create_policy_enumerator(this);
                   1586:                while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
                   1587:                {
                   1588:                        traffic_selector_t *old_my_ts = NULL, *old_other_ts = NULL;
                   1589: 
                   1590:                        /* reinstall the previous policies if we can't update the SAs */
                   1591:                        if (state == NOT_SUPPORTED)
                   1592:                        {
                   1593:                                install_policies_internal(this, this->my_addr, this->other_addr,
                   1594:                                                my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC,
                   1595:                                                POLICY_PRIORITY_DEFAULT, manual_prio, outbound);
                   1596:                        }
                   1597:                        else
                   1598:                        {
                   1599:                                /* check if we have to update a "dynamic" traffic selector */
                   1600:                                if (!me->ip_equals(me, this->my_addr) &&
                   1601:                                        my_ts->is_host(my_ts, this->my_addr))
                   1602:                                {
                   1603:                                        old_my_ts = my_ts->clone(my_ts);
                   1604:                                        my_ts->set_address(my_ts, me);
                   1605:                                }
                   1606:                                if (!other->ip_equals(other, this->other_addr) &&
                   1607:                                        other_ts->is_host(other_ts, this->other_addr))
                   1608:                                {
                   1609:                                        old_other_ts = other_ts->clone(other_ts);
                   1610:                                        other_ts->set_address(other_ts, other);
                   1611:                                }
                   1612: 
                   1613:                                /* we reinstall the virtual IP to handle interface roaming
                   1614:                                 * correctly */
1.1.1.2 ! misho    1615:                                if (vips)
        !          1616:                                {
        !          1617:                                        vips->invoke_function(vips, reinstall_vip, me);
        !          1618:                                }
1.1       misho    1619: 
                   1620:                                /* reinstall updated policies */
                   1621:                                install_policies_internal(this, me, other, my_ts, other_ts,
                   1622:                                                &my_sa, &other_sa, POLICY_IPSEC,
                   1623:                                                POLICY_PRIORITY_DEFAULT, manual_prio, outbound);
                   1624:                        }
                   1625:                        /* remove the drop policy */
                   1626:                        if (outbound)
                   1627:                        {
                   1628:                                del_policies_outbound(this, this->my_addr, this->other_addr,
                   1629:                                                old_my_ts ?: my_ts, old_other_ts ?: other_ts,
                   1630:                                                &my_sa, &other_sa, POLICY_DROP,
                   1631:                                                POLICY_PRIORITY_DEFAULT, manual_prio);
                   1632:                        }
                   1633: 
                   1634:                        DESTROY_IF(old_my_ts);
                   1635:                        DESTROY_IF(old_other_ts);
                   1636:                }
                   1637:                enumerator->destroy(enumerator);
                   1638: 
                   1639:                if (state == NOT_SUPPORTED)
                   1640:                {
                   1641:                        set_state(this, old);
                   1642:                        return NOT_SUPPORTED;
                   1643:                }
                   1644: 
                   1645:        }
                   1646:        else if (!transport_proxy_mode)
                   1647:        {
                   1648:                if (update_sas(this, me, other, encap) == NOT_SUPPORTED)
                   1649:                {
                   1650:                        set_state(this, old);
                   1651:                        return NOT_SUPPORTED;
                   1652:                }
                   1653:        }
                   1654: 
                   1655:        if (!transport_proxy_mode)
                   1656:        {
                   1657:                /* apply hosts */
                   1658:                if (!me->equals(me, this->my_addr))
                   1659:                {
                   1660:                        this->my_addr->destroy(this->my_addr);
                   1661:                        this->my_addr = me->clone(me);
                   1662:                }
                   1663:                if (!other->equals(other, this->other_addr))
                   1664:                {
                   1665:                        this->other_addr->destroy(this->other_addr);
                   1666:                        this->other_addr = other->clone(other);
                   1667:                }
                   1668:        }
                   1669: 
                   1670:        this->encap = encap;
                   1671:        set_state(this, old);
                   1672: 
                   1673:        return SUCCESS;
                   1674: }
                   1675: 
                   1676: METHOD(child_sa_t, destroy, void,
                   1677:           private_child_sa_t *this)
                   1678: {
                   1679:        enumerator_t *enumerator;
                   1680:        traffic_selector_t *my_ts, *other_ts;
                   1681:        policy_priority_t priority;
                   1682: 
                   1683:        priority = this->trap ? POLICY_PRIORITY_ROUTED : POLICY_PRIORITY_DEFAULT;
                   1684: 
                   1685:        set_state(this, CHILD_DESTROYING);
                   1686: 
                   1687:        if (!this->config->has_option(this->config, OPT_NO_POLICIES))
                   1688:        {
                   1689:                ipsec_sa_cfg_t my_sa, other_sa;
                   1690:                uint32_t manual_prio;
                   1691:                bool del_outbound;
                   1692: 
                   1693:                prepare_sa_cfg(this, &my_sa, &other_sa);
                   1694:                manual_prio = this->config->get_manual_prio(this->config);
                   1695:                del_outbound = (this->outbound_state & CHILD_OUTBOUND_POLICIES) ||
                   1696:                                                this->trap;
                   1697: 
                   1698:                /* delete all policies in the kernel */
                   1699:                enumerator = create_policy_enumerator(this);
                   1700:                while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
                   1701:                {
                   1702:                        del_policies_internal(this, this->my_addr,
                   1703:                                                this->other_addr, my_ts, other_ts, &my_sa, &other_sa,
                   1704:                                                POLICY_IPSEC, priority, manual_prio, del_outbound);
                   1705:                }
                   1706:                enumerator->destroy(enumerator);
                   1707:        }
                   1708: 
1.1.1.2 ! misho    1709:        /* delete SAs in the kernel, if they are set up, inbound is always deleted
        !          1710:         * to remove allocated SPIs */
1.1       misho    1711:        if (this->my_spi)
                   1712:        {
                   1713:                kernel_ipsec_sa_id_t id = {
                   1714:                        .src = this->other_addr,
                   1715:                        .dst = this->my_addr,
                   1716:                        .spi = this->my_spi,
                   1717:                        .proto = proto_ike2ip(this->protocol),
                   1718:                        .mark = mark_in_sa(this),
                   1719:                        .if_id = this->if_id_in,
                   1720:                };
                   1721:                kernel_ipsec_del_sa_t sa = {
                   1722:                        .cpi = this->my_cpi,
                   1723:                };
                   1724:                charon->kernel->del_sa(charon->kernel, &id, &sa);
                   1725:        }
                   1726:        if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
                   1727:        {
                   1728:                kernel_ipsec_sa_id_t id = {
                   1729:                        .src = this->my_addr,
                   1730:                        .dst = this->other_addr,
                   1731:                        .spi = this->other_spi,
                   1732:                        .proto = proto_ike2ip(this->protocol),
                   1733:                        .mark = this->mark_out,
                   1734:                        .if_id = this->if_id_out,
                   1735:                };
                   1736:                kernel_ipsec_del_sa_t sa = {
                   1737:                        .cpi = this->other_cpi,
                   1738:                };
                   1739:                charon->kernel->del_sa(charon->kernel, &id, &sa);
                   1740:        }
                   1741: 
                   1742:        if (this->reqid_allocated)
                   1743:        {
                   1744:                if (charon->kernel->release_reqid(charon->kernel,
                   1745:                                                this->reqid, this->mark_in, this->mark_out,
                   1746:                                                this->if_id_in, this->if_id_out) != SUCCESS)
                   1747:                {
                   1748:                        DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid);
                   1749:                }
                   1750:        }
                   1751: 
                   1752:        array_destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
                   1753:        array_destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
                   1754:        this->my_addr->destroy(this->my_addr);
                   1755:        this->other_addr->destroy(this->other_addr);
                   1756:        DESTROY_IF(this->proposal);
                   1757:        this->config->destroy(this->config);
                   1758:        chunk_clear(&this->encr_r);
                   1759:        chunk_clear(&this->integ_r);
                   1760:        free(this);
                   1761: }
                   1762: 
                   1763: /**
                   1764:  * Get proxy address for one side, if any
                   1765:  */
                   1766: static host_t* get_proxy_addr(child_cfg_t *config, host_t *ike, bool local)
                   1767: {
                   1768:        host_t *host = NULL;
                   1769:        uint8_t mask;
                   1770:        enumerator_t *enumerator;
                   1771:        linked_list_t *ts_list, *list;
                   1772:        traffic_selector_t *ts;
                   1773: 
                   1774:        list = linked_list_create_with_items(ike, NULL);
                   1775:        ts_list = config->get_traffic_selectors(config, local, NULL, list, FALSE);
                   1776:        list->destroy(list);
                   1777: 
                   1778:        enumerator = ts_list->create_enumerator(ts_list);
                   1779:        while (enumerator->enumerate(enumerator, &ts))
                   1780:        {
                   1781:                if (ts->is_host(ts, NULL) && ts->to_subnet(ts, &host, &mask))
                   1782:                {
                   1783:                        DBG1(DBG_CHD, "%s address: %H is a transport mode proxy for %H",
                   1784:                                 local ? "my" : "other", ike, host);
                   1785:                        break;
                   1786:                }
                   1787:        }
                   1788:        enumerator->destroy(enumerator);
                   1789:        ts_list->destroy_offset(ts_list, offsetof(traffic_selector_t, destroy));
                   1790: 
                   1791:        if (!host)
                   1792:        {
                   1793:                host = ike->clone(ike);
                   1794:        }
                   1795:        return host;
                   1796: }
                   1797: 
                   1798: /*
                   1799:  * Described in header
                   1800:  */
                   1801: child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
                   1802:                                                        child_sa_create_t *data)
                   1803: {
                   1804:        private_child_sa_t *this;
                   1805:        static refcount_t unique_id = 0, unique_mark = 0;
                   1806: 
                   1807:        INIT(this,
                   1808:                .public = {
                   1809:                        .get_name = _get_name,
                   1810:                        .get_reqid = _get_reqid,
                   1811:                        .get_unique_id = _get_unique_id,
                   1812:                        .get_config = _get_config,
                   1813:                        .get_state = _get_state,
                   1814:                        .set_state = _set_state,
                   1815:                        .get_outbound_state = _get_outbound_state,
                   1816:                        .get_spi = _get_spi,
                   1817:                        .get_cpi = _get_cpi,
                   1818:                        .get_protocol = _get_protocol,
                   1819:                        .set_protocol = _set_protocol,
                   1820:                        .get_mode = _get_mode,
                   1821:                        .set_mode = _set_mode,
                   1822:                        .get_proposal = _get_proposal,
                   1823:                        .set_proposal = _set_proposal,
                   1824:                        .get_lifetime = _get_lifetime,
                   1825:                        .get_installtime = _get_installtime,
                   1826:                        .get_usestats = _get_usestats,
                   1827:                        .get_mark = _get_mark,
                   1828:                        .get_if_id = _get_if_id,
                   1829:                        .has_encap = _has_encap,
                   1830:                        .get_ipcomp = _get_ipcomp,
                   1831:                        .set_ipcomp = _set_ipcomp,
                   1832:                        .get_close_action = _get_close_action,
                   1833:                        .set_close_action = _set_close_action,
                   1834:                        .get_dpd_action = _get_dpd_action,
                   1835:                        .set_dpd_action = _set_dpd_action,
                   1836:                        .alloc_spi = _alloc_spi,
                   1837:                        .alloc_cpi = _alloc_cpi,
                   1838:                        .install = _install,
                   1839:                        .register_outbound = _register_outbound,
                   1840:                        .install_outbound = _install_outbound,
                   1841:                        .remove_outbound = _remove_outbound,
                   1842:                        .set_rekey_spi = _set_rekey_spi,
                   1843:                        .get_rekey_spi = _get_rekey_spi,
                   1844:                        .update = _update,
                   1845:                        .set_policies = _set_policies,
                   1846:                        .install_policies = _install_policies,
                   1847:                        .create_ts_enumerator = _create_ts_enumerator,
                   1848:                        .create_policy_enumerator = _create_policy_enumerator,
                   1849:                        .destroy = _destroy,
                   1850:                },
                   1851:                .encap = data->encap,
                   1852:                .ipcomp = IPCOMP_NONE,
                   1853:                .state = CHILD_CREATED,
                   1854:                .my_ts = array_create(0, 0),
                   1855:                .other_ts = array_create(0, 0),
                   1856:                .protocol = PROTO_NONE,
                   1857:                .mode = MODE_TUNNEL,
                   1858:                .close_action = config->get_close_action(config),
                   1859:                .dpd_action = config->get_dpd_action(config),
                   1860:                .reqid = config->get_reqid(config),
                   1861:                .unique_id = ref_get(&unique_id),
                   1862:                .mark_in = config->get_mark(config, TRUE),
                   1863:                .mark_out = config->get_mark(config, FALSE),
                   1864:                .if_id_in = config->get_if_id(config, TRUE) ?: data->if_id_in_def,
                   1865:                .if_id_out = config->get_if_id(config, FALSE) ?: data->if_id_out_def,
                   1866:                .install_time = time_monotonic(NULL),
                   1867:                .policies_fwd_out = config->has_option(config, OPT_FWD_OUT_POLICIES),
                   1868:        );
                   1869: 
                   1870:        this->config = config;
                   1871:        config->get_ref(config);
                   1872: 
                   1873:        if (data->mark_in)
                   1874:        {
                   1875:                this->mark_in.value = data->mark_in;
                   1876:        }
                   1877:        if (data->mark_out)
                   1878:        {
                   1879:                this->mark_out.value = data->mark_out;
                   1880:        }
                   1881:        if (data->if_id_in)
                   1882:        {
                   1883:                this->if_id_in = data->if_id_in;
                   1884:        }
                   1885:        if (data->if_id_out)
                   1886:        {
                   1887:                this->if_id_out = data->if_id_out;
                   1888:        }
                   1889: 
                   1890:        allocate_unique_if_ids(&this->if_id_in, &this->if_id_out);
                   1891: 
                   1892:        if (MARK_IS_UNIQUE(this->mark_in.value) ||
                   1893:                MARK_IS_UNIQUE(this->mark_out.value))
                   1894:        {
                   1895:                refcount_t mark = 0;
                   1896:                bool unique_dir = this->mark_in.value == MARK_UNIQUE_DIR ||
                   1897:                                                  this->mark_out.value == MARK_UNIQUE_DIR;
                   1898: 
                   1899:                if (!unique_dir)
                   1900:                {
                   1901:                        mark = ref_get(&unique_mark);
                   1902:                }
                   1903:                if (MARK_IS_UNIQUE(this->mark_in.value))
                   1904:                {
                   1905:                        this->mark_in.value = unique_dir ? ref_get(&unique_mark) : mark;
                   1906:                }
                   1907:                if (MARK_IS_UNIQUE(this->mark_out.value))
                   1908:                {
                   1909:                        this->mark_out.value = unique_dir ? ref_get(&unique_mark) : mark;
                   1910:                }
                   1911:        }
                   1912: 
                   1913:        if (!this->reqid)
                   1914:        {
                   1915:                /* reuse old reqid if we are rekeying an existing CHILD_SA and when
                   1916:                 * initiating a trap policy. While the reqid cache would find the same
                   1917:                 * reqid for our selectors, this does not work in a special case: If an
                   1918:                 * SA is triggered by a trap policy, but the negotiated TS get
                   1919:                 * narrowed, we still must reuse the same reqid to successfully
                   1920:                 * replace the temporary SA on the kernel level. Rekeying such an SA
                   1921:                 * requires an explicit reqid, as the cache currently knows the original
                   1922:                 * selectors only for that reqid. */
                   1923:                this->reqid = data->reqid;
                   1924:        }
                   1925:        else
                   1926:        {
                   1927:                this->static_reqid = TRUE;
                   1928:        }
                   1929: 
                   1930:        /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
                   1931:        if (config->get_mode(config) == MODE_TRANSPORT &&
                   1932:                config->has_option(config, OPT_PROXY_MODE))
                   1933:        {
                   1934:                this->mode = MODE_TRANSPORT;
                   1935: 
                   1936:                this->my_addr = get_proxy_addr(config, me, TRUE);
                   1937:                this->other_addr = get_proxy_addr(config, other, FALSE);
                   1938:        }
                   1939:        else
                   1940:        {
                   1941:                this->my_addr = me->clone(me);
                   1942:                this->other_addr = other->clone(other);
                   1943:        }
                   1944:        return &this->public;
                   1945: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>