接收并解析ICMP报文

来源:互联网 发布:网络彩票推广员 编辑:程序博客网 时间:2024/05/17 20:31
// paeseICMP.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "paeseICMP.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// The one and only application objectCWinApp theApp;//接收并解析ICMP/*2016.11.24*/#include<stdio.h>#include<winsock2.h>#include<ws2tcpip.h>#include<iostream>using namespace std;#pragma comment (lib, "ws2_32.lib")#define  BUFFER_SIZE 65536//设置接收数据包的缓冲区长度/* ICMP 类型 */#define ICMP_TYPE_ECHO          8#define ICMP_TYPE_ECHO_REPLY    0struct 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;//TTLBYTE 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;}//建立原始SOCKETSOCKET 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;}