Re: [PATCH 1/2] meta: Introduce new conditions 'time', 'day' and 'hour'

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ander Juaristi <a@xxxxxxxxxxxx> wrote:
> 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.
> 
> 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 "Sat" drop;
> 	day 6 drop;
> 	hour >= 17:00 drop;
> 	hour >= "17:00:01" drop;
> 	hour >= 63000 drop;
> 
> Signed-off-by: Ander Juaristi <a@xxxxxxxxxxxx>
> ---
>  include/datatype.h                  |   3 +
>  include/linux/netfilter/nf_tables.h |   6 +
>  include/meta.h                      |   3 +
>  include/nftables.h                  |   5 +
>  include/nftables/libnftables.h      |   1 +
>  src/datatype.c                      |   3 +
>  src/main.c                          |  11 +-
>  src/meta.c                          | 286 ++++++++++++++++++++++++++++
>  src/parser_bison.y                  |   4 +
>  src/scanner.l                       |   4 +-
>  10 files changed, 324 insertions(+), 2 deletions(-)
> 
> diff --git a/include/datatype.h b/include/datatype.h
> index 63617eb..a102f3f 100644
> --- a/include/datatype.h
> +++ b/include/datatype.h
> @@ -90,6 +90,9 @@ enum datatypes {
>  	TYPE_CT_EVENTBIT,
>  	TYPE_IFNAME,
>  	TYPE_IGMP_TYPE,
> +	TYPE_TIME_TYPE,
> +	TYPE_HOUR_TYPE,
> +	TYPE_DAY_TYPE,
>  	__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 7bdb234..ce621ed 100644
> --- a/include/linux/netfilter/nf_tables.h
> +++ b/include/linux/netfilter/nf_tables.h
> @@ -793,6 +793,9 @@ enum nft_exthdr_attributes {
>   * @NFT_META_SECPATH: boolean, secpath_exists (!!skb->sp)
>   * @NFT_META_IIFKIND: packet input interface kind name (dev->rtnl_link_ops->kind)
>   * @NFT_META_OIFKIND: packet output interface kind name (dev->rtnl_link_ops->kind)
> + * @NFT_META_TIME: a UNIX timestamp
> + * @NFT_META_TIME_DAY: day of week
> + * @NFT_META_TIME_HOUR: hour of day
>   */
>  enum nft_meta_keys {
>  	NFT_META_LEN,
> @@ -823,6 +826,9 @@ enum nft_meta_keys {
>  	NFT_META_SECPATH,
>  	NFT_META_IIFKIND,
>  	NFT_META_OIFKIND,
> +	NFT_META_TIME,
> +	NFT_META_TIME_DAY,
> +	NFT_META_TIME_HOUR,
>  };
>  
>  /**
> diff --git a/include/meta.h b/include/meta.h
> index a49b4ff..a62a130 100644
> --- a/include/meta.h
> +++ b/include/meta.h
> @@ -41,6 +41,9 @@ 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;
>  
>  extern struct symbol_table *devgroup_tbl;
>  
> diff --git a/include/nftables.h b/include/nftables.h
> index ed446e2..52aff12 100644
> --- a/include/nftables.h
> +++ b/include/nftables.h
> @@ -62,6 +62,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_SECONDS;
> +}
> +
>  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 e39c588..87d4ff5 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_SECONDS          = (1 << 10),
>  	NFT_CTX_OUTPUT_NUMERIC_ALL	= (NFT_CTX_OUTPUT_NUMERIC_PROTO |
>  					   NFT_CTX_OUTPUT_NUMERIC_PRIO |
>  					   NFT_CTX_OUTPUT_NUMERIC_SYMBOL),
> diff --git a/src/datatype.c b/src/datatype.c
> index 6d6826e..2ee7a8f 100644
> --- a/src/datatype.c
> +++ b/src/datatype.c
> @@ -71,6 +71,9 @@ static const struct datatype *datatypes[TYPE_MAX + 1] = {
>  	[TYPE_BOOLEAN]		= &boolean_type,
>  	[TYPE_IFNAME]		= &ifname_type,
>  	[TYPE_IGMP_TYPE]	= &igmp_type_type,
> +	[TYPE_TIME_TYPE]	= &date_type,
> +	[TYPE_HOUR_TYPE]	= &hour_type,
> +	[TYPE_DAY_TYPE]		= &day_type,

TYPE_FOO_TYPE looks weird, maybe use

TYPE_TIME_DATE
TYPE_TIME_HOUR
TYPE_TIME_DAY

?

> +static void day_type_print(const struct expr *expr, struct output_ctx *octx)
> +{
> +	const char *days[] = {
> +		"Sunday",
> +		"Monday",
> +		"Tuesday",
> +		"Wednesday",
> +		"Thursday",
> +		"Friday",
> +		"Saturday"
> +	};
> +	uint8_t daynum = mpz_get_uint8(expr->value),
> +		 numdays = sizeof(days) / (3 * 3);

numdays = array_size(days) ?

> +#define MIN(a, b) (a < b ? a : b)

There is min() in include/utils.h.

	> +	};
> +	int daynum = -1, numdays = (sizeof(days) / 7) - 1;

numdays = array_size(days)

> +static void __hour_type_print_r(int hours, int minutes, int seconds, char *out)
> +{
> +	if (minutes == 60)
> +		return __hour_type_print_r(++hours, 0, seconds, out);
> +	else if (minutes > 60)
> +		return __hour_type_print_r((int) (minutes / 60), minutes % 60, seconds, out);
> +
> +	if (seconds == 60)
> +		return __hour_type_print_r(hours, ++minutes, 0, out);
> +	else if (seconds > 60)
> +		return __hour_type_print_r(hours, (int) (seconds / 60), seconds % 60, out);
> +
> +	if (seconds == 0)
> +		snprintf(out, 6, "%02d:%02d", hours, minutes);
> +	else
> +		snprintf(out, 9, "%02d:%02d:%02d", hours, minutes, seconds);
> +}

I think it would be preferrable to pass a size_t buflen here and use
that rather than the magic buffer sizes in snrintf().

> +const struct datatype date_type = {
> +	.type = TYPE_TIME_TYPE,
> +	.name = "time",
> +	.desc = "Relative time of packet reception",
> +	.byteorder = BYTEORDER_HOST_ENDIAN,
> +	.size = 8 * BITS_PER_BYTE,

Probably better to use sizeof(uint64_t) * BITS_PER_BYTE here.

Otherwise this looks good to me.  Once libnftnl support is ready and the
grammar accepted we also need an update to the documentation and a few
test cases for this. (in tests/py/ ).



[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux