e4342cf85d99a7dfb149f85c702bd57cf99e7bfd
[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_FIRE_ONCE_AFTER,
44 OPT_FIRE_EVERY,
45 OPT_USER_ID,
46
47 OPT_ALL,
48 OPT_FILTER,
49 OPT_EXCLUDE,
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_NAME,
66 OPT_MAX_SIZE,
67 OPT_DATA_URL,
68 OPT_CTRL_URL,
69 OPT_URL,
70 OPT_PATH,
71
72 OPT_CAPTURE,
73 };
74
75 static const struct argpar_opt_descr event_rule_opt_descrs[] = {
76 { OPT_ALL, 'a', "all", false },
77 { OPT_FILTER, 'f', "filter", true },
78 { OPT_EXCLUDE, 'x', "exclude", true },
79 { OPT_LOGLEVEL, '\0', "loglevel", true },
80 { OPT_LOGLEVEL_ONLY, '\0', "loglevel-only", 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_exp, const char *capture_str)
305 {
306 char *provider_name = NULL;
307 struct lttng_event_expr *event_expr = NULL;
308 const struct ir_load_expression_op *load_expr_op = load_exp->child;
309
310 switch (load_expr_op->type) {
311 case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT:
312 case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT:
313 {
314 const char *field_name;
315
316 load_expr_op = load_expr_op->next;
317 assert(load_expr_op);
318 assert(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
319 field_name = load_expr_op->u.symbol;
320 assert(field_name);
321
322 event_expr = load_expr_op->type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
323 lttng_event_expr_event_payload_field_create(field_name) :
324 lttng_event_expr_channel_context_field_create(field_name);
325 if (!event_expr) {
326 ERR("Failed to create %s event expression: field name = `%s`.",
327 load_expr_op->type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
328 "payload field" : "channel context",
329 field_name);
330 goto error;
331 }
332
333 break;
334 }
335 case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT:
336 {
337 const char *colon;
338 const char *type_name;
339 const char *field_name;
340
341 load_expr_op = load_expr_op->next;
342 assert(load_expr_op);
343 assert(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
344 field_name = load_expr_op->u.symbol;
345 assert(field_name);
346
347 /*
348 * The field name needs to be of the form PROVIDER:TYPE. We
349 * split it here.
350 */
351 colon = strchr(field_name, ':');
352 if (!colon) {
353 ERR("Invalid app-specific context field name: missing colon in `%s`.",
354 field_name);
355 goto error;
356 }
357
358 type_name = colon + 1;
359 if (*type_name == '\0') {
360 ERR("Invalid app-specific context field name: missing type name after colon in `%s`.",
361 field_name);
362 goto error;
363 }
364
365 provider_name = strndup(field_name, colon - field_name);
366 if (!provider_name) {
367 PERROR("Failed to allocate field name string");
368 goto error;
369 }
370
371 event_expr = lttng_event_expr_app_specific_context_field_create(
372 provider_name, type_name);
373 if (!event_expr) {
374 ERR("Failed to create app-specific context field event expression: provider name = `%s`, type name = `%s`",
375 provider_name, type_name);
376 goto error;
377 }
378
379 break;
380 }
381 default:
382 ERR("%s: unexpected load expr type %d.", __func__,
383 load_expr_op->type);
384 abort();
385 }
386
387 load_expr_op = load_expr_op->next;
388
389 /* There may be a single array index after that. */
390 if (load_expr_op->type == IR_LOAD_EXPRESSION_GET_INDEX) {
391 struct lttng_event_expr *index_event_expr;
392 const uint64_t index = load_expr_op->u.index;
393
394 index_event_expr = lttng_event_expr_array_field_element_create(event_expr, index);
395 if (!index_event_expr) {
396 ERR("Failed to create array field element event expression.");
397 goto error;
398 }
399
400 event_expr = index_event_expr;
401 load_expr_op = load_expr_op->next;
402 }
403
404 switch (load_expr_op->type) {
405 case IR_LOAD_EXPRESSION_LOAD_FIELD:
406 /*
407 * This is what we expect, IR_LOAD_EXPRESSION_LOAD_FIELD is
408 * always found at the end of the chain.
409 */
410 break;
411 case IR_LOAD_EXPRESSION_GET_SYMBOL:
412 ERR("While parsing expression `%s`: Capturing subfields is not supported.",
413 capture_str);
414 goto error;
415
416 default:
417 ERR("%s: unexpected load expression operator %s.", __func__,
418 ir_load_expression_type_str(load_expr_op->type));
419 abort();
420 }
421
422 goto end;
423
424 error:
425 lttng_event_expr_destroy(event_expr);
426 event_expr = NULL;
427
428 end:
429 free(provider_name);
430
431 return event_expr;
432 }
433
434 static
435 struct lttng_event_expr *ir_op_load_to_event_expr(
436 const struct ir_op *ir, const char *capture_str)
437 {
438 struct lttng_event_expr *event_expr = NULL;
439
440 assert(ir->op == IR_OP_LOAD);
441
442 switch (ir->data_type) {
443 case IR_DATA_EXPRESSION:
444 {
445 const struct ir_load_expression *ir_load_expr =
446 ir->u.load.u.expression;
447
448 event_expr = ir_op_load_expr_to_event_expr(
449 ir_load_expr, capture_str);
450 break;
451 }
452 default:
453 ERR("%s: unexpected data type: %s.", __func__,
454 ir_data_type_str(ir->data_type));
455 abort();
456 }
457
458 return event_expr;
459 }
460
461 static
462 const char *ir_operator_type_human_str(enum ir_op_type op)
463 {
464 const char *name;
465
466 switch (op) {
467 case IR_OP_BINARY:
468 name = "Binary";
469 break;
470 case IR_OP_UNARY:
471 name = "Unary";
472 break;
473 case IR_OP_LOGICAL:
474 name = "Logical";
475 break;
476 default:
477 abort();
478 }
479
480 return name;
481 }
482
483 static
484 struct lttng_event_expr *ir_op_root_to_event_expr(const struct ir_op *ir,
485 const char *capture_str)
486 {
487 struct lttng_event_expr *event_expr = NULL;
488
489 assert(ir->op == IR_OP_ROOT);
490 ir = ir->u.root.child;
491
492 switch (ir->op) {
493 case IR_OP_LOAD:
494 event_expr = ir_op_load_to_event_expr(ir, capture_str);
495 break;
496 case IR_OP_BINARY:
497 case IR_OP_UNARY:
498 case IR_OP_LOGICAL:
499 ERR("While parsing expression `%s`: %s operators are not allowed in capture expressions.",
500 capture_str,
501 ir_operator_type_human_str(ir->op));
502 break;
503 default:
504 ERR("%s: unexpected IR op type: %s.", __func__,
505 ir_op_type_str(ir->op));
506 abort();
507 }
508
509 return event_expr;
510 }
511
512 static
513 void destroy_event_expr(void *ptr)
514 {
515 lttng_event_expr_destroy(ptr);
516 }
517
518 struct parse_event_rule_res {
519 /* Owned by this. */
520 struct lttng_event_rule *er;
521
522 /* Array of `struct lttng_event_expr *` */
523 struct lttng_dynamic_pointer_array capture_descriptors;
524 };
525
526 static
527 struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv)
528 {
529 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
530 enum lttng_event_rule_type event_rule_type =
531 LTTNG_EVENT_RULE_TYPE_UNKNOWN;
532 struct argpar_state *state;
533 struct argpar_item *item = NULL;
534 char *error = NULL;
535 int consumed_args = -1;
536 struct lttng_kernel_probe_location *kernel_probe_location = NULL;
537 struct lttng_userspace_probe_location *userspace_probe_location = NULL;
538 struct parse_event_rule_res res = { 0 };
539 struct lttng_event_expr *event_expr = NULL;
540 struct filter_parser_ctx *parser_ctx = NULL;
541
542 /* Was the -a/--all flag provided? */
543 bool all_events = false;
544
545 /* Tracepoint name (non-option argument). */
546 const char *tracepoint_name = NULL;
547
548 /* Holds the argument of --probe / --userspace-probe. */
549 char *source = NULL;
550
551 /* Filter. */
552 char *filter = NULL;
553
554 /* Exclude. */
555 char *exclude = NULL;
556 char **exclusion_list = 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_KRETPROBE)) {
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_KPROBE)) {
635 goto error;
636 }
637
638 if (!assign_string(&source, item_opt->arg, "source")) {
639 goto error;
640 }
641
642 break;
643 case OPT_USERSPACE_PROBE:
644 if (!assign_event_rule_type(&event_rule_type,
645 LTTNG_EVENT_RULE_TYPE_UPROBE)) {
646 goto error;
647 }
648
649 if (!assign_string(&source, item_opt->arg, "source")) {
650 goto error;
651 }
652
653 break;
654 case OPT_SYSCALL:
655 if (!assign_event_rule_type(&event_rule_type,
656 LTTNG_EVENT_RULE_TYPE_SYSCALL)) {
657 goto error;
658 }
659
660 break;
661 case OPT_TRACEPOINT:
662 if (!assign_event_rule_type(&event_rule_type,
663 LTTNG_EVENT_RULE_TYPE_TRACEPOINT)) {
664 goto error;
665 }
666
667 break;
668 case OPT_ALL:
669 all_events = true;
670 break;
671 case OPT_FILTER:
672 if (!assign_string(&filter, item_opt->arg,
673 "--filter/-f")) {
674 goto error;
675 }
676
677 break;
678 case OPT_EXCLUDE:
679 if (!assign_string(&exclude, item_opt->arg,
680 "--exclude/-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 /*
743 * Don't accept two non-option arguments/tracepoint
744 * names.
745 */
746 if (tracepoint_name) {
747 ERR("Unexpected argument '%s'",
748 item_non_opt->arg);
749 goto error;
750 }
751
752 tracepoint_name = item_non_opt->arg;
753 }
754 }
755
756 if (event_rule_type == LTTNG_EVENT_RULE_TYPE_UNKNOWN) {
757 event_rule_type = LTTNG_EVENT_RULE_TYPE_TRACEPOINT;
758 }
759
760 /*
761 * Option -a is applicable to event rules of type tracepoint and
762 * syscall, and it is equivalent to using "*" as the tracepoint name.
763 */
764 if (all_events) {
765 switch (event_rule_type) {
766 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
767 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
768 break;
769 default:
770 ERR("Can't use -a/--all with %s event rules.",
771 lttng_event_rule_type_str(event_rule_type));
772 goto error;
773 }
774
775 if (tracepoint_name) {
776 ERR("Can't provide a tracepoint name with -a/--all.");
777 goto error;
778 }
779
780 /* In which case, it's equivalent to tracepoint name "*". */
781 tracepoint_name = "*";
782 }
783
784 /*
785 * A tracepoint name (or -a, for the event rule types that accept it)
786 * is required.
787 */
788 if (!tracepoint_name) {
789 ERR("Need to provide either a tracepoint name or -a/--all.");
790 goto error;
791 }
792
793 /*
794 * We don't support multiple tracepoint names for now.
795 */
796 if (strchr(tracepoint_name, ',')) {
797 ERR("Comma separated tracepoint names are not supported.");
798 goto error;
799 }
800
801 /*
802 * Update *argc and *argv so our caller can keep parsing what follows.
803 */
804 consumed_args = argpar_state_get_ingested_orig_args(state);
805 assert(consumed_args >= 0);
806 *argc -= consumed_args;
807 *argv += consumed_args;
808
809 /* Need to specify a domain. */
810 if (domain_type == LTTNG_DOMAIN_NONE) {
811 ERR("Please specify a domain (--kernel/--userspace/--jul/--log4j/--python).");
812 goto error;
813 }
814
815 /* Validate event rule type against domain. */
816 switch (event_rule_type) {
817 case LTTNG_EVENT_RULE_TYPE_KPROBE:
818 case LTTNG_EVENT_RULE_TYPE_KRETPROBE:
819 case LTTNG_EVENT_RULE_TYPE_UPROBE:
820 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
821 if (domain_type != LTTNG_DOMAIN_KERNEL) {
822 ERR("Event type not available for user-space tracing.");
823 goto error;
824 }
825 break;
826
827 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
828 break;
829
830 default:
831 abort();
832 }
833
834 /*
835 * Adding a filter to a probe, function or userspace-probe would be
836 * denied by the kernel tracer as it's not supported at the moment. We
837 * do an early check here to warn the user.
838 */
839 if (filter && domain_type == LTTNG_DOMAIN_KERNEL) {
840 switch (event_rule_type) {
841 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
842 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
843 break;
844 default:
845 ERR("Filter expressions are not supported for %s event rules.",
846 lttng_event_rule_type_str(event_rule_type));
847 goto error;
848 }
849 }
850
851 /* If --exclude/-x was passed, split it into an exclusion list. */
852 if (exclude) {
853 if (domain_type != LTTNG_DOMAIN_UST) {
854 ERR("Event name exclusions are not yet implemented for %s event rules.",
855 get_domain_str(domain_type));
856 goto error;
857 }
858
859
860 if (create_exclusion_list_and_validate(tracepoint_name, exclude,
861 &exclusion_list) != 0) {
862 ERR("Failed to create exclusion list.");
863 goto error;
864 }
865 }
866
867 if (loglevel_str && event_rule_type != LTTNG_EVENT_RULE_TYPE_TRACEPOINT) {
868 ERR("Log levels are only applicable to tracepoint event rules.");
869 goto error;
870 }
871
872 /* Finally, create the event rule object. */
873 switch (event_rule_type) {
874 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
875 {
876 enum lttng_event_rule_status event_rule_status;
877
878 res.er = lttng_event_rule_tracepoint_create(domain_type);
879 if (!res.er) {
880 ERR("Failed to create tracepoint event rule.");
881 goto error;
882 }
883
884 /* Set pattern. */
885 event_rule_status = lttng_event_rule_tracepoint_set_pattern(
886 res.er, tracepoint_name);
887 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
888 ERR("Failed to set tracepoint event rule's pattern to '%s'.",
889 tracepoint_name);
890 goto error;
891 }
892
893 /* Set filter. */
894 if (filter) {
895 event_rule_status = lttng_event_rule_tracepoint_set_filter(
896 res.er, filter);
897 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
898 ERR("Failed to set tracepoint event rule's filter to '%s'.",
899 filter);
900 goto error;
901 }
902 }
903
904 /* Set exclusion list. */
905 if (exclusion_list) {
906 int n;
907
908 for (n = 0; exclusion_list[n]; n++) {
909 event_rule_status = lttng_event_rule_tracepoint_add_exclusion(
910 res.er,
911 exclusion_list[n]);
912 if (event_rule_status !=
913 LTTNG_EVENT_RULE_STATUS_OK) {
914 ERR("Failed to set tracepoint exclusion list element '%s'",
915 exclusion_list[n]);
916 goto error;
917 }
918 }
919 }
920
921 if (loglevel_str) {
922 int loglevel;
923
924 if (domain_type == LTTNG_DOMAIN_KERNEL) {
925 ERR("Log levels are not supported by the kernel tracer.");
926 goto error;
927 }
928
929 loglevel = parse_loglevel_string(
930 loglevel_str, domain_type);
931 if (loglevel < 0) {
932 ERR("Failed to parse `%s` as a log level.",
933 loglevel_str);
934 goto error;
935 }
936
937 if (loglevel_only) {
938 event_rule_status = lttng_event_rule_tracepoint_set_log_level(
939 res.er,
940 loglevel);
941 } else {
942 event_rule_status = lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
943 res.er,
944 loglevel);
945 }
946
947 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
948 ERR("Failed to set log level on event fule.");
949 goto error;
950 }
951 }
952
953 break;
954 }
955 case LTTNG_EVENT_RULE_TYPE_KPROBE:
956 {
957 int ret;
958 enum lttng_event_rule_status event_rule_status;
959
960 res.er = lttng_event_rule_kprobe_create();
961 if (!res.er) {
962 ERR("Failed to create kprobe event rule.");
963 goto error;
964 }
965
966 ret = parse_kernel_probe_opts(source, &kernel_probe_location);
967 if (ret) {
968 ERR("Failed to parse kernel probe location.");
969 goto error;
970 }
971
972 event_rule_status = lttng_event_rule_kprobe_set_name(res.er, tracepoint_name);
973 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
974 ERR("Failed to set kprobe event rule's name to '%s'.", tracepoint_name);
975 goto error;
976 }
977
978 assert(kernel_probe_location);
979 event_rule_status = lttng_event_rule_kprobe_set_location(res.er, kernel_probe_location);
980 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
981 ERR("Failed to set kprobe event rule's location.");
982 goto error;
983 }
984
985 break;
986 }
987 case LTTNG_EVENT_RULE_TYPE_UPROBE:
988 {
989 int ret;
990 enum lttng_event_rule_status event_rule_status;
991
992 ret = parse_userspace_probe_opts(
993 source, &userspace_probe_location);
994 if (ret) {
995 ERR("Failed to parse user space probe location.");
996 goto error;
997 }
998
999 res.er = lttng_event_rule_uprobe_create();
1000 if (!res.er) {
1001 ERR("Failed to create userspace probe event rule.");
1002 goto error;
1003 }
1004
1005 event_rule_status = lttng_event_rule_uprobe_set_location(
1006 res.er, userspace_probe_location);
1007 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1008 ERR("Failed to set user space probe event rule's location.");
1009 goto error;
1010 }
1011
1012 event_rule_status = lttng_event_rule_uprobe_set_name(
1013 res.er, tracepoint_name);
1014 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1015 ERR("Failed to set user space probe event rule's name to '%s'.",
1016 tracepoint_name);
1017 goto error;
1018 }
1019
1020 break;
1021 }
1022 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
1023 {
1024 enum lttng_event_rule_status event_rule_status;
1025
1026 res.er = lttng_event_rule_syscall_create();
1027 if (!res.er) {
1028 ERR("Failed to create syscall event rule.");
1029 goto error;
1030 }
1031
1032 event_rule_status = lttng_event_rule_syscall_set_pattern(
1033 res.er, tracepoint_name);
1034 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1035 ERR("Failed to set syscall event rule's pattern to '%s'.",
1036 tracepoint_name);
1037 goto error;
1038 }
1039
1040 if (filter) {
1041 event_rule_status = lttng_event_rule_syscall_set_filter(
1042 res.er, filter);
1043 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1044 ERR("Failed to set syscall event rule's filter to '%s'.",
1045 filter);
1046 goto error;
1047 }
1048 }
1049
1050 break;
1051 }
1052 default:
1053 abort();
1054 goto error;
1055 }
1056
1057 goto end;
1058
1059 error:
1060 lttng_event_rule_destroy(res.er);
1061 res.er = NULL;
1062 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
1063
1064 end:
1065 if (parser_ctx) {
1066 filter_parser_ctx_free(parser_ctx);
1067 }
1068
1069 lttng_event_expr_destroy(event_expr);
1070 argpar_item_destroy(item);
1071 free(error);
1072 argpar_state_destroy(state);
1073 free(filter);
1074 free(exclude);
1075 free(loglevel_str);
1076 free(source);
1077 strutils_free_null_terminated_array_of_strings(exclusion_list);
1078 lttng_kernel_probe_location_destroy(kernel_probe_location);
1079 lttng_userspace_probe_location_destroy(userspace_probe_location);
1080 return res;
1081 }
1082
1083 static
1084 struct lttng_condition *handle_condition_event(int *argc, const char ***argv)
1085 {
1086 struct parse_event_rule_res res;
1087 struct lttng_condition *c;
1088 size_t i;
1089
1090 res = parse_event_rule(argc, argv);
1091 if (!res.er) {
1092 c = NULL;
1093 goto error;
1094 }
1095
1096 c = lttng_condition_event_rule_create(res.er);
1097 lttng_event_rule_destroy(res.er);
1098 res.er = NULL;
1099 if (!c) {
1100 goto error;
1101 }
1102
1103 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&res.capture_descriptors);
1104 i++) {
1105 enum lttng_condition_status status;
1106 struct lttng_event_expr **expr =
1107 lttng_dynamic_array_get_element(
1108 &res.capture_descriptors.array, i);
1109
1110 assert(expr);
1111 assert(*expr);
1112 status = lttng_condition_event_rule_append_capture_descriptor(
1113 c, *expr);
1114 if (status != LTTNG_CONDITION_STATUS_OK) {
1115 goto error;
1116 }
1117
1118 /* Ownership of event expression moved to `c` */
1119 *expr = NULL;
1120 }
1121
1122 goto end;
1123
1124 error:
1125 lttng_condition_destroy(c);
1126 c = NULL;
1127
1128 end:
1129 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
1130 lttng_event_rule_destroy(res.er);
1131 return c;
1132 }
1133
1134 static
1135 struct lttng_condition *handle_condition_session_consumed_size(int *argc, const char ***argv)
1136 {
1137 struct lttng_condition *cond = NULL;
1138 struct argpar_state *state = NULL;
1139 struct argpar_item *item = NULL;
1140 const char *threshold_arg = NULL;
1141 const char *session_name_arg = NULL;
1142 uint64_t threshold;
1143 char *error = NULL;
1144 enum lttng_condition_status condition_status;
1145
1146 state = argpar_state_create(*argc, *argv, event_rule_opt_descrs);
1147 if (!state) {
1148 ERR("Failed to allocate an argpar state.");
1149 goto error;
1150 }
1151
1152 while (true) {
1153 enum argpar_state_parse_next_status status;
1154
1155 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1156 status = argpar_state_parse_next(state, &item, &error);
1157 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1158 ERR("%s", error);
1159 goto error;
1160 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1161 /* Just stop parsing here. */
1162 break;
1163 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1164 break;
1165 }
1166
1167 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1168
1169 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1170 const struct argpar_item_opt *item_opt =
1171 (const struct argpar_item_opt *) item;
1172
1173 switch (item_opt->descr->id) {
1174 default:
1175 abort();
1176 }
1177 } else {
1178 const struct argpar_item_non_opt *item_non_opt;
1179
1180 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1181
1182 item_non_opt = (const struct argpar_item_non_opt *) item;
1183
1184 switch (item_non_opt->non_opt_index) {
1185 case 0:
1186 session_name_arg = item_non_opt->arg;
1187 break;
1188 case 1:
1189 threshold_arg = item_non_opt->arg;
1190 break;
1191 default:
1192 ERR("Unexpected argument `%s`.",
1193 item_non_opt->arg);
1194 goto error;
1195 }
1196 }
1197 }
1198
1199 *argc -= argpar_state_get_ingested_orig_args(state);
1200 *argv += argpar_state_get_ingested_orig_args(state);
1201
1202 if (!session_name_arg) {
1203 ERR("Missing session name argument.");
1204 goto error;
1205 }
1206
1207 if (!threshold_arg) {
1208 ERR("Missing threshold argument.");
1209 goto error;
1210 }
1211
1212 if (utils_parse_size_suffix(threshold_arg, &threshold) != 0) {
1213 ERR("Failed to parse `%s` as a size.", threshold_arg);
1214 goto error;
1215 }
1216
1217 cond = lttng_condition_session_consumed_size_create();
1218 if (!cond) {
1219 ERR("Failed to allocate a session consumed size condition.");
1220 goto error;
1221 }
1222
1223 condition_status = lttng_condition_session_consumed_size_set_session_name(
1224 cond, session_name_arg);
1225 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1226 ERR("Failed to set session consumed size condition's session name to '%s'.",
1227 session_name_arg);
1228 goto error;
1229 }
1230
1231 condition_status = lttng_condition_session_consumed_size_set_threshold(
1232 cond, threshold);
1233 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1234 ERR("Failed to set session consumed size condition threshold.");
1235 goto error;
1236 }
1237
1238 goto end;
1239
1240 error:
1241 lttng_condition_destroy(cond);
1242 cond = NULL;
1243
1244 end:
1245 argpar_state_destroy(state);
1246 argpar_item_destroy(item);
1247 free(error);
1248 return cond;
1249 }
1250
1251 static
1252 struct lttng_condition *handle_condition_buffer_usage_high(int *argc, const char ***argv)
1253 {
1254 ERR("High buffer usage threshold conditions are unsupported for the moment.");
1255 return NULL;
1256 }
1257
1258 static
1259 struct lttng_condition *handle_condition_buffer_usage_low(int *argc, const char ***argv)
1260 {
1261 ERR("Low buffer usage threshold conditions are unsupported for the moment.");
1262 return NULL;
1263 }
1264
1265 static
1266 struct lttng_condition *handle_condition_session_rotation_ongoing(int *argc, const char ***argv)
1267 {
1268 ERR("Session rotation ongoing conditions are unsupported for the moment.");
1269 return NULL;
1270 }
1271
1272 static
1273 struct lttng_condition *handle_condition_session_rotation_completed(int *argc, const char ***argv)
1274 {
1275 ERR("Session rotation completed conditions are unsupported for the moment.");
1276 return NULL;
1277 }
1278
1279 struct condition_descr {
1280 const char *name;
1281 struct lttng_condition *(*handler) (int *argc, const char ***argv);
1282 };
1283
1284 static const
1285 struct condition_descr condition_descrs[] = {
1286 { "on-event", handle_condition_event },
1287 { "on-session-consumed-size", handle_condition_session_consumed_size },
1288 { "on-buffer-usage-high", handle_condition_buffer_usage_high },
1289 { "on-buffer-usage-low", handle_condition_buffer_usage_low },
1290 { "on-session-rotation-ongoing", handle_condition_session_rotation_ongoing },
1291 { "on-session-rotation-completed", handle_condition_session_rotation_completed },
1292 };
1293
1294 static
1295 struct lttng_condition *parse_condition(int *argc, const char ***argv)
1296 {
1297 int i;
1298 struct lttng_condition *cond;
1299 const char *condition_name;
1300 const struct condition_descr *descr = NULL;
1301
1302 if (*argc == 0) {
1303 ERR("Missing condition name.");
1304 goto error;
1305 }
1306
1307 condition_name = (*argv)[0];
1308
1309 (*argc)--;
1310 (*argv)++;
1311
1312 for (i = 0; i < ARRAY_SIZE(condition_descrs); i++) {
1313 if (strcmp(condition_name, condition_descrs[i].name) == 0) {
1314 descr = &condition_descrs[i];
1315 break;
1316 }
1317 }
1318
1319 if (!descr) {
1320 ERR("Unknown condition name '%s'", condition_name);
1321 goto error;
1322 }
1323
1324 cond = descr->handler(argc, argv);
1325 if (!cond) {
1326 /* The handler has already printed an error message. */
1327 goto error;
1328 }
1329
1330 goto end;
1331 error:
1332 cond = NULL;
1333 end:
1334 return cond;
1335 }
1336
1337
1338 static
1339 struct lttng_action *handle_action_notify(int *argc, const char ***argv)
1340 {
1341 return lttng_action_notify_create();
1342 }
1343
1344 static const struct argpar_opt_descr no_opt_descrs[] = {
1345 ARGPAR_OPT_DESCR_SENTINEL
1346 };
1347
1348 /*
1349 * Generic handler for a kind of action that takes a session name as its sole
1350 * argument.
1351 */
1352
1353 static
1354 struct lttng_action *handle_action_simple_session(
1355 int *argc, const char ***argv,
1356 struct lttng_action *(*create_action_cb)(void),
1357 enum lttng_action_status (*set_session_name_cb)(struct lttng_action *, const char *),
1358 const char *action_name)
1359 {
1360 struct lttng_action *action = NULL;
1361 struct argpar_state *state = NULL;
1362 struct argpar_item *item = NULL;
1363 const char *session_name_arg = NULL;
1364 char *error = NULL;
1365 enum lttng_action_status action_status;
1366
1367 state = argpar_state_create(*argc, *argv, no_opt_descrs);
1368 if (!state) {
1369 ERR("Failed to allocate an argpar state.");
1370 goto error;
1371 }
1372
1373 while (true) {
1374 enum argpar_state_parse_next_status status;
1375 const struct argpar_item_non_opt *item_non_opt;
1376
1377 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1378 status = argpar_state_parse_next(state, &item, &error);
1379 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1380 ERR("%s", error);
1381 goto error;
1382 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1383 /* Just stop parsing here. */
1384 break;
1385 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1386 break;
1387 }
1388
1389 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1390 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1391
1392 item_non_opt = (const struct argpar_item_non_opt *) item;
1393
1394 switch (item_non_opt->non_opt_index) {
1395 case 0:
1396 session_name_arg = item_non_opt->arg;
1397 break;
1398 default:
1399 ERR("Unexpected argument `%s`.", item_non_opt->arg);
1400 goto error;
1401 }
1402 }
1403
1404 *argc -= argpar_state_get_ingested_orig_args(state);
1405 *argv += argpar_state_get_ingested_orig_args(state);
1406
1407 if (!session_name_arg) {
1408 ERR("Missing session name.");
1409 goto error;
1410 }
1411
1412 action = create_action_cb();
1413 if (!action) {
1414 ERR("Failed to allocate %s session action.", action_name);
1415 goto error;
1416 }
1417
1418 action_status = set_session_name_cb(action, session_name_arg);
1419 if (action_status != LTTNG_ACTION_STATUS_OK) {
1420 ERR("Failed to set action %s session's session name to '%s'.",
1421 action_name, session_name_arg);
1422 goto error;
1423 }
1424
1425 goto end;
1426
1427 error:
1428 lttng_action_destroy(action);
1429 action = NULL;
1430 argpar_item_destroy(item);
1431 end:
1432 free(error);
1433 argpar_state_destroy(state);
1434 return action;
1435 }
1436
1437 static
1438 struct lttng_action *handle_action_start_session(int *argc,
1439 const char ***argv)
1440 {
1441 return handle_action_simple_session(argc, argv,
1442 lttng_action_start_session_create,
1443 lttng_action_start_session_set_session_name,
1444 "start");
1445 }
1446
1447 static
1448 struct lttng_action *handle_action_stop_session(int *argc,
1449 const char ***argv)
1450 {
1451 return handle_action_simple_session(argc, argv,
1452 lttng_action_stop_session_create,
1453 lttng_action_stop_session_set_session_name,
1454 "stop");
1455 }
1456
1457 static
1458 struct lttng_action *handle_action_rotate_session(int *argc,
1459 const char ***argv)
1460 {
1461 return handle_action_simple_session(argc, argv,
1462 lttng_action_rotate_session_create,
1463 lttng_action_rotate_session_set_session_name,
1464 "rotate");
1465 }
1466
1467 static const struct argpar_opt_descr snapshot_action_opt_descrs[] = {
1468 { OPT_NAME, 'n', "name", true },
1469 { OPT_MAX_SIZE, 'm', "max-size", true },
1470 { OPT_CTRL_URL, '\0', "ctrl-url", true },
1471 { OPT_DATA_URL, '\0', "data-url", true },
1472 { OPT_URL, '\0', "url", true },
1473 { OPT_PATH, '\0', "path", true },
1474 ARGPAR_OPT_DESCR_SENTINEL
1475 };
1476
1477 static
1478 struct lttng_action *handle_action_snapshot_session(int *argc,
1479 const char ***argv)
1480 {
1481 struct lttng_action *action = NULL;
1482 struct argpar_state *state = NULL;
1483 struct argpar_item *item = NULL;
1484 const char *session_name_arg = NULL;
1485 char *snapshot_name_arg = NULL;
1486 char *ctrl_url_arg = NULL;
1487 char *data_url_arg = NULL;
1488 char *max_size_arg = NULL;
1489 char *url_arg = NULL;
1490 char *path_arg = NULL;
1491 char *error = NULL;
1492 enum lttng_action_status action_status;
1493 struct lttng_snapshot_output *snapshot_output = NULL;
1494 int ret;
1495 unsigned int locations_specified = 0;
1496
1497 state = argpar_state_create(*argc, *argv, snapshot_action_opt_descrs);
1498 if (!state) {
1499 ERR("Failed to allocate an argpar state.");
1500 goto error;
1501 }
1502
1503 while (true) {
1504 enum argpar_state_parse_next_status status;
1505
1506 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1507 status = argpar_state_parse_next(state, &item, &error);
1508 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1509 ERR("%s", error);
1510 goto error;
1511 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1512 /* Just stop parsing here. */
1513 break;
1514 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1515 break;
1516 }
1517
1518 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1519
1520 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1521 const struct argpar_item_opt *item_opt =
1522 (const struct argpar_item_opt *) item;
1523
1524 switch (item_opt->descr->id) {
1525 case OPT_NAME:
1526 if (!assign_string(&snapshot_name_arg, item_opt->arg, "--name/-n")) {
1527 goto error;
1528 }
1529
1530 break;
1531 case OPT_MAX_SIZE:
1532 if (!assign_string(&max_size_arg, item_opt->arg, "--max-size/-m")) {
1533 goto error;
1534 }
1535
1536 break;
1537 case OPT_CTRL_URL:
1538 if (!assign_string(&ctrl_url_arg, item_opt->arg, "--ctrl-url")) {
1539 goto error;
1540 }
1541
1542 break;
1543 case OPT_DATA_URL:
1544 if (!assign_string(&data_url_arg, item_opt->arg, "--data-url")) {
1545 goto error;
1546 }
1547
1548 break;
1549 case OPT_URL:
1550 if (!assign_string(&url_arg, item_opt->arg, "--url")) {
1551 goto error;
1552 }
1553
1554 break;
1555 case OPT_PATH:
1556 if (!assign_string(&path_arg, item_opt->arg, "--path")) {
1557 goto error;
1558 }
1559
1560 break;
1561 default:
1562 abort();
1563 }
1564 } else {
1565 const struct argpar_item_non_opt *item_non_opt;
1566
1567 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1568
1569 item_non_opt = (const struct argpar_item_non_opt *) item;
1570
1571 switch (item_non_opt->non_opt_index) {
1572 case 0:
1573 session_name_arg = item_non_opt->arg;
1574 break;
1575 default:
1576 ERR("Unexpected argument `%s`.",
1577 item_non_opt->arg);
1578 goto error;
1579 }
1580 }
1581 }
1582
1583 *argc -= argpar_state_get_ingested_orig_args(state);
1584 *argv += argpar_state_get_ingested_orig_args(state);
1585
1586 if (!session_name_arg) {
1587 ERR("Missing session name.");
1588 goto error;
1589 }
1590
1591 /* --ctrl-url and --data-url must come in pair. */
1592 if (ctrl_url_arg && !data_url_arg) {
1593 ERR("--ctrl-url is specified, but --data-url is missing.");
1594 goto error;
1595 }
1596
1597 if (!ctrl_url_arg && data_url_arg) {
1598 ERR("--data-url is specified, but --ctrl-url is missing.");
1599 goto error;
1600 }
1601
1602 locations_specified += !!(ctrl_url_arg || data_url_arg);
1603 locations_specified += !!url_arg;
1604 locations_specified += !!path_arg;
1605
1606 /* --ctrl-url/--data-url, --url and --path are mutually exclusive. */
1607 if (locations_specified > 1) {
1608 ERR("The --ctrl-url/--data-url, --url, and --path options can't be used together.");
1609 goto error;
1610 }
1611
1612 /*
1613 * Did the user specify an option that implies using a
1614 * custom/unregistered output?
1615 */
1616 if (url_arg || ctrl_url_arg || path_arg) {
1617 snapshot_output = lttng_snapshot_output_create();
1618 if (!snapshot_output) {
1619 ERR("Failed to allocate a snapshot output.");
1620 goto error;
1621 }
1622 }
1623
1624 action = lttng_action_snapshot_session_create();
1625 if (!action) {
1626 ERR("Failed to allocate snapshot session action.");
1627 goto error;
1628 }
1629
1630 action_status = lttng_action_snapshot_session_set_session_name(
1631 action, session_name_arg);
1632 if (action_status != LTTNG_ACTION_STATUS_OK) {
1633 ERR("Failed to set action snapshot session's session name to '%s'.",
1634 session_name_arg);
1635 goto error;
1636 }
1637
1638 if (snapshot_name_arg) {
1639 if (!snapshot_output) {
1640 ERR("Can't provide a snapshot output name without a snapshot output destination.");
1641 goto error;
1642 }
1643
1644 ret = lttng_snapshot_output_set_name(
1645 snapshot_name_arg, snapshot_output);
1646 if (ret != 0) {
1647 ERR("Failed to set name of snapshot output.");
1648 goto error;
1649 }
1650 }
1651
1652 if (max_size_arg) {
1653 uint64_t max_size;
1654
1655 if (!snapshot_output) {
1656 ERR("Can't provide a snapshot output max size without a snapshot output destination.");
1657 goto error;
1658 }
1659
1660 ret = utils_parse_size_suffix(max_size_arg, &max_size);
1661 if (ret != 0) {
1662 ERR("Failed to parse `%s` as a size.", max_size_arg);
1663 goto error;
1664 }
1665
1666 ret = lttng_snapshot_output_set_size(max_size, snapshot_output);
1667 if (ret != 0) {
1668 ERR("Failed to set snapshot output's max size to %" PRIu64 " bytes.",
1669 max_size);
1670 goto error;
1671 }
1672 }
1673
1674 if (url_arg) {
1675 int num_uris;
1676 struct lttng_uri *uris;
1677
1678 if (!strstr(url_arg, "://")) {
1679 ERR("Failed to parse '%s' as an URL.", url_arg);
1680 goto error;
1681 }
1682
1683 num_uris = uri_parse_str_urls(url_arg, NULL, &uris);
1684 if (num_uris < 1) {
1685 ERR("Failed to parse '%s' as an URL.", url_arg);
1686 goto error;
1687 }
1688
1689 if (uris[0].dtype == LTTNG_DST_PATH) {
1690 ret = lttng_snapshot_output_set_local_path(
1691 uris[0].dst.path, snapshot_output);
1692 free(uris);
1693 if (ret != 0) {
1694 ERR("Failed to assign '%s' as a local destination.",
1695 url_arg);
1696 goto error;
1697 }
1698 } else {
1699 ret = lttng_snapshot_output_set_network_url(
1700 url_arg, snapshot_output);
1701 free(uris);
1702 if (ret != 0) {
1703 ERR("Failed to assign '%s' as a network URL.",
1704 url_arg);
1705 goto error;
1706 }
1707 }
1708 }
1709
1710 if (path_arg) {
1711 ret = lttng_snapshot_output_set_local_path(
1712 path_arg, snapshot_output);
1713 if (ret != 0) {
1714 ERR("Failed to parse '%s' as a local path.", path_arg);
1715 goto error;
1716 }
1717 }
1718
1719 if (ctrl_url_arg) {
1720 /*
1721 * Two argument form, network output with separate control and
1722 * data URLs.
1723 */
1724 ret = lttng_snapshot_output_set_network_urls(
1725 ctrl_url_arg, data_url_arg, snapshot_output);
1726 if (ret != 0) {
1727 ERR("Failed to parse `%s` and `%s` as control and data URLs.",
1728 ctrl_url_arg, data_url_arg);
1729 goto error;
1730 }
1731 }
1732
1733 if (snapshot_output) {
1734 action_status = lttng_action_snapshot_session_set_output(
1735 action, snapshot_output);
1736 if (action_status != LTTNG_ACTION_STATUS_OK) {
1737 ERR("Failed to set snapshot session action's output.");
1738 goto error;
1739 }
1740
1741 /* Ownership of `snapshot_output` has been transferred to the action. */
1742 snapshot_output = NULL;
1743 }
1744
1745 goto end;
1746
1747 error:
1748 lttng_action_destroy(action);
1749 action = NULL;
1750 free(error);
1751 end:
1752 free(snapshot_name_arg);
1753 free(path_arg);
1754 free(url_arg);
1755 free(ctrl_url_arg);
1756 free(data_url_arg);
1757 free(snapshot_output);
1758 free(max_size_arg);
1759 argpar_state_destroy(state);
1760 argpar_item_destroy(item);
1761 return action;
1762 }
1763
1764 struct action_descr {
1765 const char *name;
1766 struct lttng_action *(*handler) (int *argc, const char ***argv);
1767 };
1768
1769 static const
1770 struct action_descr action_descrs[] = {
1771 { "notify", handle_action_notify },
1772 { "start-session", handle_action_start_session },
1773 { "stop-session", handle_action_stop_session },
1774 { "rotate-session", handle_action_rotate_session },
1775 { "snapshot-session", handle_action_snapshot_session },
1776 };
1777
1778 static
1779 struct lttng_action *parse_action(int *argc, const char ***argv)
1780 {
1781 int i;
1782 struct lttng_action *action;
1783 const char *action_name;
1784 const struct action_descr *descr = NULL;
1785
1786 if (*argc == 0) {
1787 ERR("Missing action name.");
1788 goto error;
1789 }
1790
1791 action_name = (*argv)[0];
1792
1793 (*argc)--;
1794 (*argv)++;
1795
1796 for (i = 0; i < ARRAY_SIZE(action_descrs); i++) {
1797 if (strcmp(action_name, action_descrs[i].name) == 0) {
1798 descr = &action_descrs[i];
1799 break;
1800 }
1801 }
1802
1803 if (!descr) {
1804 ERR("Unknown action name: %s", action_name);
1805 goto error;
1806 }
1807
1808 action = descr->handler(argc, argv);
1809 if (!action) {
1810 /* The handler has already printed an error message. */
1811 goto error;
1812 }
1813
1814 goto end;
1815 error:
1816 action = NULL;
1817 end:
1818 return action;
1819 }
1820
1821 static const
1822 struct argpar_opt_descr add_trigger_options[] = {
1823 { OPT_HELP, 'h', "help", false },
1824 { OPT_LIST_OPTIONS, '\0', "list-options", false },
1825 { OPT_CONDITION, '\0', "condition", false },
1826 { OPT_ACTION, '\0', "action", false },
1827 { OPT_ID, '\0', "id", true },
1828 { OPT_FIRE_ONCE_AFTER, '\0', "fire-once-after", true },
1829 { OPT_FIRE_EVERY, '\0', "fire-every", true },
1830 { OPT_USER_ID, '\0', "user-id", true },
1831 ARGPAR_OPT_DESCR_SENTINEL,
1832 };
1833
1834 static
1835 void lttng_actions_destructor(void *p)
1836 {
1837 struct lttng_action *action = p;
1838
1839 lttng_action_destroy(action);
1840 }
1841
1842 int cmd_add_trigger(int argc, const char **argv)
1843 {
1844 int ret;
1845 int my_argc = argc - 1;
1846 const char **my_argv = argv + 1;
1847 struct lttng_condition *condition = NULL;
1848 struct lttng_dynamic_pointer_array actions;
1849 struct argpar_state *argpar_state = NULL;
1850 struct argpar_item *argpar_item = NULL;
1851 struct lttng_action *action_group = NULL;
1852 struct lttng_action *action = NULL;
1853 struct lttng_trigger *trigger = NULL;
1854 char *error = NULL;
1855 char *id = NULL;
1856 int i;
1857 char *fire_once_after_str = NULL;
1858 char *fire_every_str = NULL;
1859 char *user_id = NULL;
1860
1861 lttng_dynamic_pointer_array_init(&actions, lttng_actions_destructor);
1862
1863 while (true) {
1864 enum argpar_state_parse_next_status status;
1865 const struct argpar_item_opt *item_opt;
1866 int ingested_args;
1867
1868 argpar_state_destroy(argpar_state);
1869 argpar_state = argpar_state_create(my_argc, my_argv,
1870 add_trigger_options);
1871 if (!argpar_state) {
1872 ERR("Failed to create argpar state.");
1873 goto error;
1874 }
1875
1876 ARGPAR_ITEM_DESTROY_AND_RESET(argpar_item);
1877 status = argpar_state_parse_next(argpar_state, &argpar_item, &error);
1878 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1879 ERR("%s", error);
1880 goto error;
1881 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1882 ERR("%s", error);
1883 goto error;
1884 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1885 break;
1886 }
1887
1888 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1889
1890 if (argpar_item->type == ARGPAR_ITEM_TYPE_NON_OPT) {
1891 const struct argpar_item_non_opt *item_non_opt =
1892 (const struct argpar_item_non_opt *)
1893 argpar_item;
1894
1895 ERR("Unexpected argument `%s`.", item_non_opt->arg);
1896 goto error;
1897 }
1898
1899 item_opt = (const struct argpar_item_opt *) argpar_item;
1900
1901 ingested_args = argpar_state_get_ingested_orig_args(
1902 argpar_state);
1903
1904 my_argc -= ingested_args;
1905 my_argv += ingested_args;
1906
1907 switch (item_opt->descr->id) {
1908 case OPT_HELP:
1909 SHOW_HELP();
1910 ret = 0;
1911 goto end;
1912 case OPT_LIST_OPTIONS:
1913 list_cmd_options_argpar(stdout, add_trigger_options);
1914 ret = 0;
1915 goto end;
1916 case OPT_CONDITION:
1917 {
1918 if (condition) {
1919 ERR("A --condition was already given.");
1920 goto error;
1921 }
1922
1923 condition = parse_condition(&my_argc, &my_argv);
1924 if (!condition) {
1925 /*
1926 * An error message was already printed by
1927 * parse_condition.
1928 */
1929 goto error;
1930 }
1931
1932 break;
1933 }
1934 case OPT_ACTION:
1935 {
1936 action = parse_action(&my_argc, &my_argv);
1937 if (!action) {
1938 /*
1939 * An error message was already printed by
1940 * parse_condition.
1941 */
1942 goto error;
1943 }
1944
1945 ret = lttng_dynamic_pointer_array_add_pointer(
1946 &actions, action);
1947 if (ret) {
1948 ERR("Failed to add pointer to pointer array.");
1949 goto error;
1950 }
1951
1952 /* Ownership of the action was transferred to the group. */
1953 action = NULL;
1954
1955 break;
1956 }
1957 case OPT_ID:
1958 {
1959 if (!assign_string(&id, item_opt->arg, "--id")) {
1960 goto error;
1961 }
1962
1963 break;
1964 }
1965 case OPT_FIRE_ONCE_AFTER:
1966 {
1967 if (!assign_string(&fire_once_after_str, item_opt->arg,
1968 "--fire-once-after")) {
1969 goto error;
1970 }
1971
1972 break;
1973 }
1974 case OPT_FIRE_EVERY:
1975 {
1976 if (!assign_string(&fire_every_str, item_opt->arg,
1977 "--fire-every")) {
1978 goto error;
1979 }
1980
1981 break;
1982 }
1983 case OPT_USER_ID:
1984 {
1985 if (!assign_string(&user_id, item_opt->arg,
1986 "--user-id")) {
1987 goto error;
1988 }
1989
1990 break;
1991 }
1992 default:
1993 abort();
1994 }
1995 }
1996
1997 if (!condition) {
1998 ERR("Missing --condition.");
1999 goto error;
2000 }
2001
2002 if (lttng_dynamic_pointer_array_get_count(&actions) == 0) {
2003 ERR("Need at least one --action.");
2004 goto error;
2005 }
2006
2007 if (fire_every_str && fire_once_after_str) {
2008 ERR("Can't specify both --fire-once-after and --fire-every.");
2009 goto error;
2010 }
2011
2012 action_group = lttng_action_group_create();
2013 if (!action_group) {
2014 goto error;
2015 }
2016
2017 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&actions); i++) {
2018 enum lttng_action_status status;
2019
2020 action = lttng_dynamic_pointer_array_steal_pointer(&actions, i);
2021
2022 status = lttng_action_group_add_action(action_group, action);
2023 if (status != LTTNG_ACTION_STATUS_OK) {
2024 goto error;
2025 }
2026
2027 /*
2028 * The `lttng_action_group_add_action()` takes a reference to
2029 * the action. We can destroy ours.
2030 */
2031 lttng_action_destroy(action);
2032 action = NULL;
2033 }
2034
2035 trigger = lttng_trigger_create(condition, action_group);
2036 if (!trigger) {
2037 goto error;
2038 }
2039
2040 if (id) {
2041 enum lttng_trigger_status trigger_status =
2042 lttng_trigger_set_name(trigger, id);
2043
2044 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2045 ERR("Failed to set trigger id.");
2046 goto error;
2047 }
2048 }
2049
2050 if (fire_once_after_str) {
2051 unsigned long long threshold;
2052 enum lttng_trigger_status trigger_status;
2053
2054 if (utils_parse_unsigned_long_long(fire_once_after_str, &threshold) != 0) {
2055 ERR("Failed to parse `%s` as an integer.", fire_once_after_str);
2056 goto error;
2057 }
2058
2059 trigger_status = lttng_trigger_set_firing_policy(trigger,
2060 LTTNG_TRIGGER_FIRING_POLICY_ONCE_AFTER_N,
2061 threshold);
2062 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2063 ERR("Failed to set trigger's policy to `fire once after N`.");
2064 goto error;
2065 }
2066 }
2067
2068 if (fire_every_str) {
2069 unsigned long long threshold;
2070 enum lttng_trigger_status trigger_status;
2071
2072 if (utils_parse_unsigned_long_long(fire_every_str, &threshold) != 0) {
2073 ERR("Failed to parse `%s` as an integer.", fire_every_str);
2074 goto error;
2075 }
2076
2077 trigger_status = lttng_trigger_set_firing_policy(trigger,
2078 LTTNG_TRIGGER_FIRING_POLICY_EVERY_N, threshold);
2079 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2080 ERR("Failed to set trigger's policy to `fire every N`.");
2081 goto error;
2082 }
2083 }
2084
2085 if (user_id) {
2086 enum lttng_trigger_status trigger_status;
2087 char *end;
2088 long long uid;
2089
2090 errno = 0;
2091 uid = strtol(user_id, &end, 10);
2092 if (end == user_id || *end != '\0' || errno != 0) {
2093 ERR("Failed to parse `%s` as a user id.", user_id);
2094 }
2095
2096 trigger_status = lttng_trigger_set_owner_uid(trigger, uid);
2097 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2098 ERR("Failed to set trigger's user identity.");
2099 goto error;
2100 }
2101 }
2102
2103 ret = lttng_register_trigger(trigger);
2104 if (ret) {
2105 ERR("Failed to register trigger: %s.", lttng_strerror(ret));
2106 goto error;
2107 }
2108
2109 MSG("Trigger registered successfully.");
2110
2111 goto end;
2112
2113 error:
2114 ret = 1;
2115
2116 end:
2117 argpar_state_destroy(argpar_state);
2118 argpar_item_destroy(argpar_item);
2119 lttng_dynamic_pointer_array_reset(&actions);
2120 lttng_condition_destroy(condition);
2121 lttng_action_destroy(action_group);
2122 lttng_action_destroy(action);
2123 lttng_trigger_destroy(trigger);
2124 free(error);
2125 free(id);
2126 free(fire_once_after_str);
2127 free(fire_every_str);
2128 free(user_id);
2129 return ret;
2130 }
This page took 0.128655 seconds and 3 git commands to generate.