转:http://blog.csdn.net/nerdx/article/details/12657661
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1.1 static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
-
{
-
struct sk_buff *prev, *next;
-
int flags, offset;
-
int ihl, end;
-
-
if (qp->last_in & COMPLETE)
-
goto err;
-
-
offset = ntohs(skb->nh.iph->frag_off);
-
flags = offset & ~IP_OFFSET;
-
offset &= IP_OFFSET;
-
offset <<= 3;
-
ihl = skb->nh.iph->ihl * 4;
-
-
end = offset + skb->len - ihl;
-
-
-
if ((flags & IP_MF) == 0) {
-
-
if (end < qp->len ||
-
((qp->last_in & LAST_IN) && end != qp->len))
-
goto err;
-
qp->last_in |= LAST_IN;
-
qp->len = end;
-
} else {
-
if (end&7) {
-
end &= ~7;
-
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-
skb->ip_summed = CHECKSUM_NONE;
-
}
-
if (end > qp->len) {
-
if (qp->last_in & LAST_IN)
-
goto err;
-
qp->len = end;
-
}
-
}
-
if (end == offset)
-
goto err;
-
-
-
-
-
if (pskb_pull(skb, ihl) == NULL)
-
goto err;
-
if (pskb_trim(skb, end-offset))
-
goto err;
-
-
-
-
-
-
prev = NULL;
-
for(next = qp->fragments; next != NULL; next = next->next) {
-
if (FRAG_CB(next)->offset >= offset)
-
break;
-
prev = next;
-
}
-
-
-
-
if (prev) {
-
int i = (FRAG_CB(prev)->offset + prev->len) - offset;
-
-
if (i > 0) {
-
offset += i;
-
if (end <= offset)
-
goto err;
-
if (!pskb_pull(skb, i))
-
goto err;
-
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-
skb->ip_summed = CHECKSUM_NONE;
-
}
-
}
-
-
-
while (next && FRAG_CB(next)->offset < end) {
-
int i = end - FRAG_CB(next)->offset;
-
-
-
if (i < next->len) {
-
-
if (!pskb_pull(next, i))
-
goto err;
-
-
FRAG_CB(next)->offset += i;
-
-
qp->meat -= i;
-
if (next->ip_summed != CHECKSUM_UNNECESSARY)
-
next->ip_summed = CHECKSUM_NONE;
-
break;
-
} else {
-
struct sk_buff *free_it = next;
-
-
next = next->next;
-
-
if (prev)
-
prev->next = next;
-
else
-
qp->fragments = next;
-
qp->meat -= free_it->len;
-
frag_kfree_skb(free_it, NULL);
-
}
-
}
-
-
-
-
FRAG_CB(skb)->offset = offset;
-
-
skb->next = next;
-
if (prev)
-
prev->next = skb;
-
else
-
qp->fragments = skb;
-
-
if (skb->dev)
-
qp->iif = skb->dev->ifindex;
-
skb->dev = NULL;
-
qp->stamp = skb->stamp;
-
qp->meat += skb->len;
-
-
atomic_add(skb->truesize, &ip_frag_mem);
-
if (offset == 0)
-
qp->last_in |= FIRST_IN;
-
-
write_lock(&ipfrag_lock);
-
list_move_tail(&qp->lru_list, &ipq_lru_list);
-
write_unlock(&ipfrag_lock);
-
-
return;
-
-
err:
-
kfree_skb(skb);
-
}
-
阅读(854) | 评论(0) | 转发(0) |