Merge branch 'e1000-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[pandora-kernel.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/moduleparam.h>
15 #include <linux/netfilter_ipv4/ip_tables.h>
16 #include <net/ip.h>
17
18 MODULE_LICENSE("GPL");
19 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
20 MODULE_DESCRIPTION("iptables filter table");
21
22 #define FILTER_VALID_HOOKS ((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))
23
24 static struct
25 {
26         struct ipt_replace repl;
27         struct ipt_standard entries[3];
28         struct ipt_error term;
29 } initial_table __initdata
30 = { { "filter", FILTER_VALID_HOOKS, 4,
31       sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
32       { [NF_IP_LOCAL_IN] = 0,
33         [NF_IP_FORWARD] = sizeof(struct ipt_standard),
34         [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
35       { [NF_IP_LOCAL_IN] = 0,
36         [NF_IP_FORWARD] = sizeof(struct ipt_standard),
37         [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
38       0, NULL, { } },
39     {
40             /* LOCAL_IN */
41             { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
42                 0,
43                 sizeof(struct ipt_entry),
44                 sizeof(struct ipt_standard),
45                 0, { 0, 0 }, { } },
46               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
47                 -NF_ACCEPT - 1 } },
48             /* FORWARD */
49             { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
50                 0,
51                 sizeof(struct ipt_entry),
52                 sizeof(struct ipt_standard),
53                 0, { 0, 0 }, { } },
54               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
55                 -NF_ACCEPT - 1 } },
56             /* LOCAL_OUT */
57             { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
58                 0,
59                 sizeof(struct ipt_entry),
60                 sizeof(struct ipt_standard),
61                 0, { 0, 0 }, { } },
62               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
63                 -NF_ACCEPT - 1 } }
64     },
65     /* ERROR */
66     { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
67         0,
68         sizeof(struct ipt_entry),
69         sizeof(struct ipt_error),
70         0, { 0, 0 }, { } },
71       { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
72           { } },
73         "ERROR"
74       }
75     }
76 };
77
78 static struct xt_table packet_filter = {
79         .name           = "filter",
80         .valid_hooks    = FILTER_VALID_HOOKS,
81         .lock           = RW_LOCK_UNLOCKED,
82         .me             = THIS_MODULE,
83         .af             = AF_INET,
84 };
85
86 /* The work comes in here from netfilter.c. */
87 static unsigned int
88 ipt_hook(unsigned int hook,
89          struct sk_buff **pskb,
90          const struct net_device *in,
91          const struct net_device *out,
92          int (*okfn)(struct sk_buff *))
93 {
94         return ipt_do_table(pskb, hook, in, out, &packet_filter);
95 }
96
97 static unsigned int
98 ipt_local_out_hook(unsigned int hook,
99                    struct sk_buff **pskb,
100                    const struct net_device *in,
101                    const struct net_device *out,
102                    int (*okfn)(struct sk_buff *))
103 {
104         /* root is playing with raw sockets. */
105         if ((*pskb)->len < sizeof(struct iphdr)
106             || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
107                 if (net_ratelimit())
108                         printk("ipt_hook: happy cracking.\n");
109                 return NF_ACCEPT;
110         }
111
112         return ipt_do_table(pskb, hook, in, out, &packet_filter);
113 }
114
115 static struct nf_hook_ops ipt_ops[] = {
116         {
117                 .hook           = ipt_hook,
118                 .owner          = THIS_MODULE,
119                 .pf             = PF_INET,
120                 .hooknum        = NF_IP_LOCAL_IN,
121                 .priority       = NF_IP_PRI_FILTER,
122         },
123         {
124                 .hook           = ipt_hook,
125                 .owner          = THIS_MODULE,
126                 .pf             = PF_INET,
127                 .hooknum        = NF_IP_FORWARD,
128                 .priority       = NF_IP_PRI_FILTER,
129         },
130         {
131                 .hook           = ipt_local_out_hook,
132                 .owner          = THIS_MODULE,
133                 .pf             = PF_INET,
134                 .hooknum        = NF_IP_LOCAL_OUT,
135                 .priority       = NF_IP_PRI_FILTER,
136         },
137 };
138
139 /* Default to forward because I got too much mail already. */
140 static int forward = NF_ACCEPT;
141 module_param(forward, bool, 0000);
142
143 static int __init iptable_filter_init(void)
144 {
145         int ret;
146
147         if (forward < 0 || forward > NF_MAX_VERDICT) {
148                 printk("iptables forward must be 0 or 1\n");
149                 return -EINVAL;
150         }
151
152         /* Entry 1 is the FORWARD hook */
153         initial_table.entries[1].target.verdict = -forward - 1;
154
155         /* Register table */
156         ret = ipt_register_table(&packet_filter, &initial_table.repl);
157         if (ret < 0)
158                 return ret;
159
160         /* Register hooks */
161         ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
162         if (ret < 0)
163                 goto cleanup_table;
164
165         return ret;
166
167  cleanup_table:
168         ipt_unregister_table(&packet_filter);
169         return ret;
170 }
171
172 static void __exit iptable_filter_fini(void)
173 {
174         nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
175         ipt_unregister_table(&packet_filter);
176 }
177
178 module_init(iptable_filter_init);
179 module_exit(iptable_filter_fini);