Beispiel #1
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
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);
}
Beispiel #2
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);
}