Quick & dirty statistics patch

Michel Arboi <[email protected]> Wed, 27 Oct 2004 13:34:02 +0200
Newsgroups gmane.comp.security.nessus.devel
Message-ID <[email protected]>
I'm note sure that we want this before 2.2 is out so I post it here.
You have to define CNX_STATS or replace #ifdef CNX_STATS by #if 1

_______________________________________________
Nessus-devel mailing list
[email protected]
http://mail.nessus.org/mailman/listinfo/nessus-devel
patch (text/x-patch, 8.8 KB)
--- nessus-libraries/libnessus/network.c	7 Sep 2004 19:12:49 -0000	1.142
+++ nessus-libraries/libnessus/network.c	27 Oct 2004 11:29:41 -0000
@@ -44,6 +44,11 @@
 extern int plug_get_port_transport(struct arglist*, int);
 extern void plug_set_port_transport(struct arglist*, int, int);
 
+#ifdef CNX_STATS
+static double	cnx_times = 0.0, cnx_times_sq = 0.0;
+static double	cnx_max_time = 0.0, cnx_min_time = 1e20;
+static int	cnx_nb = 0;
+#endif
 
 /*----------------------------------------------------------------*
  * Low-level connection management                                *
@@ -1482,6 +1487,8 @@
   struct timeval	to;
   int			soc, x;
   int			opt, opt_sz;
+  struct timeval	t1, t2;
+  double		delta_t;
 
   __port_closed = 0;
 
@@ -1534,6 +1541,11 @@
     }
 #endif  
   
+#ifdef CNX_STATS
+  if (gettimeofday(&t1, NULL) < 0)
+    perror("gettimeofday");
+#endif
+
   if (connect(soc, (struct sockaddr*) paddr, sizeof(*paddr)) < 0)
     {
 #if debug_SSL > 2
@@ -1590,6 +1602,21 @@
 	  return  -1;
 	}
     }
+#ifdef CNX_STATS
+  if (gettimeofday(&t2, NULL) < 0)
+    perror("gettimeofday");
+  else
+    {
+      cnx_nb ++;
+      delta_t = (t2.tv_usec - t1.tv_usec) + 1000000.0 * (t2.tv_sec - t1.tv_sec);
+      cnx_times += delta_t;
+      cnx_times_sq += delta_t * delta_t;
+      if (delta_t > cnx_max_time)
+	cnx_max_time = delta_t;
+      if (delta_t < cnx_min_time)
+	cnx_min_time = delta_t;
+    }
+#endif
   block_socket(soc);
   return soc;
 }
@@ -2234,3 +2261,30 @@
  *data_sz = 0;
  return -1;
 }
+
+#ifdef CNX_STATS
+void
+cnx_reset_stats()
+{
+  cnx_times = 0.0; cnx_times_sq = 0.0; cnx_nb = 0;
+  cnx_min_time = 1e20; cnx_max_time = 0.0;
+}
+
+void
+cnx_write_stats(const char* name)
+{
+  FILE	*fp;
+  char	buf[64];
+
+  if ((fp = fopen(name, "a")) == NULL)
+    {
+      perror(name);
+      return;
+    }
+  if (fprintf(fp, "%d\t%.15g\t%.15g\t%.15g\t%.15g\n",
+	      cnx_nb, cnx_times, cnx_times_sq, cnx_min_time, cnx_max_time) < 5)
+    perror(name);
+  if (fclose(fp) < 0)
+    perror(name);
+}
+#endif
--- nessus-libraries/libnessus/network.h	7 Jun 2003 23:39:52 -0000	1.8
+++ nessus-libraries/libnessus/network.h	27 Oct 2004 11:29:41 -0000
@@ -41,6 +41,10 @@
 int set_socket_source_addr(int, int);
 void socket_source_init(struct in_addr *);
 
+#ifdef CNX_STATS
+void	cnx_reset_stats(void);
+void	cnx_write_stats(const char*);
+#endif
 
 #ifdef HAVE_SSL
        X509*   stream_get_server_certificate(int);
--- nessus-plugins/plugins/find_service/Makefile	5 Sep 1999 14:28:21 -0000	1.4
+++ nessus-plugins/plugins/find_service/Makefile	27 Oct 2004 11:29:44 -0000
@@ -5,7 +5,8 @@
 all : $(PLUGNAME).nes
 $(PLUGNAME).nes : $(PLUGNAME).c
 	$(LIBTOOL) $(CC) $(DEFS) $(include) -c  $(PLUGNAME).c
-	$(LIBTOOL) $(CC) $(DEFS) -o lib$(PLUGNAME).la $(PLUGNAME).lo $(LIBS) \
+	$(LIBTOOL) $(CC) $(DEFS) -o lib$(PLUGNAME).la $(PLUGNAME).lo \
+	$(LIBS) -lm \
 	-rpath $(rootdir)/bin/plugins
 	../install_plug $(PLUGNAME) $(rootdir)
 clean :
--- nessus-plugins/plugins/find_service/find_service.c	6 Oct 2004 11:39:58 -0000	1.217
+++ nessus-plugins/plugins/find_service/find_service.c	27 Oct 2004 11:29:44 -0000
@@ -1799,6 +1799,14 @@
 }     
 #endif
 
+#ifdef CNX_STATS
+#ifndef L_tmpnam
+#define L_tmpnam	1024	/* ? */
+#endif
+char	stat_fname[L_tmpnam];
+#endif
+
+int	rw_timeout = 5, cnx_timeout = 5, wrap_timeout = 3;
 
 static int plugin_do_run(desc, h, test_ssl)
  struct arglist * desc;
