⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arpparse.cpp

📁 此为计算机网络课程设计C/C++源代码 包括一些协议的底层实现
💻 CPP
字号:
/*解析ARP数据包*/

#include <WINSOCK2.H>
#pragma comment(lib,"Ws2_32.lib")		//用到ntohs()
//等同于点击"Project->settings->link"打开Object/library modules编辑框后加入lib文件
#pragma comment(lib,"wpcap.lib")

#include "pcap.h"				/*winpcap包中的头文件,需要将其导入到VC中*/
#include <fstream.h>
#include <iomanip.h>
#include <conio.h>

/*
注意到接收的数据包头中代表类型,数据长度的字段采用的是big-endian
所以对于2B/4B的数据要用ntohs()转换为本机形式
*/

/*arp包结构*/
struct arppkt{
	unsigned short hdtyp;	/* 硬件类型。值0001表示其为Ehternet */
	unsigned short protyp;	/*协议类型。值0800表示上层协议为IP */
	unsigned char hdsize;	/* 硬件地址长度,值为06 */
	unsigned char prosize;	/* 协议地址长度,值为04 */
	unsigned short op;		/* 操作值:0001/0002,分别表示ARP请求/回答 */
	u_char smac[6];			/* 源MAC地址,6B */
	u_char sip[4];			/* 源IP地址,4B */
	u_char dmac[6];			/* 目的MAC地址 */
	u_char dip[4];			/* 目的IP地址 */
};

/*
自定义处理包的函数
pcap_pkthdr结构是堆文件中数据包的头,是winpcap加入的
pkt_data表示MAC帧的起始位置
out是输出流
*/
void packet_handler(const pcap_pkthdr *header,const u_char *pkt_data,ostream& out);

