kernel-interface: Raise mapping event with a proto/SPI/dst tuple
authorMartin Willi <martin@revosec.ch>
Mon, 27 Oct 2014 14:38:47 +0000 (15:38 +0100)
committerMartin Willi <martin@revosec.ch>
Fri, 20 Feb 2015 12:34:51 +0000 (13:34 +0100)
src/libcharon/kernel/kernel_handler.c
src/libcharon/processing/jobs/update_sa_job.c
src/libcharon/processing/jobs/update_sa_job.h
src/libhydra/kernel/kernel_interface.c
src/libhydra/kernel/kernel_interface.h
src/libhydra/kernel/kernel_listener.h
src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c

index a6656e7..96a51fa 100644 (file)
@@ -94,14 +94,16 @@ METHOD(kernel_listener_t, expire, bool,
 }
 
 METHOD(kernel_listener_t, mapping, bool,
-       private_kernel_handler_t *this, u_int32_t reqid, u_int32_t spi,
-       host_t *remote)
+       private_kernel_handler_t *this, u_int8_t protocol, u_int32_t spi,
+       host_t *dst, host_t *remote)
 {
-       DBG1(DBG_KNL, "NAT mappings of ESP CHILD_SA with SPI %.8x and reqid {%u} "
-                "changed, queuing update job", ntohl(spi), reqid);
+       protocol_id_t proto = proto_ip2ike(protocol);
+
+       DBG1(DBG_KNL, "NAT mappings of CHILD_SA %N/0x%08x/%H changed, "
+                "queuing update job", protocol_id_names, proto, ntohl(spi), dst);
 
        lib->processor->queue_job(lib->processor,
-                                                         (job_t*)update_sa_job_create(reqid, remote));
+                                               (job_t*)update_sa_job_create(proto, spi, dst, remote));
        return TRUE;
 }
 
index e6d7da2..862506d 100644 (file)
@@ -27,15 +27,26 @@ typedef struct private_update_sa_job_t private_update_sa_job_t;
  * Private data of an update_sa_job_t Object
  */
 struct private_update_sa_job_t {
+
        /**
         * public update_sa_job_t interface
         */
        update_sa_job_t public;
 
        /**
-        * reqid of the CHILD_SA
+        * protocol of the CHILD_SA (ESP/AH)
+        */
+       protocol_id_t protocol;
+
+       /**
+        * SPI of the CHILD_SA
         */
-       u_int32_t reqid;
+       u_int32_t spi;
+
+       /**
+        * Old SA destination address
+        */
+       host_t *dst;
 
        /**
         * New SA address and port
@@ -46,6 +57,7 @@ struct private_update_sa_job_t {
 METHOD(job_t, destroy, void,
        private_update_sa_job_t *this)
 {
+       this->dst->destroy(this->dst);
        this->new->destroy(this->new);
        free(this);
 }
@@ -55,11 +67,12 @@ METHOD(job_t, execute, job_requeue_t,
 {
        ike_sa_t *ike_sa;
 
-       ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
-                                                                                                       this->reqid, TRUE);
+       ike_sa = charon->child_sa_manager->checkout(charon->child_sa_manager,
+                                                                       this->protocol, this->spi, this->dst, NULL);
        if (ike_sa == NULL)
        {
-               DBG1(DBG_JOB, "CHILD_SA with reqid %d not found for update", this->reqid);
+               DBG1(DBG_JOB, "CHILD_SA %N/0x%08x/%H not found for update",
+                        protocol_id_names, this->protocol, htonl(this->spi), this->dst);
        }
        else
        {
@@ -78,7 +91,8 @@ METHOD(job_t, get_priority, job_priority_t,
 /*
  * Described in header
  */
-update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new)
+update_sa_job_t *update_sa_job_create(protocol_id_t protocol,
+                                                                         u_int32_t spi, host_t *dst, host_t *new)
 {
        private_update_sa_job_t *this;
 
@@ -90,10 +104,11 @@ update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new)
                                .destroy = _destroy,
                        },
                },
-               .reqid = reqid,
-               .new = new,
+               .protocol = protocol,
+               .spi = spi,
+               .dst = dst->clone(dst),
+               .new = new->clone(new),
        );
 
        return &this->public;
 }
-
index 55a3df8..9c19f5b 100644 (file)
@@ -26,6 +26,7 @@ typedef struct update_sa_job_t update_sa_job_t;
 #include <library.h>
 #include <networking/host.h>
 #include <processing/jobs/job.h>
+#include <config/proposal.h>
 
 /**
  * Update the addresses of an IKE and its CHILD_SAs.
@@ -41,10 +42,13 @@ struct update_sa_job_t {
 /**
  * Creates a job to update IKE and CHILD_SA addresses.
  *
- * @param reqid                        reqid of the CHILD_SA
+ * @param protocol             IPsec protocol of SA to update
+ * @param spi                  SPI of SA to update
+ * @param dst                  old destination host of SA to update
  * @param new                  new address and port
  * @return                             update_sa_job_t object
  */
-update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new);
+update_sa_job_t *update_sa_job_create(protocol_id_t protocol,
+                                                                         u_int32_t spi, host_t *dst, host_t *new);
 
 #endif /** UPDATE_SA_JOB_H_ @}*/
