tracert 命令简化版本

在复杂的网络中,tracert命令工具是非常有用的检查工具,废话不多说直接上代码。

 

  1 /*
  2 * 开发者:一本正经.胡说八道
  3 */
  4 
  5 #include <io.h>
  6 #include <time.h>
  7 #include <stdio.h>
  8 #include <stdlib.h>
  9 #include <string.h>
 10 #include <fcntl.h>
 11 #include <sys/stat.h>
 12 #include <unistd.h>
 13 #include <tchar.h>
 14 #include <winsock2.h>
 15 #include <Windows.h>
 16 
 17 #define    IP_HDRINCL  2
 18 #define    ICMP_ECHO  8
 19 
 20 #ifndef CLOCK_REALTIME
 21 #define CLOCK_REALTIME              0
 22 #endif
 23 
 24 /* Windows doesn't have this, so declare it ourselves. */
 25 #ifndef _TIMESPEC_DEFINED
 26 #define _TIMESPEC_DEFINED
 27 struct timespec {
 28   time_t  tv_sec;   /* Seconds */
 29   long    tv_nsec;  /* Nanoseconds */
 30 };
 31 
 32 struct itimerspec {
 33   struct timespec  it_interval;  /* Timer period */
 34   struct timespec  it_value;     /* Timer expiration */
 35 };
 36 #endif
 37 
 38 typedef double u_sec; //microseconds
 39 typedef struct { 
 40   u_sec rtt;
 41   unsigned short ttl; 
 42   unsigned short seq_num; 
 43   unsigned short tot_len;
 44   char *saddr;
 45   char *icmp_reply;
 46 } ping;
 47 
 48 struct iphdr{
 49 #if 0
 50   /* IP header. */
 51   #if BYTE_ORDER == LITTLE_ENDIAN
 52     uint8_t     ip_hl:4,        /* header length */
 53           ip_v:4;        /* version */
 54 #elif BYTE_ORDER == BIG_ENDIAN
 55     uint8_t     ip_v:4,        /* version */
 56           ip_hl:4;        /* header length */
 57 #endif
 58 #endif
 59   uint8_t vhl;
 60   uint8_t tos;
 61   uint16_t len,
 62     ipid,
 63     ipoffset;
 64   uint8_t ttl,
 65     proto;
 66   uint16_t ipchksum;
 67   uint32_t srcipaddr,
 68     destipaddr;
 69 };
 70 
 71 struct icmphdr {
 72   uint8_t type, icode;
 73   uint16_t icmpchksum;
 74   uint16_t id, seqno;
 75   uint8_t payload[12];
 76 };
 77 
 78 int send_ping(const char * destination, unsigned short icmp_id, unsigned short icmp_seq_no, unsigned short ttl, ping *p);
 79 int in_cksum(unsigned short *addr, int len);
 80 
 81 char *ip4addr_ntoa(char* addr)
 82 {
 83     unsigned char x;
 84     static char b[3],buf[sizeof("255.255.255.255")];
 85     
 86     x = addr[0];
 87     strcpy(buf,_ultoa(x,b,10));
 88     x = addr[1];
 89     strcat(buf,".");
 90     strcat(buf,_ultoa(x,b,10));
 91     x = addr[2];
 92     strcat(buf,".");
 93     strcat(buf,_ultoa(x,b,10));
 94     x = addr[3];
 95     strcat(buf,".");
 96     strcat(buf,_ultoa(x,b,10));
 97     return buf;
 98 }
 99  
