4 * Bart De Schuymer <bdschuym@pandora.be>
5 * Tim Gardner <timg@tpi.com>
14 #include "../include/ebtables_u.h"
15 #include "../include/ethernetdb.h"
16 #include <linux/if_ether.h>
17 #include <linux/netfilter_bridge/ebt_arp.h>
19 #define ARP_OPCODE '1'
27 static struct option opts
[] =
29 { "arp-opcode" , required_argument
, 0, ARP_OPCODE
},
30 { "arp-op" , required_argument
, 0, ARP_OPCODE
},
31 { "arp-htype" , required_argument
, 0, ARP_HTYPE
},
32 { "arp-ptype" , required_argument
, 0, ARP_PTYPE
},
33 { "arp-ip-src" , required_argument
, 0, ARP_IP_S
},
34 { "arp-ip-dst" , required_argument
, 0, ARP_IP_D
},
35 { "arp-mac-src" , required_argument
, 0, ARP_MAC_S
},
36 { "arp-mac-dst" , required_argument
, 0, ARP_MAC_D
},
37 { "arp-gratuitous", no_argument
, 0, ARP_GRAT
},
43 static char *opcodes
[] =
56 static void print_help()
62 "--arp-opcode [!] opcode : ARP opcode (integer or string)\n"
63 "--arp-htype [!] type : ARP hardware type (integer or string)\n"
64 "--arp-ptype [!] type : ARP protocol type (hexadecimal or string)\n"
65 "--arp-ip-src [!] address[/mask]: ARP IP source specification\n"
66 "--arp-ip-dst [!] address[/mask]: ARP IP target specification\n"
67 "--arp-mac-src [!] address[/mask]: ARP MAC source specification\n"
68 "--arp-mac-dst [!] address[/mask]: ARP MAC target specification\n"
69 "[!] --arp-gratuitous : ARP gratuitous packet\n"
70 " opcode strings: \n");
71 for (i
= 0; i
< NUMOPCODES
; i
++)
72 printf(" %d = %s\n", i
+ 1, opcodes
[i
]);
74 " hardware type string: 1 = Ethernet\n"
75 " protocol type string: see "_PATH_ETHERTYPES
"\n");
78 static void init(struct ebt_entry_match
*match
)
80 struct ebt_arp_info
*arpinfo
= (struct ebt_arp_info
*)match
->data
;
82 arpinfo
->invflags
= 0;
87 #define OPT_OPCODE 0x01
88 #define OPT_HTYPE 0x02
89 #define OPT_PTYPE 0x04
92 #define OPT_MAC_S 0x20
93 #define OPT_MAC_D 0x40
95 static int parse(int c
, char **argv
, int argc
, const struct ebt_u_entry
*entry
,
96 unsigned int *flags
, struct ebt_entry_match
**match
)
98 struct ebt_arp_info
*arpinfo
= (struct ebt_arp_info
*)(*match
)->data
;
103 unsigned char *maddr
;
104 unsigned char *mmask
;
108 ebt_check_option2(flags
, OPT_OPCODE
);
109 if (ebt_check_inverse2(optarg
))
110 arpinfo
->invflags
|= EBT_ARP_OPCODE
;
111 i
= strtol(optarg
, &end
, 10);
112 if (i
< 0 || i
>= (0x1 << 16) || *end
!='\0') {
113 for (i
= 0; i
< NUMOPCODES
; i
++)
114 if (!strcasecmp(opcodes
[i
], optarg
))
117 ebt_print_error2("Problem with specified ARP opcode");
120 arpinfo
->opcode
= htons(i
);
121 arpinfo
->bitmask
|= EBT_ARP_OPCODE
;
125 ebt_check_option2(flags
, OPT_HTYPE
);
126 if (ebt_check_inverse2(optarg
))
127 arpinfo
->invflags
|= EBT_ARP_HTYPE
;
128 i
= strtol(optarg
, &end
, 10);
129 if (i
< 0 || i
>= (0x1 << 16) || *end
!='\0') {
130 if (!strcasecmp("Ethernet", argv
[optind
- 1]))
133 ebt_print_error2("Problem with specified ARP hardware type");
135 arpinfo
->htype
= htons(i
);
136 arpinfo
->bitmask
|= EBT_ARP_HTYPE
;
143 ebt_check_option2(flags
, OPT_PTYPE
);
144 if (ebt_check_inverse2(optarg
))
145 arpinfo
->invflags
|= EBT_ARP_PTYPE
;
147 i
= strtol(optarg
, &end
, 16);
148 if (i
< 0 || i
>= (0x1 << 16) || *end
!='\0') {
149 struct ethertypeent
*ent
;
151 ent
= getethertypebyname(argv
[optind
- 1]);
153 ebt_print_error2("Problem with specified ARP "
155 proto
= ent
->e_ethertype
;
159 arpinfo
->ptype
= htons(proto
);
160 arpinfo
->bitmask
|= EBT_ARP_PTYPE
;
167 ebt_check_option2(flags
, OPT_IP_S
);
168 addr
= &arpinfo
->saddr
;
169 mask
= &arpinfo
->smsk
;
170 arpinfo
->bitmask
|= EBT_ARP_SRC_IP
;
172 ebt_check_option2(flags
, OPT_IP_D
);
173 addr
= &arpinfo
->daddr
;
174 mask
= &arpinfo
->dmsk
;
175 arpinfo
->bitmask
|= EBT_ARP_DST_IP
;
177 if (ebt_check_inverse2(optarg
)) {
179 arpinfo
->invflags
|= EBT_ARP_SRC_IP
;
181 arpinfo
->invflags
|= EBT_ARP_DST_IP
;
183 ebt_parse_ip_address(optarg
, addr
, mask
);
188 if (c
== ARP_MAC_S
) {
189 ebt_check_option2(flags
, OPT_MAC_S
);
190 maddr
= arpinfo
->smaddr
;
191 mmask
= arpinfo
->smmsk
;
192 arpinfo
->bitmask
|= EBT_ARP_SRC_MAC
;
194 ebt_check_option2(flags
, OPT_MAC_D
);
195 maddr
= arpinfo
->dmaddr
;
196 mmask
= arpinfo
->dmmsk
;
197 arpinfo
->bitmask
|= EBT_ARP_DST_MAC
;
199 if (ebt_check_inverse2(optarg
)) {
201 arpinfo
->invflags
|= EBT_ARP_SRC_MAC
;
203 arpinfo
->invflags
|= EBT_ARP_DST_MAC
;
205 if (ebt_get_mac_and_mask(optarg
, maddr
, mmask
))
206 ebt_print_error2("Problem with ARP MAC address argument");
209 ebt_check_option2(flags
, OPT_GRAT
);
210 arpinfo
->bitmask
|= EBT_ARP_GRAT
;
212 arpinfo
->invflags
|= EBT_ARP_GRAT
;
221 static void final_check(const struct ebt_u_entry
*entry
,
222 const struct ebt_entry_match
*match
, const char *name
,
223 unsigned int hookmask
, unsigned int time
)
225 if ((entry
->ethproto
!= ETH_P_ARP
&& entry
->ethproto
!= ETH_P_RARP
) ||
226 entry
->invflags
& EBT_IPROTO
)
227 ebt_print_error("For (R)ARP filtering the protocol must be specified as ARP or RARP");
230 static void print(const struct ebt_u_entry
*entry
,
231 const struct ebt_entry_match
*match
)
233 struct ebt_arp_info
*arpinfo
= (struct ebt_arp_info
*)match
->data
;
236 if (arpinfo
->bitmask
& EBT_ARP_OPCODE
) {
237 int opcode
= ntohs(arpinfo
->opcode
);
239 if (arpinfo
->invflags
& EBT_ARP_OPCODE
)
241 if (opcode
> 0 && opcode
<= NUMOPCODES
)
242 printf("%s ", opcodes
[opcode
- 1]);
244 printf("%d ", opcode
);
246 if (arpinfo
->bitmask
& EBT_ARP_HTYPE
) {
247 printf("--arp-htype ");
248 if (arpinfo
->invflags
& EBT_ARP_HTYPE
)
250 printf("%d ", ntohs(arpinfo
->htype
));
252 if (arpinfo
->bitmask
& EBT_ARP_PTYPE
) {
253 struct ethertypeent
*ent
;
255 printf("--arp-ptype ");
256 if (arpinfo
->invflags
& EBT_ARP_PTYPE
)
258 ent
= getethertypebynumber(ntohs(arpinfo
->ptype
));
260 printf("0x%x ", ntohs(arpinfo
->ptype
));
262 printf("%s ", ent
->e_name
);
264 if (arpinfo
->bitmask
& EBT_ARP_SRC_IP
) {
265 printf("--arp-ip-src ");
266 if (arpinfo
->invflags
& EBT_ARP_SRC_IP
)
268 for (i
= 0; i
< 4; i
++)
269 printf("%d%s", ((unsigned char *)&arpinfo
->saddr
)[i
],
270 (i
== 3) ? "" : ".");
271 printf("%s ", ebt_mask_to_dotted(arpinfo
->smsk
));
273 if (arpinfo
->bitmask
& EBT_ARP_DST_IP
) {
274 printf("--arp-ip-dst ");
275 if (arpinfo
->invflags
& EBT_ARP_DST_IP
)
277 for (i
= 0; i
< 4; i
++)
278 printf("%d%s", ((unsigned char *)&arpinfo
->daddr
)[i
],
279 (i
== 3) ? "" : ".");
280 printf("%s ", ebt_mask_to_dotted(arpinfo
->dmsk
));
282 if (arpinfo
->bitmask
& EBT_ARP_SRC_MAC
) {
283 printf("--arp-mac-src ");
284 if (arpinfo
->invflags
& EBT_ARP_SRC_MAC
)
286 ebt_print_mac_and_mask(arpinfo
->smaddr
, arpinfo
->smmsk
);
289 if (arpinfo
->bitmask
& EBT_ARP_DST_MAC
) {
290 printf("--arp-mac-dst ");
291 if (arpinfo
->invflags
& EBT_ARP_DST_MAC
)
293 ebt_print_mac_and_mask(arpinfo
->dmaddr
, arpinfo
->dmmsk
);
296 if (arpinfo
->bitmask
& EBT_ARP_GRAT
) {
297 if (arpinfo
->invflags
& EBT_ARP_GRAT
)
299 printf("--arp-gratuitous ");
303 static int compare(const struct ebt_entry_match
*m1
,
304 const struct ebt_entry_match
*m2
)
306 struct ebt_arp_info
*arpinfo1
= (struct ebt_arp_info
*)m1
->data
;
307 struct ebt_arp_info
*arpinfo2
= (struct ebt_arp_info
*)m2
->data
;
309 if (arpinfo1
->bitmask
!= arpinfo2
->bitmask
)
311 if (arpinfo1
->invflags
!= arpinfo2
->invflags
)
313 if (arpinfo1
->bitmask
& EBT_ARP_OPCODE
) {
314 if (arpinfo1
->opcode
!= arpinfo2
->opcode
)
317 if (arpinfo1
->bitmask
& EBT_ARP_HTYPE
) {
318 if (arpinfo1
->htype
!= arpinfo2
->htype
)
321 if (arpinfo1
->bitmask
& EBT_ARP_PTYPE
) {
322 if (arpinfo1
->ptype
!= arpinfo2
->ptype
)
325 if (arpinfo1
->bitmask
& EBT_ARP_SRC_IP
) {
326 if (arpinfo1
->saddr
!= arpinfo2
->saddr
)
328 if (arpinfo1
->smsk
!= arpinfo2
->smsk
)
331 if (arpinfo1
->bitmask
& EBT_ARP_DST_IP
) {
332 if (arpinfo1
->daddr
!= arpinfo2
->daddr
)
334 if (arpinfo1
->dmsk
!= arpinfo2
->dmsk
)
337 if (arpinfo1
->bitmask
& EBT_ARP_SRC_MAC
) {
338 if (memcmp(arpinfo1
->smaddr
, arpinfo2
->smaddr
, ETH_ALEN
))
340 if (memcmp(arpinfo1
->smmsk
, arpinfo2
->smmsk
, ETH_ALEN
))
343 if (arpinfo1
->bitmask
& EBT_ARP_DST_MAC
) {
344 if (memcmp(arpinfo1
->dmaddr
, arpinfo2
->dmaddr
, ETH_ALEN
))
346 if (memcmp(arpinfo1
->dmmsk
, arpinfo2
->dmmsk
, ETH_ALEN
))
352 static struct ebt_u_match arp_match
=
355 .size
= sizeof(struct ebt_arp_info
),
359 .final_check
= final_check
,
367 ebt_register_match(&arp_match
);