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

📄 softflowd.c

📁 根据网络原始数据生成NetFlow记录的软件。NetFlow是Cisco提出的流技术
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (ft->flows_expired != 0) {		fprintf(out, "Expired flow statistics:  minimum       average       maximum\n");		fprintf(out, "  Flow bytes:        %12.0f  %12.0f  %12.0f\n", 		    ft->octets.min, ft->octets.mean, ft->octets.max);		fprintf(out, "  Flow packets:      %12.0f  %12.0f  %12.0f\n", 		    ft->packets.min, ft->packets.mean, ft->packets.max);		fprintf(out, "  Duration:          %12.2fs %12.2fs %12.2fs\n", 		    ft->duration.min, ft->duration.mean, ft->duration.max);		fprintf(out, "\n");		fprintf(out, "Expired flow reasons:\n");		fprintf(out, "       tcp = %9llu   tcp.rst = %9llu   tcp.fin = %9llu\n", 		    ft->expired_tcp, ft->expired_tcp_rst, ft->expired_tcp_fin);		fprintf(out, "       udp = %9llu      icmp = %9llu   general = %9llu\n",		    ft->expired_udp, ft->expired_icmp, ft->expired_general);		fprintf(out, "   maxlife = %9llu\n", ft->expired_maxlife);		fprintf(out, "  over 2Gb = %9llu\n", ft->expired_overbytes);		fprintf(out, "  maxflows = %9llu\n", ft->expired_maxflows);		fprintf(out, "   flushed = %9llu\n", ft->expired_flush);		fprintf(out, "\n");		fprintf(out, "Per-protocol statistics:     Octets      Packets   Avg Life    Max Life\n");		for(i = 0; i < 256; i++) {			if (ft->packets_pp[i]) {				pe = getprotobynumber(i);				snprintf(proto, sizeof(proto), "%s (%d)", 				    pe != NULL ? pe->p_name : "Unknown", i);				fprintf(out, 				    "  %17s: %14llu %12llu   %8.2fs %10.2fs\n",				    proto,				    ft->octets_pp[i], 				    ft->packets_pp[i],				    ft->duration_pp[i].mean,				    ft->duration_pp[i].max);			}		}	}	return (0);}static voiddump_flows(struct FLOWTRACK *ft, FILE *out){	struct EXPIRY *expiry;	time_t now;	now = time(NULL);	EXPIRY_FOREACH(expiry, EXPIRIES, &ft->expiries) {		fprintf(out, "ACTIVE %s\n", format_flow(expiry->flow));		if ((long int) expiry->expires_at - now < 0) {			fprintf(out, 			    "EXPIRY EVENT for flow %llu now%s\n",			    expiry->flow->flow_seq, 			    expiry->expires_at == 0 ? " (FORCED)": "");		} else {			fprintf(out, 			    "EXPIRY EVENT for flow %llu in %ld seconds\n",			    expiry->flow->flow_seq, 			    (long int) expiry->expires_at - now);		}		fprintf(out, "\n");	}}/* * Figure out how many bytes to skip from front of packet to get past  * datalink headers. If pkt is specified, also check whether determine * whether or not it is one that we are interested in (IPv4 or IPv6 for now) * * Returns number of bytes to skip or -1 to indicate that entire  * packet should be skipped */static int datalink_check(int linktype, const u_int8_t *pkt, u_int32_t caplen, int *af){	int i, j;	u_int32_t frametype;	static const struct DATALINK *dl = NULL;	/* Try to cache last used linktype */	if (dl == NULL || dl->dlt != linktype) {		for (i = 0; lt[i].dlt != linktype && lt[i].dlt != -1; i++)			;		dl = &lt[i];	}	if (dl->dlt == -1 || pkt == NULL)		return (dl->dlt);	if (caplen <= dl->skiplen)		return (-1);	/* Suck out the frametype */	frametype = 0;	if (dl->ft_is_be) {		for (j = 0; j < dl->ft_len; j++) {			frametype <<= 8;			frametype |= pkt[j + dl->ft_off];		}	} else {		for (j = dl->ft_len - 1; j >= 0 ; j--) {			frametype <<= 8;			frametype |= pkt[j + dl->ft_off];		}	}	frametype &= dl->ft_mask;	if (frametype == dl->ft_v4)		*af = AF_INET;	else if (frametype == dl->ft_v6)		*af = AF_INET6;	else		return (-1);		return (dl->skiplen);}/* * Per-packet callback function from libpcap. Pass the packet (if it is IP) * sans datalink headers to process_packet. */static voidflow_cb(u_char *user_data, const struct pcap_pkthdr* phdr,     const u_char *pkt){	int s, af;	struct CB_CTXT *cb_ctxt = (struct CB_CTXT *)user_data;	struct timeval tv;	s = datalink_check(cb_ctxt->linktype, pkt, phdr->caplen, &af);	if (s < 0 || (!cb_ctxt->want_v6 && af == AF_INET6)) {		cb_ctxt->ft->non_ip_packets++;	} else {		tv.tv_sec = phdr->ts.tv_sec;		tv.tv_usec = phdr->ts.tv_usec;		if (process_packet(cb_ctxt->ft, pkt + s, af,		    phdr->caplen - s, phdr->len - s, &tv) == PP_MALLOC_FAIL)			cb_ctxt->fatal = 1;	}}static voidprint_timeouts(struct FLOWTRACK *ft, FILE *out){	fprintf(out, "           TCP timeout: %ds\n", ft->tcp_timeout);	fprintf(out, "  TCP post-RST timeout: %ds\n", ft->tcp_rst_timeout);	fprintf(out, "  TCP post-FIN timeout: %ds\n", ft->tcp_fin_timeout);	fprintf(out, "           UDP timeout: %ds\n", ft->udp_timeout);	fprintf(out, "          ICMP timeout: %ds\n", ft->icmp_timeout);	fprintf(out, "       General timeout: %ds\n", ft->general_timeout);	fprintf(out, "      Maximum lifetime: %ds\n", ft->maximum_lifetime);	fprintf(out, "       Expiry interval: %ds\n", ft->expiry_interval);}static intaccept_control(int lsock, struct NETFLOW_TARGET *target, struct FLOWTRACK *ft,    pcap_t *pcap, int *exit_request, int *stop_collection_flag){	unsigned char buf[64], *p;	FILE *ctlf;	int fd, ret;	if ((fd = accept(lsock, NULL, NULL)) == -1) {		logit(LOG_ERR, "ctl accept: %s - exiting",		    strerror(errno));		return(-1);	}	if ((ctlf = fdopen(fd, "r+")) == NULL) {		logit(LOG_ERR, "fdopen: %s - exiting\n",		    strerror(errno));		close(fd);		return (-1);	}	setlinebuf(ctlf);	if (fgets(buf, sizeof(buf), ctlf) == NULL) {		logit(LOG_ERR, "Control socket yielded no data");		return (0);	}	if ((p = strchr(buf, '\n')) != NULL)		*p = '\0';		if (verbose_flag)		logit(LOG_DEBUG, "Control socket \"%s\"", buf);	/* XXX - use dispatch table */	ret = -1;	if (strcmp(buf, "help") == 0) {		fprintf(ctlf, "Valid control words are:\n");		fprintf(ctlf, "\tdebug+ debug- delete-all dump-flows exit "		    "expire-all\n");		fprintf(ctlf, "\tshutdown start-gather statistics stop-gather "		    "timeouts\n");		fprintf(ctlf, "\tsend-template\n");		ret = 0;	} else if (strcmp(buf, "shutdown") == 0) {		fprintf(ctlf, "softflowd[%u]: Shutting down gracefully...\n", getpid());		graceful_shutdown_request = 1;		ret = 1;	} else if (strcmp(buf, "exit") == 0) {		fprintf(ctlf, "softflowd[%u]: Exiting now...\n", getpid());		*exit_request = 1;		ret = 1;	} else if (strcmp(buf, "expire-all") == 0) {		netflow9_resend_template();		fprintf(ctlf, "softflowd[%u]: Expired %d flows.\n", getpid(), 		    check_expired(ft, target, CE_EXPIRE_ALL));		ret = 0;	} else if (strcmp(buf, "send-template") == 0) {		netflow9_resend_template();		fprintf(ctlf, "softflowd[%u]: Template will be sent at "		    "next flow export\n", getpid());		ret = 0;	} else if (strcmp(buf, "delete-all") == 0) {		fprintf(ctlf, "softflowd[%u]: Deleted %d flows.\n", getpid(), 		    delete_all_flows(ft));		ret = 0;	} else if (strcmp(buf, "statistics") == 0) {		fprintf(ctlf, "softflowd[%u]: Accumulated statistics:\n", 		    getpid());		statistics(ft, ctlf, pcap);		ret = 0;	} else if (strcmp(buf, "debug+") == 0) {		fprintf(ctlf, "softflowd[%u]: Debug level increased.\n",		    getpid());		verbose_flag = 1;		ret = 0;	} else if (strcmp(buf, "debug-") == 0) {		fprintf(ctlf, "softflowd[%u]: Debug level decreased.\n",		    getpid());		verbose_flag = 0;		ret = 0;	} else if (strcmp(buf, "stop-gather") == 0) {		fprintf(ctlf, "softflowd[%u]: Data collection stopped.\n",		    getpid());		*stop_collection_flag = 1;		ret = 0;	} else if (strcmp(buf, "start-gather") == 0) {		fprintf(ctlf, "softflowd[%u]: Data collection resumed.\n",		    getpid());		*stop_collection_flag = 0;		ret = 0;	} else if (strcmp(buf, "dump-flows") == 0) {		fprintf(ctlf, "softflowd[%u]: Dumping flow data:\n",		    getpid());		dump_flows(ft, ctlf);		ret = 0;	} else if (strcmp(buf, "timeouts") == 0) {		fprintf(ctlf, "softflowd[%u]: Printing timeouts:\n",		    getpid());		print_timeouts(ft, ctlf);		ret = 0;	} else {		fprintf(ctlf, "Unknown control commmand \"%s\"\n", buf);		ret = 0;	}	fclose(ctlf);	close(fd);		return (ret);}static intconnsock(struct sockaddr_storage *addr, socklen_t len, int hoplimit){	int s;	unsigned int h6;	unsigned char h4;	struct sockaddr_in *in4 = (struct sockaddr_in *)addr;	struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;	if ((s = socket(addr->ss_family, SOCK_DGRAM, 0)) == -1) {		fprintf(stderr, "socket() error: %s\n", 		    strerror(errno));		exit(1);	}	if (connect(s, (struct sockaddr*)addr, len) == -1) {		fprintf(stderr, "connect() error: %s\n",		    strerror(errno));		exit(1);	}	switch (addr->ss_family) {	case AF_INET:		/* Default to link-local TTL for multicast addresses */		if (hoplimit == -1 && IN_MULTICAST(in4->sin_addr.s_addr))			hoplimit = 1;		if (hoplimit == -1)			break;		h4 = hoplimit;		if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,		    &h4, sizeof(h4)) == -1) {			fprintf(stderr, "setsockopt(IP_MULTICAST_TTL, "			    "%u): %s\n", h4, strerror(errno));			exit(1);		}		break;	case AF_INET6:		/* Default to link-local hoplimit for multicast addresses */		if (hoplimit == -1 && IN6_IS_ADDR_MULTICAST(&in6->sin6_addr))			hoplimit = 1;		if (hoplimit == -1)			break;		h6 = hoplimit;		if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,		    &h6, sizeof(h6)) == -1) {			fprintf(stderr, "setsockopt(IPV6_MULTICAST_HOPS, %u): "			"%s\n", h6, strerror(errno));			exit(1);		}	}	return(s);}static int unix_listener(const char *path){	struct sockaddr_un addr;	socklen_t addrlen;	int s;	memset(&addr, '\0', sizeof(addr));	addr.sun_family = AF_UNIX;		if (strlcpy(addr.sun_path, path, sizeof(addr.sun_path)) >=	    sizeof(addr.sun_path)) {		fprintf(stderr, "control socket path too long\n");		exit(1);	}		addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';		addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(path) + 1;#ifdef SOCK_HAS_LEN 	addr.sun_len = addrlen;#endif	if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {		fprintf(stderr, "unix domain socket() error: %s\n", 		    strerror(errno));		exit(1);	}	unlink(path);	if (bind(s, (struct sockaddr*)&addr, addrlen) == -1) {		fprintf(stderr, "unix domain bind(\"%s\") error: %s\n",		    addr.sun_path, strerror(errno));		exit(1);	}	if (listen(s, 64) == -1) {		fprintf(stderr, "unix domain listen() error: %s\n",		    strerror(errno));		exit(1);	}		return (s);}static voidsetup_packet_capture(struct pcap **pcap, int *linktype,     char *dev, char *capfile, char *bpf_prog, int need_v6){	char ebuf[PCAP_ERRBUF_SIZE];	struct bpf_program prog_c;	u_int32_t bpf_mask, bpf_net;	/* Open pcap */	if (dev != NULL) {		if ((*pcap = pcap_open_live(dev, 		    need_v6 ? LIBPCAP_SNAPLEN_V6 : LIBPCAP_SNAPLEN_V4, 		    1, 0, ebuf)) == NULL) {			fprintf(stderr, "pcap_open_live: %s\n", ebuf);			exit(1);		}		if (pcap_lookupnet(dev, &bpf_net, &bpf_mask, ebuf) == -1)			bpf_net = bpf_mask = 0;	} else {		if ((*pcap = pcap_open_offline(capfile, ebuf)) == NULL) {			fprintf(stderr, "pcap_open_offline(%s): %s\n", 			    capfile, ebuf);			exit(1);		}		bpf_net = bpf_mask = 0;	}	*linktype = pcap_datalink(*pcap);	if (datalink_check(*linktype, NULL, 0, NULL) == -1) {		fprintf(stderr, "Unsupported datalink type %d\n", *linktype);		exit(1);	}	/* Attach BPF filter, if specified */	if (bpf_prog != NULL) {		if (pcap_compile(*pcap, &prog_c, bpf_prog, 1, bpf_mask) == -1) {			fprintf(stderr, "pcap_compile(\"%s\"): %s\n", 			    bpf_prog, pcap_geterr(*pcap));			exit(1);		}		if (pcap_setfilter(*pcap, &prog_c) == -1) {			fprintf(stderr, "pcap_setfilter: %s\n", 			    pcap_geterr(*pcap));			exit(1);		}	}#ifdef BIOCLOCK	/*	 * If we are reading from an device (not a file), then 	 * lock the underlying BPF device to prevent changes in the 	 * unprivileged child	 */	if (dev != NULL && ioctl(pcap_fileno(*pcap), BIOCLOCK) < 0) {		fprintf(stderr, "ioctl(BIOCLOCK) failed: %s\n",		    strerror(errno));		exit(1);	}#endif}static voidinit_flowtrack(struct FLOWTRACK *ft){	/* Set up flow-tracking structure */	memset(ft, '\0', sizeof(*ft));	ft->next_flow_seq = 1;	FLOW_INIT(&ft->flows);	EXPIRY_INIT(&ft->expiries);		ft->track_level = TRACK_FULL;	ft->tcp_timeout = DEFAULT_TCP_TIMEOUT;	ft->tcp_rst_timeout = DEFAULT_TCP_RST_TIMEOUT;	ft->tcp_fin_timeout = DEFAULT_TCP_FIN_TIMEOUT;	ft->udp_timeout = DEFAULT_UDP_TIMEOUT;	ft->icmp_timeout = DEFAULT_ICMP_TIMEOUT;	ft->general_timeout = DEFAULT_GENERAL_TIMEOUT;	ft->maximum_lifetime = DEFAULT_MAXIMUM_LIFETIME;	ft->expiry_interval = DEFAULT_EXPIRY_INTERVAL;}static char *argv_join(int argc, char **argv){	int i;	size_t ret_len;	char *ret;	ret_len = 0;	ret = NULL;	for (i = 0; i < argc; i++) {		ret_len += strlen(argv[i]);		if ((ret = realloc(ret, ret_len + 2)) == NULL) {			fprintf(stderr, "Memory allocation failed.\n");			exit(1);		}		if (i == 0)			ret[0] = '\0';		else {			ret_len++; /* Make room for ' ' */			strlcat(ret, " ", ret_len + 1);		}					strlcat(ret, argv[i], ret_len + 1);	}	return (ret);}/* Display commandline usage information */static voidusage(void){	fprintf(stderr, "Usage: %s [options] [bpf_program]\n", PROGNAME);	fprintf(stderr, "This is %s version %s. Valid commandline options:\n", PROGNAME, PROGVER);	fprintf(stderr, "  -i interface     Specify interface to listen on\n");	fprintf(stderr, "  -r pcap_file     Specify packet capture file to read\n");	fprintf(stderr, "  -t timeout=time  Specify named timeout\n");	fprintf(stderr, "  -m max_flows     Specify maximum number of flows to track (default %d)\n", DEFAULT_MAX_FLOWS);	fprintf(stderr, "  -n host:port     Send Cisco NetFlow(tm)-compatible packets to host:port\n");	fprintf(stderr, "  -p pidfile       Record pid in specified file (default: %s)\n", DEFAULT_PIDFILE);	fprintf(stderr, "  -c pidfile       Location of control socket (default: %s)\n", DEFAULT_CTLSOCK);	fprintf(stderr, "  -v 1|5|9         NetFlow export packet version\n");	fprintf(stderr, "  -L hoplimit      Set TTL/hoplimit for export datagrams\n");

⌨️ 快捷键说明

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