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