liblttng-ctl: use export list to define exported symbols
[lttng-tools.git] / src / common / sessiond-comm / sessiond-comm.c
CommitLineData
826d496d 1/*
ab5be9fa
MJ
2 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
fac6795d 6 *
fac6795d
DG
7 */
8
6c1c0768 9#define _LGPL_SOURCE
fac6795d
DG
10#include <limits.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
fac6795d
DG
14#include <sys/stat.h>
15#include <sys/types.h>
fac6795d 16#include <unistd.h>
2288467f 17#include <inttypes.h>
fac6795d 18
90e535ef 19#include <common/common.h>
edf4b93e 20#include <common/compat/errno.h>
990570ed 21
10a8a223 22#include "sessiond-comm.h"
fac6795d 23
6364a07a 24/* For Unix socket */
2038dd6c 25#include <common/unix.h>
6364a07a
DG
26/* For Inet socket */
27#include "inet.h"
28/* For Inet6 socket */
29#include "inet6.h"
30
554831e7
MD
31#define NETWORK_TIMEOUT_ENV "LTTNG_NETWORK_SOCKET_TIMEOUT"
32
32dd26fb 33static struct lttcomm_net_family net_families[] = {
6364a07a
DG
34 { LTTCOMM_INET, lttcomm_create_inet_sock },
35 { LTTCOMM_INET6, lttcomm_create_inet6_sock },
36};
37
fac6795d
DG
38/*
39 * Human readable error message.
40 */
41static const char *lttcomm_readable_code[] = {
f73fabfd
DG
42 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_COMMAND_SOCK_READY) ] = "consumerd command socket ready",
43 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_SUCCESS_RECV_FD) ] = "consumerd success on receiving fds",
44 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_ERROR_RECV_FD) ] = "consumerd error on receiving fds",
45 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_ERROR_RECV_CMD) ] = "consumerd error on receiving command",
46 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_POLL_ERROR) ] = "consumerd error in polling thread",
47 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_POLL_NVAL) ] = "consumerd polling on closed fd",
48 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_POLL_HUP) ] = "consumerd all fd hung up",
49 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_EXIT_SUCCESS) ] = "consumerd exiting normally",
50 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_EXIT_FAILURE) ] = "consumerd exiting on error",
51 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_OUTFD_ERROR) ] = "consumerd error opening the tracefile",
52 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_SPLICE_EBADF) ] = "consumerd splice EBADF",
53 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_SPLICE_EINVAL) ] = "consumerd splice EINVAL",
54 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_SPLICE_ENOMEM) ] = "consumerd splice ENOMEM",
55 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_SPLICE_ESPIPE) ] = "consumerd splice ESPIPE",
40727660
MD
56 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_ENOMEM) ] = "Consumer is out of memory",
57 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_ERROR_METADATA) ] = "Error with metadata",
58 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_FATAL) ] = "Fatal error",
618a6a28 59 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_RELAYD_FAIL) ] = "Error on remote relayd",
80e327fa 60
f73fabfd
DG
61 /* Last element */
62 [ LTTCOMM_ERR_INDEX(LTTCOMM_NR) ] = "Unknown error code"
fac6795d
DG
63};
64
554831e7
MD
65static unsigned long network_timeout;
66
fac6795d 67/*
917216f6
DG
68 * Return ptr to string representing a human readable error code from the
69 * lttcomm_return_code enum.
fac6795d 70 *
917216f6 71 * These code MUST be negative in other to treat that as an error value.
fac6795d
DG
72 */
73const char *lttcomm_get_readable_code(enum lttcomm_return_code code)
74{
f73fabfd 75 code = -code;
fac6795d 76
c617c0c6 77 if (code < LTTCOMM_CONSUMERD_COMMAND_SOCK_READY || code > LTTCOMM_NR) {
f73fabfd 78 code = LTTCOMM_NR;
fac6795d
DG
79 }
80
f73fabfd 81 return lttcomm_readable_code[LTTCOMM_ERR_INDEX(code)];
fac6795d 82}
6364a07a
DG
83
84/*
de5e9086
DG
85 * Create socket from an already allocated lttcomm socket structure and init
86 * sockaddr in the lttcomm sock.
6364a07a 87 */
de5e9086 88int lttcomm_create_sock(struct lttcomm_sock *sock)
6364a07a 89{
de5e9086 90 int ret, _sock_type, _sock_proto, domain;
6364a07a 91
a0377dfe 92 LTTNG_ASSERT(sock);
de5e9086
DG
93
94 domain = sock->sockaddr.type;
95 if (domain != LTTCOMM_INET && domain != LTTCOMM_INET6) {
96 ERR("Create socket of unknown domain %d", domain);
97 ret = -1;
98 goto error;
6364a07a
DG
99 }
100
de5e9086
DG
101 switch (sock->proto) {
102 case LTTCOMM_SOCK_UDP:
103 _sock_type = SOCK_DGRAM;
104 _sock_proto = IPPROTO_UDP;
105 break;
106 case LTTCOMM_SOCK_TCP:
107 _sock_type = SOCK_STREAM;
108 _sock_proto = IPPROTO_TCP;
109 break;
110 default:
111 ret = -1;
112 goto error;
113 }
6364a07a 114
de5e9086
DG
115 ret = net_families[domain].create(sock, _sock_type, _sock_proto);
116 if (ret < 0) {
117 goto error;
118 }
119
120error:
121 return ret;
6364a07a
DG
122}
123
124/*
de5e9086 125 * Return allocated lttcomm socket structure.
6364a07a 126 */
de5e9086 127struct lttcomm_sock *lttcomm_alloc_sock(enum lttcomm_sock_proto proto)
6364a07a 128{
de5e9086 129 struct lttcomm_sock *sock;
6364a07a 130
de5e9086
DG
131 sock = zmalloc(sizeof(struct lttcomm_sock));
132 if (sock == NULL) {
133 PERROR("zmalloc create sock");
134 goto end;
6364a07a
DG
135 }
136
137 sock->proto = proto;
de5e9086 138 sock->fd = -1;
6364a07a 139
de5e9086
DG
140end:
141 return sock;
6364a07a
DG
142}
143
144/*
de5e9086
DG
145 * Return an allocated lttcomm socket structure and copy src content into
146 * the newly created socket.
147 *
148 * This is mostly useful when lttcomm_sock are passed between process where the
149 * fd and ops have to be changed within the correct address space.
6364a07a 150 */
de5e9086 151struct lttcomm_sock *lttcomm_alloc_copy_sock(struct lttcomm_sock *src)
6364a07a 152{
6364a07a
DG
153 struct lttcomm_sock *sock;
154
de5e9086 155 /* Safety net */
a0377dfe 156 LTTNG_ASSERT(src);
de5e9086
DG
157
158 sock = lttcomm_alloc_sock(src->proto);
6364a07a
DG
159 if (sock == NULL) {
160 goto alloc_error;
161 }
162
de5e9086 163 lttcomm_copy_sock(sock, src);
6364a07a 164
de5e9086 165alloc_error:
6364a07a 166 return sock;
de5e9086 167}
6364a07a 168
de5e9086
DG
169/*
170 * Create and copy socket from an allocated lttcomm socket structure.
171 *
172 * This is mostly useful when lttcomm_sock are passed between process where the
173 * fd and ops have to be changed within the correct address space.
174 */
175void lttcomm_copy_sock(struct lttcomm_sock *dst, struct lttcomm_sock *src)
176{
177 /* Safety net */
a0377dfe
FD
178 LTTNG_ASSERT(dst);
179 LTTNG_ASSERT(src);
de5e9086
DG
180
181 dst->proto = src->proto;
182 dst->fd = src->fd;
183 dst->ops = src->ops;
184 /* Copy sockaddr information from original socket */
185 memcpy(&dst->sockaddr, &src->sockaddr, sizeof(dst->sockaddr));
6364a07a
DG
186}
187
188/*
189 * Init IPv4 sockaddr structure.
190 */
191int lttcomm_init_inet_sockaddr(struct lttcomm_sockaddr *sockaddr,
192 const char *ip, unsigned int port)
193{
194 int ret;
195
a0377dfe
FD
196 LTTNG_ASSERT(sockaddr);
197 LTTNG_ASSERT(ip);
198 LTTNG_ASSERT(port > 0 && port <= 65535);
6364a07a
DG
199
200 memset(sockaddr, 0, sizeof(struct lttcomm_sockaddr));
201
202 sockaddr->type = LTTCOMM_INET;
203 sockaddr->addr.sin.sin_family = AF_INET;
204 sockaddr->addr.sin.sin_port = htons(port);
205 ret = inet_pton(sockaddr->addr.sin.sin_family, ip,
206 &sockaddr->addr.sin.sin_addr);
207 if (ret < 1) {
208 ret = -1;
de5e9086 209 ERR("%s with port %d: unrecognized IPv4 address", ip, port);
6364a07a
DG
210 goto error;
211 }
212 memset(sockaddr->addr.sin.sin_zero, 0, sizeof(sockaddr->addr.sin.sin_zero));
213
214error:
215 return ret;
216}
217
218/*
219 * Init IPv6 sockaddr structure.
220 */
221int lttcomm_init_inet6_sockaddr(struct lttcomm_sockaddr *sockaddr,
222 const char *ip, unsigned int port)
223{
224 int ret;
225
a0377dfe
FD
226 LTTNG_ASSERT(sockaddr);
227 LTTNG_ASSERT(ip);
228 LTTNG_ASSERT(port > 0 && port <= 65535);
6364a07a
DG
229
230 memset(sockaddr, 0, sizeof(struct lttcomm_sockaddr));
231
232 sockaddr->type = LTTCOMM_INET6;
233 sockaddr->addr.sin6.sin6_family = AF_INET6;
234 sockaddr->addr.sin6.sin6_port = htons(port);
235 ret = inet_pton(sockaddr->addr.sin6.sin6_family, ip,
236 &sockaddr->addr.sin6.sin6_addr);
237 if (ret < 1) {
238 ret = -1;
239 goto error;
240 }
241
242error:
243 return ret;
244}
de5e9086
DG
245
246/*
247 * Return allocated lttcomm socket structure from lttng URI.
248 */
249struct lttcomm_sock *lttcomm_alloc_sock_from_uri(struct lttng_uri *uri)
250{
251 int ret;
252 int _sock_proto;
253 struct lttcomm_sock *sock = NULL;
254
255 /* Safety net */
a0377dfe 256 LTTNG_ASSERT(uri);
de5e9086
DG
257
258 /* Check URI protocol */
259 if (uri->proto == LTTNG_TCP) {
260 _sock_proto = LTTCOMM_SOCK_TCP;
261 } else {
262 ERR("Relayd invalid URI proto: %d", uri->proto);
263 goto alloc_error;
264 }
265
266 sock = lttcomm_alloc_sock(_sock_proto);
267 if (sock == NULL) {
268 goto alloc_error;
269 }
270
271 /* Check destination type */
272 if (uri->dtype == LTTNG_DST_IPV4) {
273 ret = lttcomm_init_inet_sockaddr(&sock->sockaddr, uri->dst.ipv4,
274 uri->port);
275 if (ret < 0) {
276 goto error;
277 }
278 } else if (uri->dtype == LTTNG_DST_IPV6) {
279 ret = lttcomm_init_inet6_sockaddr(&sock->sockaddr, uri->dst.ipv6,
280 uri->port);
281 if (ret < 0) {
282 goto error;
283 }
284 } else {
285 /* Command URI is invalid */
286 ERR("Relayd invalid URI dst type: %d", uri->dtype);
287 goto error;
288 }
289
290 return sock;
291
292error:
293 lttcomm_destroy_sock(sock);
294alloc_error:
295 return NULL;
296}
297
298/*
299 * Destroy and free lttcomm socket.
300 */
301void lttcomm_destroy_sock(struct lttcomm_sock *sock)
302{
0e428499 303 free(sock);
de5e9086 304}
6151a90f
JD
305
306/*
307 * Allocate and return a relayd socket object using a given URI to initialize
308 * it and the major/minor version of the supported protocol.
309 *
310 * On error, NULL is returned.
311 */
312struct lttcomm_relayd_sock *lttcomm_alloc_relayd_sock(struct lttng_uri *uri,
313 uint32_t major, uint32_t minor)
314{
315 int ret;
316 struct lttcomm_sock *tmp_sock = NULL;
317 struct lttcomm_relayd_sock *rsock = NULL;
318
a0377dfe 319 LTTNG_ASSERT(uri);
6151a90f
JD
320
321 rsock = zmalloc(sizeof(*rsock));
322 if (!rsock) {
323 PERROR("zmalloc relayd sock");
324 goto error;
325 }
326
327 /* Allocate socket object from URI */
328 tmp_sock = lttcomm_alloc_sock_from_uri(uri);
329 if (tmp_sock == NULL) {
330 goto error_free;
331 }
332
333 /*
334 * Create socket object which basically sets the ops according to the
335 * socket protocol.
336 */
337 lttcomm_copy_sock(&rsock->sock, tmp_sock);
338 /* Temporary socket pointer not needed anymore. */
339 lttcomm_destroy_sock(tmp_sock);
340 ret = lttcomm_create_sock(&rsock->sock);
341 if (ret < 0) {
342 goto error_free;
343 }
344
345 rsock->major = major;
346 rsock->minor = minor;
347
348 return rsock;
349
350error_free:
351 free(rsock);
352error:
353 return NULL;
354}
554831e7 355
783a3b9a
MD
356/*
357 * Set socket receiving timeout.
358 */
783a3b9a
MD
359int lttcomm_setsockopt_rcv_timeout(int sock, unsigned int msec)
360{
361 int ret;
362 struct timeval tv;
363
364 tv.tv_sec = msec / 1000;
365 tv.tv_usec = (msec % 1000) * 1000;
366
367 ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
368 if (ret < 0) {
369 PERROR("setsockopt SO_RCVTIMEO");
370 }
371
372 return ret;
373}
374
375/*
376 * Set socket sending timeout.
377 */
783a3b9a
MD
378int lttcomm_setsockopt_snd_timeout(int sock, unsigned int msec)
379{
380 int ret;
381 struct timeval tv;
382
383 tv.tv_sec = msec / 1000;
384 tv.tv_usec = (msec % 1000) * 1000;
385
386 ret = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
387 if (ret < 0) {
388 PERROR("setsockopt SO_SNDTIMEO");
389 }
390
391 return ret;
392}
393
2288467f
JG
394int lttcomm_sock_get_port(const struct lttcomm_sock *sock, uint16_t *port)
395{
a0377dfe
FD
396 LTTNG_ASSERT(sock);
397 LTTNG_ASSERT(port);
398 LTTNG_ASSERT(sock->sockaddr.type == LTTCOMM_INET ||
2288467f 399 sock->sockaddr.type == LTTCOMM_INET6);
a0377dfe 400 LTTNG_ASSERT(sock->proto == LTTCOMM_SOCK_TCP ||
2288467f
JG
401 sock->proto == LTTCOMM_SOCK_UDP);
402
403 switch (sock->sockaddr.type) {
404 case LTTCOMM_INET:
405 *port = ntohs(sock->sockaddr.addr.sin.sin_port);
406 break;
407 case LTTCOMM_INET6:
408 *port = ntohs(sock->sockaddr.addr.sin6.sin6_port);
409 break;
410 default:
411 abort();
412 }
413
414 return 0;
415}
416
2288467f
JG
417int lttcomm_sock_set_port(struct lttcomm_sock *sock, uint16_t port)
418{
a0377dfe
FD
419 LTTNG_ASSERT(sock);
420 LTTNG_ASSERT(sock->sockaddr.type == LTTCOMM_INET ||
2288467f 421 sock->sockaddr.type == LTTCOMM_INET6);
a0377dfe 422 LTTNG_ASSERT(sock->proto == LTTCOMM_SOCK_TCP ||
2288467f
JG
423 sock->proto == LTTCOMM_SOCK_UDP);
424
425 switch (sock->sockaddr.type) {
426 case LTTCOMM_INET:
427 sock->sockaddr.addr.sin.sin_port = htons(port);
428 break;
429 case LTTCOMM_INET6:
430 sock->sockaddr.addr.sin6.sin6_port = htons(port);
431 break;
432 default:
433 abort();
434 }
435
436 return 0;
437}
438
554831e7
MD
439void lttcomm_init(void)
440{
441 const char *env;
442
443 env = getenv(NETWORK_TIMEOUT_ENV);
444 if (env) {
445 long timeout;
446
447 errno = 0;
448 timeout = strtol(env, NULL, 0);
449 if (errno != 0 || timeout < -1L) {
450 PERROR("Network timeout");
451 } else {
452 if (timeout > 0) {
453 network_timeout = timeout;
454 }
455 }
456 }
457}
458
554831e7
MD
459unsigned long lttcomm_get_network_timeout(void)
460{
461 return network_timeout;
462}
This page took 0.085123 seconds and 4 git commands to generate.