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