aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/charon-tkm/src/tkm/tkm_kernel_ipsec.c2
-rw-r--r--src/frontends/android/jni/libandroidbridge/kernel/android_ipsec.c2
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_ipsec.c2
-rw-r--r--src/libcharon/sa/child_sa.c24
-rw-r--r--src/libhydra/kernel/kernel_interface.c4
-rw-r--r--src/libhydra/kernel/kernel_interface.h3
-rw-r--r--src/libhydra/kernel/kernel_ipsec.h3
-rw-r--r--src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c2
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c8
-rw-r--r--src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c16
10 files changed, 50 insertions, 16 deletions
diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
index 69aefea97..a276166e2 100644
--- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
+++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
@@ -216,7 +216,7 @@ sad_failure:
METHOD(kernel_ipsec_t, query_sa, status_t,
private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, mark_t mark, u_int64_t *bytes,
- u_int64_t *packets)
+ u_int64_t *packets, u_int32_t *time)
{
return NOT_SUPPORTED;
}
diff --git a/src/frontends/android/jni/libandroidbridge/kernel/android_ipsec.c b/src/frontends/android/jni/libandroidbridge/kernel/android_ipsec.c
index 8e8534190..c37ca26ab 100644
--- a/src/frontends/android/jni/libandroidbridge/kernel/android_ipsec.c
+++ b/src/frontends/android/jni/libandroidbridge/kernel/android_ipsec.c
@@ -86,7 +86,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, mark_t mark,
- u_int64_t *bytes, u_int64_t *packets)
+ u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
{
return NOT_SUPPORTED;
}
diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
index 4f84845a3..49e35c4ca 100644
--- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c
+++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
@@ -71,7 +71,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, mark_t mark,
- u_int64_t *bytes, u_int64_t *packets)
+ u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
{
return NOT_SUPPORTED;
}
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 5861fe37c..34435a140 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -424,6 +424,7 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
{
status_t status = FAILED;
u_int64_t bytes, packets;
+ u_int32_t time;
if (inbound)
{
@@ -432,13 +433,17 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
status = hydra->kernel_interface->query_sa(hydra->kernel_interface,
this->other_addr, this->my_addr, this->my_spi,
proto_ike2ip(this->protocol), this->mark_in,
- &bytes, &packets);
+ &bytes, &packets, &time);
if (status == SUCCESS)
{
if (bytes > this->my_usebytes)
{
this->my_usebytes = bytes;
this->my_usepackets = packets;
+ if (time)
+ {
+ this->my_usetime = time;
+ }
return SUCCESS;
}
return FAILED;
@@ -452,13 +457,17 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
status = hydra->kernel_interface->query_sa(hydra->kernel_interface,
this->my_addr, this->other_addr, this->other_spi,
proto_ike2ip(this->protocol), this->mark_out,
- &bytes, &packets);
+ &bytes, &packets, &time);
if (status == SUCCESS)
{
if (bytes > this->other_usebytes)
{
this->other_usebytes = bytes;
this->other_usepackets = packets;
+ if (time)
+ {
+ this->other_usetime = time;
+ }
return SUCCESS;
}
return FAILED;
@@ -471,7 +480,7 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
/**
* updates the cached usetime
*/
-static void update_usetime(private_child_sa_t *this, bool inbound)
+static bool update_usetime(private_child_sa_t *this, bool inbound)
{
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
@@ -511,7 +520,7 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
if (last_use == 0)
{
- return;
+ return FALSE;
}
if (inbound)
{
@@ -521,6 +530,7 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
{
this->other_usetime = last_use;
}
+ return TRUE;
}
METHOD(child_sa_t, get_usestats, void,
@@ -534,7 +544,11 @@ METHOD(child_sa_t, get_usestats, void,
*/
if (time)
{
- update_usetime(this, inbound);
+ if (!update_usetime(this, inbound) && !bytes && !packets)
+ {
+ /* if policy query did not yield a usetime, query SAs instead */
+ update_usebytes(this, inbound);
+ }
}
}
if (time)
diff --git a/src/libhydra/kernel/kernel_interface.c b/src/libhydra/kernel/kernel_interface.c
index 290c25a62..d81fa33c7 100644
--- a/src/libhydra/kernel/kernel_interface.c
+++ b/src/libhydra/kernel/kernel_interface.c
@@ -208,14 +208,14 @@ METHOD(kernel_interface_t, update_sa, status_t,
METHOD(kernel_interface_t, query_sa, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, mark_t mark,
- u_int64_t *bytes, u_int64_t *packets)
+ u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, mark,
- bytes, packets);
+ bytes, packets, time);
}
METHOD(kernel_interface_t, del_sa, status_t,
diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h
index fd64f50c2..b333cae99 100644
--- a/src/libhydra/kernel/kernel_interface.h
+++ b/src/libhydra/kernel/kernel_interface.h
@@ -197,11 +197,12 @@ struct kernel_interface_t {
* @param mark optional mark for this SA
* @param[out] bytes the number of bytes processed by SA
* @param[out] packets number of packets processed by SA
+ * @param[out] time last time of SA use
* @return SUCCESS if operation completed
*/
status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, mark_t mark,
- u_int64_t *bytes, u_int64_t *packets);
+ u_int64_t *bytes, u_int64_t *packets, u_int32_t *time);
/**
* Delete a previously installed SA from the SAD.
diff --git a/src/libhydra/kernel/kernel_ipsec.h b/src/libhydra/kernel/kernel_ipsec.h
index ba67238e5..f61f3c3aa 100644
--- a/src/libhydra/kernel/kernel_ipsec.h
+++ b/src/libhydra/kernel/kernel_ipsec.h
@@ -155,11 +155,12 @@ struct kernel_ipsec_t {
* @param mark optional mark for this SA
* @param[out] bytes the number of bytes processed by SA
* @param[out] packets number of packets processed by SA
+ * @param[out] time last time of SA use
* @return SUCCESS if operation completed
*/
status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, mark_t mark,
- u_int64_t *bytes, u_int64_t *packets);
+ u_int64_t *bytes, u_int64_t *packets, u_int32_t *time);
/**
* Delete a previusly installed SA from the SAD.
diff --git a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
index 2d09d33cc..32bea7383 100644
--- a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
+++ b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
@@ -1911,7 +1911,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, mark_t mark,
- u_int64_t *bytes, u_int64_t *packets)
+ u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
{
return NOT_SUPPORTED; /* TODO */
}
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index b30c9533f..58bce6247 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -1595,7 +1595,7 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, mark_t mark,
- u_int64_t *bytes, u_int64_t *packets)
+ u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
{
netlink_buf_t request;
struct nlmsghdr *out = NULL, *hdr;
@@ -1680,6 +1680,12 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
{
*packets = sa->curlft.packets;
}
+ if (time)
+ { /* curlft contains an "use" time, but that contains a timestamp
+ * of the first use, not the last. Last use time must be queried
+ * on the policy on Linux */
+ *time = 0;
+ }
status = SUCCESS;
}
memwipe(out, len);
diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index 3ade6f4a5..ecab2827a 100644
--- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -1804,7 +1804,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, mark_t mark,
- u_int64_t *bytes, u_int64_t *packets)
+ u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1862,6 +1862,18 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
/* not supported by PF_KEY */
*packets = 0;
}
+ if (time)
+ {
+#ifdef __APPLE__
+ /* OS X uses the "last" time of use in usetime */
+ *time = response.lft_current->sadb_lifetime_usetime;
+#else /* !__APPLE__ */
+ /* on Linux, sadb_lifetime_usetime is set to the "first" time of use,
+ * which is actually correct according to PF_KEY. We have to query
+ * policies for the last usetime. */
+ *time = 0;
+#endif /* !__APPLE__ */
+ }
free(out);
return SUCCESS;
@@ -2435,7 +2447,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
}
else if (response.lft_current == NULL)
{
- DBG1(DBG_KNL, "unable to query policy %R === %R %N: kernel reports no "
+ DBG2(DBG_KNL, "unable to query policy %R === %R %N: kernel reports no "
"use time", src_ts, dst_ts, policy_dir_names, direction);
free(out);
return FAILED;