Linux内核分析 - 网络[十一]:ICMP模块
skb_reserve()保留skb头的hh_len大小,skb_put()扩展skb大小到fraglen,然后设置network_header和 transport_header指向skb的正确位置,data指向ICMP报头的位置,具体可以看下面的图示: skb_reserve(skb, hh_len); …… data = skb_put(skb, fraglen); skb_set_network_header(skb, exthdrlen); skb->transport_header = (skb->network_header + fragheaderlen); data += fragheaderlen; copy是要拷贝的长度,为传输层报头后的内容大小。getfrag()函数实现数据的拷贝,在icmp模块中, getfrag()指向icmp_glue_bits()函数,它从[from] + offset处拷贝copy个字节到data + transhdrlen处。 copy = datalen - transhdrlen - fraggap; if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) { err = -EFAULT; kfree_skb(skb); goto error; } 偏移offset加上已经拷贝的字节数copy,fraggap=0,length减去的就是IP报文内容长度,由于报文才56字节,一个 分片足够,所以length=0,然后把新生成的skb放入sk->sk_write_queue中,然后执行下次while循环。各参数值:copy=42, offset=42, length=0, 更新transhdrlen=0。 offset += copy; length -= datalen - fraggap; transhdrlen = 0; …… __skb_queue_tail(&sk->sk_write_queue, skb); continue; while循环判断条件是length > 0,因此跳出循环,完成了向IP层发送的数据生成,结果如下,注意, ICMP报头还是没有填写的: example 2:600 Byte echo 报文[假设MTU=520] (编辑:PHP编程网 - 黄冈站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |