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