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