rpcapd.c 34 KB

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