diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/charon/kernel/kernel_interface.c | 14 | ||||
-rw-r--r-- | src/charon/kernel/kernel_interface.h | 13 | ||||
-rw-r--r-- | src/charon/kernel/kernel_ipsec.h | 13 | ||||
-rw-r--r-- | src/charon/plugins/kernel_klips/kernel_klips_ipsec.c | 11 | ||||
-rw-r--r-- | src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c | 69 | ||||
-rw-r--r-- | src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 11 | ||||
-rw-r--r-- | src/charon/plugins/load_tester/load_tester_ipsec.c | 11 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_list.c | 42 | ||||
-rw-r--r-- | src/charon/sa/child_sa.c | 30 | ||||
-rw-r--r-- | src/charon/sa/child_sa.h | 8 |
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 |