ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / net / ipv4 / netfilter / iptable_filter.c
1 /*
2  * This is the 1999 rewrite of IP Firewalling, aiming for kernel 2.3.x.
3  *
4  * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5  * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  */
12
13 #include <linux/module.h>
14 #include <linux/netfilter_ipv4/ip_tables.h>
15
16 MODULE_LICENSE("GPL");
17 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
18 MODULE_DESCRIPTION("iptables filter table");
19
20 #define FILTER_VALID_HOOKS ((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))
21
22 /* Standard entry. */
23 struct ipt_standard
24 {
25         struct ipt_entry entry;
26         struct ipt_standard_target target;
27 };
28
29 struct ipt_error_target
30 {
31         struct ipt_entry_target target;
32         char errorname[IPT_FUNCTION_MAXNAMELEN];
33 };
34
35 struct ipt_error
36 {
37         struct ipt_entry entry;
38         struct ipt_error_target target;
39 };
40
41 static struct
42 {
43         struct ipt_replace repl;
44         struct ipt_standard entries[3];
45         struct ipt_error term;
46 } initial_table __initdata
47 = { { "filter", FILTER_VALID_HOOKS, 4,
48       sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
49       { [NF_IP_LOCAL_IN] = 0,
50         [NF_IP_FORWARD] = sizeof(struct ipt_standard),
51         [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
52       { [NF_IP_LOCAL_IN] = 0,
53         [NF_IP_FORWARD] = sizeof(struct ipt_standard),
54         [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
55       0, NULL, { } },
56     {
57             /* LOCAL_IN */
58             { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
59                 0,
60                 sizeof(struct ipt_entry),
61                 sizeof(struct ipt_standard),
62                 0, { 0, 0 }, { } },
63               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
64                 -NF_ACCEPT - 1 } },
65             /* FORWARD */
66             { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
67                 0,
68                 sizeof(struct ipt_entry),
69                 sizeof(struct ipt_standard),
70                 0, { 0, 0 }, { } },
71               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
72                 -NF_ACCEPT - 1 } },
73             /* LOCAL_OUT */
74             { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
75                 0,
76                 sizeof(struct ipt_entry),
77                 sizeof(struct ipt_standard),
78                 0, { 0, 0 }, { } },
79               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
80                 -NF_ACCEPT - 1 } }
81     },
82     /* ERROR */
83     { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
84         0,
85         sizeof(struct ipt_entry),
86         sizeof(struct ipt_error),
87         0, { 0, 0 }, { } },
88       { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
89           { } },
90         "ERROR"
91       }
92     }
93 };
94
95 static struct ipt_table packet_filter = {
96         .name           = "filter",
97         .table          = &initial_table.repl,
98         .valid_hooks    = FILTER_VALID_HOOKS,
99         .lock           = RW_LOCK_UNLOCKED,
100         .me             = THIS_MODULE
101 };
102
103 /* The work comes in here from netfilter.c. */
104 static unsigned int
105 ipt_hook(unsigned int hook,
106          struct sk_buff **pskb,
107          const struct net_device *in,
108          const struct net_device *out,
109          int (*okfn)(struct sk_buff *))
110 {
111         return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL);
112 }
113
114 static unsigned int
115 ipt_local_out_hook(unsigned int hook,
116                    struct sk_buff **pskb,
117                    const struct net_device *in,
118                    const struct net_device *out,
119                    int (*okfn)(struct sk_buff *))
120 {
121         /* root is playing with raw sockets. */
122         if ((*pskb)->len < sizeof(struct iphdr)
123             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
124                 if (net_ratelimit())
125                         printk("ipt_hook: happy cracking.\n");
126                 return NF_ACCEPT;
127         }
128
129         return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL);
130 }
131
132 static struct nf_hook_ops ipt_ops[] = {
133         {
134                 .hook           = ipt_hook,
135                 .owner          = THIS_MODULE,
136                 .pf             = PF_INET,
137                 .hooknum        = NF_IP_LOCAL_IN,
138                 .priority       = NF_IP_PRI_FILTER,
139         },
140         {
141                 .hook           = ipt_hook,
142                 .owner          = THIS_MODULE,
143                 .pf             = PF_INET,
144                 .hooknum        = NF_IP_FORWARD,
145                 .priority       = NF_IP_PRI_FILTER,
146         },
147         {
148                 .hook           = ipt_local_out_hook,
149                 .owner          = THIS_MODULE,
150                 .pf             = PF_INET,
151                 .hooknum        = NF_IP_LOCAL_OUT,
152                 .priority       = NF_IP_PRI_FILTER,
153         },
154 };
155
156 /* Default to forward because I got too much mail already. */
157 static int forward = NF_ACCEPT;
158 MODULE_PARM(forward, "i");
159
160 static int __init init(void)
161 {
162         int ret;
163
164         if (forward < 0 || forward > NF_MAX_VERDICT) {
165                 printk("iptables forward must be 0 or 1\n");
166                 return -EINVAL;
167         }
168
169         /* Entry 1 is the FORWARD hook */
170         initial_table.entries[1].target.verdict = -forward - 1;
171
172         /* Register table */
173         ret = ipt_register_table(&packet_filter);
174         if (ret < 0)
175                 return ret;
176
177         /* Register hooks */
178         ret = nf_register_hook(&ipt_ops[0]);
179         if (ret < 0)
180                 goto cleanup_table;
181
182         ret = nf_register_hook(&ipt_ops[1]);
183         if (ret < 0)
184                 goto cleanup_hook0;
185
186         ret = nf_register_hook(&ipt_ops[2]);
187         if (ret < 0)
188                 goto cleanup_hook1;
189
190         return ret;
191
192  cleanup_hook1:
193         nf_unregister_hook(&ipt_ops[1]);
194  cleanup_hook0:
195         nf_unregister_hook(&ipt_ops[0]);
196  cleanup_table:
197         ipt_unregister_table(&packet_filter);
198
199         return ret;
200 }
201
202 static void __exit fini(void)
203 {
204         unsigned int i;
205
206         for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
207                 nf_unregister_hook(&ipt_ops[i]);
208
209         ipt_unregister_table(&packet_filter);
210 }
211
212 module_init(init);
213 module_exit(fini);