diff options
Diffstat (limited to 'net/sched/em_nbyte.c')
| -rw-r--r-- | net/sched/em_nbyte.c | 82 | 
1 files changed, 82 insertions, 0 deletions
diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c new file mode 100644 index 00000000000..71ea926a9f0 --- /dev/null +++ b/net/sched/em_nbyte.c @@ -0,0 +1,82 @@ +/* + * net/sched/em_nbyte.c	N-Byte ematch + * + *		This program is free software; you can redistribute it and/or + *		modify it under the terms of the GNU General Public License + *		as published by the Free Software Foundation; either version + *		2 of the License, or (at your option) any later version. + * + * Authors:	Thomas Graf <tgraf@suug.ch> + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/skbuff.h> +#include <linux/tc_ematch/tc_em_nbyte.h> +#include <net/pkt_cls.h> + +struct nbyte_data +{ +	struct tcf_em_nbyte	hdr; +	char			pattern[0]; +}; +	 +static int em_nbyte_change(struct tcf_proto *tp, void *data, int data_len, +			   struct tcf_ematch *em) +{ +	struct tcf_em_nbyte *nbyte = data; + +	if (data_len < sizeof(*nbyte) || +	    data_len < (sizeof(*nbyte) + nbyte->len)) +		return -EINVAL; + +	em->datalen = sizeof(*nbyte) + nbyte->len; +	em->data = (unsigned long) kmalloc(em->datalen, GFP_KERNEL); +	if (em->data == 0UL) +		return -ENOBUFS; + +	memcpy((void *) em->data, data, em->datalen); + +	return 0; +} + +static int em_nbyte_match(struct sk_buff *skb, struct tcf_ematch *em, +			  struct tcf_pkt_info *info) +{ +	struct nbyte_data *nbyte = (struct nbyte_data *) em->data; +	unsigned char *ptr = tcf_get_base_ptr(skb, nbyte->hdr.layer); + +	ptr += nbyte->hdr.off; + +	if (!tcf_valid_offset(skb, ptr, nbyte->hdr.len)) +		return 0; + +	return !memcmp(ptr + nbyte->hdr.off, nbyte->pattern, nbyte->hdr.len); +} + +static struct tcf_ematch_ops em_nbyte_ops = { +	.kind	  = TCF_EM_NBYTE, +	.change	  = em_nbyte_change, +	.match	  = em_nbyte_match, +	.owner	  = THIS_MODULE, +	.link	  = LIST_HEAD_INIT(em_nbyte_ops.link) +}; + +static int __init init_em_nbyte(void) +{ +	return tcf_em_register(&em_nbyte_ops); +} + +static void __exit exit_em_nbyte(void)  +{ +	tcf_em_unregister(&em_nbyte_ops); +} + +MODULE_LICENSE("GPL"); + +module_init(init_em_nbyte); +module_exit(exit_em_nbyte);  |