Let kernel interfaces decide how to enable UDP decapsulation of ESP packets.
authorTobias Brunner <tobias@strongswan.org>
Fri, 24 Feb 2012 10:07:34 +0000 (11:07 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 8 Aug 2012 13:12:24 +0000 (15:12 +0200)
src/libcharon/plugins/load_tester/load_tester_ipsec.c
src/libcharon/plugins/socket_default/socket_default_socket.c
src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
src/libcharon/plugins/socket_raw/socket_raw_socket.c
src/libhydra/kernel/kernel_interface.c
src/libhydra/kernel/kernel_interface.h
src/libhydra/kernel/kernel_ipsec.h
src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c

index 4401972..ded6b2d 100644 (file)
@@ -108,12 +108,6 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
        return SUCCESS;
 }
 
-METHOD(kernel_ipsec_t, bypass_socket, bool,
-       private_load_tester_ipsec_t *this, int fd, int family)
-{
-       return TRUE;
-}
-
 METHOD(kernel_ipsec_t, destroy, void,
        private_load_tester_ipsec_t *this)
 {
@@ -141,7 +135,8 @@ load_tester_ipsec_t *load_tester_ipsec_create()
                                .query_policy = _query_policy,
                                .del_policy = _del_policy,
                                .flush_policies = (void*)return_failed,
-                               .bypass_socket = _bypass_socket,
+                               .bypass_socket = (void*)return_true,
+                               .enable_udp_decap = (void*)return_true,
                                .destroy = _destroy,
                        },
                },
index eba7219..b035d57 100644 (file)
@@ -40,9 +40,6 @@
 #include <netinet/ip.h>
 #include <netinet/udp.h>
 #include <net/if.h>
-#ifdef __APPLE__
-#include <sys/sysctl.h>
-#endif
 
 #include <hydra.h>
 #include <daemon.h>
 /* length of non-esp marker */
 #define MARKER_LEN sizeof(u_int32_t)
 
-/* from linux/udp.h */
-#ifndef UDP_ENCAP
-#define UDP_ENCAP 100
-#endif /*UDP_ENCAP*/
-
-#ifndef UDP_ENCAP_ESPINUDP
-#define UDP_ENCAP_ESPINUDP 2
-#endif /*UDP_ENCAP_ESPINUDP*/
-
 /* these are not defined on some platforms */
 #ifndef SOL_IP
 #define SOL_IP IPPROTO_IP
@@ -70,9 +58,6 @@
 #ifndef SOL_IPV6
 #define SOL_IPV6 IPPROTO_IPV6
 #endif
-#ifndef SOL_UDP
-#define SOL_UDP IPPROTO_UDP
-#endif
 
 /* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
  * previously defined IPV6_PKTINFO */
@@ -513,17 +498,14 @@ static int open_socket(private_socket_default_socket_t *this,
                DBG1(DBG_NET, "installing IKE bypass policy failed");
        }
 
-#ifndef __APPLE__
+       /* enable UDP decapsulation globally, only for one socket needed */
+       if (family == AF_INET && port == CHARON_NATT_PORT &&
+               !hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
+                                                                                                  skt, family, port))
        {
-               /* enable UDP decapsulation globally, only for one socket needed */
-               int type = UDP_ENCAP_ESPINUDP;
-               if (family == AF_INET && port == CHARON_NATT_PORT &&
-                       setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
-               {
-                       DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno));
-               }
+               DBG1(DBG_NET, "enabling UDP decapsulation failed");
        }
-#endif
+
        return skt;
 }
 
@@ -568,18 +550,6 @@ socket_default_socket_t *socket_default_socket_create()
                                                                        "%s.max_packet", MAX_PACKET, charon->name),
        );
 
-#ifdef __APPLE__
-       {
-               int natt_port = CHARON_NATT_PORT;
-               if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &natt_port,
-                                                sizeof(natt_port)) != 0)
-               {
-                       DBG1(DBG_NET, "could not set net.inet.ipsec.esp_port to %d: %s",
-                                natt_port, strerror(errno));
-               }
-       }
-#endif
-
        this->ipv4 = open_socket(this, AF_INET, CHARON_UDP_PORT);
        if (this->ipv4 == 0)
        {
index ec61e61..787f6f4 100644 (file)
 /* length of non-esp marker */
 #define MARKER_LEN sizeof(u_int32_t)
 
-/* from linux/udp.h */
-#ifndef UDP_ENCAP
-#define UDP_ENCAP 100
-#endif /*UDP_ENCAP*/
-
-#ifndef UDP_ENCAP_ESPINUDP
-#define UDP_ENCAP_ESPINUDP 2
-#endif /*UDP_ENCAP_ESPINUDP*/
-
 /* these are not defined on some platforms */
 #ifndef SOL_IP
 #define SOL_IP IPPROTO_IP
@@ -64,9 +55,6 @@
 #ifndef SOL_IPV6
 #define SOL_IPV6 IPPROTO_IPV6
 #endif
-#ifndef SOL_UDP
-#define SOL_UDP IPPROTO_UDP
-#endif
 
 /* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
  * previously defined IPV6_PKTINFO */
@@ -352,7 +340,7 @@ METHOD(socket_t, receiver, status_t,
 static int open_socket(private_socket_dynamic_socket_t *this,
                                           int family, u_int16_t port)
 {
-       int on = TRUE, type = UDP_ENCAP_ESPINUDP;
+       int on = TRUE;
        struct sockaddr_storage addr;
        socklen_t addrlen;
        u_int sol, pktinfo = 0;
@@ -424,10 +412,12 @@ static int open_socket(private_socket_dynamic_socket_t *this,
        }
 
        /* enable UDP decapsulation on each socket */
-       if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
+       if (!hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
+                                                                                                  fd, family, port))
        {
-               DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno));
+               DBG1(DBG_NET, "enabling UDP decapsulation failed");
        }
