[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>
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 @@
 	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 @@
 		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 @@
        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 @@
 }
 
 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 @@
 	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 @@
 		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 @@
 		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;