Fix: lttng_trace_archive_location_serialize is called on freed memory
[lttng-tools.git] / src / common / location.c
1 /*
2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <lttng/location-internal.h>
9 #include <common/macros.h>
10 #include <stdlib.h>
11 #include <common/error.h>
12
13 static
14 struct lttng_trace_archive_location *lttng_trace_archive_location_create(
15 enum lttng_trace_archive_location_type type)
16 {
17 struct lttng_trace_archive_location *location;
18
19 location = zmalloc(sizeof(*location));
20 if (!location) {
21 goto end;
22 }
23
24 urcu_ref_init(&location->ref);
25 location->type = type;
26 end:
27 return location;
28 }
29
30 static
31 void trace_archive_location_destroy_ref(struct urcu_ref *ref)
32 {
33 struct lttng_trace_archive_location *location =
34 container_of(ref, struct lttng_trace_archive_location, ref);
35
36 switch (location->type) {
37 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
38 free(location->types.local.absolute_path);
39 break;
40 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY:
41 free(location->types.relay.host);
42 free(location->types.relay.relative_path);
43 break;
44 default:
45 abort();
46 }
47
48 free(location);
49 }
50
51 LTTNG_HIDDEN
52 void lttng_trace_archive_location_get(struct lttng_trace_archive_location *location)
53 {
54 urcu_ref_get(&location->ref);
55 }
56
57 LTTNG_HIDDEN
58 void lttng_trace_archive_location_put(struct lttng_trace_archive_location *location)
59 {
60 if (!location) {
61 return;
62 }
63
64 urcu_ref_put(&location->ref, trace_archive_location_destroy_ref);
65 }
66
67 LTTNG_HIDDEN
68 struct lttng_trace_archive_location *lttng_trace_archive_location_local_create(
69 const char *absolute_path)
70 {
71 struct lttng_trace_archive_location *location = NULL;
72
73 if (!absolute_path) {
74 goto end;
75 }
76
77 location = lttng_trace_archive_location_create(
78 LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL);
79 if (!location) {
80 goto end;
81 }
82
83 location->types.local.absolute_path = strdup(absolute_path);
84 if (!location->types.local.absolute_path) {
85 goto error;
86 }
87
88 end:
89 return location;
90 error:
91 lttng_trace_archive_location_put(location);
92 return NULL;
93 }
94
95 LTTNG_HIDDEN
96 struct lttng_trace_archive_location *lttng_trace_archive_location_relay_create(
97 const char *host,
98 enum lttng_trace_archive_location_relay_protocol_type protocol,
99 uint16_t control_port, uint16_t data_port,
100 const char *relative_path)
101 {
102 struct lttng_trace_archive_location *location = NULL;
103
104 if (!host || !relative_path) {
105 goto end;
106 }
107
108 location = lttng_trace_archive_location_create(
109 LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY);
110 if (!location) {
111 goto end;
112 }
113
114 location->types.relay.host = strdup(host);
115 if (!location->types.relay.host) {
116 goto error;
117 }
118 location->types.relay.relative_path = strdup(relative_path);
119 if (!location->types.relay.relative_path) {
120 goto error;
121 }
122
123 location->types.relay.protocol = protocol;
124 location->types.relay.ports.control = control_port;
125 location->types.relay.ports.data = data_port;
126 end:
127 return location;
128 error:
129 lttng_trace_archive_location_put(location);
130 return NULL;
131 }
132
133 LTTNG_HIDDEN
134 ssize_t lttng_trace_archive_location_create_from_buffer(
135 const struct lttng_buffer_view *view,
136 struct lttng_trace_archive_location **location)
137 {
138 size_t offset = 0;
139 const struct lttng_trace_archive_location_comm *location_comm;
140 struct lttng_buffer_view location_comm_view;
141
142 location_comm_view = lttng_buffer_view_from_view(view, 0,
143 sizeof(*location_comm));
144 if (!location_comm_view.data) {
145 goto error;
146 }
147 offset += location_comm_view.size;
148 location_comm = (const struct lttng_trace_archive_location_comm *) view->data;
149
150 switch ((enum lttng_trace_archive_location_type) location_comm->type) {
151 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
152 {
153 const struct lttng_buffer_view absolute_path_view =
154 lttng_buffer_view_from_view(view, offset,
155 location_comm->types.local.absolute_path_len);
156
157 if (!absolute_path_view.data) {
158 goto error;
159 }
160 if (absolute_path_view.data[absolute_path_view.size - 1] != '\0') {
161 goto error;
162 }
163 offset += absolute_path_view.size;
164
165 *location = lttng_trace_archive_location_local_create(
166 absolute_path_view.data);
167 if (!*location) {
168 goto error;
169 }
170 break;
171 }
172 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY:
173 {
174 const struct lttng_buffer_view hostname_view =
175 lttng_buffer_view_from_view(view, offset,
176 location_comm->types.relay.hostname_len);
177 const struct lttng_buffer_view relative_path_view =
178 lttng_buffer_view_from_view(view,
179 offset + hostname_view.size,
180 location_comm->types.relay.relative_path_len);
181
182 if (!hostname_view.data || !relative_path_view.data) {
183 goto error;
184 }
185 if (hostname_view.data[hostname_view.size - 1] != '\0') {
186 goto error;
187 }
188 if (relative_path_view.data[relative_path_view.size - 1] != '\0') {
189 goto error;
190 }
191 offset += hostname_view.size + relative_path_view.size;
192
193 *location = lttng_trace_archive_location_relay_create(
194 hostname_view.data,
195 (enum lttng_trace_archive_location_relay_protocol_type) location_comm->types.relay.protocol,
196 location_comm->types.relay.ports.control,
197 location_comm->types.relay.ports.data,
198 relative_path_view.data);
199 if (!*location) {
200 goto error;
201 }
202 break;
203 }
204 default:
205 goto error;
206 }
207
208 return offset;
209 error:
210 return -1;
211 }
212
213 LTTNG_HIDDEN
214 ssize_t lttng_trace_archive_location_serialize(
215 const struct lttng_trace_archive_location *location,
216 struct lttng_dynamic_buffer *buffer)
217 {
218 int ret;
219 struct lttng_trace_archive_location_comm location_comm;
220
221 location_comm.type = (int8_t) location->type;
222
223 switch (location->type) {
224 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
225 location_comm.types.local.absolute_path_len =
226 strlen(location->types.local.absolute_path) + 1;
227 break;
228 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY:
229 location_comm.types.relay.hostname_len =
230 strlen(location->types.relay.host) + 1;
231 location_comm.types.relay.protocol =
232 (int8_t) location->types.relay.protocol;
233 location_comm.types.relay.ports.control =
234 location->types.relay.ports.control;
235 location_comm.types.relay.ports.data =
236 location->types.relay.ports.data;
237 location_comm.types.relay.relative_path_len =
238 strlen(location->types.relay.relative_path) + 1;
239 break;
240 default:
241 abort();
242 }
243
244 ret = lttng_dynamic_buffer_append(buffer, &location_comm,
245 sizeof(location_comm));
246 if (ret) {
247 goto error;
248 }
249
250 switch (location->type) {
251 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL:
252 ret = lttng_dynamic_buffer_append(buffer,
253 location->types.local.absolute_path,
254 location_comm.types.local.absolute_path_len);
255 if (ret) {
256 goto error;
257 }
258 break;
259 case LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY:
260 ret = lttng_dynamic_buffer_append(buffer,
261 location->types.relay.host,
262 location_comm.types.relay.hostname_len);
263 if (ret) {
264 goto error;
265 }
266 ret = lttng_dynamic_buffer_append(buffer,
267 location->types.relay.relative_path,
268 location_comm.types.relay.relative_path_len);
269 if (ret) {
270 goto error;
271 }
272 break;
273 default:
274 abort();
275 }
276
277 return 0;
278 error:
279 return -1;
280 }
281
282 enum lttng_trace_archive_location_type lttng_trace_archive_location_get_type(
283 const struct lttng_trace_archive_location *location)
284 {
285 enum lttng_trace_archive_location_type type;
286
287 if (!location) {
288 type = LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_UNKNOWN;
289 goto end;
290 }
291
292 type = location->type;
293 end:
294 return type;
295 }
296
297 enum lttng_trace_archive_location_status
298 lttng_trace_archive_location_local_get_absolute_path(
299 const struct lttng_trace_archive_location *location,
300 const char **absolute_path)
301 {
302 enum lttng_trace_archive_location_status status =
303 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
304
305 if (!location || !absolute_path ||
306 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL) {
307 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
308 goto end;
309 }
310
311 *absolute_path = location->types.local.absolute_path;
312 end:
313 return status;
314 }
315
316 enum lttng_trace_archive_location_status
317 lttng_trace_archive_location_relay_get_host(
318 const struct lttng_trace_archive_location *location,
319 const char **relay_host)
320 {
321 enum lttng_trace_archive_location_status status =
322 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
323
324 if (!location || !relay_host ||
325 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY) {
326 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
327 goto end;
328 }
329
330 *relay_host = location->types.relay.host;
331 end:
332 return status;
333 }
334
335 enum lttng_trace_archive_location_status
336 lttng_trace_archive_location_relay_get_relative_path(
337 const struct lttng_trace_archive_location *location,
338 const char **relative_path)
339 {
340 enum lttng_trace_archive_location_status status =
341 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
342
343 if (!location || !relative_path ||
344 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY) {
345 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
346 goto end;
347 }
348
349 *relative_path = location->types.relay.relative_path;
350 end:
351 return status;
352 }
353
354 enum lttng_trace_archive_location_status
355 lttng_trace_archive_location_relay_get_control_port(
356 const struct lttng_trace_archive_location *location,
357 uint16_t *control_port)
358 {
359 enum lttng_trace_archive_location_status status =
360 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
361
362 if (!location || !control_port ||
363 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY) {
364 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
365 goto end;
366 }
367
368 *control_port = location->types.relay.ports.control;
369 end:
370 return status;
371 }
372
373 enum lttng_trace_archive_location_status
374 lttng_trace_archive_location_relay_get_data_port(
375 const struct lttng_trace_archive_location *location,
376 uint16_t *data_port)
377 {
378 enum lttng_trace_archive_location_status status =
379 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
380
381 if (!location || !data_port ||
382 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY) {
383 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
384 goto end;
385 }
386
387 *data_port = location->types.relay.ports.data;
388 end:
389 return status;
390 }
391
392 enum lttng_trace_archive_location_status
393 lttng_trace_archive_location_relay_get_protocol_type(
394 const struct lttng_trace_archive_location *location,
395 enum lttng_trace_archive_location_relay_protocol_type *protocol)
396 {
397 enum lttng_trace_archive_location_status status =
398 LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK;
399
400 if (!location || !protocol ||
401 location->type != LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY) {
402 status = LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_INVALID;
403 goto end;
404 }
405
406 *protocol = location->types.relay.protocol;
407 end:
408 return status;
409 }
This page took 0.039392 seconds and 5 git commands to generate.