1 #include "winsock2.h" 2 #include "stdio.h" 3 4 #pragma comment( lib, "Ws2_32.lib" ) 5 6 int Init_WsaData (void) 7 { 8 WSADATA wsaData; 9 //WSAStartup (WORD wVersionRequested, LPWSADATA lpWSAData) 10 //The WSAStartup function initiates use of WS2_32.DLL by a process 11 //Success Return 0 12 if (WSAStartup (MAKEWORD (2, 2), &wsaData) == 0) 13 return 0; 14 else 15 return WSAGetLastError (); 16 17 } 18 19 20 typedef struct _IPHeader // 20×Ö½ÚµÄIPÍ· 21 { 22 UCHAR iphVerLen; // °æ±¾ºÅºÍÍ·³¤¶È£¨¸÷Õ¼4룩 23 UCHAR ipTOS; // ·þÎñÀàÐÍ 24 USHORT ipLength; // ·â°ü×ܳ¤¶È£¬¼´Õû¸öIP±¨µÄ³¤¶È 25 USHORT ipID; // ·â°ü±êʶ£¬Î©Ò»±êʶ·¢Ë͵Äÿһ¸öÊý¾Ý±¨ 26 USHORT ipFlags; // ±êÖ¾ 27 UCHAR ipTTL; // Éú´æʱ¼ä£¬¾ÍÊÇTTL 28 UCHAR ipProtocol; // ÐÒ飬¿ÉÄÜÊÇTCP¡¢UDP¡¢ICMPµÈ 29 USHORT ipChecksum; // УÑéºÍ 30 ULONG ipSource; // Ô´IPµØÖ· 31 ULONG ipDestination; // Ä¿±êIPµØÖ· 32 } IPHeader, *PIPHeader; 33 34 35 typedef struct _ICMP_HDR 36 { 37 UCHAR icmp_type; //1byte 38 USHORT icmp_check; //2byte 39 UCHAR icmp_code; //1byte 40 //echo header 41 USHORT icmp_id; //2byte 42 USHORT icmp_sequence; //2byte 43 ULONG icmp_timestamp; //8byte 44 }ICMP_HDR, *PICMP_HDR; 45 46 BOOL SetTimeout ( SOCKET s, int nTime, BOOL bRecv ) 47 { 48 int ret = ::setsockopt(s, SOL_SOCKET, 49 bRecv ? SO_RCVTIMEO : SO_SNDTIMEO, (char*)&nTime, sizeof(nTime)); 50 return ret != SOCKET_ERROR; 51 } 52 53 USHORT CheckSum ( UCHAR *buff, int nLen ) 54 { 55 UINT nSum = 0; 56 INT i = 0; 57 58 while ( nLen > 1 ) 59 { 60 nSum = nSum + ( ( buff[i] << 8 ) & 0xFF00 ) + ( buff[i + 1] & 0xFF ); 61 nLen -= 2; 62 i += 2; 63 } 64 if ( nLen ) 65 { 66 nSum = nSum + ( buff[i] | 0xFF00 ); 67 } 68 69 nSum = ( nSum >> 16 ) + ( nSum & 0x00FF ); 70 71 return (USHORT)(~nSum); 72 } 73 74 int main ( void ) 75 { 76 char szDestIp [10]; 77 printf ( " The Destination Ip: " ); 78 gets ( szDestIp ); 79 80 if ( Init_WsaData () != 0 ) 81 return 0; 82 //Create SOCK_RAW 83 SOCKET sRaw = ::socket ( AF_INET, SOCK_RAW, IPPROTO_ICMP ); 84 85 //ÉèÖýÓÊÕ³¬Ê± 86 SetTimeout ( sRaw, 1000, TRUE ); 87 88 89 SOCKADDR_IN dest; 90 dest.sin_family = AF_INET; 91 dest.sin_port = htons ( 4567 ); 92 dest.sin_addr.S_un.S_addr = inet_addr ( szDestIp ); 93 94 //´´½¨ICMP·â°ü ICMPÍ· + ÄÚÈÝ 95 char buff [sizeof (ICMP_HDR) + 32]; //header 16bytes + 32bytes ÄÚÈÝ 96 97 ICMP_HDR *pIcmp = (ICMP_HDR *)buff; 98 99 pIcmp->icmp_type = 8; //ÇëÇó»ØÏÔ 100 pIcmp->icmp_code = 0; 101 102 //»ØÏÔÍ·²¿ 103 pIcmp->icmp_id = (USHORT)::GetCurrentProcessId (); 104 pIcmp->icmp_check = 0; 105 pIcmp->icmp_sequence = 0; 106 107 //Ìî³äÊý¾Ý 108 // dest 109 // Pointer to destination. 110 // c 111 // Character to set. 112 // count 113 // Number of characters. 114 memset ( &buff[sizeof (ICMP_HDR)], 'E', 32 ); 115 116 USHORT nSeq = 0; 117 char recvBuf[1024]; 118 SOCKADDR_IN from; 119 int nLen = sizeof (from); 120 121 122 while ( TRUE ) 123 { 124 static int nCount = 0; 125 int nRet; 126 if ( nCount++ == 4 ) 127 break; 128 pIcmp->icmp_check = 0; 129 pIcmp->icmp_timestamp = ::GetTickCount (); 130 pIcmp->icmp_sequence = nSeq++; 131 pIcmp->icmp_check = CheckSum ( (unsigned char *)buff, sizeof ( ICMP_HDR ) + 32 ); 132 nRet = ::sendto ( sRaw, buff, sizeof ( ICMP_HDR ) + 32, 0, (SOCKADDR *)&dest, sizeof (dest) ); 133 if ( nRet == SOCKET_ERROR ) 134 { 135 printf ( " Error At sendto () : %d\n", WSAGetLastError () ); 136 return -1; 137 } 138 139 nRet = ::recvfrom ( sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen ); 140 if ( nRet == SOCKET_ERROR ) 141 { 142 if ( ::WSAGetLastError () == WSAETIMEDOUT ) 143 { 144 printf ( "timed out\n" ); 145 continue; 146 } 147 printf ( "Error At recvfrom (): %d\n", ::WSAGetLastError () ); 148 return -1; 149 } 150 151 int nTick = ::GetTickCount (); 152 if ( nRet < sizeof (IPHeader) + sizeof (ICMP_HDR) ) 153 // if ( nRet < sizeof (ICMP_HDR) ) 154 { 155 printf ( "Too few bytes from %s\n", ::inet_ntoa (from.sin_addr) ); 156 } 157 ICMP_HDR *pRecvIcmp = ( ICMP_HDR * )( recvBuf + sizeof ( IPHeader ) ); 158 if ( pRecvIcmp->icmp_type != 0 ) 159 { 160 printf ( "Echo Error %d\n", pRecvIcmp->icmp_type ); 161 return -1; 162 } 163 if ( pRecvIcmp->icmp_id != ::GetCurrentProcessId () ) 164 { 165 printf ( "someone else's packet!\n" ); 166 return -1; 167 } 168 169 printf ( "%d bytes from %s: ", nRet, inet_ntoa (from.sin_addr) ); 170 printf ( "icmp_seq = %d.", pRecvIcmp->icmp_sequence ); 171 printf ( "time: %d ms", nTick - pRecvIcmp->icmp_timestamp ); 172 printf ( "\n" ); 173 ::Sleep (1000); 174 } 175 176 return 0; 177 }
我构建了ICMP封包,通过原始套接字,实现ping功能,我试着ping我所在的网关,但得到的信息不是我想要的,不知道是ICMP包头上的IP包头错误,还是什么..