Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы / 3 / 5.tar / 5 / 5 / net_sniff / sniff

.cpp
Скачиваний:
19
Добавлен:
17.04.2013
Размер:
9.75 Кб
Скачать
#include <unistd.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/time.h>

#include <sys/types.h>
#include <sys/socket.h>

#include <signal.h>

/* libpcap */
#include <pcap.h>

typedef struct sockaddr SA;

#include "sniff.h"

char *sniff_dev;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program pfilter; 

char pfilter_app[] = "port 23";
bpf_u_int32 mask, net;

const struct ethhdr *eth_hdr; /* The ethernet header */
const struct iphdr *ip_hdr; /* The IP header */
const struct tcphdr *tcp_hdr; /* The TCP header */
const struct udphdr *udp_hdr; /* The UDP header */
const struct icmphdr *icmp_hdr; /* The ICMP header */

/* For readability, we'll make variables for the sizes of each of the structures */

#define DEBUG

#ifdef DEBUG
	static const int mdebug=1;
#else
	static const int mdebug=0;
#endif /* DEBUG */

#define dprintf if (mdebug) printf





void NSniff::packet_callback(u_char *args, const struct pcap_pkthdr *header,
	const u_char *packet)
{
	size_t pp_len = 0;
	
	if (qlen >= qsize){
		qsize *= 2;
		queue = (struct npacket **)realloc(queue, sizeof(struct npacket *)*qsize);
		size_t i;
		for (i = qlen; i < qsize; i++){
			queue[i] = (struct npacket *)malloc(sizeof(struct npacket));
			memset(queue[i], 0, sizeof(struct npacket));
		}
		return;
	}
	struct npacket *np = queue[qlen];
	qlen++;
	
	if (header->len > np->data_size){
		np->data_size = header->len;
		np->data = (char *)realloc(np->data, np->data_size);
	}
	
	eth_hdr = (const struct ethhdr *)packet;
	np->eth_proto = ntohs(eth_hdr->h_proto);

		memcpy(np->eth_dest, eth_hdr->h_dest, ETH_ALEN);
		memcpy(np->eth_source, eth_hdr->h_source, ETH_ALEN);
	
	pp_len += sizeof(const struct ethhdr);
	
	if (np->eth_proto == ETH_P_IP){
		ip_hdr = (const struct iphdr *)(packet + pp_len);		
		pp_len += sizeof(struct iphdr);
		
		np->ip_version = ip_hdr->version;
		np->ip_tos = ip_hdr->tos;
		np->ip_id = ntohs(ip_hdr->id);
		np->ip_df = ntohs(ip_hdr->frag_off) & 0x1; /* do not fragment */
		np->ip_mf = ntohs(ip_hdr->frag_off) & 0x2; /* more fragment */
		np->ip_ttl = ip_hdr->ttl;
		np->ip_protocol = ip_hdr->protocol;
		np->ip_saddr = ip_hdr->saddr;
		np->ip_daddr = ip_hdr->daddr;

		if (np->ip_protocol == IPPROTO_ICMP){			
			icmp_hdr = (struct icmphdr *)(packet + pp_len);
			pp_len += sizeof(struct icmphdr);
			
			np->icmp_type = icmp_hdr->type;
			np->icmp_code = icmp_hdr->code;
			np->icmp_ident = ntohs(icmp_hdr->un.echo.id);
			np->icmp_sequence = ntohs(icmp_hdr->un.echo.sequence);
		}
		else if (np->ip_protocol == IPPROTO_TCP){
			tcp_hdr = (struct tcphdr *)(packet + pp_len);
			pp_len += sizeof(struct tcphdr);
					
			np->tcp_source = ntohs(tcp_hdr->source);
			np->tcp_dest = ntohs(tcp_hdr->dest);
			np->tcp_seq = ntohl(tcp_hdr->seq);
			np->tcp_ack_seq = ntohl(tcp_hdr->ack_seq);
			
			np->tcp_fin = tcp_hdr->fin;
			np->tcp_syn = tcp_hdr->syn;
			np->tcp_rst = tcp_hdr->rst;
			np->tcp_psh = tcp_hdr->psh;
			np->tcp_ack = tcp_hdr->ack;
			np->tcp_urg = tcp_hdr->urg;
			
			np->tcp_urg_ptr = ntohs(tcp_hdr->urg_ptr);
		}
		else if (np->ip_protocol == IPPROTO_UDP){
			udp_hdr = (struct udphdr *)(packet + pp_len);
			pp_len += sizeof(struct udphdr);
					
			np->udp_source = ntohs(udp_hdr->source);
			np->udp_dest = ntohs(udp_hdr->dest);
		}
		else{
		}
			
	}
	else if (np->eth_proto == ETH_P_ARP){
		qlen--;
	}
	else {
	}
	
	np->data_len = header->len-pp_len;
	memmove(np->data, (char *)(packet + pp_len), np->data_len);
}

