common: compile libcommon as C++
[lttng-tools.git] / src / common / trigger.cpp
CommitLineData
a58c490f 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
a58c490f 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
a58c490f 5 *
a58c490f
JG
6 */
7
3da864a9 8#include <common/credentials.h>
a02903c0 9#include <common/dynamic-array.h>
9c374932 10#include <common/error.h>
6a751b95 11#include <common/mi-lttng.h>
3da864a9 12#include <common/optional.h>
9c374932
JR
13#include <common/payload-view.h>
14#include <common/payload.h>
242388e4 15#include <inttypes.h>
9c374932
JR
16#include <lttng/action/action-internal.h>
17#include <lttng/condition/buffer-usage.h>
18#include <lttng/condition/condition-internal.h>
670a26e4
JR
19#include <lttng/condition/event-rule-matches-internal.h>
20#include <lttng/condition/event-rule-matches.h>
9c374932 21#include <lttng/domain.h>
6a751b95 22#include <lttng/error-query-internal.h>
9c374932
JR
23#include <lttng/event-expr-internal.h>
24#include <lttng/event-rule/event-rule-internal.h>
25#include <lttng/trigger/trigger-internal.h>
26#include <pthread.h>
a58c490f 27
b61776fb 28bool lttng_trigger_validate(const struct lttng_trigger *trigger)
a58c490f
JG
29{
30 bool valid;
31
32 if (!trigger) {
33 valid = false;
34 goto end;
35 }
36
64eafdf6
JR
37 if (!trigger->creds.uid.is_set) {
38 valid = false;
39 goto end;
40 }
41
a58c490f
JG
42 valid = lttng_condition_validate(trigger->condition) &&
43 lttng_action_validate(trigger->action);
44end:
45 return valid;
46}
47
48struct lttng_trigger *lttng_trigger_create(
49 struct lttng_condition *condition,
50 struct lttng_action *action)
51{
52 struct lttng_trigger *trigger = NULL;
53
54 if (!condition || !action) {
55 goto end;
56 }
57
a6bc4ca9 58 trigger = (lttng_trigger *) zmalloc(sizeof(struct lttng_trigger));
a58c490f
JG
59 if (!trigger) {
60 goto end;
61 }
62
f01d28b4
JR
63 urcu_ref_init(&trigger->ref);
64
7ca172c1 65 lttng_condition_get(condition);
a58c490f 66 trigger->condition = condition;
7ca172c1
JR
67
68 lttng_action_get(action);
a58c490f 69 trigger->action = action;
3da864a9 70
9c374932
JR
71 pthread_mutex_init(&trigger->lock, NULL);
72 trigger->registered = false;
73
a58c490f
JG
74end:
75 return trigger;
76}
77
7ca172c1
JR
78/*
79 * Note: the lack of reference counting 'get' on the condition object is normal.
80 * This API was exposed as such in 2.11. The client is not expected to call
81 * lttng_condition_destroy on the returned object.
82 */
a58c490f
JG
83struct lttng_condition *lttng_trigger_get_condition(
84 struct lttng_trigger *trigger)
85{
86 return trigger ? trigger->condition : NULL;
87}
88
9b63a4aa
JG
89const struct lttng_condition *lttng_trigger_get_const_condition(
90 const struct lttng_trigger *trigger)
91{
0de2479d 92 return trigger ? trigger->condition : NULL;
9b63a4aa
JG
93}
94
7ca172c1
JR
95/*
96 * Note: the lack of reference counting 'get' on the action object is normal.
97 * This API was exposed as such in 2.11. The client is not expected to call
98 * lttng_action_destroy on the returned object.
99 */
e2ba1c78 100struct lttng_action *lttng_trigger_get_action(
a58c490f
JG
101 struct lttng_trigger *trigger)
102{
103 return trigger ? trigger->action : NULL;
104}
105
9b63a4aa
JG
106const struct lttng_action *lttng_trigger_get_const_action(
107 const struct lttng_trigger *trigger)
108{
0de2479d 109 return trigger ? trigger->action : NULL;
9b63a4aa
JG
110}
111
f01d28b4 112static void trigger_destroy_ref(struct urcu_ref *ref)
a58c490f 113{
f01d28b4
JR
114 struct lttng_trigger *trigger =
115 container_of(ref, struct lttng_trigger, ref);
7ca172c1
JR
116 struct lttng_action *action = lttng_trigger_get_action(trigger);
117 struct lttng_condition *condition =
118 lttng_trigger_get_condition(trigger);
119
a0377dfe
FD
120 LTTNG_ASSERT(action);
121 LTTNG_ASSERT(condition);
7ca172c1
JR
122
123 /* Release ownership. */
124 lttng_action_put(action);
125 lttng_condition_put(condition);
126
9c374932
JR
127 pthread_mutex_destroy(&trigger->lock);
128
242388e4 129 free(trigger->name);
a58c490f
JG
130 free(trigger);
131}
132
f01d28b4
JR
133void lttng_trigger_destroy(struct lttng_trigger *trigger)
134{
135 lttng_trigger_put(trigger);
136}
137
c0a66c84
JG
138ssize_t lttng_trigger_create_from_payload(
139 struct lttng_payload_view *src_view,
6808ef55 140 struct lttng_trigger **_trigger)
a58c490f 141{
242388e4 142 ssize_t ret, offset = 0, condition_size, action_size, name_size = 0;
a58c490f
JG
143 struct lttng_condition *condition = NULL;
144 struct lttng_action *action = NULL;
145 const struct lttng_trigger_comm *trigger_comm;
242388e4 146 const char *name = NULL;
64eafdf6
JR
147 struct lttng_credentials creds = {
148 .uid = LTTNG_OPTIONAL_INIT_UNSET,
149 .gid = LTTNG_OPTIONAL_INIT_UNSET,
150 };
6808ef55 151 struct lttng_trigger *trigger = NULL;
3e6e0df2
JG
152 const struct lttng_payload_view trigger_comm_view =
153 lttng_payload_view_from_view(
154 src_view, 0, sizeof(*trigger_comm));
a58c490f 155
6808ef55 156 if (!src_view || !_trigger) {
a58c490f
JG
157 ret = -1;
158 goto end;
159 }
160
3e6e0df2
JG
161 if (!lttng_payload_view_is_valid(&trigger_comm_view)) {
162 /* Payload not large enough to contain the header. */
163 ret = -1;
164 goto end;
165 }
166
a58c490f 167 /* lttng_trigger_comm header */
3e6e0df2 168 trigger_comm = (typeof(trigger_comm)) trigger_comm_view.buffer.data;
64eafdf6
JR
169
170 /* Set the trigger's creds. */
171 if (trigger_comm->uid > (uint64_t) ((uid_t) -1)) {
172 /* UID out of range for this platform. */
173 ret = -1;
174 goto end;
175 }
176
177 LTTNG_OPTIONAL_SET(&creds.uid, trigger_comm->uid);
178
a58c490f 179 offset += sizeof(*trigger_comm);
242388e4
JR
180
181 if (trigger_comm->name_length != 0) {
182 /* Name. */
183 const struct lttng_payload_view name_view =
184 lttng_payload_view_from_view(
3e6e0df2
JG
185 src_view, offset,
186 trigger_comm->name_length);
187
188 if (!lttng_payload_view_is_valid(&name_view)) {
189 ret = -1;
190 goto end;
191 }
242388e4
JR
192
193 name = name_view.buffer.data;
194 if (!lttng_buffer_view_contains_string(&name_view.buffer, name,
195 trigger_comm->name_length)) {
196 ret = -1;
197 goto end;
198 }
199
200 offset += trigger_comm->name_length;
201 name_size = trigger_comm->name_length;
202 }
203
c0a66c84
JG
204 {
205 /* struct lttng_condition */
206 struct lttng_payload_view condition_view =
207 lttng_payload_view_from_view(
208 src_view, offset, -1);
209
210 condition_size = lttng_condition_create_from_payload(&condition_view,
211 &condition);
212 }
a58c490f 213
a58c490f
JG
214 if (condition_size < 0) {
215 ret = condition_size;
216 goto end;
217 }
c0a66c84 218
a58c490f 219 offset += condition_size;
c0a66c84
JG
220 {
221 /* struct lttng_action */
222 struct lttng_payload_view action_view =
223 lttng_payload_view_from_view(
224 src_view, offset, -1);
225
226 action_size = lttng_action_create_from_payload(&action_view, &action);
227 }
a58c490f 228
a58c490f
JG
229 if (action_size < 0) {
230 ret = action_size;
231 goto end;
232 }
233 offset += action_size;
234
235 /* Unexpected size of inner-elements; the buffer is corrupted. */
242388e4 236 if ((ssize_t) trigger_comm->length != condition_size + action_size + name_size) {
a58c490f
JG
237 ret = -1;
238 goto error;
239 }
240
6808ef55
JG
241 trigger = lttng_trigger_create(condition, action);
242 if (!trigger) {
a58c490f
JG
243 ret = -1;
244 goto error;
245 }
c0a66c84 246
6808ef55 247 lttng_trigger_set_credentials(trigger, &creds);
64eafdf6 248
7ca172c1
JR
249 /*
250 * The trigger object owns references to the action and condition
251 * objects.
252 */
253 lttng_condition_put(condition);
254 condition = NULL;
255
256 lttng_action_put(action);
257 action = NULL;
258
242388e4
JR
259 if (name) {
260 const enum lttng_trigger_status status =
6808ef55 261 lttng_trigger_set_name(trigger, name);
242388e4
JR
262
263 if (status != LTTNG_TRIGGER_STATUS_OK) {
264 ret = -1;
265 goto end;
266 }
267 }
268
a58c490f 269 ret = offset;
7ca172c1 270
a58c490f 271error:
1065801b
JG
272 lttng_condition_put(condition);
273 lttng_action_put(action);
7ca172c1 274end:
f5d98ed9 275 if (ret >= 0) {
6808ef55
JG
276 *_trigger = trigger;
277 } else {
278 lttng_trigger_put(trigger);
279 }
280
a58c490f
JG
281 return ret;
282}
283
284/*
a58c490f
JG
285 * Both elements are stored contiguously, see their "*_comm" structure
286 * for the detailed format.
287 */
a02903c0 288int lttng_trigger_serialize(const struct lttng_trigger *trigger,
c0a66c84 289 struct lttng_payload *payload)
a58c490f 290{
3647288f 291 int ret;
242388e4 292 size_t header_offset, size_before_payload, size_name;
c0a66c84 293 struct lttng_trigger_comm trigger_comm = {};
3647288f 294 struct lttng_trigger_comm *header;
64eafdf6
JR
295 const struct lttng_credentials *creds = NULL;
296
297 creds = lttng_trigger_get_credentials(trigger);
a0377dfe 298 LTTNG_ASSERT(creds);
64eafdf6
JR
299
300 trigger_comm.uid = LTTNG_OPTIONAL_GET(creds->uid);
a58c490f 301
242388e4
JR
302 if (trigger->name != NULL) {
303 size_name = strlen(trigger->name) + 1;
304 } else {
305 size_name = 0;
306 }
307
308 trigger_comm.name_length = size_name;
309
c0a66c84
JG
310 header_offset = payload->buffer.size;
311 ret = lttng_dynamic_buffer_append(&payload->buffer, &trigger_comm,
3647288f
JG
312 sizeof(trigger_comm));
313 if (ret) {
a58c490f
JG
314 goto end;
315 }
316
c0a66c84 317 size_before_payload = payload->buffer.size;
242388e4
JR
318
319 /* Trigger name. */
320 ret = lttng_dynamic_buffer_append(
321 &payload->buffer, trigger->name, size_name);
322 if (ret) {
323 goto end;
324 }
325
c0a66c84 326 ret = lttng_condition_serialize(trigger->condition, payload);
3647288f 327 if (ret) {
a58c490f
JG
328 goto end;
329 }
a58c490f 330
c0a66c84 331 ret = lttng_action_serialize(trigger->action, payload);
3647288f 332 if (ret) {
a58c490f
JG
333 goto end;
334 }
a58c490f 335
3647288f 336 /* Update payload size. */
c0a66c84
JG
337 header = (typeof(header)) (payload->buffer.data + header_offset);
338 header->length = payload->buffer.size - size_before_payload;
a58c490f
JG
339end:
340 return ret;
341}
3da864a9 342
85c06c44
JR
343bool lttng_trigger_is_equal(
344 const struct lttng_trigger *a, const struct lttng_trigger *b)
345{
0efb2ad7
JG
346 if (!!a->name != !!b->name) {
347 /* Both must be either anonymous or named. */
348 return false;
349 }
350
351 if (a->name && strcmp(a->name, b->name) != 0) {
1ca78886
FD
352 return false;
353 }
354
85c06c44
JR
355 if (!lttng_condition_is_equal(a->condition, b->condition)) {
356 return false;
357 }
358
359 if (!lttng_action_is_equal(a->action, b->action)) {
360 return false;
361 }
362
363 if (!lttng_credentials_is_equal(lttng_trigger_get_credentials(a),
364 lttng_trigger_get_credentials(b))) {
365 return false;
366 }
367
f2bda80e
JG
368 if (a->is_hidden != b->is_hidden) {
369 return false;
370 }
371
85c06c44
JR
372 return true;
373}
374
f2bda80e
JG
375bool lttng_trigger_is_hidden(const struct lttng_trigger *trigger)
376{
377 return trigger->is_hidden;
378}
379
f2bda80e
JG
380void lttng_trigger_set_hidden(struct lttng_trigger *trigger)
381{
a0377dfe 382 LTTNG_ASSERT(!trigger->is_hidden);
f2bda80e
JG
383 trigger->is_hidden = true;
384}
385
242388e4
JR
386enum lttng_trigger_status lttng_trigger_set_name(struct lttng_trigger *trigger,
387 const char* name)
388{
389 char *name_copy = NULL;
390 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
391
a5c2d2a7 392 if (!trigger) {
242388e4
JR
393 status = LTTNG_TRIGGER_STATUS_INVALID;
394 goto end;
395 }
396
a5c2d2a7
JG
397 if (name) {
398 name_copy = strdup(name);
399 if (!name_copy) {
400 status = LTTNG_TRIGGER_STATUS_ERROR;
401 goto end;
402 }
242388e4
JR
403 }
404
405 free(trigger->name);
406
407 trigger->name = name_copy;
408 name_copy = NULL;
409end:
410 return status;
411}
412
413enum lttng_trigger_status lttng_trigger_get_name(
414 const struct lttng_trigger *trigger, const char **name)
415{
416 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
417
418 if (!trigger || !name) {
419 status = LTTNG_TRIGGER_STATUS_INVALID;
420 goto end;
421 }
422
423 if (!trigger->name) {
424 status = LTTNG_TRIGGER_STATUS_UNSET;
425 }
426
427 *name = trigger->name;
428end:
429 return status;
430}
431
242388e4
JR
432int lttng_trigger_assign_name(struct lttng_trigger *dst,
433 const struct lttng_trigger *src)
434{
435 int ret = 0;
436 enum lttng_trigger_status status;
437
438 status = lttng_trigger_set_name(dst, src->name);
439 if (status != LTTNG_TRIGGER_STATUS_OK) {
440 ret = -1;
441 ERR("Failed to set name for trigger");
442 goto end;
443 }
444end:
445 return ret;
446}
447
e6887944
JR
448void lttng_trigger_set_tracer_token(struct lttng_trigger *trigger,
449 uint64_t token)
450{
a0377dfe 451 LTTNG_ASSERT(trigger);
e6887944
JR
452 LTTNG_OPTIONAL_SET(&trigger->tracer_token, token);
453}
454
e6887944
JR
455uint64_t lttng_trigger_get_tracer_token(const struct lttng_trigger *trigger)
456{
a0377dfe 457 LTTNG_ASSERT(trigger);
e6887944
JR
458
459 return LTTNG_OPTIONAL_GET(trigger->tracer_token);
460}
461
242388e4
JR
462int lttng_trigger_generate_name(struct lttng_trigger *trigger,
463 uint64_t unique_id)
464{
465 int ret = 0;
466 char *generated_name = NULL;
467
80ea4bfa 468 ret = asprintf(&generated_name, "trigger%" PRIu64 "", unique_id);
242388e4
JR
469 if (ret < 0) {
470 ERR("Failed to generate trigger name");
471 ret = -1;
472 goto end;
473 }
474
475 ret = 0;
476 free(trigger->name);
477 trigger->name = generated_name;
478end:
479 return ret;
480}
481
f01d28b4
JR
482void lttng_trigger_get(struct lttng_trigger *trigger)
483{
484 urcu_ref_get(&trigger->ref);
485}
486
f01d28b4
JR
487void lttng_trigger_put(struct lttng_trigger *trigger)
488{
489 if (!trigger) {
490 return;
491 }
492
493 urcu_ref_put(&trigger->ref , trigger_destroy_ref);
494}
495
a02903c0
JR
496static void delete_trigger_array_element(void *ptr)
497{
a6bc4ca9 498 struct lttng_trigger *trigger = (lttng_trigger *) ptr;
a02903c0
JR
499
500 lttng_trigger_put(trigger);
501}
502
a02903c0
JR
503struct lttng_triggers *lttng_triggers_create(void)
504{
505 struct lttng_triggers *triggers = NULL;
506
a6bc4ca9 507 triggers = (lttng_triggers *) zmalloc(sizeof(*triggers));
a02903c0
JR
508 if (!triggers) {
509 goto end;
510 }
511
512 lttng_dynamic_pointer_array_init(&triggers->array, delete_trigger_array_element);
513
514end:
515 return triggers;
516}
517
a02903c0
JR
518struct lttng_trigger *lttng_triggers_borrow_mutable_at_index(
519 const struct lttng_triggers *triggers, unsigned int index)
520{
521 struct lttng_trigger *trigger = NULL;
522
a0377dfe 523 LTTNG_ASSERT(triggers);
a02903c0
JR
524 if (index >= lttng_dynamic_pointer_array_get_count(&triggers->array)) {
525 goto end;
526 }
527
528 trigger = (struct lttng_trigger *)
529 lttng_dynamic_pointer_array_get_pointer(
530 &triggers->array, index);
531end:
532 return trigger;
533}
534
a02903c0
JR
535int lttng_triggers_add(
536 struct lttng_triggers *triggers, struct lttng_trigger *trigger)
537{
538 int ret;
539
a0377dfe
FD
540 LTTNG_ASSERT(triggers);
541 LTTNG_ASSERT(trigger);
a02903c0
JR
542
543 lttng_trigger_get(trigger);
544
545 ret = lttng_dynamic_pointer_array_add_pointer(&triggers->array, trigger);
546 if (ret) {
547 lttng_trigger_put(trigger);
548 }
549
550 return ret;
551}
552
f2bda80e
JG
553int lttng_triggers_remove_hidden_triggers(struct lttng_triggers *triggers)
554{
555 int ret;
556 unsigned int trigger_count, i = 0;
557 enum lttng_trigger_status trigger_status;
558
a0377dfe 559 LTTNG_ASSERT(triggers);
f2bda80e
JG
560
561 trigger_status = lttng_triggers_get_count(triggers, &trigger_count);
a0377dfe 562 LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK);
f2bda80e
JG
563
564 while (i < trigger_count) {
565 const struct lttng_trigger *trigger =
566 lttng_triggers_get_at_index(triggers, i);
567
568 if (lttng_trigger_is_hidden(trigger)) {
569 ret = lttng_dynamic_pointer_array_remove_pointer(
570 &triggers->array, i);
571 if (ret) {
572 goto end;
573 }
574
575 trigger_count--;
576 } else {
577 i++;
578 }
579 }
580
581 ret = 0;
582end:
583 return ret;
584}
585
a02903c0
JR
586const struct lttng_trigger *lttng_triggers_get_at_index(
587 const struct lttng_triggers *triggers, unsigned int index)
588{
589 return lttng_triggers_borrow_mutable_at_index(triggers, index);
590}
591
592enum lttng_trigger_status lttng_triggers_get_count(const struct lttng_triggers *triggers, unsigned int *count)
593{
594 enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
595
596 if (!triggers || !count) {
597 status = LTTNG_TRIGGER_STATUS_INVALID;
598 goto end;
599 }
600
601 *count = lttng_dynamic_pointer_array_get_count(&triggers->array);
602end:
603 return status;
604}
605
606void lttng_triggers_destroy(struct lttng_triggers *triggers)
607{
608 if (!triggers) {
609 return;
610 }
611
612 lttng_dynamic_pointer_array_reset(&triggers->array);
613 free(triggers);
614}
615
616int lttng_triggers_serialize(const struct lttng_triggers *triggers,
617 struct lttng_payload *payload)
618{
619 int ret;
620 unsigned int i, count;
621 size_t size_before_payload;
622 struct lttng_triggers_comm triggers_comm = {};
623 struct lttng_triggers_comm *header;
624 enum lttng_trigger_status status;
625 const size_t header_offset = payload->buffer.size;
626
627 status = lttng_triggers_get_count(triggers, &count);
628 if (status != LTTNG_TRIGGER_STATUS_OK) {
629 ret = LTTNG_ERR_INVALID;
630 goto end;
631 }
632
633 triggers_comm.count = count;
634
635 /* Placeholder header; updated at the end. */
636 ret = lttng_dynamic_buffer_append(&payload->buffer, &triggers_comm,
637 sizeof(triggers_comm));
638 if (ret) {
639 goto end;
640 }
641
642 size_before_payload = payload->buffer.size;
643
644 for (i = 0; i < count; i++) {
645 const struct lttng_trigger *trigger =
646 lttng_triggers_get_at_index(triggers, i);
647
a0377dfe 648 LTTNG_ASSERT(trigger);
a02903c0
JR
649
650 ret = lttng_trigger_serialize(trigger, payload);
651 if (ret) {
652 goto end;
653 }
654 }
655
656 /* Update payload size. */
657 header = (struct lttng_triggers_comm *) ((char *) payload->buffer.data + header_offset);
658 header->length = payload->buffer.size - size_before_payload;
659end:
660 return ret;
661}
662
a02903c0
JR
663ssize_t lttng_triggers_create_from_payload(
664 struct lttng_payload_view *src_view,
665 struct lttng_triggers **triggers)
666{
667 ssize_t ret, offset = 0, triggers_size = 0;
668 unsigned int i;
669 const struct lttng_triggers_comm *triggers_comm;
670 struct lttng_triggers *local_triggers = NULL;
671
672 if (!src_view || !triggers) {
673 ret = -1;
674 goto error;
675 }
676
677 /* lttng_trigger_comms header */
678 triggers_comm = (const struct lttng_triggers_comm *) src_view->buffer.data;
679 offset += sizeof(*triggers_comm);
680
681 local_triggers = lttng_triggers_create();
682 if (!local_triggers) {
683 ret = -1;
684 goto error;
685 }
686
687 for (i = 0; i < triggers_comm->count; i++) {
688 struct lttng_trigger *trigger = NULL;
689 struct lttng_payload_view trigger_view =
690 lttng_payload_view_from_view(src_view, offset, -1);
691 ssize_t trigger_size;
692
693 trigger_size = lttng_trigger_create_from_payload(
694 &trigger_view, &trigger);
695 if (trigger_size < 0) {
696 ret = trigger_size;
697 goto error;
698 }
699
700 /* Transfer ownership of the trigger to the collection. */
701 ret = lttng_triggers_add(local_triggers, trigger);
702 lttng_trigger_put(trigger);
703 if (ret < 0) {
704 ret = -1;
705 goto error;
706 }
707
708 offset += trigger_size;
709 triggers_size += trigger_size;
710 }
711
712 /* Unexpected size of inner-elements; the buffer is corrupted. */
713 if ((ssize_t) triggers_comm->length != triggers_size) {
714 ret = -1;
715 goto error;
716 }
717
718 /* Pass ownership to caller. */
719 *triggers = local_triggers;
720 local_triggers = NULL;
721
722 ret = offset;
723error:
724
725 lttng_triggers_destroy(local_triggers);
726 return ret;
727}
728
3da864a9
JR
729const struct lttng_credentials *lttng_trigger_get_credentials(
730 const struct lttng_trigger *trigger)
731{
64eafdf6 732 return &trigger->creds;
3da864a9
JR
733}
734
64eafdf6 735void lttng_trigger_set_credentials(struct lttng_trigger *trigger,
3da864a9
JR
736 const struct lttng_credentials *creds)
737{
a0377dfe 738 LTTNG_ASSERT(creds);
64eafdf6
JR
739 trigger->creds = *creds;
740}
741
742enum lttng_trigger_status lttng_trigger_set_owner_uid(
743 struct lttng_trigger *trigger, uid_t uid)
744{
745 enum lttng_trigger_status ret = LTTNG_TRIGGER_STATUS_OK;
d84c8ae3 746 const uid_t euid = geteuid();
64eafdf6
JR
747 const struct lttng_credentials creds = {
748 .uid = LTTNG_OPTIONAL_INIT_VALUE(uid),
749 .gid = LTTNG_OPTIONAL_INIT_UNSET,
750 };
751
752 if (!trigger) {
753 ret = LTTNG_TRIGGER_STATUS_INVALID;
754 goto end;
755 }
756
757 /* Client-side validation only to report a clearer error. */
d84c8ae3 758 if (euid != 0 && euid != uid) {
64eafdf6
JR
759 ret = LTTNG_TRIGGER_STATUS_PERMISSION_DENIED;
760 goto end;
761 }
762
763 lttng_trigger_set_credentials(trigger, &creds);
764
765end:
766 return ret;
767}
768
769enum lttng_trigger_status lttng_trigger_get_owner_uid(
770 const struct lttng_trigger *trigger, uid_t *uid)
771{
772 enum lttng_trigger_status ret = LTTNG_TRIGGER_STATUS_OK;
773 const struct lttng_credentials *creds = NULL;
774
775 if (!trigger || !uid ) {
776 ret = LTTNG_TRIGGER_STATUS_INVALID;
777 goto end;
778 }
779
780 if (!trigger->creds.uid.is_set ) {
781 ret = LTTNG_TRIGGER_STATUS_UNSET;
782 goto end;
783 }
784
785 creds = lttng_trigger_get_credentials(trigger);
786 *uid = lttng_credentials_get_uid(creds);
787
788end:
789 return ret;
3da864a9 790}
5c504c41 791
91c96f62
JR
792enum lttng_domain_type lttng_trigger_get_underlying_domain_type_restriction(
793 const struct lttng_trigger *trigger)
794{
795 enum lttng_domain_type type = LTTNG_DOMAIN_NONE;
796 const struct lttng_event_rule *event_rule;
797 enum lttng_condition_status c_status;
798 enum lttng_condition_type c_type;
799
a0377dfe
FD
800 LTTNG_ASSERT(trigger);
801 LTTNG_ASSERT(trigger->condition);
91c96f62
JR
802
803 c_type = lttng_condition_get_type(trigger->condition);
804 assert (c_type != LTTNG_CONDITION_TYPE_UNKNOWN);
805
806 switch (c_type) {
807 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
808 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
809 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
810 /* Apply to any domain. */
811 type = LTTNG_DOMAIN_NONE;
812 break;
8dbb86b8 813 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES:
91c96f62 814 /* Return the domain of the event rule. */
8dbb86b8 815 c_status = lttng_condition_event_rule_matches_get_rule(
91c96f62 816 trigger->condition, &event_rule);
a0377dfe 817 LTTNG_ASSERT(c_status == LTTNG_CONDITION_STATUS_OK);
91c96f62
JR
818 type = lttng_event_rule_get_domain_type(event_rule);
819 break;
820 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
821 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
822 /* Return the domain of the channel being monitored. */
823 c_status = lttng_condition_buffer_usage_get_domain_type(
824 trigger->condition, &type);
a0377dfe 825 LTTNG_ASSERT(c_status == LTTNG_CONDITION_STATUS_OK);
91c96f62
JR
826 break;
827 default:
828 abort();
829 }
830
831 return type;
832}
58daac01
JR
833
834/*
835 * Generate bytecode related to the trigger.
836 * On success LTTNG_OK. On error, returns lttng_error code.
837 */
58daac01
JR
838enum lttng_error_code lttng_trigger_generate_bytecode(
839 struct lttng_trigger *trigger,
840 const struct lttng_credentials *creds)
841{
842 enum lttng_error_code ret;
843 struct lttng_condition *condition = NULL;
844
845 condition = lttng_trigger_get_condition(trigger);
846 if (!condition) {
847 ret = LTTNG_ERR_INVALID_TRIGGER;
848 goto end;
849 }
850
851 switch (lttng_condition_get_type(condition)) {
8dbb86b8 852 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES:
58daac01
JR
853 {
854 struct lttng_event_rule *event_rule;
855 const enum lttng_condition_status condition_status =
8dbb86b8
JR
856 lttng_condition_event_rule_matches_borrow_rule_mutable(
857 condition, &event_rule);
58daac01 858
a0377dfe 859 LTTNG_ASSERT(condition_status == LTTNG_CONDITION_STATUS_OK);
f2e97f59
JR
860
861 /* Generate the filter bytecode. */
58daac01
JR
862 ret = lttng_event_rule_generate_filter_bytecode(
863 event_rule, creds);
864 if (ret != LTTNG_OK) {
865 goto end;
866 }
867
f2e97f59 868 /* Generate the capture bytecode. */
8dbb86b8 869 ret = lttng_condition_event_rule_matches_generate_capture_descriptor_bytecode(
f2e97f59
JR
870 condition);
871 if (ret != LTTNG_OK) {
872 goto end;
873 }
874
58daac01
JR
875 ret = LTTNG_OK;
876 break;
877 }
878 default:
879 ret = LTTNG_OK;
880 break;
881 }
882end:
883 return ret;
884}
b61776fb 885
b61776fb
SM
886struct lttng_trigger *lttng_trigger_copy(const struct lttng_trigger *trigger)
887{
888 int ret;
889 struct lttng_payload copy_buffer;
94dbd8e4
JG
890 struct lttng_condition *condition_copy = NULL;
891 struct lttng_action *action_copy = NULL;
b61776fb 892 struct lttng_trigger *copy = NULL;
94dbd8e4
JG
893 enum lttng_trigger_status trigger_status;
894 const char *trigger_name;
895 uid_t trigger_owner_uid;
b61776fb
SM
896
897 lttng_payload_init(&copy_buffer);
898
94dbd8e4 899 ret = lttng_condition_serialize(trigger->condition, &copy_buffer);
b61776fb
SM
900 if (ret < 0) {
901 goto end;
902 }
903
904 {
905 struct lttng_payload_view view =
906 lttng_payload_view_from_payload(
907 &copy_buffer, 0, -1);
94dbd8e4
JG
908
909 ret = lttng_condition_create_from_payload(
910 &view, &condition_copy);
911 if (ret < 0) {
912 goto end;
913 }
914 }
915
916 lttng_payload_clear(&copy_buffer);
917
918 ret = lttng_action_serialize(trigger->action, &copy_buffer);
919 if (ret < 0) {
920 goto end;
921 }
922
923 {
924 struct lttng_payload_view view =
925 lttng_payload_view_from_payload(
926 &copy_buffer, 0, -1);
927
928 ret = lttng_action_create_from_payload(
929 &view, &action_copy);
b61776fb 930 if (ret < 0) {
b61776fb
SM
931 goto end;
932 }
933 }
934
94dbd8e4
JG
935 copy = lttng_trigger_create(condition_copy, action_copy);
936 if (!copy) {
937 ERR("Failed to allocate trigger during trigger copy");
938 goto end;
939 }
940
941 trigger_status = lttng_trigger_get_name(trigger, &trigger_name);
942 switch (trigger_status) {
943 case LTTNG_TRIGGER_STATUS_OK:
944 trigger_status = lttng_trigger_set_name(copy, trigger_name);
945 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
946 ERR("Failed to set name of new trigger during copy");
947 goto error_cleanup_trigger;
948 }
949 break;
950 case LTTNG_TRIGGER_STATUS_UNSET:
951 break;
952 default:
953 ERR("Failed to get name of original trigger during copy");
954 goto error_cleanup_trigger;
955 }
956
957 trigger_status = lttng_trigger_get_owner_uid(
958 trigger, &trigger_owner_uid);
959 switch (trigger_status) {
960 case LTTNG_TRIGGER_STATUS_OK:
961 LTTNG_OPTIONAL_SET(&copy->creds.uid, trigger_owner_uid);
962 break;
963 case LTTNG_TRIGGER_STATUS_UNSET:
964 break;
965 default:
966 ERR("Failed to get owner uid of original trigger during copy");
967 goto error_cleanup_trigger;
968 }
969
970 copy->tracer_token = trigger->tracer_token;
971 copy->registered = trigger->registered;
f2bda80e 972 copy->is_hidden = trigger->is_hidden;
94dbd8e4
JG
973 goto end;
974
975error_cleanup_trigger:
976 lttng_trigger_destroy(copy);
977 copy = NULL;
b61776fb 978end:
94dbd8e4
JG
979 lttng_condition_put(condition_copy);
980 lttng_action_put(action_copy);
b61776fb
SM
981 lttng_payload_reset(&copy_buffer);
982 return copy;
983}
c738df17 984
c738df17
FD
985bool lttng_trigger_needs_tracer_notifier(const struct lttng_trigger *trigger)
986{
987 bool needs_tracer_notifier = false;
988 const struct lttng_condition *condition =
989 lttng_trigger_get_const_condition(trigger);
990
991 switch (lttng_condition_get_type(condition)) {
8dbb86b8 992 case LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES:
c738df17
FD
993 needs_tracer_notifier = true;
994 goto end;
995 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
996 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
997 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
998 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
999 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
1000 goto end;
1001 case LTTNG_CONDITION_TYPE_UNKNOWN:
1002 default:
1003 abort();
1004 }
1005end:
1006 return needs_tracer_notifier;
1007}
9c374932 1008
9c374932
JR
1009void lttng_trigger_set_as_registered(struct lttng_trigger *trigger)
1010{
1011 pthread_mutex_lock(&trigger->lock);
1012 trigger->registered = true;
1013 pthread_mutex_unlock(&trigger->lock);
1014}
1015
9c374932
JR
1016void lttng_trigger_set_as_unregistered(struct lttng_trigger *trigger)
1017{
1018 pthread_mutex_lock(&trigger->lock);
1019 trigger->registered = false;
1020 pthread_mutex_unlock(&trigger->lock);
1021}
1022
1023/*
1024 * The trigger must be locked before calling lttng_trigger_registered.
1025 * The lock is necessary since a trigger can be unregistered at anytime.
1026 * Manipulations requiring that the trigger be registered must always acquire
1027 * the trigger lock for the duration of the manipulation using
1028 * `lttng_trigger_lock` and `lttng_trigger_unlock`.
1029 */
9c374932
JR
1030bool lttng_trigger_is_registered(struct lttng_trigger *trigger)
1031{
1032 ASSERT_LOCKED(trigger->lock);
1033 return trigger->registered;
1034}
1035
9c374932
JR
1036void lttng_trigger_lock(struct lttng_trigger *trigger)
1037{
1038 pthread_mutex_lock(&trigger->lock);
1039}
1040
9c374932
JR
1041void lttng_trigger_unlock(struct lttng_trigger *trigger)
1042{
1043 pthread_mutex_unlock(&trigger->lock);
1044}
6a751b95 1045
6a751b95
JR
1046enum lttng_error_code lttng_trigger_mi_serialize(const struct lttng_trigger *trigger,
1047 struct mi_writer *writer,
1048 const struct mi_lttng_error_query_callbacks
1049 *error_query_callbacks)
1050{
1051 int ret;
1052 enum lttng_error_code ret_code;
1053 enum lttng_trigger_status trigger_status;
1054 const struct lttng_condition *condition = NULL;
1055 const struct lttng_action *action = NULL;
1056 struct lttng_dynamic_array action_path_indexes;
1057 uid_t owner_uid;
1058
a0377dfe
FD
1059 LTTNG_ASSERT(trigger);
1060 LTTNG_ASSERT(writer);
6a751b95
JR
1061
1062 lttng_dynamic_array_init(&action_path_indexes, sizeof(uint64_t), NULL);
1063
1064 /* Open trigger element. */
1065 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_trigger);
1066 if (ret) {
1067 goto mi_error;
1068 }
1069
1070 trigger_status = lttng_trigger_get_owner_uid(trigger, &owner_uid);
a0377dfe 1071 LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK);
6a751b95
JR
1072
1073 /* Name. */
1074 ret = mi_lttng_writer_write_element_string(
1075 writer, config_element_name, trigger->name);
1076 if (ret) {
1077 goto mi_error;
1078 }
1079
1080 /* Owner uid. */
1081 ret = mi_lttng_writer_write_element_signed_int(writer,
1082 mi_lttng_element_trigger_owner_uid,
1083 (int64_t) owner_uid);
1084 if (ret) {
1085 goto mi_error;
1086 }
1087
1088 /* Condition. */
1089 condition = lttng_trigger_get_const_condition(trigger);
a0377dfe 1090 LTTNG_ASSERT(condition);
6a751b95
JR
1091 ret_code = lttng_condition_mi_serialize(
1092 trigger, condition, writer, error_query_callbacks);
1093 if (ret_code != LTTNG_OK) {
1094 goto end;
1095 }
1096
1097 /* Action. */
1098 action = lttng_trigger_get_const_action(trigger);
a0377dfe 1099 LTTNG_ASSERT(action);
6a751b95
JR
1100 ret_code = lttng_action_mi_serialize(trigger, action, writer,
1101 error_query_callbacks, &action_path_indexes);
1102 if (ret_code != LTTNG_OK) {
1103 goto end;
1104 }
1105
1106 if (error_query_callbacks && error_query_callbacks->trigger_cb) {
1107 struct lttng_error_query_results *results = NULL;
1108
1109 ret_code = error_query_callbacks->trigger_cb(trigger, &results);
1110 if (ret_code != LTTNG_OK) {
1111 goto end;
1112 }
1113
1114 ret_code = lttng_error_query_results_mi_serialize(
1115 results, writer);
1116 lttng_error_query_results_destroy(results);
1117 if (ret_code != LTTNG_OK) {
1118 goto end;
1119 }
1120 }
1121
1122 /* Close trigger element. */
1123 ret = mi_lttng_writer_close_element(writer);
1124 if (ret) {
1125 goto mi_error;
1126 }
1127
1128 ret_code = LTTNG_OK;
1129 goto end;
1130
1131mi_error:
1132 ret_code = LTTNG_ERR_MI_IO_FAIL;
1133end:
1134 lttng_dynamic_array_reset(&action_path_indexes);
1135 return ret_code;
1136}
1137
1138/* Used by qsort, which expects the semantics of strcmp(). */
1139static int compare_triggers_by_name(const void *a, const void *b)
1140{
1141 const struct lttng_trigger *trigger_a =
1142 *((const struct lttng_trigger **) a);
1143 const struct lttng_trigger *trigger_b =
1144 *((const struct lttng_trigger **) b);
1145 const char *name_a, *name_b;
1146 enum lttng_trigger_status trigger_status;
1147
1148 /* Anonymous triggers are not reachable here. */
1149 trigger_status = lttng_trigger_get_name(trigger_a, &name_a);
a0377dfe 1150 LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK);
6a751b95
JR
1151
1152 trigger_status = lttng_trigger_get_name(trigger_b, &name_b);
a0377dfe 1153 LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK);
6a751b95
JR
1154
1155 return strcmp(name_a, name_b);
1156}
1157
6a751b95
JR
1158enum lttng_error_code lttng_triggers_mi_serialize(const struct lttng_triggers *triggers,
1159 struct mi_writer *writer,
1160 const struct mi_lttng_error_query_callbacks
1161 *error_query_callbacks)
1162{
1163 int ret;
1164 enum lttng_error_code ret_code;
1165 enum lttng_trigger_status status;
1166 unsigned int count, i;
1167 struct lttng_dynamic_pointer_array sorted_triggers;
1168
a0377dfe
FD
1169 LTTNG_ASSERT(triggers);
1170 LTTNG_ASSERT(writer);
6a751b95
JR
1171
1172 /*
1173 * Sort trigger by name to ensure an order at the MI level and ignore
1174 * any anonymous trigger present.
1175 */
1176 lttng_dynamic_pointer_array_init(&sorted_triggers, NULL);
1177
1178 status = lttng_triggers_get_count(triggers, &count);
a0377dfe 1179 LTTNG_ASSERT(status == LTTNG_TRIGGER_STATUS_OK);
6a751b95
JR
1180
1181 for (i = 0; i < count; i++) {
1182 int add_ret;
1183 const char *unused_name;
1184 const struct lttng_trigger *trigger =
1185 lttng_triggers_get_at_index(triggers, i);
1186
1187 status = lttng_trigger_get_name(trigger, &unused_name);
1188 switch (status) {
1189 case LTTNG_TRIGGER_STATUS_OK:
1190 break;
1191 case LTTNG_TRIGGER_STATUS_UNSET:
1192 /* Don't list anonymous triggers. */
1193 continue;
1194 default:
1195 abort();
1196 }
1197
1198 add_ret = lttng_dynamic_pointer_array_add_pointer(
1199 &sorted_triggers, (void *) trigger);
1200
1201 if (add_ret) {
1202 ERR("Failed to lttng_trigger to sorting array.");
1203 ret_code = LTTNG_ERR_NOMEM;
1204 goto error;
1205 }
1206 }
1207
1208 qsort(sorted_triggers.array.buffer.data, count,
1209 sizeof(struct lttng_trigger *),
1210 compare_triggers_by_name);
1211
1212 /* Open triggers element. */
1213 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_triggers);
1214 if (ret) {
1215 ret_code = LTTNG_ERR_MI_IO_FAIL;
1216 goto error;
1217 }
1218
1219 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&sorted_triggers); i++) {
1220 const struct lttng_trigger *trigger =
1221 (const struct lttng_trigger *)
1222 lttng_dynamic_pointer_array_get_pointer(
1223 &sorted_triggers, i);
1224
1225 lttng_trigger_mi_serialize(trigger, writer, error_query_callbacks);
1226 }
1227
1228 /* Close triggers element. */
1229 ret = mi_lttng_writer_close_element(writer);
1230 if (ret) {
1231 ret_code = LTTNG_ERR_MI_IO_FAIL;
1232 goto error;
1233 }
1234
1235 ret_code = LTTNG_OK;
1236
1237error:
1238 lttng_dynamic_pointer_array_reset(&sorted_triggers);
1239 return ret_code;
1240}
This page took 0.096869 seconds and 4 git commands to generate.