2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include <lttng/trigger/trigger-internal.h>
9 #include <lttng/condition/condition-internal.h>
10 #include <lttng/condition/on-event-internal.h>
11 #include <lttng/condition/on-event.h>
12 #include <lttng/condition/on-event-internal.h>
13 #include <lttng/condition/buffer-usage.h>
14 #include <lttng/event-rule/event-rule-internal.h>
15 #include <lttng/event-expr-internal.h>
16 #include <lttng/action/action-internal.h>
17 #include <common/credentials.h>
18 #include <common/payload.h>
19 #include <common/payload-view.h>
20 #include <lttng/domain.h>
21 #include <common/error.h>
22 #include <common/dynamic-array.h>
23 #include <common/optional.h>
28 bool lttng_trigger_validate(const struct lttng_trigger
*trigger
)
37 if (!trigger
->creds
.uid
.is_set
) {
42 valid
= lttng_condition_validate(trigger
->condition
) &&
43 lttng_action_validate(trigger
->action
);
48 struct lttng_trigger
*lttng_trigger_create(
49 struct lttng_condition
*condition
,
50 struct lttng_action
*action
)
52 struct lttng_trigger
*trigger
= NULL
;
54 if (!condition
|| !action
) {
58 trigger
= zmalloc(sizeof(struct lttng_trigger
));
63 urcu_ref_init(&trigger
->ref
);
65 lttng_condition_get(condition
);
66 trigger
->condition
= condition
;
68 lttng_action_get(action
);
69 trigger
->action
= action
;
76 * Note: the lack of reference counting 'get' on the condition object is normal.
77 * This API was exposed as such in 2.11. The client is not expected to call
78 * lttng_condition_destroy on the returned object.
80 struct lttng_condition
*lttng_trigger_get_condition(
81 struct lttng_trigger
*trigger
)
83 return trigger
? trigger
->condition
: NULL
;
86 const struct lttng_condition
*lttng_trigger_get_const_condition(
87 const struct lttng_trigger
*trigger
)
89 return trigger
? trigger
->condition
: NULL
;
93 * Note: the lack of reference counting 'get' on the action object is normal.
94 * This API was exposed as such in 2.11. The client is not expected to call
95 * lttng_action_destroy on the returned object.
97 struct lttng_action
*lttng_trigger_get_action(
98 struct lttng_trigger
*trigger
)
100 return trigger
? trigger
->action
: NULL
;
103 const struct lttng_action
*lttng_trigger_get_const_action(
104 const struct lttng_trigger
*trigger
)
106 return trigger
? trigger
->action
: NULL
;
109 static void trigger_destroy_ref(struct urcu_ref
*ref
)
111 struct lttng_trigger
*trigger
=
112 container_of(ref
, struct lttng_trigger
, ref
);
113 struct lttng_action
*action
= lttng_trigger_get_action(trigger
);
114 struct lttng_condition
*condition
=
115 lttng_trigger_get_condition(trigger
);
120 /* Release ownership. */
121 lttng_action_put(action
);
122 lttng_condition_put(condition
);
128 void lttng_trigger_destroy(struct lttng_trigger
*trigger
)
130 lttng_trigger_put(trigger
);
134 ssize_t
lttng_trigger_create_from_payload(
135 struct lttng_payload_view
*src_view
,
136 struct lttng_trigger
**_trigger
)
138 ssize_t ret
, offset
= 0, condition_size
, action_size
, name_size
= 0;
139 struct lttng_condition
*condition
= NULL
;
140 struct lttng_action
*action
= NULL
;
141 const struct lttng_trigger_comm
*trigger_comm
;
142 const char *name
= NULL
;
143 struct lttng_credentials creds
= {
144 .uid
= LTTNG_OPTIONAL_INIT_UNSET
,
145 .gid
= LTTNG_OPTIONAL_INIT_UNSET
,
147 struct lttng_trigger
*trigger
= NULL
;
148 const struct lttng_payload_view trigger_comm_view
=
149 lttng_payload_view_from_view(
150 src_view
, 0, sizeof(*trigger_comm
));
152 if (!src_view
|| !_trigger
) {
157 if (!lttng_payload_view_is_valid(&trigger_comm_view
)) {
158 /* Payload not large enough to contain the header. */
163 /* lttng_trigger_comm header */
164 trigger_comm
= (typeof(trigger_comm
)) trigger_comm_view
.buffer
.data
;
166 /* Set the trigger's creds. */
167 if (trigger_comm
->uid
> (uint64_t) ((uid_t
) -1)) {
168 /* UID out of range for this platform. */
173 LTTNG_OPTIONAL_SET(&creds
.uid
, trigger_comm
->uid
);
175 offset
+= sizeof(*trigger_comm
);
177 if (trigger_comm
->name_length
!= 0) {
179 const struct lttng_payload_view name_view
=
180 lttng_payload_view_from_view(
182 trigger_comm
->name_length
);
184 if (!lttng_payload_view_is_valid(&name_view
)) {
189 name
= name_view
.buffer
.data
;
190 if (!lttng_buffer_view_contains_string(&name_view
.buffer
, name
,
191 trigger_comm
->name_length
)) {
196 offset
+= trigger_comm
->name_length
;
197 name_size
= trigger_comm
->name_length
;
201 /* struct lttng_condition */
202 struct lttng_payload_view condition_view
=
203 lttng_payload_view_from_view(
204 src_view
, offset
, -1);
206 condition_size
= lttng_condition_create_from_payload(&condition_view
,
210 if (condition_size
< 0) {
211 ret
= condition_size
;
215 offset
+= condition_size
;
217 /* struct lttng_action */
218 struct lttng_payload_view action_view
=
219 lttng_payload_view_from_view(
220 src_view
, offset
, -1);
222 action_size
= lttng_action_create_from_payload(&action_view
, &action
);
225 if (action_size
< 0) {
229 offset
+= action_size
;
231 /* Unexpected size of inner-elements; the buffer is corrupted. */
232 if ((ssize_t
) trigger_comm
->length
!= condition_size
+ action_size
+ name_size
) {
237 trigger
= lttng_trigger_create(condition
, action
);
243 lttng_trigger_set_credentials(trigger
, &creds
);
246 * The trigger object owns references to the action and condition
249 lttng_condition_put(condition
);
252 lttng_action_put(action
);
256 const enum lttng_trigger_status status
=
257 lttng_trigger_set_name(trigger
, name
);
259 if (status
!= LTTNG_TRIGGER_STATUS_OK
) {
268 lttng_condition_put(condition
);
269 lttng_action_put(action
);
274 lttng_trigger_put(trigger
);
281 * Both elements are stored contiguously, see their "*_comm" structure
282 * for the detailed format.
285 int lttng_trigger_serialize(const struct lttng_trigger
*trigger
,
286 struct lttng_payload
*payload
)
289 size_t header_offset
, size_before_payload
, size_name
;
290 struct lttng_trigger_comm trigger_comm
= {};
291 struct lttng_trigger_comm
*header
;
292 const struct lttng_credentials
*creds
= NULL
;
294 creds
= lttng_trigger_get_credentials(trigger
);
297 trigger_comm
.uid
= LTTNG_OPTIONAL_GET(creds
->uid
);
299 if (trigger
->name
!= NULL
) {
300 size_name
= strlen(trigger
->name
) + 1;
305 trigger_comm
.name_length
= size_name
;
307 header_offset
= payload
->buffer
.size
;
308 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &trigger_comm
,
309 sizeof(trigger_comm
));
314 size_before_payload
= payload
->buffer
.size
;
317 ret
= lttng_dynamic_buffer_append(
318 &payload
->buffer
, trigger
->name
, size_name
);
323 ret
= lttng_condition_serialize(trigger
->condition
, payload
);
328 ret
= lttng_action_serialize(trigger
->action
, payload
);
333 /* Update payload size. */
334 header
= (typeof(header
)) (payload
->buffer
.data
+ header_offset
);
335 header
->length
= payload
->buffer
.size
- size_before_payload
;
341 bool lttng_trigger_is_equal(
342 const struct lttng_trigger
*a
, const struct lttng_trigger
*b
)
344 if (strcmp(a
->name
, b
->name
) != 0) {
348 if (!lttng_condition_is_equal(a
->condition
, b
->condition
)) {
352 if (!lttng_action_is_equal(a
->action
, b
->action
)) {
356 if (!lttng_credentials_is_equal(lttng_trigger_get_credentials(a
),
357 lttng_trigger_get_credentials(b
))) {
364 enum lttng_trigger_status
lttng_trigger_set_name(struct lttng_trigger
*trigger
,
367 char *name_copy
= NULL
;
368 enum lttng_trigger_status status
= LTTNG_TRIGGER_STATUS_OK
;
370 if (!trigger
|| !name
||
372 status
= LTTNG_TRIGGER_STATUS_INVALID
;
376 name_copy
= strdup(name
);
378 status
= LTTNG_TRIGGER_STATUS_ERROR
;
384 trigger
->name
= name_copy
;
390 enum lttng_trigger_status
lttng_trigger_get_name(
391 const struct lttng_trigger
*trigger
, const char **name
)
393 enum lttng_trigger_status status
= LTTNG_TRIGGER_STATUS_OK
;
395 if (!trigger
|| !name
) {
396 status
= LTTNG_TRIGGER_STATUS_INVALID
;
400 if (!trigger
->name
) {
401 status
= LTTNG_TRIGGER_STATUS_UNSET
;
404 *name
= trigger
->name
;
410 int lttng_trigger_assign_name(struct lttng_trigger
*dst
,
411 const struct lttng_trigger
*src
)
414 enum lttng_trigger_status status
;
416 status
= lttng_trigger_set_name(dst
, src
->name
);
417 if (status
!= LTTNG_TRIGGER_STATUS_OK
) {
419 ERR("Failed to set name for trigger");
427 void lttng_trigger_set_tracer_token(struct lttng_trigger
*trigger
,
431 LTTNG_OPTIONAL_SET(&trigger
->tracer_token
, token
);
435 uint64_t lttng_trigger_get_tracer_token(const struct lttng_trigger
*trigger
)
439 return LTTNG_OPTIONAL_GET(trigger
->tracer_token
);
443 int lttng_trigger_generate_name(struct lttng_trigger
*trigger
,
447 char *generated_name
= NULL
;
449 ret
= asprintf(&generated_name
, "T%" PRIu64
"", unique_id
);
451 ERR("Failed to generate trigger name");
458 trigger
->name
= generated_name
;
464 void lttng_trigger_get(struct lttng_trigger
*trigger
)
466 urcu_ref_get(&trigger
->ref
);
470 void lttng_trigger_put(struct lttng_trigger
*trigger
)
476 urcu_ref_put(&trigger
->ref
, trigger_destroy_ref
);
479 static void delete_trigger_array_element(void *ptr
)
481 struct lttng_trigger
*trigger
= ptr
;
483 lttng_trigger_put(trigger
);
487 struct lttng_triggers
*lttng_triggers_create(void)
489 struct lttng_triggers
*triggers
= NULL
;
491 triggers
= zmalloc(sizeof(*triggers
));
496 lttng_dynamic_pointer_array_init(&triggers
->array
, delete_trigger_array_element
);
503 struct lttng_trigger
*lttng_triggers_borrow_mutable_at_index(
504 const struct lttng_triggers
*triggers
, unsigned int index
)
506 struct lttng_trigger
*trigger
= NULL
;
509 if (index
>= lttng_dynamic_pointer_array_get_count(&triggers
->array
)) {
513 trigger
= (struct lttng_trigger
*)
514 lttng_dynamic_pointer_array_get_pointer(
515 &triggers
->array
, index
);
521 int lttng_triggers_add(
522 struct lttng_triggers
*triggers
, struct lttng_trigger
*trigger
)
529 lttng_trigger_get(trigger
);
531 ret
= lttng_dynamic_pointer_array_add_pointer(&triggers
->array
, trigger
);
533 lttng_trigger_put(trigger
);
539 const struct lttng_trigger
*lttng_triggers_get_at_index(
540 const struct lttng_triggers
*triggers
, unsigned int index
)
542 return lttng_triggers_borrow_mutable_at_index(triggers
, index
);
545 enum lttng_trigger_status
lttng_triggers_get_count(const struct lttng_triggers
*triggers
, unsigned int *count
)
547 enum lttng_trigger_status status
= LTTNG_TRIGGER_STATUS_OK
;
549 if (!triggers
|| !count
) {
550 status
= LTTNG_TRIGGER_STATUS_INVALID
;
554 *count
= lttng_dynamic_pointer_array_get_count(&triggers
->array
);
559 void lttng_triggers_destroy(struct lttng_triggers
*triggers
)
565 lttng_dynamic_pointer_array_reset(&triggers
->array
);
569 int lttng_triggers_serialize(const struct lttng_triggers
*triggers
,
570 struct lttng_payload
*payload
)
573 unsigned int i
, count
;
574 size_t size_before_payload
;
575 struct lttng_triggers_comm triggers_comm
= {};
576 struct lttng_triggers_comm
*header
;
577 enum lttng_trigger_status status
;
578 const size_t header_offset
= payload
->buffer
.size
;
580 status
= lttng_triggers_get_count(triggers
, &count
);
581 if (status
!= LTTNG_TRIGGER_STATUS_OK
) {
582 ret
= LTTNG_ERR_INVALID
;
586 triggers_comm
.count
= count
;
588 /* Placeholder header; updated at the end. */
589 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &triggers_comm
,
590 sizeof(triggers_comm
));
595 size_before_payload
= payload
->buffer
.size
;
597 for (i
= 0; i
< count
; i
++) {
598 const struct lttng_trigger
*trigger
=
599 lttng_triggers_get_at_index(triggers
, i
);
603 ret
= lttng_trigger_serialize(trigger
, payload
);
609 /* Update payload size. */
610 header
= (struct lttng_triggers_comm
*) ((char *) payload
->buffer
.data
+ header_offset
);
611 header
->length
= payload
->buffer
.size
- size_before_payload
;
617 ssize_t
lttng_triggers_create_from_payload(
618 struct lttng_payload_view
*src_view
,
619 struct lttng_triggers
**triggers
)
621 ssize_t ret
, offset
= 0, triggers_size
= 0;
623 const struct lttng_triggers_comm
*triggers_comm
;
624 struct lttng_triggers
*local_triggers
= NULL
;
626 if (!src_view
|| !triggers
) {
631 /* lttng_trigger_comms header */
632 triggers_comm
= (const struct lttng_triggers_comm
*) src_view
->buffer
.data
;
633 offset
+= sizeof(*triggers_comm
);
635 local_triggers
= lttng_triggers_create();
636 if (!local_triggers
) {
641 for (i
= 0; i
< triggers_comm
->count
; i
++) {
642 struct lttng_trigger
*trigger
= NULL
;
643 struct lttng_payload_view trigger_view
=
644 lttng_payload_view_from_view(src_view
, offset
, -1);
645 ssize_t trigger_size
;
647 trigger_size
= lttng_trigger_create_from_payload(
648 &trigger_view
, &trigger
);
649 if (trigger_size
< 0) {
654 /* Transfer ownership of the trigger to the collection. */
655 ret
= lttng_triggers_add(local_triggers
, trigger
);
656 lttng_trigger_put(trigger
);
662 offset
+= trigger_size
;
663 triggers_size
+= trigger_size
;
666 /* Unexpected size of inner-elements; the buffer is corrupted. */
667 if ((ssize_t
) triggers_comm
->length
!= triggers_size
) {
672 /* Pass ownership to caller. */
673 *triggers
= local_triggers
;
674 local_triggers
= NULL
;
679 lttng_triggers_destroy(local_triggers
);
684 const struct lttng_credentials
*lttng_trigger_get_credentials(
685 const struct lttng_trigger
*trigger
)
687 return &trigger
->creds
;
691 void lttng_trigger_set_credentials(struct lttng_trigger
*trigger
,
692 const struct lttng_credentials
*creds
)
695 trigger
->creds
= *creds
;
698 enum lttng_trigger_status
lttng_trigger_set_owner_uid(
699 struct lttng_trigger
*trigger
, uid_t uid
)
701 enum lttng_trigger_status ret
= LTTNG_TRIGGER_STATUS_OK
;
702 const struct lttng_credentials creds
= {
703 .uid
= LTTNG_OPTIONAL_INIT_VALUE(uid
),
704 .gid
= LTTNG_OPTIONAL_INIT_UNSET
,
708 ret
= LTTNG_TRIGGER_STATUS_INVALID
;
712 /* Client-side validation only to report a clearer error. */
713 if (geteuid() != 0) {
714 ret
= LTTNG_TRIGGER_STATUS_PERMISSION_DENIED
;
718 lttng_trigger_set_credentials(trigger
, &creds
);
724 enum lttng_trigger_status
lttng_trigger_get_owner_uid(
725 const struct lttng_trigger
*trigger
, uid_t
*uid
)
727 enum lttng_trigger_status ret
= LTTNG_TRIGGER_STATUS_OK
;
728 const struct lttng_credentials
*creds
= NULL
;
730 if (!trigger
|| !uid
) {
731 ret
= LTTNG_TRIGGER_STATUS_INVALID
;
735 if (!trigger
->creds
.uid
.is_set
) {
736 ret
= LTTNG_TRIGGER_STATUS_UNSET
;
740 creds
= lttng_trigger_get_credentials(trigger
);
741 *uid
= lttng_credentials_get_uid(creds
);
748 enum lttng_domain_type
lttng_trigger_get_underlying_domain_type_restriction(
749 const struct lttng_trigger
*trigger
)
751 enum lttng_domain_type type
= LTTNG_DOMAIN_NONE
;
752 const struct lttng_event_rule
*event_rule
;
753 enum lttng_condition_status c_status
;
754 enum lttng_condition_type c_type
;
757 assert(trigger
->condition
);
759 c_type
= lttng_condition_get_type(trigger
->condition
);
760 assert (c_type
!= LTTNG_CONDITION_TYPE_UNKNOWN
);
763 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE
:
764 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
:
765 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
:
766 /* Apply to any domain. */
767 type
= LTTNG_DOMAIN_NONE
;
769 case LTTNG_CONDITION_TYPE_ON_EVENT
:
770 /* Return the domain of the event rule. */
771 c_status
= lttng_condition_on_event_get_rule(
772 trigger
->condition
, &event_rule
);
773 assert(c_status
== LTTNG_CONDITION_STATUS_OK
);
774 type
= lttng_event_rule_get_domain_type(event_rule
);
776 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
777 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
778 /* Return the domain of the channel being monitored. */
779 c_status
= lttng_condition_buffer_usage_get_domain_type(
780 trigger
->condition
, &type
);
781 assert(c_status
== LTTNG_CONDITION_STATUS_OK
);
791 * Generate bytecode related to the trigger.
792 * On success LTTNG_OK. On error, returns lttng_error code.
795 enum lttng_error_code
lttng_trigger_generate_bytecode(
796 struct lttng_trigger
*trigger
,
797 const struct lttng_credentials
*creds
)
799 enum lttng_error_code ret
;
800 struct lttng_condition
*condition
= NULL
;
802 condition
= lttng_trigger_get_condition(trigger
);
804 ret
= LTTNG_ERR_INVALID_TRIGGER
;
808 switch (lttng_condition_get_type(condition
)) {
809 case LTTNG_CONDITION_TYPE_ON_EVENT
:
811 struct lttng_event_rule
*event_rule
;
812 const enum lttng_condition_status condition_status
=
813 lttng_condition_on_event_borrow_rule_mutable(
814 condition
, &event_rule
);
816 assert(condition_status
== LTTNG_CONDITION_STATUS_OK
);
818 /* Generate the filter bytecode. */
819 ret
= lttng_event_rule_generate_filter_bytecode(
821 if (ret
!= LTTNG_OK
) {
825 /* Generate the capture bytecode. */
826 ret
= lttng_condition_on_event_generate_capture_descriptor_bytecode(
828 if (ret
!= LTTNG_OK
) {
844 struct lttng_trigger
*lttng_trigger_copy(const struct lttng_trigger
*trigger
)
847 struct lttng_payload copy_buffer
;
848 struct lttng_trigger
*copy
= NULL
;
850 lttng_payload_init(©_buffer
);
852 ret
= lttng_trigger_serialize(trigger
, ©_buffer
);
858 struct lttng_payload_view view
=
859 lttng_payload_view_from_payload(
860 ©_buffer
, 0, -1);
861 ret
= lttng_trigger_create_from_payload(
870 lttng_payload_reset(©_buffer
);
875 bool lttng_trigger_needs_tracer_notifier(const struct lttng_trigger
*trigger
)
877 bool needs_tracer_notifier
= false;
878 const struct lttng_condition
*condition
=
879 lttng_trigger_get_const_condition(trigger
);
881 switch (lttng_condition_get_type(condition
)) {
882 case LTTNG_CONDITION_TYPE_ON_EVENT
:
883 needs_tracer_notifier
= true;
885 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE
:
886 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
887 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
888 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
:
889 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
:
891 case LTTNG_CONDITION_TYPE_UNKNOWN
:
896 return needs_tracer_notifier
;