diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/kernel/kernel_handler.c | 12 | ||||
-rw-r--r-- | src/libcharon/processing/jobs/update_sa_job.c | 33 | ||||
-rw-r--r-- | src/libcharon/processing/jobs/update_sa_job.h | 8 | ||||
-rw-r--r-- | src/libhydra/kernel/kernel_interface.c | 7 | ||||
-rw-r--r-- | src/libhydra/kernel/kernel_interface.h | 7 | ||||
-rw-r--r-- | src/libhydra/kernel/kernel_listener.h | 7 | ||||
-rw-r--r-- | src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c | 22 | ||||
-rw-r--r-- | src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 20 |
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*/ |