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