xref: /freebsd/contrib/libpcap/rpcapd/rpcapd.c (revision 57e22627f9459b9dfd6043b32e02ecfcf205e176)
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