在上一节的分析中,曾留下3个疑问:
在分析icmp数据包处理流程之前,我有如下疑问:
1、为什么要为每一个cpu创建一个仅用于发送icmp报文的socket呢,不使用socket不也是可以把icmp报文发送出去吗?
2、ping的工作原理是什么呢?
3、Traceroute的工作原理是什么呢?
1、对于第一个问题,通过上一节的分析,应该有如下原因
a)加锁访问,保证同一时刻只能发送一个icmp报文。因为socket->sk_lock.slock有一个自旋锁的定义,使用这个自旋锁,就可以保证同一时刻只要发送一个icmp报文。而如果不是socket,我们就需要创建新的结构体,来保证同一时刻只发送一个icmp报文,既然代码中已经有现成的结构了,就没有必要创建新的结构体
b)在linux内核中,把icmp、igmp、tcp、udp均作为四层处理流程来看待,而对于tcp、udp等四层数据,收发数据包都是使用socket来实现的,已经有了一套比较完善的机制,包括ip_append_data、ip_push_pending_frames等函数,所以对于icmp也适用这一套机制,没有必要专门为icmp创建新的机制。
2、对于ping的工作原理,主要是通过echo_request、echo_reply来实现的。
其中echo_request是使用应用层来实现的,根据下面的echo格式,在linux实现中,是将identifier设置为ping请求的进程id,而Sequence则作为请求的计数值,通过源、目的ip地址、identifier、Sequence就可以区分不同的ping应答。
TYPE(8/0) | CODE(0) | Checksum |
identifier | Sequence | |
Option |
3、对于traceroute的工作原理,主要是根据echo_request、echo_reply、time_exceeded这3个icmp类型数据包实现的。
首先traceroute进程会连续发送ttl值为1 、2、3、4、5、6...的echo request数据包,而中间的路由器站点收到ttl为0的数据包后,就会发送time_exceed的icmp差错报文,这样traceroute进程就会知道每一个中间站点的ip地址,而目的地址的pc或者路由器收到echo_request类型的数据包,即会回复echo_reply类型的数据包,这就traceroute的工作流程。
TYPE(11) | CODE(0-1) | Checksum |
Not used(must set 0) | ||
Option |