aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/charon/kernel/kernel_interface.c14
-rw-r--r--src/charon/kernel/kernel_interface.h13
-rw-r--r--src/charon/kernel/kernel_ipsec.h13
-rw-r--r--src/charon/plugins/kernel_klips/kernel_klips_ipsec.c11
-rw-r--r--src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c69
-rw-r--r--src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c11
-rw-r--r--src/charon/plugins/load_tester/load_tester_ipsec.c11
-rw-r--r--src/charon/plugins/stroke/stroke_list.c42
-rw-r--r--src/charon/sa/child_sa.c30
-rw-r--r--src/charon/sa/child_sa.h8
10 files changed, 203 insertions, 19 deletions
diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c
index 5188b79fe..53ae1d200 100644
--- a/src/charon/kernel/kernel_interface.c
+++ b/src/charon/kernel/kernel_interface.c
@@ -104,6 +104,19 @@ static status_t update_sa(private_kernel_interface_t *this, u_int32_t spi,
}
/**
+ * Implementation of kernel_interface_t.query_sa
+ */
+static status_t query_sa(private_kernel_interface_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+{
+ if (!this->ipsec)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, bytes);
+}
+
+/**
* Implementation of kernel_interface_t.del_sa
*/
static status_t del_sa(private_kernel_interface_t *this, host_t *src, host_t *dst,
@@ -387,6 +400,7 @@ kernel_interface_t *kernel_interface_create()
this->public.get_cpi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
this->public.update_sa = (status_t(*)(kernel_interface_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
+ this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa;
this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t,protocol_id_t,u_int32_t,ipsec_mode_t,u_int16_t,u_int16_t,bool))add_policy;
this->public.query_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
diff --git a/src/charon/kernel/kernel_interface.h b/src/charon/kernel/kernel_interface.h
index 8c58c959a..c4a273a34 100644
--- a/src/charon/kernel/kernel_interface.h
+++ b/src/charon/kernel/kernel_interface.h
@@ -141,6 +141,19 @@ struct kernel_interface_t {
bool encap, bool new_encap);
/**
+ * Query the number of bytes processed by an SA from the SAD.
+ *
+ * @param src source address for this SA
+ * @param dst destination address for this SA
+ * @param spi SPI allocated by us or remote peer
+ * @param protocol protocol for this SA (ESP/AH)
+ * @param[out] bytes the number of bytes processed by SA
+ * @return SUCCESS if operation completed
+ */
+ status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes);
+
+ /**
* Delete a previously installed SA from the SAD.
*
* @param src source address for this SA
diff --git a/src/charon/kernel/kernel_ipsec.h b/src/charon/kernel/kernel_ipsec.h
index 6e8c5bc63..d6438c197 100644
--- a/src/charon/kernel/kernel_ipsec.h
+++ b/src/charon/kernel/kernel_ipsec.h
@@ -171,6 +171,19 @@ struct kernel_ipsec_t {
bool encap, bool new_encap);
/**
+ * Query the number of bytes processed by an SA from the SAD.
+ *
+ * @param src source address for this SA
+ * @param dst destination address for this SA
+ * @param spi SPI allocated by us or remote peer
+ * @param protocol protocol for this SA (ESP/AH)
+ * @param[out] bytes the number of bytes processed by SA
+ * @return SUCCESS if operation completed
+ */
+ status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes);
+
+ /**
* Delete a previusly installed SA from the SAD.
*
* @param src source address for this SA
diff --git a/src/charon/plugins/kernel_klips/kernel_klips_ipsec.c b/src/charon/plugins/kernel_klips/kernel_klips_ipsec.c
index c69ce4c9a..9a31c01f6 100644
--- a/src/charon/plugins/kernel_klips/kernel_klips_ipsec.c
+++ b/src/charon/plugins/kernel_klips/kernel_klips_ipsec.c
@@ -1934,6 +1934,16 @@ static status_t update_sa(private_kernel_klips_ipsec_t *this,
}
/**
+ * Implementation of kernel_interface_t.query_sa.
+ */
+static status_t query_sa(private_kernel_klips_ipsec_t *this, host_t *src,
+ host_t *dst, u_int32_t spi, protocol_id_t protocol,
+ u_int64_t *bytes)
+{
+ return NOT_SUPPORTED; /* TODO */
+}
+
+/**
* Implementation of kernel_interface_t.del_sa.
*/
static status_t del_sa(private_kernel_klips_ipsec_t *this, host_t *src,
@@ -2609,6 +2619,7 @@ kernel_klips_ipsec_t *kernel_klips_ipsec_create()
this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
+ this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa;
this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t,protocol_id_t,u_int32_t,ipsec_mode_t,u_int16_t,u_int16_t,bool))add_policy;
this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
index f5a845758..078ae3479 100644
--- a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -1233,6 +1233,74 @@ static status_t get_replay_state(private_kernel_netlink_ipsec_t *this,
}
/**
+ * Implementation of kernel_interface_t.query_sa.
+ */
+static status_t query_sa(private_kernel_netlink_ipsec_t *this, host_t *src,
+ host_t *dst, u_int32_t spi, protocol_id_t protocol,
+ u_int64_t *bytes)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *out = NULL, *hdr;
+ struct xfrm_usersa_id *sa_id;
+ struct xfrm_usersa_info *sa = NULL;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST;
+ hdr->nlmsg_type = XFRM_MSG_GETSA;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
+
+ sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
+ host2xfrm(dst, &sa_id->daddr);
+ sa_id->spi = spi;
+ sa_id->proto = proto_ike2kernel(protocol);
+ sa_id->family = dst->get_family(dst);
+
+ if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
+ {
+ hdr = out;
+ while (NLMSG_OK(hdr, len))
+ {
+ switch (hdr->nlmsg_type)
+ {
+ case XFRM_MSG_NEWSA:
+ {
+ sa = (struct xfrm_usersa_info*)NLMSG_DATA(hdr);
+ break;
+ }
+ case NLMSG_ERROR:
+ {
+ struct nlmsgerr *err = NLMSG_DATA(hdr);
+ DBG1(DBG_KNL, "querying SAD entry with SPI %.8x failed: %s (%d)",
+ ntohl(spi), strerror(-err->error), -err->error);
+ break;
+ }
+ default:
+ hdr = NLMSG_NEXT(hdr, len);
+ continue;
+ case NLMSG_DONE:
+ break;
+ }
+ break;
+ }
+ }
+
+ if (sa == NULL)
+ {
+ DBG2(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
+ free(out);
+ return FAILED;
+ }
+ *bytes = sa->curlft.bytes;
+
+ free(out);
+ return SUCCESS;
+}
+/**
* Implementation of kernel_interface_t.del_sa.
*/
static status_t del_sa(private_kernel_netlink_ipsec_t *this, host_t *src,
@@ -1891,6 +1959,7 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
+ this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa;
this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t,protocol_id_t,u_int32_t,ipsec_mode_t,u_int16_t,u_int16_t,bool))add_policy;
this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
diff --git a/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index f4003e4b8..fb951ce94 100644
--- a/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -1489,6 +1489,16 @@ static status_t update_sa(private_kernel_pfkey_ipsec_t *this,
}
/**
+ * Implementation of kernel_interface_t.query_sa.
+ */
+static status_t query_sa(private_kernel_pfkey_ipsec_t *this, host_t *src,
+ host_t *dst, u_int32_t spi, protocol_id_t protocol,
+ u_int64_t *bytes)
+{
+ return NOT_SUPPORTED; /* TODO */
+}
+
+/**
* Implementation of kernel_interface_t.del_sa.
*/
static status_t del_sa(private_kernel_pfkey_ipsec_t *this, host_t *src,
@@ -2053,6 +2063,7 @@ kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
+ this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa;
this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t,protocol_id_t,u_int32_t,ipsec_mode_t,u_int16_t,u_int16_t,bool))add_policy;
this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
diff --git a/src/charon/plugins/load_tester/load_tester_ipsec.c b/src/charon/plugins/load_tester/load_tester_ipsec.c
index d37f7a7bd..e463d2adc 100644
--- a/src/charon/plugins/load_tester/load_tester_ipsec.c
+++ b/src/charon/plugins/load_tester/load_tester_ipsec.c
@@ -84,6 +84,16 @@ static status_t update_sa(private_load_tester_ipsec_t *this,
}
/**
+ * Implementation of kernel_interface_t.query_sa.
+ */
+static status_t query_sa(private_load_tester_ipsec_t *this, host_t *src,
+ host_t *dst, u_int32_t spi, protocol_id_t protocol,
+ u_int64_t *bytes)
+{
+ return NOT_SUPPORTED;
+}
+
+/**
* Implementation of kernel_interface_t.del_sa.
*/
static status_t del_sa(private_load_tester_ipsec_t *this, host_t *src,
@@ -151,6 +161,7 @@ load_tester_ipsec_t *load_tester_ipsec_create()
this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
+ this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa;
this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t *this,host_t *, host_t *,traffic_selector_t *,traffic_selector_t *,policy_dir_t, u_int32_t,protocol_id_t, u_int32_t,ipsec_mode_t, u_int16_t, u_int16_t,bool))add_policy;
this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
diff --git a/src/charon/plugins/stroke/stroke_list.c b/src/charon/plugins/stroke/stroke_list.c
index 564a511a1..591fd3cae 100644
--- a/src/charon/plugins/stroke/stroke_list.c
+++ b/src/charon/plugins/stroke/stroke_list.c
@@ -148,6 +148,7 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
{
u_int32_t rekey, now = time(NULL);
u_int32_t use_in, use_out;
+ u_int64_t bytes_in, bytes_out;
proposal_t *proposal;
child_cfg_t *config = child_sa->get_config(child_sa);
@@ -205,6 +206,28 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
}
}
}
+
+ bytes_in = child_sa->get_usebytes(child_sa, TRUE);
+ fprintf(out, ", %lu bytes_i", bytes_in);
+ if (bytes_in)
+ {
+ use_in = child_sa->get_usetime(child_sa, TRUE);
+ if (use_in)
+ {
+ fprintf(out, " (%ds ago)", now - use_in);
+ }
+ }
+
+ bytes_out = child_sa->get_usebytes(child_sa, FALSE);
+ fprintf(out, ", %lu bytes_o", bytes_out);
+ if (bytes_out)
+ {
+ use_out = child_sa->get_usetime(child_sa, FALSE);
+ if (use_out)
+ {
+ fprintf(out, " (%ds ago)", now - use_out);
+ }
+ }
fprintf(out, ", rekeying ");
rekey = child_sa->get_lifetime(child_sa, FALSE);
@@ -224,25 +247,6 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
fprintf(out, "disabled");
}
- fprintf(out, ", last use: ");
- use_in = child_sa->get_usetime(child_sa, TRUE);
- if (use_in)
- {
- fprintf(out, "%ds_i ", now - use_in);
- }
- else
- {
- fprintf(out, "no_i ");
- }
- use_out = child_sa->get_usetime(child_sa, FALSE);
- if (use_out)
- {
- fprintf(out, "%ds_o ", now - use_out);
- }
- else
- {
- fprintf(out, "no_o ");
- }
}
}
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
index 9202e972e..3f8662318 100644
--- a/src/charon/sa/child_sa.c
+++ b/src/charon/sa/child_sa.c
@@ -398,6 +398,35 @@ static u_int32_t get_usetime(private_child_sa_t *this, bool inbound)
}
/**
+ * Implementation of child_sa_t.get_usebytes
+ */
+static u_int64_t get_usebytes(private_child_sa_t *this, bool inbound)
+{
+ status_t status = NOT_SUPPORTED;
+ u_int64_t bytes;
+
+ if (inbound)
+ {
+ if (this->my_spi)
+ {
+ status = charon->kernel_interface->query_sa(charon->kernel_interface,
+ this->other_addr, this->my_addr,
+ this->my_spi, this->protocol, &bytes);
+ }
+ }
+ else
+ {
+ if (this->other_spi)
+ {
+ status = charon->kernel_interface->query_sa(charon->kernel_interface,
+ this->my_addr, this->other_addr,
+ this->other_spi, this->protocol, &bytes);
+ }
+ }
+ return (status == SUCCESS) ? bytes : 0;
+}
+
+/**
* Implementation of child_sa_t.get_lifetime
*/
static u_int32_t get_lifetime(private_child_sa_t *this, bool hard)
@@ -776,6 +805,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->public.set_proposal = (void(*)(child_sa_t*, proposal_t *proposal))set_proposal;
this->public.get_lifetime = (u_int32_t(*)(child_sa_t*, bool))get_lifetime;
this->public.get_usetime = (u_int32_t(*)(child_sa_t*, bool))get_usetime;
+ this->public.get_usebytes = (u_int64_t(*)(child_sa_t*, bool))get_usebytes;
this->public.has_encap = (bool(*)(child_sa_t*))has_encap;
this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp;
this->public.set_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t))set_ipcomp;
diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h
index ec9b36dab..3b4e0e306 100644
--- a/src/charon/sa/child_sa.h
+++ b/src/charon/sa/child_sa.h
@@ -245,6 +245,14 @@ struct child_sa_t {
u_int32_t (*get_usetime)(child_sa_t *this, bool inbound);
/**
+ * Get number of bytes processed by CHILD_SA.
+ *
+ * @param inbound TRUE for inbound traffic, FALSE for outbound
+ * @return number of processed bytes
+ */
+ u_int64_t (*get_usebytes)(child_sa_t *this, bool inbound);
+
+ /**
* Get the traffic selectors list added for one side.
*
* @param local TRUE for own traffic selectors, FALSE for remote