1e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netfilter_ipv4/ip_tables.h>
85a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
9802169a4b0f71d25a0f798a9c0657a565b1e79bcPatrick McHardy#include <net/ip.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
116e23ae2a48750bda407a4a58f52a4865d7308bf5Patrick McHardy#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1335aad0ffdf548617940ca1e78be1f2e0bafc4496Jan Engelhardtstatic const struct xt_table packet_raw = {
14e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	.name = "raw",
15e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	.valid_hooks =  RAW_VALID_HOOKS,
162e4e6a17af35be359cc8f1c924f8f198fbd478ccHarald Welte	.me = THIS_MODULE,
17f88e6a8a50a603f8347343e75d035889784a507cJan Engelhardt	.af = NFPROTO_IPV4,
182b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt	.priority = NF_IP_PRI_RAW,
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The work comes in here from netfilter.c. */
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int
23795aa6ef6a1aba99050735eadd0c2341b789b53bPatrick McHardyiptable_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
24737535c5cf3524e4bfaa91e22edefd52eccabbceJan Engelhardt		 const struct net_device *in, const struct net_device *out,
25737535c5cf3524e4bfaa91e22edefd52eccabbceJan Engelhardt		 int (*okfn)(struct sk_buff *))
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
272b21e051472fdb4680076278b2ccf63ebc1cc3bcJan Engelhardt	const struct net *net;
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29795aa6ef6a1aba99050735eadd0c2341b789b53bPatrick McHardy	if (ops->hooknum == NF_INET_LOCAL_OUT &&
302b21e051472fdb4680076278b2ccf63ebc1cc3bcJan Engelhardt	    (skb->len < sizeof(struct iphdr) ||
312b21e051472fdb4680076278b2ccf63ebc1cc3bcJan Engelhardt	     ip_hdrlen(skb) < sizeof(struct iphdr)))
322b21e051472fdb4680076278b2ccf63ebc1cc3bcJan Engelhardt		/* root is playing with raw sockets. */
33802169a4b0f71d25a0f798a9c0657a565b1e79bcPatrick McHardy		return NF_ACCEPT;
342b21e051472fdb4680076278b2ccf63ebc1cc3bcJan Engelhardt
352b21e051472fdb4680076278b2ccf63ebc1cc3bcJan Engelhardt	net = dev_net((in != NULL) ? in : out);
36795aa6ef6a1aba99050735eadd0c2341b789b53bPatrick McHardy	return ipt_do_table(skb, ops->hooknum, in, out, net->ipv4.iptable_raw);
37802169a4b0f71d25a0f798a9c0657a565b1e79bcPatrick McHardy}
38802169a4b0f71d25a0f798a9c0657a565b1e79bcPatrick McHardy
392b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardtstatic struct nf_hook_ops *rawtable_ops __read_mostly;
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
419335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyanstatic int __net_init iptable_raw_net_init(struct net *net)
429335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan{
43e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt	struct ipt_replace *repl;
44e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt
45e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt	repl = ipt_alloc_initial_table(&packet_raw);
46e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt	if (repl == NULL)
47e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt		return -ENOMEM;
489335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan	net->ipv4.iptable_raw =
49e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt		ipt_register_table(net, &packet_raw, repl);
50e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt	kfree(repl);
518c6ffba0eddc8c110dbf444f51354ce42069abfcRusty Russell	return PTR_ERR_OR_ZERO(net->ipv4.iptable_raw);
529335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan}
539335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan
549335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyanstatic void __net_exit iptable_raw_net_exit(struct net *net)
559335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan{
56f54e9367f8499a9bf6b2afbc0dce63e1d53c525aAlexey Dobriyan	ipt_unregister_table(net, net->ipv4.iptable_raw);
579335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan}
589335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan
599335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyanstatic struct pernet_operations iptable_raw_net_ops = {
609335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan	.init = iptable_raw_net_init,
619335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan	.exit = iptable_raw_net_exit,
629335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan};
639335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan
6465b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonstatic int __init iptable_raw_init(void)
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
689335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan	ret = register_pernet_subsys(&iptable_raw_net_ops);
699335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan	if (ret < 0)
709335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan		return ret;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Register hooks */
732b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt	rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook);
742b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt	if (IS_ERR(rawtable_ops)) {
752b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt		ret = PTR_ERR(rawtable_ops);
7690efbed18a30d78145419cdbd44f9ec152efeb16Jean Sacren		unregister_pernet_subsys(&iptable_raw_net_ops);
772b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt	}
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8265b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonstatic void __exit iptable_raw_fini(void)
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
842b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt	xt_hook_unlink(&packet_raw, rawtable_ops);
859335f047fe61587ec82ff12fbb1220bcfdd32006Alexey Dobriyan	unregister_pernet_subsys(&iptable_raw_net_ops);
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8865b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonmodule_init(iptable_raw_init);
8965b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonmodule_exit(iptable_raw_fini);
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
91