Merge branch 'kernel-policies'
authorAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 11 Apr 2016 08:19:21 +0000 (10:19 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 11 Apr 2016 08:19:21 +0000 (10:19 +0200)
56 files changed:
src/charon-cmd/cmd/cmd_connection.c
src/charon-nm/nm/nm_service.c
src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
src/conftest/config.c
src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_service.c
src/frontends/android/app/src/main/jni/libandroidbridge/kernel/android_ipsec.c
src/frontends/osx/charon-xpc/xpc_dispatch.c
src/libcharon/config/child_cfg.c
src/libcharon/config/child_cfg.h
src/libcharon/config/peer_cfg.c
src/libcharon/config/peer_cfg.h
src/libcharon/kernel/kernel_interface.c
src/libcharon/kernel/kernel_interface.h
src/libcharon/kernel/kernel_ipsec.h
src/libcharon/plugins/ha/ha_tunnel.c
src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
src/libcharon/plugins/load_tester/load_tester_config.c
src/libcharon/plugins/load_tester/load_tester_ipsec.c
src/libcharon/plugins/maemo/maemo_service.c
src/libcharon/plugins/medcli/medcli_config.c
src/libcharon/plugins/medsrv/medsrv_config.c
src/libcharon/plugins/sql/sql_config.c
src/libcharon/plugins/stroke/stroke_config.c
src/libcharon/plugins/uci/uci_config.c
src/libcharon/plugins/unity/unity_handler.c
src/libcharon/plugins/vici/vici_config.c
src/libcharon/plugins/vici/vici_query.c
src/libcharon/sa/child_sa.c
src/libcharon/sa/shunt_manager.c
src/swanctl/commands/list_conns.c
src/swanctl/swanctl.opt
testing/tests/swanctl/manual-prio/description.txt [new file with mode: 0755]
testing/tests/swanctl/manual-prio/evaltest.dat [new file with mode: 0755]
testing/tests/swanctl/manual-prio/hosts/carol/etc/strongswan.conf [new file with mode: 0755]
testing/tests/swanctl/manual-prio/hosts/carol/etc/swanctl/swanctl.conf [new file with mode: 0755]
testing/tests/swanctl/manual-prio/hosts/dave/etc/strongswan.conf [new file with mode: 0755]
testing/tests/swanctl/manual-prio/hosts/dave/etc/swanctl/swanctl.conf [new file with mode: 0755]
testing/tests/swanctl/manual-prio/hosts/moon/etc/strongswan.conf [new file with mode: 0755]
testing/tests/swanctl/manual-prio/hosts/moon/etc/swanctl/swanctl.conf [new file with mode: 0755]
testing/tests/swanctl/manual-prio/posttest.dat [new file with mode: 0755]
testing/tests/swanctl/manual-prio/pretest.dat [new file with mode: 0755]
testing/tests/swanctl/manual-prio/test.conf [new file with mode: 0755]
testing/tests/swanctl/net2net-gw/description.txt [new file with mode: 0755]
testing/tests/swanctl/net2net-gw/evaltest.dat [new file with mode: 0755]
testing/tests/swanctl/net2net-gw/hosts/carol/etc/strongswan.conf [new file with mode: 0755]
testing/tests/swanctl/net2net-gw/hosts/carol/etc/swanctl/swanctl.conf [new file with mode: 0755]
testing/tests/swanctl/net2net-gw/hosts/moon/etc/strongswan.conf [new file with mode: 0755]
testing/tests/swanctl/net2net-gw/hosts/moon/etc/swanctl/swanctl.conf [new file with mode: 0755]
testing/tests/swanctl/net2net-gw/hosts/sun/etc/strongswan.conf [new file with mode: 0755]
testing/tests/swanctl/net2net-gw/hosts/sun/etc/swanctl/swanctl.conf [new file with mode: 0755]
testing/tests/swanctl/net2net-gw/posttest.dat [new file with mode: 0755]
testing/tests/swanctl/net2net-gw/pretest.dat [new file with mode: 0755]
testing/tests/swanctl/net2net-gw/test.conf [new file with mode: 0755]

index 23e2b09..71df92f 100644 (file)
@@ -144,8 +144,16 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
        peer_cfg_t *peer_cfg;
        uint16_t local_port, remote_port = IKEV2_UDP_PORT;
        ike_version_t version = IKE_ANY;
-       bool aggressive = FALSE;
        proposal_t *proposal;
+       peer_cfg_create_t peer = {
+               .cert_policy = CERT_SEND_IF_ASKED,
+               .unique = UNIQUE_REPLACE,
+               .keyingtries = 1,
+               .rekey_time = 36000, /* 10h */
+               .jitter_time = 600, /* 10min */
+               .over_time = 600, /* 10min */
+               .dpd = 30,
+       };
 
        switch (this->profile)
        {
@@ -159,7 +167,7 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
                case PROF_V1_XAUTH_AM:
                case PROF_V1_XAUTH_PSK_AM:
                case PROF_V1_HYBRID_AM:
-                       aggressive = TRUE;
+                       peer.aggressive = TRUE;
                        /* FALL */
                case PROF_V1_PUB:
                case PROF_V1_XAUTH:
@@ -189,13 +197,7 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
                ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
                ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
        }
-       peer_cfg = peer_cfg_create("cmd", ike_cfg,
-                                       CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
-                                       36000, 0, /* rekey 10h, reauth none */
-                                       600, 600, /* jitter, over 10min */
-                                       TRUE, aggressive, TRUE, /* mobike, aggressive, pull */
-                                       30, 0, /* DPD delay, timeout */
-                                       FALSE, NULL, NULL); /* mediation */
+       peer_cfg = peer_cfg_create("cmd", ike_cfg, &peer);
 
        return peer_cfg;
 }
@@ -335,18 +337,18 @@ static child_cfg_t* create_child_cfg(private_cmd_connection_t *this,
        traffic_selector_t *ts;
        proposal_t *proposal;
        bool has_v4 = FALSE, has_v6 = FALSE;
-       lifetime_cfg_t lifetime = {
-               .time = {
-                       .life = 10800 /* 3h */,
-                       .rekey = 10200 /* 2h50min */,
-                       .jitter = 300 /* 5min */
-               }
+       child_cfg_create_t child = {
+               .lifetime = {
+                       .time = {
+                               .life = 10800 /* 3h */,
+                               .rekey = 10200 /* 2h50min */,
+                               .jitter = 300 /* 5min */
+                       }
+               },
+               .mode = MODE_TUNNEL,
        };
 
-       child_cfg = child_cfg_create("cmd", &lifetime,
-                                                                NULL, FALSE, MODE_TUNNEL, /* updown, hostaccess */
-                                                                ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
-                                                                0, 0, NULL, NULL, 0);
+       child_cfg = child_cfg_create("cmd", &child);
        if (this->child_proposals->get_count(this->child_proposals))
        {
                while (this->child_proposals->remove_first(this->child_proposals,
index 4cbf8d0..5991c24 100644 (file)
@@ -289,7 +289,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
        NMSettingVPN *vpn;
        identification_t *user = NULL, *gateway = NULL;
        const char *address, *str;
-       bool virtual, encap, ipcomp;
+       bool virtual, encap;
        ike_cfg_t *ike_cfg;
        peer_cfg_t *peer_cfg;
        child_cfg_t *child_cfg;
@@ -300,12 +300,23 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
        certificate_t *cert = NULL;
        x509_t *x509;
        bool agent = FALSE, smartcard = FALSE, loose_gateway_id = FALSE;
-       lifetime_cfg_t lifetime = {
-               .time = {
-                       .life = 10800 /* 3h */,
-                       .rekey = 10200 /* 2h50min */,
-                       .jitter = 300 /* 5min */
-               }
+       peer_cfg_create_t peer = {
+               .cert_policy = CERT_SEND_IF_ASKED,
+               .unique = UNIQUE_REPLACE,
+               .keyingtries = 1,
+               .rekey_time = 36000, /* 10h */
+               .jitter_time = 600, /* 10min */
+               .over_time = 600, /* 10min */
+       };
+       child_cfg_create_t child = {
+               .lifetime = {
+                       .time = {
+                               .life = 10800 /* 3h */,
+                               .rekey = 10200 /* 2h50min */,
+                               .jitter = 300 /* 5min */
+                       },
+               },
+               .mode = MODE_TUNNEL,
        };
 
        /**
@@ -339,32 +350,29 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
                return FALSE;
        }
        str = nm_setting_vpn_get_data_item(vpn, "virtual");
-       virtual = str && streq(str, "yes");
+       virtual = streq(str, "yes");
        str = nm_setting_vpn_get_data_item(vpn, "encap");
-       encap = str && streq(str, "yes");
+       encap = streq(str, "yes");
        str = nm_setting_vpn_get_data_item(vpn, "ipcomp");
-       ipcomp = str && streq(str, "yes");
+       child.ipcomp = streq(str, "yes");
        str = nm_setting_vpn_get_data_item(vpn, "method");
-       if (str)
+       if (streq(str, "psk"))
        {
-               if (streq(str, "psk"))
-               {
-                       auth_class = AUTH_CLASS_PSK;
-               }
-               else if (streq(str, "agent"))
-               {
-                       auth_class = AUTH_CLASS_PUBKEY;
-                       agent = TRUE;
-               }
-               else if (streq(str, "key"))
-               {
-                       auth_class = AUTH_CLASS_PUBKEY;
-               }
-               else if (streq(str, "smartcard"))
-               {
-                       auth_class = AUTH_CLASS_PUBKEY;
-                       smartcard = TRUE;
-               }
+               auth_class = AUTH_CLASS_PSK;
+       }
+       else if (streq(str, "agent"))
+       {
+               auth_class = AUTH_CLASS_PUBKEY;
+               agent = TRUE;
+       }
+       else if (streq(str, "key"))
+       {
+               auth_class = AUTH_CLASS_PUBKEY;
+       }
+       else if (streq(str, "smartcard"))
+       {
+               auth_class = AUTH_CLASS_PUBKEY;
+               smartcard = TRUE;
        }
 
        /**
@@ -533,13 +541,8 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
                                                         FRAGMENTATION_NO, 0);
        ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
-       peer_cfg = peer_cfg_create(priv->name, ike_cfg,
-                                       CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
-                                       36000, 0, /* rekey 10h, reauth none */
-                                       600, 600, /* jitter, over 10min */
-                                       TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
-                                       0, 0, /* DPD delay, timeout */
-                                       FALSE, NULL, NULL); /* mediation */
+
+       peer_cfg = peer_cfg_create(priv->name, ike_cfg, &peer);
        if (virtual)
        {
                peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
@@ -561,10 +564,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
        auth->add(auth, AUTH_RULE_IDENTITY_LOOSE, loose_gateway_id);
        peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
 
-       child_cfg = child_cfg_create(priv->name, &lifetime,
-                                                                NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
-                                                                ACTION_NONE, ACTION_NONE, ACTION_NONE, ipcomp,
-                                                                0, 0, NULL, NULL, 0);
+       child_cfg = child_cfg_create(priv->name, &child);
        child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
        ts = traffic_selector_create_dynamic(0, 0, 65535);
index ba2e164..c9be898 100644 (file)
@@ -81,13 +81,8 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
 }
 
 METHOD(kernel_ipsec_t, add_sa, status_t,
-       private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
-       uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
-       uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
-       uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
-       bool initiator, bool encap, bool esn, bool inbound, bool update,
-       linked_list_t* src_ts, linked_list_t* dst_ts)
+       private_tkm_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_add_sa_t *data)
 {
        esa_info_t esa;
        esp_spi_type spi_loc, spi_rem;
@@ -97,43 +92,43 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        esa_id_type esa_id;
        nonce_type nc_rem;
 
-       if (enc_key.ptr == NULL)
+       if (data->enc_key.ptr == NULL)
        {
                DBG1(DBG_KNL, "Unable to get ESA information");
                return FAILED;
        }
-       esa = *(esa_info_t *)(enc_key.ptr);
+       esa = *(esa_info_t *)(data->enc_key.ptr);
 
        /* only handle the case where we have both distinct ESP spi's available */
-       if (esa.spi_r == spi)
+       if (esa.spi_r == id->spi)
        {
                chunk_free(&esa.nonce_i);
                chunk_free(&esa.nonce_r);
                return SUCCESS;
        }
 
-       if (initiator)
+       if (data->initiator)
        {
-               spi_loc = spi;
+               spi_loc = id->spi;
                spi_rem = esa.spi_r;
-               local = dst;
-               peer = src;
+               local = id->dst;
+               peer = id->src;
                nonce_loc = &esa.nonce_i;
                nonce_rem = &esa.nonce_r;
        }
        else
        {
                spi_loc = esa.spi_r;
-               spi_rem = spi;
-               local = src;
-               peer = dst;
+               spi_rem = id->spi;
+               local = id->src;
+               peer = id->dst;
                nonce_loc = &esa.nonce_r;
                nonce_rem = &esa.nonce_i;
        }
 
        esa_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ESA);
-       if (!tkm->sad->insert(tkm->sad, esa_id, reqid, local, peer, spi_loc, spi_rem,
-                                                 protocol))
+       if (!tkm->sad->insert(tkm->sad, esa_id, data->reqid, local, peer,
+                                                 spi_loc, spi_rem, id->proto))
        {
                DBG1(DBG_KNL, "unable to add entry (%llu) to SAD", esa_id);
                goto sad_failure;
@@ -146,8 +141,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        nonce_loc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce_loc);
        if (nonce_loc_id == 0 && esa.dh_id == 0)
        {
-               if (ike_esa_create_first(esa_id, esa.isa_id, reqid, 1, spi_loc, spi_rem)
-                       != TKM_OK)
+               if (ike_esa_create_first(esa_id, esa.isa_id, data->reqid, 1, spi_loc,
+                                                                spi_rem) != TKM_OK)
                {
                        DBG1(DBG_KNL, "child SA (%llu, first) creation failed", esa_id);
                        goto failure;
@@ -157,9 +152,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        else if (nonce_loc_id != 0 && esa.dh_id == 0)
        {
                chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type));
-               if (ike_esa_create_no_pfs(esa_id, esa.isa_id, reqid, 1, nonce_loc_id,
-                                                                 nc_rem, initiator, spi_loc, spi_rem)
-                       != TKM_OK)
+               if (ike_esa_create_no_pfs(esa_id, esa.isa_id, data->reqid, 1,
+                                                                 nonce_loc_id, nc_rem, data->initiator,
+                                                                 spi_loc, spi_rem) != TKM_OK)
                {
                        DBG1(DBG_KNL, "child SA (%llu, no PFS) creation failed", esa_id);
                        goto failure;
@@ -171,8 +166,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        else
        {
                chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type));
-               if (ike_esa_create(esa_id, esa.isa_id, reqid, 1, esa.dh_id, nonce_loc_id,
-                                                  nc_rem, initiator, spi_loc, spi_rem) != TKM_OK)
+               if (ike_esa_create(esa_id, esa.isa_id, data->reqid, 1, esa.dh_id,
+                                                  nonce_loc_id, nc_rem, data->initiator, spi_loc,
+                                                  spi_rem) != TKM_OK)
                {
                        DBG1(DBG_KNL, "child SA (%llu) creation failed", esa_id);
                        goto failure;
@@ -192,7 +188,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 
        DBG1(DBG_KNL, "added child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, "
                 "esp_spi_rem: %x, role: %s)", esa_id, esa.isa_id, ntohl(spi_loc),
-                ntohl(spi_rem), initiator ? "initiator" : "responder");
+                ntohl(spi_rem), data->initiator ? "initiator" : "responder");
        chunk_free(&esa.nonce_i);
        chunk_free(&esa.nonce_r);
 
@@ -208,20 +204,21 @@ sad_failure:
 }
 
 METHOD(kernel_ipsec_t, query_sa, status_t,
-       private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, mark_t mark, uint64_t *bytes,
-       uint64_t *packets, time_t *time)
+       private_tkm_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
+       time_t *time)
 {
        return NOT_SUPPORTED;
 }
 
 METHOD(kernel_ipsec_t, del_sa, status_t,
-       private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
+       private_tkm_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_del_sa_t *data)
 {
        esa_id_type esa_id, other_esa_id;
 
-       esa_id = tkm->sad->get_esa_id(tkm->sad, src, dst, spi, protocol);
+       esa_id = tkm->sad->get_esa_id(tkm->sad, id->src, id->dst,
+                                                                 id->spi, id->proto);
        if (esa_id)
        {
                other_esa_id = tkm->sad->get_other_esa_id(tkm->sad, esa_id);
@@ -236,7 +233,7 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
                }
 
                DBG1(DBG_KNL, "deleting child SA (esa: %llu, spi: %x)", esa_id,
-                        ntohl(spi));
+                        ntohl(id->spi));
                if (ike_esa_reset(esa_id) != TKM_OK)
                {
                        DBG1(DBG_KNL, "child SA (%llu) deletion failed", esa_id);
@@ -249,9 +246,8 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
 }
 
 METHOD(kernel_ipsec_t, update_sa, status_t,
-       private_tkm_kernel_ipsec_t *this, uint32_t spi, uint8_t protocol,
-       uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-       bool old_encap, bool new_encap, mark_t mark)
+       private_tkm_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_update_sa_t *data)
 {
        return NOT_SUPPORTED;
 }
@@ -264,27 +260,22 @@ METHOD(kernel_ipsec_t, flush_sas, status_t,
 }
 
 METHOD(kernel_ipsec_t, add_policy, status_t,
-       private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t priority)
+       private_tkm_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        return SUCCESS;
 }
 
 METHOD(kernel_ipsec_t, query_policy, status_t,
-       private_tkm_kernel_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-       time_t *use_time)
+       private_tkm_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_query_policy_t *data, time_t *use_time)
 {
        return NOT_SUPPORTED;
 }
 
 METHOD(kernel_ipsec_t, del_policy, status_t,
-       private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t priority)
+       private_tkm_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        return SUCCESS;
 }
index 907bed9..06a6850 100644 (file)
@@ -139,25 +139,23 @@ static ike_cfg_t *load_ike_config(private_config_t *this,
 static child_cfg_t *load_child_config(private_config_t *this,
                                                        settings_t *settings, char *config, char *child)
 {
+       child_cfg_create_t data = {
+               .mode = MODE_TUNNEL,
+       };
        child_cfg_t *child_cfg;
-       lifetime_cfg_t lifetime = {};
        enumerator_t *enumerator;
        proposal_t *proposal;
        traffic_selector_t *ts;
-       ipsec_mode_t mode = MODE_TUNNEL;
        char *token;
-       uint32_t tfc;
 
        if (settings->get_bool(settings, "configs.%s.%s.transport",
                                                   FALSE, config, child))
        {
-               mode = MODE_TRANSPORT;
+               data.mode = MODE_TRANSPORT;
        }
-       tfc = settings->get_int(settings, "configs.%s.%s.tfc_padding",
-                                                       0, config, child);
-       child_cfg = child_cfg_create(child, &lifetime, NULL, FALSE, mode,
-                                                                ACTION_NONE, ACTION_NONE, ACTION_NONE,
-                                                                FALSE, 0, 0, NULL, NULL, tfc);
+       data.tfc = settings->get_int(settings, "configs.%s.%s.tfc_padding",
+                                                                 0, config, child);
+       child_cfg = child_cfg_create(child, &data);
 
        token = settings->get_str(settings, "configs.%s.%s.proposal",
                                                          NULL, config, child);
@@ -249,11 +247,15 @@ static peer_cfg_t *load_peer_config(private_config_t *this,
        identification_t *lid, *rid;
        char *child, *policy, *pool;
        uintptr_t strength;
+       peer_cfg_create_t peer = {
+               .cert_policy = CERT_ALWAYS_SEND,
+               .unique = UNIQUE_NO,
+               .keyingtries = 1,
+               .no_mobike = TRUE,
+       };
 
        ike_cfg = load_ike_config(this, settings, config);
-       peer_cfg = peer_cfg_create(config, ike_cfg, CERT_ALWAYS_SEND,
-                                                          UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, FALSE, TRUE,
-                                                          0, 0, FALSE, NULL, NULL);
+       peer_cfg = peer_cfg_create(config, ike_cfg, &peer);
 
        auth = auth_cfg_create();
        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
index eb3758d..b3e91d8 100644 (file)
@@ -673,12 +673,24 @@ static job_requeue_t initiate(private_android_service_t *this)
        traffic_selector_t *ts;
        ike_sa_t *ike_sa;
        auth_cfg_t *auth;
-       lifetime_cfg_t lifetime = {
-               .time = {
-                       .life = 3600, /* 1h */
-                       .rekey = 3000, /* 50min */
-                       .jitter = 300 /* 5min */
-               }
+       peer_cfg_create_t peer = {
+               .cert_policy = CERT_SEND_IF_ASKED,
+               .unique = UNIQUE_REPLACE,
+               .rekey_time = 36000, /* 10h */
+               .jitter_time = 600, /* 10min */
+               .over_time = 600, /* 10min */
+       };
+       child_cfg_create_t child = {
+               .lifetime = {
+                       .time = {
+                               .life = 3600, /* 1h */
+                               .rekey = 3000, /* 50min */
+                               .jitter = 300 /* 5min */
+                       },
+               },
+               .mode = MODE_TUNNEL,
+               .dpd_action = ACTION_RESTART,
+               .close_action = ACTION_RESTART,
        };
        char *type, *server;
        int port;
@@ -692,13 +704,7 @@ static job_requeue_t initiate(private_android_service_t *this)
        ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
 
-       peer_cfg = peer_cfg_create("android", ike_cfg, CERT_SEND_IF_ASKED,
-                                                          UNIQUE_REPLACE, 0, /* keyingtries */
-                                                          36000, 0, /* rekey 10h, reauth none */
-                                                          600, 600, /* jitter, over 10min */
-                                                          TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
-                                                          0, 0, /* DPD delay, timeout */
-                                                          FALSE, NULL, NULL); /* mediation */
+       peer_cfg = peer_cfg_create("android", ike_cfg, &peer);
        peer_cfg->add_virtual_ip(peer_cfg, host_create_any(AF_INET));
        peer_cfg->add_virtual_ip(peer_cfg, host_create_any(AF_INET6));
 
@@ -731,9 +737,7 @@ static job_requeue_t initiate(private_android_service_t *this)
        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
        peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
 
-       child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL,
-                                                                ACTION_NONE, ACTION_RESTART, ACTION_RESTART,
-                                                                FALSE, 0, 0, NULL, NULL, 0);
+       child_cfg = child_cfg_create("android", &child);
        /* create ESP proposals with and without DH groups, let responder decide
         * if PFS is used */
        child_cfg->add_proposal(child_cfg, proposal_create_from_string(PROTO_ESP,
index 33b545a..f49fc2b 100644 (file)
@@ -60,43 +60,40 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
 }
 
 METHOD(kernel_ipsec_t, add_sa, status_t,
-       private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
-       uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
-       uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
-       uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
-       bool initiator, bool encap, bool esn, bool inbound, bool update,
-       linked_list_t *src_ts, linked_list_t *dst_ts)
+       private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_add_sa_t *data)
 {
-       return ipsec->sas->add_sa(ipsec->sas, src, dst, spi, protocol, reqid, mark,
-                                                         tfc, lifetime, enc_alg, enc_key, int_alg, int_key,
-                                                         mode, ipcomp, cpi, initiator, encap, esn,
-                                                         inbound, update);
+       return ipsec->sas->add_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
+                                       data->reqid, id->mark, data->tfc, data->lifetime,
+                                       data->enc_alg, data->enc_key, data->int_alg, data->int_key,
+                                       data->mode, data->ipcomp, data->cpi, data->initiator,
+                                       data->encap, data->esn, data->inbound, data->update);
 }
 
 METHOD(kernel_ipsec_t, update_sa, status_t,
-       private_kernel_android_ipsec_t *this, uint32_t spi, uint8_t protocol,
-       uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-       bool encap, bool new_encap, mark_t mark)
+       private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_update_sa_t *data)
 {
-       return ipsec->sas->update_sa(ipsec->sas, spi, protocol, cpi, src, dst,
-                                                                new_src, new_dst, encap, new_encap, mark);
+       return ipsec->sas->update_sa(ipsec->sas, id->spi, id->proto, data->cpi,
+                                       id->src, id->dst, data->new_src, data->new_dst, data->encap,
+                                       data->new_encap, id->mark);
 }
 
 METHOD(kernel_ipsec_t, query_sa, status_t,
-       private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, mark_t mark,
-       uint64_t *bytes, uint64_t *packets, time_t *time)
+       private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
+       time_t *time)
 {
-       return ipsec->sas->query_sa(ipsec->sas, src, dst, spi, protocol, mark,
-                                                               bytes, packets, time);
+       return ipsec->sas->query_sa(ipsec->sas, id->src, id->dst, id->spi,
+                                                               id->proto, id->mark, bytes, packets, time);
 }
 
 METHOD(kernel_ipsec_t, del_sa, status_t,
-       private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
+       private_kernel_android_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_del_sa_t *data)
 {
-       return ipsec->sas->del_sa(ipsec->sas, src, dst, spi, protocol, cpi, mark);
+       return ipsec->sas->del_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
+                                                         data->cpi, id->mark);
 }
 
 METHOD(kernel_ipsec_t, flush_sas, status_t,
@@ -106,33 +103,30 @@ METHOD(kernel_ipsec_t, flush_sas, status_t,
 }
 
 METHOD(kernel_ipsec_t, add_policy, status_t,
-       private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark,
-       policy_priority_t priority)
+       private_kernel_android_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
-       return ipsec->policies->add_policy(ipsec->policies, src, dst, src_ts,
-                                                                          dst_ts, direction, type, sa, mark,
-                                                                          priority);
+       return ipsec->policies->add_policy(ipsec->policies, data->src, data->dst,
+                                                                          id->src_ts, id->dst_ts, id->dir,
+                                                                          data->type, data->sa, id->mark,
+                                                                          data->prio);
 }
 
 METHOD(kernel_ipsec_t, query_policy, status_t,
-       private_kernel_android_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-       time_t *use_time)
+       private_kernel_android_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_query_policy_t *data, time_t *use_time)
 {
        return NOT_SUPPORTED;
 }
 
 METHOD(kernel_ipsec_t, del_policy, status_t,
-       private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t priority)
+       private_kernel_android_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
-       return ipsec->policies->del_policy(ipsec->policies, src, dst, src_ts,
-                                                                          dst_ts,  direction, type, sa, mark,
-                                                                          priority);
+       return ipsec->policies->del_policy(ipsec->policies, data->src, data->dst,
+                                                                          id->src_ts, id->dst_ts, id->dir,
+                                                                          data->type, data->sa, id->mark,
+                                                                          data->prio);
 }
 
 METHOD(kernel_ipsec_t, flush_policies, status_t,
index 2e84b0e..0483199 100644 (file)
@@ -78,6 +78,15 @@ static peer_cfg_t* create_peer_cfg(char *name, char *host)
        ike_cfg_t *ike_cfg;
        peer_cfg_t *peer_cfg;
        uint16_t local_port, remote_port = IKEV2_UDP_PORT;
+       peer_cfg_create_t peer = {
+               .cert_policy = CERT_SEND_IF_ASKED,
+               .unique = UNIQUE_REPLACE,
+               .keyingtries = 1,
+               .rekey_time = 36000, /* 10h */
+               .jitter_time = 600, /* 10min */
+               .over_time = 600, /* 10min */
+               .dpd = 30,
+       };
 
        local_port = charon->socket->get_port(charon->socket, FALSE);
        if (local_port != IKEV2_UDP_PORT)
@@ -88,13 +97,7 @@ static peer_cfg_t* create_peer_cfg(char *name, char *host)
                                                         host, remote_port, FRAGMENTATION_NO, 0);
        ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
