1*57e22627SCy Schubert /* 2*57e22627SCy Schubert * Copyright (c) 2002 - 2003 3*57e22627SCy Schubert * NetGroup, Politecnico di Torino (Italy) 4*57e22627SCy Schubert * All rights reserved. 5*57e22627SCy Schubert * 6*57e22627SCy Schubert * Redistribution and use in source and binary forms, with or without 7*57e22627SCy Schubert * modification, are permitted provided that the following conditions 8*57e22627SCy Schubert * are met: 9*57e22627SCy Schubert * 10*57e22627SCy Schubert * 1. Redistributions of source code must retain the above copyright 11*57e22627SCy Schubert * notice, this list of conditions and the following disclaimer. 12*57e22627SCy Schubert * 2. Redistributions in binary form must reproduce the above copyright 13*57e22627SCy Schubert * notice, this list of conditions and the following disclaimer in the 14*57e22627SCy Schubert * documentation and/or other materials provided with the distribution. 15*57e22627SCy Schubert * 3. Neither the name of the Politecnico di Torino nor the names of its 16*57e22627SCy Schubert * contributors may be used to endorse or promote products derived from 17*57e22627SCy Schubert * this software without specific prior written permission. 18*57e22627SCy Schubert * 19*57e22627SCy Schubert * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*57e22627SCy Schubert * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*57e22627SCy Schubert * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22*57e22627SCy Schubert * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23*57e22627SCy Schubert * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24*57e22627SCy Schubert * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25*57e22627SCy Schubert * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*57e22627SCy Schubert * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*57e22627SCy Schubert * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*57e22627SCy Schubert * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29*57e22627SCy Schubert * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*57e22627SCy Schubert * 31*57e22627SCy Schubert */ 32*57e22627SCy Schubert 33*57e22627SCy Schubert #ifdef HAVE_CONFIG_H 34*57e22627SCy Schubert #include <config.h> 35*57e22627SCy Schubert #endif 36*57e22627SCy Schubert 37*57e22627SCy Schubert #include "ftmacros.h" 38*57e22627SCy Schubert 39*57e22627SCy Schubert #include <errno.h> // for the errno variable 40*57e22627SCy Schubert #include <string.h> // for strtok, etc 41*57e22627SCy Schubert #include <stdlib.h> // for malloc(), free(), ... 42*57e22627SCy Schubert #include <pcap.h> // for PCAP_ERRBUF_SIZE 43*57e22627SCy Schubert #include <signal.h> // for signal() 44*57e22627SCy Schubert 45*57e22627SCy Schubert #include "fmtutils.h" 46*57e22627SCy Schubert #include "sockutils.h" // for socket calls 47*57e22627SCy Schubert #include "varattrs.h" // for _U_ 48*57e22627SCy Schubert #include "portability.h" 49*57e22627SCy Schubert #include "rpcapd.h" 50*57e22627SCy Schubert #include "config_params.h" // configuration file parameters 51*57e22627SCy Schubert #include "fileconf.h" // for the configuration file management 52*57e22627SCy Schubert #include "rpcap-protocol.h" 53*57e22627SCy Schubert #include "daemon.h" // the true main() method of this daemon 54*57e22627SCy Schubert #include "log.h" 55*57e22627SCy Schubert 56*57e22627SCy Schubert #ifdef _WIN32 57*57e22627SCy Schubert #include <process.h> // for thread stuff 58*57e22627SCy Schubert #include "win32-svc.h" // for Win32 service stuff 59*57e22627SCy Schubert #include "getopt.h" // for getopt()-for-Windows 60*57e22627SCy Schubert #else 61*57e22627SCy Schubert #include <fcntl.h> // for open() 62*57e22627SCy Schubert #include <unistd.h> // for exit() 63*57e22627SCy Schubert #include <sys/wait.h> // waitpid() 64*57e22627SCy Schubert #endif 65*57e22627SCy Schubert 66*57e22627SCy Schubert // 67*57e22627SCy Schubert // Element in list of sockets on which we're listening for connections. 68*57e22627SCy Schubert // 69*57e22627SCy Schubert struct listen_sock { 70*57e22627SCy Schubert struct listen_sock *next; 71*57e22627SCy Schubert SOCKET sock; 72*57e22627SCy Schubert }; 73*57e22627SCy Schubert 74*57e22627SCy Schubert // Global variables 75*57e22627SCy Schubert char hostlist[MAX_HOST_LIST + 1]; //!< Keeps the list of the hosts that are allowed to connect to this server 76*57e22627SCy Schubert struct active_pars activelist[MAX_ACTIVE_LIST]; //!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode) 77*57e22627SCy Schubert int nullAuthAllowed; //!< '1' if we permit NULL authentication, '0' otherwise 78*57e22627SCy Schubert static struct listen_sock *listen_socks; //!< sockets on which we listen 79*57e22627SCy Schubert char loadfile[MAX_LINE + 1]; //!< Name of the file from which we have to load the configuration 80*57e22627SCy Schubert static int passivemode = 1; //!< '1' if we want to run in passive mode as well 81*57e22627SCy Schubert static struct addrinfo mainhints; //!< temporary struct to keep settings needed to open the new socket 82*57e22627SCy Schubert static char address[MAX_LINE + 1]; //!< keeps the network address (either numeric or literal) to bind to 83*57e22627SCy Schubert static char port[MAX_LINE + 1]; //!< keeps the network port to bind to 84*57e22627SCy Schubert #ifdef _WIN32 85*57e22627SCy Schubert static HANDLE state_change_event; //!< event to signal that a state change should take place 86*57e22627SCy Schubert #endif 87*57e22627SCy Schubert static volatile sig_atomic_t shutdown_server; //!< '1' if the server is to shut down 88*57e22627SCy Schubert static volatile sig_atomic_t reread_config; //!< '1' if the server is to re-read its configuration 89*57e22627SCy Schubert 90*57e22627SCy Schubert extern char *optarg; // for getopt() 91*57e22627SCy Schubert 92*57e22627SCy Schubert // Function definition 93*57e22627SCy Schubert #ifdef _WIN32 94*57e22627SCy Schubert static unsigned __stdcall main_active(void *ptr); 95*57e22627SCy Schubert static BOOL WINAPI main_ctrl_event(DWORD); 96*57e22627SCy Schubert #else 97*57e22627SCy Schubert static void *main_active(void *ptr); 98*57e22627SCy Schubert static void main_terminate(int sign); 99*57e22627SCy Schubert static void main_reread_config(int sign); 100*57e22627SCy Schubert #endif 101*57e22627SCy Schubert static void accept_connections(void); 102*57e22627SCy Schubert static void accept_connection(SOCKET listen_sock); 103*57e22627SCy Schubert #ifndef _WIN32 104*57e22627SCy Schubert static void main_reap_children(int sign); 105*57e22627SCy Schubert #endif 106*57e22627SCy Schubert #ifdef _WIN32 107*57e22627SCy Schubert static unsigned __stdcall main_passive_serviceloop_thread(void *ptr); 108*57e22627SCy Schubert #endif 109*57e22627SCy Schubert 110*57e22627SCy Schubert #define RPCAP_ACTIVE_WAIT 30 /* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */ 111*57e22627SCy Schubert 112*57e22627SCy Schubert /*! 113*57e22627SCy Schubert \brief Prints the usage screen if it is launched in console mode. 114*57e22627SCy Schubert */ 115*57e22627SCy Schubert static void printusage(void) 116*57e22627SCy Schubert { 117*57e22627SCy Schubert const char *usagetext = 118*57e22627SCy Schubert "USAGE:" 119*57e22627SCy Schubert " " PROGRAM_NAME " [-b <address>] [-p <port>] [-4] [-l <host_list>] [-a <host,port>]\n" 120*57e22627SCy Schubert " [-n] [-v] [-d] " 121*57e22627SCy Schubert #ifndef _WIN32 122*57e22627SCy Schubert "[-i] " 123*57e22627SCy Schubert #endif 124*57e22627SCy Schubert "[-D] [-s <config_file>] [-f <config_file>]\n\n" 125*57e22627SCy Schubert " -b <address> the address to bind to (either numeric or literal).\n" 126*57e22627SCy Schubert " Default: binds to all local IPv4 and IPv6 addresses\n\n" 127*57e22627SCy Schubert " -p <port> the port to bind to.\n" 128*57e22627SCy Schubert " Default: binds to port " RPCAP_DEFAULT_NETPORT "\n\n" 129*57e22627SCy Schubert " -4 use only IPv4.\n" 130*57e22627SCy Schubert " Default: use both IPv4 and IPv6 waiting sockets\n\n" 131*57e22627SCy Schubert " -l <host_list> a file that contains a list of hosts that are allowed\n" 132*57e22627SCy Schubert " to connect to this server (if more than one, list them one\n" 133*57e22627SCy Schubert " per line).\n" 134*57e22627SCy Schubert " We suggest to use literal names (instead of numeric ones)\n" 135*57e22627SCy Schubert " in order to avoid problems with different address families.\n\n" 136*57e22627SCy Schubert " -n permit NULL authentication (usually used with '-l')\n\n" 137*57e22627SCy Schubert " -a <host,port> run in active mode when connecting to 'host' on port 'port'\n" 138*57e22627SCy Schubert " In case 'port' is omitted, the default port (" RPCAP_DEFAULT_NETPORT_ACTIVE ") is used\n\n" 139*57e22627SCy Schubert " -v run in active mode only (default: if '-a' is specified, it\n" 140*57e22627SCy Schubert " accepts passive connections as well)\n\n" 141*57e22627SCy Schubert " -d run in daemon mode (UNIX only) or as a service (Win32 only)\n" 142*57e22627SCy Schubert " Warning (Win32): this switch is provided automatically when\n" 143*57e22627SCy Schubert " the service is started from the control panel\n\n" 144*57e22627SCy Schubert #ifndef _WIN32 145*57e22627SCy Schubert " -i run in inetd mode (UNIX only)\n\n" 146*57e22627SCy Schubert #endif 147*57e22627SCy Schubert " -D log debugging messages\n\n" 148*57e22627SCy Schubert " -s <config_file> save the current configuration to file\n\n" 149*57e22627SCy Schubert " -f <config_file> load the current configuration from file; all switches\n" 150*57e22627SCy Schubert " specified from the command line are ignored\n\n" 151*57e22627SCy Schubert " -h print this help screen\n\n"; 152*57e22627SCy Schubert 153*57e22627SCy Schubert (void)fprintf(stderr, "RPCAPD, a remote packet capture daemon.\n" 154*57e22627SCy Schubert "Compiled with %s\n\n", pcap_lib_version()); 155*57e22627SCy Schubert printf("%s", usagetext); 156*57e22627SCy Schubert } 157*57e22627SCy Schubert 158*57e22627SCy Schubert 159*57e22627SCy Schubert 160*57e22627SCy Schubert //! Program main 161*57e22627SCy Schubert int main(int argc, char *argv[]) 162*57e22627SCy Schubert { 163*57e22627SCy Schubert char savefile[MAX_LINE + 1]; // name of the file on which we have to save the configuration 164*57e22627SCy Schubert int log_to_systemlog = 0; // Non-zero if we should log to the "system log" rather than the standard error 165*57e22627SCy Schubert int isdaemon = 0; // Non-zero if the user wants to run this program as a daemon 166*57e22627SCy Schubert #ifndef _WIN32 167*57e22627SCy Schubert int isrunbyinetd = 0; // Non-zero if this is being run by inetd or something inetd-like 168*57e22627SCy Schubert #endif 169*57e22627SCy Schubert int log_debug_messages = 0; // Non-zero if the user wants debug messages logged 170*57e22627SCy Schubert int retval; // keeps the returning value from several functions 171*57e22627SCy Schubert char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed 172*57e22627SCy Schubert #ifndef _WIN32 173*57e22627SCy Schubert struct sigaction action; 174*57e22627SCy Schubert #endif 175*57e22627SCy Schubert 176*57e22627SCy Schubert savefile[0] = 0; 177*57e22627SCy Schubert loadfile[0] = 0; 178*57e22627SCy Schubert hostlist[0] = 0; 179*57e22627SCy Schubert 180*57e22627SCy Schubert // Initialize errbuf 181*57e22627SCy Schubert memset(errbuf, 0, sizeof(errbuf)); 182*57e22627SCy Schubert 183*57e22627SCy Schubert strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE); 184*57e22627SCy Schubert strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE); 185*57e22627SCy Schubert 186*57e22627SCy Schubert // Prepare to open a new server socket 187*57e22627SCy Schubert memset(&mainhints, 0, sizeof(struct addrinfo)); 188*57e22627SCy Schubert 189*57e22627SCy Schubert mainhints.ai_family = PF_UNSPEC; 190*57e22627SCy Schubert mainhints.ai_flags = AI_PASSIVE; // Ready to a bind() socket 191*57e22627SCy Schubert mainhints.ai_socktype = SOCK_STREAM; 192*57e22627SCy Schubert 193*57e22627SCy Schubert // Getting the proper command line options 194*57e22627SCy Schubert while ((retval = getopt(argc, argv, "b:dDhip:4l:na:s:f:v")) != -1) 195*57e22627SCy Schubert { 196*57e22627SCy Schubert switch (retval) 197*57e22627SCy Schubert { 198*57e22627SCy Schubert case 'D': 199*57e22627SCy Schubert log_debug_messages = 1; 200*57e22627SCy Schubert rpcapd_log_set(log_to_systemlog, log_debug_messages); 201*57e22627SCy Schubert break; 202*57e22627SCy Schubert case 'b': 203*57e22627SCy Schubert strncpy(address, optarg, MAX_LINE); 204*57e22627SCy Schubert break; 205*57e22627SCy Schubert case 'p': 206*57e22627SCy Schubert strncpy(port, optarg, MAX_LINE); 207*57e22627SCy Schubert break; 208*57e22627SCy Schubert case '4': 209*57e22627SCy Schubert mainhints.ai_family = PF_INET; // IPv4 server only 210*57e22627SCy Schubert break; 211*57e22627SCy Schubert case 'd': 212*57e22627SCy Schubert isdaemon = 1; 213*57e22627SCy Schubert log_to_systemlog = 1; 214*57e22627SCy Schubert rpcapd_log_set(log_to_systemlog, log_debug_messages); 215*57e22627SCy Schubert break; 216*57e22627SCy Schubert case 'i': 217*57e22627SCy Schubert #ifdef _WIN32 218*57e22627SCy Schubert printusage(); 219*57e22627SCy Schubert exit(1); 220*57e22627SCy Schubert #else 221*57e22627SCy Schubert isrunbyinetd = 1; 222*57e22627SCy Schubert log_to_systemlog = 1; 223*57e22627SCy Schubert rpcapd_log_set(log_to_systemlog, log_debug_messages); 224*57e22627SCy Schubert #endif 225*57e22627SCy Schubert break; 226*57e22627SCy Schubert case 'n': 227*57e22627SCy Schubert nullAuthAllowed = 1; 228*57e22627SCy Schubert break; 229*57e22627SCy Schubert case 'v': 230*57e22627SCy Schubert passivemode = 0; 231*57e22627SCy Schubert break; 232*57e22627SCy Schubert case 'l': 233*57e22627SCy Schubert { 234*57e22627SCy Schubert strncpy(hostlist, optarg, sizeof(hostlist)); 235*57e22627SCy Schubert break; 236*57e22627SCy Schubert } 237*57e22627SCy Schubert case 'a': 238*57e22627SCy Schubert { 239*57e22627SCy Schubert char *tmpaddress, *tmpport; 240*57e22627SCy Schubert char *lasts; 241*57e22627SCy Schubert int i = 0; 242*57e22627SCy Schubert 243*57e22627SCy Schubert tmpaddress = pcap_strtok_r(optarg, RPCAP_HOSTLIST_SEP, &lasts); 244*57e22627SCy Schubert 245*57e22627SCy Schubert while ((tmpaddress != NULL) && (i < MAX_ACTIVE_LIST)) 246*57e22627SCy Schubert { 247*57e22627SCy Schubert tmpport = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts); 248*57e22627SCy Schubert 249*57e22627SCy Schubert pcap_strlcpy(activelist[i].address, tmpaddress, MAX_LINE); 250*57e22627SCy Schubert 251*57e22627SCy Schubert if ((tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0)) // the user choose a custom port 252*57e22627SCy Schubert pcap_strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE); 253*57e22627SCy Schubert else 254*57e22627SCy Schubert pcap_strlcpy(activelist[i].port, tmpport, MAX_LINE); 255*57e22627SCy Schubert 256*57e22627SCy Schubert tmpaddress = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts); 257*57e22627SCy Schubert 258*57e22627SCy Schubert i++; 259*57e22627SCy Schubert } 260*57e22627SCy Schubert 261*57e22627SCy Schubert if (i > MAX_ACTIVE_LIST) 262*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Only MAX_ACTIVE_LIST active connections are currently supported."); 263*57e22627SCy Schubert 264*57e22627SCy Schubert // I don't initialize the remaining part of the structure, since 265*57e22627SCy Schubert // it is already zeroed (it is a global var) 266*57e22627SCy Schubert break; 267*57e22627SCy Schubert } 268*57e22627SCy Schubert case 'f': 269*57e22627SCy Schubert pcap_strlcpy(loadfile, optarg, MAX_LINE); 270*57e22627SCy Schubert break; 271*57e22627SCy Schubert case 's': 272*57e22627SCy Schubert pcap_strlcpy(savefile, optarg, MAX_LINE); 273*57e22627SCy Schubert break; 274*57e22627SCy Schubert case 'h': 275*57e22627SCy Schubert printusage(); 276*57e22627SCy Schubert exit(0); 277*57e22627SCy Schubert /*NOTREACHED*/ 278*57e22627SCy Schubert default: 279*57e22627SCy Schubert exit(1); 280*57e22627SCy Schubert /*NOTREACHED*/ 281*57e22627SCy Schubert } 282*57e22627SCy Schubert } 283*57e22627SCy Schubert 284*57e22627SCy Schubert #ifndef _WIN32 285*57e22627SCy Schubert if (isdaemon && isrunbyinetd) 286*57e22627SCy Schubert { 287*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "rpcapd: -d and -i can't be used together"); 288*57e22627SCy Schubert exit(1); 289*57e22627SCy Schubert } 290*57e22627SCy Schubert #endif 291*57e22627SCy Schubert 292*57e22627SCy Schubert if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1) 293*57e22627SCy Schubert { 294*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 295*57e22627SCy Schubert exit(-1); 296*57e22627SCy Schubert } 297*57e22627SCy Schubert 298*57e22627SCy Schubert if (savefile[0] && fileconf_save(savefile)) 299*57e22627SCy Schubert rpcapd_log(LOGPRIO_DEBUG, "Error when saving the configuration to file"); 300*57e22627SCy Schubert 301*57e22627SCy Schubert // If the file does not exist, it keeps the settings provided by the command line 302*57e22627SCy Schubert if (loadfile[0]) 303*57e22627SCy Schubert fileconf_read(); 304*57e22627SCy Schubert 305*57e22627SCy Schubert #ifdef WIN32 306*57e22627SCy Schubert // 307*57e22627SCy Schubert // Create a handle to signal the main loop to tell it to do 308*57e22627SCy Schubert // something. 309*57e22627SCy Schubert // 310*57e22627SCy Schubert state_change_event = CreateEvent(NULL, FALSE, FALSE, NULL); 311*57e22627SCy Schubert if (state_change_event == NULL) 312*57e22627SCy Schubert { 313*57e22627SCy Schubert sock_geterror("Can't create state change event", errbuf, 314*57e22627SCy Schubert PCAP_ERRBUF_SIZE); 315*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 316*57e22627SCy Schubert exit(2); 317*57e22627SCy Schubert } 318*57e22627SCy Schubert 319*57e22627SCy Schubert // 320*57e22627SCy Schubert // Catch control signals. 321*57e22627SCy Schubert // 322*57e22627SCy Schubert if (!SetConsoleCtrlHandler(main_ctrl_event, TRUE)) 323*57e22627SCy Schubert { 324*57e22627SCy Schubert sock_geterror("Can't set control handler", errbuf, 325*57e22627SCy Schubert PCAP_ERRBUF_SIZE); 326*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 327*57e22627SCy Schubert exit(2); 328*57e22627SCy Schubert } 329*57e22627SCy Schubert #else 330*57e22627SCy Schubert memset(&action, 0, sizeof (action)); 331*57e22627SCy Schubert action.sa_handler = main_terminate; 332*57e22627SCy Schubert action.sa_flags = 0; 333*57e22627SCy Schubert sigemptyset(&action.sa_mask); 334*57e22627SCy Schubert sigaction(SIGTERM, &action, NULL); 335*57e22627SCy Schubert memset(&action, 0, sizeof (action)); 336*57e22627SCy Schubert action.sa_handler = main_reap_children; 337*57e22627SCy Schubert action.sa_flags = 0; 338*57e22627SCy Schubert sigemptyset(&action.sa_mask); 339*57e22627SCy Schubert sigaction(SIGCHLD, &action, NULL); 340*57e22627SCy Schubert // Ignore SIGPIPE - we'll get EPIPE when trying to write to a closed 341*57e22627SCy Schubert // connection, we don't want to get killed by a signal in that case 342*57e22627SCy Schubert signal(SIGPIPE, SIG_IGN); 343*57e22627SCy Schubert #endif 344*57e22627SCy Schubert 345*57e22627SCy Schubert #ifndef _WIN32 346*57e22627SCy Schubert if (isrunbyinetd) 347*57e22627SCy Schubert { 348*57e22627SCy Schubert // 349*57e22627SCy Schubert // -i was specified, indicating that this is being run 350*57e22627SCy Schubert // by inetd or something that can run network daemons 351*57e22627SCy Schubert // as if it were inetd (xinetd, launchd, systemd, etc.). 352*57e22627SCy Schubert // 353*57e22627SCy Schubert // We assume that the program that launched us just 354*57e22627SCy Schubert // duplicated a single socket for the connection 355*57e22627SCy Schubert // to our standard input, output, and error, so we 356*57e22627SCy Schubert // can just use the standard input as our control 357*57e22627SCy Schubert // socket. 358*57e22627SCy Schubert // 359*57e22627SCy Schubert int sockctrl; 360*57e22627SCy Schubert int devnull_fd; 361*57e22627SCy Schubert 362*57e22627SCy Schubert // 363*57e22627SCy Schubert // Duplicate the standard input as the control socket. 364*57e22627SCy Schubert // 365*57e22627SCy Schubert sockctrl = dup(0); 366*57e22627SCy Schubert if (sockctrl == -1) 367*57e22627SCy Schubert { 368*57e22627SCy Schubert sock_geterror("Can't dup standard input", errbuf, 369*57e22627SCy Schubert PCAP_ERRBUF_SIZE); 370*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 371*57e22627SCy Schubert exit(2); 372*57e22627SCy Schubert } 373*57e22627SCy Schubert 374*57e22627SCy Schubert // 375*57e22627SCy Schubert // Try to set the standard input, output, and error 376*57e22627SCy Schubert // to /dev/null. 377*57e22627SCy Schubert // 378*57e22627SCy Schubert devnull_fd = open("/dev/null", O_RDWR); 379*57e22627SCy Schubert if (devnull_fd != -1) 380*57e22627SCy Schubert { 381*57e22627SCy Schubert // 382*57e22627SCy Schubert // If this fails, just drive on. 383*57e22627SCy Schubert // 384*57e22627SCy Schubert (void)dup2(devnull_fd, 0); 385*57e22627SCy Schubert (void)dup2(devnull_fd, 1); 386*57e22627SCy Schubert (void)dup2(devnull_fd, 2); 387*57e22627SCy Schubert close(devnull_fd); 388*57e22627SCy Schubert } 389*57e22627SCy Schubert 390*57e22627SCy Schubert // 391*57e22627SCy Schubert // Handle this client. 392*57e22627SCy Schubert // This is passive mode, so we don't care whether we were 393*57e22627SCy Schubert // told by the client to close. 394*57e22627SCy Schubert // 395*57e22627SCy Schubert char *hostlist_copy = strdup(hostlist); 396*57e22627SCy Schubert if (hostlist_copy == NULL) 397*57e22627SCy Schubert { 398*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list"); 399*57e22627SCy Schubert exit(0); 400*57e22627SCy Schubert } 401*57e22627SCy Schubert (void)daemon_serviceloop(sockctrl, 0, hostlist_copy, 402*57e22627SCy Schubert nullAuthAllowed); 403*57e22627SCy Schubert 404*57e22627SCy Schubert // 405*57e22627SCy Schubert // Nothing more to do. 406*57e22627SCy Schubert // 407*57e22627SCy Schubert exit(0); 408*57e22627SCy Schubert } 409*57e22627SCy Schubert #endif 410*57e22627SCy Schubert 411*57e22627SCy Schubert if (isdaemon) 412*57e22627SCy Schubert { 413*57e22627SCy Schubert // 414*57e22627SCy Schubert // This is being run as a daemon. 415*57e22627SCy Schubert // On UN*X, it might be manually run, or run from an 416*57e22627SCy Schubert // rc file. 417*57e22627SCy Schubert // 418*57e22627SCy Schubert #ifndef _WIN32 419*57e22627SCy Schubert int pid; 420*57e22627SCy Schubert 421*57e22627SCy Schubert // 422*57e22627SCy Schubert // Daemonize ourselves. 423*57e22627SCy Schubert // 424*57e22627SCy Schubert // Unix Network Programming, pg 336 425*57e22627SCy Schubert // 426*57e22627SCy Schubert if ((pid = fork()) != 0) 427*57e22627SCy Schubert exit(0); // Parent terminates 428*57e22627SCy Schubert 429*57e22627SCy Schubert // First child continues 430*57e22627SCy Schubert // Set daemon mode 431*57e22627SCy Schubert setsid(); 432*57e22627SCy Schubert 433*57e22627SCy Schubert // generated under unix with 'kill -HUP', needed to reload the configuration 434*57e22627SCy Schubert memset(&action, 0, sizeof (action)); 435*57e22627SCy Schubert action.sa_handler = main_reread_config; 436*57e22627SCy Schubert action.sa_flags = 0; 437*57e22627SCy Schubert sigemptyset(&action.sa_mask); 438*57e22627SCy Schubert sigaction(SIGHUP, &action, NULL); 439*57e22627SCy Schubert 440*57e22627SCy Schubert if ((pid = fork()) != 0) 441*57e22627SCy Schubert exit(0); // First child terminates 442*57e22627SCy Schubert 443*57e22627SCy Schubert // LINUX WARNING: the current linux implementation of pthreads requires a management thread 444*57e22627SCy Schubert // to handle some hidden stuff. So, as soon as you create the first thread, two threads are 445*57e22627SCy Schubert // created. Fom this point on, the number of threads active are always one more compared 446*57e22627SCy Schubert // to the number you're expecting 447*57e22627SCy Schubert 448*57e22627SCy Schubert // Second child continues 449*57e22627SCy Schubert // umask(0); 450*57e22627SCy Schubert // chdir("/"); 451*57e22627SCy Schubert #else 452*57e22627SCy Schubert // 453*57e22627SCy Schubert // This is being run as a service on Windows. 454*57e22627SCy Schubert // 455*57e22627SCy Schubert // If this call succeeds, it is blocking on Win32 456*57e22627SCy Schubert // 457*57e22627SCy Schubert if (svc_start() != 1) 458*57e22627SCy Schubert rpcapd_log(LOGPRIO_DEBUG, "Unable to start the service"); 459*57e22627SCy Schubert 460*57e22627SCy Schubert // When the previous call returns, the entire application has to be stopped. 461*57e22627SCy Schubert exit(0); 462*57e22627SCy Schubert #endif 463*57e22627SCy Schubert } 464*57e22627SCy Schubert else // Console mode 465*57e22627SCy Schubert { 466*57e22627SCy Schubert #ifndef _WIN32 467*57e22627SCy Schubert // Enable the catching of Ctrl+C 468*57e22627SCy Schubert memset(&action, 0, sizeof (action)); 469*57e22627SCy Schubert action.sa_handler = main_terminate; 470*57e22627SCy Schubert action.sa_flags = 0; 471*57e22627SCy Schubert sigemptyset(&action.sa_mask); 472*57e22627SCy Schubert sigaction(SIGINT, &action, NULL); 473*57e22627SCy Schubert 474*57e22627SCy Schubert // generated under unix with 'kill -HUP', needed to reload the configuration 475*57e22627SCy Schubert // We do not have this kind of signal in Win32 476*57e22627SCy Schubert memset(&action, 0, sizeof (action)); 477*57e22627SCy Schubert action.sa_handler = main_reread_config; 478*57e22627SCy Schubert action.sa_flags = 0; 479*57e22627SCy Schubert sigemptyset(&action.sa_mask); 480*57e22627SCy Schubert sigaction(SIGHUP, &action, NULL); 481*57e22627SCy Schubert #endif 482*57e22627SCy Schubert 483*57e22627SCy Schubert printf("Press CTRL + C to stop the server...\n"); 484*57e22627SCy Schubert } 485*57e22627SCy Schubert 486*57e22627SCy Schubert // If we're a Win32 service, we have already called this function in the service_main 487*57e22627SCy Schubert main_startup(); 488*57e22627SCy Schubert 489*57e22627SCy Schubert // The code should never arrive here (since the main_startup is blocking) 490*57e22627SCy Schubert // however this avoids a compiler warning 491*57e22627SCy Schubert exit(0); 492*57e22627SCy Schubert } 493*57e22627SCy Schubert 494*57e22627SCy Schubert void main_startup(void) 495*57e22627SCy Schubert { 496*57e22627SCy Schubert char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed 497*57e22627SCy Schubert struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket 498*57e22627SCy Schubert int i; 499*57e22627SCy Schubert #ifdef _WIN32 500*57e22627SCy Schubert HANDLE threadId; // handle for the subthread 501*57e22627SCy Schubert #else 502*57e22627SCy Schubert pid_t pid; 503*57e22627SCy Schubert #endif 504*57e22627SCy Schubert 505*57e22627SCy Schubert i = 0; 506*57e22627SCy Schubert addrinfo = NULL; 507*57e22627SCy Schubert memset(errbuf, 0, sizeof(errbuf)); 508*57e22627SCy Schubert 509*57e22627SCy Schubert // Starts all the active threads 510*57e22627SCy Schubert while ((i < MAX_ACTIVE_LIST) && (activelist[i].address[0] != 0)) 511*57e22627SCy Schubert { 512*57e22627SCy Schubert activelist[i].ai_family = mainhints.ai_family; 513*57e22627SCy Schubert 514*57e22627SCy Schubert #ifdef _WIN32 515*57e22627SCy Schubert threadId = (HANDLE)_beginthreadex(NULL, 0, main_active, 516*57e22627SCy Schubert (void *)&activelist[i], 0, NULL); 517*57e22627SCy Schubert if (threadId == 0) 518*57e22627SCy Schubert { 519*57e22627SCy Schubert rpcapd_log(LOGPRIO_DEBUG, "Error creating the active child threads"); 520*57e22627SCy Schubert continue; 521*57e22627SCy Schubert } 522*57e22627SCy Schubert CloseHandle(threadId); 523*57e22627SCy Schubert #else 524*57e22627SCy Schubert if ((pid = fork()) == 0) // I am the child 525*57e22627SCy Schubert { 526*57e22627SCy Schubert main_active((void *) &activelist[i]); 527*57e22627SCy Schubert exit(0); 528*57e22627SCy Schubert } 529*57e22627SCy Schubert #endif 530*57e22627SCy Schubert i++; 531*57e22627SCy Schubert } 532*57e22627SCy Schubert 533*57e22627SCy Schubert /* 534*57e22627SCy Schubert * The code that manages the active connections is not blocking; 535*57e22627SCy Schubert * the code that manages the passive connection is blocking. 536*57e22627SCy Schubert * So, if the user does not want to run in passive mode, we have 537*57e22627SCy Schubert * to block the main thread here, otherwise the program ends and 538*57e22627SCy Schubert * all threads are stopped. 539*57e22627SCy Schubert * 540*57e22627SCy Schubert * WARNING: this means that in case we have only active mode, 541*57e22627SCy Schubert * the program does not terminate even if all the child thread 542*57e22627SCy Schubert * terminates. The user has always to press Ctrl+C (or send a 543*57e22627SCy Schubert * SIGTERM) to terminate the program. 544*57e22627SCy Schubert */ 545*57e22627SCy Schubert if (passivemode) 546*57e22627SCy Schubert { 547*57e22627SCy Schubert struct addrinfo *tempaddrinfo; 548*57e22627SCy Schubert 549*57e22627SCy Schubert // 550*57e22627SCy Schubert // Get a list of sockets on which to listen. 551*57e22627SCy Schubert // 552*57e22627SCy Schubert if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) 553*57e22627SCy Schubert { 554*57e22627SCy Schubert rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf); 555*57e22627SCy Schubert return; 556*57e22627SCy Schubert } 557*57e22627SCy Schubert 558*57e22627SCy Schubert for (tempaddrinfo = addrinfo; tempaddrinfo; 559*57e22627SCy Schubert tempaddrinfo = tempaddrinfo->ai_next) 560*57e22627SCy Schubert { 561*57e22627SCy Schubert SOCKET sock; 562*57e22627SCy Schubert struct listen_sock *sock_info; 563*57e22627SCy Schubert 564*57e22627SCy Schubert if ((sock = sock_open(tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET) 565*57e22627SCy Schubert { 566*57e22627SCy Schubert switch (tempaddrinfo->ai_family) 567*57e22627SCy Schubert { 568*57e22627SCy Schubert case AF_INET: 569*57e22627SCy Schubert { 570*57e22627SCy Schubert struct sockaddr_in *in; 571*57e22627SCy Schubert char addrbuf[INET_ADDRSTRLEN]; 572*57e22627SCy Schubert 573*57e22627SCy Schubert in = (struct sockaddr_in *)tempaddrinfo->ai_addr; 574*57e22627SCy Schubert rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for %s:%u: %s", 575*57e22627SCy Schubert inet_ntop(AF_INET, &in->sin_addr, 576*57e22627SCy Schubert addrbuf, sizeof (addrbuf)), 577*57e22627SCy Schubert ntohs(in->sin_port), 578*57e22627SCy Schubert errbuf); 579*57e22627SCy Schubert break; 580*57e22627SCy Schubert } 581*57e22627SCy Schubert 582*57e22627SCy Schubert case AF_INET6: 583*57e22627SCy Schubert { 584*57e22627SCy Schubert struct sockaddr_in6 *in6; 585*57e22627SCy Schubert char addrbuf[INET6_ADDRSTRLEN]; 586*57e22627SCy Schubert 587*57e22627SCy Schubert in6 = (struct sockaddr_in6 *)tempaddrinfo->ai_addr; 588*57e22627SCy Schubert rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for %s:%u: %s", 589*57e22627SCy Schubert inet_ntop(AF_INET6, &in6->sin6_addr, 590*57e22627SCy Schubert addrbuf, sizeof (addrbuf)), 591*57e22627SCy Schubert ntohs(in6->sin6_port), 592*57e22627SCy Schubert errbuf); 593*57e22627SCy Schubert break; 594*57e22627SCy Schubert } 595*57e22627SCy Schubert 596*57e22627SCy Schubert default: 597*57e22627SCy Schubert rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for address family %u: %s", 598*57e22627SCy Schubert tempaddrinfo->ai_family, 599*57e22627SCy Schubert errbuf); 600*57e22627SCy Schubert break; 601*57e22627SCy Schubert } 602*57e22627SCy Schubert continue; 603*57e22627SCy Schubert } 604*57e22627SCy Schubert 605*57e22627SCy Schubert sock_info = (struct listen_sock *) malloc(sizeof (struct listen_sock)); 606*57e22627SCy Schubert if (sock_info == NULL) 607*57e22627SCy Schubert { 608*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Can't allocate structure for listen socket"); 609*57e22627SCy Schubert exit(2); 610*57e22627SCy Schubert } 611*57e22627SCy Schubert sock_info->sock = sock; 612*57e22627SCy Schubert sock_info->next = listen_socks; 613*57e22627SCy Schubert listen_socks = sock_info; 614*57e22627SCy Schubert } 615*57e22627SCy Schubert 616*57e22627SCy Schubert freeaddrinfo(addrinfo); 617*57e22627SCy Schubert 618*57e22627SCy Schubert if (listen_socks == NULL) 619*57e22627SCy Schubert { 620*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Can't listen on any address"); 621*57e22627SCy Schubert exit(2); 622*57e22627SCy Schubert } 623*57e22627SCy Schubert 624*57e22627SCy Schubert // 625*57e22627SCy Schubert // Now listen on all of them, waiting for connections. 626*57e22627SCy Schubert // 627*57e22627SCy Schubert accept_connections(); 628*57e22627SCy Schubert } 629*57e22627SCy Schubert 630*57e22627SCy Schubert // 631*57e22627SCy Schubert // We're done; exit. 632*57e22627SCy Schubert // 633*57e22627SCy Schubert rpcapd_log(LOGPRIO_DEBUG, PROGRAM_NAME " is closing.\n"); 634*57e22627SCy Schubert 635*57e22627SCy Schubert #ifndef _WIN32 636*57e22627SCy Schubert // 637*57e22627SCy Schubert // Sends a KILL signal to all the processes in this process's 638*57e22627SCy Schubert // process group; i.e., it kills all the child processes 639*57e22627SCy Schubert // we've created. 640*57e22627SCy Schubert // 641*57e22627SCy Schubert // XXX - that also includes us, so we will be killed as well; 642*57e22627SCy Schubert // that may cause a message to be printed or logged. 643*57e22627SCy Schubert // 644*57e22627SCy Schubert kill(0, SIGKILL); 645*57e22627SCy Schubert #endif 646*57e22627SCy Schubert 647*57e22627SCy Schubert // 648*57e22627SCy Schubert // Just leave. We shouldn't need to clean up sockets or 649*57e22627SCy Schubert // anything else, and if we try to do so, we'll could end 650*57e22627SCy Schubert // up closing sockets, or shutting Winsock down, out from 651*57e22627SCy Schubert // under service loops, causing all sorts of noisy error 652*57e22627SCy Schubert // messages. 653*57e22627SCy Schubert // 654*57e22627SCy Schubert // We shouldn't need to worry about cleaning up any resources 655*57e22627SCy Schubert // such as handles, sockets, threads, etc. - exit() should 656*57e22627SCy Schubert // terminate the process, causing all those resources to be 657*57e22627SCy Schubert // cleaned up (including the threads; Microsoft claims in the 658*57e22627SCy Schubert // ExitProcess() documentation that, if ExitProcess() is called, 659*57e22627SCy Schubert // "If a thread is waiting on a kernel object, it will not be 660*57e22627SCy Schubert // terminated until the wait has completed.", but claims in the 661*57e22627SCy Schubert // _beginthread()/_beginthreadex() documentation that "All threads 662*57e22627SCy Schubert // are terminated if any thread calls abort, exit, _exit, or 663*57e22627SCy Schubert // ExitProcess." - the latter appears to be the case, even for 664*57e22627SCy Schubert // threads waiting on the event for a pcap_t). 665*57e22627SCy Schubert // 666*57e22627SCy Schubert exit(0); 667*57e22627SCy Schubert } 668*57e22627SCy Schubert 669*57e22627SCy Schubert #ifdef _WIN32 670*57e22627SCy Schubert static void 671*57e22627SCy Schubert send_state_change_event(void) 672*57e22627SCy Schubert { 673*57e22627SCy Schubert char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed 674*57e22627SCy Schubert 675*57e22627SCy Schubert if (!SetEvent(state_change_event)) 676*57e22627SCy Schubert { 677*57e22627SCy Schubert sock_geterror("SetEvent on shutdown event failed", errbuf, 678*57e22627SCy Schubert PCAP_ERRBUF_SIZE); 679*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 680*57e22627SCy Schubert } 681*57e22627SCy Schubert } 682*57e22627SCy Schubert 683*57e22627SCy Schubert void 684*57e22627SCy Schubert send_shutdown_notification(void) 685*57e22627SCy Schubert { 686*57e22627SCy Schubert // 687*57e22627SCy Schubert // Indicate that the server should shut down. 688*57e22627SCy Schubert // 689*57e22627SCy Schubert shutdown_server = 1; 690*57e22627SCy Schubert 691*57e22627SCy Schubert // 692*57e22627SCy Schubert // Send a state change event, to wake up WSAWaitForMultipleEvents(). 693*57e22627SCy Schubert // 694*57e22627SCy Schubert send_state_change_event(); 695*57e22627SCy Schubert } 696*57e22627SCy Schubert 697*57e22627SCy Schubert void 698*57e22627SCy Schubert send_reread_configuration_notification(void) 699*57e22627SCy Schubert { 700*57e22627SCy Schubert // 701*57e22627SCy Schubert // Indicate that the server should re-read its configuration file. 702*57e22627SCy Schubert // 703*57e22627SCy Schubert reread_config = 1; 704*57e22627SCy Schubert 705*57e22627SCy Schubert // 706*57e22627SCy Schubert // Send a state change event, to wake up WSAWaitForMultipleEvents(). 707*57e22627SCy Schubert // 708*57e22627SCy Schubert send_state_change_event(); 709*57e22627SCy Schubert } 710*57e22627SCy Schubert 711*57e22627SCy Schubert static BOOL WINAPI main_ctrl_event(DWORD ctrltype) 712*57e22627SCy Schubert { 713*57e22627SCy Schubert // 714*57e22627SCy Schubert // ctrltype is one of: 715*57e22627SCy Schubert // 716*57e22627SCy Schubert // CTRL_C_EVENT - we got a ^C; this is like SIGINT 717*57e22627SCy Schubert // CTRL_BREAK_EVENT - we got Ctrl+Break 718*57e22627SCy Schubert // CTRL_CLOSE_EVENT - the console was closed; this is like SIGHUP 719*57e22627SCy Schubert // CTRL_LOGOFF_EVENT - a user is logging off; this is received 720*57e22627SCy Schubert // only by services 721*57e22627SCy Schubert // CTRL_SHUTDOWN_EVENT - the systemis shutting down; this is 722*57e22627SCy Schubert // received only by services 723*57e22627SCy Schubert // 724*57e22627SCy Schubert // For now, we treat all but CTRL_LOGOFF_EVENT as indications 725*57e22627SCy Schubert // that we should shut down. 726*57e22627SCy Schubert // 727*57e22627SCy Schubert switch (ctrltype) 728*57e22627SCy Schubert { 729*57e22627SCy Schubert case CTRL_C_EVENT: 730*57e22627SCy Schubert case CTRL_BREAK_EVENT: 731*57e22627SCy Schubert case CTRL_CLOSE_EVENT: 732*57e22627SCy Schubert case CTRL_SHUTDOWN_EVENT: 733*57e22627SCy Schubert // 734*57e22627SCy Schubert // Set a shutdown notification. 735*57e22627SCy Schubert // 736*57e22627SCy Schubert send_shutdown_notification(); 737*57e22627SCy Schubert break; 738*57e22627SCy Schubert 739*57e22627SCy Schubert default: 740*57e22627SCy Schubert break; 741*57e22627SCy Schubert } 742*57e22627SCy Schubert 743*57e22627SCy Schubert // 744*57e22627SCy Schubert // We handled this. 745*57e22627SCy Schubert // 746*57e22627SCy Schubert return TRUE; 747*57e22627SCy Schubert } 748*57e22627SCy Schubert #else 749*57e22627SCy Schubert static void main_terminate(int sign _U_) 750*57e22627SCy Schubert { 751*57e22627SCy Schubert // 752*57e22627SCy Schubert // Note that the server should shut down. 753*57e22627SCy Schubert // select() should get an EINTR error when we return, 754*57e22627SCy Schubert // so it will wake up and know it needs to check the flag. 755*57e22627SCy Schubert // 756*57e22627SCy Schubert shutdown_server = 1; 757*57e22627SCy Schubert } 758*57e22627SCy Schubert 759*57e22627SCy Schubert static void main_reread_config(int sign _U_) 760*57e22627SCy Schubert { 761*57e22627SCy Schubert // 762*57e22627SCy Schubert // Note that the server should re-read its configuration file. 763*57e22627SCy Schubert // select() should get an EINTR error when we return, 764*57e22627SCy Schubert // so it will wake up and know it needs to check the flag. 765*57e22627SCy Schubert // 766*57e22627SCy Schubert reread_config = 1; 767*57e22627SCy Schubert } 768*57e22627SCy Schubert 769*57e22627SCy Schubert static void main_reap_children(int sign _U_) 770*57e22627SCy Schubert { 771*57e22627SCy Schubert pid_t pid; 772*57e22627SCy Schubert int exitstat; 773*57e22627SCy Schubert 774*57e22627SCy Schubert // Reap all child processes that have exited. 775*57e22627SCy Schubert // For reference, Stevens, pg 128 776*57e22627SCy Schubert 777*57e22627SCy Schubert while ((pid = waitpid(-1, &exitstat, WNOHANG)) > 0) 778*57e22627SCy Schubert rpcapd_log(LOGPRIO_DEBUG, "Child terminated"); 779*57e22627SCy Schubert 780*57e22627SCy Schubert return; 781*57e22627SCy Schubert } 782*57e22627SCy Schubert #endif 783*57e22627SCy Schubert 784*57e22627SCy Schubert // 785*57e22627SCy Schubert // Loop waiting for incoming connections and accepting them. 786*57e22627SCy Schubert // 787*57e22627SCy Schubert static void 788*57e22627SCy Schubert accept_connections(void) 789*57e22627SCy Schubert { 790*57e22627SCy Schubert #ifdef _WIN32 791*57e22627SCy Schubert struct listen_sock *sock_info; 792*57e22627SCy Schubert DWORD num_events; 793*57e22627SCy Schubert WSAEVENT *events; 794*57e22627SCy Schubert int i; 795*57e22627SCy Schubert char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed 796*57e22627SCy Schubert 797*57e22627SCy Schubert // 798*57e22627SCy Schubert // How big does the set of events need to be? 799*57e22627SCy Schubert // One for the shutdown event, plus one for every socket on which 800*57e22627SCy Schubert // we'll be listening. 801*57e22627SCy Schubert // 802*57e22627SCy Schubert num_events = 1; // shutdown event 803*57e22627SCy Schubert for (sock_info = listen_socks; sock_info; 804*57e22627SCy Schubert sock_info = sock_info->next) 805*57e22627SCy Schubert { 806*57e22627SCy Schubert if (num_events == WSA_MAXIMUM_WAIT_EVENTS) 807*57e22627SCy Schubert { 808*57e22627SCy Schubert // 809*57e22627SCy Schubert // WSAWaitForMultipleEvents() doesn't support 810*57e22627SCy Schubert // more than WSA_MAXIMUM_WAIT_EVENTS events 811*57e22627SCy Schubert // on which to wait. 812*57e22627SCy Schubert // 813*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Too many sockets on which to listen"); 814*57e22627SCy Schubert exit(2); 815*57e22627SCy Schubert } 816*57e22627SCy Schubert num_events++; 817*57e22627SCy Schubert } 818*57e22627SCy Schubert 819*57e22627SCy Schubert // 820*57e22627SCy Schubert // Allocate the array of events. 821*57e22627SCy Schubert // 822*57e22627SCy Schubert events = (WSAEVENT *) malloc(num_events * sizeof (WSAEVENT)); 823*57e22627SCy Schubert if (events == NULL) 824*57e22627SCy Schubert { 825*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Can't allocate array of events which to listen"); 826*57e22627SCy Schubert exit(2); 827*57e22627SCy Schubert } 828*57e22627SCy Schubert 829*57e22627SCy Schubert // 830*57e22627SCy Schubert // Fill it in. 831*57e22627SCy Schubert // 832*57e22627SCy Schubert events[0] = state_change_event; // state change event first 833*57e22627SCy Schubert for (sock_info = listen_socks, i = 1; sock_info; 834*57e22627SCy Schubert sock_info = sock_info->next, i++) 835*57e22627SCy Schubert { 836*57e22627SCy Schubert WSAEVENT event; 837*57e22627SCy Schubert 838*57e22627SCy Schubert // 839*57e22627SCy Schubert // Create an event that is signaled if there's a connection 840*57e22627SCy Schubert // to accept on the socket in question. 841*57e22627SCy Schubert // 842*57e22627SCy Schubert event = WSACreateEvent(); 843*57e22627SCy Schubert if (event == WSA_INVALID_EVENT) 844*57e22627SCy Schubert { 845*57e22627SCy Schubert sock_geterror("Can't create socket event", errbuf, 846*57e22627SCy Schubert PCAP_ERRBUF_SIZE); 847*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 848*57e22627SCy Schubert exit(2); 849*57e22627SCy Schubert } 850*57e22627SCy Schubert if (WSAEventSelect(sock_info->sock, event, FD_ACCEPT) == SOCKET_ERROR) 851*57e22627SCy Schubert { 852*57e22627SCy Schubert sock_geterror("Can't setup socket event", errbuf, 853*57e22627SCy Schubert PCAP_ERRBUF_SIZE); 854*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 855*57e22627SCy Schubert exit(2); 856*57e22627SCy Schubert } 857*57e22627SCy Schubert events[i] = event; 858*57e22627SCy Schubert } 859*57e22627SCy Schubert 860*57e22627SCy Schubert for (;;) 861*57e22627SCy Schubert { 862*57e22627SCy Schubert // 863*57e22627SCy Schubert // Wait for incoming connections. 864*57e22627SCy Schubert // 865*57e22627SCy Schubert DWORD ret; 866*57e22627SCy Schubert 867*57e22627SCy Schubert ret = WSAWaitForMultipleEvents(num_events, events, FALSE, 868*57e22627SCy Schubert WSA_INFINITE, FALSE); 869*57e22627SCy Schubert if (ret == WSA_WAIT_FAILED) 870*57e22627SCy Schubert { 871*57e22627SCy Schubert sock_geterror("WSAWaitForMultipleEvents failed", errbuf, 872*57e22627SCy Schubert PCAP_ERRBUF_SIZE); 873*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 874*57e22627SCy Schubert exit(2); 875*57e22627SCy Schubert } 876*57e22627SCy Schubert 877*57e22627SCy Schubert if (ret == WSA_WAIT_EVENT_0) 878*57e22627SCy Schubert { 879*57e22627SCy Schubert // 880*57e22627SCy Schubert // The state change event was set. 881*57e22627SCy Schubert // 882*57e22627SCy Schubert if (shutdown_server) 883*57e22627SCy Schubert { 884*57e22627SCy Schubert // 885*57e22627SCy Schubert // Time to quit. Exit the loop. 886*57e22627SCy Schubert // 887*57e22627SCy Schubert break; 888*57e22627SCy Schubert } 889*57e22627SCy Schubert if (reread_config) 890*57e22627SCy Schubert { 891*57e22627SCy Schubert // 892*57e22627SCy Schubert // We should re-read the configuration 893*57e22627SCy Schubert // file. 894*57e22627SCy Schubert // 895*57e22627SCy Schubert reread_config = 0; // clear the indicator 896*57e22627SCy Schubert fileconf_read(); 897*57e22627SCy Schubert } 898*57e22627SCy Schubert } 899*57e22627SCy Schubert 900*57e22627SCy Schubert // 901*57e22627SCy Schubert // Check each socket. 902*57e22627SCy Schubert // 903*57e22627SCy Schubert for (sock_info = listen_socks, i = 1; sock_info; 904*57e22627SCy Schubert sock_info = sock_info->next, i++) 905*57e22627SCy Schubert { 906*57e22627SCy Schubert WSANETWORKEVENTS network_events; 907*57e22627SCy Schubert 908*57e22627SCy Schubert if (WSAEnumNetworkEvents(sock_info->sock, 909*57e22627SCy Schubert events[i], &network_events) == SOCKET_ERROR) 910*57e22627SCy Schubert { 911*57e22627SCy Schubert sock_geterror("WSAEnumNetworkEvents failed", 912*57e22627SCy Schubert errbuf, PCAP_ERRBUF_SIZE); 913*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 914*57e22627SCy Schubert exit(2); 915*57e22627SCy Schubert } 916*57e22627SCy Schubert if (network_events.lNetworkEvents & FD_ACCEPT) 917*57e22627SCy Schubert { 918*57e22627SCy Schubert // 919*57e22627SCy Schubert // Did an error occur? 920*57e22627SCy Schubert // 921*57e22627SCy Schubert if (network_events.iErrorCode[FD_ACCEPT_BIT] != 0) 922*57e22627SCy Schubert { 923*57e22627SCy Schubert // 924*57e22627SCy Schubert // Yes - report it and keep going. 925*57e22627SCy Schubert // 926*57e22627SCy Schubert sock_fmterror("Socket error", 927*57e22627SCy Schubert network_events.iErrorCode[FD_ACCEPT_BIT], 928*57e22627SCy Schubert errbuf, 929*57e22627SCy Schubert PCAP_ERRBUF_SIZE); 930*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 931*57e22627SCy Schubert continue; 932*57e22627SCy Schubert } 933*57e22627SCy Schubert 934*57e22627SCy Schubert // 935*57e22627SCy Schubert // Accept the connection. 936*57e22627SCy Schubert // 937*57e22627SCy Schubert accept_connection(sock_info->sock); 938*57e22627SCy Schubert } 939*57e22627SCy Schubert } 940*57e22627SCy Schubert } 941*57e22627SCy Schubert #else 942*57e22627SCy Schubert struct listen_sock *sock_info; 943*57e22627SCy Schubert int num_sock_fds; 944*57e22627SCy Schubert 945*57e22627SCy Schubert // 946*57e22627SCy Schubert // How big does the bitset of sockets on which to select() have 947*57e22627SCy Schubert // to be? 948*57e22627SCy Schubert // 949*57e22627SCy Schubert num_sock_fds = 0; 950*57e22627SCy Schubert for (sock_info = listen_socks; sock_info; sock_info = sock_info->next) 951*57e22627SCy Schubert { 952*57e22627SCy Schubert if (sock_info->sock + 1 > num_sock_fds) 953*57e22627SCy Schubert { 954*57e22627SCy Schubert if ((unsigned int)(sock_info->sock + 1) > 955*57e22627SCy Schubert (unsigned int)FD_SETSIZE) 956*57e22627SCy Schubert { 957*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Socket FD is too bit for an fd_set"); 958*57e22627SCy Schubert exit(2); 959*57e22627SCy Schubert } 960*57e22627SCy Schubert num_sock_fds = sock_info->sock + 1; 961*57e22627SCy Schubert } 962*57e22627SCy Schubert } 963*57e22627SCy Schubert 964*57e22627SCy Schubert for (;;) 965*57e22627SCy Schubert { 966*57e22627SCy Schubert fd_set sock_fds; 967*57e22627SCy Schubert int ret; 968*57e22627SCy Schubert 969*57e22627SCy Schubert // 970*57e22627SCy Schubert // Set up an fd_set for all the sockets on which we're 971*57e22627SCy Schubert // listening. 972*57e22627SCy Schubert // 973*57e22627SCy Schubert // This set is modified by select(), so we have to 974*57e22627SCy Schubert // construct it anew each time. 975*57e22627SCy Schubert // 976*57e22627SCy Schubert FD_ZERO(&sock_fds); 977*57e22627SCy Schubert for (sock_info = listen_socks; sock_info; 978*57e22627SCy Schubert sock_info = sock_info->next) 979*57e22627SCy Schubert { 980*57e22627SCy Schubert FD_SET(sock_info->sock, &sock_fds); 981*57e22627SCy Schubert } 982*57e22627SCy Schubert 983*57e22627SCy Schubert // 984*57e22627SCy Schubert // Wait for incoming connections. 985*57e22627SCy Schubert // 986*57e22627SCy Schubert ret = select(num_sock_fds, &sock_fds, NULL, NULL, NULL); 987*57e22627SCy Schubert if (ret == -1) 988*57e22627SCy Schubert { 989*57e22627SCy Schubert if (errno == EINTR) 990*57e22627SCy Schubert { 991*57e22627SCy Schubert // 992*57e22627SCy Schubert // If this is a "terminate the 993*57e22627SCy Schubert // server" signal, exit the loop, 994*57e22627SCy Schubert // otherwise just keep trying. 995*57e22627SCy Schubert // 996*57e22627SCy Schubert if (shutdown_server) 997*57e22627SCy Schubert { 998*57e22627SCy Schubert // 999*57e22627SCy Schubert // Time to quit. Exit the loop. 1000*57e22627SCy Schubert // 1001*57e22627SCy Schubert break; 1002*57e22627SCy Schubert } 1003*57e22627SCy Schubert if (reread_config) 1004*57e22627SCy Schubert { 1005*57e22627SCy Schubert // 1006*57e22627SCy Schubert // We should re-read the configuration 1007*57e22627SCy Schubert // file. 1008*57e22627SCy Schubert // 1009*57e22627SCy Schubert reread_config = 0; // clear the indicator 1010*57e22627SCy Schubert fileconf_read(); 1011*57e22627SCy Schubert } 1012*57e22627SCy Schubert 1013*57e22627SCy Schubert // 1014*57e22627SCy Schubert // Go back and wait again. 1015*57e22627SCy Schubert // 1016*57e22627SCy Schubert continue; 1017*57e22627SCy Schubert } 1018*57e22627SCy Schubert else 1019*57e22627SCy Schubert { 1020*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "select failed: %s", 1021*57e22627SCy Schubert strerror(errno)); 1022*57e22627SCy Schubert exit(2); 1023*57e22627SCy Schubert } 1024*57e22627SCy Schubert } 1025*57e22627SCy Schubert 1026*57e22627SCy Schubert // 1027*57e22627SCy Schubert // Check each socket. 1028*57e22627SCy Schubert // 1029*57e22627SCy Schubert for (sock_info = listen_socks; sock_info; 1030*57e22627SCy Schubert sock_info = sock_info->next) 1031*57e22627SCy Schubert { 1032*57e22627SCy Schubert if (FD_ISSET(sock_info->sock, &sock_fds)) 1033*57e22627SCy Schubert { 1034*57e22627SCy Schubert // 1035*57e22627SCy Schubert // Accept the connection. 1036*57e22627SCy Schubert // 1037*57e22627SCy Schubert accept_connection(sock_info->sock); 1038*57e22627SCy Schubert } 1039*57e22627SCy Schubert } 1040*57e22627SCy Schubert } 1041*57e22627SCy Schubert #endif 1042*57e22627SCy Schubert 1043*57e22627SCy Schubert // 1044*57e22627SCy Schubert // Close all the listen sockets. 1045*57e22627SCy Schubert // 1046*57e22627SCy Schubert for (sock_info = listen_socks; sock_info; sock_info = sock_info->next) 1047*57e22627SCy Schubert { 1048*57e22627SCy Schubert closesocket(sock_info->sock); 1049*57e22627SCy Schubert } 1050*57e22627SCy Schubert sock_cleanup(); 1051*57e22627SCy Schubert } 1052*57e22627SCy Schubert 1053*57e22627SCy Schubert #ifdef _WIN32 1054*57e22627SCy Schubert // 1055*57e22627SCy Schubert // A structure to hold the parameters to the daemon service loop 1056*57e22627SCy Schubert // thread on Windows. 1057*57e22627SCy Schubert // 1058*57e22627SCy Schubert // (On UN*X, there is no need for this explicit copy since the 1059*57e22627SCy Schubert // fork "inherits" the parent stack.) 1060*57e22627SCy Schubert // 1061*57e22627SCy Schubert struct params_copy { 1062*57e22627SCy Schubert SOCKET sockctrl; 1063*57e22627SCy Schubert char *hostlist; 1064*57e22627SCy Schubert }; 1065*57e22627SCy Schubert #endif 1066*57e22627SCy Schubert 1067*57e22627SCy Schubert // 1068*57e22627SCy Schubert // Accept a connection and start a worker thread, on Windows, or a 1069*57e22627SCy Schubert // worker process, on UN*X, to handle the connection. 1070*57e22627SCy Schubert // 1071*57e22627SCy Schubert static void 1072*57e22627SCy Schubert accept_connection(SOCKET listen_sock) 1073*57e22627SCy Schubert { 1074*57e22627SCy Schubert char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed 1075*57e22627SCy Schubert SOCKET sockctrl; // keeps the socket ID for this control connection 1076*57e22627SCy Schubert struct sockaddr_storage from; // generic sockaddr_storage variable 1077*57e22627SCy Schubert socklen_t fromlen; // keeps the length of the sockaddr_storage variable 1078*57e22627SCy Schubert 1079*57e22627SCy Schubert #ifdef _WIN32 1080*57e22627SCy Schubert HANDLE threadId; // handle for the subthread 1081*57e22627SCy Schubert u_long off = 0; 1082*57e22627SCy Schubert struct params_copy *params_copy = NULL; 1083*57e22627SCy Schubert #else 1084*57e22627SCy Schubert pid_t pid; 1085*57e22627SCy Schubert #endif 1086*57e22627SCy Schubert 1087*57e22627SCy Schubert // Initialize errbuf 1088*57e22627SCy Schubert memset(errbuf, 0, sizeof(errbuf)); 1089*57e22627SCy Schubert 1090*57e22627SCy Schubert for (;;) 1091*57e22627SCy Schubert { 1092*57e22627SCy Schubert // Accept the connection 1093*57e22627SCy Schubert fromlen = sizeof(struct sockaddr_storage); 1094*57e22627SCy Schubert 1095*57e22627SCy Schubert sockctrl = accept(listen_sock, (struct sockaddr *) &from, &fromlen); 1096*57e22627SCy Schubert 1097*57e22627SCy Schubert if (sockctrl != INVALID_SOCKET) 1098*57e22627SCy Schubert { 1099*57e22627SCy Schubert // Success. 1100*57e22627SCy Schubert break; 1101*57e22627SCy Schubert } 1102*57e22627SCy Schubert 1103*57e22627SCy Schubert // The accept() call can return this error when a signal is catched 1104*57e22627SCy Schubert // In this case, we have simply to ignore this error code 1105*57e22627SCy Schubert // Stevens, pg 124 1106*57e22627SCy Schubert #ifdef _WIN32 1107*57e22627SCy Schubert if (WSAGetLastError() == WSAEINTR) 1108*57e22627SCy Schubert #else 1109*57e22627SCy Schubert if (errno == EINTR) 1110*57e22627SCy Schubert #endif 1111*57e22627SCy Schubert continue; 1112*57e22627SCy Schubert 1113*57e22627SCy Schubert // Don't check for errors here, since the error can be due to the fact that the thread 1114*57e22627SCy Schubert // has been killed 1115*57e22627SCy Schubert sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE); 1116*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Accept of control connection from client failed: %s", 1117*57e22627SCy Schubert errbuf); 1118*57e22627SCy Schubert return; 1119*57e22627SCy Schubert } 1120*57e22627SCy Schubert 1121*57e22627SCy Schubert #ifdef _WIN32 1122*57e22627SCy Schubert // 1123*57e22627SCy Schubert // Put the socket back into blocking mode; doing WSAEventSelect() 1124*57e22627SCy Schubert // on the listen socket makes that socket non-blocking, and it 1125*57e22627SCy Schubert // appears that sockets returned from an accept() on that socket 1126*57e22627SCy Schubert // are also non-blocking. 1127*57e22627SCy Schubert // 1128*57e22627SCy Schubert // First, we have to un-WSAEventSelect() this socket, and then 1129*57e22627SCy Schubert // we can turn non-blocking mode off. 1130*57e22627SCy Schubert // 1131*57e22627SCy Schubert // If this fails, we aren't guaranteed that, for example, any 1132*57e22627SCy Schubert // of the error message will be sent - if it can't be put in 1133*57e22627SCy Schubert // the socket queue, the send will just fail. 1134*57e22627SCy Schubert // 1135*57e22627SCy Schubert // So we just log the message and close the connection. 1136*57e22627SCy Schubert // 1137*57e22627SCy Schubert if (WSAEventSelect(sockctrl, NULL, 0) == SOCKET_ERROR) 1138*57e22627SCy Schubert { 1139*57e22627SCy Schubert sock_geterror("WSAEventSelect()", errbuf, PCAP_ERRBUF_SIZE); 1140*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 1141*57e22627SCy Schubert sock_close(sockctrl, NULL, 0); 1142*57e22627SCy Schubert return; 1143*57e22627SCy Schubert } 1144*57e22627SCy Schubert if (ioctlsocket(sockctrl, FIONBIO, &off) == SOCKET_ERROR) 1145*57e22627SCy Schubert { 1146*57e22627SCy Schubert sock_geterror("ioctlsocket(FIONBIO)", errbuf, PCAP_ERRBUF_SIZE); 1147*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "%s", errbuf); 1148*57e22627SCy Schubert sock_close(sockctrl, NULL, 0); 1149*57e22627SCy Schubert return; 1150*57e22627SCy Schubert } 1151*57e22627SCy Schubert 1152*57e22627SCy Schubert // 1153*57e22627SCy Schubert // Make a copy of the host list to pass to the new thread, so that 1154*57e22627SCy Schubert // if we update it in the main thread, it won't catch us in the 1155*57e22627SCy Schubert // middle of updating it. 1156*57e22627SCy Schubert // 1157*57e22627SCy Schubert // daemon_serviceloop() will free it once it's done with it. 1158*57e22627SCy Schubert // 1159*57e22627SCy Schubert char *hostlist_copy = strdup(hostlist); 1160*57e22627SCy Schubert if (hostlist_copy == NULL) 1161*57e22627SCy Schubert { 1162*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list"); 1163*57e22627SCy Schubert sock_close(sockctrl, NULL, 0); 1164*57e22627SCy Schubert return; 1165*57e22627SCy Schubert } 1166*57e22627SCy Schubert 1167*57e22627SCy Schubert // 1168*57e22627SCy Schubert // Allocate a location to hold the values of sockctrl. 1169*57e22627SCy Schubert // It will be freed in the newly-created thread once it's 1170*57e22627SCy Schubert // finished with it. 1171*57e22627SCy Schubert // 1172*57e22627SCy Schubert params_copy = malloc(sizeof(*params_copy)); 1173*57e22627SCy Schubert if (params_copy == NULL) 1174*57e22627SCy Schubert { 1175*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Out of memory allocating the parameter copy structure"); 1176*57e22627SCy Schubert free(hostlist_copy); 1177*57e22627SCy Schubert sock_close(sockctrl, NULL, 0); 1178*57e22627SCy Schubert return; 1179*57e22627SCy Schubert } 1180*57e22627SCy Schubert params_copy->sockctrl = sockctrl; 1181*57e22627SCy Schubert params_copy->hostlist = hostlist_copy; 1182*57e22627SCy Schubert 1183*57e22627SCy Schubert threadId = (HANDLE)_beginthreadex(NULL, 0, 1184*57e22627SCy Schubert main_passive_serviceloop_thread, (void *) params_copy, 0, NULL); 1185*57e22627SCy Schubert if (threadId == 0) 1186*57e22627SCy Schubert { 1187*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Error creating the child thread"); 1188*57e22627SCy Schubert free(params_copy); 1189*57e22627SCy Schubert free(hostlist_copy); 1190*57e22627SCy Schubert sock_close(sockctrl, NULL, 0); 1191*57e22627SCy Schubert return; 1192*57e22627SCy Schubert } 1193*57e22627SCy Schubert CloseHandle(threadId); 1194*57e22627SCy Schubert #else /* _WIN32 */ 1195*57e22627SCy Schubert pid = fork(); 1196*57e22627SCy Schubert if (pid == -1) 1197*57e22627SCy Schubert { 1198*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Error creating the child process: %s", 1199*57e22627SCy Schubert strerror(errno)); 1200*57e22627SCy Schubert sock_close(sockctrl, NULL, 0); 1201*57e22627SCy Schubert return; 1202*57e22627SCy Schubert } 1203*57e22627SCy Schubert if (pid == 0) 1204*57e22627SCy Schubert { 1205*57e22627SCy Schubert // 1206*57e22627SCy Schubert // Child process. 1207*57e22627SCy Schubert // 1208*57e22627SCy Schubert // Close the socket on which we're listening (must 1209*57e22627SCy Schubert // be open only in the parent). 1210*57e22627SCy Schubert // 1211*57e22627SCy Schubert closesocket(listen_sock); 1212*57e22627SCy Schubert 1213*57e22627SCy Schubert #if 0 1214*57e22627SCy Schubert // 1215*57e22627SCy Schubert // Modify thread params so that it can be killed at any time 1216*57e22627SCy Schubert // XXX - is this necessary? This is the main and, currently, 1217*57e22627SCy Schubert // only thread in the child process, and nobody tries to 1218*57e22627SCy Schubert // cancel us, although *we* may cancel the thread that's 1219*57e22627SCy Schubert // handling the capture loop. 1220*57e22627SCy Schubert // 1221*57e22627SCy Schubert if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) 1222*57e22627SCy Schubert goto end; 1223*57e22627SCy Schubert if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) 1224*57e22627SCy Schubert goto end; 1225*57e22627SCy Schubert #endif 1226*57e22627SCy Schubert 1227*57e22627SCy Schubert // 1228*57e22627SCy Schubert // Run the service loop. 1229*57e22627SCy Schubert // This is passive mode, so we don't care whether we were 1230*57e22627SCy Schubert // told by the client to close. 1231*57e22627SCy Schubert // 1232*57e22627SCy Schubert char *hostlist_copy = strdup(hostlist); 1233*57e22627SCy Schubert if (hostlist_copy == NULL) 1234*57e22627SCy Schubert { 1235*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list"); 1236*57e22627SCy Schubert exit(0); 1237*57e22627SCy Schubert } 1238*57e22627SCy Schubert (void)daemon_serviceloop(sockctrl, 0, hostlist_copy, 1239*57e22627SCy Schubert nullAuthAllowed); 1240*57e22627SCy Schubert 1241*57e22627SCy Schubert exit(0); 1242*57e22627SCy Schubert } 1243*57e22627SCy Schubert 1244*57e22627SCy Schubert // I am the parent 1245*57e22627SCy Schubert // Close the socket for this session (must be open only in the child) 1246*57e22627SCy Schubert closesocket(sockctrl); 1247*57e22627SCy Schubert #endif /* _WIN32 */ 1248*57e22627SCy Schubert } 1249*57e22627SCy Schubert 1250*57e22627SCy Schubert /*! 1251*57e22627SCy Schubert \brief 'true' main of the program in case the active mode is turned on. 1252*57e22627SCy Schubert 1253*57e22627SCy Schubert This function loops forever trying to connect to the remote host, until the 1254*57e22627SCy Schubert daemon is turned down. 1255*57e22627SCy Schubert 1256*57e22627SCy Schubert \param ptr: it keeps the 'activepars' parameters. It is a 'void *' 1257*57e22627SCy Schubert just because the thread APIs want this format. 1258*57e22627SCy Schubert */ 1259*57e22627SCy Schubert #ifdef _WIN32 1260*57e22627SCy Schubert static unsigned __stdcall 1261*57e22627SCy Schubert #else 1262*57e22627SCy Schubert static void * 1263*57e22627SCy Schubert #endif 1264*57e22627SCy Schubert main_active(void *ptr) 1265*57e22627SCy Schubert { 1266*57e22627SCy Schubert char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed 1267*57e22627SCy Schubert SOCKET sockctrl; // keeps the socket ID for this control connection 1268*57e22627SCy Schubert struct addrinfo hints; // temporary struct to keep settings needed to open the new socket 1269*57e22627SCy Schubert struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket 1270*57e22627SCy Schubert struct active_pars *activepars; 1271*57e22627SCy Schubert 1272*57e22627SCy Schubert activepars = (struct active_pars *) ptr; 1273*57e22627SCy Schubert 1274*57e22627SCy Schubert // Prepare to open a new server socket 1275*57e22627SCy Schubert memset(&hints, 0, sizeof(struct addrinfo)); 1276*57e22627SCy Schubert // WARNING Currently it supports only ONE socket family among IPv4 and IPv6 1277*57e22627SCy Schubert hints.ai_family = AF_INET; // PF_UNSPEC to have both IPv4 and IPv6 server 1278*57e22627SCy Schubert hints.ai_socktype = SOCK_STREAM; 1279*57e22627SCy Schubert hints.ai_family = activepars->ai_family; 1280*57e22627SCy Schubert 1281*57e22627SCy Schubert rpcapd_log(LOGPRIO_DEBUG, "Connecting to host %s, port %s, using protocol %s", 1282*57e22627SCy Schubert activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4": 1283*57e22627SCy Schubert (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified"); 1284*57e22627SCy Schubert 1285*57e22627SCy Schubert // Initialize errbuf 1286*57e22627SCy Schubert memset(errbuf, 0, sizeof(errbuf)); 1287*57e22627SCy Schubert 1288*57e22627SCy Schubert // Do the work 1289*57e22627SCy Schubert if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) 1290*57e22627SCy Schubert { 1291*57e22627SCy Schubert rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf); 1292*57e22627SCy Schubert return 0; 1293*57e22627SCy Schubert } 1294*57e22627SCy Schubert 1295*57e22627SCy Schubert for (;;) 1296*57e22627SCy Schubert { 1297*57e22627SCy Schubert int activeclose; 1298*57e22627SCy Schubert 1299*57e22627SCy Schubert if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET) 1300*57e22627SCy Schubert { 1301*57e22627SCy Schubert rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf); 1302*57e22627SCy Schubert 1303*57e22627SCy Schubert pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s", 1304*57e22627SCy Schubert activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4": 1305*57e22627SCy Schubert (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified"); 1306*57e22627SCy Schubert 1307*57e22627SCy Schubert rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf); 1308*57e22627SCy Schubert 1309*57e22627SCy Schubert sleep_secs(RPCAP_ACTIVE_WAIT); 1310*57e22627SCy Schubert 1311*57e22627SCy Schubert continue; 1312*57e22627SCy Schubert } 1313*57e22627SCy Schubert 1314*57e22627SCy Schubert char *hostlist_copy = strdup(hostlist); 1315*57e22627SCy Schubert if (hostlist_copy == NULL) 1316*57e22627SCy Schubert { 1317*57e22627SCy Schubert rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list"); 1318*57e22627SCy Schubert activeclose = 0; 1319*57e22627SCy Schubert sock_close(sockctrl, NULL, 0); 1320*57e22627SCy Schubert } 1321*57e22627SCy Schubert else 1322*57e22627SCy Schubert { 1323*57e22627SCy Schubert // 1324*57e22627SCy Schubert // daemon_serviceloop() will free the copy. 1325*57e22627SCy Schubert // 1326*57e22627SCy Schubert activeclose = daemon_serviceloop(sockctrl, 1, 1327*57e22627SCy Schubert hostlist_copy, nullAuthAllowed); 1328*57e22627SCy Schubert } 1329*57e22627SCy Schubert 1330*57e22627SCy Schubert // If the connection is closed by the user explicitely, don't try to connect to it again 1331*57e22627SCy Schubert // just exit the program 1332*57e22627SCy Schubert if (activeclose == 1) 1333*57e22627SCy Schubert break; 1334*57e22627SCy Schubert } 1335*57e22627SCy Schubert 1336*57e22627SCy Schubert freeaddrinfo(addrinfo); 1337*57e22627SCy Schubert return 0; 1338*57e22627SCy Schubert } 1339*57e22627SCy Schubert 1340*57e22627SCy Schubert #ifdef _WIN32 1341*57e22627SCy Schubert // 1342*57e22627SCy Schubert // Main routine of a passive-mode service thread. 1343*57e22627SCy Schubert // 1344*57e22627SCy Schubert unsigned __stdcall main_passive_serviceloop_thread(void *ptr) 1345*57e22627SCy Schubert { 1346*57e22627SCy Schubert struct params_copy params = *(struct params_copy *)ptr; 1347*57e22627SCy Schubert free(ptr); 1348*57e22627SCy Schubert 1349*57e22627SCy Schubert // 1350*57e22627SCy Schubert // Handle this client. 1351*57e22627SCy Schubert // This is passive mode, so we don't care whether we were 1352*57e22627SCy Schubert // told by the client to close. 1353*57e22627SCy Schubert // 1354*57e22627SCy Schubert (void)daemon_serviceloop(params.sockctrl, 0, params.hostlist, 1355*57e22627SCy Schubert nullAuthAllowed); 1356*57e22627SCy Schubert 1357*57e22627SCy Schubert return 0; 1358*57e22627SCy Schubert } 1359*57e22627SCy Schubert #endif 1360