[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>
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index f0dc727..7796511 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -80,6 +80,27 @@
 }
 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 @@
 		      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 @@
 	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 @@
 	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 @@
 
 	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) {