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 262-271 Link Here
262
/* Fake conntrack entry for untracked connections */
262
/* Fake conntrack entry for untracked connections */
263
extern struct ip_conntrack ip_conntrack_untracked;
263
extern struct ip_conntrack ip_conntrack_untracked;
264
264
265
extern int ip_ct_no_defrag;
266
/* Returns new sk_buff, or NULL */
265
/* Returns new sk_buff, or NULL */
267
struct sk_buff *
266
struct sk_buff *
268
ip_ct_gather_frags(struct sk_buff *skb);
267
ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user);
269
268
270
/* Iterate over all conntracks: if iter returns true, it's deleted. */
269
/* Iterate over all conntracks: if iter returns true, it's deleted. */
271
extern void
270
extern void
(-)a/include/net/ip.h (-3 / +14 lines)
Lines 286-294 Link Here
286
/*
286
/*
287
 *	Functions provided by ip_fragment.o
287
 *	Functions provided by ip_fragment.o
288
 */
288
 */
289
 
289
290
struct sk_buff *ip_defrag(struct sk_buff *skb);
290
enum ip_defrag_users
291
extern void ipfrag_flush(void);
291
{
292
	IP_DEFRAG_LOCAL_DELIVER,
293
	IP_DEFRAG_CALL_RA_CHAIN,
294
	IP_DEFRAG_CONNTRACK_IN,
295
	IP_DEFRAG_CONNTRACK_OUT,
296
	IP_DEFRAG_NAT_OUT,
297
	IP_DEFRAG_VS_IN,
298
	IP_DEFRAG_VS_OUT,
299
	IP_DEFRAG_VS_FWD
300
};
301
302
struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user);
292
extern int ip_frag_nqueues;
303
extern int ip_frag_nqueues;
293
extern atomic_t ip_frag_mem;
304
extern atomic_t ip_frag_mem;
294
305
(-)a/net/ipv4/ip_fragment.c (-20 / +13 lines)
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);
(-)a/net/ipv4/ip_input.c (-2 / +2 lines)
Lines 172-178 Link Here
172
		    (!sk->sk_bound_dev_if ||
172
		    (!sk->sk_bound_dev_if ||
173
		     sk->sk_bound_dev_if == skb->dev->ifindex)) {
173
		     sk->sk_bound_dev_if == skb->dev->ifindex)) {
174
			if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
174
			if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
175
				skb = ip_defrag(skb);
175
				skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN);
176
				if (skb == NULL) {
176
				if (skb == NULL) {
177
					read_unlock(&ip_ra_lock);
177
					read_unlock(&ip_ra_lock);
178
					return 1;
178
					return 1;
Lines 273-279 Link Here
273
	 */
273
	 */
274
274
275
	if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
275
	if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
276
		skb = ip_defrag(skb);
276
		skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER);
277
		if (!skb)
277
		if (!skb)
278
			return 0;
278
			return 0;
279
	}
279
	}
