]> The Tcpdump Group git mirrors - libpcap/commitdiff
Merge pull request #685 from jmayer/add-static
authorGuy Harris <[email protected]>
Mon, 2 Apr 2018 07:44:47 +0000 (00:44 -0700)
committerGitHub <[email protected]>
Mon, 2 Apr 2018 07:44:47 +0000 (00:44 -0700)
Declare some variables static (found via -Wmissing-variable-declarations)

1  2 
rpcapd/rpcapd.c

diff --combined rpcapd/rpcapd.c
index 8c1ca3eefd430793bada1e7497e1cfd2019383af,c46e3106963a0e92cf222f7e3b33951b8305803b..21217c8b09aef68a5770cf620e78b758e54e0884
@@@ -46,7 -46,6 +46,7 @@@
  #include "sockutils.h"                // for socket calls
  #include "portability.h"
  #include "rpcapd.h"
 +#include "config_params.h"    // configuration file parameters
  #include "fileconf.h"         // for the configuration file management
  #include "rpcap-protocol.h"
  #include "daemon.h"           // the true main() method of this daemon
@@@ -57,7 -56,6 +57,7 @@@
    #include "win32-svc.h"      // for Win32 service stuff
    #include "getopt.h"         // for getopt()-for-Windows
  #else
 +  #include <fcntl.h>          // for open()
    #include <unistd.h>         // for exit()
    #include <sys/wait.h>               // waitpid()
  #endif
@@@ -72,19 -70,20 +72,19 @@@ struct listen_sock 
  
  // Global variables
  char hostlist[MAX_HOST_LIST + 1];             //!< Keeps the list of the hosts that are allowed to connect to this server
- struct active_pars activelist[MAX_ACTIVE_LIST];               //!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode)
+ struct active_pars activelist[MAX_ACTIVE_LIST];       //!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode)
  int nullAuthAllowed;                          //!< '1' if we permit NULL authentication, '0' otherwise
  static struct listen_sock *listen_socks;      //!< sockets on which we listen
  char loadfile[MAX_LINE + 1];                  //!< Name of the file from which we have to load the configuration
int passivemode = 1;                          //!< '1' if we want to run in passive mode as well
- struct addrinfo mainhints;                    //!< temporary struct to keep settings needed to open the new socket
char address[MAX_LINE + 1];                   //!< keeps the network address (either numeric or literal) to bind to
char port[MAX_LINE + 1];                      //!< keeps the network port to bind to
static int passivemode = 1;                   //!< '1' if we want to run in passive mode as well
+ static struct addrinfo mainhints;             //!< temporary struct to keep settings needed to open the new socket
static char address[MAX_LINE + 1];            //!< keeps the network address (either numeric or literal) to bind to
static char port[MAX_LINE + 1];                       //!< keeps the network port to bind to
  #ifdef _WIN32
 -static HANDLE shutdown_event;                 //!< event to signal to shut down the main loop
 -#else
 +static HANDLE state_change_event;             //!< event to signal that a state change should take place
 +#endif
  static volatile sig_atomic_t shutdown_server; //!< '1' if the server is to shut down
  static volatile sig_atomic_t reread_config;   //!< '1' if the server is to re-read its configuration
 -#endif
  
  extern char *optarg;  // for getopt()
  
