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