• 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 
25 struct text_data
26 {
27 	struct tcf_em_text	cfg;
28 	char *			pattern;
29 };
30 
rtnl_ematch_text_set_from(struct rtnl_ematch * e,uint8_t layer,uint16_t offset)31 void rtnl_ematch_text_set_from(struct rtnl_ematch *e, uint8_t layer,
32 			       uint16_t offset)
33 {
34 	struct text_data *t = rtnl_ematch_data(e);
35 	t->cfg.from_offset = offset;
36 	t->cfg.from_layer = layer;
37 }
38 
rtnl_ematch_text_get_from_offset(struct rtnl_ematch * e)39 uint16_t rtnl_ematch_text_get_from_offset(struct rtnl_ematch *e)
40 {
41 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_offset;
42 }
43 
rtnl_ematch_text_get_from_layer(struct rtnl_ematch * e)44 uint8_t rtnl_ematch_text_get_from_layer(struct rtnl_ematch *e)
45 {
46 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_layer;
47 }
48 
rtnl_ematch_text_set_to(struct rtnl_ematch * e,uint8_t layer,uint16_t offset)49 void rtnl_ematch_text_set_to(struct rtnl_ematch *e, uint8_t layer,
50 			       uint16_t offset)
51 {
52 	struct text_data *t = rtnl_ematch_data(e);
53 	t->cfg.to_offset = offset;
54 	t->cfg.to_layer = layer;
55 }
56 
rtnl_ematch_text_get_to_offset(struct rtnl_ematch * e)57 uint16_t rtnl_ematch_text_get_to_offset(struct rtnl_ematch *e)
58 {
59 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_offset;
60 }
61 
rtnl_ematch_text_get_to_layer(struct rtnl_ematch * e)62 uint8_t rtnl_ematch_text_get_to_layer(struct rtnl_ematch *e)
63 {
64 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_layer;
65 }
66 
rtnl_ematch_text_set_pattern(struct rtnl_ematch * e,char * pattern,size_t len)67 void rtnl_ematch_text_set_pattern(struct rtnl_ematch *e,
68 				  char *pattern, size_t len)
69 {
70 	struct text_data *t = rtnl_ematch_data(e);
71 
72 	if (t->pattern)
73 		free(t->pattern);
74 
75 	t->pattern = pattern;
76 	t->cfg.pattern_len = len;
77 }
78 
rtnl_ematch_text_get_pattern(struct rtnl_ematch * e)79 char *rtnl_ematch_text_get_pattern(struct rtnl_ematch *e)
80 {
81 	return ((struct text_data *) rtnl_ematch_data(e))->pattern;
82 }
83 
rtnl_ematch_text_get_len(struct rtnl_ematch * e)84 size_t rtnl_ematch_text_get_len(struct rtnl_ematch *e)
85 {
86 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.pattern_len;
87 }
88 
rtnl_ematch_text_set_algo(struct rtnl_ematch * e,const char * algo)89 void rtnl_ematch_text_set_algo(struct rtnl_ematch *e, const char *algo)
90 {
91 	struct text_data *t = rtnl_ematch_data(e);
92 
93 	strncpy(t->cfg.algo, algo, sizeof(t->cfg.algo));
94 }
95 
rtnl_ematch_text_get_algo(struct rtnl_ematch * e)96 char *rtnl_ematch_text_get_algo(struct rtnl_ematch *e)
97 {
98 	struct text_data *t = rtnl_ematch_data(e);
99 
100 	return t->cfg.algo[0] ? t->cfg.algo : NULL;
101 }
102 
text_parse(struct rtnl_ematch * e,void * data,size_t len)103 static int text_parse(struct rtnl_ematch *e, void *data, size_t len)
104 {
105 	struct text_data *t = rtnl_ematch_data(e);
106 	size_t hdrlen = sizeof(struct tcf_em_text);
107 	size_t plen = len - hdrlen;
108 
109 	memcpy(&t->cfg, data, hdrlen);
110 
111 	if (t->cfg.pattern_len > plen)
112 		return -NLE_INVAL;
113 
114 	if (t->cfg.pattern_len > 0) {
115 		if (!(t->pattern = calloc(1, t->cfg.pattern_len)))
116 			return -NLE_NOMEM;
117 
118 		memcpy(t->pattern, data + hdrlen, t->cfg.pattern_len);
119 	}
120 
121 	return 0;
122 }
123 
text_dump(struct rtnl_ematch * e,struct nl_dump_params * p)124 static void text_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
125 {
126 	struct text_data *t = rtnl_ematch_data(e);
127 	char buf[64];
128 
129 	nl_dump(p, "text(%s \"%s\"",
130 		t->cfg.algo[0] ? t->cfg.algo : "no-algo",
131 		t->pattern ? : "no-pattern");
132 
133 	if (t->cfg.from_layer || t->cfg.from_offset) {
134 		nl_dump(p, " from %s",
135 			rtnl_ematch_offset2txt(t->cfg.from_layer,
136 					       t->cfg.from_offset,
137 					       buf, sizeof(buf)));
138 	}
139 
140 	if (t->cfg.to_layer || t->cfg.to_offset) {
141 		nl_dump(p, " to %s",
142 			rtnl_ematch_offset2txt(t->cfg.to_layer,
143 					       t->cfg.to_offset,
144 					       buf, sizeof(buf)));
145 	}
146 
147 	nl_dump(p, ")");
148 }
149 
text_fill(struct rtnl_ematch * e,struct nl_msg * msg)150 static int text_fill(struct rtnl_ematch *e, struct nl_msg *msg)
151 {
152 	struct text_data *t = rtnl_ematch_data(e);
153 	int err;
154 
155 	if ((err = nlmsg_append(msg, &t->cfg, sizeof(t->cfg), 0)) < 0)
156 		return err;
157 
158 	return nlmsg_append(msg, t->pattern, t->cfg.pattern_len, 0);
159 }
160 
text_free(struct rtnl_ematch * e)161 static void text_free(struct rtnl_ematch *e)
162 {
163 	struct text_data *t = rtnl_ematch_data(e);
164 	free(t->pattern);
165 }
166 
167 static struct rtnl_ematch_ops text_ops = {
168 	.eo_kind	= TCF_EM_TEXT,
169 	.eo_name	= "text",
170 	.eo_minlen	= sizeof(struct tcf_em_text),
171 	.eo_datalen	= sizeof(struct text_data),
172 	.eo_parse	= text_parse,
173 	.eo_dump	= text_dump,
174 	.eo_fill	= text_fill,
175 	.eo_free	= text_free,
176 };
177 
text_init(void)178 static void __init text_init(void)
179 {
180 	rtnl_ematch_register(&text_ops);
181 }
182 
183 /** @} */
184