-       peer_cfg = peer_cfg_create(name, ike_cfg,
-                                                          CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
-                                                          36000, 0, /* rekey 10h, reauth none */
-                                                          600, 600, /* jitter, over 10min */
-                                                          TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
-                                                          30, 0, /* DPD delay, timeout */
-                                                          FALSE, NULL, NULL); /* mediation */
+       peer_cfg = peer_cfg_create(name, ike_cfg, &peer);
        peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
 
        return peer_cfg;
@@ -125,18 +128,18 @@ static child_cfg_t* create_child_cfg(char *name)
 {
        child_cfg_t *child_cfg;
        traffic_selector_t *ts;
-       lifetime_cfg_t lifetime = {
-               .time = {
-                       .life = 10800 /* 3h */,
-                       .rekey = 10200 /* 2h50min */,
-                       .jitter = 300 /* 5min */
-               }
+       child_cfg_create_t child = {
+               .lifetime = {
+                       .time = {
+                               .life = 10800 /* 3h */,
+                               .rekey = 10200 /* 2h50min */,
+                               .jitter = 300 /* 5min */
+                       },
+               },
+               .mode = MODE_TUNNEL,
        };
 
-       child_cfg = child_cfg_create(name, &lifetime,
-                                                                NULL, FALSE, MODE_TUNNEL, /* updown, hostaccess */
-                                                                ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
-                                                                0, 0, NULL, NULL, 0);
+       child_cfg = child_cfg_create(name, &child);
        child_cfg->add_proposal(child_cfg, proposal_create_from_string(PROTO_ESP,
                                                                                "aes128gcm8-aes128gcm12-aes128gcm16-"
                                                                                "aes256gcm8-aes256gcm12-aes256gcm16"));
index 8e5c522..be84621 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * Copyright (C) 2008-2015 Tobias Brunner
+ * Copyright (C) 2016 Andreas Steffen
+ * Copyright (C) 2008-2016 Tobias Brunner
  * Copyright (C) 2005-2007 Martin Willi
  * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR 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
@@ -133,6 +134,16 @@ struct private_child_cfg_t {
        uint32_t tfc;
 
        /**
+        * Optional manually-set IPsec policy priorities
+        */
+       uint32_t manual_prio;
+
+       /**
+        * Optional restriction of IPsec policy to a given network interface
+        */
+       char *interface;
+
+       /**
         * set up IPsec transport SA in MIPv6 proxy mode
         */
        bool proxy_mode;
@@ -500,6 +511,18 @@ METHOD(child_cfg_t, get_tfc, uint32_t,
        return this->tfc;
 }
 
+METHOD(child_cfg_t, get_manual_prio, uint32_t,
+       private_child_cfg_t *this)
+{
+       return this->manual_prio;
+}
+
+METHOD(child_cfg_t, get_interface, char*,
+       private_child_cfg_t *this)
+{
+       return this->interface;
+}
+
 METHOD(child_cfg_t, get_replay_window, uint32_t,
        private_child_cfg_t *this)
 {
@@ -512,13 +535,6 @@ METHOD(child_cfg_t, set_replay_window, void,
        this->replay_window = replay_window;
 }
 
-METHOD(child_cfg_t, set_mipv6_options, void,
-       private_child_cfg_t *this, bool proxy_mode, bool install_policy)
-{
-       this->proxy_mode = proxy_mode;
-       this->install_policy = install_policy;
-}
-
 METHOD(child_cfg_t, use_proxy_mode, bool,
        private_child_cfg_t *this)
 {
@@ -532,7 +548,7 @@ METHOD(child_cfg_t, install_policy, bool,
 }
 
 #define LT_PART_EQUALS(a, b) ({ a.life == b.life && a.rekey == b.rekey && a.jitter == b.jitter; })
-#define LIFETIME_EQUALS(a, b) ({  LT_PART_EQUALS(a.time, b.time) && LT_PART_EQUALS(a.bytes, b.bytes) && LT_PART_EQUALS(a.packets, b.packets); })
+#define LIFETIME_EQUALS(a, b) ({ LT_PART_EQUALS(a.time, b.time) && LT_PART_EQUALS(a.bytes, b.bytes) && LT_PART_EQUALS(a.packets, b.packets); })
 
 METHOD(child_cfg_t, equals, bool,
        private_child_cfg_t *this, child_cfg_t *other_pub)
@@ -576,10 +592,12 @@ METHOD(child_cfg_t, equals, bool,
                this->mark_out.value == other->mark_out.value &&
                this->mark_out.mask == other->mark_out.mask &&
                this->tfc == other->tfc &&
+               this->manual_prio == other->manual_prio &&
                this->replay_window == other->replay_window &&
                this->proxy_mode == other->proxy_mode &&
                this->install_policy == other->install_policy &&
-               streq(this->updown, other->updown);
+               streq(this->updown, other->updown) &&
+               streq(this->interface, other->interface);
 }
 
 METHOD(child_cfg_t, get_ref, child_cfg_t*,
@@ -597,10 +615,8 @@ METHOD(child_cfg_t, destroy, void,
                this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
                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));
-               if (this->updown)
-               {
-                       free(this->updown);
-               }
+               free(this->updown);
+               free(this->interface);
                free(this->name);
                free(this);
        }
@@ -609,12 +625,7 @@ METHOD(child_cfg_t, destroy, void,
 /*
  * Described in header-file
  */
-child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
-                                                         char *updown, bool hostaccess,
-                                                         ipsec_mode_t mode, action_t start_action,
-                                                         action_t dpd_action, action_t close_action,
-                                                         bool ipcomp, uint32_t inactivity, uint32_t reqid,
-                                                         mark_t *mark_in, mark_t *mark_out, uint32_t tfc)
+child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
 {
        private_child_cfg_t *this;
 
@@ -634,12 +645,13 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
                        .get_close_action = _get_close_action,
                        .get_lifetime = _get_lifetime,
                        .get_dh_group = _get_dh_group,
-                       .set_mipv6_options = _set_mipv6_options,
                        .use_ipcomp = _use_ipcomp,
                        .get_inactivity = _get_inactivity,
                        .get_reqid = _get_reqid,
                        .get_mark = _get_mark,
                        .get_tfc = _get_tfc,
+                       .get_manual_prio = _get_manual_prio,
+                       .get_interface = _get_interface,
                        .get_replay_window = _get_replay_window,
                        .set_replay_window = _set_replay_window,
                        .use_proxy_mode = _use_proxy_mode,
@@ -649,35 +661,30 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
                        .destroy = _destroy,
                },
                .name = strdup(name),
-               .updown = strdupnull(updown),
-               .hostaccess = hostaccess,
-               .mode = mode,
-               .start_action = start_action,
-               .dpd_action = dpd_action,
-               .close_action = close_action,
-               .use_ipcomp = ipcomp,
-               .inactivity = inactivity,
-               .reqid = reqid,
-               .proxy_mode = FALSE,
-               .install_policy = TRUE,
+               .updown = strdupnull(data->updown),
+               .hostaccess = data->hostaccess,
+               .reqid = data->reqid,
+               .mode = data->mode,
+               .proxy_mode = data->proxy_mode,
+               .start_action = data->start_action,
+               .dpd_action = data->dpd_action,
+               .close_action = data->close_action,
+               .mark_in = data->mark_in,
+               .mark_out = data->mark_out,
+               .lifetime = data->lifetime,
+               .inactivity = data->inactivity,
+               .use_ipcomp = data->ipcomp,
+               .tfc = data->tfc,
+               .manual_prio = data->priority,
+               .interface = strdupnull(data->interface),
+               .install_policy = !data->suppress_policies,
                .refcount = 1,
                .proposals = linked_list_create(),
                .my_ts = linked_list_create(),
                .other_ts = linked_list_create(),
-               .tfc = tfc,
                .replay_window = lib->settings->get_int(lib->settings,
-                               "%s.replay_window", DEFAULT_REPLAY_WINDOW, lib->ns),
+                                                       "%s.replay_window", DEFAULT_REPLAY_WINDOW, lib->ns),
        );
 
-       if (mark_in)
-       {
-               this->mark_in = *mark_in;
-       }
-       if (mark_out)
-       {
-               this->mark_out = *mark_out;
-       }
-       memcpy(&this->lifetime, lifetime, sizeof(lifetime_cfg_t));
-
        return &this->public;
 }
index 0281f5a..7d348fd 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * Copyright (C) 2008-2015 Tobias Brunner
+ * Copyright (C) 2016 Andreas Steffen
+ * Copyright (C) 2008-2016 Tobias Brunner
  * Copyright (C) 2005-2007 Martin Willi
  * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR 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
@@ -25,6 +26,7 @@
 
 typedef enum action_t action_t;
 typedef struct child_cfg_t child_cfg_t;
+typedef struct child_cfg_create_t child_cfg_create_t;
 
 #include <library.h>
 #include <selectors/traffic_selector.h>
@@ -235,6 +237,20 @@ struct child_cfg_t {
        uint32_t (*get_tfc)(child_cfg_t *this);
 
        /**
+        * Get optional manually-set IPsec policy priority
+        *
+        * @return                              manually-set IPsec policy priority (automatic if 0)
+        */
+       uint32_t (*get_manual_prio)(child_cfg_t *this);
+
+       /**
+        * Get optional network interface restricting IPsec policy
+        *
+        * @return                              network interface)
+        */
+       char* (*get_interface)(child_cfg_t *this);
+
+       /**
         * Get anti-replay window size
         *
         * @return                              anti-replay window size
@@ -249,15 +265,6 @@ struct child_cfg_t {
        void (*set_replay_window)(child_cfg_t *this, uint32_t window);
 
        /**
-        * Sets two options needed for Mobile IPv6 interoperability.
-        *
-        * @param proxy_mode    use IPsec transport proxy mode (default FALSE)
-        * @param install_policy install IPsec kernel policies (default TRUE)
-        */
-       void (*set_mipv6_options)(child_cfg_t *this, bool proxy_mode,
-                                                                                                bool install_policy);
-
-       /**
         * Check whether IPsec transport SA should be set up in proxy mode.
         *
         * @return                              TRUE, if proxy mode should be used
@@ -297,38 +304,56 @@ struct child_cfg_t {
        void (*destroy) (child_cfg_t *this);
 };
 
+
+/**
+ * Data passed to the constructor of a child_cfg_t object.
+ */
+struct child_cfg_create_t {
+       /** Specific reqid to use for CHILD_SA, 0 for auto assignment */
+       uint32_t reqid;
+       /** Optional inbound mark */
+       mark_t mark_in;
+       /** Optional outbound mark */
+       mark_t mark_out;
+       /** Mode to propose for CHILD_SA */
+       ipsec_mode_t mode;
+       /** Use IPsec transport proxy mode */
+       bool proxy_mode;
+       /** Use IPComp, if peer supports it */
+       bool ipcomp;
+       /** TFC padding size, 0 to disable, -1 to pad to PMTU */
+       uint32_t tfc;
+       /** Optional manually-set IPsec policy priority */
+       uint32_t priority;
+       /** Optional network interface restricting IPsec policy (cloned) */
+       char *interface;
+       /** lifetime_cfg_t for this child_cfg */
+       lifetime_cfg_t lifetime;
+       /** Inactivity timeout in s before closing a CHILD_SA */
+       uint32_t inactivity;
+       /** Start action */
+       action_t start_action;
+       /** DPD action */
+       action_t dpd_action;
+       /** Close action */
+       action_t close_action;
+       /** updown script to execute on up/down event (cloned) */
+       char *updown;
+       /** TRUE to allow access to the local host */
+       bool hostaccess;
+       /** Don't install IPsec policies */
+       bool suppress_policies;
+};
+
 /**
  * Create a configuration template for CHILD_SA setup.
  *
- * The "name" string gets cloned.
- *
- * The lifetime_cfg_t object gets cloned.
- * To prevent two peers to start rekeying at the same time, a jitter may be
- * specified. Rekeying of an SA starts at (x.rekey - random(0, x.jitter)).
- *
  * After a call to create, a reference is obtained (refcount = 1).
  *
- * @param name                         name of the child_cfg
- * @param lifetime                     lifetime_cfg_t for this child_cfg
- * @param updown                       updown script to execute on up/down event
- * @param hostaccess           TRUE to allow access to the local host
- * @param mode                         mode to propose for CHILD_SA, transport, tunnel or BEET
- * @param start_action         start action
- * @param dpd_action           DPD action
- * @param close_action         close action
- * @param ipcomp                       use IPComp, if peer supports it
- * @param inactivity           inactivity timeout in s before closing a CHILD_SA
- * @param reqid                                specific reqid to use for CHILD_SA, 0 for auto assign
- * @param mark_in                      optional inbound mark (can be NULL)
- * @param mark_out                     optional outbound mark (can be NULL)
- * @param tfc                          TFC padding size, 0 to disable, -1 to pad to PMTU
+ * @param name                         name of the child_cfg (cloned)
+ * @param data                         data for this child_cfg
  * @return                                     child_cfg_t object
  */
-child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
-                                                         char *updown, bool hostaccess,
-                                                         ipsec_mode_t mode, action_t start_action,
-                                                         action_t dpd_action, action_t close_action,
-                                                         bool ipcomp, uint32_t inactivity, uint32_t reqid,
-                                                         mark_t *mark_in, mark_t *mark_out, uint32_t tfc);
+child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data);
 
 #endif /** CHILD_CFG_H_ @}*/
index 4eebfb0..6463c7a 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (C) 2007-2015 Tobias Brunner
+ * Copyright (C) 2007-2016 Tobias Brunner
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR 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
@@ -724,29 +724,22 @@ METHOD(peer_cfg_t, destroy, void,
 /*
  * Described in header-file
  */
-peer_cfg_t *peer_cfg_create(char *name,
-                                                       ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
-                                                       unique_policy_t unique, uint32_t keyingtries,
-                                                       uint32_t rekey_time, uint32_t reauth_time,
-                                                       uint32_t jitter_time, uint32_t over_time,
-                                                       bool mobike, bool aggressive, bool pull_mode,
-                                                       uint32_t dpd, uint32_t dpd_timeout,
-                                                       bool mediation, peer_cfg_t *mediated_by,
-                                                       identification_t *peer_id)
+peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
+                                                       peer_cfg_create_t *data)
 {
        private_peer_cfg_t *this;
 
-       if (rekey_time && jitter_time > rekey_time)
+       if (data->rekey_time && data->jitter_time > data->rekey_time)
        {
-               jitter_time = rekey_time;
+               data->jitter_time = data->rekey_time;
        }
-       if (reauth_time && jitter_time > reauth_time)
+       if (data->reauth_time && data->jitter_time > data->reauth_time)
        {
-               jitter_time = reauth_time;
+               data->jitter_time = data->reauth_time;
        }
-       if (dpd && dpd_timeout && dpd > dpd_timeout)
+       if (data->dpd && data->dpd_timeout && data->dpd > data->dpd_timeout)
        {
-               dpd_timeout = dpd;
+               data->dpd_timeout = data->dpd;
        }
 
        INIT(this,
@@ -789,33 +782,29 @@ peer_cfg_t *peer_cfg_create(char *name,
                .ike_cfg = ike_cfg,
                .child_cfgs = linked_list_create(),
                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
-               .cert_policy = cert_policy,
-               .unique = unique,
-               .keyingtries = keyingtries,
-               .rekey_time = rekey_time,
-               .reauth_time = reauth_time,
-               .jitter_time = jitter_time,
-               .over_time = over_time,
-               .use_mobike = mobike,
-               .aggressive = aggressive,
-               .pull_mode = pull_mode,
-               .dpd = dpd,
-               .dpd_timeout = dpd_timeout,
+               .cert_policy = data->cert_policy,
+               .unique = data->unique,
+               .keyingtries = data->keyingtries,
+               .rekey_time = data->rekey_time,
+               .reauth_time = data->reauth_time,
+               .jitter_time = data->jitter_time,
+               .over_time = data->over_time,
+               .use_mobike = !data->no_mobike,
+               .aggressive = data->aggressive,
+               .pull_mode = !data->push_mode,
+               .dpd = data->dpd,
+               .dpd_timeout = data->dpd_timeout,
                .vips = linked_list_create(),
                .pools = linked_list_create(),
                .local_auth = linked_list_create(),
                .remote_auth = linked_list_create(),
                .refcount = 1,
-       );
-
 #ifdef ME
-       this->mediation = mediation;
-       this->mediated_by = mediated_by;
-       this->peer_id = peer_id;
-#else /* ME */
-       DESTROY_IF(mediated_by);
-       DESTROY_IF(peer_id);
+               .mediation = data->mediation,
+               .mediated_by = data->mediated_by,
+               .peer_id = data->peer_id,
 #endif /* ME */
+       );
 
        return &this->public;
 }
index a4646af..2e79593 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (C) 2007-2015 Tobias Brunner
+ * Copyright (C) 2007-2016 Tobias Brunner
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR 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
@@ -26,6 +26,7 @@
 typedef enum cert_policy_t cert_policy_t;
 typedef enum unique_policy_t unique_policy_t;
 typedef struct peer_cfg_t peer_cfg_t;
+typedef struct peer_cfg_create_t peer_cfg_create_t;
 
 #include <library.h>
 #include <utils/identification.h>
@@ -367,42 +368,52 @@ struct peer_cfg_t {
 };
 
 /**
+ * Data passed to the constructor of a peer_cfg_t object.
+ */
+struct peer_cfg_create_t {
+       /** Whether to send a certificate payload */
+       cert_policy_t cert_policy;
+       /** Uniqueness of an IKE_SA */
+       unique_policy_t unique;
+       /** How many keying tries should be done before giving up */
+       uint32_t keyingtries;
+       /** Timeout in seconds before starting rekeying */
+       uint32_t rekey_time;
+       /** Timeout in seconds before starting reauthentication */
+       uint32_t reauth_time;
+       /** Time range in seconds to randomly subtract from rekey/reauth time */
+       uint32_t jitter_time;
+       /** Maximum overtime in seconds before closing a rekeying/reauth SA */
+       uint32_t over_time;
+       /** Disable MOBIKE (RFC4555) */
+       bool no_mobike;
+       /** Use/accept aggressive mode with IKEv1 */
+       bool aggressive;
+       /** TRUE to use modeconfig push, FALSE for pull */
+       bool push_mode;
+       /** DPD check interval, 0 to disable */
+       uint32_t dpd;
+       /** DPD timeout interval (IKEv1 only), if 0 default applies */
+       uint32_t dpd_timeout;
+#ifdef ME
+       /** TRUE if this is a mediation connection */
+       bool mediation;
+       /** peer_cfg_t of the mediation connection to mediate through (adopted) */
+       peer_cfg_t *mediated_by;
+       /** ID that identifies our peer at the mediation server (adopted) */
+       identification_t *peer_id;
+#endif /* ME */
+};
+
+/**
  * Create a configuration object for IKE_AUTH and later.
  *
- * name-string gets cloned, ID's not.
- * Virtual IPs are used if they are != NULL. A %any host means the virtual
- * IP should be obtained from the other peer.
- * Lifetimes are in seconds. To prevent to peers to start rekeying at the
- * same time, a jitter may be specified. Rekeying of an SA starts at
- * (rekeylifetime - random(0, jitter)).
- *
- * @param name                         name of the peer_cfg
- * @param ike_cfg                      IKE config to use when acting as initiator
- * @param cert_policy          should we send a certificate payload?
- * @param unique                       uniqueness of an IKE_SA
- * @param keyingtries          how many keying tries should be done before giving up
- * @param rekey_time           timeout before starting rekeying
- * @param reauth_time          timeout before starting reauthentication
- * @param jitter_time          timerange to randomly subtract from rekey/reauth time
- * @param over_time                    maximum overtime before closing a rekeying/reauth SA
- * @param mobike                       use MOBIKE (RFC4555) if peer supports it
- * @param aggressive           use/accept aggressive mode with IKEv1
- * @param pull_mode                    TRUE to use modeconfig pull, FALSE for push
- * @param dpd                          DPD check interval, 0 to disable
- * @param dpd_timeout          DPD timeout interval (IKEv1 only), if 0 default applies
- * @param mediation                    TRUE if this is a mediation connection
- * @param mediated_by          peer_cfg_t of the mediation connection to mediate through
- * @param peer_id                      ID that identifies our peer at the mediation server
+ * @param name                         name of the peer_cfg (cloned)
+ * @param ike_cfg                      IKE config to use when acting as initiator (adopted)
+ * @param data                         data for this peer_cfg
  * @return                                     peer_cfg_t object
  */
-peer_cfg_t *peer_cfg_create(char *name,
-                                                       ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
-                                                       unique_policy_t unique, uint32_t keyingtries,
-                                                       uint32_t rekey_time, uint32_t reauth_time,
-                                                       uint32_t jitter_time, uint32_t over_time,
-                                                       bool mobike, bool aggressive, bool pull_mode,
-                                                       uint32_t dpd, uint32_t dpd_timeout,
-                                                       bool mediation, peer_cfg_t *mediated_by,
-                                                       identification_t *peer_id);
+peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
+                                                       peer_cfg_create_t *data);
 
 #endif /** PEER_CFG_H_ @}*/
