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.