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\n"
00097     "                  are allowed to connect to this server (if more than one,\n"
00098     "                  list them one per line). We suggest to use \n"
00099     "                  literal names (instead of numeric ones) in order to avoid\n"
00100     "                  problems with different address families\n"
00101     "  -n: permit NULL authentication (usually used with '-l')\n"
00102     "  -a <host, port>: run in active mode when connecting to 'host' on port 'port'\n"
00103     "  -v: run in active mode only (default: if '-a' is specified, it accepts passive\n"
00104     "      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         if ( pthread_create( &threadId, &detachedAttribute, (void *) &main_active, (void *) &activelist[i]) )
00329         {
00330             SOCK_ASSERT("Error creating the active child thread", 1);
00331             pthread_attr_destroy(&detachedAttribute);
00332             continue;
00333         }
00334         pthread_attr_destroy(&detachedAttribute);
00335 #else
00336         if ( (pid= fork() ) == 0)   // I am the child
00337         {
00338             main_active( (void *) &activelist[i]);
00339             exit(0);
00340         }
00341 #endif
00342         i++;
00343     }
00344 
00345     /*
00346         The code that manages the active connections is not blocking; 
00347         vice versa, the code that manages the passive connection is blocking.
00348         So, if the user do not want to run in passive mode, we have to block
00349         the main thread here, otherwise the program ends and all threads
00350         are stopped.
00351 
00352         WARNING: this means that in case we have only active mode, the program does
00353         not terminate even if all the child thread terminates. The user has always to
00354         press Ctrl+C (or send a SIGTERM) to terminate the program.
00355     */
00356 
00357     if (passivemode)
00358     {
00359     struct addrinfo *tempaddrinfo;
00360 
00361         // Do the work
00362         if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
00363         {
00364             SOCK_ASSERT(errbuf, 1);
00365             return;
00366         }
00367 
00368         tempaddrinfo= addrinfo;
00369 
00370         while (tempaddrinfo)
00371         {
00372             if ( (sockmain= sock_open(tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == -1)
00373             {
00374                 SOCK_ASSERT(errbuf, 1);
00375                 tempaddrinfo= tempaddrinfo->ai_next;
00376                 continue;
00377             }
00378 
00379 #ifdef WIN32
00380             /* GV we need this to create the thread as detached. */
00381             /* GV otherwise, the thread handle is not destroyed  */
00382             pthread_attr_init(&detachedAttribute); 
00383             pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
00384             if ( pthread_create( &threadId, &detachedAttribute, (void *) &main_passive, (void *) &sockmain ) )
00385             {
00386                 SOCK_ASSERT("Error creating the passive child thread", 1);
00387                 pthread_attr_destroy(&detachedAttribute);
00388                 continue;
00389             }
00390             pthread_attr_destroy(&detachedAttribute);
00391 #else
00392             if ( (pid= fork() ) == 0)   // I am the child
00393             {
00394                 main_passive( (void *) &sockmain);
00395                 return;
00396             }
00397 #endif
00398             tempaddrinfo= tempaddrinfo->ai_next;
00399 
00400             // FULVIO (bug)
00401             // Waits for 100 ms in order to allow the child thread to save the 'sockmain' variable
00402             // before it gets overwritten by the sock_open, in case we want to open more than one waiting sockets
00403             // It's a really dirty way to create a mutex
00404             pthread_suspend(100);
00405         }
00406 
00407         freeaddrinfo(addrinfo);
00408     }
00409 
00410     // All the previous calls are no blocking, so the main line of execution goes here
00411     // and I have to avoid that the program terminates
00412     while (1)
00413         pthread_suspend(10*60*1000); // it wakes up every 10 minutes; it seems to me reasonable
00414 }
00415 
00416 
00417 /*
00418     \brief Closes gracefully (more or less) the program.
00419 
00420     This function is called:
00421     - when we're running in console
00422     - when we're running as a Win32 service (in case we press STOP)
00423 
00424     It is not called when we are running as a daemon on UNIX, since
00425     we do not define a signal in order to terminate gracefully the daemon.
00426 
00427     This function makes a fast cleanup (it does not clean everything, as 
00428     you can see from the fact that it uses kill() on UNIX), closes
00429     the main socket, free winsock resources (on Win32) and exits the
00430     program.
00431 */
00432 void main_cleanup(int sign)
00433 {
00434 #ifndef WIN32
00435     // Sends a KILL signal to all the processes
00436     // that share the same process group (i.e. kills all the childs)
00437     kill(0, SIGKILL);
00438 #endif
00439 
00440     SOCK_ASSERT(PROGRAM_NAME " is closing.\n", 1);
00441 
00442     // FULVIO (bug)
00443     // Here we close only the latest 'sockmain' created; if we opened more than one waiting sockets, 
00444     // only the latest one is closed correctly.
00445     if (sockmain)
00446         closesocket(sockmain);
00447     sock_cleanup();
00448 
00449     /*
00450         This code is executed under the following conditions:
00451         - SIGTERM: we're under UNIX, and the user kills us with 'kill -15' 
00452         (no matter is we're a daemon or in a console mode)
00453         - SIGINT: we're in console mode and the user sends us a Ctrl+C 
00454         (SIGINT signal), no matter if we're UNIX or Win32
00455 
00456         In all these cases, we have to terminate the program.
00457         The case that still remains is if we're a Win32 service: in this case,
00458         we're a child thread, and we want just to terminate ourself. This is because
00459         the exit(0) will be invoked by the main thread, which is blocked waiting that
00460         all childs terminates. We are forced to call exit from the main thread otherwise
00461         the Win32 service control manager (SCM) does not work well.
00462     */
00463     if ( (sign == SIGTERM) || (sign == SIGINT) )
00464         exit(0);
00465     else
00466         return;
00467 }
00468 
00469 
00470 
00471 #ifdef linux
00472 
00473 void main_cleanup_childs(int sign)
00474 {
00475 pid_t pid;
00476 int stat;
00477 
00478     // For reference, Stevens, pg 128
00479 
00480     while ( (pid= waitpid(-1, &stat, WNOHANG) ) > 0)
00481         SOCK_ASSERT("Child terminated", 1);
00482 
00483     return;
00484 }
00485 
00486 #endif
00487 
00488 
00489 
00490 
00491 
00505 void main_passive(void *ptr)
00506 {
00507 char errbuf[PCAP_ERRBUF_SIZE + 1];  // keeps the error string, prior to be printed
00508 SOCKET sockctrl;                // keeps the socket ID for this control connection
00509 struct sockaddr_storage from;   // generic sockaddr_storage variable
00510 socklen_t fromlen;              // keeps the length of the sockaddr_storage variable
00511 SOCKET sockmain;
00512 
00513 #ifndef WIN32
00514     pid_t pid;
00515 #endif
00516 
00517     sockmain= *((SOCKET *) ptr);
00518     // Initialize errbuf
00519     memset(errbuf, 0, sizeof(errbuf) );
00520 
00521     // main thread loop
00522     while (1)
00523     {
00524 #ifdef WIN32
00525     pthread_t threadId;                 // Pthread variable that keeps the thread structures
00526     pthread_attr_t detachedAttribute;
00527 #endif
00528     struct daemon_slpars *pars;         // parameters needed by the daemon_serviceloop()
00529 
00530         // Connection creation
00531         fromlen = sizeof(struct sockaddr_storage);
00532 
00533         sockctrl= accept(sockmain, (struct sockaddr *) &from, &fromlen);
00534         
00535         if (sockctrl == -1)
00536         {
00537             // The accept() call can return this error when a signal is catched
00538             // In this case, we have simply to ignore this error code
00539             // Stevens, pg 124
00540 #ifdef WIN32
00541             if (WSAGetLastError() == WSAEINTR)
00542 #else
00543             if (errno == EINTR)
00544 #endif
00545                 continue;
00546 
00547             // Don't check for errors here, since the error can be due to the fact that the thread 
00548             // has been killed
00549             sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
00550             SOCK_ASSERT(errbuf, 1);
00551             continue;
00552         }
00553 
00554         // checks if the connecting host is among the ones allowed
00555         if (sock_check_hostlist(hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0 )
00556         {
00557             rpcap_senderror(sockctrl, errbuf, PCAP_ERR_HOSTNOAUTH, NULL);
00558             sock_close(sockctrl, NULL, 0);
00559             continue;
00560         }
00561 
00562 
00563 #ifdef WIN32
00564         // in case of passive mode, this variable is deallocated by the daemon_serviceloop()
00565         pars= (struct daemon_slpars *) malloc ( sizeof(struct daemon_slpars) );
00566         if (pars == NULL)
00567         {
00568             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00569             continue;
00570         }
00571 
00572         pars->sockctrl= sockctrl;
00573         pars->activeclose= 0;       // useless in passive mode
00574         pars->isactive= 0;
00575         pars->nullAuthAllowed= nullAuthAllowed;
00576 
00577         /* GV we need this to create the thread as detached. */
00578         /* GV otherwise, the thread handle is not destroyed  */
00579         pthread_attr_init(&detachedAttribute); 
00580         pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
00581         if ( pthread_create( &threadId, &detachedAttribute, (void *) &daemon_serviceloop, (void *) pars) )
00582         {
00583             SOCK_ASSERT("Error creating the child thread", 1);
00584             pthread_attr_destroy(&detachedAttribute);
00585             continue;
00586         }
00587         pthread_attr_destroy(&detachedAttribute);
00588 
00589 #else
00590         if ( (pid= fork() ) == 0)   // I am the child
00591         {
00592             // in case of passive mode, this variable is deallocated by the daemon_serviceloop()
00593             pars= (struct daemon_slpars *) malloc ( sizeof(struct daemon_slpars) );
00594             if (pars == NULL)
00595             {
00596                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00597                 exit(0);
00598             }
00599 
00600             pars->sockctrl= sockctrl;
00601             pars->activeclose= 0;       // useless in passive mode
00602             pars->isactive= 0;
00603             pars->nullAuthAllowed= nullAuthAllowed;
00604 
00605             // Close the main socket (must be open only in the parent)
00606             closesocket(sockmain);
00607 
00608             daemon_serviceloop( (void *) pars);
00609             exit(0);
00610         }
00611 
00612         // I am the parent
00613         // Close the childsocket (must be open only in the child)
00614         closesocket(sockctrl);
00615 #endif
00616 
00617         // loop forever, until interrupted
00618     }
00619 }
00620 
00621 
00622 
00623 
00634 void main_active(void *ptr)
00635 {
00636 char errbuf[PCAP_ERRBUF_SIZE + 1];  // keeps the error string, prior to be printed
00637 SOCKET sockctrl;                    // keeps the socket ID for this control connection
00638 struct addrinfo hints;              // temporary struct to keep settings needed to open the new socket
00639 struct addrinfo *addrinfo;          // keeps the addrinfo chain; required to open a new socket
00640 struct active_pars *activepars;
00641 struct daemon_slpars *pars;         // parameters needed by the daemon_serviceloop()
00642 
00643 
00644     activepars= (struct active_pars *) ptr;
00645 
00646     // Prepare to open a new server socket
00647     memset(&hints, 0, sizeof(struct addrinfo));
00648                                     // WARNING Currently it supports only ONE socket family among IPv4 and IPv6 
00649     hints.ai_family = AF_INET;      // PF_UNSPEC to have both IPv4 and IPv6 server
00650     hints.ai_socktype = SOCK_STREAM;
00651     hints.ai_family= activepars->ai_family;
00652 
00653     snprintf(errbuf, PCAP_ERRBUF_SIZE, "Connecting to host %s, port %s, using protocol %s",
00654             activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4": 
00655             (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
00656     SOCK_ASSERT(errbuf, 1);
00657 
00658     // Initialize errbuf
00659     memset(errbuf, 0, sizeof(errbuf) );
00660 
00661     // Do the work
00662     if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
00663     {
00664         SOCK_ASSERT(errbuf, 1);
00665         return;
00666     }
00667 
00668     while (1)
00669     {
00670     int activeclose;
00671 
00672         if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
00673         {
00674             SOCK_ASSERT(errbuf, 1);
00675 
00676             snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
00677                     activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4": 
00678                     (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified" );
00679 
00680             SOCK_ASSERT(errbuf, 1);
00681 
00682             pthread_suspend(RPCAP_ACTIVE_WAIT * 1000);
00683 
00684             continue;
00685         }
00686 
00687         pars= (struct daemon_slpars *) malloc ( sizeof(struct daemon_slpars) );
00688         if (pars == NULL)
00689         {
00690             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00691             continue;
00692         }
00693 
00694         pars->sockctrl= sockctrl;
00695         pars->activeclose= 0;
00696         pars->isactive= 1;
00697         pars->nullAuthAllowed= nullAuthAllowed;
00698 
00699         daemon_serviceloop( (void *) pars);
00700 
00701         activeclose= pars->activeclose;
00702 
00703         free(pars);
00704 
00705         // If the connection is closed by the user explicitely, don't try to connect to it again
00706         // just exit the program
00707         if (activeclose == 1)
00708             break;
00709     }
00710 }
00711 

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