Lines 72-77
Link Here
|
72 |
struct ipq { |
72 |
struct ipq { |
73 |
struct ipq *next; /* linked list pointers */ |
73 |
struct ipq *next; /* linked list pointers */ |
74 |
struct list_head lru_list; /* lru list member */ |
74 |
struct list_head lru_list; /* lru list member */ |
|
|
75 |
u32 user; |
75 |
u32 saddr; |
76 |
u32 saddr; |
76 |
u32 daddr; |
77 |
u32 daddr; |
77 |
u16 id; |
78 |
u16 id; |
Lines 242-254
Link Here
|
242 |
/* Memory limiting on fragments. Evictor trashes the oldest |
243 |
/* Memory limiting on fragments. Evictor trashes the oldest |
243 |
* fragment queue until we are back under the threshold. |
244 |
* fragment queue until we are back under the threshold. |
244 |
*/ |
245 |
*/ |
245 |
static void __ip_evictor(int threshold) |
246 |
static void ip_evictor(void) |
246 |
{ |
247 |
{ |
247 |
struct ipq *qp; |
248 |
struct ipq *qp; |
248 |
struct list_head *tmp; |
249 |
struct list_head *tmp; |
249 |
int work; |
250 |
int work; |
250 |
|
251 |
|
251 |
work = atomic_read(&ip_frag_mem) - threshold; |
252 |
work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh; |
252 |
if (work <= 0) |
253 |
if (work <= 0) |
253 |
return; |
254 |
return; |
254 |
|
255 |
|
Lines 273-283
Link Here
|
273 |
} |
274 |
} |
274 |
} |
275 |
} |
275 |
|
276 |
|
276 |
static inline void ip_evictor(void) |
|
|
277 |
{ |
278 |
__ip_evictor(sysctl_ipfrag_low_thresh); |
279 |
} |
280 |
|
281 |
/* |
277 |
/* |
282 |
* Oops, a fragment queue timed out. Kill it and send an ICMP reply. |
278 |
* Oops, a fragment queue timed out. Kill it and send an ICMP reply. |
283 |
*/ |
279 |
*/ |
Lines 324-330
Link Here
|
324 |
if(qp->id == qp_in->id && |
320 |
if(qp->id == qp_in->id && |
325 |
qp->saddr == qp_in->saddr && |
321 |
qp->saddr == qp_in->saddr && |
326 |
qp->daddr == qp_in->daddr && |
322 |
qp->daddr == qp_in->daddr && |
327 |
qp->protocol == qp_in->protocol) { |
323 |
qp->protocol == qp_in->protocol && |
|
|
324 |
qp->user == qp_in->user) { |
328 |
atomic_inc(&qp->refcnt); |
325 |
atomic_inc(&qp->refcnt); |
329 |
write_unlock(&ipfrag_lock); |
326 |
write_unlock(&ipfrag_lock); |
330 |
qp_in->last_in |= COMPLETE; |
327 |
qp_in->last_in |= COMPLETE; |
Lines 351-357
Link Here
|
351 |
} |
348 |
} |
352 |
|
349 |
|
353 |
/* Add an entry to the 'ipq' queue for a newly received IP datagram. */ |
350 |
/* Add an entry to the 'ipq' queue for a newly received IP datagram. */ |
354 |
static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph) |
351 |
static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) |
355 |
{ |
352 |
{ |
356 |
struct ipq *qp; |
353 |
struct ipq *qp; |
357 |
|
354 |
|
Lines 363-368
Link Here
|
363 |
qp->id = iph->id; |
360 |
qp->id = iph->id; |
364 |
qp->saddr = iph->saddr; |
361 |
qp->saddr = iph->saddr; |
365 |
qp->daddr = iph->daddr; |
362 |
qp->daddr = iph->daddr; |
|
|
363 |
qp->user = user; |
366 |
qp->len = 0; |
364 |
qp->len = 0; |
367 |
qp->meat = 0; |
365 |
qp->meat = 0; |
368 |
qp->fragments = NULL; |
366 |
qp->fragments = NULL; |
Lines 385-391
Link Here
|
385 |
/* Find the correct entry in the "incomplete datagrams" queue for |
383 |
/* Find the correct entry in the "incomplete datagrams" queue for |
386 |
* this IP datagram, and create new one, if nothing is found. |
384 |
* this IP datagram, and create new one, if nothing is found. |
387 |
*/ |
385 |
*/ |
388 |
static inline struct ipq *ip_find(struct iphdr *iph) |
386 |
static inline struct ipq *ip_find(struct iphdr *iph, u32 user) |
389 |
{ |
387 |
{ |
390 |
__u16 id = iph->id; |
388 |
__u16 id = iph->id; |
391 |
__u32 saddr = iph->saddr; |
389 |
__u32 saddr = iph->saddr; |
Lines 399-405
Link Here
|
399 |
if(qp->id == id && |
397 |
if(qp->id == id && |
400 |
qp->saddr == saddr && |
398 |
qp->saddr == saddr && |
401 |
qp->daddr == daddr && |
399 |
qp->daddr == daddr && |
402 |
qp->protocol == protocol) { |
400 |
qp->protocol == protocol && |
|
|
401 |
qp->user == user) { |
403 |
atomic_inc(&qp->refcnt); |
402 |
atomic_inc(&qp->refcnt); |
404 |
read_unlock(&ipfrag_lock); |
403 |
read_unlock(&ipfrag_lock); |
405 |
return qp; |
404 |
return qp; |
Lines 407-413
Link Here
|
407 |
} |
406 |
} |
408 |
read_unlock(&ipfrag_lock); |
407 |
read_unlock(&ipfrag_lock); |
409 |
|
408 |
|
410 |
return ip_frag_create(hash, iph); |
409 |
return ip_frag_create(hash, iph, user); |
411 |
} |
410 |
} |
412 |
|
411 |
|
413 |
/* Add new segment to existing queue. */ |
412 |
/* Add new segment to existing queue. */ |
Lines 641-647
Link Here
|
641 |
} |
640 |
} |
642 |
|
641 |
|
643 |
/* Process an incoming IP datagram fragment. */ |
642 |
/* Process an incoming IP datagram fragment. */ |
644 |
struct sk_buff *ip_defrag(struct sk_buff *skb) |
643 |
struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user) |
645 |
{ |
644 |
{ |
646 |
struct iphdr *iph = skb->nh.iph; |
645 |
struct iphdr *iph = skb->nh.iph; |
647 |
struct ipq *qp; |
646 |
struct ipq *qp; |
Lines 656-662
Link Here
|
656 |
dev = skb->dev; |
655 |
dev = skb->dev; |
657 |
|
656 |
|
658 |
/* Lookup (or create) queue header */ |
657 |
/* Lookup (or create) queue header */ |
659 |
if ((qp = ip_find(iph)) != NULL) { |
658 |
if ((qp = ip_find(iph, user)) != NULL) { |
660 |
struct sk_buff *ret = NULL; |
659 |
struct sk_buff *ret = NULL; |
661 |
|
660 |
|
662 |
spin_lock(&qp->lock); |
661 |
spin_lock(&qp->lock); |
Lines 686-694
Link Here
|
686 |
ipfrag_secret_timer.function = ipfrag_secret_rebuild; |
685 |
ipfrag_secret_timer.function = ipfrag_secret_rebuild; |
687 |
ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval; |
686 |
ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval; |
688 |
add_timer(&ipfrag_secret_timer); |
687 |
add_timer(&ipfrag_secret_timer); |
689 |
} |
|
|
690 |
|
691 |
void ipfrag_flush(void) |
692 |
{ |
693 |
__ip_evictor(0); |
694 |
} |
688 |
} |