diff options
Diffstat (limited to 'extensions/libebt_arp.c')
-rw-r--r-- | extensions/libebt_arp.c | 309 |
1 files changed, 88 insertions, 221 deletions
diff --git a/extensions/libebt_arp.c b/extensions/libebt_arp.c index d5035b95..50ce32be 100644 --- a/extensions/libebt_arp.c +++ b/extensions/libebt_arp.c @@ -10,7 +10,6 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> -#include <getopt.h> #include <xtables.h> #include <netinet/ether.h> @@ -20,26 +19,31 @@ #include "iptables/nft.h" #include "iptables/nft-bridge.h" -#define ARP_OPCODE '1' -#define ARP_HTYPE '2' -#define ARP_PTYPE '3' -#define ARP_IP_S '4' -#define ARP_IP_D '5' -#define ARP_MAC_S '6' -#define ARP_MAC_D '7' -#define ARP_GRAT '8' +/* values must correspond with EBT_ARP_* bit positions */ +enum { + O_OPCODE = 0, + O_HTYPE, + O_PTYPE, + O_SRC_IP, + O_DST_IP, + O_SRC_MAC, + O_DST_MAC, + O_GRAT, +}; -static const struct option brarp_opts[] = { - { "arp-opcode" , required_argument, 0, ARP_OPCODE }, - { "arp-op" , required_argument, 0, ARP_OPCODE }, - { "arp-htype" , required_argument, 0, ARP_HTYPE }, - { "arp-ptype" , required_argument, 0, ARP_PTYPE }, - { "arp-ip-src" , required_argument, 0, ARP_IP_S }, - { "arp-ip-dst" , required_argument, 0, ARP_IP_D }, - { "arp-mac-src" , required_argument, 0, ARP_MAC_S }, - { "arp-mac-dst" , required_argument, 0, ARP_MAC_D }, - { "arp-gratuitous", no_argument, 0, ARP_GRAT }, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry brarp_opts[] = { +#define ENTRY(n, i, t) { .name = n, .id = i, .type = t, .flags = XTOPT_INVERT } + ENTRY("arp-opcode", O_OPCODE, XTTYPE_STRING), + ENTRY("arp-op", O_OPCODE, XTTYPE_STRING), + ENTRY("arp-htype", O_HTYPE, XTTYPE_STRING), + ENTRY("arp-ptype", O_PTYPE, XTTYPE_STRING), + ENTRY("arp-ip-src", O_SRC_IP, XTTYPE_HOSTMASK), + ENTRY("arp-ip-dst", O_DST_IP, XTTYPE_HOSTMASK), + ENTRY("arp-mac-src", O_SRC_MAC, XTTYPE_ETHERMACMASK), + ENTRY("arp-mac-dst", O_DST_MAC, XTTYPE_ETHERMACMASK), + ENTRY("arp-gratuitous", O_GRAT, XTTYPE_NONE), +#undef ENTRY + XTOPT_TABLEEND }; /* a few names */ @@ -62,13 +66,13 @@ static void brarp_print_help(void) printf( "arp options:\n" -"--arp-opcode [!] opcode : ARP opcode (integer or string)\n" -"--arp-htype [!] type : ARP hardware type (integer or string)\n" -"--arp-ptype [!] type : ARP protocol type (hexadecimal or string)\n" -"--arp-ip-src [!] address[/mask]: ARP IP source specification\n" -"--arp-ip-dst [!] address[/mask]: ARP IP target specification\n" -"--arp-mac-src [!] address[/mask]: ARP MAC source specification\n" -"--arp-mac-dst [!] address[/mask]: ARP MAC target specification\n" +"[!] --arp-opcode opcode : ARP opcode (integer or string)\n" +"[!] --arp-htype type : ARP hardware type (integer or string)\n" +"[!] --arp-ptype type : ARP protocol type (hexadecimal or string)\n" +"[!] --arp-ip-src address[/mask]: ARP IP source specification\n" +"[!] --arp-ip-dst address[/mask]: ARP IP target specification\n" +"[!] --arp-mac-src address[/mask]: ARP MAC source specification\n" +"[!] --arp-mac-dst address[/mask]: ARP MAC target specification\n" "[!] --arp-gratuitous : ARP gratuitous packet\n" " opcode strings: \n"); for (i = 0; i < ARRAY_SIZE(opcodes); i++) @@ -78,210 +82,74 @@ static void brarp_print_help(void) " protocol type string: see "XT_PATH_ETHERTYPES"\n"); } -#define OPT_OPCODE 0x01 -#define OPT_HTYPE 0x02 -#define OPT_PTYPE 0x04 -#define OPT_IP_S 0x08 -#define OPT_IP_D 0x10 -#define OPT_MAC_S 0x20 -#define OPT_MAC_D 0x40 -#define OPT_GRAT 0x80 - -static int undot_ip(char *ip, unsigned char *ip2) -{ - char *p, *q, *end; - long int onebyte; - int i; - char buf[20]; - - strncpy(buf, ip, sizeof(buf) - 1); - - p = buf; - for (i = 0; i < 3; i++) { - if ((q = strchr(p, '.')) == NULL) - return -1; - *q = '\0'; - onebyte = strtol(p, &end, 10); - if (*end != '\0' || onebyte > 255 || onebyte < 0) - return -1; - ip2[i] = (unsigned char)onebyte; - p = q + 1; - } - - onebyte = strtol(p, &end, 10); - if (*end != '\0' || onebyte > 255 || onebyte < 0) - return -1; - ip2[3] = (unsigned char)onebyte; - - return 0; -} - -static int ip_mask(char *mask, unsigned char *mask2) +static void brarp_parse(struct xt_option_call *cb) { + struct ebt_arp_info *arpinfo = cb->data; + struct xt_ethertypeent *ent; + long int i; char *end; - long int bits; - uint32_t mask22; - if (undot_ip(mask, mask2)) { - /* not the /a.b.c.e format, maybe the /x format */ - bits = strtol(mask, &end, 10); - if (*end != '\0' || bits > 32 || bits < 0) - return -1; - if (bits != 0) { - mask22 = htonl(0xFFFFFFFF << (32 - bits)); - memcpy(mask2, &mask22, 4); - } else { - mask22 = 0xFFFFFFFF; - memcpy(mask2, &mask22, 4); - } - } - return 0; -} - -static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk) -{ - char *p; - - /* first the mask */ - if ((p = strrchr(address, '/')) != NULL) { - *p = '\0'; - if (ip_mask(p + 1, (unsigned char *)msk)) { - xtables_error(PARAMETER_PROBLEM, - "Problem with the IP mask '%s'", p + 1); - return; - } - } else - *msk = 0xFFFFFFFF; - if (undot_ip(address, (unsigned char *)addr)) { - xtables_error(PARAMETER_PROBLEM, - "Problem with the IP address '%s'", address); - return; - } - *addr = *addr & *msk; -} + xtables_option_parse(cb); -static int -brarp_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data; - long int i; - char *end; - uint32_t *addr; - uint32_t *mask; - unsigned char *maddr; - unsigned char *mmask; + arpinfo->bitmask |= 1 << cb->entry->id; + if (cb->invert) + arpinfo->invflags |= 1 << cb->entry->id; - switch (c) { - case ARP_OPCODE: - EBT_CHECK_OPTION(flags, OPT_OPCODE); - if (invert) - arpinfo->invflags |= EBT_ARP_OPCODE; - i = strtol(optarg, &end, 10); + switch (cb->entry->id) { + case O_OPCODE: + i = strtol(cb->arg, &end, 10); if (i < 0 || i >= (0x1 << 16) || *end !='\0') { for (i = 0; i < ARRAY_SIZE(opcodes); i++) - if (!strcasecmp(opcodes[i], optarg)) + if (!strcasecmp(opcodes[i], cb->arg)) break; if (i == ARRAY_SIZE(opcodes)) - xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP opcode"); + xtables_error(PARAMETER_PROBLEM, + "Problem with specified ARP opcode"); i++; } arpinfo->opcode = htons(i); - arpinfo->bitmask |= EBT_ARP_OPCODE; break; - - case ARP_HTYPE: - EBT_CHECK_OPTION(flags, OPT_HTYPE); - if (invert) - arpinfo->invflags |= EBT_ARP_HTYPE; - i = strtol(optarg, &end, 10); + case O_HTYPE: + i = strtol(cb->arg, &end, 10); if (i < 0 || i >= (0x1 << 16) || *end !='\0') { - if (!strcasecmp("Ethernet", argv[optind - 1])) + if (!strcasecmp("Ethernet", cb->arg)) i = 1; else - xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP hardware type"); + xtables_error(PARAMETER_PROBLEM, + "Problem with specified ARP hardware type"); } arpinfo->htype = htons(i); - arpinfo->bitmask |= EBT_ARP_HTYPE; - break; - case ARP_PTYPE: { - uint16_t proto; - - EBT_CHECK_OPTION(flags, OPT_PTYPE); - if (invert) - arpinfo->invflags |= EBT_ARP_PTYPE; - - i = strtol(optarg, &end, 16); - if (i < 0 || i >= (0x1 << 16) || *end !='\0') { - struct xt_ethertypeent *ent; - - ent = xtables_getethertypebyname(argv[optind - 1]); - if (!ent) - xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP " - "protocol type"); - proto = ent->e_ethertype; - - } else - proto = i; - arpinfo->ptype = htons(proto); - arpinfo->bitmask |= EBT_ARP_PTYPE; break; - } - - case ARP_IP_S: - case ARP_IP_D: - if (c == ARP_IP_S) { - EBT_CHECK_OPTION(flags, OPT_IP_S); - addr = &arpinfo->saddr; - mask = &arpinfo->smsk; - arpinfo->bitmask |= EBT_ARP_SRC_IP; - } else { - EBT_CHECK_OPTION(flags, OPT_IP_D); - addr = &arpinfo->daddr; - mask = &arpinfo->dmsk; - arpinfo->bitmask |= EBT_ARP_DST_IP; + case O_PTYPE: + i = strtol(cb->arg, &end, 16); + if (i >= 0 && i < (0x1 << 16) && *end == '\0') { + arpinfo->ptype = htons(i); + break; } - if (invert) { - if (c == ARP_IP_S) - arpinfo->invflags |= EBT_ARP_SRC_IP; - else - arpinfo->invflags |= EBT_ARP_DST_IP; - } - ebt_parse_ip_address(optarg, addr, mask); + ent = xtables_getethertypebyname(cb->arg); + if (!ent) + xtables_error(PARAMETER_PROBLEM, + "Problem with specified ARP protocol type"); + arpinfo->ptype = htons(ent->e_ethertype); break; - case ARP_MAC_S: - case ARP_MAC_D: - if (c == ARP_MAC_S) { - EBT_CHECK_OPTION(flags, OPT_MAC_S); - maddr = arpinfo->smaddr; - mmask = arpinfo->smmsk; - arpinfo->bitmask |= EBT_ARP_SRC_MAC; - } else { - EBT_CHECK_OPTION(flags, OPT_MAC_D); - maddr = arpinfo->dmaddr; - mmask = arpinfo->dmmsk; - arpinfo->bitmask |= EBT_ARP_DST_MAC; - } - if (invert) { - if (c == ARP_MAC_S) - arpinfo->invflags |= EBT_ARP_SRC_MAC; - else - arpinfo->invflags |= EBT_ARP_DST_MAC; - } - if (xtables_parse_mac_and_mask(optarg, maddr, mmask)) - xtables_error(PARAMETER_PROBLEM, "Problem with ARP MAC address argument"); + case O_SRC_IP: + arpinfo->saddr = cb->val.haddr.ip & cb->val.hmask.ip; + arpinfo->smsk = cb->val.hmask.ip; break; - case ARP_GRAT: - EBT_CHECK_OPTION(flags, OPT_GRAT); - arpinfo->bitmask |= EBT_ARP_GRAT; - if (invert) - arpinfo->invflags |= EBT_ARP_GRAT; + case O_DST_IP: + arpinfo->daddr = cb->val.haddr.ip & cb->val.hmask.ip; + arpinfo->dmsk = cb->val.hmask.ip; + break; + case O_SRC_MAC: + memcpy(arpinfo->smaddr, cb->val.ethermac, ETH_ALEN); + memcpy(arpinfo->smmsk, cb->val.ethermacmask, ETH_ALEN); + break; + case O_DST_MAC: + memcpy(arpinfo->dmaddr, cb->val.ethermac, ETH_ALEN); + memcpy(arpinfo->dmmsk, cb->val.ethermacmask, ETH_ALEN); break; - default: - return 0; } - return 1; } static void brarp_print(const void *ip, const struct xt_entry_match *match, int numeric) @@ -290,51 +158,50 @@ static void brarp_print(const void *ip, const struct xt_entry_match *match, int if (arpinfo->bitmask & EBT_ARP_OPCODE) { int opcode = ntohs(arpinfo->opcode); - printf("--arp-op "); + if (arpinfo->invflags & EBT_ARP_OPCODE) printf("! "); + printf("--arp-op "); if (opcode > 0 && opcode <= ARRAY_SIZE(opcodes)) printf("%s ", opcodes[opcode - 1]); else printf("%d ", opcode); } if (arpinfo->bitmask & EBT_ARP_HTYPE) { - printf("--arp-htype "); if (arpinfo->invflags & EBT_ARP_HTYPE) printf("! "); - printf("%d ", ntohs(arpinfo->htype)); + printf("--arp-htype %d ", ntohs(arpinfo->htype)); } if (arpinfo->bitmask & EBT_ARP_PTYPE) { - printf("--arp-ptype "); if (arpinfo->invflags & EBT_ARP_PTYPE) printf("! "); - printf("0x%x ", ntohs(arpinfo->ptype)); + printf("--arp-ptype 0x%x ", ntohs(arpinfo->ptype)); } if (arpinfo->bitmask & EBT_ARP_SRC_IP) { - printf("--arp-ip-src "); if (arpinfo->invflags & EBT_ARP_SRC_IP) printf("! "); - printf("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->saddr), - xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->smsk)); + printf("--arp-ip-src %s%s ", + xtables_ipaddr_to_numeric((void *)&arpinfo->saddr), + xtables_ipmask_to_numeric((void *)&arpinfo->smsk)); } if (arpinfo->bitmask & EBT_ARP_DST_IP) { - printf("--arp-ip-dst "); if (arpinfo->invflags & EBT_ARP_DST_IP) printf("! "); - printf("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->daddr), - xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->dmsk)); + printf("--arp-ip-dst %s%s ", + xtables_ipaddr_to_numeric((void *)&arpinfo->daddr), + xtables_ipmask_to_numeric((void *)&arpinfo->dmsk)); } if (arpinfo->bitmask & EBT_ARP_SRC_MAC) { - printf("--arp-mac-src "); if (arpinfo->invflags & EBT_ARP_SRC_MAC) printf("! "); + printf("--arp-mac-src "); xtables_print_mac_and_mask(arpinfo->smaddr, arpinfo->smmsk); printf(" "); } if (arpinfo->bitmask & EBT_ARP_DST_MAC) { - printf("--arp-mac-dst "); if (arpinfo->invflags & EBT_ARP_DST_MAC) printf("! "); + printf("--arp-mac-dst "); xtables_print_mac_and_mask(arpinfo->dmaddr, arpinfo->dmmsk); printf(" "); } @@ -352,9 +219,9 @@ static struct xtables_match brarp_match = { .size = XT_ALIGN(sizeof(struct ebt_arp_info)), .userspacesize = XT_ALIGN(sizeof(struct ebt_arp_info)), .help = brarp_print_help, - .parse = brarp_parse, + .x6_parse = brarp_parse, .print = brarp_print, - .extra_opts = brarp_opts, + .x6_options = brarp_opts, }; void _init(void) |