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