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