OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [net/] [netfilter/] [nf_queue.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
#include <linux/kernel.h>
2
#include <linux/init.h>
3
#include <linux/module.h>
4
#include <linux/proc_fs.h>
5
#include <linux/skbuff.h>
6
#include <linux/netfilter.h>
7
#include <linux/seq_file.h>
8
#include <linux/rcupdate.h>
9
#include <net/protocol.h>
10
 
11
#include "nf_internals.h"
12
 
13
/*
14
 * A queue handler may be registered for each protocol.  Each is protected by
15
 * long term mutex.  The handler must provide an an outfn() to accept packets
16
 * for queueing and must reinject all packets it receives, no matter what.
17
 */
18
static struct nf_queue_handler *queue_handler[NPROTO];
19
 
20
static DEFINE_MUTEX(queue_handler_mutex);
21
 
22
/* return EBUSY when somebody else is registered, return EEXIST if the
23
 * same handler is registered, return 0 in case of success. */
24
int nf_register_queue_handler(int pf, struct nf_queue_handler *qh)
25
{
26
        int ret;
27
 
28
        if (pf >= NPROTO)
29
                return -EINVAL;
30
 
31
        mutex_lock(&queue_handler_mutex);
32
        if (queue_handler[pf] == qh)
33
                ret = -EEXIST;
34
        else if (queue_handler[pf])
35
                ret = -EBUSY;
36
        else {
37
                rcu_assign_pointer(queue_handler[pf], qh);
38
                ret = 0;
39
        }
40
        mutex_unlock(&queue_handler_mutex);
41
 
42
        return ret;
43
}
44
EXPORT_SYMBOL(nf_register_queue_handler);
45
 
46
/* The caller must flush their queue before this */
47
int nf_unregister_queue_handler(int pf, struct nf_queue_handler *qh)
48
{
49
        if (pf >= NPROTO)
50
                return -EINVAL;
51
 
52
        mutex_lock(&queue_handler_mutex);
53
        if (queue_handler[pf] != qh) {
54
                mutex_unlock(&queue_handler_mutex);
55
                return -EINVAL;
56
        }
57
 
58
        rcu_assign_pointer(queue_handler[pf], NULL);
59
        mutex_unlock(&queue_handler_mutex);
60
 
61
        synchronize_rcu();
62
 
63
        return 0;
64
}
65
EXPORT_SYMBOL(nf_unregister_queue_handler);
66
 
67
void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
68
{
69
        int pf;
70
 
71
        mutex_lock(&queue_handler_mutex);
72
        for (pf = 0; pf < NPROTO; pf++)  {
73
                if (queue_handler[pf] == qh)
74
                        rcu_assign_pointer(queue_handler[pf], NULL);
75
        }
76
        mutex_unlock(&queue_handler_mutex);
77
 
78
        synchronize_rcu();
79
}
80
EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
81
 
82
/*
83
 * Any packet that leaves via this function must come back
84
 * through nf_reinject().
85
 */
86
static int __nf_queue(struct sk_buff *skb,
87
                      struct list_head *elem,
88
                      int pf, unsigned int hook,
89
                      struct net_device *indev,
90
                      struct net_device *outdev,
91
                      int (*okfn)(struct sk_buff *),
92
                      unsigned int queuenum)
93
{
94
        int status;
95
        struct nf_info *info;
96
#ifdef CONFIG_BRIDGE_NETFILTER
97
        struct net_device *physindev = NULL;
98
        struct net_device *physoutdev = NULL;
99
#endif
100
        struct nf_afinfo *afinfo;
101
        struct nf_queue_handler *qh;
102
 
103
        /* QUEUE == DROP if noone is waiting, to be safe. */
104
        rcu_read_lock();
105
 
106
        qh = rcu_dereference(queue_handler[pf]);
107
        if (!qh) {
108
                rcu_read_unlock();
109
                kfree_skb(skb);
110
                return 1;
111
        }
112
 
113
        afinfo = nf_get_afinfo(pf);
114
        if (!afinfo) {
115
                rcu_read_unlock();
116
                kfree_skb(skb);
117
                return 1;
118
        }
119
 
120
        info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC);
121
        if (!info) {
122
                if (net_ratelimit())
123
                        printk(KERN_ERR "OOM queueing packet %p\n",
124
                               skb);
125
                rcu_read_unlock();
126
                kfree_skb(skb);
127
                return 1;
128
        }
129
 
130
        *info = (struct nf_info) {
131
                (struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
132
 
133
        /* If it's going away, ignore hook. */
134
        if (!try_module_get(info->elem->owner)) {
135
                rcu_read_unlock();
136
                kfree(info);
137
                return 0;
138
        }
139
 
140
        /* Bump dev refs so they don't vanish while packet is out */
141
        if (indev) dev_hold(indev);
142
        if (outdev) dev_hold(outdev);
143
 
144
#ifdef CONFIG_BRIDGE_NETFILTER
145
        if (skb->nf_bridge) {
146
                physindev = skb->nf_bridge->physindev;
147
                if (physindev) dev_hold(physindev);
148
                physoutdev = skb->nf_bridge->physoutdev;
149
                if (physoutdev) dev_hold(physoutdev);
150
        }
151
#endif
152
        afinfo->saveroute(skb, info);
153
        status = qh->outfn(skb, info, queuenum, qh->data);
154
 
155
        rcu_read_unlock();
156
 
157
        if (status < 0) {
158
                /* James M doesn't say fuck enough. */
159
                if (indev) dev_put(indev);
160
                if (outdev) dev_put(outdev);
161
#ifdef CONFIG_BRIDGE_NETFILTER
162
                if (physindev) dev_put(physindev);
163
                if (physoutdev) dev_put(physoutdev);
164
#endif
165
                module_put(info->elem->owner);
166
                kfree(info);
167
                kfree_skb(skb);
168
 
169
                return 1;
170
        }
171
 
172
        return 1;
173
}
174
 
175
int nf_queue(struct sk_buff *skb,
176
             struct list_head *elem,
177
             int pf, unsigned int hook,
178
             struct net_device *indev,
179
             struct net_device *outdev,
180
             int (*okfn)(struct sk_buff *),
181
             unsigned int queuenum)
182
{
183
        struct sk_buff *segs;
184
 
185
        if (!skb_is_gso(skb))
186
                return __nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
187
                                  queuenum);
188
 
189
        switch (pf) {
190
        case AF_INET:
191
                skb->protocol = htons(ETH_P_IP);
192
                break;
193
        case AF_INET6:
194
                skb->protocol = htons(ETH_P_IPV6);
195
                break;
196
        }
197
 
198
        segs = skb_gso_segment(skb, 0);
199
        kfree_skb(skb);
200
        if (unlikely(IS_ERR(segs)))
201
                return 1;
202
 
203
        do {
204
                struct sk_buff *nskb = segs->next;
205
 
206
                segs->next = NULL;
207
                if (!__nf_queue(segs, elem, pf, hook, indev, outdev, okfn,
208
                                queuenum))
209
                        kfree_skb(segs);
210
                segs = nskb;
211
        } while (segs);
212
        return 1;
213
}
214
 
215
void nf_reinject(struct sk_buff *skb, struct nf_info *info,
216
                 unsigned int verdict)
217
{
218
        struct list_head *elem = &info->elem->list;
219
        struct list_head *i;
220
        struct nf_afinfo *afinfo;
221
 
222
        rcu_read_lock();
223
 
224
        /* Release those devices we held, or Alexey will kill me. */
225
        if (info->indev) dev_put(info->indev);
226
        if (info->outdev) dev_put(info->outdev);
227
#ifdef CONFIG_BRIDGE_NETFILTER
228
        if (skb->nf_bridge) {
229
                if (skb->nf_bridge->physindev)
230
                        dev_put(skb->nf_bridge->physindev);
231
                if (skb->nf_bridge->physoutdev)
232
                        dev_put(skb->nf_bridge->physoutdev);
233
        }
234
#endif
235
 
236
        /* Drop reference to owner of hook which queued us. */
237
        module_put(info->elem->owner);
238
 
239
        list_for_each_rcu(i, &nf_hooks[info->pf][info->hook]) {
240
                if (i == elem)
241
                        break;
242
        }
243
 
244
        if (i == &nf_hooks[info->pf][info->hook]) {
245
                /* The module which sent it to userspace is gone. */
246
                NFDEBUG("%s: module disappeared, dropping packet.\n",
247
                        __FUNCTION__);
248
                verdict = NF_DROP;
249
        }
250
 
251
        /* Continue traversal iff userspace said ok... */
252
        if (verdict == NF_REPEAT) {
253
                elem = elem->prev;
254
                verdict = NF_ACCEPT;
255
        }
256
 
257
        if (verdict == NF_ACCEPT) {
258
                afinfo = nf_get_afinfo(info->pf);
259
                if (!afinfo || afinfo->reroute(skb, info) < 0)
260
                        verdict = NF_DROP;
261
        }
262
 
263
        if (verdict == NF_ACCEPT) {
264
        next_hook:
265
                verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
266
                                     skb, info->hook,
267
                                     info->indev, info->outdev, &elem,
268
                                     info->okfn, INT_MIN);
269
        }
270
 
271
        switch (verdict & NF_VERDICT_MASK) {
272
        case NF_ACCEPT:
273
        case NF_STOP:
274
                info->okfn(skb);
275
        case NF_STOLEN:
276
                break;
277
        case NF_QUEUE:
278
                if (!__nf_queue(skb, elem, info->pf, info->hook,
279
                                info->indev, info->outdev, info->okfn,
280
                                verdict >> NF_VERDICT_BITS))
281
                        goto next_hook;
282
                break;
283
        default:
284
                kfree_skb(skb);
285
        }
286
        rcu_read_unlock();
287
        kfree(info);
288
        return;
289
}
290
EXPORT_SYMBOL(nf_reinject);
291
 
