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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [ipv4/] [netfilter/] [ip_conntrack_standalone.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* This file contains all the functions required for the standalone
2
   ip_conntrack module.
3
 
4
   These are not required by the compatibility layer.
5
*/
6
 
7
/* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
8
   Public Licence. */
9
 
10
#include <linux/config.h>
11
#include <linux/types.h>
12
#include <linux/ip.h>
13
#include <linux/netfilter.h>
14
#include <linux/netfilter_ipv4.h>
15
#include <linux/module.h>
16
#include <linux/skbuff.h>
17
#include <linux/proc_fs.h>
18
#include <linux/version.h>
19
#include <linux/brlock.h>
20
#ifdef CONFIG_SYSCTL
21
#include <linux/sysctl.h>
22
#endif
23
#include <net/checksum.h>
24
 
25
#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
26
#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
27
 
28
#include <linux/netfilter_ipv4/ip_conntrack.h>
29
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
30
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
31
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
32
#include <linux/netfilter_ipv4/listhelp.h>
33
 
34
#if 0
35
#define DEBUGP printk
36
#else
37
#define DEBUGP(format, args...)
38
#endif
39
 
40
MODULE_LICENSE("GPL");
41
 
42
static int kill_proto(const struct ip_conntrack *i, void *data)
43
{
44
        return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
45
                        *((u_int8_t *) data));
46
}
47
 
48
static unsigned int
49
print_tuple(char *buffer, const struct ip_conntrack_tuple *tuple,
50
            struct ip_conntrack_protocol *proto)
51
{
52
        int len;
53
 
54
        len = sprintf(buffer, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
55
                      NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
56
 
57
        len += proto->print_tuple(buffer + len, tuple);
58
 
59
        return len;
60
}
61
 
62
/* FIXME: Don't print source proto part. --RR */
63
static unsigned int
64
print_expect(char *buffer, const struct ip_conntrack_expect *expect)
65
{
66
        unsigned int len;
67
 
68
        if (expect->expectant->helper->timeout)
69
                len = sprintf(buffer, "EXPECTING: %lu ",
70
                              timer_pending(&expect->timeout)
71
                              ? (expect->timeout.expires - jiffies)/HZ : 0);
72
        else
73
                len = sprintf(buffer, "EXPECTING: - ");
74
        len += sprintf(buffer + len, "use=%u proto=%u ",
75
                      atomic_read(&expect->use), expect->tuple.dst.protonum);
76
        len += print_tuple(buffer + len, &expect->tuple,
77
                           __ip_ct_find_proto(expect->tuple.dst.protonum));
78
        len += sprintf(buffer + len, "\n");
79
        return len;
80
}
81
 
82
static unsigned int
83
print_conntrack(char *buffer, struct ip_conntrack *conntrack)
84
{
85
        unsigned int len;
86
        struct ip_conntrack_protocol *proto
87
                = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
88
                               .tuple.dst.protonum);
89
 
90
        len = sprintf(buffer, "%-8s %u %lu ",
91
                      proto->name,
92
                      conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
93
                      .tuple.dst.protonum,
94
                      timer_pending(&conntrack->timeout)
95
                      ? (conntrack->timeout.expires - jiffies)/HZ : 0);
96
 
97
        len += proto->print_conntrack(buffer + len, conntrack);
98
        len += print_tuple(buffer + len,
99
                           &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
100
                           proto);
101
        if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
102
                len += sprintf(buffer + len, "[UNREPLIED] ");
103
        len += print_tuple(buffer + len,
104
                           &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
105
                           proto);
106
        if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
107
                len += sprintf(buffer + len, "[ASSURED] ");
108
        len += sprintf(buffer + len, "use=%u ",
109
                       atomic_read(&conntrack->ct_general.use));
110
        len += sprintf(buffer + len, "\n");
111
 
112
        return len;
113
}
114
 
115
/* Returns true when finished. */
116
static inline int
117
conntrack_iterate(const struct ip_conntrack_tuple_hash *hash,
118
                  char *buffer, off_t offset, off_t *upto,
119
                  unsigned int *len, unsigned int maxlen)
120
{
121
        unsigned int newlen;
122
        IP_NF_ASSERT(hash->ctrack);
123
 
124
        MUST_BE_READ_LOCKED(&ip_conntrack_lock);
125
 
126
        /* Only count originals */
127
        if (DIRECTION(hash))
128
                return 0;
129
 
130
        if ((*upto)++ < offset)
131
                return 0;
132
 
133
        newlen = print_conntrack(buffer + *len, hash->ctrack);
134
        if (*len + newlen > maxlen)
135
                return 1;
136
        else *len += newlen;
137
 
138
        return 0;
139
}
140
 
141
static int
142
list_conntracks(char *buffer, char **start, off_t offset, int length)
143
{
144
        unsigned int i;
145
        unsigned int len = 0;
146
        off_t upto = 0;
147
        struct list_head *e;
148
 
149
        READ_LOCK(&ip_conntrack_lock);
150
        /* Traverse hash; print originals then reply. */
151
        for (i = 0; i < ip_conntrack_htable_size; i++) {
152
                if (LIST_FIND(&ip_conntrack_hash[i], conntrack_iterate,
153
                              struct ip_conntrack_tuple_hash *,
154
                              buffer, offset, &upto, &len, length))
155
                        goto finished;
156
        }
157
 
158
        /* Now iterate through expecteds. */
159
        for (e = ip_conntrack_expect_list.next;
160
             e != &ip_conntrack_expect_list; e = e->next) {
161
                unsigned int last_len;
162
                struct ip_conntrack_expect *expect
163
                        = (struct ip_conntrack_expect *)e;
164
                if (upto++ < offset) continue;
165
 
166
                last_len = len;
167
                len += print_expect(buffer + len, expect);
168
                if (len > length) {
169
                        len = last_len;
170
                        goto finished;
171
                }
172
        }
173
 
174
 finished:
175
        READ_UNLOCK(&ip_conntrack_lock);
176
 
177
        /* `start' hack - see fs/proc/generic.c line ~165 */
178
        *start = (char *)((unsigned int)upto - offset);
179
        return len;
180
}
181
 
182
static unsigned int ip_confirm(unsigned int hooknum,
183
                               struct sk_buff **pskb,
184
                               const struct net_device *in,
185
                               const struct net_device *out,
186
                               int (*okfn)(struct sk_buff *))
187
{
188
        /* We've seen it coming out the other side: confirm it */
189
        return ip_conntrack_confirm(*pskb);
190
}
191
 
192
static unsigned int ip_refrag(unsigned int hooknum,
193
                              struct sk_buff **pskb,
194
                              const struct net_device *in,
195
                              const struct net_device *out,
196
                              int (*okfn)(struct sk_buff *))
197
{
198
        struct rtable *rt = (struct rtable *)(*pskb)->dst;
199
 
200
        /* We've seen it coming out the other side: confirm */
201
        if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
202
                return NF_DROP;
203
 
204
        /* Local packets are never produced too large for their
205
           interface.  We degfragment them at LOCAL_OUT, however,
206
           so we have to refragment them here. */
207
        if ((*pskb)->len > rt->u.dst.pmtu) {
208
                /* No hook can be after us, so this should be OK. */
209
                ip_fragment(*pskb, okfn);
210
                return NF_STOLEN;
211
        }
212
        return NF_ACCEPT;
213
}
214
 
215
static unsigned int ip_conntrack_local(unsigned int hooknum,
216
                                       struct sk_buff **pskb,
217
                                       const struct net_device *in,
218
                                       const struct net_device *out,
219
                                       int (*okfn)(struct sk_buff *))
220
{
221
        /* root is playing with raw sockets. */
222
        if ((*pskb)->len < sizeof(struct iphdr)
223
            || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
224
                if (net_ratelimit())
225
                        printk("ipt_hook: happy cracking.\n");
226
                return NF_ACCEPT;
227
        }
228
        return ip_conntrack_in(hooknum, pskb, in, out, okfn);
229
}
230
 
231
/* Connection tracking may drop packets, but never alters them, so
232
   make it the first hook. */
