+

  "Fossies" - the Free Open Source Software Archive  

Member "libpcap-1.10.5/./rpcapd/rpcapd.c" (30 Aug 2024, 38503 Bytes) of package /linux/misc/libpcap-1.10.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rpcapd.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.10.4_vs_1.10.5.

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