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