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