昨天大概介绍了一下IPV6,主要包括IPV6地址表示,地址类别,相关协议和技术。今天的重点是ICMPv6,之所以要先讲ICMPv6是因为它是其他技术(如邻居发现协议)的基础,没有它,其他都是浮云。
ICMPv6是控制报文,它的作用是在网络传输中发现并报告错误、传送有控制信息性质的消息。如前所说,他是邻居发现协议和组播侦听者发现协议的基础。
报文类型
错误报文
其报头的类型字段高八位为全0,所以类型字段的范围为0-127。
错误报文包括目标地址不可达、包太大、时间超时和参数错误
目标地址不可达
这种报文由路由器或者目的主机发出。报文的类型字段为1,代码字段为0-6。
出现这种错误的情况有很多,如路由器在路由表里无法找到目的主机,目的主机设置了防火墙,目的地址超出了源主机能发出信息的范围,无法解析目的主机的链路层地址等等。
代码字段具体表示如下:
0:没有到达目的地的路由。这个报文在路由器没有定义IP包的目的地路由时产生,路由器将采用默认路由来发送无法利用路由器的路由表进行转发的包。
1:与目的地的通信被管理员禁止。当被禁止的某类业务流欲到达防火墙内部的一个主机时,包过滤防火墙将产生该报文。
2:不是邻居。当使用IPv6选路扩展头并严格限定路由时,将使用这个代码。当列表中的下一个目的地与当前正执行转发的节点不能共享一个网络链路时,将会产生该报文。
3:地址不可达。这个代码指出在把高层地址解析到链路层(网络)地址时遇到了一些问题,或者在目的地网络的链路层上去往其目的地时遇到了问题。
4:端口不可达。这种情况发生在高层协议(如D P )没有侦听包目的端口的业务量,且传输层协议又没有其他办法把这个问题通知源节点时。
5:源地址被禁。当这个源地址被某个协议或者防火墙过滤掉时,报文无法发出去或者接收进来。
6:路由拒绝转发。有些路由的前缀被配置成必须马上丢弃所有接收到的包,而当一个报文遇到这种路由时,包会被丢弃。
包太大
当包的大小超过MTU(最大传输单元)时,路由器会发送包太大的错误报文。此报文的类型字段为2,代码字段为0。IPV6支持的最大传输单元(MTU)为1280byte。
时间超时
报文的类型字段为3,代码字段为0或者1。为0时表示在传输过程中路由跳数减为了0,为1表示在重组数据片段时时间超时了。
参数错误
当IPv6头或扩展头中的某些部分有问题时,路由器由于无法处理该包而会将其丢弃。路由器的实现中应该可以产生一个ICMP参数错误报文来指出问题的类型(如错误的头字段、无法识别的下一个头类型或无法识别的IPv6选项),并通过一个指针值指出在第几个字节遇到这种错误情况。
这种报文的类型字段为4,代码字段为0-2。0:错误的头字段。1:无法识别的下一个头类型。2:无法识别IPV6选项。
信息性报文
这种报文包含二种类型:回射请求和回射应答
回射请求
类型字段为128,代码字段为0.
一个主机发送回射请求给另一台主机,要求立即回复回射应答。用来确认目的主机是否可达。在ping程序中就是用的这种方法。
在ping程序中的应用如下:
void send_ip()
{
if(sequence != 0 && !flag)
printf("Destination Host Unreachable\n");
int len;
struct icmphdr *icmp_p;
icmp_p =(struct icmphdr *)send_buf;
icmp_p->type = ICMP_ECHO;
icmp_p->code = 0;
(icmp_p->un).echo.id = p_id;
(icmp_p->un).echo.sequence = sequence++;
gettimeofday((struct timeval *)(icmp_p +1),NULL);
len = sizeof(struct timeval)+packet_len;
icmp_p->checksum = 0;
icmp_p->checksum = ip_checksum((unsigned short *)icmp_p,len);
if(sendto(ip_fd,send_buf,len,0,(struct sockaddr *)&send_addr,sizeof(send_addr))<0)
{
printf("send to error\n");
exit(1);
}
}
这只是ping程序里的一小部分。完整代码我已经上传了,有兴趣的可以去下载。
回射应答
类型字段为129,代码字段为0.
当一个主机接收到回射请求时,就会发送回射应答作为回复。回射应答可以发送给一个组播地址。