微软ping命令的源代码

作者:Swords

代码:

--------------------------------------------------------------------------------

/******************************************************************************\

  • ping.c - Simple ping utility using SOCK_RAW
  • This is a part of the Microsoft Source Code Samples.
  • Copyright 1996-1997 Microsoft Corporation.
  • All rights reserved.
  • This source code is only intended as a supplement to
  • Microsoft Development Tools and/or WinHelp documentation.
  • See these sources for detailed information regarding the
  • Microsoft samples programs.
    \******************************************************************************/

#pragma pack(4)

#define WIN32_LEAN_AND_MEAN
#include

  1<winsock2.h>   
  2#include <stdio.h>   
  3#include <stdlib.h>
  4
  5#define ICMP_ECHO 8   
  6#define ICMP_ECHOREPLY 0 
  7
  8#define ICMP_MIN 8 // minimum 8 byte icmp packet (just header) 
  9
 10/* The IP header */   
 11typedef struct iphdr {   
 12unsigned int h_len:4; // length of the header   
 13unsigned int version:4; // Version of IP   
 14unsigned char tos; // Type of service   
 15unsigned short total_len; // total length of the packet   
 16unsigned short ident; // unique identifier   
 17unsigned short frag_and_flags; // flags   
 18unsigned char ttl;   
 19unsigned char proto; // protocol (TCP, UDP etc)   
 20unsigned short checksum; // IP checksum 
 21
 22unsigned int sourceIP;   
 23unsigned int destIP; 
 24
 25}IpHeader; 
 26
 27//   
 28// ICMP header   
 29//   
 30typedef struct _ihdr {   
 31BYTE i_type;   
 32BYTE i_code; /* type sub code */   
 33USHORT i_cksum;   
 34USHORT i_id;   
 35USHORT i_seq;   
 36/* This is not the std header, but we reserve space for time */   
 37ULONG timestamp;   
 38}IcmpHeader; 
 39
 40#define STATUS_FAILED 0xFFFF   
 41#define DEF_PACKET_SIZE 32   
 42#define MAX_PACKET 1024 
 43
 44#define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))   
 45#define xfree(p) HeapFree (GetProcessHeap(),0,(p)) 
 46
 47void fill_icmp_data(char *, int);   
 48USHORT checksum(USHORT *, int);   
 49void decode_resp(char *,int ,struct sockaddr_in *); 
 50
 51void Usage(char *progname){ 
 52
 53fprintf(stderr,"Usage:\n");   
 54fprintf(stderr,"%s <host> [data_size]\n",progname);   
 55fprintf(stderr,"datasize can be up to 1Kb\n");   
 56ExitProcess(STATUS_FAILED); 
 57
 58}   
 59int main(int argc, char **argv){ 
 60
 61WSADATA wsaData;   
 62SOCKET sockRaw;   
 63struct sockaddr_in dest,from;   
 64struct hostent * hp;   
 65int bread,datasize;   
 66int fromlen = sizeof(from);   
 67int timeout = 1000;   
 68char *dest_ip;   
 69char *icmp_data;   
 70char *recvbuf;   
 71unsigned int addr=0;   
 72USHORT seq_no = 0; 
 73
 74if (WSAStartup(MAKEWORD(2,1),&amp;wsaData) != 0){   
 75fprintf(stderr,"WSAStartup failed: %d\n",GetLastError());   
 76ExitProcess(STATUS_FAILED);   
 77} 
 78
 79if (argc &lt;2 ) {   
 80Usage(argv[0]);   
 81}   
 82sockRaw = WSASocket (AF_INET,   
 83SOCK_RAW,   
 84IPPROTO_ICMP,   
 85NULL, 0,0); 
 86
 87if (sockRaw == INVALID_SOCKET) {   
 88fprintf(stderr,"WSASocket() failed: %d\n",WSAGetLastError());   
 89ExitProcess(STATUS_FAILED);   
 90}   
 91bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&amp;timeout,   
 92sizeof(timeout));   
 93if(bread == SOCKET_ERROR) {   
 94fprintf(stderr,"failed to set recv timeout: %d\n",WSAGetLastError());   
 95ExitProcess(STATUS_FAILED);   
 96}   
 97timeout = 1000;   
 98bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&amp;timeout,   
 99sizeof(timeout));   
