Dialysis ICMP protocol (5): Application routing tracking ================================= this article is from Bugfree / 9CBS platform : VC6 Windows XP
This article should be written until three days ago, but because of the reason, I turned three days in BBS, Peking University, so I was either so late. I said deep apology because of the laziness caused the inconvenience to everyone.
Principle: -------- Introduction to the top four, you may have a preliminary understanding of ICMP applications. However, I will introduce the ICMP protocol before this section. Everyone knows ICMP is a third layer of ISO - network layer. It is not only the same layer with the IP protocol, but everyone may only arrive, ICMP protocols are used to use IP protocols, so there are some books that ICMP bit ISO's fourth level, that is wrong. The same examples of such books are also wrong. I found that there are two wrong paintings on a foreign-funded communications company ---------------------------------------------------------------------------------- -------- | ICMP | TCP (SCTP) | -------------------------- | IP | ----- -----------------------------------------------. .. | TCP (SCTP) | --------------------------- | ICMP | IP | ---------- ------------------
In fact, the painting method is wrong, and the correct pain should be: --------------------- | ... | TCP (SCTP) | ------------------ | ICMP | - -------------------------------------------------- -------
Next, let's explain how to implement the function of tracking routing. Everyone can understand the specific content of time-time packets through my first news (see dialysis ICMP protocol (1): Principle of protocol), if the gateway The survival period (TTL) is found to be zero when processing the data report, and this datagram must be discarded. The gateway must notify the source host through the timeout information. This is the specific structure of its packet: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - - - - - - - - - - - - - - - - - - | TYPE (11) | CODE (0/1) | Checksum | - - - - - - - - - - - - - - - - - - - - - - | Unused | - - - - - - - - - - - - - - - - - - | Internet Header 64 Bits of Original Data DataGram | - - - - - - - - - - - - - - - - - - - - - - - - - - 10005 The field can achieve this effect. The specific process is as follows, assuming that your IP reaches the target address that needs to pass N routers (n> 1). 1. Initialize the first ICMP package and set the TTL of the IP header to 1, get the timeout packet sent back by the first data router 2. Generally: Initialize the i (i The remaining problem is how to determine the router IP address of the timeout ICMP message to get its machine name. This question may be available in many readers, and getHostbyAddr () can get the answer. After the theory of argument, let us see how to achieve it. Specific implementation: (How to initiate ICMP data packages have been described in detail, just supplement the code of the routing track) -------- The main code is as follows: unsigned long ipback = 0; // Time Press The primary trial value of the IP of the text Unsigned long ms = 0; // Timeout value struct hostent * hhost; char m_address [256]; / / Until the target host is found, or reaches the maximum number of hops (ipback! = Ipfinal) {hhost = 0; / / Pin packets (TTL are 1 ~ n-1) IF (Ping (M_Address, TTL, IPBACK, MS)) {sin.sin_family = Af_Inet; sin.sin_addr .S_un.s_addr = ipback; // The IP address returned by the function // looks up the host name hhost = gethostbyaddr ((char *) & sin.sin_addr, 4, pf_inet); // You can output the content} TTL ; IF ( TTL> max_hops) // reach the maximum number of hops {Break;}} ================== ping function code =========================== int ping (const char * host, int TTL , unsigned long & ipback, unsigned long & ms) {SOCKET sockRaw; struct sockaddr_in dest, from; struct hostent * hp; int bread, datasize; int fromlen = sizeof (from); int timeout = 100; char * dest_ip; char * icmp_data; Char * recvbuf; unsigned int addr = 0; const Int max_packet = 1024; // Initialize Socket SockRaw = WSASSocket (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED); IF (SockRaw == Invalid_socket) {// Error} / / Set the TTL field breth = setsockopt (SockRaw, Ipproto_IP, IP_TTL, (CHAR *) & TTL, SIZEOF (INT); f 错 错} // Setting up the timeout 100ms bread = setsockopt (sock, sol_socket, so_rcvtimeo, (char *) & timeout, sizeof (timeout)); if (Bread == Socket_ERROR) {// Error} // Prohibit Nagle Algorithm Cache Data Bread = Setsockopt (SockRaw, SOL_SOCKET, TCP_NODELAY, (const char *) & killnagle, sizeof (int)); if (Bread == Socket_ERROR) {// Error} Timeout = 1000; // Setting Send timeout 100ms Bread = setsockopt (SockRaw, SOL_Socket, SO_SNDTIMEO, (CHAR *) & Timeout, SizeOf (Timeout)); if (BREAD == Socket_ERROR) {// Error} // The following code generates an ICMP package Memset (& DEST, 0, SIZEOF (DEST)); hp = gethostByName (Host); if (! HP) {addr = inet_addr (host);} IF ((! HP) && (AddR) == INADDR_NONE)) {// Error} if (hp! = Null) Memcpy (& (dest.sin_addr), hp-> h_addr, hp-> h_length); Else dest.sin_addr.s_addr = addr; // Initialization Dest IF (HP) dest.sin_family = hp-> h_addrtype; else dest.sin_family = AF_INET; DEST_IP = INET_NTOA (DEST.SIN_ADDR); // Set the package length DATASIZE = Def_packet_size; // Calculate the size of the DataSize = sizeof (Icmpheader); ICMP_DATA = (char *) New [max_packet]; // Assign memory, you can use new and delete recvbuf = (char *) NEW [MAX_PACKET]; IF (! iCMP_DATA) {// Release Memory, exit} IF (! recvbuf) {// Release memory, exit}} MEMSET (ICMP_DATA, 0, MAX_PACKET); Fill_ICMP_DATA (ICMP_DATA, DATASize); // This function is used to populate ICMP packets INT BWROTE; (ICMPHEADER *) ICMP_DATA) -> i_cksum = 0; (ICMPHEADER *) ICMP_DATA) -> TimeStamp = gettickcount (); // Deposit (ICMPHEADER *) ICMP_DATA) -> i_seq = SEQ_NO ; // Calculate the checksum (ICMPHEADER *) ICMP_DATA) -> i_cksum = checksum ((USHORT *) ICMP_DATA, DATASIZE); // In order to calculate the total time of the ICMP package, unsigned long tc = gettickcount (); // Send data packets BWROTE = Sendto (SockRaw, ICMP_DATA, DATASIZE, 0, (Struct Sockaddr *) & Dest, SizeOf (DEST)); IF (BWrote == Socket_ERROR) {// Error} If (BWrote // Accept the data package Bread = Recvfrom (SockRaw, Recvbuf, Max_Packet, 0, (Struct SockAddr *) & from, & fromLomlen; // Calculation Total Total Total Total Total Time MS = GetTickCount () - Tc; IF (Bread == Socket_ERROR) {//// Error} // Get the returned router ipBack = from.sin_addr.s_addr; Return 1;} =================================================================================================================================================================================================================================================== =================== // This structure will be used below TypeDef struct _ihdr {byte i_type; byte i_code; ushort i_cksum; ushort i_id; ulong timestamp; / * This is not part of the ICMP package, just for calculation time * /} icmpheader; 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); / / Calculate the start address of the data // Primary Data field MEMSET (DataPart, 'E', DATASIZE - SIZEOF (ICMPHEADER)); } Link: ------- My other article, << dialysis ICMP protocol >>, and other articles see: http://www.9cbs.net/develop/author/netauthor/bugfree/ Contact: ------- zhangliangsd@hotmail.com