Fix: get_cmdline_by_pid path length assumes a max pid of 65535
[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";
fb198a11
JG
120
121const char * const config_domain_type_kernel = "KERNEL";
122const char * const config_domain_type_ust = "UST";
123const char * const config_domain_type_jul = "JUL";
5cdb6027 124const char * const config_domain_type_log4j = "LOG4J";
0e115563 125const char * const config_domain_type_python = "PYTHON";
fb198a11
JG
126
127const char * const config_buffer_type_per_pid = "PER_PID";
128const char * const config_buffer_type_per_uid = "PER_UID";
129const char * const config_buffer_type_global = "GLOBAL";
130
131const char * const config_overwrite_mode_discard = "DISCARD";
132const char * const config_overwrite_mode_overwrite = "OVERWRITE";
133
134const char * const config_output_type_splice = "SPLICE";
135const char * const config_output_type_mmap = "MMAP";
136
137const char * const config_loglevel_type_all = "ALL";
138const char * const config_loglevel_type_range = "RANGE";
139const char * const config_loglevel_type_single = "SINGLE";
140
141const char * const config_event_type_all = "ALL";
142const char * const config_event_type_tracepoint = "TRACEPOINT";
143const char * const config_event_type_probe = "PROBE";
144const char * const config_event_type_function = "FUNCTION";
145const char * const config_event_type_function_entry = "FUNCTION_ENTRY";
146const char * const config_event_type_noop = "NOOP";
147const char * const config_event_type_syscall = "SYSCALL";
148const char * const config_event_type_kprobe = "KPROBE";
149const char * const config_event_type_kretprobe = "KRETPROBE";
150
151const char * const config_event_context_pid = "PID";
152const char * const config_event_context_procname = "PROCNAME";
153const char * const config_event_context_prio = "PRIO";
154const char * const config_event_context_nice = "NICE";
155const char * const config_event_context_vpid = "VPID";
156const char * const config_event_context_tid = "TID";
157const char * const config_event_context_vtid = "VTID";
158const char * const config_event_context_ppid = "PPID";
159const char * const config_event_context_vppid = "VPPID";
160const char * const config_event_context_pthread_id = "PTHREAD_ID";
161const char * const config_event_context_hostname = "HOSTNAME";
162const char * const config_event_context_ip = "IP";
e885a367 163const char * const config_event_context_perf_thread_counter = "PERF_THREAD_COUNTER";
fb198a11 164
dcf266c0
JG
165struct consumer_output {
166 int enabled;
167 char *path;
168 char *control_uri;
169 char *data_uri;
170};
171
1501a7f3
JG
172static 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);
192end:
193 return ret;
194}
195
196LTTNG_HIDDEN
197int 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;
7ab02a27 201 char *path;
1501a7f3
JG
202 FILE *config_file = NULL;
203 struct handler_filter_args filter = { section, handler, user_data };
204
7ab02a27
DG
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. */
1501a7f3
JG
248 if (override_path) {
249 config_file = fopen(override_path, "r");
250 if (config_file) {
7ab02a27
DG
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);
1501a7f3
JG
256 } else {
257 ERR("Failed to open daemon configuration file at %s",
258 override_path);
259 ret = -ENOENT;
7ab02a27 260 goto error;
1501a7f3
JG
261 }
262 }
263
7ab02a27
DG
264 /* Everything went well. */
265 ret = 0;
1501a7f3 266
7ab02a27 267error:
1501a7f3
JG
268 return ret;
269}
270
271LTTNG_HIDDEN
272int 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);
315end:
316 return ret;
317}
36f2332b
JG
318
319/*
320 * Returns a xmlChar string which must be released using xmlFree().
321 */
322static 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';
357end:
358 return out_str;
359}
360
361LTTNG_HIDDEN
705bb62f 362struct config_writer *config_writer_create(int fd_output, int indent)
36f2332b
JG
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);
705bb62f 388 if (ret) {
36f2332b
JG
389 goto error_destroy;
390 }
391
705bb62f
JRJ
392 ret = xmlTextWriterSetIndent(writer->writer, indent);
393 if (ret) {
36f2332b
JG
394 goto error_destroy;
395 }
396
397end:
398 return writer;
399error_destroy:
400 config_writer_destroy(writer);
401 return NULL;
402}
403
404LTTNG_HIDDEN
405int 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);
424end:
425 return ret;
426}
427
428LTTNG_HIDDEN
429int 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);
448end:
449 return ret > 0 ? 0 : ret;
450}
451
452LTTNG_HIDDEN
453int 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);
463end:
464 return ret > 0 ? 0 : ret;
465}
466
467LTTNG_HIDDEN
468int 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);
488end:
489 return ret > 0 ? 0 : ret;
490}
491
492LTTNG_HIDDEN
493int 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);
513end:
514 return ret > 0 ? 0 : ret;
515}
516
517LTTNG_HIDDEN
518int 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
525LTTNG_HIDDEN
526int 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,
dcf266c0 552 encoded_value);
36f2332b
JG
553end:
554 xmlFree(encoded_element_name);
555 xmlFree(encoded_value);
556 return ret > 0 ? 0 : ret;
557}
dcf266c0
JG
558
559static
560void 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);
6c043b48 568 va_end(args);
dcf266c0
JG
569 if (ret == -1) {
570 ERR("String allocation failed in xml error handler");
571 return;
572 }
dcf266c0
JG
573
574 fprintf(stderr, "XML Error: %s", errMsg);
575 free(errMsg);
576}
577
578static
579void 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
54e399cb
JG
597static
598char *get_session_config_xsd_path()
599{
600 char *xsd_path;
e8fa9fb0 601 const char *base_path = lttng_secure_getenv(DEFAULT_SESSION_CONFIG_XSD_PATH_ENV);
54e399cb
JG
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);
624end:
625 return xsd_path;
626}
627
dcf266c0
JG
628static
629int init_session_config_validation_ctx(
630 struct session_config_validation_ctx *ctx)
631{
632 int ret;
54e399cb
JG
633 char *xsd_path = get_session_config_xsd_path();
634
635 if (!xsd_path) {
636 ret = -LTTNG_ERR_NOMEM;
637 goto end;
638 }
dcf266c0 639
54e399cb 640 ctx->parser_ctx = xmlSchemaNewParserCtxt(xsd_path);
dcf266c0
JG
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
667end:
668 if (ret) {
669 fini_session_config_validation_ctx(ctx);
670 }
671
54e399cb 672 free(xsd_path);
dcf266c0
JG
673 return ret;
674}
675
676static
677int 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
694end:
695 return ret;
696}
697
698static
699int 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
716end:
717 return ret;
718}
719
720static
721int 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 }
739end:
740 return ret;
741}
742
743static
744int 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;
5cdb6027
DG
758 } else if (!strcmp((char *) domain, config_domain_type_log4j)) {
759 ret = LTTNG_DOMAIN_LOG4J;
0e115563
DG
760 } else if (!strcmp((char *) domain, config_domain_type_python)) {
761 ret = LTTNG_DOMAIN_PYTHON;
dcf266c0
JG
762 } else {
763 goto error;
764 }
765
766 return ret;
767error:
768 return -1;
769}
770
771static
772int 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;
791error:
792 return -1;
793}
794
795static
796int 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;
814error:
815 return -1;
816}
817
818static
819int 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;
836error:
837 return -1;
838}
839
840static
841int 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;
869error:
870 return -1;
871}
872
873static
874int 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;
895error:
896 return -1;
897}
898
899/*
900 * Return the context type or -1 on error.
901 */
902static
903int 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;
951error:
952 return -1;
953}
954
955static
956int 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;
999end:
1000 return ret;
1001}
1002
1003static
1004int 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
1029static
1030int 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
1084end:
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
1094static
1095int 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);
1119end:
1120 return ret;
1121}
1122
1123static
1124int 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);
1230error_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 }
1240end:
1241 return ret;
1242}
1243
1244static
1245int create_session(const char *name,
1246 struct lttng_domain *kernel_domain,
1247 struct lttng_domain *ust_domain,
1248 struct lttng_domain *jul_domain,
5cdb6027 1249 struct lttng_domain *log4j_domain,
dcf266c0
JG
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);
dcf266c0
JG
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[] =
c8c5f7ce 1290 { kernel_domain, ust_domain, jul_domain, log4j_domain };
dcf266c0
JG
1291
1292 /* network destination */
1293 if (live_timer_interval && live_timer_interval != UINT64_MAX) {
b664f89a
DG
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);
dcf266c0
JG
1300 } else {
1301 ret = lttng_create_session(name, NULL);
1302 }
1303 if (ret) {
1304 goto end;
1305 }
1306
301423df 1307 for (i = 0; i < (sizeof(domains) / sizeof(domains[0])); i++) {
dcf266c0
JG
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 }
1326end:
1327 free(output.path);
1328 free(output.control_uri);
1329 free(output.data_uri);
1330 return ret;
1331}
1332static
1333int 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;
1405end:
1406 return ret;
1407}
1408
1409static
1410int 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);
065321e9
JG
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 }
dcf266c0
JG
1664end:
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
1674static
1675int 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 }
1692end:
1693 return ret;
1694}
1695
1696static
1697int 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;
1945end:
1946 return ret;
1947}
1948
1949static
1950int 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 */
14ce5bd8
JG
1988 context.ctx = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
1989 LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER :
1990 LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER;
dcf266c0
JG
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);
2068end:
2069 return ret;
2070}
2071
2072static
2073int 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 }
2086end:
2087 return ret;
2088}
2089
2090static
2091int 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 }
2163end:
2164 lttng_destroy_handle(handle);
2165 return ret;
2166}
2167
2168static
2169int 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;
5cdb6027 2181 struct lttng_domain *log4j_domain = NULL;
0e115563 2182 struct lttng_domain *python_domain = NULL;
dcf266c0
JG
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;
c2da8cde 2192 goto error;
dcf266c0
JG
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;
c2da8cde 2206 goto error;
dcf266c0
JG
2207 }
2208
2209 ret = parse_bool(node_content, &started);
2210 free(node_content);
2211 if (ret) {
2212 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
c2da8cde 2213 goto error;
dcf266c0
JG
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;
c2da8cde 2231 goto error;
dcf266c0
JG
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;
c2da8cde 2238 goto error;
dcf266c0
JG
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;
c2da8cde 2246 goto error;
dcf266c0
JG
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;
c2da8cde 2253 goto error;
dcf266c0
JG
2254 }
2255 }
2256 }
2257 }
2258
2259 if (!name) {
2260 /* Mandatory attribute, as defined in the session XSD */
2261 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
c2da8cde 2262 goto error;
dcf266c0
JG
2263 }
2264
2265 if (session_name && strcmp(name, session_name)) {
2266 /* This is not the session we are looking for */
c2da8cde
DG
2267 ret = -LTTNG_ERR_NO_SESSION;
2268 goto error;
dcf266c0
JG
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;
c2da8cde 2279 goto error;
dcf266c0
JG
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:
c33e6729
DG
2289 if (kernel_domain) {
2290 /* Same domain seen twice, invalid! */
2291 goto domain_init_error;
2292 }
dcf266c0
JG
2293 kernel_domain = domain;
2294 break;
2295 case LTTNG_DOMAIN_UST:
c33e6729
DG
2296 if (ust_domain) {
2297 /* Same domain seen twice, invalid! */
2298 goto domain_init_error;
2299 }
dcf266c0
JG
2300 ust_domain = domain;
2301 break;
2302 case LTTNG_DOMAIN_JUL:
c33e6729
DG
2303 if (jul_domain) {
2304 /* Same domain seen twice, invalid! */
2305 goto domain_init_error;
2306 }
dcf266c0
JG
2307 jul_domain = domain;
2308 break;
5cdb6027
DG
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;
0e115563
DG
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;
dcf266c0
JG
2323 default:
2324 WARN("Invalid domain type");
2325 goto domain_init_error;
2326 }
2327 continue;
2328domain_init_error:
2329 free(domain);
2330 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
c2da8cde 2331 goto error;
dcf266c0
JG
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.");
c2da8cde 2339 goto error;
dcf266c0
JG
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,
5cdb6027 2349 log4j_domain, output_node, live_timer_interval);
dcf266c0
JG
2350 } else {
2351 /* regular session */
2352 ret = create_session(name, kernel_domain, ust_domain, jul_domain,
5cdb6027 2353 log4j_domain, output_node, UINT64_MAX);
dcf266c0 2354 }
dcf266c0 2355 if (ret) {
c2da8cde 2356 goto error;
dcf266c0
JG
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 }
c2da8cde 2373
dcf266c0 2374end:
b2579dc1
JG
2375 if (ret < 0) {
2376 ERR("Failed to load session %s: %s", name, lttng_strerror(ret));
2377 lttng_destroy_session(name);
2378 }
2379
c2da8cde 2380error:
dcf266c0
JG
2381 free(kernel_domain);
2382 free(ust_domain);
2383 free(jul_domain);
5cdb6027 2384 free(log4j_domain);
135a3893 2385 free(python_domain);
dcf266c0
JG
2386 free(name);
2387 return ret;
2388}
2389
cf53c06d
DG
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 */
2394static 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 }
2411valid:
2412 return 1;
2413}
2414
dcf266c0
JG
2415static
2416int 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;
dcf266c0
JG
2423
2424 assert(path);
2425 assert(validation_ctx);
2426
cf53c06d
DG
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 }
dcf266c0
JG
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 }
2466end:
2467 xmlFreeDoc(doc);
2468 if (!ret) {
a96bc65d 2469 ret = session_found ? 0 : -LTTNG_ERR_LOAD_SESSION_NOENT;
dcf266c0
JG
2470 }
2471 return ret;
2472}
2473
2474static
2475int 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;
dcf266c0
JG
2479 DIR *directory = NULL;
2480
2481 assert(path);
2482 assert(validation_ctx);
2483
4af16958
DG
2484 directory = opendir(path);
2485 if (!directory) {
11143783
DG
2486 switch (errno) {
2487 case ENOTDIR:
0f0a81b5
DG
2488 /* Try the file loading. */
2489 break;
11143783
DG
2490 case ENOENT:
2491 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
2492 goto end;
2493 default:
0f0a81b5
DG
2494 ret = -LTTNG_ERR_LOAD_IO_FAIL;
2495 goto end;
4af16958 2496 }
dcf266c0 2497 }
4af16958 2498 if (directory) {
dcf266c0
JG
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
dcf266c0
JG
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
4af16958 2527 ret = 0;
dcf266c0
JG
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
431f702e 2537 if (path_len + file_name_len >= PATH_MAX) {
dcf266c0
JG
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
2570end:
2571 if (directory) {
2572 if (closedir(directory)) {
2573 PERROR("closedir");
2574 }
2575 }
2576
2577 if (!session_found) {
a96bc65d 2578 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
dcf266c0
JG
2579 }
2580
2581 return ret;
2582}
2583
ab38c13f
DG
2584/*
2585 * Validate that the given path's credentials and the current process have the
cf53c06d 2586 * same UID. If so, return 1 else return 0 if it does NOT match.
ab38c13f
DG
2587 */
2588static int validate_path_creds(const char *path)
2589{
2590 int ret, uid = getuid();
2591 struct stat buf;
2592
2593 assert(path);
2594
cf53c06d 2595 if (uid == 0) {
ab38c13f
DG
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
2612valid:
ab38c13f 2613 return 1;
cf53c06d
DG
2614invalid:
2615 return 0;
ab38c13f
DG
2616}
2617
dcf266c0
JG
2618LTTNG_HIDDEN
2619int config_load_session(const char *path, const char *session_name,
ab38c13f 2620 int override, unsigned int autoload)
dcf266c0
JG
2621{
2622 int ret;
cf53c06d 2623 const char *path_ptr = NULL;
dcf266c0
JG
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) {
ab38c13f
DG
2632 char *home_path;
2633 const char *sys_path;
2634
dcf266c0 2635 /* Try home path */
ab38c13f 2636 home_path = utils_get_home_dir();
dcf266c0 2637 if (home_path) {
ab38c13f 2638 char path[PATH_MAX];
dcf266c0 2639
d4fcf703
DG
2640 /*
2641 * Try user session configuration path. Ignore error here so we can
2642 * continue loading the system wide sessions.
2643 */
ab38c13f
DG
2644 if (autoload) {
2645 ret = snprintf(path, sizeof(path),
2646 DEFAULT_SESSION_HOME_CONFIGPATH "/"
2647 DEFAULT_SESSION_CONFIG_AUTOLOAD, home_path);
cf53c06d
DG
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 }
ab38c13f
DG
2662 } else {
2663 ret = snprintf(path, sizeof(path),
2664 DEFAULT_SESSION_HOME_CONFIGPATH, home_path);
cf53c06d
DG
2665 if (ret < 0) {
2666 PERROR("snprintf session home config path");
2667 goto end;
2668 }
2669 path_ptr = path;
ab38c13f 2670 }
cf53c06d
DG
2671 if (path_ptr) {
2672 ret = load_session_from_path(path_ptr, session_name,
d4fcf703
DG
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 */
ab38c13f 2681 }
d4fcf703 2682 }
ab38c13f 2683
cf53c06d
DG
2684 /* Reset path pointer for the system wide dir. */
2685 path_ptr = NULL;
2686
d4fcf703
DG
2687 /* Try system wide configuration directory. */
2688 if (autoload) {
2689 sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH "/"
2690 DEFAULT_SESSION_CONFIG_AUTOLOAD;
cf53c06d
DG
2691 ret = validate_path_creds(sys_path);
2692 if (ret) {
2693 path_ptr = sys_path;
2694 }
d4fcf703 2695 } else {
cf53c06d
DG
2696 sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH;
2697 path_ptr = sys_path;
d4fcf703
DG
2698 }
2699
cf53c06d
DG
2700 if (path_ptr) {
2701 ret = load_session_from_path(path_ptr, session_name,
d4fcf703 2702 &validation_ctx, override);
dcf266c0
JG
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 }
2726end:
2727 fini_session_config_validation_ctx(&validation_ctx);
d2b6efff
JG
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 }
dcf266c0
JG
2735 return ret;
2736}
This page took 0.140617 seconds and 4 git commands to generate.