天天看点

[绝冬城]Sniff C++实现源码解析

// 定义各种结构体

typedef struct _PROTN2T

{

    int  proto ;

    char *pprototext ;

}PROTN2T ;

#define PROTO_NUM  11

typedef struct _IPHEADER {

        unsigned char  header_len:4;

        unsigned char  version:4;  

        unsigned char  tos;            // type of service

        unsigned short total_len;      // length of the packet

        unsigned short ident;          // unique identifier

        unsigned short flags;         

        unsigned char  ttl;           

        unsigned char  proto;          // protocol ( IP , TCP, UDP etc)

        unsigned short checksum;      

        unsigned int   sourceIP;

        unsigned int   destIP;

}IPHEADER;

#define UDP_HEAD_LEN 8  

#define PSEUDO_HEAD_LEN 12 

#define ICMP_HEAD_LEN 4 

struct TCPPacketHead {

    WORD SourPort;

    WORD DestPort;

    DWORD SeqNo;

    DWORD AckNo;

    BYTE HLen;

    BYTE Flag;

    WORD WndSize;

    WORD ChkSum;

    WORD UrgPtr;

};

struct ICMPPacketHead {

    BYTE Type;

    BYTE Code;

    WORD ChkSum;

};

struct UDPPacketHead {

    WORD SourPort;

    WORD DestPort;

    WORD Len;

    WORD ChkSum;

};

//定义成员变量

    DWORD  m_ipsource     ; //本机IP地址 (IN_ADDR)

    DWORD  m_iphostsource ; // same IP in host format

    DWORD  m_iphost;

    DWORD  m_ipcheckedhost;

    SOCKET m_s            ;

    DWORD  m_threadID     ;

    BOOL   m_Multihomed   ;

    BOOL   m_Local        ;

    CDWordArray m_IPArr   ; //IP队列

    friend UINT threadFunc ( LPVOID p ) ;

typedef struct _PROTN2T

{

    int  proto ;

    char *pprototext ;

}PROTN2T ;

#define PROTO_NUM  11

typedef struct _IPHEADER {

        unsigned char  header_len:4;

        unsigned char  version:4;  

        unsigned char  tos;            // type of service

        unsigned short total_len;      // length of the packet

        unsigned short ident;          // unique identifier

        unsigned short flags;         

        unsigned char  ttl;           

        unsigned char  proto;          // protocol ( IP , TCP, UDP etc)

        unsigned short checksum;      

        unsigned int   sourceIP;

        unsigned int   destIP;

}IPHEADER;

#define UDP_HEAD_LEN 8  

#define PSEUDO_HEAD_LEN 12 

#define ICMP_HEAD_LEN 4 

struct TCPPacketHead {

    WORD SourPort;

    WORD DestPort;

    DWORD SeqNo;

    DWORD AckNo;

    BYTE HLen;

    BYTE Flag;

    WORD WndSize;

    WORD ChkSum;

    WORD UrgPtr;

};

struct ICMPPacketHead {

    BYTE Type;

    BYTE Code;

    WORD ChkSum;

};

struct UDPPacketHead {

    WORD SourPort;

    WORD DestPort;

    WORD Len;

    WORD ChkSum;

};

//初始化代码

BOOL CIpmonDlg::OnInitDialog()

