Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

1) Wait for rcu grace period after releasing netns in ctnetlink,
   from Florian Westphal.

2) Incorrect command type in flowtable offload ndo invocation,
   from wenxu.

3) Incorrect callback type in flowtable offload flow tuple
   updates, also from wenxu.

4) Fix compile warning on flowtable offload infrastructure due to
   possible reference to uninitialized variable, from Nathan Chancellor.

5) Do not inline nf_ct_resolve_clash(), this is called from slow
   path / stress situations. From Florian Westphal.

6) Missing IPv6 flow selector description in flowtable offload.

7) Missing check for NETDEV_UNREGISTER in nf_tables offload
   infrastructure, from wenxu.

8) Update NAT selftest to use randomized netns names, from
   Florian Westphal.

9) Restore nfqueue bridge support, from Marco Oliverio.

10) Compilation warning in SCTP_CHUNKMAP_*() on xt_sctp header.
    From Phil Sutter.

11) Fix bogus lookup/get match for non-anonymous rbtree sets.

12) Missing netlink validation for NFT_SET_ELEM_INTERVAL_END
    elements.

13) Missing netlink validation for NFT_DATA_VALUE after
    nft_data_init().

14) If rule specifies no actions, offload infrastructure returns
    EOPNOTSUPP.

15) Module refcount leak in object updates.

16) Missing sanitization for ARP traffic from br_netfilter, from
    Eric Dumazet.

17) Compilation breakage on big-endian due to incorrect memcpy()
    size in the flowtable offload infrastructure.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2019-12-09 14:03:33 -08:00
commit 7da538c1e1
13 changed files with 288 additions and 213 deletions

View File

