Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 48f66c90 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: nft_ct: add byte/packet counter support



If the accounting extension isn't present, we'll return a counter
value of 0.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent ce1e7989
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -757,6 +757,8 @@ enum nft_ct_keys {
	NFT_CT_PROTO_SRC,
	NFT_CT_PROTO_SRC,
	NFT_CT_PROTO_DST,
	NFT_CT_PROTO_DST,
	NFT_CT_LABELS,
	NFT_CT_LABELS,
	NFT_CT_PKTS,
	NFT_CT_BYTES,
};
};


/**
/**
+38 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/netfilter/nf_tables.h>
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_acct.h>
#include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_conntrack_ecache.h>
@@ -30,6 +31,18 @@ struct nft_ct {
	};
	};
};
};


static u64 nft_ct_get_eval_counter(const struct nf_conn_counter *c,
				   enum nft_ct_keys k,
				   enum ip_conntrack_dir d)
{
	if (d < IP_CT_DIR_MAX)
		return k == NFT_CT_BYTES ? atomic64_read(&c[d].bytes) :
					   atomic64_read(&c[d].packets);

	return nft_ct_get_eval_counter(c, k, IP_CT_DIR_ORIGINAL) +
	       nft_ct_get_eval_counter(c, k, IP_CT_DIR_REPLY);
}

static void nft_ct_get_eval(const struct nft_expr *expr,
static void nft_ct_get_eval(const struct nft_expr *expr,
			    struct nft_regs *regs,
			    struct nft_regs *regs,
			    const struct nft_pktinfo *pkt)
			    const struct nft_pktinfo *pkt)
@@ -114,6 +127,17 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
			       NF_CT_LABELS_MAX_SIZE - size);
			       NF_CT_LABELS_MAX_SIZE - size);
		return;
		return;
	}
	}
	case NFT_CT_BYTES: /* fallthrough */
	case NFT_CT_PKTS: {
		const struct nf_conn_acct *acct = nf_conn_acct_find(ct);
		u64 count = 0;

		if (acct)
			count = nft_ct_get_eval_counter(acct->counter,
							priv->key, priv->dir);
		memcpy(dest, &count, sizeof(count));
		return;
	}
#endif
#endif
	default:
	default:
		break;
		break;
@@ -291,6 +315,13 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
			return -EINVAL;
			return -EINVAL;
		len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all);
		len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all);
		break;
		break;
	case NFT_CT_BYTES:
	case NFT_CT_PKTS:
		/* no direction? return sum of original + reply */
		if (tb[NFTA_CT_DIRECTION] == NULL)
			priv->dir = IP_CT_DIR_MAX;
		len = sizeof(u64);
		break;
	default:
	default:
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;
	}
	}
@@ -373,6 +404,13 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
	case NFT_CT_PROTO_DST:
	case NFT_CT_PROTO_DST:
		if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
		if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
			goto nla_put_failure;
			goto nla_put_failure;
		break;
	case NFT_CT_BYTES:
	case NFT_CT_PKTS:
		if (priv->dir < IP_CT_DIR_MAX &&
		    nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
			goto nla_put_failure;
		break;
	default:
	default:
		break;
		break;
	}
	}