void NSniff::run()
{
	err_code = 0;
	err_str = "";
		
	/* open pcap session */
	pcap_t *handle  = pcap_open_live(dev_name.ascii(), BUFSIZ, 1, 1, errbuf);
	if (!handle){
		err_code = 1;
		err_str = "Pcap open failed!\n" + QString(errbuf);
		return;
	}
	pcap_setnonblock(handle, 1, errbuf);
	
	/* setting filter */
	/*
	pcap_lookupnet(sniff_dev, &net, &mask, errbuf);
	pcap_compile(phandle, &pfilter, pfilter_app, 0, net);
	pcap_setfilter([phandle, &pfilter);
	*/

	/* allocate memory for packet queue */
	
	int datalink = pcap_datalink(handle);
	if (datalink == DLT_EN10MB){
		printf("Ok, datalink type - ethernet\n");
	}
	else{
		fprintf(stderr,"Currently unsupported datalink type <%d>\n",
				datalink); return;
	}

	stopped = 0;
	while (1){
		if ( c_stop && (qlen >= c_stop)){
			stopped++;
		}
		
		if ( t_stop && (time(NULL) >= t_stop)){
			stopped++;
		}
		
		if (stopped){
			break;
		}
		
		 struct pcap_pkthdr header;
		 const u_char *packet = pcap_next(handle, &header);

		 if (packet)
		 	packet_callback(NULL, &header, packet);
		 
		 //pcap_loop(phandle, queue_size, &packet_callback , NULL);
	}

	pcap_close(handle);
	
	stopped++;
	
	return;
}


NSniff::~NSniff( )
{
	if (queue){
		size_t i;
		for (i = 0; i < qsize; i++){
			if (queue[i]->data)
				free(queue[i]->data);
			free(queue[i]);
		}
		free(queue);
	}	
}

NSniff::NSniff( QWidget * pparent )
{
	queue = NULL;
	qsize = 0;
	qlen = 0;
	dev_name = "";
	
	stopped = true;
	
	t_stop = 0;
	c_stop = 0;
	
	parent = pparent;
	
	err_code = 0;
	err_str = "";
}
	
int NSniff::setParams(QString pdev_name, time_t ptime, size_t pcount)
{
	if (running()){
		return -1;
	}
	
	if (pdev_name == ""){
		return -1;
	}

	dev_name = pdev_name;
	t_stop = (ptime == 0) ? (0) : (time(NULL)+ptime*60);
	c_stop = pcount;

	if (pcount == 0)
		pcount = 10000;
		
	if (qsize < pcount){
		queue = (struct npacket **)realloc(queue, 
					sizeof(struct npacket *)*pcount);
		size_t i;
		for (i = qsize; i < pcount; i++){
			queue[i] = (struct npacket *)malloc(sizeof(struct npacket));
			memset(queue[i], 0, sizeof(struct npacket));
		}
		qsize = pcount;
	}
	qlen = 0;

	
	stopped = true;
	
	dprintf("dev=%s; size=%d; t_stop=%d; c_stop=%d\n",dev_name.ascii(),
			qsize, (int)t_stop, c_stop);
	return 0;
}

void NSniff::stop()
{
	stopped++;
}

int NSniff::getResults(struct npacket ***r_queue, size_t *r_len)
{
	if (running()){
		return -1;
	}
	
	*r_queue = queue;
	*r_len = qlen;
	return 0;
}

