/*
*程序2.
*程序名:AnalyzeIPv4_WinPcap.cpp
*本程序通过使用WinPcap来捕获局域网内的IPv4数据报文,并解析IPv4包头格式
*/
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <pcap.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32")
#pragma comment(lib,"wpcap")
//以太帧头结构体
typedef struct ether_header {
unsigned char ether_dhost[6];
unsigned char ether_shost[6];
unsigned short ether_type;
}ETHHEADER,*PETHHEADER;
//IPv4包头结构体
typedef struct ip_header {
unsigned char ver_ihl; //Version (4 bits) + Internet header length (4 bits)
unsigned char tos; //Type of service
unsigned short tlen; //Total length
unsigned short identification; //Identification
unsigned short flags_fo; //Flags (3 bits) + Fragment offset (13 bits)
unsigned char ttl; //Time to live
unsigned char proto; //Protocol
unsigned short crc; //Header checksum
u_char ip_src[4]; //Source address
u_char ip_dst[4]; //Destination address
unsigned int op_pad; //Option + Padding
}IPHEADER,*PIPHEADER;
void InitAdapter(); //初始化网络适配器
void dispatcher_handler(u_char*,const pcap_pkthdr*,const u_char *);//解析IPv4包头
void print_hwadd(u_char *hwadd); //打印出IPv4地址
void CloseAdapter(); //关闭网络适配器
FILE *fp;
pcap_if_t *alldevs,*d;
char errbuf[PCAP_ERRBUF_SIZE];
int i=0;
pcap_t *adhandle;
void main() {
int count=0,number;
cout<<"Please enter the number of packet sended:"<<endl;
cin>>number;
InitAdapter();
fp=fopen("f://000//ip.txt","w");
while(count<=number) {
pcap_loop(adhandle,1,dispatcher_handler,NULL); //捕获数据报
count++;
}
CloseAdapter();
}
void InitAdapter() {
int i;
if(pcap_findalldevs(&alldevs,errbuf)==-1) { //寻找网络适配器
cout<<"Error in pcap_findalldevs!";
return;
}
for(d=alldevs,i=0;i<0;d=d->next,i++);
if((adhandle=pcap_open_live(d->name,65535,1,20,errbuf))==NULL) {//打开选取的网络适配器
cout<<"Unable to open the adapter!";
pcap_freealldevs(alldevs);
return;
}
if(pcap_datalink(adhandle)!=DLT_EN10MB) { //判断网络是否为10MB以太网
cout<<"This program works only on Ethernet network!";
pcap_freealldevs(alldevs);
return;
}
}
void dispatcher_handler(u_char *,const pcap_pkthdr *header,const u_char *p) {
PETHHEADER eth=(PETHHEADER)p;
PIPHEADER ip=(PIPHEADER)(p+sizeof(ETHHEADER));
if(ntohs(eth->ether_type)==0x0800) {
fprintf(fp,"版本:");
fprintf(fp,"%d ",ip->ver_ihl>>4); //获取版本
fprintf(fp,"首部长度:");
fprintf(fp,"%d ",ip->ver_ihl&15); //获取首部长度
fprintf(fp,"服务类型:");
fprintf(fp,"%d ",ip->tos); //获取服务类型
fprintf(fp,"总长度:");
fprintf(fp,"%d ",ntohs(ip->tlen)); //获取总长度
fprintf(fp,"标识:");
fprintf(fp,"%d ",ntohs(ip->identification)); //获取标识
fprintf(fp,"标志:");
fprintf(fp,"%d ",ip->flags_fo>>13); //获取标志
fprintf(fp,"偏移量:");
fprintf(fp,"%d\n",ip->flags_fo&8191); //获取偏移量
fprintf(fp,"生存时间:");
fprintf(fp,"%d ",ip->ttl); //获取生存时间
fprintf(fp,"协议:");
fprintf(fp,"%d ",ip->proto); //获取上部协议
fprintf(fp,"首部校验和:");
fprintf(fp,"%d\n",ntohs(ip->crc)); //获取首部校验和
fprintf(fp,"源IP:");
for(int i=0;i<3;i++)
fprintf(fp,"%d.",ip->ip_src[i]); //获取源IP地址
fprintf(fp,"%d ",ip->ip_src[3]);
fprintf(fp,"-> ");
fprintf(fp,"目的IP:");
for(i=0;i<3;i++)
fprintf(fp,"%d.",ip->ip_dst[i]);
fprintf(fp,"%d ",ip->ip_dst[3]); //获取目的IP地址
fprintf(fp,"\n===============\n");
}
}
void CloseAdapter() {
fclose(fp);
pcap_freealldevs(alldevs);
pcap_close(adhandle);
}