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