blob: ffe67817132c6e2d9ab318567068c6bdb99de5db [file] [log] [blame]
Bart De Schuymerff587202005-02-08 20:02:28 +00001/* ebt_arp
2 *
3 * Authors:
4 * Bart De Schuymer <bdschuym@pandora.be>
5 * Tim Gardner <timg@tpi.com>
6 *
7 * April, 2002
8 */
9
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000010#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000013#include <getopt.h>
14#include "../include/ebtables_u.h"
Bart De Schuymerc1939b12002-11-20 19:41:54 +000015#include "../include/ethernetdb.h"
Bart De Schuymerf46b2632003-05-01 20:18:00 +000016#include <linux/if_ether.h>
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000017#include <linux/netfilter_bridge/ebt_arp.h>
18
19#define ARP_OPCODE '1'
20#define ARP_HTYPE '2'
21#define ARP_PTYPE '3'
22#define ARP_IP_S '4'
23#define ARP_IP_D '5'
Bart De Schuymerf46b2632003-05-01 20:18:00 +000024#define ARP_MAC_S '6'
25#define ARP_MAC_D '7'
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000026static struct option opts[] =
27{
28 { "arp-opcode" , required_argument, 0, ARP_OPCODE },
29 { "arp-op" , required_argument, 0, ARP_OPCODE },
30 { "arp-htype" , required_argument, 0, ARP_HTYPE },
31 { "arp-ptype" , required_argument, 0, ARP_PTYPE },
32 { "arp-ip-src" , required_argument, 0, ARP_IP_S },
33 { "arp-ip-dst" , required_argument, 0, ARP_IP_D },
Bart De Schuymerf46b2632003-05-01 20:18:00 +000034 { "arp-mac-src" , required_argument, 0, ARP_MAC_S },
35 { "arp-mac-dst" , required_argument, 0, ARP_MAC_D },
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000036 { 0 }
37};
38
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000039#define NUMOPCODES 9
Bart De Schuymer9895a8e2003-01-11 10:14:24 +000040/* a few names */
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000041static char *opcodes[] =
42{
43 "Request",
44 "Reply",
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000045 "Request_Reverse",
46 "Reply_Reverse",
47 "DRARP_Request",
48 "DRARP_Reply",
49 "DRARP_Error",
50 "InARP_Request",
51 "ARP_NAK",
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000052};
53
54static void print_help()
55{
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000056 int i;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000057
58 printf(
59"arp options:\n"
Bart De Schuymerf46b2632003-05-01 20:18:00 +000060"--arp-opcode opcode : ARP opcode (integer or string)\n"
61"--arp-htype type : ARP hardware type (integer or string)\n"
62"--arp-ptype type : ARP protocol type (hexadecimal or string)\n"
63"--arp-ip-src [!] address[/mask]: ARP IP source specification\n"
64"--arp-ip-dst [!] address[/mask]: ARP IP target specification\n"
65"--arp-mac-src [!] address[/mask]: ARP MAC source specification\n"
66"--arp-mac-dst [!] address[/mask]: ARP MAC target specification\n"
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000067" opcode strings: \n");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000068 for (i = 0; i < NUMOPCODES; i++)
Bart De Schuymer1446c292003-05-25 09:47:01 +000069 printf(" %d = %s\n", i + 1, opcodes[i]);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000070 printf(
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000071" hardware type string: 1 = Ethernet\n"
fnm36c3dc652002-11-21 10:49:38 +000072" protocol type string: see "_PATH_ETHERTYPES"\n");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000073}
74
75static void init(struct ebt_entry_match *match)
76{
77 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
78
79 arpinfo->invflags = 0;
80 arpinfo->bitmask = 0;
81}
82
Bart De Schuymerf46b2632003-05-01 20:18:00 +000083
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000084#define OPT_OPCODE 0x01
85#define OPT_HTYPE 0x02
86#define OPT_PTYPE 0x04
87#define OPT_IP_S 0x08
88#define OPT_IP_D 0x10
Bart De Schuymerf46b2632003-05-01 20:18:00 +000089#define OPT_MAC_S 0x20
90#define OPT_MAC_D 0x40
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +000091static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
92 unsigned int *flags, struct ebt_entry_match **match)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000093{
94 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000095 long int i;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000096 char *end;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000097 uint32_t *addr;
98 uint32_t *mask;
Bart De Schuymer510c9ce2006-01-23 18:50:54 +000099 unsigned char *maddr;
100 unsigned char *mmask;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000101
102 switch (c) {
103 case ARP_OPCODE:
Bart De Schuymerff587202005-02-08 20:02:28 +0000104 ebt_check_option2(flags, OPT_OPCODE);
105 if (ebt_check_inverse2(optarg))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000106 arpinfo->invflags |= EBT_ARP_OPCODE;
Bart De Schuymerff587202005-02-08 20:02:28 +0000107 i = strtol(optarg, &end, 10);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000108 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000109 for (i = 0; i < NUMOPCODES; i++)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000110 if (!strcasecmp(opcodes[i], optarg))
111 break;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000112 if (i == NUMOPCODES)
Bart De Schuymerff587202005-02-08 20:02:28 +0000113 ebt_print_error2("Problem with specified ARP opcode");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000114 i++;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000115 }
116 arpinfo->opcode = htons(i);
117 arpinfo->bitmask |= EBT_ARP_OPCODE;
118 break;
119
120 case ARP_HTYPE:
Bart De Schuymerff587202005-02-08 20:02:28 +0000121 ebt_check_option2(flags, OPT_HTYPE);
122 if (ebt_check_inverse2(optarg))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000123 arpinfo->invflags |= EBT_ARP_HTYPE;
Bart De Schuymerff587202005-02-08 20:02:28 +0000124 i = strtol(optarg, &end, 10);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000125 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
126 if (!strcasecmp("Ethernet", argv[optind - 1]))
127 i = 1;
128 else
Bart De Schuymerff587202005-02-08 20:02:28 +0000129 ebt_print_error2("Problem with specified ARP hardware type");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000130 }
131 arpinfo->htype = htons(i);
132 arpinfo->bitmask |= EBT_ARP_HTYPE;
133 break;
134
135 case ARP_PTYPE:
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000136 {
137 uint16_t proto;
138
Bart De Schuymerff587202005-02-08 20:02:28 +0000139 ebt_check_option2(flags, OPT_PTYPE);
140 if (ebt_check_inverse2(optarg))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000141 arpinfo->invflags |= EBT_ARP_PTYPE;
142
Bart De Schuymerff587202005-02-08 20:02:28 +0000143 i = strtol(optarg, &end, 16);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000144 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000145 struct ethertypeent *ent;
146
147 ent = getethertypebyname(argv[optind - 1]);
148 if (!ent)
Bart De Schuymerff587202005-02-08 20:02:28 +0000149 ebt_print_error2("Problem with specified ARP "
Bart De Schuymer64182a32004-01-21 20:39:54 +0000150 "protocol type");
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000151 proto = ent->e_ethertype;
152
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000153 } else
154 proto = i;
155 arpinfo->ptype = htons(proto);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000156 arpinfo->bitmask |= EBT_ARP_PTYPE;
157 break;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000158 }
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000159
160 case ARP_IP_S:
161 case ARP_IP_D:
162 if (c == ARP_IP_S) {
Bart De Schuymerff587202005-02-08 20:02:28 +0000163 ebt_check_option2(flags, OPT_IP_S);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000164 addr = &arpinfo->saddr;
165 mask = &arpinfo->smsk;
166 arpinfo->bitmask |= EBT_ARP_SRC_IP;
167 } else {
Bart De Schuymerff587202005-02-08 20:02:28 +0000168 ebt_check_option2(flags, OPT_IP_D);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000169 addr = &arpinfo->daddr;
170 mask = &arpinfo->dmsk;
171 arpinfo->bitmask |= EBT_ARP_DST_IP;
172 }
Bart De Schuymerff587202005-02-08 20:02:28 +0000173 if (ebt_check_inverse2(optarg)) {
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000174 if (c == ARP_IP_S)
175 arpinfo->invflags |= EBT_ARP_SRC_IP;
176 else
177 arpinfo->invflags |= EBT_ARP_DST_IP;
178 }
Bart De Schuymerff587202005-02-08 20:02:28 +0000179 ebt_parse_ip_address(optarg, addr, mask);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000180 break;
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000181
182 case ARP_MAC_S:
183 case ARP_MAC_D:
184 if (c == ARP_MAC_S) {
Bart De Schuymerff587202005-02-08 20:02:28 +0000185 ebt_check_option2(flags, OPT_MAC_S);
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000186 maddr = arpinfo->smaddr;
187 mmask = arpinfo->smmsk;
188 arpinfo->bitmask |= EBT_ARP_SRC_MAC;
189 } else {
Bart De Schuymerff587202005-02-08 20:02:28 +0000190 ebt_check_option2(flags, OPT_MAC_D);
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000191 maddr = arpinfo->dmaddr;
192 mmask = arpinfo->dmmsk;
193 arpinfo->bitmask |= EBT_ARP_DST_MAC;
194 }
Bart De Schuymerff587202005-02-08 20:02:28 +0000195 if (ebt_check_inverse2(optarg)) {
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000196 if (c == ARP_MAC_S)
197 arpinfo->invflags |= EBT_ARP_SRC_MAC;
198 else
199 arpinfo->invflags |= EBT_ARP_DST_MAC;
200 }
Bart De Schuymerff587202005-02-08 20:02:28 +0000201 if (ebt_get_mac_and_mask(optarg, maddr, mmask))
202 ebt_print_error2("Problem with ARP MAC address argument");
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000203 break;
204
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000205 default:
206 return 0;
207 }
208 return 1;
209}
210
211static void final_check(const struct ebt_u_entry *entry,
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000212 const struct ebt_entry_match *match, const char *name,
Bart De Schuymerc9b52932002-08-24 13:26:34 +0000213 unsigned int hookmask, unsigned int time)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000214{
Bart De Schuymer40573192002-08-29 16:48:36 +0000215 if ((entry->ethproto != ETH_P_ARP && entry->ethproto != ETH_P_RARP) ||
Bart De Schuymerb2632c52002-08-09 18:57:05 +0000216 entry->invflags & EBT_IPROTO)
Bart De Schuymerff587202005-02-08 20:02:28 +0000217 ebt_print_error("For (R)ARP filtering the protocol must be specified as ARP or RARP");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000218}
219
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000220static void print(const struct ebt_u_entry *entry,
221 const struct ebt_entry_match *match)
222{
223 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
224 int i;
225
226 if (arpinfo->bitmask & EBT_ARP_OPCODE) {
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000227 int opcode = ntohs(arpinfo->opcode);
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000228 printf("--arp-op ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000229 if (arpinfo->invflags & EBT_ARP_OPCODE)
230 printf("! ");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000231 if (opcode > 0 && opcode <= NUMOPCODES)
232 printf("%s ", opcodes[opcode - 1]);
233 else
234 printf("%d ", opcode);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000235 }
236 if (arpinfo->bitmask & EBT_ARP_HTYPE) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000237 printf("--arp-htype ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000238 if (arpinfo->invflags & EBT_ARP_HTYPE)
239 printf("! ");
240 printf("%d ", ntohs(arpinfo->htype));
241 }
242 if (arpinfo->bitmask & EBT_ARP_PTYPE) {
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000243 struct ethertypeent *ent;
244
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000245 printf("--arp-ptype ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000246 if (arpinfo->invflags & EBT_ARP_PTYPE)
247 printf("! ");
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000248 ent = getethertypebynumber(ntohs(arpinfo->ptype));
249 if (!ent)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000250 printf("0x%x ", ntohs(arpinfo->ptype));
251 else
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000252 printf("%s ", ent->e_name);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000253 }
254 if (arpinfo->bitmask & EBT_ARP_SRC_IP) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000255 printf("--arp-ip-src ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000256 if (arpinfo->invflags & EBT_ARP_SRC_IP)
257 printf("! ");
258 for (i = 0; i < 4; i++)
259 printf("%d%s", ((unsigned char *)&arpinfo->saddr)[i],
260 (i == 3) ? "" : ".");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000261 printf("%s ", ebt_mask_to_dotted(arpinfo->smsk));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000262 }
263 if (arpinfo->bitmask & EBT_ARP_DST_IP) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000264 printf("--arp-ip-dst ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000265 if (arpinfo->invflags & EBT_ARP_DST_IP)
266 printf("! ");
267 for (i = 0; i < 4; i++)
268 printf("%d%s", ((unsigned char *)&arpinfo->daddr)[i],
269 (i == 3) ? "" : ".");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000270 printf("%s ", ebt_mask_to_dotted(arpinfo->dmsk));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000271 }
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000272 if (arpinfo->bitmask & EBT_ARP_SRC_MAC) {
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000273 printf("--arp-mac-src ");
274 if (arpinfo->invflags & EBT_ARP_SRC_MAC)
275 printf("! ");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000276 ebt_print_mac_and_mask(arpinfo->smaddr, arpinfo->smmsk);
Bart De Schuymer1446c292003-05-25 09:47:01 +0000277 printf(" ");
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000278 }
279 if (arpinfo->bitmask & EBT_ARP_DST_MAC) {
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000280 printf("--arp-mac-dst ");
281 if (arpinfo->invflags & EBT_ARP_DST_MAC)
282 printf("! ");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000283 ebt_print_mac_and_mask(arpinfo->dmaddr, arpinfo->dmmsk);
Bart De Schuymer1446c292003-05-25 09:47:01 +0000284 printf(" ");
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000285 }
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000286}
287
288static int compare(const struct ebt_entry_match *m1,
289 const struct ebt_entry_match *m2)
290{
291 struct ebt_arp_info *arpinfo1 = (struct ebt_arp_info *)m1->data;
292 struct ebt_arp_info *arpinfo2 = (struct ebt_arp_info *)m2->data;
293
294 if (arpinfo1->bitmask != arpinfo2->bitmask)
295 return 0;
296 if (arpinfo1->invflags != arpinfo2->invflags)
297 return 0;
298 if (arpinfo1->bitmask & EBT_ARP_OPCODE) {
299 if (arpinfo1->opcode != arpinfo2->opcode)
300 return 0;
301 }
302 if (arpinfo1->bitmask & EBT_ARP_HTYPE) {
303 if (arpinfo1->htype != arpinfo2->htype)
304 return 0;
305 }
306 if (arpinfo1->bitmask & EBT_ARP_PTYPE) {
307 if (arpinfo1->ptype != arpinfo2->ptype)
308 return 0;
309 }
310 if (arpinfo1->bitmask & EBT_ARP_SRC_IP) {
311 if (arpinfo1->saddr != arpinfo2->saddr)
312 return 0;
313 if (arpinfo1->smsk != arpinfo2->smsk)
314 return 0;
315 }
316 if (arpinfo1->bitmask & EBT_ARP_DST_IP) {
317 if (arpinfo1->daddr != arpinfo2->daddr)
318 return 0;
319 if (arpinfo1->dmsk != arpinfo2->dmsk)
320 return 0;
321 }
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000322 if (arpinfo1->bitmask & EBT_ARP_SRC_MAC) {
Bart De Schuymerbee79612004-09-04 09:01:05 +0000323 if (memcmp(arpinfo1->smaddr, arpinfo2->smaddr, ETH_ALEN))
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000324 return 0;
Bart De Schuymerbee79612004-09-04 09:01:05 +0000325 if (memcmp(arpinfo1->smmsk, arpinfo2->smmsk, ETH_ALEN))
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000326 return 0;
327 }
328 if (arpinfo1->bitmask & EBT_ARP_DST_MAC) {
Bart De Schuymerbee79612004-09-04 09:01:05 +0000329 if (memcmp(arpinfo1->dmaddr, arpinfo2->dmaddr, ETH_ALEN))
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000330 return 0;
Bart De Schuymerbee79612004-09-04 09:01:05 +0000331 if (memcmp(arpinfo1->dmmsk, arpinfo2->dmmsk, ETH_ALEN))
Bart De Schuymerf46b2632003-05-01 20:18:00 +0000332 return 0;
333 }
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000334 return 1;
335}
336
337static struct ebt_u_match arp_match =
338{
Bart De Schuymer7cf1cca2003-08-30 16:20:19 +0000339 .name = EBT_ARP_MATCH,
340 .size = sizeof(struct ebt_arp_info),
341 .help = print_help,
342 .init = init,
343 .parse = parse,
344 .final_check = final_check,
345 .print = print,
346 .compare = compare,
347 .extra_ops = opts,
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000348};
349
Bart De Schuymer64182a32004-01-21 20:39:54 +0000350void _init(void)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000351{
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000352 ebt_register_match(&arp_match);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000353}