網卡數據捕獲

這部分代碼用於從鏈路層抓取數據並簡單顯示,目前爲第一個版本,後期還會進一步完善。

編譯  gcc -o file file.c

執行:./file -a eth0  |-b

-a eth0:爲將網卡etho設置爲混雜模式

-b 爲輪詢抓取數據。

#include
#include
#include
#include
#include
#include 
#include
#include
#include
#include
#include
#include
#include
#include

//#include
//以太網幀信息
#define ETH_ALEN 6
#define ETH_HLEN 14
#define ETH_ZLEN 60
#define ETH_DATA_LEN 1500
#define ETH_FRAME_LEN 1514
/*
struct ethhdr
{
	unsigned char h_dest[ETH_ALEN];
	unsigned char h_source[ETH_ALEN];
	__be16 h_proto;
};
*/


int set_eth(int,char *);
int get_data_info(int);
int get_eth_info(char *);
int get_ip_info(char*);
int get_arp_info(char*);
int get_tcp_info(char*,int len);
int get_icmp_info(char*,int len);
int get_udp_info(char *,int len);
//static int arp=0;
int main(int argc,char **argv)
{
	
	int ch;//參數列表
	int fd=0;
	int ret;
	fd=socket(PF_INET,SOCK_PACKET,htons(0x0003));
	if(fd<0)
	{
		perror("socket");
		//printf("%d\tsocket error!\n",fd);
		return -1;
	}
	while((ch=getopt(argc,argv,"a:b"))!=-1)
	{
		switch(ch)
		{
			case 'a':
				printf("設置網卡爲混雜模式\n");
				printf("需要設置的網卡名爲:%s\n",optarg);
				ret=set_eth(fd,optarg);
				if(ret<0)
				{
					printf("設置網卡%s 失敗\n",optarg);
					close(fd);
					return -1;
				}
				break;
			case 'b':
				printf("獲取數據包信息\n");
				while(1)
				{
					//sleep(1);
					ret=get_data_info(fd);
					if(ret<0)
						return -1;
				}
				break;
			default:
				printf("參數有誤!\n");
				break;
		}
	}
	return 0;
}
int get_udp_info(char *iph,int len)
{
	struct udphdr *pudph;
	pudph=(struct udphdr*)(iph+len);
	printf("\t\tUDP數據報\n");
	printf("\t\t\t源端口號:%d\n",pudph->source);
	printf("\t\t\t目的端口號:%d\n",pudph->dest);
	printf("\t\t\t長度:%d\n",pudph->len);
	
}
int get_icmp_info(char *iph,int len)
{
	struct icmp *picmp;
	picmp=(struct icmp*)(iph+len);
	printf("\t\tICMP數據報\n");
}
int get_tcp_info(char *iph,int len)
{
	struct tcphdr *ptcph;
	ptcph=(struct tcphdr*)(iph+len);
	printf("\t\tTCP數據包\n");
	printf("\t\t\t源端口:%d\n",ptcph->source);
	printf("\t\t\t目的口:%d\n",ptcph->dest);
	
}
int get_ip_info(char *ef)
{
	struct iphdr *iph;
	iph=(struct iphdr*)(ef+ETH_HLEN);
	u_int32_t ipaddr;
	ipaddr=iph->saddr;
	int ret;
	int len;
	//(struct in_addr)iph->saddr;	
	struct in_addr *s_addr=(struct in_addr*)&ipaddr;
	printf("\t\t源IP地址:%s\n",inet_ntoa(*s_addr));	
	//ipaddr=iph->daddr;	
	ipaddr=iph->daddr;
	struct in_addr *d_addr=(struct in_addr*)&ipaddr;
	printf("\t\t目的IP地址:%s\n",inet_ntoa(*d_addr));	
	printf("\t\t版本號:IPv%d\n",iph->version);
	printf("\t\t頭部長度:%d字節\n",iph->ihl*5);
	printf("\t\t服務類型:%d\n",iph->tos);
	printf("\t\t總長度:%d\n",iph->tot_len);
	printf("\t\t標識:%d\n",iph->id);
	printf("\t\t片偏移:%d\n",iph->frag_off);
	printf("\t\t生存時間:%d\n",iph->ttl);
	printf("\t\t協議號:%d\n",iph->protocol);
	if(iph->protocol==6)
	{
		len=iph->ihl*5;
		ret=get_tcp_info((char*)iph,len);
	}
	else if(iph->protocol==1)
	{
		len=iph->ihl*5;
		ret=get_icmp_info((char*)iph,len);
	}
	else if(iph->protocol==17)
	{
		len=iph->ihl*5;
		ret=get_udp_info((char*)iph,len);
	}
	return 0;
}
int get_arp_info(char *ef)
{
	struct arphdr *parph;
	parph=(struct arphdr*)(ef+ETH_HLEN);
	if(parph->ar_hrd==1)
		printf("\t\t硬件類型:以太網\n");
	else
		printf("\t\t硬件類型:未知\n");
	if(parph->ar_pro==0x0800)
		printf("\t\t上層協議:IP\n");
	else
		printf("\t\t上層協議:未知\n");
	printf("\t\t硬件地址長度:%d\n",parph->ar_hln);
	printf("\t\t協議地址長度:%d\n",parph->ar_pln);
	if(parph->ar_op==1)
		printf("\t\tarp請求報文\n");
	else
		printf("\t\tarp應答報文\n");
	
	return 0;
}
int get_eth_info(char *ef)
{
	int ret;
	int len;
	struct ethhdr *pethhdr;
	struct arphdr *parp;
	int i;
	pethhdr=(struct ethhdr*)ef;
	printf("The dest MAC:");
	for(i=0;ih_dest[i]);
	printf("%x\n",pethhdr->h_dest[ETH_ALEN-1]);
	printf("The source MAC:");
	for(i=0;ih_source[i]);
	printf("%x\n",pethhdr->h_source[ETH_ALEN-1]);
	printf("協議類型:%#x",htons(pethhdr->h_proto));
	if(ntohs(pethhdr->h_proto)==0x800)
	{
		printf("IP數據包\n");
		ret=get_ip_info(ef);
	}
	else if(ntohs(pethhdr->h_proto)==0x0806)
	{
		printf("\tARP數據包\n");
		ret=get_arp_info(ef);	
	}
	else if(ntohs(pethhdr->h_proto)==0x8035)
		printf("\t這是一個RARP數據包\n");
	else
		printf("\t不知道數據包類型\n");
	return 0;
}
int get_data_info(int fd)
{
	char ef[ETH_FRAME_LEN];
	int ret;
	//struct ethhdr *pethhdr;
	int n;
	//pethhdr=(struct ethhdr*)ef;
	n=read(fd,ef,ETH_FRAME_LEN);
	if(n<0)
	{
		//printf("read error!\n");
		perror("read");
		return -1;
	}
	ret=get_eth_info(ef);
	if(ret<0)
	{
		printf("get_eth_info error!\n");
		return -1;
	}
	
}
int set_eth(int fd,char *ethname)
{
	struct ifreq ifr;
	strcpy(ifr.ifr_name,ethname);
	int ret=ioctl(fd,SIOCGIFFLAGS,&ifr);
	if(ret<0)
	{
		//close(fd);
		perror("SIOCGIFFLAGS");
		return -1;
	}
	ifr.ifr_flags|=IFF_PROMISC;
	ret=ioctl(fd,SIOCSIFFLAGS,&ifr);
	if(ret<0)
	{
		printf("SIOCSIFFLAGS");
		return -1;
	}
	printf("網卡設置混雜模式成功!\n");
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章