• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * lib/route/cls/ematch/text.c		Text Search
3  *
4  *	This library is free software; you can redistribute it and/or
5  *	modify it under the terms of the GNU Lesser General Public
6  *	License as published by the Free Software Foundation version 2.1
7  *	of the License.
8  *
9  * Copyright (c) 2010-2013 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 /**
13  * @ingroup ematch
14  * @defgroup em_text Text Search
15  *
16  * @{
17  */
18 
19 #include <netlink-private/netlink.h>
20 #include <netlink-private/tc.h>
21 #include <netlink/netlink.h>
22 #include <netlink/route/cls/ematch.h>
23 #include <netlink/route/cls/ematch/text.h>
24 #include <linux/tc_ematch/tc_em_text.h>
25 
26 struct text_data
27 {
28 	struct tcf_em_text	cfg;
29 	char *			pattern;
30 };
31 
rtnl_ematch_text_set_from(struct rtnl_ematch * e,uint8_t layer,uint16_t offset)32 void rtnl_ematch_text_set_from(struct rtnl_ematch *e, uint8_t layer,
33 			       uint16_t offset)
34 {
35 	struct text_data *t = rtnl_ematch_data(e);
36 	t->cfg.from_offset = offset;
37 	t->cfg.from_layer = layer;
38 }
39 
rtnl_ematch_text_get_from_offset(struct rtnl_ematch * e)40 uint16_t rtnl_ematch_text_get_from_offset(struct rtnl_ematch *e)
41 {
42 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_offset;
43 }
44 
rtnl_ematch_text_get_from_layer(struct rtnl_ematch * e)45 uint8_t rtnl_ematch_text_get_from_layer(struct rtnl_ematch *e)
46 {
47 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_layer;
48 }
49 
rtnl_ematch_text_set_to(struct rtnl_ematch * e,uint8_t layer,uint16_t offset)50 void rtnl_ematch_text_set_to(struct rtnl_ematch *e, uint8_t layer,
51 			       uint16_t offset)
52 {
53 	struct text_data *t = rtnl_ematch_data(e);
54 	t->cfg.to_offset = offset;
55 	t->cfg.to_layer = layer;
56 }
57 
rtnl_ematch_text_get_to_offset(struct rtnl_ematch * e)58 uint16_t rtnl_ematch_text_get_to_offset(struct rtnl_ematch *e)
59 {
60 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_offset;
61 }
62 
rtnl_ematch_text_get_to_layer(struct rtnl_ematch * e)63 uint8_t rtnl_ematch_text_get_to_layer(struct rtnl_ematch *e)
64 {
65 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_layer;
66 }
67 
rtnl_ematch_text_set_pattern(struct rtnl_ematch * e,char * pattern,size_t len)68 void rtnl_ematch_text_set_pattern(struct rtnl_ematch *e,
69 				  char *pattern, size_t len)
70 {
71 	struct text_data *t = rtnl_ematch_data(e);
72 
73 	if (t->pattern)
74 		free(t->pattern);
75 
76 	t->pattern = pattern;
77 	t->cfg.pattern_len = len;
78 }
79 
rtnl_ematch_text_get_pattern(struct rtnl_ematch * e)80 char *rtnl_ematch_text_get_pattern(struct rtnl_ematch *e)
81 {
82 	return ((struct text_data *) rtnl_ematch_data(e))->pattern;
83 }
84 
rtnl_ematch_text_get_len(struct rtnl_ematch * e)85 size_t rtnl_ematch_text_get_len(struct rtnl_ematch *e)
86 {
87 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.pattern_len;
88 }
89 
rtnl_ematch_text_set_algo(struct rtnl_ematch * e,const char * algo)90 void rtnl_ematch_text_set_algo(struct rtnl_ematch *e, const char *algo)
91 {
92 	struct text_data *t = rtnl_ematch_data(e);
93 
94 	strncpy(t->cfg.algo, algo, sizeof(t->cfg.algo));
95 	t->cfg.algo[sizeof(t->cfg.algo) - 1] = '\0';
96 }
97 
rtnl_ematch_text_get_algo(struct rtnl_ematch * e)98 char *rtnl_ematch_text_get_algo(struct rtnl_ematch *e)
99 {
100 	struct text_data *t = rtnl_ematch_data(e);
101 
102 	return t->cfg.algo[0] ? t->cfg.algo : NULL;
103 }
104 
text_parse(struct rtnl_ematch * e,void * data,size_t len)105 static int text_parse(struct rtnl_ematch *e, void *data, size_t len)
106 {
107 	struct text_data *t = rtnl_ematch_data(e);
108 	size_t hdrlen = sizeof(struct tcf_em_text);
109 	size_t plen = len - hdrlen;
110 
111 	memcpy(&t->cfg, data, hdrlen);
112 
113 	if (t->cfg.pattern_len > plen)
114 		return -NLE_INVAL;
115 
116 	if (t->cfg.pattern_len > 0) {
117 		if (!(t->pattern = calloc(1, t->cfg.pattern_len)))
118 			return -NLE_NOMEM;
119 
120 		memcpy(t->pattern, (char *) data + hdrlen, t->cfg.pattern_len);
121 	}
122 
123 	return 0;
124 }
125 
text_dump(struct rtnl_ematch * e,struct nl_dump_params * p)126 static void text_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
127 {
128 	struct text_data *t = rtnl_ematch_data(e);
129 	char buf[64];
130 
131 	nl_dump(p, "text(%s \"%s\"",
132 		t->cfg.algo[0] ? t->cfg.algo : "no-algo",
133 		t->pattern ? t->pattern : "no-pattern");
134 
135 	if (t->cfg.from_layer || t->cfg.from_offset) {
136 		nl_dump(p, " from %s",
137 			rtnl_ematch_offset2txt(t->cfg.from_layer,
138 					       t->cfg.from_offset,
139 					       buf, sizeof(buf)));
140 	}
141 
142 	if (t->cfg.to_layer || t->cfg.to_offset) {
143 		nl_dump(p, " to %s",
144 			rtnl_ematch_offset2txt(t->cfg.to_layer,
145 					       t->cfg.to_offset,
146 					       buf, sizeof(buf)));
147 	}
148 
149 	nl_dump(p, ")");
150 }
151 
text_fill(struct rtnl_ematch * e,struct nl_msg * msg)152 static int text_fill(struct rtnl_ematch *e, struct nl_msg *msg)
153 {
154 	struct text_data *t = rtnl_ematch_data(e);
155 	int err;
156 
157 	if ((err = nlmsg_append(msg, &t->cfg, sizeof(t->cfg), 0)) < 0)
158 		return err;
159 
160 	return nlmsg_append(msg, t->pattern, t->cfg.pattern_len, 0);
161 }
162 
text_free(struct rtnl_ematch * e)163 static void text_free(struct rtnl_ematch *e)
164 {
165 	struct text_data *t = rtnl_ematch_data(e);
166 	free(t->pattern);
167 }
168 
169 static struct rtnl_ematch_ops text_ops = {
170 	.eo_kind	= TCF_EM_TEXT,
171 	.eo_name	= "text",
172 	.eo_minlen	= sizeof(struct tcf_em_text),
173 	.eo_datalen	= sizeof(struct text_data),
174 	.eo_parse	= text_parse,
175 	.eo_dump	= text_dump,
176 	.eo_fill	= text_fill,
177 	.eo_free	= text_free,
178 };
179 
text_init(void)180 static void __init text_init(void)
181 {
182 	rtnl_ematch_register(&text_ops);
183 }
184 
185 /** @} */
186