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