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