File Index
Files and directories
Sign in
FILE

em_text.c

File preview with syntax highlighting.

linux-6.19.14/net/sched/em_text.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * net/sched/em_text.c	Textsearch ematch
  4 *
  5 * Authors:	Thomas Graf <tgraf@suug.ch>
  6 */
  7
  8#include <linux/slab.h>
  9#include <linux/module.h>
 10#include <linux/types.h>
 11#include <linux/kernel.h>
 12#include <linux/string.h>
 13#include <linux/skbuff.h>
 14#include <linux/textsearch.h>
 15#include <linux/tc_ematch/tc_em_text.h>
 16#include <net/pkt_cls.h>
 17
 18struct text_match {
 19	u16			from_offset;
 20	u16			to_offset;
 21	u8			from_layer;
 22	u8			to_layer;
 23	struct ts_config	*config;
 24};
 25
 26#define EM_TEXT_PRIV(m) ((struct text_match *) (m)->data)
 27
 28static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m,
 29			 struct tcf_pkt_info *info)
 30{
 31	struct text_match *tm = EM_TEXT_PRIV(m);
 32	unsigned char *ptr;
 33	int from, to;
 34
 35	ptr = tcf_get_base_ptr(skb, tm->from_layer);
 36	if (!ptr)
 37		return 0;
 38	from = ptr - skb->data;
 39	from += tm->from_offset;
 40
 41	ptr = tcf_get_base_ptr(skb, tm->to_layer);
 42	if (!ptr)
 43		return 0;
 44	to = ptr - skb->data;
 45	to += tm->to_offset;
 46
 47	return skb_find_text(skb, from, to, tm->config) != UINT_MAX;
 48}
 49
 50static int em_text_change(struct net *net, void *data, int len,
 51			  struct tcf_ematch *m)
 52{
 53	struct text_match *tm;
 54	struct tcf_em_text *conf = data;
 55	struct ts_config *ts_conf;
 56	int flags = 0;
 57
 58	if (len < sizeof(*conf) || len < (sizeof(*conf) + conf->pattern_len))
 59		return -EINVAL;
 60
 61	if (conf->from_layer > conf->to_layer)
 62		return -EINVAL;
 63
 64	if (conf->from_layer == conf->to_layer &&
 65	    conf->from_offset > conf->to_offset)
 66		return -EINVAL;
 67
 68retry:
 69	ts_conf = textsearch_prepare(conf->algo, (u8 *) conf + sizeof(*conf),
 70				     conf->pattern_len, GFP_KERNEL, flags);
 71
 72	if (flags & TS_AUTOLOAD)
 73		rtnl_lock();
 74
 75	if (IS_ERR(ts_conf)) {
 76		if (PTR_ERR(ts_conf) == -ENOENT && !(flags & TS_AUTOLOAD)) {
 77			rtnl_unlock();
 78			flags |= TS_AUTOLOAD;
 79			goto retry;
 80		} else
 81			return PTR_ERR(ts_conf);
 82	} else if (flags & TS_AUTOLOAD) {
 83		textsearch_destroy(ts_conf);
 84		return -EAGAIN;
 85	}
 86
 87	tm = kmalloc(sizeof(*tm), GFP_KERNEL);
 88	if (tm == NULL) {
 89		textsearch_destroy(ts_conf);
 90		return -ENOBUFS;
 91	}
 92
 93	tm->from_offset = conf->from_offset;
 94	tm->to_offset   = conf->to_offset;
 95	tm->from_layer  = conf->from_layer;
 96	tm->to_layer    = conf->to_layer;
 97	tm->config      = ts_conf;
 98
 99	m->datalen = sizeof(*tm);
100	m->data = (unsigned long) tm;
101
102	return 0;
103}
104
105static void em_text_destroy(struct tcf_ematch *m)
106{
107	if (EM_TEXT_PRIV(m) && EM_TEXT_PRIV(m)->config) {
108		textsearch_destroy(EM_TEXT_PRIV(m)->config);
109		kfree(EM_TEXT_PRIV(m));
110	}
111}
112
113static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m)
114{
115	struct text_match *tm = EM_TEXT_PRIV(m);
116	struct tcf_em_text conf;
117
118	strscpy(conf.algo, tm->config->ops->name);
119	conf.from_offset = tm->from_offset;
120	conf.to_offset = tm->to_offset;
121	conf.from_layer = tm->from_layer;
122	conf.to_layer = tm->to_layer;
123	conf.pattern_len = textsearch_get_pattern_len(tm->config);
124	conf.pad = 0;
125
126	if (nla_put_nohdr(skb, sizeof(conf), &conf) < 0)
127		goto nla_put_failure;
128	if (nla_append(skb, conf.pattern_len,
129		       textsearch_get_pattern(tm->config)) < 0)
130		goto nla_put_failure;
131	return 0;
132
133nla_put_failure:
134	return -1;
135}
136
137static struct tcf_ematch_ops em_text_ops = {
138	.kind	  = TCF_EM_TEXT,
139	.change	  = em_text_change,
140	.match	  = em_text_match,
141	.destroy  = em_text_destroy,
142	.dump	  = em_text_dump,
143	.owner	  = THIS_MODULE,
144	.link	  = LIST_HEAD_INIT(em_text_ops.link)
145};
146
147static int __init init_em_text(void)
148{
149	return tcf_em_register(&em_text_ops);
150}
151
152static void __exit exit_em_text(void)
153{
154	tcf_em_unregister(&em_text_ops);
155}
156
157MODULE_DESCRIPTION("ematch classifier for embedded text in skbs");
158MODULE_LICENSE("GPL");
159
160module_init(init_em_text);
161module_exit(exit_em_text);
162
163MODULE_ALIAS_TCF_EMATCH(TCF_EM_TEXT);
~/ Read-only file preview.