@ -41,19 +41,19 @@ struct xt_sctp_info {
#define SCTP_CHUNKMAP_SET(chunkmap, type) \ #define SCTP_CHUNKMAP_SET(chunkmap, type) \
do { \ do { \
(chunkmap)[type / bytes(__u32)] |= \ (chunkmap)[type / bytes(__u32)] |= \
1 << (type % bytes(__u32)); \ 1u << (type % bytes(__u32)); \
} while (0) } while (0)
#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \ #define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
do { \ do { \
(chunkmap)[type / bytes(__u32)] &= \ (chunkmap)[type / bytes(__u32)] &= \
~(1 << (type % bytes(__u32))); \ ~(1u << (type % bytes(__u32))); \
} while (0) } while (0)
#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \ #define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
({ \ ({ \
((chunkmap)[type / bytes (__u32)] & \ ((chunkmap)[type / bytes (__u32)] & \
(1 << (type % bytes (__u32)))) ? 1: 0; \ (1u << (type % bytes (__u32)))) ? 1: 0; \
}) })
#define SCTP_CHUNKMAP_RESET(chunkmap) \ #define SCTP_CHUNKMAP_RESET(chunkmap) \

View File

@ -662,6 +662,9 @@ static unsigned int br_nf_forward_arp(void *priv,
nf_bridge_pull_encap_header(skb); nf_bridge_pull_encap_header(skb);
} }
if (unlikely(!pskb_may_pull(skb, sizeof(struct arphdr))))
return NF_DROP;
if (arp_hdr(skb)->ar_pln != 4) { if (arp_hdr(skb)->ar_pln != 4) {
if (is_vlan_arp(skb, state->net)) if (is_vlan_arp(skb, state->net))
nf_bridge_push_encap_header(skb); nf_bridge_push_encap_header(skb);

View File

@ -895,9 +895,10 @@ static void nf_ct_acct_merge(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
} }
/* Resolve race on insertion if this protocol allows this. */ /* Resolve race on insertion if this protocol allows this. */
static int nf_ct_resolve_clash(struct net *net, struct sk_buff *skb, static __cold noinline int
enum ip_conntrack_info ctinfo, nf_ct_resolve_clash(struct net *net, struct sk_buff *skb,
struct nf_conntrack_tuple_hash *h) enum ip_conntrack_info ctinfo,
struct nf_conntrack_tuple_hash *h)
{ {
/* This is the conntrack entry already in hashes that won race. */ /* This is the conntrack entry already in hashes that won race. */
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);

View File

@ -3626,6 +3626,9 @@ static void __net_exit ctnetlink_net_exit_batch(struct list_head *net_exit_list)
list_for_each_entry(net, net_exit_list, exit_list) list_for_each_entry(net, net_exit_list, exit_list)
ctnetlink_net_exit(net); ctnetlink_net_exit(net);
/* wait for other cpus until they are done with ctnl_notifiers */
synchronize_rcu();
} }
static struct pernet_operations ctnetlink_net_ops = { static struct pernet_operations ctnetlink_net_ops = {

View File

@ -28,6 +28,7 @@ struct nf_flow_key {
struct flow_dissector_key_basic basic; struct flow_dissector_key_basic basic;
union { union {
struct flow_dissector_key_ipv4_addrs ipv4; struct flow_dissector_key_ipv4_addrs ipv4;
struct flow_dissector_key_ipv6_addrs ipv6;
}; };
struct flow_dissector_key_tcp tcp; struct flow_dissector_key_tcp tcp;
struct flow_dissector_key_ports tp; struct flow_dissector_key_ports tp;
@ -57,6 +58,7 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_CONTROL, control); NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_CONTROL, control);
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_BASIC, basic); NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_BASIC, basic);
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4); NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4);
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6);
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_TCP, tcp); NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_TCP, tcp);
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_PORTS, tp); NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_PORTS, tp);
@ -69,9 +71,18 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
key->ipv4.dst = tuple->dst_v4.s_addr; key->ipv4.dst = tuple->dst_v4.s_addr;
mask->ipv4.dst = 0xffffffff; mask->ipv4.dst = 0xffffffff;
break; break;
case AF_INET6:
key->control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
key->basic.n_proto = htons(ETH_P_IPV6);
key->ipv6.src = tuple->src_v6;
memset(&mask->ipv6.src, 0xff, sizeof(mask->ipv6.src));
key->ipv6.dst = tuple->dst_v6;
memset(&mask->ipv6.dst, 0xff, sizeof(mask->ipv6.dst));
break;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
match->dissector.used_keys |= BIT(key->control.addr_type);
mask->basic.n_proto = 0xffff; mask->basic.n_proto = 0xffff;
switch (tuple->l4proto) { switch (tuple->l4proto) {
@ -96,14 +107,13 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL) | match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_BASIC) | BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_PORTS); BIT(FLOW_DISSECTOR_KEY_PORTS);
return 0; return 0;
} }
static void flow_offload_mangle(struct flow_action_entry *entry, static void flow_offload_mangle(struct flow_action_entry *entry,
enum flow_action_mangle_base htype, enum flow_action_mangle_base htype, u32 offset,
u32 offset, u8 *value, u8 *mask) const __be32 *value, const __be32 *mask)
{ {
entry->id = FLOW_ACTION_MANGLE; entry->id = FLOW_ACTION_MANGLE;
entry->mangle.htype = htype; entry->mangle.htype = htype;
@ -140,12 +150,12 @@ static int flow_offload_eth_src(struct net *net,
memcpy(&val16, dev->dev_addr, 2); memcpy(&val16, dev->dev_addr, 2);
val = val16 << 16; val = val16 << 16;
flow_offload_mangle(entry0, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4, flow_offload_mangle(entry0, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4,
(u8 *)&val, (u8 *)&mask); &val, &mask);
mask = ~0xffffffff; mask = ~0xffffffff;
memcpy(&val, dev->dev_addr + 2, 4); memcpy(&val, dev->dev_addr + 2, 4);
flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 8, flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 8,
(u8 *)&val, (u8 *)&mask); &val, &mask);
dev_put(dev); dev_put(dev);
return 0; return 0;
@ -170,13 +180,13 @@ static int flow_offload_eth_dst(struct net *net,
mask = ~0xffffffff; mask = ~0xffffffff;
memcpy(&val, n->ha, 4); memcpy(&val, n->ha, 4);
flow_offload_mangle(entry0, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 0, flow_offload_mangle(entry0, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 0,
(u8 *)&val, (u8 *)&mask); &val, &mask);
mask = ~0x0000ffff; mask = ~0x0000ffff;
memcpy(&val16, n->ha + 4, 2); memcpy(&val16, n->ha + 4, 2);
val = val16; val = val16;
flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4, flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4,
(u8 *)&val, (u8 *)&mask); &val, &mask);
neigh_release(n); neigh_release(n);
return 0; return 0;
@ -206,7 +216,7 @@ static void flow_offload_ipv4_snat(struct net *net,
} }
flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset, flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset,
(u8 *)&addr, (u8 *)&mask); &addr, &mask);
} }
static void flow_offload_ipv4_dnat(struct net *net, static void flow_offload_ipv4_dnat(struct net *net,
@ -233,12 +243,12 @@ static void flow_offload_ipv4_dnat(struct net *net,
} }
flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset, flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset,
(u8 *)&addr, (u8 *)&mask); &addr, &mask);
} }
static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule, static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule,
unsigned int offset, unsigned int offset,
u8 *addr, u8 *mask) const __be32 *addr, const __be32 *mask)
{ {
struct flow_action_entry *entry; struct flow_action_entry *entry;
int i; int i;
@ -246,8 +256,7 @@ static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule,
for (i = 0; i < sizeof(struct in6_addr) / sizeof(u32); i += sizeof(u32)) { for (i = 0; i < sizeof(struct in6_addr) / sizeof(u32); i += sizeof(u32)) {
entry = flow_action_entry_next(flow_rule); entry = flow_action_entry_next(flow_rule);
flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP6, flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP6,
offset + i, offset + i, &addr[i], mask);
&addr[i], mask);
} }
} }
@ -257,23 +266,23 @@ static void flow_offload_ipv6_snat(struct net *net,
struct nf_flow_rule *flow_rule) struct nf_flow_rule *flow_rule)
{ {
u32 mask = ~htonl(0xffffffff); u32 mask = ~htonl(0xffffffff);
const u8 *addr; const __be32 *addr;
u32 offset; u32 offset;
switch (dir) { switch (dir) {
case FLOW_OFFLOAD_DIR_ORIGINAL: case FLOW_OFFLOAD_DIR_ORIGINAL:
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6.s6_addr; addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6.s6_addr32;
offset = offsetof(struct ipv6hdr, saddr); offset = offsetof(struct ipv6hdr, saddr);
break; break;
case FLOW_OFFLOAD_DIR_REPLY: case FLOW_OFFLOAD_DIR_REPLY:
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6.s6_addr; addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6.s6_addr32;
offset = offsetof(struct ipv6hdr, daddr); offset = offsetof(struct ipv6hdr, daddr);
break; break;
default: default:
return; return;
} }
flow_offload_ipv6_mangle(flow_rule, offset, (u8 *)addr, (u8 *)&mask); flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);
} }
static void flow_offload_ipv6_dnat(struct net *net, static void flow_offload_ipv6_dnat(struct net *net,
@ -282,23 +291,23 @@ static void flow_offload_ipv6_dnat(struct net *net,
struct nf_flow_rule *flow_rule) struct nf_flow_rule *flow_rule)
{ {
u32 mask = ~htonl(0xffffffff); u32 mask = ~htonl(0xffffffff);
const u8 *addr; const __be32 *addr;
u32 offset; u32 offset;
switch (dir) { switch (dir) {
case FLOW_OFFLOAD_DIR_ORIGINAL: case FLOW_OFFLOAD_DIR_ORIGINAL:
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6.s6_addr; addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6.s6_addr32;
offset = offsetof(struct ipv6hdr, daddr); offset = offsetof(struct ipv6hdr, daddr);
break; break;
case FLOW_OFFLOAD_DIR_REPLY: case FLOW_OFFLOAD_DIR_REPLY:
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6.s6_addr; addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6.s6_addr32;
offset = offsetof(struct ipv6hdr, saddr); offset = offsetof(struct ipv6hdr, saddr);
break; break;
default: default:
return; return;
} }
flow_offload_ipv6_mangle(flow_rule, offset, (u8 *)addr, (u8 *)&mask); flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);
} }
static int flow_offload_l4proto(const struct flow_offload *flow) static int flow_offload_l4proto(const struct flow_offload *flow)
@ -326,25 +335,24 @@ static void flow_offload_port_snat(struct net *net,
struct nf_flow_rule *flow_rule) struct nf_flow_rule *flow_rule)
{ {
struct flow_action_entry *entry = flow_action_entry_next(flow_rule); struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
u32 mask = ~htonl(0xffff0000); u32 mask = ~htonl(0xffff0000), port;
__be16 port;
u32 offset; u32 offset;
switch (dir) { switch (dir) {
case FLOW_OFFLOAD_DIR_ORIGINAL: case FLOW_OFFLOAD_DIR_ORIGINAL:
port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port; port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
offset = 0; /* offsetof(struct tcphdr, source); */ offset = 0; /* offsetof(struct tcphdr, source); */
break; break;
case FLOW_OFFLOAD_DIR_REPLY: case FLOW_OFFLOAD_DIR_REPLY:
port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port; port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
offset = 0; /* offsetof(struct tcphdr, dest); */ offset = 0; /* offsetof(struct tcphdr, dest); */
break; break;
default: default:
break; return;
} }
port = htonl(port << 16);
flow_offload_mangle(entry, flow_offload_l4proto(flow), offset, flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
(u8 *)&port, (u8 *)&mask); &port, &mask);
} }
static void flow_offload_port_dnat(struct net *net, static void flow_offload_port_dnat(struct net *net,
@ -353,25 +361,24 @@ static void flow_offload_port_dnat(struct net *net,
struct nf_flow_rule *flow_rule) struct nf_flow_rule *flow_rule)
{ {
struct flow_action_entry *entry = flow_action_entry_next(flow_rule); struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
u32 mask = ~htonl(0xffff); u32 mask = ~htonl(0xffff), port;
__be16 port;
u32 offset; u32 offset;
switch (dir) { switch (dir) {
case FLOW_OFFLOAD_DIR_ORIGINAL: case FLOW_OFFLOAD_DIR_ORIGINAL:
port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port; port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
offset = 0; /* offsetof(struct tcphdr, source); */ offset = 0; /* offsetof(struct tcphdr, source); */
break; break;
case FLOW_OFFLOAD_DIR_REPLY: case FLOW_OFFLOAD_DIR_REPLY:
port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port; port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
offset = 0; /* offsetof(struct tcphdr, dest); */ offset = 0; /* offsetof(struct tcphdr, dest); */
break; break;
default: default:
break; return;
} }
port = htonl(port);
flow_offload_mangle(entry, flow_offload_l4proto(flow), offset, flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
(u8 *)&port, (u8 *)&mask); &port, &mask);
} }
static void flow_offload_ipv4_checksum(struct net *net, static void flow_offload_ipv4_checksum(struct net *net,
@ -574,7 +581,7 @@ static int flow_offload_tuple_add(struct flow_offload_work *offload,
cls_flow.rule = flow_rule->rule; cls_flow.rule = flow_rule->rule;
list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list) { list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list) {
err = block_cb->cb(TC_SETUP_FT, &cls_flow, err = block_cb->cb(TC_SETUP_CLSFLOWER, &cls_flow,
block_cb->cb_priv); block_cb->cb_priv);
if (err < 0) if (err < 0)
continue; continue;
@ -599,7 +606,7 @@ static void flow_offload_tuple_del(struct flow_offload_work *offload,
&offload->flow->tuplehash[dir].tuple, &extack); &offload->flow->tuplehash[dir].tuple, &extack);
list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list) list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list)
block_cb->cb(TC_SETUP_FT, &cls_flow, block_cb->cb_priv); block_cb->cb(TC_SETUP_CLSFLOWER, &cls_flow, block_cb->cb_priv);
offload->flow->flags |= FLOW_OFFLOAD_HW_DEAD; offload->flow->flags |= FLOW_OFFLOAD_HW_DEAD;
} }
@ -656,7 +663,7 @@ static void flow_offload_tuple_stats(struct flow_offload_work *offload,
&offload->flow->tuplehash[dir].tuple, &extack); &offload->flow->tuplehash[dir].tuple, &extack);
list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list) list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list)
block_cb->cb(TC_SETUP_FT, &cls_flow, block_cb->cb_priv); block_cb->cb(TC_SETUP_CLSFLOWER, &cls_flow, block_cb->cb_priv);
memcpy(stats, &cls_flow.stats, sizeof(*stats)); memcpy(stats, &cls_flow.stats, sizeof(*stats));
} }
@ -822,7 +829,7 @@ int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,
bo.extack = &extack; bo.extack = &extack;
INIT_LIST_HEAD(&bo.cb_list); INIT_LIST_HEAD(&bo.cb_list);
err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo); err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_FT, &bo);
if (err < 0) if (err < 0)
return err; return err;

