1/* ebt_arp 2 * 3 * Authors: 4 * Bart De Schuymer <bdschuym@pandora.be> 5 * Tim Gardner <timg@tpi.com> 6 * 7 * April, 2002 8 */ 9 10#include <stdio.h> 11#include <string.h> 12#include <stdlib.h> 13#include <getopt.h> 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> 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' 24#define ARP_MAC_S '6' 25#define ARP_MAC_D '7' 26#define ARP_GRAT '8' 27static struct option opts[] = 28{ 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 }, 38 { 0 } 39}; 40 41#define NUMOPCODES 9 42/* a few names */ 43static char *opcodes[] = 44{ 45 "Request", 46 "Reply", 47 "Request_Reverse", 48 "Reply_Reverse", 49 "DRARP_Request", 50 "DRARP_Reply", 51 "DRARP_Error", 52 "InARP_Request", 53 "ARP_NAK", 54}; 55 56static void print_help() 57{ 58 int i; 59 60 printf( 61"arp options:\n" 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]); 73 printf( 74" hardware type string: 1 = Ethernet\n" 75" protocol type string: see "_PATH_ETHERTYPES"\n"); 76} 77 78static void init(struct ebt_entry_match *match) 79{ 80 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data; 81 82 arpinfo->invflags = 0; 83 arpinfo->bitmask = 0; 84} 85 86 87#define OPT_OPCODE 0x01 88#define OPT_HTYPE 0x02 89#define OPT_PTYPE 0x04 90#define OPT_IP_S 0x08 91#define OPT_IP_D 0x10 92#define OPT_MAC_S 0x20 93#define OPT_MAC_D 0x40 94#define OPT_GRAT 0x80 95static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, 96 unsigned int *flags, struct ebt_entry_match **match) 97{ 98 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data; 99 long int i; 100 char *end; 101 uint32_t *addr; 102 uint32_t *mask; 103 unsigned char *maddr; 104 unsigned char *mmask; 105 106 switch (c) { 107 case ARP_OPCODE: 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)) 115 break; 116 if (i == NUMOPCODES) 117 ebt_print_error2("Problem with specified ARP opcode"); 118 i++; 119 } 120 arpinfo->opcode = htons(i); 121 arpinfo->bitmask |= EBT_ARP_OPCODE; 122 break; 123 124 case ARP_HTYPE: 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])) 131 i = 1; 132 else 133 ebt_print_error2("Problem with specified ARP hardware type"); 134 } 135 arpinfo->htype = htons(i); 136 arpinfo->bitmask |= EBT_ARP_HTYPE; 137 break; 138 139 case ARP_PTYPE: 140 { 141 uint16_t proto; 142 143 ebt_check_option2(flags, OPT_PTYPE); 144 if (ebt_check_inverse2(optarg)) 145 arpinfo->invflags |= EBT_ARP_PTYPE; 146 147 i = strtol(optarg, &end, 16); 148 if (i < 0 || i >= (0x1 << 16) || *end !='\0') { 149 struct ethertypeent *ent; 150 151 ent = getethertypebyname(argv[optind - 1]); 152 if (!ent) 153 ebt_print_error2("Problem with specified ARP " 154 "protocol type"); 155 proto = ent->e_ethertype; 156 157 } else 158 proto = i; 159 arpinfo->ptype = htons(proto); 160 arpinfo->bitmask |= EBT_ARP_PTYPE; 161 break; 162 } 163 164 case ARP_IP_S: 165 case ARP_IP_D: 166 if (c == ARP_IP_S) { 167 ebt_check_option2(flags, OPT_IP_S); 168 addr = &arpinfo->saddr; 169 mask = &arpinfo->smsk; 170 arpinfo->bitmask |= EBT_ARP_SRC_IP; 171 } else { 172 ebt_check_option2(flags, OPT_IP_D); 173 addr = &arpinfo->daddr; 174 mask = &arpinfo->dmsk; 175 arpinfo->bitmask |= EBT_ARP_DST_IP; 176 } 177 if (ebt_check_inverse2(optarg)) { 178 if (c == ARP_IP_S) 179 arpinfo->invflags |= EBT_ARP_SRC_IP; 180 else 181 arpinfo->invflags |= EBT_ARP_DST_IP; 182 } 183 ebt_parse_ip_address(optarg, addr, mask); 184 break; 185 186 case ARP_MAC_S: 187 case ARP_MAC_D: 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; 193 } else { 194 ebt_check_option2(flags, OPT_MAC_D); 195 maddr = arpinfo->dmaddr; 196 mmask = arpinfo->dmmsk; 197 arpinfo->bitmask |= EBT_ARP_DST_MAC; 198 } 199 if (ebt_check_inverse2(optarg)) { 200 if (c == ARP_MAC_S) 201 arpinfo->invflags |= EBT_ARP_SRC_MAC; 202 else 203 arpinfo->invflags |= EBT_ARP_DST_MAC; 204 } 205 if (ebt_get_mac_and_mask(optarg, maddr, mmask)) 206 ebt_print_error2("Problem with ARP MAC address argument"); 207 break; 208 case ARP_GRAT: 209 ebt_check_option2(flags, OPT_GRAT); 210 arpinfo->bitmask |= EBT_ARP_GRAT; 211 if (ebt_invert) 212 arpinfo->invflags |= EBT_ARP_GRAT; 213 break; 214 215 default: 216 return 0; 217 } 218 return 1; 219} 220 221static 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) 224{ 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"); 228} 229 230static void print(const struct ebt_u_entry *entry, 231 const struct ebt_entry_match *match) 232{ 233 struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data; 234 int i; 235 236 if (arpinfo->bitmask & EBT_ARP_OPCODE) { 237 int opcode = ntohs(arpinfo->opcode); 238 printf("--arp-op "); 239 if (arpinfo->invflags & EBT_ARP_OPCODE) 240 printf("! "); 241 if (opcode > 0 && opcode <= NUMOPCODES) 242 printf("%s ", opcodes[opcode - 1]); 243 else 244 printf("%d ", opcode); 245 } 246 if (arpinfo->bitmask & EBT_ARP_HTYPE) { 247 printf("--arp-htype "); 248 if (arpinfo->invflags & EBT_ARP_HTYPE) 249 printf("! "); 250 printf("%d ", ntohs(arpinfo->htype)); 251 } 252 if (arpinfo->bitmask & EBT_ARP_PTYPE) { 253 struct ethertypeent *ent; 254 255 printf("--arp-ptype "); 256 if (arpinfo->invflags & EBT_ARP_PTYPE) 257 printf("! "); 258 ent = getethertypebynumber(ntohs(arpinfo->ptype)); 259 if (!ent) 260 printf("0x%x ", ntohs(arpinfo->ptype)); 261 else 262 printf("%s ", ent->e_name); 263 } 264 if (arpinfo->bitmask & EBT_ARP_SRC_IP) { 265 printf("--arp-ip-src "); 266 if (arpinfo->invflags & EBT_ARP_SRC_IP) 267 printf("! "); 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)); 272 } 273 if (arpinfo->bitmask & EBT_ARP_DST_IP) { 274 printf("--arp-ip-dst "); 275 if (arpinfo->invflags & EBT_ARP_DST_IP) 276 printf("! "); 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)); 281 } 282 if (arpinfo->bitmask & EBT_ARP_SRC_MAC) { 283 printf("--arp-mac-src "); 284 if (arpinfo->invflags & EBT_ARP_SRC_MAC) 285 printf("! "); 286 ebt_print_mac_and_mask(arpinfo->smaddr, arpinfo->smmsk); 287 printf(" "); 288 } 289 if (arpinfo->bitmask & EBT_ARP_DST_MAC) { 290 printf("--arp-mac-dst "); 291 if (arpinfo->invflags & EBT_ARP_DST_MAC) 292 printf("! "); 293 ebt_print_mac_and_mask(arpinfo->dmaddr, arpinfo->dmmsk); 294 printf(" "); 295 } 296 if (arpinfo->bitmask & EBT_ARP_GRAT) { 297 if (arpinfo->invflags & EBT_ARP_GRAT) 298 printf("! "); 299 printf("--arp-gratuitous "); 300 } 301} 302 303static int compare(const struct ebt_entry_match *m1, 304 const struct ebt_entry_match *m2) 305{ 306 struct ebt_arp_info *arpinfo1 = (struct ebt_arp_info *)m1->data; 307 struct ebt_arp_info *arpinfo2 = (struct ebt_arp_info *)m2->data; 308 309 if (arpinfo1->bitmask != arpinfo2->bitmask) 310 return 0; 311 if (arpinfo1->invflags != arpinfo2->invflags) 312 return 0; 313 if (arpinfo1->bitmask & EBT_ARP_OPCODE) { 314 if (arpinfo1->opcode != arpinfo2->opcode) 315 return 0; 316 } 317 if (arpinfo1->bitmask & EBT_ARP_HTYPE) { 318 if (arpinfo1->htype != arpinfo2->htype) 319 return 0; 320 } 321 if (arpinfo1->bitmask & EBT_ARP_PTYPE) { 322 if (arpinfo1->ptype != arpinfo2->ptype) 323 return 0; 324 } 325 if (arpinfo1->bitmask & EBT_ARP_SRC_IP) { 326 if (arpinfo1->saddr != arpinfo2->saddr) 327 return 0; 328 if (arpinfo1->smsk != arpinfo2->smsk) 329 return 0; 330 } 331 if (arpinfo1->bitmask & EBT_ARP_DST_IP) { 332 if (arpinfo1->daddr != arpinfo2->daddr) 333 return 0; 334 if (arpinfo1->dmsk != arpinfo2->dmsk) 335 return 0; 336 } 337 if (arpinfo1->bitmask & EBT_ARP_SRC_MAC) { 338 if (memcmp(arpinfo1->smaddr, arpinfo2->smaddr, ETH_ALEN)) 339 return 0; 340 if (memcmp(arpinfo1->smmsk, arpinfo2->smmsk, ETH_ALEN)) 341 return 0; 342 } 343 if (arpinfo1->bitmask & EBT_ARP_DST_MAC) { 344 if (memcmp(arpinfo1->dmaddr, arpinfo2->dmaddr, ETH_ALEN)) 345 return 0; 346 if (memcmp(arpinfo1->dmmsk, arpinfo2->dmmsk, ETH_ALEN)) 347 return 0; 348 } 349 return 1; 350} 351 352static struct ebt_u_match arp_match = 353{ 354 .name = "arp", 355 .size = sizeof(struct ebt_arp_info), 356 .help = print_help, 357 .init = init, 358 .parse = parse, 359 .final_check = final_check, 360 .print = print, 361 .compare = compare, 362 .extra_ops = opts, 363}; 364 365void _init(void) 366{ 367 ebt_register_match(&arp_match); 368} 369