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 "portability.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
55 #include <process.h> // for thread stuff
56 #include "win32-svc.h" // for Win32 service stuff
57 #include "getopt.h" // for getopt()-for-Windows
59 #include <unistd.h> // for exit()
60 #include <sys/wait.h> // waitpid()
64 // Element in list of sockets on which we're listening for connections.
67 struct listen_sock
*next
;
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
82 static HANDLE shutdown_event
; //!< event to signal to shut down the main loop
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
88 extern char *optarg
; // for getopt()
90 // Function definition
92 static unsigned __stdcall
main_active(void *ptr
);
93 static BOOL WINAPI
main_ctrl_event(DWORD
);
95 static void *main_active(void *ptr
);
96 static void main_terminate(int sign
);
97 static void main_reread_config(int sign
);
99 static void accept_connections(void);
100 static void accept_connection(SOCKET listen_sock
);
102 static void main_abort(int sign
);
104 static void main_reap_children(int sign
);
107 #define RPCAP_ACTIVE_WAIT 30 /* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */
110 \brief Prints the usage screen if it is launched in console mode.
112 static void printusage(void)
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";
141 (void)fprintf(stderr
, "RPCAPD, a remote packet capture daemon.\n"
142 "Compiled with %s\n\n", pcap_lib_version());
143 printf("%s", usagetext
);
149 int main(int argc
, char *argv
[])
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
156 struct sigaction action
;
164 memset(errbuf
, 0, sizeof(errbuf
));
166 if (sock_init(errbuf
, PCAP_ERRBUF_SIZE
) == -1)
168 SOCK_ASSERT(errbuf
, 1);
172 strncpy(address
, RPCAP_DEFAULT_NETADDR
, MAX_LINE
);
173 strncpy(port
, RPCAP_DEFAULT_NETPORT
, MAX_LINE
);
175 // Prepare to open a new server socket
176 memset(&mainhints
, 0, sizeof(struct addrinfo
));
178 mainhints
.ai_family
= PF_UNSPEC
;
179 mainhints
.ai_flags
= AI_PASSIVE
; // Ready to a bind() socket
180 mainhints
.ai_socktype
= SOCK_STREAM
;
182 // Getting the proper command line options
183 while ((retval
= getopt(argc
, argv
, "b:dhp:4l:na:s:f:v")) != -1)
188 strncpy(address
, optarg
, MAX_LINE
);
191 strncpy(port
, optarg
, MAX_LINE
);
194 mainhints
.ai_family
= PF_INET
; // IPv4 server only
207 strncpy(hostlist
, optarg
, sizeof(hostlist
));
212 char *tmpaddress
, *tmpport
;
216 tmpaddress
= pcap_strtok_r(optarg
, RPCAP_HOSTLIST_SEP
, &lasts
);
218 while ((tmpaddress
!= NULL
) && (i
< MAX_ACTIVE_LIST
))
220 tmpport
= pcap_strtok_r(NULL
, RPCAP_HOSTLIST_SEP
, &lasts
);
222 strlcpy(activelist
[i
].address
, tmpaddress
, MAX_LINE
);
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
);
227 strlcpy(activelist
[i
].port
, tmpport
, MAX_LINE
);
229 tmpaddress
= pcap_strtok_r(NULL
, RPCAP_HOSTLIST_SEP
, &lasts
);
234 if (i
> MAX_ACTIVE_LIST
)
235 SOCK_ASSERT("Only MAX_ACTIVE_LIST active connections are currently supported.", 1);
237 // I don't initialize the remaining part of the structure, since
238 // it is already zeroed (it is a global var)
242 strlcpy(loadfile
, optarg
, MAX_LINE
);
245 strlcpy(savefile
, optarg
, MAX_LINE
);
257 if (fileconf_save(savefile
))
258 SOCK_ASSERT("Error when saving the configuration to file", 1);
261 // If the file does not exist, it keeps the settings provided by the command line
267 // Create a handle to signal when the main loop is to shut down.
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.
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.
281 shutdown_event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
282 if (shutdown_event
== NULL
)
284 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
285 rpcapd_log(LOGPRIO_ERROR
, "Can't create shutdown event: %s",
291 // Catch control signals.
293 if (!SetConsoleCtrlHandler(main_ctrl_event
, TRUE
))
295 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
296 rpcapd_log(LOGPRIO_ERROR
, "Can't set control handler: %s",
301 memset(&action
, 0, sizeof (action
));
302 action
.sa_handler
= main_terminate
;
304 sigemptyset(&action
.sa_mask
);
305 sigaction(SIGTERM
, &action
, NULL
);
306 memset(&action
, 0, sizeof (action
));
307 action
.sa_handler
= main_reap_children
;
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
);
316 // forking a daemon, if it is needed
322 // Unix Network Programming, pg 336
323 if ((pid
= fork()) != 0)
324 exit(0); // Parent terminates
326 // First child continues
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
;
334 sigemptyset(&action
.sa_mask
);
335 sigaction(SIGHUP
, &action
, NULL
);
337 if ((pid
= fork()) != 0)
338 exit(0); // First child terminates
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
345 // Second child continues
349 // We use the SIGABRT signal to kill the Win32 service
350 signal(SIGABRT
, main_abort
);
352 // If this call succeeds, it is blocking on Win32
353 if (svc_start() != 1)
354 SOCK_ASSERT("Unable to start the service", 1);
356 // When the previous call returns, the entire application has to be stopped.
363 // Enable the catching of Ctrl+C
364 memset(&action
, 0, sizeof (action
));
365 action
.sa_handler
= main_terminate
;
367 sigemptyset(&action
.sa_mask
);
368 sigaction(SIGINT
, &action
, NULL
);
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
;
375 sigemptyset(&action
.sa_mask
);
376 sigaction(SIGHUP
, &action
, NULL
);
379 printf("Press CTRL + C to stop the server...\n");
382 // If we're a Win32 service, we have already called this function in the service_main
385 // The code should never arrive here (since the main_startup is blocking)
386 // however this avoids a compiler warning
390 void main_startup(void)
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
396 HANDLE threadId
; // handle for the subthread
403 memset(errbuf
, 0, sizeof(errbuf
));
405 // Starts all the active threads
406 while ((i
< MAX_ACTIVE_LIST
) && (activelist
[i
].address
[0] != 0))
408 activelist
[i
].ai_family
= mainhints
.ai_family
;
411 threadId
= (HANDLE
)_beginthreadex(NULL
, 0, main_active
,
412 (void *)&activelist
[i
], 0, NULL
);
415 SOCK_ASSERT("Error creating the active child threads", 1);
418 CloseHandle(threadId
);
420 if ((pid
= fork()) == 0) // I am the child
422 main_active((void *) &activelist
[i
]);
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.
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.
443 struct addrinfo
*tempaddrinfo
;
446 // Get a list of sockets on which to listen.
448 if (sock_initaddress((address
[0]) ? address
: NULL
, port
, &mainhints
, &addrinfo
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
450 SOCK_ASSERT(errbuf
, 1);
454 for (tempaddrinfo
= addrinfo
; tempaddrinfo
;
455 tempaddrinfo
= tempaddrinfo
->ai_next
)
458 struct listen_sock
*sock_info
;
460 if ((sock
= sock_open(tempaddrinfo
, SOCKOPEN_SERVER
, SOCKET_MAXCONN
, errbuf
, PCAP_ERRBUF_SIZE
)) == INVALID_SOCKET
)
462 SOCK_ASSERT(errbuf
, 1);
466 sock_info
= (struct listen_sock
*) malloc(sizeof (struct listen_sock
));
467 if (sock_info
== NULL
)
469 rpcapd_log(LOGPRIO_ERROR
, "Can't allocate structure for listen socket");
472 sock_info
->sock
= sock
;
473 sock_info
->next
= listen_socks
;
474 listen_socks
= sock_info
;
477 freeaddrinfo(addrinfo
);
480 // Now listen on all of them, waiting for connections.
482 accept_connections();
488 SOCK_ASSERT(PROGRAM_NAME
" is closing.\n", 1);
492 // Sends a KILL signal to all the processes in this process's
493 // process group; i.e., it kills all the child processes
496 // XXX - that also includes us, so we will be killed as well;
497 // that may cause a message to be printed or logged.
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
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
518 static BOOL WINAPI
main_ctrl_event(DWORD ctrltype
)
520 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // keeps the error string, prior to be printed
523 // ctrltype is one of:
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
530 // CTRL_SHUTDOWN_EVENT - the systemis shutting down; this is
531 // received only by services
533 // For now, we treat all but CTRL_LOGOFF_EVENT as indications
534 // that we should shut down.
539 case CTRL_BREAK_EVENT
:
540 case CTRL_CLOSE_EVENT
:
541 case CTRL_SHUTDOWN_EVENT
:
543 // Set the shutdown event.
544 // That will wake up WSAWaitForMultipleEvents().
546 if (!SetEvent(shutdown_event
))
548 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
549 rpcapd_log(LOGPRIO_ERROR
, "SetEvent on shutdown event failed: %s", errbuf
);
563 static void main_terminate(int sign
)
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.
573 static void main_reread_config(int sign
)
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.
585 static void main_abort(int sign
)
587 struct listen_sock
*sock_info
;
589 SOCK_ASSERT(PROGRAM_NAME
" is closing due to a SIGABRT.\n", 1);
592 // XXX - there should be a way to poke the main thread to get
593 // it to shut down the service.
597 // Close all the listen sockets.
599 for (sock_info
= listen_socks
; sock_info
; sock_info
= sock_info
->next
)
601 closesocket(sock_info
->sock
);
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.
617 static void main_reap_children(int sign
)
622 // Reap all child processes that have exited.
623 // For reference, Stevens, pg 128
625 while ((pid
= waitpid(-1, &exitstat
, WNOHANG
)) > 0)
626 SOCK_ASSERT("Child terminated", 1);
633 // Loop waiting for incoming connections and accepting them.
636 accept_connections(void)
639 struct listen_sock
*sock_info
;
643 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // keeps the error string, prior to be printed
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.
650 num_events
= 1; // shutdown event
651 for (sock_info
= listen_socks
; sock_info
;
652 sock_info
= sock_info
->next
)
654 if (num_events
== WSA_MAXIMUM_WAIT_EVENTS
)
657 // WSAWaitForMultipleEvents() doesn't support
658 // more than WSA_MAXIMUM_WAIT_EVENTS events
661 rpcapd_log(LOGPRIO_ERROR
, "Too many sockets on which to listen");
668 // Allocate the array of events.
670 events
= (WSAEVENT
*) malloc(num_events
* sizeof (WSAEVENT
));
673 rpcapd_log(LOGPRIO_ERROR
, "Can't allocate array of events which to listen");
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
++)
687 // Create an event that is signaled if there's a connection
688 // to accept on the socket in question.
690 event
= WSACreateEvent();
691 if (event
== WSA_INVALID_EVENT
)
693 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
694 rpcapd_log(LOGPRIO_ERROR
, "Can't create socket event: %s", errbuf
);
697 if (WSAEventSelect(sock_info
->sock
, event
, FD_ACCEPT
) == SOCKET_ERROR
)
699 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
700 rpcapd_log(LOGPRIO_ERROR
, "Can't setup socket event: %s", errbuf
);
709 // Wait for incoming connections.
713 ret
= WSAWaitForMultipleEvents(num_events
, events
, FALSE
,
714 WSA_INFINITE
, FALSE
);
715 if (ret
== WSA_WAIT_FAILED
)
717 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
718 rpcapd_log(LOGPRIO_ERROR
, "WSAWaitForMultipleEvents failed: %s", errbuf
);
723 // Check the shutdown event.
725 if (WaitForSingleObject(shutdown_event
, 0) == WAIT_OBJECT_0
)
729 // Clear the event, for cleanliness.
731 if (!ResetEvent(shutdown_event
))
733 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
734 rpcapd_log(LOGPRIO_ERROR
, "ResetEvent on shutdown event failed: %s", errbuf
);
738 // Exit the loop, so we quit.
744 // Check each socket.
746 for (sock_info
= listen_socks
, i
= 1; sock_info
;
747 sock_info
= sock_info
->next
, i
++)
749 WSANETWORKEVENTS network_events
;
751 if (WSAEnumNetworkEvents(sock_info
->sock
,
752 events
[i
], &network_events
) == SOCKET_ERROR
)
754 sock_geterror(NULL
, errbuf
, PCAP_ERRBUF_SIZE
);
755 rpcapd_log(LOGPRIO_ERROR
, "WSAEnumNetworkEvents failed: %s", errbuf
);
758 if (network_events
.lNetworkEvents
& FD_ACCEPT
)
761 // Did an error occur?
763 if (network_events
.iErrorCode
[FD_ACCEPT_BIT
] != 0)
766 // Yes - report it and keep going.
769 network_events
.iErrorCode
[FD_ACCEPT_BIT
],
772 rpcapd_log(LOGPRIO_ERROR
, "Socket error: %s", errbuf
);
777 // Accept the connection.
779 accept_connection(sock_info
->sock
);
784 struct listen_sock
*sock_info
;
788 // How big does the bitset of sockets on which to select() have
792 for (sock_info
= listen_socks
; sock_info
; sock_info
= sock_info
->next
)
794 if (sock_info
->sock
+ 1 > num_sock_fds
)
796 if (sock_info
->sock
+ 1 > FD_SETSIZE
)
798 rpcapd_log(LOGPRIO_ERROR
, "Socket FD is too bit for an fd_set");
801 num_sock_fds
= sock_info
->sock
+ 1;
811 // Set up an fd_set for all the sockets on which we're
814 // This set is modified by select(), so we have to
815 // construct it anew each time.
818 for (sock_info
= listen_socks
; sock_info
;
819 sock_info
= sock_info
->next
)
821 FD_SET(sock_info
->sock
, &sock_fds
);
825 // Wait for incoming connections.
827 ret
= select(num_sock_fds
, &sock_fds
, NULL
, NULL
, NULL
);
833 // If this is a "terminate the
834 // server" signal, exit the loop,
835 // otherwise just keep trying.
843 // This is a "re-read the
844 // configuration file"
857 rpcapd_log(LOGPRIO_ERROR
, "select failed: %s",
864 // Check each socket.
866 for (sock_info
= listen_socks
; sock_info
;
867 sock_info
= sock_info
->next
)
869 if (FD_ISSET(sock_info
->sock
, &sock_fds
))
872 // Accept the connection.
874 accept_connection(sock_info
->sock
);
882 // Accept a connection and start a worker thread, on Windows, or a
883 // worker process, on UN*X, to handle the connection.
886 accept_connection(SOCKET listen_sock
)
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
894 HANDLE threadId
; // handle for the subthread
898 struct daemon_slpars
*pars
; // parameters needed by the daemon_serviceloop()
901 memset(errbuf
, 0, sizeof(errbuf
));
905 // Accept the connection
906 fromlen
= sizeof(struct sockaddr_storage
);
908 sockctrl
= accept(listen_sock
, (struct sockaddr
*) &from
, &fromlen
);
910 if (sockctrl
!= INVALID_SOCKET
)
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
920 if (WSAGetLastError() == WSAEINTR
)
926 // Don't check for errors here, since the error can be due to the fact that the thread
928 sock_geterror("accept(): ", errbuf
, PCAP_ERRBUF_SIZE
);
929 rpcapd_log(LOGPRIO_ERROR
, "Accept of control connection from client failed: %s",
935 // We have a connection.
936 // Check whether the connecting host is among the ones allowed.
938 if (sock_check_hostlist(hostlist
, RPCAP_HOSTLIST_SEP
, &from
, errbuf
, PCAP_ERRBUF_SIZE
) < 0)
940 rpcap_senderror(sockctrl
, 0, PCAP_ERR_HOSTNOAUTH
, errbuf
, NULL
);
941 sock_close(sockctrl
, NULL
, 0);
947 // in case of passive mode, this variable is deallocated by the daemon_serviceloop()
948 pars
= (struct daemon_slpars
*) malloc (sizeof(struct daemon_slpars
));
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);
958 pars
->sockctrl
= sockctrl
;
959 pars
->activeclose
= 0; // useless in passive mode
961 pars
->nullAuthAllowed
= nullAuthAllowed
;
963 threadId
= (HANDLE
)_beginthreadex(NULL
, 0, daemon_serviceloop
,
964 (void *) pars
, 0, NULL
);
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);
972 CloseHandle(threadId
);
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);
986 // This is passive mode, so this variable is deallocated
987 // by the daemon_serviceloop().
989 pars
= (struct daemon_slpars
*) malloc (sizeof(struct daemon_slpars
));
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);
998 pars
->sockctrl
= sockctrl
;
999 pars
->activeclose
= 0; // useless in passive mode
1001 pars
->nullAuthAllowed
= nullAuthAllowed
;
1004 // Close the socket on which we're listening (must
1005 // be open only in the parent).
1007 closesocket(listen_sock
);
1010 // Run the service loop.
1012 daemon_serviceloop((void *) pars
);
1017 // Close the socket for this session (must be open only in the child)
1018 closesocket(sockctrl
);
1023 \brief 'true' main of the program in case the active mode is turned on.
1025 This function loops forever trying to connect to the remote host, until the
1026 daemon is turned down.
1028 \param ptr: it keeps the 'activepars' parameters. It is a 'void *'
1029 just because the thread APIs want this format.
1032 static unsigned __stdcall
1036 main_active(void *ptr
)
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()
1045 activepars
= (struct active_pars
*) ptr
;
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
;
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);
1059 // Initialize errbuf
1060 memset(errbuf
, 0, sizeof(errbuf
));
1063 if (sock_initaddress(activepars
->address
, activepars
->port
, &hints
, &addrinfo
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1065 SOCK_ASSERT(errbuf
, 1);
1073 if ((sockctrl
= sock_open(addrinfo
, SOCKOPEN_CLIENT
, 0, errbuf
, PCAP_ERRBUF_SIZE
)) == INVALID_SOCKET
)
1075 SOCK_ASSERT(errbuf
, 1);
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");
1081 SOCK_ASSERT(errbuf
, 1);
1083 sleep_secs(RPCAP_ACTIVE_WAIT
);
1088 pars
= (struct daemon_slpars
*) malloc (sizeof(struct daemon_slpars
));
1091 pcap_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
,
1092 errno
, "malloc() failed");
1096 pars
->sockctrl
= sockctrl
;
1097 pars
->activeclose
= 0;
1099 pars
->nullAuthAllowed
= nullAuthAllowed
;
1101 daemon_serviceloop((void *) pars
);
1103 activeclose
= pars
->activeclose
;
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)
1113 freeaddrinfo(addrinfo
);