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

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
...@@ -799,6 +799,9 @@ enum nft_exthdr_attributes { ...@@ -799,6 +799,9 @@ enum nft_exthdr_attributes {
* @NFT_META_OIFKIND: packet output interface kind name (dev->rtnl_link_ops->kind) * @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_IIFPVID: packet input bridge port pvid
* @NFT_META_BRI_IIFVPROTO: packet input bridge vlan proto * @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 { enum nft_meta_keys {
NFT_META_LEN, NFT_META_LEN,
...@@ -831,6 +834,9 @@ enum nft_meta_keys { ...@@ -831,6 +834,9 @@ enum nft_meta_keys {
NFT_META_OIFKIND, NFT_META_OIFKIND,
NFT_META_BRI_IIFPVID, NFT_META_BRI_IIFPVID,
NFT_META_BRI_IIFVPROTO, NFT_META_BRI_IIFVPROTO,
NFT_META_TIME_NS,
NFT_META_TIME_DAY,
NFT_META_TIME_HOUR,
}; };
/** /**
......
...@@ -26,8 +26,36 @@ ...@@ -26,8 +26,36 @@
#include <uapi/linux/netfilter_bridge.h> /* NF_BR_PRE_ROUTING */ #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 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, void nft_meta_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)
...@@ -218,6 +246,15 @@ void nft_meta_get_eval(const struct nft_expr *expr, ...@@ -218,6 +246,15 @@ void nft_meta_get_eval(const struct nft_expr *expr,
goto err; goto err;
strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ); strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
break; 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: default:
WARN_ON(1); WARN_ON(1);
goto err; goto err;
...@@ -330,6 +367,15 @@ int nft_meta_get_init(const struct nft_ctx *ctx, ...@@ -330,6 +367,15 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
len = sizeof(u8); len = sizeof(u8);
break; break;
#endif #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: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment