2 * IPv6 packet mangling table, a port of the IPv4 mangle table to IPv6
4 * Copyright (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
6 #include <linux/module.h>
7 #include <linux/netfilter_ipv6/ip6_tables.h>
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))
16 #define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args)
18 #define DEBUGP(x, args...)
24 struct ip6t_entry entry;
25 struct ip6t_standard_target target;
28 struct ip6t_error_target
30 struct ip6t_entry_target target;
31 char errorname[IP6T_FUNCTION_MAXNAMELEN];
36 struct ip6t_entry entry;
37 struct ip6t_error_target target;
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},
61 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
63 sizeof(struct ip6t_entry),
64 sizeof(struct ip6t_standard),
66 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
69 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
71 sizeof(struct ip6t_entry),
72 sizeof(struct ip6t_standard),
74 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
77 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
79 sizeof(struct ip6t_entry),
80 sizeof(struct ip6t_standard),
82 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
85 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
87 sizeof(struct ip6t_entry),
88 sizeof(struct ip6t_standard),
90 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
93 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
95 sizeof(struct ip6t_entry),
96 sizeof(struct ip6t_standard),
98 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
102 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
104 sizeof(struct ip6t_entry),
105 sizeof(struct ip6t_error),
107 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
114 static struct ip6t_table packet_mangler
115 = { { NULL, NULL }, "mangle", &initial_table.repl,
116 MANGLE_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
118 /* The work comes in here from netfilter.c. */
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 *))
126 return ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL);
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 *))
137 unsigned long nfmark;
139 struct in6_addr saddr, daddr;
144 /* root is playing with raw sockets. */
145 if ((*pskb)->len < sizeof(struct iphdr)
146 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
148 printk("ip6t_hook: happy cracking.\n");
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;
159 /* flowlabel and prio (includes version, which shouldn't change either */
160 flowlabel = *((u_int32_t *) (*pskb)->nh.ipv6h);
162 ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL);
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)) {
170 /* something which could affect routing has changed */
172 DEBUGP("ip6table_mangle: we'd need to re-route a packet\n");
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 }
186 static int __init init(void)
191 ret = ip6t_register_table(&packet_mangler);
196 ret = nf_register_hook(&ip6t_ops[0]);
200 ret = nf_register_hook(&ip6t_ops[1]);
204 ret = nf_register_hook(&ip6t_ops[2]);
208 ret = nf_register_hook(&ip6t_ops[3]);
212 ret = nf_register_hook(&ip6t_ops[4]);
219 nf_unregister_hook(&ip6t_ops[3]);
221 nf_unregister_hook(&ip6t_ops[2]);
223 nf_unregister_hook(&ip6t_ops[1]);
225 nf_unregister_hook(&ip6t_ops[0]);
227 ip6t_unregister_table(&packet_mangler);
232 static void __exit fini(void)
236 for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
237 nf_unregister_hook(&ip6t_ops[i]);
239 ip6t_unregister_table(&packet_mangler);
244 MODULE_LICENSE("GPL");