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

Commit 63d10e12 authored by Ander Juaristi's avatar Ander Juaristi Committed by Pablo Neira Ayuso
Browse files

netfilter: nft_meta: support for time matching



This patch introduces meta matches in the kernel for time (a UNIX timestamp),
day (a day of week, represented as an integer between 0-6), and
hour (an hour in the current day, or: number of seconds since midnight).

All values are taken as unsigned 64-bit integers.

The 'time' keyword is internally converted to nanoseconds by nft in
userspace, and hence the timestamp is taken in nanoseconds as well.

Signed-off-by: default avatarAnder Juaristi <a@juaristi.eus>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent a1b840ad
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -799,6 +799,9 @@ enum nft_exthdr_attributes {
 * @NFT_META_OIFKIND: packet output interface kind name (dev->rtnl_link_ops->kind)
 * @NFT_META_BRI_IIFPVID: packet input bridge port pvid
 * @NFT_META_BRI_IIFVPROTO: packet input bridge vlan proto
 * @NFT_META_TIME_NS: time since epoch (in nanoseconds)
 * @NFT_META_TIME_DAY: day of week (from 0 = Sunday to 6 = Saturday)
 * @NFT_META_TIME_HOUR: hour of day (in seconds)
 */
enum nft_meta_keys {
	NFT_META_LEN,
@@ -831,6 +834,9 @@ enum nft_meta_keys {
	NFT_META_OIFKIND,
	NFT_META_BRI_IIFPVID,
	NFT_META_BRI_IIFVPROTO,
	NFT_META_TIME_NS,
	NFT_META_TIME_DAY,
	NFT_META_TIME_HOUR,
};

/**
+46 −0
Original line number Diff line number Diff line
@@ -26,8 +26,36 @@

#include <uapi/linux/netfilter_bridge.h> /* NF_BR_PRE_ROUTING */

#define NFT_META_SECS_PER_MINUTE	60
#define NFT_META_SECS_PER_HOUR		3600
#define NFT_META_SECS_PER_DAY		86400
#define NFT_META_DAYS_PER_WEEK		7

static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state);

static u8 nft_meta_weekday(unsigned long secs)
{
	unsigned int dse;
	u8 wday;

	secs -= NFT_META_SECS_PER_MINUTE * sys_tz.tz_minuteswest;
	dse = secs / NFT_META_SECS_PER_DAY;
	wday = (4 + dse) % NFT_META_DAYS_PER_WEEK;

	return wday;
}

static u32 nft_meta_hour(unsigned long secs)
{
	struct tm tm;

	time64_to_tm(secs, 0, &tm);

	return tm.tm_hour * NFT_META_SECS_PER_HOUR
		+ tm.tm_min * NFT_META_SECS_PER_MINUTE
		+ tm.tm_sec;
}

void nft_meta_get_eval(const struct nft_expr *expr,
		       struct nft_regs *regs,
		       const struct nft_pktinfo *pkt)
@@ -218,6 +246,15 @@ void nft_meta_get_eval(const struct nft_expr *expr,
			goto err;
		strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
		break;
	case NFT_META_TIME_NS:
		nft_reg_store64(dest, ktime_get_real_ns());
		break;
	case NFT_META_TIME_DAY:
		nft_reg_store8(dest, nft_meta_weekday(get_seconds()));
		break;
	case NFT_META_TIME_HOUR:
		*dest = nft_meta_hour(get_seconds());
		break;
	default:
		WARN_ON(1);
		goto err;
@@ -330,6 +367,15 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
		len = sizeof(u8);
		break;
#endif
	case NFT_META_TIME_NS:
		len = sizeof(u64);
		break;
	case NFT_META_TIME_DAY:
		len = sizeof(u8);
		break;
	case NFT_META_TIME_HOUR:
		len = sizeof(u32);
		break;
	default:
		return -EOPNOTSUPP;
	}