Linux???????????·????????IPЭ??
???????????? ???????[ 2013/1/6 10:08:12 ] ????????
????????????ж????????????????????????ip_fragment()???????ú???????????????
void ip_fragment(struct sock *sk?? struct sk_buff *skb?? struct device *dev?? int is_frag)
{
struct iphdr *iph;
unsigned char *raw;
unsigned char *ptr;
struct sk_buff *skb2;
int left?? mtu?? hlen?? len;
int offset;
unsigned long flags;
/*
* Point into the IP datagram header.
*/
raw = skb->data;
iph = (struct iphdr *) (raw + dev->hard_header_len);
skb->ip_hdr = iph;
/*
* Setup starting values.
*/
hlen = (iph->ihl * sizeof(unsigned long));
left = ntohs(iph->tot_len) - hlen; /* Space per frame */
hlen += dev->hard_header_len; /* Total header size */
mtu = (dev->mtu - hlen); /* Size of data space */
ptr = (raw + hlen); /* Where to start from */
/*
* Check for any "DF" flag. [DF means do not fragment]
*/
if (ntohs(iph->frag_off) & IP_DF)
{
/*
* Reply giving the MTU of the failed hop.
*/
ip_statistics.IpFragFails++;
icmp_send(skb??ICMP_DEST_UNREACH?? ICMP_FRAG_NEEDED?? dev->mtu?? dev);
return;
}
/*
* The protocol doesn't seem to say what to do in the case that the
* frame + options doesn't fit the mtu. As it used to fall down dead
* in this case we were fortunate it didn't happen
*/
if(mtu<8)
{
/* It's wrong but it's better than nothing */
icmp_send(skb??ICMP_DEST_UNREACH??ICMP_FRAG_NEEDED??dev->mtu?? dev);
ip_statistics.IpFragFails++;
return;
}
/*
* Fragment the datagram.
*/
/*
* The initial offset is 0 for a complete frame. When
* fragmenting fragments it's wherever this one starts.
*/
if (is_frag & 2)
offset = (ntohs(iph->frag_off) & 0x1fff) << 3;
else
offset = 0;
/*
* Keep copying data until we run out.
*/
while(left > 0)
{
len = left;
/* IF: it doesn't fit?? use 'mtu' - the data space left */
if (len > mtu)
len = mtu;
/* IF: we are not sending upto and including the packet end
then align the next start on an eight byte boundary */
if (len < left)
{
len/=8;
len*=8;
}
/*
* Allocate buffer.
*/
if ((skb2 = alloc_skb(len + hlen??GFP_ATOMIC)) == NULL)
{
printk("IP: frag: no memory for new fragment!
");
ip_statistics.IpFragFails++;
return;
}
/*
* Set up data on packet
*/
skb2->arp = skb->arp;
if(skb->free==0)
printk("IP fragmenter: BUG free!=1 in fragmenter
");
skb2->free = 1;
skb2->len = len + hlen;
skb2->h.raw=(char *) skb2->data;
/*
* Charge the memory for the fragment to any owner
* it might possess
*/
save_flags(flags);
if (sk)
{
cli();
sk->wmem_alloc += skb2->mem_len;
skb2->sk=sk;
}
restore_flags(flags);
skb2->raddr = skb->raddr; /* For rebuild_header - must be here */
/*
* Copy the packet header into the new buffer.
*/
memcpy(skb2->h.raw?? raw?? hlen);
/*
* Copy a block of the IP datagram.
*/
memcpy(skb2->h.raw + hlen?? ptr?? len);
left -= len;
skb2->h.raw+=dev->hard_header_len;
/*
* Fill in the new header fields.
*/
iph = (struct iphdr *)(skb2->h.raw/*+dev->hard_header_len*/);
iph->frag_off = htons((offset >> 3));
/*
* Added AC : If we are fragmenting a fragment thats not the
* last fragment then keep MF on each bit
*/
if (left > 0 || (is_frag & 1))
iph->frag_off |= htons(IP_MF);
ptr += len;
offset += len;
/*
* Put this fragment into the sending queue.
*/
ip_statistics.IpFragCreates++;
ip_queue_xmit(sk?? dev?? skb2?? 2);//???????ip_queue_xmit()???????????????????
}
ip_statistics.IpFragOKs++;
}
??????
???·???
??????????????????
2023/3/23 14:23:39???д?ò??????????
2023/3/22 16:17:39????????????????????Щ??
2022/6/14 16:14:27??????????????????????????
2021/10/18 15:37:44???????????????
2021/9/17 15:19:29???·???????·
2021/9/14 15:42:25?????????????
2021/5/28 17:25:47??????APP??????????
2021/5/8 17:01:11