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