From 122b4b6e6d948b1b5ffac7d4e99030ae4d53a189 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 20 Feb 2013 16:15:39 +0100 Subject: [PATCH 1/2] Include local address for Unity Split-Exclude shunt policies If we use a virtual IP, having a shunt policy for just that wouldn't work, as we want a shunt bypass using the local address. --- src/libcharon/plugins/unity/unity_handler.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/libcharon/plugins/unity/unity_handler.c b/src/libcharon/plugins/unity/unity_handler.c index 31d13add2..30573c7ff 100644 --- a/src/libcharon/plugins/unity/unity_handler.c +++ b/src/libcharon/plugins/unity/unity_handler.c @@ -174,7 +174,6 @@ static job_requeue_t add_exclude_async(entry_t *entry) ike_sa_t *ike_sa; char name[128]; host_t *host; - bool has_vip = FALSE; ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, entry->sa, FALSE); @@ -187,23 +186,19 @@ static job_requeue_t add_exclude_async(entry_t *entry) FALSE, 0, 0, NULL, NULL, FALSE); child_cfg->add_traffic_selector(child_cfg, FALSE, entry->ts->clone(entry->ts)); + host = ike_sa->get_my_host(ike_sa); + child_cfg->add_traffic_selector(child_cfg, TRUE, + traffic_selector_create_from_subnet(host->clone(host), 32, 0, 0)); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE); while (enumerator->enumerate(enumerator, &host)) { - has_vip = TRUE; child_cfg->add_traffic_selector(child_cfg, TRUE, traffic_selector_create_from_subnet(host->clone(host), 32, 0, 0)); } enumerator->destroy(enumerator); - if (!has_vip) - { - host = ike_sa->get_my_host(ike_sa); - child_cfg->add_traffic_selector(child_cfg, TRUE, - traffic_selector_create_from_subnet(host->clone(host), 32, 0, 0)); - } - charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); - charon->shunts->install(charon->shunts, child_cfg); child_cfg->destroy(child_cfg); From a2fd08dd26eadb75c4a58506fd916a9adf6d23b3 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 20 Feb 2013 16:17:31 +0100 Subject: [PATCH 2/2] Install a route for shunt policies If we install a virtual IP, its source route would render the shunt policy useless, as locally generated traffic wouldn't match. Having a route for each shunt policy with higher priority chooses the correct source address for bypassed destinations. --- .../kernel_netlink/kernel_netlink_ipsec.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c index f9b2634a0..47df381b4 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -2196,14 +2196,15 @@ 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) - * - we are in tunnel/BEET mode + * - we are in tunnel/BEET mode or install a bypass policy * - routing is not disabled via strongswan.conf */ - if (policy->direction == POLICY_FWD && - ipsec->cfg.mode != MODE_TRANSPORT && this->install_routes) + if (policy->direction == POLICY_FWD && this->install_routes && + (mapping->type != POLICY_IPSEC || ipsec->cfg.mode != MODE_TRANSPORT)) { policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)mapping; route_entry_t *route; + host_t *iface; INIT(route, .prefixlen = policy->sel.prefixlen_s, @@ -2219,9 +2220,17 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this, route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16); memcpy(route->dst_net.ptr, &policy->sel.saddr, route->dst_net.len); + /* get the interface to install the route for. If we have a local + * address, use it. Otherwise (for shunt policies) use the + * routes source address. */ + iface = ipsec->dst; + if (iface->is_anyaddr(iface)) + { + iface = route->src_ip; + } /* install route via outgoing interface */ if (!hydra->kernel_interface->get_interface(hydra->kernel_interface, - ipsec->dst, &route->if_name)) + iface, &route->if_name)) { this->mutex->unlock(this->mutex); route_entry_destroy(route); @@ -2822,4 +2831,3 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create() return &this->public; } -