void main(int argc,char *argv[])
{
	if (argc!=2)
	{
		cout<<"Usage:arpparse logfilename"<<endl;
		cout<<"Press any key to continue."<<endl;
		_getch();
		return;
	}

	pcap_if_t *alldevs;			/*网络设备结构*/
	pcap_if_t *d;			

	pcap_t *adhandle;			/*网卡描述符*/
	char errbuf[PCAP_BUF_SIZE];	/*错误信息*/
	u_int netmask;				/*子网掩码*/
	char packet_filter[]="ether proto \\arp";	/*过滤,选择ARP协议*/
	struct bpf_program fcode;
	struct pcap_pkthdr *header;
	const u_char *pkt_data;

	/*获取网络设备列表*/
	if (pcap_findalldevs(&alldevs,errbuf) ==-1 )
	{
		cout<<"Error in pcap_findalldevs:"<<errbuf;
		return;
	}

	/*选择一个ethernet卡 */
	for (d=alldevs;d;d=d->next)
	{
		/*以混杂模式打开网卡,以接收所有的帧*/
		if ((adhandle=pcap_open_live(d->name,1000,1,300,errbuf)) == NULL)
		{
			cout<<"\nUnable to open the adapter.";
			pcap_freealldevs(alldevs);
			return;
		}

		if (pcap_datalink(adhandle)==DLT_EN10MB && d->addresses != NULL)
		{
			/*检查数据链路是否为Ethernet(DLT_EN10MB) */
			break;
		}

		if (d==NULL)
		{
			cout<<"\nNo interface found!Make sure Winpcap is installed.\n";
			return;
		}


		/*获得子网掩码*/
		if (d->addresses!=NULL)
		{
			netmask=((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
		}
		else
			/*没有地址则假设为C类地址*/
			netmask=0xffffff;

		/*编译过滤器,只捕获ARP包*/
		if ( pcap_compile(adhandle,&fcode,packet_filter,1,netmask)<0 )
		{
			cout<<"\nUnable to compile the packet filter.Check the syntax.\n";
			pcap_freealldevs(alldevs);
			return;
		}

		/*设置过滤器*/
		if (pcap_setfilter(adhandle,&fcode)<0)
		{
			cout<<"\nError setting the filter.\n";
			pcap_freealldevs(alldevs);
			return;
		}

		/*显示提示信息和每项含义*/
		cout<<"\t\tListening on"<<d->description<<"..."<<endl<<endl;
		ofstream fout(argv[1],ios::app);	/*日志记录文件*/

		/*为查看日志时的方便其中加入了日期记录*/
		time_t t;
		time(&t);
		fout.seekp(0,ios::end);
		if (fout.tellp()!=0)
		{
			fout<<endl;
		}

		fout<<"\t\tARP request(1)/reply(2) on"<<ctime(&t);

		cout<<"Sour IP Addr"<<"	"<<"Sour Mac Address"
			<<"	"<<"Des IP Addr"<<"	"<<"Des Mac Address"
			<<"	"<<"OP"<<"	"<<"Time"<<endl;

		fout<<"Sour IP Addr"<<"	"<<"Sour Mac Address"
			<<"	"<<"Des IP Addr"<<"	"<<"Des Mac Address"
			<<"	"<<"OP"<<"	"<<"Time"<<endl;
		
		/*释放设备列表*/
		pcap_freealldevs(alldevs);

		/*开始捕获MAC帧*/
		int result;			/*时间到返回结果*/
		while ((result=pcap_next_ex(adhandle,&header,&pkt_data))>=0)
		{
			if (result==0)
			{
				continue;	/*超时返回*/
			}
			packet_handler(header,pkt_data,cout);	/*解析ARP包,将结果输出到屏幕*/
			packet_handler(header,pkt_data,fout);	/*输出到文件*/
		}
	}
}

void packet_handler(const pcap_pkthdr *header,const u_char *pkt_data,ostream& out)
{
	/*从截获的数据帧中ARP头的位置*/
	arppkt* arph=(arppkt *)(pkt_data + 14);
	/*14为Ethernet的帧头长度,源和目的地址长度均为12B 数据长度为2B */

	/*输出源IP*/
	for (int i=0;i<3;i++)
	{
		cout<<int(arph->sip[i])<<'.';
	}
	out.setf(ios::left);
	out<<setw(3)<<int(arph->sip[3])<<"	";
	out.unsetf(ios::left);

	/*输出源MAC地址*/
	char oldfillchar=out.fill('0');
	out.setf(ios::uppercase);
	for (i=0;i<5;i++)
	{
		out<<hex<<setw(2)<<int(arph->smac[i])<<'-';

	}
	out<<hex<<setw(2)<<int(arph->smac[5])<<"	";
	out.fill(oldfillchar);

	/*输出目的IP*/
	out.unsetf(ios::hex | ios::uppercase);
	for (i=0;i<3;i++)
	{
		cout<<int(arph->dip[i])<<'.';
	}
	out.setf(ios::left);
	out<<setw(3)<<int(arph->dip[3])<<"	";
	out.unsetf(ios::left);

	/*输出目的MAC地址*/
	out.fill('0');
	out.setf(ios::uppercase);
	//char oldfillchar=out.fill('0');
	out.setf(ios::uppercase);
	for (i=0;i<5;i++)
	{
		out<<hex<<setw(2)<<int(arph->dmac[i])<<'-';

	}
	out<<hex<<setw(2)<<int(arph->dmac[5])<<"	";
	out.fill(oldfillchar);
	out.unsetf(ios::hex | ios::uppercase);
	out<<ntohs(arph->op)<<"	";				/*输出操作类型,注意网络字节顺序的转换*/
	struct tm *ltime;
	ltime=localtime(&header->ts.tv_sec);
	out.fill('0');

	out<<ltime->tm_hour<<':'<<setw(2)<<ltime->tm_min<<':'<<setw(2)<<ltime->tm_sec;
	out.fill(oldfillchar);
	out<<endl;

}




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -