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