Commit | Line | Data |
---|---|---|
8476ce3a JR |
1 | /* |
2 | * Copyright (C) 2018 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com> | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0-only | |
5 | * | |
6 | */ | |
7 | ||
8 | #define _LGPL_SOURCE | |
9 | #include <inttypes.h> | |
10 | ||
11 | #include <common/common.hpp> | |
12 | #include <common/sessiond-comm/relayd.hpp> | |
13 | ||
14 | #include <common/compat/endian.hpp> | |
15 | #include <common/compat/string.hpp> | |
16 | #include <lttng/constant.h> | |
17 | ||
18 | #include "cmd-2-15.hpp" | |
19 | #include "utils.hpp" | |
20 | ||
21 | int cmd_create_session_2_15(const struct lttng_buffer_view *payload, | |
22 | char *session_name, | |
23 | char *hostname, | |
24 | char *base_path, | |
25 | uint32_t *live_timer, | |
26 | bool *snapshot, | |
27 | uint64_t *id_sessiond, | |
28 | lttng_uuid& sessiond_uuid, | |
29 | bool *has_current_chunk, | |
30 | uint64_t *current_chunk_id, | |
31 | time_t *creation_time, | |
32 | bool *session_name_contains_creation_time, | |
33 | relayd_trace_format& trace_format) | |
34 | { | |
35 | int ret; | |
36 | struct lttcomm_relayd_create_session_2_15 header; | |
37 | size_t header_len, received_names_size, offset; | |
38 | struct lttng_buffer_view session_name_view; | |
39 | struct lttng_buffer_view hostname_view; | |
40 | struct lttng_buffer_view base_path_view; | |
41 | ||
42 | header_len = sizeof(header); | |
43 | ||
44 | if (payload->size < header_len) { | |
45 | ERR("Unexpected payload size in \"cmd_create_session_2_15\": expected >= %zu bytes, got %zu bytes", | |
46 | header_len, payload->size); | |
47 | ret = -1; | |
48 | goto error; | |
49 | } | |
50 | memcpy(&header, payload->data, header_len); | |
51 | ||
52 | header.session_name_len = be32toh(header.session_name_len); | |
53 | header.hostname_len = be32toh(header.hostname_len); | |
54 | header.base_path_len = be32toh(header.base_path_len); | |
55 | header.live_timer = be32toh(header.live_timer); | |
56 | header.current_chunk_id.value = be64toh(header.current_chunk_id.value); | |
57 | header.current_chunk_id.is_set = !!header.current_chunk_id.is_set; | |
58 | header.creation_time = be64toh(header.creation_time); | |
59 | header.session_id = be64toh(header.session_id); | |
60 | ||
61 | std::copy(std::begin(header.sessiond_uuid), std::end(header.sessiond_uuid), | |
62 | sessiond_uuid.begin()); | |
63 | ||
64 | received_names_size = header.session_name_len + header.hostname_len + header.base_path_len; | |
65 | if (payload->size < header_len + received_names_size) { | |
66 | ERR("Unexpected payload size in \"cmd_create_session_2_15\": expected >= %zu bytes, got %zu bytes", | |
67 | header_len + received_names_size, payload->size); | |
68 | ret = -1; | |
69 | goto error; | |
70 | } | |
71 | ||
72 | /* Validate length against defined constant. */ | |
73 | if (header.session_name_len > LTTNG_NAME_MAX) { | |
74 | ret = -ENAMETOOLONG; | |
75 | ERR("Length of session name (%" PRIu32 | |
76 | " bytes) received in create_session command exceeds maximum length (%d bytes)", | |
77 | header.session_name_len, LTTNG_NAME_MAX); | |
78 | goto error; | |
79 | } else if (header.session_name_len == 0) { | |
80 | ret = -EINVAL; | |
81 | ERR("Illegal session name length of 0 received"); | |
82 | goto error; | |
83 | } | |
84 | if (header.hostname_len > LTTNG_HOST_NAME_MAX) { | |
85 | ret = -ENAMETOOLONG; | |
86 | ERR("Length of hostname (%" PRIu32 | |
87 | " bytes) received in create_session command exceeds maximum length (%d bytes)", | |
88 | header.hostname_len, LTTNG_HOST_NAME_MAX); | |
89 | goto error; | |
90 | } | |
91 | if (header.base_path_len > LTTNG_PATH_MAX) { | |
92 | ret = -ENAMETOOLONG; | |
93 | ERR("Length of base_path (%" PRIu32 | |
94 | " bytes) received in create_session command exceeds maximum length (%d bytes)", | |
95 | header.base_path_len, PATH_MAX); | |
96 | goto error; | |
97 | } | |
98 | ||
99 | offset = header_len; | |
100 | session_name_view = lttng_buffer_view_from_view(payload, offset, header.session_name_len); | |
101 | if (!lttng_buffer_view_is_valid(&session_name_view)) { | |
102 | ERR("Invalid payload in \"cmd_create_session_2_15\": buffer too short to contain session name"); | |
103 | ret = -1; | |
104 | goto error; | |
105 | } | |
106 | ||
107 | offset += header.session_name_len; | |
108 | hostname_view = lttng_buffer_view_from_view(payload, offset, header.hostname_len); | |
109 | if (!lttng_buffer_view_is_valid(&hostname_view)) { | |
110 | ERR("Invalid payload in \"cmd_create_session_2_15\": buffer too short to contain hostname"); | |
111 | ret = -1; | |
112 | goto error; | |
113 | } | |
114 | ||
115 | offset += header.hostname_len; | |
116 | base_path_view = lttng_buffer_view_from_view(payload, offset, header.base_path_len); | |
117 | if (header.base_path_len > 0 && !lttng_buffer_view_is_valid(&base_path_view)) { | |
118 | ERR("Invalid payload in \"cmd_create_session_2_15\": buffer too short to contain base path"); | |
119 | ret = -1; | |
120 | goto error; | |
121 | } | |
122 | ||
123 | /* Validate that names are NULL terminated. */ | |
124 | if (session_name_view.data[session_name_view.size - 1] != '\0') { | |
125 | ERR("cmd_create_session_2_15 session_name is invalid (not NULL terminated)"); | |
126 | ret = -1; | |
127 | goto error; | |
128 | } | |
129 | ||
130 | if (hostname_view.data[hostname_view.size - 1] != '\0') { | |
131 | ERR("cmd_create_session_2_15 hostname is invalid (not NULL terminated)"); | |
132 | ret = -1; | |
133 | goto error; | |
134 | } | |
135 | ||
136 | if (base_path_view.size != 0 && base_path_view.data[base_path_view.size - 1] != '\0') { | |
137 | ERR("cmd_create_session_2_15 base_path is invalid (not NULL terminated)"); | |
138 | ret = -1; | |
139 | goto error; | |
140 | } | |
141 | ||
142 | /* | |
143 | * Length and null-termination check are already performed. | |
144 | * LTTNG_NAME_MAX, LTTNG_HOST_NAME_MAX, and LTTNG_PATH_MAX max sizes are | |
145 | * expected. | |
146 | */ | |
147 | strcpy(session_name, session_name_view.data); | |
148 | strcpy(hostname, hostname_view.data); | |
149 | strcpy(base_path, base_path_view.size ? base_path_view.data : ""); | |
150 | ||
151 | *live_timer = header.live_timer; | |
152 | *snapshot = !!header.snapshot; | |
153 | *current_chunk_id = header.current_chunk_id.value; | |
154 | *has_current_chunk = header.current_chunk_id.is_set; | |
155 | *creation_time = (time_t) header.creation_time; | |
156 | *session_name_contains_creation_time = header.session_name_contains_creation_time; | |
157 | *id_sessiond = header.session_id; | |
158 | trace_format = static_cast<enum relayd_trace_format>(header.trace_format); | |
159 | ||
160 | ret = 0; | |
161 | ||
162 | error: | |
163 | return ret; | |
164 | } |