]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
extensions: libarpt_mangle: Use guided option parser
authorPhil Sutter <phil@nwl.cc>
Thu, 2 Sep 2021 14:53:26 +0000 (16:53 +0200)
committerPhil Sutter <phil@nwl.cc>
Thu, 23 Nov 2023 17:01:21 +0000 (18:01 +0100)
Sadly not the best conversion, struct arpt_mangle is not ideal for use
as storage backend: With MAC addresses, xtopt_parse_ethermac() refuses
to write into *_devaddr fields as they are larger than expected. With
XTTYPE_HOSTMASK OTOH, XTOPT_PUT is not supported in the first place.

As a side-effect, network names (from /etc/networks) are no longer
accepted. But earlier migrations to guided option parser had this
side-effect as well, so probably not a frequently used feature.

Signed-off-by: Phil Sutter <phil@nwl.cc>
extensions/libarpt_mangle.c
extensions/libarpt_mangle.t

index 364c9ce755b97d0a22f15b9a2187672dacd3cfea..283bb1323806c61952655e83e685a706f361d8f2 100644 (file)
@@ -25,19 +25,16 @@ static void arpmangle_print_help(void)
        "--mangle-target target (DROP, CONTINUE or ACCEPT -- default is ACCEPT)\n");
 }
 
-#define MANGLE_IPS    '1'
-#define MANGLE_IPT    '2'
-#define MANGLE_DEVS   '3'
-#define MANGLE_DEVT   '4'
-#define MANGLE_TARGET '5'
-
-static const struct option arpmangle_opts[] = {
-       { .name = "mangle-ip-s",        .has_arg = true, .val = MANGLE_IPS },
-       { .name = "mangle-ip-d",        .has_arg = true, .val = MANGLE_IPT },
-       { .name = "mangle-mac-s",       .has_arg = true, .val = MANGLE_DEVS },
-       { .name = "mangle-mac-d",       .has_arg = true, .val = MANGLE_DEVT },
-       { .name = "mangle-target",      .has_arg = true, .val = MANGLE_TARGET },
-       XT_GETOPT_TABLEEND,
+/* internal use only, explicitly not covered by ARPT_MANGLE_MASK */
+#define ARPT_MANGLE_TARGET     0x10
+
+static const struct xt_option_entry arpmangle_opts[] = {
+{ .name = "mangle-ip-s", .id = ARPT_MANGLE_SIP, .type = XTTYPE_HOSTMASK },
+{ .name = "mangle-ip-d", .id = ARPT_MANGLE_TIP, .type = XTTYPE_HOSTMASK },
+{ .name = "mangle-mac-s", .id = ARPT_MANGLE_SDEV, .type = XTTYPE_ETHERMAC },
+{ .name = "mangle-mac-d", .id = ARPT_MANGLE_TDEV, .type = XTTYPE_ETHERMAC },
+{ .name = "mangle-target", .id = ARPT_MANGLE_TARGET, .type = XTTYPE_STRING },
+XTOPT_TABLEEND,
 };
 
 static void arpmangle_init(struct xt_entry_target *target)
@@ -47,86 +44,50 @@ static void arpmangle_init(struct xt_entry_target *target)
        mangle->target = NF_ACCEPT;
 }
 
