pluto: Handle changed NAT mappings via libhydra's kernel interface.
authorTobias Brunner <tobias@strongswan.org>
Mon, 16 Aug 2010 17:07:30 +0000 (19:07 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 2 Sep 2010 17:04:24 +0000 (19:04 +0200)
src/pluto/kernel.c
src/pluto/nat_traversal.c
src/pluto/nat_traversal.h

index 5918f99..b384407 100644 (file)
@@ -1738,6 +1738,11 @@ failed:
 }
 
 /**
+ * Handler for kernel events (called by thread-pool thread)
+ */
+kernel_listener_t *kernel_handler;
+
+/**
  * Data for acquire events
  */
 typedef struct {
@@ -1756,11 +1761,6 @@ void handle_acquire(acquire_data_t *this)
                                                                          "%acquire");
 }
 
-/**
- * Handler for kernel events (called by thread-pool thread)
- */
-kernel_listener_t *kernel_handler;
-
 METHOD(kernel_listener_t, acquire, bool,
           kernel_listener_t *this, u_int32_t reqid,
           traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
@@ -1789,6 +1789,41 @@ METHOD(kernel_listener_t, acquire, bool,
        return TRUE;
 }
 
+/**
+ * Data for mapping events
+ */
+typedef struct {
+       /** reqid, spi of affected SA */
+       u_int32_t reqid, spi;
+       /** new endpont */
+       ip_address new_end;
+} mapping_data_t;
+
+/**
+ * Callback for mapping events (called by main thread)
+ */
+void handle_mapping(mapping_data_t *this)
+{
+       process_nat_t_new_mapping(this->reqid, this->spi, &this->new_end);
+}
+
+
+METHOD(kernel_listener_t, mapping, bool,
+          kernel_listener_t *this, u_int32_t reqid, u_int32_t spi, host_t *remote)
+{
+       mapping_data_t *data;
+       DBG(DBG_CONTROL,
+               DBG_log("creating mapping event for SA with SPI %.8x and reqid {%u}",
+                               spi, reqid));
+       INIT(data,
+               .reqid = reqid,
+               .spi = spi,
+               .new_end = *(ip_address*)remote->get_sockaddr(remote),
+       );
+       pluto->events->queue(pluto->events, (void*)handle_mapping, data, free);
+       return TRUE;
+}
+
 void init_kernel(void)
 {
        /* register SA types that we can negotiate */
@@ -1797,6 +1832,7 @@ void init_kernel(void)
 
        INIT(kernel_handler,
                .acquire = _acquire,
+               .mapping = _mapping,
        );
        hydra->kernel_interface->add_listener(hydra->kernel_interface,
                                                                                  kernel_handler);
index feedf2a..5e9353b 100644 (file)
@@ -1,6 +1,9 @@
-/* FreeS/WAN NAT-Traversal
- * Copyright (C) 2002-2005 Mathieu Lafon - Arkoon Network Security
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2009 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2002-2005 Mathieu Lafon
+ * Arkoon Network Security
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
 #include <signal.h>     /* used only if MSG_NOSIGNAL not defined */
 #include <sys/queue.h>
 
-#include <freeswan.h>
-#include <pfkeyv2.h>
-#include <pfkey.h>
-
 #include <library.h>
 #include <crypto/hashers/hasher.h>
 
@@ -796,80 +795,51 @@ void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st)
        }
 }
 
-struct _new_klips_mapp_nfo {
-               struct sadb_sa *sa;
-               ip_address src, dst;
-               u_int16_t sport, dport;
+struct _new_kernel_mapp_nfo {
+               u_int32_t reqid;
+               u_int32_t spi;
+               ip_address *addr;
 };
 
-static void nat_t_new_klips_mapp (struct state *st, void *data)
+static void nat_t_new_kernel_mapp (struct state *st, void *data)
 {
        connection_t *c = st->st_connection;
-       struct _new_klips_mapp_nfo *nfo = (struct _new_klips_mapp_nfo *)data;
+       struct _new_kernel_mapp_nfo *nfo = (struct _new_kernel_mapp_nfo *)data;
 
        if (c != NULL && st->st_esp.present
-       &&  sameaddr(&c->spd.that.host_addr, &(nfo->src))
-       &&  st->st_esp.our_spi == nfo->sa->sadb_sa_spi)
-       {
-               nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port,
-                                                                 &(nfo->dst), nfo->dport);
-       }
-}
-
-void process_pfkey_nat_t_new_mapping(
-               struct sadb_msg *msg __attribute__ ((unused)),
-               struct sadb_ext *extensions[SADB_EXT_MAX + 1])
-{
-       struct _new_klips_mapp_nfo nfo;
-       struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC];
-       struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST];
-       struct sockaddr *srca, *dsta;
-       err_t ugh = NULL;
-
-       nfo.sa = (void *) extensions[SADB_EXT_SA];
-
-       if (!nfo.sa || !srcx || !dstx)
+               &&  nfo->spi == st->st_esp.our_spi
+               &&  nfo->reqid == c->spd.reqid)
        {
-               plog("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: "
-                               "got NULL params");
-               return;
-       }
-
-       srca = ((struct sockaddr *)(void *)&srcx[1]);
-       dsta = ((struct sockaddr *)(void *)&dstx[1]);
+               u_int16_t port = ntohs(portof(nfo->addr));
 
