1/*
2 * Filtering ARP tables module.
3 *
4 * Copyright (C) 2002 David S. Miller (davem@redhat.com)
5 *
6 */
7
8#include <linux/module.h>
9#include <linux/netfilter_arp/arp_tables.h>
10
11#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT))
12
13/* Standard entry. */
14struct arpt_standard
15{
16	struct arpt_entry entry;
17	struct arpt_standard_target target;
18};
19
20struct arpt_error_target
21{
22	struct arpt_entry_target target;
23	char errorname[ARPT_FUNCTION_MAXNAMELEN];
24};
25
26struct arpt_error
27{
28	struct arpt_entry entry;
29	struct arpt_error_target target;
30};
31
32static struct
33{
34	struct arpt_replace repl;
35	struct arpt_standard entries[2];
36	struct arpt_error term;
37} initial_table __initdata
38= { { "filter", FILTER_VALID_HOOKS, 3,
39      sizeof(struct arpt_standard) * 2 + sizeof(struct arpt_error),
40      { [NF_ARP_IN] 0,
41	[NF_ARP_OUT] sizeof(struct arpt_standard) },
42      { [NF_ARP_IN] 0,
43	[NF_ARP_OUT] sizeof(struct arpt_standard), },
44      0, NULL, { } },
45    {
46	    /* ARP_IN */
47	    {
48		    {
49			    {
50				    { 0 }, { 0 }, { 0 }, { 0 },
51				    0, 0,
52				    { { 0, }, { 0, } },
53				    { { 0, }, { 0, } },
54				    0, 0,
55				    0, 0,
56				    0, 0,
57				    "", "", { 0 }, { 0 },
58				    0, 0
59			    },
60			    sizeof(struct arpt_entry),
61			    sizeof(struct arpt_standard),
62			    0,
63			    { 0, 0 }, { } },
64		    { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
65		      -NF_ACCEPT - 1 }
66	    },
67	    /* ARP_OUT */
68	    {
69		    {
70			    {
71				    { 0 }, { 0 }, { 0 }, { 0 },
72				    0, 0,
73				    { { 0, }, { 0, } },
74				    { { 0, }, { 0, } },
75				    0, 0,
76				    0, 0,
77				    0, 0,
78				    "", "", { 0 }, { 0 },
79				    0, 0
80			    },
81			    sizeof(struct arpt_entry),
82			    sizeof(struct arpt_standard),
83			    0,
84			    { 0, 0 }, { } },
85		    { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
86		      -NF_ACCEPT - 1 }
87	    }
88    },
89    /* ERROR */
90    {
91	    {
92		    {
93			    { 0 }, { 0 }, { 0 }, { 0 },
94			    0, 0,
95			    { { 0, }, { 0, } },
96			    { { 0, }, { 0, } },
97			    0, 0,
98			    0, 0,
99			    0, 0,
100			    "", "", { 0 }, { 0 },
101			    0, 0
102		    },
103		    sizeof(struct arpt_entry),
104		    sizeof(struct arpt_error),
105		    0,
106		    { 0, 0 }, { } },
107	    { { { { ARPT_ALIGN(sizeof(struct arpt_error_target)), ARPT_ERROR_TARGET } },
108		{ } },
109	      "ERROR"
110	    }
111    }
112};
113
114static struct arpt_table packet_filter
115= { { NULL, NULL }, "filter", &initial_table.repl,
116    FILTER_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
117
118/* The work comes in here from netfilter.c */
119static unsigned int arpt_hook(unsigned int hook,
120			      struct sk_buff **pskb,
121			      const struct net_device *in,
122			      const struct net_device *out,
123			      int (*okfn)(struct sk_buff *))
124{
125	return arpt_do_table(pskb, hook, in, out, &packet_filter, NULL);
126}
127
128static struct nf_hook_ops arpt_ops[]
129= { { { NULL, NULL }, arpt_hook, NF_ARP, NF_ARP_IN, 0 },
130    { { NULL, NULL }, arpt_hook, NF_ARP, NF_ARP_OUT, 0 }
131};
132
133static int __init init(void)
134{
135	int ret;
136
137	/* Register table */
138	ret = arpt_register_table(&packet_filter);
139	if (ret < 0)
140		return ret;
141
142	/* Register hooks */
143	ret = nf_register_hook(&arpt_ops[0]);
144	if (ret < 0)
145		goto cleanup_table;
146
147	ret = nf_register_hook(&arpt_ops[1]);
148	if (ret < 0)
149		goto cleanup_hook0;
150
151	return ret;
152
153cleanup_hook0:
154	nf_unregister_hook(&arpt_ops[0]);
155
156cleanup_table:
157	arpt_unregister_table(&packet_filter);
158
159	return ret;
160}
161
162static void __exit fini(void)
163{
164	unsigned int i;
165
166	for (i = 0; i < sizeof(arpt_ops)/sizeof(struct nf_hook_ops); i++)
167		nf_unregister_hook(&arpt_ops[i]);
168
169	arpt_unregister_table(&packet_filter);
170}
171
172module_init(init);
173module_exit(fini);
174MODULE_LICENSE("GPL");
175