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 | #ifdef DEBUG_OT |
| 24 | |
| 25 | /*** |
| 26 | * NAME |
| 27 | * flt_ot_args_dump - |
| 28 | * |
| 29 | * ARGUMENTS |
| 30 | * args - |
| 31 | * |
| 32 | * DESCRIPTION |
| 33 | * - |
| 34 | * |
| 35 | * RETURN VALUE |
| 36 | * This function does not return a value. |
| 37 | */ |
| 38 | void flt_ot_args_dump(char **args) |
| 39 | { |
Miroslav Zagorac | 4b3eb0a | 2021-04-14 11:44:58 +0200 | [diff] [blame] | 40 | int i, argc; |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 41 | |
Miroslav Zagorac | 4b3eb0a | 2021-04-14 11:44:58 +0200 | [diff] [blame] | 42 | argc = flt_ot_args_count(args); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 43 | |
Miroslav Zagorac | 4b3eb0a | 2021-04-14 11:44:58 +0200 | [diff] [blame] | 44 | (void)fprintf(stderr, FLT_OT_DBG_FMT("%.*sargs[%d]: { '%s' "), dbg_indent_level, FLT_OT_DBG_INDENT, argc, args[0]); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 45 | |
Miroslav Zagorac | 4b3eb0a | 2021-04-14 11:44:58 +0200 | [diff] [blame] | 46 | for (i = 1; i < argc; i++) |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 47 | (void)fprintf(stderr, "'%s' ", args[i]); |
| 48 | |
| 49 | (void)fprintf(stderr, "}\n"); |
| 50 | } |
| 51 | |
| 52 | |
| 53 | /*** |
| 54 | * NAME |
| 55 | * flt_ot_filters_dump - |
| 56 | * |
| 57 | * ARGUMENTS |
| 58 | * This function takes no arguments. |
| 59 | * |
| 60 | * DESCRIPTION |
| 61 | * - |
| 62 | * |
| 63 | * RETURN VALUE |
| 64 | * This function does not return a value. |
| 65 | */ |
| 66 | void flt_ot_filters_dump(void) |
| 67 | { |
| 68 | struct flt_conf *fconf; |
| 69 | struct proxy *px; |
| 70 | |
| 71 | FLT_OT_FUNC(""); |
| 72 | |
| 73 | for (px = proxies_list; px != NULL; px = px->next) { |
| 74 | FLT_OT_DBG(2, "proxy '%s'", px->id); |
| 75 | |
| 76 | list_for_each_entry(fconf, &(px->filter_configs), list) |
| 77 | if (fconf->id == ot_flt_id) { |
| 78 | struct flt_ot_conf *conf = fconf->conf; |
| 79 | |
| 80 | FLT_OT_DBG(2, " OT filter '%s'", conf->id); |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | FLT_OT_RETURN(); |
| 85 | } |
| 86 | |
| 87 | |
| 88 | /*** |
| 89 | * NAME |
| 90 | * flt_ot_chn_label - |
| 91 | * |
| 92 | * ARGUMENTS |
| 93 | * chn - |
| 94 | * |
| 95 | * DESCRIPTION |
| 96 | * - |
| 97 | * |
| 98 | * RETURN VALUE |
| 99 | * - |
| 100 | */ |
| 101 | const char *flt_ot_chn_label(const struct channel *chn) |
| 102 | { |
| 103 | return (chn->flags & CF_ISRESP) ? "RESponse" : "REQuest"; |
| 104 | } |
| 105 | |
| 106 | |
| 107 | /*** |
| 108 | * NAME |
| 109 | * flt_ot_pr_mode - |
| 110 | * |
| 111 | * ARGUMENTS |
| 112 | * s - |
| 113 | * |
| 114 | * DESCRIPTION |
| 115 | * - |
| 116 | * |
| 117 | * RETURN VALUE |
| 118 | * - |
| 119 | */ |
| 120 | const char *flt_ot_pr_mode(const struct stream *s) |
| 121 | { |
| 122 | struct proxy *px = (s->flags & SF_BE_ASSIGNED) ? s->be : strm_fe(s); |
| 123 | |
| 124 | return (px->mode == PR_MODE_HTTP) ? "HTTP" : "TCP"; |
| 125 | } |
| 126 | |
| 127 | |
| 128 | /*** |
| 129 | * NAME |
| 130 | * flt_ot_stream_pos - |
| 131 | * |
| 132 | * ARGUMENTS |
| 133 | * s - |
| 134 | * |
| 135 | * DESCRIPTION |
| 136 | * - |
| 137 | * |
| 138 | * RETURN VALUE |
| 139 | * - |
| 140 | */ |
| 141 | const char *flt_ot_stream_pos(const struct stream *s) |
| 142 | { |
| 143 | return (s->flags & SF_BE_ASSIGNED) ? "backend" : "frontend"; |
| 144 | } |
| 145 | |
| 146 | |
| 147 | /*** |
| 148 | * NAME |
| 149 | * flt_ot_type - |
| 150 | * |
| 151 | * ARGUMENTS |
| 152 | * f - |
| 153 | * |
| 154 | * DESCRIPTION |
| 155 | * - |
| 156 | * |
| 157 | * RETURN VALUE |
| 158 | * - |
| 159 | */ |
| 160 | const char *flt_ot_type(const struct filter *f) |
| 161 | { |
| 162 | return (f->flags & FLT_FL_IS_BACKEND_FILTER) ? "backend" : "frontend"; |
| 163 | } |
| 164 | |
| 165 | |
| 166 | /*** |
| 167 | * NAME |
| 168 | * flt_ot_analyzer - |
| 169 | * |
| 170 | * ARGUMENTS |
| 171 | * an_bit - |
| 172 | * |
| 173 | * DESCRIPTION |
| 174 | * - |
| 175 | * |
| 176 | * RETURN VALUE |
| 177 | * - |
| 178 | */ |
| 179 | const char *flt_ot_analyzer(uint an_bit) |
| 180 | { |
| 181 | #define FLT_OT_AN_DEF(a) { a, #a }, |
| 182 | static const struct { |
| 183 | uint an_bit; |
| 184 | const char *str; |
| 185 | } flt_ot_an[] = { FLT_OT_AN_DEFINES }; |
| 186 | #undef FLT_OT_AN_DEF |
| 187 | const char *retptr = "invalid an_bit"; |
| 188 | int i; |
| 189 | |
| 190 | for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_an); i++) |
| 191 | if (flt_ot_an[i].an_bit == an_bit) { |
| 192 | retptr = flt_ot_an[i].str; |
| 193 | |
| 194 | break; |
| 195 | } |
| 196 | |
| 197 | return retptr; |
| 198 | } |
| 199 | |
| 200 | |
| 201 | /*** |
| 202 | * NAME |
| 203 | * flt_ot_str_hex - |
| 204 | * |
| 205 | * ARGUMENTS |
| 206 | * data - |
| 207 | * size - |
| 208 | * |
| 209 | * DESCRIPTION |
| 210 | * - |
| 211 | * |
| 212 | * RETURN VALUE |
| 213 | * - |
| 214 | */ |
| 215 | const char *flt_ot_str_hex(const void *data, size_t size) |
| 216 | { |
| 217 | static THREAD_LOCAL char retbuf[BUFSIZ]; |
| 218 | const uint8_t *ptr = data; |
| 219 | size_t i; |
| 220 | |
| 221 | if (data == NULL) |
| 222 | return "(null)"; |
| 223 | else if (size == 0) |
| 224 | return "()"; |
| 225 | |
| 226 | for (i = 0, size <<= 1; (i < (sizeof(retbuf) - 2)) && (i < size); ptr++) { |
| 227 | retbuf[i++] = FLT_OT_NIBBLE_TO_HEX(*ptr >> 4); |
| 228 | retbuf[i++] = FLT_OT_NIBBLE_TO_HEX(*ptr & 0x0f); |
| 229 | } |
| 230 | |
| 231 | retbuf[i] = '\0'; |
| 232 | |
| 233 | return retbuf; |
| 234 | } |
| 235 | |
| 236 | |
| 237 | /*** |
| 238 | * NAME |
| 239 | * flt_ot_str_ctrl - |
| 240 | * |
| 241 | * ARGUMENTS |
| 242 | * data - |
| 243 | * size - |
| 244 | * |
| 245 | * DESCRIPTION |
| 246 | * - |
| 247 | * |
| 248 | * RETURN VALUE |
| 249 | * - |
| 250 | */ |
| 251 | const char *flt_ot_str_ctrl(const void *data, size_t size) |
| 252 | { |
| 253 | static THREAD_LOCAL char retbuf[BUFSIZ]; |
| 254 | const uint8_t *ptr = data; |
| 255 | size_t i, n = 0; |
| 256 | |
| 257 | if (data == NULL) |
| 258 | return "(null)"; |
| 259 | else if (size == 0) |
| 260 | return "()"; |
| 261 | |
| 262 | for (i = 0; (n < (sizeof(retbuf) - 1)) && (i < size); i++) |
| 263 | retbuf[n++] = ((ptr[i] >= 0x20) && (ptr[i] <= 0x7e)) ? ptr[i] : '.'; |
| 264 | |
| 265 | retbuf[n] = '\0'; |
| 266 | |
| 267 | return retbuf; |
| 268 | } |
| 269 | |
| 270 | |
| 271 | /*** |
| 272 | * NAME |
| 273 | * flt_ot_list_debug - |
| 274 | * |
| 275 | * ARGUMENTS |
| 276 | * head - |
| 277 | * |
| 278 | * DESCRIPTION |
| 279 | * - |
| 280 | * |
| 281 | * RETURN VALUE |
| 282 | * - |
| 283 | */ |
| 284 | const char *flt_ot_list_debug(const struct list *head) |
| 285 | { |
| 286 | FLT_OT_BUFFER_THR(retbuf, 4, 64, retptr); |
| 287 | |
| 288 | if ((head == NULL) || LIST_ISEMPTY(head)) { |
| 289 | (void)strncpy(retptr, (head == NULL) ? "{ null list }" : "{ empty list }", sizeof(retbuf[0])); |
| 290 | } |
| 291 | else if (head->p == head->n) { |
| 292 | (void)snprintf(retptr, sizeof(retbuf[0]), "{ %p * 1 }", head->p); |
| 293 | } |
| 294 | else { |
| 295 | const struct list *ptr; |
| 296 | size_t count = 0; |
| 297 | |
| 298 | for (ptr = head->n; ptr != head; ptr = ptr->n, count++); |
| 299 | |
| 300 | (void)snprintf(retptr, sizeof(retbuf[0]), "{ %p %p %zu }", head->p, head->n, count); |
| 301 | } |
| 302 | |
| 303 | return (retptr); |
| 304 | } |
| 305 | |
| 306 | #endif /* DEBUG_OT */ |
| 307 | |
| 308 | |
| 309 | /*** |
| 310 | * NAME |
| 311 | * flt_ot_chunk_add - |
| 312 | * |
| 313 | * ARGUMENTS |
| 314 | * chk - |
| 315 | * src - |
| 316 | * n - |
| 317 | * err - |
| 318 | * |
| 319 | * DESCRIPTION |
| 320 | * - |
| 321 | * |
| 322 | * RETURN VALUE |
| 323 | * - |
| 324 | */ |
| 325 | ssize_t flt_ot_chunk_add(struct buffer *chk, const void *src, size_t n, char **err) |
| 326 | { |
| 327 | FLT_OT_FUNC("%p, %p, %zu, %p:%p", chk, src, n, FLT_OT_DPTR_ARGS(err)); |
| 328 | |
| 329 | if ((chk == NULL) || (src == NULL)) |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 330 | FLT_OT_RETURN_EX(-1, ssize_t, "%ld"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 331 | |
| 332 | if (chk->area == NULL) |
| 333 | chunk_init(chk, FLT_OT_CALLOC(1, global.tune.bufsize), global.tune.bufsize); |
| 334 | |
| 335 | if (chk->area == NULL) { |
| 336 | FLT_OT_ERR("out of memory"); |
| 337 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 338 | FLT_OT_RETURN_EX(-1, ssize_t, "%ld"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 339 | } |
| 340 | else if (n > (chk->size - chk->data)) { |
| 341 | FLT_OT_ERR("chunk size too small"); |
| 342 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 343 | FLT_OT_RETURN_EX(-1, ssize_t, "%ld"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 344 | } |
| 345 | |
| 346 | (void)memcpy(chk->area + chk->data, src, n); |
| 347 | chk->data += n; |
| 348 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 349 | FLT_OT_RETURN_EX(chk->data, ssize_t, "%ld"); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 350 | } |
| 351 | |
| 352 | |
| 353 | /*** |
| 354 | * NAME |
| 355 | * flt_ot_args_count - |
| 356 | * |
| 357 | * ARGUMENTS |
| 358 | * args - |
| 359 | * |
| 360 | * DESCRIPTION |
| 361 | * - |
| 362 | * |
| 363 | * RETURN VALUE |
| 364 | * - |
| 365 | */ |
| 366 | int flt_ot_args_count(char **args) |
| 367 | { |
Miroslav Zagorac | 4b3eb0a | 2021-04-14 11:44:58 +0200 | [diff] [blame] | 368 | int i, retval = 0; |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 369 | |
Miroslav Zagorac | 4b3eb0a | 2021-04-14 11:44:58 +0200 | [diff] [blame] | 370 | if (args == NULL) |
| 371 | return retval; |
| 372 | |
| 373 | /* |
| 374 | * It is possible that some arguments within the configuration line |
| 375 | * are not specified; that is, they are set to a blank string. |
| 376 | * |
| 377 | * For example: |
| 378 | * keyword '' arg_2 |
| 379 | * |
| 380 | * In that case the content of the args field will be like this: |
| 381 | * args[0]: 'keyword' |
| 382 | * args[1]: NULL pointer |
| 383 | * args[2]: 'arg_2' |
| 384 | * args[3 .. MAX_LINE_ARGS): NULL pointers |
| 385 | * |
| 386 | * The total number of arguments is the index of the last argument |
| 387 | * (increased by 1) that is not a NULL pointer. |
| 388 | */ |
| 389 | for (i = 0; i < MAX_LINE_ARGS; i++) |
| 390 | if (FLT_OT_ARG_ISVALID(i)) |
| 391 | retval = i + 1; |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 392 | |
| 393 | return retval; |
| 394 | } |
| 395 | |
| 396 | |
| 397 | /*** |
| 398 | * NAME |
| 399 | * flt_ot_args_to_str - |
| 400 | * |
| 401 | * ARGUMENTS |
| 402 | * args - |
| 403 | * idx - |
| 404 | * str - |
| 405 | * |
| 406 | * DESCRIPTION |
| 407 | * - |
| 408 | * |
| 409 | * RETURN VALUE |
| 410 | * This function does not return a value. |
| 411 | */ |
| 412 | void flt_ot_args_to_str(char **args, int idx, char **str) |
| 413 | { |
Miroslav Zagorac | 4b3eb0a | 2021-04-14 11:44:58 +0200 | [diff] [blame] | 414 | int i, argc; |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 415 | |
| 416 | if ((args == NULL) || (*args == NULL)) |
| 417 | return; |
| 418 | |
Miroslav Zagorac | 4b3eb0a | 2021-04-14 11:44:58 +0200 | [diff] [blame] | 419 | argc = flt_ot_args_count(args); |
| 420 | |
| 421 | for (i = idx; i < argc; i++) |
| 422 | (void)memprintf(str, "%s%s%s", (*str == NULL) ? "" : *str, (i == idx) ? "" : " ", (args[i] == NULL) ? "" : args[i]); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 423 | } |
| 424 | |
| 425 | |
| 426 | /*** |
| 427 | * NAME |
| 428 | * flt_ot_strtod - |
| 429 | * |
| 430 | * ARGUMENTS |
| 431 | * nptr - |
| 432 | * limit_min - |
| 433 | * limit_max - |
| 434 | * err - |
| 435 | * |
| 436 | * DESCRIPTION |
| 437 | * - |
| 438 | * |
| 439 | * RETURN VALUE |
| 440 | * - |
| 441 | */ |
| 442 | double flt_ot_strtod(const char *nptr, double limit_min, double limit_max, char **err) |
| 443 | { |
| 444 | char *endptr = NULL; |
| 445 | double retval; |
| 446 | |
| 447 | errno = 0; |
| 448 | |
| 449 | retval = strtod(nptr, &endptr); |
| 450 | if ((errno != 0) || FLT_OT_STR_ISVALID(endptr)) |
| 451 | FLT_OT_ERR("'%s' : invalid value", nptr); |
| 452 | else if (!FLT_OT_IN_RANGE(retval, limit_min, limit_max)) |
| 453 | FLT_OT_ERR("'%s' : value out of range [%.2f, %.2f]", nptr, limit_min, limit_max); |
| 454 | |
| 455 | return retval; |
| 456 | } |
| 457 | |
| 458 | |
| 459 | /*** |
| 460 | * NAME |
| 461 | * flt_ot_strtoll - |
| 462 | * |
| 463 | * ARGUMENTS |
| 464 | * nptr - |
| 465 | * limit_min - |
| 466 | * limit_max - |
| 467 | * err - |
| 468 | * |
| 469 | * DESCRIPTION |
| 470 | * - |
| 471 | * |
| 472 | * RETURN VALUE |
| 473 | * - |
| 474 | */ |
| 475 | int64_t flt_ot_strtoll(const char *nptr, int64_t limit_min, int64_t limit_max, char **err) |
| 476 | { |
| 477 | char *endptr = NULL; |
| 478 | int64_t retval; |
| 479 | |
| 480 | errno = 0; |
| 481 | |
| 482 | retval = strtoll(nptr, &endptr, 0); |
| 483 | if ((errno != 0) || FLT_OT_STR_ISVALID(endptr)) |
| 484 | FLT_OT_ERR("'%s' : invalid value", nptr); |
| 485 | else if (!FLT_OT_IN_RANGE(retval, limit_min, limit_max)) |
| 486 | FLT_OT_ERR("'%s' : value out of range [%" PRId64 ", %" PRId64 "]", nptr, limit_min, limit_max); |
| 487 | |
| 488 | return retval; |
| 489 | } |
| 490 | |
| 491 | |
| 492 | /*** |
| 493 | * NAME |
| 494 | * flt_ot_sample_to_str - |
| 495 | * |
| 496 | * ARGUMENTS |
| 497 | * data - |
| 498 | * value - |
| 499 | * size - |
| 500 | * err - |
| 501 | * |
| 502 | * DESCRIPTION |
| 503 | * - |
| 504 | * |
| 505 | * RETURN VALUE |
| 506 | * - |
| 507 | */ |
| 508 | int flt_ot_sample_to_str(const struct sample_data *data, char *value, size_t size, char **err) |
| 509 | { |
| 510 | int retval = -1; |
| 511 | |
| 512 | FLT_OT_FUNC("%p, %p, %zu, %p:%p", data, value, size, FLT_OT_DPTR_ARGS(err)); |
| 513 | |
| 514 | if ((data == NULL) || (value == NULL) || (size == 0)) |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 515 | FLT_OT_RETURN_INT(retval); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 516 | |
| 517 | *value = '\0'; |
| 518 | |
| 519 | if (data->type == SMP_T_ANY) { |
| 520 | FLT_OT_ERR("invalid sample data type %d", data->type); |
| 521 | } |
| 522 | else if (data->type == SMP_T_BOOL) { |
| 523 | value[0] = data->u.sint ? '1' : '0'; |
| 524 | value[1] = '\0'; |
| 525 | |
| 526 | retval = 1; |
| 527 | } |
| 528 | else if (data->type == SMP_T_SINT) { |
| 529 | retval = snprintf(value, size, "%lld", data->u.sint); |
| 530 | } |
| 531 | else if (data->type == SMP_T_ADDR) { |
| 532 | /* This type is never used to qualify a sample. */ |
| 533 | } |
| 534 | else if (data->type == SMP_T_IPV4) { |
| 535 | if (INET_ADDRSTRLEN > size) |
| 536 | FLT_OT_ERR("sample data size too large"); |
| 537 | else if (inet_ntop(AF_INET, &(data->u.ipv4), value, INET_ADDRSTRLEN) == NULL) |
| 538 | FLT_OT_ERR("invalid IPv4 address"); |
| 539 | else |
| 540 | retval = strlen(value); |
| 541 | } |
| 542 | else if (data->type == SMP_T_IPV6) { |
| 543 | if (INET6_ADDRSTRLEN > size) |
| 544 | FLT_OT_ERR("sample data size too large"); |
| 545 | else if (inet_ntop(AF_INET6, &(data->u.ipv6), value, INET6_ADDRSTRLEN) == NULL) |
| 546 | FLT_OT_ERR("invalid IPv6 address"); |
| 547 | else |
| 548 | retval = strlen(value); |
| 549 | } |
| 550 | else if (data->type == SMP_T_STR) { |
| 551 | if (data->u.str.data >= size) { |
| 552 | FLT_OT_ERR("sample data size too large"); |
| 553 | } |
| 554 | else if (data->u.str.data > 0) { |
| 555 | retval = data->u.str.data; |
| 556 | |
| 557 | (void)strncat(value, data->u.str.area, retval); |
| 558 | } |
| 559 | else { |
| 560 | /* |
| 561 | * There is no content to add but we will still return |
| 562 | * the correct status. |
| 563 | */ |
| 564 | retval = 0; |
| 565 | } |
| 566 | } |
| 567 | else if (data->type == SMP_T_BIN) { |
| 568 | FLT_OT_ERR("invalid sample data type %d", data->type); |
| 569 | } |
| 570 | else if (data->type != SMP_T_METH) { |
| 571 | FLT_OT_ERR("invalid sample data type %d", data->type); |
| 572 | } |
| 573 | else if (data->u.meth.meth == HTTP_METH_OPTIONS) { |
| 574 | retval = FLT_OT_STR_SIZE(HTTP_METH_STR_OPTIONS); |
| 575 | |
| 576 | (void)memcpy(value, HTTP_METH_STR_OPTIONS, retval + 1); |
| 577 | } |
| 578 | else if (data->u.meth.meth == HTTP_METH_GET) { |
| 579 | retval = FLT_OT_STR_SIZE(HTTP_METH_STR_GET); |
| 580 | |
| 581 | (void)memcpy(value, HTTP_METH_STR_GET, retval + 1); |
| 582 | } |
| 583 | else if (data->u.meth.meth == HTTP_METH_HEAD) { |
| 584 | retval = FLT_OT_STR_SIZE(HTTP_METH_STR_HEAD); |
| 585 | |
| 586 | (void)memcpy(value, HTTP_METH_STR_HEAD, retval + 1); |
| 587 | } |
| 588 | else if (data->u.meth.meth == HTTP_METH_POST) { |
| 589 | retval = FLT_OT_STR_SIZE(HTTP_METH_STR_POST); |
| 590 | |
| 591 | (void)memcpy(value, HTTP_METH_STR_POST, retval + 1); |
| 592 | } |
| 593 | else if (data->u.meth.meth == HTTP_METH_PUT) { |
| 594 | retval = FLT_OT_STR_SIZE(HTTP_METH_STR_PUT); |
| 595 | |
| 596 | (void)memcpy(value, HTTP_METH_STR_PUT, retval + 1); |
| 597 | } |
| 598 | else if (data->u.meth.meth == HTTP_METH_DELETE) { |
| 599 | retval = FLT_OT_STR_SIZE(HTTP_METH_STR_DELETE); |
| 600 | |
| 601 | (void)memcpy(value, HTTP_METH_STR_DELETE, retval + 1); |
| 602 | } |
| 603 | else if (data->u.meth.meth == HTTP_METH_TRACE) { |
| 604 | retval = FLT_OT_STR_SIZE(HTTP_METH_STR_TRACE); |
| 605 | |
| 606 | (void)memcpy(value, HTTP_METH_STR_TRACE, retval + 1); |
| 607 | } |
| 608 | else if (data->u.meth.meth == HTTP_METH_CONNECT) { |
| 609 | retval = FLT_OT_STR_SIZE(HTTP_METH_STR_CONNECT); |
| 610 | |
| 611 | (void)memcpy(value, HTTP_METH_STR_CONNECT, retval + 1); |
| 612 | } |
| 613 | else if (data->u.meth.meth == HTTP_METH_OTHER) { |
| 614 | if (data->u.meth.str.data >= size) { |
| 615 | FLT_OT_ERR("sample data size too large"); |
| 616 | } else { |
| 617 | retval = data->u.meth.str.data; |
| 618 | |
| 619 | (void)strncat(value, data->u.meth.str.area, retval); |
| 620 | } |
| 621 | } |
| 622 | else { |
| 623 | FLT_OT_ERR("invalid HTTP method"); |
| 624 | } |
| 625 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 626 | FLT_OT_RETURN_INT(retval); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 627 | } |
| 628 | |
| 629 | |
| 630 | /*** |
| 631 | * NAME |
| 632 | * flt_ot_sample_to_value - |
| 633 | * |
| 634 | * ARGUMENTS |
| 635 | * key - |
| 636 | * data - |
| 637 | * value - |
| 638 | * err - |
| 639 | * |
| 640 | * DESCRIPTION |
| 641 | * - |
| 642 | * |
| 643 | * RETURN VALUE |
| 644 | * - |
| 645 | */ |
| 646 | int flt_ot_sample_to_value(const char *key, const struct sample_data *data, struct otc_value *value, char **err) |
| 647 | { |
| 648 | int retval = -1; |
| 649 | |
| 650 | FLT_OT_FUNC("\"%s\", %p, %p, %p:%p", key, data, value, FLT_OT_DPTR_ARGS(err)); |
| 651 | |
| 652 | if ((data == NULL) || (value == NULL)) |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 653 | FLT_OT_RETURN_INT(retval); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 654 | |
| 655 | if (data->type == SMP_T_BOOL) { |
| 656 | value->type = otc_value_bool; |
| 657 | value->value.bool_value = data->u.sint ? 1 : 0; |
| 658 | |
| 659 | retval = sizeof(value->value.bool_value); |
| 660 | } |
| 661 | else if (data->type == SMP_T_SINT) { |
| 662 | value->type = otc_value_int64; |
| 663 | value->value.int64_value = data->u.sint; |
| 664 | |
| 665 | retval = sizeof(value->value.int64_value); |
| 666 | } |
| 667 | else { |
| 668 | value->type = otc_value_string; |
| 669 | value->value.string_value = FLT_OT_MALLOC(global.tune.bufsize); |
| 670 | |
| 671 | if (value->value.string_value == NULL) |
| 672 | FLT_OT_ERR("out of memory"); |
| 673 | else |
| 674 | retval = flt_ot_sample_to_str(data, (char *)value->value.string_value, global.tune.bufsize, err); |
| 675 | } |
| 676 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 677 | FLT_OT_RETURN_INT(retval); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 678 | } |
| 679 | |
| 680 | |
| 681 | /*** |
| 682 | * NAME |
| 683 | * flt_ot_sample_add - |
| 684 | * |
| 685 | * ARGUMENTS |
| 686 | * s - |
| 687 | * dir - |
| 688 | * sample - |
| 689 | * data - |
| 690 | * type - |
| 691 | * err - |
| 692 | * |
| 693 | * DESCRIPTION |
| 694 | * - |
| 695 | * |
| 696 | * RETURN VALUE |
| 697 | * Returns a negative value if an error occurs, 0 if it needs to wait, |
| 698 | * any other value otherwise. |
| 699 | */ |
| 700 | int flt_ot_sample_add(struct stream *s, uint dir, struct flt_ot_conf_sample *sample, struct flt_ot_scope_data *data, int type, char **err) |
| 701 | { |
| 702 | const struct flt_ot_conf_sample_expr *expr; |
| 703 | struct sample smp; |
| 704 | struct otc_value value; |
| 705 | struct buffer buffer; |
| 706 | int idx = 0, rc, retval = FLT_OT_RET_OK; |
| 707 | |
| 708 | FLT_OT_FUNC("%p, %u, %p, %p, %d, %p:%p", s, dir, data, sample, type, FLT_OT_DPTR_ARGS(err)); |
| 709 | |
| 710 | FLT_OT_DBG_CONF_SAMPLE("sample ", sample); |
| 711 | |
| 712 | (void)memset(&buffer, 0, sizeof(buffer)); |
| 713 | |
| 714 | list_for_each_entry(expr, &(sample->exprs), list) { |
| 715 | FLT_OT_DBG_CONF_SAMPLE_EXPR("sample expression ", expr); |
| 716 | |
| 717 | (void)memset(&smp, 0, sizeof(smp)); |
| 718 | |
| 719 | /* |
| 720 | * If we have only one expression to process, then the data |
| 721 | * type that is the result of the expression is converted to |
| 722 | * an equivalent data type (if possible) that is written to |
| 723 | * the tracer. |
| 724 | * |
| 725 | * If conversion is not possible, or if we have multiple |
| 726 | * expressions to process, then the result is converted to |
| 727 | * a string and as such sent to the tracer. |
| 728 | */ |
| 729 | if (sample_process(s->be, s->sess, s, dir | SMP_OPT_FINAL, expr->expr, &smp) != NULL) { |
| 730 | FLT_OT_DBG(3, "data type %d: '%s'", smp.data.type, expr->value); |
| 731 | } else { |
| 732 | FLT_OT_DBG(2, "WARNING: failed to fetch '%s' value", expr->value); |
| 733 | |
| 734 | /* |
| 735 | * In case the fetch failed, we will set the result |
| 736 | * (sample) to an empty static string. |
| 737 | */ |
| 738 | (void)memset(&(smp.data), 0, sizeof(smp.data)); |
| 739 | smp.data.type = SMP_T_STR; |
| 740 | smp.data.u.str.area = ""; |
| 741 | } |
| 742 | |
| 743 | if ((sample->num_exprs == 1) && (type == FLT_OT_EVENT_SAMPLE_TAG)) { |
| 744 | if (flt_ot_sample_to_value(sample->key, &(smp.data), &value, err) == -1) |
| 745 | retval = FLT_OT_RET_ERROR; |
| 746 | } else { |
| 747 | if (buffer.area == NULL) { |
| 748 | chunk_init(&buffer, FLT_OT_CALLOC(1, global.tune.bufsize), global.tune.bufsize); |
| 749 | if (buffer.area == NULL) { |
| 750 | FLT_OT_ERR("out of memory"); |
| 751 | |
| 752 | retval = FLT_OT_RET_ERROR; |
| 753 | |
| 754 | break; |
| 755 | } |
| 756 | } |
| 757 | |
| 758 | rc = flt_ot_sample_to_str(&(smp.data), buffer.area + buffer.data, buffer.size - buffer.data, err); |
| 759 | if (rc == -1) { |
| 760 | retval = FLT_OT_RET_ERROR; |
| 761 | } else { |
| 762 | buffer.data += rc; |
| 763 | |
| 764 | if (sample->num_exprs == ++idx) { |
| 765 | value.type = otc_value_string; |
| 766 | value.value.string_value = buffer.area; |
| 767 | } |
| 768 | } |
| 769 | } |
| 770 | } |
| 771 | |
| 772 | if (retval == FLT_OT_RET_ERROR) { |
| 773 | /* Do nothing. */ |
| 774 | } |
| 775 | else if (type == FLT_OT_EVENT_SAMPLE_TAG) { |
| 776 | struct otc_tag *tag = data->tags + data->num_tags++; |
| 777 | |
| 778 | tag->key = sample->key; |
| 779 | (void)memcpy(&(tag->value), &value, sizeof(tag->value)); |
| 780 | } |
| 781 | else if (type == FLT_OT_EVENT_SAMPLE_LOG) { |
| 782 | struct otc_log_field *log_field = data->log_fields + data->num_log_fields++; |
| 783 | |
| 784 | log_field->key = sample->key; |
| 785 | (void)memcpy(&(log_field->value), &value, sizeof(log_field->value)); |
| 786 | } |
| 787 | else { |
| 788 | if (data->baggage == NULL) |
| 789 | data->baggage = otc_text_map_new(NULL, FLT_OT_MAXBAGGAGES); |
| 790 | |
| 791 | if (data->baggage == NULL) { |
| 792 | FLT_OT_ERR("out of memory"); |
| 793 | |
| 794 | retval = FLT_OT_RET_ERROR; |
| 795 | } |
| 796 | else if (otc_text_map_add(data->baggage, sample->key, 0, value.value.string_value, 0, 0) == -1) { |
| 797 | FLT_OT_ERR("out of memory"); |
| 798 | |
| 799 | retval = FLT_OT_RET_ERROR; |
| 800 | } |
| 801 | else |
| 802 | FLT_OT_DBG(3, "baggage[%zu]: '%s' -> '%s'", data->baggage->count - 1, data->baggage->key[data->baggage->count - 1], data->baggage->value[data->baggage->count - 1]); |
| 803 | } |
| 804 | |
Miroslav Zagorac | 5b5b062 | 2022-03-04 09:56:00 +0100 | [diff] [blame] | 805 | FLT_OT_RETURN_INT(retval); |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 806 | } |
| 807 | |
| 808 | /* |
| 809 | * Local variables: |
| 810 | * c-indent-level: 8 |
| 811 | * c-basic-offset: 8 |
| 812 | * End: |
| 813 | * |
| 814 | * vi: noexpandtab shiftwidth=8 tabstop=8 |
| 815 | */ |