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