more debug output
[linux-2.4.git] / net / ipv6 / netfilter / ip6table_mangle.c
1 /*
2  * IPv6 packet mangling table, a port of the IPv4 mangle table to IPv6
3  *
4  * Copyright (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
5  */
6 #include <linux/module.h>
7 #include <linux/netfilter_ipv6/ip6_tables.h>
8
9 #define MANGLE_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | \
10                             (1 << NF_IP6_LOCAL_IN) | \
11                             (1 << NF_IP6_FORWARD) | \
12                             (1 << NF_IP6_LOCAL_OUT) | \
13                             (1 << NF_IP6_POST_ROUTING))
14
15 #if 0
16 #define DEBUGP(x, args...)      printk(KERN_DEBUG x, ## args)
17 #else
18 #define DEBUGP(x, args...)
19 #endif
20
21 /* Standard entry. */
22 struct ip6t_standard
23 {
24         struct ip6t_entry entry;
25         struct ip6t_standard_target target;
26 };
27
28 struct ip6t_error_target
29 {
30         struct ip6t_entry_target target;
31         char errorname[IP6T_FUNCTION_MAXNAMELEN];
32 };
33
34 struct ip6t_error
35 {
36         struct ip6t_entry entry;
37         struct ip6t_error_target target;
38 };
39
40 static struct
41 {
42         struct ip6t_replace repl;
43         struct ip6t_standard entries[5];
44         struct ip6t_error term;
45 } initial_table __initdata
46 = { { "mangle", MANGLE_VALID_HOOKS, 6,
47       sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
48       { [NF_IP6_PRE_ROUTING]    0,
49         [NF_IP6_LOCAL_IN]       sizeof(struct ip6t_standard),
50         [NF_IP6_FORWARD]        sizeof(struct ip6t_standard) * 2,
51         [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) * 3,
52         [NF_IP6_POST_ROUTING]   sizeof(struct ip6t_standard) * 4},
53       { [NF_IP6_PRE_ROUTING]    0,
54         [NF_IP6_LOCAL_IN]       sizeof(struct ip6t_standard),
55         [NF_IP6_FORWARD]        sizeof(struct ip6t_standard) * 2,
56         [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) * 3,
57         [NF_IP6_POST_ROUTING]   sizeof(struct ip6t_standard) * 4},
58       0, NULL, { } },
59     {
60             /* PRE_ROUTING */
61             { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
62                 0,
63                 sizeof(struct ip6t_entry),
64                 sizeof(struct ip6t_standard),
65                 0, { 0, 0 }, { } },
66               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
67                 -NF_ACCEPT - 1 } },
68             /* LOCAL_IN */
69             { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
70                 0,
71                 sizeof(struct ip6t_entry),
72                 sizeof(struct ip6t_standard),
73                 0, { 0, 0 }, { } },
74               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
75                 -NF_ACCEPT - 1 } },
76             /* FORWARD */
77             { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
78                 0,
79                 sizeof(struct ip6t_entry),
80                 sizeof(struct ip6t_standard),
81                 0, { 0, 0 }, { } },
82               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
83                 -NF_ACCEPT - 1 } },
84             /* LOCAL_OUT */
85             { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
86                 0,
87                 sizeof(struct ip6t_entry),
88                 sizeof(struct ip6t_standard),
89                 0, { 0, 0 }, { } },
90               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
91                 -NF_ACCEPT - 1 } },
92             /* POST_ROUTING */
93             { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
94                 0,
95                 sizeof(struct ip6t_entry),
96                 sizeof(struct ip6t_standard),
97                 0, { 0, 0 }, { } },
98               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
99                 -NF_ACCEPT - 1 } }
100     },
101     /* ERROR */
102     { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
103         0,
104         sizeof(struct ip6t_entry),
105         sizeof(struct ip6t_error),
106         0, { 0, 0 }, { } },
107       { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
108           { } },
109         "ERROR"
110       }
111     }
112 };
113
114 static struct ip6t_table packet_mangler
115 = { { NULL, NULL }, "mangle", &initial_table.repl,
116     MANGLE_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
117
118 /* The work comes in here from netfilter.c. */
119 static unsigned int
120 ip6t_route_hook(unsigned int hook,
121          struct sk_buff **pskb,
122          const struct net_device *in,
123          const struct net_device *out,
124          int (*okfn)(struct sk_buff *))
125 {
126         return ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL);
127 }
128
129 static unsigned int
130 ip6t_local_hook(unsigned int hook,
131                    struct sk_buff **pskb,
132                    const struct net_device *in,
133                    const struct net_device *out,
134                    int (*okfn)(struct sk_buff *))
135 {
136
137         unsigned long nfmark;
138         unsigned int ret;
139         struct in6_addr saddr, daddr;
140         u_int8_t hop_limit;
141         u_int32_t flowlabel;
142
143 #if 0
144         /* root is playing with raw sockets. */
145         if ((*pskb)->len < sizeof(struct iphdr)
146             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
147                 if (net_ratelimit())
148                         printk("ip6t_hook: happy cracking.\n");
149                 return NF_ACCEPT;
150         }
151 #endif
152
153         /* save source/dest address, nfmark, hoplimit, flowlabel, priority,  */
154         memcpy(&saddr, &(*pskb)->nh.ipv6h->saddr, sizeof(saddr));
155         memcpy(&daddr, &(*pskb)->nh.ipv6h->daddr, sizeof(daddr));
156         nfmark = (*pskb)->nfmark;
157         hop_limit = (*pskb)->nh.ipv6h->hop_limit;
158
159         /* flowlabel and prio (includes version, which shouldn't change either */
160         flowlabel = *((u_int32_t *) (*pskb)->nh.ipv6h);
161
162         ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL);
163
164         if (ret != NF_DROP && ret != NF_STOLEN 
165                 && (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr))
166                     || memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr))
167                     || (*pskb)->nfmark != nfmark
168                     || (*pskb)->nh.ipv6h->hop_limit != hop_limit)) {
169
170                 /* something which could affect routing has changed */
171
172                 DEBUGP("ip6table_mangle: we'd need to re-route a packet\n");
173         }
174
175         return ret;
176 }
177
178 static struct nf_hook_ops ip6t_ops[]
179 = { { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_PRE_ROUTING,  NF_IP6_PRI_MANGLE },
180     { { NULL, NULL }, ip6t_local_hook, PF_INET6, NF_IP6_LOCAL_IN,     NF_IP6_PRI_MANGLE },
181     { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_FORWARD,      NF_IP6_PRI_MANGLE },
182     { { NULL, NULL }, ip6t_local_hook, PF_INET6, NF_IP6_LOCAL_OUT,    NF_IP6_PRI_MANGLE },
183     { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_POST_ROUTING, NF_IP6_PRI_MANGLE }
184 };
185
186 static int __init init(void)
187 {
188         int ret;
189
190         /* Register table */
191         ret = ip6t_register_table(&packet_mangler);
192         if (ret < 0)
193                 return ret;
194
195         /* Register hooks */
196         ret = nf_register_hook(&ip6t_ops[0]);
197         if (ret < 0)
198                 goto cleanup_table;
199
200         ret = nf_register_hook(&ip6t_ops[1]);
201         if (ret < 0)
202                 goto cleanup_hook0;
203
204         ret = nf_register_hook(&ip6t_ops[2]);
205         if (ret < 0)
206                 goto cleanup_hook1;
207
208         ret = nf_register_hook(&ip6t_ops[3]);
209         if (ret < 0)
210                 goto cleanup_hook2;
211
212         ret = nf_register_hook(&ip6t_ops[4]);
213         if (ret < 0)
214                 goto cleanup_hook3;
215
216         return ret;
217
218  cleanup_hook3:
219         nf_unregister_hook(&ip6t_ops[3]);
220  cleanup_hook2:
221         nf_unregister_hook(&ip6t_ops[2]);
222  cleanup_hook1:
223         nf_unregister_hook(&ip6t_ops[1]);
224  cleanup_hook0:
225         nf_unregister_hook(&ip6t_ops[0]);
226  cleanup_table:
227         ip6t_unregister_table(&packet_mangler);
228
229         return ret;
230 }
231
232 static void __exit fini(void)
233 {
234         unsigned int i;
235
236         for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
237                 nf_unregister_hook(&ip6t_ops[i]);
238
239         ip6t_unregister_table(&packet_mangler);
240 }
241
242 module_init(init);
243 module_exit(fini);
244 MODULE_LICENSE("GPL");