1353141Sphilip/*
2353141Sphilip * Copyright (c) 2002 - 2003
3353141Sphilip * NetGroup, Politecnico di Torino (Italy)
4353141Sphilip * All rights reserved.
5353141Sphilip *
6353141Sphilip * Redistribution and use in source and binary forms, with or without
7353141Sphilip * modification, are permitted provided that the following conditions
8353141Sphilip * are met:
9353141Sphilip *
10353141Sphilip * 1. Redistributions of source code must retain the above copyright
11353141Sphilip * notice, this list of conditions and the following disclaimer.
12353141Sphilip * 2. Redistributions in binary form must reproduce the above copyright
13353141Sphilip * notice, this list of conditions and the following disclaimer in the
14353141Sphilip * documentation and/or other materials provided with the distribution.
15353141Sphilip * 3. Neither the name of the Politecnico di Torino nor the names of its
16353141Sphilip * contributors may be used to endorse or promote products derived from
17353141Sphilip * this software without specific prior written permission.
18353141Sphilip *
19353141Sphilip * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20353141Sphilip * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21353141Sphilip * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22353141Sphilip * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23353141Sphilip * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24353141Sphilip * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25353141Sphilip * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26353141Sphilip * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27353141Sphilip * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28353141Sphilip * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29353141Sphilip * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30353141Sphilip *
31353141Sphilip */
32353141Sphilip
33353141Sphilip#ifdef HAVE_CONFIG_H
34353141Sphilip#include <config.h>
35353141Sphilip#endif
36353141Sphilip
37353141Sphilip#include "ftmacros.h"
38353141Sphilip
39353141Sphilip#include <errno.h>		// for the errno variable
40353141Sphilip#include <string.h>		// for strtok, etc
41353141Sphilip#include <stdlib.h>		// for malloc(), free(), ...
42353141Sphilip#include <pcap.h>		// for PCAP_ERRBUF_SIZE
43353141Sphilip#include <signal.h>		// for signal()
44353141Sphilip
45353141Sphilip#include "fmtutils.h"
46353141Sphilip#include "sockutils.h"		// for socket calls
47353141Sphilip#include "varattrs.h"		// for _U_
48353141Sphilip#include "portability.h"
49353141Sphilip#include "rpcapd.h"
50353141Sphilip#include "config_params.h"	// configuration file parameters
51353141Sphilip#include "fileconf.h"		// for the configuration file management
52353141Sphilip#include "rpcap-protocol.h"
53353141Sphilip#include "daemon.h"		// the true main() method of this daemon
54353141Sphilip#include "log.h"
55353141Sphilip
56353141Sphilip#ifdef _WIN32
57353141Sphilip  #include <process.h>		// for thread stuff
58353141Sphilip  #include "win32-svc.h"	// for Win32 service stuff
59353141Sphilip  #include "getopt.h"		// for getopt()-for-Windows
60353141Sphilip#else
61353141Sphilip  #include <fcntl.h>		// for open()
62353141Sphilip  #include <unistd.h>		// for exit()
63353141Sphilip  #include <sys/wait.h>		// waitpid()
64353141Sphilip#endif
65353141Sphilip
66353141Sphilip//
67353141Sphilip// Element in list of sockets on which we're listening for connections.
68353141Sphilip//
69353141Sphilipstruct listen_sock {
70353141Sphilip	struct listen_sock *next;
71353141Sphilip	SOCKET sock;
72353141Sphilip};
73353141Sphilip
74353141Sphilip// Global variables
75353141Sphilipchar hostlist[MAX_HOST_LIST + 1];		//!< Keeps the list of the hosts that are allowed to connect to this server
76353141Sphilipstruct active_pars activelist[MAX_ACTIVE_LIST];	//!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode)
77353141Sphilipint nullAuthAllowed;				//!< '1' if we permit NULL authentication, '0' otherwise
78353141Sphilipstatic struct listen_sock *listen_socks;	//!< sockets on which we listen
79353141Sphilipchar loadfile[MAX_LINE + 1];			//!< Name of the file from which we have to load the configuration
80353141Sphilipstatic int passivemode = 1;			//!< '1' if we want to run in passive mode as well
81353141Sphilipstatic struct addrinfo mainhints;		//!< temporary struct to keep settings needed to open the new socket
82353141Sphilipstatic char address[MAX_LINE + 1];		//!< keeps the network address (either numeric or literal) to bind to
83353141Sphilipstatic char port[MAX_LINE + 1];			//!< keeps the network port to bind to
84353141Sphilip#ifdef _WIN32
85353141Sphilipstatic HANDLE state_change_event;		//!< event to signal that a state change should take place
86353141Sphilip#endif
87353141Sphilipstatic volatile sig_atomic_t shutdown_server;	//!< '1' if the server is to shut down
88353141Sphilipstatic volatile sig_atomic_t reread_config;	//!< '1' if the server is to re-read its configuration
89353141Sphilip
90353141Sphilipextern char *optarg;	// for getopt()
91353141Sphilip
92353141Sphilip// Function definition
93353141Sphilip#ifdef _WIN32
94353141Sphilipstatic unsigned __stdcall main_active(void *ptr);
95353141Sphilipstatic BOOL WINAPI main_ctrl_event(DWORD);
96353141Sphilip#else
97353141Sphilipstatic void *main_active(void *ptr);
98353141Sphilipstatic void main_terminate(int sign);
99353141Sphilipstatic void main_reread_config(int sign);
100353141Sphilip#endif
101353141Sphilipstatic void accept_connections(void);
102353141Sphilipstatic void accept_connection(SOCKET listen_sock);
103353141Sphilip#ifndef _WIN32
104353141Sphilipstatic void main_reap_children(int sign);
105353141Sphilip#endif
106353141Sphilip#ifdef _WIN32
107353141Sphilipstatic unsigned __stdcall main_passive_serviceloop_thread(void *ptr);
108353141Sphilip#endif
109353141Sphilip
110353141Sphilip#define RPCAP_ACTIVE_WAIT 30		/* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */
111353141Sphilip
112353141Sphilip/*!
113353141Sphilip	\brief Prints the usage screen if it is launched in console mode.
114353141Sphilip*/
115353141Sphilipstatic void printusage(void)
116353141Sphilip{
117353141Sphilip	const char *usagetext =
118353141Sphilip	"USAGE:"
119353141Sphilip	" "  PROGRAM_NAME " [-b <address>] [-p <port>] [-4] [-l <host_list>] [-a <host,port>]\n"
120353141Sphilip	"              [-n] [-v] [-d] "
121353141Sphilip#ifndef _WIN32
122353141Sphilip	"[-i] "
123353141Sphilip#endif
124353141Sphilip        "[-D] [-s <config_file>] [-f <config_file>]\n\n"
125353141Sphilip	"  -b <address>    the address to bind to (either numeric or literal).\n"
126353141Sphilip	"                  Default: binds to all local IPv4 and IPv6 addresses\n\n"
127353141Sphilip	"  -p <port>       the port to bind to.\n"
128353141Sphilip	"                  Default: binds to port " RPCAP_DEFAULT_NETPORT "\n\n"
129353141Sphilip	"  -4              use only IPv4.\n"
130353141Sphilip	"                  Default: use both IPv4 and IPv6 waiting sockets\n\n"
131353141Sphilip	"  -l <host_list>  a file that contains a list of hosts that are allowed\n"
132353141Sphilip	"                  to connect to this server (if more than one, list them one\n"
133353141Sphilip	"                  per line).\n"
134353141Sphilip	"                  We suggest to use literal names (instead of numeric ones)\n"
135353141Sphilip	"                  in order to avoid problems with different address families.\n\n"
136353141Sphilip	"  -n              permit NULL authentication (usually used with '-l')\n\n"
137353141Sphilip	"  -a <host,port>  run in active mode when connecting to 'host' on port 'port'\n"
138353141Sphilip	"                  In case 'port' is omitted, the default port (" RPCAP_DEFAULT_NETPORT_ACTIVE ") is used\n\n"
139353141Sphilip	"  -v              run in active mode only (default: if '-a' is specified, it\n"
140353141Sphilip	"                  accepts passive connections as well)\n\n"
141353141Sphilip	"  -d              run in daemon mode (UNIX only) or as a service (Win32 only)\n"
142353141Sphilip	"                  Warning (Win32): this switch is provided automatically when\n"
143353141Sphilip	"                  the service is started from the control panel\n\n"
144353141Sphilip#ifndef _WIN32
145353141Sphilip	"  -i              run in inetd mode (UNIX only)\n\n"
146353141Sphilip#endif
147353141Sphilip	"  -D              log debugging messages\n\n"
148353141Sphilip	"  -s <config_file> save the current configuration to file\n\n"
149353141Sphilip	"  -f <config_file> load the current configuration from file; all switches\n"
150353141Sphilip	"                  specified from the command line are ignored\n\n"
151353141Sphilip	"  -h              print this help screen\n\n";
152353141Sphilip
153353141Sphilip	(void)fprintf(stderr, "RPCAPD, a remote packet capture daemon.\n"
154353141Sphilip	"Compiled with %s\n\n", pcap_lib_version());
155353141Sphilip	printf("%s", usagetext);
156353141Sphilip}
157353141Sphilip
158353141Sphilip
159353141Sphilip
160353141Sphilip//! Program main
161353141Sphilipint main(int argc, char *argv[])
162353141Sphilip{
163353141Sphilip	char savefile[MAX_LINE + 1];		// name of the file on which we have to save the configuration
164353141Sphilip	int log_to_systemlog = 0;		// Non-zero if we should log to the "system log" rather than the standard error
165353141Sphilip	int isdaemon = 0;			// Non-zero if the user wants to run this program as a daemon
166353141Sphilip#ifndef _WIN32
167353141Sphilip	int isrunbyinetd = 0;			// Non-zero if this is being run by inetd or something inetd-like
168353141Sphilip#endif
169353141Sphilip	int log_debug_messages = 0;		// Non-zero if the user wants debug messages logged
170353141Sphilip	int retval;				// keeps the returning value from several functions
171353141Sphilip	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
172353141Sphilip#ifndef _WIN32
173353141Sphilip	struct sigaction action;
174353141Sphilip#endif
175353141Sphilip
176353141Sphilip	savefile[0] = 0;
177353141Sphilip	loadfile[0] = 0;
178353141Sphilip	hostlist[0] = 0;
179353141Sphilip
180353141Sphilip	// Initialize errbuf
181353141Sphilip	memset(errbuf, 0, sizeof(errbuf));
182353141Sphilip
183353141Sphilip	strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE);
184353141Sphilip	strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE);
185353141Sphilip
186353141Sphilip	// Prepare to open a new server socket
187353141Sphilip	memset(&mainhints, 0, sizeof(struct addrinfo));
188353141Sphilip
189353141Sphilip	mainhints.ai_family = PF_UNSPEC;
190353141Sphilip	mainhints.ai_flags = AI_PASSIVE;	// Ready to a bind() socket
191353141Sphilip	mainhints.ai_socktype = SOCK_STREAM;
192353141Sphilip
193353141Sphilip	// Getting the proper command line options
194353141Sphilip	while ((retval = getopt(argc, argv, "b:dDhip:4l:na:s:f:v")) != -1)
195353141Sphilip	{
196353141Sphilip		switch (retval)
197353141Sphilip		{
198353141Sphilip			case 'D':
199353141Sphilip				log_debug_messages = 1;
200353141Sphilip				rpcapd_log_set(log_to_systemlog, log_debug_messages);
201353141Sphilip				break;
202353141Sphilip			case 'b':
203353141Sphilip				strncpy(address, optarg, MAX_LINE);
204353141Sphilip				break;
205353141Sphilip			case 'p':
206353141Sphilip				strncpy(port, optarg, MAX_LINE);
207353141Sphilip				break;
208353141Sphilip			case '4':
209353141Sphilip				mainhints.ai_family = PF_INET;		// IPv4 server only
210353141Sphilip				break;
211353141Sphilip			case 'd':
212353141Sphilip				isdaemon = 1;
213353141Sphilip				log_to_systemlog = 1;
214353141Sphilip				rpcapd_log_set(log_to_systemlog, log_debug_messages);
215353141Sphilip				break;
216353141Sphilip			case 'i':
217353141Sphilip#ifdef _WIN32
218353141Sphilip				printusage();
219353141Sphilip				exit(1);
220353141Sphilip#else
221353141Sphilip				isrunbyinetd = 1;
222353141Sphilip				log_to_systemlog = 1;
223353141Sphilip				rpcapd_log_set(log_to_systemlog, log_debug_messages);
224353141Sphilip#endif
225353141Sphilip				break;
226353141Sphilip			case 'n':
227353141Sphilip				nullAuthAllowed = 1;
228353141Sphilip				break;
229353141Sphilip			case 'v':
230353141Sphilip				passivemode = 0;
231353141Sphilip				break;
232353141Sphilip			case 'l':
233353141Sphilip			{
234353141Sphilip				strncpy(hostlist, optarg, sizeof(hostlist));
235353141Sphilip				break;
236353141Sphilip			}
237353141Sphilip			case 'a':
238353141Sphilip			{
239353141Sphilip				char *tmpaddress, *tmpport;
240353141Sphilip				char *lasts;
241353141Sphilip				int i = 0;
242353141Sphilip
243353141Sphilip				tmpaddress = pcap_strtok_r(optarg, RPCAP_HOSTLIST_SEP, &lasts);
244353141Sphilip
245353141Sphilip				while ((tmpaddress != NULL) && (i < MAX_ACTIVE_LIST))
246353141Sphilip				{
247353141Sphilip					tmpport = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
248353141Sphilip
249353141Sphilip					pcap_strlcpy(activelist[i].address, tmpaddress, MAX_LINE);
250353141Sphilip
251353141Sphilip					if ((tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0)) // the user choose a custom port
252353141Sphilip						pcap_strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE);
253353141Sphilip					else
254353141Sphilip						pcap_strlcpy(activelist[i].port, tmpport, MAX_LINE);
255353141Sphilip
256353141Sphilip					tmpaddress = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
257353141Sphilip
258353141Sphilip					i++;
259353141Sphilip				}
260353141Sphilip
261353141Sphilip				if (i > MAX_ACTIVE_LIST)
262353141Sphilip					rpcapd_log(LOGPRIO_ERROR, "Only MAX_ACTIVE_LIST active connections are currently supported.");
263353141Sphilip
264353141Sphilip				// I don't initialize the remaining part of the structure, since
265353141Sphilip				// it is already zeroed (it is a global var)
266353141Sphilip				break;
267353141Sphilip			}
268353141Sphilip			case 'f':
269353141Sphilip				pcap_strlcpy(loadfile, optarg, MAX_LINE);
270353141Sphilip				break;
271353141Sphilip			case 's':
272353141Sphilip				pcap_strlcpy(savefile, optarg, MAX_LINE);
273353141Sphilip				break;
274353141Sphilip			case 'h':
275353141Sphilip				printusage();
276353141Sphilip				exit(0);
277353141Sphilip				/*NOTREACHED*/
278353141Sphilip			default:
279353141Sphilip				exit(1);
280353141Sphilip				/*NOTREACHED*/
281353141Sphilip		}
282353141Sphilip	}
283353141Sphilip
284353141Sphilip#ifndef _WIN32
285353141Sphilip	if (isdaemon && isrunbyinetd)
286353141Sphilip	{
287353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "rpcapd: -d and -i can't be used together");
288353141Sphilip		exit(1);
289353141Sphilip	}
290353141Sphilip#endif
291353141Sphilip
292353141Sphilip	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
293353141Sphilip	{
294353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
295353141Sphilip		exit(-1);
296353141Sphilip	}
297353141Sphilip
298353141Sphilip	if (savefile[0] && fileconf_save(savefile))
299353141Sphilip		rpcapd_log(LOGPRIO_DEBUG, "Error when saving the configuration to file");
300353141Sphilip
301353141Sphilip	// If the file does not exist, it keeps the settings provided by the command line
302353141Sphilip	if (loadfile[0])
303353141Sphilip		fileconf_read();
304353141Sphilip
305353141Sphilip#ifdef WIN32
306353141Sphilip	//
307353141Sphilip	// Create a handle to signal the main loop to tell it to do
308353141Sphilip	// something.
309353141Sphilip	//
310353141Sphilip	state_change_event = CreateEvent(NULL, FALSE, FALSE, NULL);
311353141Sphilip	if (state_change_event == NULL)
312353141Sphilip	{
313353141Sphilip		sock_geterror("Can't create state change event", errbuf,
314353141Sphilip		    PCAP_ERRBUF_SIZE);
315353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
316353141Sphilip		exit(2);
317353141Sphilip	}
318353141Sphilip
319353141Sphilip	//
320353141Sphilip	// Catch control signals.
321353141Sphilip	//
322353141Sphilip	if (!SetConsoleCtrlHandler(main_ctrl_event, TRUE))
323353141Sphilip	{
324353141Sphilip		sock_geterror("Can't set control handler", errbuf,
325353141Sphilip		    PCAP_ERRBUF_SIZE);
326353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
327353141Sphilip		exit(2);
328353141Sphilip	}
329353141Sphilip#else
330353141Sphilip	memset(&action, 0, sizeof (action));
331353141Sphilip	action.sa_handler = main_terminate;
332353141Sphilip	action.sa_flags = 0;
333353141Sphilip	sigemptyset(&action.sa_mask);
334353141Sphilip	sigaction(SIGTERM, &action, NULL);
335353141Sphilip	memset(&action, 0, sizeof (action));
336353141Sphilip	action.sa_handler = main_reap_children;
337353141Sphilip	action.sa_flags = 0;
338353141Sphilip	sigemptyset(&action.sa_mask);
339353141Sphilip	sigaction(SIGCHLD, &action, NULL);
340353141Sphilip	// Ignore SIGPIPE - we'll get EPIPE when trying to write to a closed
341353141Sphilip	// connection, we don't want to get killed by a signal in that case
342353141Sphilip	signal(SIGPIPE, SIG_IGN);
343353141Sphilip#endif
344353141Sphilip
345353141Sphilip#ifndef _WIN32
346353141Sphilip	if (isrunbyinetd)
347353141Sphilip	{
348353141Sphilip		//
349353141Sphilip		// -i was specified, indicating that this is being run
350353141Sphilip		// by inetd or something that can run network daemons
351353141Sphilip		// as if it were inetd (xinetd, launchd, systemd, etc.).
352353141Sphilip		//
353353141Sphilip		// We assume that the program that launched us just
354353141Sphilip		// duplicated a single socket for the connection
355353141Sphilip		// to our standard input, output, and error, so we
356353141Sphilip		// can just use the standard input as our control
357353141Sphilip		// socket.
358353141Sphilip		//
359353141Sphilip		int sockctrl;
360353141Sphilip		int devnull_fd;
361353141Sphilip
362353141Sphilip		//
363353141Sphilip		// Duplicate the standard input as the control socket.
364353141Sphilip		//
365353141Sphilip		sockctrl = dup(0);
366353141Sphilip		if (sockctrl == -1)
367353141Sphilip		{
368353141Sphilip			sock_geterror("Can't dup standard input", errbuf,
369353141Sphilip			    PCAP_ERRBUF_SIZE);
370353141Sphilip			rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
371353141Sphilip			exit(2);
372353141Sphilip		}
373353141Sphilip
374353141Sphilip		//
375353141Sphilip		// Try to set the standard input, output, and error
376353141Sphilip		// to /dev/null.
377353141Sphilip		//
378353141Sphilip		devnull_fd = open("/dev/null", O_RDWR);
379353141Sphilip		if (devnull_fd != -1)
380353141Sphilip		{
381353141Sphilip			//
382353141Sphilip			// If this fails, just drive on.
383353141Sphilip			//
384353141Sphilip			(void)dup2(devnull_fd, 0);
385353141Sphilip			(void)dup2(devnull_fd, 1);
386353141Sphilip			(void)dup2(devnull_fd, 2);
387353141Sphilip			close(devnull_fd);
388353141Sphilip		}
389353141Sphilip
390353141Sphilip		//
391353141Sphilip		// Handle this client.
392353141Sphilip		// This is passive mode, so we don't care whether we were
393353141Sphilip		// told by the client to close.
394353141Sphilip		//
395353141Sphilip		char *hostlist_copy = strdup(hostlist);
396353141Sphilip		if (hostlist_copy == NULL)
397353141Sphilip		{
398353141Sphilip			rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
399353141Sphilip			exit(0);
400353141Sphilip		}
401353141Sphilip		(void)daemon_serviceloop(sockctrl, 0, hostlist_copy,
402353141Sphilip		    nullAuthAllowed);
403353141Sphilip
404353141Sphilip		//
405353141Sphilip		// Nothing more to do.
406353141Sphilip		//
407353141Sphilip		exit(0);
408353141Sphilip	}
409353141Sphilip#endif
410353141Sphilip
411353141Sphilip	if (isdaemon)
412353141Sphilip	{
413353141Sphilip		//
414353141Sphilip		// This is being run as a daemon.
415353141Sphilip		// On UN*X, it might be manually run, or run from an
416353141Sphilip		// rc file.
417353141Sphilip		//
418353141Sphilip#ifndef _WIN32
419353141Sphilip		int pid;
420353141Sphilip
421353141Sphilip		//
422353141Sphilip		// Daemonize ourselves.
423353141Sphilip		//
424353141Sphilip		// Unix Network Programming, pg 336
425353141Sphilip		//
426353141Sphilip		if ((pid = fork()) != 0)
427353141Sphilip			exit(0);		// Parent terminates
428353141Sphilip
429353141Sphilip		// First child continues
430353141Sphilip		// Set daemon mode
431353141Sphilip		setsid();
432353141Sphilip
433353141Sphilip		// generated under unix with 'kill -HUP', needed to reload the configuration
434353141Sphilip		memset(&action, 0, sizeof (action));
435353141Sphilip		action.sa_handler = main_reread_config;
436353141Sphilip		action.sa_flags = 0;
437353141Sphilip		sigemptyset(&action.sa_mask);
438353141Sphilip		sigaction(SIGHUP, &action, NULL);
439353141Sphilip
440353141Sphilip		if ((pid = fork()) != 0)
441353141Sphilip			exit(0);		// First child terminates
442353141Sphilip
443353141Sphilip		// LINUX WARNING: the current linux implementation of pthreads requires a management thread
444353141Sphilip		// to handle some hidden stuff. So, as soon as you create the first thread, two threads are
445353141Sphilip		// created. Fom this point on, the number of threads active are always one more compared
446353141Sphilip		// to the number you're expecting
447353141Sphilip
448353141Sphilip		// Second child continues
449353141Sphilip//		umask(0);
450353141Sphilip//		chdir("/");
451353141Sphilip#else
452353141Sphilip		//
453353141Sphilip		// This is being run as a service on Windows.
454353141Sphilip		//
455353141Sphilip		// If this call succeeds, it is blocking on Win32
456353141Sphilip		//
457353141Sphilip		if (svc_start() != 1)
458353141Sphilip			rpcapd_log(LOGPRIO_DEBUG, "Unable to start the service");
459353141Sphilip
460353141Sphilip		// When the previous call returns, the entire application has to be stopped.
461353141Sphilip		exit(0);
462353141Sphilip#endif
463353141Sphilip	}
464353141Sphilip	else	// Console mode
465353141Sphilip	{
466353141Sphilip#ifndef _WIN32
467353141Sphilip		// Enable the catching of Ctrl+C
468353141Sphilip		memset(&action, 0, sizeof (action));
469353141Sphilip		action.sa_handler = main_terminate;
470353141Sphilip		action.sa_flags = 0;
471353141Sphilip		sigemptyset(&action.sa_mask);
472353141Sphilip		sigaction(SIGINT, &action, NULL);
473353141Sphilip
474353141Sphilip		// generated under unix with 'kill -HUP', needed to reload the configuration
475353141Sphilip		// We do not have this kind of signal in Win32
476353141Sphilip		memset(&action, 0, sizeof (action));
477353141Sphilip		action.sa_handler = main_reread_config;
478353141Sphilip		action.sa_flags = 0;
479353141Sphilip		sigemptyset(&action.sa_mask);
480353141Sphilip		sigaction(SIGHUP, &action, NULL);
481353141Sphilip#endif
482353141Sphilip
483353141Sphilip		printf("Press CTRL + C to stop the server...\n");
484353141Sphilip	}
485353141Sphilip
486353141Sphilip	// If we're a Win32 service, we have already called this function in the service_main
487353141Sphilip	main_startup();
488353141Sphilip
489353141Sphilip	// The code should never arrive here (since the main_startup is blocking)
490353141Sphilip	//  however this avoids a compiler warning
491353141Sphilip	exit(0);
492353141Sphilip}
493353141Sphilip
494353141Sphilipvoid main_startup(void)
495353141Sphilip{
496353141Sphilip	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
497353141Sphilip	struct addrinfo *addrinfo;		// keeps the addrinfo chain; required to open a new socket
498353141Sphilip	int i;
499353141Sphilip#ifdef _WIN32
500353141Sphilip	HANDLE threadId;			// handle for the subthread
501353141Sphilip#else
502353141Sphilip	pid_t pid;
503353141Sphilip#endif
504353141Sphilip
505353141Sphilip	i = 0;
506353141Sphilip	addrinfo = NULL;
507353141Sphilip	memset(errbuf, 0, sizeof(errbuf));
508353141Sphilip
509353141Sphilip	// Starts all the active threads
510353141Sphilip	while ((i < MAX_ACTIVE_LIST) && (activelist[i].address[0] != 0))
511353141Sphilip	{
512353141Sphilip		activelist[i].ai_family = mainhints.ai_family;
513353141Sphilip
514353141Sphilip#ifdef _WIN32
515353141Sphilip		threadId = (HANDLE)_beginthreadex(NULL, 0, main_active,
516353141Sphilip		    (void *)&activelist[i], 0, NULL);
517353141Sphilip		if (threadId == 0)
518353141Sphilip		{
519353141Sphilip			rpcapd_log(LOGPRIO_DEBUG, "Error creating the active child threads");
520353141Sphilip			continue;
521353141Sphilip		}
522353141Sphilip		CloseHandle(threadId);
523353141Sphilip#else
524353141Sphilip		if ((pid = fork()) == 0)	// I am the child
525353141Sphilip		{
526353141Sphilip			main_active((void *) &activelist[i]);
527353141Sphilip			exit(0);
528353141Sphilip		}
529353141Sphilip#endif
530353141Sphilip		i++;
531353141Sphilip	}
532353141Sphilip
533353141Sphilip	/*
534353141Sphilip	 * The code that manages the active connections is not blocking;
535353141Sphilip	 * the code that manages the passive connection is blocking.
536353141Sphilip	 * So, if the user does not want to run in passive mode, we have
537353141Sphilip	 * to block the main thread here, otherwise the program ends and
538353141Sphilip	 * all threads are stopped.
539353141Sphilip	 *
540353141Sphilip	 * WARNING: this means that in case we have only active mode,
541353141Sphilip	 * the program does not terminate even if all the child thread
542353141Sphilip	 * terminates. The user has always to press Ctrl+C (or send a
543353141Sphilip	 * SIGTERM) to terminate the program.
544353141Sphilip	 */
545353141Sphilip	if (passivemode)
546353141Sphilip	{
547353141Sphilip		struct addrinfo *tempaddrinfo;
548353141Sphilip
549353141Sphilip		//
550353141Sphilip		// Get a list of sockets on which to listen.
551353141Sphilip		//
552353141Sphilip		if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
553353141Sphilip		{
554353141Sphilip			rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
555353141Sphilip			return;
556353141Sphilip		}
557353141Sphilip
558353141Sphilip		for (tempaddrinfo = addrinfo; tempaddrinfo;
559353141Sphilip		     tempaddrinfo = tempaddrinfo->ai_next)
560353141Sphilip		{
561353141Sphilip			SOCKET sock;
562353141Sphilip			struct listen_sock *sock_info;
563353141Sphilip
564353141Sphilip			if ((sock = sock_open(tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
565353141Sphilip			{
566353141Sphilip				switch (tempaddrinfo->ai_family)
567353141Sphilip				{
568353141Sphilip				case AF_INET:
569353141Sphilip				{
570353141Sphilip					struct sockaddr_in *in;
571353141Sphilip					char addrbuf[INET_ADDRSTRLEN];
572353141Sphilip
573353141Sphilip					in = (struct sockaddr_in *)tempaddrinfo->ai_addr;
574353141Sphilip					rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for %s:%u: %s",
575353141Sphilip					    inet_ntop(AF_INET, &in->sin_addr,
576353141Sphilip						addrbuf, sizeof (addrbuf)),
577353141Sphilip					    ntohs(in->sin_port),
578353141Sphilip					    errbuf);
579353141Sphilip					break;
580353141Sphilip				}
581353141Sphilip
582353141Sphilip				case AF_INET6:
583353141Sphilip				{
584353141Sphilip					struct sockaddr_in6 *in6;
585353141Sphilip					char addrbuf[INET6_ADDRSTRLEN];
586353141Sphilip
587353141Sphilip					in6 = (struct sockaddr_in6 *)tempaddrinfo->ai_addr;
588353141Sphilip					rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for %s:%u: %s",
589353141Sphilip					    inet_ntop(AF_INET6, &in6->sin6_addr,
590353141Sphilip						addrbuf, sizeof (addrbuf)),
591353141Sphilip					    ntohs(in6->sin6_port),
592353141Sphilip					    errbuf);
593353141Sphilip					break;
594353141Sphilip				}
595353141Sphilip
596353141Sphilip				default:
597353141Sphilip					rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for address family %u: %s",
598353141Sphilip					    tempaddrinfo->ai_family,
599353141Sphilip					    errbuf);
600353141Sphilip					break;
601353141Sphilip				}
602353141Sphilip				continue;
603353141Sphilip			}
604353141Sphilip
605353141Sphilip			sock_info = (struct listen_sock *) malloc(sizeof (struct listen_sock));
606353141Sphilip			if (sock_info == NULL)
607353141Sphilip			{
608353141Sphilip				rpcapd_log(LOGPRIO_ERROR, "Can't allocate structure for listen socket");
609353141Sphilip				exit(2);
610353141Sphilip			}
611353141Sphilip			sock_info->sock = sock;
612353141Sphilip			sock_info->next = listen_socks;
613353141Sphilip			listen_socks = sock_info;
614353141Sphilip		}
615353141Sphilip
616353141Sphilip		freeaddrinfo(addrinfo);
617353141Sphilip
618353141Sphilip		if (listen_socks == NULL)
619353141Sphilip		{
620353141Sphilip			rpcapd_log(LOGPRIO_ERROR, "Can't listen on any address");
621353141Sphilip			exit(2);
622353141Sphilip		}
623353141Sphilip
624353141Sphilip		//
625353141Sphilip		// Now listen on all of them, waiting for connections.
626353141Sphilip		//
627353141Sphilip		accept_connections();
628353141Sphilip	}
629353141Sphilip
630353141Sphilip	//
631353141Sphilip	// We're done; exit.
632353141Sphilip	//
633353141Sphilip	rpcapd_log(LOGPRIO_DEBUG, PROGRAM_NAME " is closing.\n");
634353141Sphilip
635353141Sphilip#ifndef _WIN32
636353141Sphilip	//
637353141Sphilip	// Sends a KILL signal to all the processes in this process's
638353141Sphilip	// process group; i.e., it kills all the child processes
639353141Sphilip	// we've created.
640353141Sphilip	//
641353141Sphilip	// XXX - that also includes us, so we will be killed as well;
642353141Sphilip	// that may cause a message to be printed or logged.
643353141Sphilip	//
644353141Sphilip	kill(0, SIGKILL);
645353141Sphilip#endif
646353141Sphilip
647353141Sphilip	//
648353141Sphilip	// Just leave.  We shouldn't need to clean up sockets or
649353141Sphilip	// anything else, and if we try to do so, we'll could end
650353141Sphilip	// up closing sockets, or shutting Winsock down, out from
651353141Sphilip	// under service loops, causing all sorts of noisy error
652353141Sphilip	// messages.
653353141Sphilip	//
654353141Sphilip	// We shouldn't need to worry about cleaning up any resources
655353141Sphilip	// such as handles, sockets, threads, etc. - exit() should
656353141Sphilip	// terminate the process, causing all those resources to be
657353141Sphilip	// cleaned up (including the threads; Microsoft claims in the
658353141Sphilip	// ExitProcess() documentation that, if ExitProcess() is called,
659353141Sphilip	// "If a thread is waiting on a kernel object, it will not be
660353141Sphilip	// terminated until the wait has completed.", but claims in the
661353141Sphilip	// _beginthread()/_beginthreadex() documentation that "All threads
662353141Sphilip	// are terminated if any thread calls abort, exit, _exit, or
663353141Sphilip	// ExitProcess." - the latter appears to be the case, even for
664353141Sphilip	// threads waiting on the event for a pcap_t).
665353141Sphilip	//
666353141Sphilip	exit(0);
667353141Sphilip}
668353141Sphilip
669353141Sphilip#ifdef _WIN32
670353141Sphilipstatic void
671353141Sphilipsend_state_change_event(void)
672353141Sphilip{
673353141Sphilip	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
674353141Sphilip
675353141Sphilip	if (!SetEvent(state_change_event))
676353141Sphilip	{
677353141Sphilip		sock_geterror("SetEvent on shutdown event failed", errbuf,
678353141Sphilip		    PCAP_ERRBUF_SIZE);
679353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
680353141Sphilip	}
681353141Sphilip}
682353141Sphilip
683353141Sphilipvoid
684353141Sphilipsend_shutdown_notification(void)
685353141Sphilip{
686353141Sphilip	//
687353141Sphilip	// Indicate that the server should shut down.
688353141Sphilip	//
689353141Sphilip	shutdown_server = 1;
690353141Sphilip
691353141Sphilip	//
692353141Sphilip	// Send a state change event, to wake up WSAWaitForMultipleEvents().
693353141Sphilip	//
694353141Sphilip	send_state_change_event();
695353141Sphilip}
696353141Sphilip
697353141Sphilipvoid
698353141Sphilipsend_reread_configuration_notification(void)
699353141Sphilip{
700353141Sphilip	//
701353141Sphilip	// Indicate that the server should re-read its configuration file.
702353141Sphilip	//
703353141Sphilip	reread_config = 1;
704353141Sphilip
705353141Sphilip	//
706353141Sphilip	// Send a state change event, to wake up WSAWaitForMultipleEvents().
707353141Sphilip	//
708353141Sphilip	send_state_change_event();
709353141Sphilip}
710353141Sphilip
711353141Sphilipstatic BOOL WINAPI main_ctrl_event(DWORD ctrltype)
712353141Sphilip{
713353141Sphilip	//
714353141Sphilip	// ctrltype is one of:
715353141Sphilip	//
716353141Sphilip	// CTRL_C_EVENT - we got a ^C; this is like SIGINT
717353141Sphilip	// CTRL_BREAK_EVENT - we got Ctrl+Break
718353141Sphilip	// CTRL_CLOSE_EVENT - the console was closed; this is like SIGHUP
719353141Sphilip	// CTRL_LOGOFF_EVENT - a user is logging off; this is received
720353141Sphilip	//   only by services
721353141Sphilip	// CTRL_SHUTDOWN_EVENT - the systemis shutting down; this is
722353141Sphilip	//   received only by services
723353141Sphilip	//
724353141Sphilip	// For now, we treat all but CTRL_LOGOFF_EVENT as indications
725353141Sphilip	// that we should shut down.
726353141Sphilip	//
727353141Sphilip	switch (ctrltype)
728353141Sphilip	{
729353141Sphilip		case CTRL_C_EVENT:
730353141Sphilip		case CTRL_BREAK_EVENT:
731353141Sphilip		case CTRL_CLOSE_EVENT:
732353141Sphilip		case CTRL_SHUTDOWN_EVENT:
733353141Sphilip			//
734353141Sphilip			// Set a shutdown notification.
735353141Sphilip			//
736353141Sphilip			send_shutdown_notification();
737353141Sphilip			break;
738353141Sphilip
739353141Sphilip		default:
740353141Sphilip			break;
741353141Sphilip	}
742353141Sphilip
743353141Sphilip	//
744353141Sphilip	// We handled this.
745353141Sphilip	//
746353141Sphilip	return TRUE;
747353141Sphilip}
748353141Sphilip#else
749353141Sphilipstatic void main_terminate(int sign _U_)
750353141Sphilip{
751353141Sphilip	//
752353141Sphilip	// Note that the server should shut down.
753353141Sphilip	// select() should get an EINTR error when we return,
754353141Sphilip	// so it will wake up and know it needs to check the flag.
755353141Sphilip	//
756353141Sphilip	shutdown_server = 1;
757353141Sphilip}
758353141Sphilip
759353141Sphilipstatic void main_reread_config(int sign _U_)
760353141Sphilip{
761353141Sphilip	//
762353141Sphilip	// Note that the server should re-read its configuration file.
763353141Sphilip	// select() should get an EINTR error when we return,
764353141Sphilip	// so it will wake up and know it needs to check the flag.
765353141Sphilip	//
766353141Sphilip	reread_config = 1;
767353141Sphilip}
768353141Sphilip
769353141Sphilipstatic void main_reap_children(int sign _U_)
770353141Sphilip{
771353141Sphilip	pid_t pid;
772353141Sphilip	int exitstat;
773353141Sphilip
774353141Sphilip	// Reap all child processes that have exited.
775353141Sphilip	// For reference, Stevens, pg 128
776353141Sphilip
777353141Sphilip	while ((pid = waitpid(-1, &exitstat, WNOHANG)) > 0)
778353141Sphilip		rpcapd_log(LOGPRIO_DEBUG, "Child terminated");
779353141Sphilip
780353141Sphilip	return;
781353141Sphilip}
782353141Sphilip#endif
783353141Sphilip
784353141Sphilip//
785353141Sphilip// Loop waiting for incoming connections and accepting them.
786353141Sphilip//
787353141Sphilipstatic void
788353141Sphilipaccept_connections(void)
789353141Sphilip{
790353141Sphilip#ifdef _WIN32
791353141Sphilip	struct listen_sock *sock_info;
792353141Sphilip	DWORD num_events;
793353141Sphilip	WSAEVENT *events;
794353141Sphilip	int i;
795353141Sphilip	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
796353141Sphilip
797353141Sphilip	//
798353141Sphilip	// How big does the set of events need to be?
799353141Sphilip	// One for the shutdown event, plus one for every socket on which
800353141Sphilip	// we'll be listening.
801353141Sphilip	//
802353141Sphilip	num_events = 1;		// shutdown event
803353141Sphilip	for (sock_info = listen_socks; sock_info;
804353141Sphilip	    sock_info = sock_info->next)
805353141Sphilip	{
806353141Sphilip		if (num_events == WSA_MAXIMUM_WAIT_EVENTS)
807353141Sphilip		{
808353141Sphilip			//
809353141Sphilip			// WSAWaitForMultipleEvents() doesn't support
810353141Sphilip			// more than WSA_MAXIMUM_WAIT_EVENTS events
811353141Sphilip			// on which to wait.
812353141Sphilip			//
813353141Sphilip			rpcapd_log(LOGPRIO_ERROR, "Too many sockets on which to listen");
814353141Sphilip			exit(2);
815353141Sphilip		}
816353141Sphilip		num_events++;
817353141Sphilip	}
818353141Sphilip
819353141Sphilip	//
820353141Sphilip	// Allocate the array of events.
821353141Sphilip	//
822353141Sphilip	events = (WSAEVENT *) malloc(num_events * sizeof (WSAEVENT));
823353141Sphilip	if (events == NULL)
824353141Sphilip	{
825353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "Can't allocate array of events which to listen");
826353141Sphilip		exit(2);
827353141Sphilip	}
828353141Sphilip
829353141Sphilip	//
830353141Sphilip	// Fill it in.
831353141Sphilip	//
832353141Sphilip	events[0] = state_change_event;	// state change event first
833353141Sphilip	for (sock_info = listen_socks, i = 1; sock_info;
834353141Sphilip	    sock_info = sock_info->next, i++)
835353141Sphilip	{
836353141Sphilip		WSAEVENT event;
837353141Sphilip
838353141Sphilip		//
839353141Sphilip		// Create an event that is signaled if there's a connection
840353141Sphilip		// to accept on the socket in question.
841353141Sphilip		//
842353141Sphilip		event = WSACreateEvent();
843353141Sphilip		if (event == WSA_INVALID_EVENT)
844353141Sphilip		{
845353141Sphilip			sock_geterror("Can't create socket event", errbuf,
846353141Sphilip			    PCAP_ERRBUF_SIZE);
847353141Sphilip			rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
848353141Sphilip			exit(2);
849353141Sphilip		}
850353141Sphilip		if (WSAEventSelect(sock_info->sock, event, FD_ACCEPT) == SOCKET_ERROR)
851353141Sphilip		{
852353141Sphilip			sock_geterror("Can't setup socket event", errbuf,
853353141Sphilip			    PCAP_ERRBUF_SIZE);
854353141Sphilip			rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
855353141Sphilip			exit(2);
856353141Sphilip		}
857353141Sphilip		events[i] = event;
858353141Sphilip	}
859353141Sphilip
860353141Sphilip	for (;;)
861353141Sphilip	{
862353141Sphilip		//
863353141Sphilip		// Wait for incoming connections.
864353141Sphilip		//
865353141Sphilip		DWORD ret;
866353141Sphilip
867353141Sphilip		ret = WSAWaitForMultipleEvents(num_events, events, FALSE,
868353141Sphilip		    WSA_INFINITE, FALSE);
869353141Sphilip		if (ret == WSA_WAIT_FAILED)
870353141Sphilip		{
871353141Sphilip			sock_geterror("WSAWaitForMultipleEvents failed", errbuf,
872353141Sphilip			    PCAP_ERRBUF_SIZE);
873353141Sphilip			rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
874353141Sphilip			exit(2);
875353141Sphilip		}
876353141Sphilip
877353141Sphilip		if (ret == WSA_WAIT_EVENT_0)
878353141Sphilip		{
879353141Sphilip			//
880353141Sphilip			// The state change event was set.
881353141Sphilip			//
882353141Sphilip			if (shutdown_server)
883353141Sphilip			{
884353141Sphilip				//
885353141Sphilip				// Time to quit. Exit the loop.
886353141Sphilip				//
887353141Sphilip				break;
888353141Sphilip			}
889353141Sphilip			if (reread_config)
890353141Sphilip			{
891353141Sphilip				//
892353141Sphilip				// We should re-read the configuration
893353141Sphilip				// file.
894353141Sphilip				//
895353141Sphilip				reread_config = 0;	// clear the indicator
896353141Sphilip				fileconf_read();
897353141Sphilip			}
898353141Sphilip		}
899353141Sphilip
900353141Sphilip		//
901353141Sphilip		// Check each socket.
902353141Sphilip		//
903353141Sphilip		for (sock_info = listen_socks, i = 1; sock_info;
904353141Sphilip		    sock_info = sock_info->next, i++)
905353141Sphilip		{
906353141Sphilip			WSANETWORKEVENTS network_events;
907353141Sphilip
908353141Sphilip			if (WSAEnumNetworkEvents(sock_info->sock,
909353141Sphilip			    events[i], &network_events) == SOCKET_ERROR)
910353141Sphilip			{
911353141Sphilip				sock_geterror("WSAEnumNetworkEvents failed",
912353141Sphilip				    errbuf, PCAP_ERRBUF_SIZE);
913353141Sphilip				rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
914353141Sphilip				exit(2);
915353141Sphilip			}
916353141Sphilip			if (network_events.lNetworkEvents & FD_ACCEPT)
917353141Sphilip			{
918353141Sphilip				//
919353141Sphilip				// Did an error occur?
920353141Sphilip				//
921353141Sphilip			 	if (network_events.iErrorCode[FD_ACCEPT_BIT] != 0)
922353141Sphilip			 	{
923353141Sphilip					//
924353141Sphilip					// Yes - report it and keep going.
925353141Sphilip					//
926353141Sphilip					sock_fmterror("Socket error",
927353141Sphilip					    network_events.iErrorCode[FD_ACCEPT_BIT],
928353141Sphilip					    errbuf,
929353141Sphilip					    PCAP_ERRBUF_SIZE);
930353141Sphilip					rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
931353141Sphilip					continue;
932353141Sphilip				}
933353141Sphilip
934353141Sphilip				//
935353141Sphilip				// Accept the connection.
936353141Sphilip				//
937353141Sphilip				accept_connection(sock_info->sock);
938353141Sphilip			}
939353141Sphilip		}
940353141Sphilip	}
941353141Sphilip#else
942353141Sphilip	struct listen_sock *sock_info;
943353141Sphilip	int num_sock_fds;
944353141Sphilip
945353141Sphilip	//
946353141Sphilip	// How big does the bitset of sockets on which to select() have
947353141Sphilip	// to be?
948353141Sphilip	//
949353141Sphilip	num_sock_fds = 0;
950353141Sphilip	for (sock_info = listen_socks; sock_info; sock_info = sock_info->next)
951353141Sphilip	{
952353141Sphilip		if (sock_info->sock + 1 > num_sock_fds)
953353141Sphilip		{
954353141Sphilip			if ((unsigned int)(sock_info->sock + 1) >
955353141Sphilip			    (unsigned int)FD_SETSIZE)
956353141Sphilip			{
957353141Sphilip				rpcapd_log(LOGPRIO_ERROR, "Socket FD is too bit for an fd_set");
958353141Sphilip				exit(2);
959353141Sphilip			}
960353141Sphilip			num_sock_fds = sock_info->sock + 1;
961353141Sphilip		}
962353141Sphilip	}
963353141Sphilip
964353141Sphilip	for (;;)
965353141Sphilip	{
966353141Sphilip		fd_set sock_fds;
967353141Sphilip		int ret;
968353141Sphilip
969353141Sphilip		//
970353141Sphilip		// Set up an fd_set for all the sockets on which we're
971353141Sphilip		// listening.
972353141Sphilip		//
973353141Sphilip		// This set is modified by select(), so we have to
974353141Sphilip		// construct it anew each time.
975353141Sphilip		//
976353141Sphilip		FD_ZERO(&sock_fds);
977353141Sphilip		for (sock_info = listen_socks; sock_info;
978353141Sphilip		    sock_info = sock_info->next)
979353141Sphilip		{
980353141Sphilip			FD_SET(sock_info->sock, &sock_fds);
981353141Sphilip		}
982353141Sphilip
983353141Sphilip		//
984353141Sphilip		// Wait for incoming connections.
985353141Sphilip		//
986353141Sphilip		ret = select(num_sock_fds, &sock_fds, NULL, NULL, NULL);
987353141Sphilip		if (ret == -1)
988353141Sphilip		{
989353141Sphilip			if (errno == EINTR)
990353141Sphilip			{
991353141Sphilip				//
992353141Sphilip				// If this is a "terminate the
993353141Sphilip				// server" signal, exit the loop,
994353141Sphilip				// otherwise just keep trying.
995353141Sphilip				//
996353141Sphilip				if (shutdown_server)
997353141Sphilip				{
998353141Sphilip					//
999353141Sphilip					// Time to quit.  Exit the loop.
1000353141Sphilip					//
1001353141Sphilip					break;
1002353141Sphilip				}
1003353141Sphilip				if (reread_config)
1004353141Sphilip				{
1005353141Sphilip					//
1006353141Sphilip					// We should re-read the configuration
1007353141Sphilip					// file.
1008353141Sphilip					//
1009353141Sphilip					reread_config = 0;	// clear the indicator
1010353141Sphilip					fileconf_read();
1011353141Sphilip				}
1012353141Sphilip
1013353141Sphilip				//
1014353141Sphilip				// Go back and wait again.
1015353141Sphilip				//
1016353141Sphilip				continue;
1017353141Sphilip			}
1018353141Sphilip			else
1019353141Sphilip			{
1020353141Sphilip				rpcapd_log(LOGPRIO_ERROR, "select failed: %s",
1021353141Sphilip				    strerror(errno));
1022353141Sphilip				exit(2);
1023353141Sphilip			}
1024353141Sphilip		}
1025353141Sphilip
1026353141Sphilip		//
1027353141Sphilip		// Check each socket.
1028353141Sphilip		//
1029353141Sphilip		for (sock_info = listen_socks; sock_info;
1030353141Sphilip		    sock_info = sock_info->next)
1031353141Sphilip		{
1032353141Sphilip			if (FD_ISSET(sock_info->sock, &sock_fds))
1033353141Sphilip			{
1034353141Sphilip				//
1035353141Sphilip				// Accept the connection.
1036353141Sphilip				//
1037353141Sphilip				accept_connection(sock_info->sock);
1038353141Sphilip			}
1039353141Sphilip		}
1040353141Sphilip	}
1041353141Sphilip#endif
1042353141Sphilip
1043353141Sphilip	//
1044353141Sphilip	// Close all the listen sockets.
1045353141Sphilip	//
1046353141Sphilip	for (sock_info = listen_socks; sock_info; sock_info = sock_info->next)
1047353141Sphilip	{
1048353141Sphilip		closesocket(sock_info->sock);
1049353141Sphilip	}
1050353141Sphilip	sock_cleanup();
1051353141Sphilip}
1052353141Sphilip
1053353141Sphilip#ifdef _WIN32
1054353141Sphilip//
1055353141Sphilip// A structure to hold the parameters to the daemon service loop
1056353141Sphilip// thread on Windows.
1057353141Sphilip//
1058353141Sphilip// (On UN*X, there is no need for this explicit copy since the
1059353141Sphilip// fork "inherits" the parent stack.)
1060353141Sphilip//
1061353141Sphilipstruct params_copy {
1062353141Sphilip	SOCKET sockctrl;
1063353141Sphilip	char *hostlist;
1064353141Sphilip};
1065353141Sphilip#endif
1066353141Sphilip
1067353141Sphilip//
1068353141Sphilip// Accept a connection and start a worker thread, on Windows, or a
1069353141Sphilip// worker process, on UN*X, to handle the connection.
1070353141Sphilip//
1071353141Sphilipstatic void
1072353141Sphilipaccept_connection(SOCKET listen_sock)
1073353141Sphilip{
1074353141Sphilip	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
1075353141Sphilip	SOCKET sockctrl;			// keeps the socket ID for this control connection
1076353141Sphilip	struct sockaddr_storage from;		// generic sockaddr_storage variable
1077353141Sphilip	socklen_t fromlen;			// keeps the length of the sockaddr_storage variable
1078353141Sphilip
1079353141Sphilip#ifdef _WIN32
1080353141Sphilip	HANDLE threadId;			// handle for the subthread
1081353141Sphilip	u_long off = 0;
1082353141Sphilip	struct params_copy *params_copy = NULL;
1083353141Sphilip#else
1084353141Sphilip	pid_t pid;
1085353141Sphilip#endif
1086353141Sphilip
1087353141Sphilip	// Initialize errbuf
1088353141Sphilip	memset(errbuf, 0, sizeof(errbuf));
1089353141Sphilip
1090353141Sphilip	for (;;)
1091353141Sphilip	{
1092353141Sphilip		// Accept the connection
1093353141Sphilip		fromlen = sizeof(struct sockaddr_storage);
1094353141Sphilip
1095353141Sphilip		sockctrl = accept(listen_sock, (struct sockaddr *) &from, &fromlen);
1096353141Sphilip
1097353141Sphilip		if (sockctrl != INVALID_SOCKET)
1098353141Sphilip		{
1099353141Sphilip			// Success.
1100353141Sphilip			break;
1101353141Sphilip		}
1102353141Sphilip
1103353141Sphilip		// The accept() call can return this error when a signal is catched
1104353141Sphilip		// In this case, we have simply to ignore this error code
1105353141Sphilip		// Stevens, pg 124
1106353141Sphilip#ifdef _WIN32
1107353141Sphilip		if (WSAGetLastError() == WSAEINTR)
1108353141Sphilip#else
1109353141Sphilip		if (errno == EINTR)
1110353141Sphilip#endif
1111353141Sphilip			continue;
1112353141Sphilip
1113353141Sphilip		// Don't check for errors here, since the error can be due to the fact that the thread
1114353141Sphilip		// has been killed
1115353141Sphilip		sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE);
1116353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "Accept of control connection from client failed: %s",
1117353141Sphilip		    errbuf);
1118353141Sphilip		return;
1119353141Sphilip	}
1120353141Sphilip
1121353141Sphilip#ifdef _WIN32
1122353141Sphilip	//
1123353141Sphilip	// Put the socket back into blocking mode; doing WSAEventSelect()
1124353141Sphilip	// on the listen socket makes that socket non-blocking, and it
1125353141Sphilip	// appears that sockets returned from an accept() on that socket
1126353141Sphilip	// are also non-blocking.
1127353141Sphilip	//
1128353141Sphilip	// First, we have to un-WSAEventSelect() this socket, and then
1129353141Sphilip	// we can turn non-blocking mode off.
1130353141Sphilip	//
1131353141Sphilip	// If this fails, we aren't guaranteed that, for example, any
1132353141Sphilip	// of the error message will be sent - if it can't be put in
1133353141Sphilip	// the socket queue, the send will just fail.
1134353141Sphilip	//
1135353141Sphilip	// So we just log the message and close the connection.
1136353141Sphilip	//
1137353141Sphilip	if (WSAEventSelect(sockctrl, NULL, 0) == SOCKET_ERROR)
1138353141Sphilip	{
1139353141Sphilip		sock_geterror("WSAEventSelect()", errbuf, PCAP_ERRBUF_SIZE);
1140353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
1141353141Sphilip		sock_close(sockctrl, NULL, 0);
1142353141Sphilip		return;
1143353141Sphilip	}
1144353141Sphilip	if (ioctlsocket(sockctrl, FIONBIO, &off) == SOCKET_ERROR)
1145353141Sphilip	{
1146353141Sphilip		sock_geterror("ioctlsocket(FIONBIO)", errbuf, PCAP_ERRBUF_SIZE);
1147353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
1148353141Sphilip		sock_close(sockctrl, NULL, 0);
1149353141Sphilip		return;
1150353141Sphilip	}
1151353141Sphilip
1152353141Sphilip	//
1153353141Sphilip	// Make a copy of the host list to pass to the new thread, so that
1154353141Sphilip	// if we update it in the main thread, it won't catch us in the
1155353141Sphilip	// middle of updating it.
1156353141Sphilip	//
1157353141Sphilip	// daemon_serviceloop() will free it once it's done with it.
1158353141Sphilip	//
1159353141Sphilip	char *hostlist_copy = strdup(hostlist);
1160353141Sphilip	if (hostlist_copy == NULL)
1161353141Sphilip	{
1162353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
1163353141Sphilip		sock_close(sockctrl, NULL, 0);
1164353141Sphilip		return;
1165353141Sphilip	}
1166353141Sphilip
1167353141Sphilip	//
1168353141Sphilip	// Allocate a location to hold the values of sockctrl.
1169353141Sphilip	// It will be freed in the newly-created thread once it's
1170353141Sphilip	// finished with it.
1171353141Sphilip	//
1172353141Sphilip	params_copy = malloc(sizeof(*params_copy));
1173353141Sphilip	if (params_copy == NULL)
1174353141Sphilip	{
1175353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "Out of memory allocating the parameter copy structure");
1176353141Sphilip		free(hostlist_copy);
1177353141Sphilip		sock_close(sockctrl, NULL, 0);
1178353141Sphilip		return;
1179353141Sphilip	}
1180353141Sphilip	params_copy->sockctrl = sockctrl;
1181353141Sphilip	params_copy->hostlist = hostlist_copy;
1182353141Sphilip
1183353141Sphilip	threadId = (HANDLE)_beginthreadex(NULL, 0,
1184353141Sphilip	    main_passive_serviceloop_thread, (void *) params_copy, 0, NULL);
1185353141Sphilip	if (threadId == 0)
1186353141Sphilip	{
1187353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "Error creating the child thread");
1188353141Sphilip		free(params_copy);
1189353141Sphilip		free(hostlist_copy);
1190353141Sphilip		sock_close(sockctrl, NULL, 0);
1191353141Sphilip		return;
1192353141Sphilip	}
1193353141Sphilip	CloseHandle(threadId);
1194353141Sphilip#else /* _WIN32 */
1195353141Sphilip	pid = fork();
1196353141Sphilip	if (pid == -1)
1197353141Sphilip	{
1198353141Sphilip		rpcapd_log(LOGPRIO_ERROR, "Error creating the child process: %s",
1199353141Sphilip		    strerror(errno));
1200353141Sphilip		sock_close(sockctrl, NULL, 0);
1201353141Sphilip		return;
1202353141Sphilip	}
1203353141Sphilip	if (pid == 0)
1204353141Sphilip	{
1205353141Sphilip		//
1206353141Sphilip		// Child process.
1207353141Sphilip		//
1208353141Sphilip		// Close the socket on which we're listening (must
1209353141Sphilip		// be open only in the parent).
1210353141Sphilip		//
1211353141Sphilip		closesocket(listen_sock);
1212353141Sphilip
1213353141Sphilip#if 0
1214353141Sphilip		//
1215353141Sphilip		// Modify thread params so that it can be killed at any time
1216353141Sphilip		// XXX - is this necessary?  This is the main and, currently,
1217353141Sphilip		// only thread in the child process, and nobody tries to
1218353141Sphilip		// cancel us, although *we* may cancel the thread that's
1219353141Sphilip		// handling the capture loop.
1220353141Sphilip		//
1221353141Sphilip		if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL))
1222353141Sphilip			goto end;
1223353141Sphilip		if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL))
1224353141Sphilip			goto end;
1225353141Sphilip#endif
1226353141Sphilip
1227353141Sphilip		//
1228353141Sphilip		// Run the service loop.
1229353141Sphilip		// This is passive mode, so we don't care whether we were
1230353141Sphilip		// told by the client to close.
1231353141Sphilip		//
1232353141Sphilip		char *hostlist_copy = strdup(hostlist);
1233353141Sphilip		if (hostlist_copy == NULL)
1234353141Sphilip		{
1235353141Sphilip			rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
1236353141Sphilip			exit(0);
1237353141Sphilip		}
1238353141Sphilip		(void)daemon_serviceloop(sockctrl, 0, hostlist_copy,
1239353141Sphilip		    nullAuthAllowed);
1240353141Sphilip
1241353141Sphilip		exit(0);
1242353141Sphilip	}
1243353141Sphilip
1244353141Sphilip	// I am the parent
1245353141Sphilip	// Close the socket for this session (must be open only in the child)
1246353141Sphilip	closesocket(sockctrl);
1247353141Sphilip#endif /* _WIN32 */
1248353141Sphilip}
1249353141Sphilip
1250353141Sphilip/*!
1251353141Sphilip	\brief 'true' main of the program in case the active mode is turned on.
1252353141Sphilip
1253353141Sphilip	This function loops forever trying to connect to the remote host, until the
1254353141Sphilip	daemon is turned down.
1255353141Sphilip
1256353141Sphilip	\param ptr: it keeps the 'activepars' parameters.  It is a 'void *'
1257353141Sphilip	just because the thread APIs want this format.
1258353141Sphilip*/
1259353141Sphilip#ifdef _WIN32
1260353141Sphilipstatic unsigned __stdcall
1261353141Sphilip#else
1262353141Sphilipstatic void *
1263353141Sphilip#endif
1264353141Sphilipmain_active(void *ptr)
1265353141Sphilip{
1266353141Sphilip	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
1267353141Sphilip	SOCKET sockctrl;			// keeps the socket ID for this control connection
1268353141Sphilip	struct addrinfo hints;			// temporary struct to keep settings needed to open the new socket
1269353141Sphilip	struct addrinfo *addrinfo;		// keeps the addrinfo chain; required to open a new socket
1270353141Sphilip	struct active_pars *activepars;
1271353141Sphilip
1272353141Sphilip	activepars = (struct active_pars *) ptr;
1273353141Sphilip
1274353141Sphilip	// Prepare to open a new server socket
1275353141Sphilip	memset(&hints, 0, sizeof(struct addrinfo));
1276353141Sphilip						// WARNING Currently it supports only ONE socket family among IPv4 and IPv6
1277353141Sphilip	hints.ai_family = AF_INET;		// PF_UNSPEC to have both IPv4 and IPv6 server
1278353141Sphilip	hints.ai_socktype = SOCK_STREAM;
1279353141Sphilip	hints.ai_family = activepars->ai_family;
1280353141Sphilip
1281353141Sphilip	rpcapd_log(LOGPRIO_DEBUG, "Connecting to host %s, port %s, using protocol %s",
1282353141Sphilip	    activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
1283353141Sphilip	    (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
1284353141Sphilip
1285353141Sphilip	// Initialize errbuf
1286353141Sphilip	memset(errbuf, 0, sizeof(errbuf));
1287353141Sphilip
1288353141Sphilip	// Do the work
1289353141Sphilip	if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
1290353141Sphilip	{
1291353141Sphilip		rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
1292353141Sphilip		return 0;
1293353141Sphilip	}
1294353141Sphilip
1295353141Sphilip	for (;;)
1296353141Sphilip	{
1297353141Sphilip		int activeclose;
1298353141Sphilip
1299353141Sphilip		if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
1300353141Sphilip		{
1301353141Sphilip			rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
1302353141Sphilip
1303353141Sphilip			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
1304353141Sphilip					activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
1305353141Sphilip					(hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
1306353141Sphilip
1307353141Sphilip			rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
1308353141Sphilip
1309353141Sphilip			sleep_secs(RPCAP_ACTIVE_WAIT);
1310353141Sphilip
1311353141Sphilip			continue;
1312353141Sphilip		}
1313353141Sphilip
1314353141Sphilip		char *hostlist_copy = strdup(hostlist);
1315353141Sphilip		if (hostlist_copy == NULL)
1316353141Sphilip		{
1317353141Sphilip			rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
1318353141Sphilip			activeclose = 0;
1319353141Sphilip			sock_close(sockctrl, NULL, 0);
1320353141Sphilip		}
1321353141Sphilip		else
1322353141Sphilip		{
1323353141Sphilip			//
1324353141Sphilip			// daemon_serviceloop() will free the copy.
1325353141Sphilip			//
1326353141Sphilip			activeclose = daemon_serviceloop(sockctrl, 1,
1327353141Sphilip			    hostlist_copy, nullAuthAllowed);
1328353141Sphilip		}
1329353141Sphilip
1330353141Sphilip		// If the connection is closed by the user explicitely, don't try to connect to it again
1331353141Sphilip		// just exit the program
1332353141Sphilip		if (activeclose == 1)
1333353141Sphilip			break;
1334353141Sphilip	}
1335353141Sphilip
1336353141Sphilip	freeaddrinfo(addrinfo);
1337353141Sphilip	return 0;
1338353141Sphilip}
1339353141Sphilip
1340353141Sphilip#ifdef _WIN32
1341353141Sphilip//
1342353141Sphilip// Main routine of a passive-mode service thread.
1343353141Sphilip//
1344353141Sphilipunsigned __stdcall main_passive_serviceloop_thread(void *ptr)
1345353141Sphilip{
1346353141Sphilip	struct params_copy params = *(struct params_copy *)ptr;
1347353141Sphilip	free(ptr);
1348353141Sphilip
1349353141Sphilip	//
1350353141Sphilip	// Handle this client.
1351353141Sphilip	// This is passive mode, so we don't care whether we were
1352353141Sphilip	// told by the client to close.
1353353141Sphilip	//
1354353141Sphilip	(void)daemon_serviceloop(params.sockctrl, 0, params.hostlist,
1355353141Sphilip	    nullAuthAllowed);
1356353141Sphilip
1357353141Sphilip	return 0;
1358353141Sphilip}
1359353141Sphilip#endif
1360