Commit 9caffe92 authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

New upstream version 1.8.6

parent eb1d7c5f
...@@ -225,7 +225,8 @@ struct nft_xt_restore_cb { ...@@ -225,7 +225,8 @@ struct nft_xt_restore_cb {
int (*chain_restore)(struct nft_handle *h, const char *chain, int (*chain_restore)(struct nft_handle *h, const char *chain,
const char *table); const char *table);
int (*table_flush)(struct nft_handle *h, const char *table); int (*table_flush)(struct nft_handle *h, const char *table,
bool verbose);
int (*do_command)(struct nft_handle *h, int argc, char *argv[], int (*do_command)(struct nft_handle *h, int argc, char *argv[],
char **table, bool restore); char **table, bool restore);
......
...@@ -265,7 +265,6 @@ struct obj_update { ...@@ -265,7 +265,6 @@ struct obj_update {
struct list_head head; struct list_head head;
enum obj_update_type type:8; enum obj_update_type type:8;
uint8_t skip:1; uint8_t skip:1;
uint8_t implicit:1;
unsigned int seq; unsigned int seq;
union { union {
struct nftnl_table *table; struct nftnl_table *table;
...@@ -350,7 +349,6 @@ static int mnl_append_error(const struct nft_handle *h, ...@@ -350,7 +349,6 @@ static int mnl_append_error(const struct nft_handle *h,
case NFT_COMPAT_RULE_SAVE: case NFT_COMPAT_RULE_SAVE:
case NFT_COMPAT_RULE_ZERO: case NFT_COMPAT_RULE_ZERO:
case NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE: case NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE:
case NFT_COMPAT_TABLE_NEW:
assert(0); assert(0);
break; break;
} }
...@@ -389,10 +387,11 @@ batch_set_add(struct nft_handle *h, enum obj_update_type type, ...@@ -389,10 +387,11 @@ batch_set_add(struct nft_handle *h, enum obj_update_type type,
return batch_add(h, type, s); return batch_add(h, type, s);
} }
static int batch_chain_add(struct nft_handle *h, enum obj_update_type type, static struct obj_update *
batch_chain_add(struct nft_handle *h, enum obj_update_type type,
struct nftnl_chain *c) struct nftnl_chain *c)
{ {
return batch_add(h, type, c) ? 0 : -1; return batch_add(h, type, c);
} }
static struct obj_update * static struct obj_update *
...@@ -645,19 +644,13 @@ const struct builtin_table xtables_bridge[NFT_TABLE_MAX] = { ...@@ -645,19 +644,13 @@ const struct builtin_table xtables_bridge[NFT_TABLE_MAX] = {
}, },
}; };
static bool nft_table_initialized(const struct nft_handle *h,
enum nft_table_type type)
{
return h->cache->table[type].initialized;
}
static int nft_table_builtin_add(struct nft_handle *h, static int nft_table_builtin_add(struct nft_handle *h,
const struct builtin_table *_t) const struct builtin_table *_t)
{ {
struct nftnl_table *t; struct nftnl_table *t;
int ret; int ret;
if (nft_table_initialized(h, _t->type)) if (h->cache->table[_t->type].exists)
return 0; return 0;
t = nftnl_table_alloc(); t = nftnl_table_alloc();
...@@ -685,7 +678,9 @@ nft_chain_builtin_alloc(const struct builtin_table *table, ...@@ -685,7 +678,9 @@ nft_chain_builtin_alloc(const struct builtin_table *table,
nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain->name); nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain->name);
nftnl_chain_set_u32(c, NFTNL_CHAIN_HOOKNUM, chain->hook); nftnl_chain_set_u32(c, NFTNL_CHAIN_HOOKNUM, chain->hook);
nftnl_chain_set_u32(c, NFTNL_CHAIN_PRIO, chain->prio); nftnl_chain_set_u32(c, NFTNL_CHAIN_PRIO, chain->prio);
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, policy); if (policy >= 0)
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, policy);
nftnl_chain_set_str(c, NFTNL_CHAIN_TYPE, chain->type); nftnl_chain_set_str(c, NFTNL_CHAIN_TYPE, chain->type);
return c; return c;
...@@ -743,22 +738,17 @@ nft_chain_builtin_find(const struct builtin_table *t, const char *chain) ...@@ -743,22 +738,17 @@ nft_chain_builtin_find(const struct builtin_table *t, const char *chain)
return found ? &t->chains[i] : NULL; return found ? &t->chains[i] : NULL;
} }
static struct nftnl_chain *
nft_chain_find(struct nft_handle *h, const char *table, const char *chain);
static void nft_chain_builtin_init(struct nft_handle *h, static void nft_chain_builtin_init(struct nft_handle *h,
const struct builtin_table *table) const struct builtin_table *table)
{ {
struct nftnl_chain_list *list;
struct nftnl_chain *c;
int i; int i;
/* Initialize built-in chains if they don't exist yet */ /* Initialize built-in chains if they don't exist yet */
for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) { for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) {
list = nft_chain_list_get(h, table->name, if (nft_chain_find(h, table->name, table->chains[i].name))
table->chains[i].name);
if (!list)
continue;
c = nftnl_chain_list_lookup_byname(list, table->chains[i].name);
if (c != NULL)
continue; continue;
nft_chain_builtin_add(h, table, &table->chains[i]); nft_chain_builtin_add(h, table, &table->chains[i]);
...@@ -776,9 +766,6 @@ static int nft_xt_builtin_init(struct nft_handle *h, const char *table) ...@@ -776,9 +766,6 @@ static int nft_xt_builtin_init(struct nft_handle *h, const char *table)
if (t == NULL) if (t == NULL)
return -1; return -1;
if (nft_table_initialized(h, t->type))
return 0;
if (nft_table_builtin_add(h, t) < 0) if (nft_table_builtin_add(h, t) < 0)
return -1; return -1;
...@@ -787,8 +774,6 @@ static int nft_xt_builtin_init(struct nft_handle *h, const char *table) ...@@ -787,8 +774,6 @@ static int nft_xt_builtin_init(struct nft_handle *h, const char *table)
nft_chain_builtin_init(h, t); nft_chain_builtin_init(h, t);
h->cache->table[t->type].initialized = true;
return 0; return 0;
} }
...@@ -892,7 +877,7 @@ static struct nftnl_chain *nft_chain_new(struct nft_handle *h, ...@@ -892,7 +877,7 @@ static struct nftnl_chain *nft_chain_new(struct nft_handle *h,
} }
/* if this built-in table does not exists, create it */ /* if this built-in table does not exists, create it */
nft_table_builtin_add(h, _t); nft_xt_builtin_init(h, table);
_c = nft_chain_builtin_find(_t, chain); _c = nft_chain_builtin_find(_t, chain);
if (_c != NULL) { if (_c != NULL) {
...@@ -920,7 +905,6 @@ int nft_chain_set(struct nft_handle *h, const char *table, ...@@ -920,7 +905,6 @@ int nft_chain_set(struct nft_handle *h, const char *table,
const struct xt_counters *counters) const struct xt_counters *counters)
{ {
struct nftnl_chain *c = NULL; struct nftnl_chain *c = NULL;
int ret;
nft_fn = nft_chain_set; nft_fn = nft_chain_set;
...@@ -928,16 +912,19 @@ int nft_chain_set(struct nft_handle *h, const char *table, ...@@ -928,16 +912,19 @@ int nft_chain_set(struct nft_handle *h, const char *table,
c = nft_chain_new(h, table, chain, NF_DROP, counters); c = nft_chain_new(h, table, chain, NF_DROP, counters);
else if (strcmp(policy, "ACCEPT") == 0) else if (strcmp(policy, "ACCEPT") == 0)
c = nft_chain_new(h, table, chain, NF_ACCEPT, counters); c = nft_chain_new(h, table, chain, NF_ACCEPT, counters);
else if (strcmp(policy, "-") == 0)
c = nft_chain_new(h, table, chain, -1, counters);
else else
errno = EINVAL; errno = EINVAL;
if (c == NULL) if (c == NULL)
return 0; return 0;
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_UPDATE, c); if (!batch_chain_add(h, NFT_COMPAT_CHAIN_UPDATE, c))
return 0;
/* the core expects 1 for success and 0 for error */ /* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0; return 1;
} }
static int __add_match(struct nftnl_expr *e, struct xt_entry_match *m) static int __add_match(struct nftnl_expr *e, struct xt_entry_match *m)
...@@ -1400,9 +1387,6 @@ err: ...@@ -1400,9 +1387,6 @@ err:
return NULL; return NULL;
} }
static struct nftnl_chain *
nft_chain_find(struct nft_handle *h, const char *table, const char *chain);
int int
nft_rule_append(struct nft_handle *h, const char *chain, const char *table, nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
struct nftnl_rule *r, struct nftnl_rule *ref, bool verbose) struct nftnl_rule *r, struct nftnl_rule *ref, bool verbose)
...@@ -1559,51 +1543,33 @@ static const char *policy_name[NF_ACCEPT+1] = { ...@@ -1559,51 +1543,33 @@ static const char *policy_name[NF_ACCEPT+1] = {
[NF_ACCEPT] = "ACCEPT", [NF_ACCEPT] = "ACCEPT",
}; };
int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list) int nft_chain_save(struct nftnl_chain *c, void *data)
{ {
struct nft_family_ops *ops = h->ops; struct nft_handle *h = data;
struct nftnl_chain_list_iter *iter; const char *policy = NULL;
struct nftnl_chain *c;
iter = nftnl_chain_list_iter_create(list);
if (iter == NULL)
return 0;
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
const char *policy = NULL;
if (nft_chain_builtin(c)) {
uint32_t pol = NF_ACCEPT;
if (nftnl_chain_get(c, NFTNL_CHAIN_POLICY))
pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
policy = policy_name[pol];
} else if (h->family == NFPROTO_BRIDGE) {
if (nftnl_chain_is_set(c, NFTNL_CHAIN_POLICY)) {
uint32_t pol;
pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
policy = policy_name[pol];
} else {
policy = "RETURN";
}
}
if (ops->save_chain)
ops->save_chain(c, policy);
c = nftnl_chain_list_iter_next(iter); if (nftnl_chain_is_set(c, NFTNL_CHAIN_POLICY)) {
policy = policy_name[nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY)];
} else if (nft_chain_builtin(c)) {
policy = "ACCEPT";
} else if (h->family == NFPROTO_BRIDGE) {
policy = "RETURN";
} }
nftnl_chain_list_iter_destroy(iter); if (h->ops->save_chain)
h->ops->save_chain(c, policy);
return 1; return 0;
} }
static int nft_chain_save_rules(struct nft_handle *h, struct nft_rule_save_data {
struct nftnl_chain *c, unsigned int format) struct nft_handle *h;
unsigned int format;
};
static int nft_rule_save_cb(struct nftnl_chain *c, void *data)
{ {
struct nft_rule_save_data *d = data;
struct nftnl_rule_iter *iter; struct nftnl_rule_iter *iter;
struct nftnl_rule *r; struct nftnl_rule *r;
...@@ -1613,7 +1579,7 @@ static int nft_chain_save_rules(struct nft_handle *h, ...@@ -1613,7 +1579,7 @@ static int nft_chain_save_rules(struct nft_handle *h,
r = nftnl_rule_iter_next(iter); r = nftnl_rule_iter_next(iter);
while (r != NULL) { while (r != NULL) {
nft_rule_print_save(h, r, NFT_RULE_APPEND, format); nft_rule_print_save(d->h, r, NFT_RULE_APPEND, d->format);
r = nftnl_rule_iter_next(iter); r = nftnl_rule_iter_next(iter);
} }
...@@ -1623,29 +1589,18 @@ static int nft_chain_save_rules(struct nft_handle *h, ...@@ -1623,29 +1589,18 @@ static int nft_chain_save_rules(struct nft_handle *h,
int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format) int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
{ {
struct nftnl_chain_list_iter *iter; struct nft_rule_save_data d = {
.h = h,
.format = format,
};
struct nftnl_chain_list *list; struct nftnl_chain_list *list;
struct nftnl_chain *c; int ret;
int ret = 0;
list = nft_chain_list_get(h, table, NULL); list = nft_chain_list_get(h, table, NULL);
if (!list) if (!list)
return 0; return 0;
iter = nftnl_chain_list_iter_create(list); ret = nftnl_chain_list_foreach(list, nft_rule_save_cb, &d);
if (!iter)
return 0;
c = nftnl_chain_list_iter_next(iter);
while (c) {
ret = nft_chain_save_rules(h, c, format);
if (ret != 0)
break;
c = nftnl_chain_list_iter_next(iter);
}
nftnl_chain_list_iter_destroy(iter);
/* the core expects 1 for success and 0 for error */ /* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0; return ret == 0 ? 1 : 0;
...@@ -1667,7 +1622,7 @@ struct nftnl_set *nft_set_batch_lookup_byid(struct nft_handle *h, ...@@ -1667,7 +1622,7 @@ struct nftnl_set *nft_set_batch_lookup_byid(struct nft_handle *h,
static void static void
__nft_rule_flush(struct nft_handle *h, const char *table, __nft_rule_flush(struct nft_handle *h, const char *table,
const char *chain, bool verbose, bool implicit) const char *chain, bool verbose, bool skip)
{ {
struct obj_update *obj; struct obj_update *obj;
struct nftnl_rule *r; struct nftnl_rule *r;
...@@ -1689,31 +1644,47 @@ __nft_rule_flush(struct nft_handle *h, const char *table, ...@@ -1689,31 +1644,47 @@ __nft_rule_flush(struct nft_handle *h, const char *table,
return; return;
} }
obj->implicit = implicit; obj->skip = skip;
}
struct nft_rule_flush_data {
struct nft_handle *h;
const char *table;
bool verbose;
};
static int nft_rule_flush_cb(struct nftnl_chain *c, void *data)
{
const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
struct nft_rule_flush_data *d = data;
batch_chain_flush(d->h, d->table, chain);
__nft_rule_flush(d->h, d->table, chain, d->verbose, false);
flush_rule_cache(d->h, d->table, c);
return 0;
} }
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
bool verbose) bool verbose)
{ {
struct nftnl_chain_list_iter *iter; struct nft_rule_flush_data d = {
.h = h,
.table = table,
.verbose = verbose,
};
struct nftnl_chain_list *list; struct nftnl_chain_list *list;
struct nftnl_chain *c = NULL; struct nftnl_chain *c = NULL;
int ret = 0; int ret = 0;
nft_xt_builtin_init(h, table);
nft_fn = nft_rule_flush; nft_fn = nft_rule_flush;
if (chain || verbose) { if (chain || verbose)
list = nft_chain_list_get(h, table, chain); nft_xt_builtin_init(h, table);
if (list == NULL) { else if (!nft_table_find(h, table))
ret = 1; return 1;
goto err;
}
}
if (chain) { if (chain) {
c = nftnl_chain_list_lookup_byname(list, chain); c = nft_chain_find(h, table, chain);
if (!c) { if (!c) {
errno = ENOENT; errno = ENOENT;
return 0; return 0;
...@@ -1727,22 +1698,13 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, ...@@ -1727,22 +1698,13 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
return 1; return 1;
} }
iter = nftnl_chain_list_iter_create(list); list = nft_chain_list_get(h, table, chain);
if (iter == NULL) { if (list == NULL) {
ret = 1; ret = 1;
goto err; goto err;
} }
c = nftnl_chain_list_iter_next(iter); ret = nftnl_chain_list_foreach(list, nft_rule_flush_cb, &d);
while (c != NULL) {
chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
batch_chain_flush(h, table, chain);
__nft_rule_flush(h, table, chain, verbose, false);
flush_rule_cache(h, table, c);
c = nftnl_chain_list_iter_next(iter);
}
nftnl_chain_list_iter_destroy(iter);
err: err:
/* the core expects 1 for success and 0 for error */ /* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0; return ret == 0 ? 1 : 0;
...@@ -1752,7 +1714,6 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl ...@@ -1752,7 +1714,6 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
{ {
struct nftnl_chain_list *list; struct nftnl_chain_list *list;
struct nftnl_chain *c; struct nftnl_chain *c;
int ret;
nft_fn = nft_chain_user_add; nft_fn = nft_chain_user_add;
...@@ -1772,31 +1733,28 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl ...@@ -1772,31 +1733,28 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
if (h->family == NFPROTO_BRIDGE) if (h->family == NFPROTO_BRIDGE)
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT); nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c); if (!batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c))
return 0;
list = nft_chain_list_get(h, table, chain); list = nft_chain_list_get(h, table, chain);
if (list) if (list)
nftnl_chain_list_add(c, list); nftnl_chain_list_add(c, list);
/* the core expects 1 for success and 0 for error */ /* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0; return 1;
} }
int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table) int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table)
{ {
struct nftnl_chain_list *list; struct nftnl_chain_list *list;
struct obj_update *obj;
struct nftnl_chain *c; struct nftnl_chain *c;
bool created = false; bool created = false;
int ret;
nft_xt_builtin_init(h, table);
c = nft_chain_find(h, table, chain); c = nft_chain_find(h, table, chain);
if (c) { if (!c) {
/* Apparently -n still flushes existing user defined
* chains that are redefined.
*/
if (h->noflush)
__nft_rule_flush(h, table, chain, false, true);
} else {
c = nftnl_chain_alloc(); c = nftnl_chain_alloc();
if (!c) if (!c)
return 0; return 0;
...@@ -1804,22 +1762,29 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table ...@@ -1804,22 +1762,29 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table
nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table); nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table);
nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain); nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain);
created = true; created = true;
}
if (h->family == NFPROTO_BRIDGE) list = nft_chain_list_get(h, table, chain);
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT); if (list)
nftnl_chain_list_add(c, list);
} else {
/* If the chain should vanish meanwhile, kernel genid changes
* and the transaction is refreshed enabling the chain add
* object. With the handle still set, kernel interprets it as a
* chain replace job and errors since it is not found anymore.
*/
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
}
if (!created) __nft_rule_flush(h, table, chain, false, created);
return 1;
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c); obj = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
if (!obj)
return 0;
list = nft_chain_list_get(h, table, chain); obj->skip = !created;
if (list)
nftnl_chain_list_add(c, list);
/* the core expects 1 for success and 0 for error */ /* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0; return 1;
} }
/* From linux/netlink.h */ /* From linux/netlink.h */
...@@ -1837,7 +1802,6 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data) ...@@ -1837,7 +1802,6 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data)
{ {
struct chain_user_del_data *d = data; struct chain_user_del_data *d = data;
struct nft_handle *h = d->handle; struct nft_handle *h = d->handle;
int ret;
/* don't delete built-in chain */ /* don't delete built-in chain */
if (nft_chain_builtin(c)) if (nft_chain_builtin(c))
...@@ -1849,8 +1813,7 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data) ...@@ -1849,8 +1813,7 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data)
/* XXX This triggers a fast lookup from the kernel. */ /* XXX This triggers a fast lookup from the kernel. */
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE); nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c); if (!batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c))
if (ret)
return -1; return -1;
nftnl_chain_list_del(c); nftnl_chain_list_del(c);
...@@ -1925,7 +1888,6 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain, ...@@ -1925,7 +1888,6 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
{ {
struct nftnl_chain *c; struct nftnl_chain *c;
uint64_t handle; uint64_t handle;
int ret;
nft_fn = nft_chain_user_rename; nft_fn = nft_chain_user_rename;
...@@ -1934,8 +1896,6 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain, ...@@ -1934,8 +1896,6 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
return 0; return 0;
} }
nft_xt_builtin_init(h, table);
/* Config load changed errno. Ensure genuine info for our callers. */ /* Config load changed errno. Ensure genuine info for our callers. */
errno = 0; errno = 0;
...@@ -1956,73 +1916,37 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain, ...@@ -1956,73 +1916,37 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, newname); nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, newname);
nftnl_chain_set_u64(c, NFTNL_CHAIN_HANDLE, handle); nftnl_chain_set_u64(c, NFTNL_CHAIN_HANDLE, handle);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_RENAME, c); if (!batch_chain_add(h, NFT_COMPAT_CHAIN_RENAME, c))
return 0;
/* the core expects 1 for success and 0 for error */ /* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0; return 1;
} }
bool nft_table_find(struct nft_handle *h, const char *tablename) bool nft_table_find(struct nft_handle *h, const char *tablename)
{ {
struct nftnl_table_list_iter *iter; const struct builtin_table *t;
struct nftnl_table_list *list;
struct nftnl_table *t;
bool ret = false;
list = nftnl_table_list_get(h);
if (list == NULL)
goto err;
iter = nftnl_table_list_iter_create(list);
if (iter == NULL)
goto err;
t = nftnl_table_list_iter_next(iter);
while (t != NULL) {
const char *this_tablename =
nftnl_table_get(t, NFTNL_TABLE_NAME);
if (strcmp(tablename, this_tablename) == 0) {
ret = true;
break;
}
t = nftnl_table_list_iter_next(iter);
}
nftnl_table_list_iter_destroy(iter);
err: t = nft_table_builtin_find(h, tablename);
return ret; return t ? h->cache->table[t->type].exists : false;
} }
int nft_for_each_table(struct nft_handle *h, int nft_for_each_table(struct nft_handle *h,
int (*func)(struct nft_handle *h, const char *tablename, void *data), int (*func)(struct nft_handle *h, const char *tablename, void *data),
void *data) void *data)
{ {
struct nftnl_table_list *list; int i;
struct nftnl_table_list_iter *iter;
struct nftnl_table *t;
list = nftnl_table_list_get(h);
if (list == NULL)
return -1;
iter = nftnl_table_list_iter_create(list);
if (iter == NULL)
return -1;
t = nftnl_table_list_iter_next(iter); for (i = 0; i < NFT_TABLE_MAX; i++) {
while (t != NULL) { if (h->tables[i].name == NULL)
const char *tablename = continue;
nftnl_table_get(t, NFTNL_TABLE_NAME);
func(h, tablename, data); if (!h->cache->table[h->tables[i].type].exists)
continue;
t = nftnl_table_list_iter_next(iter); func(h, h->tables[i].name, data);
} }
nftnl_table_list_iter_destroy(iter);
return 0; return 0;
} }
...@@ -2049,7 +1973,7 @@ static int __nft_table_flush(struct nft_handle *h, const char *table, bool exist ...@@ -2049,7 +1973,7 @@ static int __nft_table_flush(struct nft_handle *h, const char *table, bool exist
_t = nft_table_builtin_find(h, table); _t = nft_table_builtin_find(h, table);
assert(_t); assert(_t);
h->cache->table[_t->type].initialized = false; h->cache->table[_t->type].exists = false;
flush_chain_cache(h, table); flush_chain_cache(h, table);
...@@ -2058,52 +1982,21 @@ static int __nft_table_flush(struct nft_handle *h, const char *table, bool exist ...@@ -2058,52 +1982,21 @@ static int __nft_table_flush(struct nft_handle *h, const char *table, bool exist
int nft_table_flush(struct nft_handle *h, const char *table) int nft_table_flush(struct nft_handle *h, const char *table)
{ {
struct nftnl_table_list_iter *iter; const struct builtin_table *t;
struct nftnl_table_list *list;
struct nftnl_table *t;
bool exists = false;
int ret = 0; int ret = 0;
nft_fn = nft_table_flush; nft_fn = nft_table_flush;
list = nftnl_table_list_get(h); t = nft_table_builtin_find(h, table);
if (list == NULL) { if (!t)
ret = -1; return 0;
goto err_out;
}
iter = nftnl_table_list_iter_create(list);
if (iter == NULL) {
ret = -1;
goto err_table_list;
}
t = nftnl_table_list_iter_next(iter);
while (t != NULL) {
const char *table_name =
nftnl_table_get_str(t, NFTNL_TABLE_NAME);
if (strcmp(table_name, table) == 0) {
exists = true;
break;
}
t = nftnl_table_list_iter_next(iter); ret = __nft_table_flush(h, table, h->cache->table[t->type].exists);
}
ret = __nft_table_flush(h, table, exists);
nftnl_table_list_iter_destroy(iter);
err_table_list:
err_out:
/* the core expects 1 for success and 0 for error */ /* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0; return ret == 0 ? 1 : 0;
} }
void nft_table_new(struct nft_handle *h, const char *table)
{
nft_xt_builtin_init(h, table);
}
static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *r) static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *r)
{ {
struct obj_update *obj; struct obj_update *obj;
...@@ -2452,55 +2345,69 @@ static void __nft_print_header(struct nft_handle *h, ...@@ -2452,55 +2345,69 @@ static void __nft_print_header(struct nft_handle *h,
&ctrs, basechain, refs - entries, entries); &ctrs, basechain, refs - entries, entries);
} }
struct nft_rule_list_cb_data {
struct nft_handle *h;
unsigned int format;
int rulenum;
bool found;
bool save_fmt;
void (*cb)(struct nft_handle *h, struct nftnl_rule *r,
unsigned int num, unsigned int format);
};
static int nft_rule_list_cb(struct nftnl_chain *c, void *data)
{
struct nft_rule_list_cb_data *d = data;
if (!d->save_fmt) {
if (d->found)
printf("\n");
d->found = true;
__nft_print_header(d->h, c, d->format);
}
return __nft_rule_list(d->h, c, d->rulenum, d->format, d->cb);
}
int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
int rulenum, unsigned int format) int rulenum, unsigned int format)
{ {
const struct nft_family_ops *ops = h->ops; const struct nft_family_ops *ops = h->ops;
struct nft_rule_list_cb_data d = {
.h = h,
.format = format,
.rulenum = rulenum,
.cb = ops->print_rule,
};
struct nftnl_chain_list *list; struct nftnl_chain_list *list;
struct nftnl_chain_list_iter *iter;
struct nftnl_chain *c; struct nftnl_chain *c;
bool found = false;
nft_xt_builtin_init(h, table); nft_xt_builtin_init(h, table);
nft_assert_table_compatible(h, table, chain); nft_assert_table_compatible(h, table, chain);
list = nft_chain_list_get(h, table, chain);
if (!list)
return 0;
if (chain) { if (chain) {
c = nftnl_chain_list_lookup_byname(list, chain); c = nft_chain_find(h, table, chain);
if (!c) if (!c)
return 0; return 0;
if (!rulenum) { if (rulenum)
if (ops->print_table_header) d.save_fmt = true; /* skip header printing */
ops->print_table_header(table); else if (ops->print_table_header)
__nft_print_header(h, c, format); ops->print_table_header(table);
}
__nft_rule_list(h, c, rulenum, format, ops->print_rule); nft_rule_list_cb(c, &d);
return 1; return 1;
} }
iter = nftnl_chain_list_iter_create(list); list = nft_chain_list_get(h, table, chain);
if (iter == NULL) if (!list)
return 0; return 0;
if (ops->print_table_header) if (ops->print_table_header)
ops->print_table_header(table); ops->print_table_header(table);
c = nftnl_chain_list_iter_next(iter); nftnl_chain_list_foreach(list, nft_rule_list_cb, &d);
while (c != NULL) {
if (found)
printf("\n");
__nft_print_header(h, c, format);
__nft_rule_list(h, c, rulenum, format, ops->print_rule);
found = true;
c = nftnl_chain_list_iter_next(iter);
}
nftnl_chain_list_iter_destroy(iter);
return 1; return 1;
} }
...@@ -2511,7 +2418,7 @@ list_save(struct nft_handle *h, struct nftnl_rule *r, ...@@ -2511,7 +2418,7 @@ list_save(struct nft_handle *h, struct nftnl_rule *r,
nft_rule_print_save(h, r, NFT_RULE_APPEND, format); nft_rule_print_save(h, r, NFT_RULE_APPEND, format);
} }
static int __nftnl_rule_list_chain_save(struct nftnl_chain *c, void *data) static int nft_rule_list_chain_save(struct nftnl_chain *c, void *data)
{ {
const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
...@@ -2533,31 +2440,16 @@ static int __nftnl_rule_list_chain_save(struct nftnl_chain *c, void *data) ...@@ -2533,31 +2440,16 @@ static int __nftnl_rule_list_chain_save(struct nftnl_chain *c, void *data)
return 0; return 0;
} }
static int
nftnl_rule_list_chain_save(struct nft_handle *h, const char *chain,
struct nftnl_chain_list *list, int counters)
{
struct nftnl_chain *c;
if (chain) {
c = nftnl_chain_list_lookup_byname(list, chain);
if (!c)
return 0;
__nftnl_rule_list_chain_save(c, &counters);
return 1;
}
nftnl_chain_list_foreach(list, __nftnl_rule_list_chain_save, &counters);
return 1;
}
int nft_rule_list_save(struct nft_handle *h, const char *chain, int nft_rule_list_save(struct nft_handle *h, const char *chain,
const char *table, int rulenum, int counters) const char *table, int rulenum, int counters)
{ {
struct nft_rule_list_cb_data d = {
.h = h,
.rulenum = rulenum,
.save_fmt = true,
.cb = list_save,
};
struct nftnl_chain_list *list; struct nftnl_chain_list *list;
struct nftnl_chain_list_iter *iter;
unsigned int format = 0;
struct nftnl_chain *c; struct nftnl_chain *c;
int ret = 0; int ret = 0;
...@@ -2568,35 +2460,28 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain, ...@@ -2568,35 +2460,28 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
if (!list) if (!list)
return 0; return 0;
/* Dump policies and custom chains first */
if (!rulenum)
nftnl_rule_list_chain_save(h, chain, list, counters);
if (counters < 0) if (counters < 0)
format = FMT_C_COUNTS; d.format = FMT_C_COUNTS;
else if (counters == 0) else if (counters == 0)
format = FMT_NOCOUNTS; d.format = FMT_NOCOUNTS;
if (chain) { if (chain) {
c = nftnl_chain_list_lookup_byname(list, chain); c = nftnl_chain_list_lookup_byname(list, chain);
if (!c) if (!c)
return 0; return 0;
return __nft_rule_list(h, c, rulenum, format, list_save); if (!rulenum)
nft_rule_list_chain_save(c, &counters);
return nft_rule_list_cb(c, &d);
} }
/* Now dump out rules in this table */ /* Dump policies and custom chains first */
iter = nftnl_chain_list_iter_create(list); nftnl_chain_list_foreach(list, nft_rule_list_chain_save, &counters);
if (iter == NULL)
return 0;
c = nftnl_chain_list_iter_next(iter); /* Now dump out rules in this table */
while (c != NULL) { ret = nftnl_chain_list_foreach(list, nft_rule_list_cb, &d);
ret = __nft_rule_list(h, c, rulenum, format, list_save); return ret == 0 ? 1 : 0;
c = nftnl_chain_list_iter_next(iter);
}
nftnl_chain_list_iter_destroy(iter);
return ret;
} }
int nft_rule_zero_counters(struct nft_handle *h, const char *chain, int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
...@@ -2735,7 +2620,6 @@ static void batch_obj_del(struct nft_handle *h, struct obj_update *o) ...@@ -2735,7 +2620,6 @@ static void batch_obj_del(struct nft_handle *h, struct obj_update *o)
case NFT_COMPAT_RULE_SAVE: case NFT_COMPAT_RULE_SAVE:
case NFT_COMPAT_RULE_ZERO: case NFT_COMPAT_RULE_ZERO:
case NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE: case NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE:
case NFT_COMPAT_TABLE_NEW:
assert(0); assert(0);
break; break;
} }
...@@ -2754,11 +2638,6 @@ static void nft_refresh_transaction(struct nft_handle *h) ...@@ -2754,11 +2638,6 @@ static void nft_refresh_transaction(struct nft_handle *h)
h->error.lineno = 0; h->error.lineno = 0;
list_for_each_entry_safe(n, tmp, &h->obj_list, head) { list_for_each_entry_safe(n, tmp, &h->obj_list, head) {
if (n->implicit) {
batch_obj_del(h, n);
continue;
}
switch (n->type) { switch (n->type) {
case NFT_COMPAT_TABLE_FLUSH: case NFT_COMPAT_TABLE_FLUSH:
tablename = nftnl_table_get_str(n->table, NFTNL_TABLE_NAME); tablename = nftnl_table_get_str(n->table, NFTNL_TABLE_NAME);
...@@ -2784,14 +2663,22 @@ static void nft_refresh_transaction(struct nft_handle *h) ...@@ -2784,14 +2663,22 @@ static void nft_refresh_transaction(struct nft_handle *h)
c = nft_chain_find(h, tablename, chainname); c = nft_chain_find(h, tablename, chainname);
if (c) { if (c) {
/* -restore -n flushes existing rules from redefined user-chain */
__nft_rule_flush(h, tablename,
chainname, false, true);
n->skip = 1; n->skip = 1;
} else if (!c) { } else if (!c) {
n->skip = 0; n->skip = 0;
} }
break; break;
case NFT_COMPAT_RULE_FLUSH:
tablename = nftnl_rule_get_str(n->rule, NFTNL_RULE_TABLE);
if (!tablename)
continue;
chainname = nftnl_rule_get_str(n->rule, NFTNL_RULE_CHAIN);
if (!chainname)
continue;
n->skip = !nft_chain_find(h, tablename, chainname);
break;
case NFT_COMPAT_TABLE_ADD: case NFT_COMPAT_TABLE_ADD:
case NFT_COMPAT_CHAIN_ADD: case NFT_COMPAT_CHAIN_ADD:
case NFT_COMPAT_CHAIN_ZERO: case NFT_COMPAT_CHAIN_ZERO:
...@@ -2803,7 +2690,6 @@ static void nft_refresh_transaction(struct nft_handle *h) ...@@ -2803,7 +2690,6 @@ static void nft_refresh_transaction(struct nft_handle *h)
case NFT_COMPAT_RULE_INSERT: case NFT_COMPAT_RULE_INSERT:
case NFT_COMPAT_RULE_REPLACE: case NFT_COMPAT_RULE_REPLACE:
case NFT_COMPAT_RULE_DELETE: case NFT_COMPAT_RULE_DELETE:
case NFT_COMPAT_RULE_FLUSH:
case NFT_COMPAT_SET_ADD: case NFT_COMPAT_SET_ADD:
case NFT_COMPAT_RULE_LIST: case NFT_COMPAT_RULE_LIST:
case NFT_COMPAT_RULE_CHECK: case NFT_COMPAT_RULE_CHECK:
...@@ -2811,7 +2697,6 @@ static void nft_refresh_transaction(struct nft_handle *h) ...@@ -2811,7 +2697,6 @@ static void nft_refresh_transaction(struct nft_handle *h)
case NFT_COMPAT_RULE_SAVE: case NFT_COMPAT_RULE_SAVE:
case NFT_COMPAT_RULE_ZERO: case NFT_COMPAT_RULE_ZERO:
case NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE: case NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE:
case NFT_COMPAT_TABLE_NEW:
break; break;
} }
} }
...@@ -2835,9 +2720,10 @@ retry: ...@@ -2835,9 +2720,10 @@ retry:
h->nft_genid++; h->nft_genid++;
list_for_each_entry(n, &h->obj_list, head) { list_for_each_entry(n, &h->obj_list, head) {
if (n->skip) {
if (n->skip) n->seq = 0;
continue; continue;
}
n->seq = seq++; n->seq = seq++;
switch (n->type) { switch (n->type) {
...@@ -2915,7 +2801,6 @@ retry: ...@@ -2915,7 +2801,6 @@ retry:
case NFT_COMPAT_RULE_SAVE: case NFT_COMPAT_RULE_SAVE:
case NFT_COMPAT_RULE_ZERO: case NFT_COMPAT_RULE_ZERO:
case NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE: case NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE:
case NFT_COMPAT_TABLE_NEW:
assert(0); assert(0);
} }
...@@ -3178,10 +3063,6 @@ static int nft_prepare(struct nft_handle *h) ...@@ -3178,10 +3063,6 @@ static int nft_prepare(struct nft_handle *h)
ret = ebt_set_user_chain_policy(h, cmd->table, ret = ebt_set_user_chain_policy(h, cmd->table,
cmd->chain, cmd->policy); cmd->chain, cmd->policy);
break; break;
case NFT_COMPAT_TABLE_NEW:
nft_xt_builtin_init(h, cmd->table);
ret = 1;
break;
case NFT_COMPAT_SET_ADD: case NFT_COMPAT_SET_ADD:
nft_xt_builtin_init(h, cmd->table); nft_xt_builtin_init(h, cmd->table);
batch_set_add(h, NFT_COMPAT_SET_ADD, cmd->obj.set); batch_set_add(h, NFT_COMPAT_SET_ADD, cmd->obj.set);
...@@ -3406,7 +3287,7 @@ static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data) ...@@ -3406,7 +3287,7 @@ static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data)
nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0); nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0); nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE); nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
if (batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c)) if (!batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c))
return -1; return -1;
} }
......
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
#include <libiptc/linux_list.h> #include <libiptc/linux_list.h>
enum nft_table_type { enum nft_table_type {
NFT_TABLE_FILTER = 0, NFT_TABLE_MANGLE = 0,
NFT_TABLE_MANGLE,
NFT_TABLE_RAW,
NFT_TABLE_SECURITY, NFT_TABLE_SECURITY,
NFT_TABLE_RAW,
NFT_TABLE_FILTER,
NFT_TABLE_NAT, NFT_TABLE_NAT,
}; };
#define NFT_TABLE_MAX (NFT_TABLE_NAT + 1) #define NFT_TABLE_MAX (NFT_TABLE_NAT + 1)
...@@ -38,11 +38,10 @@ enum nft_cache_level { ...@@ -38,11 +38,10 @@ enum nft_cache_level {
}; };
struct nft_cache { struct nft_cache {
struct nftnl_table_list *tables;
struct { struct {
struct nftnl_chain_list *chains; struct nftnl_chain_list *chains;
struct nftnl_set_list *sets; struct nftnl_set_list *sets;
bool initialized; bool exists;
} table[NFT_TABLE_MAX]; } table[NFT_TABLE_MAX];
}; };
...@@ -68,7 +67,6 @@ enum obj_update_type { ...@@ -68,7 +67,6 @@ enum obj_update_type {
NFT_COMPAT_RULE_SAVE, NFT_COMPAT_RULE_SAVE,
NFT_COMPAT_RULE_ZERO, NFT_COMPAT_RULE_ZERO,
NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE, NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE,
NFT_COMPAT_TABLE_NEW,
}; };
struct cache_chain { struct cache_chain {
...@@ -135,7 +133,6 @@ int nft_for_each_table(struct nft_handle *h, int (*func)(struct nft_handle *h, c ...@@ -135,7 +133,6 @@ int nft_for_each_table(struct nft_handle *h, int (*func)(struct nft_handle *h, c
bool nft_table_find(struct nft_handle *h, const char *tablename); bool nft_table_find(struct nft_handle *h, const char *tablename);
int nft_table_purge_chains(struct nft_handle *h, const char *table, struct nftnl_chain_list *list); int nft_table_purge_chains(struct nft_handle *h, const char *table, struct nftnl_chain_list *list);
int nft_table_flush(struct nft_handle *h, const char *table); int nft_table_flush(struct nft_handle *h, const char *table);
void nft_table_new(struct nft_handle *h, const char *table);
const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *table); const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *table);
/* /*
...@@ -144,7 +141,7 @@ const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const c ...@@ -144,7 +141,7 @@ const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const c
struct nftnl_chain; struct nftnl_chain;
int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters); int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters);
int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list); int nft_chain_save(struct nftnl_chain *c, void *data);
int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table); int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table);
int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table, bool verbose); int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table, bool verbose);
int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table); int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table);
......
...@@ -4,6 +4,21 @@ ...@@ -4,6 +4,21 @@
TESTDIR="./$(dirname $0)/" TESTDIR="./$(dirname $0)/"
RETURNCODE_SEPARATOR="_" RETURNCODE_SEPARATOR="_"
usage() {
cat <<EOF
Usage: $(basename $0) [-v|--verbose] [-H|--host] [-V|--valgrind]
[[-l|--legacy]|[-n|--nft]] [testscript ...]
-v | --verbose Enable verbose mode (do not drop testscript output).
-H | --host Run tests against installed binaries in \$PATH,
not those built in this source tree.
-V | --valgrind Enable leak checking via valgrind.
-l | --legacy Test legacy variant only. Conflicts with --nft.
-n | --nft Test nft variant only. Conflicts with --legacy.
testscript Run only specific test(s). Implies --verbose.
EOF
}
msg_error() { msg_error() {
echo "E: $1 ..." >&2 echo "E: $1 ..." >&2
exit 1 exit 1
...@@ -50,6 +65,10 @@ while [ -n "$1" ]; do ...@@ -50,6 +65,10 @@ while [ -n "$1" ]; do
VALGRIND=y VALGRIND=y
shift shift
;; ;;
-h|--help)
usage
exit 0
;;
*${RETURNCODE_SEPARATOR}+([0-9])) *${RETURNCODE_SEPARATOR}+([0-9]))
SINGLE+=" $1" SINGLE+=" $1"
VERBOSE=y VERBOSE=y
......
#!/bin/sh
# make sure error return codes are as expected useful cases
# (e.g. commands to check ruleset state)
global_rc=0
cmd() { # (rc, cmd, [args ...])
rc_exp=$1; shift
$XT_MULTI "$@"
rc=$?
[ $rc -eq $rc_exp ] || {
echo "---> expected $rc_exp, got $rc for command '$@'"
global_rc=1
}
}
# test chain creation
cmd 0 ip6tables -N foo
cmd 1 ip6tables -N foo
# iptables-nft allows this - bug or feature?
#cmd 2 ip6tables -N "invalid name"
# test rule adding
cmd 0 ip6tables -A INPUT -j ACCEPT
cmd 1 ip6tables -A noexist -j ACCEPT
cmd 2 ip6tables -I INPUT -j foobar
# test rule checking
cmd 0 ip6tables -C INPUT -j ACCEPT
cmd 1 ip6tables -C FORWARD -j ACCEPT
cmd 1 ip6tables -C nonexist -j ACCEPT
cmd 2 ip6tables -C INPUT -j foobar
cmd 2 ip6tables -C INPUT -m foobar -j ACCEPT
cmd 3 ip6tables -t foobar -C INPUT -j ACCEPT
exit $global_rc
#!/bin/bash
set -e
DUMP="*filter
:foo - [0:0]
:bar - [0:0]
-A foo -j ACCEPT
COMMIT
*nat
:natfoo - [0:0]
:natbar - [0:0]
-A natfoo -j ACCEPT
COMMIT
*raw
:rawfoo - [0:0]
COMMIT
*mangle
:manglefoo - [0:0]
COMMIT
*security
:secfoo - [0:0]
COMMIT
"
$XT_MULTI iptables-restore <<< "$DUMP"
$XT_MULTI ip6tables-restore <<< "$DUMP"
EXPECT="Flushing chain \`INPUT'
Flushing chain \`FORWARD'
Flushing chain \`OUTPUT'
Flushing chain \`bar'
Flushing chain \`foo'
Deleting chain \`bar'
Deleting chain \`foo'
Flushing chain \`PREROUTING'
Flushing chain \`INPUT'
Flushing chain \`OUTPUT'
Flushing chain \`POSTROUTING'
Flushing chain \`natbar'
Flushing chain \`natfoo'
Deleting chain \`natbar'
Deleting chain \`natfoo'
Flushing chain \`PREROUTING'
Flushing chain \`OUTPUT'
Flushing chain \`rawfoo'
Deleting chain \`rawfoo'
Flushing chain \`PREROUTING'
Flushing chain \`INPUT'
Flushing chain \`FORWARD'
Flushing chain \`OUTPUT'
Flushing chain \`POSTROUTING'
Flushing chain \`manglefoo'
Deleting chain \`manglefoo'
Flushing chain \`INPUT'
Flushing chain \`FORWARD'
Flushing chain \`OUTPUT'
Flushing chain \`secfoo'
Deleting chain \`secfoo'"
for ipt in iptables-restore ip6tables-restore; do
diff -u -Z <(sort <<< "$EXPECT") <($XT_MULTI $ipt -v <<< "$DUMP" | sort)
done
DUMP="*filter
:baz - [0:0]
-F foo
-X bar
-A foo -j ACCEPT
COMMIT
"
EXPECT=""
for ipt in iptables-restore ip6tables-restore; do
diff -u -Z <(echo -ne "$EXPECT") <($XT_MULTI $ipt -v --noflush <<< "$DUMP")
done
#!/bin/bash
# test for iptables-restore --noflush skipping an explicitly requested chain
# flush because the chain did not exist when cache was fetched. In order to
# expect for that chain to appear when refreshing the transaction (due to a
# concurrent ruleset change), the chain flush job has to be present in batch
# job list (although disabled at first).
# The input line requesting chain flush is ':FOO - [0:0]'. RS1 and RS2 contents
# are crafted to cause EBUSY when deleting the BAR* chains if FOO is not
# flushed in the same transaction.
set -e
RS="*filter
:INPUT ACCEPT [12024:3123388]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [12840:2144421]
:FOO - [0:0]
:BAR0 - [0:0]
:BAR1 - [0:0]
:BAR2 - [0:0]
:BAR3 - [0:0]
:BAR4 - [0:0]
:BAR5 - [0:0]
:BAR6 - [0:0]
:BAR7 - [0:0]
:BAR8 - [0:0]
:BAR9 - [0:0]
"
RS1="$RS
-X BAR3
-X BAR6
-X BAR9
-A FOO -s 9.9.0.1/32 -j BAR1
-A FOO -s 9.9.0.2/32 -j BAR2
-A FOO -s 9.9.0.4/32 -j BAR4
-A FOO -s 9.9.0.5/32 -j BAR5
-A FOO -s 9.9.0.7/32 -j BAR7
-A FOO -s 9.9.0.8/32 -j BAR8
COMMIT
"
RS2="$RS
-X BAR2
-X BAR5
-X BAR7
-A FOO -s 9.9.0.1/32 -j BAR1
-A FOO -s 9.9.0.3/32 -j BAR3
-A FOO -s 9.9.0.4/32 -j BAR4
-A FOO -s 9.9.0.6/32 -j BAR6
-A FOO -s 9.9.0.8/32 -j BAR8
-A FOO -s 9.9.0.9/32 -j BAR9
COMMIT
"
NORS="*filter
COMMIT
"
for n in $(seq 1 10); do
$XT_MULTI iptables-restore <<< "$NORS"
$XT_MULTI iptables-restore --noflush -w <<< "$RS1" &
$XT_MULTI iptables-restore --noflush -w <<< "$RS2" &
wait -n
wait -n
done
...@@ -13,75 +13,84 @@ cmd() { # (rc, msg, cmd, [args ...]) ...@@ -13,75 +13,84 @@ cmd() { # (rc, msg, cmd, [args ...])
msg_exp="$1"; shift msg_exp="$1"; shift
} }
msg="$($XT_MULTI "$@" 2>&1 >/dev/null)" for ipt in iptables ip6tables; do
rc=$? msg="$($XT_MULTI $ipt "$@" 2>&1 >/dev/null)"
rc=$?
[ $rc -eq $rc_exp ] || { [ $rc -eq $rc_exp ] || {
echo "---> expected return code $rc_exp, got $rc for command '$@'" echo "---> expected return code $rc_exp, got $rc for command '$ipt $@'"
global_rc=1 global_rc=1
} }
[ -n "$msg_exp" ] || return [ -n "$msg_exp" ] || continue
grep -q "$msg_exp" <<< $msg || { msg_exp_full="${ipt}$msg_exp"
echo "---> expected error message '$msg_exp', got '$msg' for command '$@'" grep -q "$msg_exp_full" <<< $msg || {
global_rc=1 echo "---> expected error message '$msg_exp_full', got '$msg' for command '$ipt $@'"
} global_rc=1
}
done
} }
EEXIST_F="File exists." EEXIST_F=": File exists."
EEXIST="Chain already exists." EEXIST=": Chain already exists."
ENOENT="No chain/target/match by that name." ENOENT=": No chain/target/match by that name."
E2BIG_I="Index of insertion too big." E2BIG_I=": Index of insertion too big."
E2BIG_D="Index of deletion too big." E2BIG_D=": Index of deletion too big."
E2BIG_R="Index of replacement too big." E2BIG_R=": Index of replacement too big."
EBADRULE="Bad rule (does a matching rule exist in that chain?)." EBADRULE=": Bad rule (does a matching rule exist in that chain?)."
ENOTGT="Couldn't load target \`foobar':No such file or directory" #ENOTGT=" v[0-9\.]* [^ ]*: Couldn't load target \`foobar':No such file or directory"
ENOMTH="Couldn't load match \`foobar':No such file or directory" ENOMTH=" v[0-9\.]* [^ ]*: Couldn't load match \`foobar':No such file or directory"
ENOTBL="can't initialize iptables table \`foobar': Table does not exist" ENOTBL=": can't initialize iptables table \`foobar': Table does not exist"
# test chain creation # test chain creation
cmd 0 iptables -N foo cmd 0 -N foo
cmd 1 "$EEXIST" iptables -N foo cmd 1 "$EEXIST" -N foo
# iptables-nft allows this - bug or feature? # iptables-nft allows this - bug or feature?
#cmd 2 iptables -N "invalid name" #cmd 2 -N "invalid name"
# test chain flushing/zeroing # test chain flushing/zeroing
cmd 0 iptables -F foo cmd 0 -F foo
cmd 0 iptables -Z foo cmd 0 -Z foo
cmd 1 "$ENOENT" iptables -F bar cmd 1 "$ENOENT" -F bar
cmd 1 "$ENOENT" iptables -Z bar cmd 1 "$ENOENT" -Z bar
# test chain rename # test chain rename
cmd 0 iptables -E foo bar cmd 0 -E foo bar
cmd 1 "$EEXIST_F" iptables -E foo bar cmd 1 "$EEXIST_F" -E foo bar
cmd 1 "$ENOENT" iptables -E foo bar2 cmd 1 "$ENOENT" -E foo bar2
cmd 0 iptables -N foo2 cmd 0 -N foo2
cmd 1 "$EEXIST_F" iptables -E foo2 bar cmd 1 "$EEXIST_F" -E foo2 bar
# test rule adding # test rule adding
cmd 0 iptables -A INPUT -j ACCEPT cmd 0 -A INPUT -j ACCEPT
cmd 1 "$ENOENT" iptables -A noexist -j ACCEPT cmd 1 "$ENOENT" -A noexist -j ACCEPT
cmd 2 "" iptables -I INPUT -j foobar # next three differ:
cmd 2 "" iptables -R INPUT 1 -j foobar # legacy: Couldn't load target `foobar':No such file or directory
cmd 2 "" iptables -D INPUT -j foobar # nft: Chain 'foobar' does not exist
cmd 2 "" -I INPUT -j foobar
cmd 2 "" -R INPUT 1 -j foobar
cmd 2 "" -D INPUT -j foobar
cmd 1 "$EBADRULE" -D INPUT -p tcp --dport 22 -j ACCEPT
# test rulenum commands # test rulenum commands
cmd 1 "$E2BIG_I" iptables -I INPUT 23 -j ACCEPT cmd 1 "$E2BIG_I" -I INPUT 23 -j ACCEPT
cmd 1 "$E2BIG_D" iptables -D INPUT 23 cmd 1 "$E2BIG_D" -D INPUT 23
cmd 1 "$E2BIG_R" iptables -R INPUT 23 -j ACCEPT cmd 1 "$E2BIG_R" -R INPUT 23 -j ACCEPT
cmd 1 "$ENOENT" iptables -I nonexist 23 -j ACCEPT cmd 1 "$ENOENT" -I nonexist 23 -j ACCEPT
cmd 1 "$ENOENT" iptables -D nonexist 23 cmd 1 "$ENOENT" -D nonexist 23
cmd 1 "$ENOENT" iptables -R nonexist 23 -j ACCEPT cmd 1 "$ENOENT" -R nonexist 23 -j ACCEPT
# test rule checking # test rule checking
cmd 0 iptables -C INPUT -j ACCEPT cmd 0 -C INPUT -j ACCEPT
cmd 1 "$EBADRULE" iptables -C FORWARD -j ACCEPT cmd 1 "$EBADRULE" -C FORWARD -j ACCEPT
cmd 1 "$BADRULE" iptables -C nonexist -j ACCEPT cmd 1 "$BADRULE" -C nonexist -j ACCEPT
cmd 2 "$ENOMTH" iptables -C INPUT -m foobar -j ACCEPT cmd 2 "$ENOMTH" -C INPUT -m foobar -j ACCEPT
# messages of those don't match, but iptables-nft ones are actually nicer. # messages of those don't match, but iptables-nft ones are actually nicer.
#cmd 2 "$ENOTGT" iptables -C INPUT -j foobar # legacy: Couldn't load target `foobar':No such file or directory
#cmd 3 "$ENOTBL" iptables -t foobar -C INPUT -j ACCEPT # nft: Chain 'foobar' does not exist
cmd 2 "" iptables -C INPUT -j foobar cmd 2 "" -C INPUT -j foobar
cmd 3 "" iptables -t foobar -C INPUT -j ACCEPT # legacy: can't initialize ip6tables table `foobar': Table does not exist (do you need to insmod?)
# nft: table 'foobar' does not exist
cmd 3 "" -t foobar -C INPUT -j ACCEPT
exit $global_rc exit $global_rc
#!/bin/bash
[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
nft -v >/dev/null || { echo "skip $XT_MULTI (no nft)"; exit 0; }
coproc $XT_MULTI iptables-restore --noflush
cat >&"${COPROC[1]}" <<EOF
*filter
:foo [0:0]
COMMIT
*filter
:foo [0:0]
EOF
$XT_MULTI iptables-save | grep -q ':foo'
nft flush ruleset
echo "COMMIT" >&"${COPROC[1]}"
sleep 1
[[ -n $COPROC_PID ]] && kill $COPROC_PID
wait
#!/bin/bash
[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
set -e
$XT_MULTI iptables -t raw -P OUTPUT DROP
# make sure iptables-nft-restore can correctly handle basechain policies when
# they aren't set with --noflush
#
$XT_MULTI iptables-restore --noflush <<EOF
*raw
:OUTPUT - [0:0]
:PREROUTING - [0:0]
:neutron-linuxbri-OUTPUT - [0:0]
:neutron-linuxbri-PREROUTING - [0:0]
-I OUTPUT 1 -j neutron-linuxbri-OUTPUT
-I PREROUTING 1 -j neutron-linuxbri-PREROUTING
-I neutron-linuxbri-PREROUTING 1 -m physdev --physdev-in brq7425e328-56 -j CT --zone 4097
-I neutron-linuxbri-PREROUTING 2 -i brq7425e328-56 -j CT --zone 4097
-I neutron-linuxbri-PREROUTING 3 -m physdev --physdev-in tap7f101a28-1d -j CT --zone 4097
COMMIT
EOF
$XT_MULTI iptables-save | grep -C2 raw | grep OUTPUT | grep DROP
if [ $? -ne 0 ]; then
exit 1
fi
...@@ -249,15 +249,20 @@ void xs_init_match(struct xtables_match *match) ...@@ -249,15 +249,20 @@ void xs_init_match(struct xtables_match *match)
static int xtables_lock(int wait, struct timeval *wait_interval) static int xtables_lock(int wait, struct timeval *wait_interval)
{ {
struct timeval time_left, wait_time; struct timeval time_left, wait_time;
const char *lock_file;
int fd, i = 0; int fd, i = 0;
time_left.tv_sec = wait; time_left.tv_sec = wait;
time_left.tv_usec = 0; time_left.tv_usec = 0;
fd = open(XT_LOCK_NAME, O_CREAT, 0600); lock_file = getenv("XTABLES_LOCKFILE");
if (lock_file == NULL || lock_file[0] == '\0')
lock_file = XT_LOCK_NAME;
fd = open(lock_file, O_CREAT, 0600);
if (fd < 0) { if (fd < 0) {
fprintf(stderr, "Fatal: can't open lock file %s: %s\n", fprintf(stderr, "Fatal: can't open lock file %s: %s\n",
XT_LOCK_NAME, strerror(errno)); lock_file, strerror(errno));
return XT_LOCK_FAILED; return XT_LOCK_FAILED;
} }
...@@ -265,7 +270,7 @@ static int xtables_lock(int wait, struct timeval *wait_interval) ...@@ -265,7 +270,7 @@ static int xtables_lock(int wait, struct timeval *wait_interval)
if (flock(fd, LOCK_EX) == 0) if (flock(fd, LOCK_EX) == 0)
return fd; return fd;
fprintf(stderr, "Can't lock %s: %s\n", XT_LOCK_NAME, fprintf(stderr, "Can't lock %s: %s\n", lock_file,
strerror(errno)); strerror(errno));
return XT_LOCK_BUSY; return XT_LOCK_BUSY;
} }
......
...@@ -1155,7 +1155,7 @@ print_zero: ...@@ -1155,7 +1155,7 @@ print_zero:
/*case 7 :*/ /* atomic-init */ /*case 7 :*/ /* atomic-init */
/*case 10:*/ /* atomic-save */ /*case 10:*/ /* atomic-save */
case 11: /* init-table */ case 11: /* init-table */
nft_cmd_table_flush(h, *table); nft_cmd_table_flush(h, *table, false);
return 1; return 1;
/* /*
replace->command = c; replace->command = c;
......
...@@ -93,6 +93,8 @@ static int rule_cb(const struct nlmsghdr *nlh, void *data) ...@@ -93,6 +93,8 @@ static int rule_cb(const struct nlmsghdr *nlh, void *data)
if (arg->nfproto && arg->nfproto != family) if (arg->nfproto && arg->nfproto != family)
goto err_free; goto err_free;
arg->h->ops = nft_family_ops_lookup(family);
if (arg->is_event) if (arg->is_event)
printf(" EVENT: "); printf(" EVENT: ");
switch (family) { switch (family) {
......
...@@ -61,7 +61,6 @@ static void print_usage(const char *name, const char *version) ...@@ -61,7 +61,6 @@ static void print_usage(const char *name, const char *version)
static const struct nft_xt_restore_cb restore_cb = { static const struct nft_xt_restore_cb restore_cb = {
.commit = nft_commit, .commit = nft_commit,
.abort = nft_abort, .abort = nft_abort,
.table_new = nft_cmd_table_new,
.table_flush = nft_cmd_table_flush, .table_flush = nft_cmd_table_flush,
.do_command = do_commandx, .do_command = do_commandx,
.chain_set = nft_cmd_chain_set, .chain_set = nft_cmd_chain_set,
...@@ -135,7 +134,7 @@ static void xtables_restore_parse_line(struct nft_handle *h, ...@@ -135,7 +134,7 @@ static void xtables_restore_parse_line(struct nft_handle *h,
if (h->noflush == 0) { if (h->noflush == 0) {
DEBUGP("Cleaning all chains of table '%s'\n", table); DEBUGP("Cleaning all chains of table '%s'\n", table);
if (cb->table_flush) if (cb->table_flush)
cb->table_flush(h, table); cb->table_flush(h, table, verbose);
} }
ret = 1; ret = 1;
...@@ -260,7 +259,7 @@ void xtables_restore_parse(struct nft_handle *h, ...@@ -260,7 +259,7 @@ void xtables_restore_parse(struct nft_handle *h,
struct nft_xt_restore_state state = {}; struct nft_xt_restore_state state = {};
char buffer[10240] = {}; char buffer[10240] = {};
if (!h->noflush) if (!verbose && !h->noflush)
nft_cache_level_set(h, NFT_CL_FAKE, NULL); nft_cache_level_set(h, NFT_CL_FAKE, NULL);
line = 0; line = 0;
...@@ -410,7 +409,6 @@ int xtables_ip6_restore_main(int argc, char *argv[]) ...@@ -410,7 +409,6 @@ int xtables_ip6_restore_main(int argc, char *argv[])
static const struct nft_xt_restore_cb ebt_restore_cb = { static const struct nft_xt_restore_cb ebt_restore_cb = {
.commit = nft_bridge_commit, .commit = nft_bridge_commit,
.table_new = nft_cmd_table_new,
.table_flush = nft_cmd_table_flush, .table_flush = nft_cmd_table_flush,
.do_command = do_commandeb, .do_command = do_commandeb,
.chain_set = nft_cmd_chain_set, .chain_set = nft_cmd_chain_set,
...@@ -456,7 +454,6 @@ int xtables_eb_restore_main(int argc, char *argv[]) ...@@ -456,7 +454,6 @@ int xtables_eb_restore_main(int argc, char *argv[])
static const struct nft_xt_restore_cb arp_restore_cb = { static const struct nft_xt_restore_cb arp_restore_cb = {
.commit = nft_commit, .commit = nft_commit,
.table_new = nft_cmd_table_new,
.table_flush = nft_cmd_table_flush, .table_flush = nft_cmd_table_flush,
.do_command = do_commandarp, .do_command = do_commandarp,
.chain_set = nft_cmd_chain_set, .chain_set = nft_cmd_chain_set,
......
...@@ -92,7 +92,7 @@ __do_output(struct nft_handle *h, const char *tablename, void *data) ...@@ -92,7 +92,7 @@ __do_output(struct nft_handle *h, const char *tablename, void *data)
printf("*%s\n", tablename); printf("*%s\n", tablename);
/* Dump out chain names first, /* Dump out chain names first,
* thereby preventing dependency conflicts */ * thereby preventing dependency conflicts */
nft_chain_save(h, chain_list); nftnl_chain_list_foreach(chain_list, nft_chain_save, h);
nft_rule_save(h, tablename, d->format); nft_rule_save(h, tablename, d->format);
if (d->commit) if (d->commit)
printf("COMMIT\n"); printf("COMMIT\n");
......
...@@ -75,14 +75,10 @@ xtables_main(int family, const char *progname, int argc, char *argv[]) ...@@ -75,14 +75,10 @@ xtables_main(int family, const char *progname, int argc, char *argv[])
xtables_fini(); xtables_fini();
if (!ret) { if (!ret) {
if (errno == EINVAL) { fprintf(stderr, "%s: %s.%s\n", progname, nft_strerror(errno),
fprintf(stderr, "iptables: %s. " (errno == EINVAL ?
"Run `dmesg' for more information.\n", " Run `dmesg' for more information." : ""));
nft_strerror(errno));
} else {
fprintf(stderr, "iptables: %s.\n",
nft_strerror(errno));
}
if (errno == EAGAIN) if (errno == EAGAIN)
exit(RESOURCE_PROBLEM); exit(RESOURCE_PROBLEM);
} }
......
...@@ -249,7 +249,7 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[], ...@@ -249,7 +249,7 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
cs.restore = restore; cs.restore = restore;
if (!restore) if (!restore && p.command != CMD_NONE)
printf("nft "); printf("nft ");
switch (p.command) { switch (p.command) {
...@@ -310,13 +310,16 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[], ...@@ -310,13 +310,16 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
break; break;
case CMD_SET_POLICY: case CMD_SET_POLICY:
break; break;
case CMD_NONE:
ret = 1;
break;
default: default:
/* We should never reach this... */ /* We should never reach this... */
printf("Unsupported command?\n"); printf("Unsupported command?\n");
exit(1); exit(1);
} }
xtables_rule_matches_free(&cs.matches); nft_clear_iptables_command_state(&cs);
if (h->family == AF_INET) { if (h->family == AF_INET) {
free(args.s.addr.v4); free(args.s.addr.v4);
......
...@@ -275,6 +275,7 @@ SET_MAKE = @SET_MAKE@ ...@@ -275,6 +275,7 @@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@ SHELL = @SHELL@
STRIP = @STRIP@ STRIP = @STRIP@
VERSION = @VERSION@ VERSION = @VERSION@
XT_LOCK_NAME = @XT_LOCK_NAME@
abs_builddir = @abs_builddir@ abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@ abs_top_builddir = @abs_top_builddir@
......
...@@ -282,6 +282,7 @@ SET_MAKE = @SET_MAKE@ ...@@ -282,6 +282,7 @@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@ SHELL = @SHELL@
STRIP = @STRIP@ STRIP = @STRIP@
VERSION = @VERSION@ VERSION = @VERSION@
XT_LOCK_NAME = @XT_LOCK_NAME@
abs_builddir = @abs_builddir@ abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@ abs_top_builddir = @abs_top_builddir@
......
...@@ -1169,7 +1169,7 @@ static int iptcc_compile_chain(struct xtc_handle *h, STRUCT_REPLACE *repl, struc ...@@ -1169,7 +1169,7 @@ static int iptcc_compile_chain(struct xtc_handle *h, STRUCT_REPLACE *repl, struc
else else
foot->target.verdict = RETURN; foot->target.verdict = RETURN;
/* set policy-counters */ /* set policy-counters */
memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS)); foot->e.counters = c->counters;
return 0; return 0;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment