summaryrefslogtreecommitdiffstats
path: root/extensions/libarpt_mangle.c
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/libarpt_mangle.c')
-rw-r--r--extensions/libarpt_mangle.c189
1 files changed, 93 insertions, 96 deletions
diff --git a/extensions/libarpt_mangle.c b/extensions/libarpt_mangle.c
index 2fea6185..283bb132 100644
--- a/extensions/libarpt_mangle.c
+++ b/extensions/libarpt_mangle.c
@@ -13,7 +13,6 @@
#include <xtables.h>
#include <linux/netfilter_arp/arpt_mangle.h>
#include "iptables/nft.h"
-#include "iptables/nft-arp.h"
static void arpmangle_print_help(void)
{
@@ -26,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)
@@ -48,95 +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)
+{
+ 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)
{
- 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;
+ 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_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;
+ case ARPT_MANGLE_TIP:
+ mangle->u_t.tgt_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 & ARPT_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;
- break;
- case MANGLE_DEVT:
- if (e->arp.arhln_mask == 0)
- xtables_error(PARAMETER_PROBLEM,
- "no --h-length defined");
- if (e->arp.invflags & ARPT_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 void print_mac(const unsigned char *mac, int l)
-{
- int j;
-
- for (j = 0; j < l; j++)
- printf("%02x%s", mac[j],
- (j==l-1) ? "" : ":");
}
static const char *ipaddr_to(const struct in_addr *addrp, int numeric)
@@ -159,7 +110,7 @@ arpmangle_print(const void *ip, const struct xt_entry_target *target,
}
if (m->flags & ARPT_MANGLE_SDEV) {
printf(" --mangle-mac-s ");
- print_mac((unsigned char *)m->src_devaddr, 6);
+ xtables_print_mac((unsigned char *)m->src_devaddr);
}
if (m->flags & ARPT_MANGLE_TIP) {
printf(" --mangle-ip-d %s",
@@ -167,7 +118,7 @@ arpmangle_print(const void *ip, const struct xt_entry_target *target,
}
if (m->flags & ARPT_MANGLE_TDEV) {
printf(" --mangle-mac-d ");
- print_mac((unsigned char *)m->tgt_devaddr, 6);
+ xtables_print_mac((unsigned char *)m->tgt_devaddr);
}
if (m->target != NF_ACCEPT) {
printf(" --mangle-target %s",
@@ -180,6 +131,52 @@ static void arpmangle_save(const void *ip, const struct xt_entry_target *target)
arpmangle_print(ip, target, 0);
}
+static void print_devaddr_xlate(const char *macaddress, struct xt_xlate *xl)
+{
+ unsigned int i;
+
+ xt_xlate_add(xl, "%02x", macaddress[0]);
+ for (i = 1; i < ETH_ALEN; ++i)
+ xt_xlate_add(xl, ":%02x", macaddress[i]);
+}
+
+static int arpmangle_xlate(struct xt_xlate *xl,
+ const struct xt_xlate_tg_params *params)
+{
+ const struct arpt_mangle *m = (const void *)params->target->data;
+
+ if (m->flags & ARPT_MANGLE_SIP)
+ xt_xlate_add(xl, "arp saddr ip set %s ",
+ xtables_ipaddr_to_numeric(&m->u_s.src_ip));
+
+ if (m->flags & ARPT_MANGLE_SDEV) {
+ xt_xlate_add(xl, "arp %caddr ether set ", 's');
+ print_devaddr_xlate(m->src_devaddr, xl);
+ }
+
+ if (m->flags & ARPT_MANGLE_TIP)
+ xt_xlate_add(xl, "arp daddr ip set %s ",
+ xtables_ipaddr_to_numeric(&m->u_t.tgt_ip));
+
+ if (m->flags & ARPT_MANGLE_TDEV) {
+ xt_xlate_add(xl, "arp %caddr ether set ", 'd');
+ print_devaddr_xlate(m->tgt_devaddr, xl);
+ }
+
+ switch (m->target) {
+ case NF_ACCEPT:
+ xt_xlate_add(xl, "accept");
+ break;
+ case NF_DROP:
+ xt_xlate_add(xl, "drop");
+ break;
+ default:
+ break;
+ }
+
+ return 1;
+}
+
static struct xtables_target arpmangle_target = {
.name = "mangle",
.revision = 0,
@@ -189,11 +186,11 @@ 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,
};
void _init(void)