From f8f32deda31df597614d9f1f64ffb0c0320f4d54 Mon Sep 17 00:00:00 2001 From: Ander Juaristi Date: Thu, 29 Aug 2019 16:09:02 +0200 Subject: meta: Introduce new conditions 'time', 'day' and 'hour' These keywords introduce new checks for a timestamp, an absolute date (which is converted to a timestamp), an hour in the day (which is converted to the number of seconds since midnight) and a day of week. When converting an ISO date (eg. 2019-06-06 17:00) to a timestamp, we need to substract it the GMT difference in seconds, that is, the value of the 'tm_gmtoff' field in the tm structure. This is because the kernel doesn't know about time zones. And hence the kernel manages different timestamps than those that are advertised in userspace when running, for instance, date +%s. The same conversion needs to be done when converting hours (e.g 17:00) to seconds since midnight as well. The result needs to be computed modulo 86400 in case GMT offset (difference in seconds from UTC) is negative. We also introduce a new command line option (-t, --seconds) to show the actual timestamps when printing the values, rather than the ISO dates, or the hour. Some usage examples: time < "2019-06-06 17:00" drop; time < "2019-06-06 17:20:20" drop; time < 12341234 drop; day "Saturday" drop; day 6 drop; hour >= 17:00 drop; hour >= "17:00:01" drop; hour >= 63000 drop; We need to convert an ISO date to a timestamp without taking into account the time zone offset, since comparison will be done in kernel space and there is no time zone information there. Overwriting TZ is portable, but will cause problems when parsing a ruleset that has 'time' and 'hour' rules. Parsing an 'hour' type must not do time zone conversion, but that will be automatically done if TZ has been overwritten to UTC. Hence, we use timegm() to parse the 'time' type, even though it's not portable. Overwriting TZ seems to be a much worse solution. Finally, be aware that timestamps are converted to nanoseconds when transferring to the kernel (as comparison is done with nanosecond precision), and back to seconds when retrieving them for printing. We swap left and right values in a range to properly handle cross-day hour ranges (e.g. 23:15-03:22). Signed-off-by: Ander Juaristi Reviewed-by: Florian Westphal --- include/datatype.h | 6 ++++++ include/linux/netfilter/nf_tables.h | 6 ++++++ include/meta.h | 3 +++ include/nftables.h | 5 +++++ include/nftables/libnftables.h | 1 + 5 files changed, 21 insertions(+) (limited to 'include') diff --git a/include/datatype.h b/include/datatype.h index c1d08cc2..49b8f608 100644 --- a/include/datatype.h +++ b/include/datatype.h @@ -45,6 +45,9 @@ * @TYPE_DSCP: Differentiated Services Code Point (integer subtype) * @TYPE_IFNAME: interface name (string subtype) * @TYPE_IGMP: IGMP type (integer subtype) + * @TYPE_TIME_DATA Date type (integer subtype) + * @TYPE_TIME_HOUR Hour type (integer subtype) + * @TYPE_TIME_DAY Day type (integer subtype) */ enum datatypes { TYPE_INVALID, @@ -90,6 +93,9 @@ enum datatypes { TYPE_CT_EVENTBIT, TYPE_IFNAME, TYPE_IGMP_TYPE, + TYPE_TIME_DATE, + TYPE_TIME_HOUR, + TYPE_TIME_DAY, __TYPE_MAX }; #define TYPE_MAX (__TYPE_MAX - 1) diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index ec153399..0ff932da 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -800,6 +800,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, @@ -832,6 +835,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, }; /** diff --git a/include/meta.h b/include/meta.h index 0fe95fd6..1478902e 100644 --- a/include/meta.h +++ b/include/meta.h @@ -41,5 +41,8 @@ extern const struct datatype uid_type; extern const struct datatype devgroup_type; extern const struct datatype pkttype_type; extern const struct datatype ifname_type; +extern const struct datatype date_type; +extern const struct datatype hour_type; +extern const struct datatype day_type; #endif /* NFTABLES_META_H */ diff --git a/include/nftables.h b/include/nftables.h index ef737c83..1ecf5ef5 100644 --- a/include/nftables.h +++ b/include/nftables.h @@ -70,6 +70,11 @@ static inline bool nft_output_guid(const struct output_ctx *octx) return octx->flags & NFT_CTX_OUTPUT_GUID; } +static inline bool nft_output_seconds(const struct output_ctx *octx) +{ + return octx->flags & NFT_CTX_OUTPUT_NUMERIC_TIME; +} + static inline bool nft_output_numeric_proto(const struct output_ctx *octx) { return octx->flags & NFT_CTX_OUTPUT_NUMERIC_PROTO; diff --git a/include/nftables/libnftables.h b/include/nftables/libnftables.h index e39c5887..7a7a46f3 100644 --- a/include/nftables/libnftables.h +++ b/include/nftables/libnftables.h @@ -52,6 +52,7 @@ enum { NFT_CTX_OUTPUT_NUMERIC_PROTO = (1 << 7), NFT_CTX_OUTPUT_NUMERIC_PRIO = (1 << 8), NFT_CTX_OUTPUT_NUMERIC_SYMBOL = (1 << 9), + NFT_CTX_OUTPUT_NUMERIC_TIME = (1 << 10), NFT_CTX_OUTPUT_NUMERIC_ALL = (NFT_CTX_OUTPUT_NUMERIC_PROTO | NFT_CTX_OUTPUT_NUMERIC_PRIO | NFT_CTX_OUTPUT_NUMERIC_SYMBOL), -- cgit v1.2.3