要求是接收解析ICMPecho请求报文,
用命令行PraseICMP.exe log_file.txt
的形式执行。
// ParsePacket.cpp : 定义控制台应用程序的入口点。
//
//#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
/* ICMP 首部 -- RFC 792 */
struct icmp_hdr
{
unsigned char type; /* 类型 */
unsigned char code; /* 代码 */
unsigned short checksum; /* 校验和 */
unsigned short id; /* 标识符 */
unsigned short seq; /* 序列号 */
/* 这之后的不是标准 ICMP 首部, 用于记录时间 */
unsigned long timestamp;
};
//定义IP头部结构
typedef struct _IP_HEADER
{
union
{
BYTE Version; //版本(前4位)
BYTE HdrLen; //IP头部长度(后4位)
};
BYTE ServiceType; //服务类型
WORD TotalLen; //总长度
WORD ID; //标识
union
{
WORD Flags; //标志u(前3位)
WORD FragOff; //分段偏移(后13位)
};
BYTE TimeToLive; //生命期
BYTE Protocol; //协议
WORD HdrChksum; //头校验和
DWORD SrcAddr; //源地址
DWORD DstAddr; //目的地址
BYTE Options; //选项
}IP_HEADER;
#define IO_RCVALL _WSAIOW(IOC_VENDOR,1)
#define BUFFER_SIZE 65535
//解析IP包的头部长度
void getIHL(BYTE b, BYTE &length)
{
length = (b & 0x0f) * 4;
}
//解析ICMP类型
char* geticmptype(char type)
{
switch (type)
{
case 0:
return "查询报文----应答";
case 3:
return "差错报告报文----目的不可达";
case 4:
return "控制报文----源抑制";
case 5:
return "控制报文----路由重定向";
case 8:
return "查询报文----回送请求";
case 10:
return "查询报文----路由器请求";
case 11:
return "差错报告报文----超时";
case 12:
return "差错报告报文----参数出错";
case 13:
return "查询报文----时间戳请求";
case 14:
return "查询报文----时间戳应答";
case 17:
return "查询报文----掩码请求";
case 18:
return "查询报文----掩码应答";
case 19:
return "差错报告报文----通告";
default:
return "Unknown";
}
}
void ipparse(FILE* file, char* buffer)
{
int i,j;
int iphead;
IP_HEADER ip = *(IP_HEADER*)buffer;
iphead=(ip.Version & 0x0f)<<2;
icmp_hdr icmp_hd = *(icmp_hdr*)(buffer+iphead);
fseek(file, 0, SEEK_END);
if(ip.Protocol == 1 && icmp_hd.type==8)
{
printf("\n------ICMP eacho请求报文前50B------\n");
for(i=0;i<5;i++)
{
for(j=0;j<10;j++)
{
printf("%x%x ",(unsigned char)buffer[10*i+j]>>4,buffer[10*i+j]&0x0f);
}
printf("\n");
}
fprintf(file, "------解析ICMP eacho请求报文------\n");
//解析IP包的源IP地址
fprintf(file, "SrcAddr: %s\n", inet_ntoa(*(in_addr*)&ip.SrcAddr));
//解析IP包的目的IP地址
fprintf(file, "DstAdrr: %s\n", inet_ntoa(*(in_addr*)&ip.DstAddr));
//解析ICMP类型
fprintf(file, "Type: %s\n",geticmptype(icmp_hd.type));
//解析ICMP代码
fprintf(file, "Code: %d\n",icmp_hd.code);
//解析ICMP校验和
fprintf(file, "Sum: 0x%x\n",ntohs((unsigned int)icmp_hd.checksum));
//解析ICMP标识符
fprintf(file, "ID: %d\n",ntohs(icmp_hd.id));
//解析ICMP序列号
fprintf(file, "Seq: %d\n",ntohs(icmp_hd.seq));
}
}
int main(int argc, char* argv[])
{
//检查输入的命令格式
if (argc != 2)
{
printf("Please input command:ParseICMP.exe log_file.txt\n");
return 0;
}
//打开输出日志文件
FILE* file;
if ((file = fopen(argv[1], "wb+")) == NULL)
{
printf("Fail to open file %s!", argv[1]);
return 0;
}
//初始化Socket环境
WSADATA wsData;
if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0)
{
printf("WSAStartup failed!");
return 0;
}
//建立原始Socket
SOCKET sock;
if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) == INVALID_SOCKET)
{
printf("Create socket failed!");
return 0;
}
//设置IP头部操作选项,flag设置为ture
BOOL flag = true;
if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)) == SOCKET_ERROR)
{
printf("Setsockopt failed!");
return 0;
}
//获取本地主机名
char hostName[128];
if (gethostname(hostName, 100) == SOCKET_ERROR)
{
printf("Gethostbyname failed!");
return 0;
}
//获取本地主机IP地址
hostent* pHostIP;
if ((pHostIP = gethostbyname(hostName)) == NULL)
{
printf("Gethostbyname failed!");
return 0;
}
//填充SOCKADDR_IN结构
sockaddr_in addr_in, cliadd;
addr_in.sin_addr = *(in_addr*)pHostIP->h_addr_list[0];
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(5050);
//把原始Socket绑定到本地网卡
if (bind(sock, (PSOCKADDR)&addr_in, sizeof(addr_in)) == SOCKET_ERROR)
{
printf("Bind failed!");
return 0;
}
int ilen = sizeof(cliadd);
//设置SOCK_RAW为SIO_RCVALL,接收所有数据包
DWORD dwValue = 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)
{
printf("Ioctlsocket failed!");
return 0;
}
//监听经过本机的IP包
char buffer[BUFFER_SIZE];
printf("Listening on local host...\n");
while (true)
{
// int size = recv(sock, buffer, BUFFER_SIZE, 0);
int size = recvfrom(sock, buffer, BUFFER_SIZE, 0 , (struct sockaddr*)&cliadd, &ilen);
if (size > 0)
{
ipparse(stdout, buffer);
//ipparse(file, buffer);
}
}
fclose(file);
return 0;
}