QString NSniff::print_packet(size_t index)
{
	if (index >= qlen)
		return QString("No such packet");
	
	struct npacket *p = queue[index];
	QString str = "<br><br><br><hr><br>";
	str += "<font face=mono><table>\n";
	str += QString("<tr><td width=140 align=center>Property<td align=center>Data");
	
	/* get HW addr */
		int g;
		char s_addr[128];
		QString s_hw_addr = "";
		QString d_hw_addr = "";
		
    	sprintf(s_addr, "%.2hhx",p->eth_source[1]);
    	s_hw_addr += s_addr;
    	for (g=1; g < ETH_ALEN; g++){
    		sprintf(s_addr, ":%.2hhx",p->eth_source[g]);
    		s_hw_addr += s_addr;
    	}
    	sprintf(s_addr, "%.2hhx",p->eth_dest[1]);
    	d_hw_addr += s_addr;
    	for (g=1; g < ETH_ALEN; g++){
    		sprintf(s_addr, ":%.2hhx", p->eth_dest[g]);
    		d_hw_addr += s_addr;
    	}
    	
    str += QString("<tr><td>HW from address <td>%1\n").arg(s_hw_addr);
    str += QString("<tr><td>HW to address <td>%1\n").arg(d_hw_addr);
	
   	if (p->eth_proto == ETH_P_IP){
   		/* ip packet*/
   		    	
    	if (p->ip_protocol == IPPROTO_ICMP){
    		str += QString("<tr><td>Type <td>ICMP\n");
    	}
    	else if(p->ip_protocol == IPPROTO_TCP){
    		str += QString("<tr><td>Type <td>TCP\n");
    	}
    	else if(p->ip_protocol == IPPROTO_UDP){
    		str += QString("<tr><td>Type <td>UDP\n");
    	}
    	else{
    		str += QString("<tr><td>Type <td>IP #%1\n").arg(p->ip_protocol);
    	}
    	
    	/* from ip */
    	inet_ntop(AF_INET, &p->ip_saddr, s_addr, sizeof(s_addr));
    	str += QString("<tr><td>IP from address <td>%1\n").arg(s_addr);
		/* to ip */
    	inet_ntop(AF_INET, &p->ip_daddr, s_addr, sizeof(s_addr));
    	str += QString("<tr><td>IP to address <td>%1\n").arg(s_addr);
 
     	if (p->ip_protocol == IPPROTO_ICMP){
    		str += QString("<tr><td>ICMP type <td>%1\n").arg(p->icmp_type);
    		str += QString("<tr><td>ICMP code <td>%1\n").arg(p->icmp_code);
    		str += QString("<tr><td>ICMP ident <td>%1\n").arg(p->icmp_ident);
    		str += QString("<tr><td>ICMP sequence <td>%1\n").arg(p->icmp_sequence);
    	}
    	else if(p->ip_protocol == IPPROTO_TCP){
    		str += QString("<tr><td>Port from <td>%1\n").arg(p->tcp_source);
    		str += QString("<tr><td>Port to <td>%1\n").arg(p->tcp_dest);

    		str += QString("<tr><td>Seq num <td>%1\n").arg(p->tcp_seq);
    		str += QString("<tr><td>Ack num <td>%1\n").arg(p->tcp_ack_seq);
    		
    		str += QString("<tr><td>Flags <td>\n");
    		
    		if (p->tcp_ack){
    			str += QString("ACK\n");
    		}
    		if (p->tcp_fin){
    			str += QString("FIN\n");
    		}
    		if (p->tcp_syn){
    			str += QString("SYN\n");
    		}
    		if (p->tcp_rst){
    			str += QString("RST\n");
    		}
    		if (p->tcp_psh){
    			str += QString("PSH\n");
    		}
    		if (p->tcp_urg){
    			str += QString("URG\n");
    		}
/*
    u_int16_t tcp_urg_ptr;*/
    			
    	}
    	else if(p->ip_protocol == IPPROTO_UDP){
    		str += QString("<tr><td>Port from <td>%1\n").arg(p->udp_source);
    		str += QString("<tr><td>Port to <td>%1\n").arg(p->udp_dest);
    	}
    	else{
    		str += QString("<tr><td>Type <td>IP #%1\n").arg(p->ip_protocol);
    	}
   
    }
    else if (p->eth_proto == ETH_P_ARP){
    	/* arp packet */
    	str += QString("<tr><td>Type <td>ARP\n");
    }
    else{
    	str += QString("<tr><td>Type <td>ether #%1\n").arg(p->eth_proto);
    }
    
    
    str += QString("<tr><td>Data (%1 bytes) <td>\n").arg(p->data_len);
    size_t i;
    for (i=0; i < p->data_len; i++){
    	if (i % 20 == 0) str += QString("<br>");
    	
    	sprintf(s_addr, "&#%hhd;",p->data[i]);
    	str += s_addr;
     }

    str += QString("<tr><td>HEX data <td>\n");
    for (i=0; i < p->data_len; i++){
    	if (i % 10 == 0) str += QString("<br>");
    	
    	sprintf(s_addr, "%.2hhX ",p->data[i]);
    	str += s_addr;
     }

    str += QString("</table></font>");
	
	return str;
}

	
Соседние файлы в папке net_sniff