diff options
-rw-r--r-- | src/charon/kernel/kernel_interface.c | 10 | ||||
-rw-r--r-- | src/charon/kernel/kernel_interface.h | 9 | ||||
-rw-r--r-- | src/charon/kernel/kernel_ipsec.h | 9 | ||||
-rw-r--r-- | src/charon/network/socket.h | 7 | ||||
-rw-r--r-- | src/charon/network/socket_manager.c | 16 | ||||
-rw-r--r-- | src/charon/network/socket_manager.h | 7 | ||||
-rw-r--r-- | src/charon/plugins/kernel_klips/kernel_klips_ipsec.c | 8 | ||||
-rw-r--r-- | src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c | 103 | ||||
-rw-r--r-- | src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 112 | ||||
-rw-r--r-- | src/charon/plugins/socket_default/socket_default_socket.c | 67 | ||||
-rw-r--r-- | src/charon/plugins/socket_raw/socket_raw_socket.c | 67 |
11 files changed, 141 insertions, 274 deletions
diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c index e9fb81e65..64a43a7fc 100644 --- a/src/charon/kernel/kernel_interface.c +++ b/src/charon/kernel/kernel_interface.c @@ -241,6 +241,15 @@ METHOD(kernel_interface_t, del_route, status_t, 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) @@ -361,6 +370,7 @@ kernel_interface_t *kernel_interface_create() .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, diff --git a/src/charon/kernel/kernel_interface.h b/src/charon/kernel/kernel_interface.h index c39246e72..4a62e76b8 100644 --- a/src/charon/kernel/kernel_interface.h +++ b/src/charon/kernel/kernel_interface.h @@ -333,6 +333,15 @@ struct kernel_interface_t { 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 */ diff --git a/src/charon/kernel/kernel_ipsec.h b/src/charon/kernel/kernel_ipsec.h index 73ad29b0e..300464cf6 100644 --- a/src/charon/kernel/kernel_ipsec.h +++ b/src/charon/kernel/kernel_ipsec.h @@ -265,6 +265,15 @@ struct kernel_ipsec_t { 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); diff --git a/src/charon/network/socket.h b/src/charon/network/socket.h index 798d3411a..5c5a4edfb 100644 --- a/src/charon/network/socket.h +++ b/src/charon/network/socket.h @@ -59,13 +59,6 @@ struct socket_t { * - 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_ @}*/ diff --git a/src/charon/network/socket_manager.c b/src/charon/network/socket_manager.c index 5bd9356cd..0dbce4b1b 100644 --- a/src/charon/network/socket_manager.c +++ b/src/charon/network/socket_manager.c @@ -81,21 +81,6 @@ METHOD(socket_manager_t, sender, status_t, 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) { @@ -131,7 +116,6 @@ socket_manager_t *socket_manager_create() .public = { .send = _sender, .receive = _receiver, - .create_enumerator = _create_enumerator, .add_socket = _add_socket, .remove_socket = _remove_socket, .destroy = _destroy, diff --git a/src/charon/network/socket_manager.h b/src/charon/network/socket_manager.h index da38f56a9..b33d5c71c 100644 --- a/src/charon/network/socket_manager.h +++ b/src/charon/network/socket_manager.h @@ -51,13 +51,6 @@ struct socket_manager_t { 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); diff --git a/src/charon/plugins/kernel_klips/kernel_klips_ipsec.c b/src/charon/plugins/kernel_klips/kernel_klips_ipsec.c index 21f6b2ac9..c99b72133 100644 --- a/src/charon/plugins/kernel_klips/kernel_klips_ipsec.c +++ b/src/charon/plugins/kernel_klips/kernel_klips_ipsec.c @@ -2556,6 +2556,13 @@ static status_t register_pfkey_socket(private_kernel_klips_ipsec_t *this, u_int8 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) { @@ -2589,6 +2596,7 @@ kernel_klips_ipsec_t *kernel_klips_ipsec_create() .add_policy = _add_policy, .query_policy = _query_policy, .del_policy = _del_policy, + .bypass_socket = _bypass_socket, .destroy = _destroy, }, .policies = linked_list_create(), diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c index e5f7ac130..c8bcfd6ff 100644 --- a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -1892,6 +1892,47 @@ METHOD(kernel_ipsec_t, del_policy, status_t, 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) { @@ -1912,60 +1953,6 @@ METHOD(kernel_ipsec_t, destroy, void, 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. */ @@ -1986,6 +1973,7 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create() .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, @@ -2020,13 +2008,6 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create() { 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); diff --git a/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c index b92cbb785..b64e41c56 100644 --- a/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c +++ b/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -2044,75 +2044,62 @@ static status_t register_pfkey_socket(private_kernel_pfkey_ipsec_t *this, 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); } /* @@ -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) diff --git a/src/charon/plugins/socket_default/socket_default_socket.c b/src/charon/plugins/socket_default/socket_default_socket.c index d69f30975..bc998182e 100644 --- a/src/charon/plugins/socket_default/socket_default_socket.c +++ b/src/charon/plugins/socket_default/socket_default_socket.c @@ -521,6 +521,12 @@ static int open_socket(private_socket_default_socket_t *this, } } + 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 */ @@ -535,66 +541,6 @@ static int open_socket(private_socket_default_socket_t *this, 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) { @@ -629,7 +575,6 @@ socket_default_socket_t *socket_default_socket_create() .socket = { .send = _sender, .receive = _receiver, - .create_enumerator = _create_enumerator, }, .destroy = _destroy, }, diff --git a/src/charon/plugins/socket_raw/socket_raw_socket.c b/src/charon/plugins/socket_raw/socket_raw_socket.c index 78358568c..e0155fa87 100644 --- a/src/charon/plugins/socket_raw/socket_raw_socket.c +++ b/src/charon/plugins/socket_raw/socket_raw_socket.c @@ -492,6 +492,12 @@ static int open_send_socket(private_socket_raw_socket_t *this, } } + if (!charon->kernel_interface->bypass_socket(charon->kernel_interface, + skt, family)) + { + DBG1(DBG_NET, "installing bypass policy on send socket failed"); + } + return skt; } @@ -590,65 +596,13 @@ static int open_recv_socket(private_socket_raw_socket_t *this, int family) 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, @@ -693,7 +647,6 @@ socket_raw_socket_t *socket_raw_socket_create() .socket = { .send = _sender, .receive = _receiver, - .create_enumerator = _create_enumerator, }, .destroy = _destroy, }, |