index b5ade37..943b513 100644 (file)
@@ -836,17 +836,18 @@ METHOD(kernel_interface_t, expire, void,
 }
 
 METHOD(kernel_interface_t, mapping, void,
-       private_kernel_interface_t *this, u_int32_t reqid, u_int32_t spi,
-       host_t *remote)
+       private_kernel_interface_t *this, u_int8_t protocol, u_int32_t spi,
+       host_t *dst, host_t *remote)
 {
        kernel_listener_t *listener;
        enumerator_t *enumerator;
+
        this->mutex->lock(this->mutex);
        enumerator = this->listeners->create_enumerator(this->listeners);
        while (enumerator->enumerate(enumerator, &listener))
        {
                if (listener->mapping &&
-                       !listener->mapping(listener, reqid, spi, remote))
+                       !listener->mapping(listener, protocol, spi, dst, remote))
                {
                        this->listeners->remove_at(this->listeners, enumerator);
                }
index 2db53f5..2d48425 100644 (file)
@@ -570,12 +570,13 @@ struct kernel_interface_t {
        /**
         * Raise a mapping event.
         *
-        * @param reqid                 reqid of the SA
+        * @param protocol              protocol of affected SA
         * @param spi                   spi of the SA
+        * @param dst                   original destination address of SA
         * @param remote                new remote host
         */
-       void (*mapping)(kernel_interface_t *this, u_int32_t reqid, u_int32_t spi,
-                                       host_t *remote);
+       void (*mapping)(kernel_interface_t *this, u_int8_t protocol, u_int32_t spi,
+                                       host_t *dst, host_t *remote);
 
        /**
         * Raise a migrate event.
index 122453f..8074356 100644 (file)
@@ -61,13 +61,14 @@ struct kernel_listener_t {
        /**
         * Hook called if the NAT mappings of an IPsec SA changed.
         *
-        * @param reqid                 reqid of the SA
+        * @param protocol              IPsec protocol of affected SA
         * @param spi                   spi of the SA
+        * @param dst                   old destinatino address of SA
         * @param remote                new remote host
         * @return                              TRUE to remain registered, FALSE to unregister
         */
-       bool (*mapping)(kernel_listener_t *this, u_int32_t reqid, u_int32_t spi,
-                                       host_t *remote);
+       bool (*mapping)(kernel_listener_t *this, u_int8_t protocol, u_int32_t spi,
+                                       host_t *dst, host_t *remote);
 
        /**
         * Hook called if a migrate event for a policy is received.
index f8077d8..b4875ba 100644 (file)
@@ -973,23 +973,29 @@ static void process_mapping(private_kernel_netlink_ipsec_t *this,
                                                        struct nlmsghdr *hdr)
 {
        struct xfrm_user_mapping *mapping;
-       u_int32_t spi, reqid;
+       u_int32_t spi;
 
        mapping = NLMSG_DATA(hdr);
        spi = mapping->id.spi;
-       reqid = mapping->reqid;
 
        DBG2(DBG_KNL, "received a XFRM_MSG_MAPPING");
 
        if (mapping->id.proto == IPPROTO_ESP)
        {
-               host_t *host;
-               host = xfrm2host(mapping->id.family, &mapping->new_saddr,
-                                                mapping->new_sport);
-               if (host)
+               host_t *dst, *new;
+
+               dst = xfrm2host(mapping->id.family, &mapping->id.daddr, 0);
+               if (dst)
                {
-                       hydra->kernel_interface->mapping(hydra->kernel_interface, reqid,
-                                                                                        spi, host);
+                       new = xfrm2host(mapping->id.family, &mapping->new_saddr,
+                                                       mapping->new_sport);
+                       if (new)
+                       {
+                               hydra->kernel_interface->mapping(hydra->kernel_interface,
+                                                                                                IPPROTO_ESP, spi, dst, new);
+                               new->destroy(new);
+                       }
+                       dst->destroy(dst);
                }
        }
 }
index 9b84686..8b893f4 100644 (file)
@@ -1388,9 +1388,9 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this,
                                                        struct sadb_msg* msg)
 {
        pfkey_msg_t response;
-       u_int32_t spi, reqid;
+       u_int32_t spi;
        sockaddr_t *sa;
-       host_t *host;
+       host_t *dst, *new;
 
        DBG2(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING");
 
@@ -1408,7 +1408,6 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this,
        }
 
        spi = response.sa->sadb_sa_spi;
-       reqid = response.x_sa2->sadb_x_sa2_reqid;
 
        if (satype2proto(msg->sadb_msg_satype) != IPPROTO_ESP)
        {
@@ -1416,6 +1415,7 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this,
        }
 
        sa = (sockaddr_t*)(response.dst + 1);
+       dst = host_create_from_sockaddr(sa);
        switch (sa->sa_family)
        {
                case AF_INET:
@@ -1433,12 +1433,16 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this,
                default:
                        break;
        }
-
-       host = host_create_from_sockaddr(sa);
-       if (host)
+       if (dst)
        {
-               hydra->kernel_interface->mapping(hydra->kernel_interface, reqid,
-                                                                                spi, host);
+               new = host_create_from_sockaddr(sa);
+               if (new)
+               {
+                       hydra->kernel_interface->mapping(hydra->kernel_interface,
+                                                                                        IPPROTO_ESP, spi, dst, new);
+                       new->destroy(new);
+               }
+               dst->destroy(dst);
        }
 }
 #endif /*SADB_X_NAT_T_NEW_MAPPING*/