blob: bd6bffe7353ca1950f2f66ed11d9dca1dad58206 [file] [log] [blame]
Bart De Schuymer1abc55d2002-06-01 19:23:47 +00001#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
Bart De Schuymer1abc55d2002-06-01 19:23:47 +00004#include <getopt.h>
5#include "../include/ebtables_u.h"
6#include <linux/netfilter_bridge/ebt_arp.h>
7
8#define ARP_OPCODE '1'
9#define ARP_HTYPE '2'
10#define ARP_PTYPE '3'
11#define ARP_IP_S '4'
12#define ARP_IP_D '5'
13static struct option opts[] =
14{
15 { "arp-opcode" , required_argument, 0, ARP_OPCODE },
16 { "arp-op" , required_argument, 0, ARP_OPCODE },
17 { "arp-htype" , required_argument, 0, ARP_HTYPE },
18 { "arp-ptype" , required_argument, 0, ARP_PTYPE },
19 { "arp-ip-src" , required_argument, 0, ARP_IP_S },
20 { "arp-ip-dst" , required_argument, 0, ARP_IP_D },
21 { 0 }
22};
23
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000024#define NUMOPCODES 9
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000025// a few names
26static char *opcodes[] =
27{
28 "Request",
29 "Reply",
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000030 "Request_Reverse",
31 "Reply_Reverse",
32 "DRARP_Request",
33 "DRARP_Reply",
34 "DRARP_Error",
35 "InARP_Request",
36 "ARP_NAK",
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000037};
38
39static void print_help()
40{
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000041 int i;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000042
43 printf(
44"arp options:\n"
45"--arp-opcode opcode : ARP opcode (integer or string)\n"
46"--arp-htype type : ARP hardware type (integer or string)\n"
47"--arp-ptype type : ARP protocol type (hexadecimal or string)\n"
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000048"--arp-ip-src [!] address[/mask]: ARP IP source specification\n"
49"--arp-ip-dst [!] address[/mask]: ARP IP target specification\n"
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000050" opcode strings: \n");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000051 for (i = 0; i < NUMOPCODES; i++)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000052 printf("%d = %s\n", i + 1, opcodes[i]);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000053 printf(
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000054" hardware type string: 1 = Ethernet\n"
55" protocol type string: see /etc/ethertypes\n");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000056}
57
58static void init(struct ebt_entry_match *match)
59{
60 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
61
62 arpinfo->invflags = 0;
63 arpinfo->bitmask = 0;
64}
65
66// defined in ebt_ip.c
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000067void parse_ip_address(char *address, uint32_t *addr, uint32_t *msk);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000068
69#define OPT_OPCODE 0x01
70#define OPT_HTYPE 0x02
71#define OPT_PTYPE 0x04
72#define OPT_IP_S 0x08
73#define OPT_IP_D 0x10
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +000074static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
75 unsigned int *flags, struct ebt_entry_match **match)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000076{
77 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000078 long int i;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000079 char *end;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000080 uint32_t *addr;
81 uint32_t *mask;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000082
83 switch (c) {
84 case ARP_OPCODE:
85 check_option(flags, OPT_OPCODE);
86 if (check_inverse(optarg))
87 arpinfo->invflags |= EBT_ARP_OPCODE;
88
89 if (optind > argc)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000090 print_error("Missing ARP opcode argument");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000091 i = strtol(argv[optind - 1], &end, 10);
92 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000093 for (i = 0; i < NUMOPCODES; i++)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000094 if (!strcasecmp(opcodes[i], optarg))
95 break;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000096 if (i == NUMOPCODES)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000097 print_error("Problem with specified "
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000098 "ARP opcode");
99 i++;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000100 }
101 arpinfo->opcode = htons(i);
102 arpinfo->bitmask |= EBT_ARP_OPCODE;
103 break;
104
105 case ARP_HTYPE:
106 check_option(flags, OPT_HTYPE);
107 if (check_inverse(optarg))
108 arpinfo->invflags |= EBT_ARP_HTYPE;
109
110 if (optind > argc)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000111 print_error("Missing ARP hardware type argument");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000112 i = strtol(argv[optind - 1], &end, 10);
113 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
114 if (!strcasecmp("Ethernet", argv[optind - 1]))
115 i = 1;
116 else
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000117 print_error("Problem with specified ARP "
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000118 "hardware type");
119 }
120 arpinfo->htype = htons(i);
121 arpinfo->bitmask |= EBT_ARP_HTYPE;
122 break;
123
124 case ARP_PTYPE:
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000125 {
126 uint16_t proto;
127
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000128 check_option(flags, OPT_PTYPE);
129 if (check_inverse(optarg))
130 arpinfo->invflags |= EBT_ARP_PTYPE;
131
132 if (optind > argc)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000133 print_error("Missing ARP protocol type argument");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000134 i = strtol(argv[optind - 1], &end, 16);
135 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000136 if (name_to_number (argv[optind - 1], &proto) == -1)
137 print_error("Problem with specified ARP "
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000138 "protocol type");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000139 } else
140 proto = i;
141 arpinfo->ptype = htons(proto);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000142 arpinfo->bitmask |= EBT_ARP_PTYPE;
143 break;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000144 }
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000145
146 case ARP_IP_S:
147 case ARP_IP_D:
148 if (c == ARP_IP_S) {
149 check_option(flags, OPT_IP_S);
150 addr = &arpinfo->saddr;
151 mask = &arpinfo->smsk;
152 arpinfo->bitmask |= EBT_ARP_SRC_IP;
153 } else {
154 check_option(flags, OPT_IP_D);
155 addr = &arpinfo->daddr;
156 mask = &arpinfo->dmsk;
157 arpinfo->bitmask |= EBT_ARP_DST_IP;
158 }
159 if (check_inverse(optarg)) {
160 if (c == ARP_IP_S)
161 arpinfo->invflags |= EBT_ARP_SRC_IP;
162 else
163 arpinfo->invflags |= EBT_ARP_DST_IP;
164 }
165 if (optind > argc)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000166 print_error("Missing ARP IP address argument");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000167 parse_ip_address(argv[optind - 1], addr, mask);
168 break;
169 default:
170 return 0;
171 }
172 return 1;
173}
174
175static void final_check(const struct ebt_u_entry *entry,
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000176 const struct ebt_entry_match *match, const char *name,
177 unsigned int hook_mask, unsigned int time)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000178{
179 if (entry->bitmask & EBT_NOPROTO || entry->bitmask & EBT_802_3 ||
Bart De Schuymerb2632c52002-08-09 18:57:05 +0000180 (entry->ethproto != ETH_P_ARP && entry->ethproto != ETH_P_RARP) ||
181 entry->invflags & EBT_IPROTO)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000182 print_error("For (R)ARP filtering the protocol must be "
183 "specified as ARP or RARP");
184}
185
186// defined in the ebt_ip.c
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000187char *mask_to_dotted(uint32_t mask);
188
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000189static void print(const struct ebt_u_entry *entry,
190 const struct ebt_entry_match *match)
191{
192 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
193 int i;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000194 char name[21];
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000195
196 if (arpinfo->bitmask & EBT_ARP_OPCODE) {
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000197 int opcode = ntohs(arpinfo->opcode);
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000198 printf("--arp-op ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000199 if (arpinfo->invflags & EBT_ARP_OPCODE)
200 printf("! ");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000201 if (opcode > 0 && opcode <= NUMOPCODES)
202 printf("%s ", opcodes[opcode - 1]);
203 else
204 printf("%d ", opcode);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000205 }
206 if (arpinfo->bitmask & EBT_ARP_HTYPE) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000207 printf("--arp-htype ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000208 if (arpinfo->invflags & EBT_ARP_HTYPE)
209 printf("! ");
210 printf("%d ", ntohs(arpinfo->htype));
211 }
212 if (arpinfo->bitmask & EBT_ARP_PTYPE) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000213 printf("--arp-ptype ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000214 if (arpinfo->invflags & EBT_ARP_PTYPE)
215 printf("! ");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000216 if (number_to_name(ntohs(arpinfo->ptype), name))
217 printf("0x%x ", ntohs(arpinfo->ptype));
218 else
219 printf("%s ", name);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000220 }
221 if (arpinfo->bitmask & EBT_ARP_SRC_IP) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000222 printf("--arp-ip-src ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000223 if (arpinfo->invflags & EBT_ARP_SRC_IP)
224 printf("! ");
225 for (i = 0; i < 4; i++)
226 printf("%d%s", ((unsigned char *)&arpinfo->saddr)[i],
227 (i == 3) ? "" : ".");
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000228 printf("%s ", mask_to_dotted(arpinfo->smsk));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000229 }
230 if (arpinfo->bitmask & EBT_ARP_DST_IP) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000231 printf("--arp-ip-dst ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000232 if (arpinfo->invflags & EBT_ARP_DST_IP)
233 printf("! ");
234 for (i = 0; i < 4; i++)
235 printf("%d%s", ((unsigned char *)&arpinfo->daddr)[i],
236 (i == 3) ? "" : ".");
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000237 printf("%s ", mask_to_dotted(arpinfo->dmsk));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000238 }
239}
240
241static int compare(const struct ebt_entry_match *m1,
242 const struct ebt_entry_match *m2)
243{
244 struct ebt_arp_info *arpinfo1 = (struct ebt_arp_info *)m1->data;
245 struct ebt_arp_info *arpinfo2 = (struct ebt_arp_info *)m2->data;
246
247 if (arpinfo1->bitmask != arpinfo2->bitmask)
248 return 0;
249 if (arpinfo1->invflags != arpinfo2->invflags)
250 return 0;
251 if (arpinfo1->bitmask & EBT_ARP_OPCODE) {
252 if (arpinfo1->opcode != arpinfo2->opcode)
253 return 0;
254 }
255 if (arpinfo1->bitmask & EBT_ARP_HTYPE) {
256 if (arpinfo1->htype != arpinfo2->htype)
257 return 0;
258 }
259 if (arpinfo1->bitmask & EBT_ARP_PTYPE) {
260 if (arpinfo1->ptype != arpinfo2->ptype)
261 return 0;
262 }
263 if (arpinfo1->bitmask & EBT_ARP_SRC_IP) {
264 if (arpinfo1->saddr != arpinfo2->saddr)
265 return 0;
266 if (arpinfo1->smsk != arpinfo2->smsk)
267 return 0;
268 }
269 if (arpinfo1->bitmask & EBT_ARP_DST_IP) {
270 if (arpinfo1->daddr != arpinfo2->daddr)
271 return 0;
272 if (arpinfo1->dmsk != arpinfo2->dmsk)
273 return 0;
274 }
275 return 1;
276}
277
278static struct ebt_u_match arp_match =
279{
280 EBT_ARP_MATCH,
281 sizeof(struct ebt_arp_info),
282 print_help,
283 init,
284 parse,
285 final_check,
286 print,
287 compare,
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000288 opts
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000289};
290
291static void _init(void) __attribute__ ((constructor));
292static void _init(void)
293{
294 register_match(&arp_match);
295}