index bc3f907..97d5ef1 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * Copyright (C) 2008-2015 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2008-2016 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2010 Martin Willi
  * Copyright (C) 2010 revosec AG
  *
@@ -415,59 +416,48 @@ METHOD(kernel_interface_t, release_reqid, status_t,
 }
 
 METHOD(kernel_interface_t, add_sa, status_t,
-       private_kernel_interface_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
-       uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
-       uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
-       uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
-       bool initiator, bool encap, bool esn, bool inbound, bool update,
-       linked_list_t *src_ts, linked_list_t *dst_ts)
+       private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_add_sa_t *data)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
-       return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
-                               mark, tfc, lifetime, enc_alg, enc_key, int_alg, int_key, mode,
-                               ipcomp, cpi, replay_window, initiator, encap, esn, inbound,
-                               update, src_ts, dst_ts);
+       return this->ipsec->add_sa(this->ipsec, id, data);
 }
 
 METHOD(kernel_interface_t, update_sa, status_t,
-       private_kernel_interface_t *this, uint32_t spi, uint8_t protocol,
-       uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-       bool encap, bool new_encap, mark_t mark)
+       private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_update_sa_t *data)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
-       return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst,
-                                                                 new_src, new_dst, encap, new_encap, mark);
+       return this->ipsec->update_sa(this->ipsec, id, data);
 }
 
 METHOD(kernel_interface_t, query_sa, status_t,
-       private_kernel_interface_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, mark_t mark,
-       uint64_t *bytes, uint64_t *packets, time_t *time)
+       private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
+       time_t *time)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
-       return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, mark,
-                                                                bytes, packets, time);
+       return this->ipsec->query_sa(this->ipsec, id, data, bytes, packets, time);
 }
 
 METHOD(kernel_interface_t, del_sa, status_t,
-       private_kernel_interface_t *this, host_t *src, host_t *dst, uint32_t spi,
-       uint8_t protocol, uint16_t cpi, mark_t mark)
+       private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_del_sa_t *data)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
-       return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi, mark);
+       return this->ipsec->del_sa(this->ipsec, id, data);
 }
 
 METHOD(kernel_interface_t, flush_sas, status_t,
@@ -481,44 +471,36 @@ METHOD(kernel_interface_t, flush_sas, status_t,
 }
 
 METHOD(kernel_interface_t, add_policy, status_t,
-       private_kernel_interface_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t priority)
+       private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
-       return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts,
-                                                                  direction, type, sa, mark, priority);
+       return this->ipsec->add_policy(this->ipsec, id, data);
 }
 
 METHOD(kernel_interface_t, query_policy, status_t,
-       private_kernel_interface_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-       time_t *use_time)
+       private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_query_policy_t *data, time_t *use_time)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
-       return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts,
-                                                                        direction, mark, use_time);
+       return this->ipsec->query_policy(this->ipsec, id, data, use_time);
 }
 
 METHOD(kernel_interface_t, del_policy, status_t,
-       private_kernel_interface_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t priority)
+       private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
-       return this->ipsec->del_policy(this->ipsec, src, dst, src_ts, dst_ts,
-                                                                  direction, type, sa, mark, priority);
+       return this->ipsec->del_policy(this->ipsec, id, data);
 }
 
 METHOD(kernel_interface_t, flush_policies, status_t,
index ec6e140..50f6d98 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (C) 2006-2015 Tobias Brunner
+ * Copyright (C) 2006-2016 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR 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
@@ -160,41 +160,12 @@ struct kernel_interface_t {
         * This function does install a single SA for a single protocol in one
         * direction.
         *
-        * @param src                   source address for this SA
-        * @param dst                   destination address for this SA
-        * @param spi                   SPI allocated by us or remote peer
-        * @param protocol              protocol for this SA (ESP/AH)
-        * @param reqid                 reqid for this SA
-        * @param mark                  optional mark for this SA
-        * @param tfc                   Traffic Flow Confidentiality padding for this SA
-        * @param lifetime              lifetime_cfg_t for this SA
-        * @param enc_alg               Algorithm to use for encryption (ESP only)
-        * @param enc_key               key to use for encryption
-        * @param int_alg               Algorithm to use for integrity protection
-        * @param int_key               key to use for integrity protection
-        * @param mode                  mode of the SA (tunnel, transport)
-        * @param ipcomp                IPComp transform to use
-        * @param cpi                   CPI for IPComp
-        * @param replay_window anti-replay window size
-        * @param initiator             TRUE if initiator of the exchange creating this SA
-        * @param encap                 enable UDP encapsulation for NAT traversal
-        * @param esn                   TRUE to use Extended Sequence Numbers
-        * @param inbound               TRUE if this is an inbound SA
-        * @param update                TRUE if an SPI has already been allocated for SA
-        * @param src_ts                list of source traffic selectors
-        * @param dst_ts                list of destination traffic selectors
+        * @param id                    data identifying this SA
+        * @param data                  data for this SA
         * @return                              SUCCESS if operation completed
         */
-       status_t (*add_sa) (kernel_interface_t *this,
-                                               host_t *src, host_t *dst, uint32_t spi,
-                                               uint8_t protocol, uint32_t reqid, mark_t mark,
-                                               uint32_t tfc, lifetime_cfg_t *lifetime,
-                                               uint16_t enc_alg, chunk_t enc_key,
-                                               uint16_t int_alg, chunk_t int_key,
-                                               ipsec_mode_t mode, uint16_t ipcomp, uint16_t cpi,
-                                               uint32_t replay_window, bool initiator, bool encap,
-                                               bool esn, bool inbound, bool update,
-                                               linked_list_t *src_ts, linked_list_t *dst_ts);
+       status_t (*add_sa)(kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
+                                          kernel_ipsec_add_sa_t *data);
 
        /**
         * Update the hosts on an installed SA.
@@ -204,85 +175,55 @@ struct kernel_interface_t {
         * to identify SAs. Therefore if the destination address changed we
         * create a new SA and delete the old one.
         *
-        * @param spi                   SPI of the SA
-        * @param protocol              protocol for this SA (ESP/AH)
-        * @param cpi                   CPI for IPComp, 0 if no IPComp is used
-        * @param src                   current source address
-        * @param dst                   current destination address
-        * @param new_src               new source address
-        * @param new_dst               new destination address
-        * @param encap                 current use of UDP encapsulation
-        * @param new_encap             new use of UDP encapsulation
-        * @param mark                  optional mark for this SA
+        * @param id                    data identifying this SA
+        * @param data                  updated data for this SA
         * @return                              SUCCESS if operation completed, NOT_SUPPORTED if
-        *                                        the kernel interface can't update the SA
+        *                                              the kernel interface can't update the SA
         */
-       status_t (*update_sa)(kernel_interface_t *this,
-                                                 uint32_t spi, uint8_t protocol, uint16_t cpi,
-                                                 host_t *src, host_t *dst,
-                                                 host_t *new_src, host_t *new_dst,
-                                                 bool encap, bool new_encap, mark_t mark);
+       status_t (*update_sa)(kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
+                                                 kernel_ipsec_update_sa_t *data);
 
        /**
         * Query the number of bytes processed by an SA from the SAD.
         *
-        * @param src                   source address for this SA
-        * @param dst                   destination address for this SA
-        * @param spi                   SPI allocated by us or remote peer
-        * @param protocol              protocol for this SA (ESP/AH)
-        * @param mark                  optional mark for this SA
+        * @param id                    data identifying this SA
+        * @param data                  data to query the SA
         * @param[out] bytes    the number of bytes processed by SA
         * @param[out] packets  number of packets processed by SA
         * @param[out] time             last (monotonic) time of SA use
         * @return                              SUCCESS if operation completed
         */
-       status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
-                                                 uint32_t spi, uint8_t protocol, mark_t mark,
-                                                 uint64_t *bytes, uint64_t *packets, time_t *time);
+       status_t (*query_sa)(kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
+                                                kernel_ipsec_query_sa_t *data, uint64_t *bytes,
+                                                uint64_t *packets, time_t *time);
 
        /**
         * Delete a previously installed SA from the SAD.
         *
-        * @param src                   source address for this SA
-        * @param dst                   destination address for this SA
-        * @param spi                   SPI allocated by us or remote peer
-        * @param protocol              protocol for this SA (ESP/AH)
-        * @param cpi                   CPI for IPComp or 0
-        * @param mark                  optional mark for this SA
+        * @param id                    data identifying this SA
+        * @param data                  data to delete the SA
         * @return                              SUCCESS if operation completed
         */
-       status_t (*del_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
-                                               uint32_t spi, uint8_t protocol, uint16_t cpi,
-                                               mark_t mark);
+       status_t (*del_sa)(kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
+                                          kernel_ipsec_del_sa_t *data);
 
        /**
         * Flush all SAs from the SAD.
         *
         * @return                              SUCCESS if operation completed
         */
-       status_t (*flush_sas) (kernel_interface_t *this);
+       status_t (*flush_sas)(kernel_interface_t *this);
 
        /**
         * Add a policy to the SPD.
         *
-        * @param src                   source address of SA
-        * @param dst                   dest address of SA
-        * @param src_ts                traffic selector to match traffic source
-        * @param dst_ts                traffic selector to match traffic dest
-        * @param direction             direction of traffic, POLICY_(IN|OUT|FWD)
-        * @param type                  type of policy, POLICY_(IPSEC|PASS|DROP)
-        * @param sa                    details about the SA(s) tied to this policy
-        * @param mark                  mark for this policy
-        * @param priority              priority of this policy
+        * @param id                    data identifying this policy
+        * @param data                  data for this policy
         * @return                              SUCCESS if operation completed
         */
-       status_t (*add_policy) (kernel_interface_t *this,
-                                                       host_t *src, host_t *dst,
-                                                       traffic_selector_t *src_ts,
-                                                       traffic_selector_t *dst_ts,
-                                                       policy_dir_t direction, policy_type_t type,
-                                                       ipsec_sa_cfg_t *sa, mark_t mark,
-                                                       policy_priority_t priority);
+       status_t (*add_policy)(kernel_interface_t *this,
+                                                  kernel_ipsec_policy_id_t *id,
+                                                  kernel_ipsec_manage_policy_t *data);
 
        /**
         * Query the use time of a policy.
@@ -290,47 +231,33 @@ struct kernel_interface_t {
         * The use time of a policy is the time the policy was used
         * for the last time.
         *
-        * @param src_ts                traffic selector to match traffic source
-        * @param dst_ts                traffic selector to match traffic dest
-        * @param direction             direction of traffic, POLICY_(IN|OUT|FWD)
-        * @param mark                  optional mark
-        * @param[out] use_time the (monotonic) time of this SA's last use
+        * @param id                    data identifying this policy
+        * @param data                  data to query the policy
+        * @param[out] use_time the monotonic timestamp of this SA's last use
         * @return                              SUCCESS if operation completed
         */
-       status_t (*query_policy) (kernel_interface_t *this,
-                                                         traffic_selector_t *src_ts,
-                                                         traffic_selector_t *dst_ts,
-                                                         policy_dir_t direction, mark_t mark,
-                                                         time_t *use_time);
+       status_t (*query_policy)(kernel_interface_t *this,
+                                                        kernel_ipsec_policy_id_t *id,
+                                                        kernel_ipsec_query_policy_t *data,
+                                                        time_t *use_time);
 
        /**
         * Remove a policy from the SPD.
         *
-        * @param src                   source address of SA
-        * @param dst                   dest address of SA
-        * @param src_ts                traffic selector to match traffic source
-        * @param dst_ts                traffic selector to match traffic dest
-        * @param direction             direction of traffic, POLICY_(IN|OUT|FWD)
-        * @param type                  type of policy, POLICY_(IPSEC|PASS|DROP)
-        * @param sa                    details about the SA(s) tied to this policy
-        * @param mark                  mark for this policy
-        * @param priority              priority of the policy
+        * @param id                    data identifying this policy
+        * @param data                  data for this policy
         * @return                              SUCCESS if operation completed
         */
-       status_t (*del_policy) (kernel_interface_t *this,
-                                                       host_t *src, host_t *dst,
-                                                       traffic_selector_t *src_ts,
-                                                       traffic_selector_t *dst_ts,
-                                                       policy_dir_t direction, policy_type_t type,
-                                                       ipsec_sa_cfg_t *sa, mark_t mark,
-                                                       policy_priority_t priority);
+       status_t (*del_policy)(kernel_interface_t *this,
+                                                  kernel_ipsec_policy_id_t *id,
+                                                  kernel_ipsec_manage_policy_t *data);
 
        /**
         * Flush all policies from the SPD.
         *
         * @return                              SUCCESS if operation completed
         */
-       status_t (*flush_policies) (kernel_interface_t *this);
+       status_t (*flush_policies)(kernel_interface_t *this);
 
        /**
         * Get our outgoing source address for a destination.
index fdb5fc7..0ad5660 100644 (file)
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2006-2015 Tobias Brunner
+ * Copyright (C) 2016 Andreas Steffen
+ * Copyright (C) 2006-2016 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR 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
 #define KERNEL_IPSEC_H_
 
 typedef struct kernel_ipsec_t kernel_ipsec_t;
+typedef struct kernel_ipsec_sa_id_t kernel_ipsec_sa_id_t;
+typedef struct kernel_ipsec_add_sa_t kernel_ipsec_add_sa_t;
+typedef struct kernel_ipsec_update_sa_t kernel_ipsec_update_sa_t;
+typedef struct kernel_ipsec_query_sa_t kernel_ipsec_query_sa_t;
+typedef struct kernel_ipsec_del_sa_t kernel_ipsec_del_sa_t;
+typedef struct kernel_ipsec_policy_id_t kernel_ipsec_policy_id_t;
+typedef struct kernel_ipsec_manage_policy_t kernel_ipsec_manage_policy_t;
+typedef struct kernel_ipsec_query_policy_t kernel_ipsec_query_policy_t;
 
 #include <networking/host.h>
 #include <ipsec/ipsec_types.h>
@@ -33,6 +42,137 @@ typedef struct kernel_ipsec_t kernel_ipsec_t;
 #include <kernel/kernel_interface.h>
 
 /**
+ * Data required to identify an SA in the kernel
+ */
+struct kernel_ipsec_sa_id_t {
+       /** Source address */
+       host_t *src;
+       /** Destination address */
+       host_t *dst;
+       /** SPI */
+       uint32_t spi;
+       /** Protocol (ESP/AH) */
+       uint8_t proto;
+       /** Optional mark */
+       mark_t mark;
+};
+
+/**
+ * Data required to add an SA to the kernel
+ */
+struct kernel_ipsec_add_sa_t {
+       /** Reqid */
+       uint32_t reqid;
+       /** Mode (tunnel, transport...) */
+       ipsec_mode_t mode;
+       /** List of source traffic selectors */
+       linked_list_t *src_ts;
+       /** List of destination traffic selectors */
+       linked_list_t *dst_ts;
+       /** Network interface restricting policy */
+       char *interface;
+       /** Lifetime configuration */
+       lifetime_cfg_t *lifetime;
+       /** Encryption algorithm */
+       uint16_t enc_alg;
+       /** Encryption key */
+       chunk_t enc_key;
+       /** Integrity protection algorithm */
+       uint16_t int_alg;
+       /** Integrity protection key */
+       chunk_t int_key;
+       /** Anti-replay window size */
+       uint32_t replay_window;
+       /** Traffic Flow Confidentiality padding */
+       uint32_t tfc;
+       /** IPComp transform */
+       uint16_t ipcomp;
+       /** CPI for IPComp */
+       uint16_t cpi;
+       /** TRUE to enable UDP encapsulation for NAT traversal */
+       bool encap;
+       /** TRUE to use Extended Sequence Numbers */
+       bool esn;
+       /** TRUE if initiator of the exchange creating the SA */
+       bool initiator;
+       /** TRUE if this is an inbound SA */
+       bool inbound;
+       /** TRUE if an SPI has already been allocated for this SA */
+       bool update;
+};
+
+/**
+ * Data required to update the hosts of an SA in the kernel
+ */
+struct kernel_ipsec_update_sa_t {
+       /** CPI in case IPComp is used */
+       uint16_t cpi;
+       /** New source address */
+       host_t *new_src;
+       /** New destination address */
+       host_t *new_dst;
+       /** TRUE if UDP encapsulation is currently enabled */
+       bool encap;
+       /** TRUE to enable UDP encapsulation */
+       bool new_encap;
+};
+
+/**
+ * Data required to query an SA in the kernel
+ */
+struct kernel_ipsec_query_sa_t {
+       uint16_t cpi;
+};
+
+/**
+ * Data required to delete an SA in the kernel
+ */
+struct kernel_ipsec_del_sa_t {
+       /** CPI in case IPComp is used */
+       uint16_t cpi;
+};
+
+/**
+ * Data identifying a policy in the kernel
+ */
+struct kernel_ipsec_policy_id_t {
+       /** Direction of traffic */
+       policy_dir_t dir;
+       /** Source traffic selector */
+       traffic_selector_t *src_ts;
+       /** Destination traffic selector */
+       traffic_selector_t *dst_ts;
+       /** Optional mark */
+       mark_t mark;
+       /** Network interface restricting policy */
+       char *interface;
+};
+
+/**
+ * Data required to add/delete a policy to/from the kernel
+ */
+struct kernel_ipsec_manage_policy_t {
+       /** Type of policy */
+       policy_type_t type;
+       /** Priority class */
+       policy_priority_t prio;
+       /** Manually-set priority (automatic if set to 0) */
+       uint32_t manual_prio;
+       /** Source address of the SA(s) tied to this policy */
+       host_t *src;
+       /** Destination address of the SA(s) tied to this policy */
+       host_t *dst;
+       /** Details about the SA(s) tied to this policy */
+       ipsec_sa_cfg_t *sa;
+};
+
+/**
+ * Data required to query a policy in the kernel
+ */
+struct kernel_ipsec_query_policy_t {
+};
+
+/**
  * Interface to the ipsec subsystem of the kernel.
  *
  * The kernel ipsec interface handles the communication with the kernel
@@ -81,41 +221,12 @@ struct kernel_ipsec_t {
         * This function does install a single SA for a single protocol in one
         * direction.
         *
-        * @param src                   source address for this SA
-        * @param dst                   destination address for this SA
-        * @param spi                   SPI allocated by us or remote peer
-        * @param protocol              protocol for this SA (ESP/AH)
-        * @param reqid                 unique ID for this SA
-        * @param mark                  mark for this SA
-        * @param tfc                   Traffic Flow Confidentiality padding for this SA
-        * @param lifetime              lifetime_cfg_t for this SA
-        * @param enc_alg               Algorithm to use for encryption (ESP only)
-        * @param enc_key               key to use for encryption
-        * @param int_alg               Algorithm to use for integrity protection
-        * @param int_key               key to use for integrity protection
-        * @param mode                  mode of the SA (tunnel, transport)
-        * @param ipcomp                IPComp transform to use
-        * @param cpi                   CPI for IPComp
-        * @param replay_window anti-replay window size
-        * @param initiator             TRUE if initiator of the exchange creating this SA
-        * @param encap                 enable UDP encapsulation for NAT traversal
-        * @param esn                   TRUE to use Extended Sequence Numbers
-        * @param inbound               TRUE if this is an inbound SA
-        * @param update                TRUE if an SPI has already been allocated for SA
-        * @param src_ts                list of source traffic selectors
-        * @param dst_ts                list of destination traffic selectors
+        * @param id                    data identifying this SA
+        * @param data                  data for this SA
         * @return                              SUCCESS if operation completed
         */
-       status_t (*add_sa) (kernel_ipsec_t *this,
-                                               host_t *src, host_t *dst, uint32_t spi,
-                                               uint8_t protocol, uint32_t reqid,
-                                               mark_t mark, uint32_t tfc, lifetime_cfg_t *lifetime,
-                                               uint16_t enc_alg, chunk_t enc_key,
-                                               uint16_t int_alg, chunk_t int_key,
-                                               ipsec_mode_t mode, uint16_t ipcomp, uint16_t cpi,
-                                               uint32_t replay_window, bool initiator, bool encap,
-                                               bool esn, bool inbound, bool update,
-                                               linked_list_t *src_ts, linked_list_t *dst_ts);
+       status_t (*add_sa)(kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+                                          kernel_ipsec_add_sa_t *data);
 
        /**
         * Update the hosts on an installed SA.
@@ -125,85 +236,55 @@ struct kernel_ipsec_t {
         * to identify SAs. Therefore if the destination address changed we
         * create a new SA and delete the old one.
         *
-        * @param spi                   SPI of the SA
-        * @param protocol              protocol for this SA (ESP/AH)
-        * @param cpi                   CPI for IPComp, 0 if no IPComp is used
-        * @param src                   current source address
-        * @param dst                   current destination address
-        * @param new_src               new source address
-        * @param new_dst               new destination address
-        * @param encap                 current use of UDP encapsulation
-        * @param new_encap             new use of UDP encapsulation
-        * @param mark                  optional mark for this SA
+        * @param id                    data identifying this SA
+        * @param data                  updated data for this SA
         * @return                              SUCCESS if operation completed, NOT_SUPPORTED if
-        *                                        the kernel interface can't update the SA
+        *                                              the kernel interface can't update the SA
         */
-       status_t (*update_sa)(kernel_ipsec_t *this,
-                                                 uint32_t spi, uint8_t protocol, uint16_t cpi,
-                                                 host_t *src, host_t *dst,
-                                                 host_t *new_src, host_t *new_dst,
-                                                 bool encap, bool new_encap, mark_t mark);
+       status_t (*update_sa)(kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+                                                 kernel_ipsec_update_sa_t *data);
 
        /**
         * Query the number of bytes processed by an SA from the SAD.
         *
-        * @param src                   source address for this SA
-        * @param dst                   destination address for this SA
-        * @param spi                   SPI allocated by us or remote peer
-        * @param protocol              protocol for this SA (ESP/AH)
-        * @param mark                  optional mark for this SA
+        * @param id                    data identifying this SA
+        * @param data                  data to query the SA
         * @param[out] bytes    the number of bytes processed by SA
         * @param[out] packets  number of packets processed by SA
         * @param[out] time             last (monotonic) time of SA use
         * @return                              SUCCESS if operation completed
         */
-       status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
-                                                 uint32_t spi, uint8_t protocol, mark_t mark,
-                                                 uint64_t *bytes, uint64_t *packets, time_t *time);
+       status_t (*query_sa)(kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+                                                kernel_ipsec_query_sa_t *data, uint64_t *bytes,
+                                                uint64_t *packets, time_t *time);
 
        /**
-        * Delete a previusly installed SA from the SAD.
+        * Delete a previously installed SA from the SAD.
         *
-        * @param src                   source address for this SA
-        * @param dst                   destination address for this SA
-        * @param spi                   SPI allocated by us or remote peer
-        * @param protocol              protocol for this SA (ESP/AH)
-        * @param cpi                   CPI for IPComp or 0
-        * @param mark                  optional mark for this SA
+        * @param id                    data identifying this SA
+        * @param data                  data to delete the SA
         * @return                              SUCCESS if operation completed
         */
-       status_t (*del_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
-                                               uint32_t spi, uint8_t protocol, uint16_t cpi,
-                                               mark_t mark);
+       status_t (*del_sa)(kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+                                          kernel_ipsec_del_sa_t *data);
 
        /**
         * Flush all SAs from the SAD.
         *
         * @return                              SUCCESS if operation completed
         */
-       status_t (*flush_sas) (kernel_ipsec_t *this);
+       status_t (*flush_sas)(kernel_ipsec_t *this);
 
        /**
         * Add a policy to the SPD.
         *
-        * @param src                   source address of SA
-        * @param dst                   dest address of SA
-        * @param src_ts                traffic selector to match traffic source
-        * @param dst_ts                traffic selector to match traffic dest
-        * @param direction             direction of traffic, POLICY_(IN|OUT|FWD)
-        * @param type                  type of policy, POLICY_(IPSEC|PASS|DROP)
-        * @param sa                    details about the SA(s) tied to this policy
-        * @param mark                  mark for this policy
-        * @param priority              priority of this policy
+        * @param id                    data identifying this policy
+        * @param data                  data for this policy
         * @return                              SUCCESS if operation completed
         */