(-)a/net/ipv4/ipvs/ip_vs_core.c (-8 / +11 lines)
Lines 544-552 Link Here
544
}
544
}
545
545
546
static inline struct sk_buff *
546
static inline struct sk_buff *
547
ip_vs_gather_frags(struct sk_buff *skb)
547
ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
548
{
548
{
549
	skb = ip_defrag(skb);
549
	skb = ip_defrag(skb, user);
550
	if (skb)
550
	if (skb)
551
		ip_send_check(skb->nh.iph);
551
		ip_send_check(skb->nh.iph);
552
	return skb;
552
	return skb;
Lines 620-626 Link Here
620
620
621
	/* reassemble IP fragments */
621
	/* reassemble IP fragments */
622
	if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
622
	if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
623
		skb = ip_vs_gather_frags(skb);
623
		skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
624
		if (!skb)
624
		if (!skb)
625
			return NF_STOLEN;
625
			return NF_STOLEN;
626
		*pskb = skb;
626
		*pskb = skb;
Lines 759-765 Link Here
759
	/* reassemble IP fragments */
759
	/* reassemble IP fragments */
760
	if (unlikely(iph->frag_off & __constant_htons(IP_MF|IP_OFFSET) &&
760
	if (unlikely(iph->frag_off & __constant_htons(IP_MF|IP_OFFSET) &&
761
		     !pp->dont_defrag)) {
761
		     !pp->dont_defrag)) {
762
		skb = ip_vs_gather_frags(skb);
762
		skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
763
		if (!skb)
763
		if (!skb)
764
			return NF_STOLEN;
764
			return NF_STOLEN;
765
		iph = skb->nh.iph;
765
		iph = skb->nh.iph;
Lines 839-845 Link Here
839
 *	forward to the right destination host if relevant.
839
 *	forward to the right destination host if relevant.
840
 *	Currently handles error types - unreachable, quench, ttl exceeded.
840
 *	Currently handles error types - unreachable, quench, ttl exceeded.
841
 */
841
 */
842
static int ip_vs_in_icmp(struct sk_buff **pskb, int *related)
842
static int 
843
ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
843
{
844
{
844
	struct sk_buff *skb = *pskb;
845
	struct sk_buff *skb = *pskb;
845
	struct iphdr *iph;
846
	struct iphdr *iph;
Lines 853-859 Link Here
853
854
854
	/* reassemble IP fragments */
855
	/* reassemble IP fragments */
855
	if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
856
	if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
856
		skb = ip_vs_gather_frags(skb);
857
		skb = ip_vs_gather_frags(skb,
858
		                         hooknum == NF_IP_LOCAL_IN ?
859
					 IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD);
857
		if (!skb)
860
		if (!skb)
858
			return NF_STOLEN;
861
			return NF_STOLEN;
859
		*pskb = skb;
862
		*pskb = skb;
Lines 962-968 Link Here
962
965
963
	iph = skb->nh.iph;
966
	iph = skb->nh.iph;
964
	if (unlikely(iph->protocol == IPPROTO_ICMP)) {
967
	if (unlikely(iph->protocol == IPPROTO_ICMP)) {
965
		int related, verdict = ip_vs_in_icmp(pskb, &related);
968
		int related, verdict = ip_vs_in_icmp(pskb, &related, hooknum);
966
969
967
		if (related)
970
		if (related)
968
			return verdict;
971
			return verdict;
Lines 1057-1063 Link Here
1057
	if ((*pskb)->nh.iph->protocol != IPPROTO_ICMP)
1060
	if ((*pskb)->nh.iph->protocol != IPPROTO_ICMP)
1058
		return NF_ACCEPT;
1061
		return NF_ACCEPT;
1059
1062
1060
	return ip_vs_in_icmp(pskb, &r);
1063
	return ip_vs_in_icmp(pskb, &r, hooknum);
1061
}
1064
}
1062
1065
1063
1066
(-)a/net/ipv4/netfilter/ip_conntrack_core.c (-9 / +2 lines)
Lines 936-964 Link Here
936
	}
936
	}
937
}
937
}
938
938
939
int ip_ct_no_defrag;
940
941
/* Returns new sk_buff, or NULL */
939
/* Returns new sk_buff, or NULL */
942
struct sk_buff *
940
struct sk_buff *
943
ip_ct_gather_frags(struct sk_buff *skb)
941
ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
944
{
942
{
945
	struct sock *sk = skb->sk;
943
	struct sock *sk = skb->sk;
946
#ifdef CONFIG_NETFILTER_DEBUG
944
#ifdef CONFIG_NETFILTER_DEBUG
947
	unsigned int olddebug = skb->nf_debug;
945
	unsigned int olddebug = skb->nf_debug;
948
#endif
946
#endif
949
947
950
	if (unlikely(ip_ct_no_defrag)) {
951
		kfree_skb(skb);
952
		return NULL;
953
	}
954
955
	if (sk) {
948
	if (sk) {
956
		sock_hold(sk);
949
		sock_hold(sk);
957
		skb_orphan(skb);
950
		skb_orphan(skb);
958
	}
951
	}
959
952
960
	local_bh_disable(); 
953
	local_bh_disable(); 
961
	skb = ip_defrag(skb);
954
	skb = ip_defrag(skb, user);
962
	local_bh_enable();
955
	local_bh_enable();
963
956
964
	if (!skb) {
957
	if (!skb) {
(-)a/net/ipv4/netfilter/ip_conntrack_standalone.c (-7 / +4 lines)
Lines 391-397 Link Here
391
391
392
	/* Gather fragments. */
392
	/* Gather fragments. */
393
	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
393
	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
394
		*pskb = ip_ct_gather_frags(*pskb);
394
		*pskb = ip_ct_gather_frags(*pskb,
395
		                           hooknum == NF_IP_PRE_ROUTING ? 
396
					   IP_DEFRAG_CONNTRACK_IN :
397
					   IP_DEFRAG_CONNTRACK_OUT);
395
		if (!*pskb)
398
		if (!*pskb)
396
			return NF_STOLEN;
399
			return NF_STOLEN;
397
	}
400
	}
Lines 823-834 Link Here
823
 cleanup_defraglocalops:
826
 cleanup_defraglocalops:
824
	nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
827
	nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
825
 cleanup_defragops:
828
 cleanup_defragops:
826
	/* Frag queues may hold fragments with skb->dst == NULL */
827
	ip_ct_no_defrag = 1;
828
	synchronize_net();
829
	local_bh_disable();
830
	ipfrag_flush();
831
	local_bh_enable();
832
	nf_unregister_hook(&ip_conntrack_defrag_ops);
829
	nf_unregister_hook(&ip_conntrack_defrag_ops);
833
 cleanup_proc_stat:
830
 cleanup_proc_stat:
834
#ifdef CONFIG_PROC_FS
831
#ifdef CONFIG_PROC_FS
(-)a/net/ipv4/netfilter/ip_nat_standalone.c (-1 / +1 lines)
Lines 195-201 Link Here
195
	   I'm starting to have nightmares about fragments.  */
195
	   I'm starting to have nightmares about fragments.  */
196
196
197
	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
197
	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
198
		*pskb = ip_ct_gather_frags(*pskb);
198
		*pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT);
199
199
200
		if (!*pskb)
200
		if (!*pskb)
201
			return NF_STOLEN;
201
			return NF_STOLEN;
(-)a/net/ipv4/ip_output.c (+1 lines)
Lines 504-509 Link Here
504
			/* Prepare header of the next frame,
504
			/* Prepare header of the next frame,
505
			 * before previous one went down. */
505
			 * before previous one went down. */
506
			if (frag) {
506
			if (frag) {
507
				frag->ip_summed = CHECKSUM_NONE;
507
				frag->h.raw = frag->data;
508
				frag->h.raw = frag->data;
508
				frag->nh.raw = __skb_push(frag, hlen);
509
				frag->nh.raw = __skb_push(frag, hlen);
509
				memcpy(frag->nh.raw, iph, hlen);
510
				memcpy(frag->nh.raw, iph, hlen);
(-)a/net/ipv6/ip6_output.c (+1 lines)
Lines 592-597 Link Here
592
			/* Prepare header of the next frame,
592
			/* Prepare header of the next frame,
593
			 * before previous one went down. */
593
			 * before previous one went down. */
594
			if (frag) {
594
			if (frag) {
595
				frag->ip_summed = CHECKSUM_NONE;
595
				frag->h.raw = frag->data;
596
				frag->h.raw = frag->data;
596
				fh = (struct frag_hdr*)__skb_push(frag, sizeof(struct frag_hdr));
597
				fh = (struct frag_hdr*)__skb_push(frag, sizeof(struct frag_hdr));
597
				frag->nh.raw = __skb_push(frag, hlen);
598
				frag->nh.raw = __skb_push(frag, hlen);

Return to bug 81195