Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 81195 | Differences between
and this patch

Collapse All | Expand All

(-)a/include/linux/netfilter_ipv4/ip_conntrack.h (-2 / +1 lines)
Lines 249-258 Link Here
249
/* Call me when a conntrack is destroyed. */
249
/* Call me when a conntrack is destroyed. */
250
extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
250
extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
251
251
252
extern int ip_ct_no_defrag;
253
/* Returns new sk_buff, or NULL */
252
/* Returns new sk_buff, or NULL */
254
struct sk_buff *
253
struct sk_buff *
255
ip_ct_gather_frags(struct sk_buff *skb);
254
ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user);
256
255
257
/* Delete all conntracks which match. */
256
/* Delete all conntracks which match. */
258
extern void
257
extern void
(-)a/include/net/ip.h (-3 / +13 lines)
Lines 227-235 Link Here
227
/*
227
/*
228
 *	Functions provided by ip_fragment.o
228
 *	Functions provided by ip_fragment.o
229
 */
229
 */
230
 
230
231
struct sk_buff *ip_defrag(struct sk_buff *skb);
231
enum ip_defrag_users
232
extern void ipfrag_flush(void);
232
{
233
	IP_DEFRAG_LOCAL_DELIVER,
234
	IP_DEFRAG_CALL_RA_CHAIN,
235
	IP_DEFRAG_CONNTRACK_IN,
236
	IP_DEFRAG_CONNTRACK_OUT,
237
	IP_DEFRAG_NAT_OUT,
238
	IP_DEFRAG_VS_OUT,
239
	IP_DEFRAG_VS_FWD
240
};
241
242
struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user);
233
extern int ip_frag_nqueues;
243
extern int ip_frag_nqueues;
234
extern atomic_t ip_frag_mem;
244
extern atomic_t ip_frag_mem;
235
245
(-)a/net/ipv4/ip_fragment.c (-19 / +13 lines)
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
}
(-)a/net/ipv4/ip_input.c (-2 / +2 lines)
Lines 170-176 Link Here
170
		    && ((sk->bound_dev_if == 0) 
170
		    && ((sk->bound_dev_if == 0) 
171
			|| (sk->bound_dev_if == skb->dev->ifindex))) {
171
			|| (sk->bound_dev_if == skb->dev->ifindex))) {
172
			if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
172
			if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
173
				skb = ip_defrag(skb);
173
				skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN);
174
				if (skb == NULL) {
174
				if (skb == NULL) {
175
					read_unlock(&ip_ra_lock);
175
					read_unlock(&ip_ra_lock);
176
					return 1;
176
					return 1;
Lines 291-297 Link Here
291
	 */
291
	 */
292
292
293
	if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
293
	if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
294
		skb = ip_defrag(skb);
294
		skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER);
295
		if (!skb)
295
		if (!skb)
296
			return 0;
296
			return 0;
297
	}
297
	}
(-)a/net/ipv4/ipvs/ip_vs_core.c (-3 / +3 lines)
Lines 506-512 Link Here
506
506
507
	/* reassemble IP fragments, but will it happen in ICMP packets?? */
507
	/* reassemble IP fragments, but will it happen in ICMP packets?? */
508
	if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
508
	if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
509
		skb = ip_defrag(skb);
509
		skb = ip_defrag(skb, IP_DEFRAG_VS_OUT);
510
		if (!skb)
510
		if (!skb)
511
			return NF_STOLEN;
511
			return NF_STOLEN;
512
		*skb_p = skb;
512
		*skb_p = skb;
Lines 658-664 Link Here
658
658
659
	/* reassemble IP fragments */
659
	/* reassemble IP fragments */