@@ -1810,37 +1818,15 @@
  int num_unknown = 0;
  int len_head = strlen(head);
  int	might_be_socks = 0;
- 
- int	rw_timeout = 5, cnx_timeout = 5, wrap_timeout = 3;
  int	x, timeout;
- char	*rw_timeout_s = get_plugin_preference(desc, RW_TIMEOUT_PREF);
- char	*cnx_timeout_s = get_plugin_preference(desc, CNX_TIMEOUT_PREF);
-#ifdef DETECT_WRAPPED_SVC
- char	*wrap_timeout_s = get_plugin_preference(desc, WRAP_TIMEOUT_PREF);
-#endif
   unsigned char	*p;
-#ifdef NEW_KB_MGMT
-  char	*experimental = plug_get_key(desc, "global_settings/experimental_scripts", NULL);
-#else
-  char	*experimental = plug_get_key(desc, "global_settings/experimental_scripts");
-#endif
-  
   time_t	t1, t2;
   int		delta_t;
   fd_set	rfds, wfds, xfds;
   struct timeval tv;
 
-  if (rw_timeout_s != NULL && (x = atoi(rw_timeout_s)) > 0)
-    rw_timeout = x;
-  if (cnx_timeout_s != NULL && (x = atoi(cnx_timeout_s)) > 0)
-    cnx_timeout = x;
-#ifdef DETECT_WRAPPED_SVC
-  if (wrap_timeout_s != NULL && (x = atoi(wrap_timeout_s)) >= 0)
-    wrap_timeout = x;
-#endif
- 
  bzero(unknown, sizeof(unknown));
-
+ cnx_reset_stats();
 
 
  while(h && h->next)
@@ -2395,8 +2381,8 @@
     {
       char	ban[256];
       unknown[num_unknown++] = port;
-      /* If experimental_scripts is on, find_service_3digits will run after us */
-      if (! three_digits || experimental == NULL || strstr(experimental, "no") != NULL)
+      /* find_service_3digits will run after us */
+      if (! three_digits)
 	mark_unknown_svc(desc, port, banner, trp);
     }
    efree(&banner); 
@@ -2409,7 +2395,9 @@
   }
   if(h)h = h->next;
   }
-    
+#ifdef CNX_STATS
+ cnx_write_stats(stat_fname);
+#endif
  return(0);
 }
 
@@ -2505,9 +2493,11 @@
 }
 #endif
 
