|
Packit |
7b22a4 |
/*
|
|
Packit |
7b22a4 |
* (C) 2014 by Pablo Neira Ayuso <pablo@netfilter.org>
|
|
Packit |
7b22a4 |
*
|
|
Packit |
7b22a4 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
7b22a4 |
* it under the terms of the GNU General Public License as published
|
|
Packit |
7b22a4 |
* by the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
7b22a4 |
* (at your option) any later version.
|
|
Packit |
7b22a4 |
*/
|
|
Packit |
7b22a4 |
#include "config.h"
|
|
Packit |
7b22a4 |
#include <time.h>
|
|
Packit |
7b22a4 |
#include "xtables-multi.h"
|
|
Packit |
7b22a4 |
#include "nft.h"
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#include <string.h>
|
|
Packit |
7b22a4 |
#include <netdb.h>
|
|
Packit |
7b22a4 |
#include <errno.h>
|
|
Packit |
7b22a4 |
#include <stdbool.h>
|
|
Packit |
7b22a4 |
#include <stdio.h>
|
|
Packit |
7b22a4 |
#include <stdlib.h>
|
|
Packit |
7b22a4 |
#include <ctype.h>
|
|
Packit |
7b22a4 |
#include <stdarg.h>
|
|
Packit |
7b22a4 |
#include <limits.h>
|
|
Packit |
7b22a4 |
#include <unistd.h>
|
|
Packit |
7b22a4 |
#include <iptables.h>
|
|
Packit |
7b22a4 |
#include <xtables.h>
|
|
Packit |
7b22a4 |
#include <libiptc/libxtc.h>
|
|
Packit |
7b22a4 |
#include <fcntl.h>
|
|
Packit |
7b22a4 |
#include <getopt.h>
|
|
Packit |
7b22a4 |
#include "xshared.h"
|
|
Packit |
7b22a4 |
#include "nft-shared.h"
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void xlate_ifname(struct xt_xlate *xl, const char *nftmeta, const char *ifname,
|
|
Packit |
7b22a4 |
bool invert)
|
|
Packit |
7b22a4 |
{
|
|
Packit Service |
aab5b7 |
int ifaclen = strlen(ifname), i, j;
|
|
Packit Service |
aab5b7 |
char iface[IFNAMSIZ * 2];
|
|
Packit |
7b22a4 |
|
|
Packit Service |
6a5833 |
if (ifaclen < 1 || ifaclen >= IFNAMSIZ)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit Service |
aab5b7 |
for (i = 0, j = 0; i < ifaclen + 1; i++, j++) {
|
|
Packit Service |
aab5b7 |
switch (ifname[i]) {
|
|
Packit Service |
aab5b7 |
case '*':
|
|
Packit Service |
aab5b7 |
iface[j++] = '\\';
|
|
Packit Service |
aab5b7 |
/* fall through */
|
|
Packit Service |
aab5b7 |
default:
|
|
Packit Service |
aab5b7 |
iface[j] = ifname[i];
|
|
Packit Service |
aab5b7 |
break;
|
|
Packit Service |
aab5b7 |
}
|
|
Packit Service |
aab5b7 |
}
|
|
Packit Service |
aab5b7 |
|
|
Packit Service |
aab5b7 |
if (ifaclen == 1 && ifname[0] == '+') {
|
|
Packit Service |
aab5b7 |
/* Nftables does not support wildcard only string. Workaround
|
|
Packit Service |
aab5b7 |
* is easy, given that this will match always or never
|
|
Packit Service |
aab5b7 |
* depending on 'invert' value. To match always, simply don't
|
|
Packit Service |
aab5b7 |
* generate an expression. To match never, use an invalid
|
|
Packit Service |
aab5b7 |
* interface name (kernel doesn't accept '/' in names) to match
|
|
Packit Service |
aab5b7 |
* against. */
|
|
Packit Service |
aab5b7 |
if (!invert)
|
|
Packit Service |
aab5b7 |
return;
|
|
Packit Service |
aab5b7 |
strcpy(iface, "INVAL/D");
|
|
Packit Service |
aab5b7 |
invert = false;
|
|
Packit Service |
aab5b7 |
}
|
|
Packit Service |
c907bb |
|
|
Packit Service |
ecc75c |
if (iface[j - 2] == '+')
|
|
Packit Service |
ecc75c |
iface[j - 2] = '*';
|
|
Packit Service |
ecc75c |
|
|
Packit |
7b22a4 |
xt_xlate_add(xl, "%s %s\"%s\" ", nftmeta, invert ? "!= " : "", iface);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int xlate_action(const struct iptables_command_state *cs, bool goto_set,
|
|
Packit |
7b22a4 |
struct xt_xlate *xl)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
int ret = 1, numeric = cs->options & OPT_NUMERIC;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
/* If no target at all, add nothing (default to continue) */
|
|
Packit |
7b22a4 |
if (cs->target != NULL) {
|
|
Packit |
7b22a4 |
/* Standard target? */
|
|
Packit |
7b22a4 |
if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
|
|
Packit |
7b22a4 |
xt_xlate_add(xl, " accept");
|
|
Packit |
7b22a4 |
else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
|
|
Packit |
7b22a4 |
xt_xlate_add(xl, " drop");
|
|
Packit |
7b22a4 |
else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
|
|
Packit |
7b22a4 |
xt_xlate_add(xl, " return");
|
|
Packit |
7b22a4 |
else if (cs->target->xlate) {
|
|
Packit |
7b22a4 |
xt_xlate_add(xl, " ");
|
|
Packit |
7b22a4 |
struct xt_xlate_tg_params params = {
|
|
Packit |
7b22a4 |
.ip = (const void *)&cs->fw,
|
|
Packit |
7b22a4 |
.target = cs->target->t,
|
|
Packit |
7b22a4 |
.numeric = numeric,
|
|
Packit |
7b22a4 |
.escape_quotes = !cs->restore,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
ret = cs->target->xlate(xl, ¶ms);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
else
|
|
Packit |
7b22a4 |
return 0;
|
|
Packit |
7b22a4 |
} else if (strlen(cs->jumpto) > 0) {
|
|
Packit |
7b22a4 |
/* Not standard, then it's a go / jump to chain */
|
|
Packit |
7b22a4 |
if (goto_set)
|
|
Packit |
7b22a4 |
xt_xlate_add(xl, " goto %s", cs->jumpto);
|
|
Packit |
7b22a4 |
else
|
|
Packit |
7b22a4 |
xt_xlate_add(xl, " jump %s", cs->jumpto);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return ret;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int xlate_matches(const struct iptables_command_state *cs, struct xt_xlate *xl)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct xtables_rule_match *matchp;
|
|
Packit |
7b22a4 |
int ret = 1, numeric = cs->options & OPT_NUMERIC;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
for (matchp = cs->matches; matchp; matchp = matchp->next) {
|
|
Packit |
7b22a4 |
struct xt_xlate_mt_params params = {
|
|
Packit |
7b22a4 |
.ip = (const void *)&cs->fw,
|
|
Packit |
7b22a4 |
.match = matchp->match->m,
|
|
Packit |
7b22a4 |
.numeric = numeric,
|
|
Packit |
7b22a4 |
.escape_quotes = !cs->restore,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (!matchp->match->xlate)
|
|
Packit |
7b22a4 |
return 0;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ret = matchp->match->xlate(xl, ¶ms);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (strcmp(matchp->match->name, "comment") != 0)
|
|
Packit |
7b22a4 |
xt_xlate_add(xl, " ");
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (!ret)
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
return ret;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
bool xlate_find_match(const struct iptables_command_state *cs, const char *p_name)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct xtables_rule_match *matchp;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
/* Skip redundant protocol, eg. ip protocol tcp tcp dport */
|
|
Packit |
7b22a4 |
for (matchp = cs->matches; matchp; matchp = matchp->next) {
|
|
Packit |
7b22a4 |
if (strcmp(matchp->match->name, p_name) == 0)
|
|
Packit |
7b22a4 |
return true;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
const char *family2str[] = {
|
|
Packit |
7b22a4 |
[NFPROTO_IPV4] = "ip",
|
|
Packit |
7b22a4 |
[NFPROTO_IPV6] = "ip6",
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int nft_rule_xlate_add(struct nft_handle *h,
|
|
Packit |
7b22a4 |
const struct nft_xt_cmd_parse *p,
|
|
Packit |
7b22a4 |
const struct iptables_command_state *cs,
|
|
Packit |
7b22a4 |
bool append)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct xt_xlate *xl = xt_xlate_alloc(10240);
|
|
Packit |
7b22a4 |
int ret;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (append) {
|
|
Packit |
7b22a4 |
xt_xlate_add(xl, "add rule %s %s %s ",
|
|
Packit |
7b22a4 |
family2str[h->family], p->table, p->chain);
|
|
Packit |
7b22a4 |
} else {
|
|
Packit |
7b22a4 |
xt_xlate_add(xl, "insert rule %s %s %s ",
|
|
Packit |
7b22a4 |
family2str[h->family], p->table, p->chain);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ret = h->ops->xlate(cs, xl);
|
|
Packit |
7b22a4 |
if (ret)
|
|
Packit |
7b22a4 |
printf("%s\n", xt_xlate_get(xl));
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
xt_xlate_free(xl);
|
|
Packit |
7b22a4 |
return ret;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int xlate(struct nft_handle *h, struct nft_xt_cmd_parse *p,
|
|
Packit |
7b22a4 |
struct iptables_command_state *cs,
|
|
Packit |
7b22a4 |
struct xtables_args *args, bool append,
|
|
Packit |
7b22a4 |
int (*cb)(struct nft_handle *h,
|
|
Packit |
7b22a4 |
const struct nft_xt_cmd_parse *p,
|
|
Packit |
7b22a4 |
const struct iptables_command_state *cs,
|
|
Packit |
7b22a4 |
bool append))
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
unsigned int i, j;
|
|
Packit |
7b22a4 |
int ret = 1;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
for (i = 0; i < args->s.naddrs; i++) {
|
|
Packit |
7b22a4 |
switch (h->family) {
|
|
Packit |
7b22a4 |
case AF_INET:
|
|
Packit |
7b22a4 |
cs->fw.ip.src.s_addr = args->s.addr.v4[i].s_addr;
|
|
Packit |
7b22a4 |
cs->fw.ip.smsk.s_addr = args->s.mask.v4[i].s_addr;
|
|
Packit |
7b22a4 |
for (j = 0; j < args->d.naddrs; j++) {
|
|
Packit |
7b22a4 |
cs->fw.ip.dst.s_addr =
|
|
Packit |
7b22a4 |
args->d.addr.v4[j].s_addr;
|
|
Packit |
7b22a4 |
cs->fw.ip.dmsk.s_addr =
|
|
Packit |
7b22a4 |
args->d.mask.v4[j].s_addr;
|
|
Packit |
7b22a4 |
ret = cb(h, p, cs, append);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case AF_INET6:
|
|
Packit |
7b22a4 |
memcpy(&cs->fw6.ipv6.src,
|
|
Packit |
7b22a4 |
&args->s.addr.v6[i], sizeof(struct in6_addr));
|
|
Packit |
7b22a4 |
memcpy(&cs->fw6.ipv6.smsk,
|
|
Packit |
7b22a4 |
&args->s.mask.v6[i], sizeof(struct in6_addr));
|
|
Packit |
7b22a4 |
for (j = 0; j < args->d.naddrs; j++) {
|
|
Packit |
7b22a4 |
memcpy(&cs->fw6.ipv6.dst,
|
|
Packit |
7b22a4 |
&args->d.addr.v6[j],
|
|
Packit |
7b22a4 |
sizeof(struct in6_addr));
|
|
Packit |
7b22a4 |
memcpy(&cs->fw6.ipv6.dmsk,
|
|
Packit |
7b22a4 |
&args->d.mask.v6[j],
|
|
Packit |
7b22a4 |
sizeof(struct in6_addr));
|
|
Packit |
7b22a4 |
ret = cb(h, p, cs, append);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if (!cs->restore && i < args->s.naddrs - 1)
|
|
Packit |
7b22a4 |
printf("nft ");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return ret;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void print_ipt_cmd(int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
int i;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("# ");
|
|
Packit |
7b22a4 |
for (i = 1; i < argc; i++)
|
|
Packit |
7b22a4 |
printf("%s ", argv[i]);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("\n");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
|
|
Packit |
7b22a4 |
char **table, bool restore)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
int ret = 0;
|
|
Packit |
7b22a4 |
struct nft_xt_cmd_parse p = {
|
|
Packit |
7b22a4 |
.table = *table,
|
|
Packit |
7b22a4 |
.restore = restore,
|
|
Packit |
7b22a4 |
.xlate = true,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
struct iptables_command_state cs;
|
|
Packit |
7b22a4 |
struct xtables_args args = {
|
|
Packit |
7b22a4 |
.family = h->family,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
do_parse(h, argc, argv, &p, &cs, &args);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
cs.restore = restore;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (!restore)
|
|
Packit |
7b22a4 |
printf("nft ");
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch (p.command) {
|
|
Packit |
7b22a4 |
case CMD_APPEND:
|
|
Packit |
7b22a4 |
ret = 1;
|
|
Packit |
7b22a4 |
if (!xlate(h, &p, &cs, &args, true, nft_rule_xlate_add))
|
|
Packit |
7b22a4 |
print_ipt_cmd(argc, argv);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_DELETE:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_DELETE_NUM:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_CHECK:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_REPLACE:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_INSERT:
|
|
Packit |
7b22a4 |
ret = 1;
|
|
Packit |
7b22a4 |
if (!xlate(h, &p, &cs, &args, false, nft_rule_xlate_add))
|
|
Packit |
7b22a4 |
print_ipt_cmd(argc, argv);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_FLUSH:
|
|
Packit |
7b22a4 |
if (p.chain) {
|
|
Packit |
7b22a4 |
printf("flush chain %s %s %s\n",
|
|
Packit |
7b22a4 |
family2str[h->family], p.table, p.chain);
|
|
Packit |
7b22a4 |
} else {
|
|
Packit |
7b22a4 |
printf("flush table %s %s\n",
|
|
Packit |
7b22a4 |
family2str[h->family], p.table);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
ret = 1;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_ZERO:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_ZERO_NUM:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_LIST:
|
|
Packit |
7b22a4 |
case CMD_LIST|CMD_ZERO:
|
|
Packit |
7b22a4 |
case CMD_LIST|CMD_ZERO_NUM:
|
|
Packit |
7b22a4 |
printf("list table %s %s\n",
|
|
Packit |
7b22a4 |
family2str[h->family], p.table);
|
|
Packit |
7b22a4 |
ret = 1;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_LIST_RULES:
|
|
Packit |
7b22a4 |
case CMD_LIST_RULES|CMD_ZERO:
|
|
Packit |
7b22a4 |
case CMD_LIST_RULES|CMD_ZERO_NUM:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_NEW_CHAIN:
|
|
Packit |
7b22a4 |
printf("add chain %s %s %s\n",
|
|
Packit |
7b22a4 |
family2str[h->family], p.table, p.chain);
|
|
Packit |
7b22a4 |
ret = 1;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_DELETE_CHAIN:
|
|
Packit |
7b22a4 |
printf("delete chain %s %s %s\n",
|
|
Packit |
7b22a4 |
family2str[h->family], p.table, p.chain);
|
|
Packit |
7b22a4 |
ret = 1;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_RENAME_CHAIN:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case CMD_SET_POLICY:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
/* We should never reach this... */
|
|
Packit |
7b22a4 |
printf("Unsupported command?\n");
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
xtables_rule_matches_free(&cs.matches);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (h->family == AF_INET) {
|
|
Packit |
7b22a4 |
free(args.s.addr.v4);
|
|
Packit |
7b22a4 |
free(args.s.mask.v4);
|
|
Packit |
7b22a4 |
free(args.d.addr.v4);
|
|
Packit |
7b22a4 |
free(args.d.mask.v4);
|
|
Packit |
7b22a4 |
} else if (h->family == AF_INET6) {
|
|
Packit |
7b22a4 |
free(args.s.addr.v6);
|
|
Packit |
7b22a4 |
free(args.s.mask.v6);
|
|
Packit |
7b22a4 |
free(args.d.addr.v6);
|
|
Packit |
7b22a4 |
free(args.d.mask.v6);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
xtables_free_opts(1);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return ret;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void print_usage(const char *name, const char *version)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
fprintf(stderr, "%s %s "
|
|
Packit |
7b22a4 |
"(c) 2014 by Pablo Neira Ayuso <pablo@netfilter.org>\n"
|
|
Packit |
7b22a4 |
"Usage: %s [-h] [-f]\n"
|
|
Packit |
7b22a4 |
" [ --help ]\n"
|
|
Packit |
7b22a4 |
" [ --file=<FILE> ]\n", name, version, name);
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static const struct option options[] = {
|
|
Packit |
7b22a4 |
{ .name = "help", .has_arg = false, .val = 'h' },
|
|
Packit |
7b22a4 |
{ .name = "file", .has_arg = true, .val = 'f' },
|
|
Packit |
7b22a4 |
{ .name = "version", .has_arg = false, .val = 'V' },
|
|
Packit |
7b22a4 |
{ NULL },
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int xlate_chain_user_restore(struct nft_handle *h, const char *chain,
|
|
Packit |
7b22a4 |
const char *table)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
printf("add chain %s %s %s\n", family2str[h->family], table, chain);
|
|
Packit |
7b22a4 |
return 0;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int commit(struct nft_handle *h)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
return 1;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void xlate_table_new(struct nft_handle *h, const char *table)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
printf("add table %s %s\n", family2str[h->family], table);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int get_hook_prio(const char *table, const char *chain)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
int prio = 0;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (strcmp("nat", table) == 0) {
|
|
Packit |
7b22a4 |
if (strcmp(chain, "PREROUTING") == 0)
|
|
Packit |
7b22a4 |
prio = NF_IP_PRI_NAT_DST;
|
|
Packit |
7b22a4 |
if (strcmp(chain, "INPUT") == 0)
|
|
Packit |
7b22a4 |
prio = NF_IP_PRI_NAT_SRC;
|
|
Packit |
7b22a4 |
if (strcmp(chain, "OUTPUT") == 0)
|
|
Packit |
7b22a4 |
prio = NF_IP_PRI_NAT_DST;
|
|
Packit |
7b22a4 |
if (strcmp(chain, "POSTROUTING") == 0)
|
|
Packit |
7b22a4 |
prio = NF_IP_PRI_NAT_SRC;
|
|
Packit |
7b22a4 |
} else if (strcmp("mangle", table) == 0) {
|
|
Packit |
7b22a4 |
prio = NF_IP_PRI_MANGLE;
|
|
Packit |
7b22a4 |
} else if (strcmp("raw", table) == 0) {
|
|
Packit |
7b22a4 |
prio = NF_IP_PRI_RAW;
|
|
Packit |
7b22a4 |
} else if (strcmp(chain, "security") == 0) {
|
|
Packit |
7b22a4 |
prio = NF_IP_PRI_SECURITY;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return prio;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int xlate_chain_set(struct nft_handle *h, const char *table,
|
|
Packit |
7b22a4 |
const char *chain, const char *policy,
|
|
Packit |
7b22a4 |
const struct xt_counters *counters)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
const char *type = "filter";
|
|
Packit |
7b22a4 |
int prio;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (strcmp(table, "nat") == 0)
|
|
Packit |
7b22a4 |
type = "nat";
|
|
Packit |
7b22a4 |
else if (strcmp(table, "mangle") == 0 && strcmp(chain, "OUTPUT") == 0)
|
|
Packit |
7b22a4 |
type = "route";
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("add chain %s %s %s { type %s ",
|
|
Packit |
7b22a4 |
family2str[h->family], table, chain, type);
|
|
Packit |
7b22a4 |
prio = get_hook_prio(table, chain);
|
|
Packit |
7b22a4 |
if (strcmp(chain, "PREROUTING") == 0)
|
|
Packit |
7b22a4 |
printf("hook prerouting priority %d; ", prio);
|
|
Packit |
7b22a4 |
else if (strcmp(chain, "INPUT") == 0)
|
|
Packit |
7b22a4 |
printf("hook input priority %d; ", prio);
|
|
Packit |
7b22a4 |
else if (strcmp(chain, "FORWARD") == 0)
|
|
Packit |
7b22a4 |
printf("hook forward priority %d; ", prio);
|
|
Packit |
7b22a4 |
else if (strcmp(chain, "OUTPUT") == 0)
|
|
Packit |
7b22a4 |
printf("hook output priority %d; ", prio);
|
|
Packit |
7b22a4 |
else if (strcmp(chain, "POSTROUTING") == 0)
|
|
Packit |
7b22a4 |
printf("hook postrouting priority %d; ", prio);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (strcmp(policy, "ACCEPT") == 0)
|
|
Packit |
7b22a4 |
printf("policy accept; ");
|
|
Packit |
7b22a4 |
else if (strcmp(policy, "DROP") == 0)
|
|
Packit |
7b22a4 |
printf("policy drop; ");
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("}\n");
|
|
Packit |
7b22a4 |
return 1;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int dummy_compat_rev(const char *name, uint8_t rev, int opt)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
/* Avoid querying the kernel - it's not needed when just translating
|
|
Packit |
7b22a4 |
* rules and not even possible when running as unprivileged user.
|
|
Packit |
7b22a4 |
*/
|
|
Packit |
7b22a4 |
return 1;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static const struct nft_xt_restore_cb cb_xlate = {
|
|
Packit |
7b22a4 |
.table_new = xlate_table_new,
|
|
Packit |
7b22a4 |
.chain_set = xlate_chain_set,
|
|
Packit |
7b22a4 |
.chain_restore = xlate_chain_user_restore,
|
|
Packit |
7b22a4 |
.do_command = do_command_xlate,
|
|
Packit |
7b22a4 |
.commit = commit,
|
|
Packit |
7b22a4 |
.abort = commit,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int xtables_xlate_main_common(struct nft_handle *h,
|
|
Packit |
7b22a4 |
int family,
|
|
Packit |
7b22a4 |
const char *progname)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
const struct builtin_table *tables;
|
|
Packit |
7b22a4 |
int ret;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
xtables_globals.program_name = progname;
|
|
Packit |
7b22a4 |
xtables_globals.compat_rev = dummy_compat_rev;
|
|
Packit |
7b22a4 |
ret = xtables_init_all(&xtables_globals, family);
|
|
Packit |
7b22a4 |
if (ret < 0) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "%s/%s Failed to initialize xtables\n",
|
|
Packit |
7b22a4 |
xtables_globals.program_name,
|
|
Packit |
7b22a4 |
xtables_globals.program_version);
|
|
Packit |
7b22a4 |
return 1;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
switch (family) {
|
|
Packit |
7b22a4 |
case NFPROTO_IPV4:
|
|
Packit |
7b22a4 |
case NFPROTO_IPV6: /* fallthrough: same table */
|
|
Packit |
7b22a4 |
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
|
|
Packit |
7b22a4 |
init_extensions();
|
|
Packit |
7b22a4 |
init_extensions4();
|
|
Packit |
7b22a4 |
#endif
|
|
Packit |
7b22a4 |
tables = xtables_ipv4;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFPROTO_ARP:
|
|
Packit |
7b22a4 |
tables = xtables_arp;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFPROTO_BRIDGE:
|
|
Packit |
7b22a4 |
tables = xtables_bridge;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
fprintf(stderr, "Unknown family %d\n", family);
|
|
Packit |
7b22a4 |
return 1;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit Service |
635b90 |
if (nft_init(h, tables) < 0) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
|
|
Packit |
7b22a4 |
xtables_globals.program_name,
|
|
Packit |
7b22a4 |
xtables_globals.program_version,
|
|
Packit |
7b22a4 |
strerror(errno));
|
|
Packit |
7b22a4 |
return 1;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return 0;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int xtables_xlate_main(int family, const char *progname, int argc,
|
|
Packit |
7b22a4 |
char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
int ret;
|
|
Packit |
7b22a4 |
char *table = "filter";
|
|
Packit |
7b22a4 |
struct nft_handle h = {
|
|
Packit |
7b22a4 |
.family = family,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ret = xtables_xlate_main_common(&h, family, progname);
|
|
Packit |
7b22a4 |
if (ret < 0)
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ret = do_command_xlate(&h, argc, argv, &table, false);
|
|
Packit |
7b22a4 |
if (!ret)
|
|
Packit |
7b22a4 |
fprintf(stderr, "Translation not implemented\n");
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nft_fini(&h);
|
|
Packit |
7b22a4 |
exit(!ret);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int xtables_restore_xlate_main(int family, const char *progname,
|
|
Packit |
7b22a4 |
int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
int ret;
|
|
Packit |
7b22a4 |
struct nft_handle h = {
|
|
Packit |
7b22a4 |
.family = family,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
const char *file = NULL;
|
|
Packit |
7b22a4 |
struct nft_xt_restore_parse p = {
|
|
Packit |
7b22a4 |
.cb = &cb_xlate,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
time_t now = time(NULL);
|
|
Packit |
7b22a4 |
int c;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ret = xtables_xlate_main_common(&h, family, progname);
|
|
Packit |
7b22a4 |
if (ret < 0)
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
opterr = 0;
|
|
Packit |
7b22a4 |
while ((c = getopt_long(argc, argv, "hf:V", options, NULL)) != -1) {
|
|
Packit |
7b22a4 |
switch (c) {
|
|
Packit |
7b22a4 |
case 'h':
|
|
Packit |
7b22a4 |
print_usage(argv[0], PACKAGE_VERSION);
|
|
Packit |
7b22a4 |
exit(0);
|
|
Packit |
7b22a4 |
case 'f':
|
|
Packit |
7b22a4 |
file = optarg;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case 'V':
|
|
Packit |
7b22a4 |
printf("%s v%s\n", argv[0], PACKAGE_VERSION);
|
|
Packit |
7b22a4 |
exit(0);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (file == NULL) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "ERROR: missing file name\n");
|
|
Packit |
7b22a4 |
print_usage(argv[0], PACKAGE_VERSION);
|
|
Packit |
7b22a4 |
exit(0);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
p.in = fopen(file, "r");
|
|
Packit |
7b22a4 |
if (p.in == NULL) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "Cannot open file %s\n", file);
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("# Translated by %s v%s on %s",
|
|
Packit |
7b22a4 |
argv[0], PACKAGE_VERSION, ctime(&now));
|
|
Packit |
7b22a4 |
xtables_restore_parse(&h, &p);
|
|
Packit |
7b22a4 |
printf("# Completed on %s", ctime(&now));
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nft_fini(&h);
|
|
Packit |
7b22a4 |
fclose(p.in);
|
|
Packit |
7b22a4 |
exit(0);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int xtables_ip4_xlate_main(int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
return xtables_xlate_main(NFPROTO_IPV4, "iptables-translate",
|
|
Packit |
7b22a4 |
argc, argv);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int xtables_ip6_xlate_main(int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
return xtables_xlate_main(NFPROTO_IPV6, "ip6tables-translate",
|
|
Packit |
7b22a4 |
argc, argv);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int xtables_ip4_xlate_restore_main(int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
return xtables_restore_xlate_main(NFPROTO_IPV4,
|
|
Packit |
7b22a4 |
"iptables-translate-restore",
|
|
Packit |
7b22a4 |
argc, argv);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int xtables_ip6_xlate_restore_main(int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
return xtables_restore_xlate_main(NFPROTO_IPV6,
|
|
Packit |
7b22a4 |
"ip6tables-translate-restore",
|
|
Packit |
7b22a4 |
argc, argv);
|
|
Packit |
7b22a4 |
}
|