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