+
 int plugin_run(desc)
  struct arglist * desc;
 {
+   FILE	*fp;
 #ifdef NEW_KB_MGMT
  struct arglist * h = plug_get_oldstyle_kb(desc);
 #else
@@ -2521,7 +2511,7 @@
  char * num_sons_s = get_plugin_preference(desc, NUM_CHILDREN);
  int num_sons = 10;
  int port_per_son;
- int i;
+ int i, x;
  char * head = "Ports/tcp/";
  struct arglist * globals = arg_get_value(desc, "globals");
 #ifdef NEW_KB_MGMT
@@ -2529,6 +2519,11 @@
 #else
  int one_true_pipe = (int)arg_get_value(desc, "pipe");
 #endif
+ char	*rw_timeout_s = get_plugin_preference(desc, RW_TIMEOUT_PREF);
+ char	*cnx_timeout_s = get_plugin_preference(desc, CNX_TIMEOUT_PREF);
+#ifdef DETECT_WRAPPED_SVC
+ char	*wrap_timeout_s = get_plugin_preference(desc, WRAP_TIMEOUT_PREF);
+#endif
  int	test_ssl = 0;
  #ifdef HAVE_SSL
   char * key   = get_plugin_preference(desc, KEY_FILE);
@@ -2569,7 +2564,14 @@
     plug_set_ssl_CA_file(desc, cafile);
 #endif /* HAVE_SSL */  
   
-  
+  if (rw_timeout_s != NULL && (x = atoi(rw_timeout_s)) > 0)
+    rw_timeout = x;
+  if (cnx_timeout_s != NULL && (x = atoi(cnx_timeout_s)) > 0)
+    cnx_timeout = x;
+#ifdef DETECT_WRAPPED_SVC
+  if (wrap_timeout_s != NULL && (x = atoi(wrap_timeout_s)) >= 0)
+    wrap_timeout = x;
+#endif  
  
   signal(SIGTERM, sigterm);
   signal(SIGCHLD, sigchld);
@@ -2649,8 +2651,9 @@
 	
 	
  num_sons = i;		
- 
-
+#ifdef CNX_STATS
+ tmpnam(stat_fname);
+#endif
  for (i = 0; i < num_sons; i ++)
  {
   usleep(5000);
@@ -2753,6 +2756,87 @@
   if(flag == 0)
   	break;
  }
+#ifdef CNX_STATS     
+ if ((fp = fopen(stat_fname, "r")) == NULL)
+   perror(stat_fname);
+ else
+   {
+     int	n, sn = 0;
+     double	x, x2, sx = 0.0, sx2 = 0.0, v, m, sd;
+     double	min1, smin = 1e20, max1, smax = 0.0;
  
+     while (fscanf(fp, "%d%lg%lg%lg%lg", &n, &x, &x2, &min1, &max1) >= 5)
+       {
+	 if (n > 0)
+	   {
+	     sn += n;
+	     sx += x;
+	     sx2 += x2;
+	     if (min1 < smin) smin = min1;
+	     if (max1 > smax) smax = max1;
+	   }
+       }
+     fclose(fp);
+     if (sn > 0)
+       {
+	 char	report[256], *p;
+	 m = sx / sn;
+#if 0
+	 v = sx2 / sn - m * m;
+#endif
+	 /* Use the unbiased estimate for variance: divide by N-1 instead of N */
+	 if (sn > 1)
+	   v = (sx2 - sn * m * m) / (sn - 1);
+	 else
+	   v = 0.0;
+	 sprintf(report, "The mean TCP connection time is %g ms, between %g ms and %g ms", m / 1e3, smin / 1e3, smax / 1e3);
+	 for (p = report; *p != '\0'; p ++) ;
+	 if (v > 0.0)		/* might be < 0 because of rounding errors */
+	   {
+	     sd = sqrt(v);
+	     sprintf(p, " - the estimated SD is ");
+	     while (*p != '\0') p ++;
+	     if (sd > 1000000)
+	       sprintf(p, "%g s", sd / 1e6);
+	     else
+	       sprintf(p, "%g ms", sd / 1e3);
+	   }
+#if 0
+	 post_note(desc, 0, report);	 
+#else
+	 fprintf(stderr, report);
+#endif
+	 snprintf(report, sizeof(report), "%.6f", m / 1e6);
+	 plug_set_key(desc, "CnxStats/mean", ARG_STRING, report);
+	 if (v > 0.0)
+	   {
+	     snprintf(report, sizeof(report), "%.6f", sd / 1e6);
+	     plug_set_key(desc, "CnxStats/sd", ARG_STRING, report);
+	     /* We do not want to do floating point computations in NASL! 
+	      * So we store those values into the KB */
+	     x = (m + 3.0 * sd) / 1e6;
+	     snprintf(report, sizeof(report), "%.6f", x);
+	     plug_set_key(desc, "CnxStats/max3sd", ARG_STRING, report);
+	     if (x < smax / 1e6) x = smax / 1e6;
+	     if (cnx_timeout < x)
+	       {
+		 sprintf(report, "The connection timeout is too short. You should increase it to %d s at least", round(x));
+		 post_note(desc, 0, report);
+	       }
+
+	     x = m - 3.0 * sd;
+	     if (x > 0.0)
+	       {
+		 snprintf(report, sizeof(report), "%.6f", x);
+		 plug_set_key(desc, "CnxStats/min3sd", ARG_STRING, report);
+	       }
+	     else
+	       plug_set_key(desc, "CnxStats/min3sd", ARG_STRING, "0.000000");
+	   }
+       }
+   }
+ if (unlink(stat_fname))
+   perror(stat_fname);
+#endif
  return 0;
 }