View File

@ -189,7 +189,7 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
goto err; goto err;
} }
if (!skb_dst_force(skb) && state->hook != NF_INET_PRE_ROUTING) { if (skb_dst(skb) && !skb_dst_force(skb)) {
status = -ENETDOWN; status = -ENETDOWN;
goto err; goto err;
} }

View File

@ -4519,8 +4519,10 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
return err; return err;
err = -EINVAL; err = -EINVAL;
if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) {
nft_data_release(&elem.key.val, desc.type);
return err; return err;
}
priv = set->ops->get(ctx->net, set, &elem, flags); priv = set->ops->get(ctx->net, set, &elem, flags);
if (IS_ERR(priv)) if (IS_ERR(priv))
@ -4756,14 +4758,20 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
if (nla[NFTA_SET_ELEM_DATA] == NULL && if (nla[NFTA_SET_ELEM_DATA] == NULL &&
!(flags & NFT_SET_ELEM_INTERVAL_END)) !(flags & NFT_SET_ELEM_INTERVAL_END))
return -EINVAL; return -EINVAL;
if (nla[NFTA_SET_ELEM_DATA] != NULL &&
flags & NFT_SET_ELEM_INTERVAL_END)
return -EINVAL;
} else { } else {
if (nla[NFTA_SET_ELEM_DATA] != NULL) if (nla[NFTA_SET_ELEM_DATA] != NULL)
return -EINVAL; return -EINVAL;
} }
if ((flags & NFT_SET_ELEM_INTERVAL_END) &&
(nla[NFTA_SET_ELEM_DATA] ||
nla[NFTA_SET_ELEM_OBJREF] ||
nla[NFTA_SET_ELEM_TIMEOUT] ||
nla[NFTA_SET_ELEM_EXPIRATION] ||
nla[NFTA_SET_ELEM_USERDATA] ||
nla[NFTA_SET_ELEM_EXPR]))
return -EINVAL;
timeout = 0; timeout = 0;
if (nla[NFTA_SET_ELEM_TIMEOUT] != NULL) { if (nla[NFTA_SET_ELEM_TIMEOUT] != NULL) {
if (!(set->flags & NFT_SET_TIMEOUT)) if (!(set->flags & NFT_SET_TIMEOUT))
@ -5476,7 +5484,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
if (nlh->nlmsg_flags & NLM_F_REPLACE) if (nlh->nlmsg_flags & NLM_F_REPLACE)
return -EOPNOTSUPP; return -EOPNOTSUPP;
type = nft_obj_type_get(net, objtype); type = __nft_obj_type_get(objtype);
nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
return nf_tables_updobj(&ctx, type, nla[NFTA_OBJ_DATA], obj); return nf_tables_updobj(&ctx, type, nla[NFTA_OBJ_DATA], obj);

View File

@ -44,6 +44,9 @@ struct nft_flow_rule *nft_flow_rule_create(struct net *net,
expr = nft_expr_next(expr); expr = nft_expr_next(expr);
} }
if (num_actions == 0)
return ERR_PTR(-EOPNOTSUPP);
flow = nft_flow_rule_alloc(num_actions); flow = nft_flow_rule_alloc(num_actions);
if (!flow) if (!flow)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -577,6 +580,9 @@ static int nft_offload_netdev_event(struct notifier_block *this,
struct net *net = dev_net(dev); struct net *net = dev_net(dev);
struct nft_chain *chain; struct nft_chain *chain;
if (event != NETDEV_UNREGISTER)
return NOTIFY_DONE;
mutex_lock(&net->nft.commit_mutex); mutex_lock(&net->nft.commit_mutex);
chain = __nft_offload_get_chain(dev); chain = __nft_offload_get_chain(dev);
if (chain) if (chain)

View File

@ -80,7 +80,7 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
tb[NFTA_BITWISE_MASK]); tb[NFTA_BITWISE_MASK]);
if (err < 0) if (err < 0)
return err; return err;
if (d1.len != priv->len) { if (d1.type != NFT_DATA_VALUE || d1.len != priv->len) {
err = -EINVAL; err = -EINVAL;
goto err1; goto err1;
} }
@ -89,7 +89,7 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
tb[NFTA_BITWISE_XOR]); tb[NFTA_BITWISE_XOR]);
if (err < 0) if (err < 0)
goto err1; goto err1;
if (d2.len != priv->len) { if (d2.type != NFT_DATA_VALUE || d2.len != priv->len) {
err = -EINVAL; err = -EINVAL;
goto err2; goto err2;
} }

