src_ip, if_name);
}
+METHOD(kernel_interface_t, bypass_socket, bool,
+ private_kernel_interface_t *this, int fd, int family)
+{
+ if (!this->ipsec)
+ {
+ return FALSE;
+ }
+ return this->ipsec->bypass_socket(this->ipsec, fd, family);
+}
METHOD(kernel_interface_t, get_address_by_ts, status_t,
private_kernel_interface_t *this, traffic_selector_t *ts, host_t **ip)
.del_ip = _del_ip,
.add_route = _add_route,
.del_route = _del_route,
+ .bypass_socket = _bypass_socket,
.get_address_by_ts = _get_address_by_ts,
.add_ipsec_interface = _add_ipsec_interface,
host_t *gateway, host_t *src_ip, char *if_name);
/**
+ * Set up a bypass policy for a given socket.
+ *
+ * @param fd socket file descriptor to setup policy for
+ * @param family protocol family of the socket
+ * @return TRUE of policy set up successfully
+ */
+ bool (*bypass_socket)(kernel_interface_t *this, int fd, int family);
+
+ /**
* manager methods
*/
bool unrouted);
/**
+ * Install a bypass policy for the given socket.
+ *
+ * @param fd socket file descriptor to setup policy for
+ * @param family protocol family of the socket
+ * @return TRUE of policy set up successfully
+ */
+ bool (*bypass_socket)(kernel_ipsec_t *this, int fd, int family);
+
+ /**
* Destroy the implementation.
*/
void (*destroy) (kernel_ipsec_t *this);
* - FAILED when unable to send
*/
status_t (*send) (socket_t *this, packet_t *packet);
-
- /**
- * Enumerate all underlying socket file descriptors.
- *
- * @return enumerator over (int fd, int family, int port)
- */
- enumerator_t *(*create_enumerator) (socket_t *this);
};
#endif /** SOCKET_H_ @}*/
return status;
}
-METHOD(socket_manager_t, create_enumerator, enumerator_t*,
- private_socket_manager_t *this)
-{
- socket_t *socket;
-
- this->lock->read_lock(this->lock);
- if (this->sockets->get_first(this->sockets, (void**)&socket) != SUCCESS)
- {
- this->lock->unlock(this->lock);
- return enumerator_create_empty();
- }
- return enumerator_create_cleaner(socket->create_enumerator(socket),
- (void*)this->lock->unlock, this->lock);
-}
-
METHOD(socket_manager_t, add_socket, void,
private_socket_manager_t *this, socket_t *socket)
{
.public = {
.send = _sender,
.receive = _receiver,
- .create_enumerator = _create_enumerator,
.add_socket = _add_socket,
.remove_socket = _remove_socket,
.destroy = _destroy,
status_t (*send) (socket_manager_t *this, packet_t *packet);
/**
- * Enumerate all underlying socket file descriptors of the active socket.
- *
- * @return enumerator over (int fd, int family, int port)
- */
- enumerator_t *(*create_enumerator) (socket_manager_t *this);
-
- /**
* Register a socket implementation.
*/
void (*add_socket)(socket_manager_t *this, socket_t *socket);
return SUCCESS;
}
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+ private_kernel_klips_ipsec_t *this, int fd, int family)
+{
+ /* KLIPS does not need a bypass policy for IKE */
+ return TRUE;
+}
+
METHOD(kernel_ipsec_t, destroy, void,
private_kernel_klips_ipsec_t *this)
{
.add_policy = _add_policy,
.query_policy = _query_policy,
.del_policy = _del_policy,
+ .bypass_socket = _bypass_socket,
.destroy = _destroy,
},
.policies = linked_list_create(),
return SUCCESS;
}
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+ private_kernel_netlink_ipsec_t *this, int fd, int family)
+{
+ struct xfrm_userpolicy_info policy;
+ u_int sol, ipsec_policy;
+
+ switch (family)
+ {
+ case AF_INET:
+ sol = SOL_IP;
+ ipsec_policy = IP_XFRM_POLICY;
+ break;
+ case AF_INET6:
+ sol = SOL_IPV6;
+ ipsec_policy = IPV6_XFRM_POLICY;
+ break;
+ default:
+ return FALSE;
+ }
+
+ memset(&policy, 0, sizeof(policy));
+ policy.action = XFRM_POLICY_ALLOW;
+ policy.sel.family = family;
+
+ policy.dir = XFRM_POLICY_OUT;
+ 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.dir = XFRM_POLICY_IN;
+ 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_netlink_ipsec_t *this)
{
free(this);
}
-/**
- * Add bypass policies for IKE on the sockets used by charon
- */
-static bool add_bypass_policies()
-{
- 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 xfrm_userpolicy_info policy;
- u_int sol, ipsec_policy;
-
- switch (family)
- {
- case AF_INET:
- sol = SOL_IP;
- ipsec_policy = IP_XFRM_POLICY;
- break;
- case AF_INET6:
- sol = SOL_IPV6;
- ipsec_policy = IPV6_XFRM_POLICY;
- break;
- default:
- continue;
- }
-
- memset(&policy, 0, sizeof(policy));
- policy.action = XFRM_POLICY_ALLOW;
- policy.sel.family = family;
-
- policy.dir = XFRM_POLICY_OUT;
- 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.dir = XFRM_POLICY_IN;
- 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.
*/
.add_policy = _add_policy,
.query_policy = _query_policy,
.del_policy = _del_policy,
+ .bypass_socket = _bypass_socket,
.destroy = _destroy,
},
.policies = hashtable_create((hashtable_hash_t)policy_hash,
{
charon->kill(charon, "unable to bind XFRM event socket");
}
-
- /* add bypass policies on the sockets used by charon */
- if (!add_bypass_policies())
- {
- charon->kill(charon, "unable to add bypass policies on sockets");
- }
-
this->job = callback_job_create((callback_job_cb_t)receive_events,
this, NULL, NULL);
charon->processor->queue_job(charon->processor, (job_t*)this->job);
return SUCCESS;
}
-METHOD(kernel_ipsec_t, destroy, void,
- private_kernel_pfkey_ipsec_t *this)
-{
- this->job->cancel(this->job);
- close(this->socket);
- close(this->socket_events);
- this->policies->destroy_function(this->policies, (void*)policy_entry_destroy);
- this->mutex->destroy(this->mutex);
- this->mutex_pfkey->destroy(this->mutex_pfkey);
- free(this);
-}
-
-/**
- * Add bypass policies for IKE on the sockets of charon
- */
-static bool add_bypass_policies(private_kernel_pfkey_ipsec_t *this)
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+ private_kernel_pfkey_ipsec_t *this, int fd, int family)
{
- int fd, family, port;
- enumerator_t *sockets;
- bool status = TRUE;
+ struct sadb_x_policy policy;
+ u_int sol, ipsec_policy;
- sockets = charon->socket->create_enumerator(charon->socket);
- while (sockets->enumerate(sockets, &fd, &family, &port))
+ switch (family)
{
- struct sadb_x_policy policy;
- u_int sol, ipsec_policy;
-
- switch (family)
+ case AF_INET:
{
- 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;
+ sol = SOL_IP;
+ ipsec_policy = IP_IPSEC_POLICY;
break;
}
- policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
- if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+ case AF_INET6:
{
- DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
- strerror(errno));
- status = FALSE;
+ sol = SOL_IPV6;
+ ipsec_policy = IPV6_IPSEC_POLICY;
break;
}
+ default:
+ return FALSE;
}
- sockets->destroy(sockets);
- return status;
+
+ 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)
+{
+ this->job->cancel(this->job);
+ close(this->socket);
+ close(this->socket_events);
+ this->policies->destroy_function(this->policies, (void*)policy_entry_destroy);
+ this->mutex->destroy(this->mutex);
+ this->mutex_pfkey->destroy(this->mutex_pfkey);
+ free(this);
}
/*
.add_policy = _add_policy,
.query_policy = _query_policy,
.del_policy = _del_policy,
+ .bypass_socket = _bypass_socket,
.destroy = _destroy,
},
.policies = linked_list_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)
}
}
+ if (!charon->kernel_interface->bypass_socket(charon->kernel_interface,
+ skt, family))
+ {
+ DBG1(DBG_NET, "installing IKE bypass policy failed");
+ }
+
#ifndef __APPLE__
{
/* enable UDP decapsulation globally, only for one socket needed */
return skt;
}
-/**
- * enumerator for underlying sockets
- */
-typedef struct {
- /** implements enumerator_t */
- enumerator_t public;
- /** sockets we enumerate */
- private_socket_default_socket_t *socket;
- /** counter */
- int index;
-} socket_enumerator_t;
-
-/**
- * enumerate function for socket_enumerator_t
- */
-static bool enumerate(socket_enumerator_t *this, int *fd, int *family, int *port)
-{
- static const struct {
- int fd_offset;
- int family;
- int port;
- } sockets[] = {
- { offsetof(private_socket_default_socket_t, ipv4),
- AF_INET, IKEV2_UDP_PORT },
- { offsetof(private_socket_default_socket_t, ipv6),
- AF_INET6, IKEV2_UDP_PORT },
- { offsetof(private_socket_default_socket_t, ipv4_natt),
- AF_INET, IKEV2_NATT_PORT },
- { offsetof(private_socket_default_socket_t, ipv6_natt),
- AF_INET6, IKEV2_NATT_PORT }
- };
-
- while(++this->index < countof(sockets))
- {
- int sock = *(int*)((char*)this->socket + sockets[this->index].fd_offset);
- if (!sock)
- {
- continue;
- }
- *fd = sock;
- *family = sockets[this->index].family;
- *port = sockets[this->index].port;
- return TRUE;
- }
- return FALSE;
-}
-
-METHOD(socket_t, create_enumerator, enumerator_t*,
- private_socket_default_socket_t *this)
-{
- socket_enumerator_t *enumerator;
-
- enumerator = malloc_thing(socket_enumerator_t);
- enumerator->index = -1;
- enumerator->socket = this;
- enumerator->public.enumerate = (void*)enumerate;
- enumerator->public.destroy = (void*)free;
- return &enumerator->public;
-}
-
METHOD(socket_default_socket_t, destroy, void,
private_socket_default_socket_t *this)
{
.socket = {
.send = _sender,
.receive = _receiver,
- .create_enumerator = _create_enumerator,
},
.destroy = _destroy,
},
}
}
+ if (!charon->kernel_interface->bypass_socket(charon->kernel_interface,
+ skt, family))
+ {
+ DBG1(DBG_NET, "installing bypass policy on send socket failed");
+ }
+
return skt;
}
return 0;
}
- return skt;
-}
-
-/**
- * enumerator for underlying sockets
- */
-typedef struct {
- /** implements enumerator_t */
- enumerator_t public;
- /** sockets we enumerate */
- private_socket_raw_socket_t *socket;
- /** counter */
- int index;
-} socket_enumerator_t;
-
-/**
- * enumerate function for socket_enumerator_t
- */
-static bool enumerate(socket_enumerator_t *this, int *fd, int *family, int *port)
-{
- static const struct {
- int fd_offset;
- int family;
- int port;
- } sockets[] = {
- { offsetof(private_socket_raw_socket_t, recv4), AF_INET, IKEV2_UDP_PORT },
- { offsetof(private_socket_raw_socket_t, recv6), AF_INET6, IKEV2_UDP_PORT },
- { offsetof(private_socket_raw_socket_t, send4), AF_INET, IKEV2_UDP_PORT },
- { offsetof(private_socket_raw_socket_t, send6), AF_INET6, IKEV2_UDP_PORT },
- { offsetof(private_socket_raw_socket_t, send4_natt), AF_INET, IKEV2_NATT_PORT },
- { offsetof(private_socket_raw_socket_t, send6_natt), AF_INET6, IKEV2_NATT_PORT }
- };
-
- while(++this->index < countof(sockets))
+ if (!charon->kernel_interface->bypass_socket(charon->kernel_interface,
+ skt, family))
{
- int sock = *(int*)((char*)this->socket + sockets[this->index].fd_offset);
- if (!sock)
- {
- continue;
- }
- *fd = sock;
- *family = sockets[this->index].family;
- *port = sockets[this->index].port;
- return TRUE;
+ DBG1(DBG_NET, "installing bypass policy on receive socket failed");
}
- return FALSE;
-}
-METHOD(socket_t, create_enumerator, enumerator_t*,
- private_socket_raw_socket_t *this)
-{
- socket_enumerator_t *enumerator;
-
- enumerator = malloc_thing(socket_enumerator_t);
- enumerator->index = -1;
- enumerator->socket = this;
- enumerator->public.enumerate = (void*)enumerate;
- enumerator->public.destroy = (void*)free;
- return &enumerator->public;
+ return skt;
}
METHOD(socket_raw_socket_t, destroy, void,
.socket = {
.send = _sender,
.receive = _receiver,
- .create_enumerator = _create_enumerator,
},
.destroy = _destroy,
},