这部分代码用于从链路层抓取数据并简单显示,目前为第一个版本,后期还会进一步完善。
编译 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;
}