diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/ip_fragment.c | 6 | ||||
-rw-r--r-- | net/ipv4/ip_input.c | 6 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_core.c | 26 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 20 |
4 files changed, 25 insertions, 33 deletions
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. */ |
742 | struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user) | 742 | int 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 | ||
770 | void __init ipfrag_init(void) | 770 | void __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 | ||
544 | static inline struct sk_buff * | 544 | static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) |
545 | ip_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 */ |
66 | static struct sk_buff * | 66 | static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) |
67 | nf_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 | ||
81 | static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, | 82 | static 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; |