#include
#include
#include
#include
#include
#pragma comment(lib,"WS2_32.lib")
#define BUFFER_MAX 2048
#define IP_HDRINCL 2
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
using namespace std;
int main(){
SOCKET sock;
int n_read,proto;
int flag = 1;
char buffer[BUFFER_MAX];
char LocalName[256];
char *ethhead,*iphead,*tcphead,*udphead,*icmphead,*p;
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2),&WSAData)!=0)
{
printf("WSAStartup ERROR.\\n"); //如果初始化WSADATA结构得到错误码,则显示出错信息
return -1;
}
// if(sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)<0){
// cout<<"Socket创建失败"<<endl;
// exit(0);
// }
// setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)); //设置 IP 头操作选项
////////////////////////创建并设置原始套接字
sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);//启用winsock创建原始套接字,SOCK_RAW 类型表示原始套接字类型混杂模式,也就是接收所有包
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag));//设置原始套接字,设置 IP 头操作选项
////////////////////////把原始套接字绑定到本地主机网卡上,实现将本地网卡置于混杂模式
if(gethostname((char*)LocalName, sizeof(LocalName)-1)!=0) //获取本地主机IP
{
printf("获取主机名失败 Error:%d.\n",WSAGetLastError());
return -1;
}
gethostname((char*)LocalName, 256);//把本地主机名存放入指定的缓冲区中
hostent pHost = gethostbyname((char)LocalName);
SOCKADDR_IN addr_in; //获取本地 IP 地址
addr_in.sin_addr = *(in_addr *)pHost->h_addr_list[0];
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(40000);
if(bind(sock, (PSOCKADDR)&addr_in, sizeof(addr_in))!=0) //把原始套接字绑定在本地主机网卡上
{
printf("绑定失败:%d.\\n",WSAGetLastError()); //绑定失败时显示提示信息
return -1;
}
//////////////////////////设置原始套接字能够接受所有的数据
DWORD dwValue = 1;
if(ioctlsocket(sock, SIO_RCVALL, &dwValue)!=0)
{
printf("ioctlsocket Error:%d.\n",WSAGetLastError()); //设置失败时显示提示信息
return -1;
}
while(true){
int ret = recv(sock,buffer,BUFFER_MAX,0);
if(ret>0){
ethhead = buffer;
p = ethhead;
int n = 0XFF;
//链路层前6+6+2个字节为目的MAC 源MAC type
// printf("MAC: %.2X:%-02X-%.02X-%.02X-%.02X-%.02X ==> %.2X-%.2X-%.2X-%.2X-%.2X-%.2X-\n",p[6]&n,p[7]&n,p[8]&n,p[9]&n,p[10]&n,p[11]&n,
// p[0]&n,p[1]&n,p[2]&n,p[3]&n,p[4]&n,p[5]&n);
iphead = ethhead;// + 14;
p = iphead + 12;
//数据包前14个字节后为20字节的第九个字节为协议,第12-16,17-20个字节为源IP,目的IP
printf("IP: %d.%d.%d.%d ==> %d.%d.%d.%d\n",p[0]&0XFF,p[1]&0XFF,p[2]&0XFF,p[3]&0XFF,p[4]&0XFF,p[5]&0XFF,p[6]&0XFF,p[7]&0XFF);
short length = (short)(iphead+2)[0];
printf("总长度:%d\n",length);
proto = (iphead+9)[0];
p = iphead + 20;
printf("Protocol:");
switch(proto){
case 1: printf("ICMP\n");break;
case 2: printf("IGMP\n");break;
case 4: printf("IP\n");break;
case 6: printf("TCP\n");break;
case 8: printf("EGP\n");break;
case 9: printf("IGP\n");break;
case 17: printf("UDP\n");break;
case 41: printf("IPv6\n");break;
case 50: printf("ESP\n");break;
case 89: printf("OSPF\n");break;
default: printf("不知道,协议编号是%d,请自己查文档\n",proto);break;
}
}
cout<<endl;
Sleep(200);
}
}