292
#ifdef CONFIG_PROC_FS
293
static void *seq_start(struct seq_file *seq, loff_t *pos)
294
{
295
        if (*pos >= NPROTO)
296
                return NULL;
297
 
298
        return pos;
299
}
300
 
301
static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
302
{
303
        (*pos)++;
304
 
305
        if (*pos >= NPROTO)
306
                return NULL;
307
 
308
        return pos;
309
}
310
 
311
static void seq_stop(struct seq_file *s, void *v)
312
{
313
 
314
}
315
 
316
static int seq_show(struct seq_file *s, void *v)
317
{
318
        int ret;
319
        loff_t *pos = v;
320
        struct nf_queue_handler *qh;
321
 
322
        rcu_read_lock();
323
        qh = rcu_dereference(queue_handler[*pos]);
324
        if (!qh)
325
                ret = seq_printf(s, "%2lld NONE\n", *pos);
326
        else
327
                ret = seq_printf(s, "%2lld %s\n", *pos, qh->name);
328
        rcu_read_unlock();
329
 
330
        return ret;
331
}
332
 
333
static const struct seq_operations nfqueue_seq_ops = {
334
        .start  = seq_start,
335
        .next   = seq_next,
336
        .stop   = seq_stop,
337
        .show   = seq_show,
338
};
339
 
340
static int nfqueue_open(struct inode *inode, struct file *file)
341
{
342
        return seq_open(file, &nfqueue_seq_ops);
343
}
344
 
345
static const struct file_operations nfqueue_file_ops = {
346
        .owner   = THIS_MODULE,
347
        .open    = nfqueue_open,
348
        .read    = seq_read,
349
        .llseek  = seq_lseek,
350
        .release = seq_release,
351
};
352
#endif /* PROC_FS */
353
 
354
 
355
int __init netfilter_queue_init(void)
356
{
357
#ifdef CONFIG_PROC_FS
358
        struct proc_dir_entry *pde;
359
 
360
        pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter);
361
        if (!pde)
362
                return -1;
363
        pde->proc_fops = &nfqueue_file_ops;
364
#endif
365
        return 0;
366
}
367
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.