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