diff options
author | Patrick McHardy <kaber@trash.net> | 2007-12-05 01:27:19 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 14:56:16 -0800 |
commit | daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2 (patch) | |
tree | 47a5cc79b1ab10065d382b83c37f11ea4b43a5dc | |
parent | 4b3d15ef4a88683d93d1b76351297d2298a02a99 (diff) | |
download | linux-3.10-daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2.tar.gz linux-3.10-daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2.tar.bz2 linux-3.10-daaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2.zip |
[NETFILTER]: nf_queue: clean up error paths
Move duplicated error handling to end of function and add a helper function
to release the device and module references from the queue entry.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/netfilter/nf_queue.c | 93 |
1 files changed, 40 insertions, 53 deletions
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index f0dc7270411..77965114b09 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -80,6 +80,27 @@ void nf_unregister_queue_handlers(const struct nf_queue_handler *qh) } EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); +static void nf_queue_entry_release_refs(struct nf_queue_entry *entry) +{ + /* Release those devices we held, or Alexey will kill me. */ + if (entry->indev) + dev_put(entry->indev); + if (entry->outdev) + dev_put(entry->outdev); +#ifdef CONFIG_BRIDGE_NETFILTER + if (entry->skb->nf_bridge) { + struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; + + if (nf_bridge->physindev) + dev_put(nf_bridge->physindev); + if (nf_bridge->physoutdev) + dev_put(nf_bridge->physoutdev); + } +#endif + /* Drop reference to owner of hook which queued us. */ + module_put(entry->elem->owner); +} + /* * Any packet that leaves via this function must come back * through nf_reinject(). @@ -93,10 +114,10 @@ static int __nf_queue(struct sk_buff *skb, unsigned int queuenum) { int status; - struct nf_queue_entry *entry; + struct nf_queue_entry *entry = NULL; #ifdef CONFIG_BRIDGE_NETFILTER - struct net_device *physindev = NULL; - struct net_device *physoutdev = NULL; + struct net_device *physindev; + struct net_device *physoutdev; #endif struct nf_afinfo *afinfo; const struct nf_queue_handler *qh; @@ -105,28 +126,16 @@ static int __nf_queue(struct sk_buff *skb, rcu_read_lock(); qh = rcu_dereference(queue_handler[pf]); - if (!qh) { - rcu_read_unlock(); - kfree_skb(skb); - return 1; - } + if (!qh) + goto err_unlock; afinfo = nf_get_afinfo(pf); - if (!afinfo) { - rcu_read_unlock(); - kfree_skb(skb); - return 1; - } + if (!afinfo) + goto err_unlock; entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC); - if (!entry) { - if (net_ratelimit()) - printk(KERN_ERR "OOM queueing packet %p\n", - skb); - rcu_read_unlock(); - kfree_skb(skb); - return 1; - } + if (!entry) + goto err_unlock; *entry = (struct nf_queue_entry) { .skb = skb, @@ -166,25 +175,18 @@ static int __nf_queue(struct sk_buff *skb, rcu_read_unlock(); if (status < 0) { - /* James M doesn't say fuck enough. */ - if (indev) - dev_put(indev); - if (outdev) - dev_put(outdev); -#ifdef CONFIG_BRIDGE_NETFILTER - if (physindev) - dev_put(physindev); - if (physoutdev) - dev_put(physoutdev); -#endif - module_put(entry->elem->owner); - kfree(entry); - kfree_skb(skb); - - return 1; + nf_queue_entry_release_refs(entry); + goto err; } return 1; + +err_unlock: + rcu_read_unlock(); +err: + kfree_skb(skb); + kfree(entry); + return 1; } int nf_queue(struct sk_buff *skb, @@ -235,22 +237,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) rcu_read_lock(); - /* Release those devices we held, or Alexey will kill me. */ - if (entry->indev) - dev_put(entry->indev); - if (entry->outdev) - dev_put(entry->outdev); -#ifdef CONFIG_BRIDGE_NETFILTER - if (skb->nf_bridge) { - if (skb->nf_bridge->physindev) - dev_put(skb->nf_bridge->physindev); - if (skb->nf_bridge->physoutdev) - dev_put(skb->nf_bridge->physoutdev); - } -#endif - - /* Drop reference to owner of hook which queued us. */ - module_put(entry->elem->owner); + nf_queue_entry_release_refs(entry); /* Continue traversal iff userspace said ok... */ if (verdict == NF_REPEAT) { |