这两天一直在重读《TCP/IP详解卷1:协议》这部书,再一次深刻感受了这部书的神奇与伟大,但是也发现它存在的一些问题(不能说是问题,只是对于我来说有一些阅读方面的不便),第一,它的部分内容对我基本没有用,比如SLIP,部分内容不是最新的,比如IPV6没有提及;第二,它讲解协议是基于UNIX系统的,因此很多地方都在比较协议在不同UNIX系统上的表现。对于基本平台是Linux的我来说,这两类内容显得多余,另外看过书后如果不记录下来变为自己的东西,一段时间之后又难免要从头开始,因此接下来会陆续记录读这部书的笔记,也算是复习一遍TCP/IP协议。第一篇先写Ping程序。
Ping程序使用原始套接字发送ICMP回射请求并接收ICMP回射应答,一般Linux内核中都会提供此程序,图1-1是ICMP回显请求与回显应答报文格式,
图1-1
如果是ICMP回显请求,类型字段值为8,如果是ICMP回显应答,类型字段值为0。检验和字段覆盖整个ICMP报文,标识符字段置为发送进程的ID号,这样当同一台主机同时运行多个ping程序实例时,返回的回显应答报文可以被各自的发送回显请求的进程识别而得以正确处理。序列号从0开始,每发送一个新的请求就加1。选项数据的值是发送回显请求的时间,回显应答报文需要拷贝这个值,当发送进程接收到回显应答报文时,将该选项数据值取出,用当前的时间减去这个值,就求得了RTT值。
图1-2是示例的ping程序输出结果:
图1-2
其中icmp_seq对应的是序列号,ttl值在报文的IP首部中可以找到,而time值就是求得的RTT值。
图1-3是ping程序各个函数及其调用顺序,
这个图让整个程序的架构一目了然:
图1-3
下面介绍一下ping程序提供的记录路由功能,这个功能需要用到IP首部的选项字段功能,先看一下记录路由选项的一般格式(图1-4):
图1-4
对于记录路由(RR)来说,code的值为7,后面最多跟9个IPV4地址,因为IP首部的最大长度是60B,去掉固定长度20B,选项字段的前3个字节,则剩下给IP地址的则只有37B。ptr为指针字段,指向存放下一个IP地址的位置,ping程序刚运行时,其值为4,当记录下9个IP地址时,ptr的值为40,表示清单已满。
图1-5给出ping程序对应的IP报文的完整格式,其中IPv4选项对应的就是图1-4所示的结构
图1-5
使用记录路由选项运行ping程序还需举一个例子,首先参考图1-6所示的网络环境:
图1-6
图1-7是运行ping -R程序后的输出,加了-R选项表明启用记录路由,这样分组所经过的每一站都把自己的IP地址加入RR清单,
图1-7
注意有两个接口的路由器bsdi,在ping程序运行过程中,它的两个IP是以什么顺序加入RR清单中的,参考图1-6的箭头方向
以上程序的tcpdump -v输出如图1-8所示:
图1-8
optlen=40表示在IP首部中有40个字节的选项空间(IP首部长度必须为4字节的整数倍)。RR{39}的意思是记录路由选项已被设置,它的长度字段是39,然后是9个IP地址,符号“#”用来标记ptr值。
参考资料:
《TCP/IP详解卷1:协议》第7章
《UNIX网络编程 卷1》第28章
阅读(1159) | 评论(0) | 转发(0) |