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

📄 tcp.c

📁 * A ncurses user interface. * Network statistics to view the amount of packets and data in many
💻 C
字号:
/*  This file is part of sniffer, a packet capture utility and  network moniter  The author can be contacted at <mistral@stev.org>  the lastest version is avilable from   http://stev.org  This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 2 of the License, or  (at your option) any later version.  This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.  You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <stdlib.h>#include <string.h>#include <errno.h>#include <pthread.h>#include <netinet/in.h>#include "config.h"#include "locks.h"#include "list.h"#include "log.h"#include "lookup.h"#include "stat.h"#include "ip.h"#include "in_ntoa.h"#include "tcp.h"#include "tcp_dump.h"#include "ftp.h"#include "http.h"#include "pop3.h"pthread_mutex_t tcp_mutex_slist = PTHREAD_MUTEX_INITIALIZER; /* lock for sorted list */pthread_mutex_t tcp_mutex_vlist = PTHREAD_MUTEX_INITIALIZER; /* lock for view list */pthread_mutex_t tcp_gui_mutex = PTHREAD_MUTEX_INITIALIZER;struct list_t *tcp_slist; /* sorted list */struct list_t *tcp_vlist; /* viewing list */struct gen_stat tcp_stat;WINDOW *tcp_gui_window;int tcp_timeout = TCP_TIMEOUT; /* 600 = 10 minutes this might need to be bigger */int tcp_cycle = TCP_CYCLE; /* how long it takes until we recycle a record */struct tcp_proto_t tcp_proto[] = {	{21, ftp_init},	{80, http_init},	{110, pop3_init},	{0, NULL}};/****************************************************************************** TCP Packets *********************************************************************************************************/int tcp_handle(struct sniff_pkt *pkt, struct pkt_ip *ip, struct pkt_tcp *tcp) {	void *pointer;	struct tcp_data fake_data; /* this is used to search */	struct tcp_data *data;	int index;	unsigned short length;	unsigned short port;#ifdef TCP_CHECKSUM	char *ip_source, *ip_dest;	unsigned short oldcheck;#endif	pointer = (void *) tcp + (tcp->doff * 4);	length = (ntohs(ip->tot_len) - (ip->ihl * 4) - (tcp->doff * 4));	tcp_stat.packets++;	tcp_stat.bytes += length;#ifdef TCP_CHECKSUM	oldcheck = tcp->check;	tcp->check = 0;	tcp->check = tcp_check(tcp, length + (tcp->doff * 4), ip->saddr, ip->daddr);	if (oldcheck != tcp->check) {		/* if these fail then they will contain null */		ip_source = lookup(ip->saddr);		ip_dest = lookup(ip->daddr);		log_error("FAILED TCP CHECKSUM: %s -> %s Packet: %u Sniffer: %u\n", ip_source, ip_dest, oldcheck, ip->check);		tcp_stat.dropped++;		return -1;	}#endif	tcp_gui_print(ip, tcp, length);	/* search using in 1 direction */	fake_data.dest.ip   = ip->daddr;	fake_data.dest.port = tcp->dest;	fake_data.src.ip    = ip->saddr;	fake_data.src.port  = tcp->source;	SLOCK(&tcp_mutex_slist);	index = list_search(tcp_slist, &fake_data);	if (index >= 0) {		data = list_get(tcp_slist, index);		data->src.stat.packets++;		data->src.stat.bytes += length;		memcpy(&data->src.head, tcp, sizeof(struct pkt_tcp));		tcp_set_state(data, &data->src);		if (data->func_src)			data->func_src(pkt, data, pointer, length);		SUNLOCK(&tcp_mutex_slist);		return -2;	}	/* now search in the other directorion */	fake_data.src.ip	= ip->daddr;	fake_data.src.port	= tcp->dest;	fake_data.dest.ip	= ip->saddr;	fake_data.dest.port	= tcp->source;	index = list_search(tcp_slist, &fake_data);	if (index >= 0) {		data = list_get(tcp_slist, index);		data->dest.stat.packets++;		data->dest.stat.bytes += length;		memcpy(&data->dest.head, tcp, sizeof(struct pkt_tcp));		tcp_set_state(data, &data->dest);		if (data->func_dst)			data->func_dst(pkt, data, pointer, length);		SUNLOCK(&tcp_mutex_slist);		return -3;	}	/* if we get this far we need to create a new entry */		data = malloc(sizeof(struct tcp_data));	if (!data) {		log_s("malloc failed");		SUNLOCK(&tcp_mutex_slist);		return -4;	}	data->src.ip		= ip->saddr;	data->src.ip_str	= in_ntoa(ip->saddr);	data->src.ip_name	= lookup(ip->saddr, 1);	data->src.port		= tcp->source;	memcpy(&data->src.head, tcp, sizeof(struct pkt_tcp));	data->src.state		= STCP_N;	data->src.data_len	= 0;	init_stat(&data->src.stat, NULL);	data->dest.ip		= ip->daddr;	data->dest.ip_str	= in_ntoa(ip->daddr);	data->dest.ip_name	= lookup(ip->daddr, 1);	data->dest.port		= tcp->dest;	bzero(&data->dest.head, sizeof(struct pkt_tcp));	data->dest.state	= STCP_N;	data->dest.data_len	= 0;	init_stat(&data->dest.stat, NULL);	data->delme = 0;	data->cycle = 0;	data->timeout = time(NULL);	data->dat = NULL;	data->func_src = NULL;	data->func_dst = NULL;	data->func_cleanup = NULL;	data->func_lookup = NULL;	data->src.stat.packets++;	data->src.stat.bytes += length;	memcpy(&data->src.head, tcp, sizeof(struct pkt_tcp));	tcp_set_state(data, &data->src);	index = 0;	port = ntohs(tcp->dest);	while(tcp_proto[index].init) {		if (tcp_proto[index].port == port && tcp_proto[index].init)			tcp_proto[index].init(data);		index++;	}	if (data->func_src)		data->func_src(pkt, data, pointer, length);	list_add_sort(tcp_slist, data);	SUNLOCK(&tcp_mutex_slist);	SLOCK(&tcp_mutex_vlist);	list_add(tcp_vlist, data);		SUNLOCK(&tcp_mutex_vlist);	return 0;} /* end of tcp_handle *//* this will se tthe state and the flags vars in the struct tcp_info */int tcp_set_state(struct tcp_data *dat, struct tcp_info *info) {	dat->delme = 0;	dat->timeout = time(NULL);	dat->cycle = 0;	/* do we have a SYN ? */	if (info->head.syn) {		if (info->head.ack) {			info->state = STCP_SYN_RECV;		} else {			info->state = STCP_SYN_SENT;		}		/* FIXME: Log funny packets ? */		return 0;	}	/* do we have a FIN ? */	if (info->head.fin) {		if (info->head.ack) {			info->state = STCP_FIN_WAIT1;			return 0;		} else {			info->state = STCP_FIN_WAIT2;			return 0;		}	}	if (info->head.rst) {		info->state = STCP_RESET;		dat->delme = 1;		return 0;	}	if (info->head.ack) {		if (info->state == STCP_SYN_SENT && info->head.rst) {			info->state = STCP_RESET;			dat->delme = 1;			return 0;		}		if (info->state == STCP_FIN_WAIT1 || info->state == STCP_FIN_WAIT2) {			info->state = STCP_CLOSED;			dat->delme = 1;			return 0;		}		if (!info->head.fin)			info->state = STCP_ESTABLISHED;		return 0;	}	return 0;}/* lets tidy some stuff up */int tcp_tidy() {	time_t ctime;	int length;	int i, max, tmp;	struct tcp_data *data;	time(&ctime);	SLOCK(&tcp_mutex_vlist);	length = list_length(tcp_vlist);	for(i=0;i<length;i++) {		data = list_get(tcp_vlist, i);		if (data->delme)			data->cycle++;		if (data->timeout + tcp_timeout < ctime)			data->delme = 1;		if (data->cycle > tcp_cycle) {			SLOCK(&tcp_mutex_slist);			tmp = list_search(tcp_slist, data);			if (tmp < 0) {				log_s("oh dear i should have found a record to delete");				SUNLOCK(&tcp_mutex_slist);			} else {				list_del(tcp_slist, tmp);				SUNLOCK(&tcp_mutex_slist);			}			list_del(tcp_vlist, i);			if (data->func_cleanup)				data->func_cleanup(data);			if (data->src.ip_str)				free(data->src.ip_str);			if (data->dest.ip_str)				free(data->dest.ip_str);			free(data);		}		if (max >= 10) {			max = 0;			SUNLOCK(&tcp_mutex_vlist);			SLOCK(&tcp_mutex_vlist);		}		length = list_length(tcp_vlist);		max++;	}	SUNLOCK(&tcp_mutex_vlist);	return 0;}int tcp_cmp(struct tcp_data *c1, struct tcp_data *c2) {	if (c1->src.ip > c2->src.ip) return -1;	if (c1->src.ip < c2->src.ip) return 1;	if (c1->dest.ip > c2->dest.ip) return -1;	if (c1->dest.ip < c2->dest.ip) return 1;			if (c1->src.port > c2->src.port) return -1;	if (c1->src.port < c2->src.port) return 1;	if (c1->dest.port > c2->dest.port) return -1;	if (c1->dest.port < c2->dest.port) return 1;	return 0;}inline unsigned short tcp_check(struct pkt_tcp *th, unsigned short len, unsigned long saddr, unsigned long daddr) {	unsigned long sum = 0;	unsigned short *buff;		buff = (unsigned short *) &saddr;	sum += *buff++;	sum += *buff;	buff = (unsigned short *) &daddr;	sum += *buff++;	sum += *buff;	sum += IP_TCP * 256;	sum += htons(len) & 0xffff;	buff = (unsigned short *) th;	while(len > 1) {		sum += *buff++;		len -= 2;	}	if (len == 1)		sum += (*buff & 0xff);		sum = (sum >> 16) + (sum & 0xffff);	sum += (sum >> 16);	return ( (~sum) & 0xffff);}void tcp_gui_conn(struct gui_t *p, int y, int x) {	int i, length, offset = 0, cury;	WINDOW *draw;	struct tcp_data *data;	char *foot_back, buff[80];	draw = newwin(p->twin->_maxy - 1, p->twin->_maxx - 1, 1, 1);	if (!draw) {		log_s("newwin() failed");		return;	}	wbkgd(draw, COLOR_PAIR(COL_BACK));	foot_back = p->footer;	while(1) {		werase(draw);		cury = 0;		i = offset;		if (offset > 0)			mvwprintw(draw, 1, draw->_maxx - 12, "--more--");		/* we have the first 2 lines to play with the stats */		stat_process(&tcp_stat);		snprintf(&buff[0], 80, "TCP Packets: %llu Dropped: %llu Data: %llu %s",				tcp_stat.packets, tcp_stat.dropped, tcp_stat.readable, tcp_stat.messure);		gui_footer(p, &buff[0]);		SLOCK(&tcp_mutex_vlist);		length = list_len(tcp_vlist);		while(cury < draw->_maxy && i < length) {			data = list_get(tcp_vlist, i);			stat_process(&data->src.stat);			stat_process(&data->dest.stat);			if (data->src.ip_name) {				mvwprintw(draw, cury++, 0, "/%s %24.24s [%u]\t%4lli:%llu %s\t%.0f:%.2f/Sec",					tcp_gui_flags(&data->src), data->src.ip_name, ntohs(data->src.port),					data->src.stat.packets, data->src.stat.readable,					data->src.stat.messure, data->src.stat.rate_packets,					data->src.stat.rate_kb);			} else {				mvwprintw(draw, cury++, 0, "/%s %24.24s [%u]\t%4lli:%llu %s\t%.0f:%.2f/Sec",					tcp_gui_flags(&data->src), data->src.ip_str, ntohs(data->src.port),					data->src.stat.packets, data->src.stat.readable,					data->src.stat.messure, data->src.stat.rate_packets,					data->src.stat.rate_kb);				data->src.ip_name = lookup(data->src.ip, 1);			}			if (data->dest.ip_name) {				mvwprintw(draw, cury++, 0, "\\%s %24.24s [%u]\t%4lli:%llu %s\t%.0f:%.2f/Sec",					tcp_gui_flags(&data->dest), data->dest.ip_name, ntohs(data->dest.port),					data->dest.stat.packets, data->dest.stat.readable,					data->dest.stat.messure, data->dest.stat.rate_packets,					data->dest.stat.rate_kb);			} else {				mvwprintw(draw, cury++, 0, "\\%s %24.24s [%u]\t%4lli:%llu %s\t%.0f:%.2f/Sec",					tcp_gui_flags(&data->dest), data->dest.ip_str, ntohs(data->dest.port),					data->dest.stat.packets, data->dest.stat.readable,					data->dest.stat.messure, data->dest.stat.rate_packets,					data->dest.stat.rate_kb);					data->dest.ip_name = lookup(data->dest.ip, 1);			}			i++;		} /* end of loop round the list_vlist */		SUNLOCK(&tcp_mutex_vlist);				if (cury == 0) /* do we have any entries ? */			mvwprintw(draw, cury++, 0, " -- No Entries --");		else			mvwprintw(draw, cury++, 0, " -- END --");		if (cury > draw->_maxy - 1)			mvwprintw(draw, draw->_maxy , draw->_maxx - 8, "--more--");		wrefresh(draw);		switch(gui_scroll(250, 0, length, &offset)) {			case -1: /* error / timeout */				break;			case 0: /* it did something */				break;			default:				goto get_out;				break;		} /* end of switch gui_utils_scroll */	} /* end while(1) */get_out: /* cleanup / quit */	gui_footer(p, foot_back);	werase(draw);	wrefresh(draw);	delwin(draw);	return;}void tcp_gui(struct gui_t *p, int y, int x) {	WINDOW *draw;	char *foot_back, buff[80];	SLOCK(&tcp_gui_mutex);	draw = newwin(p->twin->_maxy - 1, p->twin->_maxx - 1, 1, 1);	if (!draw) {		log_s("subwin failed");		SUNLOCK(&tcp_gui_mutex);		return;	}	wbkgd(draw, COLOR_PAIR(COL_BACK));	scrollok(draw, TRUE);	werase(draw);	wrefresh(draw);	foot_back = p->footer;	tcp_gui_window = draw;	SUNLOCK(&tcp_gui_mutex);	while (1) {		if (gui_wait(250, 0) == 1) {			switch(getch()) {				default:					goto get_out;					break;			}		} else {			stat_process(&tcp_stat);			SLOCK(&tcp_gui_mutex);			wrefresh(draw);			snprintf(&buff[0], 80, "TCP Packets: %llu Data: %llu %s Drop: %llu",							tcp_stat.packets, tcp_stat.readable, tcp_stat.messure, tcp_stat.dropped);			gui_footer(p, &buff[0]);			SUNLOCK(&tcp_gui_mutex);		}	}get_out:	gui_footer(p, foot_back);	SLOCK(&tcp_gui_mutex);	tcp_gui_window = NULL;	SUNLOCK(&tcp_gui_mutex);		werase(draw);	wrefresh(draw);	delwin(draw);	return;}inline int tcp_gui_print (struct pkt_ip *ip, struct pkt_tcp *tcp, unsigned short length) {	if (!tcp_gui_window)		return 0;	SLOCK(&tcp_gui_mutex);	gui_print(tcp_gui_window, "%s %s(%u) -> %s(%u) L:%u\n\tSEQ:%lu:%lu W:%u UP:%u\n",		tcp_flags(tcp),		lookup(ip->saddr, 0), ntohs(tcp->source),		lookup(ip->daddr, 0), ntohs(tcp->dest), length,		ntohl(tcp->seq), ntohl(tcp->ack_seq), ntohs(tcp->window), ntohs(tcp->urg_ptr));	SUNLOCK(&tcp_gui_mutex);	return 0;}inline char *tcp_flags(struct pkt_tcp *tcp) {	static char flags[9];		strcpy(&flags[0], "------\0"); /* we end a null */	if (tcp->syn)		flags[0] = 'S';	if (tcp->fin)		flags[1] = 'F';	if (tcp->rst)		flags[2] = 'R';	if (tcp->urg)		flags[3] = 'U';	if (tcp->ack)		flags[4] = 'A';	if (tcp->psh)		flags[5] = 'P';	return &flags[0];}inline char *tcp_gui_flags(struct tcp_info *cur) {	static char flags[9];	bzero(&flags[0], 8);	switch(cur->state) {		case STCP_SYN_SENT:			strcpy(&flags[0], "SSENT");			break;		case STCP_SYN_RECV:			strcpy(&flags[0], "SRECV");			break;		case STCP_FIN_WAIT1:			strcpy(&flags[0], "WAIT1");			break;		case STCP_FIN_WAIT2:			strcpy(&flags[0], "WAIT2");			break;		case STCP_CLOSED:			strcpy(&flags[0], "CLOSE");			break;		case STCP_RESET:			strcpy(&flags[0], "RESET");			break;		default:			strcpy(&flags[0], "-----\0"); /* we end a null */			if (cur->head.syn)				flags[0] = 'S';			if (cur->head.fin)				flags[1] = 'F';			if (cur->head.rst)				flags[1] = 'R';			if (cur->head.urg)				flags[2] = 'U';			if (cur->head.ack)				flags[3] = 'A';			if (cur->head.psh)				flags[4] = 'P';			break;	} /* end of flags switch */	return flags;}/* lets setup a few things to get it working */int tcp_init() {	SLOCK(&tcp_mutex_slist);	tcp_slist = list_init();	list_setcmp(tcp_slist, (void *) tcp_cmp);	SUNLOCK(&tcp_mutex_slist);	SLOCK(&tcp_mutex_vlist);	tcp_vlist = list_init();	SUNLOCK(&tcp_mutex_vlist);	return 0;}

⌨️ 快捷键说明

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