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