Skip to content

Commit 63d10e1

Browse files
juaristiummakynes
authored andcommitted
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: Ander Juaristi <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent a1b840a commit 63d10e1

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,9 @@ enum nft_exthdr_attributes {
799799
* @NFT_META_OIFKIND: packet output interface kind name (dev->rtnl_link_ops->kind)
800800
* @NFT_META_BRI_IIFPVID: packet input bridge port pvid
801801
* @NFT_META_BRI_IIFVPROTO: packet input bridge vlan proto
802+
* @NFT_META_TIME_NS: time since epoch (in nanoseconds)
803+
* @NFT_META_TIME_DAY: day of week (from 0 = Sunday to 6 = Saturday)
804+
* @NFT_META_TIME_HOUR: hour of day (in seconds)
802805
*/
803806
enum nft_meta_keys {
804807
NFT_META_LEN,
@@ -831,6 +834,9 @@ enum nft_meta_keys {
831834
NFT_META_OIFKIND,
832835
NFT_META_BRI_IIFPVID,
833836
NFT_META_BRI_IIFVPROTO,
837+
NFT_META_TIME_NS,
838+
NFT_META_TIME_DAY,
839+
NFT_META_TIME_HOUR,
834840
};
835841

836842
/**

net/netfilter/nft_meta.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,36 @@
2626

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

29+
#define NFT_META_SECS_PER_MINUTE 60
30+
#define NFT_META_SECS_PER_HOUR 3600
31+
#define NFT_META_SECS_PER_DAY 86400
32+
#define NFT_META_DAYS_PER_WEEK 7
33+
2934
static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state);
3035

36+
static u8 nft_meta_weekday(unsigned long secs)
37+
{
38+
unsigned int dse;
39+
u8 wday;
40+
41+
secs -= NFT_META_SECS_PER_MINUTE * sys_tz.tz_minuteswest;
42+
dse = secs / NFT_META_SECS_PER_DAY;
43+
wday = (4 + dse) % NFT_META_DAYS_PER_WEEK;
44+
45+
return wday;
46+
}
47+
48+
static u32 nft_meta_hour(unsigned long secs)
49+
{
50+
struct tm tm;
51+
52+
time64_to_tm(secs, 0, &tm);
53+
54+
return tm.tm_hour * NFT_META_SECS_PER_HOUR
55+
+ tm.tm_min * NFT_META_SECS_PER_MINUTE
56+
+ tm.tm_sec;
57+
}
58+
3159
void nft_meta_get_eval(const struct nft_expr *expr,
3260
struct nft_regs *regs,
3361
const struct nft_pktinfo *pkt)
@@ -218,6 +246,15 @@ void nft_meta_get_eval(const struct nft_expr *expr,
218246
goto err;
219247
strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
220248
break;
249+
case NFT_META_TIME_NS:
250+
nft_reg_store64(dest, ktime_get_real_ns());
251+
break;
252+
case NFT_META_TIME_DAY:
253+
nft_reg_store8(dest, nft_meta_weekday(get_seconds()));
254+
break;
255+
case NFT_META_TIME_HOUR:
256+
*dest = nft_meta_hour(get_seconds());
257+
break;
221258
default:
222259
WARN_ON(1);
223260
goto err;
@@ -330,6 +367,15 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
330367
len = sizeof(u8);
331368
break;
332369
#endif
370+
case NFT_META_TIME_NS:
371+
len = sizeof(u64);
372+
break;
373+
case NFT_META_TIME_DAY:
374+
len = sizeof(u8);
375+
break;
376+
case NFT_META_TIME_HOUR:
377+
len = sizeof(u32);
378+
break;
333379
default:
334380
return -EOPNOTSUPP;
335381
}

0 commit comments

Comments
 (0)