Rename C++ header files to .hpp
[lttng-tools.git] / src / common / event-rule / user-tracepoint.cpp
CommitLineData
0a23a07d
JR
1/*
2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
c9e313bc
SM
8#include <common/credentials.hpp>
9#include <common/error.hpp>
10#include <common/hashtable/hashtable.hpp>
11#include <common/hashtable/utils.hpp>
12#include <common/macros.hpp>
13#include <common/mi-lttng.hpp>
14#include <common/optional.hpp>
15#include <common/payload-view.hpp>
16#include <common/payload.hpp>
17#include <common/runas.hpp>
18#include <common/string-utils/string-utils.hpp>
19#include <lttng/event-rule/event-rule-internal.hpp>
20#include <lttng/event-rule/user-tracepoint-internal.hpp>
0a23a07d 21#include <lttng/event.h>
6a751b95 22#include <lttng/log-level-rule.h>
0a23a07d
JR
23
24#define IS_USER_TRACEPOINT_EVENT_RULE(rule) \
25 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT)
26
27static void lttng_event_rule_user_tracepoint_destroy(struct lttng_event_rule *rule)
28{
29 struct lttng_event_rule_user_tracepoint *tracepoint;
30
31 if (rule == NULL) {
32 return;
33 }
34
35 tracepoint = container_of(
36 rule, struct lttng_event_rule_user_tracepoint, parent);
37
38 lttng_log_level_rule_destroy(tracepoint->log_level_rule);
39 lttng_dynamic_pointer_array_reset(&tracepoint->exclusions);
40 free(tracepoint->pattern);
41 free(tracepoint->filter_expression);
42 free(tracepoint->internal_filter.filter);
43 free(tracepoint->internal_filter.bytecode);
44 free(tracepoint);
45}
46
47static bool lttng_event_rule_user_tracepoint_validate(
48 const struct lttng_event_rule *rule)
49{
50 bool valid = false;
51 struct lttng_event_rule_user_tracepoint *tracepoint;
52
53 if (!rule) {
54 goto end;
55 }
56
57 tracepoint = container_of(
58 rule, struct lttng_event_rule_user_tracepoint, parent);
59
60 /* Required field. */
61 if (!tracepoint->pattern) {
62 ERR("Invalid user tracepoint event rule: a pattern must be set.");
63 goto end;
64 }
65
66 valid = true;
67end:
68 return valid;
69}
70
71static int lttng_event_rule_user_tracepoint_serialize(
72 const struct lttng_event_rule *rule,
73 struct lttng_payload *payload)
74{
75 int ret, i;
76 size_t pattern_len, filter_expression_len, exclusions_len, header_offset;
77 size_t size_before_log_level_rule;
78 struct lttng_event_rule_user_tracepoint *tracepoint;
79 struct lttng_event_rule_user_tracepoint_comm tracepoint_comm;
80 enum lttng_event_rule_status status;
81 unsigned int exclusion_count;
82 size_t exclusions_appended_len = 0;
83 struct lttng_event_rule_user_tracepoint_comm *header;
84
85 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule)) {
86 ret = -1;
87 goto end;
88 }
89
90 header_offset = payload->buffer.size;
91
92 DBG("Serializing user tracepoint event rule.");
93 tracepoint = container_of(
94 rule, struct lttng_event_rule_user_tracepoint, parent);
95
96 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule, &exclusion_count);
a0377dfe 97 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
98
99 pattern_len = strlen(tracepoint->pattern) + 1;
100
101 if (tracepoint->filter_expression != NULL) {
102 filter_expression_len =
103 strlen(tracepoint->filter_expression) + 1;
104 } else {
105 filter_expression_len = 0;
106 }
107
108 exclusions_len = 0;
109 for (i = 0; i < exclusion_count; i++) {
110 const char *exclusion;
111
112 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
113 rule, i, &exclusion);
a0377dfe 114 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
115
116 /* Length field. */
117 exclusions_len += sizeof(uint32_t);
118 /* Payload (null terminated). */
119 exclusions_len += strlen(exclusion) + 1;
120 }
121
122 tracepoint_comm.pattern_len = pattern_len;
123 tracepoint_comm.filter_expression_len = filter_expression_len;
124 tracepoint_comm.exclusions_count = exclusion_count;
125 tracepoint_comm.exclusions_len = exclusions_len;
126
127 ret = lttng_dynamic_buffer_append(&payload->buffer, &tracepoint_comm,
128 sizeof(tracepoint_comm));
129 if (ret) {
130 goto end;
131 }
132
133 ret = lttng_dynamic_buffer_append(
134 &payload->buffer, tracepoint->pattern, pattern_len);
135 if (ret) {
136 goto end;
137 }
138
139 ret = lttng_dynamic_buffer_append(&payload->buffer, tracepoint->filter_expression,
140 filter_expression_len);
141 if (ret) {
142 goto end;
143 }
144
145 size_before_log_level_rule = payload->buffer.size;
146
147 ret = lttng_log_level_rule_serialize(tracepoint->log_level_rule, payload);
148 if (ret < 0) {
149 goto end;
150 }
151
152 header = (typeof(header)) ((char *) payload->buffer.data + header_offset);
153 header->log_level_rule_len =
154 payload->buffer.size - size_before_log_level_rule;
155
156 for (i = 0; i < exclusion_count; i++) {
157 size_t len;
158 const char *exclusion;
159
160 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
161 rule, i, &exclusion);
a0377dfe 162 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
163
164 len = strlen(exclusion) + 1;
165 /* Append exclusion length, includes the null terminator. */
166 ret = lttng_dynamic_buffer_append(
167 &payload->buffer, &len, sizeof(uint32_t));
168 if (ret) {
169 goto end;
170 }
171
172 exclusions_appended_len += sizeof(uint32_t);
173
174 /* Include the '\0' in the payload. */
175 ret = lttng_dynamic_buffer_append(
176 &payload->buffer, exclusion, len);
177 if (ret) {
178 goto end;
179 }
180
181 exclusions_appended_len += len;
182 }
183
a0377dfe 184 LTTNG_ASSERT(exclusions_len == exclusions_appended_len);
0a23a07d
JR
185
186end:
187 return ret;
188}
189
190static bool lttng_event_rule_user_tracepoint_is_equal(
191 const struct lttng_event_rule *_a,
192 const struct lttng_event_rule *_b)
193{
194 int i;
195 bool is_equal = false;
196 struct lttng_event_rule_user_tracepoint *a, *b;
197 unsigned int count_a, count_b;
198 enum lttng_event_rule_status status;
199
200 a = container_of(_a, struct lttng_event_rule_user_tracepoint, parent);
201 b = container_of(_b, struct lttng_event_rule_user_tracepoint, parent);
202
203 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_a, &count_a);
a0377dfe 204 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d 205 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_b, &count_b);
a0377dfe 206 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
207
208 /* Quick checks. */
209 if (count_a != count_b) {
210 goto end;
211 }
212
213 if (!!a->filter_expression != !!b->filter_expression) {
214 goto end;
215 }
216
217 /* Long check. */
a0377dfe
FD
218 LTTNG_ASSERT(a->pattern);
219 LTTNG_ASSERT(b->pattern);
0a23a07d
JR
220 if (strcmp(a->pattern, b->pattern)) {
221 goto end;
222 }
223
224 if (a->filter_expression && b->filter_expression) {
225 if (strcmp(a->filter_expression, b->filter_expression)) {
226 goto end;
227 }
228 } else if (!!a->filter_expression != !!b->filter_expression) {
229 /* One is set; not the other. */
230 goto end;
231 }
232
233 if (!lttng_log_level_rule_is_equal(
234 a->log_level_rule, b->log_level_rule)) {
235 goto end;
236 }
237
238 for (i = 0; i < count_a; i++) {
239 const char *exclusion_a, *exclusion_b;
240
241 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
242 _a, i, &exclusion_a);
a0377dfe 243 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
244 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
245 _b, i, &exclusion_b);
a0377dfe 246 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
247 if (strcmp(exclusion_a, exclusion_b)) {
248 goto end;
249 }
250 }
251
252 is_equal = true;
253end:
254 return is_equal;
255}
256
257static enum lttng_error_code
258lttng_event_rule_user_tracepoint_generate_filter_bytecode(
259 struct lttng_event_rule *rule,
260 const struct lttng_credentials *creds)
261{
262 int ret;
263 enum lttng_error_code ret_code;
264 struct lttng_event_rule_user_tracepoint *tracepoint;
265 enum lttng_event_rule_status status;
266 const char *filter;
267 struct lttng_bytecode *bytecode = NULL;
268
a0377dfe 269 LTTNG_ASSERT(rule);
0a23a07d
JR
270
271 tracepoint = container_of(
272 rule, struct lttng_event_rule_user_tracepoint, parent);
273
274 status = lttng_event_rule_user_tracepoint_get_filter(rule, &filter);
275 if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
276 filter = NULL;
277 } else if (status != LTTNG_EVENT_RULE_STATUS_OK) {
278 ret_code = LTTNG_ERR_FILTER_INVAL;
279 goto end;
280 }
281
282 if (filter && filter[0] == '\0') {
283 ret_code = LTTNG_ERR_FILTER_INVAL;
284 goto error;
285 }
286
287 if (filter) {
288 tracepoint->internal_filter.filter = strdup(filter);
289 if (tracepoint->internal_filter.filter == NULL) {
290 ret_code = LTTNG_ERR_NOMEM;
291 goto error;
292 }
293 } else {
294 tracepoint->internal_filter.filter = NULL;
295 }
296
297 if (tracepoint->internal_filter.filter == NULL) {
298 ret_code = LTTNG_OK;
299 goto end;
300 }
301
302 ret = run_as_generate_filter_bytecode(
303 tracepoint->internal_filter.filter, creds,
304 &bytecode);
305 if (ret) {
306 ret_code = LTTNG_ERR_FILTER_INVAL;
307 goto end;
308 }
309
310 tracepoint->internal_filter.bytecode = bytecode;
311 bytecode = NULL;
312 ret_code = LTTNG_OK;
313
314error:
315end:
316 free(bytecode);
317 return ret_code;
318}
319
320static const char *lttng_event_rule_user_tracepoint_get_internal_filter(
321 const struct lttng_event_rule *rule)
322{
323 struct lttng_event_rule_user_tracepoint *tracepoint;
324
a0377dfe 325 LTTNG_ASSERT(rule);
0a23a07d
JR
326 tracepoint = container_of(
327 rule, struct lttng_event_rule_user_tracepoint, parent);
328 return tracepoint->internal_filter.filter;
329}
330
331static const struct lttng_bytecode *
332lttng_event_rule_user_tracepoint_get_internal_filter_bytecode(
333 const struct lttng_event_rule *rule)
334{
335 struct lttng_event_rule_user_tracepoint *tracepoint;
336
a0377dfe 337 LTTNG_ASSERT(rule);
0a23a07d
JR
338 tracepoint = container_of(
339 rule, struct lttng_event_rule_user_tracepoint, parent);
340 return tracepoint->internal_filter.bytecode;
341}
342
343static enum lttng_event_rule_generate_exclusions_status
344lttng_event_rule_user_tracepoint_generate_exclusions(
345 const struct lttng_event_rule *rule,
346 struct lttng_event_exclusion **_exclusions)
347{
348 unsigned int nb_exclusions = 0, i;
349 struct lttng_event_exclusion *exclusions;
350 enum lttng_event_rule_status event_rule_status;
351 enum lttng_event_rule_generate_exclusions_status ret_status;
352
a0377dfe 353 LTTNG_ASSERT(_exclusions);
0a23a07d
JR
354
355 event_rule_status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
356 rule, &nb_exclusions);
a0377dfe 357 LTTNG_ASSERT(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
358 if (nb_exclusions == 0) {
359 /* Nothing to do. */
360 exclusions = NULL;
361 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE;
362 goto end;
363 }
364
a6bc4ca9 365 exclusions = (lttng_event_exclusion *) zmalloc(sizeof(struct lttng_event_exclusion) +
0a23a07d
JR
366 (LTTNG_SYMBOL_NAME_LEN * nb_exclusions));
367 if (!exclusions) {
368 PERROR("Failed to allocate exclusions buffer");
369 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY;
370 goto end;
371 }
372
373 exclusions->count = nb_exclusions;
374 for (i = 0; i < nb_exclusions; i++) {
375 int copy_ret;
376 const char *exclusion_str;
377
378 event_rule_status =
379 lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
380 rule, i, &exclusion_str);
a0377dfe 381 LTTNG_ASSERT(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d 382
73b3df71
JG
383 copy_ret = lttng_strncpy(
384 LTTNG_EVENT_EXCLUSION_NAME_AT(exclusions, i),
385 exclusion_str,
386 sizeof(LTTNG_EVENT_EXCLUSION_NAME_AT(exclusions, i)));
0a23a07d
JR
387 if (copy_ret) {
388 free(exclusions);
389 exclusions = NULL;
390 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR;
391 goto end;
392 }
393 }
394
395 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK;
396
397end:
398 *_exclusions = exclusions;
399 return ret_status;
400}
401
402static void destroy_lttng_exclusions_element(void *ptr)
403{
404 free(ptr);
405}
406
407static unsigned long lttng_event_rule_user_tracepoint_hash(
408 const struct lttng_event_rule *rule)
409{
410 unsigned long hash;
411 unsigned int i, exclusion_count;
412 enum lttng_event_rule_status status;
413 struct lttng_event_rule_user_tracepoint *tp_rule =
414 container_of(rule, typeof(*tp_rule), parent);
415
416 hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT,
417 lttng_ht_seed);
418 hash ^= hash_key_str(tp_rule->pattern, lttng_ht_seed);
419
420 if (tp_rule->filter_expression) {
421 hash ^= hash_key_str(tp_rule->filter_expression, lttng_ht_seed);
422 }
423
424 if (tp_rule->log_level_rule) {
425 hash ^= lttng_log_level_rule_hash(tp_rule->log_level_rule);
426 }
427
428 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule,
429 &exclusion_count);
a0377dfe 430 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
431
432 for (i = 0; i < exclusion_count; i++) {
433 const char *exclusion;
434
435 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
436 rule, i, &exclusion);
a0377dfe 437 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
438 hash ^= hash_key_str(exclusion, lttng_ht_seed);
439 }
440
441 return hash;
442}
443
6a751b95
JR
444static enum lttng_error_code lttng_event_rule_user_tracepoint_mi_serialize(
445 const struct lttng_event_rule *rule, struct mi_writer *writer)
446{
447 int ret;
448 enum lttng_error_code ret_code;
449 enum lttng_event_rule_status status;
450 const char *filter = NULL;
451 const char *name_pattern = NULL;
452 const struct lttng_log_level_rule *log_level_rule = NULL;
453 unsigned int exclusion_count = 0;
454
a0377dfe
FD
455 LTTNG_ASSERT(rule);
456 LTTNG_ASSERT(writer);
457 LTTNG_ASSERT(IS_USER_TRACEPOINT_EVENT_RULE(rule));
6a751b95
JR
458
459 status = lttng_event_rule_user_tracepoint_get_name_pattern(
460 rule, &name_pattern);
a0377dfe
FD
461 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
462 LTTNG_ASSERT(name_pattern);
6a751b95
JR
463
464 status = lttng_event_rule_user_tracepoint_get_filter(rule, &filter);
a0377dfe 465 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
6a751b95
JR
466 status == LTTNG_EVENT_RULE_STATUS_UNSET);
467
468 status = lttng_event_rule_user_tracepoint_get_log_level_rule(
469 rule, &log_level_rule);
a0377dfe 470 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
6a751b95
JR
471 status == LTTNG_EVENT_RULE_STATUS_UNSET);
472
473 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
474 rule, &exclusion_count);
a0377dfe 475 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
6a751b95
JR
476
477 /* Open event rule user tracepoint element. */
478 ret = mi_lttng_writer_open_element(
479 writer, mi_lttng_element_event_rule_user_tracepoint);
480 if (ret) {
481 goto mi_error;
482 }
483
484 /* Name pattern. */
485 ret = mi_lttng_writer_write_element_string(writer,
486 mi_lttng_element_event_rule_name_pattern, name_pattern);
487 if (ret) {
488 goto mi_error;
489 }
490
491 /* Filter expression. */
492 if (filter != NULL) {
493 ret = mi_lttng_writer_write_element_string(writer,
494 mi_lttng_element_event_rule_filter_expression,
495 filter);
496 if (ret) {
497 goto mi_error;
498 }
499 }
500
501 /* Log level rule. */
502 if (log_level_rule) {
503 ret_code = lttng_log_level_rule_mi_serialize(
504 log_level_rule, writer);
505 if (ret_code != LTTNG_OK) {
506 goto end;
507 }
508 }
509
510 if (exclusion_count != 0) {
511 int i;
512
513 /* Open the exclusion list. */
514 ret = mi_lttng_writer_open_element(writer,
515 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions);
516 if (ret) {
517 goto mi_error;
518 }
519
520 for (i = 0; i < exclusion_count; i++) {
521 const char *exclusion;
522
523 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
524 rule, i, &exclusion);
a0377dfe 525 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
6a751b95
JR
526
527 ret = mi_lttng_writer_write_element_string(writer,
528 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion,
529 exclusion);
530 if (ret) {
531 goto mi_error;
532 }
533 }
534
535 /* Close the list. */
536 ret = mi_lttng_writer_close_element(writer);
537 if (ret) {
538 goto mi_error;
539 }
540 }
541
542 /* Close event rule user tracepoint element. */
543 ret = mi_lttng_writer_close_element(writer);
544 if (ret) {
545 goto mi_error;
546 }
547
548 ret_code = LTTNG_OK;
549 goto end;
550
551mi_error:
552 ret_code = LTTNG_ERR_MI_IO_FAIL;
553end:
554 return ret_code;
555}
556
0a23a07d
JR
557struct lttng_event_rule *lttng_event_rule_user_tracepoint_create(void)
558{
559 struct lttng_event_rule *rule = NULL;
560 struct lttng_event_rule_user_tracepoint *tp_rule;
561 enum lttng_event_rule_status status;
562
a6bc4ca9 563 tp_rule = (lttng_event_rule_user_tracepoint *) zmalloc(sizeof(struct lttng_event_rule_user_tracepoint));
0a23a07d
JR
564 if (!tp_rule) {
565 goto end;
566 }
567
568 rule = &tp_rule->parent;
569 lttng_event_rule_init(&tp_rule->parent, LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT);
570 tp_rule->parent.validate = lttng_event_rule_user_tracepoint_validate;
571 tp_rule->parent.serialize = lttng_event_rule_user_tracepoint_serialize;
572 tp_rule->parent.equal = lttng_event_rule_user_tracepoint_is_equal;
573 tp_rule->parent.destroy = lttng_event_rule_user_tracepoint_destroy;
574 tp_rule->parent.generate_filter_bytecode =
575 lttng_event_rule_user_tracepoint_generate_filter_bytecode;
576 tp_rule->parent.get_filter =
577 lttng_event_rule_user_tracepoint_get_internal_filter;
578 tp_rule->parent.get_filter_bytecode =
579 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode;
580 tp_rule->parent.generate_exclusions =
581 lttng_event_rule_user_tracepoint_generate_exclusions;
582 tp_rule->parent.hash = lttng_event_rule_user_tracepoint_hash;
6a751b95 583 tp_rule->parent.mi_serialize = lttng_event_rule_user_tracepoint_mi_serialize;
0a23a07d
JR
584
585 /* Not necessary for now. */
586 tp_rule->parent.generate_lttng_event = NULL;
587
588 tp_rule->log_level_rule = NULL;
589
590 lttng_dynamic_pointer_array_init(&tp_rule->exclusions,
591 destroy_lttng_exclusions_element);
592
593 /* Default pattern is '*'. */
594 status = lttng_event_rule_user_tracepoint_set_name_pattern(rule, "*");
595 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
596 lttng_event_rule_destroy(rule);
597 rule = NULL;
598 }
599
600end:
601 return rule;
602}
603
0a23a07d
JR
604ssize_t lttng_event_rule_user_tracepoint_create_from_payload(
605 struct lttng_payload_view *view,
606 struct lttng_event_rule **_event_rule)
607{
608 ssize_t ret, offset = 0;
609 int i;
610 enum lttng_event_rule_status status;
611 const struct lttng_event_rule_user_tracepoint_comm *tracepoint_comm;
612 const char *pattern;
613 const char *filter_expression = NULL;
614 const char **exclusions = NULL;
615 const uint32_t *exclusion_len;
616 const char *exclusion;
617 struct lttng_buffer_view current_buffer_view;
618 struct lttng_event_rule *rule = NULL;
619 struct lttng_log_level_rule *log_level_rule = NULL;
620
621 if (!_event_rule) {
622 ret = -1;
623 goto end;
624 }
625
626 current_buffer_view = lttng_buffer_view_from_view(
627 &view->buffer, offset, sizeof(*tracepoint_comm));
628 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
629 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
630 ret = -1;
631 goto end;
632 }
633
634 tracepoint_comm = (typeof(tracepoint_comm)) current_buffer_view.data;
635
636 rule = lttng_event_rule_user_tracepoint_create();
637 if (!rule) {
638 ERR("Failed to create event rule user tracepoint.");
639 ret = -1;
640 goto end;
641 }
642
643 /* Skip to payload. */
644 offset += current_buffer_view.size;
645
646 /* Map the pattern. */
647 current_buffer_view = lttng_buffer_view_from_view(
648 &view->buffer, offset, tracepoint_comm->pattern_len);
649
650 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
651 ret = -1;
652 goto end;
653 }
654
655 pattern = current_buffer_view.data;
656 if (!lttng_buffer_view_contains_string(&current_buffer_view, pattern,
657 tracepoint_comm->pattern_len)) {
658 ret = -1;
659 goto end;
660 }
661
662 /* Skip after the pattern. */
663 offset += tracepoint_comm->pattern_len;
664
665 if (!tracepoint_comm->filter_expression_len) {
666 goto skip_filter_expression;
667 }
668
669 /* Map the filter_expression. */
670 current_buffer_view = lttng_buffer_view_from_view(&view->buffer, offset,
671 tracepoint_comm->filter_expression_len);
672 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
673 ret = -1;
674 goto end;
675 }
676
677 filter_expression = current_buffer_view.data;
678 if (!lttng_buffer_view_contains_string(&current_buffer_view,
679 filter_expression,
680 tracepoint_comm->filter_expression_len)) {
681 ret = -1;
682 goto end;
683 }
684
685 /* Skip after the pattern. */
686 offset += tracepoint_comm->filter_expression_len;
687
688skip_filter_expression:
689 if (!tracepoint_comm->log_level_rule_len) {
690 goto skip_log_level_rule;
691 }
692
693 {
694 /* Map the log level rule. */
695 struct lttng_payload_view current_payload_view =
696 lttng_payload_view_from_view(view, offset,
697 tracepoint_comm->log_level_rule_len);
698
699 ret = lttng_log_level_rule_create_from_payload(
700 &current_payload_view, &log_level_rule);
701 if (ret < 0) {
702 ret = -1;
703 goto end;
704 }
705
a0377dfe 706 LTTNG_ASSERT(ret == tracepoint_comm->log_level_rule_len);
0a23a07d
JR
707 }
708
709 /* Skip after the log level rule. */
710 offset += tracepoint_comm->log_level_rule_len;
711
712skip_log_level_rule:
713 for (i = 0; i < tracepoint_comm->exclusions_count; i++) {
714 current_buffer_view = lttng_buffer_view_from_view(
715 &view->buffer, offset, sizeof(*exclusion_len));
716 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
717 ret = -1;
718 goto end;
719 }
720
721 exclusion_len = (typeof(exclusion_len)) current_buffer_view.data;
722 offset += sizeof(*exclusion_len);
723
724 current_buffer_view = lttng_buffer_view_from_view(
725 &view->buffer, offset, *exclusion_len);
726 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
727 ret = -1;
728 goto end;
729 }
730
731 exclusion = current_buffer_view.data;
732 if (!lttng_buffer_view_contains_string(&current_buffer_view,
733 exclusion, *exclusion_len)) {
734 ret = -1;
735 goto end;
736 }
737
738 status = lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(rule, exclusion);
739 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
740 ERR("Failed to add event rule user tracepoint exclusion \"%s\".",
741 exclusion);
742 ret = -1;
743 goto end;
744 }
745
746 /* Skip to next exclusion. */
747 offset += *exclusion_len;
748 }
749
750 status = lttng_event_rule_user_tracepoint_set_name_pattern(rule, pattern);
751 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
752 ERR("Failed to set event rule user tracepoint pattern.");
753 ret = -1;
754 goto end;
755 }
756
757 if (filter_expression) {
758 status = lttng_event_rule_user_tracepoint_set_filter(
759 rule, filter_expression);
760 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
761 ERR("Failed to set event rule user tracepoint pattern.");
762 ret = -1;
763 goto end;
764 }
765 }
766
767 if (log_level_rule) {
768 status = lttng_event_rule_user_tracepoint_set_log_level_rule(
769 rule, log_level_rule);
770 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
771 ERR("Failed to set event rule user tracepoint log level rule.");
772 ret = -1;
773 goto end;
774 }
775 }
776
777 *_event_rule = rule;
778 rule = NULL;
779 ret = offset;
780end:
781 free(exclusions);
782 lttng_log_level_rule_destroy(log_level_rule);
783 lttng_event_rule_destroy(rule);
784 return ret;
785}
786
787enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_name_pattern(
788 struct lttng_event_rule *rule, const char *pattern)
789{
790 char *pattern_copy = NULL;
791 struct lttng_event_rule_user_tracepoint *tracepoint;
792 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
793
794 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !pattern ||
795 strlen(pattern) == 0) {
796 status = LTTNG_EVENT_RULE_STATUS_INVALID;
797 goto end;
798 }
799
800 tracepoint = container_of(
801 rule, struct lttng_event_rule_user_tracepoint, parent);
802 pattern_copy = strdup(pattern);
803 if (!pattern_copy) {
804 status = LTTNG_EVENT_RULE_STATUS_ERROR;
805 goto end;
806 }
807
808 /* Normalize the pattern. */
809 strutils_normalize_star_glob_pattern(pattern_copy);
810
811 free(tracepoint->pattern);
812
813 tracepoint->pattern = pattern_copy;
814 pattern_copy = NULL;
815end:
816 return status;
817}
818
819enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern(
820 const struct lttng_event_rule *rule, const char **pattern)
821{
822 struct lttng_event_rule_user_tracepoint *tracepoint;
823 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
824
825 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !pattern) {
826 status = LTTNG_EVENT_RULE_STATUS_INVALID;
827 goto end;
828 }
829
830 tracepoint = container_of(
831 rule, struct lttng_event_rule_user_tracepoint, parent);
832 if (!tracepoint->pattern) {
833 status = LTTNG_EVENT_RULE_STATUS_UNSET;
834 goto end;
835 }
836
837 *pattern = tracepoint->pattern;
838end:
839 return status;
840}
841
842enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_filter(
843 struct lttng_event_rule *rule, const char *expression)
844{
845 char *expression_copy = NULL;
846 struct lttng_event_rule_user_tracepoint *tracepoint;
847 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
848
849 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !expression ||
850 strlen(expression) == 0) {
851 status = LTTNG_EVENT_RULE_STATUS_INVALID;
852 goto end;
853 }
854
855 tracepoint = container_of(
856 rule, struct lttng_event_rule_user_tracepoint, parent);
857 expression_copy = strdup(expression);
858 if (!expression_copy) {
859 PERROR("Failed to copy filter expression");
860 status = LTTNG_EVENT_RULE_STATUS_ERROR;
861 goto end;
862 }
863
864 if (tracepoint->filter_expression) {
865 free(tracepoint->filter_expression);
866 }
867
868 tracepoint->filter_expression = expression_copy;
869 expression_copy = NULL;
870end:
871 return status;
872}
873
874enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_filter(
875 const struct lttng_event_rule *rule, const char **expression)
876{
877 struct lttng_event_rule_user_tracepoint *tracepoint;
878 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
879
880 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !expression) {
881 status = LTTNG_EVENT_RULE_STATUS_INVALID;
882 goto end;
883 }
884
885 tracepoint = container_of(
886 rule, struct lttng_event_rule_user_tracepoint, parent);
887 if (!tracepoint->filter_expression) {
888 status = LTTNG_EVENT_RULE_STATUS_UNSET;
889 goto end;
890 }
891
892 *expression = tracepoint->filter_expression;
893end:
894 return status;
895}
896
897static bool log_level_rule_valid(const struct lttng_log_level_rule *rule)
898{
899 bool valid = false;
900 enum lttng_log_level_rule_status status;
901 int level;
902
903 switch (lttng_log_level_rule_get_type(rule)) {
904 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
905 status = lttng_log_level_rule_exactly_get_level(rule, &level);
906 break;
907 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
908 status = lttng_log_level_rule_at_least_as_severe_as_get_level(
909 rule, &level);
910 break;
911 default:
912 abort();
913 }
914
a0377dfe 915 LTTNG_ASSERT(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
0a23a07d
JR
916
917 if (level < LTTNG_LOGLEVEL_EMERG) {
918 /* Invalid. */
919 goto end;
920 }
921 if (level > LTTNG_LOGLEVEL_DEBUG) {
922 /* Invalid. */
923 goto end;
924 }
925
926 valid = true;
927
928end:
929 return valid;
930}
931
932enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_log_level_rule(
933 struct lttng_event_rule *rule,
934 const struct lttng_log_level_rule *log_level_rule)
935{
936 struct lttng_event_rule_user_tracepoint *tracepoint;
937 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
938 struct lttng_log_level_rule *copy = NULL;
939
940 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule)) {
941 status = LTTNG_EVENT_RULE_STATUS_INVALID;
942 goto end;
943 }
944
945 tracepoint = container_of(
946 rule, struct lttng_event_rule_user_tracepoint, parent);
947
948 if (!log_level_rule_valid(log_level_rule)) {
949 status = LTTNG_EVENT_RULE_STATUS_INVALID;
950 goto end;
951 }
952
953 copy = lttng_log_level_rule_copy(log_level_rule);
954 if (copy == NULL) {
955 status = LTTNG_EVENT_RULE_STATUS_ERROR;
956 goto end;
957 }
958
959 if (tracepoint->log_level_rule) {
960 lttng_log_level_rule_destroy(tracepoint->log_level_rule);
961 }
962
963 tracepoint->log_level_rule = copy;
964
965end:
966 return status;
967}
968
969enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_log_level_rule(
970 const struct lttng_event_rule *rule,
971 const struct lttng_log_level_rule **log_level_rule
972 )
973{
974 struct lttng_event_rule_user_tracepoint *tracepoint;
975 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
976
977 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !log_level_rule) {
978 status = LTTNG_EVENT_RULE_STATUS_INVALID;
979 goto end;
980 }
981
982 tracepoint = container_of(
983 rule, struct lttng_event_rule_user_tracepoint, parent);
984 if (tracepoint->log_level_rule == NULL) {
985 status = LTTNG_EVENT_RULE_STATUS_UNSET;
986 goto end;
987 }
988
989 *log_level_rule = tracepoint->log_level_rule;
990end:
991 return status;
992}
993
994enum lttng_event_rule_status lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
995 struct lttng_event_rule *rule,
996 const char *exclusion)
997{
998 int ret;
999 char *exclusion_copy = NULL;
1000 struct lttng_event_rule_user_tracepoint *tracepoint;
1001 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1002
1003 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) ||
1004 !exclusion) {
1005 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1006 goto end;
1007 }
1008
1009 tracepoint = container_of(
1010 rule, struct lttng_event_rule_user_tracepoint, parent);
1011
1012 if (strlen(exclusion) >= LTTNG_SYMBOL_NAME_LEN) {
1013 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1014 goto end;
1015 }
1016
1017 exclusion_copy = strdup(exclusion);
1018 if (!exclusion_copy) {
1019 status = LTTNG_EVENT_RULE_STATUS_ERROR;
1020 goto end;
1021 }
1022
1023 ret = lttng_dynamic_pointer_array_add_pointer(&tracepoint->exclusions,
1024 exclusion_copy);
1025 if (ret < 0) {
1026 status = LTTNG_EVENT_RULE_STATUS_ERROR;
1027 goto end;
1028 }
1029
1030 exclusion_copy = NULL;
1031end:
1032 free(exclusion_copy);
1033 return status;
1034}
1035
1036enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
1037 const struct lttng_event_rule *rule, unsigned int *count)
1038{
1039 struct lttng_event_rule_user_tracepoint *tracepoint;
1040 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1041
1042 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !count) {
1043 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1044 goto end;
1045 }
1046
1047 tracepoint = container_of(
1048 rule, struct lttng_event_rule_user_tracepoint, parent);
1049 *count = lttng_dynamic_pointer_array_get_count(&tracepoint->exclusions);
1050end:
1051 return status;
1052}
1053
1054enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
1055 const struct lttng_event_rule *rule,
1056 unsigned int index,
1057 const char **exclusion)
1058{
1059 unsigned int count;
1060 struct lttng_event_rule_user_tracepoint *tracepoint;
1061 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1062
1063 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !exclusion) {
1064 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1065 goto end;
1066 }
1067
1068 tracepoint = container_of(
1069 rule, struct lttng_event_rule_user_tracepoint, parent);
1070 if (lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule, &count) !=
1071 LTTNG_EVENT_RULE_STATUS_OK) {
1072 goto end;
1073 }
1074
1075 if (index >= count) {
1076 goto end;
1077 }
1078
a6bc4ca9 1079 *exclusion = (const char *) lttng_dynamic_pointer_array_get_pointer(
0a23a07d
JR
1080 &tracepoint->exclusions, index);
1081end:
1082 return status;
1083}
This page took 0.07527 seconds and 4 git commands to generate.