@@@ -102,9 -101,6 +102,9 @@@ static void accept_connection(SOCKET li
  #ifndef _WIN32
  static void main_reap_children(int sign);
  #endif
 +#ifdef _WIN32
 +static unsigned __stdcall main_passive_serviceloop_thread(void *ptr);
 +#endif
  
  #define RPCAP_ACTIVE_WAIT 30          /* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */
  
@@@ -116,11 -112,7 +116,11 @@@ static void printusage(void
        char *usagetext =
        "USAGE:"
        " "  PROGRAM_NAME " [-b <address>] [-p <port>] [-4] [-l <host_list>] [-a <host,port>]\n"
 -      "              [-n] [-v] [-d] [-s <file>] [-f <file>]\n\n"
 +      "              [-n] [-v] [-d] "
 +#ifndef _WIN32
 +      "[-i] "
 +#endif
 +      "[-s <file>] [-f <file>]\n\n"
        "  -b <address>    the address to bind to (either numeric or literal).\n"
        "                  Default: binds to all local IPv4 and IPv6 addresses\n\n"
        "  -p <port>       the port to bind to.\n"
        "  -4              use only IPv4.\n"
        "                  Default: use both IPv4 and IPv6 waiting sockets\n\n"
        "  -l <host_list>  a file that contains a list of hosts that are allowed\n"
 -      "                  to connect to this server (if more than one, list them one per line).\n"
 -      "                  We suggest to use literal names (instead of numeric ones) in\n"
 -      "                  order to avoid problems with different address families.\n\n"
 +      "                  to connect to this server (if more than one, list them one\n"
 +      "                  per line).\n"
 +      "                  We suggest to use literal names (instead of numeric ones)\n"
 +      "                  in order to avoid problems with different address families.\n\n"
        "  -n              permit NULL authentication (usually used with '-l')\n\n"
        "  -a <host,port>  run in active mode when connecting to 'host' on port 'port'\n"
        "                  In case 'port' is omitted, the default port (" RPCAP_DEFAULT_NETPORT_ACTIVE ") is used\n\n"
 -      "  -v              run in active mode only (default: if '-a' is specified, it accepts\n"
 -      "                  passive connections as well\n\n"
 +      "  -v              run in active mode only (default: if '-a' is specified, it\n"
 +      "                  accepts passive connections as well)\n\n"
        "  -d              run in daemon mode (UNIX only) or as a service (Win32 only)\n"
 -      "                  Warning (Win32): this switch is provided automatically when the service\n"
 -      "                  is started from the control panel\n\n"
 +      "                  Warning (Win32): this switch is provided automatically when\n"
 +      "                  the service is started from the control panel\n\n"
 +#ifndef _WIN32
 +      "  -i              run in inetd mode (UNIX only)\n\n"
 +#endif
        "  -s <file>       save the current configuration to file\n\n"
        "  -f <file>       load the current configuration from file; all switches\n"
        "                  specified from the command line are ignored\n\n"
  int main(int argc, char *argv[])
  {
        char savefile[MAX_LINE + 1];            // name of the file on which we have to save the configuration
 -      int isdaemon = 0;                       // Not null if the user wants to run this program as a daemon
 +      int isdaemon = 0;                       // Non-zero if the user wants to run this program as a daemon
 +#ifndef _WIN32
 +      int isrunbyinetd = 0;                   // Non-zero if this is being run by inetd or something inetd-like
 +#endif
        int retval;                             // keeps the returning value from several functions
        char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
  #ifndef _WIN32
  
        if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
 -              SOCK_ASSERT(errbuf, 1);
 +              SOCK_DEBUG_MESSAGE(errbuf);
                exit(-1);
        }
  
        mainhints.ai_socktype = SOCK_STREAM;
  
        // Getting the proper command line options
 -      while ((retval = getopt(argc, argv, "b:dhp:4l:na:s:f:v")) != -1)
 +      while ((retval = getopt(argc, argv, "b:dhip:4l:na:s:f:v")) != -1)
        {
                switch (retval)
                {
                        case 'd':
                                isdaemon = 1;
                                break;
 +                      case 'i':
 +#ifdef _WIN32
 +                              printusage();
 +                              exit(1);
 +#else
 +                              isrunbyinetd = 1;
 +#endif
 +                              break;
                        case 'n':
                                nullAuthAllowed = 1;
                                break;
                                }
  
                                if (i > MAX_ACTIVE_LIST)
 -                                      SOCK_ASSERT("Only MAX_ACTIVE_LIST active connections are currently supported.", 1);
 +                                      SOCK_DEBUG_MESSAGE("Only MAX_ACTIVE_LIST active connections are currently supported.");
  
                                // I don't initialize the remaining part of the structure, since
                                // it is already zeroed (it is a global var)
                        case 'h':
                                printusage();
                                exit(0);
 +                              break;
                        default:
 +                              exit(1);
                                break;
                }
        }
  
 -      if (savefile[0])
 +#ifndef _WIN32
 +      if (isdaemon && isrunbyinetd)
        {
 -              if (fileconf_save(savefile))
 -                      SOCK_ASSERT("Error when saving the configuration to file", 1);
 +              fprintf(stderr, "rpcapd: -d and -i can't be used together\n");
 +              exit(1);
        }
 +#endif
 +
 +      if (savefile[0] && fileconf_save(savefile))
 +              SOCK_DEBUG_MESSAGE("Error when saving the configuration to file");
  
        // If the file does not exist, it keeps the settings provided by the command line
        if (loadfile[0])
  
  #ifdef WIN32
        //
 -      // Create a handle to signal when the main loop is to shut down.
 -      //
 -      // Events are a bit annoying if you're waiting for multiple
 -      // events; unlike UN*X select() and poll(), which indicate
 -      // which FDs are available, WaitForMultipleObjects() and
 -      // WSAWaitForMultipleEvents() don't give you an indication
 -      // of *all* of the events that are signaled, they just tell
 -      // you the first one that's signaled.
 -      //
 -      // Therefore, we must use WaitForSingleObject() to test
 -      // this event; that means it must not be auto-reset,
 -      // as that means that once WSAWaitForMultipleEvents() is
 -      // woken up, it's no longer signaled.
 +      // Create a handle to signal the main loop to tell it to do
 +      // something.
        //
 -      shutdown_event = CreateEvent(NULL, TRUE, FALSE, NULL);
 -      if (shutdown_event == NULL)
 +      state_change_event = CreateEvent(NULL, FALSE, FALSE, NULL);
 +      if (state_change_event == NULL)
        {
                sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
 -              rpcapd_log(LOGPRIO_ERROR, "Can't create shutdown event: %s",
 +              rpcapd_log(LOGPRIO_ERROR, "Can't create state change event: %s",
                    errbuf);
                exit(2);
        }
        signal(SIGPIPE, SIG_IGN);
  #endif
  
 -      // forking a daemon, if it is needed
 +#ifndef _WIN32
 +      if (isrunbyinetd)
 +      {
 +              //
 +              // -i was specified, indicating that this is being run
 +              // by inetd or something that can run network daemons
 +              // as if it were inetd (xinetd, launchd, systemd, etc.).
 +              //
 +              // Our standard input is the input side of a connection,
 +              // and our standard output is the output side of a
 +              // connection.
 +              //
 +              int sockctrl_in, sockctrl_out;
 +              int devnull_fd;
 +
 +              //
 +              // Duplicate the standard input and output, making them
 +              // the input and output side of the control connection.
 +              //
 +              sockctrl_in = dup(0);
 +              if (sockctrl_in == -1)
 +              {
 +                      sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
 +                      rpcapd_log(LOGPRIO_ERROR, "Can't dup standard input: %s",
 +                          errbuf);
 +                      exit(2);
 +              }
 +              sockctrl_out = dup(1);
 +              if (sockctrl_out == -1)
 +              {
 +                      sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
 +                      rpcapd_log(LOGPRIO_ERROR, "Can't dup standard output: %s",
 +                          errbuf);
 +                      exit(2);
 +              }
 +
 +              //
 +              // Try to set the standard input and output to /dev/null.
 +              //
 +              devnull_fd = open("/dev/null", O_RDWR);
 +              if (devnull_fd != -1)
 +              {
 +                      //
 +                      // If this fails, just drive on.
 +                      //
 +                      (void)dup2(devnull_fd, 0);
 +                      (void)dup2(devnull_fd, 1);
 +                      close(devnull_fd);
 +              }
 +
 +              //
 +              // Handle this client.
 +              // This is passive mode, so we don't care whether we were
 +              // told by the client to close.
 +              //
 +              (void)daemon_serviceloop(sockctrl_in, sockctrl_out, 0,
 +                  nullAuthAllowed);
 +
 +              //
 +              // Nothing more to do.
 +              //
 +              exit(0);
 +      }
 +#endif
 +
        if (isdaemon)
        {
 +              //
 +              // This is being run as a daemon.
 +              // On UN*X, it might be manually run, or run from an
 +              // rc file.
 +              //
  #ifndef _WIN32
                int pid;
  
 +              //
 +              // Daemonize ourselves.
 +              //
                // Unix Network Programming, pg 336
 +              //
                if ((pid = fork()) != 0)
                        exit(0);                // Parent terminates
  
  //            umask(0);
  //            chdir("/");
  #else
 +              //
 +              // This is being run as a service on Windows.
 +              //
                // If this call succeeds, it is blocking on Win32
 +              //
                if (svc_start() != 1)
 -                      SOCK_ASSERT("Unable to start the service", 1);
 +                      SOCK_DEBUG_MESSAGE("Unable to start the service");
  
                // When the previous call returns, the entire application has to be stopped.
                exit(0);
@@@ -503,7 -407,7 +503,7 @@@ void main_startup(void
                    (void *)&activelist[i], 0, NULL);
                if (threadId == 0)
                {
 -                      SOCK_ASSERT("Error creating the active child threads", 1);
 +                      SOCK_DEBUG_MESSAGE("Error creating the active child threads");
                        continue;
                }
                CloseHandle(threadId);
                //
                if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
                {
 -                      SOCK_ASSERT(errbuf, 1);
 +                      SOCK_DEBUG_MESSAGE(errbuf);
                        return;
                }
  
  
                        if ((sock = sock_open(tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
                        {
 -                              SOCK_ASSERT(errbuf, 1);
 +                              SOCK_DEBUG_MESSAGE(errbuf);
                                continue;
                        }
  
        //
        // We're done; exit.
        //
 -      SOCK_ASSERT(PROGRAM_NAME " is closing.\n", 1);
 +      SOCK_DEBUG_MESSAGE(PROGRAM_NAME " is closing.\n");
  
  #ifndef _WIN32
        //
  }
  
  #ifdef _WIN32
 -void
 -send_shutdown_event(void)
 +static void
 +send_state_change_event(void)
  {
        char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
  
 -      if (!SetEvent(shutdown_event))
 +      if (!SetEvent(state_change_event))
        {
                sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
                rpcapd_log(LOGPRIO_ERROR, "SetEvent on shutdown event failed: %s", errbuf);
        }
  }
  
 +void
 +send_shutdown_notification(void)
 +{
 +      //
 +      // Indicate that the server should shut down.
 +      //
 +      shutdown_server = 1;
 +
 +      //
 +      // Send a state change event, to wake up WSAWaitForMultipleEvents().
 +      //
 +      send_state_change_event();
 +}
 +
 +void
 +send_reread_configuration_notification(void)
 +{
 +      //
 +      // Indicate that the server should re-read its configuration file.
 +      //
 +      reread_config = 1;
 +
 +      //
 +      // Send a state change event, to wake up WSAWaitForMultipleEvents().
 +      //
 +      send_state_change_event();
 +}
 +
  static BOOL WINAPI main_ctrl_event(DWORD ctrltype)
  {
        //
                case CTRL_CLOSE_EVENT:
                case CTRL_SHUTDOWN_EVENT:
                        //
 -                      // Set the shutdown event.
 -                      // That will wake up WSAWaitForMultipleEvents().
 +                      // Set a shutdown notification.
                        //
 -                      send_shutdown_event();
 +                      send_shutdown_notification();
                        break;
  
                default:
@@@ -710,7 -587,9 +710,7 @@@ static void main_reread_config(int sign
        //
        reread_config = 1;
  }
 -#endif
  
 -#ifndef _WIN32
  static void main_reap_children(int sign)
  {
        pid_t pid;
        // For reference, Stevens, pg 128
  
        while ((pid = waitpid(-1, &exitstat, WNOHANG)) > 0)
 -              SOCK_ASSERT("Child terminated", 1);
 +              SOCK_DEBUG_MESSAGE("Child terminated");
  
        return;
  }
@@@ -774,7 -653,7 +774,7 @@@ accept_connections(void
        //
        // Fill it in.
        //
 -      events[0] = shutdown_event;     // shutdown event first
 +      events[0] = state_change_event; // state change event first
        for (sock_info = listen_socks, i = 1; sock_info;
            sock_info = sock_info->next, i++)
        {
                        exit(2);
                }
  
 -              //
 -              // Check the shutdown event.
 -              //
 -              if (WaitForSingleObject(shutdown_event, 0) == WAIT_OBJECT_0)
 +              if (ret == WSA_WAIT_EVENT_0)
                {
                        //
 -                      // Time to quit.
 -                      // Clear the event, for cleanliness.
 +                      // The state change event was set.
                        //
 -                      if (!ResetEvent(shutdown_event))
 +                      if (shutdown_server)
                        {
 -                              sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
 -                              rpcapd_log(LOGPRIO_ERROR, "ResetEvent on shutdown event failed: %s", errbuf);
 +                              //
 +                              // Time to quit. Exit the loop.
 +                              //
 +                              break;
 +                      }
 +                      if (reread_config)
 +                      {
 +                              //
 +                              // We should re-read the configuration
 +                              // file.
 +                              //
 +                              reread_config = 0;      // clear the indicator
 +                              fileconf_read();
                        }
 -
 -                      //
 -                      // Exit the loop, so we quit.
 -                      //
 -                      break;
                }
  
                //
                                // otherwise just keep trying.
                                //
                                if (shutdown_server)
 +                              {
 +                                      //
 +                                      // Time to quit.  Exit the loop.
 +                                      //
                                        break;
 -                              else {
 -                                      if (reread_config)
 -                                      {
 -                                              //
 -                                              // This is a "re-read the
 -                                              // configuration file"
 -                                              // signal.  Clear the
 -                                              // flag and re-read
 -                                              // the file.
 -                                              //
 -                                              reread_config = 0;
 -                                              fileconf_read();
 -                                      }
 -                                      continue;
                                }
 +                              if (reread_config)
 +                              {
 +                                      //
 +                                      // We should re-read the configuration
 +                                      // file.
 +                                      //
 +                                      reread_config = 0;      // clear the indicator
 +                                      fileconf_read();
 +                              }
 +
 +                              //
 +                              // Go back and wait again.
 +                              //
 +                              continue;
                        }
                        else
                        {
@@@ -1005,10 -878,10 +1005,10 @@@ accept_connection(SOCKET listen_sock
  #ifdef _WIN32
        HANDLE threadId;                        // handle for the subthread
        u_long off = 0;
 +      SOCKET *sockctrl_temp;
  #else
        pid_t pid;
  #endif
 -      struct daemon_slpars *pars;     // parameters needed by the daemon_serviceloop()
  
        // Initialize errbuf
        memset(errbuf, 0, sizeof(errbuf));
                return;
        }
  
 -      // in case of passive mode, this variable is deallocated by the daemon_serviceloop()
 -      pars = (struct daemon_slpars *) malloc (sizeof(struct daemon_slpars));
 -      if (pars == NULL)
 +      //
 +      // Allocate a location to hold the value of sockctrl.
 +      // It will be freed in the newly-created thread once it's
 +      // finished with it.
 +      // I guess we *could* just cast sockctrl to a void *, but that's
 +      // a bit ugly.
 +      //
 +      sockctrl_temp = (SOCKET *)malloc(sizeof (SOCKET));
 +      if (sockctrl_temp == NULL)
        {
                pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
                    errno, "malloc() failed");
                sock_close(sockctrl, NULL, 0);
                return;
        }
 +      *sockctrl_temp = sockctrl;
  
 -      pars->sockctrl = sockctrl;
 -      pars->activeclose = 0;          // useless in passive mode
 -      pars->isactive = 0;
 -      pars->nullAuthAllowed = nullAuthAllowed;
 -
 -      threadId = (HANDLE)_beginthreadex(NULL, 0, daemon_serviceloop,
 -          (void *) pars, 0, NULL);
 +      threadId = (HANDLE)_beginthreadex(NULL, 0,
 +          main_passive_serviceloop_thread, (void *) sockctrl_temp, 0, NULL);
        if (threadId == 0)
        {
                pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the child thread");
                rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
                sock_close(sockctrl, NULL, 0);
 +              free(sockctrl_temp);
                return;
        }
        CloseHandle(threadId);
        {
                //
                // Child process.
 -              // This is passive mode, so this variable is deallocated
 -              // by the daemon_serviceloop().
 -              //
 -              pars = (struct daemon_slpars *) malloc (sizeof(struct daemon_slpars));
 -              if (pars == NULL)
 -              {
 -                      pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Can't allocate memory for the child process");
 -                      rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
 -                      sock_close(sockctrl, NULL, 0);
 -                      return;
 -              }
 -
 -              pars->sockctrl = sockctrl;
 -              pars->activeclose = 0;          // useless in passive mode
 -              pars->isactive = 0;
 -              pars->nullAuthAllowed = nullAuthAllowed;
 -
                //
                // Close the socket on which we're listening (must
                // be open only in the parent).
                //
                closesocket(listen_sock);
  
 +#if 0
 +              //
 +              // Modify thread params so that it can be killed at any time
 +              // XXX - is this necessary?  This is the main and, currently,
 +              // only thread in the child process, and nobody tries to
 +              // cancel us, although *we* may cancel the thread that's
 +              // handling the capture loop.
 +              //
 +              if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL))
 +                      goto end;
 +              if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL))
 +                      goto end;
 +#endif
 +
                //
                // Run the service loop.
 +              // This is passive mode, so we don't care whether we were
 +              // told by the client to close.
                //
 -              daemon_serviceloop((void *) pars);
 +              (void)daemon_serviceloop(sockctrl, sockctrl, 0,
 +                  nullAuthAllowed);
 +
 +              close(sockctrl);
 +
                exit(0);
        }
  
@@@ -1182,6 -1049,7 +1182,6 @@@ main_active(void *ptr
        struct addrinfo hints;                  // temporary struct to keep settings needed to open the new socket
        struct addrinfo *addrinfo;              // keeps the addrinfo chain; required to open a new socket
        struct active_pars *activepars;
 -      struct daemon_slpars *pars;             // parameters needed by the daemon_serviceloop()
  
        activepars = (struct active_pars *) ptr;
  
        pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Connecting to host %s, port %s, using protocol %s",
                        activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
                        (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
 -      SOCK_ASSERT(errbuf, 1);
 +      SOCK_DEBUG_MESSAGE(errbuf);
  
        // Initialize errbuf
        memset(errbuf, 0, sizeof(errbuf));
        // Do the work
        if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
 -              SOCK_ASSERT(errbuf, 1);
 +              SOCK_DEBUG_MESSAGE(errbuf);
                return 0;
        }
  
  
                if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
                {
 -                      SOCK_ASSERT(errbuf, 1);
 +                      SOCK_DEBUG_MESSAGE(errbuf);
  
                        pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
                                        activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
                                        (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
  
 -                      SOCK_ASSERT(errbuf, 1);
 +                      SOCK_DEBUG_MESSAGE(errbuf);
  
                        sleep_secs(RPCAP_ACTIVE_WAIT);
  
                        continue;
                }
  
 -              pars = (struct daemon_slpars *) malloc (sizeof(struct daemon_slpars));
 -              if (pars == NULL)
 -              {
 -                      pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
 -                          errno, "malloc() failed");
 -                      continue;
 -              }
 +              activeclose = daemon_serviceloop(sockctrl, sockctrl, 1,
 +                  nullAuthAllowed);
  
 -              pars->sockctrl = sockctrl;
 -              pars->activeclose = 0;
 -              pars->isactive = 1;
 -              pars->nullAuthAllowed = nullAuthAllowed;
 -
 -              daemon_serviceloop((void *) pars);
 -
 -              activeclose = pars->activeclose;
 -
 -              free(pars);
 +              sock_close(sockctrl, NULL, 0);
  
                // If the connection is closed by the user explicitely, don't try to connect to it again
                // just exit the program
        freeaddrinfo(addrinfo);
        return 0;
  }
 +
 +#ifdef _WIN32
 +//
 +// Main routine of a passive-mode service thread.
 +//
 +unsigned __stdcall main_passive_serviceloop_thread(void *ptr)
 +{
 +      SOCKET sockctrl;
 +
 +      sockctrl = *((SOCKET *)ptr);
 +      free(ptr);
 +
 +      //
 +      // Handle this client.
 +      // This is passive mode, so we don't care whether we were
 +      // told by the client to close.
 +      //
 +      (void)daemon_serviceloop(sockctrl, sockctrl, 0, nullAuthAllowed);
 +
 +      sock_close(sockctrl, NULL, 0);
 +
 +      return 0;
 +}
 +#endif