网卡数据捕获

这部分代码用于从链路层抓取数据并简单显示,目前为第一个版本,后期还会进一步完善。

编译  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;
}


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