233
static struct nf_hook_ops ip_conntrack_in_ops
234
= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
235
        NF_IP_PRI_CONNTRACK };
236
static struct nf_hook_ops ip_conntrack_local_out_ops
237
= { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
238
        NF_IP_PRI_CONNTRACK };
239
/* Refragmenter; last chance. */
240
static struct nf_hook_ops ip_conntrack_out_ops
241
= { { NULL, NULL }, ip_refrag, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_LAST };
242
static struct nf_hook_ops ip_conntrack_local_in_ops
243
= { { NULL, NULL }, ip_confirm, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_LAST-1 };
244
 
245
/* Sysctl support */
246
 
247
#ifdef CONFIG_SYSCTL
248
 
249
/* From ip_conntrack_core.c */
250
extern int ip_conntrack_max;
251
extern unsigned int ip_conntrack_htable_size;
252
 
253
/* From ip_conntrack_proto_tcp.c */
254
extern unsigned long ip_ct_tcp_timeout_syn_sent;
255
extern unsigned long ip_ct_tcp_timeout_syn_recv;
256
extern unsigned long ip_ct_tcp_timeout_established;
257
extern unsigned long ip_ct_tcp_timeout_fin_wait;
258
extern unsigned long ip_ct_tcp_timeout_close_wait;
259
extern unsigned long ip_ct_tcp_timeout_last_ack;
260
extern unsigned long ip_ct_tcp_timeout_time_wait;
261
extern unsigned long ip_ct_tcp_timeout_close;
262
 
263
/* From ip_conntrack_proto_udp.c */
264
extern unsigned long ip_ct_udp_timeout;
265
extern unsigned long ip_ct_udp_timeout_stream;
266
 
267
/* From ip_conntrack_proto_icmp.c */
268
extern unsigned long ip_ct_icmp_timeout;
269
 
270
/* From ip_conntrack_proto_icmp.c */
271
extern unsigned long ip_ct_generic_timeout;
272
 
273
static struct ctl_table_header *ip_ct_sysctl_header;
274
 
275
static ctl_table ip_ct_sysctl_table[] = {
276
        {NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max",
277
         &ip_conntrack_max, sizeof(int), 0644, NULL,
278
         &proc_dointvec},
279
        {NET_IPV4_NF_CONNTRACK_BUCKETS, "ip_conntrack_buckets",
280
         &ip_conntrack_htable_size, sizeof(unsigned int), 0444, NULL,
281
         &proc_dointvec},
282
        {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "ip_conntrack_tcp_timeout_syn_sent",
283
         &ip_ct_tcp_timeout_syn_sent, sizeof(unsigned int), 0644, NULL,
284
         &proc_dointvec_jiffies},
285
        {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "ip_conntrack_tcp_timeout_syn_recv",
286
         &ip_ct_tcp_timeout_syn_recv, sizeof(unsigned int), 0644, NULL,
287
         &proc_dointvec_jiffies},
288
        {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, "ip_conntrack_tcp_timeout_established",
289
         &ip_ct_tcp_timeout_established, sizeof(unsigned int), 0644, NULL,
290
         &proc_dointvec_jiffies},
291
        {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "ip_conntrack_tcp_timeout_fin_wait",
292
         &ip_ct_tcp_timeout_fin_wait, sizeof(unsigned int), 0644, NULL,
293
         &proc_dointvec_jiffies},
294
        {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, "ip_conntrack_tcp_timeout_close_wait",
295
         &ip_ct_tcp_timeout_close_wait, sizeof(unsigned int), 0644, NULL,
296
         &proc_dointvec_jiffies},
297
        {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "ip_conntrack_tcp_timeout_last_ack",
298
         &ip_ct_tcp_timeout_last_ack, sizeof(unsigned int), 0644, NULL,
299
         &proc_dointvec_jiffies},
300
        {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "ip_conntrack_tcp_timeout_time_wait",
301
         &ip_ct_tcp_timeout_time_wait, sizeof(unsigned int), 0644, NULL,
302
         &proc_dointvec_jiffies},
303
        {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, "ip_conntrack_tcp_timeout_close",
304
         &ip_ct_tcp_timeout_close, sizeof(unsigned int), 0644, NULL,
305
         &proc_dointvec_jiffies},
306
        {NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, "ip_conntrack_udp_timeout",
307
         &ip_ct_udp_timeout, sizeof(unsigned int), 0644, NULL,
308
         &proc_dointvec_jiffies},
309
        {NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "ip_conntrack_udp_timeout_stream",
310
         &ip_ct_udp_timeout_stream, sizeof(unsigned int), 0644, NULL,
311
         &proc_dointvec_jiffies},
312
        {NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, "ip_conntrack_icmp_timeout",
313
         &ip_ct_icmp_timeout, sizeof(unsigned int), 0644, NULL,
314
         &proc_dointvec_jiffies},
315
        {NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, "ip_conntrack_generic_timeout",
316
         &ip_ct_generic_timeout, sizeof(unsigned int), 0644, NULL,
317
         &proc_dointvec_jiffies},
318
        {0}
319
};
320
 
