From 84c04e36eab024efa7c396ee370bf053c89af895 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 10 Apr 2018 10:55:30 +0200 Subject: ebtables-compat: add nat match extensions adds snat and dnat. Translation for snat isn't complete, the --snat-arp switch isn't supported so far. Signed-off-by: Florian Westphal --- extensions/libebt_dnat.c | 134 +++++++++++++++++++++++++++++++++++++ extensions/libebt_dnat.txlate | 8 +++ extensions/libebt_snat.c | 151 ++++++++++++++++++++++++++++++++++++++++++ extensions/libebt_snat.txlate | 5 ++ iptables/xtables-eb.c | 2 + 5 files changed, 300 insertions(+) create mode 100644 extensions/libebt_dnat.c create mode 100644 extensions/libebt_dnat.txlate create mode 100644 extensions/libebt_snat.c create mode 100644 extensions/libebt_snat.txlate diff --git a/extensions/libebt_dnat.c b/extensions/libebt_dnat.c new file mode 100644 index 00000000..c179d8c1 --- /dev/null +++ b/extensions/libebt_dnat.c @@ -0,0 +1,134 @@ +/* ebt_nat + * + * Authors: + * Bart De Schuymer + * + * June, 2002 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "iptables/nft.h" +#include "iptables/nft-bridge.h" + +#define NAT_D '1' +#define NAT_D_TARGET '2' +static const struct option brdnat_opts[] = +{ + { "to-destination", required_argument, 0, NAT_D }, + { "to-dst" , required_argument, 0, NAT_D }, + { "dnat-target" , required_argument, 0, NAT_D_TARGET }, + { 0 } +}; + +static void brdnat_print_help(void) +{ + printf( + "dnat options:\n" + " --to-dst address : MAC address to map destination to\n" + " --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n"); +} + +static void brdnat_init(struct xt_entry_target *target) +{ + struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data; + + natinfo->target = EBT_ACCEPT; +} + +#define OPT_DNAT 0x01 +#define OPT_DNAT_TARGET 0x02 +static int brdnat_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data; + struct ether_addr *addr; + + switch (c) { + case NAT_D: + EBT_CHECK_OPTION(flags, OPT_DNAT); + if (!(addr = ether_aton(optarg))) + xtables_error(PARAMETER_PROBLEM, "Problem with specified --to-destination mac"); + memcpy(natinfo->mac, addr, ETH_ALEN); + break; + case NAT_D_TARGET: + EBT_CHECK_OPTION(flags, OPT_DNAT_TARGET); + if (ebt_fill_target(optarg, (unsigned int *)&natinfo->target)) + xtables_error(PARAMETER_PROBLEM, "Illegal --dnat-target target"); + break; + default: + return 0; + } + return 1; +} + +static void brdnat_final_check(unsigned int flags) +{ + if (!flags) + xtables_error(PARAMETER_PROBLEM, + "You must specify proper arguments"); +} + +static void ebt_print_mac(const unsigned char *mac) +{ + printf("%s", ether_ntoa((struct ether_addr *) mac)); +} + +static void brdnat_print(const void *ip, const struct xt_entry_target *target, int numeric) +{ + struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data; + + printf("--to-dst "); + ebt_print_mac(natinfo->mac); + printf(" --dnat-target %s", ebt_target_name(natinfo->target)); +} + +static const char* brdnat_verdict(int verdict) +{ + switch (verdict) { + case EBT_ACCEPT: return "accept"; + case EBT_DROP: return "drop"; + case EBT_CONTINUE: return "continue"; + case EBT_RETURN: return "return"; + } + + return ""; +} + +static int brdnat_xlate(struct xt_xlate *xl, + const struct xt_xlate_tg_params *params) +{ + const struct ebt_nat_info *natinfo = (const void*)params->target->data; + + xt_xlate_add(xl, "ether daddr set %s %s ", + ether_ntoa((struct ether_addr *)natinfo->mac), + brdnat_verdict(natinfo->target)); + + return 1; +} + +static struct xtables_target brdnat_target = +{ + .name = "dnat", + .version = XTABLES_VERSION, + .family = NFPROTO_BRIDGE, + .size = XT_ALIGN(sizeof(struct ebt_nat_info)), + .userspacesize = XT_ALIGN(sizeof(struct ebt_nat_info)), + .help = brdnat_print_help, + .init = brdnat_init, + .parse = brdnat_parse, + .final_check = brdnat_final_check, + .print = brdnat_print, + .xlate = brdnat_xlate, + .extra_opts = brdnat_opts, +}; + +void _init(void) +{ + xtables_register_target(&brdnat_target); +} diff --git a/extensions/libebt_dnat.txlate b/extensions/libebt_dnat.txlate new file mode 100644 index 00000000..2652dd55 --- /dev/null +++ b/extensions/libebt_dnat.txlate @@ -0,0 +1,8 @@ +ebtables-translate -t nat -A PREROUTING -i someport --to-dst de:ad:00:be:ee:ff +nft add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff accept counter + +ebtables-translate -t nat -A PREROUTING -i someport --to-dst de:ad:00:be:ee:ff --dnat-target ACCEPT +nft add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff accept counter + +ebtables-translate -t nat -A PREROUTING -i someport --to-dst de:ad:00:be:ee:ff --dnat-target CONTINUE +nft add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff continue counter diff --git a/extensions/libebt_snat.c b/extensions/libebt_snat.c new file mode 100644 index 00000000..95b32f9c --- /dev/null +++ b/extensions/libebt_snat.c @@ -0,0 +1,151 @@ +/* ebt_nat + * + * Authors: + * Bart De Schuymer + * + * June, 2002 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "iptables/nft.h" +#include "iptables/nft-bridge.h" + +#define NAT_S '1' +#define NAT_S_TARGET '2' +#define NAT_S_ARP '3' +static const struct option brsnat_opts[] = +{ + { "to-source" , required_argument, 0, NAT_S }, + { "to-src" , required_argument, 0, NAT_S }, + { "snat-target" , required_argument, 0, NAT_S_TARGET }, + { "snat-arp" , no_argument, 0, NAT_S_ARP }, + { 0 } +}; + +static void brsnat_print_help(void) +{ + printf( + "snat options:\n" + " --to-src address : MAC address to map source to\n" + " --snat-target target : ACCEPT, DROP, RETURN or CONTINUE\n" + " --snat-arp : also change src address in arp msg\n"); +} + +static void brsnat_init(struct xt_entry_target *target) +{ + struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data; + + natinfo->target = EBT_ACCEPT; +} + +#define OPT_SNAT 0x01 +#define OPT_SNAT_TARGET 0x02 +#define OPT_SNAT_ARP 0x04 +static int brsnat_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data; + struct ether_addr *addr; + + switch (c) { + case NAT_S: + EBT_CHECK_OPTION(flags, OPT_SNAT); + if (!(addr = ether_aton(optarg))) + xtables_error(PARAMETER_PROBLEM, "Problem with specified --to-source mac"); + memcpy(natinfo->mac, addr, ETH_ALEN); + break; + case NAT_S_TARGET: + { unsigned int tmp; + EBT_CHECK_OPTION(flags, OPT_SNAT_TARGET); + if (ebt_fill_target(optarg, &tmp)) + xtables_error(PARAMETER_PROBLEM, "Illegal --snat-target target"); + natinfo->target = (natinfo->target & ~EBT_VERDICT_BITS) | (tmp & EBT_VERDICT_BITS); + } + break; + case NAT_S_ARP: + EBT_CHECK_OPTION(flags, OPT_SNAT_ARP); + natinfo->target ^= NAT_ARP_BIT; + break; + default: + return 0; + } + return 1; +} + +static void brsnat_final_check(unsigned int flags) +{ + if (!flags) + xtables_error(PARAMETER_PROBLEM, + "You must specify proper arguments"); +} + +static void ebt_print_mac(const unsigned char *mac) +{ + printf("%s", ether_ntoa((struct ether_addr *) mac)); +} + +static void brsnat_print(const void *ip, const struct xt_entry_target *target, int numeric) +{ + struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data; + + printf("--to-src "); + ebt_print_mac(natinfo->mac); + if (!(natinfo->target&NAT_ARP_BIT)) + printf(" --snat-arp"); + printf(" --snat-target %s", ebt_target_name((natinfo->target|~EBT_VERDICT_BITS))); +} + +static const char* brsnat_verdict(int verdict) +{ + switch (verdict) { + case EBT_ACCEPT: return "accept"; + case EBT_DROP: return "drop"; + case EBT_CONTINUE: return "continue"; + case EBT_RETURN: return "return"; + } + + return ""; +} + +static int brsnat_xlate(struct xt_xlate *xl, + const struct xt_xlate_tg_params *params) +{ + const struct ebt_nat_info *natinfo = (const void*)params->target->data; + + xt_xlate_add(xl, "ether saddr set %s ", + ether_ntoa((struct ether_addr *)natinfo->mac)); + + /* NAT_ARP_BIT set -> no arp mangling, not set -> arp mangling (yes, its inverted) */ + if (!(natinfo->target&NAT_ARP_BIT)) + return 0; + + xt_xlate_add(xl, "%s ", brsnat_verdict(natinfo->target | ~EBT_VERDICT_BITS)); + return 1; +} + +static struct xtables_target brsnat_target = +{ + .name = "snat", + .version = XTABLES_VERSION, + .family = NFPROTO_BRIDGE, + .size = XT_ALIGN(sizeof(struct ebt_nat_info)), + .userspacesize = XT_ALIGN(sizeof(struct ebt_nat_info)), + .help = brsnat_print_help, + .init = brsnat_init, + .parse = brsnat_parse, + .final_check = brsnat_final_check, + .print = brsnat_print, + .xlate = brsnat_xlate, + .extra_opts = brsnat_opts, +}; + +void _init(void) +{ + xtables_register_target(&brsnat_target); +} diff --git a/extensions/libebt_snat.txlate b/extensions/libebt_snat.txlate new file mode 100644 index 00000000..0d846024 --- /dev/null +++ b/extensions/libebt_snat.txlate @@ -0,0 +1,5 @@ +ebtables-translate -t nat -A POSTROUTING -s 0:0:0:0:0:0 -o someport+ --to-source de:ad:00:be:ee:ff +nft add rule bridge nat POSTROUTING oifname "someport*" ether saddr 00:00:00:00:00:00 ether saddr set de:ad:0:be:ee:ff accept counter + +ebtables-translate -t nat -A POSTROUTING -o someport --to-src de:ad:00:be:ee:ff --snat-target CONTINUE +nft add rule bridge nat POSTROUTING oifname "someport" ether saddr set de:ad:0:be:ee:ff continue counter diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c index 8708bea3..a72c9073 100644 --- a/iptables/xtables-eb.c +++ b/iptables/xtables-eb.c @@ -676,6 +676,8 @@ void ebt_load_match_extensions(void) ebt_load_watcher("nflog"); ebt_load_target("mark"); + ebt_load_target("dnat"); + ebt_load_target("snat"); } void ebt_add_match(struct xtables_match *m, -- cgit v1.2.3