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