⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 softflowd.c

📁 根据网络原始数据生成NetFlow记录的软件。NetFlow是Cisco提出的流技术
💻 C
📖 第 1 页 / 共 4 页
字号:
	fprintf(stderr, "  -T full|proto|ip Set flow tracking level (default: full)\n");	fprintf(stderr, "  -6               Track IPv6 flows, regardless of whether selected \n"	                "                   NetFlow export protocol supports it\n");	fprintf(stderr, "  -d               Don't daemonise\n");	fprintf(stderr, "  -D               Debug mode: don't daemonise + verbosity + track v6 flows\n");	fprintf(stderr, "  -h               Display this help\n");	fprintf(stderr, "\n");	fprintf(stderr, "Valid timeout names and default values:\n");	fprintf(stderr, "  tcp     (default %6d)", DEFAULT_TCP_TIMEOUT);	fprintf(stderr, "  tcp.rst (default %6d)", DEFAULT_TCP_RST_TIMEOUT);	fprintf(stderr, "  tcp.fin (default %6d)\n", DEFAULT_TCP_FIN_TIMEOUT);	fprintf(stderr, "  udp     (default %6d)", DEFAULT_UDP_TIMEOUT);	fprintf(stderr, "  icmp    (default %6d)", DEFAULT_ICMP_TIMEOUT);	fprintf(stderr, "  general (default %6d)\n", DEFAULT_GENERAL_TIMEOUT);	fprintf(stderr, "  maxlife (default %6d)", DEFAULT_MAXIMUM_LIFETIME);	fprintf(stderr, "  expint  (default %6d)\n", DEFAULT_EXPIRY_INTERVAL);	fprintf(stderr, "\n");}static voidset_timeout(struct FLOWTRACK *ft, const char *to_spec){	char *name, *value;	int timeout;	if ((name = strdup(to_spec)) == NULL) {		fprintf(stderr, "Out of memory\n");		exit(1);	}	if ((value = strchr(name, '=')) == NULL ||	    *(++value) == '\0') {		fprintf(stderr, "Invalid -t option \"%s\".\n", name);		usage();		exit(1);	}	*(value - 1) = '\0';	timeout = convtime(value);	if (timeout < 0) {		fprintf(stderr, "Invalid -t timeout.\n");		usage();		exit(1);	}	if (strcmp(name, "tcp") == 0)		ft->tcp_timeout = timeout;	else if (strcmp(name, "tcp.rst") == 0)		ft->tcp_rst_timeout = timeout;	else if (strcmp(name, "tcp.fin") == 0)		ft->tcp_fin_timeout = timeout;	else if (strcmp(name, "udp") == 0)		ft->udp_timeout = timeout;	else if (strcmp(name, "icmp") == 0)		ft->icmp_timeout = timeout;	else if (strcmp(name, "general") == 0)		ft->general_timeout = timeout;	else if (strcmp(name, "maxlife") == 0)		ft->maximum_lifetime = timeout;	else if (strcmp(name, "expint") == 0)		ft->expiry_interval = timeout;	else {		fprintf(stderr, "Invalid -t name.\n");		usage();		exit(1);	}	if (ft->general_timeout == 0) {		fprintf(stderr, "\"general\" flow timeout must be "		    "greater than zero\n");		exit(1);	}	free(name);}static voidparse_hostport(const char *s, struct sockaddr *addr, socklen_t *len){	char *orig, *host, *port;	struct addrinfo hints, *res;	int herr;	if ((host = orig = strdup(s)) == NULL) {		fprintf(stderr, "Out of memory\n");		exit(1);	}	if ((port = strrchr(host, ':')) == NULL ||	    *(++port) == '\0' || *host == '\0') {		fprintf(stderr, "Invalid -n argument.\n");		usage();		exit(1);	}	*(port - 1) = '\0';		/* Accept [host]:port for numeric IPv6 addresses */	if (*host == '[' && *(port - 2) == ']') {		host++;		*(port - 2) = '\0';	}	memset(&hints, '\0', sizeof(hints));	hints.ai_socktype = SOCK_DGRAM;	if ((herr = getaddrinfo(host, port, &hints, &res)) == -1) {		fprintf(stderr, "Address lookup failed: %s\n",		    gai_strerror(herr));		exit(1);	}	if (res == NULL || res->ai_addr == NULL) {		fprintf(stderr, "No addresses found for [%s]:%s\n", host, port);		exit(1);	}	if (res->ai_addrlen > *len) {		fprintf(stderr, "Address too long\n");		exit(1);	}	memcpy(addr, res->ai_addr, res->ai_addrlen);	free(orig);	*len = res->ai_addrlen;}/*  * Drop privileges and chroot, will exit on failure */static void drop_privs(void){	struct passwd *pw;		if ((pw = getpwnam(PRIVDROP_USER)) == NULL) {		logit(LOG_ERR, "Unable to find unprivileged user \"%s\"", 		    PRIVDROP_USER);		exit(1);	}	if (chdir(PRIVDROP_CHROOT_DIR) != 0) {		logit(LOG_ERR, "Unable to chdir to chroot directory \"%s\": %s",		    PRIVDROP_CHROOT_DIR, strerror(errno));		exit(1);	}	if (chroot(PRIVDROP_CHROOT_DIR) != 0) {		logit(LOG_ERR, "Unable to chroot to directory \"%s\": %s",		    PRIVDROP_CHROOT_DIR, strerror(errno));		exit(1);	}	if (chdir("/") != 0) {		logit(LOG_ERR, "Unable to chdir to chroot root: %s",		    strerror(errno));		exit(1);	}	if (setgroups(1, &pw->pw_gid) != 0) {		logit(LOG_ERR, "Couldn't setgroups (%u): %s",		    (unsigned int)pw->pw_gid, strerror(errno));		exit(1);	}#if defined(HAVE_SETRESGID)	if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) {#elif defined(HAVE_SETREGID)	if (setregid(pw->pw_gid, pw->pw_gid) == -1) {#else	if (setegid(pw->pw_gid) == -1 || setgid(pw->pw_gid) == -1) {#endif		logit(LOG_ERR, "Couldn't set gid (%u): %s",		    (unsigned int)pw->pw_gid, strerror(errno));		exit(1);	}#if defined(HAVE_SETRESUID)	if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) {#elif defined(HAVE_SETREUID)	if (setreuid(pw->pw_uid, pw->pw_uid) == -1) {#else	if (seteuid(pw->pw_uid) == -1 || setuid(pw->pw_uid) == -1) {#endif		logit(LOG_ERR, "Couldn't set uid (%u): %s",		    (unsigned int)pw->pw_uid, strerror(errno));		exit(1);	}}intmain(int argc, char **argv){	char *dev, *capfile, *bpf_prog, dest_addr[256], dest_serv[256];	const char *pidfile_path, *ctlsock_path;	extern char *optarg;	extern int optind;	int ch, dontfork_flag, linktype, ctlsock, i, r, err, always_v6;	int max_flows, stop_collection_flag, exit_request, hoplimit;	pcap_t *pcap = NULL;	struct sockaddr_storage dest;	struct FLOWTRACK flowtrack;	socklen_t dest_len;	struct NETFLOW_TARGET target;	struct CB_CTXT cb_ctxt;	struct pollfd pl[2];	closefrom(STDERR_FILENO + 1);	init_flowtrack(&flowtrack);	memset(&dest, '\0', sizeof(dest));	memset(&target, '\0', sizeof(target));	target.fd = -1;	target.dialect = &nf[0];	hoplimit = -1;	bpf_prog = NULL;	ctlsock = -1;	dev = capfile = NULL;	max_flows = DEFAULT_MAX_FLOWS;	pidfile_path = DEFAULT_PIDFILE;	ctlsock_path = DEFAULT_CTLSOCK;	dontfork_flag = 0;	always_v6 = 0;	while ((ch = getopt(argc, argv, "6hdDL:T:i:r:f:t:n:m:p:c:v:")) != -1) {		switch (ch) {		case '6':			always_v6 = 1;			break;		case 'h':			usage();			return (0);		case 'D':			verbose_flag = 1;			always_v6 = 1;			/* FALLTHROUGH */		case 'd':			dontfork_flag = 1;			break;		case 'i':			if (capfile != NULL || dev != NULL) {				fprintf(stderr, "Packet source already specified.\n\n");				usage();				exit(1);			}			dev = optarg;			break;		case 'r':			if (capfile != NULL || dev != NULL) {				fprintf(stderr, "Packet source already specified.\n\n");				usage();				exit(1);			}			capfile = optarg;			dontfork_flag = 1;			ctlsock_path = NULL;			break;		case 't':			/* Will exit on failure */			set_timeout(&flowtrack, optarg); 			break;		case 'T':			if (strcasecmp(optarg, "full") == 0)				flowtrack.track_level = TRACK_FULL;			else if (strcasecmp(optarg, "proto") == 0)				flowtrack.track_level = TRACK_IP_PROTO;			else if (strcasecmp(optarg, "ip") == 0)				flowtrack.track_level = TRACK_IP_ONLY;			else {				fprintf(stderr, "Unknown flow tracking level\n");				usage();				exit(1);			}			break;		case 'L':			hoplimit = atoi(optarg);			if (hoplimit < 0 || hoplimit > 255) {				fprintf(stderr, "Invalid hop limit\n\n");				usage();				exit(1);			}			break;		case 'm':			if ((max_flows = atoi(optarg)) < 0) {				fprintf(stderr, "Invalid maximum flows\n\n");				usage();				exit(1);			}			break;		case 'n':			/* Will exit on failure */			dest_len = sizeof(dest);			parse_hostport(optarg, (struct sockaddr *)&dest,			    &dest_len);			break;		case 'p':			pidfile_path = optarg;			break;		case 'c':			if (strcmp(optarg, "none") == 0)				ctlsock_path = NULL;			else				ctlsock_path = optarg;			break;		case 'v':			for(i = 0, r = atoi(optarg); nf[i].version != -1; i++) {				if (nf[i].version == r)					break;			}			if (nf[i].version == -1) {				fprintf(stderr, "Invalid NetFlow version\n");				exit(1);			}			target.dialect = &nf[i];			break;		default:			fprintf(stderr, "Invalid commandline option.\n");			usage();			exit(1);		}	}	if (capfile == NULL && dev == NULL) {		fprintf(stderr, "-i or -r option not specified.\n");		usage();		exit(1);	}		/* join remaining arguments (if any) into bpf program */	bpf_prog = argv_join(argc - optind, argv + optind);	/* Will exit on failure */	setup_packet_capture(&pcap, &linktype, dev, capfile, bpf_prog,	    target.dialect->v6_capable || always_v6);		/* Netflow send socket */	if (dest.ss_family != 0) {		if ((err = getnameinfo((struct sockaddr *)&dest,		    dest_len, dest_addr, sizeof(dest_addr), 		    dest_serv, sizeof(dest_serv), NI_NUMERICHOST)) == -1) {			fprintf(stderr, "getnameinfo: %d\n", err);			exit(1);		}		target.fd = connsock(&dest, dest_len, hoplimit);	}		/* Control socket */	if (ctlsock_path != NULL)		ctlsock = unix_listener(ctlsock_path); /* Will exit on fail */		if (dontfork_flag) {		loginit(PROGNAME, 1);	} else {			FILE *pidfile;		daemon(0, 0);		loginit(PROGNAME, 0);		if ((pidfile = fopen(pidfile_path, "w")) == NULL) {			fprintf(stderr, "Couldn't open pidfile %s: %s\n",			    pidfile_path, strerror(errno));			exit(1);		}		fprintf(pidfile, "%u\n", getpid());		fclose(pidfile);		signal(SIGINT, sighand_graceful_shutdown);		signal(SIGTERM, sighand_graceful_shutdown);		signal(SIGSEGV, sighand_other);		setprotoent(1);		drop_privs();	}	logit(LOG_NOTICE, "%s v%s starting data collection", 	    PROGNAME, PROGVER);	if (dest.ss_family != 0) {		logit(LOG_NOTICE, "Exporting flows to [%s]:%s",		    dest_addr, dest_serv);	}	/* Main processing loop */	gettimeofday(&flowtrack.system_boot_time, NULL);	stop_collection_flag = 0;	memset(&cb_ctxt, '\0', sizeof(cb_ctxt));	cb_ctxt.ft = &flowtrack;	cb_ctxt.linktype = linktype;	cb_ctxt.want_v6 = target.dialect->v6_capable || always_v6;	for(;;) {		/*		 * Silly libpcap's timeout function doesn't work, so we		 * do it here (only if we are reading live)		 */		r = 0;		if (capfile == NULL) {			memset(pl, '\0', sizeof(pl));			/* This can only be set via the control socket */			if (!stop_collection_flag) {				pl[0].events = POLLIN|POLLERR|POLLHUP;				pl[0].fd = pcap_fileno(pcap);			}			if (ctlsock != -1) {				pl[1].fd = ctlsock;				pl[1].events = POLLIN|POLLERR|POLLHUP;			}			r = poll(pl, (ctlsock == -1) ? 1 : 2, 			    next_expire(&flowtrack));			if (r == -1 && errno != EINTR) {				logit(LOG_ERR, "Exiting on poll: %s", 				    strerror(errno));				break;			}		}		/* Accept connection on control socket if present */		if (ctlsock != -1 && pl[1].revents != 0) {			if (accept_control(ctlsock, &target, &flowtrack, pcap,			    &exit_request, &stop_collection_flag) != 0)				break;		}		/* If we have data, run it through libpcap */		if (!stop_collection_flag && 		    (capfile != NULL || pl[0].revents != 0)) {			r = pcap_dispatch(pcap, max_flows, flow_cb, (void*)&cb_ctxt);			if (r == -1) {				logit(LOG_ERR, "Exiting on pcap_dispatch: %s", 				    pcap_geterr(pcap));				break;			} else if (r == 0) {				logit(LOG_NOTICE, "Shutting down after pcap EOF");				graceful_shutdown_request = 1;				break;			}		}		r = 0;		/* Fatal error from per-packet functions */		if (cb_ctxt.fatal) {			logit(LOG_WARNING, "Fatal error - exiting immediately");			break;		}		/*		 * Expiry processing happens every recheck_rate seconds		 * or whenever we have exceeded the maximum number of active 		 * flows		 */		if (flowtrack.num_flows > max_flows || 		    next_expire(&flowtrack) == 0) {expiry_check:			/*			 * If we are reading from a capture file, we never			 * expire flows based on time - instead we only 			 * expire flows when the flow table is full. 			 */			if (check_expired(&flowtrack, &target, 			    capfile == NULL ? CE_EXPIRE_NORMAL : CE_EXPIRE_FORCED) < 0)				logit(LOG_WARNING, "Unable to export flows");				/*			 * If we are over max_flows, force-expire the oldest 			 * out first and immediately reprocess to evict them			 */			if (flowtrack.num_flows > max_flows) {				force_expire(&flowtrack, flowtrack.num_flows - max_flows);				goto expiry_check;			}		}	}	/* Flags set by signal handlers or control socket */	if (graceful_shutdown_request) {		logit(LOG_WARNING, "Shutting down on user request");		check_expired(&flowtrack, &target, CE_EXPIRE_ALL);	} else if (exit_request)		logit(LOG_WARNING, "Exiting immediately on user request");	else		logit(LOG_ERR, "Exiting immediately on internal error");			if (capfile != NULL && dontfork_flag)		statistics(&flowtrack, stdout, pcap);	pcap_close(pcap);		if (target.fd != -1)		close(target.fd);	unlink(pidfile_path);	if (ctlsock_path != NULL)		unlink(ctlsock_path);		return(r == 0 ? 0 : 1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -