[netperf-dev] netperf2 commit notice r518 - in trunk: . src

raj at netperf.org raj at netperf.org
Mon Jan 23 16:09:38 PST 2012


Author: raj
Date: 2012-01-23 16:09:38 -0800 (Mon, 23 Jan 2012)
New Revision: 518

Modified:
   trunk/Release_Notes
   trunk/src/netlib.c
   trunk/src/netlib.h
   trunk/src/netperf.c
   trunk/src/netserver.c
   trunk/src/netsh.c
   trunk/src/netsh.h
Log:
Add the ability to control access to netserver via a passphrase.  While it is simplistic and it does not remove the need for other forms of access control it should help make it a little bit more difficult for someone with nefarious intent to dial up a netserver and make it do unpleasant things.

Modified: trunk/Release_Notes
===================================================================
--- trunk/Release_Notes	2012-01-23 19:11:54 UTC (rev 517)
+++ trunk/Release_Notes	2012-01-24 00:09:38 UTC (rev 518)
@@ -1,5 +1,17 @@
 These are the Release Notes for post Revision 2.5.0 top-of-trunk netperf:
 
+*) A new global -Z option has been added to netperf and netserver.
+   This takes as an argument a passphrase.  In the case of netserver
+   it will expect a control message with the passphrase as the first
+   thing it receives on the control connection.  If netserver does not
+   receive a control message with the passphrase it will close the
+   control connection and move-on.  If the netserver receives a
+   control message with a passprhase when it is not lookign for one,
+   it will be ignored. There is at present a 20 second timeout on the
+   attempted receipt of the request message. In the case of netperf,
+   the passphrase will be the first thing sent on the control
+   connection.  There is no response to a passphrase control message.
+
 *) Demo mode output format will now track the omni output format. So,
    if the omni ouput format is CSV then the interim results will be
    emitted in csv. Likewise for keyval.  If the mode is human (default

Modified: trunk/src/netlib.c
===================================================================
--- trunk/src/netlib.c	2012-01-23 19:11:54 UTC (rev 517)
+++ trunk/src/netlib.c	2012-01-24 00:09:38 UTC (rev 518)
@@ -2535,15 +2535,18 @@
    portion are always converted. raj 2008-02-05 */
 
 int
-recv_request_n(int n)
+recv_request_timed_n(int n, int seconds)
 {
-int     tot_bytes_recvd,
-        bytes_recvd, 
-        bytes_left;
-char    *buf = (char *)&netperf_request;
-int     buflen = sizeof(netperf_request);
-int     counter,count;
+  int     tot_bytes_recvd,
+    bytes_recvd, 
+    bytes_left;
+  char    *buf = (char *)&netperf_request;
+  int     buflen = sizeof(netperf_request);
+  int     counter,count;
 
+  fd_set  readfds;
+  struct timeval timeout;
+
   if (n < 0) count = sizeof(netperf_request)/4;
   else count = 2 + n;
 
@@ -2558,15 +2561,39 @@
     count = sizeof(netperf_request)/4;
   }
 
+  /* for the time being, we rather rely on select decrementing timeout
+     each time to preclude someone with nefarious intent from just
+     dribbling data to us piecemeal.  of course, who knows what
+     someone with nefarious intent might come-up with. raj 2012-01-23 */
   tot_bytes_recvd = 0;    
   bytes_recvd = 0;     /* nt_lint; bytes_recvd uninitialized if buflen == 0 */
   bytes_left      = buflen;
-  while ((tot_bytes_recvd != buflen) &&
-	 ((bytes_recvd = recv(server_sock, buf, bytes_left,0)) > 0 )) {
-    tot_bytes_recvd += bytes_recvd;
-    buf             += bytes_recvd;
-    bytes_left      -= bytes_recvd;
-  }
+  timeout.tv_sec = seconds;
+  timeout.tv_usec = 0;
+  do {
+    FD_ZERO(&readfds);
+    FD_SET(server_sock,&readfds);
+    if (select(FD_SETSIZE,
+	       &readfds,
+	       0,
+	       0,
+	       (seconds > 0) ? &timeout : NULL) != 1) {
+      fprintf(where,
+	      "Issue receiving request on control connection. Errno %d (%s)\n",
+	      errno,
+	      strerror(errno));
+      fflush(where);
+      close(server_sock);
+      return -1;
+    }
+
+    if ((bytes_recvd = recv(server_sock, buf, bytes_left, 0)) > 0) {
+      tot_bytes_recvd += bytes_recvd;
+      buf             += bytes_recvd;
+      bytes_left      -= bytes_recvd;
+    }
+  }  while ((tot_bytes_recvd != buflen) &&
+	    (bytes_recvd > 0 ));
   
   /* put the request into host order */
   
@@ -2585,7 +2612,8 @@
     Print_errno(where,
 		"recv_request: error on recv");
     fflush(where);
-    exit(1);
+    close(server_sock);
+    return -1;
   }
   
   if (bytes_recvd == 0) {
@@ -2609,7 +2637,8 @@
 	    "recv_request: partial request received of %d bytes\n",
 	    tot_bytes_recvd);
     fflush(where);