View File

@ -81,6 +81,12 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
if (err < 0) if (err < 0)
return err; return err;
if (desc.type != NFT_DATA_VALUE) {
err = -EINVAL;
nft_data_release(&priv->data, desc.type);
return err;
}
priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]); priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]);
err = nft_validate_register_load(priv->sreg, desc.len); err = nft_validate_register_load(priv->sreg, desc.len);
if (err < 0) if (err < 0)

View File

@ -66,11 +66,21 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr
if (err < 0) if (err < 0)
return err; return err;
if (desc_from.type != NFT_DATA_VALUE) {
err = -EINVAL;
goto err1;
}
err = nft_data_init(NULL, &priv->data_to, sizeof(priv->data_to), err = nft_data_init(NULL, &priv->data_to, sizeof(priv->data_to),
&desc_to, tb[NFTA_RANGE_TO_DATA]); &desc_to, tb[NFTA_RANGE_TO_DATA]);
if (err < 0) if (err < 0)
goto err1; goto err1;
if (desc_to.type != NFT_DATA_VALUE) {
err = -EINVAL;
goto err2;
}
if (desc_from.len != desc_to.len) { if (desc_from.len != desc_to.len) {
err = -EINVAL; err = -EINVAL;
goto err2; goto err2;

View File

@ -74,8 +74,13 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
parent = rcu_dereference_raw(parent->rb_left); parent = rcu_dereference_raw(parent->rb_left);
continue; continue;
} }
if (nft_rbtree_interval_end(rbe)) if (nft_rbtree_interval_end(rbe)) {
goto out; if (nft_set_is_anonymous(set))
return false;
parent = rcu_dereference_raw(parent->rb_left);
interval = NULL;
continue;
}
*ext = &rbe->ext; *ext = &rbe->ext;
return true; return true;
@ -88,7 +93,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
*ext = &interval->ext; *ext = &interval->ext;
return true; return true;
} }
out:
return false; return false;
} }
@ -139,8 +144,10 @@ static bool __nft_rbtree_get(const struct net *net, const struct nft_set *set,
if (flags & NFT_SET_ELEM_INTERVAL_END) if (flags & NFT_SET_ELEM_INTERVAL_END)
interval = rbe; interval = rbe;
} else { } else {
if (!nft_set_elem_active(&rbe->ext, genmask)) if (!nft_set_elem_active(&rbe->ext, genmask)) {
parent = rcu_dereference_raw(parent->rb_left); parent = rcu_dereference_raw(parent->rb_left);
continue;
}
if (!nft_set_ext_exists(&rbe->ext, NFT_SET_EXT_FLAGS) || if (!nft_set_ext_exists(&rbe->ext, NFT_SET_EXT_FLAGS) ||
(*nft_set_ext_flags(&rbe->ext) & NFT_SET_ELEM_INTERVAL_END) == (*nft_set_ext_flags(&rbe->ext) & NFT_SET_ELEM_INTERVAL_END) ==
@ -148,7 +155,11 @@ static bool __nft_rbtree_get(const struct net *net, const struct nft_set *set,
*elem = rbe; *elem = rbe;
return true; return true;
} }
return false;
if (nft_rbtree_interval_end(rbe))
interval = NULL;
parent = rcu_dereference_raw(parent->rb_left);
} }
} }

View File

