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