-       if (srca->sa_family != AF_INET || dsta->sa_family != AF_INET)
-       {
-               ugh = "only AF_INET supported";
-       }
-       else
-       {
-               char text_said[SATOT_BUF];
-               char _srca[ADDRTOT_BUF], _dsta[ADDRTOT_BUF];
-               ip_said said;
-
-               initaddr((const void *) &((const struct sockaddr_in *)srca)->sin_addr,
-                                               sizeof(((const struct sockaddr_in *)srca)->sin_addr),
-                                               srca->sa_family, &(nfo.src));
-               nfo.sport = ntohs(((const struct sockaddr_in *)srca)->sin_port);
-               initaddr((const void *) &((const struct sockaddr_in *)dsta)->sin_addr,
-                                               sizeof(((const struct sockaddr_in *)dsta)->sin_addr),
-                                               dsta->sa_family, &(nfo.dst));
-               nfo.dport = ntohs(((const struct sockaddr_in *)dsta)->sin_port);
+               DBG(DBG_NATT, {
+                       char text_said[SATOT_BUF];
+                       char olda[ADDRTOT_BUF];
+                       char newa[ADDRTOT_BUF];
+                       ip_said said;
 
-               DBG(DBG_NATT,
-                       initsaid(&nfo.src, nfo.sa->sadb_sa_spi, SA_ESP, &said);
+                       initsaid(&c->spd.that.host_addr, nfo->spi, SA_ESP, &said);
                        satot(&said, 0, text_said, SATOT_BUF);
-                       addrtot(&nfo.src, 0, _srca, ADDRTOT_BUF);
-                       addrtot(&nfo.dst, 0, _dsta, ADDRTOT_BUF);
-                       DBG_log("new klips mapping %s %s:%d %s:%d",
-                                               text_said, _srca, nfo.sport, _dsta, nfo.dport);
-               )
+                       addrtot(&c->spd.that.host_addr, 0, olda, ADDRTOT_BUF);
+                       addrtot(nfo->addr, 0, newa, ADDRTOT_BUF);
+
+                       DBG_log("new kernel mapping %s %s:%d %s:%d",
+                                       text_said, olda, c->spd.that.host_port, newa, port);
+               })
 
-               for_each_state((void *)nat_t_new_klips_mapp, &nfo);
+               nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port,
+                                                                 nfo->addr, port);
        }
+}
 
-       if (ugh != NULL)
-               plog("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: %s", ugh);
+void process_nat_t_new_mapping(u_int32_t reqid, u_int32_t spi,
+                                                          ip_address *new_end)
+{
+       struct _new_kernel_mapp_nfo nfo = {
+               .reqid = reqid,
+               .spi = spi,
+               .addr = new_end,
+       };
+       for_each_state((void *)nat_t_new_kernel_mapp, &nfo);
 }
 
index 98b0a2b..80bdaf7 100644 (file)
@@ -1,5 +1,8 @@
-/* FreeS/WAN NAT-Traversal
- * Copyright (C) 2002-2003 Mathieu Lafon - Arkoon Network Security
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2002-2003 Mathieu Lafon
+ * Arkoon Network Security
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -115,11 +118,8 @@ void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st);
 /**
  * New NAT mapping
  */
-#ifdef __PFKEY_V2_H
-void process_pfkey_nat_t_new_mapping(
-               struct sadb_msg *,
-               struct sadb_ext *[SADB_EXT_MAX + 1]);
-#endif
+void process_nat_t_new_mapping(u_int32_t reqid, u_int32_t spi,
+                                                          ip_address *new_end);
 
 /**
  * IKE port floating