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