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