aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libcharon/kernel/kernel_handler.c12
-rw-r--r--src/libcharon/processing/jobs/update_sa_job.c33
-rw-r--r--src/libcharon/processing/jobs/update_sa_job.h8
-rw-r--r--src/libhydra/kernel/kernel_interface.c7
-rw-r--r--src/libhydra/kernel/kernel_interface.h7
-rw-r--r--src/libhydra/kernel/kernel_listener.h7
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c22
-rw-r--r--src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c20
8 files changed, 75 insertions, 41 deletions
diff --git a/src/libcharon/kernel/kernel_handler.c b/src/libcharon/kernel/kernel_handler.c
index a6656e7d5..96a51fabd 100644
--- a/src/libcharon/kernel/kernel_handler.c
+++ b/src/libcharon/kernel/kernel_handler.c
@@ -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;
}
diff --git a/src/libcharon/processing/jobs/update_sa_job.c b/src/libcharon/processing/jobs/update_sa_job.c
index e6d7da2c6..862506d90 100644
--- a/src/libcharon/processing/jobs/update_sa_job.c
+++ b/src/libcharon/processing/jobs/update_sa_job.c
@@ -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;
}
-
diff --git a/src/libcharon/processing/jobs/update_sa_job.h b/src/libcharon/processing/jobs/update_sa_job.h
index 55a3df83e..9c19f5b6e 100644
--- a/src/libcharon/processing/jobs/update_sa_job.h
+++ b/src/libcharon/processing/jobs/update_sa_job.h
@@ -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_ @}*/
diff --git a/src/libhydra/kernel/kernel_interface.c b/src/libhydra/kernel/kernel_interface.c
index b5ade37d1..943b513b2 100644
--- a/src/libhydra/kernel/kernel_interface.c
+++ b/src/libhydra/kernel/kernel_interface.c
@@ -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);
}
diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h
index 2db53f504..2d484251f 100644
--- a/src/libhydra/kernel/kernel_interface.h
+++ b/src/libhydra/kernel/kernel_interface.h
@@ -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.
diff --git a/src/libhydra/kernel/kernel_listener.h b/src/libhydra/kernel/kernel_listener.h
index 122453f72..8074356a4 100644
--- a/src/libhydra/kernel/kernel_listener.h
+++ b/src/libhydra/kernel/kernel_listener.h
@@ -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.
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index f8077d836..b4875ba58 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -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);
}
}
}
diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index 9b846864e..8b893f485 100644
--- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -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*/