-       status_t (*add_policy) (kernel_ipsec_t *this,
-                                                       host_t *src, host_t *dst,
-                                                       traffic_selector_t *src_ts,
-                                                       traffic_selector_t *dst_ts,
-                                                       policy_dir_t direction, policy_type_t type,
-                                                       ipsec_sa_cfg_t *sa, mark_t mark,
-                                                       policy_priority_t priority);
+       status_t (*add_policy)(kernel_ipsec_t *this,
+                                                  kernel_ipsec_policy_id_t *id,
+                                                  kernel_ipsec_manage_policy_t *data);
 
        /**
         * Query the use time of a policy.
@@ -212,47 +293,33 @@ struct kernel_ipsec_t {
         * time. It is not the system time, but a monotonic timestamp as returned
         * by time_monotonic.
         *
-        * @param src_ts                traffic selector to match traffic source
-        * @param dst_ts                traffic selector to match traffic dest
-        * @param direction             direction of traffic, POLICY_(IN|OUT|FWD)
-        * @param mark                  optional mark
+        * @param id                    data identifying this policy
+        * @param data                  data to query the policy
         * @param[out] use_time the monotonic timestamp of this SA's last use
         * @return                              SUCCESS if operation completed
         */
-       status_t (*query_policy) (kernel_ipsec_t *this,
-                                                         traffic_selector_t *src_ts,
-                                                         traffic_selector_t *dst_ts,
-                                                         policy_dir_t direction, mark_t mark,
-                                                         time_t *use_time);
+       status_t (*query_policy)(kernel_ipsec_t *this,
+                                                        kernel_ipsec_policy_id_t *id,
+                                                        kernel_ipsec_query_policy_t *data,
+                                                        time_t *use_time);
 
        /**
         * Remove a policy from the SPD.
         *
-        * @param src                   source address of SA
-        * @param dst                   dest address of SA
-        * @param src_ts                traffic selector to match traffic source
-        * @param dst_ts                traffic selector to match traffic dest
-        * @param direction             direction of traffic, POLICY_(IN|OUT|FWD)
-        * @param type                  type of policy, POLICY_(IPSEC|PASS|DROP)
-        * @param sa                    details about the SA(s) tied to this policy
-        * @param mark                  mark for this policy
-        * @param priority              priority of the policy
+        * @param id                    data identifying this policy
+        * @param data                  data for this policy
         * @return                              SUCCESS if operation completed
         */
-       status_t (*del_policy) (kernel_ipsec_t *this,
-                                                       host_t *src, host_t *dst,
-                                                       traffic_selector_t *src_ts,
-                                                       traffic_selector_t *dst_ts,
-                                                       policy_dir_t direction, policy_type_t type,
-                                                       ipsec_sa_cfg_t *sa, mark_t mark,
-                                                       policy_priority_t priority);
+       status_t (*del_policy)(kernel_ipsec_t *this,
+                                                  kernel_ipsec_policy_id_t *id,
+                                                  kernel_ipsec_manage_policy_t *data);
 
        /**
         * Flush all policies from the SPD.
         *
         * @return                              SUCCESS if operation completed
         */
-       status_t (*flush_policies) (kernel_ipsec_t *this);
+       status_t (*flush_policies)(kernel_ipsec_t *this);
 
        /**
         * Install a bypass policy for the given socket.
@@ -277,7 +344,7 @@ struct kernel_ipsec_t {
        /**
         * Destroy the implementation.
         */
-       void (*destroy) (kernel_ipsec_t *this);
+       void (*destroy)(kernel_ipsec_t *this);
 };
 
 /**
index fd8e646..a0e5146 100644 (file)
@@ -183,10 +183,22 @@ static void setup_tunnel(private_ha_tunnel_t *this,
        auth_cfg_t *auth_cfg;
        child_cfg_t *child_cfg;
        traffic_selector_t *ts;
-       lifetime_cfg_t lifetime = {
-               .time = {
-                       .life = 21600, .rekey = 20400, .jitter = 400,
+       peer_cfg_create_t peer = {
+               .cert_policy = CERT_NEVER_SEND,
+               .unique = UNIQUE_KEEP,
+               .rekey_time = 86400, /* 24h */
+               .jitter_time = 7200, /* 2h */
+               .over_time = 3600, /* 1h */
+               .no_mobike = TRUE,
+               .dpd = 30,
+       };
+       child_cfg_create_t child = {
+               .lifetime = {
+                       .time = {
+                               .life = 21600, .rekey = 20400, .jitter = 400,
+                       },
                },
+               .mode = MODE_TRANSPORT,
        };
 
        /* setup credentials */
@@ -208,9 +220,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
                                                         remote, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
        ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
-       peer_cfg = peer_cfg_create("ha", ike_cfg, CERT_NEVER_SEND,
-                                               UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE,
-                                               TRUE, 30, 0, FALSE, NULL, NULL);
+       peer_cfg = peer_cfg_create("ha", ike_cfg, &peer);
 
        auth_cfg = auth_cfg_create();
        auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
@@ -224,9 +234,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
                                  identification_create_from_string(remote));
        peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
 
-       child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, MODE_TRANSPORT,
-                                                                ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
-                                                                0, 0, NULL, NULL, 0);
+       child_cfg = child_cfg_create("ha", &child);
        ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT);
        child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
        ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
index e6274e8..f134032 100644 (file)
@@ -248,42 +248,38 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
 }
 
 METHOD(kernel_ipsec_t, add_sa, status_t,
-       private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
-       uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
-       uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
-       uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
-       bool initiator, bool encap, bool esn, bool inbound, bool update,
-       linked_list_t *src_ts, linked_list_t *dst_ts)
+       private_kernel_libipsec_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_add_sa_t *data)
 {
-       return ipsec->sas->add_sa(ipsec->sas, src, dst, spi, protocol, reqid, mark,
-                                                         tfc, lifetime, enc_alg, enc_key, int_alg, int_key,
-                                                         mode, ipcomp, cpi, initiator, encap, esn,
-                                                         inbound, update);
+       return ipsec->sas->add_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
+                                       data->reqid, id->mark, data->tfc, data->lifetime,
+                                       data->enc_alg, data->enc_key, data->int_alg, data->int_key,
+                                       data->mode, data->ipcomp, data->cpi, data->initiator,
+                                       data->encap, data->esn, data->inbound, data->update);
 }
 
 METHOD(kernel_ipsec_t, update_sa, status_t,
-       private_kernel_libipsec_ipsec_t *this, uint32_t spi, uint8_t protocol,
-       uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-       bool encap, bool new_encap, mark_t mark)
+       private_kernel_libipsec_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_update_sa_t *data)
 {
        return NOT_SUPPORTED;
 }
 
 METHOD(kernel_ipsec_t, query_sa, status_t,
-       private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, mark_t mark, uint64_t *bytes,
-       uint64_t *packets, time_t *time)
+       private_kernel_libipsec_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
+       time_t *time)
 {
-       return ipsec->sas->query_sa(ipsec->sas, src, dst, spi, protocol, mark,
-                                                               bytes, packets, time);
+       return ipsec->sas->query_sa(ipsec->sas, id->src, id->dst, id->spi,
+                                                               id->proto, id->mark, bytes, packets, time);
 }
 
 METHOD(kernel_ipsec_t, del_sa, status_t,
-       private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
+       private_kernel_libipsec_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_del_sa_t *data)
 {
-       return ipsec->sas->del_sa(ipsec->sas, src, dst, spi, protocol, cpi, mark);
+       return ipsec->sas->del_sa(ipsec->sas, id->src, id->dst, id->spi, id->proto,
+                                                         data->cpi, id->mark);
 }
 
 METHOD(kernel_ipsec_t, flush_sas, status_t,
@@ -509,22 +505,22 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
 }
 
 METHOD(kernel_ipsec_t, add_policy, status_t,
-       private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark,
-       policy_priority_t priority)
+       private_kernel_libipsec_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        policy_entry_t *policy, *found = NULL;
        status_t status;
 
-       status = ipsec->policies->add_policy(ipsec->policies, src, dst, src_ts,
-                                                               dst_ts, direction, type, sa, mark, priority);
+       status = ipsec->policies->add_policy(ipsec->policies, data->src, data->dst,
+                                                                                id->src_ts, id->dst_ts, id->dir,
+                                                                                data->type, data->sa, id->mark,
+                                                                                data->prio);
        if (status != SUCCESS)
        {
                return status;
        }
        /* we track policies in order to install routes */
-       policy = create_policy_entry(src_ts, dst_ts, direction);
+       policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
 
        this->mutex->lock(this->mutex);
        if (this->policies->find_first(this->policies,
@@ -540,7 +536,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        }
        policy->refs++;
 
-       if (!install_route(this, src, dst, src_ts, dst_ts, policy))
+       if (!install_route(this, data->src, data->dst, id->src_ts, id->dst_ts,
+                                          policy))
        {
                return FAILED;
        }
@@ -548,26 +545,25 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
 }
 
 METHOD(kernel_ipsec_t, query_policy, status_t,
-       private_kernel_libipsec_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-       time_t *use_time)
+       private_kernel_libipsec_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_query_policy_t *data, time_t *use_time)
 {
        return NOT_SUPPORTED;
 }
 
 METHOD(kernel_ipsec_t, del_policy, status_t,
-       private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t priority)
+       private_kernel_libipsec_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        policy_entry_t *policy, *found = NULL;
        status_t status;
 
-       status = ipsec->policies->del_policy(ipsec->policies, src, dst, src_ts,
-                                                               dst_ts, direction, type, sa, mark, priority);
+       status = ipsec->policies->del_policy(ipsec->policies, data->src, data->dst,
+                                                                                id->src_ts, id->dst_ts, id->dir,
+                                                                                data->type, data->sa, id->mark,
+                                                                                data->prio);
 
-       policy = create_policy_entry(src_ts, dst_ts, direction);
+       policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
 
        this->mutex->lock(this->mutex);
        if (this->policies->find_first(this->policies,
@@ -596,8 +592,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
                                                                          route->src_ip, route->if_name) != SUCCESS)
                {
                        DBG1(DBG_KNL, "error uninstalling route installed with "
-                                                 "policy %R === %R %N", src_ts, dst_ts,
-                                                  policy_dir_names, direction);
+                                "policy %R === %R %N", id->src_ts, id->dst_ts,
+                                policy_dir_names, id->dir);
                }
                remove_exclude_route(this, route);
        }
index cbce0a5..b21485e 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2006-2015 Tobias Brunner
+ * Copyright (C) 2006-2016 Tobias Brunner
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2008-2016 Andreas Steffen
  * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR 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
@@ -26,6 +26,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/xfrm.h>
 #include <linux/udp.h>
+#include <net/if.h>
 #include <unistd.h>
 #include <time.h>
 #include <errno.h>
@@ -72,7 +73,7 @@
 #endif
 
 /** Base priority for installed policies */
-#define PRIO_BASE 384
+#define PRIO_BASE 100000
 
 /** Default lifetime of an acquire XFRM state (in seconds) */
 #define DEFAULT_ACQUIRE_LIFETIME 165
@@ -463,7 +464,7 @@ static void ipsec_sa_destroy(private_kernel_netlink_ipsec_t *this,
 }
 
 typedef struct policy_sa_t policy_sa_t;
-typedef struct policy_sa_fwd_t policy_sa_fwd_t;
+typedef struct policy_sa_in_t policy_sa_in_t;
 
 /**
  * Mapping between a policy and an IPsec SA.
@@ -480,10 +481,10 @@ struct policy_sa_t {
 };
 
 /**
- * For forward policies we also cache the traffic selectors in order to install
+ * For inbound policies we also cache the traffic selectors in order to install
  * the route.
  */
-struct policy_sa_fwd_t {
+struct policy_sa_in_t {
        /** Generic interface */
        policy_sa_t generic;
 
@@ -495,7 +496,7 @@ struct policy_sa_fwd_t {
 };
 
 /**
- * Create a policy_sa(_fwd)_t object
+ * Create a policy_sa(_in)_t object
  */
 static policy_sa_t *policy_sa_create(private_kernel_netlink_ipsec_t *this,
        policy_dir_t dir, policy_type_t type, host_t *src, host_t *dst,
@@ -504,14 +505,14 @@ static policy_sa_t *policy_sa_create(private_kernel_netlink_ipsec_t *this,
 {
        policy_sa_t *policy;
 
-       if (dir == POLICY_FWD)
+       if (dir == POLICY_IN)
        {
-               policy_sa_fwd_t *fwd;
-               INIT(fwd,
+               policy_sa_in_t *in;
+               INIT(in,
                        .src_ts = src_ts->clone(src_ts),
                        .dst_ts = dst_ts->clone(dst_ts),
                );
-               policy = &fwd->generic;
+               policy = &in->generic;
        }
        else
        {
@@ -523,16 +524,16 @@ static policy_sa_t *policy_sa_create(private_kernel_netlink_ipsec_t *this,
 }
 
 /**
- * Destroy a policy_sa(_fwd)_t object
+ * Destroy a policy_sa(_in)_t object
  */
 static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t *dir,
                                                          private_kernel_netlink_ipsec_t *this)
 {
-       if (*dir == POLICY_FWD)
+       if (*dir == POLICY_IN)
        {
-               policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)policy;
-               fwd->src_ts->destroy(fwd->src_ts);
-               fwd->dst_ts->destroy(fwd->dst_ts);
+               policy_sa_in_t *in = (policy_sa_in_t*)policy;
+               in->src_ts->destroy(in->src_ts);
+               in->dst_ts->destroy(in->dst_ts);
        }
        ipsec_sa_destroy(this, policy->sa);
        free(policy);
@@ -604,32 +605,66 @@ static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key)
 }
 
 /**
+ * Determine number of set bits in 16 bit port mask
+ */
+static inline uint32_t port_mask_bits(uint16_t port_mask)
+{
+       uint32_t bits;
+       uint16_t bit_mask = 0x8000;
+
+       port_mask = ntohs(port_mask);
+
+       for (bits = 0; bits < 16; bits++)
+       {
+               if (!(port_mask & bit_mask))
+               {
+                       break;
+               }
+               bit_mask >>= 1;
+       }
+       return bits;
+}
+
+/**
  * Calculate the priority of a policy
+ *
+ * bits 0-0:  restriction to network interface (0..1)   1 bit
+ * bits 1-6:  src + dst port mask bits (2 * 0..16)      6 bits
+ * bits 7-7:  restriction to protocol (0..1)            1 bit
+ * bits 8-16: src + dst network mask bits (2 * 0..128)  9 bits
+ *                                                     17 bits
+ *
+ * smallest value: 000000000 0 000000 0:      0, lowest priority = 100'000
+ * largest value : 100000000 1 100000 1: 65'729, highst priority =  34'271
  */
-static inline uint32_t get_priority(policy_entry_t *policy,
-                                                                        policy_priority_t prio)
+static uint32_t get_priority(policy_entry_t *policy, policy_priority_t prio,
+                                                        char *interface)
 {
-       uint32_t priority = PRIO_BASE;
+       uint32_t priority = PRIO_BASE, sport_mask_bits, dport_mask_bits;
+
        switch (prio)
        {
                case POLICY_PRIORITY_FALLBACK:
-                       priority <<= 1;
-                       /* fall-through */
+                       priority += PRIO_BASE;
+                       /* fall-through to next case */
                case POLICY_PRIORITY_ROUTED:
-                       priority <<= 1;
-                       /* fall-through */
+                       priority += PRIO_BASE;
+                       /* fall-through to next case */
                case POLICY_PRIORITY_DEFAULT:
-                       priority <<= 1;
-                       /* fall-through */
+                       priority += PRIO_BASE;
+                       /* fall-through to next case */
                case POLICY_PRIORITY_PASS:
                        break;
        }
-       /* calculate priority based on selector size, small size = high prio */
-       priority -= policy->sel.prefixlen_s;
-       priority -= policy->sel.prefixlen_d;
-       priority <<= 2; /* make some room for the two flags */
-       priority += policy->sel.sport_mask || policy->sel.dport_mask ? 0 : 2;
-       priority += policy->sel.proto ? 0 : 1;
+       sport_mask_bits = port_mask_bits(policy->sel.sport_mask);
+       dport_mask_bits = port_mask_bits(policy->sel.dport_mask);
+
+       /* calculate priority */
+       priority -= (policy->sel.prefixlen_s + policy->sel.prefixlen_d) * 256;
+       priority -=  policy->sel.proto ? 128 : 0;
+       priority -= (sport_mask_bits + dport_mask_bits) * 2;
+       priority -= (interface != NULL);
+
        return priority;
 }
 
@@ -739,7 +774,8 @@ static void ts2ports(traffic_selector_t* ts,
  * Convert a pair of traffic_selectors to an xfrm_selector
  */
 static struct xfrm_selector ts2selector(traffic_selector_t *src,
-                                                                               traffic_selector_t *dst)
+                                                                               traffic_selector_t *dst,
+                                                                               char *interface)
 {
        struct xfrm_selector sel;
        uint16_t port;
@@ -763,7 +799,7 @@ static struct xfrm_selector ts2selector(traffic_selector_t *src,
                sel.dport = htons(traffic_selector_icmp_code(port));
                sel.dport_mask = sel.dport ? ~0 : 0;
        }
-       sel.ifindex = 0;
+       sel.ifindex = interface ? if_nametoindex(interface) : 0;
        sel.user = 0;
 
        return sel;
@@ -1200,32 +1236,45 @@ static bool add_mark(struct nlmsghdr *hdr, int buflen, mark_t mark)
 }
 
 METHOD(kernel_ipsec_t, add_sa, status_t,
-       private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
-       uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
-       uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
-       uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
-       bool initiator, bool encap, bool esn, bool inbound, bool update,
-       linked_list_t* src_ts, linked_list_t* dst_ts)
+       private_kernel_netlink_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_add_sa_t *data)
 {
        netlink_buf_t request;
        char *alg_name;
        struct nlmsghdr *hdr;
        struct xfrm_usersa_info *sa;
-       uint16_t icv_size = 64;
-       ipsec_mode_t original_mode = mode;
+       uint16_t icv_size = 64, ipcomp = data->ipcomp;
+       ipsec_mode_t mode = data->mode, original_mode = data->mode;
        traffic_selector_t *first_src_ts, *first_dst_ts;
        status_t status = FAILED;
 
        /* if IPComp is used, we install an additional IPComp SA. if the cpi is 0
         * we are in the recursive call below */
-       if (ipcomp != IPCOMP_NONE && cpi != 0)
+       if (ipcomp != IPCOMP_NONE && data->cpi != 0)
        {
                lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
-               add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
-                          tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED,
-                          chunk_empty, mode, ipcomp, 0, 0, initiator, FALSE, FALSE,
-                          inbound, update, src_ts, dst_ts);
+               kernel_ipsec_sa_id_t ipcomp_id = {
+                       .src = id->src,
+                       .dst = id->dst,
+                       .spi = htonl(ntohs(data->cpi)),
+                       .proto = IPPROTO_COMP,
+                       .mark = id->mark,
+               };
+               kernel_ipsec_add_sa_t ipcomp_sa = {
+                       .reqid = data->reqid,
+                       .mode = data->mode,
+                       .src_ts = data->src_ts,
+                       .dst_ts = data->dst_ts,
+                       .lifetime = &lft,
+                       .enc_alg = ENCR_UNDEFINED,
+                       .int_alg = AUTH_UNDEFINED,
+                       .tfc = data->tfc,
+                       .ipcomp = data->ipcomp,
+                       .initiator = data->initiator,
+                       .inbound = data->inbound,
+                       .update = data->update,
+               };
+               add_sa(this, &ipcomp_id, &ipcomp_sa);
                ipcomp = IPCOMP_NONE;
                /* use transport mode ESP SA, IPComp uses tunnel mode */
                mode = MODE_TRANSPORT;
@@ -1234,19 +1283,20 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        memset(&request, 0, sizeof(request));
 
        DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}  (mark "
-                                 "%u/0x%08x)", ntohl(spi), reqid, mark.value, mark.mask);
+                "%u/0x%08x)", ntohl(id->spi), data->reqid, id->mark.value,
+                id->mark.mask);
 
        hdr = &request.hdr;
        hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-       hdr->nlmsg_type = update ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
+       hdr->nlmsg_type = data->update ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
 
        sa = NLMSG_DATA(hdr);
-       host2xfrm(src, &sa->saddr);
-       host2xfrm(dst, &sa->id.daddr);
-       sa->id.spi = spi;
-       sa->id.proto = protocol;
-       sa->family = src->get_family(src);
+       host2xfrm(id->src, &sa->saddr);
+       host2xfrm(id->dst, &sa->id.daddr);
+       sa->id.spi = id->spi;
+       sa->id.proto = id->proto;
+       sa->family = id->src->get_family(id->src);
        sa->mode = mode2kernel(mode);
        switch (mode)
        {
@@ -1260,10 +1310,13 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                                 * selector can be installed other traffic would get dropped */
                                break;
                        }
-                       if (src_ts->get_first(src_ts, (void**)&first_src_ts) == SUCCESS &&
-                               dst_ts->get_first(dst_ts, (void**)&first_dst_ts) == SUCCESS)
+                       if (data->src_ts->get_first(data->src_ts,
+                                                                               (void**)&first_src_ts) == SUCCESS &&
+                               data->dst_ts->get_first(data->dst_ts,
+                                                                               (void**)&first_dst_ts) == SUCCESS)
                        {
-                               sa->sel = ts2selector(first_src_ts, first_dst_ts);
+                               sa->sel = ts2selector(first_src_ts, first_dst_ts,
+                                                                         data->interface);
                                if (!this->proto_port_transport)
                                {
                                        /* don't install proto/port on SA. This would break
@@ -1279,18 +1332,18 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                        break;
        }
 
-       sa->reqid = reqid;
-       sa->lft.soft_byte_limit = XFRM_LIMIT(lifetime->bytes.rekey);
-       sa->lft.hard_byte_limit = XFRM_LIMIT(lifetime->bytes.life);
-       sa->lft.soft_packet_limit = XFRM_LIMIT(lifetime->packets.rekey);
-       sa->lft.hard_packet_limit = XFRM_LIMIT(lifetime->packets.life);
+       sa->reqid = data->reqid;
+       sa->lft.soft_byte_limit = XFRM_LIMIT(data->lifetime->bytes.rekey);
+       sa->lft.hard_byte_limit = XFRM_LIMIT(data->lifetime->bytes.life);
+       sa->lft.soft_packet_limit = XFRM_LIMIT(data->lifetime->packets.rekey);
+       sa->lft.hard_packet_limit = XFRM_LIMIT(data->lifetime->packets.life);
        /* we use lifetimes since added, not since used */
-       sa->lft.soft_add_expires_seconds = lifetime->time.rekey;
-       sa->lft.hard_add_expires_seconds = lifetime->time.life;
+       sa->lft.soft_add_expires_seconds = data->lifetime->time.rekey;
+       sa->lft.hard_add_expires_seconds = data->lifetime->time.life;
        sa->lft.soft_use_expires_seconds = 0;
        sa->lft.hard_use_expires_seconds = 0;
 
-       switch (enc_alg)
+       switch (data->enc_alg)
        {
                case ENCR_UNDEFINED:
                        /* no encryption */
@@ -1313,71 +1366,73 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                {
                        struct xfrm_algo_aead *algo;
 
-                       alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
+                       alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, data->enc_alg);
                        if (alg_name == NULL)
                        {
                                DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
-                                                encryption_algorithm_names, enc_alg);
+                                                encryption_algorithm_names, data->enc_alg);
                                        goto failed;
                        }
                        DBG2(DBG_KNL, "  using encryption algorithm %N with key size %d",
-                                encryption_algorithm_names, enc_alg, enc_key.len * 8);
+                                encryption_algorithm_names, data->enc_alg,
+                                data->enc_key.len * 8);
 
                        algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AEAD,
-                                                                  sizeof(*algo) + enc_key.len);
+                                                                  sizeof(*algo) + data->enc_key.len);
                        if (!algo)
                        {
                                goto failed;
                        }
-                       algo->alg_key_len = enc_key.len * 8;
+                       algo->alg_key_len = data->enc_key.len * 8;
                        algo->alg_icv_len = icv_size;
                        strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
                        algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
