互联网控制消息协议(,缩写:)是互联网协议族的核心协议之一。它用于网际协议(IP)中发送控制消息,提供可能发生在通信环境中的各种问题反馈。通过这些信息,使管理者可以对所发生的问题作出诊断,然后采取适当的措施解决。
ICMP 依靠IP來完成它的任务,它是IP的主要部分。它与传输协议(如TCP和UDP)显著不同:它一般不用于在两点间传输数据。它通常不由网络程序直接使用,除了 ping 和 traceroute 这两个特別的例子。
IPv4中的ICMP被称作ICMPv4,IPv6中的ICMP则被称作ICMPv6。
技術細節
ICMP是在 RFC 792 中定义的互联网协议族之一。通常用于返回的错误信息或是分析路由。ICMP错误消息总是包括了源数据并返回给发送者。
ICMP错误消息的例子之一是TTL值过期。每个路由器在转发数据报的时候都会把IP包头中的TTL值减1。如果TTL值为0,“TTL在传输中过期”的消息将会回报给源地址。
每个ICMP消息都是直接封裝在一个IP数据包中的,因此,和UDP一样,ICMP是不可靠的。
虽然ICMP是包含在IP数据包中的,但是对ICMP消息通常会特殊处理,會和一般IP數據包的處理不同,而不是作為IP的一個子協議來處理。在很多時候,需要去查看ICMP消息的內容,然後發送適當的錯誤消息到那個原來產生IP數據包的程序,即那個導致ICMP訊息被傳送的IP數據包。
很多常用的工具是基於ICMP消息的。traceroute 是通過發送包含有特殊的TTL的包,然後接收ICMP超時消息和目標不可達消息來實現的。 ping 則是用ICMP的"Echo request"(类别代码:8)和"Echo reply"(类别代码:0)消息來實現的。
ICMP报文結構
報頭
ICMP報頭從IP報頭的第160位開始(IP首部20字节)(除非使用了IP報頭的可選部分)。
- Type - ICMP的類型,标识生成的错误报文;
- Code - 進一步劃分ICMP的類型,该字段用来查找产生错误的原因.;例如,ICMP的目標不可達類型可以把這個位設為1至15等來表示不同的意思。
- Checksum - Internet校驗和(RFC 1071),用於進行錯誤檢查,該校驗和是從ICMP頭和以該字段替換為0的數據計算得出的。
- Rest of Header - 報頭的其餘部分,四字節字段,內容根據ICMP類型和代碼而有所不同。
填充數據
填充的數據緊接在ICMP報頭的後面(以8位為一組):
- Linux的"ping"工具填充的ICMP除了8個8位元組的報頭以外,默认情况下還另外填充數據使得總大小為64字節。
- Windows的"ping.exe"填充的ICMP除了8個8位元組的報頭以外,默认情况下還另外填充數據使得總大小為40字節。
报文类型
源站抑制
源站抑制报文旨在请求发送方降低发往路由器或主机的报文发送速率。在接收的过程中,当接收方没有足够的接收缓冲区来处理接收到的报文,或者接收这个报文会导致临近其本身的缓冲区限制时,就会触发源站抑制报文。
数据被从一个或一群主机高速地发往网络上的一个路由器,虽然路由器有缓冲机制,但是路由器的缓冲区大小通常(由于物理内存有限的原因)被限制。因此,如果路由器的通信量过大,路由器最终会(由于内存耗尽,导致必须丢弃掉接收到的数据报)无法继续处理超过输入缓冲区限制的部分数据,直到路由器缓冲队列有空余空间可以存放新的数据报。但是由于网络层(Network Layer)缺乏確認訊息(ACK)机制,因此客户端无法获知数据是否成功抵达接收方。所以研究者提出了源站抑制这一补救措施来解决这一问题:当路由器发现流入数据速率远远高于流出数据速率时,会发送ICMP源站抑制报文给源站,通知源站应该降低其数据传输速度或等待一定时间后再尝试发送更多数据。当源站接收到ICMP源站抑制报文时会减慢数据发送的速度,或者在再次尝试发送数据前等待一定的时间,使得路由器能够(在处理完当前接收到的数据之后)清空输入缓冲队列。
但是因为有研究表明「源站抑制是一种无效的(不公平的)补救措施」,所以路由的源站抑制报文已在1995年被[https://tools.ietf.org/html/rfc1812 RFC 1812] 弃用。此外,(路由)转发和回应任何形式的源站抑制报文已在2012年被[https://tools.ietf.org/html/rfc6633 RFC 6633] 弃用
其中:
:类型(Type) 必须设置为 18
:代码(Code) 必须设置为 0
:地址掩码(Address mask) 为待回答的地址掩码
源站不可达
源站不可达 报文是由主机或入站网关用于通知客户端出于目的站无法连接的报文。这些原因可能包括:物理连接失效(也即网络距离无限大),或指定的地址或端口处于非激活状态,或者数据报长度过长而导致必须分片但是IP首部指定了“不分片”选项导致无法分片。如果是TCP端口不可达,则会返回TCP RST,而不会返回此报文。如果是IP多播的情况,也不会返回此报文。
其中:
:类型(Type) 必须设置为 3
:代码(Code) 字段用于指示具体导致源站不可达的原因。见下表。
::
:Next-hop MTU 当需要分片但是DF(Do not Fragment)置位的错误发生时,包含了下一跳网络的MTU的值。
:IP header 用于源站根据收到的源站不可达报文来确定具体哪个数据报引起了源站不可达错误。
C语言
#include
#include
#include
#include
#include
#include
#include
#include
unsigned short checksum(void *b, int len) {
unsigned short *buf = b;
unsigned int sum = 0;
unsigned short result;
for (sum = 0; len > 1; len -= 2)
sum += *buf++;
if (len == 1)
sum += (unsigned char)buf;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
result = ~sum;
return result;
}
int main() {
int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
if (sockfd type = ICMP_ECHO;
icmp->code = 0;
icmp->un.echo.id = getpid() & 0xFFFF;
icmp->un.echo.sequence = 1;
icmp->checksum = checksum(sendbuf, sizeof(sendbuf));
struct timeval start, end;
gettimeofday(&start, NULL);
if (sendto(sockfd, sendbuf, sizeof(sendbuf), 0,
(struct sockaddr *)&addr, sizeof(addr))
參考
外部連結
- RFC 792, Internet Control Message Protocol
- [http://www.eventhelix.com/RealtimeMantra/Networking/Icmp.pdf ICMP Sequence Diagram]
- RFC 1122, Requirements for Internet Hosts -- Communication Layers
- RFC 1716, Towards Requirements for IP Router
- RFC 1812, Requirements for IP Version 4 Routers
- RFC 6633, Deprecation of ICMP Source Quench Messages
- [https://web.archive.org/web/20080519015614/http://www.daemon.be/maarten/icmpfilter.html Filtering ICMP on firewalls]
- [http://www.iana.org/assignments/icmp-parameters IANA]
评论 (0)