aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-12-05 04:25:30 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:56:12 -0500
commitb43d8d85987bf21578e270c9f57c8503114ff399 (patch)
tree20a6fc625a2909bfd55e2d480d74398aa2ad11e0
parent0ac41e81462de20f87242caac2b9084c202c33b7 (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.c100
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
174static void nfqnl_flush(struct nfqnl_instance *queue, int verdict); 174static void nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn,
175 unsigned long data);
175 176
176static void 177static 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 */
242static 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
255static 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
262static 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
277static 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
286static inline int 239static 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
315static struct nfqnl_queue_entry * 268static struct nfqnl_queue_entry *
316find_dequeue_entry(struct nfqnl_instance *queue, 269find_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
328static void 292static void
329nfqnl_flush(struct nfqnl_instance *queue, int verdict) 293nfqnl_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
647static inline int
648id_cmp(struct nfqnl_queue_entry *e, unsigned long id)
649{
650 return (id == e->id);
651}
652
653static int 619static int
654nfqnl_set_mode(struct nfqnl_instance *queue, 620nfqnl_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;