aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-12-05 04:25:46 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:56:12 -0500
commit9521409265d3bae939ace4c259f765c29339730f (patch)
treec622a14e0b245b2b32b2915b45649fa06f2fb7ea /net
parentb43d8d85987bf21578e270c9f57c8503114ff399 (diff)
[NETFILTER]: ip_queue: deobfuscate entry lookups
A queue entry lookup currently looks like this: ipq_find_dequeue_entry -> __ipq_find_dequeue_entry -> __ipq_find_entry -> cmpfn -> id_cmp Use simple open-coded list walking and kill the cmpfn for ipq_find_dequeue_entry. Instead add it to ipq_flush (after similar cleanups) and use ipq_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/ipv4/netfilter/ip_queue.c101
1 files changed, 37 insertions, 64 deletions
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 9e72246ede25..df2957c5bcb4 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -77,52 +77,6 @@ __ipq_enqueue_entry(struct ipq_queue_entry *entry)
77 queue_total++; 77 queue_total++;
78} 78}
79 79
80/*
81 * Find and return a queued entry matched by cmpfn, or return the last
82 * entry if cmpfn is NULL.
83 */
84static inline struct ipq_queue_entry *
85__ipq_find_entry(ipq_cmpfn cmpfn, unsigned long data)
86{
87 struct ipq_queue_entry *entry;
88
89 list_for_each_entry(entry, &queue_list, list) {
90 if (!cmpfn || cmpfn(entry, data))
91 return entry;
92 }
93 return NULL;
94}
95
96static inline void
97__ipq_dequeue_entry(struct ipq_queue_entry *entry)
98{
99 list_del(&entry->list);
100 queue_total--;
101}
102
103static inline struct ipq_queue_entry *
104__ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data)
105{
106 struct ipq_queue_entry *entry;
107
108 entry = __ipq_find_entry(cmpfn, data);
109 if (entry == NULL)
110 return NULL;
111
112 __ipq_dequeue_entry(entry);
113 return entry;
114}
115
116
117static inline void
118__ipq_flush(int verdict)
119{
120 struct ipq_queue_entry *entry;
121
122 while ((entry = __ipq_find_dequeue_entry(NULL, 0)))
123 ipq_issue_verdict(entry, verdict);
124}
125
126static inline int 80static inline int
127__ipq_set_mode(unsigned char mode, unsigned int range) 81__ipq_set_mode(unsigned char mode, unsigned int range)
128{ 82{
@@ -149,31 +103,59 @@ __ipq_set_mode(unsigned char mode, unsigned int range)
149 return status; 103 return status;
150} 104}
151 105
106static void __ipq_flush(ipq_cmpfn cmpfn, unsigned long data);
107
152static inline void 108static inline void
153__ipq_reset(void) 109__ipq_reset(void)
154{ 110{
155 peer_pid = 0; 111 peer_pid = 0;
156 net_disable_timestamp(); 112 net_disable_timestamp();
157 __ipq_set_mode(IPQ_COPY_NONE, 0); 113 __ipq_set_mode(IPQ_COPY_NONE, 0);
158 __ipq_flush(NF_DROP); 114 __ipq_flush(NULL, 0);
159} 115}
160 116
161static struct ipq_queue_entry * 117static struct ipq_queue_entry *
162ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data) 118ipq_find_dequeue_entry(unsigned long id)
163{ 119{
164 struct ipq_queue_entry *entry; 120 struct ipq_queue_entry *entry = NULL, *i;
165 121
166 write_lock_bh(&queue_lock); 122 write_lock_bh(&queue_lock);
167 entry = __ipq_find_dequeue_entry(cmpfn, data); 123
124 list_for_each_entry(i, &queue_list, list) {
125 if ((unsigned long)i == id) {
126 entry = i;
127 break;
128 }
129 }
130
131 if (entry) {
132 list_del(&entry->list);
133 queue_total--;
134 }
135
168 write_unlock_bh(&queue_lock); 136 write_unlock_bh(&queue_lock);
169 return entry; 137 return entry;
170} 138}
171 139
172static void 140static void
173ipq_flush(int verdict) 141__ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
142{
143 struct ipq_queue_entry *entry, *next;
144
145 list_for_each_entry_safe(entry, next, &queue_list, list) {
146 if (!cmpfn || cmpfn(entry, data)) {
147 list_del(&entry->list);
148 queue_total--;
149 ipq_issue_verdict(entry, NF_DROP);
150 }
151 }
152}
153
154static void
155ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
174{ 156{
175 write_lock_bh(&queue_lock); 157 write_lock_bh(&queue_lock);
176 __ipq_flush(verdict); 158 __ipq_flush(cmpfn, data);
177 write_unlock_bh(&queue_lock); 159 write_unlock_bh(&queue_lock);
178} 160}
179 161
@@ -367,12 +349,6 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
367 return 0; 349 return 0;
368} 350}
369 351
370static inline int
371id_cmp(struct ipq_queue_entry *e, unsigned long id)
372{
373 return (id == (unsigned long )e);
374}
375
376static int 352static int
377ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len) 353ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
378{ 354{
@@ -381,7 +357,7 @@ ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
381 if (vmsg->value > NF_MAX_VERDICT) 357 if (vmsg->value > NF_MAX_VERDICT)
382 return -EINVAL; 358 return -EINVAL;
383 359
384 entry = ipq_find_dequeue_entry(id_cmp, vmsg->id); 360 entry = ipq_find_dequeue_entry(vmsg->id);
385 if (entry == NULL) 361 if (entry == NULL)
386 return -ENOENT; 362 return -ENOENT;
387 else { 363 else {
@@ -460,10 +436,7 @@ dev_cmp(struct ipq_queue_entry *entry, unsigned long ifindex)
460static void 436static void
461ipq_dev_drop(int ifindex) 437ipq_dev_drop(int ifindex)
462{ 438{
463 struct ipq_queue_entry *entry; 439 ipq_flush(dev_cmp, ifindex);
464
465 while ((entry = ipq_find_dequeue_entry(dev_cmp, ifindex)) != NULL)
466 ipq_issue_verdict(entry, NF_DROP);
467} 440}
468 441
469#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) 442#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
@@ -699,7 +672,7 @@ static void __exit ip_queue_fini(void)
699{ 672{
700 nf_unregister_queue_handlers(&nfqh); 673 nf_unregister_queue_handlers(&nfqh);
701 synchronize_net(); 674 synchronize_net();
702 ipq_flush(NF_DROP); 675 ipq_flush(NULL, 0);
703 676
704 unregister_sysctl_table(ipq_sysctl_header); 677 unregister_sysctl_table(ipq_sysctl_header);
705 unregister_netdevice_notifier(&ipq_dev_notifier); 678 unregister_netdevice_notifier(&ipq_dev_notifier);