Re: [PATCH] [RFC] netfilter: add xt_skbuff xtables match

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

 



On Fri, Dec 07, 2012 at 07:04:04PM -0500, Willem de Bruijn wrote:
> Add an iptables match based on skb fields, such as mark, priority,
> input interface and rxhash. The match supports range based matching
> on one field, with optional inversion and masking.
> 
> v2: switches from xt_priority to xt_skbuff. Pablo, is this what
> you had in mind? It doesn't perfectly duplicate the values from
> nftables xt_meta. Needs more testing to cover the field-specific
> codepaths.

Yes, I think this is the good direction for it.

> Tested by inserting
> 
> iptables -t mangle -A PREROUTING -s $SRC -j MARK --set-mark 10
> iptables -A INPUT -m skbuff --min 10 --max 10 -j TRACE

Hm, you have to specify the field type in the iptables rule, right?i

> The userspace tool needs work, too. For one, I just hardcoded the
> field_id to be skb_field_mark for this test. That's why it's missing
> from the command line.

Please, once you're done with the user-space part, post it to the ML
in order to help testing this.

> Signed-off-by: Willem de Bruijn <willemb@xxxxxxxxxx>
> ---
>  include/linux/netfilter/xt_skbuff.h |   33 ++++++++
>  net/netfilter/Kconfig               |    9 ++
>  net/netfilter/Makefile              |    1 +
>  net/netfilter/xt_skbuff.c           |  141 +++++++++++++++++++++++++++++++++++
>  4 files changed, 184 insertions(+), 0 deletions(-)
>  create mode 100644 include/linux/netfilter/xt_skbuff.h
>  create mode 100644 net/netfilter/xt_skbuff.c
> 
> diff --git a/include/linux/netfilter/xt_skbuff.h b/include/linux/netfilter/xt_skbuff.h
> new file mode 100644
> index 0000000..10eb8d8
> --- /dev/null
> +++ b/include/linux/netfilter/xt_skbuff.h
> @@ -0,0 +1,33 @@
> +#ifndef _XT_SKBUFF_H
> +#define _XT_SKBUFF_H
> +
> +#include <linux/types.h>
> +
> +enum xt_skbuff_field_selector {

these enums in uppercase.

> +	skb_field_csum = 0,
> +	skb_field_hatype,
> +	skb_field_iif,
> +	skb_field_len,
> +	skb_field_mark,
> +	skb_field_pkt_type,
> +	skb_field_priority,
> +	skb_field_protocol,
> +	skb_field_queue_mapping,
> +	skb_field_rt_classid,
> +	skb_field_rxhash,
> +	skb_field_secmark,
> +	skb_field_sk_uid,
> +	skb_field_sk_gid,
> +	skb_field_tstamp,
> +	skb_field_vlan_tci,

Please, check if these all are worth to be exposed to user-space via
iptables.

> +};
> +
> +struct xt_skbuff_info {
> +	__u16 field_id;		/* an xt_skbuff_field_selector value */
> +	__u8  invert;
> +	__u64 min;
> +	__u64 max;
> +	__u64 mask;
> +};
> +
> +#endif /*_XT_SKBUFF_H */
> diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
> index fefa514..3a07a86 100644
> --- a/net/netfilter/Kconfig
> +++ b/net/netfilter/Kconfig
> @@ -1093,6 +1093,15 @@ config NETFILTER_XT_MATCH_PKTTYPE
>  
>  	  To compile it as a module, choose M here.  If unsure, say N.
>  
> +config NETFILTER_XT_MATCH_SKBUFF
> +	tristate '"skbuff" match support'
> +	depends on NETFILTER_ADVANCED
> +	help
> +	  This option adds a match based on the value of a chosen sk_buff
> +	  field.
> +
> +	  To compile it as a module, choose M here.  If unsure, say N.
> +
>  config NETFILTER_XT_MATCH_QUOTA
>  	tristate '"quota" match support'
>  	depends on NETFILTER_ADVANCED
> diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
> index 3259697..9bc95e0 100644
> --- a/net/netfilter/Makefile
> +++ b/net/netfilter/Makefile
> @@ -129,6 +129,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RATEEST) += xt_rateest.o
>  obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
>  obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT) += xt_recent.o
>  obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
> +obj-$(CONFIG_NETFILTER_XT_MATCH_SKBUFF) += xt_skbuff.o
>  obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
>  obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
>  obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
> diff --git a/net/netfilter/xt_skbuff.c b/net/netfilter/xt_skbuff.c
> new file mode 100644
> index 0000000..5ca30eb
> --- /dev/null
> +++ b/net/netfilter/xt_skbuff.c
> @@ -0,0 +1,141 @@
> +/* Xtables module to match packets based on sk_buff fields.
> + * Copyright 2012 Google Inc.
> + * Written by Willem de Bruijn <willemb@xxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/skbuff.h>
> +#include <net/sock.h>
> +
> +#include <linux/netfilter/xt_skbuff.h>
> +#include <linux/netfilter/x_tables.h>
> +
> +MODULE_AUTHOR("Willem de Bruijn <willemb@xxxxxxxxxx>");
> +MODULE_DESCRIPTION("Xtables: skbuff match");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("ipt_priority");
> +MODULE_ALIAS("ip6t_priority");

you'll have to remove this aliasing support. There was not previous
priority match in mainstream.

> +static bool skbuff_mt(const struct sk_buff *skb,
> +			struct xt_action_param *par)
> +{
> +	const struct xt_skbuff_info *info = par->matchinfo;
> +	u64 value;
> +
> +	switch (info->field_id) {
> +	case skb_field_csum:
> +		if (skb->ip_summed != CHECKSUM_COMPLETE)
> +			return false;
> +		value = skb->csum;
> +		break;
> +	case skb_field_hatype:
> +		if (!skb->dev)
> +			return false;
> +		value = skb->dev->type;
> +		break;
> +	case skb_field_iif:
> +		value = skb->skb_iif;
> +		break;
> +	case skb_field_len:
> +		value = skb->len;
> +		break;
> +	case skb_field_mark:
> +		value = skb->mark;
> +		break;
> +	case skb_field_pkt_type:
> +		value = skb->pkt_type;
> +		break;
> +	case skb_field_priority:
> +		value = skb->priority;
> +		break;
> +	case skb_field_protocol:
> +		value = skb->protocol;
> +		break;
> +	case skb_field_queue_mapping:
> +		value = skb->queue_mapping;
> +		break;
> +	case skb_field_rt_classid:
> +#ifdef CONFIG_NET_CLS_ROUTE
> +		const struct dst_entry *dst;
> +
> +		rcu_read_lock();
> +		dst = skb_dst(skb);
> +		if (dst)
> +			value = dst->tclassid;
> +		rcu_read_unlock();
> +		if (!dst)
> +			return false;
> +		break;
> +#else
> +		return false;
> +#endif
> +	case skb_field_rxhash:
> +		value = skb->rxhash;
> +		break;
> +	case skb_field_secmark:
> +#ifdef CONFIG_NETWORK_SECMARK
> +		value = skb->secmark;
> +		break;
> +#else
> +		return false;
> +#endif
> +	case skb_field_sk_uid:
> +		if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
> +			return false;
> +		value = skb->sk->sk_socket->file->f_cred->fsuid;
> +		break;
> +	case skb_field_sk_gid:
> +		if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
> +			return false;
> +		value = skb->sk->sk_socket->file->f_cred->fsgid;
> +		break;
> +	case skb_field_tstamp:
> +		value = skb->tstamp.tv64;
> +		break;
> +	case skb_field_vlan_tci:
> +		value = skb->vlan_tci;
> +		break;
> +	default:
> +		return false;
> +	}
> +
> +	value &= info->mask;
> +	return (value >= info->min && value <= info->max) ^ info->invert;
> +}
> +
> +static int skbuff_mt_check(const struct xt_mtchk_param *par)
> +{
> +	const struct xt_skbuff_info *info = par->matchinfo;
> +
> +	if (info->field_id > skb_field_vlan_tci)

Better define SKB_FIELD_MAX ?

> +		return -EINVAL;

probably -EOPNOTSUPP is better in case we add some new skbuff field
that we support.

> +
> +	return 0;
> +}
> +
> +static struct xt_match skbuff_mt_reg __read_mostly = {
> +	.name		= "skbuff",
> +	.revision	= 0,
> +	.family		= NFPROTO_UNSPEC,
> +	.match		= skbuff_mt,
> +	.matchsize	= sizeof(struct xt_skbuff_info),
> +	.checkentry	= skbuff_mt_check,
> +	.me		= THIS_MODULE,
> +};
> +
> +static int __init skbuff_mt_init(void)
> +{
> +	return xt_register_match(&skbuff_mt_reg);
> +}
> +
> +static void __exit skbuff_mt_exit(void)
> +{
> +	xt_unregister_match(&skbuff_mt_reg);
> +}
> +
> +module_init(skbuff_mt_init);
> +module_exit(skbuff_mt_exit);
> -- 
> 1.7.7.3
> 
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux