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