透析ICMP協議(五): 應用篇路由追蹤 (轉)
透析ICMP(五):
應用篇追蹤
===============================
這篇文章出自free/CSDN
平臺: VC6 XP
這篇文章本應該在三天之前寫完, 但是由於眾所周知的原因, 我在北大bbs上轉了三天, 所以這麼遲才發出. 由於的懶惰導致對大家的不便, 我表示深深的道歉.
原理簡介:
--------
透過前四節的介紹, 可能大家對ICMP的應用有了初步的瞭解. 不過開始本節之前我對ICMP協議再從宏觀上做些介紹. 大家都知道ICMP是為於ISO的第三層---層。 既是它同IP協議為於同一層, 然而大家可能也只到,ICMP協議要用到IP協議, 所以有一些書上說ICMP位ISO的第四層, 那是錯誤的。 同樣這樣那些書上這樣畫的的例子也是錯誤的, 我就發現某外資通訊公司的資料上有這樣兩種錯誤的畫法
--------------------------
| ICMP | TCP(SCTP) |
--------------------------
| IP |
--------------------------
---------------------------
|... | TCP(SCTP) |
---------------------------
| ICMP | IP |
----------------------------
其實如上的畫法是錯誤的, 正確地畫法應為:
---------------------
|... | TCP(SCTP) |
---------------------
| ICMP | |
---------- |
| IP |
---------------------
接下來,讓我們來說明怎樣實現追蹤路由的功能, 大家透過我的第一節的閱讀可能已經瞭解了超時報文的具體內容(參見透析ICMP協議(一): 協議原理), 它在如果閘道器在處理資料包時發現生存週期域(ttl)為零,此資料包必須拋棄。閘道器同時必須透過超時資訊通知源主機。這是它的報文的具體結構:
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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Inte Header + 64 bits of Original Data Datagram |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
透過利用setsockopt()設定ICMP包的IP包頭中的ttl欄位便可以達到這種效果。 具體過程如下, 假設你的IP到達目標地址需要過n個路由器(n>1)。 則 剩下的問題為如何確定超時ICMP報文的路由器得到它的機器名的資訊。 這個問題可能很多讀者都會求, 用gethostbyaddr()可以得到答案。 經過理論的論證後, 讓我們看看如何實現。 具體實現:(具體如何初試化ICMP的資料包上節已有詳細的介紹,這裡只是補充路由追蹤的程式碼) unsigned long ipback = 0; //超時報文的IP的初試值 //直到找到目標主機, 或達到最大跳數(HOPS) ================== //初始化Socket if (sockRaw == INVALID_SOCKET) // 設定IP包頭的ttl欄位 // 設定接受超時為100ms //禁止用Nagle演算法快取資料 timeout = 1000; //下面的程式碼生成ICMP包 //初始化dest // 設定包長度 // 計算包大小 icmp_data = (char *)new[MAX_PACKET]; //分配,可以用new 和 delete if (!icmp_data) if (!recvbuf) memset(icmp_data,0,MAX_PACKET); int bwrote; // 為了最後計算ICMP包回來的總時間 if (bwrote == SOCKET_ERROR) // 接受資料包 if (bread == SOCKET_ERROR) // 得到返回的路由器 return 1; =============================== void fill_icmp_data(char * icmp_data, int datasize){ IcmpHeader *icmp_hdr; icmp_hdr = (IcmpHeader*)icmp_data; icmp_hdr->i_type = ICMP_ECHO; } 聯絡方式:
1. 初始化第一個ICMP包,並設定IP包頭中的TTL為1, 則得到第一個資料路由器發回的超時報文
2. 一般情況下:初始化第i(i
--------
主要程式碼如下:
unsigned long ms = 0; //超時值
struct hostent *hHost;
char m_address[256];
while (ipback != ipfinal){
hHost = 0;
//對到目標主機中間的某個路由器發放的報文(ttl為1~N-1之間)
if (Ping(m_address,ttl,ipback,ms))
{
sin.sin_family = AF_INET;
sin.sin_addr.S_un.S_addr = ipback; // 由函式返回的IP地址
// 查詢主機名
hHost = gethostbyaddr((char*)&sin.sin_addr, 4, PF_INET);
//這裡可以輸出hHost的內容
}
ttl++;
if (ttl > MAX_HOPS) //達到最大跳數
{
break;
}
}
ping函式的程式碼
==================
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;
sockRaw = Wocket (AF_INET,
SOCK_RAW,
IPPROTO_ICMP,
NULL, 0, WSA_FLAG_OVERLAPPED);
{
// 錯誤
}
bread = setsockopt(sockRaw, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(int));
if(bread == SOCKET_ERROR)
{
// 錯誤
}
bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));
if(bread == SOCKET_ERROR)
{
// 錯誤
}
bread = setsockopt(sockRaw, SOL_SOCKET, TCP_NODELAY, (const char*)&killnagle, sizeof(int));
if (bread == SOCKET_ERROR)
{
// 錯誤
}
// 設定傳送超時為100ms
bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,
sizeof(timeout));
if(bread == SOCKET_ERROR)
{
// 錯誤
}
memset(&dest,0,sizeof(dest));
hp = gethostbyname(host);
if (!hp)
{
addr =_addr(host);
}
if ((!hp) && (addr == INADDR_NONE) )
{
// 錯誤
}
if (hp != NULL)
memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
else
dest.sin_addr.s_addr = addr;
if (hp)
dest.sin_family = hp->h_addrtype;
else
dest.sin_family = AF_INET;
dest_= inet_ntoa(dest.sin_addr);
datasize = DEF_PACKET_SIZE;
datasize += sizeof(IcmpHeader);
recvbuf = (char *)new[MAX_PACKET];
{
// 釋放記憶體,退出
}
{
// 釋放記憶體,退出 }
}
fill_icmp_data(icmp_data,datasize); // 這個函式用來填充ICMP的資料包
((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);
unsigned long tc = GetTickCount();
//傳送資料包
bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest, sizeof(dest));
{
// 錯誤
}
if (bwrote < datasize ) //傳送位元組數對否
{
}
bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,
&fromlen);
//計算總時間
ms = GetTickCount() - tc;
{
// 錯誤
}
ipback = from.sin_addr.s_addr;
}
函式fill_icmp_data()的
===============================
//這個結構下面將用到
typedef struct _ihdr {
BYTE i_type;
BYTE i_code;
USHORT i_cksum;
USHORT i_id;
USHORT i_seq;
ULONG timestamp; /* 這不是ICMP包的一部分, 只是為了計算時間 */
}IcmpHeader;
char *datapart;
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); //計算資料域的開始地址
// 初試化資料域
memset(datapart,'E', datasize - sizeof(IcmpHeader));
連結:
-------
我的其它文章,<>, 和其它文章參見:
http://www.csdn.net/develop/author/netauthor/bugfree/
-------
to:zhangliangsd@.com">zhangliangsd@hotmail.com
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993426/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 透析ICMP協議(三): 牛刀初試之一 應用篇ping(ICMP.dll) (轉)協議
- 透析ICMP協議(四): 牛刀初試之二 應用篇ping(RAW Socket) (轉)協議
- ICMP協議協議
- 網路管理之ICMP協議篇協議
- TCP IP之ICMP協議TCP協議
- ICMP協議的定義協議
- icmp和arp協議協議
- 網路通訊協議-ICMP協議詳解!協議
- 【網路協議】ICMP協議、Ping、Traceroute協議
- 路由追蹤命令詳解路由
- ICMP Internet控制資訊協議協議
- ICMP協議結構全解(2)協議
- ICMP協議結構全解(1)協議
- 簡單而重要的協議:ICMP協議
- TCP/IP五層模型-應用層-DNS協議TCP模型DNS協議
- 如何做路由追蹤?【免工具】路由
- [系列] - go-gin-api 路由中介軟體 - Jaeger 鏈路追蹤(五)GoAPI路由
- Linux基礎命令---tracepath追蹤路由Linux路由
- 應用層協議協議
- 計算機網路之四:ICMP協議計算機網路協議
- 路由協議與閘道器協議路由協議
- Linux基礎命令---traceroute追蹤路由Linux路由
- AsyncLocal<T>在鏈路追蹤中的應用
- 分散式應用追蹤系統 - Skywalking分散式
- 圖解路由協議!圖解路由協議
- SQL追蹤和事件追蹤SQL事件
- 淺談TCP、UDP、ICMP三種常見協議TCPUDP協議
- TCP應用層協議TCP協議
- 鏈路追蹤技術的應用及實踐
- TGDC | 向陽而生 —— 光線追蹤的專案應用
- Jaeger鏈路追蹤在專案中的應用
- 追蹤應用程式所執行的sql語句SQL
- 追蹤時間的10個給力應用程式
- 通過ICMP協議反彈SHELL並執行命令協議
- Protobuf協議應用乾貨協議
- 應用隱私政策協議協議
- web應用與http協議WebHTTP協議
- HCIA—應用層常用協議協議