From b43d8d85987bf21578e270c9f57c8503114ff399 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 5 Dec 2007 01:25:30 -0800 Subject: [PATCH] [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 Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_queue.c | 100 +++++++++++++--------------------------- 1 file changed, 31 insertions(+), 69 deletions(-) diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 74d5ed9..cb901cf 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; -- 2.7.4