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

📄 netflow9.c

📁 根据网络原始数据生成NetFlow记录的软件。NetFlow是Cisco提出的流技术
💻 C
字号:
/* * Copyright 2002 Damien Miller <djm@mindrot.org> All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *//* $Id: netflow9.c,v 1.9 2006/03/16 08:23:13 djm Exp $ */#include "common.h"#include "log.h"#include "treetype.h"#include "softflowd.h"RCSID("$Id: netflow9.c,v 1.9 2006/03/16 08:23:13 djm Exp $");/* Netflow v.9 */struct NF9_HEADER {	u_int16_t version, flows;	u_int32_t uptime_ms, time_sec;	u_int32_t package_sequence, source_id;} __packed;struct NF9_FLOWSET_HEADER_COMMON {	u_int16_t flowset_id, length;} __packed;struct NF9_TEMPLATE_FLOWSET_HEADER {	struct NF9_FLOWSET_HEADER_COMMON c;	u_int16_t template_id, count;} __packed;struct NF9_TEMPLATE_FLOWSET_RECORD {	u_int16_t type, length;} __packed;struct NF9_DATA_FLOWSET_HEADER {	struct NF9_FLOWSET_HEADER_COMMON c;} __packed;#define NF9_TEMPLATE_FLOWSET_ID		0#define NF9_OPTIONS_FLOWSET_ID		1#define NF9_MIN_RECORD_FLOWSET_ID	256/* Flowset record types the we care about */#define NF9_IN_BYTES			1#define NF9_IN_PACKETS			2/* ... */#define NF9_IN_PROTOCOL			4/* ... */#define NF9_TCP_FLAGS			6#define NF9_L4_SRC_PORT			7#define NF9_IPV4_SRC_ADDR		8/* ... */#define NF9_L4_DST_PORT			11#define NF9_IPV4_DST_ADDR		12/* ... */#define NF9_LAST_SWITCHED		21#define NF9_FIRST_SWITCHED		22/* ... */#define NF9_IPV6_SRC_ADDR		27#define NF9_IPV6_DST_ADDR		28/* ... */#define NF9_IP_PROTOCOL_VERSION		60/* Stuff pertaining to the templates that softflowd uses */#define NF9_SOFTFLOWD_TEMPLATE_NRECORDS	11struct NF9_SOFTFLOWD_TEMPLATE {	struct NF9_TEMPLATE_FLOWSET_HEADER h;	struct NF9_TEMPLATE_FLOWSET_RECORD r[NF9_SOFTFLOWD_TEMPLATE_NRECORDS];} __packed;/* softflowd data flowset types */struct NF9_SOFTFLOWD_DATA_COMMON {	u_int32_t first_switched, last_switched;	u_int32_t bytes, packets;	u_int16_t src_port, dst_port;	u_int8_t protocol, tcp_flags, ipproto;} __packed;struct NF9_SOFTFLOWD_DATA_V4 {	u_int32_t src_addr, dst_addr;	struct NF9_SOFTFLOWD_DATA_COMMON c;} __packed;struct NF9_SOFTFLOWD_DATA_V6 {	u_int8_t src_addr[16], dst_addr[16];	struct NF9_SOFTFLOWD_DATA_COMMON c;} __packed;/* Local data: templates and counters */#define NF9_SOFTFLOWD_MAX_PACKET_SIZE	512#define NF9_SOFTFLOWD_V4_TEMPLATE_ID	1024#define NF9_SOFTFLOWD_V6_TEMPLATE_ID	2048#define NF9_DEFAULT_TEMPLATE_INTERVAL	16static struct NF9_SOFTFLOWD_TEMPLATE v4_template;static struct NF9_SOFTFLOWD_TEMPLATE v6_template;static int nf9_pkts_until_template = -1;static voidnf9_init_template(void){	bzero(&v4_template, sizeof(v4_template));	v4_template.h.c.flowset_id = htons(0);	v4_template.h.c.length = htons(sizeof(v4_template));	v4_template.h.template_id = htons(NF9_SOFTFLOWD_V4_TEMPLATE_ID);	v4_template.h.count = htons(NF9_SOFTFLOWD_TEMPLATE_NRECORDS);	v4_template.r[0].type = htons(NF9_IPV4_SRC_ADDR);	v4_template.r[0].length = htons(4);	v4_template.r[1].type = htons(NF9_IPV4_DST_ADDR);	v4_template.r[1].length = htons(4);	v4_template.r[2].type = htons(NF9_LAST_SWITCHED);	v4_template.r[2].length = htons(4);	v4_template.r[3].type = htons(NF9_FIRST_SWITCHED);	v4_template.r[3].length = htons(4);	v4_template.r[4].type = htons(NF9_IN_BYTES);	v4_template.r[4].length = htons(4);	v4_template.r[5].type = htons(NF9_IN_PACKETS);	v4_template.r[5].length = htons(4);	v4_template.r[6].type = htons(NF9_L4_SRC_PORT);	v4_template.r[6].length = htons(2);	v4_template.r[7].type = htons(NF9_L4_DST_PORT);	v4_template.r[7].length = htons(2);	v4_template.r[8].type = htons(NF9_IN_PROTOCOL);	v4_template.r[8].length = htons(1);	v4_template.r[9].type = htons(NF9_TCP_FLAGS);	v4_template.r[9].length = htons(1);	v4_template.r[10].type = htons(NF9_IP_PROTOCOL_VERSION);	v4_template.r[10].length = htons(1);	bzero(&v6_template, sizeof(v6_template));	v6_template.h.c.flowset_id = htons(0);	v6_template.h.c.length = htons(sizeof(v6_template));	v6_template.h.template_id = htons(NF9_SOFTFLOWD_V6_TEMPLATE_ID);	v6_template.h.count = htons(NF9_SOFTFLOWD_TEMPLATE_NRECORDS);	v6_template.r[0].type = htons(NF9_IPV6_SRC_ADDR);	v6_template.r[0].length = htons(16);	v6_template.r[1].type = htons(NF9_IPV6_DST_ADDR);	v6_template.r[1].length = htons(16);	v6_template.r[2].type = htons(NF9_LAST_SWITCHED);	v6_template.r[2].length = htons(4);	v6_template.r[3].type = htons(NF9_FIRST_SWITCHED);	v6_template.r[3].length = htons(4);	v6_template.r[4].type = htons(NF9_IN_BYTES);	v6_template.r[4].length = htons(4);	v6_template.r[5].type = htons(NF9_IN_PACKETS);	v6_template.r[5].length = htons(4);	v6_template.r[6].type = htons(NF9_L4_SRC_PORT);	v6_template.r[6].length = htons(2);	v6_template.r[7].type = htons(NF9_L4_DST_PORT);	v6_template.r[7].length = htons(2);	v6_template.r[8].type = htons(NF9_IN_PROTOCOL);	v6_template.r[8].length = htons(1);	v6_template.r[9].type = htons(NF9_TCP_FLAGS);	v6_template.r[9].length = htons(1);	v6_template.r[10].type = htons(NF9_IP_PROTOCOL_VERSION);	v6_template.r[10].length = htons(1);}static intnf_flow_to_flowset(const struct FLOW *flow, u_char *packet, u_int len,    const struct timeval *system_boot_time, u_int *len_used){	union {		struct NF9_SOFTFLOWD_DATA_V4 d4;		struct NF9_SOFTFLOWD_DATA_V6 d6;	} d[2];	struct NF9_SOFTFLOWD_DATA_COMMON *dc[2];	u_int freclen, ret_len, nflows;	bzero(d, sizeof(d));	*len_used = nflows = ret_len = 0;	switch (flow->af) {	case AF_INET:		freclen = sizeof(struct NF9_SOFTFLOWD_DATA_V4);		memcpy(&d[0].d4.src_addr, &flow->addr[0].v4, 4);		memcpy(&d[0].d4.dst_addr, &flow->addr[1].v4, 4);		memcpy(&d[1].d4.src_addr, &flow->addr[1].v4, 4);		memcpy(&d[1].d4.dst_addr, &flow->addr[0].v4, 4);		dc[0] = &d[0].d4.c;		dc[1] = &d[1].d4.c;		dc[0]->ipproto = dc[1]->ipproto = 4;		break;	case AF_INET6:		freclen = sizeof(struct NF9_SOFTFLOWD_DATA_V6);		memcpy(&d[0].d6.src_addr, &flow->addr[0].v6, 16);		memcpy(&d[0].d6.dst_addr, &flow->addr[1].v6, 16);		memcpy(&d[1].d6.src_addr, &flow->addr[1].v6, 16);		memcpy(&d[1].d6.dst_addr, &flow->addr[0].v6, 16);		dc[0] = &d[0].d6.c;		dc[1] = &d[1].d6.c;		dc[0]->ipproto = dc[1]->ipproto = 6;		break;	default:		return (-1);	}	dc[0]->first_switched = dc[1]->first_switched = 	    htonl(timeval_sub_ms(&flow->flow_start, system_boot_time));	dc[0]->last_switched = dc[1]->last_switched = 	    htonl(timeval_sub_ms(&flow->flow_last, system_boot_time));	dc[0]->bytes = htonl(flow->octets[0]);	dc[1]->bytes = htonl(flow->octets[1]);	dc[0]->packets = htonl(flow->packets[0]);	dc[1]->packets = htonl(flow->packets[1]);	dc[0]->src_port = dc[1]->dst_port = flow->port[0];	dc[1]->src_port = dc[0]->dst_port = flow->port[1];	dc[0]->protocol = dc[1]->protocol = flow->protocol;	dc[0]->tcp_flags = flow->tcp_flags[0];	dc[1]->tcp_flags = flow->tcp_flags[1];	if (flow->octets[0] > 0) {		if (ret_len + freclen > len)			return (-1);		memcpy(packet + ret_len, &d[0], freclen);		ret_len += freclen;		nflows++;	}	if (flow->octets[1] > 0) {		if (ret_len + freclen > len)			return (-1);		memcpy(packet + ret_len, &d[1], freclen);		ret_len += freclen;		nflows++;	}	*len_used = ret_len;	return (nflows);}/* * Given an array of expired flows, send netflow v9 report packets * Returns number of packets sent or -1 on error */intsend_netflow_v9(struct FLOW **flows, int num_flows, int nfsock,    u_int64_t *flows_exported, struct timeval *system_boot_time,    int verbose_flag){	struct NF9_HEADER *nf9;	struct NF9_DATA_FLOWSET_HEADER *dh;	struct timeval now;	u_int offset, last_af, i, j, num_packets, inc, last_valid;	socklen_t errsz;	int err, r;	u_char packet[NF9_SOFTFLOWD_MAX_PACKET_SIZE];	gettimeofday(&now, NULL);	if (nf9_pkts_until_template == -1) {		nf9_init_template();		nf9_pkts_until_template = 0;	}			last_valid = num_packets = 0;	for (j = 0; j < num_flows;) {		bzero(packet, sizeof(packet));		nf9 = (struct NF9_HEADER *)packet;		nf9->version = htons(9);		nf9->flows = 0; /* Filled as we go, htons at end */		nf9->uptime_ms = htonl(timeval_sub_ms(&now, system_boot_time));		nf9->time_sec = htonl(time(NULL));		nf9->package_sequence = htonl(*flows_exported + j);		nf9->source_id = 0;		offset = sizeof(*nf9);		/* Refresh template headers if we need to */		if (nf9_pkts_until_template <= 0) {			memcpy(packet + offset, &v4_template,			    sizeof(v4_template));			offset += sizeof(v4_template);			memcpy(packet + offset, &v6_template,			    sizeof(v6_template));			offset += sizeof(v6_template);			nf9_pkts_until_template = NF9_DEFAULT_TEMPLATE_INTERVAL;		}		dh = NULL;		last_af = 0;		for (i = 0; i + j < num_flows; i++) {			if (dh == NULL || flows[i + j]->af != last_af) {				if (dh != NULL) {					if (offset % 4 != 0) {						/* Pad to multiple of 4 */						dh->c.length += 4 - (offset % 4);						offset += 4 - (offset % 4);					}					/* Finalise last header */					dh->c.length = htons(dh->c.length);				}				if (offset + sizeof(*dh) > sizeof(packet)) {					/* Mark header is finished */					dh = NULL;					break;				}				dh = (struct NF9_DATA_FLOWSET_HEADER *)				    (packet + offset);				dh->c.flowset_id =				    (flows[i + j]->af == AF_INET) ?				    v4_template.h.template_id : 				    v6_template.h.template_id;				last_af = flows[i + j]->af;				last_valid = offset;				dh->c.length = sizeof(*dh); /* Filled as we go */				offset += sizeof(*dh);			}			r = nf_flow_to_flowset(flows[i + j], packet + offset,			    sizeof(packet) - offset, system_boot_time, &inc);			if (r <= 0) {				/* yank off data header, if we had to go back */				if (last_valid)					offset = last_valid;				break;			}			offset += inc;			dh->c.length += inc;			nf9->flows += r;			last_valid = 0; /* Don't clobber this header now */			if (verbose_flag) {				logit(LOG_DEBUG, "Flow %d/%d: "				    "r %d offset %d type %04x len %d(0x%04x) "				    "flows %d", r, i, j, offset, 				    dh->c.flowset_id, dh->c.length, 				    dh->c.length, nf9->flows);			}		}		/* Don't finish header if it has already been done */		if (dh != NULL) {			if (offset % 4 != 0) {				/* Pad to multiple of 4 */				dh->c.length += 4 - (offset % 4);				offset += 4 - (offset % 4);			}			/* Finalise last header */			dh->c.length = htons(dh->c.length);		}		nf9->flows = htons(nf9->flows);		if (verbose_flag)			logit(LOG_DEBUG, "Sending flow packet len = %d", offset);		errsz = sizeof(err);		/* Clear ICMP errors */		getsockopt(nfsock, SOL_SOCKET, SO_ERROR, &err, &errsz); 		if (send(nfsock, packet, (size_t)offset, 0) == -1)			return (-1);		num_packets++;		nf9_pkts_until_template--;		j += i;	}	*flows_exported += j;	return (num_packets);}voidnetflow9_resend_template(void){	if (nf9_pkts_until_template > 0)		nf9_pkts_until_template = 0;}

⌨️ 快捷键说明

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