#include "heads.h"
#include <winsock2.h>
#include <mstcpip.h> //定义 SIO_RCVALL
#include <iostream.h>
#include <ws2tcpip.h> //定义 IP_HDRINCL
#pragma comment(lib,"ws2_32")
unsigned int hostIP; //本地IP地址
int recv_packet(); //**********接收数据包函数***********
void parsePacket(char *recvBuffer); //**********解析数据包函数***********
void send_packet(char *sendBuffer); //**********发送数据包函数***********
/*****************************主函数********************************/
void main()
{
cout<<" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"<<endl;
cout<<" -*-*-* 利用原始套接字实现网络防火墙*-*-*-"<<endl;
cout<<" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"<<endl;
cout<<" # 开发者-!-张 毅 # "<<endl;
cout<<endl<<endl;
WSADATA WSAData; // WSADATA 结构用来存储WINDOWS SOCKETS初始化信息
/*---------------------------------------------------------!
*** struct WSAData {
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYSSTATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
}
加载成功后:
wVersion = 2 表示加载版本为2.0
wHighVersion = 514 表示当前系统支持socket最高版本为2.2
szDescription = "WinSock 2.0"
szSystemStatus = "Running" 表示正在运行
iMaxSockets = 0 表示同时打开的socket最大数,为0表示没有限制
iMaxUdpDg = 0 表示同时打开的数据报最大数,为0表示没有限制
lpVendorInfo 没有使用,为厂商指定信息预留
!---------------------------------------------------------*/
struct hostent *host; //hostent结构用来存储本地主机信息
/*---------------------------------------------------------!
*** struct hostent {
char FAR * h_name; //这个主机的正式名称
char FAR * FAR * h_aliases; //一个以NULL(空字符)结尾的数组,里面存储了主机的备用名称
short h_addrtype; //返回地址的类型,一般来说是"AF_INET"
short h_length; //地址的字节长度
char FAR * FAR * h_addr_list; //一个以0 结尾的数组,存储了主机的网络地址
}
!---------------------------------------------------------*/
char hostname[128]; //本地主机名
if ( WSAStartup(MAKEWORD(2,2), &WSAData) ) //加载动态链接库Winsock32.DLL,初始化Winsock版本信息
{
cout<<"WSAStartup Error = "<<WSAGetLastError()<<"!!!"<<endl;
exit(0);
}
else
cout<<"初始化Winsock版本2.2 , 加载WinSock32.dll成功!!"<<endl;
cout<<endl;
gethostname(hostname, 128); //获取主机名
host = gethostbyname(hostname); //根据主机名获取主机相关信息
if(host == NULL)
{
cout<<"获取本地主机信息失败!!!"<<endl;
WSACleanup();
exit(0);
}
else
cout<<"本地计算机名: "<<host->h_name<<endl;
memcpy( &hostIP, host->h_addr_list[0], sizeof(host->h_addr_list) );
char *dotIP=inet_ntoa( *( struct in_addr * ) &hostIP ); //转换为用点标识的IP地址字符串
/*******************************************************
char dotIP;
strcpy( &dotIP , inet_ntoa(*(struct in_addr *)&hostIP) );
!*******************************************************/
/*-----------------------------------------------------!
*** in_addr用来存储计算机IP地址,结构如下:
struct in_addr {
union {
struct{
unsigned char s_b1,
s_b2,
s_b3,
s_b4;
} S_un_b;
struct {
unsigned short s_w1,
s_w2;
} S_un_w;
unsigned long S_addr;
} S_un;
}
!------------------------------!
*** inet_ntoa函数 把一个IPV4的因特网网络地址结构转换成 用点标识的标准IP地址字符串
char FAR * inet_ntoa (
struct in_addr in
)
!---------------------------*/
cout<<"本机IP地址: "<< dotIP <<endl;
cout<<endl;
recv_packet(); //调用接收数据包函数
}
/******************** 接收数据包recv_packet()函数 ************************/
int recv_packet()
{
SOCKET recv_sock; //定义一个套接字
/*--------------------------------------------------------!
*** SOCKET socket (
int af,
int type,
int protocol
)
!--------------------------------------------------------*/
/********************建立一个套接字***********************/
recv_sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED);
/*********************************************************
sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
*********************************************************/
if(recv_sock==INVALID_SOCKET)
{
cout<<"Receive Socket WSASocket Error = "<<WSAGetLastError()<<"!!!"<<endl;
exit(0);
}
else
cout<<"已经建立原始套接字!!"<<endl<<endl;
SOCKADDR_IN sock_addr; //声明一个套接字接口地址信息
/*--------------------------------------------------------!
struct sockaddr_in{
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
}
!--------------------------------------------------------*/
/**********************设置绑定接口信息*******************/
sock_addr.sin_family = AF_INET;
sock_addr.sin_port = htons(0); //随机选择一个未用的端口
sock_addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.1"); //绑定本机IP地址
/*****************************************************
sock_addr.sin_addr.s_addr = hostIP;
*****************************************************/
/**********把建立的套接字与本机IP地址绑定**************/
int b=bind(recv_sock, (sockaddr *)&sock_addr, sizeof(sock_addr));
if(b==SOCKET_ERROR)
{
cout<<"Bind Error = "<<WSAGetLastError()<<"!!!"<<endl;
exit(0);
}
else
cout<<"原始套接字已经绑定本机端口"<<sock_addr.sin_port<<" !!"<<endl<<endl;
/****************设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包*********/
DWORD dwBufferLen[10] ;
DWORD dwBufferInLen = 1 ;
DWORD dwBytesReturned = 0 ;
if(WSAIoctl(recv_sock, SIO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen),
&dwBufferLen, sizeof(dwBufferLen), &dwBytesReturned, NULL, NULL)==SOCKET_ERROR)
{
cout<<"WSAIoctl Error = "<<WSAGetLastError()<<endl<<endl;
exit(0);
}
else
cout<<"已经设置网卡为混杂模式,接收所有数据包!!"<<endl<<endl;
/*-----------------------------------------------------------------!
int WSAIoctl(
SOCKET s, //一个指定的套接字
DWORD dwIoControlCode, //控制操作码
LPVOID lpvInBuffer, //指向输入数据流的指针
DWORD cbInBuffer, //输入数据流的大小(字节数)
LPVOID lpvOutBuffer, // 指向输出数据流的指针
DWORD cbOutBuffer, //输出数据流的大小(字节数)
LPDWORD lpcbBytesReturned, //指向输出字节流数目的实数值
LPWSAOVERLAPPED lpOverlapped, //指向一个WSAOVERLAPPED结构
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)//指向操作完成时执行的例程
!------------------------------------------------------------------*/
/**************************接收数据包**********************/
while(1)
{
char recvBuffer[65000] = {0}; //存储接收到的数据包
//memset(recvBuffer , 0 , sizeof(recvBuffer) );
int bytesRecived = recv(recv_sock, recvBuffer, sizeof(recvBuffer), 0);
/*---------------------------------------------------------------------!
int recv( SOCKET s, 为准备接收数据的