{

    CDialog::OnInitDialog();

    CHAR       szHostName[128] = {0};  //主机名

    HOSTENT*   pHost = NULL;           //主机HOSTENT信息

    CHAR*      pszIp = NULL;

    int        iNum = 0;

    if(AfxSocketInit(NULL)==FALSE)  //初始化socket

    {

       AfxMessageBox("Sorry, socket load error!");

       return FALSE;

    }

    if(gethostname(szHostName, 128)==0) //获取主机名

    {     

       pHost = gethostbyname(szHostName); //通过主机名获取主机网络信息

       if(pHost != NULL)

       {

              pszIp = inet_ntoa(*(in_addr*)pHost->h_addr_list[iNum]);

              m_ipsource = inet_addr(pszIp);

              // inet_addr 用途和 inet_ntoa 相反

       }

       else AfxMessageBox("pHost = NULL!");

    }

    else AfxMessageBox("can't find host name!");

    //  ListView initialize

    DWORD dwStyle=GetWindowLong(m_ctrList.GetSafeHwnd(),GWL_STYLE);

    dwStyle&=~LVS_TYPEMASK;

    dwStyle|=LVS_REPORT;

    SetWindowLong(m_ctrList.GetSafeHwnd(),GWL_STYLE,dwStyle);

    m_ctrList.InsertColumn(0,"数据",LVCFMT_LEFT,525);

    m_ctrList.InsertColumn(0,"大小",LVCFMT_LEFT,80);

    m_ctrList.InsertColumn(0,"端口",LVCFMT_LEFT,40);

    m_ctrList.InsertColumn(0,"目的地址",LVCFMT_LEFT,100);

    m_ctrList.InsertColumn(0,"端口",LVCFMT_LEFT,40);

    m_ctrList.InsertColumn(0,"源地址",LVCFMT_LEFT,100);

    m_ctrList.InsertColumn(0,"协议",LVCFMT_LEFT,50);

    ::SendMessage(m_ctrList.m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE,

       LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);

    // 读取本机所有IP地址

    DWORD dwSize = 0 ;

    GetIpAddrTable( NULL , &dwSize, FALSE ) ; //IPhelper中的函数

    PMIB_IPADDRTABLE pIpAddrTable = (PMIB_IPADDRTABLE )new BYTE [ dwSize ] ;

    if( pIpAddrTable )

    {

       if( GetIpAddrTable( (PMIB_IPADDRTABLE)pIpAddrTable,   // // buffer for IP table

                         &dwSize,                // size of buffer

                         FALSE                  // sort by IP address

                         ) == NO_ERROR )

       {

           if(  pIpAddrTable->dwNumEntries > 2 ) // Second is MS TCP loopback IP ( 127.0.0.1 )

           { //如果IP地址大于2

              m_Multihomed = TRUE ;

              char szIP[16];

              for( int i = 0 ; i < (int)pIpAddrTable->dwNumEntries ; i++ )

              {  //逐个读出IP地址

                  in_addr ina ;

                  ina.S_un.S_addr = pIpAddrTable->table[i].dwAddr ;

                  char *pIP = inet_ntoa( ina ) ;

                  strcpy( szIP , pIP ) ;

                  if( stricmp( szIP , "127.0.0.1" ) ) //与127.0.0.1做对比

                     m_IPArr.Add(pIpAddrTable->table[i].dwAddr) ; //存储入CDWORDARRAY队列

              }

           }

       }

       delete [] pIpAddrTable ;

    }

    return TRUE;  // return TRUE  unles

}

void CIpmonDlg::OnLookUp()  //点击查看按钮

{

    // TODO: Add your control notification handler code here

    char        szErr [ 50 ] , szHostName[MAX_PATH];

    DWORD       dwErr ;

    SOCKADDR_IN sa;

    gethostname(szHostName, sizeof(szHostName)) ;  //获取本机名

    m_iphostsource = m_ipsource ;  //赋值本机ip地址(IN_ADDR)

    m_ipcheckedhost = ntohl(m_iphost) ;

       if( 0 == m_threadID )

       {

           SetDlgItemText(IDC_LOOKUP,"停止查看!" );

       }

       else

       {

           if( m_threadID )

           {

                PostThreadMessage(m_threadID,WM_CLOSE,0,0) ;

               SetDlgItemText(IDC_LOOKUP,"开始查看!");

              m_start.EnableWindow(FALSE) ;

           }

           return ;

       }

        DWORD dwBufferLen[10] ;

       DWORD dwBufferInLen= 1 ;

       DWORD dwBytesReturned = 0 ;

       m_s = socket( AF_INET , SOCK_RAW , IPPROTO_IP ) ;

       if( INVALID_SOCKET == m_s )

       {

           dwErr = WSAGetLastError() ;

           sprintf( szErr , "Error socket() = %ld " , dwErr ) ;

           AfxMessageBox( szErr ) ;

           closesocket( m_s ) ;

           return ;

       }

       int rcvtimeo = 5000 ; //套接字超时选项

       //设置超时

        if( setsockopt( m_s , SOL_SOCKET , SO_RCVTIMEO , (const char *)&rcvtimeo ,

                        sizeof(rcvtimeo) ) == SOCKET_ERROR)

       {

           dwErr = WSAGetLastError() ;

           sprintf( szErr , "Error WSAIoctl = %ld " , dwErr ) ;

           AfxMessageBox( szErr ) ;

           closesocket( m_s ) ;

           return ;

       }

       sa.sin_family = AF_INET;

       sa.sin_port = htons(7000);

       //htons  converts a u_short from host to TCP/IP network byte order

       sa.sin_addr.s_addr= m_iphostsource;   //设置好一个SOCKADDR_IN

        if (bind(m_s,(PSOCKADDR)&sa, sizeof(sa)) == SOCKET_ERROR)

       {

           dwErr = WSAGetLastError() ;

           sprintf( szErr , "Error bind() = %ld " , dwErr ) ;

           AfxMessageBox( szErr ) ;

           closesocket( m_s ) ;

           return ;

       }

        if( SOCKET_ERROR != WSAIoctl( m_s, SIO_RCVALL , &dwBufferInLen, sizeof(dwBufferInLen),            

                                      &dwBufferLen, sizeof(dwBufferLen),

                                  &dwBytesReturned , NULL , NULL ) )

            AfxBeginThread( threadFunc , (LPVOID)this );

       else

       {

           dwErr = WSAGetLastError() ;

           sprintf( szErr , "Error WSAIoctl = %ld " , dwErr ) ;

           AfxMessageBox( szErr ) ;

           closesocket( m_s ) ;

            return ;

       }

}

