Linux内核分析 - 网络[十一]:ICMP模块
经过IP层处理,skb- >data指向icmp报头的位置,而报头最小为4字节,所以这里判断skb->len < 4,是则丢弃该报文。从这里也可以看出 ,时间戳请求报文可以只有4节字头部,而没有时间戳信息。 if (skb->len < 4) goto out_err; 这段代码设置时间戳响应的时间戳信息,包括接收时间戳和发送时间戳,两者分别代表主机收到报文 的时间,发送响应报文的时间,而从这部分代码也可以看出icmp_param.data.times[2] = icmp_param.data.times[1]协议栈简 单的将接收和发送时间戳置为相同的。时间戳的计算很简单,格林尼治时间的当天时间的微秒数。最后skb_copy_bits()从skb的 ICMP报文内容拷贝4节字的时间到icmp_param_data.times[0],即发起时间戳,所以最后情形如下: icmp_param_data.times[0] 发起时间戳,从请求报文中拷贝 icmp_param_data.times[0] 接收时间戳,处理ICMP报头时的 时间 icmp_param_data.times[0] 发送时间戳,设置为与接收时间戳相同 getnstimeofday(&tv); icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC); icmp_param.data.times[2] = icmp_param.data.times[1]; if (skb_copy_bits(skb, 0, &icmp_param.data.times[0], 4)) BUG(); 前面已经说过,icmp_param就是要发送ICMP报文的内容,上面设置了内容,接下来设置报头,同样是直接拷贝 了ICMP请求的报头,改变type为ICMP_TIMESTAMPREPLY。注意这里的data_len设置为0,因为它与icmp echo不同,一定是没有分 片的,即没有paged_data部分。head_len设置为icmphdrlen+12,这里是为了调用icmp_reply()回复时的统一,实现表示ICMP部 分的长度,主要是有分片时会根据head_len来跳过报头而只拷贝每个分片的内容。 icmp_param.data.icmph = *icmp_hdr(skb); icmp_param.data.icmph.type = ICMP_TIMESTAMPREPLY; icmp_param.data.icmph.code = 0; icmp_param.skb = skb; icmp_param.offset = 0; icmp_param.data_len = 0; icmp_param.head_len = sizeof(struct icmphdr) + 12; 最后调用icmp_reply()回复,这与icmp_echo()是相同的 。 icmp_reply(&icmp_param, skb); 注意两者设置icmp_param参数时的区别: icmp_echo()中 icmp_param.data_len=skb->len; icmp_param.head_len=sizeof(struct icmphdr); icmp_timestamp()中icmp_param.data_len=0。 icmp_param.head_len=sizeof(struct icmphdr) +12; icmp_reply() (编辑:源码网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |