mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
Merge tag 'nf-next-26-08-10' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next
Pablo Neira Ayuso says:
====================
Netfilter updates for net
This includes an enhancement to detect ct memleaks easier via
DEBUG_NET and flowtable preparation patches for IPv4 over IPV6
and vice-versa. This also includes a fix for the nft_ct custom
expectation support.
1) Add DEBUG_NET_WARN_ON_ONCE to nf_ct_set() to spot ct memleaks.
2) Pass struct net_device_path_ctx to dev_fill_forward_path() to
make it easier to pass more parameters to this function.
From Lorenzo Bianconi.
3) Add ether_type field to net_device_path context structucture.
4) Rename tun.l3_proto field to tun.inner_proto.
5) Rename ctx.tun.proto to ctx.tun.inner_proto.
6) Store ether_type in flowtable context.
7) Move IPv4 and IPv6 xmit path to a helper function.
8) Move encapsulation header parser out of the flowtable lookup
function.
9) Rework nft_ct custom expectation support to address a possible
reallocation of ct extension area while expectation list also
contains expectations. Move datapath to a ct helper to fix it.
10) Ensure timeout is always lowered for the non-closing RST case
in the TCP connection tracking.
11) Bail out when inserting already dead expectation, this should
not ever happen, hence report it via DEBUG_NET.
12) Comestic updates for improving the conntrack selftest dump and
flush userspace program, from Qingshuang Fu.
* tag 'nf-next-26-08-10' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next:
selftests: netfilter: conntrack_dump_flush: remove unused variables and fix typo
netfilter: nf_conntrack_expect: bail out on insert dead expectations
netfilter: conntrack: always lower timeout for non-closing RST packets
netfilter: nft_ct: move custom expectation support to helper
netfilter: flowtable: detach layer 2 encapsulation parser from lookup
netfilter: flowtable: move ipv4 and ipv6 xmit path to function
netfilter: flowtable: store ethertype in flowtable context
netfilter: flowtable: rename ctx.tun.proto to ctx.tun.inner_proto
netfilter: flowtable: rename tun.l3_proto to tun.inner_proto
net: netfilter: add ether_type to net_device_path_ctx and use it
net: pass net_device_path_ctx to dev_fill_forward_path()
netfilter: add DEBUG_NET_WARN_ON_ONCE to skb_set_nfct()
====================
Link: https://patch.msgid.link/20260810194015.932627-1-pablo@netfilter.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -283,14 +283,19 @@ static int airoha_ppe_get_wdma_info(struct net_device *dev, const u8 *addr,
|
||||
struct airoha_wdma_info *info)
|
||||
{
|
||||
struct net_device_path_stack stack;
|
||||
struct net_device_path_ctx ctx = {
|
||||
.dev = dev,
|
||||
};
|
||||
struct net_device_path *path;
|
||||
int err;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
ether_addr_copy(ctx.daddr, addr);
|
||||
|
||||
rcu_read_lock();
|
||||
err = dev_fill_forward_path(dev, addr, &stack);
|
||||
err = dev_fill_forward_path(&ctx, &stack);
|
||||
rcu_read_unlock();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -92,6 +92,9 @@ static int
|
||||
mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_info *info)
|
||||
{
|
||||
struct net_device_path_stack stack;
|
||||
struct net_device_path_ctx ctx = {
|
||||
.dev = dev,
|
||||
};
|
||||
struct net_device_path *path;
|
||||
int err;
|
||||
|
||||
@@ -101,8 +104,10 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
|
||||
if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED))
|
||||
return -1;
|
||||
|
||||
ether_addr_copy(ctx.daddr, addr);
|
||||
|
||||
rcu_read_lock();
|
||||
err = dev_fill_forward_path(dev, addr, &stack);
|
||||
err = dev_fill_forward_path(&ctx, &stack);
|
||||
rcu_read_unlock();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -904,7 +904,7 @@ struct net_device_path {
|
||||
struct in6_addr dst_v6;
|
||||
};
|
||||
|
||||
u8 l3_proto;
|
||||
u8 inner_proto;
|
||||
} tun;
|
||||
struct {
|
||||
enum {
|
||||
@@ -941,6 +941,7 @@ struct net_device_path_stack {
|
||||
struct net_device_path_ctx {
|
||||
const struct net_device *dev;
|
||||
u8 daddr[ETH_ALEN];
|
||||
__be16 ether_type;
|
||||
|
||||
int num_vlans;
|
||||
struct {
|
||||
@@ -3428,7 +3429,7 @@ void dev_remove_offload(struct packet_offload *po);
|
||||
|
||||
int dev_get_iflink(const struct net_device *dev);
|
||||
int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
|
||||
int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
|
||||
int dev_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||
struct net_device_path_stack *stack);
|
||||
void dev_fill_forward_path_release(struct net_device_path_stack *stack);
|
||||
struct net_device *dev_get_by_name(struct net *net, const char *name);
|
||||
|
||||
@@ -5004,6 +5004,7 @@ static inline unsigned long skb_get_nfct(const struct sk_buff *skb)
|
||||
static inline void skb_set_nfct(struct sk_buff *skb, unsigned long nfct)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
|
||||
DEBUG_NET_WARN_ON_ONCE(skb->_nfct & NFCT_PTRMASK);
|
||||
skb->slow_gro |= !!nfct;
|
||||
skb->_nfct = nfct;
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -2131,7 +2131,7 @@ static inline void ip_vs_notrack(struct sk_buff *skb)
|
||||
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
||||
|
||||
if (ct) {
|
||||
nf_conntrack_put(&ct->ct_general);
|
||||
nf_reset_ct(skb);
|
||||
nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -106,6 +106,7 @@ void nf_ct_helper_init(struct nf_conntrack_helper *helper,
|
||||
int nf_conntrack_helper_register(struct nf_conntrack_helper *, struct nf_conntrack_helper **);
|
||||
int __nf_conntrack_helper_register(struct nf_conntrack_helper *);
|
||||
void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
|
||||
void nf_conntrack_helper_release(struct nf_conntrack_helper *);
|
||||
|
||||
int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int,
|
||||
struct nf_conntrack_helper **);
|
||||
|
||||
@@ -117,7 +117,7 @@ struct flow_offload_tunnel {
|
||||
struct in6_addr dst_v6;
|
||||
};
|
||||
|
||||
u8 l3_proto;
|
||||
u8 inner_proto;
|
||||
};
|
||||
|
||||
struct flow_offload_tuple {
|
||||
|
||||
+7
-11
@@ -769,35 +769,31 @@ void dev_fill_forward_path_release(struct net_device_path_stack *stack)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_fill_forward_path_release);
|
||||
|
||||
int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
|
||||
int dev_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||
struct net_device_path_stack *stack)
|
||||
{
|
||||
const struct net_device *last_dev;
|
||||
struct net_device_path_ctx ctx = {
|
||||
.dev = dev,
|
||||
};
|
||||
struct net_device_path *path;
|
||||
int ret = 0;
|
||||
|
||||
memcpy(ctx.daddr, daddr, sizeof(ctx.daddr));
|
||||
stack->num_paths = 0;
|
||||
while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) {
|
||||
last_dev = ctx.dev;
|
||||
while (ctx->dev && ctx->dev->netdev_ops->ndo_fill_forward_path) {
|
||||
last_dev = ctx->dev;
|
||||
path = dev_fwd_path(stack);
|
||||
if (!path)
|
||||
goto err_out;
|
||||
|
||||
memset(path, 0, sizeof(struct net_device_path));
|
||||
ret = ctx.dev->netdev_ops->ndo_fill_forward_path(&ctx, path);
|
||||
ret = ctx->dev->netdev_ops->ndo_fill_forward_path(ctx, path);
|
||||
if (ret < 0)
|
||||
goto err_out;
|
||||
|
||||
stack->num_paths++;
|
||||
if (WARN_ON_ONCE(last_dev == ctx.dev))
|
||||
if (WARN_ON_ONCE(last_dev == ctx->dev))
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (!ctx.dev)
|
||||
if (!ctx->dev)
|
||||
return ret;
|
||||
|
||||
path = dev_fwd_path(stack);
|
||||
@@ -805,7 +801,7 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
|
||||
goto err_out;
|
||||
|
||||
path->type = DEV_PATH_ETHERNET;
|
||||
path->dev = ctx.dev;
|
||||
path->dev = ctx->dev;
|
||||
stack->num_paths++;
|
||||
|
||||
return 0;
|
||||
|
||||
+4
-1
@@ -360,6 +360,9 @@ static int ipip_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||
const struct iphdr *tiph = &tunnel->parms.iph;
|
||||
struct rtable *rt;
|
||||
|
||||
if (ctx->ether_type != cpu_to_be16(ETH_P_IP))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (tunnel->collect_md)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@@ -375,7 +378,7 @@ static int ipip_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||
path->type = DEV_PATH_TUN;
|
||||
path->tun.src_v4.s_addr = tiph->saddr;
|
||||
path->tun.dst_v4.s_addr = tiph->daddr;
|
||||
path->tun.l3_proto = IPPROTO_IPIP;
|
||||
path->tun.inner_proto = IPPROTO_IPIP;
|
||||
path->tun.dst = &rt->dst;
|
||||
path->dev = ctx->dev;
|
||||
|
||||
|
||||
@@ -1852,6 +1852,9 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||
struct flowi6 fl6;
|
||||
int err;
|
||||
|
||||
if (ctx->ether_type != cpu_to_be16(ETH_P_IPV6))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (t->parms.flags & (IP6_TNL_F_USE_ORIG_TCLASS |
|
||||
IP6_TNL_F_USE_ORIG_FLOWLABEL |
|
||||
IP6_TNL_F_USE_ORIG_FWMARK))
|
||||
@@ -1872,7 +1875,7 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||
path->type = DEV_PATH_TUN;
|
||||
path->tun.src_v6 = fl6.saddr;
|
||||
path->tun.dst_v6 = fl6.daddr;
|
||||
path->tun.l3_proto = IPPROTO_IPV6;
|
||||
path->tun.inner_proto = IPPROTO_IPV6;
|
||||
path->tun.dst = dst;
|
||||
path->dev = ctx->dev;
|
||||
ctx->dev = dst->dev;
|
||||
|
||||
@@ -1031,7 +1031,7 @@ static int __nf_ct_resolve_clash(struct sk_buff *skb,
|
||||
nf_conntrack_get(&ct->ct_general);
|
||||
|
||||
nf_ct_acct_merge(ct, ctinfo, loser_ct);
|
||||
nf_ct_put(loser_ct);
|
||||
nf_reset_ct(skb);
|
||||
nf_ct_set(skb, ct, ctinfo);
|
||||
|
||||
NF_CT_STAT_INC(net, clash_resolve);
|
||||
|
||||
@@ -528,6 +528,12 @@ int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
|
||||
int ret;
|
||||
|
||||
spin_lock_bh(&nf_conntrack_expect_lock);
|
||||
if (expect->flags & NF_CT_EXPECT_DEAD) {
|
||||
DEBUG_NET_WARN_ON_ONCE(1);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
master_help = nfct_help(expect->master);
|
||||
if (!master_help) {
|
||||
ret = -ESHUTDOWN;
|
||||
|
||||
@@ -448,6 +448,15 @@ static bool expect_iter_me(struct nf_conntrack_expect *exp, void *data)
|
||||
return this == me;
|
||||
}
|
||||
|
||||
void nf_conntrack_helper_release(struct nf_conntrack_helper *me)
|
||||
{
|
||||
nf_ct_expect_iterate_destroy(expect_iter_me, me);
|
||||
|
||||
if (refcount_dec_and_test(&me->ct_refcnt))
|
||||
kfree_rcu(me, rcu);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_helper_release);
|
||||
|
||||
void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
|
||||
{
|
||||
mutex_lock(&nf_ct_helper_mutex);
|
||||
@@ -463,10 +472,7 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
|
||||
*/
|
||||
synchronize_rcu();
|
||||
|
||||
nf_ct_expect_iterate_destroy(expect_iter_me, me);
|
||||
|
||||
if (refcount_dec_and_test(&me->ct_refcnt))
|
||||
kfree_rcu(me, rcu);
|
||||
nf_conntrack_helper_release(me);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
|
||||
|
||||
|
||||
@@ -1326,7 +1326,8 @@ int nf_conntrack_tcp_packet(struct nf_conn *ct,
|
||||
timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS])
|
||||
timeout = timeouts[TCP_CONNTRACK_RETRANS];
|
||||
else if (unlikely(index == TCP_RST_SET &&
|
||||
new_state == TCP_CONNTRACK_ESTABLISHED))
|
||||
new_state == TCP_CONNTRACK_ESTABLISHED) &&
|
||||
timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK])
|
||||
timeout = timeouts[TCP_CONNTRACK_UNACK];
|
||||
else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) &
|
||||
IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
|
||||
|
||||
@@ -147,13 +147,14 @@ static bool ip_has_options(unsigned int thoff)
|
||||
|
||||
struct nf_flowtable_ctx {
|
||||
const struct net_device *in;
|
||||
__be16 ether_type;
|
||||
u32 offset;
|
||||
u32 hdrsize;
|
||||
struct {
|
||||
/* Tunnel IP header size */
|
||||
u32 hdr_size;
|
||||
/* IP tunnel protocol */
|
||||
u8 proto;
|
||||
u8 inner_proto;
|
||||
} tun;
|
||||
};
|
||||
|
||||
@@ -161,7 +162,6 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
|
||||
struct sk_buff *skb,
|
||||
struct flow_offload_tuple *tuple)
|
||||
{
|
||||
__be16 inner_proto = skb->protocol;
|
||||
struct vlan_ethhdr *veth;
|
||||
struct pppoe_hdr *phdr;
|
||||
struct ipv6hdr *ip6h;
|
||||
@@ -179,33 +179,31 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
|
||||
veth = (struct vlan_ethhdr *)skb_mac_header(skb);
|
||||
tuple->encap[i].id = ntohs(veth->h_vlan_TCI);
|
||||
tuple->encap[i].proto = skb->protocol;
|
||||
inner_proto = veth->h_vlan_encapsulated_proto;
|
||||
offset += VLAN_HLEN;
|
||||
break;
|
||||
case htons(ETH_P_PPP_SES):
|
||||
phdr = (struct pppoe_hdr *)skb_network_header(skb);
|
||||
tuple->encap[i].id = ntohs(phdr->sid);
|
||||
tuple->encap[i].proto = skb->protocol;
|
||||
inner_proto = *((__be16 *)(phdr + 1));
|
||||
offset += PPPOE_SES_HLEN;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (inner_proto) {
|
||||
switch (ctx->ether_type) {
|
||||
case htons(ETH_P_IP):
|
||||
iph = (struct iphdr *)(skb_network_header(skb) + offset);
|
||||
if (ctx->tun.proto == IPPROTO_IPIP) {
|
||||
if (ctx->tun.inner_proto == IPPROTO_IPIP) {
|
||||
tuple->tun.dst_v4.s_addr = iph->daddr;
|
||||
tuple->tun.src_v4.s_addr = iph->saddr;
|
||||
tuple->tun.l3_proto = IPPROTO_IPIP;
|
||||
tuple->tun.inner_proto = IPPROTO_IPIP;
|
||||
}
|
||||
break;
|
||||
case htons(ETH_P_IPV6):
|
||||
ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
|
||||
if (ctx->tun.proto == IPPROTO_IPV6) {
|
||||
if (ctx->tun.inner_proto == IPPROTO_IPV6) {
|
||||
tuple->tun.dst_v6 = ip6h->daddr;
|
||||
tuple->tun.src_v6 = ip6h->saddr;
|
||||
tuple->tun.l3_proto = IPPROTO_IPV6;
|
||||
tuple->tun.inner_proto = IPPROTO_IPV6;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -329,7 +327,7 @@ static bool nf_flow_ip4_tunnel_proto(struct nf_flowtable_ctx *ctx,
|
||||
return false;
|
||||
|
||||
if (iph->protocol == IPPROTO_IPIP) {
|
||||
ctx->tun.proto = iph->protocol;
|
||||
ctx->tun.inner_proto = iph->protocol;
|
||||
ctx->tun.hdr_size = size;
|
||||
ctx->offset += ctx->tun.hdr_size;
|
||||
}
|
||||
@@ -354,7 +352,7 @@ static bool nf_flow_ip6_tunnel_proto(struct nf_flowtable_ctx *ctx,
|
||||
return false;
|
||||
|
||||
if (ip6h->nexthdr == IPPROTO_IPV6) {
|
||||
ctx->tun.proto = ip6h->nexthdr;
|
||||
ctx->tun.inner_proto = ip6h->nexthdr;
|
||||
ctx->tun.hdr_size = sizeof(*ip6h);
|
||||
ctx->offset += ctx->tun.hdr_size;
|
||||
}
|
||||
@@ -368,8 +366,8 @@ static bool nf_flow_ip6_tunnel_proto(struct nf_flowtable_ctx *ctx,
|
||||
static void nf_flow_ip_tunnel_pop(struct nf_flowtable_ctx *ctx,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
if (ctx->tun.proto != IPPROTO_IPIP &&
|
||||
ctx->tun.proto != IPPROTO_IPV6)
|
||||
if (ctx->tun.inner_proto != IPPROTO_IPIP &&
|
||||
ctx->tun.inner_proto != IPPROTO_IPV6)
|
||||
return;
|
||||
|
||||
skb_pull(skb, ctx->tun.hdr_size);
|
||||
@@ -377,10 +375,10 @@ static void nf_flow_ip_tunnel_pop(struct nf_flowtable_ctx *ctx,
|
||||
}
|
||||
|
||||
static bool nf_flow_skb_encap_protocol(struct nf_flowtable_ctx *ctx,
|
||||
struct sk_buff *skb, __be16 proto)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
__be16 inner_proto = skb->protocol;
|
||||
struct vlan_ethhdr *veth;
|
||||
__be16 ether_type;
|
||||
bool ret = false;
|
||||
|
||||
switch (skb->protocol) {
|
||||
@@ -389,22 +387,27 @@ static bool nf_flow_skb_encap_protocol(struct nf_flowtable_ctx *ctx,
|
||||
return false;
|
||||
|
||||
veth = (struct vlan_ethhdr *)skb_mac_header(skb);
|
||||
if (veth->h_vlan_encapsulated_proto == proto) {
|
||||
ctx->offset += VLAN_HLEN;
|
||||
inner_proto = proto;
|
||||
ret = true;
|
||||
}
|
||||
ctx->ether_type = veth->h_vlan_encapsulated_proto;
|
||||
ctx->offset += VLAN_HLEN;
|
||||
ret = true;
|
||||
break;
|
||||
case htons(ETH_P_PPP_SES):
|
||||
if (nf_flow_pppoe_proto(skb, &inner_proto) &&
|
||||
inner_proto == proto) {
|
||||
ctx->offset += PPPOE_SES_HLEN;
|
||||
ret = true;
|
||||
}
|
||||
if (!nf_flow_pppoe_proto(skb, ðer_type))
|
||||
return false;
|
||||
|
||||
ctx->ether_type = ether_type;
|
||||
ctx->offset += PPPOE_SES_HLEN;
|
||||
ret = true;
|
||||
break;
|
||||
case htons(ETH_P_IP):
|
||||
case htons(ETH_P_IPV6):
|
||||
ctx->ether_type = skb->protocol;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (inner_proto) {
|
||||
switch (ctx->ether_type) {
|
||||
case htons(ETH_P_IP):
|
||||
ret = nf_flow_ip4_tunnel_proto(ctx, skb);
|
||||
break;
|
||||
@@ -456,9 +459,6 @@ nf_flow_offload_lookup(struct nf_flowtable_ctx *ctx,
|
||||
{
|
||||
struct flow_offload_tuple tuple = {};
|
||||
|
||||
if (!nf_flow_skb_encap_protocol(ctx, skb, htons(ETH_P_IP)))
|
||||
return NULL;
|
||||
|
||||
if (nf_flow_tuple_ip(ctx, skb, &tuple) < 0)
|
||||
return NULL;
|
||||
|
||||
@@ -612,7 +612,7 @@ static int nf_flow_tunnel_ipip_push(struct net *net, struct sk_buff *skb,
|
||||
iph->version = 4;
|
||||
iph->ihl = sizeof(*iph) >> 2;
|
||||
iph->frag_off = ip_mtu_locked(&rt->dst) ? 0 : frag_off;
|
||||
iph->protocol = tuple->tun.l3_proto;
|
||||
iph->protocol = tuple->tun.inner_proto;
|
||||
iph->tos = tos;
|
||||
iph->daddr = tuple->tun.src_v4.s_addr;
|
||||
iph->saddr = tuple->tun.dst_v4.s_addr;
|
||||
@@ -795,33 +795,17 @@ static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
|
||||
return NF_STOLEN;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
|
||||
const struct nf_hook_state *state)
|
||||
static int nf_flow_queue_xmit4(struct sk_buff *skb,
|
||||
struct flow_offload_tuple_rhash *tuplehash,
|
||||
const struct nf_hook_state *state)
|
||||
{
|
||||
struct flow_offload_tuple_rhash *tuplehash;
|
||||
struct nf_flowtable *flow_table = priv;
|
||||
struct flow_offload_tuple *other_tuple;
|
||||
enum flow_offload_tuple_dir dir;
|
||||
struct nf_flowtable_ctx ctx = {
|
||||
.in = state->in,
|
||||
};
|
||||
struct nf_flow_xmit xmit = {};
|
||||
struct flow_offload *flow;
|
||||
struct neighbour *neigh;
|
||||
struct rtable *rt;
|
||||
__be32 ip_daddr;
|
||||
int ret;
|
||||
|
||||
tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb);
|
||||
if (!tuplehash)
|
||||
return NF_ACCEPT;
|
||||
|
||||
ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);
|
||||
if (ret < 0)
|
||||
return NF_DROP;
|
||||
else if (ret == 0)
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
|
||||
rt = dst_rtable(tuplehash->tuple.dst_cache);
|
||||
@@ -875,6 +859,36 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
|
||||
|
||||
return nf_flow_queue_xmit(state->net, skb, &xmit);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
|
||||
const struct nf_hook_state *state)
|
||||
{
|
||||
struct flow_offload_tuple_rhash *tuplehash;
|
||||
struct nf_flowtable *flow_table = priv;
|
||||
struct nf_flowtable_ctx ctx = {
|
||||
.in = state->in,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!nf_flow_skb_encap_protocol(&ctx, skb))
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (unlikely(ctx.ether_type != htons(ETH_P_IP)))
|
||||
return NF_ACCEPT;
|
||||
|
||||
tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb);
|
||||
if (!tuplehash)
|
||||
return NF_ACCEPT;
|
||||
|
||||
ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);
|
||||
if (ret < 0)
|
||||
return NF_DROP;
|
||||
else if (ret == 0)
|
||||
return NF_ACCEPT;
|
||||
|
||||
return nf_flow_queue_xmit4(skb, tuplehash, state);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook);
|
||||
|
||||
static void nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff,
|
||||
@@ -1103,42 +1117,23 @@ nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx,
|
||||
{
|
||||
struct flow_offload_tuple tuple = {};
|
||||
|
||||
if (!nf_flow_skb_encap_protocol(ctx, skb, htons(ETH_P_IPV6)))
|
||||
return NULL;
|
||||
|
||||
if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0)
|
||||
return NULL;
|
||||
|
||||
return flow_offload_lookup(flow_table, &tuple);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
|
||||
const struct nf_hook_state *state)
|
||||
static int nf_flow_queue_xmit6(struct sk_buff *skb,
|
||||
struct flow_offload_tuple_rhash *tuplehash,
|
||||
const struct nf_hook_state *state)
|
||||
{
|
||||
struct flow_offload_tuple_rhash *tuplehash;
|
||||
struct nf_flowtable *flow_table = priv;
|
||||
struct flow_offload_tuple *other_tuple;
|
||||
enum flow_offload_tuple_dir dir;
|
||||
struct nf_flowtable_ctx ctx = {
|
||||
.in = state->in,
|
||||
};
|
||||
struct nf_flow_xmit xmit = {};
|
||||
struct in6_addr *ip6_daddr;
|
||||
struct flow_offload *flow;
|
||||
struct neighbour *neigh;
|
||||
struct rt6_info *rt;
|
||||
int ret;
|
||||
|
||||
tuplehash = nf_flow_offload_ipv6_lookup(&ctx, flow_table, skb);
|
||||
if (tuplehash == NULL)
|
||||
return NF_ACCEPT;
|
||||
|
||||
ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash, skb);
|
||||
if (ret < 0)
|
||||
return NF_DROP;
|
||||
else if (ret == 0)
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
|
||||
rt = dst_rt6_info(tuplehash->tuple.dst_cache);
|
||||
@@ -1193,4 +1188,34 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
|
||||
|
||||
return nf_flow_queue_xmit(state->net, skb, &xmit);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
|
||||
const struct nf_hook_state *state)
|
||||
{
|
||||
struct flow_offload_tuple_rhash *tuplehash;
|
||||
struct nf_flowtable *flow_table = priv;
|
||||
struct nf_flowtable_ctx ctx = {
|
||||
.in = state->in,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!nf_flow_skb_encap_protocol(&ctx, skb))
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (unlikely(ctx.ether_type != htons(ETH_P_IPV6)))
|
||||
return NF_ACCEPT;
|
||||
|
||||
tuplehash = nf_flow_offload_ipv6_lookup(&ctx, flow_table, skb);
|
||||
if (!tuplehash)
|
||||
return NF_ACCEPT;
|
||||
|
||||
ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash, skb);
|
||||
if (ret < 0)
|
||||
return NF_DROP;
|
||||
else if (ret == 0)
|
||||
return NF_ACCEPT;
|
||||
|
||||
return nf_flow_queue_xmit6(skb, tuplehash, state);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook);
|
||||
|
||||
@@ -44,11 +44,16 @@ static bool nft_is_valid_ether_device(const struct net_device *dev)
|
||||
|
||||
static int nft_dev_fill_forward_path(const struct dst_entry *dst_cache,
|
||||
const struct nf_conn *ct,
|
||||
enum ip_conntrack_dir dir, u8 *ha,
|
||||
enum ip_conntrack_dir dir,
|
||||
u8 *ha, __be16 ether_type,
|
||||
struct net_device_path_stack *stack)
|
||||
{
|
||||
const void *daddr = &ct->tuplehash[!dir].tuple.src.u3;
|
||||
struct net_device *dev = dst_cache->dev;
|
||||
struct net_device_path_ctx ctx = {
|
||||
.dev = dev,
|
||||
.ether_type = ether_type,
|
||||
};
|
||||
struct neighbour *n;
|
||||
u8 nud_state;
|
||||
|
||||
@@ -71,7 +76,9 @@ static int nft_dev_fill_forward_path(const struct dst_entry *dst_cache,
|
||||
return -1;
|
||||
|
||||
out:
|
||||
return dev_fill_forward_path(dev, ha, stack);
|
||||
ether_addr_copy(ctx.daddr, ha);
|
||||
|
||||
return dev_fill_forward_path(&ctx, stack);
|
||||
}
|
||||
|
||||
struct nft_forward_info {
|
||||
@@ -126,7 +133,7 @@ static int nft_dev_path_info(struct net_device_path_stack *stack,
|
||||
|
||||
info->tun.src_v6 = path->tun.src_v6;
|
||||
info->tun.dst_v6 = path->tun.dst_v6;
|
||||
info->tun.l3_proto = path->tun.l3_proto;
|
||||
info->tun.inner_proto = path->tun.inner_proto;
|
||||
info->tun_dst = path->tun.dst;
|
||||
info->num_tuns++;
|
||||
} else {
|
||||
@@ -223,7 +230,7 @@ static int nft_dev_forward_path(const struct nft_pktinfo *pkt,
|
||||
unsigned char ha[ETH_ALEN];
|
||||
int i;
|
||||
|
||||
if (nft_dev_fill_forward_path(dst, ct, dir, ha, &stack) < 0 ||
|
||||
if (nft_dev_fill_forward_path(dst, ct, dir, ha, pkt->ethertype, &stack) < 0 ||
|
||||
nft_dev_path_info(&stack, &info, ha, ft) < 0)
|
||||
return -ENOENT;
|
||||
|
||||
@@ -238,7 +245,7 @@ static int nft_dev_forward_path(const struct nft_pktinfo *pkt,
|
||||
if (info.num_tuns) {
|
||||
route->tuple[!dir].in.tun.src_v6 = info.tun.dst_v6;
|
||||
route->tuple[!dir].in.tun.dst_v6 = info.tun.src_v6;
|
||||
route->tuple[!dir].in.tun.l3_proto = info.tun.l3_proto;
|
||||
route->tuple[!dir].in.tun.inner_proto = info.tun.inner_proto;
|
||||
route->tuple[!dir].in.num_tuns = info.num_tuns;
|
||||
dst_release(route->tuple[dir].dst);
|
||||
route->tuple[dir].dst = info.tun_dst;
|
||||
|
||||
+125
-44
@@ -1213,6 +1213,8 @@ struct nft_ct_expect_obj {
|
||||
u8 l4proto;
|
||||
u8 size;
|
||||
u32 timeout;
|
||||
|
||||
struct nf_conntrack_helper *helper;
|
||||
};
|
||||
|
||||
static int nft_ct_expect_timeout_get(const struct nlattr *attr, u32 *val)
|
||||
@@ -1226,6 +1228,93 @@ static int nft_ct_expect_timeout_get(const struct nlattr *attr, u32 *val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_NF_NAT)
|
||||
static void nft_ct_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this)
|
||||
{
|
||||
const struct nf_ct_helper_expectfn *expfn;
|
||||
|
||||
expfn = nf_ct_helper_expectfn_find_by_name("nat-follow-master");
|
||||
if (expfn)
|
||||
expfn->expectfn(ct, this);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct nft_ct_expect_data {
|
||||
struct nft_ct_expect_obj obj;
|
||||
enum ip_conntrack_dir dir;
|
||||
};
|
||||
|
||||
static int ct_expect_help(struct sk_buff *skb, unsigned int protoff,
|
||||
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
|
||||
{
|
||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
||||
struct nft_ct_expect_data *expect_data;
|
||||
struct nf_conntrack_expect *exp;
|
||||
int ret = NF_ACCEPT;
|
||||
u16 l3num;
|
||||
|
||||
if (nf_ct_is_confirmed(ct))
|
||||
return NF_ACCEPT;
|
||||
|
||||
expect_data = nfct_help_data(ct);
|
||||
if (!expect_data)
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (expect_data->dir != dir)
|
||||
return NF_ACCEPT;
|
||||
|
||||
exp = nf_ct_expect_alloc(ct);
|
||||
if (!exp)
|
||||
return NF_DROP;
|
||||
|
||||
if (expect_data->obj.l3num == NFPROTO_INET)
|
||||
l3num = nf_ct_l3num(ct);
|
||||
else
|
||||
l3num = expect_data->obj.l3num;
|
||||
|
||||
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, l3num,
|
||||
&ct->tuplehash[!dir].tuple.src.u3,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
expect_data->obj.l4proto, NULL, &expect_data->obj.dport);
|
||||
exp->timeout += expect_data->obj.timeout;
|
||||
|
||||
#if IS_ENABLED(CONFIG_NF_NAT)
|
||||
if (ct->status & IPS_NAT_MASK) {
|
||||
exp->saved_proto.tcp.port = expect_data->obj.dport;
|
||||
exp->dir = !dir;
|
||||
exp->expectfn = nft_ct_nat_follow_master;
|
||||
}
|
||||
#endif
|
||||
if (nf_ct_expect_related(exp, 0) != 0)
|
||||
ret = NF_ACCEPT;
|
||||
|
||||
nf_ct_expect_put(exp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nft_ct_expect_helper_alloc(struct nft_ct_expect_obj *priv)
|
||||
{
|
||||
struct nf_conntrack_helper *ct_expect_helper;
|
||||
|
||||
ct_expect_helper = kzalloc_obj(struct nf_conntrack_helper,
|
||||
GFP_KERNEL_ACCOUNT);
|
||||
if (!ct_expect_helper)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(ct_expect_helper->name, sizeof(ct_expect_helper->name), "%s",
|
||||
"nft_ct_expect");
|
||||
ct_expect_helper->me = THIS_MODULE;
|
||||
ct_expect_helper->expect_policy[NF_CT_EXPECT_CLASS_DEFAULT].max_expected = priv->size;
|
||||
rcu_assign_pointer(ct_expect_helper->help, ct_expect_help);
|
||||
refcount_set(&ct_expect_helper->ct_refcnt, 1);
|
||||
|
||||
/* No need to register this helper, this is internal. */
|
||||
priv->helper = ct_expect_helper;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const tb[],
|
||||
struct nft_object *obj)
|
||||
@@ -1233,6 +1322,8 @@ static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,
|
||||
struct nft_ct_expect_obj *priv = nft_obj_data(obj);
|
||||
int err;
|
||||
|
||||
NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nft_ct_expect_data));
|
||||
|
||||
if (!tb[NFTA_CT_EXPECT_L4PROTO] ||
|
||||
!tb[NFTA_CT_EXPECT_DPORT] ||
|
||||
!tb[NFTA_CT_EXPECT_TIMEOUT] ||
|
||||
@@ -1272,13 +1363,31 @@ static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,
|
||||
|
||||
priv->dport = nla_get_be16(tb[NFTA_CT_EXPECT_DPORT]);
|
||||
priv->size = nla_get_u8(tb[NFTA_CT_EXPECT_SIZE]);
|
||||
if (!priv->size)
|
||||
priv->size = NF_CT_EXPECT_MAX_CNT;
|
||||
|
||||
return nf_ct_netns_get(ctx->net, ctx->family);
|
||||
err = nf_ct_netns_get(ctx->net, ctx->family);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nft_ct_expect_helper_alloc(priv);
|
||||
if (err < 0) {
|
||||
nf_ct_netns_put(ctx->net, ctx->family);
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void nft_ct_expect_obj_destroy(const struct nft_ctx *ctx,
|
||||
struct nft_object *obj)
|
||||
struct nft_object *obj)
|
||||
{
|
||||
const struct nft_ct_expect_obj *priv = nft_obj_data(obj);
|
||||
struct nf_conntrack_helper *me = priv->helper;
|
||||
|
||||
/* This helper is going away, disable it. */
|
||||
rcu_assign_pointer(me->help, NULL);
|
||||
nf_conntrack_helper_release(me);
|
||||
nf_ct_netns_put(ctx->net, ctx->family);
|
||||
}
|
||||
|
||||
@@ -1297,27 +1406,14 @@ static int nft_ct_expect_obj_dump(struct sk_buff *skb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_NF_NAT)
|
||||
static void nft_ct_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this)
|
||||
{
|
||||
const struct nf_ct_helper_expectfn *expfn;
|
||||
|
||||
expfn = nf_ct_helper_expectfn_find_by_name("nat-follow-master");
|
||||
if (expfn)
|
||||
expfn->expectfn(ct, this);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void nft_ct_expect_obj_eval(struct nft_object *obj,
|
||||
struct nft_regs *regs,
|
||||
const struct nft_pktinfo *pkt)
|
||||
{
|
||||
const struct nft_ct_expect_obj *priv = nft_obj_data(obj);
|
||||
struct nf_conntrack_expect *exp;
|
||||
struct nft_ct_expect_data *expect_data;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct nf_conn_help *help;
|
||||
enum ip_conntrack_dir dir;
|
||||
u16 l3num = priv->l3num;
|
||||
struct nf_conn *ct;
|
||||
|
||||
ct = nf_ct_get(pkt->skb, &ctinfo);
|
||||
@@ -1325,45 +1421,30 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj,
|
||||
regs->verdict.code = NFT_BREAK;
|
||||
return;
|
||||
}
|
||||
dir = CTINFO2DIR(ctinfo);
|
||||
|
||||
help = nfct_help(ct);
|
||||
if (!help)
|
||||
help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
|
||||
if (help) {
|
||||
regs->verdict.code = NFT_BREAK;
|
||||
return;
|
||||
}
|
||||
|
||||
help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
|
||||
if (!help) {
|
||||
regs->verdict.code = NF_DROP;
|
||||
return;
|
||||
}
|
||||
|
||||
if (help->expecting[NF_CT_EXPECT_CLASS_DEFAULT] >= priv->size) {
|
||||
expect_data = nfct_help_data(ct);
|
||||
if (!expect_data) {
|
||||
regs->verdict.code = NFT_BREAK;
|
||||
return;
|
||||
}
|
||||
if (l3num == NFPROTO_INET)
|
||||
l3num = nf_ct_l3num(ct);
|
||||
expect_data->obj = *priv;
|
||||
expect_data->obj.helper = NULL;
|
||||
expect_data->dir = CTINFO2DIR(ctinfo);
|
||||
|
||||
exp = nf_ct_expect_alloc(ct);
|
||||
if (exp == NULL) {
|
||||
regs->verdict.code = NF_DROP;
|
||||
return;
|
||||
}
|
||||
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, l3num,
|
||||
&ct->tuplehash[!dir].tuple.src.u3,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
priv->l4proto, NULL, &priv->dport);
|
||||
exp->timeout += priv->timeout;
|
||||
|
||||
#if IS_ENABLED(CONFIG_NF_NAT)
|
||||
if (ct->status & IPS_NAT_MASK) {
|
||||
exp->saved_proto.tcp.port = priv->dport;
|
||||
exp->dir = !dir;
|
||||
exp->expectfn = nft_ct_nat_follow_master;
|
||||
}
|
||||
#endif
|
||||
if (nf_ct_expect_related(exp, 0) != 0)
|
||||
regs->verdict.code = NF_DROP;
|
||||
|
||||
nf_ct_expect_put(exp);
|
||||
if (help && refcount_inc_not_zero(&priv->helper->ct_refcnt))
|
||||
rcu_assign_pointer(help->helper, priv->helper);
|
||||
}
|
||||
|
||||
static const struct nla_policy nft_ct_expect_policy[NFTA_CT_EXPECT_MAX + 1] = {
|
||||
|
||||
@@ -603,7 +603,7 @@ static bool skb_nfct_cached(struct net *net,
|
||||
if (nf_ct_is_confirmed(ct))
|
||||
nf_ct_delete(ct, 0, 0);
|
||||
|
||||
nf_ct_put(ct);
|
||||
nf_reset_ct(skb);
|
||||
nf_ct_set(skb, NULL, 0);
|
||||
return false;
|
||||
}
|
||||
@@ -745,8 +745,7 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
|
||||
|
||||
/* Associate skb with specified zone. */
|
||||
if (tmpl) {
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
nf_ct_put(ct);
|
||||
nf_reset_ct(skb);
|
||||
nf_conntrack_get(&tmpl->ct_general);
|
||||
nf_ct_set(skb, tmpl, IP_CT_NEW);
|
||||
}
|
||||
@@ -1075,12 +1074,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
|
||||
|
||||
int ovs_ct_clear(struct sk_buff *skb, struct sw_flow_key *key)
|
||||
{
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct nf_conn *ct;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
|
||||
nf_ct_put(ct);
|
||||
nf_reset_ct(skb);
|
||||
nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
|
||||
|
||||
if (key)
|
||||
|
||||
+3
-3
@@ -782,7 +782,7 @@ static bool tcf_ct_skb_nfct_cached(struct net *net, struct sk_buff *skb,
|
||||
return true;
|
||||
|
||||
drop_ct:
|
||||
nf_ct_put(ct);
|
||||
nf_reset_ct(skb);
|
||||
nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
|
||||
|
||||
return false;
|
||||
@@ -1008,7 +1008,7 @@ TC_INDIRECT_SCOPE int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
|
||||
qdisc_skb_cb(skb)->post_ct = false;
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
if (ct) {
|
||||
nf_ct_put(ct);
|
||||
nf_reset_ct(skb);
|
||||
nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
|
||||
}
|
||||
|
||||
@@ -1055,7 +1055,7 @@ TC_INDIRECT_SCOPE int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
|
||||
|
||||
/* Associate skb with specified zone. */
|
||||
if (tmpl) {
|
||||
nf_conntrack_put(skb_nfct(skb));
|
||||
nf_reset_ct(skb);
|
||||
nf_conntrack_get(&tmpl->ct_general);
|
||||
nf_ct_set(skb, tmpl, IP_CT_NEW);
|
||||
}
|
||||
|
||||
@@ -102,7 +102,6 @@ static int conntrack_data_insert(struct mnl_socket *sock, struct nlmsghdr *nlh,
|
||||
uint16_t zone)
|
||||
{
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *rplnlh;
|
||||
unsigned int portid;
|
||||
int ret;
|
||||
|
||||
@@ -216,12 +215,11 @@ static int count_entries(const struct nlmsghdr *nlh, void *data)
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int conntracK_count_zone(struct mnl_socket *sock, uint16_t zone)
|
||||
static int conntrack_count_zone(struct mnl_socket *sock, uint16_t zone)
|
||||
{
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh, *rplnlh;
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfh;
|
||||
struct nlattr *nest;
|
||||
unsigned int portid;
|
||||
int ret;
|
||||
|
||||
@@ -266,9 +264,8 @@ static int conntracK_count_zone(struct mnl_socket *sock, uint16_t zone)
|
||||
static int conntrack_flush_zone(struct mnl_socket *sock, uint16_t zone)
|
||||
{
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh, *rplnlh;
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfh;
|
||||
struct nlattr *nest;
|
||||
unsigned int portid;
|
||||
int ret;
|
||||
|
||||
@@ -326,7 +323,7 @@ FIXTURE_SETUP(conntrack_dump_flush)
|
||||
ret = mnl_socket_bind(self->sock, 0, MNL_SOCKET_AUTOPID);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
ret = conntracK_count_zone(self->sock, TEST_ZONE_ID);
|
||||
ret = conntrack_count_zone(self->sock, TEST_ZONE_ID);
|
||||
if (ret < 0 && errno == EPERM)
|
||||
SKIP(return, "Needs to be run as root");
|
||||
else if (ret < 0 && errno == EOPNOTSUPP)
|
||||
@@ -423,7 +420,7 @@ FIXTURE_SETUP(conntrack_dump_flush)
|
||||
NF_CT_DEFAULT_ZONE_ID);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
ret = conntracK_count_zone(self->sock, TEST_ZONE_ID);
|
||||
ret = conntrack_count_zone(self->sock, TEST_ZONE_ID);
|
||||
EXPECT_GE(ret, 2);
|
||||
if (ret > 2)
|
||||
SKIP(return, "kernel does not support filtering by zone");
|
||||
@@ -437,7 +434,7 @@ TEST_F(conntrack_dump_flush, test_dump_by_zone)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = conntracK_count_zone(self->sock, TEST_ZONE_ID);
|
||||
ret = conntrack_count_zone(self->sock, TEST_ZONE_ID);
|
||||
EXPECT_EQ(ret, 2);
|
||||
}
|
||||
|
||||
@@ -447,13 +444,13 @@ TEST_F(conntrack_dump_flush, test_flush_by_zone)
|
||||
|
||||
ret = conntrack_flush_zone(self->sock, TEST_ZONE_ID);
|
||||
EXPECT_EQ(ret, 0);
|
||||
ret = conntracK_count_zone(self->sock, TEST_ZONE_ID);
|
||||
ret = conntrack_count_zone(self->sock, TEST_ZONE_ID);
|
||||
EXPECT_EQ(ret, 0);
|
||||
ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 1);
|
||||
ret = conntrack_count_zone(self->sock, TEST_ZONE_ID + 1);
|
||||
EXPECT_EQ(ret, 2);
|
||||
ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 2);
|
||||
ret = conntrack_count_zone(self->sock, TEST_ZONE_ID + 2);
|
||||
EXPECT_EQ(ret, 2);
|
||||
ret = conntracK_count_zone(self->sock, NF_CT_DEFAULT_ZONE_ID);
|
||||
ret = conntrack_count_zone(self->sock, NF_CT_DEFAULT_ZONE_ID);
|
||||
EXPECT_EQ(ret, 2);
|
||||
}
|
||||
|
||||
@@ -463,13 +460,13 @@ TEST_F(conntrack_dump_flush, test_flush_by_zone_default)
|
||||
|
||||
ret = conntrack_flush_zone(self->sock, NF_CT_DEFAULT_ZONE_ID);
|
||||
EXPECT_EQ(ret, 0);
|
||||
ret = conntracK_count_zone(self->sock, TEST_ZONE_ID);
|
||||
ret = conntrack_count_zone(self->sock, TEST_ZONE_ID);
|
||||
EXPECT_EQ(ret, 2);
|
||||
ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 1);
|
||||
ret = conntrack_count_zone(self->sock, TEST_ZONE_ID + 1);
|
||||
EXPECT_EQ(ret, 2);
|
||||
ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 2);
|
||||
ret = conntrack_count_zone(self->sock, TEST_ZONE_ID + 2);
|
||||
EXPECT_EQ(ret, 2);
|
||||
ret = conntracK_count_zone(self->sock, NF_CT_DEFAULT_ZONE_ID);
|
||||
ret = conntrack_count_zone(self->sock, NF_CT_DEFAULT_ZONE_ID);
|
||||
EXPECT_EQ(ret, 0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user