接收并解析ICMP报文

// paeseICMP.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "paeseICMP.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

CWinApp theApp;

//接收并解析ICMP
/*
2016.11.24
*/
#include

#include
#include
#include

using namespace std;

#pragma comment (lib, "ws2_32.lib")

#define  BUFFER_SIZE 65536		//设置接收数据包的缓冲区长度

/* ICMP 类型 */
#define ICMP_TYPE_ECHO          8
#define ICMP_TYPE_ECHO_REPLY    0


struct icmp_hdr
{   
    unsigned short type;   /* 类型 */
    unsigned short code;         /* 代码 */
    unsigned short checksum;    /* 校验和 */
    unsigned short id;          /* 标识符 */
    unsigned short seq;         /* 序列号 */
};

//定义IP首部数据结构
typedef struct _IP_HEADER
{
	union 
	{
		BYTE Version;		//版本(前四位)
		BYTE HdrLen;		//IHL(后四位),IP头的长度
	};
	
	BYTE ServiceType;		//服务类型
	WORD TotalLen;			//总长度
	WORD ID;				//标识

	union 
	{
		WORD Flags;			//(前三位)标志
		WORD FragOff;		//(后十三位)分段偏移
	};
	
	BYTE TimeToLive;		//TTL
	BYTE Protocol;			//协议
	
	WORD HdrChksum;			//头校验和
	DWORD SrcAddr;			//源地址
	DWORD DstAddr;			//目的地址
	//BYTE Options;			//选项
	icmp_hdr icmp_hdr;

}IP_HEADER;


//逐步解析ICMP头中的信息

void getIHL(BYTE b, BYTE &result)
{
	result = (b & 0x0f) * 4;
}


void icmpprase(FILE * file, char * buffer)
{
	IP_HEADER ip = *(IP_HEADER *) buffer;
	fseek(file, 0, SEEK_END);

	if((ip.Protocol) == 1)
	{
		struct icmp_hdr icmp_hdr;
		icmp_hdr=ip.icmp_hdr;
		if(icmp_hdr.type ==ICMP_TYPE_ECHO)
		{
		fprintf(file,"ICMP报文解析:\r\n");
		fprintf(file,"源地址%s:\r\n",inet_ntoa(*(in_addr*)&ip.SrcAddr));
		fprintf(file,"目的地址%s:\r\n",inet_ntoa(*(in_addr*)&ip.DstAddr));
		fprintf(file,"类型:%d\r\n",icmp_hdr.type);
		fprintf(file,"代码:%d\r\n",icmp_hdr.code);
		fprintf(file,"校验和:%d\r\n",icmp_hdr.checksum);
		fprintf(file,"\n\n\n\n");
		}
	}
}

int main(int argc, char * argv[])
{
	if(argc != 2)
	{
		cout << "usage error!" << endl;
		return -1;
	}
	
	FILE * file;
	if((file = fopen(argv[1],"wb+")) == NULL)
	{
		cout << "fail to open file %s" << argv[1] << endl;
		return -1;
	}
	
	WSADATA wsData;
	//如果程序初始化失败,那么程序退出
	if(WSAStartup(MAKEWORD(2, 2), &wsData) != 0)
	{
		cout << "WSAStartup failed" << endl;
		return -1;
	}
	
	//建立原始SOCKET
	SOCKET sock;
	if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) == INVALID_SOCKET)
	{
		cout << "CREATE SOCKET FAILED" << endl;
		return -1;
	}
	
	//设置IP头操作选项,其中flag设为TURE, 用户可以亲自对IP头进行处理
	BOOL flag = TRUE;
	if(setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*) & flag, sizeof(flag)) == SOCKET_ERROR)
	{
		cout << "setsockopt failed" << endl;
		return -1;
	}
	
	char hostName[128];
	if(gethostname(hostName, 100) == SOCKET_ERROR)
	{
		cout << "gethostName failed" << endl;
		return -1;
	}
	
	//获取本机IP地址
	hostent * pHostIP;
	if((pHostIP = gethostbyname(hostName)) == NULL)
	{
		cout << "gethostbyname failed" << endl;
		return -1;
	}
	
	//填充SOCKADDR_IN结构
	sockaddr_in addr_in;
	addr_in.sin_addr = *(in_addr*) pHostIP -> h_addr_list[0];
	addr_in.sin_family = AF_INET;
	addr_in.sin_port = htons(6000);
	
	//把原始的socket绑定到网卡
	if(bind (sock, (PSOCKADDR) & addr_in, sizeof(addr_in)) == SOCKET_ERROR)
	{
		cout << "bind failed" << endl;
		return -1;
	}
	DWORD dwValue = 1;
	
	//设置SOCK_RAW为SIO_RCVALL, 以便接收所有的IP包
	#define IO_RCVALL _WSAIOW (IOC_VENDOR, 1)
	DWORD dwBufferLen[10];
	DWORD dwBufferInLen = 1;
	DWORD dwBytesReturned = 0;
	
	if(WSAIoctl (sock, IO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen, sizeof(dwBufferLen), &dwBytesReturned, NULL, NULL) == SOCKET_ERROR)
	{
		cout << "ioctlsocket failed" << endl;
		return -1;
	}
	
	//设置接收数据包的缓冲区长度
	char buffer[BUFFER_SIZE];
	
	//监听网卡
	cout << "开始解析经过本机的ICMP数据包" << endl << endl;
	
	while (true)
	{
		int size = recv(sock, buffer, BUFFER_SIZE, 0);
		if(size > 0)
		{
			icmpprase(stdout, buffer);
			icmpprase(file, buffer);
		}
	}
	fclose(file);
	return 0;
}

你可能感兴趣的:(接收并解析ICMP报文)