blob: f9fdeccb9cb7aa83623b6e2a9fe40da8b6c83418 [file] [log] [blame]
Miroslav Zagorac70230c62020-12-09 16:54:31 +01001/***
2 * Copyright 2020 HAProxy Technologies
3 *
4 * This file is part of the HAProxy OpenTracing filter.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20#include "include.h"
21
22
23#define FLT_OT_GROUP_DEF(a,b,c) { a, b, c },
24const struct flt_ot_group_data flt_ot_group_data[] = { FLT_OT_GROUP_DEFINES };
25#undef FLT_OT_GROUP_DEF
26
27
28/***
29 * NAME
30 * flt_ot_group_action -
31 *
32 * ARGUMENTS
33 * rule -
34 * px -
35 * sess -
36 * s -
37 * opts -
38 *
39 * DESCRIPTION
40 * This is the action_ptr callback of a rule associated to the
41 * FLT_OT_ACTION_GROUP action.
42 *
43 * RETURN VALUE
44 * The function returns ACT_RET_CONT if processing is finished (with error or
45 * not), otherwise, it returns ACT_RET_YIELD if the action is in progress.
46 */
47static enum act_return flt_ot_group_action(struct act_rule *rule, struct proxy *px, struct session *sess, struct stream *s, int opts)
48{
49 const struct filter *filter;
50 const struct flt_conf *fconf;
51 const struct flt_ot_conf *conf;
52 const struct flt_ot_conf_group *conf_group;
53 const struct flt_ot_runtime_context *rt_ctx = NULL;
54 const struct flt_ot_conf_ph *ph_scope;
55 char *err = NULL;
56 int i, rc;
57
58 FLT_OT_FUNC("%p, %p, %p, %p, %d", rule, px, sess, s, opts);
59
60 FLT_OT_DBG(3, "from: %d, arg.act %p:{ %p %p %p %p }", rule->from, &(rule->arg.act), rule->arg.act.p[0], rule->arg.act.p[1], rule->arg.act.p[2], rule->arg.act.p[3]);
61
62 fconf = rule->arg.act.p[FLT_OT_ARG_FLT_CONF];
63 conf = rule->arg.act.p[FLT_OT_ARG_CONF];
64 conf_group = ((const struct flt_ot_conf_ph *)(rule->arg.act.p[FLT_OT_ARG_GROUP]))->ptr;
65
66 if ((fconf == NULL) || (conf == NULL) || (conf_group == NULL)) {
67 FLT_OT_LOG(LOG_ERR, FLT_OT_ACTION_GROUP ": internal error, invalid group action");
68
69 FLT_OT_RETURN(ACT_RET_CONT);
70 }
71
72 if (conf->tracer->flag_disabled) {
73 FLT_OT_DBG(1, "filter '%s' disabled, group action '%s' ignored", conf->id, conf_group->id);
74
75 FLT_OT_RETURN(ACT_RET_CONT);
76 }
77
78 /* Find the OpenTracing filter instance from the current stream. */
79 list_for_each_entry(filter, &(s->strm_flt.filters), list)
80 if (filter->config == fconf) {
81 rt_ctx = filter->ctx;
82
83 break;
84 }
85
86 if (rt_ctx == NULL) {
87 FLT_OT_DBG(1, "cannot find filter, probably not attached to the stream");
88
89 FLT_OT_RETURN(ACT_RET_CONT);
90 }
91 else if (flt_ot_is_disabled(filter FLT_OT_DBG_ARGS(, -1))) {
92 FLT_OT_RETURN(ACT_RET_CONT);
93 }
94 else {
95 FLT_OT_DBG(3, "run group '%s'", conf_group->id);
96 FLT_OT_DBG_CONF_GROUP("run group ", conf_group);
97 }
98
99 /*
100 * Check the value of rule->from; in case it is incorrect,
101 * report an error.
102 */
103 for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_group_data); i++)
104 if (flt_ot_group_data[i].act_from == rule->from)
105 break;
106
107 if (i >= FLT_OT_TABLESIZE(flt_ot_group_data)) {
108 FLT_OT_LOG(LOG_ERR, FLT_OT_ACTION_GROUP ": internal error, invalid rule->from=%d", rule->from);
109
110 FLT_OT_RETURN(ACT_RET_CONT);
111 }
112
113 list_for_each_entry(ph_scope, &(conf_group->ph_scopes), list) {
114 rc = flt_ot_scope_run(s, rt_ctx->filter, &(s->res), ph_scope->ptr, NULL, SMP_OPT_DIR_RES, &err);
115 if ((rc == FLT_OT_RET_ERROR) && (opts & ACT_OPT_FINAL)) {
116 /* XXX */
117 }
118 }
119
120 FLT_OT_RETURN(ACT_RET_CONT);
121}
122
123
124/***
125 * NAME
126 * flt_ot_group_check -
127 *
128 * ARGUMENTS
129 * rule -
130 * px -
131 * err -
132 *
133 * DESCRIPTION
134 * This is the check_ptr callback of a rule associated to the
135 * FLT_OT_ACTION_GROUP action.
136 *
137 * RETURN VALUE
138 * The function returns 1 in success case, otherwise,
139 * it returns 0 and err is filled.
140 */
141static int flt_ot_group_check(struct act_rule *rule, struct proxy *px, char **err)
142{
143 struct flt_conf *fconf_tmp, *fconf = NULL;
144 struct flt_ot_conf *conf;
145 struct flt_ot_conf_ph *ph_group;
146 const char *filter_id;
147 const char *group_id;
148 bool flag_found = 0;
149 int i;
150
151 FLT_OT_FUNC("%p, %p, %p:%p", rule, px, FLT_OT_DPTR_ARGS(err));
152
153 filter_id = rule->arg.act.p[FLT_OT_ARG_FILTER_ID];
154 group_id = rule->arg.act.p[FLT_OT_ARG_GROUP_ID];
155
156 FLT_OT_DBG(2, "checking filter_id='%s', group_id='%s'", filter_id, group_id);
157
158 /*
159 * Check the value of rule->from; in case it is incorrect,
160 * report an error.
161 */
162 for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_group_data); i++)
163 if (flt_ot_group_data[i].act_from == rule->from)
164 break;
165
166 if (i >= FLT_OT_TABLESIZE(flt_ot_group_data)) {
167 FLT_OT_ERR("internal error, unexpected rule->from=%d, please report this bug!", rule->from);
168
169 FLT_OT_RETURN(0);
170 }
171
172 /*
173 * Try to find the OpenTracing filter by checking all filters
174 * for the proxy <px>.
175 */
176 list_for_each_entry(fconf_tmp, &(px->filter_configs), list) {
177 conf = fconf_tmp->conf;
178
179 if (fconf_tmp->id != ot_flt_id) {
180 /* This is not an OpenTracing filter. */
181 continue;
182 }
183 else if (strcmp(conf->id, filter_id) == 0) {
184 /* This is the good filter ID. */
185 fconf = fconf_tmp;
186
187 break;
188 }
189 }
190
191 if (fconf == NULL) {
192 FLT_OT_ERR("unable to find the OpenTracing filter '%s' used by the " FLT_OT_ACTION_GROUP " '%s'", filter_id, group_id);
193
194 FLT_OT_RETURN(0);
195 }
196
197 /*
198 * Attempt to find if the group is defined in the OpenTracing filter
199 * configuration.
200 */
201 list_for_each_entry(ph_group, &(conf->tracer->ph_groups), list)
202 if (strcmp(ph_group->id, group_id) == 0) {
203 flag_found = 1;
204
205 break;
206 }
207
208 if (!flag_found) {
209 FLT_OT_ERR("unable to find group '%s' in the OpenTracing filter '%s' configuration", group_id, filter_id);
210
211 FLT_OT_RETURN(0);
212 }
213
214 FLT_OT_FREE_CLEAR(rule->arg.act.p[FLT_OT_ARG_FILTER_ID]);
215 FLT_OT_FREE_CLEAR(rule->arg.act.p[FLT_OT_ARG_GROUP_ID]);
216
217 rule->arg.act.p[FLT_OT_ARG_FLT_CONF] = fconf;
218 rule->arg.act.p[FLT_OT_ARG_CONF] = conf;
219 rule->arg.act.p[FLT_OT_ARG_GROUP] = ph_group;
220
221 FLT_OT_RETURN(1);
222}
223
224
225/***
226 * NAME
227 * flt_ot_group_release -
228 *
229 * ARGUMENTS
230 * rule -
231 *
232 * DESCRIPTION
233 * This is the release_ptr callback of a rule associated to the
234 * FLT_OT_ACTION_GROUP action.
235 *
236 * RETURN VALUE
237 * This function does not return a value.
238 */
239static void flt_ot_group_release(struct act_rule *rule)
240{
241 FLT_OT_FUNC("%p", rule);
242
243 FLT_OT_RETURN();
244}
245
246
247/***
248 * NAME
249 * flt_ot_group_parse -
250 *
251 * ARGUMENTS
252 * args -
253 * cur_arg -
254 * px -
255 * rule -
256 * err -
257 *
258 * DESCRIPTION
259 * -
260 *
261 * RETURN VALUE
262 * Returns ACT_RET_PRS_ERR if an error occurs, ACT_RET_PRS_OK otherwise.
263 */
264static enum act_parse_ret flt_ot_group_parse(const char **args, int *cur_arg, struct proxy *px, struct act_rule *rule, char **err)
265{
266 FLT_OT_FUNC("%p, %p, %p, %p, %p:%p", args, cur_arg, px, rule, FLT_OT_DPTR_ARGS(err));
267
268 if (!FLT_OT_ARG_ISVALID(*cur_arg) ||
269 !FLT_OT_ARG_ISVALID(*cur_arg + 1) ||
270 (FLT_OT_ARG_ISVALID(*cur_arg + 2) &&
271 (strcmp(args[*cur_arg + 2], FLT_OT_CONDITION_IF) != 0) &&
272 (strcmp(args[*cur_arg + 2], FLT_OT_CONDITION_UNLESS) != 0))) {
273 FLT_OT_ERR("expects: <filter-id> <group-id> [{ if | unless } ...]");
274
275 FLT_OT_RETURN(ACT_RET_PRS_ERR);
276 }
277
278 /* Copy the OpenTracing filter id. */
279 rule->arg.act.p[FLT_OT_ARG_FILTER_ID] = FLT_OT_STRDUP(args[*cur_arg]);
280 if (rule->arg.act.p[FLT_OT_ARG_FILTER_ID] == NULL) {
281 FLT_OT_ERR("%s : out of memory", args[*cur_arg]);
282
283 FLT_OT_RETURN(ACT_RET_PRS_ERR);
284 }
285
286 /* Copy the OpenTracing group id. */
287 rule->arg.act.p[FLT_OT_ARG_GROUP_ID] = FLT_OT_STRDUP(args[*cur_arg + 1]);
288 if (rule->arg.act.p[FLT_OT_ARG_GROUP_ID] == NULL) {
289 FLT_OT_ERR("%s : out of memory", args[*cur_arg + 1]);
290
291 FLT_OT_FREE_CLEAR(rule->arg.act.p[FLT_OT_ARG_FILTER_ID]);
292
293 FLT_OT_RETURN(ACT_RET_PRS_ERR);
294 }
295
296 rule->action = ACT_CUSTOM;
297 rule->action_ptr = flt_ot_group_action;
298 rule->check_ptr = flt_ot_group_check;
299 rule->release_ptr = flt_ot_group_release;
300
301 *cur_arg += 2;
302
303 FLT_OT_RETURN(ACT_RET_PRS_OK);
304}
305
306
307static struct action_kw_list tcp_req_action_kws = { ILH, {
308 { FLT_OT_ACTION_GROUP, flt_ot_group_parse },
309 { /* END */ },
310 }
311};
312
313INITCALL1(STG_REGISTER, tcp_req_cont_keywords_register, &tcp_req_action_kws);
314
315static struct action_kw_list tcp_res_action_kws = { ILH, {
316 { FLT_OT_ACTION_GROUP, flt_ot_group_parse },
317 { /* END */ },
318 }
319};
320
321INITCALL1(STG_REGISTER, tcp_res_cont_keywords_register, &tcp_res_action_kws);
322
323static struct action_kw_list http_req_action_kws = { ILH, {
324 { FLT_OT_ACTION_GROUP, flt_ot_group_parse },
325 { /* END */ },
326 }
327};
328
329INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_action_kws);
330
331static struct action_kw_list http_res_action_kws = { ILH, {
332 { FLT_OT_ACTION_GROUP, flt_ot_group_parse },
333 { /* END */ },
334 }
335};
336
337INITCALL1(STG_REGISTER, http_res_keywords_register, &http_res_action_kws);
338
339static struct action_kw_list http_after_res_actions_kws = { ILH, {
340 { FLT_OT_ACTION_GROUP, flt_ot_group_parse },
341 { /* END */ },
342 }
343};
344
345INITCALL1(STG_REGISTER, http_after_res_keywords_register, &http_after_res_actions_kws);
346
347/*
348 * Local variables:
349 * c-indent-level: 8
350 * c-basic-offset: 8
351 * End:
352 *
353 * vi: noexpandtab shiftwidth=8 tabstop=8
354 */