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