lttng add-trigger: remove support for conditions other than event-rule-matches
[lttng-tools.git] / src / bin / lttng / commands / add_trigger.c
1 /*
2 * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #include <ctype.h>
9 #include <stdio.h>
10
11 #include "../command.h"
12 #include "../loglevel.h"
13 #include "../uprobe.h"
14
15 #include "common/argpar/argpar.h"
16 #include "common/dynamic-array.h"
17 #include "common/string-utils/string-utils.h"
18 #include "common/utils.h"
19 /* For lttng_event_rule_type_str(). */
20 #include <lttng/event-rule/event-rule-internal.h>
21 #include <lttng/lttng.h>
22 #include "common/filter/filter-ast.h"
23 #include "common/filter/filter-ir.h"
24 #include "common/dynamic-array.h"
25
26 #if (LTTNG_SYMBOL_NAME_LEN == 256)
27 #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
28 #endif
29
30 #ifdef LTTNG_EMBED_HELP
31 static const char help_msg[] =
32 #include <lttng-add-trigger.1.h>
33 ;
34 #endif
35
36 enum {
37 OPT_HELP,
38 OPT_LIST_OPTIONS,
39
40 OPT_CONDITION,
41 OPT_ACTION,
42 OPT_ID,
43 OPT_OWNER_UID,
44 OPT_RATE_POLICY,
45
46 OPT_NAME,
47 OPT_FILTER,
48 OPT_EXCLUDE_NAMES,
49 OPT_EVENT_NAME,
50 OPT_LOG_LEVEL,
51
52 OPT_DOMAIN,
53 OPT_TYPE,
54 OPT_LOCATION,
55
56 OPT_MAX_SIZE,
57 OPT_DATA_URL,
58 OPT_CTRL_URL,
59 OPT_URL,
60 OPT_PATH,
61
62 OPT_CAPTURE,
63 };
64
65 static const struct argpar_opt_descr event_rule_opt_descrs[] = {
66 { OPT_FILTER, 'f', "filter", true },
67 { OPT_NAME, 'n', "name", true },
68 { OPT_EXCLUDE_NAMES, 'x', "exclude-names", true },
69 { OPT_LOG_LEVEL, 'l', "log-level", true },
70 { OPT_EVENT_NAME, 'E', "event-name", true },
71
72 { OPT_DOMAIN, 'd', "domain", true },
73 { OPT_TYPE, 't', "type", true },
74 { OPT_LOCATION, 'L', "location", true },
75
76 /* Capture descriptor */
77 { OPT_CAPTURE, '\0', "capture", true },
78
79 ARGPAR_OPT_DESCR_SENTINEL
80 };
81
82 static
83 bool assign_domain_type(enum lttng_domain_type *dest, const char *arg)
84 {
85 bool ret;
86
87 if (*dest != LTTNG_DOMAIN_NONE) {
88 ERR("More than one `--domain` was specified.");
89 goto error;
90 }
91
92 if (strcmp(arg, "kernel") == 0) {
93 *dest = LTTNG_DOMAIN_KERNEL;
94 } else if (strcmp(arg, "user") == 0 || strcmp(arg, "userspace") == 0) {
95 *dest = LTTNG_DOMAIN_UST;
96 } else if (strcmp(arg, "jul") == 0) {
97 *dest = LTTNG_DOMAIN_JUL;
98 } else if (strcmp(arg, "log4j") == 0) {
99 *dest = LTTNG_DOMAIN_LOG4J;
100 } else if (strcmp(arg, "python") == 0) {
101 *dest = LTTNG_DOMAIN_PYTHON;
102 } else {
103 ERR("Invalid `--domain` value: %s", arg);
104 goto error;
105 }
106
107 ret = true;
108 goto end;
109
110 error:
111 ret = false;
112
113 end:
114 return ret;
115 }
116
117 static
118 bool assign_event_rule_type(enum lttng_event_rule_type *dest, const char *arg)
119 {
120 bool ret;
121
122 if (*dest != LTTNG_EVENT_RULE_TYPE_UNKNOWN) {
123 ERR("More than one `--type` was specified.");
124 goto error;
125 }
126
127 if (strcmp(arg, "tracepoint") == 0 || strcmp(arg, "logging") == 0) {
128 *dest = LTTNG_EVENT_RULE_TYPE_TRACEPOINT;
129 } else if (strcmp (arg, "kprobe") == 0 || strcmp(arg, "kernel-probe") == 0) {
130 *dest = LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE;
131 } else if (strcmp (arg, "uprobe") == 0 || strcmp(arg, "userspace-probe") == 0) {
132 *dest = LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE;
133 } else if (strcmp (arg, "function") == 0) {
134 *dest = LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION;
135 } else if (strcmp (arg, "syscall") == 0) {
136 *dest = LTTNG_EVENT_RULE_TYPE_SYSCALL;
137 } else {
138 ERR("Invalid `--type` value: %s", arg);
139 goto error;
140 }
141
142 ret = true;
143 goto end;
144
145 error:
146 ret = false;
147
148 end:
149 return ret;
150 }
151
152 static
153 bool assign_string(char **dest, const char *src, const char *opt_name)
154 {
155 bool ret;
156
157 if (*dest) {
158 ERR("Duplicate '%s' given.", opt_name);
159 goto error;
160 }
161
162 *dest = strdup(src);
163 if (!*dest) {
164 PERROR("Failed to allocate string '%s'.", opt_name);
165 goto error;
166 }
167
168 ret = true;
169 goto end;
170
171 error:
172 ret = false;
173
174 end:
175 return ret;
176 }
177
178 /* This is defined in enable_events.c. */
179 LTTNG_HIDDEN
180 int create_exclusion_list_and_validate(const char *event_name,
181 const char *exclusions_arg,
182 char ***exclusion_list);
183
184 /*
185 * Parse `str` as a log level in domain `domain_type`.
186 *
187 * Return the log level in `*log_level`. Return true in `*log_level_only` if
188 * the string specifies exactly this log level, false if it specifies at least
189 * this log level.
190 *
191 * Return true if the string was successfully parsed as a log level string.
192 */
193 static bool parse_log_level_string(const char *str,
194 enum lttng_domain_type domain_type,
195 int *log_level,
196 bool *log_level_only)
197 {
198 bool ret;
199
200 switch (domain_type) {
201 case LTTNG_DOMAIN_UST:
202 {
203 enum lttng_loglevel log_level_min, log_level_max;
204 if (!loglevel_parse_range_string(
205 str, &log_level_min, &log_level_max)) {
206 goto error;
207 }
208
209 /* Only support VAL and VAL.. for now. */
210 if (log_level_min != log_level_max &&
211 log_level_max != LTTNG_LOGLEVEL_EMERG) {
212 goto error;
213 }
214
215 *log_level = (int) log_level_min;
216 *log_level_only = log_level_min == log_level_max;
217 break;
218 }
219 case LTTNG_DOMAIN_LOG4J:
220 {
221 enum lttng_loglevel_log4j log_level_min, log_level_max;
222 if (!loglevel_log4j_parse_range_string(
223 str, &log_level_min, &log_level_max)) {
224 goto error;
225 }
226
227 /* Only support VAL and VAL.. for now. */
228 if (log_level_min != log_level_max &&
229 log_level_max != LTTNG_LOGLEVEL_LOG4J_FATAL) {
230 goto error;
231 }
232
233 *log_level = (int) log_level_min;
234 *log_level_only = log_level_min == log_level_max;
235 break;
236 }
237 case LTTNG_DOMAIN_JUL:
238 {
239 enum lttng_loglevel_jul log_level_min, log_level_max;
240 if (!loglevel_jul_parse_range_string(
241 str, &log_level_min, &log_level_max)) {
242 goto error;
243 }
244
245 /* Only support VAL and VAL.. for now. */
246 if (log_level_min != log_level_max &&
247 log_level_max != LTTNG_LOGLEVEL_JUL_SEVERE) {
248 goto error;
249 }
250
251 *log_level = (int) log_level_min;
252 *log_level_only = log_level_min == log_level_max;
253 break;
254 }
255 case LTTNG_DOMAIN_PYTHON:
256 {
257 enum lttng_loglevel_python log_level_min, log_level_max;
258 if (!loglevel_python_parse_range_string(
259 str, &log_level_min, &log_level_max)) {
260 goto error;
261 }
262
263 /* Only support VAL and VAL.. for now. */
264 if (log_level_min != log_level_max &&
265 log_level_max !=
266 LTTNG_LOGLEVEL_PYTHON_CRITICAL) {
267 goto error;
268 }
269
270 *log_level = (int) log_level_min;
271 *log_level_only = log_level_min == log_level_max;
272 break;
273 }
274 default:
275 /* Invalid domain type. */
276 abort();
277 }
278
279 ret = true;
280 goto end;
281
282 error:
283 ret = false;
284
285 end:
286 return ret;
287 }
288
289 static int parse_kernel_probe_opts(const char *source,
290 struct lttng_kernel_probe_location **location)
291 {
292 int ret = 0;
293 int match;
294 char s_hex[19];
295 char name[LTTNG_SYMBOL_NAME_LEN];
296 char *symbol_name = NULL;
297 uint64_t offset;
298
299 /* Check for symbol+offset. */
300 match = sscanf(source,
301 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
302 "[^'+']+%18s",
303 name, s_hex);
304 if (match == 2) {
305 if (*s_hex == '\0') {
306 ERR("Kernel probe symbol offset is missing.");
307 goto error;
308 }
309
310 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
311 if (!symbol_name) {
312 PERROR("Failed to copy kernel probe location symbol name.");
313 goto error;
314 }
315 offset = strtoul(s_hex, NULL, 0);
316
317 *location = lttng_kernel_probe_location_symbol_create(
318 symbol_name, offset);
319 if (!*location) {
320 ERR("Failed to create symbol kernel probe location.");
321 goto error;
322 }
323
324 goto end;
325 }
326
327 /* Check for symbol. */
328 if (isalpha(name[0]) || name[0] == '_') {
329 match = sscanf(source,
330 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
331 "s",
332 name);
333 if (match == 1) {
334 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
335 if (!symbol_name) {
336 ERR("Failed to copy kernel probe location symbol name.");
337 goto error;
338 }
339
340 *location = lttng_kernel_probe_location_symbol_create(
341 symbol_name, 0);
342 if (!*location) {
343 ERR("Failed to create symbol kernel probe location.");
344 goto error;
345 }
346
347 goto end;
348 }
349 }
350
351 /* Check for address. */
352 match = sscanf(source, "%18s", s_hex);
353 if (match > 0) {
354 uint64_t address;
355
356 if (*s_hex == '\0') {
357 ERR("Invalid kernel probe location address.");
358 goto error;
359 }
360
361 address = strtoul(s_hex, NULL, 0);
362 *location = lttng_kernel_probe_location_address_create(address);
363 if (!*location) {
364 ERR("Failed to create symbol kernel probe location.");
365 goto error;
366 }
367
368 goto end;
369 }
370
371 error:
372 /* No match */
373 ret = -1;
374 *location = NULL;
375
376 end:
377 free(symbol_name);
378 return ret;
379 }
380
381 static
382 struct lttng_event_expr *ir_op_load_expr_to_event_expr(
383 const struct ir_load_expression *load_expr,
384 const char *capture_str)
385 {
386 char *provider_name = NULL;
387 struct lttng_event_expr *event_expr = NULL;
388 const struct ir_load_expression_op *load_expr_op = load_expr->child;
389 const enum ir_load_expression_type load_expr_child_type =
390 load_expr_op->type;
391
392 switch (load_expr_child_type) {
393 case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT:
394 case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT:
395 {
396 const char *field_name;
397
398 load_expr_op = load_expr_op->next;
399 assert(load_expr_op);
400 assert(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
401 field_name = load_expr_op->u.symbol;
402 assert(field_name);
403
404 event_expr = load_expr_child_type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
405 lttng_event_expr_event_payload_field_create(field_name) :
406 lttng_event_expr_channel_context_field_create(field_name);
407 if (!event_expr) {
408 ERR("Failed to create %s event expression: field name = `%s`.",
409 load_expr_child_type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
410 "payload field" : "channel context",
411 field_name);
412 goto error;
413 }
414
415 break;
416 }
417 case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT:
418 {
419 const char *colon;
420 const char *type_name;
421 const char *field_name;
422
423 load_expr_op = load_expr_op->next;
424 assert(load_expr_op);
425 assert(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
426 field_name = load_expr_op->u.symbol;
427 assert(field_name);
428
429 /*
430 * The field name needs to be of the form PROVIDER:TYPE. We
431 * split it here.
432 */
433 colon = strchr(field_name, ':');
434 if (!colon) {
435 ERR("Invalid app-specific context field name: missing colon in `%s`.",
436 field_name);
437 goto error;
438 }
439
440 type_name = colon + 1;
441 if (*type_name == '\0') {
442 ERR("Invalid app-specific context field name: missing type name after colon in `%s`.",
443 field_name);
444 goto error;
445 }
446
447 provider_name = strndup(field_name, colon - field_name);
448 if (!provider_name) {
449 PERROR("Failed to allocate field name string");
450 goto error;
451 }
452
453 event_expr = lttng_event_expr_app_specific_context_field_create(
454 provider_name, type_name);
455 if (!event_expr) {
456 ERR("Failed to create app-specific context field event expression: provider name = `%s`, type name = `%s`",
457 provider_name, type_name);
458 goto error;
459 }
460
461 break;
462 }
463 default:
464 ERR("%s: unexpected load expr type %d.", __func__,
465 load_expr_op->type);
466 abort();
467 }
468
469 load_expr_op = load_expr_op->next;
470
471 /* There may be a single array index after that. */
472 if (load_expr_op->type == IR_LOAD_EXPRESSION_GET_INDEX) {
473 struct lttng_event_expr *index_event_expr;
474 const uint64_t index = load_expr_op->u.index;
475
476 index_event_expr = lttng_event_expr_array_field_element_create(event_expr, index);
477 if (!index_event_expr) {
478 ERR("Failed to create array field element event expression.");
479 goto error;
480 }
481
482 event_expr = index_event_expr;
483 load_expr_op = load_expr_op->next;
484 }
485
486 switch (load_expr_op->type) {
487 case IR_LOAD_EXPRESSION_LOAD_FIELD:
488 /*
489 * This is what we expect, IR_LOAD_EXPRESSION_LOAD_FIELD is
490 * always found at the end of the chain.
491 */
492 break;
493 case IR_LOAD_EXPRESSION_GET_SYMBOL:
494 ERR("While parsing expression `%s`: Capturing subfields is not supported.",
495 capture_str);
496 goto error;
497
498 default:
499 ERR("%s: unexpected load expression operator %s.", __func__,
500 ir_load_expression_type_str(load_expr_op->type));
501 abort();
502 }
503
504 goto end;
505
506 error:
507 lttng_event_expr_destroy(event_expr);
508 event_expr = NULL;
509
510 end:
511 free(provider_name);
512
513 return event_expr;
514 }
515
516 static
517 struct lttng_event_expr *ir_op_load_to_event_expr(
518 const struct ir_op *ir, const char *capture_str)
519 {
520 struct lttng_event_expr *event_expr = NULL;
521
522 assert(ir->op == IR_OP_LOAD);
523
524 switch (ir->data_type) {
525 case IR_DATA_EXPRESSION:
526 {
527 const struct ir_load_expression *ir_load_expr =
528 ir->u.load.u.expression;
529
530 event_expr = ir_op_load_expr_to_event_expr(
531 ir_load_expr, capture_str);
532 break;
533 }
534 default:
535 ERR("%s: unexpected data type: %s.", __func__,
536 ir_data_type_str(ir->data_type));
537 abort();
538 }
539
540 return event_expr;
541 }
542
543 static
544 const char *ir_operator_type_human_str(enum ir_op_type op)
545 {
546 const char *name;
547
548 switch (op) {
549 case IR_OP_BINARY:
550 name = "Binary";
551 break;
552 case IR_OP_UNARY:
553 name = "Unary";
554 break;
555 case IR_OP_LOGICAL:
556 name = "Logical";
557 break;
558 default:
559 abort();
560 }
561
562 return name;
563 }
564
565 static
566 struct lttng_event_expr *ir_op_root_to_event_expr(const struct ir_op *ir,
567 const char *capture_str)
568 {
569 struct lttng_event_expr *event_expr = NULL;
570
571 assert(ir->op == IR_OP_ROOT);
572 ir = ir->u.root.child;
573
574 switch (ir->op) {
575 case IR_OP_LOAD:
576 event_expr = ir_op_load_to_event_expr(ir, capture_str);
577 break;
578 case IR_OP_BINARY:
579 case IR_OP_UNARY:
580 case IR_OP_LOGICAL:
581 ERR("While parsing expression `%s`: %s operators are not allowed in capture expressions.",
582 capture_str,
583 ir_operator_type_human_str(ir->op));
584 break;
585 default:
586 ERR("%s: unexpected IR op type: %s.", __func__,
587 ir_op_type_str(ir->op));
588 abort();
589 }
590
591 return event_expr;
592 }
593
594 static
595 void destroy_event_expr(void *ptr)
596 {
597 lttng_event_expr_destroy(ptr);
598 }
599
600 struct parse_event_rule_res {
601 /* Owned by this. */
602 struct lttng_event_rule *er;
603
604 /* Array of `struct lttng_event_expr *` */
605 struct lttng_dynamic_pointer_array capture_descriptors;
606 };
607
608 static
609 struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv)
610 {
611 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
612 enum lttng_event_rule_type event_rule_type =
613 LTTNG_EVENT_RULE_TYPE_UNKNOWN;
614 struct argpar_state *state;
615 struct argpar_item *item = NULL;
616 char *error = NULL;
617 int consumed_args = -1;
618 struct lttng_kernel_probe_location *kernel_probe_location = NULL;
619 struct lttng_userspace_probe_location *userspace_probe_location = NULL;
620 struct parse_event_rule_res res = { 0 };
621 struct lttng_event_expr *event_expr = NULL;
622 struct filter_parser_ctx *parser_ctx = NULL;
623 struct lttng_log_level_rule *log_level_rule = NULL;
624
625 /* Tracepoint and syscall options. */
626 char *name = NULL;
627 char *exclude_names = NULL;
628 char **exclusion_list = NULL;
629
630 /* For userspace / kernel probe and function. */
631 char *location = NULL;
632 char *event_name = NULL;
633
634 /* Filter. */
635 char *filter = NULL;
636
637 /* Log level. */
638 char *log_level_str = NULL;
639
640 lttng_dynamic_pointer_array_init(&res.capture_descriptors,
641 destroy_event_expr);
642 state = argpar_state_create(*argc, *argv, event_rule_opt_descrs);
643 if (!state) {
644 ERR("Failed to allocate an argpar state.");
645 goto error;
646 }
647
648 while (true) {
649 enum argpar_state_parse_next_status status;
650
651 ARGPAR_ITEM_DESTROY_AND_RESET(item);
652 status = argpar_state_parse_next(state, &item, &error);
653 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
654 ERR("%s", error);
655 goto error;
656 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
657 /* Just stop parsing here. */
658 break;
659 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
660 break;
661 }
662
663 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
664
665 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
666 const struct argpar_item_opt *item_opt =
667 (const struct argpar_item_opt *) item;
668
669 switch (item_opt->descr->id) {
670 /* Domains. */
671 case OPT_DOMAIN:
672 if (!assign_domain_type(&domain_type,
673 item_opt->arg)) {
674 goto error;
675 }
676
677 break;
678 case OPT_TYPE:
679 if (!assign_event_rule_type(&event_rule_type,
680 item_opt->arg)) {
681 goto error;
682 }
683
684 break;
685 case OPT_LOCATION:
686 if (!assign_string(&location,
687 item_opt->arg,
688 "--location/-L")) {
689 goto error;
690 }
691
692 break;
693 case OPT_EVENT_NAME:
694 if (!assign_string(&event_name,
695 item_opt->arg,
696 "--event-name/-E")) {
697 goto error;
698 }
699
700 break;
701 case OPT_FILTER:
702 if (!assign_string(&filter, item_opt->arg,
703 "--filter/-f")) {
704 goto error;
705 }
706
707 break;
708 case OPT_NAME:
709 if (!assign_string(&name, item_opt->arg,
710 "--name/-n")) {
711 goto error;
712 }
713
714 break;
715 case OPT_EXCLUDE_NAMES:
716 if (!assign_string(&exclude_names,
717 item_opt->arg,
718 "--exclude-names/-x")) {
719 goto error;
720 }
721
722 break;
723 case OPT_LOG_LEVEL:
724 if (!assign_string(&log_level_str,
725 item_opt->arg, "--log-level/-l")) {
726 goto error;
727 }
728
729 break;
730 case OPT_CAPTURE:
731 {
732 int ret;
733 const char *capture_str = item_opt->arg;
734
735 ret = filter_parser_ctx_create_from_filter_expression(
736 capture_str, &parser_ctx);
737 if (ret) {
738 ERR("Failed to parse capture expression `%s`.",
739 capture_str);
740 goto error;
741 }
742
743 event_expr = ir_op_root_to_event_expr(
744 parser_ctx->ir_root,
745 capture_str);
746 if (!event_expr) {
747 /*
748 * ir_op_root_to_event_expr has printed
749 * an error message.
750 */
751 goto error;
752 }
753
754 ret = lttng_dynamic_pointer_array_add_pointer(
755 &res.capture_descriptors,
756 event_expr);
757 if (ret) {
758 goto error;
759 }
760
761 /*
762 * The ownership of event expression was
763 * transferred to the dynamic array.
764 */
765 event_expr = NULL;
766
767 break;
768 }
769 default:
770 abort();
771 }
772 } else {
773 const struct argpar_item_non_opt *item_non_opt =
774 (const struct argpar_item_non_opt *)
775 item;
776
777 /* Don't accept non-option arguments. */
778 ERR("Unexpected argument '%s'", item_non_opt->arg);
779 goto error;
780 }
781 }
782
783 if (event_rule_type == LTTNG_EVENT_RULE_TYPE_UNKNOWN) {
784 event_rule_type = LTTNG_EVENT_RULE_TYPE_TRACEPOINT;
785 }
786
787 /*
788 * Option --name is applicable to event rules of type tracepoint
789 * and syscall. For tracepoint and syscall rules, if --name is
790 * omitted, it is implicitly "*".
791 */
792 switch (event_rule_type) {
793 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
794 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
795 if (!name) {
796 name = strdup("*");
797 }
798 break;
799
800 default:
801 if (name) {
802 ERR("Can't use --name with %s event rules.",
803 lttng_event_rule_type_str(
804 event_rule_type));
805 goto error;
806 }
807
808 if (exclude_names) {
809 ERR("Can't use --exclude-names/-x with %s event rules.",
810 lttng_event_rule_type_str(
811 event_rule_type));
812 goto error;
813 }
814 }
815
816 /*
817 * Option --location is only applicable to (and mandatory for) event
818 * rules of type {k,u}probe and function.
819 *
820 * Option --event-name is only applicable to event rules of type probe.
821 * If omitted, it defaults to the location.
822 */
823 switch (event_rule_type) {
824 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE:
825 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE:
826 case LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION:
827 if (!location) {
828 ERR("Event rule of type %s requires a --location.",
829 lttng_event_rule_type_str(event_rule_type));
830 goto error;
831 }
832
833 if (!event_name) {
834 event_name = strdup(location);
835 }
836
837 break;
838
839 default:
840 if (location) {
841 ERR("Can't use --location with %s event rules.",
842 lttng_event_rule_type_str(event_rule_type));
843 goto error;
844 }
845
846 if (event_name) {
847 ERR("Can't use --event-name with %s event rules.",
848 lttng_event_rule_type_str(
849 event_rule_type));
850 goto error;
851 }
852 }
853
854 /*
855 * Update *argc and *argv so our caller can keep parsing what follows.
856 */
857 consumed_args = argpar_state_get_ingested_orig_args(state);
858 assert(consumed_args >= 0);
859 *argc -= consumed_args;
860 *argv += consumed_args;
861
862 /* Need to specify a domain. */
863 if (domain_type == LTTNG_DOMAIN_NONE) {
864 ERR("Please specify a domain (--domain=(kernel,user,jul,log4j,python)).");
865 goto error;
866 }
867
868 /* Validate event rule type against domain. */
869 switch (event_rule_type) {
870 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE:
871 case LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION:
872 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE:
873 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
874 if (domain_type != LTTNG_DOMAIN_KERNEL) {
875 ERR("Event type not available for user-space tracing.");
876 goto error;
877 }
878 break;
879
880 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
881 break;
882
883 default:
884 abort();
885 }
886
887 /*
888 * Adding a filter to a probe, function or userspace-probe would be
889 * denied by the kernel tracer as it's not supported at the moment. We
890 * do an early check here to warn the user.
891 */
892 if (filter && domain_type == LTTNG_DOMAIN_KERNEL) {
893 switch (event_rule_type) {
894 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
895 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
896 break;
897 default:
898 ERR("Filter expressions are not supported for %s event rules.",
899 lttng_event_rule_type_str(event_rule_type));
900 goto error;
901 }
902 }
903
904 /* If --exclude/-x was passed, split it into an exclusion list. */
905 if (exclude_names) {
906 if (domain_type != LTTNG_DOMAIN_UST) {
907 ERR("Event name exclusions are not yet implemented for %s event rules.",
908 get_domain_str(domain_type));
909 goto error;
910 }
911
912 if (create_exclusion_list_and_validate(name,
913 exclude_names, &exclusion_list) != 0) {
914 ERR("Failed to create exclusion list.");
915 goto error;
916 }
917 }
918
919 if (log_level_str) {
920 if (event_rule_type != LTTNG_EVENT_RULE_TYPE_TRACEPOINT) {
921 ERR("Log levels are only applicable to tracepoint event rules.");
922 goto error;
923 }
924
925 if (domain_type == LTTNG_DOMAIN_KERNEL) {
926 ERR("Log levels are not supported by the kernel tracer.");
927 goto error;
928 }
929 }
930
931 /* Finally, create the event rule object. */
932 switch (event_rule_type) {
933 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
934 {
935 enum lttng_event_rule_status event_rule_status;
936
937 res.er = lttng_event_rule_tracepoint_create(domain_type);
938 if (!res.er) {
939 ERR("Failed to create tracepoint event rule.");
940 goto error;
941 }
942
943 /* Set pattern. */
944 event_rule_status = lttng_event_rule_tracepoint_set_pattern(
945 res.er, name);
946 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
947 ERR("Failed to set tracepoint event rule's pattern to '%s'.",
948 name);
949 goto error;
950 }
951
952 /* Set filter. */
953 if (filter) {
954 event_rule_status = lttng_event_rule_tracepoint_set_filter(
955 res.er, filter);
956 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
957 ERR("Failed to set tracepoint event rule's filter to '%s'.",
958 filter);
959 goto error;
960 }
961 }
962
963 /* Set exclusion list. */
964 if (exclusion_list) {
965 int n;
966
967 for (n = 0; exclusion_list[n]; n++) {
968 event_rule_status = lttng_event_rule_tracepoint_add_exclusion(
969 res.er,
970 exclusion_list[n]);
971 if (event_rule_status !=
972 LTTNG_EVENT_RULE_STATUS_OK) {
973 ERR("Failed to set tracepoint exclusion list element '%s'",
974 exclusion_list[n]);
975 goto error;
976 }
977 }
978 }
979
980 /*
981 * ".." is the same as passing no log level option and
982 * correspond the the "ANY" case.
983 */
984 if (log_level_str && strcmp(log_level_str, "..") != 0) {
985 int log_level;
986 bool log_level_only;
987
988 if (!parse_log_level_string(log_level_str, domain_type,
989 &log_level, &log_level_only)) {
990 ERR("Failed to parse log level string `%s`.",
991 log_level_str);
992 goto error;
993 }
994
995 if (log_level_only) {
996 log_level_rule = lttng_log_level_rule_exactly_create(log_level);
997 } else {
998 log_level_rule = lttng_log_level_rule_at_least_as_severe_as_create(log_level);
999 }
1000
1001 if (log_level_rule == NULL) {
1002 ERR("Failed to create log level rule object.");
1003 goto error;
1004 }
1005
1006 event_rule_status =
1007 lttng_event_rule_tracepoint_set_log_level_rule(
1008 res.er, log_level_rule);
1009
1010 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1011 ERR("Failed to set log level on event fule.");
1012 goto error;
1013 }
1014 }
1015
1016 break;
1017 }
1018 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE:
1019 {
1020 int ret;
1021 enum lttng_event_rule_status event_rule_status;
1022
1023 ret = parse_kernel_probe_opts(
1024 location, &kernel_probe_location);
1025 if (ret) {
1026 ERR("Failed to parse kernel probe location.");
1027 goto error;
1028 }
1029
1030 assert(kernel_probe_location);
1031 res.er = lttng_event_rule_kernel_probe_create(kernel_probe_location);
1032 if (!res.er) {
1033 ERR("Failed to create kprobe event rule.");
1034 goto error;
1035 }
1036
1037 event_rule_status =
1038 lttng_event_rule_kernel_probe_set_event_name(
1039 res.er, event_name);
1040 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1041 ERR("Failed to set kprobe event rule's name to '%s'.",
1042 event_name);
1043 goto error;
1044 }
1045
1046 break;
1047 }
1048 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE:
1049 {
1050 int ret;
1051 enum lttng_event_rule_status event_rule_status;
1052
1053 ret = parse_userspace_probe_opts(
1054 location, &userspace_probe_location);
1055 if (ret) {
1056 ERR("Failed to parse user space probe location.");
1057 goto error;
1058 }
1059
1060 res.er = lttng_event_rule_userspace_probe_create(userspace_probe_location);
1061 if (!res.er) {
1062 ERR("Failed to create userspace probe event rule.");
1063 goto error;
1064 }
1065
1066 event_rule_status =
1067 lttng_event_rule_userspace_probe_set_event_name(
1068 res.er, event_name);
1069 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1070 ERR("Failed to set user space probe event rule's name to '%s'.",
1071 event_name);
1072 goto error;
1073 }
1074
1075 break;
1076 }
1077 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
1078 {
1079 enum lttng_event_rule_status event_rule_status;
1080
1081 res.er = lttng_event_rule_syscall_create();
1082 if (!res.er) {
1083 ERR("Failed to create syscall event rule.");
1084 goto error;
1085 }
1086
1087 event_rule_status = lttng_event_rule_syscall_set_pattern(
1088 res.er, name);
1089 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1090 ERR("Failed to set syscall event rule's pattern to '%s'.",
1091 name);
1092 goto error;
1093 }
1094
1095 if (filter) {
1096 event_rule_status = lttng_event_rule_syscall_set_filter(
1097 res.er, filter);
1098 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1099 ERR("Failed to set syscall event rule's filter to '%s'.",
1100 filter);
1101 goto error;
1102 }
1103 }
1104
1105 break;
1106 }
1107 default:
1108 abort();
1109 goto error;
1110 }
1111
1112 goto end;
1113
1114 error:
1115 lttng_event_rule_destroy(res.er);
1116 res.er = NULL;
1117 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
1118
1119 end:
1120 if (parser_ctx) {
1121 filter_parser_ctx_free(parser_ctx);
1122 }
1123
1124 lttng_event_expr_destroy(event_expr);
1125 argpar_item_destroy(item);
1126 free(error);
1127 argpar_state_destroy(state);
1128 free(filter);
1129 free(name);
1130 free(exclude_names);
1131 free(log_level_str);
1132 free(location);
1133 free(event_name);
1134
1135 strutils_free_null_terminated_array_of_strings(exclusion_list);
1136 lttng_kernel_probe_location_destroy(kernel_probe_location);
1137 lttng_userspace_probe_location_destroy(userspace_probe_location);
1138 lttng_log_level_rule_destroy(log_level_rule);
1139 return res;
1140 }
1141
1142 static
1143 struct lttng_condition *handle_condition_event(int *argc, const char ***argv)
1144 {
1145 struct parse_event_rule_res res;
1146 struct lttng_condition *c;
1147 size_t i;
1148
1149 res = parse_event_rule(argc, argv);
1150 if (!res.er) {
1151 c = NULL;
1152 goto error;
1153 }
1154
1155 c = lttng_condition_on_event_create(res.er);
1156 lttng_event_rule_destroy(res.er);
1157 res.er = NULL;
1158 if (!c) {
1159 goto error;
1160 }
1161
1162 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&res.capture_descriptors);
1163 i++) {
1164 enum lttng_condition_status status;
1165 struct lttng_event_expr **expr =
1166 lttng_dynamic_array_get_element(
1167 &res.capture_descriptors.array, i);
1168
1169 assert(expr);
1170 assert(*expr);
1171 status = lttng_condition_on_event_append_capture_descriptor(
1172 c, *expr);
1173 if (status != LTTNG_CONDITION_STATUS_OK) {
1174 if (status == LTTNG_CONDITION_STATUS_UNSUPPORTED) {
1175 ERR("The capture feature is unsupported by the event-rule condition type");
1176 }
1177
1178 goto error;
1179 }
1180
1181 /* Ownership of event expression moved to `c` */
1182 *expr = NULL;
1183 }
1184
1185 goto end;
1186
1187 error:
1188 lttng_condition_destroy(c);
1189 c = NULL;
1190
1191 end:
1192 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
1193 lttng_event_rule_destroy(res.er);
1194 return c;
1195 }
1196
1197 struct condition_descr {
1198 const char *name;
1199 struct lttng_condition *(*handler) (int *argc, const char ***argv);
1200 };
1201
1202 static const
1203 struct condition_descr condition_descrs[] = {
1204 { "event-rule-matches", handle_condition_event },
1205 };
1206
1207 static
1208 struct lttng_condition *parse_condition(const char *condition_name, int *argc,
1209 const char ***argv)
1210 {
1211 int i;
1212 struct lttng_condition *cond;
1213 const struct condition_descr *descr = NULL;
1214
1215 for (i = 0; i < ARRAY_SIZE(condition_descrs); i++) {
1216 if (strcmp(condition_name, condition_descrs[i].name) == 0) {
1217 descr = &condition_descrs[i];
1218 break;
1219 }
1220 }
1221
1222 if (!descr) {
1223 ERR("Unknown condition name '%s'", condition_name);
1224 goto error;
1225 }
1226
1227 cond = descr->handler(argc, argv);
1228 if (!cond) {
1229 /* The handler has already printed an error message. */
1230 goto error;
1231 }
1232
1233 goto end;
1234 error:
1235 cond = NULL;
1236 end:
1237 return cond;
1238 }
1239
1240 static struct lttng_rate_policy *parse_rate_policy(const char *policy_str)
1241 {
1242 int num_token;
1243 char **tokens = NULL;
1244 struct lttng_rate_policy *policy = NULL;
1245 enum lttng_rate_policy_type policy_type;
1246 unsigned long long value;
1247 char *policy_type_str;
1248 char *policy_value_str;
1249
1250 assert(policy_str);
1251
1252 /*
1253 * rate policy fields are separated by ':'.
1254 */
1255 tokens = strutils_split(policy_str, ':', 1);
1256 num_token = strutils_array_of_strings_len(tokens);
1257
1258 /*
1259 * Early sanity check that the number of parameter is exactly 2.
1260 * i.e : type:value
1261 */
1262 if (num_token != 2) {
1263 ERR("Rate policy format is invalid.");
1264 goto end;
1265 }
1266
1267 policy_type_str = tokens[0];
1268 policy_value_str = tokens[1];
1269
1270 /* Parse the type. */
1271 if (strcmp(policy_type_str, "once-after") == 0) {
1272 policy_type = LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N;
1273 } else if (strcmp(policy_type_str, "every") == 0) {
1274 policy_type = LTTNG_RATE_POLICY_TYPE_EVERY_N;
1275 } else {
1276 ERR("Rate policy type `%s` unknown.", policy_type_str);
1277 goto end;
1278 }
1279
1280 /* Parse the value. */
1281 if (utils_parse_unsigned_long_long(policy_value_str, &value) != 0) {
1282 ERR("Failed to parse rate policy value `%s` as an integer.",
1283 policy_value_str);
1284 goto end;
1285 }
1286
1287 if (value == 0) {
1288 ERR("Rate policy value `%s` must be > 0.", policy_value_str);
1289 goto end;
1290 }
1291
1292 switch (policy_type) {
1293 case LTTNG_RATE_POLICY_TYPE_EVERY_N:
1294 policy = lttng_rate_policy_every_n_create(value);
1295 break;
1296 case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N:
1297 policy = lttng_rate_policy_once_after_n_create(value);
1298 break;
1299 default:
1300 abort();
1301 }
1302
1303 if (policy == NULL) {
1304 ERR("Failed to create rate policy `%s`.", policy_str);
1305 }
1306
1307 end:
1308 strutils_free_null_terminated_array_of_strings(tokens);
1309 return policy;
1310 }
1311
1312 static const struct argpar_opt_descr notify_action_opt_descrs[] = {
1313 { OPT_RATE_POLICY, '\0', "rate-policy", true },
1314 ARGPAR_OPT_DESCR_SENTINEL
1315 };
1316
1317 static
1318 struct lttng_action *handle_action_notify(int *argc, const char ***argv)
1319 {
1320 struct lttng_action *action = NULL;
1321 struct argpar_state *state = NULL;
1322 struct argpar_item *item = NULL;
1323 char *error = NULL;
1324 struct lttng_rate_policy *policy = NULL;
1325
1326 state = argpar_state_create(*argc, *argv, notify_action_opt_descrs);
1327 if (!state) {
1328 ERR("Failed to allocate an argpar state.");
1329 goto error;
1330 }
1331
1332 while (true) {
1333 enum argpar_state_parse_next_status status;
1334
1335 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1336 status = argpar_state_parse_next(state, &item, &error);
1337 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1338 ERR("%s", error);
1339 goto error;
1340 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1341 /* Just stop parsing here. */
1342 break;
1343 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1344 break;
1345 }
1346
1347 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1348
1349 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1350 const struct argpar_item_opt *item_opt =
1351 (const struct argpar_item_opt *) item;
1352
1353 switch (item_opt->descr->id) {
1354 case OPT_RATE_POLICY:
1355 {
1356 policy = parse_rate_policy(item_opt->arg);
1357 if (!policy) {
1358 goto error;
1359 }
1360 break;
1361 }
1362 default:
1363 abort();
1364 }
1365 } else {
1366 const struct argpar_item_non_opt *item_non_opt;
1367
1368 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1369
1370 item_non_opt = (const struct argpar_item_non_opt *) item;
1371
1372 switch (item_non_opt->non_opt_index) {
1373 default:
1374 ERR("Unexpected argument `%s`.",
1375 item_non_opt->arg);
1376 goto error;
1377 }
1378 }
1379 }
1380
1381 *argc -= argpar_state_get_ingested_orig_args(state);
1382 *argv += argpar_state_get_ingested_orig_args(state);
1383
1384 action = lttng_action_notify_create();
1385 if (!action) {
1386 ERR("Failed to create notify action");
1387 goto error;
1388 }
1389
1390 if (policy) {
1391 enum lttng_action_status status;
1392 status = lttng_action_notify_set_rate_policy(action, policy);
1393 if (status != LTTNG_ACTION_STATUS_OK) {
1394 ERR("Failed to set rate policy");
1395 goto error;
1396 }
1397 }
1398
1399 goto end;
1400
1401 error:
1402 lttng_action_destroy(action);
1403 action = NULL;
1404 end:
1405 free(error);
1406 lttng_rate_policy_destroy(policy);
1407 argpar_state_destroy(state);
1408 argpar_item_destroy(item);
1409 return action;
1410 }
1411
1412 /*
1413 * Generic handler for a kind of action that takes a session name and an
1414 * optional rate policy.
1415 */
1416
1417 static struct lttng_action *handle_action_simple_session_with_policy(int *argc,
1418 const char ***argv,
1419 struct lttng_action *(*create_action_cb)(void),
1420 enum lttng_action_status (*set_session_name_cb)(
1421 struct lttng_action *, const char *),
1422 enum lttng_action_status (*set_rate_policy_cb)(
1423 struct lttng_action *,
1424 const struct lttng_rate_policy *),
1425 const char *action_name)
1426 {
1427 struct lttng_action *action = NULL;
1428 struct argpar_state *state = NULL;
1429 struct argpar_item *item = NULL;
1430 const char *session_name_arg = NULL;
1431 char *error = NULL;
1432 enum lttng_action_status action_status;
1433 struct lttng_rate_policy *policy = NULL;
1434
1435 assert(set_session_name_cb);
1436 assert(set_rate_policy_cb);
1437
1438 const struct argpar_opt_descr rate_policy_opt_descrs[] = {
1439 { OPT_RATE_POLICY, '\0', "rate-policy", true },
1440 ARGPAR_OPT_DESCR_SENTINEL
1441 };
1442
1443 state = argpar_state_create(*argc, *argv, rate_policy_opt_descrs);
1444 if (!state) {
1445 ERR("Failed to allocate an argpar state.");
1446 goto error;
1447 }
1448
1449 while (true) {
1450 enum argpar_state_parse_next_status status;
1451
1452 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1453 status = argpar_state_parse_next(state, &item, &error);
1454 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1455 ERR("%s", error);
1456 goto error;
1457 } else if (status ==
1458 ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1459 /* Just stop parsing here. */
1460 break;
1461 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1462 break;
1463 }
1464
1465 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1466 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1467 const struct argpar_item_opt *item_opt =
1468 (const struct argpar_item_opt *) item;
1469
1470 switch (item_opt->descr->id) {
1471 case OPT_RATE_POLICY:
1472 {
1473 policy = parse_rate_policy(item_opt->arg);
1474 if (!policy) {
1475 goto error;
1476 }
1477 break;
1478 }
1479 default:
1480 abort();
1481 }
1482 } else {
1483 const struct argpar_item_non_opt *item_non_opt;
1484 item_non_opt = (const struct argpar_item_non_opt *) item;
1485
1486 switch (item_non_opt->non_opt_index) {
1487 case 0:
1488 session_name_arg = item_non_opt->arg;
1489 break;
1490 default:
1491 ERR("Unexpected argument `%s`.",
1492 item_non_opt->arg);
1493 goto error;
1494 }
1495 }
1496 }
1497
1498 *argc -= argpar_state_get_ingested_orig_args(state);
1499 *argv += argpar_state_get_ingested_orig_args(state);
1500
1501 if (!session_name_arg) {
1502 ERR("Missing session name.");
1503 goto error;
1504 }
1505
1506 action = create_action_cb();
1507 if (!action) {
1508 ERR("Failed to allocate %s session action.", action_name);
1509 goto error;
1510 }
1511
1512 action_status = set_session_name_cb(action, session_name_arg);
1513 if (action_status != LTTNG_ACTION_STATUS_OK) {
1514 ERR("Failed to set action %s session's session name to '%s'.",
1515 action_name, session_name_arg);
1516 goto error;
1517 }
1518
1519 if (policy) {
1520 action_status = set_rate_policy_cb(action, policy);
1521 if (action_status != LTTNG_ACTION_STATUS_OK) {
1522 ERR("Failed to set rate policy");
1523 goto error;
1524 }
1525 }
1526
1527 goto end;
1528
1529 error:
1530 lttng_action_destroy(action);
1531 action = NULL;
1532 argpar_item_destroy(item);
1533 end:
1534 lttng_rate_policy_destroy(policy);
1535 free(error);
1536 argpar_state_destroy(state);
1537 return action;
1538 }
1539
1540 static
1541 struct lttng_action *handle_action_start_session(int *argc,
1542 const char ***argv)
1543 {
1544 return handle_action_simple_session_with_policy(argc, argv,
1545 lttng_action_start_session_create,
1546 lttng_action_start_session_set_session_name,
1547 lttng_action_start_session_set_rate_policy, "start");
1548 }
1549
1550 static
1551 struct lttng_action *handle_action_stop_session(int *argc,
1552 const char ***argv)
1553 {
1554 return handle_action_simple_session_with_policy(argc, argv,
1555 lttng_action_stop_session_create,
1556 lttng_action_stop_session_set_session_name,
1557 lttng_action_stop_session_set_rate_policy, "stop");
1558 }
1559
1560 static
1561 struct lttng_action *handle_action_rotate_session(int *argc,
1562 const char ***argv)
1563 {
1564 return handle_action_simple_session_with_policy(argc, argv,
1565 lttng_action_rotate_session_create,
1566 lttng_action_rotate_session_set_session_name,
1567 lttng_action_rotate_session_set_rate_policy,
1568 "rotate");
1569 }
1570
1571 static const struct argpar_opt_descr snapshot_action_opt_descrs[] = {
1572 { OPT_NAME, 'n', "name", true },
1573 { OPT_MAX_SIZE, 'm', "max-size", true },
1574 { OPT_CTRL_URL, '\0', "ctrl-url", true },
1575 { OPT_DATA_URL, '\0', "data-url", true },
1576 { OPT_URL, '\0', "url", true },
1577 { OPT_PATH, '\0', "path", true },
1578 { OPT_RATE_POLICY, '\0', "rate-policy", true },
1579 ARGPAR_OPT_DESCR_SENTINEL
1580 };
1581
1582 static
1583 struct lttng_action *handle_action_snapshot_session(int *argc,
1584 const char ***argv)
1585 {
1586 struct lttng_action *action = NULL;
1587 struct argpar_state *state = NULL;
1588 struct argpar_item *item = NULL;
1589 const char *session_name_arg = NULL;
1590 char *snapshot_name_arg = NULL;
1591 char *ctrl_url_arg = NULL;
1592 char *data_url_arg = NULL;
1593 char *max_size_arg = NULL;
1594 char *url_arg = NULL;
1595 char *path_arg = NULL;
1596 char *error = NULL;
1597 enum lttng_action_status action_status;
1598 struct lttng_snapshot_output *snapshot_output = NULL;
1599 struct lttng_rate_policy *policy = NULL;
1600 int ret;
1601 unsigned int locations_specified = 0;
1602
1603 state = argpar_state_create(*argc, *argv, snapshot_action_opt_descrs);
1604 if (!state) {
1605 ERR("Failed to allocate an argpar state.");
1606 goto error;
1607 }
1608
1609 while (true) {
1610 enum argpar_state_parse_next_status status;
1611
1612 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1613 status = argpar_state_parse_next(state, &item, &error);
1614 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1615 ERR("%s", error);
1616 goto error;
1617 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1618 /* Just stop parsing here. */
1619 break;
1620 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1621 break;
1622 }
1623
1624 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1625
1626 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1627 const struct argpar_item_opt *item_opt =
1628 (const struct argpar_item_opt *) item;
1629
1630 switch (item_opt->descr->id) {
1631 case OPT_NAME:
1632 if (!assign_string(&snapshot_name_arg, item_opt->arg, "--name/-n")) {
1633 goto error;
1634 }
1635
1636 break;
1637 case OPT_MAX_SIZE:
1638 if (!assign_string(&max_size_arg, item_opt->arg, "--max-size/-m")) {
1639 goto error;
1640 }
1641
1642 break;
1643 case OPT_CTRL_URL:
1644 if (!assign_string(&ctrl_url_arg, item_opt->arg, "--ctrl-url")) {
1645 goto error;
1646 }
1647
1648 break;
1649 case OPT_DATA_URL:
1650 if (!assign_string(&data_url_arg, item_opt->arg, "--data-url")) {
1651 goto error;
1652 }
1653
1654 break;
1655 case OPT_URL:
1656 if (!assign_string(&url_arg, item_opt->arg, "--url")) {
1657 goto error;
1658 }
1659
1660 break;
1661 case OPT_PATH:
1662 if (!assign_string(&path_arg, item_opt->arg, "--path")) {
1663 goto error;
1664 }
1665
1666 break;
1667 case OPT_RATE_POLICY:
1668 {
1669 policy = parse_rate_policy(item_opt->arg);
1670 if (!policy) {
1671 goto error;
1672 }
1673 break;
1674 }
1675 default:
1676 abort();
1677 }
1678 } else {
1679 const struct argpar_item_non_opt *item_non_opt;
1680
1681 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1682
1683 item_non_opt = (const struct argpar_item_non_opt *) item;
1684
1685 switch (item_non_opt->non_opt_index) {
1686 case 0:
1687 session_name_arg = item_non_opt->arg;
1688 break;
1689 default:
1690 ERR("Unexpected argument `%s`.",
1691 item_non_opt->arg);
1692 goto error;
1693 }
1694 }
1695 }
1696
1697 *argc -= argpar_state_get_ingested_orig_args(state);
1698 *argv += argpar_state_get_ingested_orig_args(state);
1699
1700 if (!session_name_arg) {
1701 ERR("Missing session name.");
1702 goto error;
1703 }
1704
1705 /* --ctrl-url and --data-url must come in pair. */
1706 if (ctrl_url_arg && !data_url_arg) {
1707 ERR("--ctrl-url is specified, but --data-url is missing.");
1708 goto error;
1709 }
1710
1711 if (!ctrl_url_arg && data_url_arg) {
1712 ERR("--data-url is specified, but --ctrl-url is missing.");
1713 goto error;
1714 }
1715
1716 locations_specified += !!(ctrl_url_arg || data_url_arg);
1717 locations_specified += !!url_arg;
1718 locations_specified += !!path_arg;
1719
1720 /* --ctrl-url/--data-url, --url and --path are mutually exclusive. */
1721 if (locations_specified > 1) {
1722 ERR("The --ctrl-url/--data-url, --url, and --path options can't be used together.");
1723 goto error;
1724 }
1725
1726 /*
1727 * Did the user specify an option that implies using a
1728 * custom/unregistered output?
1729 */
1730 if (url_arg || ctrl_url_arg || path_arg) {
1731 snapshot_output = lttng_snapshot_output_create();
1732 if (!snapshot_output) {
1733 ERR("Failed to allocate a snapshot output.");
1734 goto error;
1735 }
1736 }
1737
1738 action = lttng_action_snapshot_session_create();
1739 if (!action) {
1740 ERR("Failed to allocate snapshot session action.");
1741 goto error;
1742 }
1743
1744 action_status = lttng_action_snapshot_session_set_session_name(
1745 action, session_name_arg);
1746 if (action_status != LTTNG_ACTION_STATUS_OK) {
1747 ERR("Failed to set action snapshot session's session name to '%s'.",
1748 session_name_arg);
1749 goto error;
1750 }
1751
1752 if (snapshot_name_arg) {
1753 if (!snapshot_output) {
1754 ERR("Can't provide a snapshot output name without a snapshot output destination.");
1755 goto error;
1756 }
1757
1758 ret = lttng_snapshot_output_set_name(
1759 snapshot_name_arg, snapshot_output);
1760 if (ret != 0) {
1761 ERR("Failed to set name of snapshot output.");
1762 goto error;
1763 }
1764 }
1765
1766 if (max_size_arg) {
1767 uint64_t max_size;
1768
1769 if (!snapshot_output) {
1770 ERR("Can't provide a snapshot output max size without a snapshot output destination.");
1771 goto error;
1772 }
1773
1774 ret = utils_parse_size_suffix(max_size_arg, &max_size);
1775 if (ret != 0) {
1776 ERR("Failed to parse `%s` as a size.", max_size_arg);
1777 goto error;
1778 }
1779
1780 ret = lttng_snapshot_output_set_size(max_size, snapshot_output);
1781 if (ret != 0) {
1782 ERR("Failed to set snapshot output's max size to %" PRIu64 " bytes.",
1783 max_size);
1784 goto error;
1785 }
1786 }
1787
1788 if (url_arg) {
1789 int num_uris;
1790 struct lttng_uri *uris;
1791
1792 if (!strstr(url_arg, "://")) {
1793 ERR("Failed to parse '%s' as an URL.", url_arg);
1794 goto error;
1795 }
1796
1797 num_uris = uri_parse_str_urls(url_arg, NULL, &uris);
1798 if (num_uris < 1) {
1799 ERR("Failed to parse '%s' as an URL.", url_arg);
1800 goto error;
1801 }
1802
1803 if (uris[0].dtype == LTTNG_DST_PATH) {
1804 ret = lttng_snapshot_output_set_local_path(
1805 uris[0].dst.path, snapshot_output);
1806 free(uris);
1807 if (ret != 0) {
1808 ERR("Failed to assign '%s' as a local destination.",
1809 url_arg);
1810 goto error;
1811 }
1812 } else {
1813 ret = lttng_snapshot_output_set_network_url(
1814 url_arg, snapshot_output);
1815 free(uris);
1816 if (ret != 0) {
1817 ERR("Failed to assign '%s' as a network URL.",
1818 url_arg);
1819 goto error;
1820 }
1821 }
1822 }
1823
1824 if (path_arg) {
1825 ret = lttng_snapshot_output_set_local_path(
1826 path_arg, snapshot_output);
1827 if (ret != 0) {
1828 ERR("Failed to parse '%s' as a local path.", path_arg);
1829 goto error;
1830 }
1831 }
1832
1833 if (ctrl_url_arg) {
1834 /*
1835 * Two argument form, network output with separate control and
1836 * data URLs.
1837 */
1838 ret = lttng_snapshot_output_set_network_urls(
1839 ctrl_url_arg, data_url_arg, snapshot_output);
1840 if (ret != 0) {
1841 ERR("Failed to parse `%s` and `%s` as control and data URLs.",
1842 ctrl_url_arg, data_url_arg);
1843 goto error;
1844 }
1845 }
1846
1847 if (snapshot_output) {
1848 action_status = lttng_action_snapshot_session_set_output(
1849 action, snapshot_output);
1850 if (action_status != LTTNG_ACTION_STATUS_OK) {
1851 ERR("Failed to set snapshot session action's output.");
1852 goto error;
1853 }
1854
1855 /* Ownership of `snapshot_output` has been transferred to the action. */
1856 snapshot_output = NULL;
1857 }
1858
1859 if (policy) {
1860 enum lttng_action_status status;
1861 status = lttng_action_snapshot_session_set_rate_policy(
1862 action, policy);
1863 if (status != LTTNG_ACTION_STATUS_OK) {
1864 ERR("Failed to set rate policy");
1865 goto error;
1866 }
1867 }
1868
1869 goto end;
1870
1871 error:
1872 lttng_action_destroy(action);
1873 action = NULL;
1874 free(error);
1875 end:
1876 free(snapshot_name_arg);
1877 free(path_arg);
1878 free(url_arg);
1879 free(ctrl_url_arg);
1880 free(data_url_arg);
1881 free(snapshot_output);
1882 free(max_size_arg);
1883 lttng_rate_policy_destroy(policy);
1884 argpar_state_destroy(state);
1885 argpar_item_destroy(item);
1886 return action;
1887 }
1888
1889 struct action_descr {
1890 const char *name;
1891 struct lttng_action *(*handler) (int *argc, const char ***argv);
1892 };
1893
1894 static const
1895 struct action_descr action_descrs[] = {
1896 { "notify", handle_action_notify },
1897 { "start-session", handle_action_start_session },
1898 { "stop-session", handle_action_stop_session },
1899 { "rotate-session", handle_action_rotate_session },
1900 { "snapshot-session", handle_action_snapshot_session },
1901 };
1902
1903 static
1904 struct lttng_action *parse_action(const char *action_name, int *argc, const char ***argv)
1905 {
1906 int i;
1907 struct lttng_action *action;
1908 const struct action_descr *descr = NULL;
1909
1910 for (i = 0; i < ARRAY_SIZE(action_descrs); i++) {
1911 if (strcmp(action_name, action_descrs[i].name) == 0) {
1912 descr = &action_descrs[i];
1913 break;
1914 }
1915 }
1916
1917 if (!descr) {
1918 ERR("Unknown action name: %s", action_name);
1919 goto error;
1920 }
1921
1922 action = descr->handler(argc, argv);
1923 if (!action) {
1924 /* The handler has already printed an error message. */
1925 goto error;
1926 }
1927
1928 goto end;
1929 error:
1930 action = NULL;
1931 end:
1932 return action;
1933 }
1934
1935 static const
1936 struct argpar_opt_descr add_trigger_options[] = {
1937 { OPT_HELP, 'h', "help", false },
1938 { OPT_LIST_OPTIONS, '\0', "list-options", false },
1939 { OPT_CONDITION, '\0', "condition", true },
1940 { OPT_ACTION, '\0', "action", true },
1941 { OPT_NAME, '\0', "name", true },
1942 { OPT_OWNER_UID, '\0', "owner-uid", true },
1943 ARGPAR_OPT_DESCR_SENTINEL,
1944 };
1945
1946 static
1947 void lttng_actions_destructor(void *p)
1948 {
1949 struct lttng_action *action = p;
1950
1951 lttng_action_destroy(action);
1952 }
1953
1954 int cmd_add_trigger(int argc, const char **argv)
1955 {
1956 int ret;
1957 int my_argc = argc - 1;
1958 const char **my_argv = argv + 1;
1959 struct lttng_condition *condition = NULL;
1960 struct lttng_dynamic_pointer_array actions;
1961 struct argpar_state *argpar_state = NULL;
1962 struct argpar_item *argpar_item = NULL;
1963 struct lttng_action *action_group = NULL;
1964 struct lttng_action *action = NULL;
1965 struct lttng_trigger *trigger = NULL;
1966 char *error = NULL;
1967 char *name = NULL;
1968 int i;
1969 char *owner_uid = NULL;
1970
1971 lttng_dynamic_pointer_array_init(&actions, lttng_actions_destructor);
1972
1973 while (true) {
1974 enum argpar_state_parse_next_status status;
1975 const struct argpar_item_opt *item_opt;
1976 int ingested_args;
1977
1978 argpar_state_destroy(argpar_state);
1979 argpar_state = argpar_state_create(my_argc, my_argv,
1980 add_trigger_options);
1981 if (!argpar_state) {
1982 ERR("Failed to create argpar state.");
1983 goto error;
1984 }
1985
1986 ARGPAR_ITEM_DESTROY_AND_RESET(argpar_item);
1987 status = argpar_state_parse_next(argpar_state, &argpar_item, &error);
1988 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1989 ERR("%s", error);
1990 goto error;
1991 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1992 ERR("%s", error);
1993 goto error;
1994 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1995 break;
1996 }
1997
1998 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1999
2000 if (argpar_item->type == ARGPAR_ITEM_TYPE_NON_OPT) {
2001 const struct argpar_item_non_opt *item_non_opt =
2002 (const struct argpar_item_non_opt *)
2003 argpar_item;
2004
2005 ERR("Unexpected argument `%s`.", item_non_opt->arg);
2006 goto error;
2007 }
2008
2009 item_opt = (const struct argpar_item_opt *) argpar_item;
2010
2011 ingested_args = argpar_state_get_ingested_orig_args(
2012 argpar_state);
2013
2014 my_argc -= ingested_args;
2015 my_argv += ingested_args;
2016
2017 switch (item_opt->descr->id) {
2018 case OPT_HELP:
2019 SHOW_HELP();
2020 ret = 0;
2021 goto end;
2022 case OPT_LIST_OPTIONS:
2023 list_cmd_options_argpar(stdout, add_trigger_options);
2024 ret = 0;
2025 goto end;
2026 case OPT_CONDITION:
2027 {
2028 if (condition) {
2029 ERR("A --condition was already given.");
2030 goto error;
2031 }
2032
2033 condition = parse_condition(item_opt->arg, &my_argc, &my_argv);
2034 if (!condition) {
2035 /*
2036 * An error message was already printed by
2037 * parse_condition.
2038 */
2039 goto error;
2040 }
2041
2042 break;
2043 }
2044 case OPT_ACTION:
2045 {
2046 action = parse_action(item_opt->arg, &my_argc, &my_argv);
2047 if (!action) {
2048 /*
2049 * An error message was already printed by
2050 * parse_condition.
2051 */
2052 goto error;
2053 }
2054
2055 ret = lttng_dynamic_pointer_array_add_pointer(
2056 &actions, action);
2057 if (ret) {
2058 ERR("Failed to add pointer to pointer array.");
2059 goto error;
2060 }
2061
2062 /* Ownership of the action was transferred to the group. */
2063 action = NULL;
2064
2065 break;
2066 }
2067 case OPT_NAME:
2068 {
2069 if (!assign_string(&name, item_opt->arg, "--name")) {
2070 goto error;
2071 }
2072
2073 break;
2074 }
2075 case OPT_OWNER_UID:
2076 {
2077 if (!assign_string(&owner_uid, item_opt->arg,
2078 "--owner-uid")) {
2079 goto error;
2080 }
2081
2082 break;
2083 }
2084 default:
2085 abort();
2086 }
2087 }
2088
2089 if (!condition) {
2090 ERR("Missing --condition.");
2091 goto error;
2092 }
2093
2094 if (lttng_dynamic_pointer_array_get_count(&actions) == 0) {
2095 ERR("Need at least one --action.");
2096 goto error;
2097 }
2098
2099 action_group = lttng_action_group_create();
2100 if (!action_group) {
2101 goto error;
2102 }
2103
2104 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&actions); i++) {
2105 enum lttng_action_status status;
2106
2107 action = lttng_dynamic_pointer_array_steal_pointer(&actions, i);
2108
2109 status = lttng_action_group_add_action(action_group, action);
2110 if (status != LTTNG_ACTION_STATUS_OK) {
2111 goto error;
2112 }
2113
2114 /*
2115 * The `lttng_action_group_add_action()` takes a reference to
2116 * the action. We can destroy ours.
2117 */
2118 lttng_action_destroy(action);
2119 action = NULL;
2120 }
2121
2122 trigger = lttng_trigger_create(condition, action_group);
2123 if (!trigger) {
2124 goto error;
2125 }
2126
2127 if (name) {
2128 enum lttng_trigger_status trigger_status =
2129 lttng_trigger_set_name(trigger, name);
2130
2131 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2132 ERR("Failed to set trigger name.");
2133 goto error;
2134 }
2135 }
2136
2137 if (owner_uid) {
2138 enum lttng_trigger_status trigger_status;
2139 char *end;
2140 long long uid;
2141
2142 errno = 0;
2143 uid = strtol(owner_uid, &end, 10);
2144 if (end == owner_uid || *end != '\0' || errno != 0) {
2145 ERR("Failed to parse `%s` as a user id.", owner_uid);
2146 }
2147
2148 trigger_status = lttng_trigger_set_owner_uid(trigger, uid);
2149 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2150 ERR("Failed to set trigger's user identity.");
2151 goto error;
2152 }
2153 }
2154
2155 ret = lttng_register_trigger(trigger);
2156 if (ret) {
2157 ERR("Failed to register trigger: %s.", lttng_strerror(ret));
2158 goto error;
2159 }
2160
2161 MSG("Trigger registered successfully.");
2162
2163 goto end;
2164
2165 error:
2166 ret = 1;
2167
2168 end:
2169 argpar_state_destroy(argpar_state);
2170 argpar_item_destroy(argpar_item);
2171 lttng_dynamic_pointer_array_reset(&actions);
2172 lttng_condition_destroy(condition);
2173 lttng_action_destroy(action_group);
2174 lttng_action_destroy(action);
2175 lttng_trigger_destroy(trigger);
2176 free(error);
2177 free(name);
2178 free(owner_uid);
2179 return ret;
2180 }
This page took 0.115406 seconds and 4 git commands to generate.