diff options
author | Patrick McHardy <kaber@trash.net> | 2007-12-05 04:25:30 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:56:12 -0500 |
commit | b43d8d85987bf21578e270c9f57c8503114ff399 (patch) | |
tree | 20a6fc625a2909bfd55e2d480d74398aa2ad11e0 | |
parent | 0ac41e81462de20f87242caac2b9084c202c33b7 (diff) |
[NETFILTER]: nfnetlink_queue: deobfuscate entry lookups
A queue entry lookup currently looks like this:
find_dequeue_entry -> __find_dequeue_entry ->
__find_entry -> cmpfn -> id_cmp
Use simple open-coded list walking and kill the cmpfn for
find_dequeue_entry. Instead add it to nfqnl_flush (after
similar cleanups) and use nfqnl_flush for both complete
flushes and flushing entries related to a device.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/netfilter/nfnetlink_queue.c | 100 |
1 files changed, 31 insertions, 69 deletions
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 74d5ed9490a9..cb901cf75776 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -171,7 +171,8 @@ out_unlock: | |||
171 | return NULL; | 171 | return NULL; |
172 | } | 172 | } |
173 | 173 | ||
174 | static void nfqnl_flush(struct nfqnl_instance *queue, int verdict); | 174 | static void nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, |
175 | unsigned long data); | ||
175 | 176 | ||
176 | static void | 177 | static void |
177 | _instance_destroy2(struct nfqnl_instance *inst, int lock) | 178 | _instance_destroy2(struct nfqnl_instance *inst, int lock) |
@@ -188,7 +189,7 @@ _instance_destroy2(struct nfqnl_instance *inst, int lock) | |||
188 | write_unlock_bh(&instances_lock); | 189 | write_unlock_bh(&instances_lock); |
189 | 190 | ||
190 | /* then flush all pending skbs from the queue */ | 191 | /* then flush all pending skbs from the queue */ |
191 | nfqnl_flush(inst, NF_DROP); | 192 | nfqnl_flush(inst, NULL, 0); |
192 | 193 | ||
193 | /* and finally put the refcount */ | 194 | /* and finally put the refcount */ |
194 | instance_put(inst); | 195 | instance_put(inst); |
@@ -235,54 +236,6 @@ __enqueue_entry(struct nfqnl_instance *queue, | |||
235 | queue->queue_total++; | 236 | queue->queue_total++; |
236 | } | 237 | } |
237 | 238 | ||
238 | /* | ||
239 | * Find and return a queued entry matched by cmpfn, or return the last | ||
240 | * entry if cmpfn is NULL. | ||
241 | */ | ||
242 | static inline struct nfqnl_queue_entry * | ||
243 | __find_entry(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, | ||
244 | unsigned long data) | ||
245 | { | ||
246 | struct nfqnl_queue_entry *entry; | ||
247 | |||
248 | list_for_each_entry(entry, &queue->queue_list, list) { | ||
249 | if (!cmpfn || cmpfn(entry, data)) | ||
250 | return entry; | ||
251 | } | ||
252 | return NULL; | ||
253 | } | ||
254 | |||
255 | static inline void | ||
256 | __dequeue_entry(struct nfqnl_instance *q, struct nfqnl_queue_entry *entry) | ||
257 | { | ||
258 | list_del(&entry->list); | ||
259 | q->queue_total--; | ||
260 | } | ||
261 | |||
262 | static inline struct nfqnl_queue_entry * | ||
263 | __find_dequeue_entry(struct nfqnl_instance *queue, | ||
264 | nfqnl_cmpfn cmpfn, unsigned long data) | ||
265 | { | ||
266 | struct nfqnl_queue_entry *entry; | ||
267 | |||
268 | entry = __find_entry(queue, cmpfn, data); | ||
269 | if (entry == NULL) | ||
270 | return NULL; | ||
271 | |||
272 | __dequeue_entry(queue, entry); | ||
273 | return entry; | ||
274 | } | ||
275 | |||
276 | |||
277 | static inline void | ||
278 | __nfqnl_flush(struct nfqnl_instance *queue, int verdict) | ||
279 | { | ||
280 | struct nfqnl_queue_entry *entry; | ||
281 | |||
282 | while ((entry = __find_dequeue_entry(queue, NULL, 0))) | ||
283 | issue_verdict(entry, verdict); | ||
284 | } | ||
285 | |||
286 | static inline int | 239 | static inline int |
287 | __nfqnl_set_mode(struct nfqnl_instance *queue, | 240 | __nfqnl_set_mode(struct nfqnl_instance *queue, |
288 | unsigned char mode, unsigned int range) | 241 | unsigned char mode, unsigned int range) |
@@ -313,23 +266,42 @@ __nfqnl_set_mode(struct nfqnl_instance *queue, | |||
313 | } | 266 | } |
314 | 267 | ||
315 | static struct nfqnl_queue_entry * | 268 | static struct nfqnl_queue_entry * |
316 | find_dequeue_entry(struct nfqnl_instance *queue, | 269 | find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id) |
317 | nfqnl_cmpfn cmpfn, unsigned long data) | ||
318 | { | 270 | { |
319 | struct nfqnl_queue_entry *entry; | 271 | struct nfqnl_queue_entry *entry = NULL, *i; |
320 | 272 | ||
321 | spin_lock_bh(&queue->lock); | 273 | spin_lock_bh(&queue->lock); |
322 | entry = __find_dequeue_entry(queue, cmpfn, data); | 274 | |
275 | list_for_each_entry(i, &queue->queue_list, list) { | ||
276 | if (i->id == id) { | ||
277 | entry = i; | ||
278 | break; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | if (entry) { | ||
283 | list_del(&entry->list); | ||
284 | queue->queue_total--; | ||
285 | } | ||
286 | |||
323 | spin_unlock_bh(&queue->lock); | 287 | spin_unlock_bh(&queue->lock); |
324 | 288 | ||
325 | return entry; | 289 | return entry; |
326 | } | 290 | } |
327 | 291 | ||
328 | static void | 292 | static void |
329 | nfqnl_flush(struct nfqnl_instance *queue, int verdict) | 293 | nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data) |
330 | { | 294 | { |
295 | struct nfqnl_queue_entry *entry, *next; | ||
296 | |||
331 | spin_lock_bh(&queue->lock); | 297 | spin_lock_bh(&queue->lock); |
332 | __nfqnl_flush(queue, verdict); | 298 | list_for_each_entry_safe(entry, next, &queue->queue_list, list) { |
299 | if (!cmpfn || cmpfn(entry, data)) { | ||
300 | list_del(&entry->list); | ||
301 | queue->queue_total--; | ||
302 | issue_verdict(entry, NF_DROP); | ||
303 | } | ||
304 | } | ||
333 | spin_unlock_bh(&queue->lock); | 305 | spin_unlock_bh(&queue->lock); |
334 | } | 306 | } |
335 | 307 | ||
@@ -644,12 +616,6 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) | |||
644 | return 0; | 616 | return 0; |
645 | } | 617 | } |
646 | 618 | ||
647 | static inline int | ||
648 | id_cmp(struct nfqnl_queue_entry *e, unsigned long id) | ||
649 | { | ||
650 | return (id == e->id); | ||
651 | } | ||
652 | |||
653 | static int | 619 | static int |
654 | nfqnl_set_mode(struct nfqnl_instance *queue, | 620 | nfqnl_set_mode(struct nfqnl_instance *queue, |
655 | unsigned char mode, unsigned int range) | 621 | unsigned char mode, unsigned int range) |
@@ -706,12 +672,8 @@ nfqnl_dev_drop(int ifindex) | |||
706 | struct nfqnl_instance *inst; | 672 | struct nfqnl_instance *inst; |
707 | struct hlist_head *head = &instance_table[i]; | 673 | struct hlist_head *head = &instance_table[i]; |
708 | 674 | ||
709 | hlist_for_each_entry(inst, tmp, head, hlist) { | 675 | hlist_for_each_entry(inst, tmp, head, hlist) |
710 | struct nfqnl_queue_entry *entry; | 676 | nfqnl_flush(inst, dev_cmp, ifindex); |
711 | while ((entry = find_dequeue_entry(inst, dev_cmp, | ||
712 | ifindex)) != NULL) | ||
713 | issue_verdict(entry, NF_DROP); | ||
714 | } | ||
715 | } | 677 | } |
716 | 678 | ||
717 | read_unlock_bh(&instances_lock); | 679 | read_unlock_bh(&instances_lock); |
@@ -811,7 +773,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, | |||
811 | goto err_out_put; | 773 | goto err_out_put; |
812 | } | 774 | } |
813 | 775 | ||
814 | entry = find_dequeue_entry(queue, id_cmp, ntohl(vhdr->id)); | 776 | entry = find_dequeue_entry(queue, ntohl(vhdr->id)); |
815 | if (entry == NULL) { | 777 | if (entry == NULL) { |
816 | err = -ENOENT; | 778 | err = -ENOENT; |
817 | goto err_out_put; | 779 | goto err_out_put; |