-    exit(1);
+    close(server_sock);
+    return -1;
   }
 
   if (debug > 1) {
@@ -2628,6 +2657,19 @@
   return buflen;
 }
 
+/* receive a request, only converting the first n ints-worth of the
+   test-specific data via htonl() before sending on the
+   connection. the first two ints, which are before the test-specific
+   portion are always converted. raj 2008-02-05 */
+
+int
+recv_request_n(int n)
+{
+
+  return recv_request_timed_n(n,0);
+
+}
+
  /***********************************************************************/
  /*                                                                     */
  /*     recv_request()                                                  */

Modified: trunk/src/netlib.h
===================================================================
--- trunk/src/netlib.h	2012-01-23 19:11:54 UTC (rev 517)
+++ trunk/src/netlib.h	2012-01-24 00:09:38 UTC (rev 518)
@@ -33,6 +33,7 @@
 #define         DEBUG_OK                3
 #define         NODE_IDENTIFY           4
 #define         CPU_CALIBRATE           5
+#define         PASSPHRASE              6
 
 #define         DO_TCP_STREAM           10
 #define         TCP_STREAM_RESPONSE     11

Modified: trunk/src/netperf.c
===================================================================
--- trunk/src/netperf.c	2012-01-23 19:11:54 UTC (rev 517)
+++ trunk/src/netperf.c	2012-01-24 00:09:38 UTC (rev 518)
@@ -50,6 +50,12 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
 #endif
