int _cdecl main(int argc, char *argv[]) { int c; int not_inetd = 0; #ifdef WIN32 BOOL child = FALSE; #endif char arg1[BUFSIZ], arg2[BUFSIZ]; #ifndef PATH_MAX #define PATH_MAX MAX_PATH #endif char FileName[PATH_MAX]; /* for opening the debug log file */ struct sockaddr name; netperf_socklen_t namelen = sizeof(name); #ifdef WIN32 WSADATA wsa_data ; /* Initialize the winsock lib ( version 2.2 ) */ if ( WSAStartup(MAKEWORD(2,2), &wsa_data) == SOCKET_ERROR ){ printf("WSAStartup() failed : %d\n", GetLastError()) ; return 1 ; } #endif /* WIN32 */ /* Save away the program name */ program = (char *)malloc(strlen(argv[0]) + 1); if (program == NULL) { printf("malloc(%d) failed!\n", strlen(argv[0]) + 1); return 1 ; } strcpy(program, argv[0]); netlib_init(); /* Scan the command line to see if we are supposed to set-up our own */ /* listen socket instead of relying on inetd. */ /* first set a copy of initial values */ strncpy(local_host_name,"0.0.0.0",sizeof(local_host_name)); local_address_family = AF_UNSPEC; strncpy(listen_port,TEST_PORT,sizeof(listen_port)); while ((c = getopt(argc, argv, SERVER_ARGS)) != EOF) { switch (c) { case '?': case 'h': print_netserver_usage(); exit(1); case 'd': /* we want to set the debug file name sometime */ debug++; break; case 'L': not_inetd = 1; break_args_explicit(optarg,arg1,arg2); if (arg1[0]) { strncpy(local_host_name,arg1,sizeof(local_host_name)); } if (arg2[0]) { local_address_family = parse_address_family(arg2); /* if only the address family was set, we may need to set the local_host_name accordingly. since our defaults are IPv4 this should only be necessary if we have IPv6 support raj 2005-02-07 */ #if defined (AF_INET6) if (!arg1[0]) { strncpy(local_host_name,"::0",sizeof(local_host_name)); } #endif } break; case 'n': shell_num_cpus = atoi(optarg); if (shell_num_cpus > MAXCPUS) { fprintf(stderr, "netserver: This version can only support %d CPUs. Please", MAXCPUS); fprintf(stderr, " increase MAXCPUS in netlib.h and recompile.\n"); fflush(stderr); exit(1); } break; case 'p': /* we want to open a listen socket at a */ /* specified port number */ strncpy(listen_port,optarg,sizeof(listen_port)); not_inetd = 1; break; case '4': local_address_family = AF_INET; break; case '6': #if defined(AF_INET6) local_address_family = AF_INET6; strncpy(local_host_name,"::0",sizeof(local_host_name)); #else local_address_family = AF_UNSPEC; #endif break; case 'v': /* say how much to say */ verbosity = atoi(optarg); break; case 'V': printf("Netperf version %s\n",NETPERF_VERSION); exit(0); break; #ifdef WIN32 /*+*+SAF */ case 'I': child = TRUE; /* This is the handle we expect to inherit. */ /*+*+SAF server_sock = (HANDLE)atoi(optarg); */ break; case 'i': /* This is a handle we should NOT inherit. */ /*+*+SAF CloseHandle((HANDLE)atoi(optarg)); */ break; #endif } } /* +*+SAF I need a better way to find inherited handles I should close! */ /* +*+SAF Use DuplicateHandle to force inheritable attribute (or reset it)? */ /* unlink(DEBUG_LOG_FILE); */ strcpy(FileName, DEBUG_LOG_FILE); #ifndef WIN32 snprintf(&FileName[strlen(FileName)], sizeof(FileName) - strlen(FileName), "_%d", getpid()); if ((where = fopen(FileName, "w")) == NULL) { perror("netserver: debug file"); exit(1); } #else { if (child) { snprintf(&FileName[strlen(FileName)], sizeof(FileName) - strlen(FileName), "_%x", getpid()); } /* Hopefully, by closing stdout & stderr, the subsequent fopen calls will get mapped to the correct std handles. */ fclose(stdout); if ((where = fopen(FileName, "w")) == NULL) { perror("netserver: fopen of debug file as new stdout failed!"); exit(1); } fclose(stderr); if ((where = fopen(FileName, "w")) == NULL) { fprintf(stdout, "fopen of debug file as new stderr failed!\n"); exit(1); } } #endif #ifndef WIN32 chmod(DEBUG_LOG_FILE,0644); #endif #if WIN32 if (child) { server_sock = (SOCKET)GetStdHandle(STD_INPUT_HANDLE); } #endif /* if we are not a child of an inetd or the like, then we should open a socket and hang listens off of it. otherwise, we should go straight into processing requests. the do_listen() routine will sit in an infinite loop accepting connections and forking child processes. the child processes will call process_requests */ /* If fd 0 is not a socket then assume we're not being called */ /* from inetd and start server socket on the default port. */ /* this enhancement comes from [email protected] (Von Welch) */ if (not_inetd) { /* the user specified a port number on the command line */ set_up_server(local_host_name,listen_port,local_address_family); } #ifdef WIN32 /* OK, with Win2003 WinNT's POSIX subsystem is gone, and hence so is */ /* fork. But hopefully the kernel support will continue to exist */ /* for some time. We are not counting on the address space */ /* copy_on_write support, since it isn't exposed except through the */ /* NT native APIs (which are not public). We will try to use the */ /* InheritHandles flag in CreateProcess though since this is public */ /* and is used for more than just POSIX so hopefully it won't go */ /* away. */ else if (TRUE) { if (child) { process_requests(); } else { strncpy(listen_port,TEST_PORT,sizeof(listen_port)); set_up_server(local_host_name,listen_port,local_address_family); } } #endif #if !defined(__VMS) else if (getsockname(0, &name, &namelen) == SOCKET_ERROR) { /* we may not be a child of inetd */ if (errno == ENOTSOCK) { strncpy(listen_port,TEST_PORT,sizeof(listen_port)); set_up_server(local_host_name,listen_port,local_address_family); } } #endif /* !defined(__VMS) */ else { /* we are probably a child of inetd, or are being invoked via the VMS auxilliarly server mechanism */ #if !defined(__VMS) server_sock = 0; #else if ( (server_sock = socket(TCPIP$C_AUXS, SOCK_STREAM, 0)) == INVALID_SOCKET ) { perror("Failed to grab aux server socket" ); exit(1); } #endif /* !defined(__VMS) */ process_requests(); } #ifdef WIN32 /* Cleanup the winsock lib */ WSACleanup(); #endif return(0); }
void scan_cmd_line(int argc, char *argv[]) { extern int optind; /* index of first unused arg */ extern char *optarg; /* pointer to option string */ int c; char arg1[BUFSIZ], /* argument holders */ arg2[BUFSIZ]; program = (char *)malloc(strlen(argv[0]) + 1); if (program == NULL) { printf("malloc(%d) failed!\n", strlen(argv[0]) + 1); exit(1); } strcpy(program, argv[0]); /* Go through all the command line arguments and break them */ /* out. For those options that take two parms, specifying only */ /* the first will set both to that value. Specifying only the */ /* second will leave the first untouched. To change only the */ /* first, use the form first, (see the routine break_args.. */ while ((c= getopt(argc, argv, GLOBAL_CMD_LINE_ARGS)) != EOF) { switch (c) { case '?': case 'h': print_netperf_usage(); exit(1); case 'a': /* set local alignments */ break_args(optarg,arg1,arg2); if (arg1[0]) { local_send_align = convert(arg1); } if (arg2[0]) local_recv_align = convert(arg2); break; case 'A': /* set remote alignments */ break_args(optarg,arg1,arg2); if (arg1[0]) { remote_send_align = convert(arg1); } if (arg2[0]) remote_recv_align = convert(arg2); break; case 'c': /* measure local cpu usage please. the user */ /* may have specified the cpu rate as an */ /* optional parm */ if (argv[optind] && isdigit((unsigned char)argv[optind][0])){ /* there was an optional parm */ local_cpu_rate = (float)atof(argv[optind]); optind++; } local_cpu_usage++; break; case 'C': /* measure remote cpu usage please */ if (argv[optind] && isdigit((unsigned char)argv[optind][0])){ /* there was an optional parm */ remote_cpu_rate = (float)atof(argv[optind]); optind++; } remote_cpu_usage++; break; case 'd': debug++; break; case 'D': #if (defined WANT_DEMO) demo_mode++; if (argv[optind] && isdigit((unsigned char)argv[optind][0])){ /* there was an optional parm */ break_args_explicit(argv[optind],arg1,arg2); optind++; if (arg1[0]) { demo_interval = atof(arg1) * 1000000.0; } if (arg2[0]) { demo_units = convert(arg2); } } #else printf("Sorry, Demo Mode not configured into this netperf.\n"); printf("please consider reconfiguring netperf with\n"); printf("--enable-demo=yes and recompiling\n"); #endif break; case 'f': /* set the thruput formatting */ libfmt = *optarg; break; case 'F': /* set the fill_file variable for pre-filling buffers */ strcpy(fill_file,optarg); break; case 'i': /* set the iterations min and max for confidence intervals */ break_args(optarg,arg1,arg2); if (arg1[0]) { iteration_max = convert(arg1); } if (arg2[0] ) { iteration_min = convert(arg2); } /* limit maximum to 30 iterations */ if(iteration_max>30) iteration_max=30; if(iteration_min>30) iteration_min=30; break; case 'I': /* set the confidence level (95 or 99) and width */ break_args(optarg,arg1,arg2); if (arg1[0]) { confidence_level = convert(arg1); } if((confidence_level != 95) && (confidence_level != 99)){ printf("Only 95%% and 99%% confidence level is supported\n"); exit(1); } if (arg2[0] ) { interval = (double) convert(arg2)/100; } break; case 'k': /* local dirty and clean counts */ #ifdef DIRTY break_args(optarg,arg1,arg2); if (arg1[0]) { loc_dirty_count = convert(arg1); } if (arg2[0] ) { loc_clean_count = convert(arg2); } #else printf("I don't know how to get dirty.\n"); #endif /* DIRTY */ break; case 'K': /* remote dirty and clean counts */ #ifdef DIRTY break_args(optarg,arg1,arg2); if (arg1[0]) { rem_dirty_count = convert(arg1); } if (arg2[0] ) { rem_clean_count = convert(arg2); } #else printf("I don't know how to get dirty.\n"); #endif /* DIRTY */ break; case 'n': shell_num_cpus = atoi(optarg); break; case 'o': /* set the local offsets */ break_args(optarg,arg1,arg2); if (arg1[0]) local_send_offset = convert(arg1); if (arg2[0]) local_recv_offset = convert(arg2); break; case 'O': /* set the remote offsets */ break_args(optarg,arg1,arg2); if (arg1[0]) remote_send_offset = convert(arg1); if (arg2[0]) remote_recv_offset = convert(arg2); break; case 'P': /* to print or not to print, that is */ /* the header question */ print_headers = convert(optarg); break; case 't': /* set the test name */ strcpy(test_name,optarg); break; case 'T': /* We want to set the processor on which netserver or netperf */ /* will run */ break_args(optarg,arg1,arg2); if (arg1[0]) { local_proc_affinity = convert(arg1); bind_to_specific_processor(local_proc_affinity); } if (arg2[0]) remote_proc_affinity = convert(arg2); break; case 'W': /* set the "width" of the user space data buffer ring. This will */ /* be the number of send_size buffers malloc'd in the tests */ break_args(optarg,arg1,arg2); if (arg1[0]) send_width = convert(arg1); if (arg2[0]) recv_width = convert(arg2); break; case 'l': /* determine test end conditions */ /* assume a timed test */ test_time = convert(optarg); test_bytes = test_trans = 0; if (test_time < 0) { test_bytes = -1 * test_time; test_trans = test_bytes; test_time = 0; } break; case 'v': /* say how much to say */ verbosity = convert(optarg); break; case 'p': /* specify an alternate port number we use break_args_explicit here to maintain backwards compatibility with previous generations of netperf where having a single value did not set both remote _and_ local port number. raj 2005-02-04 */ break_args_explicit(optarg,arg1,arg2); if (arg1[0]) strncpy(test_port,arg1,PORTBUFSIZE); if (arg2[0]) strncpy(local_test_port,arg2,PORTBUFSIZE); break; case 'H': /* save-off the host identifying information, use break_args_explicit since passing just one value should not set both */ break_args_explicit(optarg,arg1,arg2); if (arg1[0]) strncpy(host_name,arg1,sizeof(host_name)); if (arg2[0]) address_family = parse_address_family(arg2); break; case 'L': /* save-off the local control socket addressing information. use break_args_explicit since passing just one value should not set both */ break_args_explicit(optarg,arg1,arg2); if (arg1[0]) strncpy(local_host_name,arg1,sizeof(local_host_name)); if (arg2[0]) local_address_family = parse_address_family(arg2); break; case 'w': /* We want to send requests at a certain wate. */ /* Remember that there are 1000000 usecs in a */ /* second, and that the packet rate is */ /* expressed in packets per millisecond. */ #ifdef WANT_INTERVALS interval_wate = convert(optarg); interval_usecs = interval_wate * 1000; #else fprintf(where, "Packet rate control is not compiled in.\n"); #endif break; case 'b': /* we want to have a burst so many packets per */ /* interval. */ #ifdef WANT_INTERVALS interval_burst = convert(optarg); #else fprintf(where, "Packet burst size is not compiled in. \n"); #endif /* WANT_INTERVALS */ break; case '4': address_family = AF_INET; local_address_family = AF_INET; break; case '6': #if defined(AF_INET6) address_family = AF_INET6; local_address_family = AF_INET6; #else printf("This netperf was not compiled on an IPv6 capable system!\n"); exit(-1); #endif break; }; } /* ok, what should our default hostname and local binding info be? */ if ('\0' == host_name[0]) { /* host_name was not set */ switch (address_family) { case AF_INET: strcpy(host_name,"localhost"); break; case AF_UNSPEC: /* what to do here? case it off the local_address_family I suppose */ switch (local_address_family) { case AF_INET: case AF_UNSPEC: strcpy(host_name,"localhost"); break; #if defined(AF_INET6) case AF_INET6: strcpy(host_name,"::1"); break; #endif default: printf("Netperf does not understand %d as an address family\n", address_family); exit(-1); } break; #if defined(AF_INET6) case AF_INET6: strcpy(host_name,"::1"); break; #endif default: printf("Netperf does not understand %d as an address family\n", address_family); exit(-1); } } /* now, having established the name to which the control will connect, from what should it come? */ if ('\0' == local_host_name[0]) { switch (local_address_family) { case AF_INET: strcpy(local_host_name,"0.0.0.0"); break; case AF_UNSPEC: switch (address_family) { case AF_INET: case AF_UNSPEC: strcpy(local_host_name,"0.0.0.0"); break; #if defined(AF_INET6) case AF_INET6: strcpy(local_host_name,"::0"); break; #endif default: printf("Netperf does not understand %d as an address family\n", address_family); exit(-1); } break; #if defined(AF_INET6) case AF_INET6: strcpy(local_host_name,"::0"); break; #endif default: printf("Netperf does not understand %d as an address family\n", address_family); exit(-1); } } /* parsing test-specific options used to be conditional on there being a "--" in the option stream. however, some of the tests have other initialization happening in their "scan" routines so we want to call them regardless. raj 2005-02-08 */ if ((strcasecmp(test_name,"TCP_STREAM") == 0) || #ifdef HAVE_ICSC_EXS (strcasecmp(test_name,"EXS_TCP_STREAM") == 0) || #endif /* HAVE_ICSC_EXS */ #ifdef HAVE_SENDFILE (strcasecmp(test_name,"TCP_SENDFILE") == 0) || #endif /* HAVE_SENDFILE */ (strcasecmp(test_name,"TCP_MAERTS") == 0) || (strcasecmp(test_name,"TCP_RR") == 0) || (strcasecmp(test_name,"TCP_CRR") == 0) || (strcasecmp(test_name,"TCP_CC") == 0) || #ifdef DO_1644 (strcasecmp(test_name,"TCP_TRR") == 0) || #endif /* DO_1644 */ #ifdef DO_NBRR (strcasecmp(test_name,"TCP_TRR") == 0) || #endif /* DO_NBRR */ (strcasecmp(test_name,"UDP_STREAM") == 0) || (strcasecmp(test_name,"UDP_RR") == 0)) { scan_sockets_args(argc, argv); } #ifdef WANT_DLPI else if ((strcasecmp(test_name,"DLCO_RR") == 0) || (strcasecmp(test_name,"DLCL_RR") == 0) || (strcasecmp(test_name,"DLCO_STREAM") == 0) || (strcasecmp(test_name,"DLCL_STREAM") == 0)) { scan_dlpi_args(argc, argv); } #endif /* WANT_DLPI */ #ifdef WANT_UNIX else if ((strcasecmp(test_name,"STREAM_RR") == 0) || (strcasecmp(test_name,"DG_RR") == 0) || (strcasecmp(test_name,"STREAM_STREAM") == 0) || (strcasecmp(test_name,"DG_STREAM") == 0)) { scan_unix_args(argc, argv); } #endif /* WANT_UNIX */ #ifdef WANT_XTI else if ((strcasecmp(test_name,"XTI_TCP_RR") == 0) || (strcasecmp(test_name,"XTI_TCP_STREAM") == 0) || (strcasecmp(test_name,"XTI_UDP_RR") == 0) || (strcasecmp(test_name,"XTI_UDP_STREAM") == 0)) { scan_xti_args(argc, argv); } #endif /* WANT_XTI */ #ifdef WANT_SCTP else if ((strcasecmp(test_name,"SCTP_STREAM") == 0) || (strcasecmp(test_name,"SCTP_RR") == 0) || (strcasecmp(test_name,"SCTP_STREAM_MANY") == 0) || (strcasecmp(test_name,"SCTP_RR_MANY") == 0)) { scan_sctp_args(argc, argv); } #endif #ifdef DO_DNS else if (strcasecmp(test_name,"DNS_RR") == 0) { scan_dns_args(argc, argv); } #endif /* DO_DNS */ }
void scan_netserver_args(int argc, char *argv[]) { int c; char arg1[BUFSIZ], arg2[BUFSIZ]; if (debug) { fprintf(where, "%s: enter\n", __FUNCTION__); fflush(where); } while ((c = getopt(argc, argv, SERVER_ARGS)) != EOF){ switch (c) { case '?': case 'h': print_netserver_usage(); exit(1); case 'd': debug++; suppress_debug = 0; break; case 'D': /* perhaps one of these days we'll take an argument */ want_daemonize = 0; not_inetd = 1; break; case 'f': spawn_on_accept = 0; not_inetd = 1; break; #ifdef WIN32 case 'I': child = TRUE; break; case 'i': break; #endif case 'L': not_inetd = 1; break_args_explicit(optarg,arg1,arg2); if (arg1[0]) { strncpy(local_host_name,arg1,sizeof(local_host_name)); } if (arg2[0]) { local_address_family = parse_address_family(arg2); } break; case 'n': shell_num_cpus = atoi(optarg); if (shell_num_cpus > MAXCPUS) { fprintf(stderr, "netserver: This version can only support %d CPUs. Please" "increase MAXCPUS in netlib.h and recompile.\n", MAXCPUS); fflush(stderr); exit(1); } break; case 'N': suppress_debug = 1; debug = 0; break; case 'p': /* we want to open a listen socket at a specified port number */ 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. Windows does not seem to have a strndup() so just malloc and strncpy it. we weren't checking the strndup() return so won't bother with checking malloc(). we will though make certain we only allocated it once in the event that someone puts -Z on the command line more than once */ if (passphrase == NULL) passphrase = malloc(sizeof(netperf_request.content.test_specific_data)); strncpy(passphrase, optarg, sizeof(netperf_request.content.test_specific_data)); passphrase[sizeof(netperf_request.content.test_specific_data) - 1] = '\0'; break; case '4': local_address_family = AF_INET; break; case '6': #if defined(AF_INET6) local_address_family = AF_INET6; #else local_address_family = AF_UNSPEC; #endif break; case 'v': /* say how much to say */ verbosity = atoi(optarg); break; case 'V': printf("Netperf version %s\n",NETPERF_VERSION); exit(0); break; } } }
void scan_netserver_args(int argc, char *argv[]) { int c; char arg1[BUFSIZ], arg2[BUFSIZ]; if (debug) { fprintf(where, "%s: enter\n", __FUNCTION__); fflush(where); } while ((c = getopt(argc, argv, SERVER_ARGS)) != EOF){ switch (c) { case '?': case 'h': print_netserver_usage(); exit(1); case 'd': debug++; suppress_debug = 0; break; case 'D': /* perhaps one of these days we'll take an argument */ want_daemonize = 0; not_inetd = 1; break; case 'f': spawn_on_accept = 0; not_inetd = 1; break; #ifdef WIN32 case 'I': child = TRUE; break; case 'i': break; #endif case 'L': not_inetd = 1; break_args_explicit(optarg,arg1,arg2); if (arg1[0]) { strncpy(local_host_name,arg1,sizeof(local_host_name)); } if (arg2[0]) { local_address_family = parse_address_family(arg2); } break; case 'n': shell_num_cpus = atoi(optarg); if (shell_num_cpus > MAXCPUS) { fprintf(stderr, "netserver: This version can only support %d CPUs. Please" "increase MAXCPUS in netlib.h and recompile.\n", MAXCPUS); fflush(stderr); exit(1); } break; case 'N': suppress_debug = 1; debug = 0; break; case 'p': /* we want to open a listen socket at a specified port number */ strncpy(listen_port,optarg,sizeof(listen_port)); not_inetd = 1; break; case '4': local_address_family = AF_INET; break; case '6': #if defined(AF_INET6) local_address_family = AF_INET6; #else local_address_family = AF_UNSPEC; #endif break; case 'v': /* say how much to say */ verbosity = atoi(optarg); break; case 'V': printf("Netperf version %s\n",NETPERF_VERSION); exit(0); break; } } }