#include "winsock2.h" 
#include "ws2tcpip.h" 
#include "iostream"
#include "stdio.h" 
#pragma   comment(lib,"ws2_32.lib")  

/*定义IP头部数据结构*/
typedef struct _IP_HEADER
   {
 
   union
     {
 
       BYTE Version;    //版本(前四位)
        BYTE HdrLen;    //报头标长(后四位),IP头长度
     };
 
    BYTE ServiceType;    //服务类型
     WORD TotalLen;     //总长度
     WORD ID;         //标志
     union
     {
 
       WORD Flags;
        WORD FragOff;
     };
 
    BYTE TimeToLive;    //生存时间
     BYTE Protocol;     //协议
  
   WORD HdrChksum;    //首部检验和
     DWORD SrcAddr;      //源地址
     DWORD DstAddr;      //目的地址
     BYTE Options;
    }IP_HEADER;
/*逐位解析IP头中的信息,获取版本号*/
void getVersion(BYTE b, BYTE & version)
 {
  version=b>>4;            
 }  

void getIHL(BYTE b,BYTE & result)
 {
  result=(b&0x0f)*4; 
 }


/*解析服务类型*/ 

char * parseServiceType_getProcedence(BYTE b)
 {     
     switch (b>>5)
  {case 7:          
   return "Network Control";
        break;
  case 6:   
        return "Internet work Control";
    break;       case 5:
     return "CRITIC/ECP"; 
    break;
  case 4:
      return "Flash Override";  
    break;
  case 3:
     return "Flsah";
    break;
  case 2:  
       return "Immediate";                
       break; 
 case 1:  
       return "Priority";     
    break; 
 case 0:   
        return "Routine";          
    break; 
 default:  
       return "Unknow";  
       break;
  }
 }  

char * parseServiceType_getTOS(BYTE b)
 {
  b=(b>>1)&0x0f;
  switch(b)                      
  {        
   case 0:
           return "Normal service";          
           break;
  case 1: 
           return "Minimize monetary cost";      
           break;  
   case 2:  
           return "Maximize reliability";      
             break;  
   case 4:
            return "Maximize throughput";          
            break;
    case 8:  
             return "Minimize delay";   
       break; 
     case 15:  
             return "Maximize security";       
       break;            
   default:  
            return "Unknow";    
   }
   }
/* 获取禁止分片标志和分片标志 */

void getFlags(WORD w,BYTE & DF,BYTE & MF)
{
  DF=(w>>14)&0x01;  
    MF=(w>>13)&0x01;
 }

/* 获取分片偏移量 */ 

void getFragOff(WORD w,WORD & fragOff)           
{
  fragOff=w&0x1fff;
}  
/*获取协议*/ 

char * getProtocol(BYTE Protocol)              
{
  switch(Protocol)                           
    {                            
  case 1: return "ICMP";         
  case 2: return "IGMP";  
 case 4: return "IP in IP"; 
 case 6:  return "TCP"; 
 case 8: return "EGP";
  case 17: return "UDP";             
  case 41: return "IPv6";  
    case 46: return "RSVP";  
    case 89: return "OSPF";
  default: return "UNKNOW";
  }
}  

/* 解析IP数据包 */ 
void ipparse(FILE* file,char* buffer)
{
 
 IP_HEADER ip=*(IP_HEADER*)buffer; 
  fseek(file,0,SEEK_END); 
  BYTE version; 
  
   getVersion(ip.Version,version); 
 
  fprintf(file,"版本号=%d\r\n",version); 
  BYTE headerLen; 
   
    getIHL(ip.HdrLen,headerLen); 
  
   fprintf(file,"报头标长=%d(BYTE)\r\n",headerLen);
  fprintf(file,"服务类型=%s,%s\r\n", 

  parseServiceType_getProcedence(ip.ServiceType),
  parseServiceType_getTOS(ip.ServiceType));  
  fprintf(file,"总长度=%d(BYTE)\r\n",ip.TotalLen); 
  fprintf(file,"标识=%d\r\n",ip.ID);   
   BYTE DF,MF; 
  
   getFlags(ip.Flags,DF,MF); 
 
    fprintf(file,"标志 DF=%d,MF=%d\r\n",DF,MF); 
  WORD fragOff; 
  
   getFragOff(ip.FragOff,fragOff); 
 
  fprintf(file,"分段偏移值=%d\r\n",fragOff); 

  fprintf(file,"生存期=%d(hopes)\r\n",ip.TimeToLive);  
  fprintf(file,"协议=%s\r\n",getProtocol(ip.Protocol));  
  fprintf(file,"头校验和=0x%0x\r\n",ip.HdrChksum); 
  
   fprintf(file,"源IP地址=%s\r\n",inet_ntoa(*(in_addr*)&ip.SrcAddr)); 
  fprintf(file,"目的IP地址=%s\r\n",inet_ntoa(*(in_addr*)&ip.DstAddr)); 
  fprintf(file,"---------------------------------------------\r\n");

}  

//主程序开始 
int main() 
{
  int nRetCode = 0;
  {
   FILE * file;
  if((file=fopen("d:\\a.txt","wb+"))==NULL)
  {
    printf("fail to open file %s");
     return -1;
  }
  WSADATA wsData;/* 启动2.2版本的Socket,并将Socket版本信息保存到wsData中 */
  WSAStartup(MAKEWORD(2,2),&wsData);
  SOCKET sock;/* 创建原始套接字 */
  sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP);
  BOOL flag=TRUE;/* 设置IP头操作选项 */
  setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char*)&flag,sizeof(flag));
  char hostName[128];/* 获取本地主机名 */
  gethostname(hostName,100);
  hostent * pHostIP;/* 根据主机名获取主机信息 */
  pHostIP=gethostbyname(hostName);   /* 封装IP地址信息 */
  sockaddr_in addr_in;
  addr_in.sin_addr=*(in_addr*)pHostIP->h_addr_list[0];
  addr_in.sin_family=AF_INET;
  addr_in.sin_port=htons(6000);
  bind(sock,(PSOCKADDR)&addr_in,sizeof(addr_in));    
  DWORD dwValue=1;
  #define IO_RCVALL _WSAIOW(IOC_VENDOR,1)
  DWORD dwBufferLen[10];
  DWORD dwBufferInLen=1;
  DWORD dwBytesReturned=0;
  WSAIoctl(sock,IO_RCVALL,&dwBufferInLen,sizeof(dwBufferInLen),
      &dwBufferLen,sizeof(dwBufferLen),&dwBytesReturned,NULL,NULL);
  #define BUFFER_SIZE 65535
  char buffer[BUFFER_SIZE];
 
 printf("开始解析经过本机的IP数据包:\n");
   while(true)
  {
   /* 从套接字接收IP数据报 */
   int size=recv(sock,buffer,BUFFER_SIZE,0);
   if (size>0)
   {
    ipparse(stdout,buffer);
    ipparse(file,buffer);
   }
  }
 
  //关闭文件 
    fclose(file);
   return 0;
  }
 
 return nRetCode;

}