2 * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #include <lttng/event.h>
19 #include <lttng/event-rule/event-rule-internal.h>
20 #include <lttng/event-rule/tracepoint-internal.h>
21 #include <common/macros.h>
22 #include <common/error.h>
23 #include <common/runas.h>
26 #define IS_TRACEPOINT_EVENT_RULE(rule) ( \
27 lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT \
31 void lttng_event_rule_tracepoint_destroy(struct lttng_event_rule
*rule
)
33 struct lttng_event_rule_tracepoint
*tracepoint
;
39 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
42 free(tracepoint
->pattern
);
43 free(tracepoint
->filter_expression
);
44 for(int i
= 0; i
< tracepoint
->exclusions
.count
; i
++) {
45 free(tracepoint
->exclusions
.values
[i
]);
47 free(tracepoint
->exclusions
.values
);
48 free(tracepoint
->internal_filter
.filter
);
49 free(tracepoint
->internal_filter
.bytecode
);
54 bool lttng_event_rule_tracepoint_validate(
55 const struct lttng_event_rule
*rule
)
58 struct lttng_event_rule_tracepoint
*tracepoint
;
64 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
68 if (!tracepoint
->pattern
) {
69 ERR("Invalid tracepoint event rule: a pattern must be set.");
72 if (tracepoint
->domain
== LTTNG_DOMAIN_NONE
) {
73 ERR("Invalid tracepoint event rule: a domain must be set.");
77 /* QUESTION: do we validate inside state on validate or during set of
86 int lttng_event_rule_tracepoint_serialize(
87 const struct lttng_event_rule
*rule
,
88 struct lttng_dynamic_buffer
*buf
,
92 size_t pattern_len
, filter_expression_len
, exclusions_len
;
93 struct lttng_event_rule_tracepoint
*tracepoint
;
94 struct lttng_event_rule_tracepoint_comm tracepoint_comm
;
96 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
101 DBG("Serializing tracepoint event rule");
102 tracepoint
= container_of(
103 rule
, struct lttng_event_rule_tracepoint
, parent
);
105 pattern_len
= strlen(tracepoint
->pattern
) + 1;
107 if (tracepoint
->filter_expression
!= NULL
) {
108 filter_expression_len
=
109 strlen(tracepoint
->filter_expression
) + 1;
111 filter_expression_len
= 0;
115 for (int i
= 0; i
< tracepoint
->exclusions
.count
; i
++) {
117 exclusions_len
+= strlen(tracepoint
->exclusions
.values
[i
]) + 1;
119 exclusions_len
+= sizeof(uint32_t);
122 tracepoint_comm
.domain_type
= (int8_t) tracepoint
->domain
;
123 tracepoint_comm
.loglevel_type
= (int8_t) tracepoint
->loglevel
.type
;
124 tracepoint_comm
.loglevel_value
= tracepoint
->loglevel
.value
;
125 tracepoint_comm
.pattern_len
= pattern_len
;
126 tracepoint_comm
.filter_expression_len
= filter_expression_len
;
127 tracepoint_comm
.exclusions_count
= tracepoint
->exclusions
.count
;
128 tracepoint_comm
.exclusions_len
= exclusions_len
;
130 ret
= lttng_dynamic_buffer_append(
131 buf
, &tracepoint_comm
, sizeof(tracepoint_comm
));
135 ret
= lttng_dynamic_buffer_append(buf
, tracepoint
->pattern
,
140 ret
= lttng_dynamic_buffer_append(buf
, tracepoint
->filter_expression
,
141 filter_expression_len
);
146 size_t exclusions_appended
= 0;
147 for (int i
= 0; i
< tracepoint
->exclusions
.count
; i
++) {
149 len
= strlen(tracepoint
->exclusions
.values
[i
]) + 1;
150 /* Append bound check, does not include the '\0' */
151 ret
= lttng_dynamic_buffer_append(buf
, &len
, sizeof(uint32_t));
155 exclusions_appended
+= sizeof(uint32_t);
157 /* Include the '\0' in the payload */
158 ret
= lttng_dynamic_buffer_append(buf
, tracepoint
->exclusions
.values
[i
],
163 exclusions_appended
+= len
;
166 assert(exclusions_len
== exclusions_appended
);
178 bool lttng_event_rule_tracepoint_is_equal(const struct lttng_event_rule
*_a
,
179 const struct lttng_event_rule
*_b
)
181 bool is_equal
= false;
182 struct lttng_event_rule_tracepoint
*a
, *b
;
184 a
= container_of(_a
, struct lttng_event_rule_tracepoint
, parent
);
185 b
= container_of(_b
, struct lttng_event_rule_tracepoint
, parent
);
188 if (a
->domain
!= b
->domain
) {
192 if (a
->exclusions
.count
!= b
->exclusions
.count
) {
196 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
201 /* Tracepoint is invalid if this is not true */
204 if (strcmp(a
->pattern
, b
->pattern
)) {
208 if (a
->filter_expression
&& b
->filter_expression
) {
209 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
214 if (a
->loglevel
.type
!= b
->loglevel
.type
) {
218 if (a
->loglevel
.value
!= b
->loglevel
.value
) {
222 for (int i
= 0; i
< a
->exclusions
.count
; i
++) {
223 if (strcmp(a
->exclusions
.values
[i
], b
->exclusions
.values
[i
])) {
234 * On success ret is 0;
236 * On error ret is negative.
238 * An event with NO loglevel and the name is * will return NULL.
240 static int generate_agent_filter(
241 const struct lttng_event_rule
*rule
,
242 char **_agent_filter
)
246 char *agent_filter
= NULL
;
249 enum lttng_loglevel_type loglevel_type
;
250 enum lttng_event_rule_status status
;
253 assert(_agent_filter
);
255 status
= lttng_event_rule_tracepoint_get_pattern(rule
, &pattern
);
256 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
261 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
262 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
264 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
269 status
= lttng_event_rule_tracepoint_get_loglevel_type(rule
, &loglevel_type
);
270 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
275 /* Don't add filter for the '*' event. */
276 if (strcmp(pattern
, "*") != 0) {
278 err
= asprintf(&agent_filter
, "(%s) && (logger_name == \"%s\")", filter
,
281 err
= asprintf(&agent_filter
, "logger_name == \"%s\"", pattern
);
290 if (loglevel_type
!= LTTNG_EVENT_LOGLEVEL_ALL
) {
294 status
= lttng_event_rule_tracepoint_get_loglevel(rule
, &loglevel_value
);
295 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
300 if (loglevel_type
== LTTNG_EVENT_LOGLEVEL_RANGE
) {
306 if (filter
|| agent_filter
) {
309 err
= asprintf(&new_filter
, "(%s) && (int_loglevel %s %d)",
310 agent_filter
? agent_filter
: filter
, op
,
315 agent_filter
= new_filter
;
317 err
= asprintf(&agent_filter
, "int_loglevel %s %d", op
,
327 *_agent_filter
= agent_filter
;
336 enum lttng_error_code
lttng_event_rule_tracepoint_populate(struct lttng_event_rule
*rule
, uid_t uid
, gid_t gid
)
339 enum lttng_error_code ret_code
;
340 struct lttng_event_rule_tracepoint
*tracepoint
;
341 enum lttng_domain_type domain_type
;
342 enum lttng_event_rule_status status
;
344 struct lttng_filter_bytecode
*bytecode
= NULL
;
348 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
351 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
352 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
354 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
355 ret_code
= LTTNG_ERR_FILTER_INVAL
;
359 if (filter
&& filter
[0] == '\0') {
360 ret_code
= LTTNG_ERR_FILTER_INVAL
;
364 status
= lttng_event_rule_tracepoint_get_domain_type(rule
, &domain_type
);
365 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
366 ret_code
= LTTNG_ERR_UNK
;
370 switch (domain_type
) {
371 case LTTNG_DOMAIN_LOG4J
:
372 case LTTNG_DOMAIN_JUL
:
373 case LTTNG_DOMAIN_PYTHON
:
376 ret
= generate_agent_filter(rule
, &agent_filter
);
378 ret_code
= LTTNG_ERR_FILTER_INVAL
;
381 tracepoint
->internal_filter
.filter
= agent_filter
;
387 tracepoint
->internal_filter
.filter
= strdup(filter
);
388 if (tracepoint
->internal_filter
.filter
== NULL
) {
389 ret_code
= LTTNG_ERR_NOMEM
;
393 tracepoint
->internal_filter
.filter
= NULL
;
399 if (tracepoint
->internal_filter
.filter
== NULL
) {
404 ret
= run_as_generate_filter_bytecode(tracepoint
->internal_filter
.filter
, uid
, gid
, &bytecode
);
406 ret_code
= LTTNG_ERR_FILTER_INVAL
;
409 tracepoint
->internal_filter
.bytecode
= bytecode
;
420 static const char *lttng_event_rule_tracepoint_get_internal_filter(
421 const struct lttng_event_rule
*rule
)
423 struct lttng_event_rule_tracepoint
*tracepoint
;
426 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
428 return tracepoint
->internal_filter
.filter
;
431 static const struct lttng_filter_bytecode
*
432 lttng_event_rule_tracepoint_get_internal_filter_bytecode(
433 const struct lttng_event_rule
*rule
)
435 struct lttng_event_rule_tracepoint
*tracepoint
;
438 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
440 return tracepoint
->internal_filter
.bytecode
;
443 /* TODO: review error handling, the function should be able to
444 * return error information.
446 static struct lttng_event_exclusion
*
447 lttng_event_rule_tracepoint_generate_exclusions(struct lttng_event_rule
*rule
)
449 enum lttng_domain_type domain_type
= LTTNG_DOMAIN_NONE
;
450 struct lttng_event_exclusion
*local_exclusions
= NULL
;
451 struct lttng_event_exclusion
*ret_exclusions
= NULL
;
452 unsigned int nb_exclusions
= 0;
454 (void) lttng_event_rule_tracepoint_get_domain_type(rule
, &domain_type
);
456 switch (domain_type
) {
457 case LTTNG_DOMAIN_KERNEL
:
458 case LTTNG_DOMAIN_JUL
:
459 case LTTNG_DOMAIN_LOG4J
:
460 case LTTNG_DOMAIN_PYTHON
:
462 ret_exclusions
= NULL
;
464 case LTTNG_DOMAIN_UST
:
465 /* Exclusions supported */
471 (void) lttng_event_rule_tracepoint_get_exclusions_count(rule
, &nb_exclusions
);
472 if (nb_exclusions
== 0) {
474 ret_exclusions
= NULL
;
478 local_exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) + (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
479 if (!local_exclusions
) {
480 ERR("local exclusion allocation");
481 ret_exclusions
= NULL
;
485 local_exclusions
->count
= nb_exclusions
;
486 for (unsigned int i
= 0; i
< nb_exclusions
; i
++) {
487 /* TODO: check for truncation.
488 * Part of this should be validated on set exclusion
491 (void) lttng_event_rule_tracepoint_get_exclusion_at_index(rule
, i
, &tmp
);
492 strncpy(local_exclusions
->names
[i
], tmp
, LTTNG_SYMBOL_NAME_LEN
);
493 local_exclusions
->names
[i
][LTTNG_SYMBOL_NAME_LEN
-1] = '\0';
497 ret_exclusions
= local_exclusions
;
498 local_exclusions
= NULL
;
500 free(local_exclusions
);
502 return ret_exclusions
;
505 static struct lttng_event
*lttng_event_rule_tracepoint_generate_lttng_event(
506 const struct lttng_event_rule
*rule
)
508 const struct lttng_event_rule_tracepoint
*tracepoint
;
509 struct lttng_event
*local_event
= NULL
;
510 struct lttng_event
*event
= NULL
;
512 tracepoint
= container_of(
513 rule
, const struct lttng_event_rule_tracepoint
, parent
);
515 local_event
= zmalloc(sizeof(*local_event
));
520 local_event
->type
= LTTNG_EVENT_TRACEPOINT
;
521 (void) strncpy(local_event
->name
, tracepoint
->pattern
,
522 sizeof(local_event
->name
) - 1);
523 local_event
->name
[sizeof(local_event
->name
) - 1] = '\0';
524 local_event
->loglevel_type
= tracepoint
->loglevel
.type
;
525 local_event
->loglevel
= tracepoint
->loglevel
.value
;
534 struct lttng_event_rule
*lttng_event_rule_tracepoint_create(enum lttng_domain_type domain_type
)
536 struct lttng_event_rule_tracepoint
*rule
;
538 if (domain_type
== LTTNG_DOMAIN_NONE
) {
542 rule
= zmalloc(sizeof(struct lttng_event_rule_tracepoint
));
547 lttng_event_rule_init(&rule
->parent
, LTTNG_EVENT_RULE_TYPE_TRACEPOINT
);
548 rule
->parent
.validate
= lttng_event_rule_tracepoint_validate
;
549 rule
->parent
.serialize
= lttng_event_rule_tracepoint_serialize
;
550 rule
->parent
.equal
= lttng_event_rule_tracepoint_is_equal
;
551 rule
->parent
.destroy
= lttng_event_rule_tracepoint_destroy
;
552 rule
->parent
.populate
= lttng_event_rule_tracepoint_populate
;
553 rule
->parent
.get_filter
= lttng_event_rule_tracepoint_get_internal_filter
;
554 rule
->parent
.get_filter_bytecode
= lttng_event_rule_tracepoint_get_internal_filter_bytecode
;
555 rule
->parent
.generate_exclusions
= 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(view
, offset
, sizeof(*tracepoint_comm
));
595 tracepoint_comm
= (typeof(tracepoint_comm
)) current_view
.data
;
597 if(!tracepoint_comm
) {
602 if (tracepoint_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
603 tracepoint_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
604 /* Invalid domain value. */
605 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer",
606 (int) tracepoint_comm
->domain_type
);
611 domain_type
= (enum lttng_domain_type
) tracepoint_comm
->domain_type
;
612 rule
= lttng_event_rule_tracepoint_create(domain_type
);
614 ERR("Failed to create event rule tracepoint");
619 loglevel_type
= (enum lttng_loglevel_type
)
620 tracepoint_comm
->loglevel_type
;
621 switch (loglevel_type
) {
622 case LTTNG_EVENT_LOGLEVEL_ALL
:
623 status
= lttng_event_rule_tracepoint_set_loglevel_all(rule
);
625 case LTTNG_EVENT_LOGLEVEL_RANGE
:
626 status
= lttng_event_rule_tracepoint_set_loglevel_range(
627 rule
, (enum lttng_loglevel_type
) tracepoint_comm
630 case LTTNG_EVENT_LOGLEVEL_SINGLE
:
631 status
= lttng_event_rule_tracepoint_set_loglevel(
632 rule
, (enum lttng_loglevel_type
) tracepoint_comm
636 ERR("Failed to set event rule tracepoint loglevel: unknown loglevel type");
640 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
641 ERR("Failed to set event rule tracepoint loglevel");
644 /* Skip to payload */
645 offset
+= current_view
.size
;
647 /* Map the pattern */
648 current_view
= lttng_buffer_view_from_view(view
, offset
, tracepoint_comm
->pattern_len
);
649 pattern
= current_view
.data
;
655 if (tracepoint_comm
->pattern_len
== 1 ||
656 pattern
[tracepoint_comm
->pattern_len
- 1] != '\0' ||
657 strlen(pattern
) != tracepoint_comm
->pattern_len
- 1) {
659 * Check that the pattern is not NULL, is NULL-terminated, and
660 * does not contain a NULL before the last byte.
666 /* Skip after the pattern */
667 offset
+= tracepoint_comm
->pattern_len
;
669 if (!tracepoint_comm
->filter_expression_len
) {
670 goto skip_filter_expression
;
673 /* Map the filter_expression */
674 current_view
= lttng_buffer_view_from_view(view
, offset
, tracepoint_comm
->filter_expression_len
);
675 filter_expression
= current_view
.data
;
676 if (!filter_expression
) {
681 if (tracepoint_comm
->filter_expression_len
== 1 ||
682 filter_expression
[tracepoint_comm
->filter_expression_len
-
684 strlen(filter_expression
) !=
685 tracepoint_comm
->filter_expression_len
-
688 * Check that the filter expression is not NULL, is
689 * NULL-terminated, and does not contain a NULL before the last
696 /* Skip after the pattern */
697 offset
+= tracepoint_comm
->filter_expression_len
;
699 skip_filter_expression
:
701 if (!tracepoint_comm
->exclusions_count
) {
702 goto skip_exclusions
;
705 exclusions
= zmalloc(sizeof(*exclusions
) * tracepoint_comm
->exclusions_count
);
711 for (int i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
712 current_view
= lttng_buffer_view_from_view(view
, offset
, sizeof(*exclusion_len
));
713 exclusion_len
= (typeof(exclusion_len
)) current_view
.data
;
714 if (!exclusion_len
) {
719 offset
+= sizeof(*exclusion_len
);
720 current_view
= lttng_buffer_view_from_view(view
, offset
, *exclusion_len
);
721 exclusion
= current_view
.data
;
722 if (*exclusion_len
== 1 ||
723 exclusion
[*exclusion_len
- 1] != '\0' ||
724 strlen(exclusion
) != *exclusion_len
- 1) {
726 * Check that the exclusion is not NULL, is
727 * NULL-terminated, and does not contain a NULL before
733 exclusions
[i
] = exclusion
;
734 /* Skip to next exclusion */
735 offset
+= *exclusion_len
;
739 status
= lttng_event_rule_tracepoint_set_pattern(rule
, pattern
);
740 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
741 ERR("Failed to set event rule tracepoint pattern");
746 if (filter_expression
) {
747 status
= lttng_event_rule_tracepoint_set_filter(
748 rule
, filter_expression
);
749 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
750 ERR("Failed to set event rule tracepoint pattern");
757 status
= lttng_event_rule_tracepoint_set_exclusions(rule
,
758 tracepoint_comm
->exclusions_count
, exclusions
);
759 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
760 ERR("Failed to set event rule tracepoint exclusions");
771 lttng_event_rule_destroy(rule
);
775 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_pattern(
776 struct lttng_event_rule
*rule
, const char *pattern
)
778 char *pattern_copy
= NULL
;
779 struct lttng_event_rule_tracepoint
*tracepoint
;
780 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
782 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
783 strlen(pattern
) == 0) {
784 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
788 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
790 pattern_copy
= strdup(pattern
);
792 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
796 if (tracepoint
->pattern
) {
797 free(tracepoint
->pattern
);
800 tracepoint
->pattern
= pattern_copy
;
806 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_pattern(
807 const struct lttng_event_rule
*rule
, const char **pattern
)
809 struct lttng_event_rule_tracepoint
*tracepoint
;
810 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
812 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
813 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
817 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
819 if (!tracepoint
->pattern
) {
820 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
824 *pattern
= tracepoint
->pattern
;
829 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_domain_type(
830 const struct lttng_event_rule
*rule
,
831 enum lttng_domain_type
*type
)
833 struct lttng_event_rule_tracepoint
*tracepoint
;
834 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
836 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
837 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
841 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
843 *type
= tracepoint
->domain
;
848 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_filter(
849 struct lttng_event_rule
*rule
, const char *expression
)
851 char *expression_copy
= NULL
;
852 struct lttng_event_rule_tracepoint
*tracepoint
;
853 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
855 /* TODO: validate that the passed expression is valid */
857 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
858 strlen(expression
) == 0) {
859 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
863 tracepoint
= container_of(
864 rule
, struct lttng_event_rule_tracepoint
, parent
);
865 expression_copy
= strdup(expression
);
866 if (!expression_copy
) {
867 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
871 if (tracepoint
->filter_expression
) {
872 free(tracepoint
->filter_expression
);
875 tracepoint
->filter_expression
= expression_copy
;
876 expression_copy
= NULL
;
881 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_filter(
882 const struct lttng_event_rule
*rule
, const char **expression
)
884 struct lttng_event_rule_tracepoint
*tracepoint
;
885 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
887 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
888 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
892 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
894 if (!tracepoint
->filter_expression
) {
895 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
899 *expression
= tracepoint
->filter_expression
;
904 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_loglevel(
905 struct lttng_event_rule
*rule
, int level
)
907 struct lttng_event_rule_tracepoint
*tracepoint
;
908 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
911 * TODO/QUESTION: do we validate the passed level based on the domain?
912 * What if no domain is set yet? Should we move the domain to the
913 * "create" api call to enforce the domain type?
915 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
916 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
920 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
922 tracepoint
->loglevel
.value
= level
;
923 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
928 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_loglevel_range(
929 struct lttng_event_rule
*rule
, int level
)
931 struct lttng_event_rule_tracepoint
*tracepoint
;
932 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
935 * TODO/QUESTION: do we validate the passed level based on the domain?
936 * What if no domain is set yet? Should we move the domain to the
937 * "create" api call to enforce the domain type?
939 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
940 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
944 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
946 tracepoint
->loglevel
.value
= level
;
947 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
952 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_loglevel_all(
953 struct lttng_event_rule
*rule
)
955 struct lttng_event_rule_tracepoint
*tracepoint
;
956 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
958 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
959 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
963 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
965 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
970 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_loglevel_type(
971 const struct lttng_event_rule
*rule
, enum lttng_loglevel_type
*type
)
973 struct lttng_event_rule_tracepoint
*tracepoint
;
974 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
976 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
977 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
981 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
983 *type
= tracepoint
->loglevel
.type
;
988 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_loglevel(
989 const struct lttng_event_rule
*rule
, int *level
)
991 struct lttng_event_rule_tracepoint
*tracepoint
;
992 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
994 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !level
) {
995 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
999 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
1001 if (tracepoint
->loglevel
.type
== LTTNG_EVENT_LOGLEVEL_ALL
) {
1002 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1005 *level
= tracepoint
->loglevel
.value
;
1010 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_exclusions(
1011 struct lttng_event_rule
*rule
,
1013 const char **exclusions
)
1015 char **exclusions_copy
= NULL
;
1016 struct lttng_event_rule_tracepoint
*tracepoint
;
1017 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1018 enum lttng_domain_type domain_type
;
1020 /* TODO: validate that the passed exclusions are valid? */
1022 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || count
== 0 ||
1024 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1028 tracepoint
= container_of(
1029 rule
, struct lttng_event_rule_tracepoint
, parent
);
1031 status
= lttng_event_rule_tracepoint_get_domain_type(rule
, &domain_type
);
1032 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
1036 switch (domain_type
) {
1037 case LTTNG_DOMAIN_KERNEL
:
1038 case LTTNG_DOMAIN_JUL
:
1039 case LTTNG_DOMAIN_LOG4J
:
1040 case LTTNG_DOMAIN_PYTHON
:
1041 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1043 case LTTNG_DOMAIN_UST
:
1044 /* Exclusions supported */
1050 exclusions_copy
= zmalloc(sizeof(char *) * count
);
1051 if (!exclusions_copy
) {
1052 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1056 /* Perform the copy locally */
1057 for (int i
= 0; i
< count
; i
++) {
1058 exclusions_copy
[i
] = strdup(exclusions
[i
]);
1059 if (!exclusions_copy
[i
]) {
1060 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1065 if (tracepoint
->exclusions
.count
!= 0) {
1066 for (int i
= 0; i
< tracepoint
->exclusions
.count
; i
++) {
1067 free(tracepoint
->exclusions
.values
[i
]);
1069 free(tracepoint
->exclusions
.values
);
1072 tracepoint
->exclusions
.values
= exclusions_copy
;
1073 tracepoint
->exclusions
.count
= count
;
1074 exclusions_copy
= NULL
;
1076 if (exclusions_copy
) {
1077 for (int i
= 0; i
< count
; i
++) {
1078 free(exclusions_copy
[i
]);
1080 free(exclusions_copy
);
1085 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusions_count(
1086 const struct lttng_event_rule
*rule
, unsigned int *count
)
1088 struct lttng_event_rule_tracepoint
*tracepoint
;
1089 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1091 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1092 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1096 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
1098 *count
= tracepoint
->exclusions
.count
;
1103 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusion_at_index(
1104 const struct lttng_event_rule
*rule
,
1106 const char **exclusion
)
1108 struct lttng_event_rule_tracepoint
*tracepoint
;
1109 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1111 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1112 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1116 tracepoint
= container_of(rule
, struct lttng_event_rule_tracepoint
,
1118 if (index
>= tracepoint
->exclusions
.count
) {
1119 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1122 *exclusion
= tracepoint
->exclusions
.values
[index
];