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