//! Program main int main(int argc, char *argv[], char *envp[]) { char savefile[MAX_LINE + 1]; // name of the file on which we have to save the configuration int isdaemon= 0; // Not null if the user wants to run this program as a daemon int retval; // keeps the returning value from several functions char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed int k; savefile[0]= 0; loadfile[0]= 0; hostlist[0]= 0; // Initialize errbuf memset(errbuf, 0, sizeof(errbuf) ); if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1) { log_warn("%s", errbuf); exit(-1); } strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE); strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE); // Prepare to open a new server socket memset(&mainhints, 0, sizeof(struct addrinfo)); mainhints.ai_family = PF_UNSPEC; mainhints.ai_flags = AI_PASSIVE; // Ready to a bind() socket mainhints.ai_socktype = SOCK_STREAM; // Getting the proper command line options while ((retval = getopt(argc, argv, "b:dhp:4l:na:s:f:vyz:u:gc:e:m:k:t:SLi:")) != -1) { switch (retval) { case 'b': strncpy(address, optarg, MAX_LINE); break; case 'p': strncpy(port, optarg, MAX_LINE); break; case '4': mainhints.ai_family = PF_INET; // IPv4 server only break; case 'd': isdaemon= 1; break; case 'n': nullAuthAllowed= 1; break; case 'v': passivemode= 0; break; case 'l': { strncpy(hostlist, optarg, sizeof(hostlist) ); break; } case 'a': { char *tmpaddress, *tmpport; int i= 0; tmpaddress= strtok(optarg, RPCAP_HOSTLIST_SEP); while ( (tmpaddress != NULL) && (i < MAX_ACTIVE_LIST) ) { tmpport= strtok(NULL, RPCAP_HOSTLIST_SEP); snprintf(activelist[i].address, MAX_LINE, "%s", tmpaddress); if ( (tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0) ) // the user choose a custom port snprintf(activelist[i].port, MAX_LINE, RPCAP_DEFAULT_NETPORT_ACTIVE); else snprintf(activelist[i].port, MAX_LINE, "%s", tmpport); tmpaddress = strtok(NULL, RPCAP_HOSTLIST_SEP); i++; } if (i > MAX_ACTIVE_LIST) log_warn("Only MAX_ACTIVE_LIST active connections are currently supported."); // I don't initialize the remaining part of the structure, since // it is already zeroed (it is a global var) break; } case 'f': strncpy(loadfile, optarg, MAX_LINE); break; case 's': strncpy(savefile, optarg, MAX_LINE); break; case 'm': rpcapd_opt.ringbuf_max_pkt_data = atoi(optarg) * 1000 * 1000; if (rpcapd_opt.ringbuf_max_pkt_data <= 0) { log_warn("ignoring invalid ringbuf memory size"); } break; case 'k': k = atoi(optarg); if (k <= 0) { log_warn("ignoring invalid ringbuf pkt count"); break; } rpcapd_opt.ringbuf_max_pkts = 1; while (rpcapd_opt.ringbuf_max_pkts < k) { rpcapd_opt.ringbuf_max_pkts <<= 1; } break; case 'y': rpcapd_opt.no_udp = 1; log_warn("DRY RUN - NO UDP WILL BE SENT"); break; case 'z': rpcapd_opt.pcap_buffer_size = atoi(optarg); break; case 'u': rpcapd_opt.udp_sndbuf_size = atoi(optarg); if (rpcapd_opt.udp_sndbuf_size <= 0) { log_warn("ignoring invalid udp sndbuf size"); } break; case 'g': rpcapd_opt.blocking_udp_socket = 1; break; case 'c': if (strcmp("single", optarg) == 0) { rpcapd_opt.single_threaded = 1; break; } if (sscanf(optarg, "%d,%d", &rpcapd_opt.cpu_affinity_pcap, &rpcapd_opt.cpu_affinity_udp) < 2) { rpcapd_opt.single_threaded = 1; } else { rpcapd_opt.single_threaded = 0; } break; case 'e': sscanf(optarg, "%d,%d", &rpcapd_opt.nice_pcap, &rpcapd_opt.nice_udp); break; case 't': rpcapd_opt.udp_mtu = atoi(optarg); if (rpcapd_opt.udp_mtu > 65000) { rpcapd_opt.udp_mtu = 65000; } break; case 'S': rpcapd_opt.print_stats = 1; break; case 'L': rpcapd_opt.use_syslog = 1; break; case 'i': if (strlen(optarg) >= sizeof(rpcapd_opt.preselected_ifname)) { log_warn("-i option too long"); break; } strncpy(rpcapd_opt.preselected_ifname, optarg, sizeof(rpcapd_opt.preselected_ifname)); break; case 'h': printusage(); exit(0); default: break; } } if (rpcapd_opt.use_syslog) { rpcapd_log_init(argv[0], !isdaemon); } if (savefile[0]) { if (fileconf_save(savefile) ) log_warn("Error when saving the configuration to file"); } // If the file does not exist, it keeps the settings provided by the command line if (loadfile[0]) fileconf_read(0); #ifdef linux // SIGTERM (i.e. kill -15) is not generated in WIN32, although it is included for ANSI compatibility signal(SIGTERM, main_cleanup); signal(SIGCHLD, main_cleanup_childs); #endif // forking a daemon, if it is needed if (isdaemon) { #ifndef WIN32 int pid; // Unix Network Programming, pg 336 if ( (pid = fork() ) != 0) exit(0); // Parent terminates // First child continues // Set daemon mode setsid(); // generated under unix with 'kill -HUP', needed to reload the configuration signal(SIGHUP, fileconf_read); if ( (pid = fork() ) != 0) exit(0); // First child terminates // LINUX WARNING: the current linux implementation of pthreads requires a management thread // to handle some hidden stuff. So, as soon as you create the first thread, two threads are // created. Fom this point on, the number of threads active are always one more compared // to the number you're expecting // Second child continues // umask(0); // chdir("/"); #else // We use the SIGABRT signal to kill the Win32 service signal(SIGABRT, main_cleanup); // If this call succeeds, it is blocking on Win32 if ( svc_start() != 1) log_warn("Unable to start the service"); // When the previous call returns, the entire application has to be stopped. exit(0); #endif } else // Console mode { // Enable the catching of Ctrl+C signal(SIGINT, main_cleanup); #ifndef WIN32 // generated under unix with 'kill -HUP', needed to reload the configuration // We do not have this kind of signal in Win32 signal(SIGHUP, fileconf_read); #endif printf("Press CTRL + C to stop the server...\n"); } // If we're a Win32 service, we have already called this function in the service_main main_startup(); // The code should never arrive here (since the main_startup is blocking) // however this avoids a compiler warning exit(0); }
//! Program main int main(int argc, char *argv[], char *envp[]) { char savefile[MAX_LINE + 1]; // name of the file on which we have to save the configuration int isdaemon = 0; // Not null if the user wants to run this program as a daemon int retval; // keeps the returning value from several functions char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed savefile[0] = 0; loadfile[0] = 0; hostlist[0] = 0; // Initialize errbuf memset(errbuf, 0, sizeof(errbuf)); if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1) { SOCK_ASSERT(errbuf, 1); exit(-1); } strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE); strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE); // Prepare to open a new server socket memset(&mainhints, 0, sizeof(struct addrinfo)); mainhints.ai_family = PF_UNSPEC; mainhints.ai_flags = AI_PASSIVE; // Ready to a bind() socket mainhints.ai_socktype = SOCK_STREAM; // Getting the proper command line options while ((retval = getopt(argc, argv, "b:dhp:4l:na:s:f:v")) != -1) { switch (retval) { case 'b': strncpy(address, optarg, MAX_LINE); break; case 'p': strncpy(port, optarg, MAX_LINE); break; case '4': mainhints.ai_family = PF_INET; // IPv4 server only break; case 'd': isdaemon = 1; break; case 'n': nullAuthAllowed = 1; break; case 'v': passivemode = 0; break; case 'l': { strncpy(hostlist, optarg, sizeof(hostlist)); break; } case 'a': { char *tmpaddress, *tmpport; char *lasts; int i = 0; tmpaddress = pcap_strtok_r(optarg, RPCAP_HOSTLIST_SEP, &lasts); while ((tmpaddress != NULL) && (i < MAX_ACTIVE_LIST)) { tmpport = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts); strlcpy(activelist[i].address, tmpaddress, MAX_LINE); if ((tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0)) // the user choose a custom port strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE); else strlcpy(activelist[i].port, tmpport, MAX_LINE); tmpaddress = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts); i++; } if (i > MAX_ACTIVE_LIST) SOCK_ASSERT("Only MAX_ACTIVE_LIST active connections are currently supported.", 1); // I don't initialize the remaining part of the structure, since // it is already zeroed (it is a global var) break; } case 'f': strlcpy(loadfile, optarg, MAX_LINE); break; case 's': strlcpy(savefile, optarg, MAX_LINE); break; case 'h': printusage(); exit(0); default: break; } } if (savefile[0]) { if (fileconf_save(savefile)) SOCK_ASSERT("Error when saving the configuration to file", 1); } // If the file does not exist, it keeps the settings provided by the command line if (loadfile[0]) fileconf_read(0); #ifndef _WIN32 // SIGTERM (i.e. kill -15) is not generated in Win32, although it is included for ANSI compatibility signal(SIGTERM, main_cleanup); signal(SIGCHLD, main_cleanup_childs); #endif // forking a daemon, if it is needed if (isdaemon) { #ifndef _WIN32 int pid; // Unix Network Programming, pg 336 if ((pid = fork()) != 0) exit(0); // Parent terminates // First child continues // Set daemon mode setsid(); // generated under unix with 'kill -HUP', needed to reload the configuration signal(SIGHUP, fileconf_read); if ((pid = fork()) != 0) exit(0); // First child terminates // LINUX WARNING: the current linux implementation of pthreads requires a management thread // to handle some hidden stuff. So, as soon as you create the first thread, two threads are // created. Fom this point on, the number of threads active are always one more compared // to the number you're expecting // Second child continues // umask(0); // chdir("/"); #else // We use the SIGABRT signal to kill the Win32 service signal(SIGABRT, main_cleanup); // If this call succeeds, it is blocking on Win32 if (svc_start() != 1) SOCK_ASSERT("Unable to start the service", 1); // When the previous call returns, the entire application has to be stopped. exit(0); #endif } else // Console mode { // Enable the catching of Ctrl+C signal(SIGINT, main_cleanup); #ifndef _WIN32 // generated under unix with 'kill -HUP', needed to reload the configuration // We do not have this kind of signal in Win32 signal(SIGHUP, fileconf_read); #endif printf("Press CTRL + C to stop the server...\n"); } // If we're a Win32 service, we have already called this function in the service_main main_startup(); // The code should never arrive here (since the main_startup is blocking) // however this avoids a compiler warning exit(0); }