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