-                       memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
+                       memcpy(algo->alg_key, data->enc_key.ptr, data->enc_key.len);
                        break;
                }
                default:
                {
                        struct xfrm_algo *algo;
 
-                       alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
+                       alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, data->enc_alg);
                        if (alg_name == NULL)
                        {
                                DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
-                                        encryption_algorithm_names, enc_alg);
+                                        encryption_algorithm_names, data->enc_alg);
                                goto failed;
                        }
                        DBG2(DBG_KNL, "  using encryption algorithm %N with key size %d",
-                                encryption_algorithm_names, enc_alg, enc_key.len * 8);
+                                encryption_algorithm_names, data->enc_alg,
+                                data->enc_key.len * 8);
 
                        algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_CRYPT,
-                                                                  sizeof(*algo) + enc_key.len);
+                                                                  sizeof(*algo) + data->enc_key.len);
                        if (!algo)
                        {
                                goto failed;
                        }
-                       algo->alg_key_len = enc_key.len * 8;
+                       algo->alg_key_len = data->enc_key.len * 8;
                        strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
                        algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
-                       memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
+                       memcpy(algo->alg_key, data->enc_key.ptr, data->enc_key.len);
                }
        }
 
-       if (int_alg != AUTH_UNDEFINED)
+       if (data->int_alg != AUTH_UNDEFINED)
        {
                u_int trunc_len = 0;
 
-               alg_name = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg);
+               alg_name = lookup_algorithm(INTEGRITY_ALGORITHM, data->int_alg);
                if (alg_name == NULL)
                {
                        DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
-                                integrity_algorithm_names, int_alg);
+                                integrity_algorithm_names, data->int_alg);
                        goto failed;
                }
                DBG2(DBG_KNL, "  using integrity algorithm %N with key size %d",
-                        integrity_algorithm_names, int_alg, int_key.len * 8);
+                        integrity_algorithm_names, data->int_alg, data->int_key.len * 8);
 
-               switch (int_alg)
+               switch (data->int_alg)
                {
                        case AUTH_HMAC_MD5_128:
                        case AUTH_HMAC_SHA2_256_128:
@@ -1398,31 +1453,31 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                         * use specified truncation size supported by newer kernels.
                         * also use this for untruncated MD5 and SHA1. */
                        algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH_TRUNC,
-                                                                  sizeof(*algo) + int_key.len);
+                                                                  sizeof(*algo) + data->int_key.len);
                        if (!algo)
                        {
                                goto failed;
                        }
-                       algo->alg_key_len = int_key.len * 8;
+                       algo->alg_key_len = data->int_key.len * 8;
                        algo->alg_trunc_len = trunc_len;
                        strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
                        algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
-                       memcpy(algo->alg_key, int_key.ptr, int_key.len);
+                       memcpy(algo->alg_key, data->int_key.ptr, data->int_key.len);
                }
                else
                {
                        struct xfrm_algo* algo;
 
                        algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH,
-                                                                  sizeof(*algo) + int_key.len);
+                                                                  sizeof(*algo) + data->int_key.len);
                        if (!algo)
                        {
                                goto failed;
                        }
-                       algo->alg_key_len = int_key.len * 8;
+                       algo->alg_key_len = data->int_key.len * 8;
                        strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
                        algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
-                       memcpy(algo->alg_key, int_key.ptr, int_key.len);
+                       memcpy(algo->alg_key, data->int_key.ptr, data->int_key.len);
                }
        }
 
@@ -1451,7 +1506,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
        }
 
-       if (encap)
+       if (data->encap)
        {
                struct xfrm_encap_tmpl *tmpl;
 
@@ -1461,8 +1516,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                        goto failed;
                }
                tmpl->encap_type = UDP_ENCAP_ESPINUDP;
-               tmpl->encap_sport = htons(src->get_port(src));
-               tmpl->encap_dport = htons(dst->get_port(dst));
+               tmpl->encap_sport = htons(id->src->get_port(id->src));
+               tmpl->encap_dport = htons(id->dst->get_port(id->dst));
                memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
                /* encap_oa could probably be derived from the
                 * traffic selectors [rfc4306, p39]. In the netlink kernel
@@ -1476,12 +1531,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                 * checks it marks them "checksum ok" so OA isn't needed. */
        }
 
-       if (!add_mark(hdr, sizeof(request), mark))
+       if (!add_mark(hdr, sizeof(request), id->mark))
        {
                goto failed;
        }
 
-       if (tfc && protocol == IPPROTO_ESP && mode == MODE_TUNNEL)
+       if (data->tfc && id->proto == IPPROTO_ESP && mode == MODE_TUNNEL)
        {       /* the kernel supports TFC padding only for tunnel mode ESP SAs */
                uint32_t *tfcpad;
 
@@ -1491,19 +1546,19 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                {
                        goto failed;
                }
-               *tfcpad = tfc;
+               *tfcpad = data->tfc;
        }
 
-       if (protocol != IPPROTO_COMP)
+       if (id->proto != IPPROTO_COMP)
        {
-               if (replay_window != 0 && (esn || replay_window > 32))
+               if (data->replay_window != 0 && (data->esn || data->replay_window > 32))
                {
                        /* for ESN or larger replay windows we need the new
                         * XFRMA_REPLAY_ESN_VAL attribute to configure a bitmap */
                        struct xfrm_replay_state_esn *replay;
                        uint32_t bmp_size;
 
-                       bmp_size = round_up(replay_window, sizeof(uint32_t) * 8) / 8;
+                       bmp_size = round_up(data->replay_window, sizeof(uint32_t) * 8) / 8;
                        replay = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL,
                                                                         sizeof(*replay) + bmp_size);
                        if (!replay)
@@ -1512,10 +1567,11 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                        }
                        /* bmp_len contains number uf __u32's */
                        replay->bmp_len = bmp_size / sizeof(uint32_t);
-                       replay->replay_window = replay_window;
-                       DBG2(DBG_KNL, "  using replay window of %u packets", replay_window);
+                       replay->replay_window = data->replay_window;
+                       DBG2(DBG_KNL, "  using replay window of %u packets",
+                                data->replay_window);
 
-                       if (esn)
+                       if (data->esn)
                        {
                                DBG2(DBG_KNL, "  using extended sequence numbers (ESN)");
                                sa->flags |= XFRM_STATE_ESN;
@@ -1523,21 +1579,24 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                }
                else
                {
-                       DBG2(DBG_KNL, "  using replay window of %u packets", replay_window);
-                       sa->replay_window = replay_window;
+                       DBG2(DBG_KNL, "  using replay window of %u packets",
+                                data->replay_window);
+                       sa->replay_window = data->replay_window;
                }
        }
 
        if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
        {
-               if (mark.value)
+               if (id->mark.value)
                {
-                       DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x  "
-                                                 "(mark %u/0x%08x)", ntohl(spi), mark.value, mark.mask);
+                       DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x  (mark "
+                                "%u/0x%08x)", ntohl(id->spi), id->mark.value,
+                                id->mark.mask);
                }
                else
                {
-                       DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+                       DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x",
+                                ntohl(id->spi));
                }
                goto failed;
        }
@@ -1555,8 +1614,7 @@ failed:
  * Allocates into one the replay state structure we get from the kernel.
  */
 static void get_replay_state(private_kernel_netlink_ipsec_t *this,
-                                                        uint32_t spi, uint8_t protocol,
-                                                        host_t *dst, mark_t mark,
+                                                        kernel_ipsec_sa_id_t *sa,
                                                         struct xfrm_replay_state_esn **replay_esn,
                                                         uint32_t *replay_esn_len,
                                                         struct xfrm_replay_state **replay,
@@ -1572,7 +1630,7 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this,
        memset(&request, 0, sizeof(request));
 
        DBG2(DBG_KNL, "querying replay state from SAD entry with SPI %.8x",
-                                  ntohl(spi));
+                ntohl(sa->spi));
 
        hdr = &request.hdr;
        hdr->nlmsg_flags = NLM_F_REQUEST;
@@ -1582,12 +1640,12 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this,
        aevent_id = NLMSG_DATA(hdr);
        aevent_id->flags = XFRM_AE_RVAL;
 
-       host2xfrm(dst, &aevent_id->sa_id.daddr);
-       aevent_id->sa_id.spi = spi;
-       aevent_id->sa_id.proto = protocol;
-       aevent_id->sa_id.family = dst->get_family(dst);
+       host2xfrm(sa->dst, &aevent_id->sa_id.daddr);
+       aevent_id->sa_id.spi = sa->spi;
+       aevent_id->sa_id.proto = sa->proto;
+       aevent_id->sa_id.family = sa->dst->get_family(sa->dst);
 
-       if (!add_mark(hdr, sizeof(request), mark))
+       if (!add_mark(hdr, sizeof(request), sa->mark))
        {
                return;
        }
@@ -1657,9 +1715,9 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this,
 }
 
 METHOD(kernel_ipsec_t, query_sa, status_t,
-       private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, mark_t mark,
-       uint64_t *bytes, uint64_t *packets, time_t *time)
+       private_kernel_netlink_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
+       time_t *time)
 {
        netlink_buf_t request;
        struct nlmsghdr *out = NULL, *hdr;
@@ -1671,7 +1729,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
        memset(&request, 0, sizeof(request));
 
        DBG2(DBG_KNL, "querying SAD entry with SPI %.8x  (mark %u/0x%08x)",
-                                  ntohl(spi), mark.value, mark.mask);
+                ntohl(id->spi), id->mark.value, id->mark.mask);
 
        hdr = &request.hdr;
        hdr->nlmsg_flags = NLM_F_REQUEST;
@@ -1679,12 +1737,12 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
 
        sa_id = NLMSG_DATA(hdr);
-       host2xfrm(dst, &sa_id->daddr);
-       sa_id->spi = spi;
-       sa_id->proto = protocol;
-       sa_id->family = dst->get_family(dst);
+       host2xfrm(id->dst, &sa_id->daddr);
+       sa_id->spi = id->spi;
+       sa_id->proto = id->proto;
+       sa_id->family = id->dst->get_family(id->dst);
 
-       if (!add_mark(hdr, sizeof(request), mark))
+       if (!add_mark(hdr, sizeof(request), id->mark))
        {
                return FAILED;
        }
@@ -1705,18 +1763,18 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
                                {
                                        struct nlmsgerr *err = NLMSG_DATA(hdr);
 
-                                       if (mark.value)
+                                       if (id->mark.value)
                                        {
-                                               DBG1(DBG_KNL, "querying SAD entry with SPI %.8x  "
-                                                                         "(mark %u/0x%08x) failed: %s (%d)",
-                                                                          ntohl(spi), mark.value, mark.mask,
-                                                                          strerror(-err->error), -err->error);
+                                               DBG1(DBG_KNL, "querying SAD entry with SPI %.8x  (mark "
+                                                        "%u/0x%08x) failed: %s (%d)", ntohl(id->spi),
+                                                        id->mark.value, id->mark.mask,
+                                                        strerror(-err->error), -err->error);
                                        }
                                        else
                                        {
                                                DBG1(DBG_KNL, "querying SAD entry with SPI %.8x "
-                                                                         "failed: %s (%d)", ntohl(spi),
-                                                                          strerror(-err->error), -err->error);
+                                                        "failed: %s (%d)", ntohl(id->spi),
+                                                        strerror(-err->error), -err->error);
                                        }
                                        break;
                                }
@@ -1732,7 +1790,8 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
 
        if (sa == NULL)
        {
-               DBG2(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
+               DBG2(DBG_KNL, "unable to query SAD entry with SPI %.8x",
+                        ntohl(id->spi));
        }
        else
        {
@@ -1758,23 +1817,31 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
 }
 
 METHOD(kernel_ipsec_t, del_sa, status_t,
-       private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
+       private_kernel_netlink_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_del_sa_t *data)
 {
        netlink_buf_t request;
        struct nlmsghdr *hdr;
        struct xfrm_usersa_id *sa_id;
 
        /* if IPComp was used, we first delete the additional IPComp SA */
-       if (cpi)
-       {
-               del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark);
+       if (data->cpi)
+       {
+               kernel_ipsec_sa_id_t ipcomp_id = {
+                       .src = id->src,
+                       .dst = id->dst,
+                       .spi = htonl(ntohs(data->cpi)),
+                       .proto = IPPROTO_COMP,
+                       .mark = id->mark,
+               };
+               kernel_ipsec_del_sa_t ipcomp = {};
+               del_sa(this, &ipcomp_id, &ipcomp);
        }
 
        memset(&request, 0, sizeof(request));
 
        DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x  (mark %u/0x%08x)",
-                                  ntohl(spi), mark.value, mark.mask);
+                ntohl(id->spi), id->mark.value, id->mark.mask);
 
        hdr = &request.hdr;
        hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
@@ -1782,12 +1849,12 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
 
        sa_id = NLMSG_DATA(hdr);
-       host2xfrm(dst, &sa_id->daddr);
-       sa_id->spi = spi;
-       sa_id->proto = protocol;
-       sa_id->family = dst->get_family(dst);
+       host2xfrm(id->dst, &sa_id->daddr);
+       sa_id->spi = id->spi;
+       sa_id->proto = id->proto;
+       sa_id->family = id->dst->get_family(id->dst);
 
-       if (!add_mark(hdr, sizeof(request), mark))
+       if (!add_mark(hdr, sizeof(request), id->mark))
        {
                return FAILED;
        }
@@ -1795,30 +1862,30 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
        switch (this->socket_xfrm->send_ack(this->socket_xfrm, hdr))
        {
                case SUCCESS:
-                       DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x (mark %u/0x%08x)",
-                                ntohl(spi), mark.value, mark.mask);
+                       DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x  (mark %u/0x%08x)",
+                                ntohl(id->spi), id->mark.value, id->mark.mask);
                        return SUCCESS;
                case NOT_FOUND:
                        return NOT_FOUND;
                default:
-                       if (mark.value)
+                       if (id->mark.value)
                        {
-                               DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x "
-                                        "(mark %u/0x%08x)", ntohl(spi), mark.value, mark.mask);
+                               DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x  (mark "
+                                        "%u/0x%08x)", ntohl(id->spi), id->mark.value,
+                                        id->mark.mask);
                        }
                        else
                        {
                                DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x",
-                                        ntohl(spi));
+                                        ntohl(id->spi));
                        }
                        return FAILED;
        }
 }
 
 METHOD(kernel_ipsec_t, update_sa, status_t,
-       private_kernel_netlink_ipsec_t *this, uint32_t spi, uint8_t protocol,
-       uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-       bool old_encap, bool new_encap, mark_t mark)
+       private_kernel_netlink_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_update_sa_t *data)
 {
        netlink_buf_t request;
        struct nlmsghdr *hdr, *out = NULL;
@@ -1832,18 +1899,30 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
        struct xfrm_replay_state_esn *replay_esn = NULL;
        struct xfrm_lifetime_cur *lifetime = NULL;
        uint32_t replay_esn_len = 0;
+       kernel_ipsec_del_sa_t del = { 0 };
        status_t status = FAILED;
 
        /* if IPComp is used, we first update the IPComp SA */
-       if (cpi)
-       {
-               update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0,
-                                 src, dst, new_src, new_dst, FALSE, FALSE, mark);
+       if (data->cpi)
+       {
+               kernel_ipsec_sa_id_t ipcomp_id = {
+                       .src = id->src,
+                       .dst = id->dst,
+                       .spi = htonl(ntohs(data->cpi)),
+                       .proto = IPPROTO_COMP,
+                       .mark = id->mark,
+               };
+               kernel_ipsec_update_sa_t ipcomp = {
+                       .new_src = data->new_src,
+                       .new_dst = data->new_dst,
+               };
+               update_sa(this, &ipcomp_id, &ipcomp);
        }
 
        memset(&request, 0, sizeof(request));
 
-       DBG2(DBG_KNL, "querying SAD entry with SPI %.8x for update", ntohl(spi));
+       DBG2(DBG_KNL, "querying SAD entry with SPI %.8x for update",
+                ntohl(id->spi));
 
        /* query the existing SA first */
        hdr = &request.hdr;
@@ -1852,12 +1931,12 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
 
        sa_id = NLMSG_DATA(hdr);
-       host2xfrm(dst, &sa_id->daddr);
-       sa_id->spi = spi;
-       sa_id->proto = protocol;
-       sa_id->family = dst->get_family(dst);
+       host2xfrm(id->dst, &sa_id->daddr);
+       sa_id->spi = id->spi;
+       sa_id->proto = id->proto;
+       sa_id->family = id->dst->get_family(id->dst);
 
-       if (!add_mark(hdr, sizeof(request), mark))
+       if (!add_mark(hdr, sizeof(request), id->mark))
        {
                return FAILED;
        }
@@ -1892,23 +1971,25 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
        }
        if (out_sa == NULL)
        {
-               DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
+               DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x",
+                        ntohl(id->spi));
                goto failed;
        }
 
-       get_replay_state(this, spi, protocol, dst, mark, &replay_esn,
-                                        &replay_esn_len, &replay, &lifetime);
+       get_replay_state(this, id, &replay_esn, &replay_esn_len, &replay,
+                                        &lifetime);
 
        /* delete the old SA (without affecting the IPComp SA) */
-       if (del_sa(this, src, dst, spi, protocol, 0, mark) != SUCCESS)
+       if (del_sa(this, id, &del) != SUCCESS)
        {
                DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x",
-                                          ntohl(spi));
+                        ntohl(id->spi));
                goto failed;
        }
 
        DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
-                                  ntohl(spi), src, dst, new_src, new_dst);
+                ntohl(id->spi), id->src, id->dst, data->new_src,
+                data->new_dst);
        /* copy over the SA from out to request */
        hdr = &request.hdr;
        hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
@@ -1916,15 +1997,15 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
        sa = NLMSG_DATA(hdr);
        memcpy(sa, NLMSG_DATA(out), sizeof(struct xfrm_usersa_info));
-       sa->family = new_dst->get_family(new_dst);
+       sa->family = data->new_dst->get_family(data->new_dst);
 
-       if (!src->ip_equals(src, new_src))
+       if (!id->src->ip_equals(id->src, data->new_src))
        {
-               host2xfrm(new_src, &sa->saddr);
+               host2xfrm(data->new_src, &sa->saddr);
        }
-       if (!dst->ip_equals(dst, new_dst))
+       if (!id->dst->ip_equals(id->dst, data->new_dst))
        {
-               host2xfrm(new_dst, &sa->id.daddr);
+               host2xfrm(data->new_dst, &sa->id.daddr);
        }
 
        rta = XFRM_RTA(out, struct xfrm_usersa_info);
@@ -1932,13 +2013,13 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
        while (RTA_OK(rta, rtasize))
        {
                /* copy all attributes, but not XFRMA_ENCAP if we are disabling it */
-               if (rta->rta_type != XFRMA_ENCAP || new_encap)
+               if (rta->rta_type != XFRMA_ENCAP || data->new_encap)
                {
                        if (rta->rta_type == XFRMA_ENCAP)
                        {       /* update encap tmpl */
                                tmpl = RTA_DATA(rta);
-                               tmpl->encap_sport = ntohs(new_src->get_port(new_src));
-                               tmpl->encap_dport = ntohs(new_dst->get_port(new_dst));
+                               tmpl->encap_sport = ntohs(data->new_src->get_port(data->new_src));
+                               tmpl->encap_dport = ntohs(data->new_dst->get_port(data->new_dst));
                        }
                        netlink_add_attribute(hdr, rta->rta_type,
                                                                  chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)),
@@ -1947,7 +2028,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
                rta = RTA_NEXT(rta, rtasize);
        }
 
-       if (tmpl == NULL && new_encap)
+       if (tmpl == NULL && data->new_encap)
        {       /* add tmpl if we are enabling it */
                tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
                if (!tmpl)
@@ -1955,8 +2036,8 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
                        goto failed;
                }
                tmpl->encap_type = UDP_ENCAP_ESPINUDP;
-               tmpl->encap_sport = ntohs(new_src->get_port(new_src));
-               tmpl->encap_dport = ntohs(new_dst->get_port(new_dst));
+               tmpl->encap_sport = ntohs(data->new_src->get_port(data->new_src));
+               tmpl->encap_dport = ntohs(data->new_dst->get_port(data->new_dst));
                memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
        }
 
@@ -1987,7 +2068,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
        else
        {
                DBG1(DBG_KNL, "unable to copy replay state from old SAD entry with "
-                        "SPI %.8x", ntohl(spi));
+                        "SPI %.8x", ntohl(id->spi));
        }
        if (lifetime)
        {
@@ -2004,12 +2085,13 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
        else
        {
                DBG1(DBG_KNL, "unable to copy usage stats from old SAD entry with "
-                        "SPI %.8x", ntohl(spi));
+                        "SPI %.8x", ntohl(id->spi));
        }
 
        if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
+               DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x",
+                        ntohl(id->spi));
                goto failed;
        }
 
@@ -2111,7 +2193,7 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
        policy_info->lft.soft_use_expires_seconds = 0;
        policy_info->lft.hard_use_expires_seconds = 0;
 
-       if (mapping->type == POLICY_IPSEC)
+       if (mapping->type == POLICY_IPSEC && ipsec->cfg.reqid)
        {
                struct xfrm_user_tmpl *tmpl;
                struct {
@@ -2198,14 +2280,14 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
        }
 
        /* install a route, if:
-        * - this is a forward policy (to just get one for each child)
+        * - this is a inbound policy (to just get one for each child)
         * - we are in tunnel/BEET mode or install a bypass policy
         * - routing is not disabled via strongswan.conf
         */
-       if (policy->direction == POLICY_FWD && this->install_routes &&
+       if (policy->direction == POLICY_IN && this->install_routes &&
                (mapping->type != POLICY_IPSEC || ipsec->cfg.mode != MODE_TRANSPORT))
        {
-               policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)mapping;
+               policy_sa_in_t *in = (policy_sa_in_t*)mapping;
                route_entry_t *route;
                host_t *iface;
 
@@ -2213,10 +2295,10 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
                        .prefixlen = policy->sel.prefixlen_s,
                );
 
-               if (charon->kernel->get_address_by_ts(charon->kernel, fwd->dst_ts,
+               if (charon->kernel->get_address_by_ts(charon->kernel, in->dst_ts,
                                                                                          &route->src_ip, NULL) == SUCCESS)
                {
-                       /* get the nexthop to src (src as we are in POLICY_FWD) */
+                       /* get the nexthop to src (src as we are in POLICY_IN) */
                        if (!ipsec->src->is_anyaddr(ipsec->src))
                        {
                                route->gateway = charon->kernel->get_nexthop(charon->kernel,
@@ -2265,8 +2347,8 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
                                                                                old->src_ip, old->if_name) != SUCCESS)
                                {
                                        DBG1(DBG_KNL, "error uninstalling route installed with "
-                                                                 "policy %R === %R %N", fwd->src_ts,
-                                                                  fwd->dst_ts, policy_dir_names,
+                                                                 "policy %R === %R %N", in->src_ts,
+                                                                  in->dst_ts, policy_dir_names,
                                                                   policy->direction);
                                }
                                route_entry_destroy(old);
@@ -2274,7 +2356,7 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
                        }
 
                        DBG2(DBG_KNL, "installing route: %R via %H src %H dev %s",
-                                fwd->src_ts, route->gateway, route->src_ip, route->if_name);
+                                in->src_ts, route->gateway, route->src_ip, route->if_name);
                        switch (charon->kernel->add_route(charon->kernel, route->dst_net,
                                                                                          route->prefixlen, route->gateway,
                                                                                          route->src_ip, route->if_name))
@@ -2303,10 +2385,8 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
 }
 
 METHOD(kernel_ipsec_t, add_policy, status_t,
-       private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t priority)
+       private_kernel_netlink_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        policy_entry_t *policy, *current;
        policy_sa_t *assigned_sa, *current_sa;
@@ -2315,10 +2395,10 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
 
        /* create a policy */
        INIT(policy,
-               .sel = ts2selector(src_ts, dst_ts),
-               .mark = mark.value & mark.mask,
-               .direction = direction,
-               .reqid = sa->reqid,
+               .sel = ts2selector(id->src_ts, id->dst_ts, id->interface),
+               .mark = id->mark.value & id->mark.mask,
+               .direction = id->dir,
+               .reqid = data->sa->reqid,
        );
 
        /* find the policy, which matches EXACTLY */
@@ -2326,21 +2406,21 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        current = this->policies->get(this->policies, policy);
        if (current)
        {
-               if (current->reqid && sa->reqid && current->reqid != sa->reqid)
+               if (current->reqid && data->sa->reqid &&
+                       current->reqid != data->sa->reqid)
                {
                        DBG1(DBG_CFG, "unable to install policy %R === %R %N (mark "
                                 "%u/0x%08x) for reqid %u, the same policy for reqid %u exists",
-                                src_ts, dst_ts, policy_dir_names, direction,
-                                mark.value, mark.mask, sa->reqid, current->reqid);
+                                id->src_ts, id->dst_ts, policy_dir_names, id->dir,
+                                id->mark.value, id->mark.mask, data->sa->reqid, current->reqid);
                        policy_entry_destroy(this, policy);
                        this->mutex->unlock(this->mutex);
                        return INVALID_STATE;
                }
                /* use existing policy */
-               DBG2(DBG_KNL, "policy %R === %R %N  (mark %u/0x%08x) "
-                                         "already exists, increasing refcount",
-                                          src_ts, dst_ts, policy_dir_names, direction,
-                                          mark.value, mark.mask);
+               DBG2(DBG_KNL, "policy %R === %R %N  (mark %u/0x%08x) already exists, "
+                       "increasing refcount", id->src_ts, id->dst_ts, policy_dir_names,
+                       id->dir, id->mark.value, id->mark.mask);
                policy_entry_destroy(this, policy);
                policy = current;
                found = TRUE;
@@ -2352,15 +2432,22 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        }
 
        /* cache the assigned IPsec SA */
