diff options
Diffstat (limited to 'iptables/xtables-translate.c')
-rw-r--r-- | iptables/xtables-translate.c | 102 |
1 files changed, 68 insertions, 34 deletions
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c index d1e87f16..3d8617f0 100644 --- a/iptables/xtables-translate.c +++ b/iptables/xtables-translate.c @@ -41,7 +41,9 @@ void xlate_ifname(struct xt_xlate *xl, const char *nftmeta, const char *ifname, for (i = 0, j = 0; i < ifaclen + 1; i++, j++) { switch (ifname[i]) { case '*': - iface[j++] = '\\'; + /* asterisk is non-special mid-string */ + if (i == ifaclen - 1) + iface[j++] = '\\'; /* fall through */ default: iface[j] = ifname[i]; @@ -83,12 +85,10 @@ int xlate_action(const struct iptables_command_state *cs, bool goto_set, else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0) xt_xlate_add(xl, " return"); else if (cs->target->xlate) { - xt_xlate_add(xl, " "); struct xt_xlate_tg_params params = { .ip = (const void *)&cs->fw, .target = cs->target->t, .numeric = numeric, - .escape_quotes = !cs->restore, }; ret = cs->target->xlate(xl, ¶ms); } @@ -115,17 +115,12 @@ int xlate_matches(const struct iptables_command_state *cs, struct xt_xlate *xl) .ip = (const void *)&cs->fw, .match = matchp->match->m, .numeric = numeric, - .escape_quotes = !cs->restore, }; if (!matchp->match->xlate) return 0; ret = matchp->match->xlate(xl, ¶ms); - - if (strcmp(matchp->match->name, "comment") != 0) - xt_xlate_add(xl, " "); - if (!ret) break; } @@ -136,7 +131,6 @@ bool xlate_find_match(const struct iptables_command_state *cs, const char *p_nam { struct xtables_rule_match *matchp; - /* Skip redundant protocol, eg. ip protocol tcp tcp dport */ for (matchp = cs->matches; matchp; matchp = matchp->next) { if (strcmp(matchp->match->name, p_name) == 0) return true; @@ -144,7 +138,24 @@ bool xlate_find_match(const struct iptables_command_state *cs, const char *p_nam return false; } +bool xlate_find_protomatch(const struct iptables_command_state *cs, + uint16_t proto) +{ + struct protoent *pent; + int i; + + /* Skip redundant protocol, eg. ip protocol tcp tcp dport */ + for (i = 0; xtables_chain_protos[i].name != NULL; i++) { + if (xtables_chain_protos[i].num == proto && + xlate_find_match(cs, xtables_chain_protos[i].name)) + return true; + } + pent = getprotobynumber(proto); + return pent && xlate_find_match(cs, pent->p_name); +} + const char *family2str[] = { + [NFPROTO_ARP] = "arp", [NFPROTO_IPV4] = "ip", [NFPROTO_IPV6] = "ip6", }; @@ -155,6 +166,7 @@ static int nft_rule_xlate_add(struct nft_handle *h, bool append) { struct xt_xlate *xl = xt_xlate_alloc(10240); + const char *tick = cs->restore ? "" : "'"; const char *set; int ret; @@ -165,21 +177,22 @@ static int nft_rule_xlate_add(struct nft_handle *h, set = xt_xlate_set_get(xl); if (set[0]) { - printf("add set %s %s %s\n", family2str[h->family], p->table, - xt_xlate_set_get(xl)); + printf("%sadd set %s %s %s%s\n", + tick, family2str[h->family], p->table, + xt_xlate_set_get(xl), tick); if (!cs->restore && p->command != CMD_NONE) printf("nft "); } - if (append) { - printf("add rule %s %s %s ", - family2str[h->family], p->table, p->chain); - } else { - printf("insert rule %s %s %s ", - family2str[h->family], p->table, p->chain); - } - printf("%s\n", xt_xlate_rule_get(xl)); + printf("%s%s rule %s %s %s ", + tick, + append ? "add" : "insert", + family2str[h->family], p->table, p->chain); + if (!append && p->rulenum > 1) + printf("index %d ", p->rulenum); + + printf("%s%s\n", xt_xlate_rule_get(xl), tick); err_out: xt_xlate_free(xl); @@ -199,6 +212,15 @@ static int xlate(struct nft_handle *h, struct xt_cmd_parse *p, for (i = 0; i < args->s.naddrs; i++) { switch (h->family) { + case NFPROTO_ARP: + cs->arp.arp.src.s_addr = args->s.addr.v4[i].s_addr; + cs->arp.arp.smsk.s_addr = args->s.mask.v4[i].s_addr; + for (j = 0; j < args->d.naddrs; j++) { + cs->arp.arp.tgt.s_addr = args->d.addr.v4[j].s_addr; + cs->arp.arp.tmsk.s_addr = args->d.mask.v4[j].s_addr; + ret = cb(h, p, cs, append); + } + break; case AF_INET: cs->fw.ip.src.s_addr = args->s.addr.v4[i].s_addr; cs->fw.ip.smsk.s_addr = args->s.mask.v4[i].s_addr; @@ -252,7 +274,6 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[], .table = *table, .restore = restore, .line = line, - .xlate = true, .ops = &h->ops->cmd_parse, }; struct iptables_command_state cs = { @@ -341,19 +362,9 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[], exit(1); } - nft_clear_iptables_command_state(&cs); - - if (h->family == AF_INET) { - free(args.s.addr.v4); - free(args.s.mask.v4); - free(args.d.addr.v4); - free(args.d.mask.v4); - } else if (h->family == AF_INET6) { - free(args.s.addr.v6); - free(args.s.mask.v6); - free(args.d.addr.v6); - free(args.d.mask.v6); - } + h->ops->clear_cs(&cs); + + xtables_clear_args(&args); xtables_free_opts(1); return ret; @@ -478,7 +489,24 @@ static int xtables_xlate_main_common(struct nft_handle *h, xtables_globals.program_name = progname; xtables_globals.compat_rev = dummy_compat_rev; - ret = xtables_init_all(&xtables_globals, family); + + switch (family) { + case NFPROTO_IPV4: + ret = xtables_init_all(&xtables_globals, family); + break; + case NFPROTO_IPV6: + ret = xtables_init_all(&xtables_globals, family); + break; + case NFPROTO_ARP: + arptables_globals.program_name = progname; + arptables_globals.compat_rev = dummy_compat_rev; + ret = xtables_init_all(&arptables_globals, family); + break; + default: + ret = -1; + break; + } + if (ret < 0) { fprintf(stderr, "%s/%s Failed to initialize xtables\n", xtables_globals.program_name, @@ -593,6 +621,12 @@ static int xtables_restore_xlate_main(int family, const char *progname, exit(0); } +int xtables_arp_xlate_main(int argc, char *argv[]) +{ + return xtables_xlate_main(NFPROTO_ARP, "arptables-translate", + argc, argv); +} + int xtables_ip4_xlate_main(int argc, char *argv[]) { return xtables_xlate_main(NFPROTO_IPV4, "iptables-translate", |