使用socket编程实现IP协议数据帧的抓取:
#include "stdafx.h"
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define MAX_HOSTNAME_LAN 255
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
#define MAX_ADDR_LEN 16
//IP协议头
struct ipheader {
unsigned char ip_hl:4, ip_v:4; /* this means that each member is 4 bits */
unsigned char ip_tos;
unsigned short int ip_len;
unsigned short int ip_id;
unsigned short int ip_off;
unsigned char ip_ttl;
unsigned char ip_p;
unsigned short int ip_sum;
unsigned int ip_src;
unsigned int ip_dst;
}; /* total ip header length: 20 bytes (=160 bits) */
//UDP协议头
typedef struct udphdr {
unsigned short sport;
unsigned short dport;
unsigned short len;
unsigned short cksum;
}UDP_HDR;
//TCP协议头
typedef struct tcphdr {
//待实现
}TCP_HDR;
void main()
{
SOCKET sock;
WSADATA wsd;
DWORD dwBytesRet;
unsigned int optval = 1;
unsigned char *dataudp,*pUdpData;
int QQ,iUdpDataLen;
SOCKADDR_IN sa,saSource, saDest;
struct hostent FAR * pHostent;
char FAR name[MAX_HOSTNAME_LAN];
char szSourceIP[MAX_ADDR_LEN],RecvBuf[65535] = {0};
struct udphdr *pUdpheader;
struct ipheader *pIpheader;
WSAStartup(MAKEWORD(2,1),&wsd);
if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP))==SOCKET_ERROR)
exit(1);
gethostname(name, MAX_HOSTNAME_LAN);
pHostent = gethostbyname(name);
sa.sin_family = AF_INET;
sa.sin_port = htons(0);//0即监听所有端口
memcpy(&sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length);
bind(sock, (SOCKADDR *)&sa, sizeof(sa));
if ((WSAGetLastError())==10013)
exit(1);
WSAIoctl(sock, SIO_RCVALL, &optval, sizeof(optval), NULL, 0, &dwBytesRet, NULL, NULL);
while (1)
{
memset(RecvBuf, 0, sizeof(RecvBuf));
recv(sock, RecvBuf, sizeof(RecvBuf), 0);
pIpheader = (struct ipheader *)RecvBuf;
if((pIpheader->ip_p)==IPPROTO_UDP)
{
pUdpheader = (struct udphdr *) (RecvBuf+ sizeof(struct ipheader ));
pUdpData=(unsigned char *) RecvBuf+sizeof(struct ipheader)+sizeof(struct udphdr);
iUdpDataLen=ntohs(pIpheader->ip_len)-(sizeof(struct ipheader)+sizeof(struct udphdr));
printf("recv udp data from %d:%d,to %d:%d,data len:%d\n",ntohl(pIpheader->ip_src),ntohs(pUdpheader->sport),ntohl(pIpheader->ip_dst),ntohs(pUdpheader->dport),iUdpDataLen);
printf("udp data:%s\n",pUdpData);
}
else if((pIpheader->ip_p)==IPPROTO_TCP)
{
//解析TCP协议头和数据
printf("recv tcp data\n");
}
else if((pIpheader->ip_p)==IPPROTO_ICMP)
{
//解析ICMP协议头和数据
printf("recv icmp data\n");
}
else if((pIpheader->ip_p)==IPPROTO_IGMP)
{
//解析IGMP协议头和数据
printf("recv igmp data\n");
}
else
{
printf("other ip protocol:%d\n",pIpheader->ip_p);
}
}
}