-       assigned_sa = policy_sa_create(this, direction, type, src, dst, src_ts,
-                                                                  dst_ts, mark, sa);
-       assigned_sa->priority = get_priority(policy, priority);
+       assigned_sa = policy_sa_create(this, id->dir, data->type, data->src,
+                                               data->dst, id->src_ts, id->dst_ts, id->mark, data->sa);
+       assigned_sa->priority = data->manual_prio ? data->manual_prio :
+                                                       get_priority(policy, data->prio, id->interface);
 
        /* insert the SA according to its priority */
        enumerator = policy->used_by->create_enumerator(policy->used_by);
        while (enumerator->enumerate(enumerator, (void**)&current_sa))
        {
-               if (current_sa->priority >= assigned_sa->priority)
+               if (current_sa->priority > assigned_sa->priority)
+               {
+                       break;
+               }
+               /* prefer SAs with a reqid over those without */
+               if (current_sa->priority == assigned_sa->priority &&
+                       (!current_sa->sa->cfg.reqid || assigned_sa->sa->cfg.reqid))
                {
                        break;
                }
@@ -2383,23 +2470,22 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        }
 
        DBG2(DBG_KNL, "%s policy %R === %R %N  (mark %u/0x%08x)",
-                                  found ? "updating" : "adding", src_ts, dst_ts,
-                                  policy_dir_names, direction, mark.value, mark.mask);
+                found ? "updating" : "adding", id->src_ts, id->dst_ts,
+                policy_dir_names, id->dir, id->mark.value, id->mark.mask);
 
        if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS)
        {
                DBG1(DBG_KNL, "unable to %s policy %R === %R %N",
-                                          found ? "update" : "add", src_ts, dst_ts,
-                                          policy_dir_names, direction);
+                        found ? "update" : "add", id->src_ts, id->dst_ts,
+                        policy_dir_names, id->dir);
                return FAILED;
        }
        return SUCCESS;
 }
 
 METHOD(kernel_ipsec_t, query_policy, status_t,
-       private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-       time_t *use_time)
+       private_kernel_netlink_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_query_policy_t *data, time_t *use_time)
 {
        netlink_buf_t request;
        struct nlmsghdr *out = NULL, *hdr;
@@ -2410,8 +2496,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
        memset(&request, 0, sizeof(request));
 
        DBG2(DBG_KNL, "querying policy %R === %R %N  (mark %u/0x%08x)",
-                                  src_ts, dst_ts, policy_dir_names, direction,
-                                  mark.value, mark.mask);
+                id->src_ts, id->dst_ts, policy_dir_names, id->dir, id->mark.value,
+                id->mark.mask);
 
        hdr = &request.hdr;
        hdr->nlmsg_flags = NLM_F_REQUEST;
@@ -2419,10 +2505,10 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
 
        policy_id = NLMSG_DATA(hdr);
-       policy_id->sel = ts2selector(src_ts, dst_ts);
-       policy_id->dir = direction;
+       policy_id->sel = ts2selector(id->src_ts, id->dst_ts, id->interface);
+       policy_id->dir = id->dir;
 
-       if (!add_mark(hdr, sizeof(request), mark))
+       if (!add_mark(hdr, sizeof(request), id->mark))
        {
                return FAILED;
        }
@@ -2443,7 +2529,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
                                {
                                        struct nlmsgerr *err = NLMSG_DATA(hdr);
                                        DBG1(DBG_KNL, "querying policy failed: %s (%d)",
-                                                                  strerror(-err->error), -err->error);
+                                                strerror(-err->error), -err->error);
                                        break;
                                }
                                default:
@@ -2458,8 +2544,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
 
        if (policy == NULL)
        {
-               DBG2(DBG_KNL, "unable to query policy %R === %R %N", src_ts, dst_ts,
-                                          policy_dir_names, direction);
+               DBG2(DBG_KNL, "unable to query policy %R === %R %N", id->src_ts,
+                        id->dst_ts, policy_dir_names, id->dir);
                free(out);
                return FAILED;
        }
@@ -2479,10 +2565,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
 }
 
 METHOD(kernel_ipsec_t, del_policy, status_t,
-       private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t prio)
+       private_kernel_netlink_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        policy_entry_t *current, policy;
        enumerator_t *enumerator;
@@ -2493,52 +2577,54 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
        bool is_installed = TRUE;
        uint32_t priority;
        ipsec_sa_t assigned_sa = {
-               .src = src,
-               .dst = dst,
-               .mark = mark,
-               .cfg = *sa,
+               .src = data->src,
+               .dst = data->dst,
+               .mark = id->mark,
+               .cfg = *data->sa,
        };
 
        DBG2(DBG_KNL, "deleting policy %R === %R %N  (mark %u/0x%08x)",
-                                  src_ts, dst_ts, policy_dir_names, direction,
-                                  mark.value, mark.mask);
+                id->src_ts, id->dst_ts, policy_dir_names, id->dir, id->mark.value,
+                id->mark.mask);
 
        /* create a policy */
        memset(&policy, 0, sizeof(policy_entry_t));
-       policy.sel = ts2selector(src_ts, dst_ts);
-       policy.mark = mark.value & mark.mask;
-       policy.direction = direction;
+       policy.sel = ts2selector(id->src_ts, id->dst_ts, id->interface);
+       policy.mark = id->mark.value & id->mark.mask;
+       policy.direction = id->dir;
 
        /* find the policy */
        this->mutex->lock(this->mutex);
        current = this->policies->get(this->policies, &policy);
        if (!current)
        {
-               if (mark.value)
+               if (id->mark.value)
                {
                        DBG1(DBG_KNL, "deleting policy %R === %R %N  (mark %u/0x%08x) "
-                                                 "failed, not found", src_ts, dst_ts, policy_dir_names,
-                                                  direction, mark.value, mark.mask);
+                                "failed, not found", id->src_ts, id->dst_ts,
+                                policy_dir_names, id->dir, id->mark.value, id->mark.mask);
                }
                else
                {
                        DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found",
-                                                  src_ts, dst_ts, policy_dir_names, direction);
+                                id->src_ts, id->dst_ts, policy_dir_names, id->dir);
                }
                this->mutex->unlock(this->mutex);
                return NOT_FOUND;
        }
 
        /* remove mapping to SA by reqid and priority */
-       priority = get_priority(current, prio);
+       priority = data->manual_prio ? data->manual_prio :
+                          get_priority(current, data->prio,id->interface);
+
        enumerator = current->used_by->create_enumerator(current->used_by);
        while (enumerator->enumerate(enumerator, (void**)&mapping))
        {
-               if (priority == mapping->priority && type == mapping->type &&
+               if (priority == mapping->priority && data->type == mapping->type &&
                        ipsec_sa_equals(mapping->sa, &assigned_sa))
                {
                        current->used_by->remove_at(current->used_by, enumerator);
-                       policy_sa_destroy(mapping, &direction, this);
+                       policy_sa_destroy(mapping, &id->dir, this);
                        break;
                }
                is_installed = FALSE;
@@ -2555,14 +2641,14 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
                }
 
                DBG2(DBG_KNL, "updating policy %R === %R %N  (mark %u/0x%08x)",
-                                          src_ts, dst_ts, policy_dir_names, direction,
-                                          mark.value, mark.mask);
+                        id->src_ts, id->dst_ts, policy_dir_names, id->dir, id->mark.value,
+                        id->mark.mask);
 
                current->used_by->get_first(current->used_by, (void**)&mapping);
                if (add_policy_internal(this, current, mapping, TRUE) != SUCCESS)
                {
                        DBG1(DBG_KNL, "unable to update policy %R === %R %N",
-                                                  src_ts, dst_ts, policy_dir_names, direction);
+                                id->src_ts, id->dst_ts, policy_dir_names, id->dir);
                        return FAILED;
                }
                return SUCCESS;
@@ -2577,9 +2663,9 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
 
        policy_id = NLMSG_DATA(hdr);
        policy_id->sel = current->sel;
-       policy_id->dir = direction;
+       policy_id->dir = id->dir;
 
-       if (!add_mark(hdr, sizeof(request), mark))
+       if (!add_mark(hdr, sizeof(request), id->mark))
        {
                this->mutex->unlock(this->mutex);
                return FAILED;
@@ -2592,9 +2678,9 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
                                                                          route->prefixlen, route->gateway,
                                                                          route->src_ip, route->if_name) != SUCCESS)
                {
-                       DBG1(DBG_KNL, "error uninstalling route installed with "
-                                                 "policy %R === %R %N", src_ts, dst_ts,
-                                                  policy_dir_names, direction);
+                       DBG1(DBG_KNL, "error uninstalling route installed with policy "
+                                "%R === %R %N", id->src_ts, id->dst_ts, policy_dir_names,
+                                id->dir);
                }
        }
 
@@ -2604,16 +2690,16 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
 
        if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
        {
-               if (mark.value)
+               if (id->mark.value)
                {
-                       DBG1(DBG_KNL, "unable to delete policy %R === %R %N  "
-                                                 "(mark %u/0x%08x)", src_ts, dst_ts, policy_dir_names,
-                                                  direction, mark.value, mark.mask);
+                       DBG1(DBG_KNL, "unable to delete policy %R === %R %N  (mark "
+                                "%u/0x%08x)", id->src_ts, id->dst_ts, policy_dir_names,
+                                id->dir, id->mark.value, id->mark.mask);
                }
                else
                {
                        DBG1(DBG_KNL, "unable to delete policy %R === %R %N",
-                                                  src_ts, dst_ts, policy_dir_names, direction);
+                                id->src_ts, id->dst_ts, policy_dir_names, id->dir);
                }
                return FAILED;
        }
index 880f2dc..7eb6c58 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Copyright (C) 2008-2015 Tobias Brunner
+ * Copyright (C) 2008-2016 Tobias Brunner
  * Copyright (C) 2008 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
+ * HSR 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
@@ -1605,13 +1605,8 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
 }
 
 METHOD(kernel_ipsec_t, add_sa, status_t,
-       private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, uint32_t spi,
-       uint8_t protocol, uint32_t reqid, mark_t mark, uint32_t tfc,
-       lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
-       uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
-       uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
-       bool initiator, bool encap, bool esn, bool inbound, bool update,
-       linked_list_t *src_ts, linked_list_t *dst_ts)
+       private_kernel_pfkey_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_add_sa_t *data)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1620,22 +1615,42 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        struct sadb_lifetime *lft;
        struct sadb_key *key;
        size_t len;
+       uint16_t ipcomp = data->ipcomp;
+       ipsec_mode_t mode = data->mode;
 
        /* if IPComp is used, we install an additional IPComp SA. if the cpi is 0
         * we are in the recursive call below */
-       if (ipcomp != IPCOMP_NONE && cpi != 0)
+       if (ipcomp != IPCOMP_NONE && data->cpi != 0)
        {
                lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
-               add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
-                          tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED,
-                          chunk_empty, mode, ipcomp, 0, 0, FALSE, FALSE, FALSE, inbound,
-                          update, NULL, NULL);
+               kernel_ipsec_sa_id_t ipcomp_id = {
+                       .src = id->src,
+                       .dst = id->dst,
+                       .spi = htonl(ntohs(data->cpi)),
+                       .proto = IPPROTO_COMP,
+                       .mark = id->mark,
+               };
+               kernel_ipsec_add_sa_t ipcomp_sa = {
+                       .reqid = data->reqid,
+                       .mode = data->mode,
+                       .src_ts = data->src_ts,
+                       .dst_ts = data->dst_ts,
+                       .lifetime = &lft,
+                       .enc_alg = ENCR_UNDEFINED,
+                       .int_alg = AUTH_UNDEFINED,
+                       .tfc = data->tfc,
+                       .ipcomp = data->ipcomp,
+                       .initiator = data->initiator,
+                       .inbound = data->inbound,
+                       .update = data->update,
+               };
+               add_sa(this, &ipcomp_id, &ipcomp_sa);
                ipcomp = IPCOMP_NONE;
                /* use transport mode ESP SA, IPComp uses tunnel mode */
                mode = MODE_TRANSPORT;
        }
 
-       if (update)
+       if (data->update)
        {
                /* As we didn't know the reqid during SPI allocation, we used reqid
                 * zero. Unfortunately we can't SADB_UPDATE to the new reqid, hence we
@@ -1643,10 +1658,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                 * selector does not count for that, therefore we have to delete
                 * that state before installing the new SA to avoid deleting the
                 * the new state after installing it. */
-               mark_t zeromark = {0, 0};
-
-               if (this->public.interface.del_sa(&this->public.interface,
-                                       src, dst, spi, protocol, 0, zeromark) != SUCCESS)
+               kernel_ipsec_sa_id_t del_id = {
+                       .src = id->src,
+                       .dst = id->dst,
+                       .spi = id->spi,
+                       .proto = id->proto,
+               };
+               kernel_ipsec_del_sa_t del = { 0 };
+
+               if (this->public.interface.del_sa(&this->public.interface, &del_id,
+                                                                                 &del) != SUCCESS)
                {
                        DBG1(DBG_KNL, "deleting SPI allocation SA failed");
                }
@@ -1655,20 +1676,20 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        memset(&request, 0, sizeof(request));
 
        DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}",
-                                  ntohl(spi), reqid);
+                ntohl(id->spi), data->reqid);
 
        msg = (struct sadb_msg*)request;
        msg->sadb_msg_version = PF_KEY_V2;
        msg->sadb_msg_type = SADB_ADD;
-       msg->sadb_msg_satype = proto2satype(protocol);
+       msg->sadb_msg_satype = proto2satype(id->proto);
        msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
 
 #ifdef __APPLE__
-       if (encap)
+       if (data->encap)
        {
                struct sadb_sa_2 *sa_2;
                sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg);
-               sa_2->sadb_sa_natt_port = dst->get_port(dst);
+               sa_2->sadb_sa_natt_port = id->dst->get_port(id->dst);
                sa = &sa_2->sa;
                sa->sadb_sa_flags |= SADB_X_EXT_NATT;
                len = sizeof(struct sadb_sa_2);
@@ -1681,22 +1702,24 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        }
        sa->sadb_sa_exttype = SADB_EXT_SA;
        sa->sadb_sa_len = PFKEY_LEN(len);
-       sa->sadb_sa_spi = spi;
-       if (protocol == IPPROTO_COMP)
+       sa->sadb_sa_spi = id->spi;
+       if (id->proto == IPPROTO_COMP)
        {
-               sa->sadb_sa_encrypt = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp);
+               sa->sadb_sa_encrypt = lookup_algorithm(COMPRESSION_ALGORITHM,
+                                                                                          ipcomp);
        }
        else
        {
                /* Linux interprets sadb_sa_replay as number of packets/bits in the
                 * replay window, whereas on BSD it's the size of the window in bytes */
 #ifdef __linux__
-               sa->sadb_sa_replay = min(replay_window, 32);
+               sa->sadb_sa_replay = min(data->replay_window, 32);
 #else
-               sa->sadb_sa_replay = (replay_window + 7) / 8;
+               sa->sadb_sa_replay = (data->replay_window + 7) / 8;
 #endif
-               sa->sadb_sa_auth = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg);
-               sa->sadb_sa_encrypt = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
+               sa->sadb_sa_auth = lookup_algorithm(INTEGRITY_ALGORITHM, data->int_alg);
+               sa->sadb_sa_encrypt = lookup_algorithm(ENCRYPTION_ALGORITHM,
+                                                                                          data->enc_alg);
        }
        PFKEY_EXT_ADD(msg, sa);
 
@@ -1704,86 +1727,88 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
        sa2->sadb_x_sa2_len = PFKEY_LEN(sizeof(struct sadb_spirange));
        sa2->sadb_x_sa2_mode = mode2kernel(mode);
-       sa2->sadb_x_sa2_reqid = reqid;
+       sa2->sadb_x_sa2_reqid = data->reqid;
        PFKEY_EXT_ADD(msg, sa2);
 
-       add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
-       add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
+       add_addr_ext(msg, id->src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
+       add_addr_ext(msg, id->dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
 
        lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg);
        lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
        lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime));
-       lft->sadb_lifetime_allocations = lifetime->packets.rekey;
-       lft->sadb_lifetime_bytes = lifetime->bytes.rekey;
-       lft->sadb_lifetime_addtime = lifetime->time.rekey;
+       lft->sadb_lifetime_allocations = data->lifetime->packets.rekey;
+       lft->sadb_lifetime_bytes = data->lifetime->bytes.rekey;
+       lft->sadb_lifetime_addtime = data->lifetime->time.rekey;
        lft->sadb_lifetime_usetime = 0; /* we only use addtime */
        PFKEY_EXT_ADD(msg, lft);
 
        lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg);
        lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
        lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime));
-       lft->sadb_lifetime_allocations = lifetime->packets.life;
-       lft->sadb_lifetime_bytes = lifetime->bytes.life;
-       lft->sadb_lifetime_addtime = lifetime->time.life;
+       lft->sadb_lifetime_allocations = data->lifetime->packets.life;
+       lft->sadb_lifetime_bytes = data->lifetime->bytes.life;
+       lft->sadb_lifetime_addtime = data->lifetime->time.life;
        lft->sadb_lifetime_usetime = 0; /* we only use addtime */
        PFKEY_EXT_ADD(msg, lft);
 
-       if (enc_alg != ENCR_UNDEFINED)
+       if (data->enc_alg != ENCR_UNDEFINED)
        {
                if (!sa->sadb_sa_encrypt)
                {
                        DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
-                                                  encryption_algorithm_names, enc_alg);
+                                encryption_algorithm_names, data->enc_alg);
                        return FAILED;
                }
                DBG2(DBG_KNL, "  using encryption algorithm %N with key size %d",
-                                                encryption_algorithm_names, enc_alg, enc_key.len * 8);
+                        encryption_algorithm_names, data->enc_alg, data->enc_key.len * 8);
 
                key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
                key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
-               key->sadb_key_bits = enc_key.len * 8;
-               key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + enc_key.len);
-               memcpy(key + 1, enc_key.ptr, enc_key.len);
+               key->sadb_key_bits = data->enc_key.len * 8;
+               key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + data->enc_key.len);
+               memcpy(key + 1, data->enc_key.ptr, data->enc_key.len);
 
                PFKEY_EXT_ADD(msg, key);
        }
 
-       if (int_alg != AUTH_UNDEFINED)
+       if (data->int_alg != AUTH_UNDEFINED)
        {
                if (!sa->sadb_sa_auth)
                {
                        DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
-                                                  integrity_algorithm_names, int_alg);
+                                integrity_algorithm_names, data->int_alg);
                        return FAILED;
                }
                DBG2(DBG_KNL, "  using integrity algorithm %N with key size %d",
-                                                integrity_algorithm_names, int_alg, int_key.len * 8);
+                        integrity_algorithm_names, data->int_alg, data->int_key.len * 8);
 
                key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
                key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
-               key->sadb_key_bits = int_key.len * 8;
-               key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + int_key.len);
-               memcpy(key + 1, int_key.ptr, int_key.len);
+               key->sadb_key_bits = data->int_key.len * 8;
+               key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + data->int_key.len);
+               memcpy(key + 1, data->int_key.ptr, data->int_key.len);
 
                PFKEY_EXT_ADD(msg, key);
        }
 
 #ifdef HAVE_NATT
-       if (encap)
+       if (data->encap)
        {
-               add_encap_ext(msg, src, dst);
+               add_encap_ext(msg, id->src, id->dst);
        }
 #endif /*HAVE_NATT*/
 
        if (pfkey_send(this, msg, &out, &len) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+               DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x",
+                        ntohl(id->spi));
                return FAILED;
        }
        else if (out->sadb_msg_errno)
        {
                DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x: %s (%d)",
-                               ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+                        ntohl(id->spi), strerror(out->sadb_msg_errno),
+                        out->sadb_msg_errno);
                free(out);
                return FAILED;
        }
@@ -1793,9 +1818,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 }
 
 METHOD(kernel_ipsec_t, update_sa, status_t,
-       private_kernel_pfkey_ipsec_t *this, uint32_t spi, uint8_t protocol,
-       uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-       bool encap, bool new_encap, mark_t mark)
+       private_kernel_pfkey_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_update_sa_t *data)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1806,72 +1830,84 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
        /* we can't update the SA if any of the ip addresses have changed.
         * that's because we can't use SADB_UPDATE and by deleting and readding the
         * SA the sequence numbers would get lost */
-       if (!src->ip_equals(src, new_src) ||
-               !dst->ip_equals(dst, new_dst))
+       if (!id->src->ip_equals(id->src, data->new_src) ||
+               !id->dst->ip_equals(id->dst, data->new_dst))
        {
                DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: address "
-                                         "changes are not supported", ntohl(spi));
+                        "changes are not supported", ntohl(id->spi));
                return NOT_SUPPORTED;
        }
 
        /* if IPComp is used, we first update the IPComp SA */
-       if (cpi)
-       {
-               update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0,
-                                 src, dst, new_src, new_dst, FALSE, FALSE, mark);
+       if (data->cpi)
+       {
+               kernel_ipsec_sa_id_t ipcomp_id = {
+                       .src = id->src,
+                       .dst = id->dst,
+                       .spi = htonl(ntohs(data->cpi)),
+                       .proto = IPPROTO_COMP,
+                       .mark = id->mark,
+               };
+               kernel_ipsec_update_sa_t ipcomp = {
+                       .new_src = data->new_src,
+                       .new_dst = data->new_dst,
+               };
+               update_sa(this, &ipcomp_id, &ipcomp);
        }
 
        memset(&request, 0, sizeof(request));
 
-       DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
+       DBG2(DBG_KNL, "querying SAD entry with SPI %.8x for update",
+                ntohl(id->spi));
 
        msg = (struct sadb_msg*)request;
        msg->sadb_msg_version = PF_KEY_V2;
        msg->sadb_msg_type = SADB_GET;
-       msg->sadb_msg_satype = proto2satype(protocol);
+       msg->sadb_msg_satype = proto2satype(id->proto);
        msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
 
        sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
        sa->sadb_sa_exttype = SADB_EXT_SA;
        sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
-       sa->sadb_sa_spi = spi;
+       sa->sadb_sa_spi = id->spi;
        PFKEY_EXT_ADD(msg, sa);
 
        /* the kernel wants a SADB_EXT_ADDRESS_SRC to be present even though
         * it is not used for anything. */