UINT threadFunc ( LPVOID p )

{

    CIpmonDlg *pDlg = static_cast<CIpmonDlg *>(p) ;

    char  buf [1000] , *bufwork ;

    MSG   msg ;

    int   iRet ;

    DWORD dwErr ;

    char  *pSource , *pDest ;

    IPHEADER *pIpHeader ;

    in_addr ina ;

    char   szSource [16] , szDest[16] , szErr [ 50 ];

    char *pLastBuf = NULL ;

    int    HdrLen, totallen;

    WORD   sourport, destport;

    struct TCPPacketHead *pTCPHead;

    struct ICMPPacketHead    *pICMPHead;

    struct UDPPacketHead *pUDPHead;

    BYTE                 *pdata = NULL;

    PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)  ; // Force to make the queue

    pDlg->m_threadID = GetCurrentThreadId() ;

    while( TRUE )

    {

        //检测队列中是否有WM_CLOSE消息

        if( PeekMessage( &msg , 0 , WM_CLOSE,WM_CLOSE,PM_NOREMOVE ) )

       {

            closesocket( pDlg->m_s ) ;

            pDlg->m_threadID = 0 ;

           pDlg->m_start.EnableWindow(TRUE) ;

           break ;

       }

       memset( buf , 0 , sizeof(buf) ) ;

       iRet =     recv( pDlg->m_s , buf , sizeof( buf ) , 0 ) ;//接收至buf

       if( iRet == SOCKET_ERROR )

       {

           dwErr = WSAGetLastError() ;

           sprintf( szErr , "Error recv() = %ld " , dwErr ) ;

           continue ;

       }

       else

           if( *buf )

           {  

              bufwork   = buf ;

               pIpHeader = (IPHEADER *)bufwork ; //强制转换为IPHEADER结构

                WORD iLen = ntohs(pIpHeader->total_len) ; //包的长度

                //The ntohs function converts a u_short

                //from TCP/IP network byte order to host byte order

              while( TRUE )

              {

                  if( iLen <= iRet ) //iRet为返回的包的长度

                  {

                         ina.S_un.S_addr = pIpHeader->sourceIP ; //开始设置in_addr

                             //SourceIP为源IP地址

                         pSource = inet_ntoa( ina ) ; //char  *pSource , *pDest ;

                         strcpy( szSource , pSource ) ;

                         //char   szSource [16] , szDest[16] , szErr [ 50 ];

                         ina.S_un.S_addr = pIpHeader->destIP ; //目的 IP地址

                         pDest = inet_ntoa( ina ) ;

                         strcpy( szDest , pDest ) ;

                         CString str, strProto, strSourPort, strDestPort, strData, strSize;

                         strProto = get_proto_name( pIpHeader->proto );

                         HdrLen = pIpHeader->header_len&0xf;

                         HdrLen *= 4;

                         totallen = ntohs(pIpHeader->total_len);

                         totallen-=HdrLen;

                         switch(pIpHeader->proto) //switch 各种协议

                         {

                         case IPPROTO_ICMP:

                            {

                                pICMPHead=(struct ICMPPacketHead *)(buf+HdrLen);

                                //strL4.Format(" type:%d code:%d/n",pICMPHead->Type,pICMPHead->Code);

                                strSourPort = "-";

                                strDestPort = "-";

                                pdata=((BYTE *)pICMPHead)+ICMP_HEAD_LEN;

                                totallen -= ICMP_HEAD_LEN;

                                break;

                            }

                         case IPPROTO_TCP:

                            {

                                pTCPHead=(struct TCPPacketHead *)(buf+HdrLen);

                                sourport = ntohs(pTCPHead->SourPort);

                                destport = ntohs(pTCPHead->DestPort);

                                //strL4.Format(" sour port:%d,dest port:%d",sourport,destport);

                                strSourPort.Format("%d",sourport);

                                strDestPort.Format("%d",destport);

                                HdrLen = (pTCPHead->HLen)>>4;  //in fact only 4 bits

                                HdrLen *= 4;

                                pdata=((BYTE *)pTCPHead)+HdrLen;

                                totallen -= HdrLen;

                                break;

                            }

                         case IPPROTO_UDP:

                            {

                                pUDPHead=(struct UDPPacketHead *)(buf+HdrLen);

                                sourport = ntohs(pUDPHead->SourPort);

                                destport = ntohs(pUDPHead->DestPort);

                                //strL4.Format(" sour port:%d,dest port:%d",sourport,destport);

                                strSourPort.Format("%d",sourport);

                                strDestPort.Format("%d",destport);

                                pdata=((BYTE *)pUDPHead)+UDP_HEAD_LEN;

                                totallen -= UDP_HEAD_LEN;

                                break;

                            }

                         }

                         if(pIpHeader->proto == IPPROTO_ICMP)

                            strData.Format("type:%d code:%d data:%s",pICMPHead->Type,pICMPHead->Code,pdata);

                         else strData.Format("  %s",pdata);

                         strSize.Format("%d",totallen);

                         pDlg->AddData(strProto,szSource,strSourPort,szDest,strDestPort,strSize,strData);

                     if( iLen < iRet )

                     {

                         iRet -= iLen ;

                         bufwork  += iLen ;

                          pIpHeader = (IPHEADER *)bufwork ;

                     }

                     else

                         break ; // pIpHeader->total_len == iRet and go out

                  }

                  else

                  { // read last part of buf. I wrote it , but always recv() read exactly

                      // the lenght of the packet

                     int iLast = iLen - iRet ;

                     pLastBuf = new char [ iLen ] ;

                     int iReaden = iRet ;

                     memcpy( pLastBuf , bufwork , iReaden ) ;

                     iRet =     recv( pDlg->m_s , pLastBuf + iReaden , iLast , 0 ) ;

                     if( iRet == SOCKET_ERROR )

                     {

                         dwErr = WSAGetLastError() ;

                         sprintf( szErr , "Error recv() = %ld " , dwErr ) ;

                         break ;

                     }

                     else

                     {

                         bufwork = pLastBuf ;

                         pIpHeader = (IPHEADER *)bufwork ;

                         if( iRet == iLast )

                            iRet = iLen ;

                         else

                         { // read all last data

                            iReaden += iRet ;

                            iLast -= iRet ;

                            while( TRUE )

                            {

                                iRet = recv( pDlg->m_s , pLastBuf +iReaden , iLast , 0 ) ;

                                if( iRet == SOCKET_ERROR )

                                {

                                   dwErr = WSAGetLastError() ;

                                   sprintf( szErr , "Error recv() = %ld " , dwErr ) ;

                                   break ;

                                }

                                else

                                {

                                    iReaden += iRet ;

                                    iLast -= iRet ;

                                    if( iLast <= 0 )

                                       break ;

                                }  

                            } // while

                         }

                     }

                  }  

              }   // while

              if( pLastBuf )

                  delete [ ] pLastBuf ;

           }

           else

           {

              AfxMessageBox( "No data on network" ) ;

              continue ;

           }

    }

    return TRUE ;

}

void CIpmonDlg::OnOK()

{

    // TODO: Add extra validation here

    if( NULL != m_threadID )

        PostThreadMessage(m_threadID,WM_CLOSE,0,0) ;

    if( m_IPArr.GetSize() )

        m_IPArr.RemoveAll() ;

    CDialog::OnOK();

}

void CIpmonDlg::AddData(CString s0,CString s1, CString s2, CString s3, CString s4, CString s5, CString s6)

{

    int index;

    index = m_ctrList.InsertItem(0,s0);

    m_ctrList.SetItem(index,1,LVIF_TEXT,s1, 0, 0, 0,0);

    m_ctrList.SetItem(index,2,LVIF_TEXT,s2, 0, 0, 0,0);

    m_ctrList.SetItem(index,3,LVIF_TEXT,s3, 0, 0, 0,0);

    m_ctrList.SetItem(index,4,LVIF_TEXT,s4, 0, 0, 0,0);

    m_ctrList.SetItem(index,5,LVIF_TEXT,s5, 0, 0, 0,0);

    m_ctrList.SetItem(index,6,LVIF_TEXT,s6, 0, 0, 0,0);

}

继续阅读