Merge branch 'nat-transport'
Enable transport mode in NAT situations when using IKEv2. Additionally brings an extended leftsubnet format, where each subnet can take a separate protocol and port.
This commit is contained in:
+34
-24
@@ -731,29 +731,10 @@ different from the default additionally requires a socket implementation that
|
|||||||
listens on this port.
|
listens on this port.
|
||||||
.TP
|
.TP
|
||||||
.BR leftprotoport " = <protocol>/<port>"
|
.BR leftprotoport " = <protocol>/<port>"
|
||||||
restrict the traffic selector to a single protocol and/or port.
|
restrict the traffic selector to a single protocol and/or port. This option
|
||||||
Examples:
|
is now deprecated, protocol/port information can be defined for each subnet
|
||||||
.B leftprotoport=tcp/http
|
directly in
|
||||||
or
|
.BR leftsubnet .
|
||||||
.B leftprotoport=6/80
|
|
||||||
or
|
|
||||||
.B leftprotoport=udp
|
|
||||||
or
|
|
||||||
.BR leftprotoport=/53 .
|
|
||||||
Instead of omitting either value
|
|
||||||
.B %any
|
|
||||||
can be used to the same effect, e.g.
|
|
||||||
.B leftprotoport=udp/%any
|
|
||||||
or
|
|
||||||
.BR leftprotoport=%any/53 .
|
|
||||||
|
|
||||||
The port value can alternatively take the value
|
|
||||||
.B %opaque
|
|
||||||
for RFC 4301 OPAQUE selectors, or a numerical range in the form
|
|
||||||
.BR 1024-65535 .
|
|
||||||
None of the kernel backends currently supports opaque or port ranges and uses
|
|
||||||
.B %any
|
|
||||||
for policy installation instead.
|
|
||||||
.TP
|
.TP
|
||||||
.BR leftsigkey " = <raw public key> | <path to public key>"
|
.BR leftsigkey " = <raw public key> | <path to public key>"
|
||||||
the left participant's public key for public key signature authentication,
|
the left participant's public key for public key signature authentication,
|
||||||
@@ -807,7 +788,7 @@ echoed back. Also supported are address pools expressed as
|
|||||||
or the use of an external IP address pool using %\fIpoolname\fR,
|
or the use of an external IP address pool using %\fIpoolname\fR,
|
||||||
where \fIpoolname\fR is the name of the IP address pool used for the lookup.
|
where \fIpoolname\fR is the name of the IP address pool used for the lookup.
|
||||||
.TP
|
.TP
|
||||||
.BR leftsubnet " = <ip subnet>"
|
.BR leftsubnet " = <ip subnet>[:<proto/port>][,...]"
|
||||||
private subnet behind the left participant, expressed as
|
private subnet behind the left participant, expressed as
|
||||||
\fInetwork\fB/\fInetmask\fR;
|
\fInetwork\fB/\fInetmask\fR;
|
||||||
if omitted, essentially assumed to be \fIleft\fB/32\fR,
|
if omitted, essentially assumed to be \fIleft\fB/32\fR,
|
||||||
@@ -818,6 +799,35 @@ implementations, make sure to configure identical subnets in such
|
|||||||
configurations. IKEv2 supports multiple subnets separated by commas. IKEv1 only
|
configurations. IKEv2 supports multiple subnets separated by commas. IKEv1 only
|
||||||
interprets the first subnet of such a definition, unless the Cisco Unity
|
interprets the first subnet of such a definition, unless the Cisco Unity
|
||||||
extension plugin is enabled.
|
extension plugin is enabled.
|
||||||
|
|
||||||
|
The part in each subnet following an optional colon specifies a protocol/port
|
||||||
|
to restrict the selector for that subnet.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.BR leftsubnet=10.0.0.1:tcp/http,10.0.0.2:6/80,10.0.0.3:udp,10.0.0.0/16:/53 .
|
||||||
|
Instead of omitting either value
|
||||||
|
.B %any
|
||||||
|
can be used to the same effect, e.g.
|
||||||
|
.BR leftsubnet=10.0.0.3:udp/%any,10.0.0.0/16=%any/53 .
|
||||||
|
|
||||||
|
The port value can alternatively take the value
|
||||||
|
.B %opaque
|
||||||
|
for RFC 4301 OPAQUE selectors, or a numerical range in the form
|
||||||
|
.BR 1024-65535 .
|
||||||
|
None of the kernel backends currently supports opaque or port ranges and uses
|
||||||
|
.B %any
|
||||||
|
for policy installation instead.
|
||||||
|
|
||||||
|
Instead of specifying a subnet,
|
||||||
|
.B %dynamic
|
||||||
|
can be used to replace it with the IKE address, having the same effect
|
||||||
|
as omitting
|
||||||
|
.B leftsubnet
|
||||||
|
completely. Using
|
||||||
|
.B %dynamic
|
||||||
|
can be used to define multiple dynamic selectors, each having a potentially
|
||||||
|
different protocol/port definiton.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR leftupdown " = <path>"
|
.BR leftupdown " = <path>"
|
||||||
what ``updown'' script to run to adjust routing and/or firewalling
|
what ``updown'' script to run to adjust routing and/or firewalling
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
#include <threading/mutex.h>
|
#include <threading/mutex.h>
|
||||||
#include <utils/lexparser.h>
|
#include <utils/lexparser.h>
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
typedef struct private_stroke_config_t private_stroke_config_t;
|
typedef struct private_stroke_config_t private_stroke_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -882,6 +884,89 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
|
|||||||
return peer_cfg;
|
return peer_cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a protoport specifier
|
||||||
|
*/
|
||||||
|
static bool parse_protoport(char *token, u_int16_t *from_port,
|
||||||
|
u_int16_t *to_port, u_int8_t *protocol)
|
||||||
|
{
|
||||||
|
char *sep, *port = "", *endptr;
|
||||||
|
struct protoent *proto;
|
||||||
|
struct servent *svc;
|
||||||
|
long int p;
|
||||||
|
|
||||||
|
sep = strchr(token, '/');
|
||||||
|
if (sep)
|
||||||
|
{ /* protocol/port */
|
||||||
|
*sep = '\0';
|
||||||
|
port = sep + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streq(token, "%any"))
|
||||||
|
{
|
||||||
|
*protocol = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
proto = getprotobyname(token);
|
||||||
|
if (proto)
|
||||||
|
{
|
||||||
|
*protocol = proto->p_proto;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = strtol(token, &endptr, 0);
|
||||||
|
if ((*token && *endptr) || p < 0 || p > 0xff)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*protocol = (u_int8_t)p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (streq(port, "%any"))
|
||||||
|
{
|
||||||
|
*from_port = 0;
|
||||||
|
*to_port = 0xffff;
|
||||||
|
}
|
||||||
|
else if (streq(port, "%opaque"))
|
||||||
|
{
|
||||||
|
*from_port = 0xffff;
|
||||||
|
*to_port = 0;
|
||||||
|
}
|
||||||
|
else if (*port)
|
||||||
|
{
|
||||||
|
svc = getservbyname(port, NULL);
|
||||||
|
if (svc)
|
||||||
|
{
|
||||||
|
*from_port = *to_port = ntohs(svc->s_port);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = strtol(port, &endptr, 0);
|
||||||
|
if (p < 0 || p > 0xffff)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*from_port = p;
|
||||||
|
if (*endptr == '-')
|
||||||
|
{
|
||||||
|
port = endptr + 1;
|
||||||
|
p = strtol(port, &endptr, 0);
|
||||||
|
if (p < 0 || p > 0xffff)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*to_port = p;
|
||||||
|
if (*endptr)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* build a traffic selector from a stroke_end
|
* build a traffic selector from a stroke_end
|
||||||
*/
|
*/
|
||||||
@@ -913,13 +998,38 @@ static void add_ts(private_stroke_config_t *this,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
char *subnet;
|
char *subnet, *pos;
|
||||||
|
u_int16_t from_port, to_port;
|
||||||
|
u_int8_t proto;
|
||||||
|
|
||||||
enumerator = enumerator_create_token(end->subnets, ",", " ");
|
enumerator = enumerator_create_token(end->subnets, ",", " ");
|
||||||
while (enumerator->enumerate(enumerator, &subnet))
|
while (enumerator->enumerate(enumerator, &subnet))
|
||||||
{
|
{
|
||||||
ts = traffic_selector_create_from_cidr(subnet, end->protocol,
|
from_port = end->from_port;
|
||||||
end->from_port, end->to_port);
|
to_port = end->to_port;
|
||||||
|
proto = end->protocol;
|
||||||
|
|
||||||
|
pos = strchr(subnet, ':');
|
||||||
|
if (pos)
|
||||||
|
{
|
||||||
|
*(pos++) = '\0';
|
||||||
|
if (!parse_protoport(pos, &from_port, &to_port, &proto))
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "invalid proto/port: %s, skipped subnet",
|
||||||
|
pos);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (streq(subnet, "%dynamic"))
|
||||||
|
{
|
||||||
|
ts = traffic_selector_create_dynamic(proto,
|
||||||
|
from_port, to_port);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ts = traffic_selector_create_from_cidr(subnet, proto,
|
||||||
|
from_port, to_port);
|
||||||
|
}
|
||||||
if (ts)
|
if (ts)
|
||||||
{
|
{
|
||||||
child_cfg->add_traffic_selector(child_cfg, local, ts);
|
child_cfg->add_traffic_selector(child_cfg, local, ts);
|
||||||
|
|||||||
@@ -342,6 +342,79 @@ static linked_list_t *get_dynamic_hosts(ike_sa_t *ike_sa, bool local)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Substitude any host address with NATed address in traffic selector
|
||||||
|
*/
|
||||||
|
static linked_list_t* get_transport_nat_ts(private_child_create_t *this,
|
||||||
|
bool local, linked_list_t *in)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
linked_list_t *out;
|
||||||
|
traffic_selector_t *ts;
|
||||||
|
host_t *ike, *first = NULL;
|
||||||
|
u_int8_t mask;
|
||||||
|
|
||||||
|
if (local)
|
||||||
|
{
|
||||||
|
ike = this->ike_sa->get_my_host(this->ike_sa);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ike = this->ike_sa->get_other_host(this->ike_sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
out = linked_list_create();
|
||||||
|
|
||||||
|
enumerator = in->create_enumerator(in);
|
||||||
|
while (enumerator->enumerate(enumerator, &ts))
|
||||||
|
{
|
||||||
|
/* require that all selectors match the first "host" selector */
|
||||||
|
if (ts->is_host(ts, first))
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
{
|
||||||
|
ts->to_subnet(ts, &first, &mask);
|
||||||
|
}
|
||||||
|
ts = ts->clone(ts);
|
||||||
|
ts->set_address(ts, ike);
|
||||||
|
out->insert_last(out, ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
DESTROY_IF(first);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Narrow received traffic selectors with configuration
|
||||||
|
*/
|
||||||
|
static linked_list_t* narrow_ts(private_child_create_t *this, bool local,
|
||||||
|
linked_list_t *in)
|
||||||
|
{
|
||||||
|
linked_list_t *hosts, *nat, *ts;
|
||||||
|
ike_condition_t cond;
|
||||||
|
|
||||||
|
cond = local ? COND_NAT_HERE : COND_NAT_THERE;
|
||||||
|
hosts = get_dynamic_hosts(this->ike_sa, local);
|
||||||
|
|
||||||
|
if (this->mode == MODE_TRANSPORT &&
|
||||||
|
this->ike_sa->has_condition(this->ike_sa, cond))
|
||||||
|
{
|
||||||
|
nat = get_transport_nat_ts(this, local, in);
|
||||||
|
ts = this->config->get_traffic_selectors(this->config, local, nat, hosts);
|
||||||
|
nat->destroy_offset(nat, offsetof(traffic_selector_t, destroy));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ts = this->config->get_traffic_selectors(this->config, local, in, hosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
hosts->destroy(hosts);
|
||||||
|
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install a CHILD_SA for usage, return value:
|
* Install a CHILD_SA for usage, return value:
|
||||||
* - FAILED: no acceptable proposal
|
* - FAILED: no acceptable proposal
|
||||||
@@ -355,7 +428,7 @@ static status_t select_and_install(private_child_create_t *this,
|
|||||||
chunk_t nonce_i, nonce_r;
|
chunk_t nonce_i, nonce_r;
|
||||||
chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
|
chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
|
||||||
chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
|
chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
|
||||||
linked_list_t *my_ts, *other_ts, *list;
|
linked_list_t *my_ts, *other_ts;
|
||||||
host_t *me, *other;
|
host_t *me, *other;
|
||||||
bool private;
|
bool private;
|
||||||
|
|
||||||
@@ -416,24 +489,16 @@ static status_t select_and_install(private_child_create_t *this,
|
|||||||
{
|
{
|
||||||
nonce_i = this->my_nonce;
|
nonce_i = this->my_nonce;
|
||||||
nonce_r = this->other_nonce;
|
nonce_r = this->other_nonce;
|
||||||
my_ts = this->tsi;
|
my_ts = narrow_ts(this, TRUE, this->tsi);
|
||||||
other_ts = this->tsr;
|
other_ts = narrow_ts(this, FALSE, this->tsr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nonce_r = this->my_nonce;
|
nonce_r = this->my_nonce;
|
||||||
nonce_i = this->other_nonce;
|
nonce_i = this->other_nonce;
|
||||||
my_ts = this->tsr;
|
my_ts = narrow_ts(this, TRUE, this->tsr);
|
||||||
other_ts = this->tsi;
|
other_ts = narrow_ts(this, FALSE, this->tsi);
|
||||||
}
|
}
|
||||||
list = get_dynamic_hosts(this->ike_sa, TRUE);
|
|
||||||
my_ts = this->config->get_traffic_selectors(this->config,
|
|
||||||
TRUE, my_ts, list);
|
|
||||||
list->destroy(list);
|
|
||||||
list = get_dynamic_hosts(this->ike_sa, FALSE);
|
|
||||||
other_ts = this->config->get_traffic_selectors(this->config,
|
|
||||||
FALSE, other_ts, list);
|
|
||||||
list->destroy(list);
|
|
||||||
|
|
||||||
if (this->initiator)
|
if (this->initiator)
|
||||||
{
|
{
|
||||||
@@ -490,10 +555,9 @@ static status_t select_and_install(private_child_create_t *this,
|
|||||||
this->mode = MODE_TUNNEL;
|
this->mode = MODE_TUNNEL;
|
||||||
DBG1(DBG_IKE, "not using transport mode, not host-to-host");
|
DBG1(DBG_IKE, "not using transport mode, not host-to-host");
|
||||||
}
|
}
|
||||||
else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
|
if (this->config->get_mode(this->config) != MODE_TRANSPORT)
|
||||||
{
|
{
|
||||||
this->mode = MODE_TUNNEL;
|
this->mode = MODE_TUNNEL;
|
||||||
DBG1(DBG_IKE, "not using transport mode, connection NATed");
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MODE_BEET:
|
case MODE_BEET:
|
||||||
@@ -503,6 +567,10 @@ static status_t select_and_install(private_child_create_t *this,
|
|||||||
this->mode = MODE_TUNNEL;
|
this->mode = MODE_TUNNEL;
|
||||||
DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
|
DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
|
||||||
}
|
}
|
||||||
|
if (this->config->get_mode(this->config) != MODE_BEET)
|
||||||
|
{
|
||||||
|
this->mode = MODE_TUNNEL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -895,12 +963,6 @@ METHOD(task_t, build_i, status_t,
|
|||||||
this->proposals = this->config->get_proposals(this->config,
|
this->proposals = this->config->get_proposals(this->config,
|
||||||
this->dh_group == MODP_NONE);
|
this->dh_group == MODP_NONE);
|
||||||
this->mode = this->config->get_mode(this->config);
|
this->mode = this->config->get_mode(this->config);
|
||||||
if (this->mode == MODE_TRANSPORT &&
|
|
||||||
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
|
|
||||||
{
|
|
||||||
this->mode = MODE_TUNNEL;
|
|
||||||
DBG1(DBG_IKE, "not using transport mode, connection NATed");
|
|
||||||
}
|
|
||||||
|
|
||||||
this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
|
this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
|
||||||
this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
|
this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
|
||||||
@@ -996,10 +1058,77 @@ static void handle_child_sa_failure(private_child_create_t *this,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Substitute transport mode NAT selectors, if applicable
|
||||||
|
*/
|
||||||
|
static linked_list_t* get_ts_if_nat_transport(private_child_create_t *this,
|
||||||
|
bool local, linked_list_t *in)
|
||||||
|
{
|
||||||
|
linked_list_t *out = NULL;
|
||||||
|
ike_condition_t cond;
|
||||||
|
|
||||||
|
if (this->mode == MODE_TRANSPORT)
|
||||||
|
{
|
||||||
|
cond = local ? COND_NAT_HERE : COND_NAT_THERE;
|
||||||
|
if (this->ike_sa->has_condition(this->ike_sa, cond))
|
||||||
|
{
|
||||||
|
out = get_transport_nat_ts(this, local, in);
|
||||||
|
if (out->get_count(out) == 0)
|
||||||
|
{
|
||||||
|
out->destroy(out);
|
||||||
|
out = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select a matching CHILD config as responder
|
||||||
|
*/
|
||||||
|
static child_cfg_t* select_child_cfg(private_child_create_t *this)
|
||||||
|
{
|
||||||
|
peer_cfg_t *peer_cfg;
|
||||||
|
child_cfg_t *child_cfg = NULL;;
|
||||||
|
|
||||||
|
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||||
|
if (peer_cfg && this->tsi && this->tsr)
|
||||||
|
{
|
||||||
|
linked_list_t *listr, *listi, *tsr, *tsi;
|
||||||
|
|
||||||
|
tsr = get_ts_if_nat_transport(this, TRUE, this->tsr);
|
||||||
|
tsi = get_ts_if_nat_transport(this, FALSE, this->tsi);
|
||||||
|
|
||||||
|
listr = get_dynamic_hosts(this->ike_sa, TRUE);
|
||||||
|
listi = get_dynamic_hosts(this->ike_sa, FALSE);
|
||||||
|
child_cfg = peer_cfg->select_child_cfg(peer_cfg,
|
||||||
|
tsr ?: this->tsr, tsi ?: this->tsi,
|
||||||
|
listr, listi);
|
||||||
|
if ((tsi || tsr) && child_cfg &&
|
||||||
|
child_cfg->get_mode(child_cfg) != MODE_TRANSPORT)
|
||||||
|
{
|
||||||
|
/* found a CHILD config, but it doesn't use transport mode */
|
||||||
|
child_cfg->destroy(child_cfg);
|
||||||
|
child_cfg = NULL;
|
||||||
|
}
|
||||||
|
if (!child_cfg && (tsi || tsr))
|
||||||
|
{
|
||||||
|
/* no match for the substituted NAT selectors, try it without */
|
||||||
|
child_cfg = peer_cfg->select_child_cfg(peer_cfg,
|
||||||
|
this->tsr, this->tsi, listr, listi);
|
||||||
|
}
|
||||||
|
listr->destroy(listr);
|
||||||
|
listi->destroy(listi);
|
||||||
|
DESTROY_OFFSET_IF(tsi, offsetof(traffic_selector_t, destroy));
|
||||||
|
DESTROY_OFFSET_IF(tsr, offsetof(traffic_selector_t, destroy));
|
||||||
|
}
|
||||||
|
|
||||||
|
return child_cfg;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(task_t, build_r, status_t,
|
METHOD(task_t, build_r, status_t,
|
||||||
private_child_create_t *this, message_t *message)
|
private_child_create_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
peer_cfg_t *peer_cfg;
|
|
||||||
payload_t *payload;
|
payload_t *payload;
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
bool no_dh = TRUE, ike_auth = FALSE;
|
bool no_dh = TRUE, ike_auth = FALSE;
|
||||||
@@ -1034,19 +1163,10 @@ METHOD(task_t, build_r, status_t,
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
|
if (this->config == NULL)
|
||||||
if (!this->config && peer_cfg && this->tsi && this->tsr)
|
|
||||||
{
|
{
|
||||||
linked_list_t *listr, *listi;
|
this->config = select_child_cfg(this);
|
||||||
|
|
||||||
listr = get_dynamic_hosts(this->ike_sa, TRUE);
|
|
||||||
listi = get_dynamic_hosts(this->ike_sa, FALSE);
|
|
||||||
this->config = peer_cfg->select_child_cfg(peer_cfg,
|
|
||||||
this->tsr, this->tsi, listr, listi);
|
|
||||||
listr->destroy(listr);
|
|
||||||
listi->destroy(listi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->config == NULL)
|
if (this->config == NULL)
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable",
|
DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable",
|
||||||
|
|||||||
@@ -1224,6 +1224,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
|||||||
if(src_ts && dst_ts)
|
if(src_ts && dst_ts)
|
||||||
{
|
{
|
||||||
sa->sel = ts2selector(src_ts, dst_ts);
|
sa->sel = ts2selector(src_ts, dst_ts);
|
||||||
|
/* don't install proto/port on SA. This would break
|
||||||
|
* potential secondary SAs for the same address using a
|
||||||
|
* different prot/port. */
|
||||||
|
sa->sel.proto = 0;
|
||||||
|
sa->sel.dport = sa->sel.dport_mask = 0;
|
||||||
|
sa->sel.sport = sa->sel.sport_mask = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user