Merge branch 'e1000-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[pandora-kernel.git] / net / ipv6 / netfilter / ip6table_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 #include <linux/module.h>
13 #include <linux/moduleparam.h>
14 #include <linux/netfilter_ipv6/ip6_tables.h>
15
16 MODULE_LICENSE("GPL");
17 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
18 MODULE_DESCRIPTION("ip6tables filter table");
19
20 #define FILTER_VALID_HOOKS ((1 << NF_IP6_LOCAL_IN) | (1 << NF_IP6_FORWARD) | (1 << NF_IP6_LOCAL_OUT))
21
22 static struct
23 {
24         struct ip6t_replace repl;
25         struct ip6t_standard entries[3];
26         struct ip6t_error term;
27 } initial_table __initdata
28 = { { "filter", FILTER_VALID_HOOKS, 4,
29       sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
30       { [NF_IP6_LOCAL_IN] = 0,
31         [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
32         [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 },
33       { [NF_IP6_LOCAL_IN] = 0,
34         [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
35         [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 },
36       0, NULL, { } },
37     {
38             /* LOCAL_IN */
39             { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
40                 0,
41                 sizeof(struct ip6t_entry),
42                 sizeof(struct ip6t_standard),
43                 0, { 0, 0 }, { } },
44               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
45                 -NF_ACCEPT - 1 } },
46             /* FORWARD */
47             { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
48                 0,
49                 sizeof(struct ip6t_entry),
50                 sizeof(struct ip6t_standard),
51                 0, { 0, 0 }, { } },
52               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
53                 -NF_ACCEPT - 1 } },
54             /* LOCAL_OUT */
55             { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
56                 0,
57                 sizeof(struct ip6t_entry),
58                 sizeof(struct ip6t_standard),
59                 0, { 0, 0 }, { } },
60               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
61                 -NF_ACCEPT - 1 } }
62     },
63     /* ERROR */
64     { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
65         0,
66         sizeof(struct ip6t_entry),
67         sizeof(struct ip6t_error),
68         0, { 0, 0 }, { } },
69       { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
70           { } },
71         "ERROR"
72       }
73     }
74 };
75
76 static struct xt_table packet_filter = {
77         .name           = "filter",
78         .valid_hooks    = FILTER_VALID_HOOKS,
79         .lock           = RW_LOCK_UNLOCKED,
80         .me             = THIS_MODULE,
81         .af             = AF_INET6,
82 };
83
84 /* The work comes in here from netfilter.c. */
85 static unsigned int
86 ip6t_hook(unsigned int hook,
87          struct sk_buff **pskb,
88          const struct net_device *in,
89          const struct net_device *out,
90          int (*okfn)(struct sk_buff *))
91 {
92         return ip6t_do_table(pskb, hook, in, out, &packet_filter);
93 }
94
95 static unsigned int
96 ip6t_local_out_hook(unsigned int hook,
97                    struct sk_buff **pskb,
98                    const struct net_device *in,
99                    const struct net_device *out,
100                    int (*okfn)(struct sk_buff *))
101 {
102 #if 0
103         /* root is playing with raw sockets. */
104         if ((*pskb)->len < sizeof(struct iphdr)
105             || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
106                 if (net_ratelimit())
107                         printk("ip6t_hook: happy cracking.\n");
108                 return NF_ACCEPT;
109         }
110 #endif
111
112         return ip6t_do_table(pskb, hook, in, out, &packet_filter);
113 }
114
115 static struct nf_hook_ops ip6t_ops[] = {
116         {
117                 .hook           = ip6t_hook,
118                 .owner          = THIS_MODULE,
119                 .pf             = PF_INET6,
120                 .hooknum        = NF_IP6_LOCAL_IN,
121                 .priority       = NF_IP6_PRI_FILTER,
122         },
123         {
124                 .hook           = ip6t_hook,
125                 .owner          = THIS_MODULE,
126                 .pf             = PF_INET6,
127                 .hooknum        = NF_IP6_FORWARD,
128                 .priority       = NF_IP6_PRI_FILTER,
129         },
130         {
131                 .hook           = ip6t_local_out_hook,
132                 .owner          = THIS_MODULE,
133                 .pf             = PF_INET6,
134                 .hooknum        = NF_IP6_LOCAL_OUT,
135                 .priority       = NF_IP6_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 ip6table_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 = ip6t_register_table(&packet_filter, &initial_table.repl);
157         if (ret < 0)
158                 return ret;
159
160         /* Register hooks */
161         ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
162         if (ret < 0)
163                 goto cleanup_table;
164
165         return ret;
166
167  cleanup_table:
168         ip6t_unregister_table(&packet_filter);
169         return ret;
170 }
171
172 static void __exit ip6table_filter_fini(void)
173 {
174         nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
175         ip6t_unregister_table(&packet_filter);
176 }
177
178 module_init(ip6table_filter_init);
179 module_exit(ip6table_filter_fini);