這部分代碼用於從鏈路層抓取數據並簡單顯示,目前爲第一個版本,後期還會進一步完善。
編譯 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;
}