@@ -133,6 +139,14 @@
   if (!no_control) {
     establish_control(host_name,test_port,address_family,
 		      local_host_name,local_test_port,local_address_family);
+
+    if (passphrase != NULL) {
+      netperf_request.content.request_type = PASSPHRASE;
+      strncpy((char *)netperf_request.content.test_specific_data,
+	      passphrase,
+	      sizeof(netperf_request.content.test_specific_data));
+      send_request_n(0);
+    }
   }
   
   if (strcasecmp(test_name,"TCP_STREAM") == 0) {

Modified: trunk/src/netserver.c
===================================================================
--- trunk/src/netserver.c	2012-01-23 19:11:54 UTC (rev 517)
+++ trunk/src/netserver.c	2012-01-24 00:09:38 UTC (rev 518)
@@ -178,8 +178,6 @@
 #endif
 char     FileName[PATH_MAX];
 
-
-
 char     listen_port[10];
 
 struct listen_elt {
@@ -203,6 +201,8 @@
 extern	char	*optarg;
 extern	int	optind, opterr;
 
+/* char  *passphrase = NULL; */
+
 static void
 init_netserver_globals() {
 
@@ -691,6 +691,34 @@
   }
 }
 
+static int
+recv_passphrase() {
+
+  /* may need to revisit the timeout. we only respond if there is an
+     error with receiving the passphrase */
+  if ((recv_request_timed_n(0,20) > 0) &&
+      (netperf_request.content.request_type == PASSPHRASE) &&
+      (!strcmp(passphrase,
+	       (char *)netperf_request.content.test_specific_data))) {
+    /* it was okey dokey */
+    return 0;
+  }
+#if defined(SEND_PASSPHRASE_RESPONSE)
+  netperf_response.content.response_type = PASSPHRASE;
+  netperf_response.content.serv_errno = 403;
+    snprintf((char *)netperf_response.content.test_specific_data,
+	     sizeof(netperf_response.content.test_specific_data),
+	     "Sorry, unable to match with required passphrase\n");
+  send_response_n(0);
+#endif
+  fprintf(where,
+	  "Unable to match required passphrase.  Closing control connection\n");
+  fflush(where);
+  
+  close(server_sock);
+  return -1;
+}
+
 /* This routine implements the "main event loop" of the netperf server
    code. Code above it will have set-up the control connection so it
    can just merrily go about its business, which is to "schedule"
@@ -709,10 +737,20 @@
     fflush(where);
   }
 
+  /* if the netserver was started with a passphrase, look for it in
+     the first request to arrive.  if there is no passphrase in the
+     first request we will end-up dumping the control connection. raj
+     2012-01-23 */
+
+  if ((passphrase != NULL)  && (recv_passphrase()))
+      return;
+
   while (1) {
 
-    if (recv_request() == 0) 
+    if (recv_request() <= 0) {
+      close(server_sock);
       return;
+    }
 
     switch (netperf_request.content.request_type) {
       
@@ -958,6 +996,13 @@
       break;
 #endif
 
+    case PASSPHRASE:
+      if (debug) {
+	fprintf(where,"Ignoring an unexpected passphrase control message\n");
+	fflush(where);
+      }
+      break;
+
     default:
       fprintf(where,"unknown test number %d\n",
 	      netperf_request.content.request_type);
@@ -1247,9 +1292,9 @@
 }
 
 #ifndef WIN32
-#define SERVER_ARGS "DdfhL:n:Np:v:V46"
+#define SERVER_ARGS "DdfhL:n:Np:v:VZ:46"
 #else
-#define SERVER_ARGS "DdfhL:n:Np:v:V46I:i:"
+#define SERVER_ARGS "DdfhL:n:Np:v:VZ:46I:i:"
 #endif
 void
 scan_netserver_args(int argc, char *argv[]) {
@@ -1320,6 +1365,12 @@
       strncpy(listen_port,optarg,sizeof(listen_port));
       not_inetd = 1;
       break;
+    case 'Z':
+      /* only copy as much of the passphrase as could fit in the
+	 test-specific portion of a control message. */
+      passphrase = strndup(optarg,
+			   sizeof(netperf_request.content.test_specific_data));
+      break;
     case '4':
       local_address_family = AF_INET;
       break;

Modified: trunk/src/netsh.c
===================================================================
--- trunk/src/netsh.c	2012-01-23 19:11:54 UTC (rev 517)
+++ trunk/src/netsh.c	2012-01-24 00:09:38 UTC (rev 518)
@@ -87,7 +87,7 @@
    getopt to parse the command line, we will tell getopt that they do
    not take parms, and then look for them ourselves */
 
-#define GLOBAL_CMD_LINE_ARGS "A:a:b:B:CcdDf:F:H:hi:I:jk:K:l:L:n:NO:o:P:p:rSs:t:T:v:VW:w:y:Y:46"
+#define GLOBAL_CMD_LINE_ARGS "A:a:b:B:CcdDf:F:H:hi:I:jk:K:l:L:n:NO:o:P:p:rSs:t:T:v:VW:w:y:Y:Z:46"
 
 /************************************************************************/
 /*									*/
@@ -233,6 +233,9 @@
 /* are we not establishing a control connection? */
 int no_control = 0;
 
+/* what is the passphrase? */
+char *passphrase = NULL;
+
 char netserver_usage[] = "\n\
 Usage: netserver [options] \n\
 \n\
@@ -248,6 +251,7 @@
     -6                Do IPv6\n\
     -v verbosity      Specify the verbosity level\n\
     -V                Display version information and exit\n\
+    -Z passphrase     Expect passphrase as the first thing received\n\
 \n";
 
 /* netperf_usage done as two concatenated strings to make the MS
@@ -292,7 +296,8 @@
     -v level          Set the verbosity level (default 1, min 0)\n\
     -V                Display the netperf version and exit\n\
     -y local,remote   Set the socket priority\n\
-    -Y local,remote   Set the IP_TOS. Use hexadecimal.\n";
+    -Y local,remote   Set the IP_TOS. Use hexadecimal.\n\
+    -Z passphrase     Set and pass to netserver a passphrase\n";
 
 char netperf_usage2[] = "\n\
 For those options taking two parms, at least one must be specified;\n\
@@ -891,6 +896,12 @@
       if (arg2[0])
 	remote_socket_tos = strtol(arg2,NULL,0);
       break;
+    case 'Z':
+      /* only copy as much of the passphrase as could fit in the
+	 test-specific portion of a control message. */
+      passphrase = strndup(optarg,
+			   sizeof(netperf_request.content.test_specific_data));
+      break;
     case 'l':
       /* determine test end conditions */
       /* assume a timed test */

Modified: trunk/src/netsh.h
===================================================================
--- trunk/src/netsh.h	2012-01-23 19:11:54 UTC (rev 517)
+++ trunk/src/netsh.h	2012-01-24 00:09:38 UTC (rev 518)
@@ -77,6 +77,8 @@
 extern char		*program; /* program invocation name		*/
 extern char             *command_line;  /* how we were invoked          */
 
+extern char  *passphrase;
+
 /* stuff to say where this test is going                                */
 extern char	host_name[HOSTNAMESIZE];/* remote host name or ip addr  */
 extern char     local_host_name[HOSTNAMESIZE];



More information about the netperf-dev mailing list