- 论坛徽章:
- 0
|
如果是带选项的分片报文,某些选项是每个分片都包含例如松散路由,有些选项是只有第一片包含的例如记录路由,那么就造成分片的头长度不一样,比如分两片第一片头长可能是40,第二片可能头长是32,那么如果我是中间设备转发时怎么处理,我看linux源码不能很好的处理:
iph = skb->nh.iph; //这是第一片的IP头
hlen = iph->ihl * 4; //取到第一片的IP头长度安上面的假设是40,我第一片是32
for (; {
/* Prepare header of the next frame,
* before previous one went down. */
if (frag) {//这个是分片 skb->next 这片的ip头应该是32了
frag->ip_summed = CHECKSUM_NONE;
frag->h.raw = frag->data;
frag->nh.raw = __skb_push(frag, hlen); //*问题在此* 从data往回指了40个字节回去,本来应该往回指32个字节的这边指了40个字节,然后下面拷贝了40个字节,那么就相当于把原本的mac头的数据覆盖掉一部分,而且报文也变化比较大,如果这个是带pppoe头的报文,我认为这个报文就被**掉了,因为ppoe头被踩了,没办法恢复(如果中间设备不能提供pppoe功能),mac头被踩了没事,可以自己添加,pppoe不行吧,请大神指教
memcpy(frag->nh.raw, iph, hlen);
iph = frag->nh.iph;
iph->tot_len = htons(frag->len);
ipv4_copy_metadata(frag, skb);
if (offset == 0)
ip_options_fragment(frag);
offset += skb->len - hlen;
iph->frag_off = htons(offset>>3);
if (frag->next != NULL)
iph->frag_off |= htons(IP_MF);
/* Ready, complete checksum */
ip_send_check(iph);
} |
|