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