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
Serious. Nonsense

浙公网安备 33010602011771号