Fix: session-descriptor.c: Dereference before null check
[lttng-tools.git] / src / common / session-descriptor.c
1 /*
2 * Copyright (C) 2019 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include <lttng/session-descriptor-internal.h>
19 #include <common/macros.h>
20 #include <common/uri.h>
21 #include <common/defaults.h>
22 #include <common/error.h>
23 #include <time.h>
24 #include <assert.h>
25 #include <stdio.h>
26
27 struct lttng_session_descriptor_network_location {
28 struct lttng_uri *control;
29 struct lttng_uri *data;
30 };
31
32 struct lttng_session_descriptor {
33 enum lttng_session_descriptor_type type;
34 /*
35 * If an output type that is not OUTPUT_TYPE_NONE is specified,
36 * it means that an output of that type must be generated at
37 * session-creation time.
38 */
39 enum lttng_session_descriptor_output_type output_type;
40 char *name;
41 union {
42 struct lttng_session_descriptor_network_location network;
43 struct lttng_uri *local;
44 } output;
45 };
46
47 struct lttng_session_descriptor_snapshot {
48 struct lttng_session_descriptor base;
49 /*
50 * Assumes at-most one snapshot output is supported. Uses
51 * the output field of the base class.
52 */
53 };
54
55 struct lttng_session_descriptor_live {
56 struct lttng_session_descriptor base;
57 unsigned long long live_timer_us;
58 };
59
60 struct lttng_session_descriptor_comm {
61 /* enum lttng_session_descriptor_type */
62 uint8_t type;
63 /* enum lttng_session_descriptor_output_type */
64 uint8_t output_type;
65 /* Includes trailing null. */
66 uint32_t name_len;
67 /* Name follows, followed by URIs */
68 uint8_t uri_count;
69 } LTTNG_PACKED;
70
71 struct lttng_session_descriptor_live_comm {
72 struct lttng_session_descriptor_comm base;
73 /* Live-specific parameters. */
74 uint64_t live_timer_us;
75 } LTTNG_PACKED;
76
77 static
78 struct lttng_uri *uri_copy(const struct lttng_uri *uri)
79 {
80 struct lttng_uri *new_uri = NULL;
81
82 if (!uri) {
83 goto end;
84 }
85
86 new_uri = zmalloc(sizeof(*new_uri));
87 if (!new_uri) {
88 goto end;
89 }
90 memcpy(new_uri, uri, sizeof(*new_uri));
91 end:
92 return new_uri;
93 }
94
95 static
96 struct lttng_uri *uri_from_path(const char *path)
97 {
98 struct lttng_uri *uris = NULL;
99 ssize_t uri_count;
100 char local_protocol_string[LTTNG_PATH_MAX + sizeof("file://")] =
101 "file://";
102
103 if (strlen(path) >= LTTNG_PATH_MAX) {
104 goto end;
105 }
106
107 if (path[0] != '/') {
108 /* Not an absolute path. */
109 goto end;
110 }
111
112 strncat(local_protocol_string, path, LTTNG_PATH_MAX);
113 uri_count = uri_parse(local_protocol_string, &uris);
114 if (uri_count != 1) {
115 goto error;
116 }
117 if (uris[0].dtype != LTTNG_DST_PATH) {
118 goto error;
119 }
120
121 end:
122 return uris;
123 error:
124 free(uris);
125 return NULL;
126 }
127
128 static
129 void network_location_fini(
130 struct lttng_session_descriptor_network_location *location)
131 {
132 free(location->control);
133 free(location->data);
134 }
135
136 /* Assumes ownership of control and data. */
137 static
138 int network_location_set_from_lttng_uris(
139 struct lttng_session_descriptor_network_location *location,
140 struct lttng_uri *control, struct lttng_uri *data)
141 {
142 int ret = 0;
143
144 if (!control && !data) {
145 goto end;
146 }
147
148 if (!(control && data)) {
149 /* None or both must be set. */
150 ret = -1;
151 goto end;
152 }
153
154 if (control->stype != LTTNG_STREAM_CONTROL ||
155 data->stype != LTTNG_STREAM_DATA) {
156 ret = -1;
157 goto end;
158 }
159
160 free(location->control);
161 free(location->data);
162 location->control = control;
163 location->data = data;
164 control = NULL;
165 data = NULL;
166 end:
167 free(control);
168 free(data);
169 return ret;
170 }
171
172 static
173 int network_location_set_from_uri_strings(
174 struct lttng_session_descriptor_network_location *location,
175 const char *control, const char *data)
176 {
177 int ret = 0;
178 ssize_t uri_count;
179 struct lttng_uri *parsed_uris = NULL;
180 struct lttng_uri *control_uri = NULL;
181 struct lttng_uri *data_uri = NULL;
182
183 uri_count = uri_parse_str_urls(control, data, &parsed_uris);
184 if (uri_count != 2 && uri_count != 0) {
185 ret = -1;
186 goto end;
187 }
188
189 /*
190 * uri_parse_str_urls returns a contiguous array of lttng_uris whereas
191 * session descriptors expect individually allocated lttng_uris.
192 */
193 if (uri_count == 2) {
194 control_uri = zmalloc(sizeof(*control_uri));
195 data_uri = zmalloc(sizeof(*data_uri));
196 if (!control_uri || !data_uri) {
197 ret = -1;
198 goto end;
199 }
200 memcpy(control_uri, &parsed_uris[0], sizeof(*control_uri));
201 memcpy(data_uri, &parsed_uris[1], sizeof(*data_uri));
202 }
203
204 /* Ownership of control and data uris is transferred. */
205 ret = network_location_set_from_lttng_uris(
206 location,
207 control_uri,
208 data_uri);
209 control_uri = NULL;
210 data_uri = NULL;
211 end:
212 free(parsed_uris);
213 free(control_uri);
214 free(data_uri);
215 return ret;
216 }
217
218 struct lttng_session_descriptor *
219 lttng_session_descriptor_create(const char *name)
220 {
221 struct lttng_session_descriptor *descriptor;
222
223 descriptor = zmalloc(sizeof(*descriptor));
224 if (!descriptor) {
225 goto error;
226 }
227
228 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
229 descriptor->output_type =
230 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
231 if (lttng_session_descriptor_set_session_name(descriptor, name)) {
232 goto error;
233 }
234 return descriptor;
235 error:
236 lttng_session_descriptor_destroy(descriptor);
237 return NULL;
238 }
239
240 /* Ownership of uri is transferred. */
241 static
242 struct lttng_session_descriptor *
243 _lttng_session_descriptor_local_create(const char *name,
244 struct lttng_uri *uri)
245 {
246 struct lttng_session_descriptor *descriptor;
247
248 descriptor = lttng_session_descriptor_create(name);
249 if (!descriptor) {
250 goto error;
251 }
252 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
253 descriptor->output_type =
254 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL;
255 if (uri) {
256 if (uri->dtype != LTTNG_DST_PATH) {
257 goto error;
258 }
259 descriptor->output.local = uri;
260 uri = NULL;
261 }
262 return descriptor;
263 error:
264 free(uri);
265 lttng_session_descriptor_destroy(descriptor);
266 return NULL;
267 }
268
269 struct lttng_session_descriptor *
270 lttng_session_descriptor_local_create(const char *name, const char *path)
271 {
272 struct lttng_uri *uri = NULL;
273 struct lttng_session_descriptor *descriptor;
274
275 if (path) {
276 uri = uri_from_path(path);
277 if (!uri) {
278 goto error;
279 }
280 }
281 descriptor = _lttng_session_descriptor_local_create(name, uri);
282 return descriptor;
283 error:
284 return NULL;
285 }
286
287 /* Assumes the ownership of both uris. */
288 static
289 struct lttng_session_descriptor *
290 _lttng_session_descriptor_network_create(const char *name,
291 struct lttng_uri *control, struct lttng_uri *data)
292 {
293 int ret;
294 struct lttng_session_descriptor *descriptor;
295
296 descriptor = lttng_session_descriptor_create(name);
297 if (!descriptor) {
298 goto error;
299 }
300
301 descriptor->type = LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR;
302 descriptor->output_type = LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
303 /* Assumes the ownership of both uris. */
304 ret = network_location_set_from_lttng_uris(&descriptor->output.network,
305 control, data);
306 control = NULL;
307 data = NULL;
308 if (ret) {
309 goto error;
310 }
311 return descriptor;
312 error:
313 lttng_session_descriptor_destroy(descriptor);
314 free(control);
315 free(data);
316 return NULL;
317 }
318
319 struct lttng_session_descriptor *
320 lttng_session_descriptor_network_create(const char *name,
321 const char *control_url, const char *data_url)
322 {
323 int ret;
324 struct lttng_session_descriptor *descriptor;
325
326 descriptor = _lttng_session_descriptor_network_create(name,
327 NULL, NULL);
328 if (!descriptor) {
329 goto error;
330 }
331
332 ret = network_location_set_from_uri_strings(&descriptor->output.network,
333 control_url, data_url);
334 if (ret) {
335 goto error;
336 }
337 return descriptor;
338 error:
339 lttng_session_descriptor_destroy(descriptor);
340 return NULL;
341 }
342
343 static
344 struct lttng_session_descriptor_snapshot *
345 _lttng_session_descriptor_snapshot_create(const char *name)
346 {
347 struct lttng_session_descriptor_snapshot *descriptor;
348
349 descriptor = zmalloc(sizeof(*descriptor));
350 if (!descriptor) {
351 goto error;
352 }
353
354 descriptor->base.type = LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT;
355 descriptor->base.output_type =
356 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
357 if (lttng_session_descriptor_set_session_name(&descriptor->base,
358 name)) {
359 goto error;
360 }
361 return descriptor;
362 error:
363 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
364 return NULL;
365 }
366
367 /* Ownership of control and data is transferred. */
368 static
369 struct lttng_session_descriptor_snapshot *
370 _lttng_session_descriptor_snapshot_network_create(const char *name,
371 struct lttng_uri *control, struct lttng_uri *data)
372 {
373 int ret;
374 struct lttng_session_descriptor_snapshot *descriptor;
375
376 descriptor = _lttng_session_descriptor_snapshot_create(name);
377 if (!descriptor) {
378 goto error;
379 }
380
381 descriptor->base.output_type =
382 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
383 /* Ownership of control and data is transferred. */
384 ret = network_location_set_from_lttng_uris(
385 &descriptor->base.output.network,
386 control, data);
387 control = NULL;
388 data = NULL;
389 if (ret) {
390 goto error;
391 }
392 return descriptor;
393 error:
394 free(control);
395 free(data);
396 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
397 return NULL;
398 }
399
400 struct lttng_session_descriptor *
401 lttng_session_descriptor_snapshot_create(const char *name)
402 {
403 struct lttng_session_descriptor_snapshot *descriptor;
404
405 descriptor = _lttng_session_descriptor_snapshot_create(name);
406 return descriptor ? &descriptor->base : NULL;
407 }
408
409 struct lttng_session_descriptor *
410 lttng_session_descriptor_snapshot_network_create(const char *name,
411 const char *control_url, const char *data_url)
412 {
413 int ret;
414 struct lttng_session_descriptor_snapshot *descriptor;
415
416 descriptor = _lttng_session_descriptor_snapshot_network_create(name,
417 NULL, NULL);
418 if (!descriptor) {
419 goto error;
420 }
421
422 ret = network_location_set_from_uri_strings(
423 &descriptor->base.output.network,
424 control_url, data_url);
425 if (ret) {
426 goto error;
427 }
428 return &descriptor->base;
429 error:
430 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
431 return NULL;
432 }
433
434 /* Ownership of uri is transferred. */
435 static
436 struct lttng_session_descriptor_snapshot *
437 _lttng_session_descriptor_snapshot_local_create(const char *name,
438 struct lttng_uri *uri)
439 {
440 struct lttng_session_descriptor_snapshot *descriptor;
441
442 descriptor = _lttng_session_descriptor_snapshot_create(name);
443 if (!descriptor) {
444 goto error;
445 }
446 descriptor->base.output_type =
447 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL;
448 if (uri) {
449 if (uri->dtype != LTTNG_DST_PATH) {
450 goto error;
451 }
452 descriptor->base.output.local = uri;
453 uri = NULL;
454 }
455 return descriptor;
456 error:
457 free(uri);
458 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
459 return NULL;
460 }
461
462 struct lttng_session_descriptor *
463 lttng_session_descriptor_snapshot_local_create(const char *name,
464 const char *path)
465 {
466 struct lttng_uri *path_uri = NULL;
467 struct lttng_session_descriptor_snapshot *descriptor;
468
469 if (path) {
470 path_uri = uri_from_path(path);
471 if (!path_uri) {
472 goto error;
473 }
474 }
475 descriptor = _lttng_session_descriptor_snapshot_local_create(name,
476 path_uri);
477 return descriptor ? &descriptor->base : NULL;
478 error:
479 return NULL;
480 }
481
482 static
483 struct lttng_session_descriptor_live *
484 _lttng_session_descriptor_live_create(const char *name,
485 unsigned long long live_timer_interval_us)
486 {
487 struct lttng_session_descriptor_live *descriptor = NULL;
488
489 if (live_timer_interval_us == 0) {
490 goto error;
491 }
492 descriptor = zmalloc(sizeof(*descriptor));
493 if (!descriptor) {
494 goto error;
495 }
496
497 descriptor->base.type = LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE;
498 descriptor->base.output_type =
499 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE;
500 descriptor->live_timer_us = live_timer_interval_us;
501 if (lttng_session_descriptor_set_session_name(&descriptor->base,
502 name)) {
503 goto error;
504 }
505
506 return descriptor;
507 error:
508 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
509 return NULL;
510 }
511
512 /* Ownership of control and data is transferred. */
513 static
514 struct lttng_session_descriptor_live *
515 _lttng_session_descriptor_live_network_create(
516 const char *name,
517 struct lttng_uri *control, struct lttng_uri *data,
518 unsigned long long live_timer_interval_us)
519 {
520 int ret;
521 struct lttng_session_descriptor_live *descriptor;
522
523 descriptor = _lttng_session_descriptor_live_create(name,
524 live_timer_interval_us);
525 if (!descriptor) {
526 goto error;
527 }
528
529 descriptor->base.output_type =
530 LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK;
531
532 /* Ownerwhip of control and data is transferred. */
533 ret = network_location_set_from_lttng_uris(
534 &descriptor->base.output.network,
535 control, data);
536 control = NULL;
537 data = NULL;
538 if (ret) {
539 goto error;
540 }
541 return descriptor;
542 error:
543 free(control);
544 free(data);
545 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
546 return NULL;
547 }
548
549 struct lttng_session_descriptor *
550 lttng_session_descriptor_live_create(
551 const char *name,
552 unsigned long long live_timer_us)
553 {
554 struct lttng_session_descriptor_live *descriptor;
555
556 descriptor = _lttng_session_descriptor_live_create(name, live_timer_us);
557
558 return descriptor ? &descriptor->base : NULL;
559 }
560
561 struct lttng_session_descriptor *
562 lttng_session_descriptor_live_network_create(
563 const char *name,
564 const char *control_url, const char *data_url,
565 unsigned long long live_timer_us)
566 {
567 int ret;
568 struct lttng_session_descriptor_live *descriptor;
569
570 descriptor = _lttng_session_descriptor_live_network_create(name,
571 NULL, NULL, live_timer_us);
572 if (!descriptor) {
573 goto error;
574 }
575
576 ret = network_location_set_from_uri_strings(
577 &descriptor->base.output.network,
578 control_url, data_url);
579 if (ret) {
580 goto error;
581 }
582 return &descriptor->base;
583 error:
584 lttng_session_descriptor_destroy(descriptor ? &descriptor->base : NULL);
585 return NULL;
586 }
587
588 void lttng_session_descriptor_destroy(
589 struct lttng_session_descriptor *descriptor)
590 {
591 if (!descriptor) {
592 return;
593 }
594
595 switch (descriptor->output_type) {
596 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
597 break;
598 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
599 free(descriptor->output.local);
600 break;
601 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
602 network_location_fini(&descriptor->output.network);
603 break;
604 default:
605 abort();
606 }
607
608 free(descriptor->name);
609 free(descriptor);
610 }
611
612 LTTNG_HIDDEN
613 ssize_t lttng_session_descriptor_create_from_buffer(
614 const struct lttng_buffer_view *payload,
615 struct lttng_session_descriptor **descriptor)
616 {
617 int i;
618 ssize_t offset = 0, ret;
619 struct lttng_buffer_view current_view;
620 const char *name = NULL;
621 const struct lttng_session_descriptor_comm *base_header;
622 size_t max_expected_uri_count;
623 uint64_t live_timer_us = 0;
624 struct lttng_uri *uris[2] = {};
625 enum lttng_session_descriptor_type type;
626 enum lttng_session_descriptor_output_type output_type;
627
628 current_view = lttng_buffer_view_from_view(payload, offset,
629 sizeof(*base_header));
630 base_header = (typeof(base_header)) current_view.data;
631 if (!base_header) {
632 ret = -1;
633 goto end;
634 }
635
636 switch (base_header->type) {
637 case LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR:
638 case LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT:
639 break;
640 case LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE:
641 {
642 const struct lttng_session_descriptor_live_comm *live_header;
643
644 current_view = lttng_buffer_view_from_view(payload, offset,
645 sizeof(*live_header));
646 live_header = (typeof(live_header)) current_view.data;
647 if (!live_header) {
648 ret = -1;
649 goto end;
650 }
651
652 live_timer_us = live_header->live_timer_us;
653 break;
654 }
655 default:
656 ret = -1;
657 goto end;
658 }
659 /* type has been validated. */
660 type = base_header->type;
661
662 switch (base_header->output_type) {
663 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
664 max_expected_uri_count = 0;
665 break;
666 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
667 max_expected_uri_count = 1;
668 break;
669 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
670 max_expected_uri_count = 2;
671 break;
672 default:
673 ret = -1;
674 goto end;
675 }
676 /* output_type has been validated. */
677 output_type = base_header->output_type;
678
679 /* Skip after header. */
680 offset += current_view.size;
681 if (!base_header->name_len) {
682 goto skip_name;
683 }
684
685 /* Map the name. */
686 current_view = lttng_buffer_view_from_view(payload, offset,
687 base_header->name_len);
688 name = current_view.data;
689 if (!name) {
690 ret = -1;
691 goto end;
692 }
693
694 if (base_header->name_len == 1 ||
695 name[base_header->name_len - 1] ||
696 strlen(name) != base_header->name_len - 1) {
697 /*
698 * Check that the name is not NULL, is NULL-terminated, and
699 * does not contain a NULL before the last byte.
700 */
701 ret = -1;
702 goto end;
703 }
704
705 /* Skip after the name. */
706 offset += base_header->name_len;
707 skip_name:
708 if (base_header->uri_count > max_expected_uri_count) {
709 ret = -1;
710 goto end;
711 }
712
713 for (i = 0; i < base_header->uri_count; i++) {
714 struct lttng_uri *uri;
715
716 /* Map a URI. */
717 current_view = lttng_buffer_view_from_view(payload,
718 offset, sizeof(*uri));
719 uri = (typeof(uri)) current_view.data;
720 if (!uri) {
721 ret = -1;
722 goto end;
723 }
724 uris[i] = zmalloc(sizeof(*uri));
725 if (!uris[i]) {
726 ret = -1;
727 goto end;
728 }
729 memcpy(uris[i], uri, sizeof(*uri));
730 offset += sizeof(*uri);
731 }
732
733 switch (type) {
734 case LTTNG_SESSION_DESCRIPTOR_TYPE_REGULAR:
735 switch (output_type) {
736 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
737 *descriptor = lttng_session_descriptor_create(name);
738 break;
739 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
740 *descriptor = _lttng_session_descriptor_local_create(
741 name, uris[0]);
742 break;
743 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
744 *descriptor = _lttng_session_descriptor_network_create(
745 name, uris[0], uris[1]);
746 break;
747 default:
748 /* Already checked. */
749 abort();
750 }
751 break;
752 case LTTNG_SESSION_DESCRIPTOR_TYPE_SNAPSHOT:
753 {
754 struct lttng_session_descriptor_snapshot *snapshot;
755 switch (output_type) {
756 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
757 snapshot = _lttng_session_descriptor_snapshot_create(
758 name);
759 break;
760 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
761 snapshot = _lttng_session_descriptor_snapshot_local_create(
762 name, uris[0]);
763 break;
764 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
765 snapshot = _lttng_session_descriptor_snapshot_network_create(
766 name, uris[0], uris[1]);
767 break;
768 default:
769 /* Already checked. */
770 abort();
771 }
772 *descriptor = snapshot ? &snapshot->base : NULL;
773 break;
774 }
775 case LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE:
776 {
777 struct lttng_session_descriptor_live *live;
778
779 switch (output_type) {
780 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
781 live = _lttng_session_descriptor_live_create(
782 name, live_timer_us);
783 break;
784 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
785 live = _lttng_session_descriptor_live_network_create(
786 name, uris[0], uris[1],
787 live_timer_us);
788 break;
789 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
790 ret = -1;
791 goto end;
792 default:
793 /* Already checked. */
794 abort();
795 }
796 *descriptor = live ? &live->base : NULL;
797 break;
798 }
799 default:
800 /* Already checked. */
801 abort();
802 }
803 memset(uris, 0, sizeof(uris));
804 if (!*descriptor) {
805 ret = -1;
806 goto end;
807 }
808
809 ret = offset;
810 end:
811 free(uris[0]);
812 free(uris[1]);
813 return ret;
814 }
815
816 LTTNG_HIDDEN
817 int lttng_session_descriptor_serialize(
818 const struct lttng_session_descriptor *descriptor,
819 struct lttng_dynamic_buffer *buffer)
820 {
821 int ret, i;
822 /* There are, at most, two URIs to serialize. */
823 struct lttng_uri *uris[2] = {};
824 size_t uri_count = 0;
825 /* The live header is a superset of all headers. */
826 struct lttng_session_descriptor_live_comm header = {
827 .base.type = (uint8_t) descriptor->type,
828 .base.output_type = (uint8_t) descriptor->output_type,
829 .base.name_len = descriptor->name ?
830 strlen(descriptor->name) + 1 : 0,
831 };
832 const void *header_ptr = NULL;
833 size_t header_size;
834
835 switch (descriptor->output_type) {
836 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
837 break;
838 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
839 uris[0] = descriptor->output.local;
840 break;
841 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
842 uris[0] = descriptor->output.network.control;
843 uris[1] = descriptor->output.network.data;
844 break;
845 default:
846 ret = -1;
847 goto end;
848 }
849 uri_count += !!uris[0];
850 uri_count += !!uris[1];
851
852 header.base.uri_count = uri_count;
853 if (descriptor->type == LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE) {
854 const struct lttng_session_descriptor_live *live =
855 container_of(descriptor, typeof(*live),
856 base);
857
858 header.live_timer_us = live->live_timer_us;
859 header_ptr = &header;
860 header_size = sizeof(header);
861 } else {
862 header_ptr = &header.base;
863 header_size = sizeof(header.base);
864 }
865
866 ret = lttng_dynamic_buffer_append(buffer, header_ptr, header_size);
867 if (ret) {
868 goto end;
869 }
870 if (header.base.name_len) {
871 ret = lttng_dynamic_buffer_append(buffer, descriptor->name,
872 header.base.name_len);
873 if (ret) {
874 goto end;
875 }
876 }
877
878 for (i = 0; i < uri_count; i++) {
879 ret = lttng_dynamic_buffer_append(buffer, uris[i],
880 sizeof(struct lttng_uri));
881 if (ret) {
882 goto end;
883 }
884 }
885 end:
886 return ret;
887 }
888
889 LTTNG_HIDDEN
890 enum lttng_session_descriptor_type
891 lttng_session_descriptor_get_type(
892 const struct lttng_session_descriptor *descriptor)
893 {
894 return descriptor->type;
895 }
896
897 LTTNG_HIDDEN
898 enum lttng_session_descriptor_output_type
899 lttng_session_descriptor_get_output_type(
900 const struct lttng_session_descriptor *descriptor)
901 {
902 return descriptor->output_type;
903 }
904
905 LTTNG_HIDDEN
906 void lttng_session_descriptor_get_local_output_uri(
907 const struct lttng_session_descriptor *descriptor,
908 struct lttng_uri *local_uri)
909 {
910 memcpy(local_uri, descriptor->output.local, sizeof(*local_uri));
911 }
912
913 LTTNG_HIDDEN
914 void lttng_session_descriptor_get_network_output_uris(
915 const struct lttng_session_descriptor *descriptor,
916 struct lttng_uri *control,
917 struct lttng_uri *data)
918 {
919 memcpy(control, descriptor->output.network.control, sizeof(*control));
920 memcpy(data, descriptor->output.network.data, sizeof(*data));
921 }
922
923 LTTNG_HIDDEN
924 unsigned long long
925 lttng_session_descriptor_live_get_timer_interval(
926 const struct lttng_session_descriptor *descriptor)
927 {
928 struct lttng_session_descriptor_live *live;
929
930 live = container_of(descriptor, typeof(*live), base);
931 return live->live_timer_us;
932 }
933
934 enum lttng_session_descriptor_status
935 lttng_session_descriptor_get_session_name(
936 const struct lttng_session_descriptor *descriptor,
937 const char **session_name)
938 {
939 enum lttng_session_descriptor_status status;
940
941 if (!descriptor || !session_name) {
942 status = LTTNG_SESSION_DESCRIPTOR_STATUS_INVALID;
943 goto end;
944 }
945
946 *session_name = descriptor->name;
947 status = descriptor->name ?
948 LTTNG_SESSION_DESCRIPTOR_STATUS_OK :
949 LTTNG_SESSION_DESCRIPTOR_STATUS_UNSET;
950 end:
951 return status;
952 }
953
954 LTTNG_HIDDEN
955 int lttng_session_descriptor_set_session_name(
956 struct lttng_session_descriptor *descriptor,
957 const char *name)
958 {
959 int ret = 0;
960 char *new_name;
961
962 if (!name) {
963 goto end;
964 }
965 if (strlen(name) >= LTTNG_NAME_MAX) {
966 ret = -1;
967 goto end;
968 }
969 new_name = strdup(name);
970 if (!new_name) {
971 ret = -1;
972 goto end;
973 }
974 free(descriptor->name);
975 descriptor->name = new_name;
976 end:
977 return ret;
978 }
979
980 LTTNG_HIDDEN
981 bool lttng_session_descriptor_is_output_destination_initialized(
982 const struct lttng_session_descriptor *descriptor)
983 {
984 switch (descriptor->output_type) {
985 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
986 return true;
987 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
988 return descriptor->output.local;
989 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
990 return descriptor->output.network.control;
991 default:
992 abort();
993 }
994 }
995
996 LTTNG_HIDDEN
997 bool lttng_session_descriptor_has_output_directory(
998 const struct lttng_session_descriptor *descriptor)
999 {
1000 switch (descriptor->output_type) {
1001 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
1002 break;
1003 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1004 if (descriptor->output.local) {
1005 return *descriptor->output.local->dst.path;
1006 }
1007 break;
1008 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1009 if (descriptor->output.network.control) {
1010 return *descriptor->output.network.control->subdir;
1011 }
1012 break;
1013 default:
1014 abort();
1015 }
1016 return false;
1017 }
1018
1019 LTTNG_HIDDEN
1020 enum lttng_error_code lttng_session_descriptor_set_default_output(
1021 struct lttng_session_descriptor *descriptor,
1022 time_t *session_creation_time,
1023 const char *absolute_home_path)
1024 {
1025 enum lttng_error_code ret_code = LTTNG_OK;
1026 struct lttng_uri *uris = NULL;
1027
1028 switch (descriptor->output_type) {
1029 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
1030 goto end;
1031 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1032 {
1033 int ret;
1034 ssize_t uri_ret;
1035 char local_uri[LTTNG_PATH_MAX];
1036 char creation_datetime_suffix[17] = {};
1037
1038 if (session_creation_time) {
1039 size_t strftime_ret;
1040 struct tm *timeinfo;
1041
1042 timeinfo = localtime(session_creation_time);
1043 if (!timeinfo) {
1044 ret_code = LTTNG_ERR_FATAL;
1045 goto end;
1046 }
1047 strftime_ret = strftime(creation_datetime_suffix,
1048 sizeof(creation_datetime_suffix),
1049 "-%Y%m%d-%H%M%S", timeinfo);
1050 if (strftime_ret == 0) {
1051 ERR("Failed to format session creation timestamp while setting default local output destination");
1052 ret_code = LTTNG_ERR_FATAL;
1053 goto end;
1054 }
1055 }
1056 assert(descriptor->name);
1057 ret = snprintf(local_uri, sizeof(local_uri),
1058 "file://%s/%s/%s%s",
1059 absolute_home_path,
1060 DEFAULT_TRACE_DIR_NAME, descriptor->name,
1061 creation_datetime_suffix);
1062 if (ret >= sizeof(local_uri)) {
1063 ERR("Truncation occurred while setting default local output destination");
1064 ret_code = LTTNG_ERR_SET_URL;
1065 goto end;
1066 } else if (ret < 0) {
1067 PERROR("Failed to format default local output URI");
1068 ret_code = LTTNG_ERR_SET_URL;
1069 goto end;
1070 }
1071
1072 uri_ret = uri_parse(local_uri, &uris);
1073 if (uri_ret != 1) {
1074 ret_code = LTTNG_ERR_SET_URL;
1075 goto end;
1076 }
1077 free(descriptor->output.local);
1078 descriptor->output.local = &uris[0];
1079 uris = NULL;
1080 break;
1081 }
1082 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1083 {
1084 int ret;
1085 ssize_t uri_ret;
1086 struct lttng_uri *control = NULL, *data = NULL;
1087
1088 uri_ret = uri_parse_str_urls("net://127.0.0.1", NULL, &uris);
1089 if (uri_ret != 2) {
1090 ret_code = LTTNG_ERR_SET_URL;
1091 goto end;
1092 }
1093
1094 control = uri_copy(&uris[0]);
1095 data = uri_copy(&uris[1]);
1096 if (!control || !data) {
1097 free(control);
1098 free(data);
1099 ret_code = LTTNG_ERR_SET_URL;
1100 goto end;
1101 }
1102
1103 /* Ownership of uris is transferred. */
1104 ret = network_location_set_from_lttng_uris(
1105 &descriptor->output.network,
1106 control, data);
1107 if (ret) {
1108 abort();
1109 ret_code = LTTNG_ERR_SET_URL;
1110 goto end;
1111 }
1112 break;
1113 }
1114 default:
1115 abort();
1116 }
1117 end:
1118 free(uris);
1119 return ret_code;
1120 }
1121
1122 /*
1123 * Note that only properties that can be populated by the session daemon
1124 * (output destination and name) are assigned.
1125 */
1126 LTTNG_HIDDEN
1127 int lttng_session_descriptor_assign(
1128 struct lttng_session_descriptor *dst,
1129 const struct lttng_session_descriptor *src)
1130 {
1131 int ret = 0;
1132
1133 if (dst->type != src->type) {
1134 ret = -1;
1135 goto end;
1136 }
1137 if (dst->output_type != src->output_type) {
1138 ret = -1;
1139 goto end;
1140 }
1141 ret = lttng_session_descriptor_set_session_name(dst, src->name);
1142 if (ret) {
1143 goto end;
1144 }
1145 switch (dst->output_type) {
1146 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1147 free(dst->output.local);
1148 dst->output.local = uri_copy(src->output.local);
1149 if (!dst->output.local) {
1150 ret = -1;
1151 goto end;
1152 }
1153 break;
1154 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1155 {
1156 struct lttng_uri *control_copy = NULL, *data_copy = NULL;
1157
1158 control_copy = uri_copy(dst->output.network.control);
1159 if (!control_copy && dst->output.network.control) {
1160 ret = -1;
1161 goto end;
1162 }
1163 data_copy = uri_copy(dst->output.network.data);
1164 if (!data_copy && dst->output.network.data) {
1165 free(control_copy);
1166 ret = -1;
1167 goto end;
1168 }
1169 ret = network_location_set_from_lttng_uris(&dst->output.network,
1170 control_copy, data_copy);
1171 break;
1172 }
1173 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
1174 goto end;
1175 }
1176 end:
1177 return ret;
1178 }
1179
1180 LTTNG_HIDDEN
1181 int lttng_session_descriptor_get_base_path(struct lttng_session_descriptor *dst,
1182 const char **_base_path)
1183 {
1184 switch (dst->output_type) {
1185 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK:
1186 {
1187 if (dst->output.network.control &&
1188 dst->output.network.control->subdir[0]) {
1189 *_base_path = dst->output.network.control->subdir;
1190 } else {
1191 *_base_path = NULL;
1192 }
1193 break;
1194 }
1195 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL:
1196 case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE:
1197 *_base_path = NULL;
1198 break;
1199 }
1200 return 0;
1201 }
This page took 0.091651 seconds and 4 git commands to generate.