liblttng-ctl: use export list to define exported symbols
[lttng-tools.git] / src / common / event-rule / user-tracepoint.c
1 /*
2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <common/credentials.h>
9 #include <common/error.h>
10 #include <common/hashtable/hashtable.h>
11 #include <common/hashtable/utils.h>
12 #include <common/macros.h>
13 #include <common/mi-lttng.h>
14 #include <common/optional.h>
15 #include <common/payload-view.h>
16 #include <common/payload.h>
17 #include <common/runas.h>
18 #include <common/string-utils/string-utils.h>
19 #include <lttng/event-rule/event-rule-internal.h>
20 #include <lttng/event-rule/user-tracepoint-internal.h>
21 #include <lttng/event.h>
22 #include <lttng/log-level-rule.h>
23
24 #define IS_USER_TRACEPOINT_EVENT_RULE(rule) \
25 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT)
26
27 static 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
47 static 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;
67 end:
68 return valid;
69 }
70
71 static 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);
97 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
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);
114 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
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);
162 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
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
184 LTTNG_ASSERT(exclusions_len == exclusions_appended_len);
185
186 end:
187 return ret;
188 }
189
190 static 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);
204 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
205 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_b, &count_b);
206 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
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. */
218 LTTNG_ASSERT(a->pattern);
219 LTTNG_ASSERT(b->pattern);
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);
243 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
244 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
245 _b, i, &exclusion_b);
246 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
247 if (strcmp(exclusion_a, exclusion_b)) {
248 goto end;
249 }
250 }
251
252 is_equal = true;
253 end:
254 return is_equal;
255 }
256
257 static enum lttng_error_code
258 lttng_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
269 LTTNG_ASSERT(rule);
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
314 error:
315 end:
316 free(bytecode);
317 return ret_code;
318 }
319
320 static 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
325 LTTNG_ASSERT(rule);
326 tracepoint = container_of(
327 rule, struct lttng_event_rule_user_tracepoint, parent);
328 return tracepoint->internal_filter.filter;
329 }
330
331 static const struct lttng_bytecode *
332 lttng_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
337 LTTNG_ASSERT(rule);
338 tracepoint = container_of(
339 rule, struct lttng_event_rule_user_tracepoint, parent);
340 return tracepoint->internal_filter.bytecode;
341 }
342
343 static enum lttng_event_rule_generate_exclusions_status
344 lttng_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
353 LTTNG_ASSERT(_exclusions);
354
355 event_rule_status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
356 rule, &nb_exclusions);
357 LTTNG_ASSERT(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
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
365 exclusions = zmalloc(sizeof(struct lttng_event_exclusion) +
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);
381 LTTNG_ASSERT(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
382
383 copy_ret = lttng_strncpy(exclusions->names[i], exclusion_str,
384 LTTNG_SYMBOL_NAME_LEN);
385 if (copy_ret) {
386 free(exclusions);
387 exclusions = NULL;
388 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR;
389 goto end;
390 }
391 }
392
393 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK;
394
395 end:
396 *_exclusions = exclusions;
397 return ret_status;
398 }
399
400 static void destroy_lttng_exclusions_element(void *ptr)
401 {
402 free(ptr);
403 }
404
405 static unsigned long lttng_event_rule_user_tracepoint_hash(
406 const struct lttng_event_rule *rule)
407 {
408 unsigned long hash;
409 unsigned int i, exclusion_count;
410 enum lttng_event_rule_status status;
411 struct lttng_event_rule_user_tracepoint *tp_rule =
412 container_of(rule, typeof(*tp_rule), parent);
413
414 hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT,
415 lttng_ht_seed);
416 hash ^= hash_key_str(tp_rule->pattern, lttng_ht_seed);
417
418 if (tp_rule->filter_expression) {
419 hash ^= hash_key_str(tp_rule->filter_expression, lttng_ht_seed);
420 }
421
422 if (tp_rule->log_level_rule) {
423 hash ^= lttng_log_level_rule_hash(tp_rule->log_level_rule);
424 }
425
426 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule,
427 &exclusion_count);
428 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
429
430 for (i = 0; i < exclusion_count; i++) {
431 const char *exclusion;
432
433 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
434 rule, i, &exclusion);
435 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
436 hash ^= hash_key_str(exclusion, lttng_ht_seed);
437 }
438
439 return hash;
440 }
441
442 static enum lttng_error_code lttng_event_rule_user_tracepoint_mi_serialize(
443 const struct lttng_event_rule *rule, struct mi_writer *writer)
444 {
445 int ret;
446 enum lttng_error_code ret_code;
447 enum lttng_event_rule_status status;
448 const char *filter = NULL;
449 const char *name_pattern = NULL;
450 const struct lttng_log_level_rule *log_level_rule = NULL;
451 unsigned int exclusion_count = 0;
452
453 LTTNG_ASSERT(rule);
454 LTTNG_ASSERT(writer);
455 LTTNG_ASSERT(IS_USER_TRACEPOINT_EVENT_RULE(rule));
456
457 status = lttng_event_rule_user_tracepoint_get_name_pattern(
458 rule, &name_pattern);
459 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
460 LTTNG_ASSERT(name_pattern);
461
462 status = lttng_event_rule_user_tracepoint_get_filter(rule, &filter);
463 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
464 status == LTTNG_EVENT_RULE_STATUS_UNSET);
465
466 status = lttng_event_rule_user_tracepoint_get_log_level_rule(
467 rule, &log_level_rule);
468 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
469 status == LTTNG_EVENT_RULE_STATUS_UNSET);
470
471 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
472 rule, &exclusion_count);
473 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
474
475 /* Open event rule user tracepoint element. */
476 ret = mi_lttng_writer_open_element(
477 writer, mi_lttng_element_event_rule_user_tracepoint);
478 if (ret) {
479 goto mi_error;
480 }
481
482 /* Name pattern. */
483 ret = mi_lttng_writer_write_element_string(writer,
484 mi_lttng_element_event_rule_name_pattern, name_pattern);
485 if (ret) {
486 goto mi_error;
487 }
488
489 /* Filter expression. */
490 if (filter != NULL) {
491 ret = mi_lttng_writer_write_element_string(writer,
492 mi_lttng_element_event_rule_filter_expression,
493 filter);
494 if (ret) {
495 goto mi_error;
496 }
497 }
498
499 /* Log level rule. */
500 if (log_level_rule) {
501 ret_code = lttng_log_level_rule_mi_serialize(
502 log_level_rule, writer);
503 if (ret_code != LTTNG_OK) {
504 goto end;
505 }
506 }
507
508 if (exclusion_count != 0) {
509 int i;
510
511 /* Open the exclusion list. */
512 ret = mi_lttng_writer_open_element(writer,
513 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions);
514 if (ret) {
515 goto mi_error;
516 }
517
518 for (i = 0; i < exclusion_count; i++) {
519 const char *exclusion;
520
521 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
522 rule, i, &exclusion);
523 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
524
525 ret = mi_lttng_writer_write_element_string(writer,
526 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion,
527 exclusion);
528 if (ret) {
529 goto mi_error;
530 }
531 }
532
533 /* Close the list. */
534 ret = mi_lttng_writer_close_element(writer);
535 if (ret) {
536 goto mi_error;
537 }
538 }
539
540 /* Close event rule user tracepoint element. */
541 ret = mi_lttng_writer_close_element(writer);
542 if (ret) {
543 goto mi_error;
544 }
545
546 ret_code = LTTNG_OK;
547 goto end;
548
549 mi_error:
550 ret_code = LTTNG_ERR_MI_IO_FAIL;
551 end:
552 return ret_code;
553 }
554
555 struct lttng_event_rule *lttng_event_rule_user_tracepoint_create(void)
556 {
557 struct lttng_event_rule *rule = NULL;
558 struct lttng_event_rule_user_tracepoint *tp_rule;
559 enum lttng_event_rule_status status;
560
561 tp_rule = zmalloc(sizeof(struct lttng_event_rule_user_tracepoint));
562 if (!tp_rule) {
563 goto end;
564 }
565
566 rule = &tp_rule->parent;
567 lttng_event_rule_init(&tp_rule->parent, LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT);
568 tp_rule->parent.validate = lttng_event_rule_user_tracepoint_validate;
569 tp_rule->parent.serialize = lttng_event_rule_user_tracepoint_serialize;
570 tp_rule->parent.equal = lttng_event_rule_user_tracepoint_is_equal;
571 tp_rule->parent.destroy = lttng_event_rule_user_tracepoint_destroy;
572 tp_rule->parent.generate_filter_bytecode =
573 lttng_event_rule_user_tracepoint_generate_filter_bytecode;
574 tp_rule->parent.get_filter =
575 lttng_event_rule_user_tracepoint_get_internal_filter;
576 tp_rule->parent.get_filter_bytecode =
577 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode;
578 tp_rule->parent.generate_exclusions =
579 lttng_event_rule_user_tracepoint_generate_exclusions;
580 tp_rule->parent.hash = lttng_event_rule_user_tracepoint_hash;
581 tp_rule->parent.mi_serialize = lttng_event_rule_user_tracepoint_mi_serialize;
582
583 /* Not necessary for now. */
584 tp_rule->parent.generate_lttng_event = NULL;
585
586 tp_rule->log_level_rule = NULL;
587
588 lttng_dynamic_pointer_array_init(&tp_rule->exclusions,
589 destroy_lttng_exclusions_element);
590
591 /* Default pattern is '*'. */
592 status = lttng_event_rule_user_tracepoint_set_name_pattern(rule, "*");
593 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
594 lttng_event_rule_destroy(rule);
595 rule = NULL;
596 }
597
598 end:
599 return rule;
600 }
601
602 ssize_t lttng_event_rule_user_tracepoint_create_from_payload(
603 struct lttng_payload_view *view,
604 struct lttng_event_rule **_event_rule)
605 {
606 ssize_t ret, offset = 0;
607 int i;
608 enum lttng_event_rule_status status;
609 const struct lttng_event_rule_user_tracepoint_comm *tracepoint_comm;
610 const char *pattern;
611 const char *filter_expression = NULL;
612 const char **exclusions = NULL;
613 const uint32_t *exclusion_len;
614 const char *exclusion;
615 struct lttng_buffer_view current_buffer_view;
616 struct lttng_event_rule *rule = NULL;
617 struct lttng_log_level_rule *log_level_rule = NULL;
618
619 if (!_event_rule) {
620 ret = -1;
621 goto end;
622 }
623
624 current_buffer_view = lttng_buffer_view_from_view(
625 &view->buffer, offset, sizeof(*tracepoint_comm));
626 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
627 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
628 ret = -1;
629 goto end;
630 }
631
632 tracepoint_comm = (typeof(tracepoint_comm)) current_buffer_view.data;
633
634 rule = lttng_event_rule_user_tracepoint_create();
635 if (!rule) {
636 ERR("Failed to create event rule user tracepoint.");
637 ret = -1;
638 goto end;
639 }
640
641 /* Skip to payload. */
642 offset += current_buffer_view.size;
643
644 /* Map the pattern. */
645 current_buffer_view = lttng_buffer_view_from_view(
646 &view->buffer, offset, tracepoint_comm->pattern_len);
647
648 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
649 ret = -1;
650 goto end;
651 }
652
653 pattern = current_buffer_view.data;
654 if (!lttng_buffer_view_contains_string(&current_buffer_view, pattern,
655 tracepoint_comm->pattern_len)) {
656 ret = -1;
657 goto end;
658 }
659
660 /* Skip after the pattern. */
661 offset += tracepoint_comm->pattern_len;
662
663 if (!tracepoint_comm->filter_expression_len) {
664 goto skip_filter_expression;
665 }
666
667 /* Map the filter_expression. */
668 current_buffer_view = lttng_buffer_view_from_view(&view->buffer, offset,
669 tracepoint_comm->filter_expression_len);
670 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
671 ret = -1;
672 goto end;
673 }
674
675 filter_expression = current_buffer_view.data;
676 if (!lttng_buffer_view_contains_string(&current_buffer_view,
677 filter_expression,
678 tracepoint_comm->filter_expression_len)) {
679 ret = -1;
680 goto end;
681 }
682
683 /* Skip after the pattern. */
684 offset += tracepoint_comm->filter_expression_len;
685
686 skip_filter_expression:
687 if (!tracepoint_comm->log_level_rule_len) {
688 goto skip_log_level_rule;
689 }
690
691 {
692 /* Map the log level rule. */
693 struct lttng_payload_view current_payload_view =
694 lttng_payload_view_from_view(view, offset,
695 tracepoint_comm->log_level_rule_len);
696
697 ret = lttng_log_level_rule_create_from_payload(
698 &current_payload_view, &log_level_rule);
699 if (ret < 0) {
700 ret = -1;
701 goto end;
702 }
703
704 LTTNG_ASSERT(ret == tracepoint_comm->log_level_rule_len);
705 }
706
707 /* Skip after the log level rule. */
708 offset += tracepoint_comm->log_level_rule_len;
709
710 skip_log_level_rule:
711 for (i = 0; i < tracepoint_comm->exclusions_count; i++) {
712 current_buffer_view = lttng_buffer_view_from_view(
713 &view->buffer, offset, sizeof(*exclusion_len));
714 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
715 ret = -1;
716 goto end;
717 }
718
719 exclusion_len = (typeof(exclusion_len)) current_buffer_view.data;
720 offset += sizeof(*exclusion_len);
721
722 current_buffer_view = lttng_buffer_view_from_view(
723 &view->buffer, offset, *exclusion_len);
724 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
725 ret = -1;
726 goto end;
727 }
728
729 exclusion = current_buffer_view.data;
730 if (!lttng_buffer_view_contains_string(&current_buffer_view,
731 exclusion, *exclusion_len)) {
732 ret = -1;
733 goto end;
734 }
735
736 status = lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(rule, exclusion);
737 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
738 ERR("Failed to add event rule user tracepoint exclusion \"%s\".",
739 exclusion);
740 ret = -1;
741 goto end;
742 }
743
744 /* Skip to next exclusion. */
745 offset += *exclusion_len;
746 }
747
748 status = lttng_event_rule_user_tracepoint_set_name_pattern(rule, pattern);
749 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
750 ERR("Failed to set event rule user tracepoint pattern.");
751 ret = -1;
752 goto end;
753 }
754
755 if (filter_expression) {
756 status = lttng_event_rule_user_tracepoint_set_filter(
757 rule, filter_expression);
758 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
759 ERR("Failed to set event rule user tracepoint pattern.");
760 ret = -1;
761 goto end;
762 }
763 }
764
765 if (log_level_rule) {
766 status = lttng_event_rule_user_tracepoint_set_log_level_rule(
767 rule, log_level_rule);
768 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
769 ERR("Failed to set event rule user tracepoint log level rule.");
770 ret = -1;
771 goto end;
772 }
773 }
774
775 *_event_rule = rule;
776 rule = NULL;
777 ret = offset;
778 end:
779 free(exclusions);
780 lttng_log_level_rule_destroy(log_level_rule);
781 lttng_event_rule_destroy(rule);
782 return ret;
783 }
784
785 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_name_pattern(
786 struct lttng_event_rule *rule, const char *pattern)
787 {
788 char *pattern_copy = NULL;
789 struct lttng_event_rule_user_tracepoint *tracepoint;
790 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
791
792 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !pattern ||
793 strlen(pattern) == 0) {
794 status = LTTNG_EVENT_RULE_STATUS_INVALID;
795 goto end;
796 }
797
798 tracepoint = container_of(
799 rule, struct lttng_event_rule_user_tracepoint, parent);
800 pattern_copy = strdup(pattern);
801 if (!pattern_copy) {
802 status = LTTNG_EVENT_RULE_STATUS_ERROR;
803 goto end;
804 }
805
806 /* Normalize the pattern. */
807 strutils_normalize_star_glob_pattern(pattern_copy);
808
809 free(tracepoint->pattern);
810
811 tracepoint->pattern = pattern_copy;
812 pattern_copy = NULL;
813 end:
814 return status;
815 }
816
817 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern(
818 const struct lttng_event_rule *rule, const char **pattern)
819 {
820 struct lttng_event_rule_user_tracepoint *tracepoint;
821 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
822
823 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !pattern) {
824 status = LTTNG_EVENT_RULE_STATUS_INVALID;
825 goto end;
826 }
827
828 tracepoint = container_of(
829 rule, struct lttng_event_rule_user_tracepoint, parent);
830 if (!tracepoint->pattern) {
831 status = LTTNG_EVENT_RULE_STATUS_UNSET;
832 goto end;
833 }
834
835 *pattern = tracepoint->pattern;
836 end:
837 return status;
838 }
839
840 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_filter(
841 struct lttng_event_rule *rule, const char *expression)
842 {
843 char *expression_copy = NULL;
844 struct lttng_event_rule_user_tracepoint *tracepoint;
845 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
846
847 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !expression ||
848 strlen(expression) == 0) {
849 status = LTTNG_EVENT_RULE_STATUS_INVALID;
850 goto end;
851 }
852
853 tracepoint = container_of(
854 rule, struct lttng_event_rule_user_tracepoint, parent);
855 expression_copy = strdup(expression);
856 if (!expression_copy) {
857 PERROR("Failed to copy filter expression");
858 status = LTTNG_EVENT_RULE_STATUS_ERROR;
859 goto end;
860 }
861
862 if (tracepoint->filter_expression) {
863 free(tracepoint->filter_expression);
864 }
865
866 tracepoint->filter_expression = expression_copy;
867 expression_copy = NULL;
868 end:
869 return status;
870 }
871
872 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_filter(
873 const struct lttng_event_rule *rule, const char **expression)
874 {
875 struct lttng_event_rule_user_tracepoint *tracepoint;
876 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
877
878 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !expression) {
879 status = LTTNG_EVENT_RULE_STATUS_INVALID;
880 goto end;
881 }
882
883 tracepoint = container_of(
884 rule, struct lttng_event_rule_user_tracepoint, parent);
885 if (!tracepoint->filter_expression) {
886 status = LTTNG_EVENT_RULE_STATUS_UNSET;
887 goto end;
888 }
889
890 *expression = tracepoint->filter_expression;
891 end:
892 return status;
893 }
894
895 static bool log_level_rule_valid(const struct lttng_log_level_rule *rule)
896 {
897 bool valid = false;
898 enum lttng_log_level_rule_status status;
899 int level;
900
901 switch (lttng_log_level_rule_get_type(rule)) {
902 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
903 status = lttng_log_level_rule_exactly_get_level(rule, &level);
904 break;
905 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
906 status = lttng_log_level_rule_at_least_as_severe_as_get_level(
907 rule, &level);
908 break;
909 default:
910 abort();
911 }
912
913 LTTNG_ASSERT(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
914
915 if (level < LTTNG_LOGLEVEL_EMERG) {
916 /* Invalid. */
917 goto end;
918 }
919 if (level > LTTNG_LOGLEVEL_DEBUG) {
920 /* Invalid. */
921 goto end;
922 }
923
924 valid = true;
925
926 end:
927 return valid;
928 }
929
930 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_log_level_rule(
931 struct lttng_event_rule *rule,
932 const struct lttng_log_level_rule *log_level_rule)
933 {
934 struct lttng_event_rule_user_tracepoint *tracepoint;
935 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
936 struct lttng_log_level_rule *copy = NULL;
937
938 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule)) {
939 status = LTTNG_EVENT_RULE_STATUS_INVALID;
940 goto end;
941 }
942
943 tracepoint = container_of(
944 rule, struct lttng_event_rule_user_tracepoint, parent);
945
946 if (!log_level_rule_valid(log_level_rule)) {
947 status = LTTNG_EVENT_RULE_STATUS_INVALID;
948 goto end;
949 }
950
951 copy = lttng_log_level_rule_copy(log_level_rule);
952 if (copy == NULL) {
953 status = LTTNG_EVENT_RULE_STATUS_ERROR;
954 goto end;
955 }
956
957 if (tracepoint->log_level_rule) {
958 lttng_log_level_rule_destroy(tracepoint->log_level_rule);
959 }
960
961 tracepoint->log_level_rule = copy;
962
963 end:
964 return status;
965 }
966
967 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_log_level_rule(
968 const struct lttng_event_rule *rule,
969 const struct lttng_log_level_rule **log_level_rule
970 )
971 {
972 struct lttng_event_rule_user_tracepoint *tracepoint;
973 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
974
975 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !log_level_rule) {
976 status = LTTNG_EVENT_RULE_STATUS_INVALID;
977 goto end;
978 }
979
980 tracepoint = container_of(
981 rule, struct lttng_event_rule_user_tracepoint, parent);
982 if (tracepoint->log_level_rule == NULL) {
983 status = LTTNG_EVENT_RULE_STATUS_UNSET;
984 goto end;
985 }
986
987 *log_level_rule = tracepoint->log_level_rule;
988 end:
989 return status;
990 }
991
992 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
993 struct lttng_event_rule *rule,
994 const char *exclusion)
995 {
996 int ret;
997 char *exclusion_copy = NULL;
998 struct lttng_event_rule_user_tracepoint *tracepoint;
999 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1000
1001 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) ||
1002 !exclusion) {
1003 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1004 goto end;
1005 }
1006
1007 tracepoint = container_of(
1008 rule, struct lttng_event_rule_user_tracepoint, parent);
1009
1010 if (strlen(exclusion) >= LTTNG_SYMBOL_NAME_LEN) {
1011 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1012 goto end;
1013 }
1014
1015 exclusion_copy = strdup(exclusion);
1016 if (!exclusion_copy) {
1017 status = LTTNG_EVENT_RULE_STATUS_ERROR;
1018 goto end;
1019 }
1020
1021 ret = lttng_dynamic_pointer_array_add_pointer(&tracepoint->exclusions,
1022 exclusion_copy);
1023 if (ret < 0) {
1024 status = LTTNG_EVENT_RULE_STATUS_ERROR;
1025 goto end;
1026 }
1027
1028 exclusion_copy = NULL;
1029 end:
1030 free(exclusion_copy);
1031 return status;
1032 }
1033
1034 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
1035 const struct lttng_event_rule *rule, unsigned int *count)
1036 {
1037 struct lttng_event_rule_user_tracepoint *tracepoint;
1038 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1039
1040 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !count) {
1041 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1042 goto end;
1043 }
1044
1045 tracepoint = container_of(
1046 rule, struct lttng_event_rule_user_tracepoint, parent);
1047 *count = lttng_dynamic_pointer_array_get_count(&tracepoint->exclusions);
1048 end:
1049 return status;
1050 }
1051
1052 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
1053 const struct lttng_event_rule *rule,
1054 unsigned int index,
1055 const char **exclusion)
1056 {
1057 unsigned int count;
1058 struct lttng_event_rule_user_tracepoint *tracepoint;
1059 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1060
1061 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !exclusion) {
1062 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1063 goto end;
1064 }
1065
1066 tracepoint = container_of(
1067 rule, struct lttng_event_rule_user_tracepoint, parent);
1068 if (lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule, &count) !=
1069 LTTNG_EVENT_RULE_STATUS_OK) {
1070 goto end;
1071 }
1072
1073 if (index >= count) {
1074 goto end;
1075 }
1076
1077 *exclusion = lttng_dynamic_pointer_array_get_pointer(
1078 &tracepoint->exclusions, index);
1079 end:
1080 return status;
1081 }
This page took 0.051088 seconds and 4 git commands to generate.