aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter/nf_queue.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-12-05 04:27:19 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:56:16 -0500
commitdaaa8be2e0ec1c27d11e6724c8ebd8ed53914ae2 (patch)
tree47a5cc79b1ab10065d382b83c37f11ea4b43a5dc /net/netfilter/nf_queue.c
parent4b3d15ef4a88683d93d1b76351297d2298a02a99 (diff)
[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>
Diffstat (limited to 'net/netfilter/nf_queue.c')
-rw-r--r--net/netfilter/nf_queue.c93
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)
80} 80}
81EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); 81EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
82 82
83static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
84{
85 /* Release those devices we held, or Alexey will kill me. */
86 if (entry->indev)
87 dev_put(entry->indev);
88 if (entry->outdev)
89 dev_put(entry->outdev);
90#ifdef CONFIG_BRIDGE_NETFILTER
91 if (entry->skb->nf_bridge) {
92 struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
93
94 if (nf_bridge->physindev)
95 dev_put(nf_bridge->physindev);
96 if (nf_bridge->physoutdev)
97 dev_put(nf_bridge->physoutdev);
98 }
99#endif
100 /* Drop reference to owner of hook which queued us. */
101 module_put(entry->elem->owner);
102}
103
83/* 104/*
84 * Any packet that leaves via this function must come back 105 * Any packet that leaves via this function must come back
85 * through nf_reinject(). 106 * through nf_reinject().
@@ -93,10 +114,10 @@ static int __nf_queue(struct sk_buff *skb,
93 unsigned int queuenum) 114 unsigned int queuenum)
94{ 115{
95 int status; 116 int status;
96 struct nf_queue_entry *entry; 117 struct nf_queue_entry *entry = NULL;
97#ifdef CONFIG_BRIDGE_NETFILTER 118#ifdef CONFIG_BRIDGE_NETFILTER
98 struct net_device *physindev = NULL; 119 struct net_device *physindev;
99 struct net_device *physoutdev = NULL; 120 struct net_device *physoutdev;
100#endif 121#endif
101 struct nf_afinfo *afinfo; 122 struct nf_afinfo *afinfo;
102 const struct nf_queue_handler *qh; 123 const struct nf_queue_handler *qh;
@@ -105,28 +126,16 @@ static int __nf_queue(struct sk_buff *skb,
105 rcu_read_lock(); 126 rcu_read_lock();
106 127
107 qh = rcu_dereference(queue_handler[pf]); 128 qh = rcu_dereference(queue_handler[pf]);
108 if (!qh) { 129 if (!qh)
109 rcu_read_unlock(); 130 goto err_unlock;
110 kfree_skb(skb);
111 return 1;
112 }
113 131
114 afinfo = nf_get_afinfo(pf); 132 afinfo = nf_get_afinfo(pf);
115 if (!afinfo) { 133 if (!afinfo)
116 rcu_read_unlock(); 134 goto err_unlock;
117 kfree_skb(skb);
118 return 1;
119 }
120 135
121 entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC); 136 entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC);
122 if (!entry) { 137 if (!entry)
123 if (net_ratelimit()) 138 goto err_unlock;
124 printk(KERN_ERR "OOM queueing packet %p\n",
125 skb);
126 rcu_read_unlock();
127 kfree_skb(skb);
128 return 1;
129 }
130 139
131 *entry = (struct nf_queue_entry) { 140 *entry = (struct nf_queue_entry) {
132 .skb = skb, 141 .skb = skb,
@@ -166,25 +175,18 @@ static int __nf_queue(struct sk_buff *skb,
166 rcu_read_unlock(); 175 rcu_read_unlock();
167 176
168 if (status < 0) { 177 if (status < 0) {
169 /* James M doesn't say fuck enough. */ 178 nf_queue_entry_release_refs(entry);
170 if (indev) 179 goto err;
171 dev_put(indev);
172 if (outdev)
173 dev_put(outdev);
174#ifdef CONFIG_BRIDGE_NETFILTER
175 if (physindev)
176 dev_put(physindev);
177 if (physoutdev)
178 dev_put(physoutdev);
179#endif
180 module_put(entry->elem->owner);
181 kfree(entry);
182 kfree_skb(skb);
183
184 return 1;
185 } 180 }
186 181
187 return 1; 182 return 1;
183
184err_unlock:
185 rcu_read_unlock();
186err:
187 kfree_skb(skb);
188 kfree(entry);
189 return 1;
188} 190}
189 191
190int nf_queue(struct sk_buff *skb, 192int nf_queue(struct sk_buff *skb,
@@ -235,22 +237,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
235 237
236 rcu_read_lock(); 238 rcu_read_lock();
237 239
238 /* Release those devices we held, or Alexey will kill me. */ 240 nf_queue_entry_release_refs(entry);
239 if (entry->indev)
240 dev_put(entry->indev);
241 if (entry->outdev)
242 dev_put(entry->outdev);
243#ifdef CONFIG_BRIDGE_NETFILTER
244 if (skb->nf_bridge) {
245 if (skb->nf_bridge->physindev)
246 dev_put(skb->nf_bridge->physindev);
247 if (skb->nf_bridge->physoutdev)
248 dev_put(skb->nf_bridge->physoutdev);
249 }
250#endif
251
252 /* Drop reference to owner of hook which queued us. */
253 module_put(entry->elem->owner);
254 241
255 /* Continue traversal iff userspace said ok... */ 242 /* Continue traversal iff userspace said ok... */
256 if (verdict == NF_REPEAT) { 243 if (verdict == NF_REPEAT) {