display transmitted bytes per SA
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 30 Jul 2009 19:33:19 +0000 (21:33 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 30 Jul 2009 19:33:19 +0000 (21:33 +0200)
src/charon/kernel/kernel_interface.c
src/charon/kernel/kernel_interface.h
src/charon/kernel/kernel_ipsec.h
src/charon/plugins/kernel_klips/kernel_klips_ipsec.c
src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
src/charon/plugins/load_tester/load_tester_ipsec.c
src/charon/plugins/stroke/stroke_list.c
src/charon/sa/child_sa.c
src/charon/sa/child_sa.h

index 5188b79..53ae1d2 100644 (file)
@@ -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;
index 8c58c95..c4a273a 100644 (file)
@@ -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
index 6e8c5bc..d6438c1 100644 (file)
@@ -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
index c69ce4c..9a31c01 100644 (file)
@@ -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;
index f5a8457..078ae34 100644 (file)
@@ -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;
index f4003e4..fb951ce 100644 (file)
@@ -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;
index d37f7a7..e463d2a 100644 (file)
@@ -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;
index 564a511..591fd3c 100644 (file)
@@ -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 ");
-                       }
                }
        }
        
index 9202e97..3f86623 100644 (file)
@@ -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;
index ec9b36d..3b4e0e3 100644 (file)
@@ -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