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.