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