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