1 利用libpcap进行抓 MAC帧,并且对其中的IP数据包进行分析。
问题及解释见注释
#include"pcap.h"
struct ether_header{
u_int8_t ether_dhost[6];
u_int8_t ether_shost[6];
u_int16_t ether_type;
};
typedef u_int32_t in_addr_t;
struct in_addr{
in_addr_t a_addr;
};
struct ip_header{ //IP头数据结构
#ifdef WORDS_BIGENDIAN
u_int8_t ip_version:4;
u_int8_t ip_header_length:4;
#else
u_int8_t ip_header_length:4;
u_int8_t ip_version:4;
#endif
u_int8_t ip_tos;// 啥事 tos服务质量
u_int16_t ip_length;
u_int16_t ip_id;
u_int16_t ip_off;
u_int8_t ip_ttl;
u_int8_t ip_protocol;
u_int16_t ip_checksum;
struct in_addr ip_souce_address;
struct in_addr ip_destination_address;
};
void ip_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr * packet_header,const u_char * packet_content){
struct ip_header *ip_protocol;
u_int header_length;
u_int offset;
u_char tos;
u_int16_t checksum;
ip_protocol=(struct ip_header* )(packet_content+14);
checksum=ntohs(ip_protocol->ip_checksum);
header_length=ip_protocol->ip_header_length*4;
tos=ip_protocol->ip_tos;
offset=ntohs(ip_protocol->ip_off);// 偏移量
printf("---------IP Protocol (Network Layer)\n");
printf("IP Versin:%d\n",ip_protocol->ip_version);
printf("Header length\n",header_length);
printf("TOS:%d\n",tos);
printf("Total length:%d\n",ntohs(ip_protocol->ip_length));
printf("Identification :%d\n",ntohs(ip_protocol->ip_id));
printf("offset:%d\n",(offset&0x1fff)*8);
printf("TTL:%d\n",ip_protocol->ip_ttl);
printf("Protool:%d\n",ip_protocol->ip_protocol);
// judge the type
switch(ip_protocol->ip_protocol){
case 6:printf("The Transport Layer Protocol is TCP\n");break;
case 17:printf("The Transport Transport Layer Protocol is UDP");break;
case 1:printf("The Transport Layer Protocol is ICMP\n");break;
default :break;
}
printf("Header checksum:%d\n",checksum);
// 下面这两个会引起段错误,还没搞清楚为什么
//printf("Source address:%s\n",inet_ntoa(ip_protocol->ip_souce_address)); /
//printf("Destination address :%s\n",inet_ntoa(ip_protocol->ip_destination_address));
}
void ethernet_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr * packet_header,const u_char * packet_content){
u_short ethernet_type;//保存以太网类型。
struct ether_header * ethernet_protocol;//
u_char * mac_string;
static int packet_number=1;
printf("*********************************");
printf("Ethernet protocol (link layer)\n");
ethernet_protocol=(struct ether_header *)packet_content;// 卡以太网头。
printf("Ethernet type is :\n");
ethernet_type=ntohs(ethernet_protocol->ether_type);//
printf("%04x\n",ethernet_type);
// judge
switch(ethernet_type){
case 0x0800:printf("The network layer is IP protocol\n");break;
case 0x0806:printf("THe network layer is ARP protocol\n");break;
case 0x8035:printf("The network layer is RARP protocol\n");break;
default :break;
}
printf("Mac Source Address is :\n");
mac_string=ethernet_protocol->ether_shost;
printf("%02x:%02x:%02x:%02x:%02x:%02x",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
switch(ethernet_type){
case 0x0800:// 根据以太网
ip_protocol_packet_callback(argument,packet_header,packet_content);break;// 执行 IP数据报的函数。
}
printf("*************************************************************");
packet_number++;
}
void main(){
pcap_t * pcap_handle;
char error_content[PCAP_ERRBUF_SIZE];
char *net_interface;
struct bpf_program bpf_filter;
char bpf_filter_string[]="ip";
bpf_u_int32 net_mask;
bpf_u_int32 net_ip;
net_interface=pcap_lookupdev(error_content);// 获取网络接口,
pcap_lookupnet(net_interface,&net_ip,&net_mask,error_content);// 获得IP地址和子网掩码
pcap_handle=pcap_open_live(net_interface,BUFSIZ,1,0,error_content);// 打开
pcap_compile(pcap_handle,&bpf_filter,bpf_filter_string,0,net_ip);
pcap_setfilter(pcap_handle,&bpf_filter);
if(pcap_datalink(pcap_handle)!=DLT_EN10MB){
return;
}
pcap_loop(pcap_handle,-1,ethernet_protocol_packet_callback,NULL);// 每次抓获一个包就会执行 ethernet_protocol_packet_callback的回调函数。
pcap_close(pcap_handle);
}