321
#define NET_IP_CONNTRACK_MAX 2089
322
 
323
static ctl_table ip_ct_netfilter_table[] = {
324
        {NET_IPV4_NETFILTER, "netfilter", NULL, 0, 0555, ip_ct_sysctl_table, 0, 0, 0, 0, 0},
325
        {NET_IP_CONNTRACK_MAX, "ip_conntrack_max",
326
         &ip_conntrack_max, sizeof(int), 0644, NULL,
327
         &proc_dointvec},
328
        {0}
329
};
330
 
331
static ctl_table ip_ct_ipv4_table[] = {
332
        {NET_IPV4, "ipv4", NULL, 0, 0555, ip_ct_netfilter_table, 0, 0, 0, 0, 0},
333
        {0}
334
};
335
 
336
static ctl_table ip_ct_net_table[] = {
337
        {CTL_NET, "net", NULL, 0, 0555, ip_ct_ipv4_table, 0, 0, 0, 0, 0},
338
        {0}
339
};
340
#endif
341
static int init_or_cleanup(int init)
342
{
343
        struct proc_dir_entry *proc;
344
        int ret = 0;
345
 
346
        if (!init) goto cleanup;
347
 
348
        ret = ip_conntrack_init();
349
        if (ret < 0)
350
                goto cleanup_nothing;
351
 
352
        proc = proc_net_create("ip_conntrack",0,list_conntracks);
353
        if (!proc) goto cleanup_init;
354
        proc->owner = THIS_MODULE;
355
 
356
        ret = nf_register_hook(&ip_conntrack_in_ops);
357
        if (ret < 0) {
358
                printk("ip_conntrack: can't register pre-routing hook.\n");
359
                goto cleanup_proc;
360
        }
361
        ret = nf_register_hook(&ip_conntrack_local_out_ops);
362
        if (ret < 0) {
363
                printk("ip_conntrack: can't register local out hook.\n");
364
                goto cleanup_inops;
365
        }
366
        ret = nf_register_hook(&ip_conntrack_out_ops);
367
        if (ret < 0) {
368
                printk("ip_conntrack: can't register post-routing hook.\n");
369
                goto cleanup_inandlocalops;
370
        }
371
        ret = nf_register_hook(&ip_conntrack_local_in_ops);
372
        if (ret < 0) {
373
                printk("ip_conntrack: can't register local in hook.\n");
374
                goto cleanup_inoutandlocalops;
375
        }
376
#ifdef CONFIG_SYSCTL
377
        ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
378
        if (ip_ct_sysctl_header == NULL) {
379
                printk("ip_conntrack: can't register to sysctl.\n");
380
                goto cleanup;
381
        }
382
#endif
383
 
384
        return ret;
385
 
386
 cleanup:
387
#ifdef CONFIG_SYSCTL
388
        unregister_sysctl_table(ip_ct_sysctl_header);
389
#endif
390
        nf_unregister_hook(&ip_conntrack_local_in_ops);
391
 cleanup_inoutandlocalops:
392
        nf_unregister_hook(&ip_conntrack_out_ops);
393
 cleanup_inandlocalops:
394
        nf_unregister_hook(&ip_conntrack_local_out_ops);
395
 cleanup_inops:
396
        nf_unregister_hook(&ip_conntrack_in_ops);
397
 cleanup_proc:
398
        proc_net_remove("ip_conntrack");
399
 cleanup_init:
400
        ip_conntrack_cleanup();
401
 cleanup_nothing:
402
        return ret;
403
}
404
 
