diff options
author | Patrick McHardy <kaber@trash.net> | 2007-12-05 01:25:30 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 14:56:12 -0800 |
commit | b43d8d85987bf21578e270c9f57c8503114ff399 (patch) | |
tree | 20a6fc625a2909bfd55e2d480d74398aa2ad11e0 /net | |
parent | 0ac41e81462de20f87242caac2b9084c202c33b7 (diff) | |
download | linux-stable-b43d8d85987bf21578e270c9f57c8503114ff399.tar.gz linux-stable-b43d8d85987bf21578e270c9f57c8503114ff399.tar.bz2 linux-stable-b43d8d85987bf21578e270c9f57c8503114ff399.zip |
[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>
Diffstat (limited to '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: return NULL; } -static void nfqnl_flush(struct nfqnl_instance *queue, int verdict); +static void nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, + unsigned long data); static void _instance_destroy2(struct nfqnl_instance *inst, int lock) @@ -188,7 +189,7 @@ _instance_destroy2(struct nfqnl_instance *inst, int lock) write_unlock_bh(&instances_lock); /* then flush all pending skbs from the queue */ - nfqnl_flush(inst, NF_DROP); + nfqnl_flush(inst, NULL, 0); /* and finally put the refcount */ instance_put(inst); @@ -235,54 +236,6 @@ __enqueue_entry(struct nfqnl_instance *queue, queue->queue_total++; } -/* - * Find and return a queued entry matched by cmpfn, or return the last - * entry if cmpfn is NULL. - */ -static inline struct nfqnl_queue_entry * -__find_entry(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, - unsigned long data) -{ - struct nfqnl_queue_entry *entry; - - list_for_each_entry(entry, &queue->queue_list, list) { - if (!cmpfn || cmpfn(entry, data)) - return entry; - } - return NULL; -} - -static inline void -__dequeue_entry(struct nfqnl_instance *q, struct nfqnl_queue_entry *entry) -{ - list_del(&entry->list); - q->queue_total--; -} - -static inline struct nfqnl_queue_entry * -__find_dequeue_entry(struct nfqnl_instance *queue, - nfqnl_cmpfn cmpfn, unsigned long data) -{ - struct nfqnl_queue_entry *entry; - - entry = __find_entry(queue, cmpfn, data); - if (entry == NULL) - return NULL; - - __dequeue_entry(queue, entry); - return entry; -} - - -static inline void -__nfqnl_flush(struct nfqnl_instance *queue, int verdict) -{ - struct nfqnl_queue_entry *entry; - - while ((entry = __find_dequeue_entry(queue, NULL, 0))) - issue_verdict(entry, verdict); -} - static inline int __nfqnl_set_mode(struct nfqnl_instance *queue, unsigned char mode, unsigned int range) @@ -313,23 +266,42 @@ __nfqnl_set_mode(struct nfqnl_instance *queue, } static struct nfqnl_queue_entry * -find_dequeue_entry(struct nfqnl_instance *queue, - nfqnl_cmpfn cmpfn, unsigned long data) +find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id) { - struct nfqnl_queue_entry *entry; + struct nfqnl_queue_entry *entry = NULL, *i; spin_lock_bh(&queue->lock); - entry = __find_dequeue_entry(queue, cmpfn, data); + + list_for_each_entry(i, &queue->queue_list, list) { + if (i->id == id) { + entry = i; + break; + } + } + + if (entry) { + list_del(&entry->list); + queue->queue_total--; + } + spin_unlock_bh(&queue->lock); return entry; } static void -nfqnl_flush(struct nfqnl_instance *queue, int verdict) +nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data) { + struct nfqnl_queue_entry *entry, *next; + spin_lock_bh(&queue->lock); - __nfqnl_flush(queue, verdict); + list_for_each_entry_safe(entry, next, &queue->queue_list, list) { + if (!cmpfn || cmpfn(entry, data)) { + list_del(&entry->list); + queue->queue_total--; + issue_verdict(entry, NF_DROP); + } + } spin_unlock_bh(&queue->lock); } @@ -644,12 +616,6 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) return 0; } -static inline int -id_cmp(struct nfqnl_queue_entry *e, unsigned long id) -{ - return (id == e->id); -} - static int nfqnl_set_mode(struct nfqnl_instance *queue, unsigned char mode, unsigned int range) @@ -706,12 +672,8 @@ nfqnl_dev_drop(int ifindex) struct nfqnl_instance *inst; struct hlist_head *head = &instance_table[i]; - hlist_for_each_entry(inst, tmp, head, hlist) { - struct nfqnl_queue_entry *entry; - while ((entry = find_dequeue_entry(inst, dev_cmp, - ifindex)) != NULL) - issue_verdict(entry, NF_DROP); - } + hlist_for_each_entry(inst, tmp, head, hlist) + nfqnl_flush(inst, dev_cmp, ifindex); } read_unlock_bh(&instances_lock); @@ -811,7 +773,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, goto err_out_put; } - entry = find_dequeue_entry(queue, id_cmp, ntohl(vhdr->id)); + entry = find_dequeue_entry(queue, ntohl(vhdr->id)); if (entry == NULL) { err = -ENOENT; goto err_out_put; |