+
        return fd;
 }
 
index 600f545..8d0b422 100644 (file)
 #define IKE_VERSION_OFFSET 17
 #define IKE_LENGTH_OFFSET 24
 
-/* from linux/udp.h */
-#ifndef UDP_ENCAP
-#define UDP_ENCAP 100
-#endif /*UDP_ENCAP*/
-
-#ifndef UDP_ENCAP_ESPINUDP
-#define UDP_ENCAP_ESPINUDP 2
-#endif /*UDP_ENCAP_ESPINUDP*/
-
 /* needed for older kernel headers */
 #ifndef IPV6_2292PKTINFO
 #define IPV6_2292PKTINFO 2
@@ -412,7 +403,6 @@ static int open_send_socket(private_socket_raw_socket_t *this,
                                                        int family, u_int16_t port)
 {
        int on = TRUE;
-       int type = UDP_ENCAP_ESPINUDP;
        struct sockaddr_storage addr;
        int skt;
 
@@ -463,22 +453,20 @@ static int open_send_socket(private_socket_raw_socket_t *this,
                return 0;
        }
 
-       if (family == AF_INET)
-       {
-               /* enable UDP decapsulation globally, only for one socket needed */
-               if (setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
-               {
-                       DBG1(DBG_NET, "unable to set UDP_ENCAP: %s; NAT-T may fail",
-                                strerror(errno));
-               }
-       }
-
        if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
                                                                                                skt, family))
        {
                DBG1(DBG_NET, "installing bypass policy on send socket failed");
        }
 
+       /* enable UDP decapsulation globally, only for one socket needed */
+       if (family == AF_INET && port == CHARON_NATT_PORT &&
+               !hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
+                                                                                                  skt, family, port))
+       {
+               DBG1(DBG_NET, "enabling UDP decapsulation failed");
+       }
+
        return skt;
 }
 
index b6bc5d9..650cb1e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2011 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  * Copyright (C) 2010 Martin Willi
  * Copyright (C) 2010 revosec AG
@@ -294,6 +294,16 @@ METHOD(kernel_interface_t, bypass_socket, bool,
        return this->ipsec->bypass_socket(this->ipsec, fd, family);
 }
 
