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