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