Pass sockets to bypass to kernel interface, allowing us to register them dynamically

This commit is contained in:
Martin Willi
2010-02-26 11:44:33 +01:00
parent 3e631491a0
commit 54f818590e
11 changed files with 141 additions and 274 deletions
@@ -2044,6 +2044,52 @@ static status_t register_pfkey_socket(private_kernel_pfkey_ipsec_t *this,
return SUCCESS;
}
METHOD(kernel_ipsec_t, bypass_socket, bool,
private_kernel_pfkey_ipsec_t *this, int fd, int family)
{
struct sadb_x_policy policy;
u_int sol, ipsec_policy;
switch (family)
{
case AF_INET:
{
sol = SOL_IP;
ipsec_policy = IP_IPSEC_POLICY;
break;
}
case AF_INET6:
{
sol = SOL_IPV6;
ipsec_policy = IPV6_IPSEC_POLICY;
break;
}
default:
return FALSE;
}
memset(&policy, 0, sizeof(policy));
policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t);
policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
{
DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
strerror(errno));
return FALSE;
}
policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
{
DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
strerror(errno));
return FALSE;
}
return TRUE;
}
METHOD(kernel_ipsec_t, destroy, void,
private_kernel_pfkey_ipsec_t *this)
{
@@ -2056,65 +2102,6 @@ METHOD(kernel_ipsec_t, destroy, void,
free(this);
}
/**
* Add bypass policies for IKE on the sockets of charon
*/
static bool add_bypass_policies(private_kernel_pfkey_ipsec_t *this)
{
int fd, family, port;
enumerator_t *sockets;
bool status = TRUE;
sockets = charon->socket->create_enumerator(charon->socket);
while (sockets->enumerate(sockets, &fd, &family, &port))
{
struct sadb_x_policy policy;
u_int sol, ipsec_policy;
switch (family)
{
case AF_INET:
{
sol = SOL_IP;
ipsec_policy = IP_IPSEC_POLICY;
break;
}
case AF_INET6:
{
sol = SOL_IPV6;
ipsec_policy = IPV6_IPSEC_POLICY;
break;
}
default:
continue;
}
memset(&policy, 0, sizeof(policy));
policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t);
policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
{
DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
strerror(errno));
status = FALSE;
break;
}
policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
{
DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
strerror(errno));
status = FALSE;
break;
}
}
sockets->destroy(sockets);
return status;
}
/*
* Described in header.
*/
@@ -2133,6 +2120,7 @@ kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
.add_policy = _add_policy,
.query_policy = _query_policy,
.del_policy = _del_policy,
.bypass_socket = _bypass_socket,
.destroy = _destroy,
},
.policies = linked_list_create(),
@@ -2156,12 +2144,6 @@ kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
charon->kill(charon, "unable to create PF_KEY event socket");
}
/* add bypass policies on the sockets used by charon */
if (!add_bypass_policies(this))
{
charon->kill(charon, "unable to add bypass policies on sockets");
}
/* register the event socket */
if (register_pfkey_socket(this, SADB_SATYPE_ESP) != SUCCESS ||
register_pfkey_socket(this, SADB_SATYPE_AH) != SUCCESS)