Today's small series will give you to share my graduate students at the Northeastern University learned about the implementation of the route tracking, I hope that you read the small part of this blog post can be under the windows of the TRACERT command to have a certain understanding.
1. Experimental purpose
Tracert (Trace routing) is a route trace utility that determines the path taken by the IP datagram access target. The Tracert command uses the IP time-to-Live (TTL) field and the ICMP error message to determine the route from one host to another host on the network.
2. Experimental environment
A computer with access to the extranet and a connected network.
3. Experimental content and requirements
Windows system Environment
CMD command tracert www.baidu.com
4. Principle of experiment
By sending an Internet Control Message Protocol (ICMP) response packet with a different IP time-to-live (TTL) value to the target, the Tracert diagnostics determines the route taken to the destination. Each router on the path is required to decrement at least 1 of the TTL on the packet before forwarding the packet. The TTL on the packet is reduced to 0 o'clock, and the router should send the "ICMP timed out" message back to the source system.
The Tracert sends a response packet with a TTL of 1 and increments the TTL by 1 for each subsequent send process until the target response or TTL reaches the maximum value to determine the route. The route is determined by checking the "ICMP timed out" message sent back by the intermediate router. Some routers discard TTL-expired packets without asking directly, which is not visible in the Tracert utility.
The Tracert command prints the list of near-end router interfaces in the path that returns the "ICMP timed out" message in order. If you use the-D option, the Tracert utility does not query DNS on each IP address.
5. Detection mode
Tracert is a common command-line tool under Windows, and it corresponds to traceroute under UNIX. If you want to know how many routers your computer has passed to Www.aorb. org, you can enter tracert www.aorb at the command line. Org for probing, the return result may be the same as ping-r, but it is implemented in another way. Instead of using the options field of the IP protocol package in the record route options probe technology, this approach takes advantage of the TTL field in the IP protocol package.
The basic idea is this: www.aorb. org This server sells eggplant (provides HTTP service), also sells cucumbers (FTP service provided), but does not sell potatoes (UDP ports not listening). A buyer, in order to know a letter arrived at the vegetable supplier Www.aorb. The org needs to pass through several post offices (routers), so write to Www.aorb. Org asks for the price of potatoes.
In the first step, the buyer writes the number 1 in the TTL position of the envelope, when the letter arrives at the first post office adjacent to itself, the post office of the person to the TTL value minus 1, so the TTL is 0, the Post Office Regulations, the TTL value of 0 of the letter was thrown into the dustbin, and then sent to the buyer a letter called the time-out, the letter wrote the letter lost the post office name, To tell the buyer who lost the letter.
In the second step, the buyer writes the number 2 at the TTL of the envelope, and when the letter arrives at the first post office adjacent to itself, the Post Office person decrements the TTL value by 1, now the TTL value is 1, and the Post Office Regulation stipulates that a datagram with a TTL value of not 0 will need to be forwarded to the next post office. When the next post office received this letter, the Post Office people to the TTL value minus 1, so the TTL is 0, the Post Office regulations, the letter of the TTL value of 0 is thrown into the dustbin, and then sent to the buyer a letter of the name of the time-out, the letter wrote the name of the post office to tell the buyer who lost the letter
Through the first step, the buyer knew the first relay router. Through the second step, the buyer knows the second relay router. Then the buyer only need to constantly add the TTL value of 1, you can according to the above steps to detect which routers in the middle.
In the third step, we assume that only two post office letters will arrive at the destination in the middle. Next, the buyer chose to set the TTL value to 3, when the letter arrives at the first post office adjacent to itself, the post Office people to the TTL value minus 1, now the TTL value of 2, the Post Office regulation, the TTL value of not 0 of the datagram needs to continue to forward to the next post office, so this letter was forwarded to the next post office When the next post office received this letter, the Post Office people to the TTL value minus 1, so the TTL is 1, the Post Office regulation, the TTL value of not 0 of the datagram needs to continue to forward to the next post office, so this letter was forwarded to the next post office, but the next post office is the final destination www.aorb. org, Although Www.aorb. org has reduced the TTL by 1 to 0, it does not discard it because the destination is www.aorb. org AH. So www.aorb. org delivered the letter from the IP-layer postman to the responsible seller, but we started to say that www.aorb. org does not sell potatoes, so it sends back a letter to the buyer with a name that is unreachable (ICMP Type 3, code 3).
Fourth, when a buyer receives a letter of a type that is not reachable, he no longer adds 1 to the TTL on the letter that asked for the price of the potato, because he already knows all the routes to the destination.
6. Source
#pragma pack (4) #pragma comment (lib, "Ws2_32.lib") #define Win32_lean_and_mean #include <winsock2.h> #include < ws2tcpip.h> #include <stdio.h> #include <stdlib.h>/////ICMP Message type//#define ICMP_ECHOREPLY 0 #defi NE icmp_destunreach 3 #define ICMP_SRCQUENCH 4 #define ICMP_REDIRECT 5 #define ICMP_ECHO 8 #define Icmp_timeout #define ICMP_PARMERR #define MAX_HOPS #define ICMP_MIN 8//icmp message Minimum Length (only Head)////IP packet Header//typedef struct IPHDR {unsigned int h_len:4; Length of the header unsigned int version:4; Version of IP unsigned char tos; Type of service unsigned short total_len; Total length of the packet unsigned short ident; Unique identifier unsigned short frag_and_flags; Flags unsigned char ttl; Time to live unsigned char proto; Protocol (TCP, UDP etc) unsigned short checksum; IP Checksum
unsigned int sourceIP; Source IP unsigned int destip;
Destination IP} ipheader; ICMP Datagram Header//typedef struct _IHDR {BYTE i_type; ICMP message type BYTE i_code;
Sub code USHORT i_cksum; USHORT i_id; Unique ID USHORT i_seq;
Sequence number//This isn't the STD header, but we reserve space for time ULONG timestamp;
} Icmpheader; #define DEF_PACKET_SIZE #define Max_packet 1024//print user information void usage (char *progname) {printf ("Usage
:%s Host-name [max-hops]\n], progname);
GetChar ();
ExitProcess (-1);
}//Set survival time int Set_ttl (SOCKET s, int ntimetolive) {int nret;
Nret = setsockopt (S, Ipproto_ip, Ip_ttl, (LPSTR) &ntimetolive, sizeof (int));
if (nret = = socket_error) {printf ("setsockopt (IP_TTL) failed:%d\n", WSAGetLastError ());
return 0;
} return 1;
}//To respond with a dedicated compilation int decode_resp (char *buf, int bytes, sockaddr_in *from, int ttl) {Ipheader *IPHDR = NULL; IP header Icmpheader *icmphdr = NULL; ICMP head unsigned short iphdrlen; IP head length struct hostent *lphostent = NULL;
Host entity struct IN_ADDR inaddr = From->sin_addr;//ipv4 network Address IPHDR = (Ipheader *) buf;
Number of 32-bit words * 4 = Bytes Iphdrlen = Iphdr->h_len * 4;
if (bytes < Iphdrlen + icmp_min)//ip packet length over segment printf ("Too few bytes from%s\n", Inet_ntoa (FROM->SIN_ADDR));
ICMPHDR = (icmpheader*) (buf + Iphdrlen); Switch (icmphdr->i_type) {case icmp_echoreply://Response from Destination Lphostent = gethostbyaddr ((const C
Har *) &from->sin_addr, af_inet, sizeof (struct in_addr));
if (lphostent! = NULL) printf ("%2d%s (%s)", TTL, Lphostent->h_name, Inet_ntoa (INADDR));
return 1;
Break
Case Icmp_timeout://Response from router along the the-the-same-the-the---"%2d%s/n", TTL, Inet_ntoa (INADDR));
return 0;
Break Case Icmp_destunreach://Can ' t reach the destination @ all printf ("%2d%s reports:host is unreachable\n", TTL, Inet_ntoa (INADDR));
return 1;
Break
default:printf ("Non-echo type%d recvd\n", icmphdr->i_type);
return 1;
Break
} return 0;
}//Detect and USHORT checksum (USHORT *buffer, int size) {unsigned long cksum = 0;
while (Size > 1) {cksum + = *buffer++;
Size-= sizeof (USHORT);
if (size) cksum + = * (uchar*) buffer;
Cksum = (cksum >> +) + (Cksum & 0xFFFF);
Cksum + = (cksum >> 16);
Return (USHORT) (~cksum);
}//padding ICMP data void fill_icmp_data (char * icmp_data, int datasize) {Icmpheader *icmp_hdr;
Char *datapart;
ICMP_HDR = (icmpheader*) icmp_data;
Icmp_hdr->i_type = Icmp_echo;
Icmp_hdr->i_code = 0;
icmp_hdr->i_id = (USHORT) getcurrentprocessid ();
icmp_hdr->i_cksum = 0;
Icmp_hdr->i_seq = 0;
Datapart = icmp_data + sizeof (icmpheader); Place some junk in the buffer.
Don ' t care is about the data ...//memset (Datapart, ' E ', datasize-sizeof (Icmpheader)); }////FunCtion:main//int main (int argc, char **argv) {wsadata WSD;
SOCKET Sockraw;
Hostent *hp = NULL;
Sockaddr_in dest, from;
int ret;
int datasize;
int fromlen = sizeof (from);
int timeout;
int done = 0;
int maxhops;
int ttl = 1;
Char *icmp_data;
Char *recvbuf;
BOOL bopt;
USHORT seq_no = 0; Initialize the Winsock2 DLL//if (WSAStartup (Makeword (2, 2), &WSD)! = 0) {printf ("WSAStartup () failed:%d\n"
, GetLastError ());
return-1;
} if (argc < 2) usage (argv[0]);
if (argc = = 3) Maxhops = Atoi (argv[2]);
else Maxhops = Max_hops;
Sockraw = WSASocket (Af_inet, Sock_raw, ipproto_icmp, NULL, 0, wsa_flag_overlapped);
if (Sockraw = = Invalid_socket) {printf ("WSASocket () failed:%d\n", WSAGetLastError ());
ExitProcess (-1);
} timeout = 1000;
ret = setsockopt (Sockraw, Sol_socket, So_rcvtimeo, (char *) &timeout, sizeof (timeout)); if (ret = = socket_error) {printf ("SetsockopT (So_rcvtimeo) failed:%d\n ", WSAGetLastError ());
return-1;
} timeout = 1000;
ret = setsockopt (Sockraw, Sol_socket, So_sndtimeo, (char *) &timeout, sizeof (timeout));
if (ret = = socket_error) {printf ("setsockopt (So_sndtimeo) failed:%d\n", WSAGetLastError ());
return-1;
} zeromemory (&dest, sizeof (dest));
dest.sin_family = af_inet;
if ((dest.sin_addr.s_addr = inet_addr (argv[1])) = = Inaddr_none) {hp = gethostbyname (argv[1]);
if (HP) memcpy (& (DEST.SIN_ADDR), hp->h_addr, hp->h_length);
else {printf ("Unable to resolve%s\n", argv[1]);
ExitProcess (-1);
}} datasize = Def_packet_size;
DataSize + = sizeof (Icmpheader);
Icmp_data = (char *) (HeapAlloc (GetProcessHeap (), Heap_zero_memory, Max_packet));
RECVBUF = (char *) (HeapAlloc (GetProcessHeap (), Heap_zero_memory, Max_packet)); if ((!icmp_data) | | |
(!RECVBUF))
{printf ("HeapAlloc () failed%d\n", GetLastError ());
return-1;
} bopt = TRUE; if (setsockopt (Sockraw, Sol_sockET, So_dontroute, (char *) &bopt, sizeof (BOOL)) = = Socket_error) printf ("SetSockOpt (So_dontroute) failed:%d\n",
WSAGetLastError ());
memset (icmp_data, 0, Max_packet);
Fill_icmp_data (Icmp_data, datasize);
printf ("/ntracing route to%s over a maximum of%d hops:\n\n", argv[1], maxhops); for (TTL = 1; (TTL < Maxhops) && (!done));
ttl++) {int bwrote;
((icmpheader*) icmp_data)->i_cksum = 0;
((icmpheader*) icmp_data)->timestamp = GetTickCount ();
((icmpheader*) icmp_data)->i_seq = seq_no++;
((icmpheader*) icmp_data)->i_cksum = Checksum ((ushort*) icmp_data, datasize);
Bwrote = SendTo (Sockraw, Icmp_data, DataSize, 0, (SOCKADDR *) &dest, sizeof (dest)); if (bwrote = = Socket_error) {if (wsagetlasterror () = = Wsaetimedout) {printf ("%2d Send Request timed out.
\ n ", TTL);
Continue
} printf ("SendTo () failed:%d\n", WSAGetLastError ());
return-1; } ret = Recvfrom (Sockraw, Recvbuf, max_packet, 0, struct sockaddr*) &from, &fromlen); if (ret = = Socket_error) {if (wsagetlasterror () = = Wsaetimedout) {printf ("%2d Receive Request timed out.
\ n ", TTL);
Continue
} printf ("Recvfrom () failed:%d \ n", WSAGetLastError ());
return-1;
} done = Decode_resp (Recvbuf, ret, &from, TTL);
Sleep (1000);
} heapfree (GetProcessHeap (), 0, recvbuf);
HeapFree (GetProcessHeap (), 0, Icmp_data);
GetChar ();
return 0;
}
7. Experimental results