void setup_listens(char name[], char port[], int af) { int do_inet; int no_name = 0; #ifdef AF_INET6 int do_inet6; #endif if (debug) { fprintf(where, "%s: enter\n", __FUNCTION__); fflush(where); } if (strcmp(name,"") == 0) { no_name = 1; switch (af) { case AF_UNSPEC: do_inet = 1; #ifdef AF_INET6 do_inet6 = 1; #endif break; case AF_INET: do_inet = 1; #ifdef AF_INET6 do_inet6 = 0; #endif break; #ifdef AF_INET6 case AF_INET6: do_inet = 0; do_inet6 = 1; break; #endif default: do_inet = 1; } /* if we have IPv6, try that one first because it may be a superset */ #ifdef AF_INET6 if (do_inet6) create_listens("::0",port,AF_INET6); #endif if (do_inet) create_listens("0.0.0.0",port,AF_INET); } else { create_listens(name,port,af); } if (listen_list) { fprintf(stdout, "Starting netserver with host '%s' port '%s' and family %s\n", (no_name) ? "IN(6)ADDR_ANY" : name, port, inet_ftos(af)); fflush(stdout); } else { fprintf(stderr, "Unable to start netserver with '%s' port '%s' and family %s\n", (no_name) ? "IN(6)ADDR_ANY" : name, port, inet_ftos(af)); fflush(stderr); exit(1); } }
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); #if defined(HAVE_FORK) switch (fork()) #else switch (vfork()) #endif { 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); #if defined(HAVE_FORK) switch (fork()) #else switch (vfork()) #endif { 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 */ }
void create_listens(char hostname[], char port[], int af) { struct addrinfo hints; struct addrinfo *local_res; struct addrinfo *local_res_temp; int count, error; int on = 1; SOCKET temp_socket; struct listen_elt *temp_elt; if (debug) { fprintf(stderr, "%s: called with host '%s' port '%s' family %s(%d)\n", __FUNCTION__, hostname, port, inet_ftos(af), 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, "%s: Sleeping on getaddrinfo EAI_AGAIN\n", __FUNCTION__); fflush(stderr); } sleep(1); } } while ((error == EAI_AGAIN) && (count <= 5)); if (error) { if (debug) { fprintf(stderr, "%s: could not resolve remote '%s' port '%s' af %d\n" "\tgetaddrinfo returned %s (%d)\n", __FUNCTION__, hostname, port, af, gai_strerror(error), error); } return; } if (debug) { dump_addrinfo(stderr, local_res, hostname, port, af); } local_res_temp = local_res; while (local_res_temp != NULL) { temp_socket = socket(local_res_temp->ai_family,SOCK_STREAM,0); if (temp_socket == INVALID_SOCKET) { if (debug) { fprintf(stderr, "%s could not allocate a socket: %s (errno %d)\n", __FUNCTION__, strerror(errno), errno); fflush(stderr); } local_res_temp = local_res_temp->ai_next; continue; } /* happiness and joy, keep going */ if (setsockopt(temp_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on , sizeof(on)) == SOCKET_ERROR) { if (debug) { fprintf(stderr, "%s: warning: could not set SO_REUSEADDR: %s (errno %d)\n", __FUNCTION__, strerror(errno), errno); fflush(stderr); } } /* still happy and joyful */ if ((bind(temp_socket, local_res_temp->ai_addr, local_res_temp->ai_addrlen) != SOCKET_ERROR) && (listen(temp_socket,1024) != SOCKET_ERROR)) { /* OK, now add to the list */ temp_elt = (struct listen_elt *)malloc(sizeof(struct listen_elt)); if (temp_elt) { temp_elt->fd = temp_socket; if (listen_list) { temp_elt->next = listen_list; } else { temp_elt->next = NULL; } listen_list = temp_elt; } else { fprintf(stderr, "%s: could not malloc a listen_elt\n", __FUNCTION__); fflush(stderr); exit(1); } } else { /* we consider a bind() or listen() failure a transient and try the next address */ if (debug) { fprintf(stderr, "%s: warning: bind or listen call failure: %s (errno %d)\n", __FUNCTION__, strerror(errno), errno); fflush(stderr); } close(temp_socket); } local_res_temp = local_res_temp->ai_next; } }