summaryrefslogtreecommitdiff
path: root/src/charon/sa/child_sa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa/child_sa.c')
-rw-r--r--src/charon/sa/child_sa.c1015
1 files changed, 0 insertions, 1015 deletions
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
deleted file mode 100644
index 3fdfb51ad..000000000
--- a/src/charon/sa/child_sa.c
+++ /dev/null
@@ -1,1015 +0,0 @@
-/*
- * Copyright (C) 2006-2009 Tobias Brunner
- * Copyright (C) 2005-2008 Martin Willi
- * Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#define _GNU_SOURCE
-#include "child_sa.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#include <daemon.h>
-
-ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
- "CREATED",
- "ROUTED",
- "INSTALLING",
- "INSTALLED",
- "UPDATING",
- "REKEYING",
- "DELETING",
- "DESTROYING",
-);
-
-typedef struct private_child_sa_t private_child_sa_t;
-
-/**
- * Private data of a child_sa_t object.
- */
-struct private_child_sa_t {
- /**
- * Public interface of child_sa_t.
- */
- child_sa_t public;
-
- /**
- * address of us
- */
- host_t *my_addr;
-
- /**
- * address of remote
- */
- host_t *other_addr;
-
- /**
- * our actually used SPI, 0 if unused
- */
- u_int32_t my_spi;
-
- /**
- * others used SPI, 0 if unused
- */
- u_int32_t other_spi;
-
- /**
- * our Compression Parameter Index (CPI) used, 0 if unused
- */
- u_int16_t my_cpi;
-
- /**
- * others Compression Parameter Index (CPI) used, 0 if unused
- */
- u_int16_t other_cpi;
-
- /**
- * List for local traffic selectors
- */
- linked_list_t *my_ts;
-
- /**
- * List for remote traffic selectors
- */
- linked_list_t *other_ts;
-
- /**
- * Protocol used to protect this SA, ESP|AH
- */
- protocol_id_t protocol;
-
- /**
- * reqid used for this child_sa
- */
- u_int32_t reqid;
-
- /**
- * absolute time when rekeying is scheduled
- */
- time_t rekey_time;
-
- /**
- * absolute time when the SA expires
- */
- time_t expire_time;
-
- /**
- * state of the CHILD_SA
- */
- child_sa_state_t state;
-
- /**
- * Specifies if UDP encapsulation is enabled (NAT traversal)
- */
- bool encap;
-
- /**
- * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
- */
- ipcomp_transform_t ipcomp;
-
- /**
- * mode this SA uses, tunnel/transport
- */
- ipsec_mode_t mode;
-
- /**
- * selected proposal
- */
- proposal_t *proposal;
-
- /**
- * config used to create this child
- */
- child_cfg_t *config;
-
- /**
- * time of last use in seconds (inbound)
- */
- u_int32_t my_usetime;
-
- /**
- * time of last use in seconds (outbound)
- */
- u_int32_t other_usetime;
-
- /**
- * last number of inbound bytes
- */
- u_int64_t my_usebytes;
-
- /**
- * last number of outbound bytes
- */
- u_int64_t other_usebytes;
-};
-
-/**
- * Implementation of child_sa_t.get_name
- */
-static char *get_name(private_child_sa_t *this)
-{
- return this->config->get_name(this->config);
-}
-
-/**
- * Implements child_sa_t.get_reqid
- */
-static u_int32_t get_reqid(private_child_sa_t *this)
-{
- return this->reqid;
-}
-
-/**
- * Implements child_sa_t.get_config
- */
-static child_cfg_t* get_config(private_child_sa_t *this)
-{
- return this->config;
-}
-
-/**
- * Implements child_sa_t.set_state
- */
-static void set_state(private_child_sa_t *this, child_sa_state_t state)
-{
- charon->bus->child_state_change(charon->bus, &this->public, state);
- this->state = state;
-}
-
-/**
- * Implements child_sa_t.get_state
- */
-static child_sa_state_t get_state(private_child_sa_t *this)
-{
- return this->state;
-}
-
-/**
- * Implements child_sa_t.get_spi
- */
-u_int32_t get_spi(private_child_sa_t *this, bool inbound)
-{
- return inbound ? this->my_spi : this->other_spi;
-}
-
-/**
- * Implements child_sa_t.get_cpi
- */
-u_int16_t get_cpi(private_child_sa_t *this, bool inbound)
-{
- return inbound ? this->my_cpi : this->other_cpi;
-}
-
-/**
- * Implements child_sa_t.get_protocol
- */
-protocol_id_t get_protocol(private_child_sa_t *this)
-{
- return this->protocol;
-}
-
-/**
- * Implementation of child_sa_t.set_protocol
- */
-static void set_protocol(private_child_sa_t *this, protocol_id_t protocol)
-{
- this->protocol = protocol;
-}
-
-/**
- * Implementation of child_sa_t.get_mode
- */
-static ipsec_mode_t get_mode(private_child_sa_t *this)
-{
- return this->mode;
-}
-
-/**
- * Implementation of child_sa_t.set_mode
- */
-static void set_mode(private_child_sa_t *this, ipsec_mode_t mode)
-{
- this->mode = mode;
-}
-
-/**
- * Implementation of child_sa_t.has_encap
- */
-static bool has_encap(private_child_sa_t *this)
-{
- return this->encap;
-}
-
-/**
- * Implementation of child_sa_t.get_ipcomp
- */
-static ipcomp_transform_t get_ipcomp(private_child_sa_t *this)
-{
- return this->ipcomp;
-}
-
-/**
- * Implementation of child_sa_t.set_ipcomp.
- */
-static void set_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp)
-{
- this->ipcomp = ipcomp;
-}
-
-/**
- * Implementation of child_sa_t.get_proposal
- */
-static proposal_t* get_proposal(private_child_sa_t *this)
-{
- return this->proposal;
-}
-
-/**
- * Implementation of child_sa_t.set_proposal
- */
-static void set_proposal(private_child_sa_t *this, proposal_t *proposal)
-{
- this->proposal = proposal->clone(proposal);
-}
-
-/**
- * Implementation of child_sa_t.get_traffic_selectors.
- */
-static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local)
-{
- return local ? this->my_ts : this->other_ts;
-}
-
-typedef struct policy_enumerator_t policy_enumerator_t;
-
-/**
- * Private policy enumerator
- */
-struct policy_enumerator_t {
- /** implements enumerator_t */
- enumerator_t public;
- /** enumerator over own TS */
- enumerator_t *mine;
- /** enumerator over others TS */
- enumerator_t *other;
- /** list of others TS, to recreate enumerator */
- linked_list_t *list;
- /** currently enumerating TS for "me" side */
- traffic_selector_t *ts;
-};
-
-/**
- * enumerator function of create_policy_enumerator()
- */
-static bool policy_enumerate(policy_enumerator_t *this,
- traffic_selector_t **my_out, traffic_selector_t **other_out)
-{
- traffic_selector_t *other_ts;
-
- while (this->ts || this->mine->enumerate(this->mine, &this->ts))
- {
- if (!this->other->enumerate(this->other, &other_ts))
- { /* end of others list, restart with new of mine */
- this->other->destroy(this->other);
- this->other = this->list->create_enumerator(this->list);
- this->ts = NULL;
- continue;
- }
- if (this->ts->get_type(this->ts) != other_ts->get_type(other_ts))
- { /* family mismatch */
- continue;
- }
- if (this->ts->get_protocol(this->ts) &&
- other_ts->get_protocol(other_ts) &&
- this->ts->get_protocol(this->ts) != other_ts->get_protocol(other_ts))
- { /* protocol mismatch */
- continue;
- }
- *my_out = this->ts;
- *other_out = other_ts;
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * destroy function of create_policy_enumerator()
- */
-static void policy_destroy(policy_enumerator_t *this)
-{
- this->mine->destroy(this->mine);
- this->other->destroy(this->other);
- free(this);
-}
-
-/**
- * Implementation of child_sa_t.create_policy_enumerator
- */
-static enumerator_t* create_policy_enumerator(private_child_sa_t *this)
-{
- policy_enumerator_t *e = malloc_thing(policy_enumerator_t);
-
- e->public.enumerate = (void*)policy_enumerate;
- e->public.destroy = (void*)policy_destroy;
- e->mine = this->my_ts->create_enumerator(this->my_ts);
- e->other = this->other_ts->create_enumerator(this->other_ts);
- e->list = this->other_ts;
- e->ts = NULL;
-
- return &e->public;
-}
-
-/**
- * update the cached usebytes
- * returns SUCCESS if the usebytes have changed, FAILED if not or no SPIs
- * are available, and NOT_SUPPORTED if the kernel interface does not support
- * querying the usebytes.
- */
-static status_t update_usebytes(private_child_sa_t *this, bool inbound)
-{
- status_t status = FAILED;
- u_int64_t bytes;
-
- if (inbound)
- {
- if (this->my_spi)
- {
- status = charon->kernel_interface->query_sa(
- charon->kernel_interface,
- this->other_addr, this->my_addr,
- this->my_spi, this->protocol, &bytes);
- if (status == SUCCESS)
- {
- if (bytes > this->my_usebytes)
- {
- this->my_usebytes = bytes;
- return SUCCESS;
- }
- return FAILED;
- }
- }
- }
- else
- {
- if (this->other_spi)
- {
- status = charon->kernel_interface->query_sa(
- charon->kernel_interface,
- this->my_addr, this->other_addr,
- this->other_spi, this->protocol, &bytes);
- if (status == SUCCESS)
- {
- if (bytes > this->other_usebytes)
- {
- this->other_usebytes = bytes;
- return SUCCESS;
- }
- return FAILED;
- }
- }
- }
- return status;
-}
-
-/**
- * updates the cached usetime
- */
-static void update_usetime(private_child_sa_t *this, bool inbound)
-{
- enumerator_t *enumerator;
- traffic_selector_t *my_ts, *other_ts;
- u_int32_t last_use = 0;
-
- enumerator = create_policy_enumerator(this);
- while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
- {
- u_int32_t in, out, fwd;
-
- if (inbound)
- {
- if (charon->kernel_interface->query_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, &in) == SUCCESS)
- {
- last_use = max(last_use, in);
- }
- if (this->mode != MODE_TRANSPORT)
- {
- if (charon->kernel_interface->query_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, &fwd) == SUCCESS)
- {
- last_use = max(last_use, fwd);
- }
- }
- }
- else
- {
- if (charon->kernel_interface->query_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, &out) == SUCCESS)
- {
- last_use = max(last_use, out);
- }
- }
- }
- enumerator->destroy(enumerator);
-
- if (last_use == 0)
- {
- return;
- }
- if (inbound)
- {
- this->my_usetime = last_use;
- }
- else
- {
- this->other_usetime = last_use;
- }
-}
-
-/**
- * Implementation of child_sa_t.get_usestats
- */
-static void get_usestats(private_child_sa_t *this, bool inbound,
- time_t *time, u_int64_t *bytes)
-{
- if (update_usebytes(this, inbound) != FAILED)
- {
- /* there was traffic since last update or the kernel interface
- * does not support querying the number of usebytes.
- */
- update_usetime(this, inbound);
- }
- if (time)
- {
- *time = inbound ? this->my_usetime : this->other_usetime;
- }
- if (bytes)
- {
- *bytes = inbound ? this->my_usebytes : this->other_usebytes;
- }
-}
-
-/**
- * Implementation of child_sa_t.get_lifetime
- */
-static time_t get_lifetime(private_child_sa_t *this, bool hard)
-{
- return hard ? this->expire_time : this->rekey_time;
-}
-
-/**
- * Implementation of child_sa_t.alloc_spi
- */
-static u_int32_t alloc_spi(private_child_sa_t *this, protocol_id_t protocol)
-{
- if (charon->kernel_interface->get_spi(charon->kernel_interface,
- this->other_addr, this->my_addr, protocol,
- this->reqid, &this->my_spi) == SUCCESS)
- {
- return this->my_spi;
- }
- return 0;
-}
-
-/**
- * Implementation of child_sa_t.alloc_cpi
- */
-static u_int16_t alloc_cpi(private_child_sa_t *this)
-{
- if (charon->kernel_interface->get_cpi(charon->kernel_interface,
- this->other_addr, this->my_addr, this->reqid,
- &this->my_cpi) == SUCCESS)
- {
- return this->my_cpi;
- }
- return 0;
-}
-
-/**
- * Implementation of child_sa_t.install
- */
-static status_t install(private_child_sa_t *this, chunk_t encr, chunk_t integ,
- u_int32_t spi, u_int16_t cpi, bool inbound,
- linked_list_t *my_ts, linked_list_t *other_ts)
-{
- u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
- traffic_selector_t *src_ts = NULL, *dst_ts = NULL;
- time_t now;
- lifetime_cfg_t *lifetime;
- host_t *src, *dst;
- status_t status;
- bool update = FALSE;
-
- /* now we have to decide which spi to use. Use self allocated, if "in",
- * or the one in the proposal, if not "in" (others). Additionally,
- * source and dest host switch depending on the role */
- if (inbound)
- {
- dst = this->my_addr;
- src = this->other_addr;
- if (this->my_spi == spi)
- { /* alloc_spi has been called, do an SA update */
- update = TRUE;
- }
- this->my_spi = spi;
- this->my_cpi = cpi;
- }
- else
- {
- src = this->my_addr;
- dst = this->other_addr;
- this->other_spi = spi;
- this->other_cpi = cpi;
- }
-
- DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
- protocol_id_names, this->protocol);
-
- /* send SA down to the kernel */
- DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
-
- this->proposal->get_algorithm(this->proposal, ENCRYPTION_ALGORITHM,
- &enc_alg, &size);
- this->proposal->get_algorithm(this->proposal, INTEGRITY_ALGORITHM,
- &int_alg, &size);
-
- lifetime = this->config->get_lifetime(this->config);
-
- now = time_monotonic(NULL);
- if (lifetime->time.rekey)
- {
- this->rekey_time = now + lifetime->time.rekey;
- }
- if (lifetime->time.life)
- {
- this->expire_time = now + lifetime->time.life;
- }
-
- if (!lifetime->time.jitter && !inbound)
- { /* avoid triggering multiple rekey events */
- lifetime->time.rekey = 0;
- }
-
- if (this->mode == MODE_BEET)
- {
- /* BEET requires the bound address from the traffic selectors.
- * TODO: We add just the first traffic selector for now, as the
- * kernel accepts a single TS per SA only */
- if (inbound)
- {
- my_ts->get_first(my_ts, (void**)&dst_ts);
- other_ts->get_first(other_ts, (void**)&src_ts);
- }
- else
- {
- my_ts->get_first(my_ts, (void**)&src_ts);
- other_ts->get_first(other_ts, (void**)&dst_ts);
- }
- }
-
- status = charon->kernel_interface->add_sa(charon->kernel_interface,
- src, dst, spi, this->protocol, this->reqid, lifetime,
- enc_alg, encr, int_alg, integ, this->mode, this->ipcomp, cpi,
- this->encap, update, src_ts, dst_ts);
-
- free(lifetime);
-
- return status;
-}
-
-/**
- * Implementation of child_sa_t.add_policies
- */
-static status_t add_policies(private_child_sa_t *this,
- linked_list_t *my_ts_list, linked_list_t *other_ts_list)
-{
- enumerator_t *enumerator;
- traffic_selector_t *my_ts, *other_ts;
- status_t status = SUCCESS;
- bool routed = (this->state == CHILD_CREATED);
-
- /* apply traffic selectors */
- enumerator = my_ts_list->create_enumerator(my_ts_list);
- while (enumerator->enumerate(enumerator, &my_ts))
- {
- this->my_ts->insert_last(this->my_ts, my_ts->clone(my_ts));
- }
- enumerator->destroy(enumerator);
- enumerator = other_ts_list->create_enumerator(other_ts_list);
- while (enumerator->enumerate(enumerator, &other_ts))
- {
- this->other_ts->insert_last(this->other_ts, other_ts->clone(other_ts));
- }
- enumerator->destroy(enumerator);
-
- if (this->config->install_policy(this->config))
- {
- /* enumerate pairs of traffic selectors */
- enumerator = create_policy_enumerator(this);
- while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
- {
- /* install 3 policies: out, in and forward */
- status |= charon->kernel_interface->add_policy(charon->kernel_interface,
- this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
- this->other_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->other_cpi, routed);
-
- status |= charon->kernel_interface->add_policy(charon->kernel_interface,
- this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
- this->my_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->my_cpi, routed);
- if (this->mode != MODE_TRANSPORT)
- {
- status |= charon->kernel_interface->add_policy(charon->kernel_interface,
- this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
- this->my_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->my_cpi, routed);
- }
-
- if (status != SUCCESS)
- {
- break;
- }
- }
- enumerator->destroy(enumerator);
- }
-
- if (status == SUCCESS && this->state == CHILD_CREATED)
- { /* switch to routed state if no SAD entry set up */
- set_state(this, CHILD_ROUTED);
- }
- return status;
-}
-
-/**
- * Implementation of child_sa_t.update.
- */
-static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
- host_t *vip, bool encap)
-{
- child_sa_state_t old;
- bool transport_proxy_mode;
-
- /* anything changed at all? */
- if (me->equals(me, this->my_addr) &&
- other->equals(other, this->other_addr) && this->encap == encap)
- {
- return SUCCESS;
- }
-
- old = this->state;
- set_state(this, CHILD_UPDATING);
- transport_proxy_mode = this->config->use_proxy_mode(this->config) &&
- this->mode == MODE_TRANSPORT;
-
- if (!transport_proxy_mode)
- {
- /* update our (initator) SA */
- if (this->my_spi)
- {
- if (charon->kernel_interface->update_sa(charon->kernel_interface,
- this->my_spi, this->protocol,
- this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
- this->other_addr, this->my_addr, other, me,
- this->encap, encap) == NOT_SUPPORTED)
- {
- return NOT_SUPPORTED;
- }
- }
-
- /* update his (responder) SA */
- if (this->other_spi)
- {
- if (charon->kernel_interface->update_sa(charon->kernel_interface,
- this->other_spi, this->protocol,
- this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
- this->my_addr, this->other_addr, me, other,
- this->encap, encap) == NOT_SUPPORTED)
- {
- return NOT_SUPPORTED;
- }
- }
- }
-
- if (this->config->install_policy(this->config))
- {
- /* update policies */
- if (!me->ip_equals(me, this->my_addr) ||
- !other->ip_equals(other, this->other_addr))
- {
- enumerator_t *enumerator;
- traffic_selector_t *my_ts, *other_ts;
-
- /* always use high priorities, as hosts getting updated are INSTALLED */
- enumerator = create_policy_enumerator(this);
- while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
- {
- /* remove old policies first */
- charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, FALSE);
- charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, FALSE);
- if (this->mode != MODE_TRANSPORT)
- {
- charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, FALSE);
- }
-
- /* check whether we have to update a "dynamic" traffic selector */
- if (!me->ip_equals(me, this->my_addr) &&
- my_ts->is_host(my_ts, this->my_addr))
- {
- my_ts->set_address(my_ts, me);
- }
- if (!other->ip_equals(other, this->other_addr) &&
- other_ts->is_host(other_ts, this->other_addr))
- {
- other_ts->set_address(other_ts, other);
- }
-
- /* we reinstall the virtual IP to handle interface roaming
- * correctly */
- if (vip)
- {
- charon->kernel_interface->del_ip(charon->kernel_interface, vip);
- charon->kernel_interface->add_ip(charon->kernel_interface, vip, me);
- }
-
- /* reinstall updated policies */
- charon->kernel_interface->add_policy(charon->kernel_interface,
- me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->other_cpi, FALSE);
- charon->kernel_interface->add_policy(charon->kernel_interface,
- other, me, other_ts, my_ts, POLICY_IN, this->my_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->my_cpi, FALSE);
- if (this->mode != MODE_TRANSPORT)
- {
- charon->kernel_interface->add_policy(charon->kernel_interface,
- other, me, other_ts, my_ts, POLICY_FWD, this->my_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->my_cpi, FALSE);
- }
- }
- enumerator->destroy(enumerator);
- }
- }
-
- if (!transport_proxy_mode)
- {
- /* apply hosts */
- if (!me->equals(me, this->my_addr))
- {
- this->my_addr->destroy(this->my_addr);
- this->my_addr = me->clone(me);
- }
- if (!other->equals(other, this->other_addr))
- {
- this->other_addr->destroy(this->other_addr);
- this->other_addr = other->clone(other);
- }
- }
-
- this->encap = encap;
- set_state(this, old);
-
- return SUCCESS;
-}
-
-/**
- * Implementation of child_sa_t.destroy.
- */
-static void destroy(private_child_sa_t *this)
-{
- enumerator_t *enumerator;
- traffic_selector_t *my_ts, *other_ts;
- bool unrouted = (this->state == CHILD_ROUTED);
-
- set_state(this, CHILD_DESTROYING);
-
- /* delete SAs in the kernel, if they are set up */
- if (this->my_spi)
- {
- /* if CHILD was not established, use PROTO_ESP used during alloc_spi().
- * TODO: For AH support, we have to store protocol specific SPI.s */
- if (this->protocol == PROTO_NONE)
- {
- this->protocol = PROTO_ESP;
- }
- charon->kernel_interface->del_sa(charon->kernel_interface,
- this->other_addr, this->my_addr, this->my_spi,
- this->protocol, this->my_cpi);
- }
- if (this->other_spi)
- {
- charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, this->other_addr, this->other_spi,
- this->protocol, this->other_cpi);
- }
-
- if (this->config->install_policy(this->config))
- {
- /* delete all policies in the kernel */
- enumerator = create_policy_enumerator(this);
- while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
- {
- charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, unrouted);
- charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, unrouted);
- if (this->mode != MODE_TRANSPORT)
- {
- charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, unrouted);
- }
- }
- enumerator->destroy(enumerator);
- }
-
- this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
- this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
- this->my_addr->destroy(this->my_addr);
- this->other_addr->destroy(this->other_addr);
- DESTROY_IF(this->proposal);
- this->config->destroy(this->config);
- free(this);
-}
-
-/*
- * Described in header.
- */
-child_sa_t * child_sa_create(host_t *me, host_t* other,
- child_cfg_t *config, u_int32_t rekey, bool encap)
-{
- static u_int32_t reqid = 0;
- private_child_sa_t *this = malloc_thing(private_child_sa_t);
-
- /* public functions */
- this->public.get_name = (char*(*)(child_sa_t*))get_name;
- this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid;
- this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
- this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
- this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
- this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi;
- this->public.get_cpi = (u_int16_t(*)(child_sa_t*, bool))get_cpi;
- this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol;
- this->public.set_protocol = (void(*)(child_sa_t*, protocol_id_t protocol))set_protocol;
- this->public.get_mode = (ipsec_mode_t(*)(child_sa_t*))get_mode;
- this->public.set_mode = (void(*)(child_sa_t*, ipsec_mode_t mode))set_mode;
- this->public.get_proposal = (proposal_t*(*)(child_sa_t*))get_proposal;
- this->public.set_proposal = (void(*)(child_sa_t*, proposal_t *proposal))set_proposal;
- this->public.get_lifetime = (time_t(*)(child_sa_t*, bool))get_lifetime;
- this->public.get_usestats = (void(*)(child_sa_t*,bool,time_t*,u_int64_t*))get_usestats;
- this->public.has_encap = (bool(*)(child_sa_t*))has_encap;
- this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp;
- this->public.set_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t))set_ipcomp;
- this->public.alloc_spi = (u_int32_t(*)(child_sa_t*, protocol_id_t protocol))alloc_spi;
- this->public.alloc_cpi = (u_int16_t(*)(child_sa_t*))alloc_cpi;
- this->public.install = (status_t(*)(child_sa_t*, chunk_t encr, chunk_t integ, u_int32_t spi, u_int16_t cpi, bool inbound, linked_list_t *my_ts_list, linked_list_t *other_ts_list))install;
- this->public.update = (status_t (*)(child_sa_t*,host_t*,host_t*,host_t*,bool))update;
- this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
- this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
- this->public.create_policy_enumerator = (enumerator_t*(*)(child_sa_t*))create_policy_enumerator;
- this->public.destroy = (void(*)(child_sa_t*))destroy;
-
- /* private data */
- this->my_addr = me->clone(me);
- this->other_addr = other->clone(other);
- this->my_spi = 0;
- this->other_spi = 0;
- this->my_cpi = 0;
- this->other_cpi = 0;
- this->encap = encap;
- this->ipcomp = IPCOMP_NONE;
- this->state = CHILD_CREATED;
- this->my_usetime = 0;
- this->other_usetime = 0;
- this->my_usebytes = 0;
- this->other_usebytes = 0;
- /* reuse old reqid if we are rekeying an existing CHILD_SA */
- this->reqid = rekey ? rekey : ++reqid;
- this->my_ts = linked_list_create();
- this->other_ts = linked_list_create();
- this->protocol = PROTO_NONE;
- this->mode = MODE_TUNNEL;
- this->proposal = NULL;
- this->rekey_time = 0;
- this->expire_time = 0;
- this->config = config;
- config->get_ref(config);
-
- /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
- if (config->get_mode(config) == MODE_TRANSPORT &&
- config->use_proxy_mode(config))
- {
- ts_type_t type;
- int family;
- chunk_t addr;
- host_t *host;
- enumerator_t *enumerator;
- linked_list_t *my_ts_list, *other_ts_list;
- traffic_selector_t *my_ts, *other_ts;
-
- this->mode = MODE_TRANSPORT;
-
- my_ts_list = config->get_traffic_selectors(config, TRUE, NULL, me);
- enumerator = my_ts_list->create_enumerator(my_ts_list);
- if (enumerator->enumerate(enumerator, &my_ts))
- {
- if (my_ts->is_host(my_ts, NULL) &&
- !my_ts->is_host(my_ts, this->my_addr))
- {
- type = my_ts->get_type(my_ts);
- family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
- addr = my_ts->get_from_address(my_ts);
- host = host_create_from_chunk(family, addr, 0);
- free(addr.ptr);
- DBG1(DBG_CHD, "my address: %H is a transport mode proxy for %H",
- this->my_addr, host);
- this->my_addr->destroy(this->my_addr);
- this->my_addr = host;
- }
- }
- enumerator->destroy(enumerator);
- my_ts_list->destroy_offset(my_ts_list, offsetof(traffic_selector_t, destroy));
-
- other_ts_list = config->get_traffic_selectors(config, FALSE, NULL, other);
- enumerator = other_ts_list->create_enumerator(other_ts_list);
- if (enumerator->enumerate(enumerator, &other_ts))
- {
- if (other_ts->is_host(other_ts, NULL) &&
- !other_ts->is_host(other_ts, this->other_addr))
- {
- type = other_ts->get_type(other_ts);
- family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
- addr = other_ts->get_from_address(other_ts);
- host = host_create_from_chunk(family, addr, 0);
- free(addr.ptr);
- DBG1(DBG_CHD, "other address: %H is a transport mode proxy for %H",
- this->other_addr, host);
- this->other_addr->destroy(this->other_addr);
- this->other_addr = host;
- }
- }
- enumerator->destroy(enumerator);
- other_ts_list->destroy_offset(other_ts_list, offsetof(traffic_selector_t, destroy));
- }
-
- return &this->public;
-}