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