-       add_anyaddr_ext(msg, dst->get_family(dst), SADB_EXT_ADDRESS_SRC);
-       add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
+       add_anyaddr_ext(msg, id->dst->get_family(id->dst), SADB_EXT_ADDRESS_SRC);
+       add_addr_ext(msg, id->dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
 
        if (pfkey_send(this, msg, &out, &len) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
+               DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x",
+                        ntohl(id->spi));
                return FAILED;
        }
        else if (out->sadb_msg_errno)
        {
                DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: %s (%d)",
-                                          ntohl(spi), strerror(out->sadb_msg_errno),
-                                          out->sadb_msg_errno);
+                        ntohl(id->spi), strerror(out->sadb_msg_errno),
+                        out->sadb_msg_errno);
                free(out);
                return FAILED;
        }
        else if (parse_pfkey_message(out, &response) != SUCCESS)
        {
                DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: parsing "
-                                         "response from kernel failed", ntohl(spi));
+                        "response from kernel failed", ntohl(id->spi));
                free(out);
                return FAILED;
        }
 
        DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
-                                  ntohl(spi), src, dst, new_src, new_dst);
+                ntohl(id->spi), id->src, id->dst, data->new_src, data->new_dst);
 
        memset(&request, 0, sizeof(request));
 
        msg = (struct sadb_msg*)request;
        msg->sadb_msg_version = PF_KEY_V2;
        msg->sadb_msg_type = SADB_UPDATE;
-       msg->sadb_msg_satype = proto2satype(protocol);
+       msg->sadb_msg_satype = proto2satype(id->proto);
        msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
 
 #ifdef __APPLE__
@@ -1880,9 +1916,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
                sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg);
                sa_2->sa.sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa_2));
                memcpy(&sa_2->sa, response.sa, sizeof(struct sadb_sa));
-               if (encap)
+               if (data->encap)
                {
-                       sa_2->sadb_sa_natt_port = new_dst->get_port(new_dst);
+                       sa_2->sadb_sa_natt_port = data->new_dst->get_port(data->new_dst);
                        sa_2->sa.sadb_sa_flags |= SADB_X_EXT_NATT;
                }
        }
@@ -1908,9 +1944,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
        }
 
 #ifdef HAVE_NATT
-       if (new_encap)
+       if (data->new_encap)
        {
-               add_encap_ext(msg, new_src, new_dst);
+               add_encap_ext(msg, data->new_src, data->new_dst);
        }
 #endif /*HAVE_NATT*/
 
@@ -1918,14 +1954,14 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
 
        if (pfkey_send(this, msg, &out, &len) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
+               DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x",
+                        ntohl(id->spi));
                return FAILED;
        }
        else if (out->sadb_msg_errno)
        {
                DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: %s (%d)",
-                                          ntohl(spi), strerror(out->sadb_msg_errno),
-                                          out->sadb_msg_errno);
+                        ntohl(id->spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
                free(out);
                return FAILED;
        }
@@ -1935,9 +1971,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
 }
 
 METHOD(kernel_ipsec_t, query_sa, status_t,
-       private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, mark_t mark,
-       uint64_t *bytes, uint64_t *packets, time_t *time)
+       private_kernel_pfkey_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
+       time_t *time)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1947,42 +1983,44 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
 
        memset(&request, 0, sizeof(request));
 
-       DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
+       DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(id->spi));
 
        msg = (struct sadb_msg*)request;
        msg->sadb_msg_version = PF_KEY_V2;
        msg->sadb_msg_type = SADB_GET;
-       msg->sadb_msg_satype = proto2satype(protocol);
+       msg->sadb_msg_satype = proto2satype(id->proto);
        msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
 
        sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
        sa->sadb_sa_exttype = SADB_EXT_SA;
        sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
-       sa->sadb_sa_spi = spi;
+       sa->sadb_sa_spi = id->spi;
        PFKEY_EXT_ADD(msg, sa);
 
        /* the Linux Kernel doesn't care for the src address, but other systems do
         * (e.g. FreeBSD)
         */
-       add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
-       add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
+       add_addr_ext(msg, id->src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
+       add_addr_ext(msg, id->dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
 
        if (pfkey_send(this, msg, &out, &len) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
+               DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x",
+                        ntohl(id->spi));
                return FAILED;
        }
        else if (out->sadb_msg_errno)
        {
                DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: %s (%d)",
-                                          ntohl(spi), strerror(out->sadb_msg_errno),
-                                          out->sadb_msg_errno);
+                        ntohl(id->spi), strerror(out->sadb_msg_errno),
+                        out->sadb_msg_errno);
                free(out);
                return FAILED;
        }
        else if (parse_pfkey_message(out, &response) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
+               DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x",
+                        ntohl(id->spi));
                free(out);
                return FAILED;
        }
@@ -2013,8 +2051,8 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
 }
 
 METHOD(kernel_ipsec_t, del_sa, status_t,
-       private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
+       private_kernel_pfkey_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_del_sa_t *data)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -2022,48 +2060,57 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
        size_t len;
 
        /* if IPComp was used, we first delete the additional IPComp SA */
-       if (cpi)
+       if (data->cpi)
        {
-               del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark);
+               kernel_ipsec_sa_id_t ipcomp_id = {
+                       .src = id->src,
+                       .dst = id->dst,
+                       .spi = htonl(ntohs(data->cpi)),
+                       .proto = IPPROTO_COMP,
+                       .mark = id->mark,
+               };
+               kernel_ipsec_del_sa_t ipcomp = { 0 };
+               del_sa(this, &ipcomp_id, &ipcomp);
        }
 
        memset(&request, 0, sizeof(request));
 
-       DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
+       DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(id->spi));
 
        msg = (struct sadb_msg*)request;
        msg->sadb_msg_version = PF_KEY_V2;
        msg->sadb_msg_type = SADB_DELETE;
-       msg->sadb_msg_satype = proto2satype(protocol);
+       msg->sadb_msg_satype = proto2satype(id->proto);
        msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
 
        sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
        sa->sadb_sa_exttype = SADB_EXT_SA;
        sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
-       sa->sadb_sa_spi = spi;
+       sa->sadb_sa_spi = id->spi;
        PFKEY_EXT_ADD(msg, sa);
 
        /* the Linux Kernel doesn't care for the src address, but other systems do
         * (e.g. FreeBSD)
         */
-       add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
-       add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
+       add_addr_ext(msg, id->src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
+       add_addr_ext(msg, id->dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
 
        if (pfkey_send(this, msg, &out, &len) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+               DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x",
+                        ntohl(id->spi));
                return FAILED;
        }
        else if (out->sadb_msg_errno)
        {
                DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x: %s (%d)",
-                                          ntohl(spi), strerror(out->sadb_msg_errno),
-                                          out->sadb_msg_errno);
+                        ntohl(id->spi), strerror(out->sadb_msg_errno),
+                        out->sadb_msg_errno);
                free(out);
                return FAILED;
        }
 
-       DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+       DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(id->spi));
        free(out);
        return SUCCESS;
 }
@@ -2381,53 +2428,56 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
        pol->sadb_x_policy_priority = mapping->priority;
 #endif
 
-       /* one or more sadb_x_ipsecrequest extensions are added to the
-        * sadb_x_policy extension */
-       proto_mode = ipsec->cfg.mode;
+       if (mapping->type == POLICY_IPSEC && ipsec->cfg.reqid)
+       {
+               /* one or more sadb_x_ipsecrequest extensions are added to the
+                * sadb_x_policy extension */
+               proto_mode = ipsec->cfg.mode;
 
-       req = (struct sadb_x_ipsecrequest*)(pol + 1);
+               req = (struct sadb_x_ipsecrequest*)(pol + 1);
 
-       if (ipsec->cfg.ipcomp.transform != IPCOMP_NONE)
-       {
-               req->sadb_x_ipsecrequest_proto = IPPROTO_COMP;
+               if (ipsec->cfg.ipcomp.transform != IPCOMP_NONE)
+               {
+                       req->sadb_x_ipsecrequest_proto = IPPROTO_COMP;
+
+                       /* !!! the length here MUST be in octets instead of 64 bit words */
+                       req->sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest);
+                       req->sadb_x_ipsecrequest_mode = mode2kernel(ipsec->cfg.mode);
+                       req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid;
+                       req->sadb_x_ipsecrequest_level = (policy->direction == POLICY_OUT) ?
+                                                                                       IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_USE;
+                       if (ipsec->cfg.mode == MODE_TUNNEL)
+                       {
+                               len = hostcpy(req + 1, ipsec->src, FALSE);
+                               req->sadb_x_ipsecrequest_len += len;
+                               len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE);
+                               req->sadb_x_ipsecrequest_len += len;
+                               /* use transport mode for other SAs */
+                               proto_mode = MODE_TRANSPORT;
+                       }
 
+                       pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
+                       req = (struct sadb_x_ipsecrequest*)((char*)(req) +
+                                                                                               req->sadb_x_ipsecrequest_len);
+               }
+
+               req->sadb_x_ipsecrequest_proto = ipsec->cfg.esp.use ? IPPROTO_ESP
+                                                                                                                       : IPPROTO_AH;
                /* !!! the length here MUST be in octets instead of 64 bit words */
                req->sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest);
-               req->sadb_x_ipsecrequest_mode = mode2kernel(ipsec->cfg.mode);
+               req->sadb_x_ipsecrequest_mode = mode2kernel(proto_mode);
                req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid;
-               req->sadb_x_ipsecrequest_level = (policy->direction == POLICY_OUT) ?
-                                                                                 IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_USE;
-               if (ipsec->cfg.mode == MODE_TUNNEL)
+               req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
+               if (proto_mode == MODE_TUNNEL)
                {
                        len = hostcpy(req + 1, ipsec->src, FALSE);
                        req->sadb_x_ipsecrequest_len += len;
                        len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE);
                        req->sadb_x_ipsecrequest_len += len;
-                       /* use transport mode for other SAs */
-                       proto_mode = MODE_TRANSPORT;
                }
 
                pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
-               req = (struct sadb_x_ipsecrequest*)((char*)(req) +
-                                                                                       req->sadb_x_ipsecrequest_len);
        }
-
-       req->sadb_x_ipsecrequest_proto = ipsec->cfg.esp.use ? IPPROTO_ESP
-                                                                                                               : IPPROTO_AH;
-       /* !!! the length here MUST be in octets instead of 64 bit words */
-       req->sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest);
-       req->sadb_x_ipsecrequest_mode = mode2kernel(proto_mode);
-       req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid;
-       req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
-       if (proto_mode == MODE_TUNNEL)
-       {
-               len = hostcpy(req + 1, ipsec->src, FALSE);
-               req->sadb_x_ipsecrequest_len += len;
-               len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE);
-               req->sadb_x_ipsecrequest_len += len;
-       }
-
-       pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
        PFKEY_EXT_ADD(msg, pol);
 
        add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
@@ -2506,23 +2556,21 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
 }
 
 METHOD(kernel_ipsec_t, add_policy, status_t,
-       private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t priority)
+       private_kernel_pfkey_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        policy_entry_t *policy, *found = NULL;
        policy_sa_t *assigned_sa, *current_sa;
        enumerator_t *enumerator;
        bool update = TRUE;
 
-       if (dir2kernel(direction) == IPSEC_DIR_INVALID)
+       if (dir2kernel(id->dir) == IPSEC_DIR_INVALID)
        {       /* FWD policies are not supported on all platforms */
                return SUCCESS;
        }
 
        /* create a policy */
-       policy = create_policy_entry(src_ts, dst_ts, direction);
+       policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
 
        /* find a matching policy */
        this->mutex->lock(this->mutex);
@@ -2531,7 +2579,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
                                                                  (void**)&found, policy) == SUCCESS)
        {       /* use existing policy */
                DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
-                                         "refcount", src_ts, dst_ts, policy_dir_names, direction);
+                        "refcount", id->src_ts, id->dst_ts, policy_dir_names, id->dir);
                policy_entry_destroy(policy, this);
                policy = found;
        }
@@ -2542,15 +2590,21 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        }
 
        /* cache the assigned IPsec SA */
-       assigned_sa = policy_sa_create(this, direction, type, src, dst, src_ts,
-                                                                  dst_ts, sa);
-       assigned_sa->priority = get_priority(policy, priority);
+       assigned_sa = policy_sa_create(this, id->dir, data->type, data->src,
+                                                                  data->dst, id->src_ts, id->dst_ts, data->sa);
+       assigned_sa->priority = get_priority(policy, data->prio);
 
        /* insert the SA according to its priority */
        enumerator = policy->used_by->create_enumerator(policy->used_by);
        while (enumerator->enumerate(enumerator, (void**)&current_sa))
        {
-               if (current_sa->priority >= assigned_sa->priority)
+               if (current_sa->priority > assigned_sa->priority)
+               {
+                       break;
+               }
+               /* prefer SAs with a reqid over those without */
+               if (current_sa->priority == assigned_sa->priority &&
+                       (!current_sa->sa->cfg.reqid || assigned_sa->sa->cfg.reqid))
                {
                        break;
                }
@@ -2567,23 +2621,22 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        }
 
        DBG2(DBG_KNL, "%s policy %R === %R %N",
-                                  found ? "updating" : "adding", src_ts, dst_ts,
-                                  policy_dir_names, direction);
+                found ? "updating" : "adding", id->src_ts, id->dst_ts,
+                policy_dir_names, id->dir);
 
        if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS)
        {
                DBG1(DBG_KNL, "unable to %s policy %R === %R %N",
-                                          found ? "update" : "add", src_ts, dst_ts,
-                                          policy_dir_names, direction);
+                        found ? "update" : "add", id->src_ts, id->dst_ts,
+                        policy_dir_names, id->dir);
                return FAILED;
        }
        return SUCCESS;
 }
 
 METHOD(kernel_ipsec_t, query_policy, status_t,
-       private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-       time_t *use_time)
+       private_kernel_pfkey_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_query_policy_t *data, time_t *use_time)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -2592,16 +2645,16 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
        pfkey_msg_t response;
        size_t len;
 
-       if (dir2kernel(direction) == IPSEC_DIR_INVALID)
+       if (dir2kernel(id->dir) == IPSEC_DIR_INVALID)
        {       /* FWD policies are not supported on all platforms */
                return NOT_FOUND;
        }
 
-       DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
-                                  policy_dir_names, direction);
+       DBG2(DBG_KNL, "querying policy %R === %R %N", id->src_ts, id->dst_ts,
+                policy_dir_names, id->dir);
 
        /* create a policy */
-       policy = create_policy_entry(src_ts, dst_ts, direction);
+       policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
 
        /* find a matching policy */
        this->mutex->lock(this->mutex);
@@ -2609,8 +2662,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
                                                                  (linked_list_match_t)policy_entry_equals,
                                                                  (void**)&found, policy) != SUCCESS)
        {
-               DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found", src_ts,
-                                          dst_ts, policy_dir_names, direction);
+               DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found",
+                        id->src_ts, id->dst_ts, policy_dir_names, id->dir);
                policy_entry_destroy(policy, this);
                this->mutex->unlock(this->mutex);
                return NOT_FOUND;
@@ -2630,7 +2683,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
        pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
        pol->sadb_x_policy_id = policy->index;
        pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy));
-       pol->sadb_x_policy_dir = dir2kernel(direction);
+       pol->sadb_x_policy_dir = dir2kernel(id->dir);
        pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
        PFKEY_EXT_ADD(msg, pol);
 
@@ -2643,30 +2696,31 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
 
        if (pfkey_send(this, msg, &out, &len) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to query policy %R === %R %N", src_ts, dst_ts,
-                                          policy_dir_names, direction);
+               DBG1(DBG_KNL, "unable to query policy %R === %R %N", id->src_ts,
+                        id->dst_ts, policy_dir_names, id->dir);
                return FAILED;
        }
        else if (out->sadb_msg_errno)
        {
-               DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts,
-                                          dst_ts, policy_dir_names, direction,
-                                          strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+               DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)",
+                        id->src_ts, id->dst_ts, policy_dir_names, id->dir,
+                        strerror(out->sadb_msg_errno), out->sadb_msg_errno);
                free(out);
                return FAILED;
        }
        else if (parse_pfkey_message(out, &response) != SUCCESS)
        {
                DBG1(DBG_KNL, "unable to query policy %R === %R %N: parsing response "
-                                         "from kernel failed", src_ts, dst_ts, policy_dir_names,
-                                          direction);
+                        "from kernel failed", id->src_ts, id->dst_ts, policy_dir_names,
+                        id->dir);
                free(out);
                return FAILED;
        }
        else if (response.lft_current == NULL)
        {
                DBG2(DBG_KNL, "unable to query policy %R === %R %N: kernel reports no "
-                                         "use time", src_ts, dst_ts, policy_dir_names, direction);
+                        "use time", id->src_ts, id->dst_ts, policy_dir_names,
+                        id->dir);
                free(out);
                return FAILED;
        }
@@ -2686,10 +2740,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
 }
 
 METHOD(kernel_ipsec_t, del_policy, status_t,
-       private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t prio)
+       private_kernel_pfkey_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -2701,21 +2753,21 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
        uint32_t priority;
        size_t len;
        ipsec_sa_t assigned_sa = {
-               .src = src,
-               .dst = dst,
-               .cfg = *sa,
+               .src = data->src,
+               .dst = data->dst,
+               .cfg = *data->sa,
        };
 
-       if (dir2kernel(direction) == IPSEC_DIR_INVALID)
+       if (dir2kernel(id->dir) == IPSEC_DIR_INVALID)
        {       /* FWD policies are not supported on all platforms */
                return SUCCESS;
        }
 
-       DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
-                                  policy_dir_names, direction);
+       DBG2(DBG_KNL, "deleting policy %R === %R %N", id->src_ts, id->dst_ts,
+                policy_dir_names, id->dir);
 
        /* create a policy */
-       policy = create_policy_entry(src_ts, dst_ts, direction);
+       policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
 
        /* find a matching policy */
        this->mutex->lock(this->mutex);
@@ -2723,8 +2775,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
                                                                  (linked_list_match_t)policy_entry_equals,
                                                                  (void**)&found, policy) != SUCCESS)
        {
-               DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
-                                          dst_ts, policy_dir_names, direction);
+               DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found",
+                        id->src_ts, id->dst_ts, policy_dir_names, id->dir);
                policy_entry_destroy(policy, this);
                this->mutex->unlock(this->mutex);
                return NOT_FOUND;
@@ -2734,7 +2786,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
 
        /* remove mapping to SA by reqid and priority, if multiple match, which
         * could happen when rekeying due to an address change, remove the oldest */
-       priority = get_priority(policy, prio);
+       priority = get_priority(policy, data->prio);
        enumerator = policy->used_by->create_enumerator(policy->used_by);
        while (enumerator->enumerate(enumerator, (void**)&mapping))
        {
@@ -2762,7 +2814,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
        if (policy->used_by->get_count(policy->used_by) > 0)
        {       /* policy is used by more SAs, keep in kernel */
                DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
-               policy_sa_destroy(mapping, &direction, this);
+               policy_sa_destroy(mapping, &id->dir, this);
 
                if (!is_installed)
                {       /* no need to update as the policy was not installed for this SA */
@@ -2770,13 +2822,13 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
                        return SUCCESS;
                }
 
-               DBG2(DBG_KNL, "updating policy %R === %R %N", src_ts, dst_ts,
-                                          policy_dir_names, direction);
+               DBG2(DBG_KNL, "updating policy %R === %R %N", id->src_ts, id->dst_ts,
+                        policy_dir_names, id->dir);
                policy->used_by->get_first(policy->used_by, (void**)&mapping);
                if (add_policy_internal(this, policy, mapping, TRUE) != SUCCESS)
                {
                        DBG1(DBG_KNL, "unable to update policy %R === %R %N",
-                                                  src_ts, dst_ts, policy_dir_names, direction);
+                                id->src_ts, id->dst_ts, policy_dir_names, id->dir);
                        return FAILED;
                }
                return SUCCESS;
@@ -2793,7 +2845,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
        pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg);
        pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
        pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy));
-       pol->sadb_x_policy_dir = dir2kernel(direction);
+       pol->sadb_x_policy_dir = dir2kernel(id->dir);
        pol->sadb_x_policy_type = type2kernel(mapping->type);
        PFKEY_EXT_ADD(msg, pol);
 
@@ -2810,28 +2862,28 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
                                                                          route->src_ip, route->if_name) != SUCCESS)
                {
                        DBG1(DBG_KNL, "error uninstalling route installed with "
-                                                 "policy %R === %R %N", src_ts, dst_ts,
-                                                  policy_dir_names, direction);
+                                "policy %R === %R %N", id->src_ts, id->dst_ts,
+                                policy_dir_names, id->dir);
                }
                remove_exclude_route(this, route);
        }
 
        this->policies->remove(this->policies, found, NULL);
-       policy_sa_destroy(mapping, &direction, this);
+       policy_sa_destroy(mapping, &id->dir, this);
        policy_entry_destroy(policy, this);
        this->mutex->unlock(this->mutex);
 
        if (pfkey_send(this, msg, &out, &len) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts,
-                                          policy_dir_names, direction);
+               DBG1(DBG_KNL, "unable to delete policy %R === %R %N", id->src_ts,
+                        id->dst_ts, policy_dir_names, id->dir);
                return FAILED;
        }
        else if (out->sadb_msg_errno)
        {
-               DBG1(DBG_KNL, "unable to delete policy %R === %R %N: %s (%d)", src_ts,
-                                          dst_ts, policy_dir_names, direction,
-                                          strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+               DBG1(DBG_KNL, "unable to delete policy %R === %R %N: %s (%d)",
+                        id->src_ts, id->dst_ts, policy_dir_names, id->dir,
+                        strerror(out->sadb_msg_errno), out->sadb_msg_errno);
                free(out);
                return FAILED;
        }
index 086d06e..c12d384 100644 (file)
@@ -2093,57 +2093,55 @@ static void schedule_expire(private_kernel_wfp_ipsec_t *this, uint32_t spi,
 }
 
 METHOD(kernel_ipsec_t, add_sa, status_t,
-       private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
-       uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
-       uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
-       uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
-       bool initiator, bool encap, bool esn, bool inbound, bool update,
-       linked_list_t *src_ts, linked_list_t *dst_ts)
+       private_kernel_wfp_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_add_sa_t *data)
 {
        host_t *local, *remote;
        entry_t *entry;
 
-       if (inbound)
+       if (data->inbound)
        {
                /* comes first, create new entry */
-               local = dst->clone(dst);
-               remote = src->clone(src);
+               local = id->dst->clone(id->dst);
+               remote = id->src->clone(id->src);
 
                INIT(entry,
-                       .reqid = reqid,
+                       .reqid = data->reqid,
                        .isa = {
-                               .spi = spi,
+                               .spi = id->spi,
                                .dst = local,
-                               .protocol = protocol,
-                               .lifetime = lifetime->time.life,
+                               .protocol = id->proto,
+                               .lifetime = data->lifetime->time.life,
                                .encr = {
-                                       .alg = enc_alg,
-                                       .key = chunk_clone(enc_key),
+                                       .alg = data->enc_alg,
+                                       .key = chunk_clone(data->enc_key),
                                },
                                .integ = {
-                                       .alg = int_alg,
-                                       .key = chunk_clone(int_key),
+                                       .alg = data->int_alg,
+                                       .key = chunk_clone(data->int_key),
                                },
                        },
                        .sps = array_create(0, 0),
                        .local = local,
                        .remote = remote,
-                       .mode = mode,
-                       .encap = encap,
+                       .mode = data->mode,
+                       .encap = data->encap,
                );
 
-               if (lifetime->time.life)
+               if (data->lifetime->time.life)
                {
-                       schedule_expire(this, spi, local, lifetime->time.life, TRUE);
+                       schedule_expire(this, id->spi, local,
+                                                       data->lifetime->time.life, TRUE);
                }
-               if (lifetime->time.rekey && lifetime->time.rekey != lifetime->time.life)
+               if (data->lifetime->time.rekey &&
+                       data->lifetime->time.rekey != data->lifetime->time.life)
                {
-                       schedule_expire(this, spi, local, lifetime->time.rekey, FALSE);
+                       schedule_expire(this, id->spi, local,
+                                                       data->lifetime->time.rekey, FALSE);
                }
 
                this->mutex->lock(this->mutex);
-               this->tsas->put(this->tsas, (void*)(uintptr_t)reqid, entry);
+               this->tsas->put(this->tsas, (void*)(uintptr_t)data->reqid, entry);
                this->isas->put(this->isas, &entry->isa, entry);
                this->mutex->unlock(this->mutex);
        }
@@ -2151,29 +2149,29 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        {
                /* comes after inbound, update entry */
                this->mutex->lock(this->mutex);
-               entry = this->tsas->remove(this->tsas, (void*)(uintptr_t)reqid);
+               entry = this->tsas->remove(this->tsas, (void*)(uintptr_t)data->reqid);
                this->mutex->unlock(this->mutex);
 
                if (!entry)
                {
                        DBG1(DBG_KNL, "adding outbound SA failed, no inbound SA found "
-                                "for reqid %u ", reqid);
+                                "for reqid %u ", data->reqid);
                        return NOT_FOUND;
                }
                /* TODO: should we check for local/remote, mode etc.? */
 
                entry->osa = (sa_entry_t){
-                       .spi = spi,
+                       .spi = id->spi,
                        .dst = entry->remote,
-                       .protocol = protocol,
-                       .lifetime = lifetime->time.life,
+                       .protocol = id->proto,
+                       .lifetime = data->lifetime->time.life,
                        .encr = {
-                               .alg = enc_alg,
-                               .key = chunk_clone(enc_key),
+                               .alg = data->enc_alg,
+                               .key = chunk_clone(data->enc_key),
                        },
                        .integ = {
-                               .alg = int_alg,
-                               .key = chunk_clone(int_key),
+                               .alg = data->int_alg,
+                               .key = chunk_clone(data->int_key),
                        },
                };
 
@@ -2186,14 +2184,13 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 }
 
 METHOD(kernel_ipsec_t, update_sa, status_t,
-       private_kernel_wfp_ipsec_t *this, uint32_t spi, uint8_t protocol,
-       uint16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-       bool encap, bool new_encap, mark_t mark)
+       private_kernel_wfp_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_update_sa_t *data)
 {
        entry_t *entry;
        sa_entry_t key = {
-               .dst = dst,
-               .spi = spi,
+               .dst = id->dst,
+               .spi = id->spi,
        };
        UINT64 sa_id = 0;
        IPSEC_SA_CONTEXT1 *ctx;
@@ -2233,16 +2230,16 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
                DBG1(DBG_KNL, "getting WFP SA context for updated failed: 0x%08x", res);
                return FAILED;
        }
