Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 1 | /*** |
| 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 }, |
| 24 | const 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 | */ |
| 47 | static 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 69 | FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 75 | FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 89 | FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 90 | } |
| 91 | else if (flt_ot_is_disabled(filter FLT_OT_DBG_ARGS(, -1))) { |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 92 | FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 110 | FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 120 | FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | */ |
| 141 | static 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 169 | FLT_OT_RETURN_INT(0); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 194 | FLT_OT_RETURN_INT(0); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 211 | FLT_OT_RETURN_INT(0); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 221 | FLT_OT_RETURN_INT(1); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | */ |
| 239 | static 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 | */ |
| 264 | static 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 275 | FLT_OT_RETURN_EX(ACT_RET_PRS_ERR, enum act_parse_ret, "%d"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 283 | FLT_OT_RETURN_EX(ACT_RET_PRS_ERR, enum act_parse_ret, "%d"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 293 | FLT_OT_RETURN_EX(ACT_RET_PRS_ERR, enum act_parse_ret, "%d"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 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 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 303 | FLT_OT_RETURN_EX(ACT_RET_PRS_OK, enum act_parse_ret, "%d"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 304 | } |
| 305 | |
| 306 | |
| 307 | static struct action_kw_list tcp_req_action_kws = { ILH, { |
| 308 | { FLT_OT_ACTION_GROUP, flt_ot_group_parse }, |
| 309 | { /* END */ }, |
| 310 | } |
| 311 | }; |
| 312 | |
| 313 | INITCALL1(STG_REGISTER, tcp_req_cont_keywords_register, &tcp_req_action_kws); |
| 314 | |
| 315 | static struct action_kw_list tcp_res_action_kws = { ILH, { |
| 316 | { FLT_OT_ACTION_GROUP, flt_ot_group_parse }, |
| 317 | { /* END */ }, |
| 318 | } |
| 319 | }; |
| 320 | |
| 321 | INITCALL1(STG_REGISTER, tcp_res_cont_keywords_register, &tcp_res_action_kws); |
| 322 | |
| 323 | static struct action_kw_list http_req_action_kws = { ILH, { |
| 324 | { FLT_OT_ACTION_GROUP, flt_ot_group_parse }, |
| 325 | { /* END */ }, |
| 326 | } |
| 327 | }; |
| 328 | |
| 329 | INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_action_kws); |
| 330 | |
| 331 | static struct action_kw_list http_res_action_kws = { ILH, { |
| 332 | { FLT_OT_ACTION_GROUP, flt_ot_group_parse }, |
| 333 | { /* END */ }, |
| 334 | } |
| 335 | }; |
| 336 | |
| 337 | INITCALL1(STG_REGISTER, http_res_keywords_register, &http_res_action_kws); |
| 338 | |
| 339 | static struct action_kw_list http_after_res_actions_kws = { ILH, { |
| 340 | { FLT_OT_ACTION_GROUP, flt_ot_group_parse }, |
| 341 | { /* END */ }, |
| 342 | } |
| 343 | }; |
| 344 | |
| 345 | INITCALL1(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 | */ |