blob: 6323fc4abaf96f8d43976364fbbe57076ec2533c [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"
Bart De Schuymerc1939b12002-11-20 19:41:54 +00006#include "../include/ethernetdb.h"
Bart De Schuymerf46b2632003-05-01 20:18:00 +00007#include <linux/if_ether.h>
Bart De Schuymer1abc55d2002-06-01 19:23:47 +00008#include <linux/netfilter_bridge/ebt_arp.h>
9
10#define ARP_OPCODE '1'
11#define ARP_HTYPE '2'
12#define ARP_PTYPE '3'
13#define ARP_IP_S '4'
14#define ARP_IP_D '5'
Bart De Schuymerf46b2632003-05-01 20:18:00 +000015#define ARP_MAC_S '6'
16#define ARP_MAC_D '7'
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000017static struct option opts[] =
18{
19 { "arp-opcode" , required_argument, 0, ARP_OPCODE },
20 { "arp-op" , required_argument, 0, ARP_OPCODE },
21 { "arp-htype" , required_argument, 0, ARP_HTYPE },
22 { "arp-ptype" , required_argument, 0, ARP_PTYPE },
23 { "arp-ip-src" , required_argument, 0, ARP_IP_S },
24 { "arp-ip-dst" , required_argument, 0, ARP_IP_D },
Bart De Schuymerf46b2632003-05-01 20:18:00 +000025 { "arp-mac-src" , required_argument, 0, ARP_MAC_S },
26 { "arp-mac-dst" , required_argument, 0, ARP_MAC_D },
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000027 { 0 }
28};
29
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000030#define NUMOPCODES 9
Bart De Schuymer9895a8e2003-01-11 10:14:24 +000031/* a few names */
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000032static char *opcodes[] =
33{
34 "Request",
35 "Reply",
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000036 "Request_Reverse",
37 "Reply_Reverse",
38 "DRARP_Request",
39 "DRARP_Reply",
40 "DRARP_Error",
41 "InARP_Request",
42 "ARP_NAK",
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000043};
44
45static void print_help()
46{
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000047 int i;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000048
49 printf(
50"arp options:\n"
Bart De Schuymerf46b2632003-05-01 20:18:00 +000051"--arp-opcode opcode : ARP opcode (integer or string)\n"
52"--arp-htype type : ARP hardware type (integer or string)\n"
53"--arp-ptype type : ARP protocol type (hexadecimal or string)\n"
54"--arp-ip-src [!] address[/mask]: ARP IP source specification\n"
55"--arp-ip-dst [!] address[/mask]: ARP IP target specification\n"
56"--arp-mac-src [!] address[/mask]: ARP MAC source specification\n"
57"--arp-mac-dst [!] address[/mask]: ARP MAC target specification\n"
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000058" opcode strings: \n");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000059 for (i = 0; i < NUMOPCODES; i++)
Bart De Schuymer1446c292003-05-25 09:47:01 +000060 printf(" %d = %s\n", i + 1, opcodes[i]);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000061 printf(
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000062" hardware type string: 1 = Ethernet\n"
fnm36c3dc652002-11-21 10:49:38 +000063" protocol type string: see "_PATH_ETHERTYPES"\n");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000064}
65
66static void init(struct ebt_entry_match *match)
67{
68 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
69
70 arpinfo->invflags = 0;
71 arpinfo->bitmask = 0;
72}
73
Bart De Schuymerf46b2632003-05-01 20:18:00 +000074
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000075#define OPT_OPCODE 0x01
76#define OPT_HTYPE 0x02
77#define OPT_PTYPE 0x04
78#define OPT_IP_S 0x08
79#define OPT_IP_D 0x10
Bart De Schuymerf46b2632003-05-01 20:18:00 +000080#define OPT_MAC_S 0x20
81#define OPT_MAC_D 0x40
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +000082static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
83 unsigned int *flags, struct ebt_entry_match **match)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000084{
85 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000086 long int i;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000087 char *end;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000088 uint32_t *addr;
89 uint32_t *mask;
Bart De Schuymerf46b2632003-05-01 20:18:00 +000090 char *maddr;
91 char *mmask;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000092
93 switch (c) {
94 case ARP_OPCODE:
Bart De Schuymer8339ff12004-01-14 20:05:27 +000095 ebt_check_option(flags, OPT_OPCODE);
96 if (ebt_check_inverse(optarg))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000097 arpinfo->invflags |= EBT_ARP_OPCODE;
98
99 if (optind > argc)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000100 ebt_print_error("Missing ARP opcode argument");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000101 i = strtol(argv[optind - 1], &end, 10);
102 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000103 for (i = 0; i < NUMOPCODES; i++)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000104 if (!strcasecmp(opcodes[i], optarg))
105 break;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000106 if (i == NUMOPCODES)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000107 ebt_print_error("Problem with specified "
108 "ARP opcode");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000109 i++;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000110 }
111 arpinfo->opcode = htons(i);
112 arpinfo->bitmask |= EBT_ARP_OPCODE;
113 break;
114
115 case ARP_HTYPE:
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000116 ebt_check_option(flags, OPT_HTYPE);
117 if (ebt_check_inverse(optarg))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000118 arpinfo->invflags |= EBT_ARP_HTYPE;
119
120 if (optind > argc)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000121 ebt_print_error("Missing ARP hardware type argument");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000122 i = strtol(argv[optind - 1], &end, 10);
123 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
124 if (!strcasecmp("Ethernet", argv[optind - 1]))
125 i = 1;
126 else
Bart De Schuymer64182a32004-01-21 20:39:54 +0000127 ebt_print_error("Problem with specified ARP "
128 "hardware type");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000129 }
130 arpinfo->htype = htons(i);
131 arpinfo->bitmask |= EBT_ARP_HTYPE;
132 break;
133
134 case ARP_PTYPE:
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000135 {
136 uint16_t proto;
137
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000138 ebt_check_option(flags, OPT_PTYPE);
139 if (ebt_check_inverse(optarg))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000140 arpinfo->invflags |= EBT_ARP_PTYPE;
141
142 if (optind > argc)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000143 ebt_print_error("Missing ARP protocol type argument");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000144 i = strtol(argv[optind - 1], &end, 16);
145 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000146 struct ethertypeent *ent;
147
148 ent = getethertypebyname(argv[optind - 1]);
149 if (!ent)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000150 ebt_print_error("Problem with specified ARP "
151 "protocol type");
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000152 proto = ent->e_ethertype;
153
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000154 } else
155 proto = i;
156 arpinfo->ptype = htons(proto);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000157 arpinfo->bitmask |= EBT_ARP_PTYPE;
158 break;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000159 }
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000160
161 case ARP_IP_S:
162 case ARP_IP_D:
163 if (c == ARP_IP_S) {
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000164 ebt_check_option(flags, OPT_IP_S);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000165 addr = &arpinfo->saddr;
166 mask = &arpinfo->smsk;
167 arpinfo->bitmask |= EBT_ARP_SRC_IP;
168 } else {
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000169 ebt_check_option(flags, OPT_IP_D);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000170 addr = &arpinfo->daddr;
171 mask = &arpinfo->dmsk;
172 arpinfo->bitmask |= EBT_ARP_DST_IP;
173 }
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000174 if (ebt_check_inverse(optarg)) {
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000175 if (c == ARP_IP_S)
176 arpinfo->invflags |= EBT_ARP_SRC_IP;
177 else
178 arpinfo->invflags |= EBT_ARP_DST_IP;
179 }
180 if (optind > argc)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000181 ebt_print_error("Missing ARP IP address argument");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000182 ebt_parse_ip_address(argv[optind - 1], addr, mask);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000183 break;
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000184
185 case ARP_MAC_S:
186 case ARP_MAC_D:
187 if (c == ARP_MAC_S) {
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000188 ebt_check_option(flags, OPT_MAC_S);
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000189 maddr = arpinfo->smaddr;
190 mmask = arpinfo->smmsk;
191 arpinfo->bitmask |= EBT_ARP_SRC_MAC;
192 } else {
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000193 ebt_check_option(flags, OPT_MAC_D);
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000194 maddr = arpinfo->dmaddr;
195 mmask = arpinfo->dmmsk;
196 arpinfo->bitmask |= EBT_ARP_DST_MAC;
197 }
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000198 if (ebt_check_inverse(optarg)) {
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000199 if (c == ARP_MAC_S)
200 arpinfo->invflags |= EBT_ARP_SRC_MAC;
201 else
202 arpinfo->invflags |= EBT_ARP_DST_MAC;
203 }
204 if (optind > argc)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000205 ebt_print_error("Missing ARP MAC address argument");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000206 if (ebt_get_mac_and_mask(argv[optind - 1], maddr, mmask))
Bart De Schuymer64182a32004-01-21 20:39:54 +0000207 ebt_print_error("Problem with ARP MAC address "
208 "argument");
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000209 break;
210
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000211 default:
212 return 0;
213 }
214 return 1;
215}
216
217static void final_check(const struct ebt_u_entry *entry,
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000218 const struct ebt_entry_match *match, const char *name,
Bart De Schuymerc9b52932002-08-24 13:26:34 +0000219 unsigned int hookmask, unsigned int time)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000220{
Bart De Schuymer40573192002-08-29 16:48:36 +0000221 if ((entry->ethproto != ETH_P_ARP && entry->ethproto != ETH_P_RARP) ||
Bart De Schuymerb2632c52002-08-09 18:57:05 +0000222 entry->invflags & EBT_IPROTO)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000223 ebt_print_error("For (R)ARP filtering the protocol must be "
224 "specified as ARP or RARP");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000225}
226
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000227static void print(const struct ebt_u_entry *entry,
228 const struct ebt_entry_match *match)
229{
230 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
231 int i;
232
233 if (arpinfo->bitmask & EBT_ARP_OPCODE) {
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000234 int opcode = ntohs(arpinfo->opcode);
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000235 printf("--arp-op ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000236 if (arpinfo->invflags & EBT_ARP_OPCODE)
237 printf("! ");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000238 if (opcode > 0 && opcode <= NUMOPCODES)
239 printf("%s ", opcodes[opcode - 1]);
240 else
241 printf("%d ", opcode);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000242 }
243 if (arpinfo->bitmask & EBT_ARP_HTYPE) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000244 printf("--arp-htype ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000245 if (arpinfo->invflags & EBT_ARP_HTYPE)
246 printf("! ");
247 printf("%d ", ntohs(arpinfo->htype));
248 }
249 if (arpinfo->bitmask & EBT_ARP_PTYPE) {
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000250 struct ethertypeent *ent;
251
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000252 printf("--arp-ptype ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000253 if (arpinfo->invflags & EBT_ARP_PTYPE)
254 printf("! ");
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000255 ent = getethertypebynumber(ntohs(arpinfo->ptype));
256 if (!ent)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000257 printf("0x%x ", ntohs(arpinfo->ptype));
258 else
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000259 printf("%s ", ent->e_name);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000260 }
261 if (arpinfo->bitmask & EBT_ARP_SRC_IP) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000262 printf("--arp-ip-src ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000263 if (arpinfo->invflags & EBT_ARP_SRC_IP)
264 printf("! ");
265 for (i = 0; i < 4; i++)
266 printf("%d%s", ((unsigned char *)&arpinfo->saddr)[i],
267 (i == 3) ? "" : ".");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000268 printf("%s ", ebt_mask_to_dotted(arpinfo->smsk));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000269 }
270 if (arpinfo->bitmask & EBT_ARP_DST_IP) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000271 printf("--arp-ip-dst ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000272 if (arpinfo->invflags & EBT_ARP_DST_IP)
273 printf("! ");
274 for (i = 0; i < 4; i++)
275 printf("%d%s", ((unsigned char *)&arpinfo->daddr)[i],
276 (i == 3) ? "" : ".");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000277 printf("%s ", ebt_mask_to_dotted(arpinfo->dmsk));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000278 }
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000279 if (arpinfo->bitmask & EBT_ARP_SRC_MAC) {
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000280 printf("--arp-mac-src ");
281 if (arpinfo->invflags & EBT_ARP_SRC_MAC)
282 printf("! ");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000283 ebt_print_mac_and_mask(arpinfo->smaddr, arpinfo->smmsk);
Bart De Schuymer1446c292003-05-25 09:47:01 +0000284 printf(" ");
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000285 }
286 if (arpinfo->bitmask & EBT_ARP_DST_MAC) {
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000287 printf("--arp-mac-dst ");
288 if (arpinfo->invflags & EBT_ARP_DST_MAC)
289 printf("! ");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000290 ebt_print_mac_and_mask(arpinfo->dmaddr, arpinfo->dmmsk);
Bart De Schuymer1446c292003-05-25 09:47:01 +0000291 printf(" ");
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000292 }
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000293}
294
295static int compare(const struct ebt_entry_match *m1,
296 const struct ebt_entry_match *m2)
297{
298 struct ebt_arp_info *arpinfo1 = (struct ebt_arp_info *)m1->data;
299 struct ebt_arp_info *arpinfo2 = (struct ebt_arp_info *)m2->data;
300
301 if (arpinfo1->bitmask != arpinfo2->bitmask)
302 return 0;
303 if (arpinfo1->invflags != arpinfo2->invflags)
304 return 0;
305 if (arpinfo1->bitmask & EBT_ARP_OPCODE) {
306 if (arpinfo1->opcode != arpinfo2->opcode)
307 return 0;
308 }
309 if (arpinfo1->bitmask & EBT_ARP_HTYPE) {
310 if (arpinfo1->htype != arpinfo2->htype)
311 return 0;
312 }
313 if (arpinfo1->bitmask & EBT_ARP_PTYPE) {
314 if (arpinfo1->ptype != arpinfo2->ptype)
315 return 0;
316 }
317 if (arpinfo1->bitmask & EBT_ARP_SRC_IP) {
318 if (arpinfo1->saddr != arpinfo2->saddr)
319 return 0;
320 if (arpinfo1->smsk != arpinfo2->smsk)
321 return 0;
322 }
323 if (arpinfo1->bitmask & EBT_ARP_DST_IP) {
324 if (arpinfo1->daddr != arpinfo2->daddr)
325 return 0;
326 if (arpinfo1->dmsk != arpinfo2->dmsk)
327 return 0;
328 }
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000329 if (arpinfo1->bitmask & EBT_ARP_SRC_MAC) {
330 if (arpinfo1->smaddr != arpinfo2->smaddr)
331 return 0;
332 if (arpinfo1->smmsk != arpinfo2->smmsk)
333 return 0;
334 }
335 if (arpinfo1->bitmask & EBT_ARP_DST_MAC) {
336 if (arpinfo1->dmaddr != arpinfo2->dmaddr)
337 return 0;
338 if (arpinfo1->dmmsk != arpinfo2->dmmsk)
339 return 0;
340 }
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000341 return 1;
342}
343
344static struct ebt_u_match arp_match =
345{
Bart De Schuymer7cf1cca2003-08-30 16:20:19 +0000346 .name = EBT_ARP_MATCH,
347 .size = sizeof(struct ebt_arp_info),
348 .help = print_help,
349 .init = init,
350 .parse = parse,
351 .final_check = final_check,
352 .print = print,
353 .compare = compare,
354 .extra_ops = opts,
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000355};
356
Bart De Schuymer64182a32004-01-21 20:39:54 +0000357void _init(void)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000358{
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000359 ebt_register_match(&arp_match);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000360}