blob: 732527053e6444db7657e6da8121d59236848304 [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 Schuymer1abc55d2002-06-01 19:23:47 +00007#include <linux/netfilter_bridge/ebt_arp.h>
8
9#define ARP_OPCODE '1'
10#define ARP_HTYPE '2'
11#define ARP_PTYPE '3'
12#define ARP_IP_S '4'
13#define ARP_IP_D '5'
14static struct option opts[] =
15{
16 { "arp-opcode" , required_argument, 0, ARP_OPCODE },
17 { "arp-op" , required_argument, 0, ARP_OPCODE },
18 { "arp-htype" , required_argument, 0, ARP_HTYPE },
19 { "arp-ptype" , required_argument, 0, ARP_PTYPE },
20 { "arp-ip-src" , required_argument, 0, ARP_IP_S },
21 { "arp-ip-dst" , required_argument, 0, ARP_IP_D },
22 { 0 }
23};
24
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000025#define NUMOPCODES 9
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000026// a few names
27static char *opcodes[] =
28{
29 "Request",
30 "Reply",
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000031 "Request_Reverse",
32 "Reply_Reverse",
33 "DRARP_Request",
34 "DRARP_Reply",
35 "DRARP_Error",
36 "InARP_Request",
37 "ARP_NAK",
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000038};
39
40static void print_help()
41{
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000042 int i;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000043
44 printf(
45"arp options:\n"
46"--arp-opcode opcode : ARP opcode (integer or string)\n"
47"--arp-htype type : ARP hardware type (integer or string)\n"
48"--arp-ptype type : ARP protocol type (hexadecimal or string)\n"
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000049"--arp-ip-src [!] address[/mask]: ARP IP source specification\n"
50"--arp-ip-dst [!] address[/mask]: ARP IP target specification\n"
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000051" opcode strings: \n");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000052 for (i = 0; i < NUMOPCODES; i++)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000053 printf("%d = %s\n", i + 1, opcodes[i]);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000054 printf(
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000055" hardware type string: 1 = Ethernet\n"
fnm36c3dc652002-11-21 10:49:38 +000056" protocol type string: see "_PATH_ETHERTYPES"\n");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000057}
58
59static void init(struct ebt_entry_match *match)
60{
61 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
62
63 arpinfo->invflags = 0;
64 arpinfo->bitmask = 0;
65}
66
67// defined in ebt_ip.c
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000068void parse_ip_address(char *address, uint32_t *addr, uint32_t *msk);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000069
70#define OPT_OPCODE 0x01
71#define OPT_HTYPE 0x02
72#define OPT_PTYPE 0x04
73#define OPT_IP_S 0x08
74#define OPT_IP_D 0x10
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +000075static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
76 unsigned int *flags, struct ebt_entry_match **match)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000077{
78 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000079 long int i;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000080 char *end;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000081 uint32_t *addr;
82 uint32_t *mask;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000083
84 switch (c) {
85 case ARP_OPCODE:
86 check_option(flags, OPT_OPCODE);
87 if (check_inverse(optarg))
88 arpinfo->invflags |= EBT_ARP_OPCODE;
89
90 if (optind > argc)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000091 print_error("Missing ARP opcode argument");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000092 i = strtol(argv[optind - 1], &end, 10);
93 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000094 for (i = 0; i < NUMOPCODES; i++)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000095 if (!strcasecmp(opcodes[i], optarg))
96 break;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000097 if (i == NUMOPCODES)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000098 print_error("Problem with specified "
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000099 "ARP opcode");
100 i++;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000101 }
102 arpinfo->opcode = htons(i);
103 arpinfo->bitmask |= EBT_ARP_OPCODE;
104 break;
105
106 case ARP_HTYPE:
107 check_option(flags, OPT_HTYPE);
108 if (check_inverse(optarg))
109 arpinfo->invflags |= EBT_ARP_HTYPE;
110
111 if (optind > argc)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000112 print_error("Missing ARP hardware type argument");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000113 i = strtol(argv[optind - 1], &end, 10);
114 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
115 if (!strcasecmp("Ethernet", argv[optind - 1]))
116 i = 1;
117 else
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000118 print_error("Problem with specified ARP "
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000119 "hardware type");
120 }
121 arpinfo->htype = htons(i);
122 arpinfo->bitmask |= EBT_ARP_HTYPE;
123 break;
124
125 case ARP_PTYPE:
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000126 {
127 uint16_t proto;
128
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000129 check_option(flags, OPT_PTYPE);
130 if (check_inverse(optarg))
131 arpinfo->invflags |= EBT_ARP_PTYPE;
132
133 if (optind > argc)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000134 print_error("Missing ARP protocol type argument");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000135 i = strtol(argv[optind - 1], &end, 16);
136 if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000137 struct ethertypeent *ent;
138
139 ent = getethertypebyname(argv[optind - 1]);
140 if (!ent)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000141 print_error("Problem with specified ARP "
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000142 "protocol type");
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000143 proto = ent->e_ethertype;
144
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000145 } else
146 proto = i;
147 arpinfo->ptype = htons(proto);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000148 arpinfo->bitmask |= EBT_ARP_PTYPE;
149 break;
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000150 }
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000151
152 case ARP_IP_S:
153 case ARP_IP_D:
154 if (c == ARP_IP_S) {
155 check_option(flags, OPT_IP_S);
156 addr = &arpinfo->saddr;
157 mask = &arpinfo->smsk;
158 arpinfo->bitmask |= EBT_ARP_SRC_IP;
159 } else {
160 check_option(flags, OPT_IP_D);
161 addr = &arpinfo->daddr;
162 mask = &arpinfo->dmsk;
163 arpinfo->bitmask |= EBT_ARP_DST_IP;
164 }
165 if (check_inverse(optarg)) {
166 if (c == ARP_IP_S)
167 arpinfo->invflags |= EBT_ARP_SRC_IP;
168 else
169 arpinfo->invflags |= EBT_ARP_DST_IP;
170 }
171 if (optind > argc)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000172 print_error("Missing ARP IP address argument");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000173 parse_ip_address(argv[optind - 1], addr, mask);
174 break;
175 default:
176 return 0;
177 }
178 return 1;
179}
180
181static void final_check(const struct ebt_u_entry *entry,
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000182 const struct ebt_entry_match *match, const char *name,
Bart De Schuymerc9b52932002-08-24 13:26:34 +0000183 unsigned int hookmask, unsigned int time)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000184{
Bart De Schuymer40573192002-08-29 16:48:36 +0000185 if ((entry->ethproto != ETH_P_ARP && entry->ethproto != ETH_P_RARP) ||
Bart De Schuymerb2632c52002-08-09 18:57:05 +0000186 entry->invflags & EBT_IPROTO)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000187 print_error("For (R)ARP filtering the protocol must be "
188 "specified as ARP or RARP");
189}
190
191// defined in the ebt_ip.c
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000192char *mask_to_dotted(uint32_t mask);
193
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000194static void print(const struct ebt_u_entry *entry,
195 const struct ebt_entry_match *match)
196{
197 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
198 int i;
199
200 if (arpinfo->bitmask & EBT_ARP_OPCODE) {
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000201 int opcode = ntohs(arpinfo->opcode);
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000202 printf("--arp-op ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000203 if (arpinfo->invflags & EBT_ARP_OPCODE)
204 printf("! ");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000205 if (opcode > 0 && opcode <= NUMOPCODES)
206 printf("%s ", opcodes[opcode - 1]);
207 else
208 printf("%d ", opcode);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000209 }
210 if (arpinfo->bitmask & EBT_ARP_HTYPE) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000211 printf("--arp-htype ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000212 if (arpinfo->invflags & EBT_ARP_HTYPE)
213 printf("! ");
214 printf("%d ", ntohs(arpinfo->htype));
215 }
216 if (arpinfo->bitmask & EBT_ARP_PTYPE) {
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000217 struct ethertypeent *ent;
218
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000219 printf("--arp-ptype ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000220 if (arpinfo->invflags & EBT_ARP_PTYPE)
221 printf("! ");
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000222 ent = getethertypebynumber(ntohs(arpinfo->ptype));
223 if (!ent)
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000224 printf("0x%x ", ntohs(arpinfo->ptype));
225 else
Bart De Schuymerc1939b12002-11-20 19:41:54 +0000226 printf("%s ", ent->e_name);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000227 }
228 if (arpinfo->bitmask & EBT_ARP_SRC_IP) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000229 printf("--arp-ip-src ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000230 if (arpinfo->invflags & EBT_ARP_SRC_IP)
231 printf("! ");
232 for (i = 0; i < 4; i++)
233 printf("%d%s", ((unsigned char *)&arpinfo->saddr)[i],
234 (i == 3) ? "" : ".");
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000235 printf("%s ", mask_to_dotted(arpinfo->smsk));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000236 }
237 if (arpinfo->bitmask & EBT_ARP_DST_IP) {
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000238 printf("--arp-ip-dst ");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000239 if (arpinfo->invflags & EBT_ARP_DST_IP)
240 printf("! ");
241 for (i = 0; i < 4; i++)
242 printf("%d%s", ((unsigned char *)&arpinfo->daddr)[i],
243 (i == 3) ? "" : ".");
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000244 printf("%s ", mask_to_dotted(arpinfo->dmsk));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000245 }
246}
247
248static int compare(const struct ebt_entry_match *m1,
249 const struct ebt_entry_match *m2)
250{
251 struct ebt_arp_info *arpinfo1 = (struct ebt_arp_info *)m1->data;
252 struct ebt_arp_info *arpinfo2 = (struct ebt_arp_info *)m2->data;
253
254 if (arpinfo1->bitmask != arpinfo2->bitmask)
255 return 0;
256 if (arpinfo1->invflags != arpinfo2->invflags)
257 return 0;
258 if (arpinfo1->bitmask & EBT_ARP_OPCODE) {
259 if (arpinfo1->opcode != arpinfo2->opcode)
260 return 0;
261 }
262 if (arpinfo1->bitmask & EBT_ARP_HTYPE) {
263 if (arpinfo1->htype != arpinfo2->htype)
264 return 0;
265 }
266 if (arpinfo1->bitmask & EBT_ARP_PTYPE) {
267 if (arpinfo1->ptype != arpinfo2->ptype)
268 return 0;
269 }
270 if (arpinfo1->bitmask & EBT_ARP_SRC_IP) {
271 if (arpinfo1->saddr != arpinfo2->saddr)
272 return 0;
273 if (arpinfo1->smsk != arpinfo2->smsk)
274 return 0;
275 }
276 if (arpinfo1->bitmask & EBT_ARP_DST_IP) {
277 if (arpinfo1->daddr != arpinfo2->daddr)
278 return 0;
279 if (arpinfo1->dmsk != arpinfo2->dmsk)
280 return 0;
281 }
282 return 1;
283}
284
285static struct ebt_u_match arp_match =
286{
287 EBT_ARP_MATCH,
288 sizeof(struct ebt_arp_info),
289 print_help,
290 init,
291 parse,
292 final_check,
293 print,
294 compare,
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000295 opts
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000296};
297
298static void _init(void) __attribute__ ((constructor));
299static void _init(void)
300{
301 register_match(&arp_match);
302}