660
	if (iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
660
	if (iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
661
		skb = ip_defrag(skb);
661
		skb = ip_defrag(skb, IP_DEFRAG_VS_OUT);
662
		if (!skb)
662
		if (!skb)
663
			return NF_STOLEN;
663
			return NF_STOLEN;
664
		iph = skb->nh.iph;
664
		iph = skb->nh.iph;
Lines 1164-1170 Link Here
1164
		return NF_ACCEPT;
1164
		return NF_ACCEPT;
1165
1165
1166
	if (iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
1166
	if (iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
1167
		skb = ip_defrag(skb);
1167
		skb = ip_defrag(skb, IP_DEFRAG_VS_FWD);
1168
		if (!skb)
1168
		if (!skb)
1169
			return NF_STOLEN;
1169
			return NF_STOLEN;
1170
		*skb_p = skb;
1170
		*skb_p = skb;
(-)a/net/ipv4/netfilter/ip_conntrack_core.c (-10 / +6 lines)
Lines 834-840 Link Here
834
834
835
	/* Gather fragments. */
835
	/* Gather fragments. */
836
	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
836
	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
837
		*pskb = ip_ct_gather_frags(*pskb);
837
		*pskb = ip_ct_gather_frags(*pskb,
838
		                           hooknum == NF_IP_PRE_ROUTING ?
839
		                           IP_DEFRAG_CONNTRACK_IN :
840
		                           IP_DEFRAG_CONNTRACK_OUT);
838
		if (!*pskb)
841
		if (!*pskb)
839
			return NF_STOLEN;
842
			return NF_STOLEN;
840
	}
843
	}
Lines 1183-1211 Link Here
1183
	WRITE_UNLOCK(&ip_conntrack_lock);
1186
	WRITE_UNLOCK(&ip_conntrack_lock);
1184
}
1187
}
1185
1188
1186
int ip_ct_no_defrag;
1187
1188
/* Returns new sk_buff, or NULL */
1189
/* Returns new sk_buff, or NULL */
1189
struct sk_buff *
1190
struct sk_buff *
1190
ip_ct_gather_frags(struct sk_buff *skb)
1191
ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
1191
{
1192
{
1192
	struct sock *sk = skb->sk;
1193
	struct sock *sk = skb->sk;
1193
#ifdef CONFIG_NETFILTER_DEBUG
1194
#ifdef CONFIG_NETFILTER_DEBUG
1194
	unsigned int olddebug = skb->nf_debug;
1195
	unsigned int olddebug = skb->nf_debug;
1195
#endif
1196
#endif
1196
1197
1197
	if (unlikely(ip_ct_no_defrag)) {
1198
		kfree_skb(skb);
1199
		return NULL;
1200
	}
1201
1202
	if (sk) {
1198
	if (sk) {
1203
		sock_hold(sk);
1199
		sock_hold(sk);
1204
		skb_orphan(skb);
1200
		skb_orphan(skb);
1205
	}
1201
	}
1206
1202
1207
	local_bh_disable(); 
1203
	local_bh_disable(); 
1208
	skb = ip_defrag(skb);
1204
	skb = ip_defrag(skb, user);
1209
	local_bh_enable();
1205
	local_bh_enable();
1210
1206
1211
	if (!skb) {
1207
	if (!skb) {
(-)a/net/ipv4/netfilter/ip_conntrack_standalone.c (-7 lines)
Lines 393-405 Link Here
393
 cleanup_inandlocalops:
393
 cleanup_inandlocalops:
394
	nf_unregister_hook(&ip_conntrack_local_out_ops);
394
	nf_unregister_hook(&ip_conntrack_local_out_ops);
395
 cleanup_inops:
395
 cleanup_inops:
396
	/* Frag queues may hold fragments with skb->dst == NULL */
397
	ip_ct_no_defrag = 1;
398
	local_bh_disable();
399
	br_write_lock(BR_NETPROTO_LOCK);
400
	br_write_unlock(BR_NETPROTO_LOCK);
401
	ipfrag_flush();
402
	local_bh_enable();
403
	nf_unregister_hook(&ip_conntrack_in_ops);
396
	nf_unregister_hook(&ip_conntrack_in_ops);
404
 cleanup_proc:
397
 cleanup_proc:
405
	proc_net_remove("ip_conntrack");
398
	proc_net_remove("ip_conntrack");
(-)a/net/ipv4/netfilter/ip_nat_standalone.c (-1 / +1 lines)
Lines 201-207 Link Here
201
	   I'm starting to have nightmares about fragments.  */
201
	   I'm starting to have nightmares about fragments.  */
202
202
203
	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
203
	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
204
		*pskb = ip_ct_gather_frags(*pskb);
204
		*pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT);
205
205
206
		if (!*pskb)
206
		if (!*pskb)
207
			return NF_STOLEN;
207
			return NF_STOLEN;
(-)a/net/netsyms.c (-1 lines)
Lines 287-293 Link Here
287
EXPORT_SYMBOL(inetdev_by_index);
287
EXPORT_SYMBOL(inetdev_by_index);
288
EXPORT_SYMBOL(in_dev_finish_destroy);
288
EXPORT_SYMBOL(in_dev_finish_destroy);
289
EXPORT_SYMBOL(ip_defrag);
289
EXPORT_SYMBOL(ip_defrag);
290
EXPORT_SYMBOL(ipfrag_flush);
291
290
292
/* Route manipulation */
291
/* Route manipulation */
293
EXPORT_SYMBOL(ip_rt_ioctl);
292
EXPORT_SYMBOL(ip_rt_ioctl);

Return to bug 81195