2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/error.h>
10 #include <common/macros.h>
11 #include <common/runas.h>
12 #include <lttng/event-rule/event-rule-internal.h>
13 #include <lttng/event-rule/tracepoint-internal.h>
14 #include <lttng/event.h>
16 #define IS_TRACEPOINT_EVENT_RULE(rule) \
17 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT)
19 static void lttng_event_rule_tracepoint_destroy(struct lttng_event_rule
*rule
)
21 struct lttng_event_rule_tracepoint
*tracepoint
;
27 tracepoint
= container_of(
28 rule
, struct lttng_event_rule_tracepoint
, parent
);
30 free(tracepoint
->pattern
);
31 free(tracepoint
->filter_expression
);
32 for (int i
= 0; i
< tracepoint
->exclusions
.count
; i
++) {
33 free(tracepoint
->exclusions
.values
[i
]);
35 free(tracepoint
->exclusions
.values
);
36 free(tracepoint
->internal_filter
.filter
);
37 free(tracepoint
->internal_filter
.bytecode
);
41 static bool lttng_event_rule_tracepoint_validate(
42 const struct lttng_event_rule
*rule
)
45 struct lttng_event_rule_tracepoint
*tracepoint
;
51 tracepoint
= container_of(
52 rule
, struct lttng_event_rule_tracepoint
, parent
);
55 if (!tracepoint
->pattern
) {
56 ERR("Invalid tracepoint event rule: a pattern must be set.");
59 if (tracepoint
->domain
== LTTNG_DOMAIN_NONE
) {
60 ERR("Invalid tracepoint event rule: a domain must be set.");
64 /* QUESTION: do we validate inside state on validate or during set of
72 static int lttng_event_rule_tracepoint_serialize(
73 const struct lttng_event_rule
*rule
,
74 struct lttng_dynamic_buffer
*buf
,
78 size_t pattern_len
, filter_expression_len
, exclusions_len
;
79 struct lttng_event_rule_tracepoint
*tracepoint
;
80 struct lttng_event_rule_tracepoint_comm tracepoint_comm
;
82 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
87 DBG("Serializing tracepoint event rule");
88 tracepoint
= container_of(
89 rule
, struct lttng_event_rule_tracepoint
, parent
);
91 pattern_len
= strlen(tracepoint
->pattern
) + 1;
93 if (tracepoint
->filter_expression
!= NULL
) {
94 filter_expression_len
=
95 strlen(tracepoint
->filter_expression
) + 1;
97 filter_expression_len
= 0;
101 for (int i
= 0; i
< tracepoint
->exclusions
.count
; i
++) {
103 exclusions_len
+= strlen(tracepoint
->exclusions
.values
[i
]) + 1;
105 exclusions_len
+= sizeof(uint32_t);
108 tracepoint_comm
.domain_type
= (int8_t) tracepoint
->domain
;
109 tracepoint_comm
.loglevel_type
= (int8_t) tracepoint
->loglevel
.type
;
110 tracepoint_comm
.loglevel_value
= tracepoint
->loglevel
.value
;
111 tracepoint_comm
.pattern_len
= pattern_len
;
112 tracepoint_comm
.filter_expression_len
= filter_expression_len
;
113 tracepoint_comm
.exclusions_count
= tracepoint
->exclusions
.count
;
114 tracepoint_comm
.exclusions_len
= exclusions_len
;
116 ret
= lttng_dynamic_buffer_append(
117 buf
, &tracepoint_comm
, sizeof(tracepoint_comm
));
121 ret
= lttng_dynamic_buffer_append(
122 buf
, tracepoint
->pattern
, pattern_len
);
126 ret
= lttng_dynamic_buffer_append(buf
, tracepoint
->filter_expression
,
127 filter_expression_len
);
132 size_t exclusions_appended
= 0;
133 for (int i
= 0; i
< tracepoint
->exclusions
.count
; i
++) {
135 len
= strlen(tracepoint
->exclusions
.values
[i
]) + 1;
136 /* Append bound check, does not include the '\0' */
137 ret
= lttng_dynamic_buffer_append(buf
, &len
, sizeof(uint32_t));
141 exclusions_appended
+= sizeof(uint32_t);
143 /* Include the '\0' in the payload */
144 ret
= lttng_dynamic_buffer_append(
145 buf
, tracepoint
->exclusions
.values
[i
], len
);
149 exclusions_appended
+= len
;
152 assert(exclusions_len
== exclusions_appended
);
163 static bool lttng_event_rule_tracepoint_is_equal(
164 const struct lttng_event_rule
*_a
,
165 const struct lttng_event_rule
*_b
)
167 bool is_equal
= false;
168 struct lttng_event_rule_tracepoint
*a
, *b
;
170 a
= container_of(_a
, struct lttng_event_rule_tracepoint
, parent
);
171 b
= container_of(_b
, struct lttng_event_rule_tracepoint
, parent
);
174 if (a
->domain
!= b
->domain
) {
178 if (a
->exclusions
.count
!= b
->exclusions
.count
) {
182 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
187 /* Tracepoint is invalid if this is not true */
190 if (strcmp(a
->pattern
, b
->pattern
)) {
194 if (a
->filter_expression
&& b
->filter_expression
) {
195 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
200 if (a
->loglevel
.type
!= b
->loglevel
.type
) {
204 if (a
->loglevel
.value
!= b
->loglevel
.value
) {
208 for (int i
= 0; i
< a
->exclusions
.count
; i
++) {
209 if (strcmp(a
->exclusions
.values
[i
], b
->exclusions
.values
[i
])) {
220 * On success ret is 0;
222 * On error ret is negative.
224 * An event with NO loglevel and the name is * will return NULL.
226 static int generate_agent_filter(
227 const struct lttng_event_rule
*rule
, char **_agent_filter
)
231 char *agent_filter
= NULL
;
234 enum lttng_loglevel_type loglevel_type
;
235 enum lttng_event_rule_status status
;
238 assert(_agent_filter
);
240 status
= lttng_event_rule_tracepoint_get_pattern(rule
, &pattern
);
241 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
246 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
247 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
249 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
254 status
= lttng_event_rule_tracepoint_get_loglevel_type(
255 rule
, &loglevel_type
);
256 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
261 /* Don't add filter for the '*' event. */
262 if (strcmp(pattern
, "*") != 0) {
264 err
= asprintf(&agent_filter
,
265 "(%s) && (logger_name == \"%s\")",
268 err
= asprintf(&agent_filter
, "logger_name == \"%s\"",
278 if (loglevel_type
!= LTTNG_EVENT_LOGLEVEL_ALL
) {
282 status
= lttng_event_rule_tracepoint_get_loglevel(
283 rule
, &loglevel_value
);
284 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
289 if (loglevel_type
== LTTNG_EVENT_LOGLEVEL_RANGE
) {
295 if (filter
|| agent_filter
) {
298 err
= asprintf(&new_filter
,
299 "(%s) && (int_loglevel %s %d)",
300 agent_filter
? agent_filter
: filter
,
305 agent_filter
= new_filter
;
307 err
= asprintf(&agent_filter
, "int_loglevel %s %d", op
,
317 *_agent_filter
= agent_filter
;
325 static enum lttng_error_code
lttng_event_rule_tracepoint_populate(
326 struct lttng_event_rule
*rule
, uid_t uid
, gid_t gid
)
329 enum lttng_error_code ret_code
;
330 struct lttng_event_rule_tracepoint
*tracepoint
;
331 enum lttng_domain_type domain_type
;
332 enum lttng_event_rule_status status
;
334 struct lttng_bytecode
*bytecode
= NULL
;
338 tracepoint
= container_of(
339 rule
, struct lttng_event_rule_tracepoint
, parent
);
341 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
342 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
344 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
345 ret_code
= LTTNG_ERR_FILTER_INVAL
;
349 if (filter
&& filter
[0] == '\0') {
350 ret_code
= LTTNG_ERR_FILTER_INVAL
;
354 status
= lttng_event_rule_tracepoint_get_domain_type(
356 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
357 ret_code
= LTTNG_ERR_UNK
;
361 switch (domain_type
) {
362 case LTTNG_DOMAIN_LOG4J
:
363 case LTTNG_DOMAIN_JUL
:
364 case LTTNG_DOMAIN_PYTHON
:
367 ret
= generate_agent_filter(rule
, &agent_filter
);
369 ret_code
= LTTNG_ERR_FILTER_INVAL
;
372 tracepoint
->internal_filter
.filter
= agent_filter
;
378 tracepoint
->internal_filter
.filter
= strdup(filter
);
379 if (tracepoint
->internal_filter
.filter
== NULL
) {
380 ret_code
= LTTNG_ERR_NOMEM
;
384 tracepoint
->internal_filter
.filter
= NULL
;
390 if (tracepoint
->internal_filter
.filter
== NULL
) {
395 ret
= run_as_generate_filter_bytecode(
396 tracepoint
->internal_filter
.filter
, uid
, gid
,
399 ret_code
= LTTNG_ERR_FILTER_INVAL
;
403 tracepoint
->internal_filter
.bytecode
= bytecode
;
413 static const char *lttng_event_rule_tracepoint_get_internal_filter(
414 const struct lttng_event_rule
*rule
)
416 struct lttng_event_rule_tracepoint
*tracepoint
;
419 tracepoint
= container_of(
420 rule
, struct lttng_event_rule_tracepoint
, parent
);
421 return tracepoint
->internal_filter
.filter
;
424 static const struct lttng_bytecode
*
425 lttng_event_rule_tracepoint_get_internal_filter_bytecode(
426 const struct lttng_event_rule
*rule
)
428 struct lttng_event_rule_tracepoint
*tracepoint
;
431 tracepoint
= container_of(
432 rule
, struct lttng_event_rule_tracepoint
, parent
);
433 return tracepoint
->internal_filter
.bytecode
;
436 /* TODO: review error handling, the function should be able to
437 * return error information.
439 static struct lttng_event_exclusion
*
440 lttng_event_rule_tracepoint_generate_exclusions(struct lttng_event_rule
*rule
)
442 enum lttng_domain_type domain_type
= LTTNG_DOMAIN_NONE
;
443 struct lttng_event_exclusion
*local_exclusions
= NULL
;
444 struct lttng_event_exclusion
*ret_exclusions
= NULL
;
445 unsigned int nb_exclusions
= 0;
447 (void) lttng_event_rule_tracepoint_get_domain_type(rule
, &domain_type
);
449 switch (domain_type
) {
450 case LTTNG_DOMAIN_KERNEL
:
451 case LTTNG_DOMAIN_JUL
:
452 case LTTNG_DOMAIN_LOG4J
:
453 case LTTNG_DOMAIN_PYTHON
:
455 ret_exclusions
= NULL
;
457 case LTTNG_DOMAIN_UST
:
458 /* Exclusions supported */
464 (void) lttng_event_rule_tracepoint_get_exclusions_count(
465 rule
, &nb_exclusions
);
466 if (nb_exclusions
== 0) {
468 ret_exclusions
= NULL
;
472 local_exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) +
473 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
474 if (!local_exclusions
) {
475 ERR("local exclusion allocation");
476 ret_exclusions
= NULL
;
480 local_exclusions
->count
= nb_exclusions
;
481 for (unsigned int i
= 0; i
< nb_exclusions
; i
++) {
482 /* TODO: check for truncation.
483 * Part of this should be validated on set exclusion
486 (void) lttng_event_rule_tracepoint_get_exclusion_at_index(
488 strncpy(local_exclusions
->names
[i
], tmp
, LTTNG_SYMBOL_NAME_LEN
);
489 local_exclusions
->names
[i
][LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
493 ret_exclusions
= local_exclusions
;
494 local_exclusions
= NULL
;
496 free(local_exclusions
);
498 return ret_exclusions
;
501 static struct lttng_event
*lttng_event_rule_tracepoint_generate_lttng_event(
502 const struct lttng_event_rule
*rule
)
504 const struct lttng_event_rule_tracepoint
*tracepoint
;
505 struct lttng_event
*local_event
= NULL
;
506 struct lttng_event
*event
= NULL
;
508 tracepoint
= container_of(
509 rule
, const struct lttng_event_rule_tracepoint
, parent
);
511 local_event
= zmalloc(sizeof(*local_event
));
516 local_event
->type
= LTTNG_EVENT_TRACEPOINT
;
517 (void) strncpy(local_event
->name
, tracepoint
->pattern
,
518 sizeof(local_event
->name
) - 1);
519 local_event
->name
[sizeof(local_event
->name
) - 1] = '\0';
520 local_event
->loglevel_type
= tracepoint
->loglevel
.type
;
521 local_event
->loglevel
= tracepoint
->loglevel
.value
;
530 struct lttng_event_rule
*lttng_event_rule_tracepoint_create(
531 enum lttng_domain_type domain_type
)
533 struct lttng_event_rule_tracepoint
*rule
;
535 if (domain_type
== LTTNG_DOMAIN_NONE
) {
539 rule
= zmalloc(sizeof(struct lttng_event_rule_tracepoint
));
544 lttng_event_rule_init(&rule
->parent
, LTTNG_EVENT_RULE_TYPE_TRACEPOINT
);
545 rule
->parent
.validate
= lttng_event_rule_tracepoint_validate
;
546 rule
->parent
.serialize
= lttng_event_rule_tracepoint_serialize
;
547 rule
->parent
.equal
= lttng_event_rule_tracepoint_is_equal
;
548 rule
->parent
.destroy
= lttng_event_rule_tracepoint_destroy
;
549 rule
->parent
.populate
= lttng_event_rule_tracepoint_populate
;
550 rule
->parent
.get_filter
=
551 lttng_event_rule_tracepoint_get_internal_filter
;
552 rule
->parent
.get_filter_bytecode
=
553 lttng_event_rule_tracepoint_get_internal_filter_bytecode
;
554 rule
->parent
.generate_exclusions
=
555 lttng_event_rule_tracepoint_generate_exclusions
;
556 rule
->parent
.generate_lttng_event
=
557 lttng_event_rule_tracepoint_generate_lttng_event
;
559 rule
->domain
= domain_type
;
560 rule
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
562 return &rule
->parent
;
566 ssize_t
lttng_event_rule_tracepoint_create_from_buffer(
567 const struct lttng_buffer_view
*view
,
568 struct lttng_event_rule
**_event_rule
)
570 ssize_t ret
, offset
= 0;
571 enum lttng_event_rule_status status
;
572 enum lttng_domain_type domain_type
;
573 enum lttng_loglevel_type loglevel_type
;
574 const struct lttng_event_rule_tracepoint_comm
*tracepoint_comm
;
576 const char *filter_expression
= NULL
;
577 const char **exclusions
= NULL
;
578 const uint32_t *exclusion_len
;
579 const char *exclusion
;
580 struct lttng_buffer_view current_view
;
581 struct lttng_event_rule
*rule
= NULL
;
588 if (view
->size
< sizeof(*tracepoint_comm
)) {
589 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header");
594 current_view
= lttng_buffer_view_from_view(
595 view
, offset
, sizeof(*tracepoint_comm
));
596 tracepoint_comm
= (typeof(tracepoint_comm
)) current_view
.data
;
598 if (!tracepoint_comm
) {
603 if (tracepoint_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
604 tracepoint_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
605 /* Invalid domain value. */
606 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer",
607 (int) tracepoint_comm
->domain_type
);
612 domain_type
= (enum lttng_domain_type
) tracepoint_comm
->domain_type
;
613 rule
= lttng_event_rule_tracepoint_create(domain_type
);
615 ERR("Failed to create event rule tracepoint");
620 loglevel_type
= (enum lttng_loglevel_type
)
621 tracepoint_comm
->loglevel_type
;
622 switch (loglevel_type
) {
623 case LTTNG_EVENT_LOGLEVEL_ALL
:
624 status
= lttng_event_rule_tracepoint_set_loglevel_all(rule
);
626 case LTTNG_EVENT_LOGLEVEL_RANGE
:
627 status
= lttng_event_rule_tracepoint_set_loglevel_range(
628 rule
, (enum lttng_loglevel_type
) tracepoint_comm
631 case LTTNG_EVENT_LOGLEVEL_SINGLE
:
632 status
= lttng_event_rule_tracepoint_set_loglevel(
633 rule
, (enum lttng_loglevel_type
) tracepoint_comm
637 ERR("Failed to set event rule tracepoint loglevel: unknown loglevel type");
641 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
642 ERR("Failed to set event rule tracepoint loglevel");
645 /* Skip to payload */
646 offset
+= current_view
.size
;
648 /* Map the pattern */
649 current_view
= lttng_buffer_view_from_view(
650 view
, offset
, tracepoint_comm
->pattern_len
);
651 pattern
= current_view
.data
;
657 if (tracepoint_comm
->pattern_len
== 1 ||
658 pattern
[tracepoint_comm
->pattern_len
- 1] != '\0' ||
659 strlen(pattern
) != tracepoint_comm
->pattern_len
- 1) {
661 * Check that the pattern is not NULL, is NULL-terminated, and
662 * does not contain a NULL before the last byte.
668 /* Skip after the pattern */
669 offset
+= tracepoint_comm
->pattern_len
;
671 if (!tracepoint_comm
->filter_expression_len
) {
672 goto skip_filter_expression
;
675 /* Map the filter_expression */
676 current_view
= lttng_buffer_view_from_view(
677 view
, offset
, tracepoint_comm
->filter_expression_len
);
678 filter_expression
= current_view
.data
;
679 if (!filter_expression
) {
684 if (tracepoint_comm
->filter_expression_len
== 1 ||
685 filter_expression
[tracepoint_comm
->filter_expression_len
-
687 strlen(filter_expression
) !=
688 tracepoint_comm
->filter_expression_len
-
691 * Check that the filter expression is not NULL, is
692 * NULL-terminated, and does not contain a NULL before the last
699 /* Skip after the pattern */
700 offset
+= tracepoint_comm
->filter_expression_len
;
702 skip_filter_expression
:
704 if (!tracepoint_comm
->exclusions_count
) {
705 goto skip_exclusions
;
708 exclusions
= zmalloc(sizeof(*exclusions
) *
709 tracepoint_comm
->exclusions_count
);
715 for (int i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
716 current_view
= lttng_buffer_view_from_view(
717 view
, offset
, sizeof(*exclusion_len
));
718 exclusion_len
= (typeof(exclusion_len
)) current_view
.data
;
719 if (!exclusion_len
) {
724 offset
+= sizeof(*exclusion_len
);
725 current_view
= lttng_buffer_view_from_view(
726 view
, offset
, *exclusion_len
);
727 exclusion
= current_view
.data
;
728 if (*exclusion_len
== 1 ||
729 exclusion
[*exclusion_len
- 1] != '\0' ||
730 strlen(exclusion
) != *exclusion_len
- 1) {
732 * Check that the exclusion is not NULL, is
733 * NULL-terminated, and does not contain a NULL before
739 exclusions
[i
] = exclusion
;
740 /* Skip to next exclusion */
741 offset
+= *exclusion_len
;
745 status
= lttng_event_rule_tracepoint_set_pattern(rule
, pattern
);
746 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
747 ERR("Failed to set event rule tracepoint pattern");
752 if (filter_expression
) {
753 status
= lttng_event_rule_tracepoint_set_filter(
754 rule
, filter_expression
);
755 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
756 ERR("Failed to set event rule tracepoint pattern");
763 status
= lttng_event_rule_tracepoint_set_exclusions(rule
,
764 tracepoint_comm
->exclusions_count
, exclusions
);
765 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
766 ERR("Failed to set event rule tracepoint exclusions");
777 lttng_event_rule_destroy(rule
);
781 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_pattern(
782 struct lttng_event_rule
*rule
, const char *pattern
)
784 char *pattern_copy
= NULL
;
785 struct lttng_event_rule_tracepoint
*tracepoint
;
786 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
788 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
789 strlen(pattern
) == 0) {
790 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
794 tracepoint
= container_of(
795 rule
, struct lttng_event_rule_tracepoint
, parent
);
796 pattern_copy
= strdup(pattern
);
798 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
802 if (tracepoint
->pattern
) {
803 free(tracepoint
->pattern
);
806 tracepoint
->pattern
= pattern_copy
;
812 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_pattern(
813 const struct lttng_event_rule
*rule
, const char **pattern
)
815 struct lttng_event_rule_tracepoint
*tracepoint
;
816 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
818 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
819 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
823 tracepoint
= container_of(
824 rule
, struct lttng_event_rule_tracepoint
, parent
);
825 if (!tracepoint
->pattern
) {
826 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
830 *pattern
= tracepoint
->pattern
;
835 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_domain_type(
836 const struct lttng_event_rule
*rule
,
837 enum lttng_domain_type
*type
)
839 struct lttng_event_rule_tracepoint
*tracepoint
;
840 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
842 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
843 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
847 tracepoint
= container_of(
848 rule
, struct lttng_event_rule_tracepoint
, parent
);
849 *type
= tracepoint
->domain
;
854 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_filter(
855 struct lttng_event_rule
*rule
, const char *expression
)
857 char *expression_copy
= NULL
;
858 struct lttng_event_rule_tracepoint
*tracepoint
;
859 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
861 /* TODO: validate that the passed expression is valid */
863 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
864 strlen(expression
) == 0) {
865 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
869 tracepoint
= container_of(
870 rule
, struct lttng_event_rule_tracepoint
, parent
);
871 expression_copy
= strdup(expression
);
872 if (!expression_copy
) {
873 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
877 if (tracepoint
->filter_expression
) {
878 free(tracepoint
->filter_expression
);
881 tracepoint
->filter_expression
= expression_copy
;
882 expression_copy
= NULL
;
887 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_filter(
888 const struct lttng_event_rule
*rule
, const char **expression
)
890 struct lttng_event_rule_tracepoint
*tracepoint
;
891 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
893 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
894 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
898 tracepoint
= container_of(
899 rule
, struct lttng_event_rule_tracepoint
, parent
);
900 if (!tracepoint
->filter_expression
) {
901 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
905 *expression
= tracepoint
->filter_expression
;
910 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_loglevel(
911 struct lttng_event_rule
*rule
, int level
)
913 struct lttng_event_rule_tracepoint
*tracepoint
;
914 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
917 * TODO/QUESTION: do we validate the passed level based on the domain?
918 * What if no domain is set yet? Should we move the domain to the
919 * "create" api call to enforce the domain type?
921 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
922 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
926 tracepoint
= container_of(
927 rule
, struct lttng_event_rule_tracepoint
, parent
);
928 tracepoint
->loglevel
.value
= level
;
929 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
934 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_loglevel_range(
935 struct lttng_event_rule
*rule
, int level
)
937 struct lttng_event_rule_tracepoint
*tracepoint
;
938 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
941 * TODO/QUESTION: do we validate the passed level based on the domain?
942 * What if no domain is set yet? Should we move the domain to the
943 * "create" api call to enforce the domain type?
945 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
946 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
950 tracepoint
= container_of(
951 rule
, struct lttng_event_rule_tracepoint
, parent
);
952 tracepoint
->loglevel
.value
= level
;
953 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
958 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_loglevel_all(
959 struct lttng_event_rule
*rule
)
961 struct lttng_event_rule_tracepoint
*tracepoint
;
962 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
964 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
965 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
969 tracepoint
= container_of(
970 rule
, struct lttng_event_rule_tracepoint
, parent
);
971 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
976 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_loglevel_type(
977 const struct lttng_event_rule
*rule
,
978 enum lttng_loglevel_type
*type
)
980 struct lttng_event_rule_tracepoint
*tracepoint
;
981 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
983 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
984 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
988 tracepoint
= container_of(
989 rule
, struct lttng_event_rule_tracepoint
, parent
);
990 *type
= tracepoint
->loglevel
.type
;
995 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_loglevel(
996 const struct lttng_event_rule
*rule
, int *level
)
998 struct lttng_event_rule_tracepoint
*tracepoint
;
999 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1001 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !level
) {
1002 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1006 tracepoint
= container_of(
1007 rule
, struct lttng_event_rule_tracepoint
, parent
);
1008 if (tracepoint
->loglevel
.type
== LTTNG_EVENT_LOGLEVEL_ALL
) {
1009 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1012 *level
= tracepoint
->loglevel
.value
;
1017 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_exclusions(
1018 struct lttng_event_rule
*rule
,
1020 const char **exclusions
)
1022 char **exclusions_copy
= NULL
;
1023 struct lttng_event_rule_tracepoint
*tracepoint
;
1024 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1025 enum lttng_domain_type domain_type
;
1027 /* TODO: validate that the passed exclusions are valid? */
1029 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || count
== 0 ||
1031 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1035 tracepoint
= container_of(
1036 rule
, struct lttng_event_rule_tracepoint
, parent
);
1038 status
= lttng_event_rule_tracepoint_get_domain_type(
1039 rule
, &domain_type
);
1040 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
1044 switch (domain_type
) {
1045 case LTTNG_DOMAIN_KERNEL
:
1046 case LTTNG_DOMAIN_JUL
:
1047 case LTTNG_DOMAIN_LOG4J
:
1048 case LTTNG_DOMAIN_PYTHON
:
1049 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1051 case LTTNG_DOMAIN_UST
:
1052 /* Exclusions supported */
1058 exclusions_copy
= zmalloc(sizeof(char *) * count
);
1059 if (!exclusions_copy
) {
1060 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1064 /* Perform the copy locally */
1065 for (int i
= 0; i
< count
; i
++) {
1066 exclusions_copy
[i
] = strdup(exclusions
[i
]);
1067 if (!exclusions_copy
[i
]) {
1068 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1073 if (tracepoint
->exclusions
.count
!= 0) {
1074 for (int i
= 0; i
< tracepoint
->exclusions
.count
; i
++) {
1075 free(tracepoint
->exclusions
.values
[i
]);
1077 free(tracepoint
->exclusions
.values
);
1080 tracepoint
->exclusions
.values
= exclusions_copy
;
1081 tracepoint
->exclusions
.count
= count
;
1082 exclusions_copy
= NULL
;
1084 if (exclusions_copy
) {
1085 for (int i
= 0; i
< count
; i
++) {
1086 free(exclusions_copy
[i
]);
1088 free(exclusions_copy
);
1093 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusions_count(
1094 const struct lttng_event_rule
*rule
, unsigned int *count
)
1096 struct lttng_event_rule_tracepoint
*tracepoint
;
1097 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1099 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1100 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1104 tracepoint
= container_of(
1105 rule
, struct lttng_event_rule_tracepoint
, parent
);
1106 *count
= tracepoint
->exclusions
.count
;
1111 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusion_at_index(
1112 const struct lttng_event_rule
*rule
,
1114 const char **exclusion
)
1116 struct lttng_event_rule_tracepoint
*tracepoint
;
1117 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1119 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1120 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1124 tracepoint
= container_of(
1125 rule
, struct lttng_event_rule_tracepoint
, parent
);
1126 if (index
>= tracepoint
->exclusions
.count
) {
1127 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1130 *exclusion
= tracepoint
->exclusions
.values
[index
];