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 1434