11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * This is the 1999 rewrite of IP Firewalling, aiming for kernel 2.3.x.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
51da177e4SLinus Torvalds  * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org>
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds  * it under the terms of the GNU General Public License version 2 as
91da177e4SLinus Torvalds  * published by the Free Software Foundation.
101da177e4SLinus Torvalds  */
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds #include <linux/module.h>
131da177e4SLinus Torvalds #include <linux/moduleparam.h>
141da177e4SLinus Torvalds #include <linux/netfilter_ipv6/ip6_tables.h>
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds MODULE_LICENSE("GPL");
171da177e4SLinus Torvalds MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
181da177e4SLinus Torvalds MODULE_DESCRIPTION("ip6tables filter table");
191da177e4SLinus Torvalds 
206e23ae2aSPatrick McHardy #define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \
216e23ae2aSPatrick McHardy 			    (1 << NF_INET_FORWARD) | \
226e23ae2aSPatrick McHardy 			    (1 << NF_INET_LOCAL_OUT))
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds static struct
251da177e4SLinus Torvalds {
261da177e4SLinus Torvalds 	struct ip6t_replace repl;
271da177e4SLinus Torvalds 	struct ip6t_standard entries[3];
281da177e4SLinus Torvalds 	struct ip6t_error term;
298280aa61SAlexey Dobriyan } initial_table __net_initdata = {
303c2ad469SPatrick McHardy 	.repl = {
313c2ad469SPatrick McHardy 		.name = "filter",
323c2ad469SPatrick McHardy 		.valid_hooks = FILTER_VALID_HOOKS,
333c2ad469SPatrick McHardy 		.num_entries = 4,
343c2ad469SPatrick McHardy 		.size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
353c2ad469SPatrick McHardy 		.hook_entry = {
366e23ae2aSPatrick McHardy 			[NF_INET_LOCAL_IN] = 0,
376e23ae2aSPatrick McHardy 			[NF_INET_FORWARD] = sizeof(struct ip6t_standard),
386e23ae2aSPatrick McHardy 			[NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
391da177e4SLinus Torvalds 		},
403c2ad469SPatrick McHardy 		.underflow = {
416e23ae2aSPatrick McHardy 			[NF_INET_LOCAL_IN] = 0,
426e23ae2aSPatrick McHardy 			[NF_INET_FORWARD] = sizeof(struct ip6t_standard),
436e23ae2aSPatrick McHardy 			[NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
443c2ad469SPatrick McHardy 		},
453c2ad469SPatrick McHardy 	},
463c2ad469SPatrick McHardy 	.entries = {
473c2ad469SPatrick McHardy 		IP6T_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_IN */
483c2ad469SPatrick McHardy 		IP6T_STANDARD_INIT(NF_ACCEPT),	/* FORWARD */
493c2ad469SPatrick McHardy 		IP6T_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_OUT */
503c2ad469SPatrick McHardy 	},
513c2ad469SPatrick McHardy 	.term = IP6T_ERROR_INIT,		/* ERROR */
521da177e4SLinus Torvalds };
531da177e4SLinus Torvalds 
5435aad0ffSJan Engelhardt static const struct xt_table packet_filter = {
551da177e4SLinus Torvalds 	.name		= "filter",
561da177e4SLinus Torvalds 	.valid_hooks	= FILTER_VALID_HOOKS,
571da177e4SLinus Torvalds 	.me		= THIS_MODULE,
58f88e6a8aSJan Engelhardt 	.af		= NFPROTO_IPV6,
591da177e4SLinus Torvalds };
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds /* The work comes in here from netfilter.c. */
621da177e4SLinus Torvalds static unsigned int
63737535c5SJan Engelhardt ip6table_filter_hook(unsigned int hook, struct sk_buff *skb,
64737535c5SJan Engelhardt 		     const struct net_device *in, const struct net_device *out,
6543de9dfeSAlexey Dobriyan 		     int (*okfn)(struct sk_buff *))
6643de9dfeSAlexey Dobriyan {
67737535c5SJan Engelhardt 	if (hook == NF_INET_LOCAL_OUT)
68737535c5SJan Engelhardt 		return ip6t_do_table(skb, hook, in, out,
69737535c5SJan Engelhardt 				     dev_net(out)->ipv6.ip6table_filter);
70737535c5SJan Engelhardt 
71737535c5SJan Engelhardt 	/* INPUT/FORWARD: */
7243de9dfeSAlexey Dobriyan 	return ip6t_do_table(skb, hook, in, out,
7348dc7865SAlexey Dobriyan 			     dev_net(in)->ipv6.ip6table_filter);
741da177e4SLinus Torvalds }
751da177e4SLinus Torvalds 
761999414aSPatrick McHardy static struct nf_hook_ops ip6t_ops[] __read_mostly = {
771da177e4SLinus Torvalds 	{
78737535c5SJan Engelhardt 		.hook		= ip6table_filter_hook,
791da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
8024c232d8SJan Engelhardt 		.pf		= NFPROTO_IPV6,
816e23ae2aSPatrick McHardy 		.hooknum	= NF_INET_LOCAL_IN,
821da177e4SLinus Torvalds 		.priority	= NF_IP6_PRI_FILTER,
831da177e4SLinus Torvalds 	},
841da177e4SLinus Torvalds 	{
85737535c5SJan Engelhardt 		.hook		= ip6table_filter_hook,
861da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
8724c232d8SJan Engelhardt 		.pf		= NFPROTO_IPV6,
886e23ae2aSPatrick McHardy 		.hooknum	= NF_INET_FORWARD,
891da177e4SLinus Torvalds 		.priority	= NF_IP6_PRI_FILTER,
901da177e4SLinus Torvalds 	},
911da177e4SLinus Torvalds 	{
92737535c5SJan Engelhardt 		.hook		= ip6table_filter_hook,
931da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
9424c232d8SJan Engelhardt 		.pf		= NFPROTO_IPV6,
956e23ae2aSPatrick McHardy 		.hooknum	= NF_INET_LOCAL_OUT,
961da177e4SLinus Torvalds 		.priority	= NF_IP6_PRI_FILTER,
971da177e4SLinus Torvalds 	},
981da177e4SLinus Torvalds };
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds /* Default to forward because I got too much mail already. */
1011da177e4SLinus Torvalds static int forward = NF_ACCEPT;
1021da177e4SLinus Torvalds module_param(forward, bool, 0000);
1031da177e4SLinus Torvalds 
1048280aa61SAlexey Dobriyan static int __net_init ip6table_filter_net_init(struct net *net)
1058280aa61SAlexey Dobriyan {
1068280aa61SAlexey Dobriyan 	/* Register table */
1078280aa61SAlexey Dobriyan 	net->ipv6.ip6table_filter =
1088280aa61SAlexey Dobriyan 		ip6t_register_table(net, &packet_filter, &initial_table.repl);
1098280aa61SAlexey Dobriyan 	if (IS_ERR(net->ipv6.ip6table_filter))
1108280aa61SAlexey Dobriyan 		return PTR_ERR(net->ipv6.ip6table_filter);
1118280aa61SAlexey Dobriyan 	return 0;
1128280aa61SAlexey Dobriyan }
1138280aa61SAlexey Dobriyan 
1148280aa61SAlexey Dobriyan static void __net_exit ip6table_filter_net_exit(struct net *net)
1158280aa61SAlexey Dobriyan {
116f54e9367SAlexey Dobriyan 	ip6t_unregister_table(net, net->ipv6.ip6table_filter);
1178280aa61SAlexey Dobriyan }
1188280aa61SAlexey Dobriyan 
1198280aa61SAlexey Dobriyan static struct pernet_operations ip6table_filter_net_ops = {
1208280aa61SAlexey Dobriyan 	.init = ip6table_filter_net_init,
1218280aa61SAlexey Dobriyan 	.exit = ip6table_filter_net_exit,
1228280aa61SAlexey Dobriyan };
1238280aa61SAlexey Dobriyan 
12465b4b4e8SAndrew Morton static int __init ip6table_filter_init(void)
1251da177e4SLinus Torvalds {
1261da177e4SLinus Torvalds 	int ret;
1271da177e4SLinus Torvalds 
1281da177e4SLinus Torvalds 	if (forward < 0 || forward > NF_MAX_VERDICT) {
1291da177e4SLinus Torvalds 		printk("iptables forward must be 0 or 1\n");
1301da177e4SLinus Torvalds 		return -EINVAL;
1311da177e4SLinus Torvalds 	}
1321da177e4SLinus Torvalds 
1331da177e4SLinus Torvalds 	/* Entry 1 is the FORWARD hook */
1341da177e4SLinus Torvalds 	initial_table.entries[1].target.verdict = -forward - 1;
1351da177e4SLinus Torvalds 
1368280aa61SAlexey Dobriyan 	ret = register_pernet_subsys(&ip6table_filter_net_ops);
1378280aa61SAlexey Dobriyan 	if (ret < 0)
1388280aa61SAlexey Dobriyan 		return ret;
1391da177e4SLinus Torvalds 
1401da177e4SLinus Torvalds 	/* Register hooks */
141964ddaa1SPatrick McHardy 	ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
1421da177e4SLinus Torvalds 	if (ret < 0)
1431da177e4SLinus Torvalds 		goto cleanup_table;
1441da177e4SLinus Torvalds 
1451da177e4SLinus Torvalds 	return ret;
1461da177e4SLinus Torvalds 
1471da177e4SLinus Torvalds  cleanup_table:
1488280aa61SAlexey Dobriyan 	unregister_pernet_subsys(&ip6table_filter_net_ops);
1491da177e4SLinus Torvalds 	return ret;
1501da177e4SLinus Torvalds }
1511da177e4SLinus Torvalds 
15265b4b4e8SAndrew Morton static void __exit ip6table_filter_fini(void)
1531da177e4SLinus Torvalds {
154964ddaa1SPatrick McHardy 	nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
1558280aa61SAlexey Dobriyan 	unregister_pernet_subsys(&ip6table_filter_net_ops);
1561da177e4SLinus Torvalds }
1571da177e4SLinus Torvalds 
15865b4b4e8SAndrew Morton module_init(ip6table_filter_init);
15965b4b4e8SAndrew Morton module_exit(ip6table_filter_fini);
160