-static int
-arpmangle_parse(int c, char **argv, int invert, unsigned int *flags,
-               const void *entry, struct xt_entry_target **target)
+static void assert_hopts(const struct arpt_entry *e, const char *optname)
 {
-       struct arpt_mangle *mangle = (struct arpt_mangle *)(*target)->data;
-       struct in_addr *ipaddr, mask;
-       struct ether_addr *macaddr;
-       const struct arpt_entry *e = (const struct arpt_entry *)entry;
-       unsigned int nr;
-       int ret = 1;
-
-       memset(&mask, 0, sizeof(mask));
-
-       switch (c) {
-       case MANGLE_IPS:
-               xtables_ipparse_any(optarg, &ipaddr, &mask, &nr);
-               mangle->u_s.src_ip.s_addr = ipaddr->s_addr;
-               free(ipaddr);
-               mangle->flags |= ARPT_MANGLE_SIP;
-               break;
-       case MANGLE_IPT:
-               xtables_ipparse_any(optarg, &ipaddr, &mask, &nr);
-               mangle->u_t.tgt_ip.s_addr = ipaddr->s_addr;
-               free(ipaddr);
-               mangle->flags |= ARPT_MANGLE_TIP;
+       if (e->arp.arhln_mask == 0)
+               xtables_error(PARAMETER_PROBLEM, "no --h-length defined");
+       if (e->arp.invflags & IPT_INV_ARPHLN)
+               xtables_error(PARAMETER_PROBLEM,
+                             "! hln not allowed for --%s", optname);
+       if (e->arp.arhln != 6)
+               xtables_error(PARAMETER_PROBLEM, "only --h-length 6 supported");
+}
+
+static void arpmangle_parse(struct xt_option_call *cb)
+{
+       const struct arpt_entry *e = cb->xt_entry;
+       struct arpt_mangle *mangle = cb->data;
+
+       xtables_option_parse(cb);
+       mangle->flags |= (cb->entry->id & ARPT_MANGLE_MASK);
+       switch (cb->entry->id) {
+       case ARPT_MANGLE_SIP:
+               mangle->u_s.src_ip = cb->val.haddr.in;
                break;
-       case MANGLE_DEVS:
-               if (e->arp.arhln_mask == 0)
-                       xtables_error(PARAMETER_PROBLEM,
-                                     "no --h-length defined");
-               if (e->arp.invflags & IPT_INV_ARPHLN)
-                       xtables_error(PARAMETER_PROBLEM,
-                                     "! --h-length not allowed for "
-                                     "--mangle-mac-s");
-               if (e->arp.arhln != 6)
-                       xtables_error(PARAMETER_PROBLEM,
-                                     "only --h-length 6 supported");
-               macaddr = ether_aton(optarg);
-               if (macaddr == NULL)
-                       xtables_error(PARAMETER_PROBLEM,
-                                     "invalid source MAC");
-               memcpy(mangle->src_devaddr, macaddr, e->arp.arhln);
-               mangle->flags |= ARPT_MANGLE_SDEV;
+       case ARPT_MANGLE_TIP:
+               mangle->u_t.tgt_ip = cb->val.haddr.in;
                break;
-       case MANGLE_DEVT:
-               if (e->arp.arhln_mask == 0)
-                       xtables_error(PARAMETER_PROBLEM,
-                                     "no --h-length defined");
-               if (e->arp.invflags & IPT_INV_ARPHLN)
-                       xtables_error(PARAMETER_PROBLEM,
-                                     "! hln not allowed for --mangle-mac-d");
-               if (e->arp.arhln != 6)
-                       xtables_error(PARAMETER_PROBLEM,
-                                     "only --h-length 6 supported");
-               macaddr = ether_aton(optarg);
-               if (macaddr == NULL)
-                       xtables_error(PARAMETER_PROBLEM, "invalid target MAC");
-               memcpy(mangle->tgt_devaddr, macaddr, e->arp.arhln);
-               mangle->flags |= ARPT_MANGLE_TDEV;
+       case ARPT_MANGLE_SDEV:
+               assert_hopts(e, cb->entry->name);
+               memcpy(mangle->src_devaddr, cb->val.ethermac, ETH_ALEN);
+       case ARPT_MANGLE_TDEV:
+               assert_hopts(e, cb->entry->name);
+               memcpy(mangle->tgt_devaddr, cb->val.ethermac, ETH_ALEN);
                break;
-       case MANGLE_TARGET:
-               if (!strcmp(optarg, "DROP"))
+       case ARPT_MANGLE_TARGET:
+               if (!strcmp(cb->arg, "DROP"))
                        mangle->target = NF_DROP;
-               else if (!strcmp(optarg, "ACCEPT"))
+               else if (!strcmp(cb->arg, "ACCEPT"))
                        mangle->target = NF_ACCEPT;
-               else if (!strcmp(optarg, "CONTINUE"))
+               else if (!strcmp(cb->arg, "CONTINUE"))
                        mangle->target = XT_CONTINUE;
                else
                        xtables_error(PARAMETER_PROBLEM,
                                      "bad target for --mangle-target");
                break;
-       default:
-               ret = 0;
        }
-
-       return ret;
-}
-
-static void arpmangle_final_check(unsigned int flags)
-{
 }
 
 static const char *ipaddr_to(const struct in_addr *addrp, int numeric)
@@ -225,11 +186,10 @@ static struct xtables_target arpmangle_target = {
        .userspacesize  = XT_ALIGN(sizeof(struct arpt_mangle)),
        .help           = arpmangle_print_help,
        .init           = arpmangle_init,
-       .parse          = arpmangle_parse,
-       .final_check    = arpmangle_final_check,
+       .x6_parse       = arpmangle_parse,
        .print          = arpmangle_print,
        .save           = arpmangle_save,
-       .extra_opts     = arpmangle_opts,
+       .x6_options     = arpmangle_opts,
        .xlate          = arpmangle_xlate,
 };
 
index da9669489d291395ac8191169791809c9835520d..7a639ee10aa0fea4d4fd2dae1769f40a1260b67d 100644 (file)
@@ -3,3 +3,7 @@
 -j mangle -d 1.2.3.4 --mangle-ip-d 1.2.3.5;=;OK
 -j mangle -d 1.2.3.4 --mangle-mac-d 00:01:02:03:04:05;=;OK
 -d 1.2.3.4 --h-length 5 -j mangle --mangle-mac-s 00:01:02:03:04:05;=;FAIL
+-j mangle --mangle-ip-s 1.2.3.4 --mangle-target DROP;=;OK
+-j mangle --mangle-ip-s 1.2.3.4 --mangle-target ACCEPT;-j mangle --mangle-ip-s 1.2.3.4;OK
+-j mangle --mangle-ip-s 1.2.3.4 --mangle-target CONTINUE;=;OK
+-j mangle --mangle-ip-s 1.2.3.4 --mangle-target FOO;=;FAIL