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