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