auto import from //depot/cupcake/@135843
diff --git a/netserver.c b/netserver.c
new file mode 100644
index 0000000..02be3ce
--- /dev/null
+++ b/netserver.c
@@ -0,0 +1,1022 @@
+/*
+
+ Copyright (C) 1993-2007 Hewlett-Packard Company
+ ALL RIGHTS RESERVED.
+
+ The enclosed software and documentation includes copyrighted works
+ of Hewlett-Packard Co. For as long as you comply with the following
+ limitations, you are hereby authorized to (i) use, reproduce, and
+ modify the software and documentation, and to (ii) distribute the
+ software and documentation, including modifications, for
+ non-commercial purposes only.
+
+ 1. The enclosed software and documentation is made available at no
+ charge in order to advance the general development of
+ high-performance networking products.
+
+ 2. You may not delete any copyright notices contained in the
+ software or documentation. All hard copies, and copies in
+ source code or object code form, of the software or
+ documentation (including modifications) must contain at least
+ one of the copyright notices.
+
+ 3. The enclosed software and documentation has not been subjected
+ to testing and quality control and is not a Hewlett-Packard Co.
+ product. At a future time, Hewlett-Packard Co. may or may not
+ offer a version of the software and documentation as a product.
+
+ 4. THE SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS".
+ HEWLETT-PACKARD COMPANY DOES NOT WARRANT THAT THE USE,
+ REPRODUCTION, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR
+ DOCUMENTATION WILL NOT INFRINGE A THIRD PARTY'S INTELLECTUAL
+ PROPERTY RIGHTS. HP DOES NOT WARRANT THAT THE SOFTWARE OR
+ DOCUMENTATION IS ERROR FREE. HP DISCLAIMS ALL WARRANTIES,
+ EXPRESS AND IMPLIED, WITH REGARD TO THE SOFTWARE AND THE
+ DOCUMENTATION. HP SPECIFICALLY DISCLAIMS ALL WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ 5. HEWLETT-PACKARD COMPANY WILL NOT IN ANY EVENT BE LIABLE FOR ANY
+ DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ (INCLUDING LOST PROFITS) RELATED TO ANY USE, REPRODUCTION,
+ MODIFICATION, OR DISTRIBUTION OF THE SOFTWARE OR DOCUMENTATION.
+
+*/
+
+#include "netperf_version.h"
+
+char netserver_id[]="\
+@(#)netserver.c (c) Copyright 1993-2007 Hewlett-Packard Co. Version 2.4.3";
+
+ /***********************************************************************/
+ /* */
+ /* netserver.c */
+ /* */
+ /* This is the server side code for the netperf test package. It */
+ /* will operate either stand-alone, or as a child of inetd. In this */
+ /* way, we insure that it can be installed on systems with or without */
+ /* root permissions (editing inetd.conf). Essentially, this code is */
+ /* the analog to the netsh.c code. */
+ /* */
+ /***********************************************************************/
+
+
+/************************************************************************/
+/* */
+/* Global include files */
+/* */
+/************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#ifndef WIN32
+#include <errno.h>
+#include <signal.h>
+#endif
+#if !defined(WIN32) && !defined(__VMS)
+#include <sys/ipc.h>
+#endif /* !defined(WIN32) && !defined(__VMS) */
+#include <fcntl.h>
+#ifdef WIN32
+#include <time.h>
+#include <winsock2.h>
+#define netperf_socklen_t socklen_t
+/* we need to find some other way to decide to include ws2 */
+/* if you are trying to compile on Windows 2000 or NT 4 you will */
+/* probably have to define DONT_IPV6 */
+#ifndef DONT_IPV6
+#include <ws2tcpip.h>
+#endif /* DONT_IPV6 */
+#include <windows.h>
+#define sleep(x) Sleep((x)*1000)
+#else
+#ifndef MPE
+#include <sys/time.h>
+#endif /* MPE */
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <unistd.h>
+#ifndef DONT_WAIT
+#include <sys/wait.h>
+#endif /* DONT_WAIT */
+#endif /* WIN32 */
+#include <stdlib.h>
+#ifdef __VMS
+#include <tcpip$inetdef.h>
+#include <unixio.h>
+#endif /* __VMS */
+#include "netlib.h"
+#include "nettest_bsd.h"
+
+#ifdef WANT_UNIX
+#include "nettest_unix.h"
+#endif /* WANT_UNIX */
+
+#ifdef WANT_DLPI
+#include "nettest_dlpi.h"
+#endif /* WANT_DLPI */
+
+#ifdef WANT_SCTP
+#include "nettest_sctp.h"
+#endif
+
+#include "netsh.h"
+
+#ifndef DEBUG_LOG_FILE
+#ifndef WIN32
+#define DEBUG_LOG_FILE "/tmp/netperf.debug"
+#else
+#define DEBUG_LOG_FILE "c:\\temp\\netperf.debug"
+#endif /* WIN32 */
+#endif /* DEBUG_LOG_FILE */
+
+ /* some global variables */
+
+FILE *afp;
+char listen_port[10];
+extern char *optarg;
+extern int optind, opterr;
+
+#ifndef WIN32
+#define SERVER_ARGS "dL:n:p:v:V46"
+#else
+#define SERVER_ARGS "dL:n:p:v:V46I:i:"
+#endif
+
+/* perhaps one day we will use this as part of only opening a debug
+ log file if debug is set, of course we have to be wary of the base
+ use of "where" and so probably always need "where" pointing
+ "somewhere" or other. */
+void
+open_debug_file()
+{
+#ifndef WIN32
+#ifndef PATH_MAX
+#define PATH_MAX MAX_PATH
+#endif
+ char FileName[PATH_MAX]; /* for opening the debug log file */
+ strcpy(FileName, DEBUG_LOG_FILE);
+
+ if (where != NULL) fflush(where);
+
+ snprintf(&FileName[strlen(FileName)], sizeof(FileName) - strlen(FileName), "_%d", getpid());
+ if ((where = fopen(FileName, "w")) == NULL) {
+ perror("netserver: debug file");
+ exit(1);
+ }
+
+ chmod(FileName,0644);
+#endif
+
+}
+ /* 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" performance tests on the server. */
+
+void
+process_requests()
+{
+
+ float temp_rate;
+
+ if (debug) open_debug_file();
+
+
+ while (1) {
+ recv_request();
+
+ switch (netperf_request.content.request_type) {
+
+ case DEBUG_ON:
+ netperf_response.content.response_type = DEBUG_OK;
+ /* dump_request already present in recv_request; redundant? */
+ if (!debug) {
+ debug++;
+ open_debug_file();
+ dump_request();
+ }
+ send_response();
+ break;
+
+ case DEBUG_OFF:
+ if (debug)
+ debug--;
+ netperf_response.content.response_type = DEBUG_OK;
+ send_response();
+ /* +SAF why??? */
+ if (!debug)
+ {
+ fclose(where);
+#if !defined(WIN32) && !defined(MPE) && !defined(__VMS)
+ /* For Unix: reopen the debug write file descriptor to "/dev/null" */
+ /* and redirect stdout to it. */
+ fflush (stdout);
+ where = fopen ("/dev/null", "w");
+ if (where == NULL)
+ {
+ perror ("netserver: reopening debug fp for writing: /dev/null");
+ exit (1);
+ }
+ if (close (STDOUT_FILENO) == -1)
+ {
+ perror ("netserver: closing stdout file descriptor");
+ exit (1);
+ }
+ if (dup (fileno (where)) == -1)
+ {
+ perror ("netserver: duplicate /dev/null write file descr. to stdout");
+ exit (1);
+ }
+#endif /* !WIN32 !MPE !__VMS */
+ }
+ break;
+
+ case CPU_CALIBRATE:
+ netperf_response.content.response_type = CPU_CALIBRATE;
+ temp_rate = calibrate_local_cpu(0.0);
+ bcopy((char *)&temp_rate,
+ (char *)netperf_response.content.test_specific_data,
+ sizeof(temp_rate));
+ bcopy((char *)&lib_num_loc_cpus,
+ (char *)netperf_response.content.test_specific_data + sizeof(temp_rate),
+ sizeof(lib_num_loc_cpus));
+ if (debug) {
+ fprintf(where,"netserver: sending CPU information:");
+ fprintf(where,"rate is %g num cpu %d\n",temp_rate,lib_num_loc_cpus);
+ fflush(where);
+ }
+
+ /* we need the cpu_start, cpu_stop in the looper case to kill the */
+ /* child proceses raj 7/95 */
+
+#ifdef USE_LOOPER
+ cpu_start(1);
+ cpu_stop(1,&temp_rate);
+#endif /* USE_LOOPER */
+
+ send_response();
+ break;
+
+ case DO_TCP_STREAM:
+ recv_tcp_stream();
+ break;
+
+ case DO_TCP_MAERTS:
+ recv_tcp_maerts();
+ break;
+
+ case DO_TCP_RR:
+ recv_tcp_rr();
+ break;
+
+ case DO_TCP_CRR:
+ recv_tcp_conn_rr();
+ break;
+
+ case DO_TCP_CC:
+ recv_tcp_cc();
+ break;
+
+#ifdef DO_1644
+ case DO_TCP_TRR:
+ recv_tcp_tran_rr();
+ break;
+#endif /* DO_1644 */
+
+#ifdef DO_NBRR
+ case DO_TCP_NBRR:
+ recv_tcp_nbrr();
+ break;
+#endif /* DO_NBRR */
+
+ case DO_UDP_STREAM:
+ recv_udp_stream();
+ break;
+
+ case DO_UDP_RR:
+ recv_udp_rr();
+ break;
+
+#ifdef WANT_DLPI
+
+ case DO_DLPI_CO_RR:
+ recv_dlpi_co_rr();
+ break;
+
+ case DO_DLPI_CL_RR:
+ recv_dlpi_cl_rr();
+ break;
+
+ case DO_DLPI_CO_STREAM:
+ recv_dlpi_co_stream();
+ break;
+
+ case DO_DLPI_CL_STREAM:
+ recv_dlpi_cl_stream();
+ break;
+
+#endif /* WANT_DLPI */
+
+#ifdef WANT_UNIX
+
+ case DO_STREAM_STREAM:
+ recv_stream_stream();
+ break;
+
+ case DO_STREAM_RR:
+ recv_stream_rr();
+ break;
+
+ case DO_DG_STREAM:
+ recv_dg_stream();
+ break;
+
+ case DO_DG_RR:
+ recv_dg_rr();
+ break;
+
+#endif /* WANT_UNIX */
+
+#ifdef WANT_XTI
+ case DO_XTI_TCP_STREAM:
+ recv_xti_tcp_stream();
+ break;
+
+ case DO_XTI_TCP_RR:
+ recv_xti_tcp_rr();
+ break;
+
+ case DO_XTI_UDP_STREAM:
+ recv_xti_udp_stream();
+ break;
+
+ case DO_XTI_UDP_RR:
+ recv_xti_udp_rr();
+ break;
+
+#endif /* WANT_XTI */
+
+#ifdef WANT_SCTP
+ case DO_SCTP_STREAM:
+ recv_sctp_stream();
+ break;
+
+ case DO_SCTP_STREAM_MANY:
+ recv_sctp_stream_1toMany();
+ break;
+
+ case DO_SCTP_RR:
+ recv_sctp_rr();
+ break;
+
+ case DO_SCTP_RR_MANY:
+ recv_sctp_rr_1toMany();
+ break;
+#endif
+
+#ifdef WANT_SDP
+ case DO_SDP_STREAM:
+ recv_sdp_stream();
+ break;
+
+ case DO_SDP_MAERTS:
+ recv_sdp_maerts();
+ break;
+
+ case DO_SDP_RR:
+ recv_sdp_rr();
+ break;
+#endif
+
+ default:
+ fprintf(where,"unknown test number %d\n",
+ netperf_request.content.request_type);
+ fflush(where);
+ netperf_response.content.serv_errno=998;
+ send_response();
+ break;
+
+ }
+ }
+}
+
+/*
+ set_up_server()
+
+ set-up the server listen socket. we only call this routine if the
+ user has specified a port number on the command line or we believe we
+ are not a child of inetd or its platform-specific equivalent */
+
+/*KC*/
+
+void
+set_up_server(char hostname[], char port[], int af)
+{
+
+ struct addrinfo hints;
+ struct addrinfo *local_res;
+ struct addrinfo *local_res_temp;
+
+ struct sockaddr_storage peeraddr;
+ netperf_socklen_t peeraddr_len = sizeof(peeraddr);
+
+ SOCKET server_control;
+ int on=1;
+ int count;
+ int error;
+ int not_listening;
+
+#if !defined(WIN32) && !defined(MPE) && !defined(__VMS)
+ FILE *rd_null_fp; /* Used to redirect from "/dev/null". */
+ FILE *wr_null_fp; /* Used to redirect to "/dev/null". */
+#endif /* !WIN32 !MPE !__VMS */
+
+ if (debug) {
+ fprintf(stderr,
+ "set_up_server called with host '%s' port '%s' remfam %d\n",
+ hostname,
+ port,
+ af);
+ fflush(stderr);
+ }
+
+ memset(&hints,0,sizeof(hints));
+ hints.ai_family = af;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_flags = AI_PASSIVE;
+
+ count = 0;
+ do {
+ error = getaddrinfo((char *)hostname,
+ (char *)port,
+ &hints,
+ &local_res);
+ count += 1;
+ if (error == EAI_AGAIN) {
+ if (debug) {
+ fprintf(stderr,"Sleeping on getaddrinfo EAI_AGAIN\n");
+ fflush(stderr);
+ }
+ sleep(1);
+ }
+ } while ((error == EAI_AGAIN) && (count <= 5));
+
+ if (error) {
+ fprintf(stderr,
+ "set_up_server: could not resolve remote '%s' port '%s' af %d",
+ hostname,
+ port,
+ af);
+ fprintf(stderr,"\n\tgetaddrinfo returned %d %s\n",
+ error,
+ gai_strerror(error));
+ exit(-1);
+ }
+
+ if (debug) {
+ dump_addrinfo(stderr, local_res, hostname, port, af);
+ }
+
+ not_listening = 1;
+ local_res_temp = local_res;
+
+ while((local_res_temp != NULL) && (not_listening)) {
+
+ fprintf(stderr,
+ "Starting netserver at port %s\n",
+ port);
+
+ server_control = socket(local_res_temp->ai_family,SOCK_STREAM,0);
+
+ if (server_control == INVALID_SOCKET) {
+ perror("set_up_server could not allocate a socket");
+ exit(-1);
+ }
+
+ /* happiness and joy, keep going */
+ if (setsockopt(server_control,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ (char *)&on ,
+ sizeof(on)) == SOCKET_ERROR) {
+ if (debug) {
+ perror("warning: set_up_server could not set SO_REUSEADDR");
+ }
+ }
+ /* still happy and joyful */
+
+ if ((bind (server_control,
+ local_res_temp->ai_addr,
+ local_res_temp->ai_addrlen) != SOCKET_ERROR) &&
+ (listen (server_control,5) != SOCKET_ERROR)) {
+ not_listening = 0;
+ break;
+ }
+ else {
+ /* we consider a bind() or listen() failure a transient and try
+ the next address */
+ if (debug) {
+ perror("warning: set_up_server failed a bind or listen call\n");
+ }
+ local_res_temp = local_res_temp->ai_next;
+ continue;
+ }
+ }
+
+ if (not_listening) {
+ fprintf(stderr,
+ "set_up_server could not establish a listen endpoint for %s port %s with family %s\n",
+ host_name,
+ port,
+ inet_ftos(af));
+ fflush(stderr);
+ exit(-1);
+ }
+ else {
+ printf("Starting netserver at hostname %s port %s and family %s\n",
+ hostname,
+ port,
+ inet_ftos(af));
+ }
+
+ /*
+ setpgrp();
+ */
+
+#if !defined(WIN32) && !defined(MPE) && !defined(__VMS)
+ /* Flush the standard I/O file descriptors before forking. */
+ fflush (stdin);
+ fflush (stdout);
+ fflush (stderr);
+ switch (fork())
+ {
+ case -1:
+ perror("netperf server error");
+ exit(1);
+
+ case 0:
+ /* Redirect stdin from "/dev/null". */
+ rd_null_fp = fopen ("/dev/null", "r");
+ if (rd_null_fp == NULL)
+ {
+ perror ("netserver: opening for reading: /dev/null");
+ exit (1);
+ }
+ if (close (STDIN_FILENO) == -1)
+ {
+ perror ("netserver: closing stdin file descriptor");
+ exit (1);
+ }
+ if (dup (fileno (rd_null_fp)) == -1)
+ {
+ perror ("netserver: duplicate /dev/null read file descr. to stdin");
+ exit (1);
+ }
+
+ /* Redirect stdout to the debug write file descriptor. */
+ if (close (STDOUT_FILENO) == -1)
+ {
+ perror ("netserver: closing stdout file descriptor");
+ exit (1);
+ }
+ if (dup (fileno (where)) == -1)
+ {
+ perror ("netserver: duplicate the debug write file descr. to stdout");
+ exit (1);
+ }
+
+ /* Redirect stderr to "/dev/null". */
+ wr_null_fp = fopen ("/dev/null", "w");
+ if (wr_null_fp == NULL)
+ {
+ perror ("netserver: opening for writing: /dev/null");
+ exit (1);
+ }
+ if (close (STDERR_FILENO) == -1)
+ {
+ perror ("netserver: closing stderr file descriptor");
+ exit (1);
+ }
+ if (dup (fileno (wr_null_fp)) == -1)
+ {
+ perror ("netserver: dupicate /dev/null write file descr. to stderr");
+ exit (1);
+ }
+
+#ifndef NO_SETSID
+ setsid();
+#else
+ setpgrp();
+#endif /* NO_SETSID */
+
+ /* some OS's have SIGCLD defined as SIGCHLD */
+#ifndef SIGCLD
+#define SIGCLD SIGCHLD
+#endif /* SIGCLD */
+
+ signal(SIGCLD, SIG_IGN);
+
+#endif /* !WIN32 !MPE !__VMS */
+
+ for (;;)
+ {
+ if ((server_sock=accept(server_control,
+ (struct sockaddr *)&peeraddr,
+ &peeraddr_len)) == INVALID_SOCKET)
+ {
+ printf("server_control: accept failed errno %d\n",errno);
+ exit(1);
+ }
+#if defined(MPE) || defined(__VMS)
+ /*
+ * Since we cannot fork this process , we cant fire any threads
+ * as they all share the same global data . So we better allow
+ * one request at at time
+ */
+ process_requests() ;
+#elif WIN32
+ {
+ BOOL b;
+ char cmdline[80];
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ int i;
+
+ memset(&si, 0 , sizeof(STARTUPINFO));
+ si.cb = sizeof(STARTUPINFO);
+
+ /* Pass the server_sock as stdin for the new process. */
+ /* Hopefully this will continue to be created with the OBJ_INHERIT attribute. */
+ si.hStdInput = (HANDLE)server_sock;
+ si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ si.dwFlags = STARTF_USESTDHANDLES;
+
+ /* Build cmdline for child process */
+ strcpy(cmdline, program);
+ if (verbosity > 1) {
+ snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -v %d", verbosity);
+ }
+ for (i=0; i < debug; i++) {
+ snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -d");
+ }
+ snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -I %x", (int)(UINT_PTR)server_sock);
+ snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -i %x", (int)(UINT_PTR)server_control);
+ snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -i %x", (int)(UINT_PTR)where);
+
+ b = CreateProcess(NULL, /* Application Name */
+ cmdline,
+ NULL, /* Process security attributes */
+ NULL, /* Thread security attributes */
+ TRUE, /* Inherit handles */
+ 0, /* Creation flags PROCESS_QUERY_INFORMATION, */
+ NULL, /* Enviornment */
+ NULL, /* Current directory */
+ &si, /* StartupInfo */
+ &pi);
+ if (!b)
+ {
+ perror("CreateProcessfailure: ");
+ exit(1);
+ }
+
+ /* We don't need the thread or process handles any more; let them */
+ /* go away on their own timeframe. */
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ /* And close the server_sock since the child will own it. */
+
+ close(server_sock);
+ }
+#else
+ signal(SIGCLD, SIG_IGN);
+
+ switch (fork())
+ {
+ case -1:
+ /* something went wrong */
+ exit(1);
+ case 0:
+ /* we are the child process */
+ close(server_control);
+ process_requests();
+ exit(0);
+ break;
+ default:
+ /* we are the parent process */
+ close(server_sock);
+ /* we should try to "reap" some of our children. on some */
+ /* systems they are being left as defunct processes. we */
+ /* will call waitpid, looking for any child process, */
+ /* with the WNOHANG feature. when waitpid return a zero, */
+ /* we have reaped all the children there are to reap at */
+ /* the moment, so it is time to move on. raj 12/94 */
+#ifndef DONT_WAIT
+#ifdef NO_SETSID
+ /* Only call "waitpid()" if "setsid()" is not used. */
+ while(waitpid(-1, NULL, WNOHANG) > 0) { }
+#endif /* NO_SETSID */
+#endif /* DONT_WAIT */
+ break;
+ }
+#endif /* !WIN32 !MPE !__VMS */
+ } /*for*/
+#if !defined(WIN32) && !defined(MPE) && !defined(__VMS)
+ break; /*case 0*/
+
+ default:
+ exit (0);
+
+ }
+#endif /* !WIN32 !MPE !__VMS */
+}
+
+#ifdef WIN32
+
+ /* 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 child address space copy_on_write */
+ /* support, since it isn't exposed except through the NT native APIs */
+ /* (which is not public). */
+
+ /* We will try to use the InheritHandles flag in CreateProcess. It */
+ /* is in the public API, though it is documented as "must be FALSE". */
+
+ /* So where we would have forked, we will now create a new process. */
+ /* I have added a set of command line switches to specify a list of */
+ /* handles that the child should close since they shouldn't have */
+ /* been inherited ("-i#"), and a single switch to specify the handle */
+ /* for the server_sock ("I#"). */
+
+ /* A better alternative would be to re-write NetPerf to be */
+ /* multi-threaded; i.e., move all of the various NetPerf global */
+ /* variables in to thread specific structures. But this is a bigger */
+ /* effort than I want to tackle at this time. (And I doubt that the */
+ /* HP-UX author sees value in this effort). */
+
+#endif
+
+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 vwelch@ncsa.uiuc.edu (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);
+}