2 * Copyright (c) 2002 - 2003
3 * NetGroup, Politecnico di Torino (Italy)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
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()
46 #include "sockutils.h" // for socket calls
47 #include "varattrs.h" // for _U_
48 #include "portability.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
57 #include <process.h> // for thread stuff
58 #include "win32-svc.h" // for Win32 service stuff
59 #include "getopt.h" // for getopt()-for-Windows
61 #include <fcntl.h> // for open()
62 #include <unistd.h> // for exit()
63 #include <sys/wait.h> // waitpid()
67 // Element in list of sockets on which we're listening for connections.
70 struct listen_sock
*next
;
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
85 static HANDLE state_change_event
; //!< event to signal that a state change should take place
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
90 extern char *optarg
; // for getopt()
92 // Function definition
94 static unsigned __stdcall
main_active(void *ptr
);
95 static BOOL WINAPI
main_ctrl_event(DWORD
);
97 static void *main_active(void *ptr
);
98 static void main_terminate(int sign
);
99 static void main_reread_config(int sign
);
101 static void accept_connections(void);
102 static void accept_connection(SOCKET listen_sock
);
104 static void main_reap_children(int sign
);
107 static unsigned __stdcall
main_passive_serviceloop_thread(void *ptr
);
110 #define RPCAP_ACTIVE_WAIT 30 /* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */
113 \brief Prints the usage screen if it is launched in console mode.
115 static void printusage(void)
119 " " PROGRAM_NAME
" [-b <address>] [-p <port>] [-4] [-l <host_list>] [-a <host,port>]\n"
124 "[-s <file>] [-f <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"
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"
145 " -i run in inetd mode (UNIX only)\n\n"
147 " -s <file> save the current configuration to file\n\n"
148 " -f <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";
152 (void)fprintf(stderr
, "RPCAPD, a remote packet capture daemon.\n"
153 "Compiled with %s\n\n", pcap_lib_version());
154 printf("%s", usagetext
);
160 int main(int argc
, char *argv
[])
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
165 int isrunbyinetd
= 0; // Non-zero if this is being run by inetd or something inetd-like
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
170 struct sigaction action
;
178 memset(errbuf
, 0, sizeof(errbuf
));
180 if (sock_init(errbuf
, PCAP_ERRBUF_SIZE
) == -1)
182 SOCK_DEBUG_MESSAGE(errbuf
);
186 strncpy(address
, RPCAP_DEFAULT_NETADDR
, MAX_LINE
);
187 strncpy(port
, RPCAP_DEFAULT_NETPORT
, MAX_LINE
);
189 // Prepare to open a new server socket
190 memset(&mainhints
, 0, sizeof(struct addrinfo
));
192 mainhints
.ai_family
= PF_UNSPEC
;
193 mainhints
.ai_flags
= AI_PASSIVE
; // Ready to a bind() socket
194 mainhints
.ai_socktype
= SOCK_STREAM
;
196 // Getting the proper command line options
197 while ((retval
= getopt(argc
, argv
, "b:dhip:4l:na:s:f:v")) != -1)
202 strncpy(address
, optarg
, MAX_LINE
);
205 strncpy(port
, optarg
, MAX_LINE
);
208 mainhints
.ai_family
= PF_INET
; // IPv4 server only
229 strncpy(hostlist
, optarg
, sizeof(hostlist
));
234 char *tmpaddress
, *tmpport
;
238 tmpaddress
= pcap_strtok_r(optarg
, RPCAP_HOSTLIST_SEP
, &lasts
);
240 while ((tmpaddress
!= NULL
) && (i
< MAX_ACTIVE_LIST
))
242 tmpport
= pcap_strtok_r(NULL
, RPCAP_HOSTLIST_SEP
, &lasts
);
244 strlcpy(activelist
[i
].address
, tmpaddress
, MAX_LINE
);
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
);
249 strlcpy(activelist
[i
].port
, tmpport
, MAX_LINE
);
251 tmpaddress
= pcap_strtok_r(NULL
, RPCAP_HOSTLIST_SEP
, &lasts
);
256 if (i
> MAX_ACTIVE_LIST
)
257 SOCK_DEBUG_MESSAGE("Only MAX_ACTIVE_LIST active connections are currently supported.");
259 // I don't initialize the remaining part of the structure, since
260 // it is already zeroed (it is a global var)
264 strlcpy(loadfile
, optarg
, MAX_LINE
);
267 strlcpy(savefile
, optarg
, MAX_LINE
);
280 if (isdaemon
&& isrunbyinetd
)
282 fprintf(stderr
, "rpcapd: -d and -i can't be used together\n");
287 if (savefile
[0] && fileconf_save(savefile
))
288 SOCK_DEBUG_MESSAGE("Error when saving the configuration to file");
290 // If the file does not exist, it keeps the settings provided by the command line
296 // Create a handle to signal the main loop to tell it to do
299 state_change_event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
300 if (state_change_event
== NULL
)
302 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
303 rpcapd_log(LOGPRIO_ERROR
, "Can't create state change event: %s",
309 // Catch control signals.
311 if (!SetConsoleCtrlHandler(main_ctrl_event
, TRUE
))
313 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
314 rpcapd_log(LOGPRIO_ERROR
, "Can't set control handler: %s",
319 memset(&action
, 0, sizeof (action
));
320 action
.sa_handler
= main_terminate
;
322 sigemptyset(&action
.sa_mask
);
323 sigaction(SIGTERM
, &action
, NULL
);
324 memset(&action
, 0, sizeof (action
));
325 action
.sa_handler
= main_reap_children
;
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
);
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.).
342 // Our standard input is the input side of a connection,
343 // and our standard output is the output side of a
346 int sockctrl_in
, sockctrl_out
;
350 // Duplicate the standard input and output, making them
351 // the input and output side of the control connection.
353 sockctrl_in
= dup(0);
354 if (sockctrl_in
== -1)
356 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
357 rpcapd_log(LOGPRIO_ERROR
, "Can't dup standard input: %s",
361 sockctrl_out
= dup(1);
362 if (sockctrl_out
== -1)
364 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
365 rpcapd_log(LOGPRIO_ERROR
, "Can't dup standard output: %s",
371 // Try to set the standard input and output to /dev/null.
373 devnull_fd
= open("/dev/null", O_RDWR
);
374 if (devnull_fd
!= -1)
377 // If this fails, just drive on.
379 (void)dup2(devnull_fd
, 0);
380 (void)dup2(devnull_fd
, 1);
385 // Handle this client.
386 // This is passive mode, so we don't care whether we were
387 // told by the client to close.
389 (void)daemon_serviceloop(sockctrl_in
, sockctrl_out
, 0,
393 // Nothing more to do.
402 // This is being run as a daemon.
403 // On UN*X, it might be manually run, or run from an
410 // Daemonize ourselves.
412 // Unix Network Programming, pg 336
414 if ((pid
= fork()) != 0)
415 exit(0); // Parent terminates
417 // First child continues
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
;
425 sigemptyset(&action
.sa_mask
);
426 sigaction(SIGHUP
, &action
, NULL
);
428 if ((pid
= fork()) != 0)
429 exit(0); // First child terminates
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
436 // Second child continues
441 // This is being run as a service on Windows.
443 // If this call succeeds, it is blocking on Win32
445 if (svc_start() != 1)
446 SOCK_DEBUG_MESSAGE("Unable to start the service");
448 // When the previous call returns, the entire application has to be stopped.
455 // Enable the catching of Ctrl+C
456 memset(&action
, 0, sizeof (action
));
457 action
.sa_handler
= main_terminate
;
459 sigemptyset(&action
.sa_mask
);
460 sigaction(SIGINT
, &action
, NULL
);
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
;
467 sigemptyset(&action
.sa_mask
);
468 sigaction(SIGHUP
, &action
, NULL
);
471 printf("Press CTRL + C to stop the server...\n");
474 // If we're a Win32 service, we have already called this function in the service_main
477 // The code should never arrive here (since the main_startup is blocking)
478 // however this avoids a compiler warning
482 void main_startup(void)
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
488 HANDLE threadId
; // handle for the subthread
495 memset(errbuf
, 0, sizeof(errbuf
));
497 // Starts all the active threads
498 while ((i
< MAX_ACTIVE_LIST
) && (activelist
[i
].address
[0] != 0))
500 activelist
[i
].ai_family
= mainhints
.ai_family
;
503 threadId
= (HANDLE
)_beginthreadex(NULL
, 0, main_active
,
504 (void *)&activelist
[i
], 0, NULL
);
507 SOCK_DEBUG_MESSAGE("Error creating the active child threads");
510 CloseHandle(threadId
);
512 if ((pid
= fork()) == 0) // I am the child
514 main_active((void *) &activelist
[i
]);
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.
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.
535 struct addrinfo
*tempaddrinfo
;
538 // Get a list of sockets on which to listen.
540 if (sock_initaddress((address
[0]) ? address
: NULL
, port
, &mainhints
, &addrinfo
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
542 SOCK_DEBUG_MESSAGE(errbuf
);
546 for (tempaddrinfo
= addrinfo
; tempaddrinfo
;
547 tempaddrinfo
= tempaddrinfo
->ai_next
)
550 struct listen_sock
*sock_info
;
552 if ((sock
= sock_open(tempaddrinfo
, SOCKOPEN_SERVER
, SOCKET_MAXCONN
, errbuf
, PCAP_ERRBUF_SIZE
)) == INVALID_SOCKET
)
554 SOCK_DEBUG_MESSAGE(errbuf
);
558 sock_info
= (struct listen_sock
*) malloc(sizeof (struct listen_sock
));
559 if (sock_info
== NULL
)
561 rpcapd_log(LOGPRIO_ERROR
, "Can't allocate structure for listen socket");
564 sock_info
->sock
= sock
;
565 sock_info
->next
= listen_socks
;
566 listen_socks
= sock_info
;
569 freeaddrinfo(addrinfo
);
572 // Now listen on all of them, waiting for connections.
574 accept_connections();
580 SOCK_DEBUG_MESSAGE(PROGRAM_NAME
" is closing.\n");
584 // Sends a KILL signal to all the processes in this process's
585 // process group; i.e., it kills all the child processes
588 // XXX - that also includes us, so we will be killed as well;
589 // that may cause a message to be printed or logged.
595 // Just leave. We shouldn't need to clean up sockets or
596 // anything else, and if we try to do so, we'll could end
597 // up closing sockets, or shutting Winsock down, out from
598 // under service loops, causing all sorts of noisy error
601 // We shouldn't need to worry about cleaning up any resources
602 // such as handles, sockets, threads, etc. - exit() should
603 // terminate the process, causing all those resources to be
604 // cleaned up (including the threads; Microsoft claims in the
605 // ExitProcess() documentation that, if ExitProcess() is called,
606 // "If a thread is waiting on a kernel object, it will not be
607 // terminated until the wait has completed.", but claims in the
608 // _beginthread()/_beginthreadex() documentation that "All threads
609 // are terminated if any thread calls abort, exit, _exit, or
610 // ExitProcess." - the latter appears to be the case, even for
611 // threads waiting on the event for a pcap_t).
618 send_state_change_event(void)
620 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // keeps the error string, prior to be printed
622 if (!SetEvent(state_change_event
))
624 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
625 rpcapd_log(LOGPRIO_ERROR
, "SetEvent on shutdown event failed: %s", errbuf
);
630 send_shutdown_notification(void)
633 // Indicate that the server should shut down.
638 // Send a state change event, to wake up WSAWaitForMultipleEvents().
640 send_state_change_event();
644 send_reread_configuration_notification(void)
647 // Indicate that the server should re-read its configuration file.
652 // Send a state change event, to wake up WSAWaitForMultipleEvents().
654 send_state_change_event();
657 static BOOL WINAPI
main_ctrl_event(DWORD ctrltype
)
660 // ctrltype is one of:
662 // CTRL_C_EVENT - we got a ^C; this is like SIGINT
663 // CTRL_BREAK_EVENT - we got Ctrl+Break
664 // CTRL_CLOSE_EVENT - the console was closed; this is like SIGHUP
665 // CTRL_LOGOFF_EVENT - a user is logging off; this is received
667 // CTRL_SHUTDOWN_EVENT - the systemis shutting down; this is
668 // received only by services
670 // For now, we treat all but CTRL_LOGOFF_EVENT as indications
671 // that we should shut down.
676 case CTRL_BREAK_EVENT
:
677 case CTRL_CLOSE_EVENT
:
678 case CTRL_SHUTDOWN_EVENT
:
680 // Set a shutdown notification.
682 send_shutdown_notification();
695 static void main_terminate(int sign _U_
)
698 // Note that the server should shut down.
699 // select() should get an EINTR error when we return,
700 // so it will wake up and know it needs to check the flag.
705 static void main_reread_config(int sign _U_
)
708 // Note that the server should re-read its configuration file.
709 // select() should get an EINTR error when we return,
710 // so it will wake up and know it needs to check the flag.
715 static void main_reap_children(int sign _U_
)
720 // Reap all child processes that have exited.
721 // For reference, Stevens, pg 128
723 while ((pid
= waitpid(-1, &exitstat
, WNOHANG
)) > 0)
724 SOCK_DEBUG_MESSAGE("Child terminated");
731 // Loop waiting for incoming connections and accepting them.
734 accept_connections(void)
737 struct listen_sock
*sock_info
;
741 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // keeps the error string, prior to be printed
744 // How big does the set of events need to be?
745 // One for the shutdown event, plus one for every socket on which
746 // we'll be listening.
748 num_events
= 1; // shutdown event
749 for (sock_info
= listen_socks
; sock_info
;
750 sock_info
= sock_info
->next
)
752 if (num_events
== WSA_MAXIMUM_WAIT_EVENTS
)
755 // WSAWaitForMultipleEvents() doesn't support
756 // more than WSA_MAXIMUM_WAIT_EVENTS events
759 rpcapd_log(LOGPRIO_ERROR
, "Too many sockets on which to listen");
766 // Allocate the array of events.
768 events
= (WSAEVENT
*) malloc(num_events
* sizeof (WSAEVENT
));
771 rpcapd_log(LOGPRIO_ERROR
, "Can't allocate array of events which to listen");
778 events
[0] = state_change_event
; // state change event first
779 for (sock_info
= listen_socks
, i
= 1; sock_info
;
780 sock_info
= sock_info
->next
, i
++)
785 // Create an event that is signaled if there's a connection
786 // to accept on the socket in question.
788 event
= WSACreateEvent();
789 if (event
== WSA_INVALID_EVENT
)
791 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
792 rpcapd_log(LOGPRIO_ERROR
, "Can't create socket event: %s", errbuf
);
795 if (WSAEventSelect(sock_info
->sock
, event
, FD_ACCEPT
) == SOCKET_ERROR
)
797 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
798 rpcapd_log(LOGPRIO_ERROR
, "Can't setup socket event: %s", errbuf
);
807 // Wait for incoming connections.
811 ret
= WSAWaitForMultipleEvents(num_events
, events
, FALSE
,
812 WSA_INFINITE
, FALSE
);
813 if (ret
== WSA_WAIT_FAILED
)
815 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
816 rpcapd_log(LOGPRIO_ERROR
, "WSAWaitForMultipleEvents failed: %s", errbuf
);
820 if (ret
== WSA_WAIT_EVENT_0
)
823 // The state change event was set.
828 // Time to quit. Exit the loop.
835 // We should re-read the configuration
838 reread_config
= 0; // clear the indicator
844 // Check each socket.
846 for (sock_info
= listen_socks
, i
= 1; sock_info
;
847 sock_info
= sock_info
->next
, i
++)
849 WSANETWORKEVENTS network_events
;
851 if (WSAEnumNetworkEvents(sock_info
->sock
,
852 events
[i
], &network_events
) == SOCKET_ERROR
)
854 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
855 rpcapd_log(LOGPRIO_ERROR
, "WSAEnumNetworkEvents failed: %s", errbuf
);
858 if (network_events
.lNetworkEvents
& FD_ACCEPT
)
861 // Did an error occur?
863 if (network_events
.iErrorCode
[FD_ACCEPT_BIT
] != 0)
866 // Yes - report it and keep going.
869 network_events
.iErrorCode
[FD_ACCEPT_BIT
],
872 rpcapd_log(LOGPRIO_ERROR
, "Socket error: %s", errbuf
);
877 // Accept the connection.
879 accept_connection(sock_info
->sock
);
884 struct listen_sock
*sock_info
;
888 // How big does the bitset of sockets on which to select() have
892 for (sock_info
= listen_socks
; sock_info
; sock_info
= sock_info
->next
)
894 if (sock_info
->sock
+ 1 > num_sock_fds
)
896 if (sock_info
->sock
+ 1 > FD_SETSIZE
)
898 rpcapd_log(LOGPRIO_ERROR
, "Socket FD is too bit for an fd_set");
901 num_sock_fds
= sock_info
->sock
+ 1;
911 // Set up an fd_set for all the sockets on which we're
914 // This set is modified by select(), so we have to
915 // construct it anew each time.
918 for (sock_info
= listen_socks
; sock_info
;
919 sock_info
= sock_info
->next
)
921 FD_SET(sock_info
->sock
, &sock_fds
);
925 // Wait for incoming connections.
927 ret
= select(num_sock_fds
, &sock_fds
, NULL
, NULL
, NULL
);
933 // If this is a "terminate the
934 // server" signal, exit the loop,
935 // otherwise just keep trying.
940 // Time to quit. Exit the loop.
947 // We should re-read the configuration
950 reread_config
= 0; // clear the indicator
955 // Go back and wait again.
961 rpcapd_log(LOGPRIO_ERROR
, "select failed: %s",
968 // Check each socket.
970 for (sock_info
= listen_socks
; sock_info
;
971 sock_info
= sock_info
->next
)
973 if (FD_ISSET(sock_info
->sock
, &sock_fds
))
976 // Accept the connection.
978 accept_connection(sock_info
->sock
);
985 // Close all the listen sockets.
987 for (sock_info
= listen_socks
; sock_info
; sock_info
= sock_info
->next
)
989 closesocket(sock_info
->sock
);
995 // Accept a connection and start a worker thread, on Windows, or a
996 // worker process, on UN*X, to handle the connection.
999 accept_connection(SOCKET listen_sock
)
1001 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // keeps the error string, prior to be printed
1002 SOCKET sockctrl
; // keeps the socket ID for this control connection
1003 struct sockaddr_storage from
; // generic sockaddr_storage variable
1004 socklen_t fromlen
; // keeps the length of the sockaddr_storage variable
1007 HANDLE threadId
; // handle for the subthread
1009 SOCKET
*sockctrl_temp
;
1014 // Initialize errbuf
1015 memset(errbuf
, 0, sizeof(errbuf
));
1019 // Accept the connection
1020 fromlen
= sizeof(struct sockaddr_storage
);
1022 sockctrl
= accept(listen_sock
, (struct sockaddr
*) &from
, &fromlen
);
1024 if (sockctrl
!= INVALID_SOCKET
)
1030 // The accept() call can return this error when a signal is catched
1031 // In this case, we have simply to ignore this error code
1034 if (WSAGetLastError() == WSAEINTR
)
1040 // Don't check for errors here, since the error can be due to the fact that the thread
1042 sock_geterror("accept(): ", errbuf
, PCAP_ERRBUF_SIZE
);
1043 rpcapd_log(LOGPRIO_ERROR
, "Accept of control connection from client failed: %s",
1049 // We have a connection.
1050 // Check whether the connecting host is among the ones allowed.
1052 if (sock_check_hostlist(hostlist
, RPCAP_HOSTLIST_SEP
, &from
, errbuf
, PCAP_ERRBUF_SIZE
) < 0)
1054 rpcap_senderror(sockctrl
, 0, PCAP_ERR_HOSTNOAUTH
, errbuf
, NULL
);
1055 sock_close(sockctrl
, NULL
, 0);
1061 // Put the socket back into blocking mode; doing WSAEventSelect()
1062 // on the listen socket makes that socket non-blocking, and it
1063 // appears that sockets returned from an accept() on that socket
1064 // are also non-blocking.
1066 // First, we have to un-WSAEventSelect() this socket, and then
1067 // we can turn non-blocking mode off.
1069 if (WSAEventSelect(sockctrl
, NULL
, 0) == SOCKET_ERROR
)
1071 sock_geterror("ioctlsocket(FIONBIO): ", errbuf
, PCAP_ERRBUF_SIZE
);
1072 rpcap_senderror(sockctrl
, 0, PCAP_ERR_HOSTNOAUTH
, errbuf
, NULL
);
1073 sock_close(sockctrl
, NULL
, 0);
1076 if (ioctlsocket(sockctrl
, FIONBIO
, &off
) == SOCKET_ERROR
)
1078 sock_geterror("ioctlsocket(FIONBIO): ", errbuf
, PCAP_ERRBUF_SIZE
);
1079 rpcap_senderror(sockctrl
, 0, PCAP_ERR_HOSTNOAUTH
, errbuf
, NULL
);
1080 sock_close(sockctrl
, NULL
, 0);
1085 // Allocate a location to hold the value of sockctrl.
1086 // It will be freed in the newly-created thread once it's
1087 // finished with it.
1088 // I guess we *could* just cast sockctrl to a void *, but that's
1091 sockctrl_temp
= (SOCKET
*)malloc(sizeof (SOCKET
));
1092 if (sockctrl_temp
== NULL
)
1094 pcap_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
,
1095 errno
, "malloc() failed");
1096 rpcap_senderror(sockctrl
, 0, PCAP_ERR_OPEN
, errbuf
, NULL
);
1097 sock_close(sockctrl
, NULL
, 0);
1100 *sockctrl_temp
= sockctrl
;
1102 threadId
= (HANDLE
)_beginthreadex(NULL
, 0,
1103 main_passive_serviceloop_thread
, (void *) sockctrl_temp
, 0, NULL
);
1106 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error creating the child thread");
1107 rpcap_senderror(sockctrl
, 0, PCAP_ERR_OPEN
, errbuf
, NULL
);
1108 sock_close(sockctrl
, NULL
, 0);
1109 free(sockctrl_temp
);
1112 CloseHandle(threadId
);
1117 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error creating the child process");
1118 rpcap_senderror(sockctrl
, 0, PCAP_ERR_OPEN
, errbuf
, NULL
);
1119 sock_close(sockctrl
, NULL
, 0);
1127 // Close the socket on which we're listening (must
1128 // be open only in the parent).
1130 closesocket(listen_sock
);
1134 // Modify thread params so that it can be killed at any time
1135 // XXX - is this necessary? This is the main and, currently,
1136 // only thread in the child process, and nobody tries to
1137 // cancel us, although *we* may cancel the thread that's
1138 // handling the capture loop.
1140 if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
))
1142 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
))
1147 // Run the service loop.
1148 // This is passive mode, so we don't care whether we were
1149 // told by the client to close.
1151 (void)daemon_serviceloop(sockctrl
, sockctrl
, 0,
1160 // Close the socket for this session (must be open only in the child)
1161 closesocket(sockctrl
);
1166 \brief 'true' main of the program in case the active mode is turned on.
1168 This function loops forever trying to connect to the remote host, until the
1169 daemon is turned down.
1171 \param ptr: it keeps the 'activepars' parameters. It is a 'void *'
1172 just because the thread APIs want this format.
1175 static unsigned __stdcall
1179 main_active(void *ptr
)
1181 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // keeps the error string, prior to be printed
1182 SOCKET sockctrl
; // keeps the socket ID for this control connection
1183 struct addrinfo hints
; // temporary struct to keep settings needed to open the new socket
1184 struct addrinfo
*addrinfo
; // keeps the addrinfo chain; required to open a new socket
1185 struct active_pars
*activepars
;
1187 activepars
= (struct active_pars
*) ptr
;
1189 // Prepare to open a new server socket
1190 memset(&hints
, 0, sizeof(struct addrinfo
));
1191 // WARNING Currently it supports only ONE socket family among IPv4 and IPv6
1192 hints
.ai_family
= AF_INET
; // PF_UNSPEC to have both IPv4 and IPv6 server
1193 hints
.ai_socktype
= SOCK_STREAM
;
1194 hints
.ai_family
= activepars
->ai_family
;
1196 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Connecting to host %s, port %s, using protocol %s",
1197 activepars
->address
, activepars
->port
, (hints
.ai_family
== AF_INET
) ? "IPv4":
1198 (hints
.ai_family
== AF_INET6
) ? "IPv6" : "Unspecified");
1199 SOCK_DEBUG_MESSAGE(errbuf
);
1201 // Initialize errbuf
1202 memset(errbuf
, 0, sizeof(errbuf
));
1205 if (sock_initaddress(activepars
->address
, activepars
->port
, &hints
, &addrinfo
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1207 SOCK_DEBUG_MESSAGE(errbuf
);
1215 if ((sockctrl
= sock_open(addrinfo
, SOCKOPEN_CLIENT
, 0, errbuf
, PCAP_ERRBUF_SIZE
)) == INVALID_SOCKET
)
1217 SOCK_DEBUG_MESSAGE(errbuf
);
1219 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error connecting to host %s, port %s, using protocol %s",
1220 activepars
->address
, activepars
->port
, (hints
.ai_family
== AF_INET
) ? "IPv4":
1221 (hints
.ai_family
== AF_INET6
) ? "IPv6" : "Unspecified");
1223 SOCK_DEBUG_MESSAGE(errbuf
);
1225 sleep_secs(RPCAP_ACTIVE_WAIT
);
1230 activeclose
= daemon_serviceloop(sockctrl
, sockctrl
, 1,
1233 sock_close(sockctrl
, NULL
, 0);
1235 // If the connection is closed by the user explicitely, don't try to connect to it again
1236 // just exit the program
1237 if (activeclose
== 1)
1241 freeaddrinfo(addrinfo
);
1247 // Main routine of a passive-mode service thread.
1249 unsigned __stdcall
main_passive_serviceloop_thread(void *ptr
)
1253 sockctrl
= *((SOCKET
*)ptr
);
1257 // Handle this client.
1258 // This is passive mode, so we don't care whether we were
1259 // told by the client to close.
1261 (void)daemon_serviceloop(sockctrl
, sockctrl
, 0, nullAuthAllowed
);
1263 sock_close(sockctrl
, NULL
, 0);