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

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

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