100if(bread == SOCKET_ERROR) {   
101fprintf(stderr,"failed to set send timeout: %d\n",WSAGetLastError());   
102ExitProcess(STATUS_FAILED);   
103}   
104memset(&amp;dest,0,sizeof(dest)); 
105
106hp = gethostbyname(argv[1]); 
107
108if (!hp){   
109addr = inet_addr(argv[1]);   
110}   
111if ((!hp) &amp;&amp; (addr == INADDR_NONE) ) {   
112fprintf(stderr,"Unable to resolve %s\n",argv[1]);   
113ExitProcess(STATUS_FAILED);   
114} 
115
116if (hp != NULL)   
117memcpy(&amp;(dest.sin_addr),hp-&gt;h_addr,hp-&gt;h_length);   
118else   
119dest.sin_addr.s_add = addr; 
120
121if (hp)   
122dest.sin_family = hp-&gt;h_addrtype;   
123else   
124dest.sin_family = AF_INET; 
125
126dest_ip = inet_ntoa(dest.sin_addr); 
127
128if (argc &gt;2) {   
129datasize = atoi(argv[2]);   
130if (datasize == 0)   
131datasize = DEF_PACKET_SIZE; 
132
133}   
134else   
135datasize = DEF_PACKET_SIZE; 
136
137datasize += sizeof(IcmpHeader); 
138
139icmp_data = xmalloc(MAX_PACKET);   
140recvbuf = xmalloc(MAX_PACKET); 
141
142if (!icmp_data) {   
143fprintf(stderr,"HeapAlloc failed %d\n",GetLastError());   
144ExitProcess(STATUS_FAILED);   
145} 
146
147  
148memset(icmp_data,0,MAX_PACKET);   
149fill_icmp_data(icmp_data,datasize); 
150
151while(1) {   
152int bwrote; 
153
154((IcmpHeader*)icmp_data)-&gt;i_cksum = 0;   
155((IcmpHeader*)icmp_data)-&gt;timestamp = GetTickCount(); 
156
157((IcmpHeader*)icmp_data)-&gt;i_seq = seq_no++;   
158((IcmpHeader*)icmp_data)-&gt;i_cksum = checksum((USHORT*)icmp_data,   
159datasize); 
160
161bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&amp;dest,   
162sizeof(dest));   
163if (bwrote == SOCKET_ERROR){   
164if (WSAGetLastError() == WSAETIMEDOUT) {   
165printf("timed out\n");   
166continue;   
167}   
168fprintf(stderr,"sendto failed: %d\n",WSAGetLastError());   
169ExitProcess(STATUS_FAILED);   
170}   
171if (bwrote &lt; datasize ) {   
172fprintf(stdout,"Wrote %d bytes\n",bwrote);   
173}   
174bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&amp;from,   
175&amp;fromlen);   
176if (bread == SOCKET_ERROR){   
177if (WSAGetLastError() == WSAETIMEDOUT) {   
178printf("timed out\n");   
179continue;   
180}   
181fprintf(stderr,"recvfrom failed: %d\n",WSAGetLastError());   
182ExitProcess(STATUS_FAILED);   
183}   
184decode_resp(recvbuf,bread,&amp;from);   
185Sleep(1000); 
186
187}   
188return 0; 
189
190}   
191/*   
192The response is an IP packet. We must decode the IP header to locate   
193the ICMP data   
194*/   
195void decode_resp(char *buf, int bytes,struct sockaddr_in *from) { 
196
197IpHeader *iphdr;   
198IcmpHeader *icmphdr;   
199unsigned short iphdrlen; 
200
201iphdr = (IpHeader *)buf; 
202
203iphdrlen = iphdr-&gt;h_len * 4 ; // number of 32-bit words *4 = bytes 
204
205if (bytes &lt; iphdrlen + ICMP_MIN) {   
206printf("Too few bytes from %s\n",inet_ntoa(from-&gt;sin_addr));   
207} 
208
209icmphdr = (IcmpHeader*)(buf + iphdrlen); 
210
211if (icmphdr-&gt;i_type != ICMP_ECHOREPLY) {   
212fprintf(stderr,"non-echo type %d recvd\n",icmphdr-&gt;i_type);   
213return;   
214}   
215if (icmphdr-&gt;i_id != (USHORT)GetCurrentProcessId()) {   
216fprintf(stderr,"someone else's packet!\n");   
217return ;   
218}   
219printf("%d bytes from %s:",bytes, inet_ntoa(from-&gt;sin_addr));   
220printf(" icmp_seq = %d. ",icmphdr-&gt;i_seq);   
221printf(" time: %d ms ",GetTickCount()-icmphdr-&gt;timestamp);   
222printf("\n"); 
223
224} 
225
226  
227USHORT checksum(USHORT *buffer, int size) { 
228
229unsigned long cksum=0; 
230
231while(size &gt;1) {   
232cksum+=*buffer++;   
233size -=sizeof(USHORT);   
234} 
235
236if(size ) {   
237cksum += *(UCHAR*)buffer;   
238} 
239
240cksum = (cksum &gt;&gt; 16) + (cksum &amp; 0xffff);   
241cksum += (cksum &gt;&gt;16);   
242return (USHORT)(~cksum);   
243}   
244/*   
245Helper function to fill in various stuff in our ICMP request.   
246*/   
247void fill_icmp_data(char * icmp_data, int datasize){ 
248
249IcmpHeader *icmp_hdr;   
250char *datapart; 
251
252icmp_hdr = (IcmpHeader*)icmp_data; 
253
254icmp_hdr-&gt;i_type = ICMP_ECHO;   
255icmp_hdr-&gt;i_code = 0;   
256icmp_hdr-&gt;i_id = (USHORT)GetCurrentProcessId();   
257icmp_hdr-&gt;i_cksum = 0;   
258icmp_hdr-&gt;i_seq = 0; 
259
260datapart = icmp_data + sizeof(IcmpHeader);   
261//   
262// Place some junk in the buffer.   
263//   
264memset(datapart,'E', datasize - sizeof(IcmpHeader)); 
265
266}</host></stdlib.h></stdio.h></winsock2.h>
Published At
Categories with 网络技术
Tagged with
comments powered by Disqus