Commit 776c729e authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[IPV4]: Change ip_defrag to return an integer

Now that ip_frag always returns the packet given to it on input, we can
change it to return an integer indicating error instead.  This patch does
that and updates all its callers accordingly.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1706d587
...@@ -332,7 +332,7 @@ enum ip_defrag_users ...@@ -332,7 +332,7 @@ enum ip_defrag_users
IP_DEFRAG_VS_FWD IP_DEFRAG_VS_FWD
}; };
struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user); int ip_defrag(struct sk_buff *skb, u32 user);
extern int ip_frag_nqueues; extern int ip_frag_nqueues;
extern atomic_t ip_frag_mem; extern atomic_t ip_frag_mem;
......
...@@ -739,7 +739,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, ...@@ -739,7 +739,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
} }
/* Process an incoming IP datagram fragment. */ /* Process an incoming IP datagram fragment. */
struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user) int ip_defrag(struct sk_buff *skb, u32 user)
{ {
struct ipq *qp; struct ipq *qp;
...@@ -759,12 +759,12 @@ struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user) ...@@ -759,12 +759,12 @@ struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
spin_unlock(&qp->lock); spin_unlock(&qp->lock);
ipq_put(qp, NULL); ipq_put(qp, NULL);
return ret ? NULL : skb; return ret;
} }
IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
kfree_skb(skb); kfree_skb(skb);
return NULL; return -ENOMEM;
} }
void __init ipfrag_init(void) void __init ipfrag_init(void)
......
...@@ -172,8 +172,7 @@ int ip_call_ra_chain(struct sk_buff *skb) ...@@ -172,8 +172,7 @@ int ip_call_ra_chain(struct sk_buff *skb)
(!sk->sk_bound_dev_if || (!sk->sk_bound_dev_if ||
sk->sk_bound_dev_if == skb->dev->ifindex)) { sk->sk_bound_dev_if == skb->dev->ifindex)) {
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN); if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) {
if (skb == NULL) {
read_unlock(&ip_ra_lock); read_unlock(&ip_ra_lock);
return 1; return 1;
} }
...@@ -265,8 +264,7 @@ int ip_local_deliver(struct sk_buff *skb) ...@@ -265,8 +264,7 @@ int ip_local_deliver(struct sk_buff *skb)
*/ */
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER); if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))
if (!skb)
return 0; return 0;
} }
......
...@@ -541,13 +541,14 @@ __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) ...@@ -541,13 +541,14 @@ __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
} }
static inline struct sk_buff * static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
{ {
skb = ip_defrag(skb, user); int err = ip_defrag(skb, user);
if (skb)
if (!err)
ip_send_check(ip_hdr(skb)); ip_send_check(ip_hdr(skb));
return skb;
return err;
} }
/* /*
...@@ -619,10 +620,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related) ...@@ -619,10 +620,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
/* reassemble IP fragments */ /* reassemble IP fragments */
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT); if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
if (!skb)
return NF_STOLEN; return NF_STOLEN;
*pskb = skb;
} }
iph = ip_hdr(skb); iph = ip_hdr(skb);
...@@ -756,11 +755,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, ...@@ -756,11 +755,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
/* reassemble IP fragments */ /* reassemble IP fragments */
if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) && if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) &&
!pp->dont_defrag)) { !pp->dont_defrag)) {
skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT); if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
if (!skb)
return NF_STOLEN; return NF_STOLEN;
iph = ip_hdr(skb); iph = ip_hdr(skb);
*pskb = skb;
} }
ihl = iph->ihl << 2; ihl = iph->ihl << 2;
...@@ -861,12 +858,9 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum) ...@@ -861,12 +858,9 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
/* reassemble IP fragments */ /* reassemble IP fragments */
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
skb = ip_vs_gather_frags(skb, if (ip_vs_gather_frags(skb, hooknum == NF_IP_LOCAL_IN ?
hooknum == NF_IP_LOCAL_IN ? IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD))
IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD);
if (!skb)
return NF_STOLEN; return NF_STOLEN;
*pskb = skb;
} }
iph = ip_hdr(skb); iph = ip_hdr(skb);
......
...@@ -63,19 +63,20 @@ static int ipv4_print_conntrack(struct seq_file *s, ...@@ -63,19 +63,20 @@ static int ipv4_print_conntrack(struct seq_file *s,
} }
/* Returns new sk_buff, or NULL */ /* Returns new sk_buff, or NULL */
static struct sk_buff * static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
{ {
int err;
skb_orphan(skb); skb_orphan(skb);
local_bh_disable(); local_bh_disable();
skb = ip_defrag(skb, user); err = ip_defrag(skb, user);
local_bh_enable(); local_bh_enable();
if (skb) if (!err)
ip_send_check(ip_hdr(skb)); ip_send_check(ip_hdr(skb));
return skb; return err;
} }
static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, 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,11 +149,10 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
/* Gather fragments. */ /* Gather fragments. */
if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) { if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) {
*pskb = nf_ct_ipv4_gather_frags(*pskb, if (nf_ct_ipv4_gather_frags(*pskb,
hooknum == NF_IP_PRE_ROUTING ? hooknum == NF_IP_PRE_ROUTING ?
IP_DEFRAG_CONNTRACK_IN : IP_DEFRAG_CONNTRACK_IN :
IP_DEFRAG_CONNTRACK_OUT); IP_DEFRAG_CONNTRACK_OUT))
if (!*pskb)
return NF_STOLEN; return NF_STOLEN;
} }
return NF_ACCEPT; return NF_ACCEPT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment