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