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