Base lttng_trace_format_descriptor
[lttng-tools.git] / src / common / config / session-config.cpp
1 /*
2 * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include "lttng/tracker.h"
9 #define _LGPL_SOURCE
10 #include <ctype.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <inttypes.h>
15 #include <dirent.h>
16 #include <unistd.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <stdbool.h>
20
21 #include <common/defaults.hpp>
22 #include <common/error.hpp>
23 #include <common/macros.hpp>
24 #include <common/utils.hpp>
25 #include <common/dynamic-buffer.hpp>
26 #include <common/compat/getenv.hpp>
27 #include <lttng/lttng-error.h>
28 #include <libxml/parser.h>
29 #include <libxml/valid.h>
30 #include <libxml/xmlschemas.h>
31 #include <libxml/tree.h>
32 #include <lttng/lttng.h>
33 #include <lttng/snapshot.h>
34 #include <lttng/rotation.h>
35 #include <lttng/userspace-probe.h>
36
37 #include "session-config.hpp"
38 #include "config-internal.hpp"
39
40 #define CONFIG_USERSPACE_PROBE_LOOKUP_METHOD_NAME_MAX_LEN 7
41
42 namespace {
43 struct session_config_validation_ctx {
44 xmlSchemaParserCtxtPtr parser_ctx;
45 xmlSchemaPtr schema;
46 xmlSchemaValidCtxtPtr schema_validation_ctx;
47 };
48 } /* namespace */
49
50 const char * const config_element_all = "all";
51 LTTNG_EXPORT const char *config_xml_encoding = "UTF-8";
52 LTTNG_EXPORT size_t config_xml_encoding_bytes_per_char = 2; /* Size of the encoding's largest character */
53 LTTNG_EXPORT const char *config_xml_indent_string = "\t";
54 LTTNG_EXPORT const char *config_xml_true = "true";
55 LTTNG_EXPORT const char *config_xml_false = "false";
56
57 const char * const config_element_channel = "channel";
58 const char * const config_element_channels = "channels";
59 const char * const config_element_domain = "domain";
60 const char * const config_element_domains = "domains";
61 const char * const config_element_event = "event";
62 const char * const config_element_events = "events";
63 const char * const config_element_context = "context";
64 const char * const config_element_contexts = "contexts";
65 const char * const config_element_attributes = "attributes";
66 const char * const config_element_exclusion = "exclusion";
67 const char * const config_element_exclusions = "exclusions";
68 const char * const config_element_function_attributes = "function_attributes";
69 const char * const config_element_probe_attributes = "probe_attributes";
70 const char * const config_element_symbol_name = "symbol_name";
71 const char * const config_element_address = "address";
72 const char * const config_element_offset = "offset";
73
74 const char * const config_element_userspace_probe_lookup = "lookup_method";
75 const char * const config_element_userspace_probe_lookup_function_default = "DEFAULT";
76 const char * const config_element_userspace_probe_lookup_function_elf = "ELF";
77 const char * const config_element_userspace_probe_lookup_tracepoint_sdt = "SDT";
78 const char * const config_element_userspace_probe_location_binary_path = "binary_path";
79 const char * const config_element_userspace_probe_function_attributes = "userspace_probe_function_attributes";
80 const char * const config_element_userspace_probe_function_location_function_name = "function_name";
81 const char * const config_element_userspace_probe_tracepoint_attributes = "userspace_probe_tracepoint_attributes";
82 const char * const config_element_userspace_probe_tracepoint_location_provider_name = "provider_name";
83 const char * const config_element_userspace_probe_tracepoint_location_probe_name = "probe_name";
84
85 const char * const config_element_name = "name";
86 const char * const config_element_enabled = "enabled";
87 const char * const config_element_overwrite_mode = "overwrite_mode";
88 const char * const config_element_subbuf_size = "subbuffer_size";
89 const char * const config_element_num_subbuf = "subbuffer_count";
90 const char * const config_element_switch_timer_interval = "switch_timer_interval";
91 const char * const config_element_read_timer_interval = "read_timer_interval";
92 const char * const config_element_monitor_timer_interval = "monitor_timer_interval";
93 const char * const config_element_blocking_timeout = "blocking_timeout";
94 const char * const config_element_output = "output";
95 const char * const config_element_output_type = "output_type";
96 const char * const config_element_tracefile_size = "tracefile_size";
97 const char * const config_element_tracefile_count = "tracefile_count";
98 const char * const config_element_live_timer_interval = "live_timer_interval";
99 const char * const config_element_discarded_events = "discarded_events";
100 const char * const config_element_lost_packets = "lost_packets";
101 const char * const config_element_type = "type";
102 const char * const config_element_buffer_type = "buffer_type";
103 const char * const config_element_session = "session";
104 const char * const config_element_sessions = "sessions";
105 const char * const config_element_context_perf = "perf";
106 const char * const config_element_context_app = "app";
107 const char * const config_element_context_app_provider_name = "provider_name";
108 const char * const config_element_context_app_ctx_name = "ctx_name";
109 const char * const config_element_config = "config";
110 const char * const config_element_started = "started";
111 const char * const config_element_snapshot_mode = "snapshot_mode";
112 const char * const config_element_loglevel = "loglevel";
113 const char * const config_element_loglevel_type = "loglevel_type";
114 const char * const config_element_filter = "filter";
115 const char * const config_element_filter_expression = "filter_expression";
116 const char * const config_element_snapshot_outputs = "snapshot_outputs";
117 const char * const config_element_consumer_output = "consumer_output";
118 const char * const config_element_destination = "destination";
119 const char * const config_element_path = "path";
120 const char * const config_element_net_output = "net_output";
121 const char * const config_element_control_uri = "control_uri";
122 const char * const config_element_data_uri = "data_uri";
123 const char * const config_element_max_size = "max_size";
124 const char * const config_element_pid = "pid";
125 const char * const config_element_pids = "pids";
126 const char * const config_element_shared_memory_path = "shared_memory_path";
127
128 const char * const config_element_process_attr_id = "id";
129 const char * const config_element_process_attr_tracker_pid = "pid_process_attr_tracker";
130 const char * const config_element_process_attr_tracker_vpid = "vpid_process_attr_tracker";
131 const char * const config_element_process_attr_tracker_uid = "uid_process_attr_tracker";
132 const char * const config_element_process_attr_tracker_vuid = "vuid_process_attr_tracker";
133 const char * const config_element_process_attr_tracker_gid = "gid_process_attr_tracker";
134 const char * const config_element_process_attr_tracker_vgid = "vgid_process_attr_tracker";
135 const char * const config_element_process_attr_trackers = "process_attr_trackers";
136 const char * const config_element_process_attr_values = "process_attr_values";
137 const char * const config_element_process_attr_value_type = "process_attr_value_type";
138 const char * const config_element_process_attr_pid_value = "pid";
139 const char * const config_element_process_attr_vpid_value = "vpid";
140 const char * const config_element_process_attr_uid_value = "uid";
141 const char * const config_element_process_attr_vuid_value = "vuid";
142 const char * const config_element_process_attr_gid_value = "gid";
143 const char * const config_element_process_attr_vgid_value = "vgid";
144 const char * const config_element_process_attr_tracker_type = "process_attr_tracker_type";
145
146 /* Used for support of legacy tracker serialization (< 2.12). */
147 const char * const config_element_trackers_legacy = "trackers";
148 const char * const config_element_pid_tracker_legacy = "pid_tracker";
149 const char * const config_element_tracker_targets_legacy = "targets";
150 const char * const config_element_tracker_pid_legacy = "pid";
151
152 const char * const config_element_rotation_schedules = "rotation_schedules";
153 const char * const config_element_rotation_schedule_periodic = "periodic";
154 const char * const config_element_rotation_schedule_periodic_time_us = "time_us";
155 const char * const config_element_rotation_schedule_size_threshold = "size_threshold";
156 const char * const config_element_rotation_schedule_size_threshold_bytes = "bytes";
157
158 const char * const config_domain_type_kernel = "KERNEL";
159 const char * const config_domain_type_ust = "UST";
160 const char * const config_domain_type_jul = "JUL";
161 const char * const config_domain_type_log4j = "LOG4J";
162 const char * const config_domain_type_python = "PYTHON";
163
164 const char * const config_buffer_type_per_pid = "PER_PID";
165 const char * const config_buffer_type_per_uid = "PER_UID";
166 const char * const config_buffer_type_global = "GLOBAL";
167
168 const char * const config_overwrite_mode_discard = "DISCARD";
169 const char * const config_overwrite_mode_overwrite = "OVERWRITE";
170
171 const char * const config_output_type_splice = "SPLICE";
172 const char * const config_output_type_mmap = "MMAP";
173
174 const char * const config_loglevel_type_all = "ALL";
175 const char * const config_loglevel_type_range = "RANGE";
176 const char * const config_loglevel_type_single = "SINGLE";
177
178 const char * const config_event_type_all = "ALL";
179 const char * const config_event_type_tracepoint = "TRACEPOINT";
180 const char * const config_event_type_probe = "PROBE";
181 const char * const config_event_type_userspace_probe = "USERSPACE_PROBE";
182 const char * const config_event_type_function = "FUNCTION";
183 const char * const config_event_type_function_entry = "FUNCTION_ENTRY";
184 const char * const config_event_type_noop = "NOOP";
185 const char * const config_event_type_syscall = "SYSCALL";
186 const char * const config_event_type_kprobe = "KPROBE";
187 const char * const config_event_type_kretprobe = "KRETPROBE";
188
189 const char * const config_event_context_pid = "PID";
190 const char * const config_event_context_procname = "PROCNAME";
191 const char * const config_event_context_prio = "PRIO";
192 const char * const config_event_context_nice = "NICE";
193 const char * const config_event_context_vpid = "VPID";
194 const char * const config_event_context_tid = "TID";
195 const char * const config_event_context_vtid = "VTID";
196 const char * const config_event_context_ppid = "PPID";
197 const char * const config_event_context_vppid = "VPPID";
198 const char * const config_event_context_pthread_id = "PTHREAD_ID";
199 const char * const config_event_context_hostname = "HOSTNAME";
200 const char * const config_event_context_ip = "IP";
201 const char * const config_event_context_perf_thread_counter = "PERF_THREAD_COUNTER";
202 const char * const config_event_context_app = "APP";
203 const char * const config_event_context_interruptible = "INTERRUPTIBLE";
204 const char * const config_event_context_preemptible = "PREEMPTIBLE";
205 const char * const config_event_context_need_reschedule = "NEED_RESCHEDULE";
206 const char * const config_event_context_migratable = "MIGRATABLE";
207 const char * const config_event_context_callstack_user= "CALLSTACK_USER";
208 const char * const config_event_context_callstack_kernel = "CALLSTACK_KERNEL";
209 const char * const config_event_context_cgroup_ns = "CGROUP_NS";
210 const char * const config_event_context_ipc_ns = "IPC_NS";
211 const char * const config_event_context_mnt_ns = "MNT_NS";
212 const char * const config_event_context_net_ns = "NET_NS";
213 const char * const config_event_context_pid_ns = "PID_NS";
214 const char * const config_event_context_time_ns = "TIME_NS";
215 const char * const config_event_context_user_ns = "USER_NS";
216 const char * const config_event_context_uts_ns = "UTS_NS";
217 const char * const config_event_context_uid = "UID";
218 const char * const config_event_context_euid = "EUID";
219 const char * const config_event_context_suid = "SUID";
220 const char * const config_event_context_gid = "GID";
221 const char * const config_event_context_egid = "EGID";
222 const char * const config_event_context_sgid = "SGID";
223 const char * const config_event_context_vuid = "VUID";
224 const char * const config_event_context_veuid = "VEUID";
225 const char * const config_event_context_vsuid = "VSUID";
226 const char * const config_event_context_vgid = "VGID";
227 const char * const config_event_context_vegid = "VEGID";
228 const char * const config_event_context_vsgid = "VSGID";
229
230 const char * const config_element_session_trace_format = "trace_format";
231 const char * const config_element_session_trace_format_ctf1 = "ctf1";
232 const char * const config_element_session_trace_format_ctf2 = "ctf2";
233
234
235 /* Deprecated symbols */
236 LTTNG_EXPORT const char *config_element_perf;
237
238 enum process_event_node_phase {
239 CREATION = 0,
240 ENABLE = 1,
241 };
242
243 namespace {
244 struct consumer_output {
245 int enabled;
246 char *path;
247 char *control_uri;
248 char *data_uri;
249 };
250 } /* namespace */
251
252 /*
253 * Returns a xmlChar string which must be released using xmlFree().
254 */
255 static xmlChar *encode_string(const char *in_str)
256 {
257 xmlChar *out_str = NULL;
258 xmlCharEncodingHandlerPtr handler;
259 int out_len, ret, in_len;
260
261 LTTNG_ASSERT(in_str);
262
263 handler = xmlFindCharEncodingHandler(config_xml_encoding);
264 if (!handler) {
265 ERR("xmlFindCharEncodingHandler return NULL!. Configure issue!");
266 goto end;
267 }
268
269 in_len = strlen(in_str);
270 /*
271 * Add 1 byte for the NULL terminted character. The factor 4 here is
272 * used because UTF-8 characters can take up to 4 bytes.
273 */
274 out_len = (in_len * 4) + 1;
275 out_str = (xmlChar *) xmlMalloc(out_len);
276 if (!out_str) {
277 goto end;
278 }
279
280 ret = handler->input(out_str, &out_len, (const xmlChar *) in_str, &in_len);
281 if (ret < 0) {
282 xmlFree(out_str);
283 out_str = NULL;
284 goto end;
285 }
286
287 /* out_len is now the size of out_str */
288 out_str[out_len] = '\0';
289 end:
290 return out_str;
291 }
292
293 struct config_writer *config_writer_create(int fd_output, int indent)
294 {
295 int ret;
296 struct config_writer *writer;
297 xmlOutputBufferPtr buffer;
298
299 writer = zmalloc<config_writer>();
300 if (!writer) {
301 PERROR("zmalloc config_writer_create");
302 goto end;
303 }
304
305 buffer = xmlOutputBufferCreateFd(fd_output, NULL);
306 if (!buffer) {
307 goto error_destroy;
308 }
309
310 writer->writer = xmlNewTextWriter(buffer);
311 ret = xmlTextWriterStartDocument(writer->writer, NULL,
312 config_xml_encoding, NULL);
313 if (ret < 0) {
314 goto error_destroy;
315 }
316
317 ret = xmlTextWriterSetIndentString(writer->writer,
318 BAD_CAST config_xml_indent_string);
319 if (ret) {
320 goto error_destroy;
321 }
322
323 ret = xmlTextWriterSetIndent(writer->writer, indent);
324 if (ret) {
325 goto error_destroy;
326 }
327
328 end:
329 return writer;
330 error_destroy:
331 config_writer_destroy(writer);
332 return NULL;
333 }
334
335 int config_writer_destroy(struct config_writer *writer)
336 {
337 int ret = 0;
338
339 if (!writer) {
340 ret = -EINVAL;
341 goto end;
342 }
343
344 if (xmlTextWriterEndDocument(writer->writer) < 0) {
345 WARN("Could not close XML document");
346 ret = -EIO;
347 }
348
349 if (writer->writer) {
350 xmlFreeTextWriter(writer->writer);
351 }
352
353 free(writer);
354 end:
355 return ret;
356 }
357
358 int config_writer_open_element(struct config_writer *writer,
359 const char *element_name)
360 {
361 int ret;
362 xmlChar *encoded_element_name;
363
364 if (!writer || !writer->writer || !element_name || !element_name[0]) {
365 ret = -1;
366 goto end;
367 }
368
369 encoded_element_name = encode_string(element_name);
370 if (!encoded_element_name) {
371 ret = -1;
372 goto end;
373 }
374
375 ret = xmlTextWriterStartElement(writer->writer, encoded_element_name);
376 xmlFree(encoded_element_name);
377 end:
378 return ret >= 0 ? 0 : ret;
379 }
380
381 int config_writer_write_attribute(struct config_writer *writer,
382 const char *name, const char *value)
383 {
384 int ret;
385 xmlChar *encoded_name = NULL;
386 xmlChar *encoded_value = NULL;
387
388 if (!writer || !writer->writer || !name || !name[0]) {
389 ret = -1;
390 goto end;
391 }
392
393 encoded_name = encode_string(name);
394 if (!encoded_name) {
395 ret = -1;
396 goto end;
397 }
398
399 encoded_value = encode_string(value);
400 if (!encoded_value) {
401 ret = -1;
402 goto end;
403 }
404
405 ret = xmlTextWriterWriteAttribute(writer->writer, encoded_name,
406 encoded_value);
407 end:
408 xmlFree(encoded_name);
409 xmlFree(encoded_value);
410 return ret >= 0 ? 0 : ret;
411 }
412
413 int config_writer_close_element(struct config_writer *writer)
414 {
415 int ret;
416
417 if (!writer || !writer->writer) {
418 ret = -1;
419 goto end;
420 }
421
422 ret = xmlTextWriterEndElement(writer->writer);
423 end:
424 return ret >= 0 ? 0 : ret;
425 }
426
427 int config_writer_write_element_unsigned_int(struct config_writer *writer,
428 const char *element_name, uint64_t value)
429 {
430 int ret;
431 xmlChar *encoded_element_name;
432
433 if (!writer || !writer->writer || !element_name || !element_name[0]) {
434 ret = -1;
435 goto end;
436 }
437
438 encoded_element_name = encode_string(element_name);
439 if (!encoded_element_name) {
440 ret = -1;
441 goto end;
442 }
443
444 ret = xmlTextWriterWriteFormatElement(writer->writer,
445 encoded_element_name, "%" PRIu64, value);
446 xmlFree(encoded_element_name);
447 end:
448 return ret >= 0 ? 0 : ret;
449 }
450
451 int config_writer_write_element_signed_int(struct config_writer *writer,
452 const char *element_name, int64_t value)
453 {
454 int ret;
455 xmlChar *encoded_element_name;
456
457 if (!writer || !writer->writer || !element_name || !element_name[0]) {
458 ret = -1;
459 goto end;
460 }
461
462 encoded_element_name = encode_string(element_name);
463 if (!encoded_element_name) {
464 ret = -1;
465 goto end;
466 }
467
468 ret = xmlTextWriterWriteFormatElement(writer->writer,
469 encoded_element_name, "%" PRIi64, value);
470 xmlFree(encoded_element_name);
471 end:
472 return ret >= 0 ? 0 : ret;
473 }
474
475 int config_writer_write_element_bool(struct config_writer *writer,
476 const char *element_name, int value)
477 {
478 return config_writer_write_element_string(writer, element_name,
479 value ? config_xml_true : config_xml_false);
480 }
481
482 int config_writer_write_element_double(struct config_writer *writer,
483 const char *element_name,
484 double value)
485 {
486 int ret;
487 xmlChar *encoded_element_name;
488
489 if (!writer || !writer->writer || !element_name || !element_name[0]) {
490 ret = -1;
491 goto end;
492 }
493
494 encoded_element_name = encode_string(element_name);
495 if (!encoded_element_name) {
496 ret = -1;
497 goto end;
498 }
499
500 ret = xmlTextWriterWriteFormatElement(
501 writer->writer, encoded_element_name, "%f", value);
502 xmlFree(encoded_element_name);
503 end:
504 return ret >= 0 ? 0 : ret;
505 }
506
507 int config_writer_write_element_string(struct config_writer *writer,
508 const char *element_name, const char *value)
509 {
510 int ret;
511 xmlChar *encoded_element_name = NULL;
512 xmlChar *encoded_value = NULL;
513
514 if (!writer || !writer->writer || !element_name || !element_name[0] ||
515 !value) {
516 ret = -1;
517 goto end;
518 }
519
520 encoded_element_name = encode_string(element_name);
521 if (!encoded_element_name) {
522 ret = -1;
523 goto end;
524 }
525
526 encoded_value = encode_string(value);
527 if (!encoded_value) {
528 ret = -1;
529 goto end;
530 }
531
532 ret = xmlTextWriterWriteElement(writer->writer, encoded_element_name,
533 encoded_value);
534 end:
535 xmlFree(encoded_element_name);
536 xmlFree(encoded_value);
537 return ret >= 0 ? 0 : ret;
538 }
539
540 static ATTR_FORMAT_PRINTF(2, 3)
541 void xml_error_handler(void *ctx __attribute__((unused)), const char *format, ...)
542 {
543 char *errMsg;
544 va_list args;
545 int ret;
546
547 va_start(args, format);
548 ret = vasprintf(&errMsg, format, args);
549 va_end(args);
550 if (ret == -1) {
551 ERR("String allocation failed in xml error handler");
552 return;
553 }
554
555 fprintf(stderr, "XML Error: %s", errMsg);
556 free(errMsg);
557 }
558
559 static
560 void fini_session_config_validation_ctx(
561 struct session_config_validation_ctx *ctx)
562 {
563 if (ctx->parser_ctx) {
564 xmlSchemaFreeParserCtxt(ctx->parser_ctx);
565 }
566
567 if (ctx->schema) {
568 xmlSchemaFree(ctx->schema);
569 }
570
571 if (ctx->schema_validation_ctx) {
572 xmlSchemaFreeValidCtxt(ctx->schema_validation_ctx);
573 }
574
575 memset(ctx, 0, sizeof(struct session_config_validation_ctx));
576 }
577
578 static
579 char *get_session_config_xsd_path(void)
580 {
581 char *xsd_path;
582 const char *base_path = lttng_secure_getenv(DEFAULT_SESSION_CONFIG_XSD_PATH_ENV);
583 size_t base_path_len;
584 size_t max_path_len;
585
586 if (!base_path) {
587 base_path = DEFAULT_SESSION_CONFIG_XSD_PATH;
588 }
589
590 base_path_len = strlen(base_path);
591 max_path_len = base_path_len +
592 sizeof(DEFAULT_SESSION_CONFIG_XSD_FILENAME) + 1;
593 xsd_path = zmalloc<char>(max_path_len);
594 if (!xsd_path) {
595 goto end;
596 }
597
598 strcpy(xsd_path, base_path);
599 if (xsd_path[base_path_len - 1] != '/') {
600 xsd_path[base_path_len++] = '/';
601 }
602
603 strcpy(xsd_path + base_path_len, DEFAULT_SESSION_CONFIG_XSD_FILENAME);
604 end:
605 return xsd_path;
606 }
607
608 static
609 int init_session_config_validation_ctx(
610 struct session_config_validation_ctx *ctx)
611 {
612 int ret;
613 char *xsd_path = get_session_config_xsd_path();
614
615 if (!xsd_path) {
616 ret = -LTTNG_ERR_NOMEM;
617 goto end;
618 }
619
620 ctx->parser_ctx = xmlSchemaNewParserCtxt(xsd_path);
621 if (!ctx->parser_ctx) {
622 ERR("XSD parser context creation failed");
623 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
624 goto end;
625 }
626 xmlSchemaSetParserErrors(ctx->parser_ctx, xml_error_handler,
627 xml_error_handler, NULL);
628
629 ctx->schema = xmlSchemaParse(ctx->parser_ctx);
630 if (!ctx->schema) {
631 ERR("XSD parsing failed");
632 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
633 goto end;
634 }
635
636 ctx->schema_validation_ctx = xmlSchemaNewValidCtxt(ctx->schema);
637 if (!ctx->schema_validation_ctx) {
638 ERR("XSD validation context creation failed");
639 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
640 goto end;
641 }
642
643 xmlSchemaSetValidErrors(ctx->schema_validation_ctx, xml_error_handler,
644 xml_error_handler, NULL);
645 ret = 0;
646
647 end:
648 if (ret) {
649 fini_session_config_validation_ctx(ctx);
650 }
651
652 free(xsd_path);
653 return ret;
654 }
655
656 static
657 int parse_uint(xmlChar *str, uint64_t *val)
658 {
659 int ret;
660 char *endptr;
661
662 if (!str || !val) {
663 ret = -1;
664 goto end;
665 }
666
667 *val = strtoull((const char *) str, &endptr, 10);
668 if (!endptr || *endptr) {
669 ret = -1;
670 } else {
671 ret = 0;
672 }
673
674 end:
675 return ret;
676 }
677
678 static
679 int parse_int(xmlChar *str, int64_t *val)
680 {
681 int ret;
682 char *endptr;
683
684 if (!str || !val) {
685 ret = -1;
686 goto end;
687 }
688
689 *val = strtoll((const char *) str, &endptr, 10);
690 if (!endptr || *endptr) {
691 ret = -1;
692 } else {
693 ret = 0;
694 }
695
696 end:
697 return ret;
698 }
699
700 static
701 int parse_bool(xmlChar *str, int *val)
702 {
703 int ret = 0;
704
705 if (!str || !val) {
706 ret = -1;
707 goto end;
708 }
709
710 if (!strcmp((const char *) str, config_xml_true) ||
711 !strcmp((const char *) str, "1")) {
712 *val = 1;
713 } else if (!strcmp((const char *) str, config_xml_false) ||
714 !strcmp((const char *) str, "0")) {
715 *val = 0;
716 } else {
717 WARN("Invalid boolean value encountered (%s).",
718 (const char *) str);
719 ret = -1;
720 }
721 end:
722 return ret;
723 }
724
725 static
726 int get_domain_type(xmlChar *domain)
727 {
728 int ret;
729
730 if (!domain) {
731 goto error;
732 }
733
734 if (!strcmp((char *) domain, config_domain_type_kernel)) {
735 ret = LTTNG_DOMAIN_KERNEL;
736 } else if (!strcmp((char *) domain, config_domain_type_ust)) {
737 ret = LTTNG_DOMAIN_UST;
738 } else if (!strcmp((char *) domain, config_domain_type_jul)) {
739 ret = LTTNG_DOMAIN_JUL;
740 } else if (!strcmp((char *) domain, config_domain_type_log4j)) {
741 ret = LTTNG_DOMAIN_LOG4J;
742 } else if (!strcmp((char *) domain, config_domain_type_python)) {
743 ret = LTTNG_DOMAIN_PYTHON;
744 } else {
745 goto error;
746 }
747
748 return ret;
749 error:
750 return -1;
751 }
752
753 static
754 int get_buffer_type(xmlChar *buffer_type)
755 {
756 int ret;
757
758 if (!buffer_type) {
759 goto error;
760 }
761
762 if (!strcmp((char *) buffer_type, config_buffer_type_global)) {
763 ret = LTTNG_BUFFER_GLOBAL;
764 } else if (!strcmp((char *) buffer_type, config_buffer_type_per_uid)) {
765 ret = LTTNG_BUFFER_PER_UID;
766 } else if (!strcmp((char *) buffer_type, config_buffer_type_per_pid)) {
767 ret = LTTNG_BUFFER_PER_PID;
768 } else {
769 goto error;
770 }
771
772 return ret;
773 error:
774 return -1;
775 }
776
777 static
778 int get_overwrite_mode(xmlChar *overwrite_mode)
779 {
780 int ret;
781
782 if (!overwrite_mode) {
783 goto error;
784 }
785
786 if (!strcmp((char *) overwrite_mode, config_overwrite_mode_overwrite)) {
787 ret = 1;
788 } else if (!strcmp((char *) overwrite_mode,
789 config_overwrite_mode_discard)) {
790 ret = 0;
791 } else {
792 goto error;
793 }
794
795 return ret;
796 error:
797 return -1;
798 }
799
800 static
801 int get_output_type(xmlChar *output_type)
802 {
803 int ret;
804
805 if (!output_type) {
806 goto error;
807 }
808
809 if (!strcmp((char *) output_type, config_output_type_mmap)) {
810 ret = LTTNG_EVENT_MMAP;
811 } else if (!strcmp((char *) output_type, config_output_type_splice)) {
812 ret = LTTNG_EVENT_SPLICE;
813 } else {
814 goto error;
815 }
816
817 return ret;
818 error:
819 return -1;
820 }
821
822 static
823 int get_event_type(xmlChar *event_type)
824 {
825 int ret;
826
827 if (!event_type) {
828 goto error;
829 }
830
831 if (!strcmp((char *) event_type, config_event_type_all)) {
832 ret = LTTNG_EVENT_ALL;
833 } else if (!strcmp((char *) event_type, config_event_type_tracepoint)) {
834 ret = LTTNG_EVENT_TRACEPOINT;
835 } else if (!strcmp((char *) event_type, config_event_type_probe)) {
836 ret = LTTNG_EVENT_PROBE;
837 } else if (!strcmp((char *) event_type,
838 config_event_type_userspace_probe)) {
839 ret = LTTNG_EVENT_USERSPACE_PROBE;
840 } else if (!strcmp((char *) event_type, config_event_type_function)) {
841 ret = LTTNG_EVENT_FUNCTION;
842 } else if (!strcmp((char *) event_type,
843 config_event_type_function_entry)) {
844 ret = LTTNG_EVENT_FUNCTION_ENTRY;
845 } else if (!strcmp((char *) event_type, config_event_type_noop)) {
846 ret = LTTNG_EVENT_NOOP;
847 } else if (!strcmp((char *) event_type, config_event_type_syscall)) {
848 ret = LTTNG_EVENT_SYSCALL;
849 } else {
850 goto error;
851 }
852
853 return ret;
854 error:
855 return -1;
856 }
857
858 static
859 int get_loglevel_type(xmlChar *loglevel_type)
860 {
861 int ret;
862
863 if (!loglevel_type) {
864 goto error;
865 }
866
867 if (!strcmp((char *) loglevel_type, config_loglevel_type_all)) {
868 ret = LTTNG_EVENT_LOGLEVEL_ALL;
869 } else if (!strcmp((char *) loglevel_type,
870 config_loglevel_type_range)) {
871 ret = LTTNG_EVENT_LOGLEVEL_RANGE;
872 } else if (!strcmp((char *) loglevel_type,
873 config_loglevel_type_single)) {
874 ret = LTTNG_EVENT_LOGLEVEL_SINGLE;
875 } else {
876 goto error;
877 }
878
879 return ret;
880 error:
881 return -1;
882 }
883
884 /*
885 * Return the context type or -1 on error.
886 */
887 static
888 int get_context_type(xmlChar *context_type)
889 {
890 int ret;
891
892 if (!context_type) {
893 goto error;
894 }
895
896 if (!strcmp((char *) context_type, config_event_context_pid)) {
897 ret = LTTNG_EVENT_CONTEXT_PID;
898 } else if (!strcmp((char *) context_type,
899 config_event_context_procname)) {
900 ret = LTTNG_EVENT_CONTEXT_PROCNAME;
901 } else if (!strcmp((char *) context_type,
902 config_event_context_prio)) {
903 ret = LTTNG_EVENT_CONTEXT_PRIO;
904 } else if (!strcmp((char *) context_type,
905 config_event_context_nice)) {
906 ret = LTTNG_EVENT_CONTEXT_NICE;
907 } else if (!strcmp((char *) context_type,
908 config_event_context_vpid)) {
909 ret = LTTNG_EVENT_CONTEXT_VPID;
910 } else if (!strcmp((char *) context_type,
911 config_event_context_tid)) {
912 ret = LTTNG_EVENT_CONTEXT_TID;
913 } else if (!strcmp((char *) context_type,
914 config_event_context_vtid)) {
915 ret = LTTNG_EVENT_CONTEXT_VTID;
916 } else if (!strcmp((char *) context_type,
917 config_event_context_ppid)) {
918 ret = LTTNG_EVENT_CONTEXT_PPID;
919 } else if (!strcmp((char *) context_type,
920 config_event_context_vppid)) {
921 ret = LTTNG_EVENT_CONTEXT_VPPID;
922 } else if (!strcmp((char *) context_type,
923 config_event_context_pthread_id)) {
924 ret = LTTNG_EVENT_CONTEXT_PTHREAD_ID;
925 } else if (!strcmp((char *) context_type,
926 config_event_context_hostname)) {
927 ret = LTTNG_EVENT_CONTEXT_HOSTNAME;
928 } else if (!strcmp((char *) context_type,
929 config_event_context_ip)) {
930 ret = LTTNG_EVENT_CONTEXT_IP;
931 } else if (!strcmp((char *) context_type,
932 config_event_context_interruptible)) {
933 ret = LTTNG_EVENT_CONTEXT_INTERRUPTIBLE;
934 } else if (!strcmp((char *) context_type,
935 config_event_context_preemptible)) {
936 ret = LTTNG_EVENT_CONTEXT_PREEMPTIBLE;
937 } else if (!strcmp((char *) context_type,
938 config_event_context_need_reschedule)) {
939 ret = LTTNG_EVENT_CONTEXT_NEED_RESCHEDULE;
940 } else if (!strcmp((char *) context_type,
941 config_event_context_migratable)) {
942 ret = LTTNG_EVENT_CONTEXT_MIGRATABLE;
943 } else if (!strcmp((char *) context_type,
944 config_event_context_callstack_user)) {
945 ret = LTTNG_EVENT_CONTEXT_CALLSTACK_USER;
946 } else if (!strcmp((char *) context_type,
947 config_event_context_callstack_kernel)) {
948 ret = LTTNG_EVENT_CONTEXT_CALLSTACK_KERNEL;
949 } else if (!strcmp((char *) context_type,
950 config_event_context_cgroup_ns)) {
951 ret = LTTNG_EVENT_CONTEXT_CGROUP_NS;
952 } else if (!strcmp((char *) context_type,
953 config_event_context_ipc_ns)) {
954 ret = LTTNG_EVENT_CONTEXT_IPC_NS;
955 } else if (!strcmp((char *) context_type,
956 config_event_context_mnt_ns)) {
957 ret = LTTNG_EVENT_CONTEXT_MNT_NS;
958 } else if (!strcmp((char *) context_type,
959 config_event_context_net_ns)) {
960 ret = LTTNG_EVENT_CONTEXT_NET_NS;
961 } else if (!strcmp((char *) context_type,
962 config_event_context_pid_ns)) {
963 ret = LTTNG_EVENT_CONTEXT_PID_NS;
964 } else if (!strcmp((char *) context_type,
965 config_event_context_time_ns)) {
966 ret = LTTNG_EVENT_CONTEXT_TIME_NS;
967 } else if (!strcmp((char *) context_type,
968 config_event_context_user_ns)) {
969 ret = LTTNG_EVENT_CONTEXT_USER_NS;
970 } else if (!strcmp((char *) context_type,
971 config_event_context_uts_ns)) {
972 ret = LTTNG_EVENT_CONTEXT_UTS_NS;
973 } else if (!strcmp((char *) context_type,
974 config_event_context_uid)) {
975 ret = LTTNG_EVENT_CONTEXT_UID;
976 } else if (!strcmp((char *) context_type,
977 config_event_context_euid)) {
978 ret = LTTNG_EVENT_CONTEXT_EUID;
979 } else if (!strcmp((char *) context_type,
980 config_event_context_suid)) {
981 ret = LTTNG_EVENT_CONTEXT_SUID;
982 } else if (!strcmp((char *) context_type,
983 config_event_context_gid)) {
984 ret = LTTNG_EVENT_CONTEXT_GID;
985 } else if (!strcmp((char *) context_type,
986 config_event_context_egid)) {
987 ret = LTTNG_EVENT_CONTEXT_EGID;
988 } else if (!strcmp((char *) context_type,
989 config_event_context_sgid)) {
990 ret = LTTNG_EVENT_CONTEXT_SGID;
991 } else if (!strcmp((char *) context_type,
992 config_event_context_vuid)) {
993 ret = LTTNG_EVENT_CONTEXT_VUID;
994 } else if (!strcmp((char *) context_type,
995 config_event_context_veuid)) {
996 ret = LTTNG_EVENT_CONTEXT_VEUID;
997 } else if (!strcmp((char *) context_type,
998 config_event_context_vsuid)) {
999 ret = LTTNG_EVENT_CONTEXT_VSUID;
1000 } else if (!strcmp((char *) context_type,
1001 config_event_context_vgid)) {
1002 ret = LTTNG_EVENT_CONTEXT_VGID;
1003 } else if (!strcmp((char *) context_type,
1004 config_event_context_vegid)) {
1005 ret = LTTNG_EVENT_CONTEXT_VEGID;
1006 } else if (!strcmp((char *) context_type,
1007 config_event_context_vsgid)) {
1008 ret = LTTNG_EVENT_CONTEXT_VSGID;
1009 } else {
1010 goto error;
1011 }
1012
1013 return ret;
1014 error:
1015 return -1;
1016 }
1017
1018 static
1019 int init_domain(xmlNodePtr domain_node, struct lttng_domain *domain)
1020 {
1021 int ret;
1022 xmlNodePtr node;
1023
1024 for (node = xmlFirstElementChild(domain_node); node;
1025 node = xmlNextElementSibling(node)) {
1026 if (!strcmp((const char *) node->name, config_element_type)) {
1027 /* domain type */
1028 xmlChar *node_content = xmlNodeGetContent(node);
1029 if (!node_content) {
1030 ret = -LTTNG_ERR_NOMEM;
1031 goto end;
1032 }
1033
1034 ret = get_domain_type(node_content);
1035 free(node_content);
1036 if (ret < 0) {
1037 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1038 goto end;
1039 }
1040
1041 domain->type = (lttng_domain_type) ret;
1042 } else if (!strcmp((const char *) node->name,
1043 config_element_buffer_type)) {
1044 /* buffer type */
1045 xmlChar *node_content = xmlNodeGetContent(node);
1046 if (!node_content) {
1047 ret = -LTTNG_ERR_NOMEM;
1048 goto end;
1049 }
1050
1051 ret = get_buffer_type(node_content);
1052 free(node_content);
1053 if (ret < 0) {
1054 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1055 goto end;
1056 }
1057
1058 domain->buf_type = (lttng_buffer_type) ret;
1059 }
1060 }
1061 ret = 0;
1062 end:
1063 return ret;
1064 }
1065
1066 static
1067 int get_net_output_uris(xmlNodePtr net_output_node, char **control_uri,
1068 char **data_uri)
1069 {
1070 xmlNodePtr node;
1071
1072 for (node = xmlFirstElementChild(net_output_node); node;
1073 node = xmlNextElementSibling(node)) {
1074 if (!strcmp((const char *) node->name, config_element_control_uri)) {
1075 /* control_uri */
1076 *control_uri = (char *) xmlNodeGetContent(node);
1077 if (!*control_uri) {
1078 break;
1079 }
1080 } else {
1081 /* data_uri */
1082 *data_uri = (char *) xmlNodeGetContent(node);
1083 if (!*data_uri) {
1084 break;
1085 }
1086 }
1087 }
1088
1089 return *control_uri || *data_uri ? 0 : -LTTNG_ERR_LOAD_INVALID_CONFIG;
1090 }
1091
1092 static
1093 int process_consumer_output(xmlNodePtr consumer_output_node,
1094 struct consumer_output *output)
1095 {
1096 int ret;
1097 xmlNodePtr node;
1098
1099 LTTNG_ASSERT(output);
1100
1101 for (node = xmlFirstElementChild(consumer_output_node); node;
1102 node = xmlNextElementSibling(node)) {
1103 if (!strcmp((const char *) node->name, config_element_enabled)) {
1104 xmlChar *enabled_str = xmlNodeGetContent(node);
1105
1106 /* enabled */
1107 if (!enabled_str) {
1108 ret = -LTTNG_ERR_NOMEM;
1109 goto end;
1110 }
1111
1112 ret = parse_bool(enabled_str, &output->enabled);
1113 free(enabled_str);
1114 if (ret) {
1115 goto end;
1116 }
1117 } else {
1118 xmlNodePtr output_type_node;
1119
1120 /* destination */
1121 output_type_node = xmlFirstElementChild(node);
1122 if (!output_type_node) {
1123 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1124 goto end;
1125 }
1126
1127 if (!strcmp((const char *) output_type_node->name,
1128 config_element_path)) {
1129 /* path */
1130 output->path = (char *) xmlNodeGetContent(output_type_node);
1131 if (!output->path) {
1132 ret = -LTTNG_ERR_NOMEM;
1133 goto end;
1134 }
1135 } else {
1136 /* net_output */
1137 ret = get_net_output_uris(output_type_node,
1138 &output->control_uri, &output->data_uri);
1139 if (ret) {
1140 goto end;
1141 }
1142 }
1143 }
1144 }
1145 ret = 0;
1146
1147 end:
1148 if (ret) {
1149 free(output->path);
1150 free(output->control_uri);
1151 free(output->data_uri);
1152 memset(output, 0, sizeof(struct consumer_output));
1153 }
1154 return ret;
1155 }
1156
1157 static
1158 int create_snapshot_session(const char *session_name, xmlNodePtr output_node,
1159 const struct config_load_session_override_attr *overrides)
1160 {
1161 int ret;
1162 enum lttng_error_code ret_code;
1163 xmlNodePtr node = NULL;
1164 xmlNodePtr snapshot_output_list_node;
1165 xmlNodePtr snapshot_output_node;
1166 struct lttng_session_descriptor *session_descriptor = nullptr;
1167
1168 LTTNG_ASSERT(session_name);
1169 LTTNG_ASSERT(output_node);
1170
1171 /*
1172 * Use a descriptor without output since consumer output size is not
1173 * exposed by the session descriptor api.
1174 */
1175 session_descriptor = lttng_session_descriptor_snapshot_create(session_name);
1176 if (session_descriptor == nullptr) {
1177 ret = -LTTNG_ERR_NOMEM;
1178 goto end;
1179 }
1180
1181 ret_code = lttng_create_session_ext(session_descriptor);
1182 if (ret_code != LTTNG_OK) {
1183 ret = -ret_code;
1184 goto end;
1185 }
1186
1187 snapshot_output_list_node = xmlFirstElementChild(output_node);
1188
1189 /* Parse and create snapshot outputs */
1190 for (snapshot_output_node =
1191 xmlFirstElementChild(snapshot_output_list_node);
1192 snapshot_output_node; snapshot_output_node =
1193 xmlNextElementSibling(snapshot_output_node)) {
1194 char *name = NULL;
1195 uint64_t max_size = UINT64_MAX;
1196 struct consumer_output output = {};
1197 struct lttng_snapshot_output *snapshot_output = NULL;
1198 const char *control_uri = NULL;
1199 const char *data_uri = NULL;
1200 const char *path = NULL;
1201
1202 for (node = xmlFirstElementChild(snapshot_output_node); node;
1203 node = xmlNextElementSibling(node)) {
1204 if (!strcmp((const char *) node->name,
1205 config_element_name)) {
1206 /* name */
1207 name = (char *) xmlNodeGetContent(node);
1208 if (!name) {
1209 ret = -LTTNG_ERR_NOMEM;
1210 goto error_snapshot_output;
1211 }
1212 } else if (!strcmp((const char *) node->name,
1213 config_element_max_size)) {
1214 xmlChar *content = xmlNodeGetContent(node);
1215
1216 /* max_size */
1217 if (!content) {
1218 ret = -LTTNG_ERR_NOMEM;
1219 goto error_snapshot_output;
1220 }
1221 ret = parse_uint(content, &max_size);
1222 free(content);
1223 if (ret) {
1224 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1225 goto error_snapshot_output;
1226 }
1227 } else {
1228 /* consumer_output */
1229 ret = process_consumer_output(node, &output);
1230 if (ret) {
1231 goto error_snapshot_output;
1232 }
1233 }
1234 }
1235
1236 control_uri = output.control_uri;
1237 data_uri = output.data_uri;
1238 path = output.path;
1239
1240 if (overrides) {
1241 if (overrides->path_url) {
1242 path = overrides->path_url;
1243 /* Control/data_uri are null */
1244 control_uri = NULL;
1245 data_uri = NULL;
1246 } else {
1247 if (overrides->ctrl_url) {
1248 control_uri = overrides->ctrl_url;
1249 /* path is null */
1250 path = NULL;
1251 }
1252 if (overrides->data_url) {
1253 data_uri = overrides->data_url;
1254 /* path is null */
1255 path = NULL;
1256 }
1257 }
1258 }
1259
1260 snapshot_output = lttng_snapshot_output_create();
1261 if (!snapshot_output) {
1262 ret = -LTTNG_ERR_NOMEM;
1263 goto error_snapshot_output;
1264 }
1265
1266 ret = lttng_snapshot_output_set_name(name, snapshot_output);
1267 if (ret) {
1268 goto error_snapshot_output;
1269 }
1270
1271 ret = lttng_snapshot_output_set_size(max_size, snapshot_output);
1272 if (ret) {
1273 goto error_snapshot_output;
1274 }
1275
1276 if (path) {
1277 ret = lttng_snapshot_output_set_ctrl_url(path,
1278 snapshot_output);
1279 if (ret) {
1280 goto error_snapshot_output;
1281 }
1282 } else {
1283 if (control_uri) {
1284 ret = lttng_snapshot_output_set_ctrl_url(control_uri,
1285 snapshot_output);
1286 if (ret) {
1287 goto error_snapshot_output;
1288 }
1289 }
1290
1291 if (data_uri) {
1292 ret = lttng_snapshot_output_set_data_url(data_uri,
1293 snapshot_output);
1294 if (ret) {
1295 goto error_snapshot_output;
1296 }
1297 }
1298 }
1299
1300 ret = lttng_snapshot_add_output(session_name, snapshot_output);
1301 error_snapshot_output:
1302 free(name);
1303 free(output.path);
1304 free(output.control_uri);
1305 free(output.data_uri);
1306 lttng_snapshot_output_destroy(snapshot_output);
1307 if (ret) {
1308 goto end;
1309 }
1310 }
1311 end:
1312 lttng_session_descriptor_destroy(session_descriptor);
1313 return ret;
1314 }
1315
1316 static
1317 int create_session(const char *name,
1318 xmlNodePtr output_node,
1319 uint64_t live_timer_interval,
1320 const struct config_load_session_override_attr *overrides)
1321 {
1322 int ret = 0;
1323 enum lttng_error_code ret_code;
1324 struct consumer_output output = {};
1325 xmlNodePtr consumer_output_node;
1326 const char *control_uri = NULL;
1327 const char *data_uri = NULL;
1328 const char *path = NULL;
1329 struct lttng_session_descriptor *session_descriptor = nullptr;
1330
1331 LTTNG_ASSERT(name);
1332
1333 if (output_node) {
1334 consumer_output_node = xmlFirstElementChild(output_node);
1335 if (!consumer_output_node) {
1336 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1337 goto end;
1338 }
1339
1340 if (strcmp((const char *) consumer_output_node->name,
1341 config_element_consumer_output)) {
1342 WARN("Invalid output type, expected %s node",
1343 config_element_consumer_output);
1344 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1345 goto end;
1346 }
1347
1348 ret = process_consumer_output(consumer_output_node, &output);
1349 if (ret) {
1350 goto end;
1351 }
1352 }
1353
1354 control_uri = output.control_uri;
1355 data_uri = output.data_uri;
1356 path = output.path;
1357
1358 /* Check for override and apply them */
1359 if (overrides) {
1360 if (overrides->path_url) {
1361 path = overrides->path_url;
1362 /* control/data_uri are null */;
1363 control_uri = NULL;
1364 data_uri = NULL;
1365 } else {
1366 if (overrides->ctrl_url) {
1367 control_uri = overrides->ctrl_url;
1368 /* path is null */
1369 path = NULL;
1370 }
1371 if (overrides->data_url) {
1372 data_uri = overrides->data_url;
1373 /* path is null */
1374 path = NULL;
1375 }
1376 }
1377 }
1378
1379 if (live_timer_interval != UINT64_MAX && !control_uri && !data_uri) {
1380 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1381 goto end;
1382 }
1383
1384 if (control_uri || data_uri) {
1385 /* network destination */
1386 if (live_timer_interval && live_timer_interval != UINT64_MAX) {
1387 /*
1388 * URLs are provided for sure since the test above make sure that
1389 * with a live timer the data and control URIs are provided. So,
1390 * NULL is passed here and will be set right after.
1391 */
1392 session_descriptor = lttng_session_descriptor_live_network_create(
1393 name, control_uri, data_uri, live_timer_interval);
1394 } else {
1395 session_descriptor = lttng_session_descriptor_network_create(
1396 name, control_uri, data_uri);
1397 }
1398
1399 } else if (path != nullptr) {
1400 session_descriptor = lttng_session_descriptor_local_create(name, path);
1401 } else {
1402 /* No output */
1403 session_descriptor = lttng_session_descriptor_create(name);
1404 }
1405
1406 if (session_descriptor == nullptr) {
1407 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1408 goto end;
1409 }
1410
1411 ret_code = lttng_create_session_ext(session_descriptor);
1412 if (ret_code != LTTNG_OK) {
1413 ret = -ret_code;
1414 goto end;
1415 }
1416
1417 end:
1418 free(output.path);
1419 free(output.control_uri);
1420 free(output.data_uri);
1421 lttng_session_descriptor_destroy(session_descriptor);
1422 return ret;
1423 }
1424
1425 static
1426 struct lttng_userspace_probe_location *
1427 process_userspace_probe_function_attribute_node(
1428 xmlNodePtr attribute_node)
1429 {
1430 xmlNodePtr function_attribute_node;
1431 char *function_name = NULL, *binary_path = NULL;
1432 struct lttng_userspace_probe_location *location = NULL;
1433 struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
1434
1435 /*
1436 * Process userspace probe location function attributes. The order of
1437 * the fields are not guaranteed so we need to iterate over all fields
1438 * and check at the end if everything we need for this location type is
1439 * there.
1440 */
1441 for (function_attribute_node =
1442 xmlFirstElementChild(attribute_node);
1443 function_attribute_node;
1444 function_attribute_node = xmlNextElementSibling(
1445 function_attribute_node)) {
1446 /* Handle function name, binary path and lookup method. */
1447 if (!strcmp((const char *) function_attribute_node->name,
1448 config_element_userspace_probe_function_location_function_name)) {
1449 function_name = (char *) xmlNodeGetContent(function_attribute_node);
1450 if (!function_name) {
1451 goto error;
1452 }
1453 } else if (!strcmp((const char *) function_attribute_node->name,
1454 config_element_userspace_probe_location_binary_path)) {
1455 binary_path = (char *) xmlNodeGetContent(function_attribute_node);
1456 if (!binary_path) {
1457 goto error;
1458 }
1459 } else if (!strcmp((const char *) function_attribute_node->name,
1460 config_element_userspace_probe_lookup)) {
1461 char *lookup_method_name;
1462
1463 lookup_method_name = (char *) xmlNodeGetContent(
1464 function_attribute_node);
1465 if (!lookup_method_name) {
1466 goto error;
1467 }
1468
1469 /*
1470 * function_default lookup method defaults to
1471 * function_elf lookup method at the moment.
1472 */
1473 if (!strcmp(lookup_method_name, config_element_userspace_probe_lookup_function_elf)
1474 || !strcmp(lookup_method_name, config_element_userspace_probe_lookup_function_default)) {
1475 lookup_method = lttng_userspace_probe_location_lookup_method_function_elf_create();
1476 if (!lookup_method) {
1477 PERROR("Error creating function default/ELF lookup method");
1478 }
1479 } else {
1480 WARN("Unknown function lookup method");
1481 }
1482
1483 free(lookup_method_name);
1484 if (!lookup_method) {
1485 goto error;
1486 }
1487 } else {
1488 goto error;
1489 }
1490
1491 /* Check if all the necessary fields were found. */
1492 if (binary_path && function_name && lookup_method) {
1493 /* Ownership of lookup_method is transferred. */
1494 location =
1495 lttng_userspace_probe_location_function_create(
1496 binary_path, function_name,
1497 lookup_method);
1498 lookup_method = NULL;
1499 goto error;
1500 }
1501 }
1502 error:
1503 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
1504 free(binary_path);
1505 free(function_name);
1506 return location;
1507 }
1508
1509 static
1510 struct lttng_userspace_probe_location *
1511 process_userspace_probe_tracepoint_attribute_node(
1512 xmlNodePtr attribute_node)
1513 {
1514 xmlNodePtr tracepoint_attribute_node;
1515 char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
1516 struct lttng_userspace_probe_location *location = NULL;
1517 struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
1518
1519 /*
1520 * Process userspace probe location tracepoint attributes. The order of
1521 * the fields are not guaranteed so we need to iterate over all fields
1522 * and check at the end if everything we need for this location type is
1523 * there.
1524 */
1525 for (tracepoint_attribute_node =
1526 xmlFirstElementChild(attribute_node); tracepoint_attribute_node;
1527 tracepoint_attribute_node = xmlNextElementSibling(
1528 tracepoint_attribute_node)) {
1529 if (!strcmp((const char *) tracepoint_attribute_node->name,
1530 config_element_userspace_probe_tracepoint_location_probe_name)) {
1531 probe_name = (char *) xmlNodeGetContent(tracepoint_attribute_node);
1532 if (!probe_name) {
1533 goto error;
1534 }
1535 } else if (!strcmp((const char *) tracepoint_attribute_node->name,
1536 config_element_userspace_probe_tracepoint_location_provider_name)) {
1537 provider_name = (char *) xmlNodeGetContent(tracepoint_attribute_node);
1538 if (!provider_name) {
1539 goto error;
1540 }
1541 } else if (!strcmp((const char *) tracepoint_attribute_node->name,
1542 config_element_userspace_probe_location_binary_path)) {
1543 binary_path = (char *) xmlNodeGetContent(tracepoint_attribute_node);
1544 if (!binary_path) {
1545 goto error;
1546 }
1547 } else if (!strcmp((const char *) tracepoint_attribute_node->name,
1548 config_element_userspace_probe_lookup)) {
1549 char *lookup_method_name;
1550
1551 lookup_method_name = (char *) xmlNodeGetContent(
1552 tracepoint_attribute_node);
1553 if (!lookup_method_name) {
1554 goto error;
1555 }
1556
1557 if (!strcmp(lookup_method_name,
1558 config_element_userspace_probe_lookup_tracepoint_sdt)) {
1559 lookup_method =
1560 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1561 if (!lookup_method) {
1562 PERROR("Error creating tracepoint SDT lookup method");
1563 }
1564 } else {
1565 WARN("Unknown tracepoint lookup method");
1566 }
1567
1568 free(lookup_method_name);
1569 if (!lookup_method) {
1570 goto error;
1571 }
1572 } else {
1573 WARN("Unknown tracepoint attribute");
1574 goto error;
1575 }
1576
1577 /* Check if all the necessary fields were found. */
1578 if (binary_path && provider_name && probe_name && lookup_method) {
1579 /* Ownership of lookup_method is transferred. */
1580 location =
1581 lttng_userspace_probe_location_tracepoint_create(
1582 binary_path, provider_name,
1583 probe_name, lookup_method);
1584 lookup_method = NULL;
1585 goto error;
1586 }
1587 }
1588 error:
1589 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
1590 free(binary_path);
1591 free(provider_name);
1592 free(probe_name);
1593 return location;
1594 }
1595
1596 static
1597 int process_probe_attribute_node(xmlNodePtr probe_attribute_node,
1598 struct lttng_event_probe_attr *attr)
1599 {
1600 int ret;
1601
1602 LTTNG_ASSERT(probe_attribute_node);
1603 LTTNG_ASSERT(attr);
1604
1605 if (!strcmp((const char *) probe_attribute_node->name,
1606 config_element_address)) {
1607 xmlChar *content;
1608 uint64_t addr = 0;
1609
1610 /* addr */
1611 content = xmlNodeGetContent(probe_attribute_node);
1612 if (!content) {
1613 ret = -LTTNG_ERR_NOMEM;
1614 goto end;
1615 }
1616
1617 ret = parse_uint(content, &addr);
1618 free(content);
1619 if (ret) {
1620 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1621 goto end;
1622 }
1623
1624 attr->addr = addr;
1625 } else if (!strcmp((const char *) probe_attribute_node->name,
1626 config_element_offset)) {
1627 xmlChar *content;
1628 uint64_t offset = 0;
1629
1630 /* offset */
1631 content = xmlNodeGetContent(probe_attribute_node);
1632 if (!content) {
1633 ret = -LTTNG_ERR_NOMEM;
1634 goto end;
1635 }
1636
1637 ret = parse_uint(content, &offset);
1638 free(content);
1639 if (ret) {
1640 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1641 goto end;
1642 }
1643
1644 attr->offset = offset;
1645 } else if (!strcmp((const char *) probe_attribute_node->name,
1646 config_element_symbol_name)) {
1647 xmlChar *content;
1648
1649 /* symbol_name */
1650 content = xmlNodeGetContent(probe_attribute_node);
1651 if (!content) {
1652 ret = -LTTNG_ERR_NOMEM;
1653 goto end;
1654 }
1655
1656 ret = lttng_strncpy(attr->symbol_name,
1657 (const char *) content,
1658 LTTNG_SYMBOL_NAME_LEN);
1659 if (ret == -1) {
1660 ERR("symbol name \"%s\"'s length (%zu) exceeds the maximal permitted length (%d) in session configuration",
1661 (const char *) content,
1662 strlen((const char *) content),
1663 LTTNG_SYMBOL_NAME_LEN);
1664 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1665 free(content);
1666 goto end;
1667 }
1668 free(content);
1669 }
1670 ret = 0;
1671 end:
1672 return ret;
1673 }
1674
1675 static
1676 int process_event_node(xmlNodePtr event_node, struct lttng_handle *handle,
1677 const char *channel_name, const enum process_event_node_phase phase)
1678 {
1679 int ret = 0, i;
1680 xmlNodePtr node;
1681 struct lttng_event *event;
1682 char **exclusions = NULL;
1683 unsigned long exclusion_count = 0;
1684 char *filter_expression = NULL;
1685
1686 LTTNG_ASSERT(event_node);
1687 LTTNG_ASSERT(handle);
1688 LTTNG_ASSERT(channel_name);
1689
1690 event = lttng_event_create();
1691 if (!event) {
1692 ret = -LTTNG_ERR_NOMEM;
1693 goto end;
1694 }
1695
1696 /* Initialize default log level which varies by domain */
1697 switch (handle->domain.type)
1698 {
1699 case LTTNG_DOMAIN_JUL:
1700 event->loglevel = LTTNG_LOGLEVEL_JUL_ALL;
1701 break;
1702 case LTTNG_DOMAIN_LOG4J:
1703 event->loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
1704 break;
1705 case LTTNG_DOMAIN_PYTHON:
1706 event->loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
1707 break;
1708 case LTTNG_DOMAIN_UST:
1709 case LTTNG_DOMAIN_KERNEL:
1710 event->loglevel = LTTNG_LOGLEVEL_DEBUG;
1711 break;
1712 default:
1713 abort();
1714 }
1715
1716 for (node = xmlFirstElementChild(event_node); node;
1717 node = xmlNextElementSibling(node)) {
1718 if (!strcmp((const char *) node->name, config_element_name)) {
1719 xmlChar *content;
1720
1721 /* name */
1722 content = xmlNodeGetContent(node);
1723 if (!content) {
1724 ret = -LTTNG_ERR_NOMEM;
1725 goto end;
1726 }
1727
1728 ret = lttng_strncpy(event->name,
1729 (const char *) content,
1730 LTTNG_SYMBOL_NAME_LEN);
1731 if (ret == -1) {
1732 WARN("Event \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration",
1733 (const char *) content,
1734 strlen((const char *) content),
1735 LTTNG_SYMBOL_NAME_LEN);
1736 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1737 free(content);
1738 goto end;
1739 }
1740 free(content);
1741 } else if (!strcmp((const char *) node->name,
1742 config_element_enabled)) {
1743 xmlChar *content = xmlNodeGetContent(node);
1744
1745 /* enabled */
1746 if (!content) {
1747 ret = -LTTNG_ERR_NOMEM;
1748 goto end;
1749 }
1750
1751 ret = parse_bool(content, &event->enabled);
1752 free(content);
1753 if (ret) {
1754 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1755 goto end;
1756 }
1757 } else if (!strcmp((const char *) node->name,
1758 config_element_type)) {
1759 xmlChar *content = xmlNodeGetContent(node);
1760
1761 /* type */
1762 if (!content) {
1763 ret = -LTTNG_ERR_NOMEM;
1764 goto end;
1765 }
1766
1767 ret = get_event_type(content);
1768 free(content);
1769 if (ret < 0) {
1770 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1771 goto end;
1772 }
1773
1774 event->type = (lttng_event_type) ret;
1775 } else if (!strcmp((const char *) node->name,
1776 config_element_loglevel_type)) {
1777 xmlChar *content = xmlNodeGetContent(node);
1778
1779 /* loglevel_type */
1780 if (!content) {
1781 ret = -LTTNG_ERR_NOMEM;
1782 goto end;
1783 }
1784
1785 ret = get_loglevel_type(content);
1786 free(content);
1787 if (ret < 0) {
1788 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1789 goto end;
1790 }
1791
1792 event->loglevel_type = (lttng_loglevel_type) ret;
1793 } else if (!strcmp((const char *) node->name,
1794 config_element_loglevel)) {
1795 xmlChar *content;
1796 int64_t loglevel = 0;
1797
1798 /* loglevel */
1799 content = xmlNodeGetContent(node);
1800 if (!content) {
1801 ret = -LTTNG_ERR_NOMEM;
1802 goto end;
1803 }
1804
1805 ret = parse_int(content, &loglevel);
1806 free(content);
1807 if (ret) {
1808 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1809 goto end;
1810 }
1811
1812 if (loglevel > INT_MAX || loglevel < INT_MIN) {
1813 WARN("loglevel out of range.");
1814 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1815 goto end;
1816 }
1817
1818 event->loglevel = loglevel;
1819 } else if (!strcmp((const char *) node->name,
1820 config_element_filter)) {
1821 xmlChar *content =
1822 xmlNodeGetContent(node);
1823
1824 /* filter */
1825 if (!content) {
1826 ret = -LTTNG_ERR_NOMEM;
1827 goto end;
1828 }
1829
1830 free(filter_expression);
1831 filter_expression = strdup((char *) content);
1832 free(content);
1833 if (!filter_expression) {
1834 ret = -LTTNG_ERR_NOMEM;
1835 goto end;
1836 }
1837 } else if (!strcmp((const char *) node->name,
1838 config_element_exclusions)) {
1839 xmlNodePtr exclusion_node;
1840 int exclusion_index = 0;
1841
1842 /* exclusions */
1843 if (exclusions) {
1844 /*
1845 * Exclusions has already been initialized,
1846 * invalid file.
1847 */
1848 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1849 goto end;
1850 }
1851
1852 exclusion_count = xmlChildElementCount(node);
1853 if (!exclusion_count) {
1854 continue;
1855 }
1856
1857 exclusions = calloc<char *>(exclusion_count);
1858 if (!exclusions) {
1859 exclusion_count = 0;
1860 ret = -LTTNG_ERR_NOMEM;
1861 goto end;
1862 }
1863
1864 for (exclusion_node = xmlFirstElementChild(node); exclusion_node;
1865 exclusion_node = xmlNextElementSibling(exclusion_node)) {
1866 xmlChar *content =
1867 xmlNodeGetContent(exclusion_node);
1868
1869 if (!content) {
1870 ret = -LTTNG_ERR_NOMEM;
1871 goto end;
1872 }
1873
1874 exclusions[exclusion_index] = strdup((const char *) content);
1875 free(content);
1876 if (!exclusions[exclusion_index]) {
1877 ret = -LTTNG_ERR_NOMEM;
1878 goto end;
1879 }
1880 exclusion_index++;
1881 }
1882
1883 event->exclusion = 1;
1884 } else if (!strcmp((const char *) node->name,
1885 config_element_attributes)) {
1886 xmlNodePtr attribute_node = xmlFirstElementChild(node);
1887
1888 /* attributes */
1889 if (!attribute_node) {
1890 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1891 goto end;
1892 }
1893
1894 if (!strcmp((const char *) attribute_node->name,
1895 config_element_probe_attributes)) {
1896 xmlNodePtr probe_attribute_node;
1897
1898 /* probe_attributes */
1899 for (probe_attribute_node =
1900 xmlFirstElementChild(attribute_node); probe_attribute_node;
1901 probe_attribute_node = xmlNextElementSibling(
1902 probe_attribute_node)) {
1903
1904 ret = process_probe_attribute_node(probe_attribute_node,
1905 &event->attr.probe);
1906 if (ret) {
1907 goto end;
1908 }
1909 }
1910 } else if (!strcmp((const char *) attribute_node->name,
1911 config_element_function_attributes)) {
1912 size_t sym_len;
1913 xmlChar *content;
1914 xmlNodePtr symbol_node = xmlFirstElementChild(attribute_node);
1915
1916 /* function_attributes */
1917 content = xmlNodeGetContent(symbol_node);
1918 if (!content) {
1919 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1920 goto end;
1921 }
1922
1923 sym_len = strlen((char *) content);
1924 if (sym_len >= LTTNG_SYMBOL_NAME_LEN) {
1925 WARN("Function name too long.");
1926 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1927 free(content);
1928 goto end;
1929 }
1930
1931 ret = lttng_strncpy(
1932 event->attr.ftrace.symbol_name,
1933 (char *) content, sym_len);
1934 if (ret == -1) {
1935 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1936 free(content);
1937 goto end;
1938 }
1939 free(content);
1940 } else if (!strcmp((const char *) attribute_node->name,
1941 config_element_userspace_probe_tracepoint_attributes)) {
1942 struct lttng_userspace_probe_location *location;
1943
1944 location = process_userspace_probe_tracepoint_attribute_node(attribute_node);
1945 if (!location) {
1946 WARN("Error processing userspace probe tracepoint attribute");
1947 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1948 goto end;
1949 }
1950 ret = lttng_event_set_userspace_probe_location(
1951 event, location);
1952 if (ret) {
1953 WARN("Error setting userspace probe location field");
1954 lttng_userspace_probe_location_destroy(
1955 location);
1956 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1957 goto end;
1958 }
1959 } else if (!strcmp((const char *) attribute_node->name,
1960 config_element_userspace_probe_function_attributes)) {
1961 struct lttng_userspace_probe_location *location;
1962
1963 location =
1964 process_userspace_probe_function_attribute_node(
1965 attribute_node);
1966 if (!location) {
1967 WARN("Error processing userspace probe function attribute");
1968 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1969 goto end;
1970 }
1971
1972 ret = lttng_event_set_userspace_probe_location(
1973 event, location);
1974 if (ret) {
1975 WARN("Error setting userspace probe location field");
1976 lttng_userspace_probe_location_destroy(
1977 location);
1978 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1979 goto end;
1980 }
1981 } else {
1982 /* Unknown event attribute. */
1983 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1984 goto end;
1985 }
1986 }
1987 }
1988
1989 if ((event->enabled && phase == ENABLE) || phase == CREATION) {
1990 ret = lttng_enable_event_with_exclusions(handle, event, channel_name,
1991 filter_expression, exclusion_count, exclusions);
1992 if (ret < 0) {
1993 WARN("Enabling event (name:%s) on load failed.", event->name);
1994 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1995 goto end;
1996 }
1997 }
1998 ret = 0;
1999 end:
2000 for (i = 0; i < exclusion_count; i++) {
2001 free(exclusions[i]);
2002 }
2003
2004 lttng_event_destroy(event);
2005 free(exclusions);
2006 free(filter_expression);
2007 return ret;
2008 }
2009
2010 static
2011 int process_events_node(xmlNodePtr events_node, struct lttng_handle *handle,
2012 const char *channel_name)
2013 {
2014 int ret = 0;
2015 struct lttng_event event;
2016 xmlNodePtr node;
2017
2018 LTTNG_ASSERT(events_node);
2019 LTTNG_ASSERT(handle);
2020 LTTNG_ASSERT(channel_name);
2021
2022 for (node = xmlFirstElementChild(events_node); node;
2023 node = xmlNextElementSibling(node)) {
2024 ret = process_event_node(node, handle, channel_name, CREATION);
2025 if (ret) {
2026 goto end;
2027 }
2028 }
2029
2030 /*
2031 * Disable all events to enable only the necessary events.
2032 * Limitations regarding lttng_disable_events and tuple descriptor
2033 * force this approach.
2034 */
2035 memset(&event, 0, sizeof(event));
2036 event.loglevel = -1;
2037 event.type = LTTNG_EVENT_ALL;
2038 ret = lttng_disable_event_ext(handle, &event, channel_name, NULL);
2039 if (ret) {
2040 goto end;
2041 }
2042
2043 for (node = xmlFirstElementChild(events_node); node;
2044 node = xmlNextElementSibling(node)) {
2045 ret = process_event_node(node, handle, channel_name, ENABLE);
2046 if (ret) {
2047 goto end;
2048 }
2049 }
2050
2051 end:
2052 return ret;
2053 }
2054
2055 static
2056 int process_channel_attr_node(xmlNodePtr attr_node,
2057 struct lttng_channel *channel, xmlNodePtr *contexts_node,
2058 xmlNodePtr *events_node)
2059 {
2060 int ret;
2061
2062 LTTNG_ASSERT(attr_node);
2063 LTTNG_ASSERT(channel);
2064 LTTNG_ASSERT(contexts_node);
2065 LTTNG_ASSERT(events_node);
2066
2067 if (!strcmp((const char *) attr_node->name, config_element_name)) {
2068 xmlChar *content;
2069
2070 /* name */
2071 content = xmlNodeGetContent(attr_node);
2072 if (!content) {
2073 ret = -LTTNG_ERR_NOMEM;
2074 goto end;
2075 }
2076
2077 ret = lttng_strncpy(channel->name,
2078 (const char *) content,
2079 LTTNG_SYMBOL_NAME_LEN);
2080 if (ret == -1) {
2081 WARN("Channel \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration",
2082 (const char *) content,
2083 strlen((const char *) content),
2084 LTTNG_SYMBOL_NAME_LEN);
2085 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2086 free(content);
2087 goto end;
2088 }
2089 free(content);
2090 } else if (!strcmp((const char *) attr_node->name,
2091 config_element_enabled)) {
2092 xmlChar *content;
2093 int enabled;
2094
2095 /* enabled */
2096 content = xmlNodeGetContent(attr_node);
2097 if (!content) {
2098 ret = -LTTNG_ERR_NOMEM;
2099 goto end;
2100 }
2101
2102 ret = parse_bool(content, &enabled);
2103 free(content);
2104 if (ret) {
2105 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2106 goto end;
2107 }
2108
2109 channel->enabled = enabled;
2110 } else if (!strcmp((const char *) attr_node->name,
2111 config_element_overwrite_mode)) {
2112 xmlChar *content;
2113
2114 /* overwrite_mode */
2115 content = xmlNodeGetContent(attr_node);
2116 if (!content) {
2117 ret = -LTTNG_ERR_NOMEM;
2118 goto end;
2119 }
2120
2121 ret = get_overwrite_mode(content);
2122 free(content);
2123 if (ret < 0) {
2124 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2125 goto end;
2126 }
2127
2128 channel->attr.overwrite = ret;
2129 } else if (!strcmp((const char *) attr_node->name,
2130 config_element_subbuf_size)) {
2131 xmlChar *content;
2132
2133 /* subbuffer_size */
2134 content = xmlNodeGetContent(attr_node);
2135 if (!content) {
2136 ret = -LTTNG_ERR_NOMEM;
2137 goto end;
2138 }
2139
2140 ret = parse_uint(content, &channel->attr.subbuf_size);
2141 free(content);
2142 if (ret) {
2143 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2144 goto end;
2145 }
2146 } else if (!strcmp((const char *) attr_node->name,
2147 config_element_num_subbuf)) {
2148 xmlChar *content;
2149
2150 /* subbuffer_count */
2151 content = xmlNodeGetContent(attr_node);
2152 if (!content) {
2153 ret = -LTTNG_ERR_NOMEM;
2154 goto end;
2155 }
2156
2157 ret = parse_uint(content, &channel->attr.num_subbuf);
2158 free(content);
2159 if (ret) {
2160 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2161 goto end;
2162 }
2163 } else if (!strcmp((const char *) attr_node->name,
2164 config_element_switch_timer_interval)) {
2165 xmlChar *content;
2166 uint64_t switch_timer_interval = 0;
2167
2168 /* switch_timer_interval */
2169 content = xmlNodeGetContent(attr_node);
2170 if (!content) {
2171 ret = -LTTNG_ERR_NOMEM;
2172 goto end;
2173 }
2174
2175 ret = parse_uint(content, &switch_timer_interval);
2176 free(content);
2177 if (ret) {
2178 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2179 goto end;
2180 }
2181
2182 if (switch_timer_interval > UINT_MAX) {
2183 WARN("switch_timer_interval out of range.");
2184 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2185 goto end;
2186 }
2187
2188 channel->attr.switch_timer_interval =
2189 switch_timer_interval;
2190 } else if (!strcmp((const char *) attr_node->name,
2191 config_element_read_timer_interval)) {
2192 xmlChar *content;
2193 uint64_t read_timer_interval = 0;
2194
2195 /* read_timer_interval */
2196 content = xmlNodeGetContent(attr_node);
2197 if (!content) {
2198 ret = -LTTNG_ERR_NOMEM;
2199 goto end;
2200 }
2201
2202 ret = parse_uint(content, &read_timer_interval);
2203 free(content);
2204 if (ret) {
2205 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2206 goto end;
2207 }
2208
2209 if (read_timer_interval > UINT_MAX) {
2210 WARN("read_timer_interval out of range.");
2211 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2212 goto end;
2213 }
2214
2215 channel->attr.read_timer_interval =
2216 read_timer_interval;
2217 } else if (!strcmp((const char *) attr_node->name,
2218 config_element_output_type)) {
2219 xmlChar *content;
2220
2221 /* output_type */
2222 content = xmlNodeGetContent(attr_node);
2223 if (!content) {
2224 ret = -LTTNG_ERR_NOMEM;
2225 goto end;
2226 }
2227
2228 ret = get_output_type(content);
2229 free(content);
2230 if (ret < 0) {
2231 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2232 goto end;
2233 }
2234
2235 channel->attr.output = (lttng_event_output) ret;
2236 } else if (!strcmp((const char *) attr_node->name,
2237 config_element_tracefile_size)) {
2238 xmlChar *content;
2239
2240 /* tracefile_size */
2241 content = xmlNodeGetContent(attr_node);
2242 if (!content) {
2243 ret = -LTTNG_ERR_NOMEM;
2244 goto end;
2245 }
2246
2247 ret = parse_uint(content, &channel->attr.tracefile_size);
2248 free(content);
2249 if (ret) {
2250 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2251 goto end;
2252 }
2253 } else if (!strcmp((const char *) attr_node->name,
2254 config_element_tracefile_count)) {
2255 xmlChar *content;
2256
2257 /* tracefile_count */
2258 content = xmlNodeGetContent(attr_node);
2259 if (!content) {
2260 ret = -LTTNG_ERR_NOMEM;
2261 goto end;
2262 }
2263
2264 ret = parse_uint(content, &channel->attr.tracefile_count);
2265 free(content);
2266 if (ret) {
2267 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2268 goto end;
2269 }
2270 } else if (!strcmp((const char *) attr_node->name,
2271 config_element_live_timer_interval)) {
2272 xmlChar *content;
2273 uint64_t live_timer_interval = 0;
2274
2275 /* live_timer_interval */
2276 content = xmlNodeGetContent(attr_node);
2277 if (!content) {
2278 ret = -LTTNG_ERR_NOMEM;
2279 goto end;
2280 }
2281
2282 ret = parse_uint(content, &live_timer_interval);
2283 free(content);
2284 if (ret) {
2285 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2286 goto end;
2287 }
2288
2289 if (live_timer_interval > UINT_MAX) {
2290 WARN("live_timer_interval out of range.");
2291 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2292 goto end;
2293 }
2294
2295 channel->attr.live_timer_interval =
2296 live_timer_interval;
2297 } else if (!strcmp((const char *) attr_node->name,
2298 config_element_monitor_timer_interval)) {
2299 xmlChar *content;
2300 uint64_t monitor_timer_interval = 0;
2301
2302 /* monitor_timer_interval */
2303 content = xmlNodeGetContent(attr_node);
2304 if (!content) {
2305 ret = -LTTNG_ERR_NOMEM;
2306 goto end;
2307 }
2308
2309 ret = parse_uint(content, &monitor_timer_interval);
2310 free(content);
2311 if (ret) {
2312 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2313 goto end;
2314 }
2315
2316 ret = lttng_channel_set_monitor_timer_interval(channel,
2317 monitor_timer_interval);
2318 if (ret) {
2319 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2320 goto end;
2321 }
2322 } else if (!strcmp((const char *) attr_node->name,
2323 config_element_blocking_timeout)) {
2324 xmlChar *content;
2325 int64_t blocking_timeout = 0;
2326
2327 /* blocking_timeout */
2328 content = xmlNodeGetContent(attr_node);
2329 if (!content) {
2330 ret = -LTTNG_ERR_NOMEM;
2331 goto end;
2332 }
2333
2334 ret = parse_int(content, &blocking_timeout);
2335 free(content);
2336 if (ret) {
2337 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2338 goto end;
2339 }
2340
2341 ret = lttng_channel_set_blocking_timeout(channel,
2342 blocking_timeout);
2343 if (ret) {
2344 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2345 goto end;
2346 }
2347 } else if (!strcmp((const char *) attr_node->name,
2348 config_element_events)) {
2349 /* events */
2350 *events_node = attr_node;
2351 } else {
2352 /* contexts */
2353 *contexts_node = attr_node;
2354 }
2355 ret = 0;
2356 end:
2357 return ret;
2358 }
2359
2360 static
2361 int process_context_node(xmlNodePtr context_node,
2362 struct lttng_handle *handle, const char *channel_name)
2363 {
2364 int ret;
2365 struct lttng_event_context context;
2366 xmlNodePtr context_child_node = xmlFirstElementChild(context_node);
2367
2368 LTTNG_ASSERT(handle);
2369 LTTNG_ASSERT(channel_name);
2370
2371 if (!context_child_node) {
2372 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2373 goto end;
2374 }
2375
2376 memset(&context, 0, sizeof(context));
2377
2378 if (!strcmp((const char *) context_child_node->name,
2379 config_element_type)) {
2380 /* type */
2381 xmlChar *content = xmlNodeGetContent(context_child_node);
2382
2383 if (!content) {
2384 ret = -LTTNG_ERR_NOMEM;
2385 goto end;
2386 }
2387
2388 ret = get_context_type(content);
2389 free(content);
2390 if (ret < 0) {
2391 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2392 goto end;
2393 }
2394
2395 context.ctx = (lttng_event_context_type) ret;
2396 } else if (!strcmp((const char *) context_child_node->name,
2397 config_element_context_perf)) {
2398 /* perf */
2399 xmlNodePtr perf_attr_node;
2400
2401 context.ctx = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
2402 LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER :
2403 LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER;
2404 for (perf_attr_node = xmlFirstElementChild(context_child_node);
2405 perf_attr_node; perf_attr_node =
2406 xmlNextElementSibling(perf_attr_node)) {
2407 if (!strcmp((const char *) perf_attr_node->name,
2408 config_element_type)) {
2409 xmlChar *content;
2410 uint64_t type = 0;
2411
2412 /* type */
2413 content = xmlNodeGetContent(perf_attr_node);
2414 if (!content) {
2415 ret = -LTTNG_ERR_NOMEM;
2416 goto end;
2417 }
2418
2419 ret = parse_uint(content, &type);
2420 free(content);
2421 if (ret) {
2422 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2423 goto end;
2424 }
2425
2426 if (type > UINT32_MAX) {
2427 WARN("perf context type out of range.");
2428 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2429 goto end;
2430 }
2431
2432 context.u.perf_counter.type = type;
2433 } else if (!strcmp((const char *) perf_attr_node->name,
2434 config_element_config)) {
2435 xmlChar *content;
2436 uint64_t config = 0;
2437
2438 /* config */
2439 content = xmlNodeGetContent(perf_attr_node);
2440 if (!content) {
2441 ret = -LTTNG_ERR_NOMEM;
2442 goto end;
2443 }
2444
2445 ret = parse_uint(content, &config);
2446 free(content);
2447 if (ret) {
2448 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2449 goto end;
2450 }
2451
2452 context.u.perf_counter.config = config;
2453 } else if (!strcmp((const char *) perf_attr_node->name,
2454 config_element_name)) {
2455 xmlChar *content;
2456
2457 /* name */
2458 content = xmlNodeGetContent(perf_attr_node);
2459 if (!content) {
2460 ret = -LTTNG_ERR_NOMEM;
2461 goto end;
2462 }
2463
2464 ret = lttng_strncpy(context.u.perf_counter.name,
2465 (const char *) content,
2466 LTTNG_SYMBOL_NAME_LEN);
2467 if (ret == -1) {
2468 WARN("Perf counter \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration",
2469 (const char *) content,
2470 strlen((const char *) content),
2471 LTTNG_SYMBOL_NAME_LEN);
2472 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2473 free(content);
2474 goto end;
2475 }
2476 free(content);
2477 }
2478 }
2479 } else if (!strcmp((const char *) context_child_node->name,
2480 config_element_context_app)) {
2481 /* application context */
2482 xmlNodePtr app_ctx_node;
2483
2484 context.ctx = LTTNG_EVENT_CONTEXT_APP_CONTEXT;
2485 for (app_ctx_node = xmlFirstElementChild(context_child_node);
2486 app_ctx_node; app_ctx_node =
2487 xmlNextElementSibling(app_ctx_node)) {
2488 xmlChar *content;
2489 char **target = strcmp(
2490 (const char *) app_ctx_node->name,
2491 config_element_context_app_provider_name) == 0 ?
2492 &context.u.app_ctx.provider_name :
2493 &context.u.app_ctx.ctx_name;
2494
2495 content = xmlNodeGetContent(app_ctx_node);
2496 if (!content) {
2497 ret = -LTTNG_ERR_NOMEM;
2498 goto end;
2499 }
2500
2501 *target = (char *) content;
2502 }
2503 } else {
2504 /* Unrecognized context type */
2505 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2506 goto end;
2507 }
2508
2509 ret = lttng_add_context(handle, &context, NULL, channel_name);
2510 if (context.ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
2511 free(context.u.app_ctx.provider_name);
2512 free(context.u.app_ctx.ctx_name);
2513 }
2514 end:
2515 return ret;
2516 }
2517
2518 static
2519 int process_contexts_node(xmlNodePtr contexts_node,
2520 struct lttng_handle *handle, const char *channel_name)
2521 {
2522 int ret = 0;
2523 xmlNodePtr context_node;
2524
2525 for (context_node = xmlFirstElementChild(contexts_node); context_node;
2526 context_node = xmlNextElementSibling(context_node)) {
2527 ret = process_context_node(context_node, handle, channel_name);
2528 if (ret) {
2529 goto end;
2530 }
2531 }
2532 end:
2533 return ret;
2534 }
2535
2536 static int get_tracker_elements(enum lttng_process_attr process_attr,
2537 const char **element_id_tracker,
2538 const char **element_value_type,
2539 const char **element_value,
2540 const char **element_value_alias,
2541 const char **element_name)
2542 {
2543 int ret = 0;
2544
2545 switch (process_attr) {
2546 case LTTNG_PROCESS_ATTR_PROCESS_ID:
2547 *element_id_tracker = config_element_process_attr_tracker_pid;
2548 *element_value_type = config_element_process_attr_pid_value;
2549 *element_value = config_element_process_attr_id;
2550 *element_value_alias = config_element_process_attr_id;
2551 *element_name = NULL;
2552 break;
2553 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
2554 *element_id_tracker = config_element_process_attr_tracker_vpid;
2555 *element_value_type = config_element_process_attr_vpid_value;
2556 *element_value = config_element_process_attr_id;
2557 *element_value_alias = NULL;
2558 *element_name = NULL;
2559 break;
2560 case LTTNG_PROCESS_ATTR_USER_ID:
2561 *element_id_tracker = config_element_process_attr_tracker_uid;
2562 *element_value_type = config_element_process_attr_uid_value;
2563 *element_value = config_element_process_attr_id;
2564 *element_value_alias = NULL;
2565 *element_name = config_element_name;
2566 break;
2567 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
2568 *element_id_tracker = config_element_process_attr_tracker_vuid;
2569 *element_value_type = config_element_process_attr_vuid_value;
2570 *element_value = config_element_process_attr_id;
2571 *element_value_alias = NULL;
2572 *element_name = config_element_name;
2573 break;
2574 case LTTNG_PROCESS_ATTR_GROUP_ID:
2575 *element_id_tracker = config_element_process_attr_tracker_gid;
2576 *element_value_type = config_element_process_attr_gid_value;
2577 *element_value = config_element_process_attr_id;
2578 *element_value_alias = NULL;
2579 *element_name = config_element_name;
2580 break;
2581 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
2582 *element_id_tracker = config_element_process_attr_tracker_vgid;
2583 *element_value_type = config_element_process_attr_vgid_value;
2584 *element_value = config_element_process_attr_id;
2585 *element_value_alias = NULL;
2586 *element_name = config_element_name;
2587 break;
2588 default:
2589 ret = LTTNG_ERR_INVALID;
2590 }
2591 return ret;
2592 }
2593
2594 static int process_legacy_pid_tracker_node(
2595 xmlNodePtr trackers_node, struct lttng_handle *handle)
2596 {
2597 int ret = 0, child_count;
2598 xmlNodePtr targets_node = NULL;
2599 xmlNodePtr node;
2600 const char *element_id_tracker;
2601 const char *element_target_id;
2602 const char *element_id;
2603 const char *element_id_alias;
2604 const char *element_name;
2605 enum lttng_error_code tracker_handle_ret_code;
2606 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
2607 enum lttng_process_attr_tracker_handle_status status;
2608 const enum lttng_process_attr process_attr =
2609 handle->domain.type == LTTNG_DOMAIN_UST ?
2610 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID :
2611 LTTNG_PROCESS_ATTR_PROCESS_ID;
2612
2613 LTTNG_ASSERT(handle);
2614
2615 tracker_handle_ret_code = lttng_session_get_tracker_handle(
2616 handle->session_name, handle->domain.type,
2617 process_attr,
2618 &tracker_handle);
2619 if (tracker_handle_ret_code != LTTNG_OK) {
2620 ret = LTTNG_ERR_INVALID;
2621 goto end;
2622 }
2623
2624 ret = get_tracker_elements(process_attr, &element_id_tracker,
2625 &element_target_id, &element_id, &element_id_alias,
2626 &element_name);
2627 if (ret) {
2628 goto end;
2629 }
2630
2631 /* Get the targets node */
2632 for (node = xmlFirstElementChild(trackers_node); node;
2633 node = xmlNextElementSibling(node)) {
2634 if (!strcmp((const char *) node->name,
2635 config_element_tracker_targets_legacy)) {
2636 targets_node = node;
2637 break;
2638 }
2639 }
2640
2641 if (!targets_node) {
2642 ret = LTTNG_ERR_INVALID;
2643 goto end;
2644 }
2645
2646 /* Go through all id target node */
2647 child_count = xmlChildElementCount(targets_node);
2648 status = lttng_process_attr_tracker_handle_set_tracking_policy(
2649 tracker_handle,
2650 child_count == 0 ? LTTNG_TRACKING_POLICY_EXCLUDE_ALL :
2651 LTTNG_TRACKING_POLICY_INCLUDE_SET);
2652 if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
2653 ret = LTTNG_ERR_UNK;
2654 goto end;
2655 }
2656
2657 /* Add all tracked values. */
2658 for (node = xmlFirstElementChild(targets_node); node;
2659 node = xmlNextElementSibling(node)) {
2660 xmlNodePtr pid_target_node = node;
2661
2662 /* get pid_target node and track it */
2663 for (node = xmlFirstElementChild(pid_target_node); node;
2664 node = xmlNextElementSibling(node)) {
2665 if (!strcmp((const char *) node->name,
2666 config_element_tracker_pid_legacy)) {
2667 int64_t id;
2668 xmlChar *content = xmlNodeGetContent(node);
2669
2670 if (!content) {
2671 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2672 goto end;
2673 }
2674
2675 ret = parse_int(content, &id);
2676 free(content);
2677 if (ret) {
2678 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2679 goto end;
2680 }
2681
2682 switch (process_attr) {
2683 case LTTNG_PROCESS_ATTR_PROCESS_ID:
2684 status = lttng_process_attr_process_id_tracker_handle_add_pid(
2685 tracker_handle,
2686 (pid_t) id);
2687 break;
2688 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
2689 status = lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
2690 tracker_handle,
2691 (pid_t) id);
2692 break;
2693 default:
2694 ret = LTTNG_ERR_INVALID;
2695 goto end;
2696 }
2697 }
2698 switch (status) {
2699 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
2700 continue;
2701 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID:
2702 ret = LTTNG_ERR_INVALID;
2703 break;
2704 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS:
2705 ret = LTTNG_ERR_PROCESS_ATTR_EXISTS;
2706 break;
2707 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING:
2708 ret = LTTNG_ERR_PROCESS_ATTR_MISSING;
2709 break;
2710 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR:
2711 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
2712 default:
2713 ret = LTTNG_ERR_UNK;
2714 goto end;
2715 }
2716 }
2717 node = pid_target_node;
2718 }
2719
2720 end:
2721 lttng_process_attr_tracker_handle_destroy(tracker_handle);
2722 return ret;
2723 }
2724
2725 static int process_id_tracker_node(xmlNodePtr id_tracker_node,
2726 struct lttng_handle *handle,
2727 enum lttng_process_attr process_attr)
2728 {
2729 int ret = 0, child_count;
2730 xmlNodePtr values_node = NULL;
2731 xmlNodePtr node;
2732 const char *element_id_tracker;
2733 const char *element_target_id;
2734 const char *element_id;
2735 const char *element_id_alias;
2736 const char *element_name;
2737 enum lttng_error_code tracker_handle_ret_code;
2738 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
2739 enum lttng_process_attr_tracker_handle_status status;
2740
2741 LTTNG_ASSERT(handle);
2742 LTTNG_ASSERT(id_tracker_node);
2743
2744 tracker_handle_ret_code = lttng_session_get_tracker_handle(
2745 handle->session_name, handle->domain.type, process_attr,
2746 &tracker_handle);
2747 if (tracker_handle_ret_code != LTTNG_OK) {
2748 ret = LTTNG_ERR_INVALID;
2749 goto end;
2750 }
2751
2752 ret = get_tracker_elements(process_attr, &element_id_tracker,
2753 &element_target_id, &element_id, &element_id_alias,
2754 &element_name);
2755 if (ret) {
2756 goto end;
2757 }
2758
2759 /* get the values node */
2760 for (node = xmlFirstElementChild(id_tracker_node); node;
2761 node = xmlNextElementSibling(node)) {
2762 if (!strcmp((const char *) node->name,
2763 config_element_process_attr_values)) {
2764 values_node = node;
2765 break;
2766 }
2767 }
2768
2769 if (!values_node) {
2770 ret = LTTNG_ERR_INVALID;
2771 goto end;
2772 }
2773
2774 /* Go through all id target node */
2775 child_count = xmlChildElementCount(values_node);
2776 status = lttng_process_attr_tracker_handle_set_tracking_policy(
2777 tracker_handle,
2778 child_count == 0 ? LTTNG_TRACKING_POLICY_EXCLUDE_ALL :
2779 LTTNG_TRACKING_POLICY_INCLUDE_SET);
2780 if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
2781 ret = LTTNG_ERR_UNK;
2782 goto end;
2783 }
2784
2785 /* Add all tracked values. */
2786 for (node = xmlFirstElementChild(values_node); node;
2787 node = xmlNextElementSibling(node)) {
2788 xmlNodePtr id_target_node = node;
2789
2790 /* get id node and track it */
2791 for (node = xmlFirstElementChild(id_target_node); node;
2792 node = xmlNextElementSibling(node)) {
2793 if (!strcmp((const char *) node->name, element_id) ||
2794 (element_id_alias &&
2795 !strcmp((const char *) node->name,
2796 element_id_alias))) {
2797 int64_t id;
2798 xmlChar *content = xmlNodeGetContent(node);
2799
2800 if (!content) {
2801 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2802 goto end;
2803 }
2804
2805 ret = parse_int(content, &id);
2806 free(content);
2807 if (ret) {
2808 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2809 goto end;
2810 }
2811
2812 switch (process_attr) {
2813 case LTTNG_PROCESS_ATTR_PROCESS_ID:
2814 status = lttng_process_attr_process_id_tracker_handle_add_pid(
2815 tracker_handle,
2816 (pid_t) id);
2817 break;
2818 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
2819 status = lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
2820 tracker_handle,
2821 (pid_t) id);
2822 break;
2823 case LTTNG_PROCESS_ATTR_USER_ID:
2824 status = lttng_process_attr_user_id_tracker_handle_add_uid(
2825 tracker_handle,
2826 (uid_t) id);
2827 break;
2828 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
2829 status = lttng_process_attr_virtual_user_id_tracker_handle_add_uid(
2830 tracker_handle,
2831 (uid_t) id);
2832 break;
2833 case LTTNG_PROCESS_ATTR_GROUP_ID:
2834 status = lttng_process_attr_group_id_tracker_handle_add_gid(
2835 tracker_handle,
2836 (gid_t) id);
2837 break;
2838 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
2839 status = lttng_process_attr_virtual_group_id_tracker_handle_add_gid(
2840 tracker_handle,
2841 (gid_t) id);
2842 break;
2843 default:
2844 ret = LTTNG_ERR_INVALID;
2845 goto end;
2846 }
2847 } else if (element_name &&
2848 !strcmp((const char *) node->name,
2849 element_name)) {
2850 xmlChar *content = xmlNodeGetContent(node);
2851
2852 if (!content) {
2853 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2854 goto end;
2855 }
2856
2857 switch (process_attr) {
2858 case LTTNG_PROCESS_ATTR_USER_ID:
2859 status = lttng_process_attr_user_id_tracker_handle_add_user_name(
2860 tracker_handle,
2861 (const char *) content);
2862 break;
2863 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
2864 status = lttng_process_attr_virtual_user_id_tracker_handle_add_user_name(
2865 tracker_handle,
2866 (const char *) content);
2867 break;
2868 case LTTNG_PROCESS_ATTR_GROUP_ID:
2869 status = lttng_process_attr_group_id_tracker_handle_add_group_name(
2870 tracker_handle,
2871 (const char *) content);
2872 break;
2873 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
2874 status = lttng_process_attr_virtual_group_id_tracker_handle_add_group_name(
2875 tracker_handle,
2876 (const char *) content);
2877 break;
2878 default:
2879 free(content);
2880 ret = LTTNG_ERR_INVALID;
2881 goto end;
2882 }
2883 free(content);
2884 }
2885 switch (status) {
2886 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
2887 continue;
2888 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID:
2889 ret = LTTNG_ERR_INVALID;
2890 break;
2891 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS:
2892 ret = LTTNG_ERR_PROCESS_ATTR_EXISTS;
2893 break;
2894 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING:
2895 ret = LTTNG_ERR_PROCESS_ATTR_MISSING;
2896 break;
2897 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR:
2898 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
2899 default:
2900 ret = LTTNG_ERR_UNK;
2901 goto end;
2902 }
2903 }
2904 node = id_target_node;
2905 }
2906
2907 end:
2908 lttng_process_attr_tracker_handle_destroy(tracker_handle);
2909 return ret;
2910 }
2911
2912 static
2913 int process_domain_node(xmlNodePtr domain_node, const char *session_name)
2914 {
2915 int ret;
2916 struct lttng_domain domain {};
2917 struct lttng_handle *handle = NULL;
2918 struct lttng_channel *channel = NULL;
2919 xmlNodePtr channels_node = NULL;
2920 xmlNodePtr trackers_node = NULL;
2921 xmlNodePtr pid_tracker_node = NULL;
2922 xmlNodePtr vpid_tracker_node = NULL;
2923 xmlNodePtr uid_tracker_node = NULL;
2924 xmlNodePtr vuid_tracker_node = NULL;
2925 xmlNodePtr gid_tracker_node = NULL;
2926 xmlNodePtr vgid_tracker_node = NULL;
2927 xmlNodePtr node;
2928
2929 LTTNG_ASSERT(session_name);
2930
2931 ret = init_domain(domain_node, &domain);
2932 if (ret) {
2933 goto end;
2934 }
2935
2936 handle = lttng_create_handle(session_name, &domain);
2937 if (!handle) {
2938 ret = -LTTNG_ERR_NOMEM;
2939 goto end;
2940 }
2941
2942 /* get the channels node */
2943 for (node = xmlFirstElementChild(domain_node); node;
2944 node = xmlNextElementSibling(node)) {
2945 if (!strcmp((const char *) node->name,
2946 config_element_channels)) {
2947 channels_node = node;
2948 break;
2949 }
2950 }
2951
2952 if (!channels_node) {
2953 goto end;
2954 }
2955
2956 /* create all channels */
2957 for (node = xmlFirstElementChild(channels_node); node;
2958 node = xmlNextElementSibling(node)) {
2959 const enum lttng_domain_type original_domain = domain.type;
2960 xmlNodePtr contexts_node = NULL;
2961 xmlNodePtr events_node = NULL;
2962 xmlNodePtr channel_attr_node;
2963
2964 /*
2965 * Channels of the "agent" types cannot be created directly.
2966 * They are meant to be created implicitly through the
2967 * activation of events in their domain. However, a user
2968 * can override the default channel configuration attributes
2969 * by creating the underlying UST channel _before_ enabling
2970 * an agent domain event.
2971 *
2972 * Hence, the channel's type is substituted before the creation
2973 * and restored by the time the events are created.
2974 */
2975 switch (domain.type) {
2976 case LTTNG_DOMAIN_JUL:
2977 case LTTNG_DOMAIN_LOG4J:
2978 case LTTNG_DOMAIN_PYTHON:
2979 domain.type = LTTNG_DOMAIN_UST;
2980 default:
2981 break;
2982 }
2983
2984 channel = lttng_channel_create(&domain);
2985 if (!channel) {
2986 ret = -1;
2987 goto end;
2988 }
2989
2990 for (channel_attr_node = xmlFirstElementChild(node);
2991 channel_attr_node; channel_attr_node =
2992 xmlNextElementSibling(channel_attr_node)) {
2993 ret = process_channel_attr_node(channel_attr_node,
2994 channel, &contexts_node, &events_node);
2995 if (ret) {
2996 goto end;
2997 }
2998 }
2999
3000 ret = lttng_enable_channel(handle, channel);
3001 if (ret < 0) {
3002 goto end;
3003 }
3004
3005 /* Restore the original channel domain. */
3006 domain.type = original_domain;
3007
3008 ret = process_events_node(events_node, handle, channel->name);
3009 if (ret) {
3010 goto end;
3011 }
3012
3013 ret = process_contexts_node(contexts_node, handle,
3014 channel->name);
3015 if (ret) {
3016 goto end;
3017 }
3018
3019 lttng_channel_destroy(channel);
3020 }
3021 channel = NULL;
3022
3023 /* get the trackers node */
3024 for (node = xmlFirstElementChild(domain_node); node;
3025 node = xmlNextElementSibling(node)) {
3026 if (!strcmp((const char *) node->name,
3027 config_element_process_attr_trackers) ||
3028 !strcmp((const char *) node->name,
3029 config_element_trackers_legacy)) {
3030 if (trackers_node) {
3031 ERR("Only one instance of `%s` or `%s` is allowed in a session configuration",
3032 config_element_process_attr_trackers,
3033 config_element_trackers_legacy);
3034 ret = -1;
3035 goto end;
3036 }
3037 trackers_node = node;
3038 break;
3039 }
3040 }
3041
3042 if (!trackers_node) {
3043 goto end;
3044 }
3045
3046 for (node = xmlFirstElementChild(trackers_node); node;
3047 node = xmlNextElementSibling(node)) {
3048 if (!strcmp((const char *) node->name,
3049 config_element_process_attr_tracker_pid)) {
3050 pid_tracker_node = node;
3051 ret = process_id_tracker_node(pid_tracker_node, handle,
3052 LTTNG_PROCESS_ATTR_PROCESS_ID);
3053 if (ret) {
3054 goto end;
3055 }
3056 }
3057 if (!strcmp((const char *) node->name,
3058 config_element_process_attr_tracker_vpid)) {
3059 vpid_tracker_node = node;
3060 ret = process_id_tracker_node(vpid_tracker_node, handle,
3061 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
3062 if (ret) {
3063 goto end;
3064 }
3065 }
3066 if (!strcmp((const char *) node->name,
3067 config_element_process_attr_tracker_uid)) {
3068 uid_tracker_node = node;
3069 ret = process_id_tracker_node(uid_tracker_node, handle,
3070 LTTNG_PROCESS_ATTR_USER_ID);
3071 if (ret) {
3072 goto end;
3073 }
3074 }
3075 if (!strcmp((const char *) node->name,
3076 config_element_process_attr_tracker_vuid)) {
3077 vuid_tracker_node = node;
3078 ret = process_id_tracker_node(vuid_tracker_node, handle,
3079 LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
3080 if (ret) {
3081 goto end;
3082 }
3083 }
3084 if (!strcmp((const char *) node->name,
3085 config_element_process_attr_tracker_gid)) {
3086 gid_tracker_node = node;
3087 ret = process_id_tracker_node(gid_tracker_node, handle,
3088 LTTNG_PROCESS_ATTR_GROUP_ID);
3089 if (ret) {
3090 goto end;
3091 }
3092 }
3093 if (!strcmp((const char *) node->name,
3094 config_element_process_attr_tracker_vgid)) {
3095 vgid_tracker_node = node;
3096 ret = process_id_tracker_node(vgid_tracker_node, handle,
3097 LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
3098 if (ret) {
3099 goto end;
3100 }
3101 }
3102 if (!strcmp((const char *) node->name,
3103 config_element_pid_tracker_legacy)) {
3104 ret = process_legacy_pid_tracker_node(node, handle);
3105 if (ret) {
3106 goto end;
3107 }
3108 }
3109 }
3110
3111 end:
3112 lttng_channel_destroy(channel);
3113 lttng_destroy_handle(handle);
3114 return ret;
3115 }
3116
3117 static
3118 int add_periodic_rotation(const char *name, uint64_t time_us)
3119 {
3120 int ret;
3121 enum lttng_rotation_status status;
3122 struct lttng_rotation_schedule *periodic =
3123 lttng_rotation_schedule_periodic_create();
3124
3125 if (!periodic) {
3126 ret = -LTTNG_ERR_NOMEM;
3127 goto error;
3128 }
3129
3130 status = lttng_rotation_schedule_periodic_set_period(periodic,
3131 time_us);
3132 if (status != LTTNG_ROTATION_STATUS_OK) {
3133 ret = -LTTNG_ERR_INVALID;
3134 goto error;
3135 }
3136
3137 status = lttng_session_add_rotation_schedule(name, periodic);
3138 switch (status) {
3139 case LTTNG_ROTATION_STATUS_OK:
3140 ret = 0;
3141 break;
3142 case LTTNG_ROTATION_STATUS_SCHEDULE_ALREADY_SET:
3143 case LTTNG_ROTATION_STATUS_INVALID:
3144 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3145 break;
3146 default:
3147 ret = -LTTNG_ERR_UNK;
3148 break;
3149 }
3150 error:
3151 lttng_rotation_schedule_destroy(periodic);
3152 return ret;
3153 }
3154
3155 static
3156 int add_size_rotation(const char *name, uint64_t size_bytes)
3157 {
3158 int ret;
3159 enum lttng_rotation_status status;
3160 struct lttng_rotation_schedule *size =
3161 lttng_rotation_schedule_size_threshold_create();
3162
3163 if (!size) {
3164 ret = -LTTNG_ERR_NOMEM;
3165 goto error;
3166 }
3167
3168 status = lttng_rotation_schedule_size_threshold_set_threshold(size,
3169 size_bytes);
3170 if (status != LTTNG_ROTATION_STATUS_OK) {
3171 ret = -LTTNG_ERR_INVALID;
3172 goto error;
3173 }
3174
3175 status = lttng_session_add_rotation_schedule(name, size);
3176 switch (status) {
3177 case LTTNG_ROTATION_STATUS_OK:
3178 ret = 0;
3179 break;
3180 case LTTNG_ROTATION_STATUS_SCHEDULE_ALREADY_SET:
3181 case LTTNG_ROTATION_STATUS_INVALID:
3182 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3183 break;
3184 default:
3185 ret = -LTTNG_ERR_UNK;
3186 break;
3187 }
3188 error:
3189 lttng_rotation_schedule_destroy(size);
3190 return ret;
3191 }
3192
3193 static
3194 int process_session_rotation_schedules_node(
3195 xmlNodePtr schedules_node,
3196 uint64_t *rotation_timer_interval,
3197 uint64_t *rotation_size)
3198 {
3199 int ret = 0;
3200 xmlNodePtr child;
3201
3202 for (child = xmlFirstElementChild(schedules_node);
3203 child;
3204 child = xmlNextElementSibling(child)) {
3205 if (!strcmp((const char *) child->name,
3206 config_element_rotation_schedule_periodic)) {
3207 xmlChar *content;
3208 xmlNodePtr time_us_node;
3209
3210 /* periodic rotation schedule */
3211 time_us_node = xmlFirstElementChild(child);
3212 if (!time_us_node ||
3213 strcmp((const char *) time_us_node->name,
3214 config_element_rotation_schedule_periodic_time_us)) {
3215 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3216 goto end;
3217 }
3218
3219 /* time_us child */
3220 content = xmlNodeGetContent(time_us_node);
3221 if (!content) {
3222 ret = -LTTNG_ERR_NOMEM;
3223 goto end;
3224 }
3225 ret = parse_uint(content, rotation_timer_interval);
3226 free(content);
3227 if (ret) {
3228 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3229 goto end;
3230 }
3231 } else if (!strcmp((const char *) child->name,
3232 config_element_rotation_schedule_size_threshold)) {
3233 xmlChar *content;
3234 xmlNodePtr bytes_node;
3235
3236 /* size_threshold rotation schedule */
3237 bytes_node = xmlFirstElementChild(child);
3238 if (!bytes_node ||
3239 strcmp((const char *) bytes_node->name,
3240 config_element_rotation_schedule_size_threshold_bytes)) {
3241 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3242 goto end;
3243 }
3244
3245 /* bytes child */
3246 content = xmlNodeGetContent(bytes_node);
3247 if (!content) {
3248 ret = -LTTNG_ERR_NOMEM;
3249 goto end;
3250 }
3251 ret = parse_uint(content, rotation_size);
3252 free(content);
3253 if (ret) {
3254 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3255 goto end;
3256 }
3257 }
3258 }
3259
3260 end:
3261 return ret;
3262 }
3263
3264 static
3265 int process_session_node(xmlNodePtr session_node, const char *session_name,
3266 int overwrite,
3267 const struct config_load_session_override_attr *overrides)
3268 {
3269 int ret, started = -1, snapshot_mode = -1;
3270 uint64_t live_timer_interval = UINT64_MAX,
3271 rotation_timer_interval = 0,
3272 rotation_size = 0;
3273 xmlChar *name = NULL;
3274 xmlChar *shm_path = NULL;
3275 xmlNodePtr domains_node = NULL;
3276 xmlNodePtr output_node = NULL;
3277 xmlNodePtr node;
3278 xmlNodePtr attributes_child;
3279 struct lttng_domain *kernel_domain = NULL;
3280 struct lttng_domain *ust_domain = NULL;
3281 struct lttng_domain *jul_domain = NULL;
3282 struct lttng_domain *log4j_domain = NULL;
3283 struct lttng_domain *python_domain = NULL;
3284
3285 for (node = xmlFirstElementChild(session_node); node;
3286 node = xmlNextElementSibling(node)) {
3287 if (!name && !strcmp((const char *) node->name,
3288 config_element_name)) {
3289 /* name */
3290 xmlChar *node_content = xmlNodeGetContent(node);
3291 if (!node_content) {
3292 ret = -LTTNG_ERR_NOMEM;
3293 goto error;
3294 }
3295
3296 name = node_content;
3297 } else if (!domains_node && !strcmp((const char *) node->name,
3298 config_element_domains)) {
3299 /* domains */
3300 domains_node = node;
3301 } else if (started == -1 && !strcmp((const char *) node->name,
3302 config_element_started)) {
3303 /* started */
3304 xmlChar *node_content = xmlNodeGetContent(node);
3305 if (!node_content) {
3306 ret = -LTTNG_ERR_NOMEM;
3307 goto error;
3308 }
3309
3310 ret = parse_bool(node_content, &started);
3311 free(node_content);
3312 if (ret) {
3313 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3314 goto error;
3315 }
3316 } else if (!output_node && !strcmp((const char *) node->name,
3317 config_element_output)) {
3318 /* output */
3319 output_node = node;
3320 } else if (!shm_path && !strcmp((const char *) node->name,
3321 config_element_shared_memory_path)) {
3322 /* shared memory path */
3323 xmlChar *node_content = xmlNodeGetContent(node);
3324 if (!node_content) {
3325 ret = -LTTNG_ERR_NOMEM;
3326 goto error;
3327 }
3328
3329 shm_path = node_content;
3330 } else {
3331 /*
3332 * attributes, snapshot_mode, live_timer_interval, rotation_size,
3333 * rotation_timer_interval.
3334 */
3335 for (attributes_child = xmlFirstElementChild(node); attributes_child;
3336 attributes_child = xmlNextElementSibling(attributes_child)) {
3337 if (!strcmp((const char *) attributes_child->name,
3338 config_element_snapshot_mode)) {
3339 /* snapshot_mode */
3340 xmlChar *snapshot_mode_content =
3341 xmlNodeGetContent(attributes_child);
3342 if (!snapshot_mode_content) {
3343 ret = -LTTNG_ERR_NOMEM;
3344 goto error;
3345 }
3346
3347 ret = parse_bool(snapshot_mode_content, &snapshot_mode);
3348 free(snapshot_mode_content);
3349 if (ret) {
3350 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3351 goto error;
3352 }
3353 } else if (!strcmp((const char *) attributes_child->name,
3354 config_element_live_timer_interval)) {
3355 /* live_timer_interval */
3356 xmlChar *timer_interval_content =
3357 xmlNodeGetContent(attributes_child);
3358 if (!timer_interval_content) {
3359 ret = -LTTNG_ERR_NOMEM;
3360 goto error;
3361 }
3362
3363 ret = parse_uint(timer_interval_content, &live_timer_interval);
3364 free(timer_interval_content);
3365 if (ret) {
3366 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3367 goto error;
3368 }
3369 } else if (!strcmp((const char *) attributes_child->name,
3370 config_element_rotation_schedules)) {
3371 ret = process_session_rotation_schedules_node(
3372 attributes_child,
3373 &rotation_timer_interval,
3374 &rotation_size);
3375 if (ret) {
3376 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3377 goto error;
3378 }
3379
3380 }
3381 }
3382 }
3383 }
3384
3385 if (!name) {
3386 /* Mandatory attribute, as defined in the session XSD */
3387 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3388 goto error;
3389 }
3390
3391 if (session_name && strcmp((char *) name, session_name)) {
3392 /* This is not the session we are looking for */
3393 ret = -LTTNG_ERR_NO_SESSION;
3394 goto error;
3395 }
3396
3397 /* Init domains to create the session handles */
3398 for (node = xmlFirstElementChild(domains_node); node;
3399 node = xmlNextElementSibling(node)) {
3400 lttng_domain *domain = zmalloc<lttng_domain>();
3401
3402 if (!domain) {
3403 ret = -LTTNG_ERR_NOMEM;
3404 goto error;
3405 }
3406
3407 ret = init_domain(node, domain);
3408 if (ret) {
3409 goto domain_init_error;
3410 }
3411
3412 switch (domain->type) {
3413 case LTTNG_DOMAIN_KERNEL:
3414 if (kernel_domain) {
3415 /* Same domain seen twice, invalid! */
3416 goto domain_init_error;
3417 }
3418 kernel_domain = domain;
3419 break;
3420 case LTTNG_DOMAIN_UST:
3421 if (ust_domain) {
3422 /* Same domain seen twice, invalid! */
3423 goto domain_init_error;
3424 }
3425 ust_domain = domain;
3426 break;
3427 case LTTNG_DOMAIN_JUL:
3428 if (jul_domain) {
3429 /* Same domain seen twice, invalid! */
3430 goto domain_init_error;
3431 }
3432 jul_domain = domain;
3433 break;
3434 case LTTNG_DOMAIN_LOG4J:
3435 if (log4j_domain) {
3436 /* Same domain seen twice, invalid! */
3437 goto domain_init_error;
3438 }
3439 log4j_domain = domain;
3440 break;
3441 case LTTNG_DOMAIN_PYTHON:
3442 if (python_domain) {
3443 /* Same domain seen twice, invalid! */
3444 goto domain_init_error;
3445 }
3446 python_domain = domain;
3447 break;
3448 default:
3449 WARN("Invalid domain type");
3450 goto domain_init_error;
3451 }
3452 continue;
3453 domain_init_error:
3454 free(domain);
3455 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3456 goto error;
3457 }
3458
3459 /* Apply overrides */
3460 if (overrides) {
3461 if (overrides->session_name) {
3462 xmlChar *name_override = xmlStrdup(BAD_CAST(overrides->session_name));
3463 if (!name_override) {
3464 ret = -LTTNG_ERR_NOMEM;
3465 goto error;
3466 }
3467
3468 /* Overrides the session name to the provided name */
3469 xmlFree(name);
3470 name = name_override;
3471 }
3472 }
3473
3474 if (overwrite) {
3475 /* Destroy session if it exists */
3476 ret = lttng_destroy_session((const char *) name);
3477 if (ret && ret != -LTTNG_ERR_SESS_NOT_FOUND) {
3478 ERR("Failed to destroy existing session.");
3479 goto error;
3480 }
3481 }
3482
3483 /* Create session type depending on output type */
3484 if (snapshot_mode && snapshot_mode != -1) {
3485 ret = create_snapshot_session((const char *) name, output_node,
3486 overrides);
3487 } else if (live_timer_interval &&
3488 live_timer_interval != UINT64_MAX) {
3489 ret = create_session((const char *) name,
3490 output_node, live_timer_interval, overrides);
3491 } else {
3492 /* regular session */
3493 ret = create_session((const char *) name,
3494 output_node, UINT64_MAX, overrides);
3495 }
3496 if (ret) {
3497 goto error;
3498 }
3499
3500 if (shm_path) {
3501 ret = lttng_set_session_shm_path((const char *) name,
3502 (const char *) shm_path);
3503 if (ret) {
3504 goto error;
3505 }
3506 }
3507
3508 for (node = xmlFirstElementChild(domains_node); node;
3509 node = xmlNextElementSibling(node)) {
3510 ret = process_domain_node(node, (const char *) name);
3511 if (ret) {
3512 goto end;
3513 }
3514 }
3515
3516 if (rotation_timer_interval) {
3517 ret = add_periodic_rotation((const char *) name,
3518 rotation_timer_interval);
3519 if (ret < 0) {
3520 goto error;
3521 }
3522 }
3523 if (rotation_size) {
3524 ret = add_size_rotation((const char *) name,
3525 rotation_size);
3526 if (ret < 0) {
3527 goto error;
3528 }
3529 }
3530
3531 if (started) {
3532 ret = lttng_start_tracing((const char *) name);
3533 if (ret) {
3534 goto end;
3535 }
3536 }
3537
3538 end:
3539 if (ret < 0) {
3540 ERR("Failed to load session %s: %s", (const char *) name,
3541 lttng_strerror(ret));
3542 lttng_destroy_session((const char *) name);
3543 }
3544
3545 error:
3546 free(kernel_domain);
3547 free(ust_domain);
3548 free(jul_domain);
3549 free(log4j_domain);
3550 free(python_domain);
3551 xmlFree(name);
3552 xmlFree(shm_path);
3553 return ret;
3554 }
3555
3556 /*
3557 * Return 1 if the given path is readable by the current UID or 0 if not.
3558 * Return -1 if the path is EPERM.
3559 */
3560 static int validate_file_read_creds(const char *path)
3561 {
3562 int ret;
3563
3564 LTTNG_ASSERT(path);
3565
3566 /* Can we read the file. */
3567 ret = access(path, R_OK);
3568 if (!ret) {
3569 goto valid;
3570 }
3571 if (errno == EACCES) {
3572 return -1;
3573 } else {
3574 /* Invalid. */
3575 return 0;
3576 }
3577 valid:
3578 return 1;
3579 }
3580
3581 static
3582 int load_session_from_file(const char *path, const char *session_name,
3583 struct session_config_validation_ctx *validation_ctx, int overwrite,
3584 const struct config_load_session_override_attr *overrides)
3585 {
3586 int ret, session_found = !session_name;
3587 xmlDocPtr doc = NULL;
3588 xmlNodePtr sessions_node;
3589 xmlNodePtr session_node;
3590
3591 LTTNG_ASSERT(path);
3592 LTTNG_ASSERT(validation_ctx);
3593
3594 ret = validate_file_read_creds(path);
3595 if (ret != 1) {
3596 if (ret == -1) {
3597 ret = -LTTNG_ERR_EPERM;
3598 } else {
3599 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
3600 }
3601 goto end;
3602 }
3603
3604 doc = xmlParseFile(path);
3605 if (!doc) {
3606 ret = -LTTNG_ERR_LOAD_IO_FAIL;
3607 goto end;
3608 }
3609
3610 ret = xmlSchemaValidateDoc(validation_ctx->schema_validation_ctx, doc);
3611 if (ret) {
3612 ERR("Session configuration file validation failed");
3613 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3614 goto end;
3615 }
3616
3617 sessions_node = xmlDocGetRootElement(doc);
3618 if (!sessions_node) {
3619 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3620 goto end;
3621 }
3622
3623 for (session_node = xmlFirstElementChild(sessions_node);
3624 session_node; session_node =
3625 xmlNextElementSibling(session_node)) {
3626 ret = process_session_node(session_node,
3627 session_name, overwrite, overrides);
3628 if (!session_name && ret) {
3629 /* Loading error occurred. */
3630 goto end;
3631 } else if (session_name) {
3632 if (ret == 0) {
3633 /* Target session found and loaded */
3634 session_found = 1;
3635 break;
3636 } else if (ret == -LTTNG_ERR_NO_SESSION) {
3637 /*
3638 * Ignore this error, we are looking for a
3639 * specific session.
3640 */
3641 ret = 0;
3642 } else {
3643 /* Loading error occurred. */
3644 goto end;
3645 }
3646 }
3647 }
3648 end:
3649 xmlFreeDoc(doc);
3650 if (!ret) {
3651 ret = session_found ? 0 : -LTTNG_ERR_LOAD_SESSION_NOENT;
3652 }
3653 return ret;
3654 }
3655
3656 static
3657 int load_session_from_path(const char *path, const char *session_name,
3658 struct session_config_validation_ctx *validation_ctx, int overwrite,
3659 const struct config_load_session_override_attr *overrides)
3660 {
3661 int ret, session_found = !session_name;
3662 DIR *directory = NULL;
3663 struct lttng_dynamic_buffer file_path;
3664 size_t path_len;
3665
3666 LTTNG_ASSERT(path);
3667 LTTNG_ASSERT(validation_ctx);
3668 path_len = strlen(path);
3669 lttng_dynamic_buffer_init(&file_path);
3670 if (path_len >= LTTNG_PATH_MAX) {
3671 ERR("Session configuration load path \"%s\" length (%zu) exceeds the maximal length allowed (%d)",
3672 path, path_len, LTTNG_PATH_MAX);
3673 ret = -LTTNG_ERR_INVALID;
3674 goto end;
3675 }
3676
3677 directory = opendir(path);
3678 if (!directory) {
3679 switch (errno) {
3680 case ENOTDIR:
3681 /* Try the file loading. */
3682 break;
3683 case ENOENT:
3684 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
3685 goto end;
3686 default:
3687 ret = -LTTNG_ERR_LOAD_IO_FAIL;
3688 goto end;
3689 }
3690 }
3691 if (directory) {
3692 size_t file_path_root_len;
3693
3694 ret = lttng_dynamic_buffer_set_capacity(&file_path,
3695 LTTNG_PATH_MAX);
3696 if (ret) {
3697 ret = -LTTNG_ERR_NOMEM;
3698 goto end;
3699 }
3700
3701 ret = lttng_dynamic_buffer_append(&file_path, path, path_len);
3702 if (ret) {
3703 ret = -LTTNG_ERR_NOMEM;
3704 goto end;
3705 }
3706
3707 if (file_path.data[file_path.size - 1] != '/') {
3708 ret = lttng_dynamic_buffer_append(&file_path, "/", 1);
3709 if (ret) {
3710 ret = -LTTNG_ERR_NOMEM;
3711 goto end;
3712 }
3713 }
3714 file_path_root_len = file_path.size;
3715
3716 /* Search for *.lttng files */
3717 for (;;) {
3718 size_t file_name_len;
3719 struct dirent *result;
3720
3721 /*
3722 * When the end of the directory stream is reached, NULL
3723 * is returned and errno is kept unchanged. When an
3724 * error occurs, NULL is returned and errno is set
3725 * accordingly. To distinguish between the two, set
3726 * errno to zero before calling readdir().
3727 *
3728 * On success, readdir() returns a pointer to a dirent
3729 * structure. This structure may be statically
3730 * allocated, do not attempt to free(3) it.
3731 */
3732 errno = 0;
3733 result = readdir(directory);
3734
3735 /* Reached end of dir stream or error out. */
3736 if (!result) {
3737 if (errno) {
3738 PERROR("Failed to enumerate the contents of path \"%s\" while loading session, readdir returned", path);
3739 ret = -LTTNG_ERR_LOAD_IO_FAIL;
3740 goto end;
3741 }
3742 break;
3743 }
3744
3745 file_name_len = strlen(result->d_name);
3746
3747 if (file_name_len <=
3748 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION)) {
3749 continue;
3750 }
3751
3752 if (file_path.size + file_name_len >= LTTNG_PATH_MAX) {
3753 WARN("Ignoring file \"%s\" since the path's length (%zu) would exceed the maximal permitted size (%d)",
3754 result->d_name,
3755 /* +1 to account for NULL terminator. */
3756 file_path.size + file_name_len + 1,
3757 LTTNG_PATH_MAX);
3758 continue;
3759 }
3760
3761 /* Does the file end with .lttng? */
3762 if (strcmp(DEFAULT_SESSION_CONFIG_FILE_EXTENSION,
3763 result->d_name + file_name_len - sizeof(
3764 DEFAULT_SESSION_CONFIG_FILE_EXTENSION) + 1)) {
3765 continue;
3766 }
3767
3768 ret = lttng_dynamic_buffer_append(&file_path, result->d_name,
3769 file_name_len + 1);
3770 if (ret) {
3771 ret = -LTTNG_ERR_NOMEM;
3772 goto end;
3773 }
3774
3775 ret = load_session_from_file(file_path.data, session_name,
3776 validation_ctx, overwrite, overrides);
3777 if (session_name &&
3778 (!ret || ret != -LTTNG_ERR_LOAD_SESSION_NOENT)) {
3779 session_found = 1;
3780 break;
3781 }
3782 if (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT) {
3783 goto end;
3784 }
3785 /*
3786 * Reset the buffer's size to the location of the
3787 * path's trailing '/'.
3788 */
3789 ret = lttng_dynamic_buffer_set_size(&file_path,
3790 file_path_root_len);
3791 if (ret) {
3792 ret = -LTTNG_ERR_UNK;
3793 goto end;
3794 }
3795 }
3796 } else {
3797 ret = load_session_from_file(path, session_name,
3798 validation_ctx, overwrite, overrides);
3799 if (ret) {
3800 goto end;
3801 }
3802 session_found = 1;
3803 }
3804
3805 ret = 0;
3806 end:
3807 if (directory) {
3808 if (closedir(directory)) {
3809 PERROR("closedir");
3810 }
3811 }
3812 if (!ret && !session_found) {
3813 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
3814 }
3815 lttng_dynamic_buffer_reset(&file_path);
3816 return ret;
3817 }
3818
3819 /*
3820 * Validate that the given path's credentials and the current process have the
3821 * same UID. If so, return 1 else return 0 if it does NOT match.
3822 */
3823 static int validate_path_creds(const char *path)
3824 {
3825 int ret, uid = getuid();
3826 struct stat buf;
3827
3828 LTTNG_ASSERT(path);
3829
3830 if (uid == 0) {
3831 goto valid;
3832 }
3833
3834 ret = stat(path, &buf);
3835 if (ret < 0) {
3836 if (errno != ENOENT) {
3837 PERROR("stat");
3838 }
3839 goto valid;
3840 }
3841
3842 if (buf.st_uid != uid) {
3843 goto invalid;
3844 }
3845
3846 valid:
3847 return 1;
3848 invalid:
3849 return 0;
3850 }
3851
3852 int config_load_session(const char *path, const char *session_name,
3853 int overwrite, unsigned int autoload,
3854 const struct config_load_session_override_attr *overrides)
3855 {
3856 int ret;
3857 bool session_loaded = false;
3858 const char *path_ptr = NULL;
3859 struct session_config_validation_ctx validation_ctx = {};
3860
3861 ret = init_session_config_validation_ctx(&validation_ctx);
3862 if (ret) {
3863 goto end;
3864 }
3865
3866 if (!path) {
3867 const char *home_path;
3868 const char *sys_path;
3869
3870 /* Try home path */
3871 home_path = utils_get_home_dir();
3872 if (home_path) {
3873 char path_buf[PATH_MAX];
3874
3875 /*
3876 * Try user session configuration path. Ignore error here so we can
3877 * continue loading the system wide sessions.
3878 */
3879 if (autoload) {
3880 ret = snprintf(path_buf, sizeof(path_buf),
3881 DEFAULT_SESSION_HOME_CONFIGPATH
3882 "/" DEFAULT_SESSION_CONFIG_AUTOLOAD,
3883 home_path);
3884 if (ret < 0) {
3885 PERROR("snprintf session autoload home config path");
3886 ret = -LTTNG_ERR_INVALID;
3887 goto end;
3888 }
3889
3890 /*
3891 * Credentials are only validated for the autoload in order to
3892 * avoid any user session daemon to try to load kernel sessions
3893 * automatically and failing all the times.
3894 */
3895 ret = validate_path_creds(path_buf);
3896 if (ret) {
3897 path_ptr = path_buf;
3898 }
3899 } else {
3900 ret = snprintf(path_buf, sizeof(path_buf),
3901 DEFAULT_SESSION_HOME_CONFIGPATH,
3902 home_path);
3903 if (ret < 0) {
3904 PERROR("snprintf session home config path");
3905 ret = -LTTNG_ERR_INVALID;
3906 goto end;
3907 }
3908 path_ptr = path_buf;
3909 }
3910 if (path_ptr) {
3911 ret = load_session_from_path(path_ptr, session_name,
3912 &validation_ctx, overwrite, overrides);
3913 if (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT) {
3914 goto end;
3915 }
3916 /*
3917 * Continue even if the session was found since we have to try
3918 * the system wide sessions.
3919 */
3920 session_loaded = true;
3921 }
3922 }
3923
3924 /* Reset path pointer for the system wide dir. */
3925 path_ptr = NULL;
3926
3927 /* Try system wide configuration directory. */
3928 if (autoload) {
3929 sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH "/"
3930 DEFAULT_SESSION_CONFIG_AUTOLOAD;
3931 ret = validate_path_creds(sys_path);
3932 if (ret) {
3933 path_ptr = sys_path;
3934 }
3935 } else {
3936 sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH;
3937 path_ptr = sys_path;
3938 }
3939
3940 if (path_ptr) {
3941 ret = load_session_from_path(path_ptr, session_name,
3942 &validation_ctx, overwrite, overrides);
3943 if (!ret) {
3944 session_loaded = true;
3945 }
3946 } else {
3947 ret = 0;
3948 }
3949 } else {
3950 ret = access(path, F_OK);
3951 if (ret < 0) {
3952 PERROR("access");
3953 switch (errno) {
3954 case ENOENT:
3955 ret = -LTTNG_ERR_INVALID;
3956 WARN("Session configuration path does not exist.");
3957 break;
3958 case EACCES:
3959 ret = -LTTNG_ERR_EPERM;
3960 break;
3961 default:
3962 ret = -LTTNG_ERR_UNK;
3963 break;
3964 }
3965 goto end;
3966 }
3967
3968 ret = load_session_from_path(path, session_name,
3969 &validation_ctx, overwrite, overrides);
3970 }
3971 end:
3972 fini_session_config_validation_ctx(&validation_ctx);
3973 if (ret == -LTTNG_ERR_LOAD_SESSION_NOENT && !session_name && !path) {
3974 /*
3975 * Don't report an error if no sessions are found when called
3976 * without a session_name or a search path.
3977 */
3978 ret = 0;
3979 }
3980
3981 if (session_loaded && ret == -LTTNG_ERR_LOAD_SESSION_NOENT) {
3982 /* A matching session was found in one of the search paths. */
3983 ret = 0;
3984 }
3985 return ret;
3986 }
3987
3988 static
3989 void __attribute__((destructor)) session_config_exit(void)
3990 {
3991 xmlCleanupParser();
3992 }
This page took 0.136731 seconds and 5 git commands to generate.