Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

# rpcapd.c

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 2002 - 2003
    00003  * NetGroup, Politecnico di Torino (Italy)
    00004  * All rights reserved.
    00005  *
    00006  * Redistribution and use in source and binary forms, with or without
    00007  * modification, are permitted provided that the following conditions
    00008  * are met:
    00009  *
    00010  * 1. Redistributions of source code must retain the above copyright
    00011  * notice, this list of conditions and the following disclaimer.
    00012  * 2. Redistributions in binary form must reproduce the above copyright
    00013  * notice, this list of conditions and the following disclaimer in the
    00014  * documentation and/or other materials provided with the distribution.
    00015  * 3. Neither the name of the Politecnico di Torino nor the names of its
    00016  * contributors may be used to endorse or promote products derived from
    00017  * this software without specific prior written permission.
    00018  *
    00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    00022  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    00023  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    00024  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    00025  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    00026  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    00027  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    00029  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00030  *
    00031  */
    00032
    00033
    00034
    00035
    00036
    00037 #include <errno.h>      // for the errno variable
    00038 #include <string.h>     // for strtok, etc
    00039 #include <stdlib.h>     // for malloc(), free(), ...
    00040 #include <pcap.h>       // for PCAP_ERRBUF_SIZE
    00041 #include <signal.h>     // for signal()
    00042 #include <pthread.h>
    00043 #include "rpcapd.h"
    00044 #include "fileconf.h"   // for the configuration file management
    00045 #include "pcap-remote.h"
    00046 #include "daemon.h"     // the true main() method of this daemon
    00047 #include "utils.h"      // Missing calls and such
    00048 #include "sockutils.h"  // for socket calls
    00049
    00050 #ifndef WIN32
    00051 #include <unistd.h>     // for exit()
    00052 #include <sys/wait.h>   // waitpid()
    00053 #else
    00054 #include "win32-svc.h"  // for Win32 service stuff
    00055 #endif
    00056
    00057
    00058 // Global variables
    00059 char hostlist[MAX_HOST_LIST + 1];
    00060 struct active_pars activelist[MAX_ACTIVE_LIST];
    00061 int nullAuthAllowed;
    00062 SOCKET sockmain;
    00063 char loadfile[MAX_LINE + 1];
    00064 int passivemode= 1;
    00065 struct addrinfo mainhints;
    00066 char address[MAX_LINE + 1];
    00067 char port[MAX_LINE + 1];
    00068
    00069 extern char *optarg;    // for getopt()
    00070
    00071
    00072
    00073 // Function definition
    00074 void main_passive(void *ptr);
    00075 void main_active(void *ptr);
    00076
    00077
    00078 #ifndef WIN32
    00079 void main_cleanup_childs(int sign);
    00080 #endif
    00081
    00082
    00086 void printusage()
    00087 {
    00088     char *usagetext =
    00089     "USAGE:\n"
    00090     " "  PROGRAM_NAME " [-b <address>] [-p <port>] [-6] [-l <host_list>] [-a <host,port>]\n"
    00091     "        [-n] [-v] [-d] [-s <file>] [-f <file>]\n"
    00092     "  -b <address>: the address to bind to (either numeric or literal).\n"
    00093     "      Default: it binds to all local IPv4 addresses\n"
    00094     "  -p <port>: the port to bind to. Default: it binds to port " RPCAP_DEFAULT_NETPORT "\n"
    00095     "  -4: use only IPv4 (default both IPv4 and IPv6 waiting sockets are used)\n"
    00096     "  -l <host_list>: a file that keeps the list of the hosts which are allowed\n"
    00097     "      to connect to this server (if more than one, list them one per line).\n"
    00098     "      We suggest to use literal names (instead of numeric ones) in order to\n"
    00099     "      avoid problems with different address families\n"
    00100     "  -n: permit NULL authentication (usually used with '-l')\n"
    00101     "  -a <host,port>: run in active mode when connecting to 'host' on port 'port'\n"
    00102     "      In case 'port' is omitted, the default port (" RPCAP_DEFAULT_NETPORT_ACTIVE ") is used\n"
    00103     "  -v: run in active mode only (default: if '-a' is specified, it accepts\n"
    00104     "      passive connections as well\n"
    00105     "  -d: run in daemon mode (UNIX only) or as a service (Win32 only)\n"
    00106     "      Warning (Win32): this switch is provided automatically when the service\n"
    00107     "      is started from the control panel\n"
    00108     "  -s <file>: save the current configuration to file\n"
    00109     "  -f <file>: load the current configuration from file; all the switches\n"
    00110     "      specified from the command line are ignored\n"
    00111     "  -h: print this help screen\n\n";
    00112
    00113     printf(usagetext);
    00114 }
    00115
    00116
    00117
    00119 int main(int argc, char *argv[], char *envp[])
    00120 {
    00121 char savefile[MAX_LINE + 1];        // name of the file on which we have to save the configuration
    00122 int isdaemon= 0;                    // Not null if the user wants to run this program as a daemon
    00123 int retval;                         // keeps the returning value from several functions
    00124 char errbuf[PCAP_ERRBUF_SIZE + 1];  // keeps the error string, prior to be printed
    00125
    00126
    00127     savefile[0]= 0;
    00128     loadfile[0]= 0;
    00129     hostlist[0]= 0;
    00130
    00131     // Initialize errbuf
    00132     memset(errbuf, 0, sizeof(errbuf) );
    00133
    00134     if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
    00135     {
    00136         SOCK_ASSERT(errbuf, 1);
    00137         exit(-1);
    00138     }
    00139
    00140     strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE);
    00141     strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE);
    00142
    00143     // Prepare to open a new server socket
    00144     memset(&mainhints, 0, sizeof(struct addrinfo));
    00145
    00146     mainhints.ai_family = PF_UNSPEC;
    00147     mainhints.ai_flags = AI_PASSIVE;    // Ready to a bind() socket
    00148     mainhints.ai_socktype = SOCK_STREAM;
    00149
    00150     // Getting the proper command line options
    00151     while ((retval = getopt(argc, argv, "b:dhp:4l:na:s:f:v")) != -1)
    00152     {
    00153         switch (retval)
    00154         {
    00155             case 'b':
    00156                 strncpy(address, optarg, MAX_LINE);
    00157                 break;
    00158             case 'p':
    00159                 strncpy(port, optarg, MAX_LINE);
    00160                 break;
    00161             case '4':
    00162                 mainhints.ai_family = PF_INET;      // IPv4 server only
    00163                 break;
    00164             case 'd':
    00165                 isdaemon= 1;
    00166                 break;
    00167             case 'n':
    00168                 nullAuthAllowed= 1;
    00169                 break;
    00170             case 'v':
    00171                 passivemode= 0;
    00172                 break;
    00173             case 'l':
    00174             {
    00175                 strncpy(hostlist, optarg, sizeof(hostlist) );
    00176                 break;
    00177             }
    00178             case 'a':
    00179             {
    00180             char *tmpaddress, *tmpport;
    00181             int i= 0;
    00182
    00183                 tmpaddress= strtok(optarg, RPCAP_HOSTLIST_SEP);
    00184
    00185                 while ( (tmpaddress != NULL) && (i < MAX_ACTIVE_LIST) )
    00186                 {
    00187                     tmpport= strtok(NULL, RPCAP_HOSTLIST_SEP);
    00188
    00189                     snprintf(activelist[i].address, MAX_LINE, tmpaddress);
    00190
    00191                     if ( (tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0) ) // the user choose a custom port
    00192                         snprintf(activelist[i].port, MAX_LINE, RPCAP_DEFAULT_NETPORT_ACTIVE);
    00193                     else
    00194                         snprintf(activelist[i].port, MAX_LINE, tmpport);
    00195
    00196                     tmpaddress = strtok(NULL, RPCAP_HOSTLIST_SEP);
    00197
    00198                     i++;
    00199                 }
    00200
    00201                 if (i > MAX_ACTIVE_LIST)
    00202                     SOCK_ASSERT("Only MAX_ACTIVE_LIST active connections are currently supported.", 1);
    00203
    00204                 // I don't initialize the remaining part of the structure, since
    00205                 // it is already zeroed (it is a global var)
    00206                 break;
    00207             }
    00208             case 'f':
    00209                 strncpy(loadfile, optarg, MAX_LINE);
    00210                 break;
    00211             case 's':
    00212                 strncpy(savefile, optarg, MAX_LINE);
    00213                 break;
    00214             case 'h':
    00215                 printusage();
    00216                 exit(0);
    00217             default:
    00218                 break;
    00219         }
    00220     }
    00221
    00222     if (savefile[0])
    00223     {
    00224         if (fileconf_save(savefile) )
    00225             SOCK_ASSERT("Error when saving the configuration to file", 1);
    00226     }
    00227
    00228     // If the file does not exist, it keeps the settings provided by the command line
    00229     if (loadfile[0])
    00230         fileconf_read(0);
    00231
    00232 #ifdef linux
    00233     // SIGTERM (i.e. kill -15) is not generated in WIN32, although it is included for ANSI compatibility
    00234     signal(SIGTERM, main_cleanup);
    00235     signal(SIGCHLD, main_cleanup_childs);
    00236 #endif
    00237
    00238     // forking a daemon, if it is needed
    00239     if (isdaemon)
    00240     {
    00241     #ifndef WIN32
    00242     int pid;
    00243
    00244         // Unix Network Programming, pg 336
    00245         if ( (pid = fork() ) != 0)
    00246             exit(0);        // Parent terminates
    00247
    00248         // First child continues
    00249         // Set daemon mode
    00250         setsid();
    00251
    00252         // generated under unix with 'kill -HUP', needed to reload the configuration
    00253         signal(SIGHUP, fileconf_read);
    00254
    00255         if ( (pid = fork() ) != 0)
    00256             exit(0);        // First child terminates
    00257
    00258         // LINUX WARNING: the current linux implementation of pthreads requires a management thread
    00259         // to handle some hidden stuff. So, as soon as you create the first thread, two threads are
    00260         // created. Fom this point on, the number of threads active are always one more compared
    00261         // to the number you're expecting
    00262
    00263         // Second child continues
    00264 //      umask(0);
    00265 //      chdir("/");
    00266     #else
    00267         // We use the SIGABRT signal to kill the Win32 service
    00268         signal(SIGABRT, main_cleanup);
    00269
    00270         // If this call succeeds, it is blocking on Win32
    00271         if ( svc_start() != 1)
    00272             SOCK_ASSERT(1, "Unable to start the service");
    00273
    00274         // When the previous call returns, the entire application has to be stopped.
    00275         exit(0);
    00276     #endif
    00277     }
    00278     else    // Console mode
    00279     {
    00280         // Enable the catching of Ctrl+C
    00281         signal(SIGINT, main_cleanup);
    00282
    00283 #ifndef WIN32
    00284         // generated under unix with 'kill -HUP', needed to reload the configuration
    00285         // We do not have this kind of signal in Win32
    00286         signal(SIGHUP, fileconf_read);
    00287 #endif
    00288
    00289         printf("Press CTRL + C to stop the server...\n");
    00290     }
    00291
    00292     // If we're a Win32 service, we have already called this function in the service_main
    00293     main_startup();
    00294
    00295     // The code should never arrive here (since the main_startup is blocking)
    00296     //  however this avoids a compiler warning
    00297     exit(0);
    00298 }
    00299
    00300
    00301
    00302 void main_startup(void)
    00303 {
    00304 char errbuf[PCAP_ERRBUF_SIZE + 1];  // keeps the error string, prior to be printed
    00305 struct addrinfo *addrinfo;              // keeps the addrinfo chain; required to open a new socket
    00306 int i;
    00307 #ifdef WIN32
    00308     pthread_t threadId;                 // Pthread variable that keeps the thread structures
    00309     pthread_attr_t detachedAttribute;   // PThread attribute needed to create the thread as detached
    00310 #else
    00311     pid_t pid;
    00312 #endif
    00313
    00314     i= 0;
    00315     addrinfo= NULL;
    00316     memset(errbuf, 0, sizeof(errbuf) );
    00317
    00318     // Starts all the active threads
    00319     while ( (activelist[i].address[0] != 0) && (i < MAX_ACTIVE_LIST) )
    00320     {
    00321         activelist[i].ai_family= mainhints.ai_family;
    00322
    00323 #ifdef WIN32
    00324         /* GV we need this to create the thread as detached. */
    00325         /* GV otherwise, the thread handle is not destroyed  */
    00326         pthread_attr_init(&detachedAttribute);
    00327         pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
    00328
    00329         if ( pthread_create( &threadId, &detachedAttribute, (void *) &main_active, (void *) &activelist[i]) )
    00330         {
    00331             SOCK_ASSERT("Error creating the active child thread", 1);
    00332             pthread_attr_destroy(&detachedAttribute);
    00333             continue;
    00334         }
    00335         pthread_attr_destroy(&detachedAttribute);
    00336 #else
    00337         if ( (pid= fork() ) == 0)   // I am the child
    00338         {
    00339             main_active( (void *) &activelist[i]);
    00340             exit(0);
    00341         }
    00342 #endif
    00343         i++;
    00344     }
    00345
    00346     /*
    00347         The code that manages the active connections is not blocking;
    00348         vice versa, the code that manages the passive connection is blocking.
    00349         So, if the user do not want to run in passive mode, we have to block
    00350         the main thread here, otherwise the program ends and all threads
    00351         are stopped.
    00352
    00353         WARNING: this means that in case we have only active mode, the program does
    00354         not terminate even if all the child thread terminates. The user has always to
    00355         press Ctrl+C (or send a SIGTERM) to terminate the program.
    00356     */
    00357
    00358     if (passivemode)
    00359     {
    00360     struct addrinfo *tempaddrinfo;
    00361
    00362         // Do the work
    00363         if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00364         {
    00365             SOCK_ASSERT(errbuf, 1);
    00366             return;
    00367         }
    00368
    00369         tempaddrinfo= addrinfo;
    00370
    00371         while (tempaddrinfo)
    00372         {
    00373         SOCKET *socktemp;
    00374
    00375             if ( (sockmain= sock_open(tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    00376             {
    00377                 SOCK_ASSERT(errbuf, 1);
    00378                 tempaddrinfo= tempaddrinfo->ai_next;
    00379                 continue;
    00380             }
    00381
    00382             // This trick is needed in order to allow the child thread to save the 'sockmain' variable
    00383             // withouth getting it overwritten by the sock_open, in case we want to open more than one waiting sockets
    00384             // For instance, the pthread_create() will accept the socktemp variable, and it will deallocate immediately that variable
    00385             socktemp= (SOCKET *) malloc (sizeof (SOCKET));
    00386             if (socktemp == NULL)
    00387                 exit(0);
    00388
    00389             *socktemp= sockmain;
    00390
    00391 #ifdef WIN32
    00392             /* GV we need this to create the thread as detached. */
    00393             /* GV otherwise, the thread handle is not destroyed  */
    00394             pthread_attr_init(&detachedAttribute);
    00395             pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
    00396
    00397             if ( pthread_create( &threadId, &detachedAttribute, (void *) &main_passive, (void *) socktemp ) )
    00398             {
    00399                 SOCK_ASSERT("Error creating the passive child thread", 1);
    00400                 pthread_attr_destroy(&detachedAttribute);
    00401                 continue;
    00402             }
    00403
    00404             pthread_attr_destroy(&detachedAttribute);
    00405 #else
    00406             if ( (pid= fork() ) == 0)   // I am the child
    00407             {
    00408                 main_passive( (void *) socktemp);
    00409                 return;
    00410             }
    00411 #endif
    00412             tempaddrinfo= tempaddrinfo->ai_next;
    00413         }
    00414
    00415         freeaddrinfo(addrinfo);
    00416     }
    00417
    00418     // All the previous calls are no blocking, so the main line of execution goes here
    00419     // and I have to avoid that the program terminates
    00420     while (1)
    00421         pthread_suspend(10*60*1000); // it wakes up every 10 minutes; it seems to me reasonable
    00422 }
    00423
    00424
    00425 /*
    00426     \brief Closes gracefully (more or less) the program.
    00427
    00428     This function is called:
    00429     - when we're running in console
    00430     - when we're running as a Win32 service (in case we press STOP)
    00431
    00432     It is not called when we are running as a daemon on UNIX, since
    00433     we do not define a signal in order to terminate gracefully the daemon.
    00434
    00435     This function makes a fast cleanup (it does not clean everything, as
    00436     you can see from the fact that it uses kill() on UNIX), closes
    00437     the main socket, free winsock resources (on Win32) and exits the
    00438     program.
    00439 */
    00440 void main_cleanup(int sign)
    00441 {
    00442 #ifndef WIN32
    00443     // Sends a KILL signal to all the processes
    00444     // that share the same process group (i.e. kills all the childs)
    00445     kill(0, SIGKILL);
    00446 #endif
    00447
    00448     SOCK_ASSERT(PROGRAM_NAME " is closing.\n", 1);
    00449
    00450     // FULVIO (bug)
    00451     // Here we close only the latest 'sockmain' created; if we opened more than one waiting sockets,
    00452     // only the latest one is closed correctly.
    00453     if (sockmain)
    00454         closesocket(sockmain);
    00455     sock_cleanup();
    00456
    00457     /*
    00458         This code is executed under the following conditions:
    00459         - SIGTERM: we're under UNIX, and the user kills us with 'kill -15'
    00460         (no matter is we're a daemon or in a console mode)
    00461         - SIGINT: we're in console mode and the user sends us a Ctrl+C
    00462         (SIGINT signal), no matter if we're UNIX or Win32
    00463
    00464         In all these cases, we have to terminate the program.
    00465         The case that still remains is if we're a Win32 service: in this case,
    00466         we're a child thread, and we want just to terminate ourself. This is because
    00467         the exit(0) will be invoked by the main thread, which is blocked waiting that
    00468         all childs terminates. We are forced to call exit from the main thread otherwise
    00469         the Win32 service control manager (SCM) does not work well.
    00470     */
    00471     if ( (sign == SIGTERM) || (sign == SIGINT) )
    00472         exit(0);
    00473     else
    00474         return;
    00475 }
    00476
    00477
    00478
    00479 #ifdef linux
    00480
    00481 void main_cleanup_childs(int sign)
    00482 {
    00483 pid_t pid;
    00484 int stat;
    00485
    00486     // For reference, Stevens, pg 128
    00487
    00488     while ( (pid= waitpid(-1, &stat, WNOHANG) ) > 0)
    00489         SOCK_ASSERT("Child terminated", 1);
    00490
    00491     return;
    00492 }
    00493
    00494 #endif
    00495
    00496
    00497
    00498
    00499
    00513 void main_passive(void *ptr)
    00514 {
    00515 char errbuf[PCAP_ERRBUF_SIZE + 1];  // keeps the error string, prior to be printed
    00516 SOCKET sockctrl;                // keeps the socket ID for this control connection
    00517 struct sockaddr_storage from;   // generic sockaddr_storage variable
    00518 socklen_t fromlen;              // keeps the length of the sockaddr_storage variable
    00519 SOCKET sockmain;
    00520
    00521 #ifndef WIN32
    00522     pid_t pid;
    00523 #endif
    00524
    00525     sockmain= *((SOCKET *) ptr);
    00526
    00527     // Delete the pointer (which has been allocated in the main)
    00528     free(ptr);
    00529
    00530     // Initialize errbuf
    00531     memset(errbuf, 0, sizeof(errbuf) );
    00532
    00533     // main thread loop
    00534     while (1)
    00535     {
    00536 #ifdef WIN32
    00537     pthread_t threadId;                 // Pthread variable that keeps the thread structures
    00538     pthread_attr_t detachedAttribute;
    00539 #endif
    00540     struct daemon_slpars *pars;         // parameters needed by the daemon_serviceloop()
    00541
    00542         // Connection creation
    00543         fromlen = sizeof(struct sockaddr_storage);
    00544
    00545         sockctrl= accept(sockmain, (struct sockaddr *) &from, &fromlen);
    00546
    00547         if (sockctrl == -1)
    00548         {
    00549             // The accept() call can return this error when a signal is catched
    00550             // In this case, we have simply to ignore this error code
    00551             // Stevens, pg 124
    00552 #ifdef WIN32
    00553             if (WSAGetLastError() == WSAEINTR)
    00554 #else
    00555             if (errno == EINTR)
    00556 #endif
    00557                 continue;
    00558
    00559             // Don't check for errors here, since the error can be due to the fact that the thread
    00560             // has been killed
    00561             sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
    00562             SOCK_ASSERT(errbuf, 1);
    00563             continue;
    00564         }
    00565
    00566         // checks if the connecting host is among the ones allowed
    00567         if (sock_check_hostlist(hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0 )
    00568         {
    00569             rpcap_senderror(sockctrl, errbuf, PCAP_ERR_HOSTNOAUTH, NULL);
    00570             sock_close(sockctrl, NULL, 0);
    00571             continue;
    00572         }
    00573
    00574
    00575 #ifdef WIN32
    00576         // in case of passive mode, this variable is deallocated by the daemon_serviceloop()
    00577         pars= (struct daemon_slpars *) malloc ( sizeof(struct daemon_slpars) );
    00578         if (pars == NULL)
    00579         {
    00580             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00581             continue;
    00582         }
    00583
    00584         pars->sockctrl= sockctrl;
    00585         pars->activeclose= 0;       // useless in passive mode
    00586         pars->isactive= 0;
    00587         pars->nullAuthAllowed= nullAuthAllowed;
    00588
    00589         /* GV we need this to create the thread as detached. */
    00590         /* GV otherwise, the thread handle is not destroyed  */
    00591         pthread_attr_init(&detachedAttribute);
    00592         pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
    00593         if ( pthread_create( &threadId, &detachedAttribute, (void *) &daemon_serviceloop, (void *) pars) )
    00594         {
    00595             SOCK_ASSERT("Error creating the child thread", 1);
    00596             pthread_attr_destroy(&detachedAttribute);
    00597             continue;
    00598         }
    00599         pthread_attr_destroy(&detachedAttribute);
    00600
    00601 #else
    00602         if ( (pid= fork() ) == 0)   // I am the child
    00603         {
    00604             // in case of passive mode, this variable is deallocated by the daemon_serviceloop()
    00605             pars= (struct daemon_slpars *) malloc ( sizeof(struct daemon_slpars) );
    00606             if (pars == NULL)
    00607             {
    00608                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00609                 exit(0);
    00610             }
    00611
    00612             pars->sockctrl= sockctrl;
    00613             pars->activeclose= 0;       // useless in passive mode
    00614             pars->isactive= 0;
    00615             pars->nullAuthAllowed= nullAuthAllowed;
    00616
    00617             // Close the main socket (must be open only in the parent)
    00618             closesocket(sockmain);
    00619
    00620             daemon_serviceloop( (void *) pars);
    00621             exit(0);
    00622         }
    00623
    00624         // I am the parent
    00625         // Close the childsocket (must be open only in the child)
    00626         closesocket(sockctrl);
    00627 #endif
    00628
    00629         // loop forever, until interrupted
    00630     }
    00631 }
    00632
    00633
    00634
    00635
    00646 void main_active(void *ptr)
    00647 {
    00648 char errbuf[PCAP_ERRBUF_SIZE + 1];  // keeps the error string, prior to be printed
    00649 SOCKET sockctrl;                    // keeps the socket ID for this control connection
    00650 struct addrinfo hints;              // temporary struct to keep settings needed to open the new socket
    00651 struct addrinfo *addrinfo;          // keeps the addrinfo chain; required to open a new socket
    00652 struct active_pars *activepars;
    00653 struct daemon_slpars *pars;         // parameters needed by the daemon_serviceloop()
    00654
    00655
    00656     activepars= (struct active_pars *) ptr;
    00657
    00658     // Prepare to open a new server socket
    00659     memset(&hints, 0, sizeof(struct addrinfo));
    00660                                     // WARNING Currently it supports only ONE socket family among IPv4 and IPv6
    00661     hints.ai_family = AF_INET;      // PF_UNSPEC to have both IPv4 and IPv6 server
    00662     hints.ai_socktype = SOCK_STREAM;
    00663     hints.ai_family= activepars->ai_family;
    00664
    00665     snprintf(errbuf, PCAP_ERRBUF_SIZE, "Connecting to host %s, port %s, using protocol %s",
    00666             activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
    00667             (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
    00668     SOCK_ASSERT(errbuf, 1);
    00669
    00670     // Initialize errbuf
    00671     memset(errbuf, 0, sizeof(errbuf) );
    00672
    00673     // Do the work
    00674     if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00675     {
    00676         SOCK_ASSERT(errbuf, 1);
    00677         return;
    00678     }
    00679
    00680     while (1)
    00681     {
    00682     int activeclose;
    00683
    00684         if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    00685         {
    00686             SOCK_ASSERT(errbuf, 1);
    00687
    00688             snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
    00689                     activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
    00690                     (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified" );
    00691
    00692             SOCK_ASSERT(errbuf, 1);
    00693
    00694             pthread_suspend(RPCAP_ACTIVE_WAIT * 1000);
    00695
    00696             continue;
    00697         }
    00698
    00699         pars= (struct daemon_slpars *) malloc ( sizeof(struct daemon_slpars) );
    00700         if (pars == NULL)
    00701         {
    00702             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00703             continue;
    00704         }
    00705
    00706         pars->sockctrl= sockctrl;
    00707         pars->activeclose= 0;
    00708         pars->isactive= 1;
    00709         pars->nullAuthAllowed= nullAuthAllowed;
    00710
    00711         daemon_serviceloop( (void *) pars);
    00712
    00713         activeclose= pars->activeclose;
    00714
    00715         free(pars);
    00716
    00717         // If the connection is closed by the user explicitely, don't try to connect to it again
    00718         // just exit the program
    00719         if (activeclose == 1)
    00720             break;
    00721     }
    00722 }
    00723

documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.