@ -8,9 +8,14 @@ ksft_skip=4
ret=0 ret=0
test_inet_nat=true test_inet_nat=true
sfx=$(mktemp -u "XXXXXXXX")
ns0="ns0-$sfx"
ns1="ns1-$sfx"
ns2="ns2-$sfx"
cleanup() cleanup()
{ {
for i in 0 1 2; do ip netns del ns$i;done for i in 0 1 2; do ip netns del ns$i-"$sfx";done
} }
nft --version > /dev/null 2>&1 nft --version > /dev/null 2>&1
@ -25,40 +30,49 @@ if [ $? -ne 0 ];then
exit $ksft_skip exit $ksft_skip
fi fi
ip netns add ns0 ip netns add "$ns0"
if [ $? -ne 0 ];then if [ $? -ne 0 ];then
echo "SKIP: Could not create net namespace" echo "SKIP: Could not create net namespace $ns0"
exit $ksft_skip exit $ksft_skip
fi fi
trap cleanup EXIT trap cleanup EXIT
ip netns add ns1 ip netns add "$ns1"
ip netns add ns2 if [ $? -ne 0 ];then
echo "SKIP: Could not create net namespace $ns1"
exit $ksft_skip
fi
ip link add veth0 netns ns0 type veth peer name eth0 netns ns1 > /dev/null 2>&1 ip netns add "$ns2"
if [ $? -ne 0 ];then
echo "SKIP: Could not create net namespace $ns2"
exit $ksft_skip
fi
ip link add veth0 netns "$ns0" type veth peer name eth0 netns "$ns1" > /dev/null 2>&1
if [ $? -ne 0 ];then if [ $? -ne 0 ];then
echo "SKIP: No virtual ethernet pair device support in kernel" echo "SKIP: No virtual ethernet pair device support in kernel"
exit $ksft_skip exit $ksft_skip
fi fi
ip link add veth1 netns ns0 type veth peer name eth0 netns ns2 ip link add veth1 netns "$ns0" type veth peer name eth0 netns "$ns2"
ip -net ns0 link set lo up ip -net "$ns0" link set lo up
ip -net ns0 link set veth0 up ip -net "$ns0" link set veth0 up
ip -net ns0 addr add 10.0.1.1/24 dev veth0 ip -net "$ns0" addr add 10.0.1.1/24 dev veth0
ip -net ns0 addr add dead:1::1/64 dev veth0 ip -net "$ns0" addr add dead:1::1/64 dev veth0
ip -net ns0 link set veth1 up ip -net "$ns0" link set veth1 up
ip -net ns0 addr add 10.0.2.1/24 dev veth1 ip -net "$ns0" addr add 10.0.2.1/24 dev veth1
ip -net ns0 addr add dead:2::1/64 dev veth1 ip -net "$ns0" addr add dead:2::1/64 dev veth1
for i in 1 2; do for i in 1 2; do
ip -net ns$i link set lo up ip -net ns$i-$sfx link set lo up
ip -net ns$i link set eth0 up ip -net ns$i-$sfx link set eth0 up
ip -net ns$i addr add 10.0.$i.99/24 dev eth0 ip -net ns$i-$sfx addr add 10.0.$i.99/24 dev eth0
ip -net ns$i route add default via 10.0.$i.1 ip -net ns$i-$sfx route add default via 10.0.$i.1
ip -net ns$i addr add dead:$i::99/64 dev eth0 ip -net ns$i-$sfx addr add dead:$i::99/64 dev eth0
ip -net ns$i route add default via dead:$i::1 ip -net ns$i-$sfx route add default via dead:$i::1
done done
bad_counter() bad_counter()
@ -66,8 +80,9 @@ bad_counter()
local ns=$1 local ns=$1
local counter=$2 local counter=$2
local expect=$3 local expect=$3
local tag=$4
echo "ERROR: $counter counter in $ns has unexpected value (expected $expect)" 1>&2 echo "ERROR: $counter counter in $ns has unexpected value (expected $expect) at $tag" 1>&2
ip netns exec $ns nft list counter inet filter $counter 1>&2 ip netns exec $ns nft list counter inet filter $counter 1>&2
} }
@ -78,24 +93,24 @@ check_counters()
cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84") cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter $ns ns0in "packets 1 bytes 84" bad_counter $ns ns0in "packets 1 bytes 84" "check_counters 1"
lret=1 lret=1
fi fi
cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84") cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter $ns ns0out "packets 1 bytes 84" bad_counter $ns ns0out "packets 1 bytes 84" "check_counters 2"
lret=1 lret=1
fi fi
expect="packets 1 bytes 104" expect="packets 1 bytes 104"
cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect") cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter $ns ns0in6 "$expect" bad_counter $ns ns0in6 "$expect" "check_counters 3"
lret=1 lret=1
fi fi
cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect") cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter $ns ns0out6 "$expect" bad_counter $ns ns0out6 "$expect" "check_counters 4"
lret=1 lret=1
fi fi
@ -107,41 +122,41 @@ check_ns0_counters()
local ns=$1 local ns=$1
local lret=0 local lret=0
cnt=$(ip netns exec ns0 nft list counter inet filter ns0in | grep -q "packets 0 bytes 0") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0in | grep -q "packets 0 bytes 0")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 ns0in "packets 0 bytes 0" bad_counter "$ns0" ns0in "packets 0 bytes 0" "check_ns0_counters 1"
lret=1 lret=1
fi fi
cnt=$(ip netns exec ns0 nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 ns0in6 "packets 0 bytes 0" bad_counter "$ns0" ns0in6 "packets 0 bytes 0"
lret=1 lret=1
fi fi
cnt=$(ip netns exec ns0 nft list counter inet filter ns0out | grep -q "packets 0 bytes 0") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0out | grep -q "packets 0 bytes 0")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 ns0out "packets 0 bytes 0" bad_counter "$ns0" ns0out "packets 0 bytes 0" "check_ns0_counters 2"
lret=1 lret=1
fi fi
cnt=$(ip netns exec ns0 nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 ns0out6 "packets 0 bytes 0" bad_counter "$ns0" ns0out6 "packets 0 bytes 0" "check_ns0_counters3 "
lret=1 lret=1
fi fi
for dir in "in" "out" ; do for dir in "in" "out" ; do
expect="packets 1 bytes 84" expect="packets 1 bytes 84"
cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ${ns}${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 $ns$dir "$expect" bad_counter "$ns0" $ns$dir "$expect" "check_ns0_counters 4"
lret=1 lret=1
fi fi
expect="packets 1 bytes 104" expect="packets 1 bytes 104"
cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir}6 | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ${ns}${dir}6 | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 $ns$dir6 "$expect" bad_counter "$ns0" $ns$dir6 "$expect" "check_ns0_counters 5"
lret=1 lret=1
fi fi
done done
@ -152,7 +167,7 @@ check_ns0_counters()
reset_counters() reset_counters()
{ {
for i in 0 1 2;do for i in 0 1 2;do
ip netns exec ns$i nft reset counters inet > /dev/null ip netns exec ns$i-$sfx nft reset counters inet > /dev/null
done done
} }
@ -166,7 +181,7 @@ test_local_dnat6()
IPF="ip6" IPF="ip6"
fi fi
ip netns exec ns0 nft -f - <<EOF ip netns exec "$ns0" nft -f /dev/stdin <<EOF
table $family nat { table $family nat {
chain output { chain output {
type nat hook output priority 0; policy accept; type nat hook output priority 0; policy accept;
@ -180,7 +195,7 @@ EOF
fi fi
# ping netns1, expect rewrite to netns2 # ping netns1, expect rewrite to netns2
ip netns exec ns0 ping -q -c 1 dead:1::99 > /dev/null ip netns exec "$ns0" ping -q -c 1 dead:1::99 > /dev/null
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
lret=1 lret=1
echo "ERROR: ping6 failed" echo "ERROR: ping6 failed"
@ -189,18 +204,18 @@ EOF
expect="packets 0 bytes 0" expect="packets 0 bytes 0"
for dir in "in6" "out6" ; do for dir in "in6" "out6" ; do
cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 ns1$dir "$expect" bad_counter "$ns0" ns1$dir "$expect" "test_local_dnat6 1"
lret=1 lret=1
fi fi
done done
expect="packets 1 bytes 104" expect="packets 1 bytes 104"
for dir in "in6" "out6" ; do for dir in "in6" "out6" ; do
cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 ns2$dir "$expect" bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat6 2"
lret=1 lret=1
fi fi
done done
@ -208,9 +223,9 @@ EOF
# expect 0 count in ns1 # expect 0 count in ns1
expect="packets 0 bytes 0" expect="packets 0 bytes 0"
for dir in "in6" "out6" ; do for dir in "in6" "out6" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns0$dir "$expect" bad_counter "$ns1" ns0$dir "$expect" "test_local_dnat6 3"
lret=1 lret=1
fi fi
done done
@ -218,15 +233,15 @@ EOF
# expect 1 packet in ns2 # expect 1 packet in ns2
expect="packets 1 bytes 104" expect="packets 1 bytes 104"
for dir in "in6" "out6" ; do for dir in "in6" "out6" ; do
cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns2 ns0$dir "$expect" bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat6 4"
lret=1 lret=1
fi fi
done done
test $lret -eq 0 && echo "PASS: ipv6 ping to ns1 was $family NATted to ns2" test $lret -eq 0 && echo "PASS: ipv6 ping to $ns1 was $family NATted to $ns2"
ip netns exec ns0 nft flush chain ip6 nat output ip netns exec "$ns0" nft flush chain ip6 nat output
return $lret return $lret
} }
@ -241,7 +256,7 @@ test_local_dnat()
IPF="ip" IPF="ip"
fi fi
ip netns exec ns0 nft -f - <<EOF 2>/dev/null ip netns exec "$ns0" nft -f /dev/stdin <<EOF 2>/dev/null
table $family nat { table $family nat {
chain output { chain output {
type nat hook output priority 0; policy accept; type nat hook output priority 0; policy accept;
@ -260,7 +275,7 @@ EOF
fi fi
# ping netns1, expect rewrite to netns2 # ping netns1, expect rewrite to netns2
ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null ip netns exec "$ns0" ping -q -c 1 10.0.1.99 > /dev/null
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
lret=1 lret=1
echo "ERROR: ping failed" echo "ERROR: ping failed"
@ -269,18 +284,18 @@ EOF
expect="packets 0 bytes 0" expect="packets 0 bytes 0"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 ns1$dir "$expect" bad_counter "$ns0" ns1$dir "$expect" "test_local_dnat 1"
lret=1 lret=1
fi fi
done done
expect="packets 1 bytes 84" expect="packets 1 bytes 84"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 ns2$dir "$expect" bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat 2"
lret=1 lret=1
fi fi
done done
@ -288,9 +303,9 @@ EOF
# expect 0 count in ns1 # expect 0 count in ns1
expect="packets 0 bytes 0" expect="packets 0 bytes 0"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns0$dir "$expect" bad_counter "$ns1" ns0$dir "$expect" "test_local_dnat 3"
lret=1 lret=1
fi fi
done done
@ -298,19 +313,19 @@ EOF
# expect 1 packet in ns2 # expect 1 packet in ns2
expect="packets 1 bytes 84" expect="packets 1 bytes 84"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns2 ns0$dir "$expect" bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat 4"
lret=1 lret=1
fi fi
done done
test $lret -eq 0 && echo "PASS: ping to ns1 was $family NATted to ns2" test $lret -eq 0 && echo "PASS: ping to $ns1 was $family NATted to $ns2"
ip netns exec ns0 nft flush chain $family nat output ip netns exec "$ns0" nft flush chain $family nat output
reset_counters reset_counters
ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null ip netns exec "$ns0" ping -q -c 1 10.0.1.99 > /dev/null
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
lret=1 lret=1
echo "ERROR: ping failed" echo "ERROR: ping failed"
@ -319,17 +334,17 @@ EOF
expect="packets 1 bytes 84" expect="packets 1 bytes 84"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns1$dir "$expect" bad_counter "$ns1" ns1$dir "$expect" "test_local_dnat 5"
lret=1 lret=1
fi fi
done done
expect="packets 0 bytes 0" expect="packets 0 bytes 0"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 ns2$dir "$expect" bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat 6"
lret=1 lret=1
fi fi
done done
@ -337,9 +352,9 @@ EOF
# expect 1 count in ns1 # expect 1 count in ns1
expect="packets 1 bytes 84" expect="packets 1 bytes 84"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns0 ns0$dir "$expect" bad_counter "$ns0" ns0$dir "$expect" "test_local_dnat 7"
lret=1 lret=1
fi fi
done done
@ -347,14 +362,14 @@ EOF
# expect 0 packet in ns2 # expect 0 packet in ns2
expect="packets 0 bytes 0" expect="packets 0 bytes 0"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns2 ns2$dir "$expect" bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat 8"
lret=1 lret=1
fi fi
done done
test $lret -eq 0 && echo "PASS: ping to ns1 OK after $family nat output chain flush" test $lret -eq 0 && echo "PASS: ping to $ns1 OK after $family nat output chain flush"
return $lret return $lret
} }
@ -366,26 +381,26 @@ test_masquerade6()
local natflags=$2 local natflags=$2
local lret=0 local lret=0
ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "ERROR: cannot ping ns1 from ns2 via ipv6" echo "ERROR: cannot ping $ns1 from $ns2 via ipv6"
return 1 return 1
lret=1 lret=1
fi fi
expect="packets 1 bytes 104" expect="packets 1 bytes 104"
for dir in "in6" "out6" ; do for dir in "in6" "out6" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns2$dir "$expect" bad_counter "$ns1" ns2$dir "$expect" "test_masquerade6 1"
lret=1 lret=1
fi fi
cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns2 ns1$dir "$expect" bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 2"
lret=1 lret=1
fi fi
done done
@ -393,7 +408,7 @@ test_masquerade6()
reset_counters reset_counters
# add masquerading rule # add masquerading rule
ip netns exec ns0 nft -f - <<EOF ip netns exec "$ns0" nft -f /dev/stdin <<EOF
table $family nat { table $family nat {
chain postrouting { chain postrouting {
type nat hook postrouting priority 0; policy accept; type nat hook postrouting priority 0; policy accept;
@ -406,24 +421,24 @@ EOF
return $ksft_skip return $ksft_skip
fi fi
ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "ERROR: cannot ping ns1 from ns2 with active $family masquerade $natflags" echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags"
lret=1 lret=1
fi fi
# ns1 should have seen packets from ns0, due to masquerade # ns1 should have seen packets from ns0, due to masquerade
expect="packets 1 bytes 104" expect="packets 1 bytes 104"
for dir in "in6" "out6" ; do for dir in "in6" "out6" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns0$dir "$expect" bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 3"
lret=1 lret=1
fi fi
cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns2 ns1$dir "$expect" bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 4"
lret=1 lret=1
fi fi
done done
@ -431,32 +446,32 @@ EOF
# ns1 should not have seen packets from ns2, due to masquerade # ns1 should not have seen packets from ns2, due to masquerade
expect="packets 0 bytes 0" expect="packets 0 bytes 0"
for dir in "in6" "out6" ; do for dir in "in6" "out6" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns0$dir "$expect" bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 5"
lret=1 lret=1
fi fi
cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns2 ns1$dir "$expect" bad_counter "$ns0" ns1$dir "$expect" "test_masquerade6 6"
lret=1 lret=1
fi fi
done done
ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerade $natflags (attempt 2)" echo "ERROR: cannot ping $ns1 from $ns2 with active ipv6 masquerade $natflags (attempt 2)"
lret=1 lret=1
fi fi
ip netns exec ns0 nft flush chain $family nat postrouting ip netns exec "$ns0" nft flush chain $family nat postrouting
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "ERROR: Could not flush $family nat postrouting" 1>&2 echo "ERROR: Could not flush $family nat postrouting" 1>&2
lret=1 lret=1
fi fi
test $lret -eq 0 && echo "PASS: $family IPv6 masquerade $natflags for ns2" test $lret -eq 0 && echo "PASS: $family IPv6 masquerade $natflags for $ns2"
return $lret return $lret
} }
@ -467,26 +482,26 @@ test_masquerade()
local natflags=$2 local natflags=$2
local lret=0 local lret=0
ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "ERROR: cannot ping ns1 from ns2 $natflags" echo "ERROR: cannot ping $ns1 from "$ns2" $natflags"
lret=1 lret=1
fi fi
expect="packets 1 bytes 84" expect="packets 1 bytes 84"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns2$dir "$expect" bad_counter "$ns1" ns2$dir "$expect" "test_masquerade 1"
lret=1 lret=1
fi fi
cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns2 ns1$dir "$expect" bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 2"
lret=1 lret=1
fi fi
done done
@ -494,7 +509,7 @@ test_masquerade()
reset_counters reset_counters
# add masquerading rule # add masquerading rule
ip netns exec ns0 nft -f - <<EOF ip netns exec "$ns0" nft -f /dev/stdin <<EOF
table $family nat { table $family nat {
chain postrouting { chain postrouting {
type nat hook postrouting priority 0; policy accept; type nat hook postrouting priority 0; policy accept;
@ -507,24 +522,24 @@ EOF
return $ksft_skip return $ksft_skip
fi fi
ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "ERROR: cannot ping ns1 from ns2 with active $family masquerade $natflags" echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags"
lret=1 lret=1
fi fi
# ns1 should have seen packets from ns0, due to masquerade # ns1 should have seen packets from ns0, due to masquerade
expect="packets 1 bytes 84" expect="packets 1 bytes 84"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns0$dir "$expect" bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 3"
lret=1 lret=1
fi fi
cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns2 ns1$dir "$expect" bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 4"
lret=1 lret=1
fi fi
done done
@ -532,32 +547,32 @@ EOF
# ns1 should not have seen packets from ns2, due to masquerade # ns1 should not have seen packets from ns2, due to masquerade
expect="packets 0 bytes 0" expect="packets 0 bytes 0"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns0$dir "$expect" bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 5"
lret=1 lret=1
fi fi
cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns2 ns1$dir "$expect" bad_counter "$ns0" ns1$dir "$expect" "test_masquerade 6"
lret=1 lret=1
fi fi
done done
ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "ERROR: cannot ping ns1 from ns2 with active ip masquerade $natflags (attempt 2)" echo "ERROR: cannot ping $ns1 from $ns2 with active ip masquerade $natflags (attempt 2)"
lret=1 lret=1
fi fi
ip netns exec ns0 nft flush chain $family nat postrouting ip netns exec "$ns0" nft flush chain $family nat postrouting
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "ERROR: Could not flush $family nat postrouting" 1>&2 echo "ERROR: Could not flush $family nat postrouting" 1>&2
lret=1 lret=1
fi fi
test $lret -eq 0 && echo "PASS: $family IP masquerade $natflags for ns2" test $lret -eq 0 && echo "PASS: $family IP masquerade $natflags for $ns2"
return $lret return $lret
} }
@ -567,25 +582,25 @@ test_redirect6()
local family=$1 local family=$1
local lret=0 local lret=0
ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "ERROR: cannnot ping ns1 from ns2 via ipv6" echo "ERROR: cannnot ping $ns1 from $ns2 via ipv6"
lret=1 lret=1
fi fi
expect="packets 1 bytes 104" expect="packets 1 bytes 104"
for dir in "in6" "out6" ; do for dir in "in6" "out6" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns2$dir "$expect" bad_counter "$ns1" ns2$dir "$expect" "test_redirect6 1"
lret=1 lret=1
fi fi
cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns2 ns1$dir "$expect" bad_counter "$ns2" ns1$dir "$expect" "test_redirect6 2"
lret=1 lret=1
fi fi
done done
@ -593,7 +608,7 @@ test_redirect6()
reset_counters reset_counters
# add redirect rule # add redirect rule
ip netns exec ns0 nft -f - <<EOF ip netns exec "$ns0" nft -f /dev/stdin <<EOF
table $family nat { table $family nat {
chain prerouting { chain prerouting {
type nat hook prerouting priority 0; policy accept; type nat hook prerouting priority 0; policy accept;
@ -606,18 +621,18 @@ EOF
return $ksft_skip return $ksft_skip
fi fi
ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "ERROR: cannot ping ns1 from ns2 via ipv6 with active $family redirect" echo "ERROR: cannot ping $ns1 from $ns2 via ipv6 with active $family redirect"
lret=1 lret=1
fi fi
# ns1 should have seen no packets from ns2, due to redirection # ns1 should have seen no packets from ns2, due to redirection
expect="packets 0 bytes 0" expect="packets 0 bytes 0"
for dir in "in6" "out6" ; do for dir in "in6" "out6" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns0$dir "$expect" bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 3"
lret=1 lret=1
fi fi
done done
@ -625,20 +640,20 @@ EOF
# ns0 should have seen packets from ns2, due to masquerade # ns0 should have seen packets from ns2, due to masquerade
expect="packets 1 bytes 104" expect="packets 1 bytes 104"
for dir in "in6" "out6" ; do for dir in "in6" "out6" ; do
cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns0$dir "$expect" bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 4"
lret=1 lret=1
fi fi
done done
ip netns exec ns0 nft delete table $family nat ip netns exec "$ns0" nft delete table $family nat
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "ERROR: Could not delete $family nat table" 1>&2 echo "ERROR: Could not delete $family nat table" 1>&2
lret=1 lret=1
fi fi
test $lret -eq 0 && echo "PASS: $family IPv6 redirection for ns2" test $lret -eq 0 && echo "PASS: $family IPv6 redirection for $ns2"
return $lret return $lret
} }
@ -648,26 +663,26 @@ test_redirect()
local family=$1 local family=$1
local lret=0 local lret=0
ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "ERROR: cannot ping ns1 from ns2" echo "ERROR: cannot ping $ns1 from $ns2"
lret=1 lret=1
fi fi
expect="packets 1 bytes 84" expect="packets 1 bytes 84"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns2$dir "$expect" bad_counter "$ns1" $ns2$dir "$expect" "test_redirect 1"
lret=1 lret=1
fi fi
cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns2 ns1$dir "$expect" bad_counter "$ns2" ns1$dir "$expect" "test_redirect 2"
lret=1 lret=1
fi fi
done done
@ -675,7 +690,7 @@ test_redirect()
reset_counters reset_counters
# add redirect rule # add redirect rule
ip netns exec ns0 nft -f - <<EOF ip netns exec "$ns0" nft -f /dev/stdin <<EOF
table $family nat { table $family nat {
chain prerouting { chain prerouting {
type nat hook prerouting priority 0; policy accept; type nat hook prerouting priority 0; policy accept;
@ -688,9 +703,9 @@ EOF
return $ksft_skip return $ksft_skip
fi fi
ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "ERROR: cannot ping ns1 from ns2 with active $family ip redirect" echo "ERROR: cannot ping $ns1 from $ns2 with active $family ip redirect"
lret=1 lret=1
fi fi
@ -698,9 +713,9 @@ EOF
expect="packets 0 bytes 0" expect="packets 0 bytes 0"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns0$dir "$expect" bad_counter "$ns1" ns0$dir "$expect" "test_redirect 3"
lret=1 lret=1
fi fi
done done
@ -708,28 +723,28 @@ EOF
# ns0 should have seen packets from ns2, due to masquerade # ns0 should have seen packets from ns2, due to masquerade
expect="packets 1 bytes 84" expect="packets 1 bytes 84"
for dir in "in" "out" ; do for dir in "in" "out" ; do
cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect") cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
bad_counter ns1 ns0$dir "$expect" bad_counter "$ns0" ns0$dir "$expect" "test_redirect 4"
lret=1 lret=1
fi fi
done done
ip netns exec ns0 nft delete table $family nat ip netns exec "$ns0" nft delete table $family nat
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "ERROR: Could not delete $family nat table" 1>&2 echo "ERROR: Could not delete $family nat table" 1>&2
lret=1 lret=1
fi fi
test $lret -eq 0 && echo "PASS: $family IP redirection for ns2" test $lret -eq 0 && echo "PASS: $family IP redirection for $ns2"
return $lret return $lret
} }
# ip netns exec ns0 ping -c 1 -q 10.0.$i.99 # ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99
for i in 0 1 2; do for i in 0 1 2; do
ip netns exec ns$i nft -f - <<EOF ip netns exec ns$i-$sfx nft -f /dev/stdin <<EOF
table inet filter { table inet filter {
counter ns0in {} counter ns0in {}
counter ns1in {} counter ns1in {}
@ -796,18 +811,18 @@ done
sleep 3 sleep 3
# test basic connectivity # test basic connectivity
for i in 1 2; do for i in 1 2; do
ip netns exec ns0 ping -c 1 -q 10.0.$i.99 > /dev/null ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99 > /dev/null
if [ $? -ne 0 ];then if [ $? -ne 0 ];then
echo "ERROR: Could not reach other namespace(s)" 1>&2 echo "ERROR: Could not reach other namespace(s)" 1>&2
ret=1 ret=1
fi fi
ip netns exec ns0 ping -c 1 -q dead:$i::99 > /dev/null ip netns exec "$ns0" ping -c 1 -q dead:$i::99 > /dev/null
if [ $? -ne 0 ];then if [ $? -ne 0 ];then
echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2 echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2
ret=1 ret=1
fi fi
check_counters ns$i check_counters ns$i-$sfx
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
ret=1 ret=1
fi fi
@ -820,7 +835,7 @@ for i in 1 2; do
done done
if [ $ret -eq 0 ];then if [ $ret -eq 0 ];then
echo "PASS: netns routing/connectivity: ns0 can reach ns1 and ns2" echo "PASS: netns routing/connectivity: $ns0 can reach $ns1 and $ns2"
fi fi
reset_counters reset_counters
@ -846,4 +861,9 @@ reset_counters
$test_inet_nat && test_redirect inet $test_inet_nat && test_redirect inet
$test_inet_nat && test_redirect6 inet $test_inet_nat && test_redirect6 inet
if [ $ret -ne 0 ];then
echo -n "FAIL: "
nft --version
fi
exit $ret exit $ret