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