100 int main(int argc, char *argv[])
101 {
102   ping p;
103   unsigned short seq_no;
104 
105   srand ( time(NULL) );
106   unsigned short id = rand();
107   unsigned short ttl = 1;
108   
109   printf("argv[0]=%s|argv[1]=%s\n",argv[0],argv[1]);
110   
111   for(seq_no=1;seq_no <= 66;seq_no++) {
112     ttl = seq_no;
113     send_ping(argv[1], id, seq_no, ttl, &p);
114    
115     printf("%d bytes from %s: icmp_seq=%d, ttl=%d, time=%.1f ms\n", 
116        p.tot_len,
117        p.saddr,
118        p.seq_num,
119        p.ttl,
120        p.rtt
121        );
122 
123     usleep(1000);
124     //退出...
125     if(strcmp(argv[1],p.saddr)==0)break;
126   }
127 
128   return 0;
129 }
130 
131 #if 0
132 struct tcpip_hdr {
133   /* IP header. */
134   u8_t vhl,
135     tos;
136   u16_t len,
137     ipid,
138     ipoffset;
139   u8_t ttl,
140     proto;
141   u16_t ipchksum;
142   u16_t srcipaddr[2],
143     destipaddr[2];
144   
145   /* TCP header. */
146   u16_t srcport,
147     destport;
148   u8_t seqno[4],
149     ackno[4],
150     tcpoffset,
151     flags,
152     wnd[2];
153   u16_t tcpchksum;
154   u8_t urgp[2];
155   u8_t optdata[4];
156 };
157 
158 struct icmpip_hdr {
159   /* IP header. */
160   u8_t vhl,
161     tos,
162     len[2],
163     ipid[2],
164     ipoffset[2],
165     ttl,
166     proto;
167   u16_t ipchksum;
168   u16_t srcipaddr[2],
169     destipaddr[2];
170   /* ICMP (echo) header. */
171   u8_t type, icode;
172   u16_t icmpchksum;
173   u16_t id, seqno;
174   u8_t payload[1];
175 };
176 
177 /*
178  * Structure of an internet header, naked of options.
179  */
180 struct ip {
181 #if _BYTE_ORDER == _LITTLE_ENDIAN
182     u_int     ip_hl:4,        /* header length */
183           ip_v:4;        /* version */
184 #endif
185 #if _BYTE_ORDER == _BIG_ENDIAN
186     u_int     ip_v:4,        /* version */
187           ip_hl:4;        /* header length */
188 #endif
189     u_int8_t  ip_tos;        /* type of service */
190     u_int16_t ip_len;        /* total length */
191     u_int16_t ip_id;        /* identification */
192     u_int16_t ip_off;        /* fragment offset field */
193 #define    IP_RF 0x8000            /* reserved fragment flag */
194 #define    IP_DF 0x4000            /* dont fragment flag */
195 #define    IP_MF 0x2000            /* more fragments flag */
196 #define    IP_OFFMASK 0x1fff        /* mask for fragmenting bits */
197     u_int8_t  ip_ttl;        /* time to live */
198     u_int8_t  ip_p;            /* protocol */
199     u_int16_t ip_sum;        /* checksum */
200     struct      in_addr ip_src, ip_dst; /* source and dest address */
201 };
202 
203 #define    IP_MAXPACKET    65535        /* maximum packet size */
204 
205 /*
206  * Structure of an icmp header.
207  */
208 struct icmp {
209     u_int8_t  icmp_type;        /* type of message, see below */
210     u_int8_t  icmp_code;        /* type sub code */
211     u_int16_t icmp_cksum;        /* ones complement cksum of struct */
212     union {
213         u_int8_t  ih_pptr;    /* ICMP_PARAMPROB */
214         struct ih_exthdr {    /* RFC4884 extended header */
215             u_int8_t  iex_pad;
216             u_int8_t  iex_length;
217         } ih_exthdr;
218         struct in_addr ih_gwaddr;    /* ICMP_REDIRECT */
219         struct ih_idseq {
220               u_int16_t icd_id;
221               u_int16_t icd_seq;
222         } ih_idseq;
223         int32_t   ih_void;
224 
225         /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
226         struct ih_pmtu {
227               u_int16_t ipm_void;
228               u_int16_t ipm_nextmtu;
229         } ih_pmtu;
230 
231         struct ih_rtradv {
232             u_int8_t irt_num_addrs;
233             u_int8_t irt_wpa;
234             u_int16_t irt_lifetime;
235         } ih_rtradv;
236     } icmp_hun;
237 #define    icmp_pptr      icmp_hun.ih_pptr
238 #define    icmp_length      icmp_hun.ih_exthdr.iex_length
239 #define    icmp_gwaddr      icmp_hun.ih_gwaddr
240 #define    icmp_id          icmp_hun.ih_idseq.icd_id
241 #define    icmp_seq      icmp_hun.ih_idseq.icd_seq
242 #define    icmp_void      icmp_hun.ih_void
243 #define    icmp_pmvoid      icmp_hun.ih_pmtu.ipm_void
244 #define    icmp_nextmtu      icmp_hun.ih_pmtu.ipm_nextmtu
245 #define    icmp_num_addrs      icmp_hun.ih_rtradv.irt_num_addrs
246 #define    icmp_wpa      icmp_hun.ih_rtradv.irt_wpa
247 #define    icmp_lifetime      icmp_hun.ih_rtradv.irt_lifetime
248     union {
249         struct id_ts {
250               u_int32_t its_otime;
251               u_int32_t its_rtime;
252               u_int32_t its_ttime;
253         } id_ts;
254         struct id_ip  {
255               struct ip idi_ip;
256               /* options and then 64 bits of data */
257         } id_ip;
258         u_int32_t id_mask;
259         int8_t      id_data[1];
260     } icmp_dun;
261 #define    icmp_otime      icmp_dun.id_ts.its_otime
262 #define    icmp_rtime      icmp_dun.id_ts.its_rtime
263 #define    icmp_ttime      icmp_dun.id_ts.its_ttime
264 #define    icmp_ip          icmp_dun.id_ip.idi_ip
265 #define    icmp_mask      icmp_dun.id_mask
266 #define    icmp_data      icmp_dun.id_data
267 };
268 #endif
269 
270 int send_ping(const char * destination, unsigned short icmp_id, unsigned short icmp_seq_no, unsigned short ttl, ping *p)
271 {
272   int i,sock;
273   WSADATA wsa;
274   //src and dst
275   int nNetTimeout=10000;
276   uint32_t nsource = inet_addr("192.168.0.200");
277   uint32_t ndestination = inet_addr(destination);
278 
279   //round-trip time for one packet in ms
280   double rtt;
281   struct timespec ping_start, ping_end;
282 
283   //for packet
284   char *packet,buf[1024];
285   struct iphdr * ip_header; 
286   struct icmphdr * icmp_header;
287   
288     if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
289     {
290         printf("%s WSAStartup failed\n",destination);
291         return -1;
292     }
293 
294   srand ( time(NULL) );
295   //where do we send (yes, we have to provide dst twice, here and in ip_header)
296   struct sockaddr_in dst;
297   dst.sin_family = AF_INET;
298   dst.sin_addr.s_addr = ndestination;
299   //dst.sin_addr.S_un.S_addr = ndestination;
300 
301   //allocate memory for packet
302   packet = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
303   ip_header = (struct iphdr *) packet;
304   icmp_header = (struct icmphdr *) (packet + sizeof(struct iphdr));
305 
306    //ip header configuration, see http://tools.ietf.org/html/rfc791
307   //ip_header->ip_v = 4;
308   //ip_header->ip_hl = 5; //internet header length in byte
309   ip_header->vhl = 0x45;
310   ip_header->tos = 0;
311   ip_header->len = sizeof(struct iphdr) + sizeof(struct icmphdr); //total length
312   //printf("ip_header->len=%d\n",ip_header->len);
313   ip_header->ipid = rand();
314   ip_header->ipoffset = 0;
315   ip_header->ttl = ttl; 
316   ip_header->proto = IPPROTO_ICMP;
317   ip_header->ipchksum = 0;
318   ip_header->srcipaddr = nsource; //we don't need a source address - this is actually set automatically by the socket
319   ip_header->destipaddr = ndestination;
320 
321   ip_header->ipchksum = in_cksum((unsigned short *) ip_header, sizeof(struct iphdr));
322 
323   //set icmp header, see http://tools.ietf.org/html/rfc792
324   icmp_header->type = ICMP_ECHO; //type 8
325   icmp_header->icode = 0; //0 by default
326   icmp_header->icmpchksum = 0; //0 for computation
327   icmp_header->id = icmp_id; //funcions as "port number"
328   icmp_header->seqno = icmp_seq_no; //sequence number
329   strcpy(icmp_header->payload,"18659161633");//发送包数据
330 
331   icmp_header->icmpchksum = in_cksum((unsigned short *) icmp_header, sizeof(struct icmphdr));
332   
333   //create socket
334   if( (sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1 ) {
335     perror("Error opening socket");
336     exit(1);
337   }
338 
339   //do NOT automatically add an IP header; we already defined on
340   int is_header_included = 1; //do NOT include header
341   setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &is_header_included, sizeof(int));
342   //设置发送超时
343     setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int));
344     //设置接收超时
345     setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int));
346 
347   //send out
348   clock_gettime(CLOCK_REALTIME, &ping_start);
349   if( sendto(sock, packet, ip_header->len, 0, (struct sockaddr *) &dst, sizeof(dst)) == -1 ) {
350     perror("Sending icmp");
351     exit(1);
352   }
353   //printf("Send complete wait for receive\n");
354   //get reply; we write back to packet, so all pointers now point to the reply
355   /*if( recv(sock, packet, ip_header->len, 0) == -1 ) {
356   //if( recvfrom(sock, (char*) buf, 1024, 0, (struct sockaddr*) &dst,&i) < 0 ) {
357 
358     perror("Receiving answer");
359     exit(1);
360   }
361   //packet = buf;*/
362   while( recv(sock, packet, ip_header->len, 0) != -1 );
363   
364   clock_gettime(CLOCK_REALTIME, &ping_end);
365   rtt = (ping_end.tv_sec - ping_start.tv_sec) * 1000
366     + 
367     (ping_end.tv_nsec - ping_start.tv_nsec) / 1E6;
368 
369   //struct in_addr saddr = { ip_header->srcipaddr  };
370   p->seq_num = icmp_header->seqno;
371   p->ttl = ip_header->ttl;
372   p->rtt = rtt;
373   p->icmp_reply = packet;
374   p->tot_len = ntohs(ip_header->len);
375   p->saddr = ip4addr_ntoa(&ip_header->srcipaddr);//inet_ntoa(saddr);
376   
377   //关闭连接
378     shutdown(sock,2);
379     closesocket(sock);
380     WSACleanup();
381 
382   return 0;
383 }
384 
385 /*
386  * in_cksum --
387  *    Checksum routine for Internet Protocol family headers (C Version)
388  */
389 int in_cksum(unsigned short *addr, int len)
390 {
391     int nleft = len;
392     u_short *w = addr;
393     int sum = 0;
394     u_short answer = 0;
395 
396     /*
397      * Our algorithm is simple, using a 32 bit accumulator (sum), we add
398      * sequential 16 bit words to it, and at the end, fold back all the
399      * carry bits from the top 16 bits into the lower 16 bits.
400      */
401     while (nleft > 1) {
402         sum += *w++;
403         nleft -= 2;
404     }
405 
406     /* mop up an odd byte, if necessary */
407     if (nleft == 1) {
408         *(u_char *)(&answer) = *(u_char *)w ;
409         sum += answer;
410     }
411 
412     /* add back carry outs from top 16 bits to low 16 bits */
413     sum = (sum >> 16) + (sum & 0xffff);    /* add hi 16 to low 16 */
414     sum += (sum >> 16);            /* add carry */
415     answer = ~sum;                /* truncate to 16 bits */
416     return(answer);
417 }

 

 

 

 

 

 

附件下载地址 tracert

posted @ 2020-08-21 16:57  一本正经-胡说八道  阅读(319)  评论(0)    收藏  举报