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