blob: da3d9d669a1801d39603ccdb81d4e88c6ec73117 [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,
Bart De Schuymerc9b52932002-08-24 13:26:34 +0000177 unsigned int hookmask, unsigned int time)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000178{
Bart De Schuymer40573192002-08-29 16:48:36 +0000179 if ((entry->ethproto != ETH_P_ARP && entry->ethproto != ETH_P_RARP) ||
Bart De Schuymerb2632c52002-08-09 18:57:05 +0000180 entry->invflags & EBT_IPROTO)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000181 print_error("For (R)ARP filtering the protocol must be "
182 "specified as ARP or RARP");
183}
184
185// defined in the ebt_ip.c
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000186char *mask_to_dotted(uint32_t mask);
187
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000188static void print(const struct ebt_u_entry *entry,
189 const struct ebt_entry_match *match)
190{
191 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
192 int i;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000193 char name[21];
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000194
195 if (arpinfo->bitmask & EBT_ARP_OPCODE) {
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000196 int opcode = ntohs(arpinfo->opcode);
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000197 printf("--arp-op ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000198 if (arpinfo->invflags & EBT_ARP_OPCODE)
199 printf("! ");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000200 if (opcode > 0 && opcode <= NUMOPCODES)
201 printf("%s ", opcodes[opcode - 1]);
202 else
203 printf("%d ", opcode);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000204 }
205 if (arpinfo->bitmask & EBT_ARP_HTYPE) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000206 printf("--arp-htype ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000207 if (arpinfo->invflags & EBT_ARP_HTYPE)
208 printf("! ");
209 printf("%d ", ntohs(arpinfo->htype));
210 }
211 if (arpinfo->bitmask & EBT_ARP_PTYPE) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000212 printf("--arp-ptype ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000213 if (arpinfo->invflags & EBT_ARP_PTYPE)
214 printf("! ");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000215 if (number_to_name(ntohs(arpinfo->ptype), name))
216 printf("0x%x ", ntohs(arpinfo->ptype));
217 else
218 printf("%s ", name);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000219 }
220 if (arpinfo->bitmask & EBT_ARP_SRC_IP) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000221 printf("--arp-ip-src ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000222 if (arpinfo->invflags & EBT_ARP_SRC_IP)
223 printf("! ");
224 for (i = 0; i < 4; i++)
225 printf("%d%s", ((unsigned char *)&arpinfo->saddr)[i],
226 (i == 3) ? "" : ".");
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000227 printf("%s ", mask_to_dotted(arpinfo->smsk));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000228 }
229 if (arpinfo->bitmask & EBT_ARP_DST_IP) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000230 printf("--arp-ip-dst ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000231 if (arpinfo->invflags & EBT_ARP_DST_IP)
232 printf("! ");
233 for (i = 0; i < 4; i++)
234 printf("%d%s", ((unsigned char *)&arpinfo->daddr)[i],
235 (i == 3) ? "" : ".");
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000236 printf("%s ", mask_to_dotted(arpinfo->dmsk));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000237 }
238}
239
240static int compare(const struct ebt_entry_match *m1,
241 const struct ebt_entry_match *m2)
242{
243 struct ebt_arp_info *arpinfo1 = (struct ebt_arp_info *)m1->data;
244 struct ebt_arp_info *arpinfo2 = (struct ebt_arp_info *)m2->data;
245
246 if (arpinfo1->bitmask != arpinfo2->bitmask)
247 return 0;
248 if (arpinfo1->invflags != arpinfo2->invflags)
249 return 0;
250 if (arpinfo1->bitmask & EBT_ARP_OPCODE) {
251 if (arpinfo1->opcode != arpinfo2->opcode)
252 return 0;
253 }
254 if (arpinfo1->bitmask & EBT_ARP_HTYPE) {
255 if (arpinfo1->htype != arpinfo2->htype)
256 return 0;
257 }
258 if (arpinfo1->bitmask & EBT_ARP_PTYPE) {
259 if (arpinfo1->ptype != arpinfo2->ptype)
260 return 0;
261 }
262 if (arpinfo1->bitmask & EBT_ARP_SRC_IP) {
263 if (arpinfo1->saddr != arpinfo2->saddr)
264 return 0;
265 if (arpinfo1->smsk != arpinfo2->smsk)
266 return 0;
267 }
268 if (arpinfo1->bitmask & EBT_ARP_DST_IP) {
269 if (arpinfo1->daddr != arpinfo2->daddr)
270 return 0;
271 if (arpinfo1->dmsk != arpinfo2->dmsk)
272 return 0;
273 }
274 return 1;
275}
276
277static struct ebt_u_match arp_match =
278{
279 EBT_ARP_MATCH,
280 sizeof(struct ebt_arp_info),
281 print_help,
282 init,
283 parse,
284 final_check,
285 print,
286 compare,
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000287 opts
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000288};
289
290static void _init(void) __attribute__ ((constructor));
291static void _init(void)
292{
293 register_match(&arp_match);
294}