+METHOD(kernel_interface_t, enable_udp_decap, bool,
+       private_kernel_interface_t *this, int fd, int family, u_int16_t port)
+{
+       if (!this->ipsec)
+       {
+               return FALSE;
+       }
+       return this->ipsec->enable_udp_decap(this->ipsec, fd, family, port);
+}
+
 METHOD(kernel_interface_t, get_address_by_ts, status_t,
        private_kernel_interface_t *this, traffic_selector_t *ts, host_t **ip)
 {
@@ -539,6 +549,7 @@ kernel_interface_t *kernel_interface_create()
                        .add_route = _add_route,
                        .del_route = _del_route,
                        .bypass_socket = _bypass_socket,
+                       .enable_udp_decap = _enable_udp_decap,
 
                        .get_address_by_ts = _get_address_by_ts,
                        .add_ipsec_interface = _add_ipsec_interface,
index 991cfaf..37b72f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2011 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
@@ -361,11 +361,23 @@ struct kernel_interface_t {
         *
         * @param fd                    socket file descriptor to setup policy for
         * @param family                protocol family of the socket
-        * @return                              TRUE of policy set up successfully
+        * @return                              TRUE if policy set up successfully
         */
        bool (*bypass_socket)(kernel_interface_t *this, int fd, int family);
 
        /**
+        * Enable decapsulation of ESP-in-UDP packets for the given port/socket.
+        *
+        * @param fd                    socket file descriptor
+        * @param family                protocol family of the socket
+        * @param port                  the UDP port
+        * @return                              TRUE if UDP decapsulation was enabled successfully
+        */
+       bool (*enable_udp_decap)(kernel_interface_t *this, int fd, int family,
+                                                        u_int16_t port);
+
+
+       /**
         * manager methods
         */
 
index 852f056..500a77c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2011 Tobias Brunner
+ * Copyright (C) 2006-2012 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
@@ -403,6 +403,17 @@ struct kernel_ipsec_t {
        bool (*bypass_socket)(kernel_ipsec_t *this, int fd, int family);
 
        /**
+        * Enable decapsulation of ESP-in-UDP packets for the given port/socket.
+        *
+        * @param fd                    socket file descriptor
+        * @param family                protocol family of the socket
+        * @param port                  the UDP port
+        * @return                              TRUE if UDP decapsulation was enabled successfully
+        */
+       bool (*enable_udp_decap)(kernel_ipsec_t *this, int fd, int family,
+                                                        u_int16_t port);
+
+       /**
         * Destroy the implementation.
         */
        void (*destroy) (kernel_ipsec_t *this);
index 7e58cf3..5f077b2 100644 (file)
@@ -2537,13 +2537,6 @@ 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)
 {
@@ -2585,7 +2578,10 @@ kernel_klips_ipsec_t *kernel_klips_ipsec_create()
                                .query_policy = _query_policy,
                                .del_policy = _del_policy,
                                .flush_policies = (void*)return_failed,
-                               .bypass_socket = _bypass_socket,
+                               /* KLIPS does not need a bypass policy for IKE */
+                               .bypass_socket = (void*)return_true,
+                               /* KLIPS does not need enabling UDP decap explicitly */
+                               .enable_udp_decap = (void*)return_true,
                                .destroy = _destroy,
                        },
                },
index b46450c..73d2900 100644 (file)
 #define IPV6_XFRM_POLICY 34
 #endif /*IPV6_XFRM_POLICY*/
 
+/* from linux/udp.h */
+#ifndef UDP_ENCAP
+#define UDP_ENCAP 100
+#endif
+
+#ifndef UDP_ENCAP_ESPINUDP
+#define UDP_ENCAP_ESPINUDP 2
+#endif
+
+/* this is not defined on some platforms */
+#ifndef SOL_UDP
+#define SOL_UDP IPPROTO_UDP
+#endif
+
 /** Default priority of installed policies */
 #define PRIO_BASE 512
 
@@ -2607,6 +2621,19 @@ METHOD(kernel_ipsec_t, bypass_socket, bool,
        return TRUE;
 }
 
+METHOD(kernel_ipsec_t, enable_udp_decap, bool,
+       private_kernel_netlink_ipsec_t *this, int fd, int family, u_int16_t port)
+{
+       int type = UDP_ENCAP_ESPINUDP;
+
+       if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
+       {
+               DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno));
+               return FALSE;
+       }
+       return TRUE;
+}
+
 METHOD(kernel_ipsec_t, destroy, void,
        private_kernel_netlink_ipsec_t *this)
 {
@@ -2654,6 +2681,7 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
                                .del_policy = _del_policy,
                                .flush_policies = _flush_policies,
                                .bypass_socket = _bypass_socket,
+                               .enable_udp_decap = _enable_udp_decap,
                                .destroy = _destroy,
                        },
                },
index dfe10f9..1342267 100644 (file)
@@ -51,6 +51,9 @@
 #include <unistd.h>
 #include <time.h>
 #include <errno.h>
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
 
 #include "kernel_pfkey_ipsec.h"
 
 #define IPV6_IPSEC_POLICY 34
 #endif
 
+/* from linux/udp.h */
+#ifndef UDP_ENCAP
+#define UDP_ENCAP 100
+#endif
+
+#ifndef UDP_ENCAP_ESPINUDP
+#define UDP_ENCAP_ESPINUDP 2
+#endif
+
+/* this is not defined on some platforms */
+#ifndef SOL_UDP
+#define SOL_UDP IPPROTO_UDP
+#endif
+
 /** default priority of installed policies */
 #define PRIO_BASE 512
 
@@ -2488,6 +2505,30 @@ METHOD(kernel_ipsec_t, bypass_socket, bool,
        return TRUE;
 }
 
+METHOD(kernel_ipsec_t, enable_udp_decap, bool,
+       private_kernel_pfkey_ipsec_t *this, int fd, int family, u_int16_t port)
+{
+#ifndef __APPLE__
+       int type = UDP_ENCAP_ESPINUDP;
+
+       if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
+       {
+               DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno));
+               return FALSE;
+       }
+#else /* __APPLE__ */
+       if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &port,
+                                        sizeof(port)) != 0)
+       {
+               DBG1(DBG_KNL, "could not set net.inet.ipsec.esp_port to %d: %s",
+                        port, strerror(errno));
+               return FALSE;
+       }
+#endif /* __APPLE__ */
+
+       return TRUE;
+}
+
 METHOD(kernel_ipsec_t, destroy, void,
        private_kernel_pfkey_ipsec_t *this)
 {
@@ -2532,6 +2573,7 @@ kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
                                .del_policy = _del_policy,
                                .flush_policies = _flush_policies,
                                .bypass_socket = _bypass_socket,
+                               .enable_udp_decap = _enable_udp_decap,
                                .destroy = _destroy,
                        },
                },