11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Filtering ARP tables module. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002 David S. Miller (davem@redhat.com) 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 9e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt#include <linux/netfilter/x_tables.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netfilter_arp/arp_tables.h> 115a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("arptables filter table"); 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \ 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (1 << NF_ARP_FORWARD)) 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2035aad0ffdf548617940ca1e78be1f2e0bafc4496Jan Engelhardtstatic const struct xt_table packet_filter = { 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "filter", 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .valid_hooks = FILTER_VALID_HOOKS, 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .me = THIS_MODULE, 24ee999d8b9573df1b547aacdc6d79f86eb79c25cdJan Engelhardt .af = NFPROTO_ARP, 252b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt .priority = NF_IP_PRI_FILTER, 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The work comes in here from netfilter.c */ 29737535c5cf3524e4bfaa91e22edefd52eccabbceJan Engelhardtstatic unsigned int 30795aa6ef6a1aba99050735eadd0c2341b789b53bPatrick McHardyarptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, 31737535c5cf3524e4bfaa91e22edefd52eccabbceJan Engelhardt const struct net_device *in, const struct net_device *out, 32737535c5cf3524e4bfaa91e22edefd52eccabbceJan Engelhardt int (*okfn)(struct sk_buff *)) 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 342b21e051472fdb4680076278b2ccf63ebc1cc3bcJan Engelhardt const struct net *net = dev_net((in != NULL) ? in : out); 353918fed5f31213067c1c345bd904e1ea369e6819Alexey Dobriyan 36795aa6ef6a1aba99050735eadd0c2341b789b53bPatrick McHardy return arpt_do_table(skb, ops->hooknum, in, out, 37795aa6ef6a1aba99050735eadd0c2341b789b53bPatrick McHardy net->ipv4.arptable_filter); 383918fed5f31213067c1c345bd904e1ea369e6819Alexey Dobriyan} 393918fed5f31213067c1c345bd904e1ea369e6819Alexey Dobriyan 402b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardtstatic struct nf_hook_ops *arpfilter_ops __read_mostly; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 429ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyanstatic int __net_init arptable_filter_net_init(struct net *net) 439ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan{ 44e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt struct arpt_replace *repl; 45e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt 46e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt repl = arpt_alloc_initial_table(&packet_filter); 47e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt if (repl == NULL) 48e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt return -ENOMEM; 499ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan net->ipv4.arptable_filter = 50e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt arpt_register_table(net, &packet_filter, repl); 51e3eaa9910b380530cfd2c0670fcd3f627674da8aJan Engelhardt kfree(repl); 528c6ffba0eddc8c110dbf444f51354ce42069abfcRusty Russell return PTR_ERR_OR_ZERO(net->ipv4.arptable_filter); 539ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan} 549ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan 559ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyanstatic void __net_exit arptable_filter_net_exit(struct net *net) 569ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan{ 579ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan arpt_unregister_table(net->ipv4.arptable_filter); 589ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan} 599ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan 609ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyanstatic struct pernet_operations arptable_filter_net_ops = { 619ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan .init = arptable_filter_net_init, 629ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan .exit = arptable_filter_net_exit, 639ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan}; 649ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan 6565b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonstatic int __init arptable_filter_init(void) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 67964ddaa10de8f3aeed12bc2a30726514ff309e64Patrick McHardy int ret; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 699ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan ret = register_pernet_subsys(&arptable_filter_net_ops); 709ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan if (ret < 0) 719ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan return ret; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 732b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook); 742b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt if (IS_ERR(arpfilter_ops)) { 752b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt ret = PTR_ERR(arpfilter_ops); 76964ddaa10de8f3aeed12bc2a30726514ff309e64Patrick McHardy goto cleanup_table; 772b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt } 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 80964ddaa10de8f3aeed12bc2a30726514ff309e64Patrick McHardycleanup_table: 819ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan unregister_pernet_subsys(&arptable_filter_net_ops); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8565b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonstatic void __exit arptable_filter_fini(void) 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 872b95efe7f6bb750256a702cc32d33b0cb2cd8223Jan Engelhardt xt_hook_unlink(&packet_filter, arpfilter_ops); 889ea0cb2601c4747dff758a9a7a5a4a433ad527f3Alexey Dobriyan unregister_pernet_subsys(&arptable_filter_net_ops); 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9165b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonmodule_init(arptable_filter_init); 9265b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonmodule_exit(arptable_filter_fini); 93