]> The Tcpdump Group git mirrors - libpcap/blob - rpcapd/rpcapd.c
d1df031d5533a7eecfe608e6b14e4bd3c58f2a4b
[libpcap] / rpcapd / rpcapd.c
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 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #ifdef _WIN32
38 #define USE_THREADS // threads vs. subprocesses
39 #endif
40
41 #include <errno.h> // for the errno variable
42 #include <string.h> // for strtok, etc
43 #include <stdlib.h> // for malloc(), free(), ...
44 #include <pcap.h> // for PCAP_ERRBUF_SIZE
45 #include <signal.h> // for signal()
46 #include <pthread.h>
47
48 #include "portability.h"
49 #include "rpcapd.h"
50 #include "fileconf.h" // for the configuration file management
51 #include "sockutils.h" // for socket calls
52 #include "rpcap-protocol.h"
53 #include "pcap-rpcap-int.h"
54 #include "daemon.h" // the true main() method of this daemon
55 #include "utils.h" // Missing calls and such
56
57 #ifdef _WIN32
58 #include "win32-svc.h" // for Win32 service stuff
59 #else
60 #include <unistd.h> // for exit()
61 #include <sys/wait.h> // waitpid()
62 #endif
63
64
65 // Global variables
66 char hostlist[MAX_HOST_LIST + 1]; //!< Keeps the list of the hosts that are allowed to connect to this server
67 struct active_pars activelist[MAX_ACTIVE_LIST]; //!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode)
68 int nullAuthAllowed; //!< '1' if we permit NULL authentication, '0' otherwise
69 static SOCKET sockmain; //!< keeps the main socket identifier
70 char loadfile[MAX_LINE + 1]; //!< Name of the file from which we have to load the configuration
71 int passivemode = 1; //!< '1' if we want to run in passive mode as well
72 struct addrinfo mainhints; //!< temporary struct to keep settings needed to open the new socket
73 char address[MAX_LINE + 1]; //!< keeps the network address (either numeric or literal) to bind to
74 char port[MAX_LINE + 1]; //!< keeps the network port to bind to
75
76 extern char *optarg; // for getopt()
77
78 // Function definition
79 static void main_passive(void *ptr);
80 static void main_active(void *ptr);
81
82 #ifndef _WIN32
83 static void main_cleanup_childs(int sign);
84 #endif
85
86 #define RPCAP_ACTIVE_WAIT 30 /* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */
87
88 /*!
89 \brief Prints the usage screen if it is launched in console mode.
90 */
91 static void printusage(void)
92 {
93 char *usagetext =
94 "USAGE:\n"
95 " " PROGRAM_NAME " [-b <address>] [-p <port>] [-6] [-l <host_list>] [-a <host,port>]\n"
96 " [-n] [-v] [-d] [-s <file>] [-f <file>]\n"
97 " -b <address>: the address to bind to (either numeric or literal).\n"
98 " Default: it binds to all local IPv4 addresses\n"
99 " -p <port>: the port to bind to. Default: it binds to port " RPCAP_DEFAULT_NETPORT "\n"
100 " -4: use only IPv4 (default both IPv4 and IPv6 waiting sockets are used)\n"
101 " -l <host_list>: a file that keeps the list of the hosts which are allowed\n"
102 " to connect to this server (if more than one, list them one per line).\n"
103 " We suggest to use literal names (instead of numeric ones) in order to\n"
104 " avoid problems with different address families\n"
105 " -n: permit NULL authentication (usually used with '-l')\n"
106 " -a <host,port>: run in active mode when connecting to 'host' on port 'port'\n"
107 " In case 'port' is omitted, the default port (" RPCAP_DEFAULT_NETPORT_ACTIVE ") is used\n"
108 " -v: run in active mode only (default: if '-a' is specified, it accepts\n"
109 " passive connections as well\n"
110 " -d: run in daemon mode (UNIX only) or as a service (Win32 only)\n"
111 " Warning (Win32): this switch is provided automatically when the service\n"
112 " is started from the control panel\n"
113 " -s <file>: save the current configuration to file\n"
114 " -f <file>: load the current configuration from file; all the switches\n"
115 " specified from the command line are ignored\n"
116 " -h: print this help screen\n\n";
117
118 printf("%s", usagetext);
119 }
120
121
122
123 //! Program main
124 int main(int argc, char *argv[], char *envp[])
125 {
126 char savefile[MAX_LINE + 1]; // name of the file on which we have to save the configuration
127 int isdaemon = 0; // Not null if the user wants to run this program as a daemon
128 int retval; // keeps the returning value from several functions
129 char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
130
131 savefile[0] = 0;
132 loadfile[0] = 0;
133 hostlist[0] = 0;
134
135 // Initialize errbuf
136 memset(errbuf, 0, sizeof(errbuf));
137
138 if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
139 {
140 SOCK_ASSERT(errbuf, 1);
141 exit(-1);
142 }
143
144 strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE);
145 strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE);
146
147 // Prepare to open a new server socket
148 memset(&mainhints, 0, sizeof(struct addrinfo));
149
150 mainhints.ai_family = PF_UNSPEC;
151 mainhints.ai_flags = AI_PASSIVE; // Ready to a bind() socket
152 mainhints.ai_socktype = SOCK_STREAM;
153
154 // Getting the proper command line options
155 while ((retval = getopt(argc, argv, "b:dhp:4l:na:s:f:v")) != -1)
156 {
157 switch (retval)
158 {
159 case 'b':
160 strncpy(address, optarg, MAX_LINE);
161 break;
162 case 'p':
163 strncpy(port, optarg, MAX_LINE);
164 break;
165 case '4':
166 mainhints.ai_family = PF_INET; // IPv4 server only
167 break;
168 case 'd':
169 isdaemon = 1;
170 break;
171 case 'n':
172 nullAuthAllowed = 1;
173 break;
174 case 'v':
175 passivemode = 0;
176 break;
177 case 'l':
178 {
179 strncpy(hostlist, optarg, sizeof(hostlist));
180 break;
181 }
182 case 'a':
183 {
184 char *tmpaddress, *tmpport;
185 char *lasts;
186 int i = 0;
187
188 tmpaddress = pcap_strtok_r(optarg, RPCAP_HOSTLIST_SEP, &lasts);
189
190 while ((tmpaddress != NULL) && (i < MAX_ACTIVE_LIST))
191 {
192 tmpport = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
193
194 strlcpy(activelist[i].address, tmpaddress, MAX_LINE);
195
196 if ((tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0)) // the user choose a custom port
197 strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE);
198 else
199 strlcpy(activelist[i].port, tmpport, MAX_LINE);
200
201 tmpaddress = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
202
203 i++;
204 }
205
206 if (i > MAX_ACTIVE_LIST)
207 SOCK_ASSERT("Only MAX_ACTIVE_LIST active connections are currently supported.", 1);
208
209 // I don't initialize the remaining part of the structure, since
210 // it is already zeroed (it is a global var)
211 break;
212 }
213 case 'f':
214 strlcpy(loadfile, optarg, MAX_LINE);
215 break;
216 case 's':
217 strlcpy(savefile, optarg, MAX_LINE);
218 break;
219 case 'h':
220 printusage();
221 exit(0);
222 default:
223 break;
224 }
225 }
226
227 if (savefile[0])
228 {
229 if (fileconf_save(savefile))
230 SOCK_ASSERT("Error when saving the configuration to file", 1);
231 }
232
233 // If the file does not exist, it keeps the settings provided by the command line
234 if (loadfile[0])
235 fileconf_read(0);
236
237 #ifndef _WIN32
238 // SIGTERM (i.e. kill -15) is not generated in Win32, although it is included for ANSI compatibility
239 signal(SIGTERM, main_cleanup);
240 signal(SIGCHLD, main_cleanup_childs);
241 #endif
242
243 // forking a daemon, if it is needed
244 if (isdaemon)
245 {
246 #ifndef _WIN32
247 int pid;
248
249 // Unix Network Programming, pg 336
250 if ((pid = fork()) != 0)
251 exit(0); // Parent terminates
252
253 // First child continues
254 // Set daemon mode
255 setsid();
256
257 // generated under unix with 'kill -HUP', needed to reload the configuration
258 signal(SIGHUP, fileconf_read);
259
260 if ((pid = fork()) != 0)
261 exit(0); // First child terminates
262
263 // LINUX WARNING: the current linux implementation of pthreads requires a management thread
264 // to handle some hidden stuff. So, as soon as you create the first thread, two threads are
265 // created. Fom this point on, the number of threads active are always one more compared
266 // to the number you're expecting
267
268 // Second child continues
269 // umask(0);
270 // chdir("/");
271 #else
272 // We use the SIGABRT signal to kill the Win32 service
273 signal(SIGABRT, main_cleanup);
274
275 // If this call succeeds, it is blocking on Win32
276 if (svc_start() != 1)
277 SOCK_ASSERT("Unable to start the service", 1);
278
279 // When the previous call returns, the entire application has to be stopped.
280 exit(0);
281 #endif
282 }
283 else // Console mode
284 {
285 // Enable the catching of Ctrl+C
286 signal(SIGINT, main_cleanup);
287
288 #ifndef _WIN32
289 // generated under unix with 'kill -HUP', needed to reload the configuration
290 // We do not have this kind of signal in Win32
291 signal(SIGHUP, fileconf_read);
292 #endif
293
294 printf("Press CTRL + C to stop the server...\n");
295 }
296
297 // If we're a Win32 service, we have already called this function in the service_main
298 main_startup();
299
300 // The code should never arrive here (since the main_startup is blocking)
301 // however this avoids a compiler warning
302 exit(0);
303 }
304
305 void main_startup(void)
306 {
307 char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
308 struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket
309 int i;
310 #ifdef USE_THREADS
311 pthread_t threadId; // Pthread variable that keeps the thread structures
312 pthread_attr_t detachedAttribute; // PThread attribute needed to create the thread as detached
313 #else
314 pid_t pid;
315 #endif
316
317 i = 0;
318 addrinfo = NULL;
319 memset(errbuf, 0, sizeof(errbuf));
320
321 // Starts all the active threads
322 while ((activelist[i].address[0] != 0) && (i < MAX_ACTIVE_LIST))
323 {
324 activelist[i].ai_family = mainhints.ai_family;
325
326 #ifdef USE_THREADS
327 /* GV we need this to create the thread as detached. */
328 /* GV otherwise, the thread handle is not destroyed */
329 pthread_attr_init(&detachedAttribute);
330 pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
331
332 if (pthread_create(&threadId, &detachedAttribute, (void *) &main_active, (void *) &activelist[i]))
333 {
334 SOCK_ASSERT("Error creating the active child thread", 1);
335 pthread_attr_destroy(&detachedAttribute);
336 continue;
337 }
338 pthread_attr_destroy(&detachedAttribute);
339 #else
340 if ((pid = fork()) == 0) // I am the child
341 {
342 main_active((void *) &activelist[i]);
343 exit(0);
344 }
345 #endif
346 i++;
347 }
348
349 /*
350 * The code that manages the active connections is not blocking;
351 * the code that manages the passive connection is blocking.
352 * So, if the user does not want to run in passive mode, we have
353 * to block the main thread here, otherwise the program ends and
354 * all threads are stopped.
355 *
356 * WARNING: this means that in case we have only active mode,
357 * the program does not terminate even if all the child thread
358 * terminates. The user has always to press Ctrl+C (or send a
359 * SIGTERM) to terminate the program.
360 */
361 if (passivemode)
362 {
363 struct addrinfo *tempaddrinfo;
364
365 // Do the work
366 if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
367 {
368 SOCK_ASSERT(errbuf, 1);
369 return;
370 }
371
372 tempaddrinfo = addrinfo;
373
374 while (tempaddrinfo)
375 {
376 SOCKET *socktemp;
377
378 if ((sockmain = sock_open(tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == -1)
379 {
380 SOCK_ASSERT(errbuf, 1);
381 tempaddrinfo = tempaddrinfo->ai_next;
382 continue;
383 }
384
385 // This trick is needed in order to allow the child thread to save the 'sockmain' variable
386 // withouth getting it overwritten by the sock_open, in case we want to open more than one waiting sockets
387 // For instance, the pthread_create() will accept the socktemp variable, and it will deallocate immediately that variable
388 socktemp = (SOCKET *) malloc (sizeof (SOCKET));
389 if (socktemp == NULL)
390 exit(0);
391
392 *socktemp = sockmain;
393
394 #ifdef USE_THREADS
395 /* GV we need this to create the thread as detached. */
396 /* GV otherwise, the thread handle is not destroyed */
397 pthread_attr_init(&detachedAttribute);
398 pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
399
400 if (pthread_create(&threadId, &detachedAttribute, (void *) &main_passive, (void *) socktemp))
401 {
402 SOCK_ASSERT("Error creating the passive child thread", 1);
403 pthread_attr_destroy(&detachedAttribute);
404 continue;
405 }
406
407 pthread_attr_destroy(&detachedAttribute);
408 #else
409 if ((pid = fork()) == 0) // I am the child
410 {
411 main_passive((void *) socktemp);
412 return;
413 }
414 #endif
415 tempaddrinfo = tempaddrinfo->ai_next;
416 }
417
418 freeaddrinfo(addrinfo);
419 }
420
421 // All the previous calls are no blocking, so the main line of execution goes here
422 // and I have to avoid that the program terminates
423 while (1)
424 pthread_suspend(10*60*1000); // it wakes up every 10 minutes; it seems to me reasonable
425 }
426
427
428 /*
429 \brief Closes gracefully (more or less) the program.
430
431 This function is called:
432 - when we're running in console
433 - when we're running as a Win32 service (in case we press STOP)
434
435 It is not called when we are running as a daemon on UNIX, since
436 we do not define a signal in order to terminate gracefully the daemon.
437
438 This function makes a fast cleanup (it does not clean everything, as
439 you can see from the fact that it uses kill() on UNIX), closes
440 the main socket, free winsock resources (on Win32) and exits the
441 program.
442 */
443 void main_cleanup(int sign)
444 {
445 #ifndef _WIN32
446 // Sends a KILL signal to all the processes
447 // that share the same process group (i.e. kills all the childs)
448 kill(0, SIGKILL);
449 #endif
450
451 SOCK_ASSERT(PROGRAM_NAME " is closing.\n", 1);
452
453 // FULVIO (bug)
454 // Here we close only the latest 'sockmain' created; if we opened more than one waiting sockets,
455 // only the latest one is closed correctly.
456 if (sockmain)
457 closesocket(sockmain);
458 sock_cleanup();
459
460 /*
461 This code is executed under the following conditions:
462 - SIGTERM: we're under UNIX, and the user kills us with 'kill -15'
463 (no matter is we're a daemon or in a console mode)
464 - SIGINT: we're in console mode and the user sends us a Ctrl+C
465 (SIGINT signal), no matter if we're UNIX or Win32
466
467 In all these cases, we have to terminate the program.
468 The case that still remains is if we're a Win32 service: in this case,
469 we're a child thread, and we want just to terminate ourself. This is because
470 the exit(0) will be invoked by the main thread, which is blocked waiting that
471 all childs terminates. We are forced to call exit from the main thread otherwise
472 the Win32 service control manager (SCM) does not work well.
473 */
474 if ((sign == SIGTERM) || (sign == SIGINT))
475 exit(0);
476 else
477 return;
478 }
479
480 #ifndef _WIN32
481 static void main_cleanup_childs(int sign)
482 {
483 pid_t pid;
484 int stat;
485
486 // For reference, Stevens, pg 128
487
488 while ((pid = waitpid(-1, &stat, WNOHANG)) > 0)
489 SOCK_ASSERT("Child terminated", 1);
490
491 return;
492 }
493 #endif
494
495 /*!
496 \brief 'true' main of the program.
497
498 It must be in a separate function because:
499 - if we're in 'console' mode, we have to put the main thread waiting for a Ctrl+C
500 (in order to be able to stop everything)
501 - if we're in daemon mode, the main program must terminate and a new child must be
502 created in order to create the daemon
503
504 \param ptr: it keeps the main socket handler (what's called 'sockmain' in the main()), that
505 represents the socket used in the main connection. It is a 'void *' just because pthreads
506 want this format.
507 */
508 static void main_passive(void *ptr)
509 {
510 char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
511 SOCKET sockctrl; // keeps the socket ID for this control connection
512 struct sockaddr_storage from; // generic sockaddr_storage variable
513 socklen_t fromlen; // keeps the length of the sockaddr_storage variable
514 SOCKET sockmain;
515
516 #ifndef USE_THREADS
517 pid_t pid;
518 #endif
519
520 sockmain = *((SOCKET *) ptr);
521
522 // Delete the pointer (which has been allocated in the main)
523 free(ptr);
524
525 // Initialize errbuf
526 memset(errbuf, 0, sizeof(errbuf));
527
528 // main thread loop
529 while (1)
530 {
531 #ifdef USE_THREADS
532 pthread_t threadId; // Pthread variable that keeps the thread structures
533 pthread_attr_t detachedAttribute;
534 #endif
535 struct daemon_slpars *pars; // parameters needed by the daemon_serviceloop()
536
537 // Connection creation
538 fromlen = sizeof(struct sockaddr_storage);
539
540 sockctrl = accept(sockmain, (struct sockaddr *) &from, &fromlen);
541
542 if (sockctrl == -1)
543 {
544 // The accept() call can return this error when a signal is catched
545 // In this case, we have simply to ignore this error code
546 // Stevens, pg 124
547 #ifdef _WIN32
548 if (WSAGetLastError() == WSAEINTR)
549 #else
550 if (errno == EINTR)
551 #endif
552 continue;
553
554 // Don't check for errors here, since the error can be due to the fact that the thread
555 // has been killed
556 sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
557 SOCK_ASSERT(errbuf, 1);
558 continue;
559 }
560
561 // checks if the connecting host is among the ones allowed
562 if (sock_check_hostlist(hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
563 {
564 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_HOSTNOAUTH, NULL);
565 sock_close(sockctrl, NULL, 0);
566 continue;
567 }
568
569
570 #ifdef USE_THREADS
571 // in case of passive mode, this variable is deallocated by the daemon_serviceloop()
572 pars = (struct daemon_slpars *) malloc (sizeof(struct daemon_slpars));
573 if (pars == NULL)
574 {
575 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
576 continue;
577 }
578
579 pars->sockctrl = sockctrl;
580 pars->activeclose = 0; // useless in passive mode
581 pars->isactive = 0;
582 pars->nullAuthAllowed = nullAuthAllowed;
583
584 /* GV we need this to create the thread as detached. */
585 /* GV otherwise, the thread handle is not destroyed */
586 pthread_attr_init(&detachedAttribute);
587 pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
588 if (pthread_create(&threadId, &detachedAttribute, (void *) &daemon_serviceloop, (void *) pars))
589 {
590 SOCK_ASSERT("Error creating the child thread", 1);
591 pthread_attr_destroy(&detachedAttribute);
592 continue;
593 }
594 pthread_attr_destroy(&detachedAttribute);
595
596 #else
597 if ((pid = fork()) == 0) // I am the child
598 {
599 // in case of passive mode, this variable is deallocated by the daemon_serviceloop()
600 pars = (struct daemon_slpars *) malloc (sizeof(struct daemon_slpars));
601 if (pars == NULL)
602 {
603 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
604 exit(0);
605 }
606
607 pars->sockctrl = sockctrl;
608 pars->activeclose = 0; // useless in passive mode
609 pars->isactive = 0;
610 pars->nullAuthAllowed = nullAuthAllowed;
611
612 // Close the main socket (must be open only in the parent)
613 closesocket(sockmain);
614
615 daemon_serviceloop((void *) pars);
616 exit(0);
617 }
618
619 // I am the parent
620 // Close the childsocket (must be open only in the child)
621 closesocket(sockctrl);
622 #endif
623
624 // loop forever, until interrupted
625 }
626 }
627
628 /*!
629 \brief 'true' main of the program in case the active mode is turned on.
630
631 It does not have any return value nor parameters.
632 This function loops forever trying to connect to the remote host, until the
633 daemon is turned down.
634
635 \param ptr: it keeps the 'activepars' parameters. It is a 'void *' just because pthreads
636 want this format.
637 */
638 static void main_active(void *ptr)
639 {
640 char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
641 SOCKET sockctrl; // keeps the socket ID for this control connection
642 struct addrinfo hints; // temporary struct to keep settings needed to open the new socket
643 struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket
644 struct active_pars *activepars;
645 struct daemon_slpars *pars; // parameters needed by the daemon_serviceloop()
646
647 activepars = (struct active_pars *) ptr;
648
649 // Prepare to open a new server socket
650 memset(&hints, 0, sizeof(struct addrinfo));
651 // WARNING Currently it supports only ONE socket family among IPv4 and IPv6
652 hints.ai_family = AF_INET; // PF_UNSPEC to have both IPv4 and IPv6 server
653 hints.ai_socktype = SOCK_STREAM;
654 hints.ai_family = activepars->ai_family;
655
656 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Connecting to host %s, port %s, using protocol %s",
657 activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
658 (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
659 SOCK_ASSERT(errbuf, 1);
660
661 // Initialize errbuf
662 memset(errbuf, 0, sizeof(errbuf));
663
664 // Do the work
665 if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
666 {
667 SOCK_ASSERT(errbuf, 1);
668 return;
669 }
670
671 while (1)
672 {
673 int activeclose;
674
675 if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
676 {
677 SOCK_ASSERT(errbuf, 1);
678
679 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
680 activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
681 (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
682
683 SOCK_ASSERT(errbuf, 1);
684
685 pthread_suspend(RPCAP_ACTIVE_WAIT * 1000);
686
687 continue;
688 }
689
690 pars = (struct daemon_slpars *) malloc (sizeof(struct daemon_slpars));
691 if (pars == NULL)
692 {
693 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
694 continue;
695 }
696
697 pars->sockctrl = sockctrl;
698 pars->activeclose = 0;
699 pars->isactive = 1;
700 pars->nullAuthAllowed = nullAuthAllowed;
701
702 daemon_serviceloop((void *) pars);
703
704 activeclose = pars->activeclose;
705
706 free(pars);
707
708 // If the connection is closed by the user explicitely, don't try to connect to it again
709 // just exit the program
710 if (activeclose == 1)
711 break;
712 }
713 }