aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ip.h2
-rw-r--r--net/ipv4/ip_fragment.c6
-rw-r--r--net/ipv4/ip_input.c6
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c26
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c20
5 files changed, 26 insertions, 34 deletions
diff --git a/include/net/ip.h b/include/net/ip.h
index 3af3ed9d320b..875c5ed53343 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -332,7 +332,7 @@ enum ip_defrag_users
332 IP_DEFRAG_VS_FWD 332 IP_DEFRAG_VS_FWD
333}; 333};
334 334
335struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user); 335int ip_defrag(struct sk_buff *skb, u32 user);
336extern int ip_frag_nqueues; 336extern int ip_frag_nqueues;
337extern atomic_t ip_frag_mem; 337extern atomic_t ip_frag_mem;
338 338
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index d7fa2bf3a0c1..32108cf2a784 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -739,7 +739,7 @@ out_fail:
739} 739}
740 740
741/* Process an incoming IP datagram fragment. */ 741/* Process an incoming IP datagram fragment. */
742struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user) 742int ip_defrag(struct sk_buff *skb, u32 user)
743{ 743{
744 struct ipq *qp; 744 struct ipq *qp;
745 745
@@ -759,12 +759,12 @@ struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
759 759
760 spin_unlock(&qp->lock); 760 spin_unlock(&qp->lock);
761 ipq_put(qp, NULL); 761 ipq_put(qp, NULL);
762 return ret ? NULL : skb; 762 return ret;
763 } 763 }
764 764
765 IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); 765 IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
766 kfree_skb(skb); 766 kfree_skb(skb);
767 return NULL; 767 return -ENOMEM;
768} 768}
769 769
770void __init ipfrag_init(void) 770void __init ipfrag_init(void)
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 41d8964591e7..8f75e43ad3b3 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -172,8 +172,7 @@ int ip_call_ra_chain(struct sk_buff *skb)
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 (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { 174 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
175 skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN); 175 if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) {
176 if (skb == NULL) {
177 read_unlock(&ip_ra_lock); 176 read_unlock(&ip_ra_lock);
178 return 1; 177 return 1;
179 } 178 }
@@ -265,8 +264,7 @@ int ip_local_deliver(struct sk_buff *skb)
265 */ 264 */
266 265
267 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { 266 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
268 skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER); 267 if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))
269 if (!skb)
270 return 0; 268 return 0;
271 } 269 }
272 270
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index fbca2a2ff29f..3487337192c6 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -541,13 +541,14 @@ __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
541 return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); 541 return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
542} 542}
543 543
544static inline struct sk_buff * 544static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
545ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
546{ 545{
547 skb = ip_defrag(skb, user); 546 int err = ip_defrag(skb, user);
548 if (skb) 547
548 if (!err)
549 ip_send_check(ip_hdr(skb)); 549 ip_send_check(ip_hdr(skb));
550 return skb; 550
551 return err;
551} 552}
552 553
553/* 554/*
@@ -619,10 +620,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
619 620
620 /* reassemble IP fragments */ 621 /* reassemble IP fragments */
621 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { 622 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
622 skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT); 623 if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
623 if (!skb)
624 return NF_STOLEN; 624 return NF_STOLEN;
625 *pskb = skb;
626 } 625 }
627 626
628 iph = ip_hdr(skb); 627 iph = ip_hdr(skb);
@@ -756,11 +755,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
756 /* reassemble IP fragments */ 755 /* reassemble IP fragments */
757 if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) && 756 if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) &&
758 !pp->dont_defrag)) { 757 !pp->dont_defrag)) {
759 skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT); 758 if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
760 if (!skb)
761 return NF_STOLEN; 759 return NF_STOLEN;
762 iph = ip_hdr(skb); 760 iph = ip_hdr(skb);
763 *pskb = skb;
764 } 761 }
765 762
766 ihl = iph->ihl << 2; 763 ihl = iph->ihl << 2;
@@ -861,12 +858,9 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
861 858
862 /* reassemble IP fragments */ 859 /* reassemble IP fragments */
863 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { 860 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
864 skb = ip_vs_gather_frags(skb, 861 if (ip_vs_gather_frags(skb, hooknum == NF_IP_LOCAL_IN ?
865 hooknum == NF_IP_LOCAL_IN ? 862 IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD))
866 IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD);
867 if (!skb)
868 return NF_STOLEN; 863 return NF_STOLEN;
869 *pskb = skb;
870 } 864 }
871 865
872 iph = ip_hdr(skb); 866 iph = ip_hdr(skb);
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 2fcb9249a8da..48fdd9eb1c71 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -63,19 +63,20 @@ static int ipv4_print_conntrack(struct seq_file *s,
63} 63}
64 64
65/* Returns new sk_buff, or NULL */ 65/* Returns new sk_buff, or NULL */
66static struct sk_buff * 66static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
67nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
68{ 67{
68 int err;
69
69 skb_orphan(skb); 70 skb_orphan(skb);
70 71
71 local_bh_disable(); 72 local_bh_disable();
72 skb = ip_defrag(skb, user); 73 err = ip_defrag(skb, user);
73 local_bh_enable(); 74 local_bh_enable();
74 75
75 if (skb) 76 if (!err)
76 ip_send_check(ip_hdr(skb)); 77 ip_send_check(ip_hdr(skb));
77 78
78 return skb; 79 return err;
79} 80}
80 81
81static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, 82static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
@@ -148,11 +149,10 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
148 149
149 /* Gather fragments. */ 150 /* Gather fragments. */
150 if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) { 151 if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) {
151 *pskb = nf_ct_ipv4_gather_frags(*pskb, 152 if (nf_ct_ipv4_gather_frags(*pskb,
152 hooknum == NF_IP_PRE_ROUTING ? 153 hooknum == NF_IP_PRE_ROUTING ?
153 IP_DEFRAG_CONNTRACK_IN : 154 IP_DEFRAG_CONNTRACK_IN :
154 IP_DEFRAG_CONNTRACK_OUT); 155 IP_DEFRAG_CONNTRACK_OUT))
155 if (!*pskb)
156 return NF_STOLEN; 156 return NF_STOLEN;
157 } 157 }
158 return NF_ACCEPT; 158 return NF_ACCEPT;