Skip to content

Commit

Permalink
netfilter: nft_meta: support for time matching
Browse files Browse the repository at this point in the history
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 <a@juaristi.eus>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Ander Juaristi authored and Pablo Neira Ayuso committed Aug 26, 2019
1 parent a1b840a commit 63d10e1
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
6 changes: 6 additions & 0 deletions include/uapi/linux/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
};

/**
Expand Down
46 changes: 46 additions & 0 deletions net/netfilter/nft_meta.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 63d10e1

Please sign in to comment.