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