405
/* FIXME: Allow NULL functions and sub in pointers to generic for
406
   them. --RR */
407
int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
408
{
409
        int ret = 0;
410
        struct list_head *i;
411
 
412
        WRITE_LOCK(&ip_conntrack_lock);
413
        for (i = protocol_list.next; i != &protocol_list; i = i->next) {
414
                if (((struct ip_conntrack_protocol *)i)->proto
415
                    == proto->proto) {
416
                        ret = -EBUSY;
417
                        goto out;
418
                }
419
        }
420
 
421
        list_prepend(&protocol_list, proto);
422
        MOD_INC_USE_COUNT;
423
 
424
 out:
425
        WRITE_UNLOCK(&ip_conntrack_lock);
426
        return ret;
427
}
428
 
429
void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
430
{
431
        WRITE_LOCK(&ip_conntrack_lock);
432
 
433
        /* ip_ct_find_proto() returns proto_generic in case there is no protocol
434
         * helper. So this should be enough - HW */
435
        LIST_DELETE(&protocol_list, proto);
436
        WRITE_UNLOCK(&ip_conntrack_lock);
437
 
438
        /* Somebody could be still looking at the proto in bh. */
439
        br_write_lock_bh(BR_NETPROTO_LOCK);
440
        br_write_unlock_bh(BR_NETPROTO_LOCK);
441
 
442
        /* Remove all contrack entries for this protocol */
443
        ip_ct_selective_cleanup(kill_proto, &proto->proto);
444
 
445
        MOD_DEC_USE_COUNT;
446
}
447
 
448
static int __init init(void)
449
{
450
        return init_or_cleanup(1);
451
}
452
 
453
static void __exit fini(void)
454
{
455
        init_or_cleanup(0);
456
}
457
 
458
module_init(init);
459
module_exit(fini);
460
 
461
EXPORT_SYMBOL(ip_conntrack_protocol_register);
462
EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
463
EXPORT_SYMBOL(invert_tuplepr);
464
EXPORT_SYMBOL(ip_conntrack_alter_reply);
465
EXPORT_SYMBOL(ip_conntrack_destroyed);
466
EXPORT_SYMBOL(ip_conntrack_get);
467
EXPORT_SYMBOL(ip_conntrack_helper_register);
468
EXPORT_SYMBOL(ip_conntrack_helper_unregister);
469
EXPORT_SYMBOL(ip_ct_selective_cleanup);
470
EXPORT_SYMBOL(ip_ct_refresh);
471
EXPORT_SYMBOL(ip_ct_find_proto);
472
EXPORT_SYMBOL(__ip_ct_find_proto);
473
EXPORT_SYMBOL(ip_ct_find_helper);
474
EXPORT_SYMBOL(ip_conntrack_expect_related);
475
EXPORT_SYMBOL(ip_conntrack_change_expect);
476
EXPORT_SYMBOL(ip_conntrack_unexpect_related);
477
EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
478
EXPORT_SYMBOL_GPL(ip_conntrack_expect_put);
479
EXPORT_SYMBOL(ip_conntrack_tuple_taken);
480
EXPORT_SYMBOL(ip_ct_gather_frags);
481
EXPORT_SYMBOL(ip_conntrack_htable_size);
482
EXPORT_SYMBOL(ip_conntrack_expect_list);
483
EXPORT_SYMBOL(ip_conntrack_lock);
484
EXPORT_SYMBOL(ip_conntrack_hash);
485
EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
486
EXPORT_SYMBOL_GPL(ip_conntrack_put);

powered by: WebSVN 2.1.0

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