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