【网络协议】使用soket实现IP协议数据包抓取

使用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);
		}

	}
}


你可能感兴趣的:(【网络协议】使用soket实现IP协议数据包抓取)