pluto: Listen for kernel events via libhydra's kernel interface.
authorTobias Brunner <tobias@strongswan.org>
Tue, 3 Aug 2010 09:58:47 +0000 (11:58 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 2 Sep 2010 17:04:22 +0000 (19:04 +0200)
src/pluto/kernel.c
src/pluto/kernel.h
src/pluto/plutomain.c
src/pluto/server.c

index 690f28a..164e428 100644 (file)
@@ -38,6 +38,7 @@
 #include <library.h>
 #include <hydra.h>
 #include <crypto/rngs/rng.h>
+#include <kernel/kernel_listener.h>
 
 #ifdef KLIPS
 #include <signal.h>
@@ -66,6 +67,7 @@
 #include "nat_traversal.h"
 #include "alg_info.h"
 #include "kernel_alg.h"
+#include "pluto.h"
 
 
 bool can_do_IPcomp = TRUE;  /* can system actually perform IPCOMP? */
@@ -182,6 +184,22 @@ static traffic_selector_t *traffic_selector_from_subnet(const ip_subnet *client,
        return ts;
 }
 
+/**
+ * Helper function that converts a traffic_selector_t to an ip_subnet.
+ */
+static ip_subnet subnet_from_traffic_selector(traffic_selector_t *ts)
+{
+       ip_subnet subnet;
+       host_t *net;
+       u_int8_t mask;
+       ts->to_subnet(ts, &net, &mask);
+       subnet.addr = *(ip_address*)net->get_sockaddr(net);
+       subnet.maskbits = mask;
+       net->destroy(net);
+       return subnet;
+}
+
+
 void record_and_initiate_opportunistic(const ip_subnet *ours,
                                                                           const ip_subnet *his,
                                                                           int transport_proto, const char *why)
@@ -1773,17 +1791,63 @@ failed:
 
 const struct kernel_ops *kernel_ops;
 
-#endif /* KLIPS */
+/**
+ * Data for acquire events
+ */
+typedef struct {
+       /** Subnets */
+       ip_subnet src, dst;
+       /** Transport protocol */
+       int proto;
+} acquire_data_t;
 
-void init_kernel(void)
+/**
+ * Callback for acquire events (called by main thread)
+ */
+void handle_acquire(acquire_data_t *this)
 {
-#ifdef KLIPS
+       record_and_initiate_opportunistic(&this->src, &this->dst, this->proto,
+                                                                         "%acquire");
+}
+
+/**
+ * Handler for kernel events (called by thread-pool thread)
+ */
+kernel_listener_t *kernel_handler;
 
-       if (no_klips)
+METHOD(kernel_listener_t, acquire, bool,
+          kernel_listener_t *this, u_int32_t reqid,
+          traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+{
+       if (src_ts && dst_ts)
        {
-               kernel_ops = &noklips_kernel_ops;
-               return;
+               acquire_data_t *data;
+               DBG(DBG_CONTROL,
+                       DBG_log("creating acquire event for policy %R === %R "
+                                       "with reqid {%u}", src_ts, dst_ts, reqid));
+               INIT(data,
+                       .src = subnet_from_traffic_selector(src_ts),
+                       .dst = subnet_from_traffic_selector(dst_ts),
+                       .proto = src_ts->get_protocol(src_ts),
+               );
+               pluto->events->queue(pluto->events, (void*)handle_acquire, data, free);
        }
+       else
+       {
+               DBG(DBG_CONTROL,
+                       DBG_log("ignoring acquire without traffic selectors for policy "
+                                       "with reqid {%u}", reqid));
+       }
+       DESTROY_IF(src_ts);
+       DESTROY_IF(dst_ts);
+       return TRUE;
+}
+
+#endif /* KLIPS */
+
+void init_kernel(void)
+{
+#ifdef KLIPS
 
        init_pfkey();
 
@@ -1807,14 +1871,23 @@ void init_kernel(void)
        }
 #endif
 
-       if (kernel_ops->init)
-       {
-               kernel_ops->init();
-       }
-
        /* register SA types that we can negotiate */
        can_do_IPcomp = FALSE;  /* until we get a response from KLIPS */
        kernel_ops->pfkey_register();
+
+       INIT(kernel_handler,
+               .acquire = _acquire,
+       );
+       hydra->kernel_interface->add_listener(hydra->kernel_interface,
+                                                                                 kernel_handler);
+#endif
+}
+
+void kernel_finalize()
+{
+#ifdef KLIPS
+       hydra->kernel_interface->remove_listener(hydra->kernel_interface,
+                                                                                        kernel_handler);
 #endif
 }
 
index 26efd00..9b1d57a 100644 (file)
@@ -151,6 +151,7 @@ extern void record_and_initiate_opportunistic(const ip_subnet *
                                                                                          , const char *why);
 
 extern void init_kernel(void);
+extern void kernel_finalize(void);
 
 extern bool trap_connection(struct connection *c);
 extern void unroute_connection(struct connection *c);
index c172e8f..ecb4aa5 100644 (file)
@@ -786,6 +786,7 @@ void exit_pluto(int status)
        free_remembered_public_keys();
        delete_every_connection();
        whack_attribute_finalize(); /* free in-memory pools */
+       kernel_finalize();
        fetch_finalize();           /* stop fetching thread */
        free_crl_fetch();           /* free chain of crl fetch requests */
        free_ocsp_fetch();          /* free chain of ocsp fetch requests */
index 6ad4964..1f90039 100644 (file)
@@ -859,20 +859,6 @@ call_server(void)
                                maxfd = events_fd;
                        FD_SET(events_fd, &readfds);
 
-#ifdef KLIPS
-                       if (!no_klips)
-                       {
-                               int fd = *kernel_ops->async_fdp;
-
-                               if (kernel_ops->process_queue)
-                                       kernel_ops->process_queue();
-                               if (maxfd < fd)
-                                       maxfd = fd;
-                               passert(!FD_ISSET(fd, &readfds));
-                               FD_SET(fd, &readfds);
-                       }
-#endif
-
                        if (listening)
                        {
                                for (ifp = interfaces; ifp != NULL; ifp = ifp->next)
@@ -964,19 +950,6 @@ call_server(void)
                                ndes--;
                        }
 
-#ifdef KLIPS
-                       if (!no_klips && FD_ISSET(*kernel_ops->async_fdp, &readfds))
-                       {
-                               passert(ndes > 0);
-                               DBG(DBG_CONTROL,
-                                       DBG_log(BLANK_FORMAT);
-                                       DBG_log("*received kernel message"));
-                               kernel_ops->process_msg();
-                               passert(GLOBALS_ARE_RESET());
-                               ndes--;
-                       }
-#endif
-
                        for (ifp = interfaces; ifp != NULL; ifp = ifp->next)
                        {
                                if (FD_ISSET(ifp->fd, &readfds))