trap-manager: Enable auto=route with right=%any for transport mode connections
Fixes #196.
This commit is contained in:
+118
-27
@@ -105,6 +105,8 @@ typedef struct {
|
|||||||
peer_cfg_t *peer_cfg;
|
peer_cfg_t *peer_cfg;
|
||||||
/** ref to instantiated CHILD_SA (i.e the trap policy) */
|
/** ref to instantiated CHILD_SA (i.e the trap policy) */
|
||||||
child_sa_t *child_sa;
|
child_sa_t *child_sa;
|
||||||
|
/** TRUE in case of wildcard Transport Mode SA */
|
||||||
|
bool wildcard;
|
||||||
} entry_t;
|
} entry_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,6 +117,8 @@ typedef struct {
|
|||||||
ike_sa_t *ike_sa;
|
ike_sa_t *ike_sa;
|
||||||
/** reqid of pending trap policy */
|
/** reqid of pending trap policy */
|
||||||
u_int32_t reqid;
|
u_int32_t reqid;
|
||||||
|
/** destination address (wildcard case) */
|
||||||
|
host_t *dst;
|
||||||
} acquire_t;
|
} acquire_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,6 +137,7 @@ static void destroy_entry(entry_t *this)
|
|||||||
*/
|
*/
|
||||||
static void destroy_acquire(acquire_t *this)
|
static void destroy_acquire(acquire_t *this)
|
||||||
{
|
{
|
||||||
|
DESTROY_IF(this->dst);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +149,14 @@ static bool acquire_by_reqid(acquire_t *this, u_int32_t *reqid)
|
|||||||
return this->reqid == *reqid;
|
return this->reqid == *reqid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* match an acquire entry by destination address
|
||||||
|
*/
|
||||||
|
static bool acquire_by_dst(acquire_t *this, host_t *dst)
|
||||||
|
{
|
||||||
|
return this->dst && this->dst->ip_equals(this->dst, dst);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(trap_manager_t, install, u_int32_t,
|
METHOD(trap_manager_t, install, u_int32_t,
|
||||||
private_trap_manager_t *this, peer_cfg_t *peer, child_cfg_t *child,
|
private_trap_manager_t *this, peer_cfg_t *peer, child_cfg_t *child,
|
||||||
u_int32_t reqid)
|
u_int32_t reqid)
|
||||||
@@ -158,29 +171,40 @@ METHOD(trap_manager_t, install, u_int32_t,
|
|||||||
linked_list_t *proposals;
|
linked_list_t *proposals;
|
||||||
proposal_t *proposal;
|
proposal_t *proposal;
|
||||||
protocol_id_t proto = PROTO_ESP;
|
protocol_id_t proto = PROTO_ESP;
|
||||||
|
bool wildcard = FALSE;
|
||||||
|
|
||||||
/* try to resolve addresses */
|
/* try to resolve addresses */
|
||||||
ike_cfg = peer->get_ike_cfg(peer);
|
ike_cfg = peer->get_ike_cfg(peer);
|
||||||
other = ike_cfg->resolve_other(ike_cfg, AF_UNSPEC);
|
other = ike_cfg->resolve_other(ike_cfg, AF_UNSPEC);
|
||||||
if (!other || other->is_anyaddr(other))
|
if (other && other->is_anyaddr(other) &&
|
||||||
|
child->get_mode(child) == MODE_TRANSPORT)
|
||||||
|
{
|
||||||
|
/* allow wildcard for Transport Mode SAs */
|
||||||
|
me = host_create_any(other->get_family(other));
|
||||||
|
wildcard = TRUE;
|
||||||
|
}
|
||||||
|
else if (!other || other->is_anyaddr(other))
|
||||||
{
|
{
|
||||||
DESTROY_IF(other);
|
DESTROY_IF(other);
|
||||||
DBG1(DBG_CFG, "installing trap failed, remote address unknown");
|
DBG1(DBG_CFG, "installing trap failed, remote address unknown");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
me = ike_cfg->resolve_me(ike_cfg, other->get_family(other));
|
else
|
||||||
if (!me || me->is_anyaddr(me))
|
|
||||||
{
|
{
|
||||||
DESTROY_IF(me);
|
me = ike_cfg->resolve_me(ike_cfg, other->get_family(other));
|
||||||
me = hydra->kernel_interface->get_source_addr(
|
if (!me || me->is_anyaddr(me))
|
||||||
hydra->kernel_interface, other, NULL);
|
|
||||||
if (!me)
|
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "installing trap failed, local address unknown");
|
DESTROY_IF(me);
|
||||||
other->destroy(other);
|
me = hydra->kernel_interface->get_source_addr(
|
||||||
return 0;
|
hydra->kernel_interface, other, NULL);
|
||||||
|
if (!me)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "installing trap failed, local address unknown");
|
||||||
|
other->destroy(other);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
me->set_port(me, ike_cfg->get_my_port(ike_cfg));
|
||||||
}
|
}
|
||||||
me->set_port(me, ike_cfg->get_my_port(ike_cfg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->lock->write_lock(this->lock);
|
this->lock->write_lock(this->lock);
|
||||||
@@ -220,6 +244,7 @@ METHOD(trap_manager_t, install, u_int32_t,
|
|||||||
INIT(entry,
|
INIT(entry,
|
||||||
.name = strdup(child->get_name(child)),
|
.name = strdup(child->get_name(child)),
|
||||||
.peer_cfg = peer->get_ref(peer),
|
.peer_cfg = peer->get_ref(peer),
|
||||||
|
.wildcard = wildcard,
|
||||||
);
|
);
|
||||||
this->traps->insert_first(this->traps, entry);
|
this->traps->insert_first(this->traps, entry);
|
||||||
this->installing++;
|
this->installing++;
|
||||||
@@ -374,6 +399,8 @@ METHOD(trap_manager_t, acquire, void,
|
|||||||
peer_cfg_t *peer;
|
peer_cfg_t *peer;
|
||||||
child_cfg_t *child;
|
child_cfg_t *child;
|
||||||
ike_sa_t *ike_sa;
|
ike_sa_t *ike_sa;
|
||||||
|
host_t *host;
|
||||||
|
bool wildcard, ignore = FALSE;
|
||||||
|
|
||||||
this->lock->read_lock(this->lock);
|
this->lock->read_lock(this->lock);
|
||||||
enumerator = this->traps->create_enumerator(this->traps);
|
enumerator = this->traps->create_enumerator(this->traps);
|
||||||
@@ -390,38 +417,94 @@ METHOD(trap_manager_t, acquire, void,
|
|||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "trap not found, unable to acquire reqid %d",reqid);
|
DBG1(DBG_CFG, "trap not found, unable to acquire reqid %d", reqid);
|
||||||
this->lock->unlock(this->lock);
|
this->lock->unlock(this->lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
reqid = found->child_sa->get_reqid(found->child_sa);
|
reqid = found->child_sa->get_reqid(found->child_sa);
|
||||||
|
wildcard = found->wildcard;
|
||||||
|
|
||||||
this->mutex->lock(this->mutex);
|
this->mutex->lock(this->mutex);
|
||||||
if (this->acquires->find_first(this->acquires, (void*)acquire_by_reqid,
|
if (wildcard)
|
||||||
(void**)&acquire, &reqid) == SUCCESS)
|
{ /* for wildcard acquires we check that we don't have a pending acquire
|
||||||
{
|
* with the same peer */
|
||||||
DBG1(DBG_CFG, "ignoring acquire, connection attempt pending");
|
u_int8_t mask;
|
||||||
this->mutex->unlock(this->mutex);
|
|
||||||
this->lock->unlock(this->lock);
|
dst->to_subnet(dst, &host, &mask);
|
||||||
return;
|
if (this->acquires->find_first(this->acquires, (void*)acquire_by_dst,
|
||||||
|
(void**)&acquire, host) == SUCCESS)
|
||||||
|
{
|
||||||
|
host->destroy(host);
|
||||||
|
ignore = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
INIT(acquire,
|
||||||
|
.dst = host,
|
||||||
|
.reqid = reqid,
|
||||||
|
);
|
||||||
|
this->acquires->insert_last(this->acquires, acquire);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
INIT(acquire,
|
if (this->acquires->find_first(this->acquires, (void*)acquire_by_reqid,
|
||||||
.reqid = reqid,
|
(void**)&acquire, &reqid) == SUCCESS)
|
||||||
);
|
{
|
||||||
this->acquires->insert_last(this->acquires, acquire);
|
ignore = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
INIT(acquire,
|
||||||
|
.reqid = reqid,
|
||||||
|
);
|
||||||
|
this->acquires->insert_last(this->acquires, acquire);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this->mutex->unlock(this->mutex);
|
this->mutex->unlock(this->mutex);
|
||||||
|
if (ignore)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "ignoring acquire, connection attempt pending");
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
peer = found->peer_cfg->get_ref(found->peer_cfg);
|
peer = found->peer_cfg->get_ref(found->peer_cfg);
|
||||||
child = found->child_sa->get_config(found->child_sa);
|
child = found->child_sa->get_config(found->child_sa);
|
||||||
child = child->get_ref(child);
|
child = child->get_ref(child);
|
||||||
/* don't hold the lock while checking out the IKE_SA */
|
/* don't hold the lock while checking out the IKE_SA */
|
||||||
this->lock->unlock(this->lock);
|
this->lock->unlock(this->lock);
|
||||||
|
|
||||||
ike_sa = charon->ike_sa_manager->checkout_by_config(
|
if (wildcard)
|
||||||
|
{ /* the peer config would match IKE_SAs with other peers */
|
||||||
|
ike_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
|
||||||
|
peer->get_ike_version(peer), TRUE);
|
||||||
|
if (ike_sa)
|
||||||
|
{
|
||||||
|
ike_cfg_t *ike_cfg;
|
||||||
|
u_int16_t port;
|
||||||
|
u_int8_t mask;
|
||||||
|
|
||||||
|
ike_sa->set_peer_cfg(ike_sa, peer);
|
||||||
|
ike_cfg = ike_sa->get_ike_cfg(ike_sa);
|
||||||
|
|
||||||
|
port = ike_cfg->get_other_port(ike_cfg);
|
||||||
|
dst->to_subnet(dst, &host, &mask);
|
||||||
|
host->set_port(host, port);
|
||||||
|
ike_sa->set_other_host(ike_sa, host);
|
||||||
|
|
||||||
|
port = ike_cfg->get_my_port(ike_cfg);
|
||||||
|
src->to_subnet(src, &host, &mask);
|
||||||
|
host->set_port(host, port);
|
||||||
|
ike_sa->set_my_host(ike_sa, host);
|
||||||
|
|
||||||
|
charon->bus->set_sa(charon->bus, ike_sa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ike_sa = charon->ike_sa_manager->checkout_by_config(
|
||||||
charon->ike_sa_manager, peer);
|
charon->ike_sa_manager, peer);
|
||||||
|
}
|
||||||
if (ike_sa)
|
if (ike_sa)
|
||||||
{
|
{
|
||||||
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
|
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
|
||||||
@@ -476,9 +559,17 @@ static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (child_sa && child_sa->get_reqid(child_sa) != acquire->reqid)
|
if (child_sa)
|
||||||
{
|
{
|
||||||
continue;
|
if (acquire->dst)
|
||||||
|
{
|
||||||
|
/* since every wildcard acquire results in a separate IKE_SA
|
||||||
|
* there is no need to compare the destination address */
|
||||||
|
}
|
||||||
|
else if (child_sa->get_reqid(child_sa) != acquire->reqid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this->acquires->remove_at(this->acquires, enumerator);
|
this->acquires->remove_at(this->acquires, enumerator);
|
||||||
destroy_acquire(acquire);
|
destroy_acquire(acquire);
|
||||||
|
|||||||
Reference in New Issue
Block a user