summaryrefslogtreecommitdiffstats
path: root/extensions/libebt_arp.c
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2023-11-28 14:16:03 +0100
committerPhil Sutter <phil@nwl.cc>2024-01-10 16:07:31 +0100
commit1c21ae4ab5f0f74bbe67f3f3ab5724cf991a8d91 (patch)
tree42f6b175ea6356f93642ceba6e9cf11fc7af6a46 /extensions/libebt_arp.c
parent221f35690948d0fc17675cb76e14fcc6d57f3555 (diff)
extensions: libebt_arp: Use guided option parser
Diffstat (limited to 'extensions/libebt_arp.c')
-rw-r--r--extensions/libebt_arp.c201
1 files changed, 71 insertions, 130 deletions
diff --git a/extensions/libebt_arp.c b/extensions/libebt_arp.c
index 63a953d4..b6d691d8 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 */
@@ -78,137 +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
-brarp_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brarp_parse(struct xt_option_call *cb)
{
- struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
- struct in_addr *ipaddr, ipmask;
+ struct ebt_arp_info *arpinfo = cb->data;
+ struct xt_ethertypeent *ent;
long int i;
char *end;
- unsigned char *maddr;
- unsigned char *mmask;
- unsigned int ipnr;
- switch (c) {
- case ARP_OPCODE:
- EBT_CHECK_OPTION(flags, OPT_OPCODE);
- if (invert)
- arpinfo->invflags |= EBT_ARP_OPCODE;
- i = strtol(optarg, &end, 10);
+
+ xtables_option_parse(cb);
+
+ arpinfo->bitmask |= 1 << cb->entry->id;
+ if (cb->invert)
+ arpinfo->invflags |= 1 << cb->entry->id;
+
+ 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:
- xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
- if (c == ARP_IP_S) {
- EBT_CHECK_OPTION(flags, OPT_IP_S);
- arpinfo->saddr = ipaddr->s_addr;
- arpinfo->smsk = ipmask.s_addr;
- arpinfo->bitmask |= EBT_ARP_SRC_IP;
- } else {
- EBT_CHECK_OPTION(flags, OPT_IP_D);
- arpinfo->daddr = ipaddr->s_addr;
- arpinfo->dmsk = ipmask.s_addr;
- arpinfo->bitmask |= EBT_ARP_DST_IP;
- }
- free(ipaddr);
- if (invert) {
- if (c == ARP_IP_S)
- arpinfo->invflags |= EBT_ARP_SRC_IP;
- else
- arpinfo->invflags |= 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;
}
+ 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 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 ARP_GRAT:
- EBT_CHECK_OPTION(flags, OPT_GRAT);
- arpinfo->bitmask |= EBT_ARP_GRAT;
- if (invert)
- arpinfo->invflags |= EBT_ARP_GRAT;
+ 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)
@@ -279,9 +220,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)