-       if (!hosts2traffic(this, new_dst, new_src, &ctx->inboundSa->traffic) ||
-               !hosts2traffic(this, new_dst, new_src, &ctx->outboundSa->traffic))
+       if (!hosts2traffic(this, data->new_dst, data->new_src, &ctx->inboundSa->traffic) ||
+               !hosts2traffic(this, data->new_dst, data->new_src, &ctx->outboundSa->traffic))
        {
                FwpmFreeMemory0((void**)&ctx);
                return FAILED;
        }
 
-       if (new_encap != encap)
+       if (data->new_encap != data->encap)
        {
-               if (new_encap)
+               if (data->new_encap)
                {
                        ctx->inboundSa->udpEncapsulation = &ports;
                        ctx->outboundSa->udpEncapsulation = &ports;
@@ -2273,8 +2270,8 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
 
                entry->local->destroy(entry->local);
                entry->remote->destroy(entry->remote);
-               entry->local = new_dst->clone(new_dst);
-               entry->remote = new_src->clone(new_src);
+               entry->local = data->new_dst->clone(data->new_dst);
+               entry->remote = data->new_src->clone(data->new_src);
                entry->isa.dst = entry->local;
                entry->osa.dst = entry->remote;
 
@@ -2290,9 +2287,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
 }
 
 METHOD(kernel_ipsec_t, query_sa, status_t,
-       private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, mark_t mark, uint64_t *bytes,
-       uint64_t *packets, time_t *time)
+       private_kernel_wfp_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
+       time_t *time)
 {
        /* It does not seem that WFP provides any means of getting per-SA traffic
         * statistics. IPsecGetStatistics0/1() provides global stats, and
@@ -2302,13 +2299,13 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
 }
 
 METHOD(kernel_ipsec_t, del_sa, status_t,
-       private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
+       private_kernel_wfp_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_del_sa_t *data)
 {
        entry_t *entry;
        sa_entry_t key = {
-               .dst = dst,
-               .spi = spi,
+               .dst = id->dst,
+               .spi = id->spi,
        };
 
        this->mutex->lock(this->mutex);
@@ -2341,25 +2338,23 @@ METHOD(kernel_ipsec_t, flush_sas, status_t,
 }
 
 METHOD(kernel_ipsec_t, add_policy, status_t,
-       private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark,
-       policy_priority_t priority)
+       private_kernel_wfp_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        status_t status = SUCCESS;
        entry_t *entry;
        sp_entry_t *sp;
        sa_entry_t key = {
-               .spi = sa->esp.use ? sa->esp.spi : sa->ah.spi,
-               .dst = dst,
+               .spi = data->sa->esp.use ? data->sa->esp.spi : data->sa->ah.spi,
+               .dst = data->dst,
        };
 
-       if (sa->esp.use && sa->ah.use)
+       if (data->sa->esp.use && data->sa->ah.use)
        {
                return NOT_SUPPORTED;
        }
 
-       switch (type)
+       switch (data->type)
        {
                case POLICY_IPSEC:
                        break;
@@ -2368,7 +2363,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
                        return NOT_SUPPORTED;
        }
 
-       switch (direction)
+       switch (id->dir)
        {
                case POLICY_OUT:
                        break;
@@ -2380,18 +2375,20 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
                        return NOT_SUPPORTED;
        }
 
-       switch (priority)
+       switch (data->prio)
        {
                case POLICY_PRIORITY_DEFAULT:
                        break;
                case POLICY_PRIORITY_ROUTED:
-                       if (!add_trap(this, sa->reqid, FALSE, src, dst, src_ts, dst_ts))
+                       if (!add_trap(this, data->sa->reqid, FALSE, data->src, data->dst,
+                                                 id->src_ts, id->dst_ts))
                        {
                                return FAILED;
                        }
-                       if (sa->mode == MODE_TUNNEL)
+                       if (data->sa->mode == MODE_TUNNEL)
                        {
-                               if (!add_trap(this, sa->reqid, TRUE, src, dst, src_ts, dst_ts))
+                               if (!add_trap(this, data->sa->reqid, TRUE, data->src, data->dst,
+                                                         id->src_ts, id->dst_ts))
                                {
                                        return FAILED;
                                }
@@ -2406,14 +2403,14 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        entry = this->osas->get(this->osas, &key);
        if (entry)
        {
-               if (sa->mode == MODE_TUNNEL || array_count(entry->sps) == 0)
+               if (data->sa->mode == MODE_TUNNEL || array_count(entry->sps) == 0)
                {
                        INIT(sp,
-                               .src = src_ts->clone(src_ts),
-                               .dst = dst_ts->clone(dst_ts),
+                               .src = id->src_ts->clone(id->src_ts),
+                               .dst = id->dst_ts->clone(id->dst_ts),
                        );
                        array_insert(entry->sps, -1, sp);
-                       if (array_count(entry->sps) == sa->policy_count)
+                       if (array_count(entry->sps) == data->sa->policy_count)
                        {
                                if (!install(this, entry))
                                {
@@ -2442,25 +2439,24 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
 }
 
 METHOD(kernel_ipsec_t, query_policy, status_t,
-       private_kernel_wfp_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-       time_t *use_time)
+       private_kernel_wfp_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_query_policy_t *data, time_t *use_time)
 {
        /* see query_sa() for some notes */
        return NOT_SUPPORTED;
 }
 
 METHOD(kernel_ipsec_t, del_policy, status_t,
-       private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t priority)
+       private_kernel_wfp_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
-       if (direction == POLICY_OUT && priority == POLICY_PRIORITY_ROUTED)
+       if (id->dir == POLICY_OUT && data->prio == POLICY_PRIORITY_ROUTED)
        {
-               if (remove_trap(this, sa->reqid, FALSE, src_ts, dst_ts))
+               if (remove_trap(this, data->sa->reqid, FALSE, id->src_ts,
+                                               id->dst_ts))
                {
-                       remove_trap(this, sa->reqid, TRUE, src_ts, dst_ts);
+                       remove_trap(this, data->sa->reqid, TRUE, id->src_ts,
+                                               id->dst_ts);
                        return SUCCESS;
                }
                return NOT_FOUND;
index 9366556..28421c2 100644 (file)
@@ -688,13 +688,25 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
        peer_cfg_t *peer_cfg;
        char local[32], *remote;
        host_t *addr;
-       ipsec_mode_t mode = MODE_TUNNEL;
-       lifetime_cfg_t lifetime = {
-               .time = {
-                       .life = this->child_rekey * 2,
-                       .rekey = this->child_rekey,
-                       .jitter = 0
-               }
+       peer_cfg_create_t peer = {
+               .cert_policy = CERT_SEND_IF_ASKED,
+               .unique = UNIQUE_NO,
+               .keyingtries = 1,
+               .rekey_time = this->ike_rekey,
+               .over_time = this->ike_rekey,
+               .no_mobike = TRUE,
+               .dpd = this->dpd_delay,
+               .dpd_timeout = this->dpd_timeout,
+       };
+       child_cfg_create_t child = {
+               .lifetime = {
+                       .time = {
+                               .life = this->child_rekey * 2,
+                               .rekey = this->child_rekey,
+                               .jitter = 0
+                       },
+               },
+               .mode = MODE_TUNNEL,
        };
 
        if (num)
@@ -737,14 +749,8 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
                                                                 FRAGMENTATION_NO, 0);
        }
        ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
-       peer_cfg = peer_cfg_create("load-test", ike_cfg,
-                                                          CERT_SEND_IF_ASKED, UNIQUE_NO, 1, /* keytries */
-                                                          this->ike_rekey, 0, /* rekey, reauth */
-                                                          0, this->ike_rekey, /* jitter, overtime */
-                                                          FALSE, FALSE, TRUE, /* mobike, aggressive, pull */
-                                                          this->dpd_delay,   /* dpd_delay */
-                                                          this->dpd_timeout, /* dpd_timeout */
-                                                          FALSE, NULL, NULL);
+       peer_cfg = peer_cfg_create("load-test", ike_cfg, &peer);
+
        if (this->vip)
        {
                peer_cfg->add_virtual_ip(peer_cfg, this->vip->clone(this->vip));
@@ -768,17 +774,15 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
        {
                if (streq(this->mode, "transport"))
                {
-                       mode = MODE_TRANSPORT;
+                       child.mode = MODE_TRANSPORT;
                }
                else if (streq(this->mode, "beet"))
                {
-                       mode = MODE_BEET;
+                       child.mode = MODE_BEET;
                }
        }
 
-       child_cfg = child_cfg_create("load-test", &lifetime, NULL, TRUE, mode,
-                                                                ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
-                                                                0, 0, NULL, NULL, 0);
+       child_cfg = child_cfg_create("load-test", &child);
        child_cfg->add_proposal(child_cfg, this->esp->clone(this->esp));
 
        if (num)
index deca190..4e20c8f 100644 (file)
@@ -50,63 +50,52 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
 }
 
 METHOD(kernel_ipsec_t, add_sa, status_t,
-       private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint32_t reqid, mark_t mark,
-       uint32_t tfc, lifetime_cfg_t *lifetime, uint16_t enc_alg, chunk_t enc_key,
-       uint16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
-       uint16_t ipcomp, uint16_t cpi, uint32_t replay_window,
-       bool initiator, bool encap, bool esn, bool inbound, bool update,
-       linked_list_t *src_ts, linked_list_t *dst_ts)
+       private_load_tester_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_add_sa_t *data)
 {
        return SUCCESS;
 }
 
 METHOD(kernel_ipsec_t, update_sa, status_t,
-       private_load_tester_ipsec_t *this, uint32_t spi, uint8_t protocol,
-       uint16_t cpi, host_t *src, host_t *dst, host_t *new_src,
-       host_t *new_dst, bool encap, bool new_encap, mark_t mark)
+       private_load_tester_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_update_sa_t *data)
 {
        return SUCCESS;
 }
 
 METHOD(kernel_ipsec_t, query_sa, status_t,
-       private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, mark_t mark,
-       uint64_t *bytes, uint64_t *packets, time_t *time)
+       private_load_tester_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
+       time_t *time)
 {
        return NOT_SUPPORTED;
 }
 
 METHOD(kernel_ipsec_t, del_sa, status_t,
-       private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
-       uint32_t spi, uint8_t protocol, uint16_t cpi, mark_t mark)
+       private_load_tester_ipsec_t *this, kernel_ipsec_sa_id_t *id,
+       kernel_ipsec_del_sa_t *data)
 {
        return SUCCESS;
 }
 
 METHOD(kernel_ipsec_t, add_policy, status_t,
-       private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t priority)
+       private_load_tester_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        return SUCCESS;
 }
 
 METHOD(kernel_ipsec_t, query_policy, status_t,
-       private_load_tester_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-       time_t *use_time)
+       private_load_tester_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_query_policy_t *data, time_t *use_time)
 {
        *use_time = 1;
        return SUCCESS;
 }
 
 METHOD(kernel_ipsec_t, del_policy, status_t,
-       private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-       policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-       mark_t mark, policy_priority_t priority)
+       private_load_tester_ipsec_t *this, kernel_ipsec_policy_id_t *id,
+       kernel_ipsec_manage_policy_t *data)
 {
        return SUCCESS;
 }
index 2e96f8f..3e5861b 100644 (file)
@@ -236,12 +236,23 @@ static gboolean initiate_connection(private_maemo_service_t *this,
        traffic_selector_t *ts;
        auth_cfg_t *auth;
        certificate_t *cert;
-       lifetime_cfg_t lifetime = {
-               .time = {
-                       .life = 10800, /* 3h */
-                       .rekey = 10200, /* 2h50min */
-                       .jitter = 300 /* 5min */
-               }
+       peer_cfg_create_t peer = {
+               .cert_policy = CERT_SEND_IF_ASKED,
+               .unique = UNIQUE_REPLACE,
+               .keyingtries = 1,
+               .rekey_time = 36000, /* 10h */
+               .jitter_time = 600, /* 10min */
+               .over_time = 600, /* 10min */
+       };
+       child_cfg_create_t child = {
+               .lifetime = {
+                       .time = {
+                               .life = 10800, /* 3h */
+                               .rekey = 10200, /* 2h50min */
+                               .jitter = 300 /* 5min */
+                       },
+               },
+               .mode = MODE_TUNNEL,
        };
 
        if (this->status == VPN_STATUS_CONNECTED ||
@@ -329,14 +340,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
        ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
 
-       peer_cfg = peer_cfg_create(this->current, ike_cfg,
-                                                          CERT_SEND_IF_ASKED,
-                                                          UNIQUE_REPLACE, 1, /* keyingtries */
-                                                          36000, 0, /* rekey 10h, reauth none */
-                                                          600, 600, /* jitter, over 10min */
-                                                          TRUE, FALSE, TRUE, /* mobike, aggressive, pull */
-                                                          0, 0, /* DPD delay, timeout */
-                                                          FALSE, NULL, NULL); /* mediation */
+       peer_cfg = peer_cfg_create(this->current, ike_cfg, &peer);
        peer_cfg->add_virtual_ip(peer_cfg,  host_create_from_string("0.0.0.0", 0));
 
        auth = auth_cfg_create();
@@ -348,9 +352,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
        auth->add(auth, AUTH_RULE_IDENTITY, gateway);
        peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
 
-       child_cfg = child_cfg_create(this->current, &lifetime, NULL /* updown */,
-                                                                TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE,
-                                                                ACTION_NONE, FALSE, 0, 0, NULL, NULL, 0);
+       child_cfg = child_cfg_create(this->current, &child);
        child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
        ts = traffic_selector_create_dynamic(0, 0, 65535);
index 25b1383..4452739 100644 (file)
@@ -82,12 +82,25 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
        child_cfg_t *child_cfg;
        chunk_t me, other;
        char *address, *local_net, *remote_net;
-       lifetime_cfg_t lifetime = {
-               .time = {
-                       .life = this->rekey * 60 + this->rekey,
-                       .rekey = this->rekey,
-                       .jitter = this->rekey
-               }
+       peer_cfg_create_t peer = {
+               .cert_policy = CERT_NEVER_SEND,
+               .unique = UNIQUE_REPLACE,
+               .keyingtries = 1,
+               .rekey_time = this->rekey * 60,
+               .jitter_time = this->rekey * 5,
+               .over_time = this->rekey * 3,
+               .dpd = this->dpd,
+               .mediation = TRUE,
+       };
+       child_cfg_create_t child = {
+               .lifetime = {
+                       .time = {
+                               .life = this->rekey * 60 + this->rekey,
+                               .rekey = this->rekey,
+                               .jitter = this->rekey
+                       },
+               },
+               .mode = MODE_TUNNEL,
        };
 
        /* query mediation server config:
@@ -107,14 +120,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
                                                         address, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
        ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
-       med_cfg = peer_cfg_create(
-               "mediation", ike_cfg,
-               CERT_NEVER_SEND, UNIQUE_REPLACE,
-               1, this->rekey*60, 0,                   /* keytries, rekey, reauth */
-               this->rekey*5, this->rekey*3,   /* jitter, overtime */
-               TRUE, FALSE, TRUE,                              /* mobike, aggressive, pull */
-               this->dpd, 0,                                   /* DPD delay, timeout */
-               TRUE, NULL, NULL);                              /* mediation, med by, peer id */
+       med_cfg = peer_cfg_create("mediation", ike_cfg, &peer);
        e->destroy(e);
 
        auth = auth_cfg_create();
@@ -144,15 +150,10 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
                DESTROY_IF(e);
                return NULL;
        }
-       peer_cfg = peer_cfg_create(
-               name, this->ike->get_ref(this->ike),
-               CERT_NEVER_SEND, UNIQUE_REPLACE,
-               1, this->rekey*60, 0,                   /* keytries, rekey, reauth */
-               this->rekey*5, this->rekey*3,   /* jitter, overtime */
-               TRUE, FALSE, TRUE,                              /* mobike, aggressive, pull */
-               this->dpd, 0,                                   /* DPD delay, timeout */
-               FALSE, med_cfg,                                 /* mediation, med by */
-               identification_create_from_encoding(ID_KEY_ID, other));
+       peer.mediation = FALSE;
+       peer.mediated_by = med_cfg;
+       peer.peer_id = identification_create_from_encoding(ID_KEY_ID, other);
+       peer_cfg = peer_cfg_create(name, this->ike->get_ref(this->ike), &peer);
 
        auth = auth_cfg_create();
        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
@@ -165,9 +166,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
                          identification_create_from_encoding(ID_KEY_ID, other));
        peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
 
-       child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
-                                                                ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
-                                                                0, 0, NULL, NULL, 0);
+       child_cfg = child_cfg_create(name, &child);
        child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
        child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
@@ -205,12 +204,24 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
        chunk_t me, other;
        child_cfg_t *child_cfg;
        auth_cfg_t *auth;
-       lifetime_cfg_t lifetime = {
-               .time = {
-                       .life = this->rekey * 60 + this->rekey,
-                       .rekey = this->rekey,
-                       .jitter = this->rekey
-               }
+       peer_cfg_create_t peer = {
+               .cert_policy = CERT_NEVER_SEND,
+               .unique = UNIQUE_REPLACE,
+               .keyingtries = 1,
+               .rekey_time = this->rekey * 60,
+               .jitter_time = this->rekey * 5,
+               .over_time = this->rekey * 3,
+               .dpd = this->dpd,
+       };
+       child_cfg_create_t child = {
+               .lifetime = {
+                       .time = {
+                               .life = this->rekey * 60 + this->rekey,
+                               .rekey = this->rekey,
+                               .jitter = this->rekey
+                       },
+               },
+               .mode = MODE_TUNNEL,
        };
 
        DESTROY_IF(this->current);
@@ -220,14 +231,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
                this->current = NULL;
                return FALSE;
        }
-       this->current = peer_cfg_create(
-                               name, this->ike->get_ref(this->ike),
-                               CERT_NEVER_SEND, UNIQUE_REPLACE,
-                               1, this->rekey*60, 0,                   /* keytries, rekey, reauth */
-                               this->rekey*5, this->rekey*3,   /* jitter, overtime */
-                               TRUE, FALSE, TRUE,                              /* mobike, aggressive, pull */
-                               this->dpd, 0,                                   /* DPD delay, timeout */
-                               FALSE, NULL, NULL);                             /* mediation, med by, peer id */
+       this->current = peer_cfg_create(name, this->ike->get_ref(this->ike), &peer);
 
        auth = auth_cfg_create();
        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
@@ -240,9 +244,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
                          identification_create_from_encoding(ID_KEY_ID, other));
        this->current->add_auth_cfg(this->current, auth, FALSE);
 
-       child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
-                                                                ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
-                                                                0, 0, NULL, NULL, 0);
+       child_cfg = child_cfg_create(name, &child);
        child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
        child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
index 02d805e..be7f481 100644 (file)
@@ -87,14 +87,18 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
 
                if (e->enumerate(e, &name))
                {
-                       peer_cfg = peer_cfg_create(
-                               name, this->ike->get_ref(this->ike),
-                               CERT_NEVER_SEND, UNIQUE_REPLACE,
-                               1, this->rekey*60, 0,                   /* keytries, rekey, reauth */
-                               this->rekey*5, this->rekey*3,   /* jitter, overtime */
-                               TRUE, FALSE, TRUE,                              /* mobike, aggressive, pull */
-                               this->dpd, 0,                                   /* DPD delay, timeout */
-                               TRUE, NULL, NULL);                              /* mediation, med by, peer id */
+                       peer_cfg_create_t peer = {
+                               .cert_policy = CERT_NEVER_SEND,
+                               .unique = UNIQUE_REPLACE,
+                               .keyingtries = 1,
+                               .rekey_time = this->rekey * 60,
+                               .jitter_time = this->rekey * 5,
+                               .over_time = this->rekey * 3,
+                               .dpd = this->dpd,
+                               .mediation = TRUE,
+                       };
+                       peer_cfg = peer_cfg_create(name, this->ike->get_ref(this->ike),
+                                                                          &peer);
                        e->destroy(e);
 
                        auth = auth_cfg_create();
index ce24d18..bbc20dc 100644 (file)
@@ -170,12 +170,22 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
        if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter, &updown,
                                                &hostaccess, &mode, &start, &dpd, &close, &ipcomp, &reqid))
        {
-               lifetime_cfg_t lft = {
-                       .time = { .life = lifetime, .rekey = rekeytime, .jitter = jitter }
+               child_cfg_create_t child = {
+                       .mode = mode,
+                       .reqid = reqid,
+                       .ipcomp = ipcomp,
+                       .lifetime = {
+                               .time = {
+                                       .life = lifetime, .rekey = rekeytime, .jitter = jitter
+                               },
+                       },
+                       .start_action = start,
+                       .dpd_action = dpd,
+                       .close_action = close,
+                       .updown = updown,
+                       .hostaccess = hostaccess,
                };
-               child_cfg = child_cfg_create(name, &lft, updown, hostaccess, mode,
-                                                                        start, dpd, close, ipcomp, 0, reqid,
-                                                                        NULL, NULL, 0);
+               child_cfg = child_cfg_create(name, &child);
                add_esp_proposals(this, child_cfg, id);
                add_traffic_selectors(this, child_cfg, id);
                return child_cfg;
@@ -290,6 +300,7 @@ static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id)
        return ike_cfg;
 }
 
+#ifdef ME
 /**
  * Query a peer config by its id
  */
@@ -322,6 +333,7 @@ static peer_cfg_t *get_peer_cfg_by_id(private_sql_config_t *this, int id)
        }
        return peer_cfg;
 }
+#endif /* ME */
 
 /**
  * Check if the two IDs match (the first one is optional)
@@ -353,7 +365,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
                        &mediation, &mediated_by, &p_type, &p_data))
        {
                identification_t *local_id, *remote_id, *peer_id = NULL;
-               peer_cfg_t *peer_cfg, *mediated_cfg;
+               peer_cfg_t *peer_cfg, *mediated_cfg = NULL;
                ike_cfg_t *ike;
                host_t *vip = NULL;
                auth_cfg_t *auth;
@@ -367,22 +379,38 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
                        continue;
                }
                ike = get_ike_cfg_by_id(this, ike_cfg);
+
+#ifdef ME
                mediated_cfg = mediated_by ? get_peer_cfg_by_id(this, mediated_by) : NULL;
                if (p_type)
                {
                  &n