2 * Copyright (C) 2011 EfficiOS Inc.
3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * SPDX-License-Identifier: GPL-2.0-only
9 #include <sys/socket.h>
11 #include "sessiond-comm.hpp"
13 #include <common/common.hpp>
14 #include <common/compat/errno.hpp>
22 #include <sys/types.h>
26 #include <common/unix.hpp>
29 /* For Inet6 socket */
32 #define NETWORK_TIMEOUT_ENV "LTTNG_NETWORK_SOCKET_TIMEOUT"
34 static struct lttcomm_net_family net_families
[] = {
35 { LTTCOMM_INET
, lttcomm_create_inet_sock
},
36 { LTTCOMM_INET6
, lttcomm_create_inet6_sock
},
40 * Human readable error message.
42 static const char *lttcomm_return_code_str(lttcomm_return_code code
)
45 case LTTCOMM_CONSUMERD_SUCCESS
:
46 return "consumerd success";
47 case LTTCOMM_CONSUMERD_COMMAND_SOCK_READY
:
48 return "consumerd command socket ready";
49 case LTTCOMM_CONSUMERD_SUCCESS_RECV_FD
:
50 return "consumerd success on receiving fds";
51 case LTTCOMM_CONSUMERD_ERROR_RECV_FD
:
52 return "consumerd error on receiving fds";
53 case LTTCOMM_CONSUMERD_ERROR_RECV_CMD
:
54 return "consumerd error on receiving command";
55 case LTTCOMM_CONSUMERD_POLL_ERROR
:
56 return "consumerd error in polling thread";
57 case LTTCOMM_CONSUMERD_POLL_NVAL
:
58 return "consumerd polling on closed fd";
59 case LTTCOMM_CONSUMERD_POLL_HUP
:
60 return "consumerd all fd hung up";
61 case LTTCOMM_CONSUMERD_EXIT_SUCCESS
:
62 return "consumerd exiting normally";
63 case LTTCOMM_CONSUMERD_EXIT_FAILURE
:
64 return "consumerd exiting on error";
65 case LTTCOMM_CONSUMERD_OUTFD_ERROR
:
66 return "consumerd error opening the tracefile";
67 case LTTCOMM_CONSUMERD_SPLICE_EBADF
:
68 return "consumerd splice EBADF";
69 case LTTCOMM_CONSUMERD_SPLICE_EINVAL
:
70 return "consumerd splice EINVAL";
71 case LTTCOMM_CONSUMERD_SPLICE_ENOMEM
:
72 return "consumerd splice ENOMEM";
73 case LTTCOMM_CONSUMERD_SPLICE_ESPIPE
:
74 return "consumerd splice ESPIPE";
75 case LTTCOMM_CONSUMERD_ENOMEM
:
76 return "consumerd is out of memory";
77 case LTTCOMM_CONSUMERD_ERROR_METADATA
:
78 return "consumerd error with metadata";
79 case LTTCOMM_CONSUMERD_FATAL
:
80 return "consumerd fatal error";
81 case LTTCOMM_CONSUMERD_RELAYD_FAIL
:
82 return "consumerd error on remote relayd";
83 case LTTCOMM_CONSUMERD_CHANNEL_FAIL
:
84 return "consumerd channel creation fail";
85 case LTTCOMM_CONSUMERD_CHAN_NOT_FOUND
:
86 return "consumerd channel not found";
87 case LTTCOMM_CONSUMERD_ALREADY_SET
:
88 return "consumerd resource already set";
89 case LTTCOMM_CONSUMERD_ROTATION_FAIL
:
90 return "consumerd rotation failed";
91 case LTTCOMM_CONSUMERD_SNAPSHOT_FAILED
:
92 return "consumerd snapshot has failed";
93 case LTTCOMM_CONSUMERD_CREATE_TRACE_CHUNK_FAILED
:
94 return "consumerd trace chunk creation failed";
95 case LTTCOMM_CONSUMERD_CLOSE_TRACE_CHUNK_FAILED
:
96 return "consumerd trace chunk closing failed";
97 case LTTCOMM_CONSUMERD_INVALID_PARAMETERS
:
98 return "consumerd invalid parameters";
99 case LTTCOMM_CONSUMERD_TRACE_CHUNK_EXISTS_LOCAL
:
100 return "consumerd trace chunk exists on consumer daemon";
101 case LTTCOMM_CONSUMERD_TRACE_CHUNK_EXISTS_REMOTE
:
102 return "consumedd trace chunk exists on relay daemon";
103 case LTTCOMM_CONSUMERD_UNKNOWN_TRACE_CHUNK
:
104 return "consumerd unknown trace chunk";
105 case LTTCOMM_CONSUMERD_RELAYD_CLEAR_DISALLOWED
:
106 return "consumed relayd does not accept clear command";
107 case LTTCOMM_CONSUMERD_UNKNOWN_ERROR
:
108 return "consumerd unknown error";
116 static unsigned long network_timeout
;
119 * Return ptr to string representing a human readable error code from the
120 * lttcomm_return_code enum.
122 * These code MUST be negative in other to treat that as an error value.
124 const char *lttcomm_get_readable_code(enum lttcomm_return_code code
)
126 code
= (lttcomm_return_code
) -code
;
128 if (code
!= LTTCOMM_CONSUMERD_SUCCESS
&&
129 !(code
>= LTTCOMM_CONSUMERD_COMMAND_SOCK_READY
&& code
< LTTCOMM_NR
)) {
130 code
= LTTCOMM_CONSUMERD_UNKNOWN_ERROR
;
133 return lttcomm_return_code_str(code
);
137 * Create socket from an already allocated lttcomm socket structure and init
138 * sockaddr in the lttcomm sock.
140 int lttcomm_create_sock(struct lttcomm_sock
*sock
)
142 int ret
, _sock_type
, _sock_proto
, domain
;
146 domain
= sock
->sockaddr
.type
;
147 if (domain
!= LTTCOMM_INET
&& domain
!= LTTCOMM_INET6
) {
148 ERR("Create socket of unknown domain %d", domain
);
153 switch (sock
->proto
) {
154 case LTTCOMM_SOCK_UDP
:
155 _sock_type
= SOCK_DGRAM
;
156 _sock_proto
= IPPROTO_UDP
;
158 case LTTCOMM_SOCK_TCP
:
159 _sock_type
= SOCK_STREAM
;
160 _sock_proto
= IPPROTO_TCP
;
167 ret
= net_families
[domain
].create(sock
, _sock_type
, _sock_proto
);
177 * Return allocated lttcomm socket structure.
179 struct lttcomm_sock
*lttcomm_alloc_sock(enum lttcomm_sock_proto proto
)
181 struct lttcomm_sock
*sock
= zmalloc
<lttcomm_sock
>();
183 if (sock
== nullptr) {
184 PERROR("zmalloc create sock");
196 * Return an allocated lttcomm socket structure and copy src content into
197 * the newly created socket.
199 * This is mostly useful when lttcomm_sock are passed between process where the
200 * fd and ops have to be changed within the correct address space.
202 struct lttcomm_sock
*lttcomm_alloc_copy_sock(struct lttcomm_sock
*src
)
204 struct lttcomm_sock
*sock
;
209 sock
= lttcomm_alloc_sock(src
->proto
);
210 if (sock
== nullptr) {
214 lttcomm_copy_sock(sock
, src
);
221 * Create and copy socket from an allocated lttcomm socket structure.
223 * This is mostly useful when lttcomm_sock are passed between process where the
224 * fd and ops have to be changed within the correct address space.
226 void lttcomm_copy_sock(struct lttcomm_sock
*dst
, struct lttcomm_sock
*src
)
232 dst
->proto
= src
->proto
;
235 /* Copy sockaddr information from original socket */
236 memcpy(&dst
->sockaddr
, &src
->sockaddr
, sizeof(dst
->sockaddr
));
240 * Init IPv4 sockaddr structure.
242 int lttcomm_init_inet_sockaddr(struct lttcomm_sockaddr
*sockaddr
, const char *ip
, unsigned int port
)
246 LTTNG_ASSERT(sockaddr
);
248 LTTNG_ASSERT(port
> 0 && port
<= 65535);
250 memset(sockaddr
, 0, sizeof(struct lttcomm_sockaddr
));
252 sockaddr
->type
= LTTCOMM_INET
;
253 sockaddr
->addr
.sin
.sin_family
= AF_INET
;
254 sockaddr
->addr
.sin
.sin_port
= htons(port
);
255 ret
= inet_pton(sockaddr
->addr
.sin
.sin_family
, ip
, &sockaddr
->addr
.sin
.sin_addr
);
258 ERR("%s with port %d: unrecognized IPv4 address", ip
, port
);
261 memset(sockaddr
->addr
.sin
.sin_zero
, 0, sizeof(sockaddr
->addr
.sin
.sin_zero
));
268 * Init IPv6 sockaddr structure.
270 int lttcomm_init_inet6_sockaddr(struct lttcomm_sockaddr
*sockaddr
,
276 LTTNG_ASSERT(sockaddr
);
278 LTTNG_ASSERT(port
> 0 && port
<= 65535);
280 memset(sockaddr
, 0, sizeof(struct lttcomm_sockaddr
));
282 sockaddr
->type
= LTTCOMM_INET6
;
283 sockaddr
->addr
.sin6
.sin6_family
= AF_INET6
;
284 sockaddr
->addr
.sin6
.sin6_port
= htons(port
);
285 ret
= inet_pton(sockaddr
->addr
.sin6
.sin6_family
, ip
, &sockaddr
->addr
.sin6
.sin6_addr
);
296 * Return allocated lttcomm socket structure from lttng URI.
298 struct lttcomm_sock
*lttcomm_alloc_sock_from_uri(struct lttng_uri
*uri
)
302 struct lttcomm_sock
*sock
= nullptr;
307 /* Check URI protocol */
308 if (uri
->proto
== LTTNG_TCP
) {
309 _sock_proto
= LTTCOMM_SOCK_TCP
;
311 ERR("Relayd invalid URI proto: %d", uri
->proto
);
315 sock
= lttcomm_alloc_sock((lttcomm_sock_proto
) _sock_proto
);
316 if (sock
== nullptr) {
320 /* Check destination type */
321 if (uri
->dtype
== LTTNG_DST_IPV4
) {
322 ret
= lttcomm_init_inet_sockaddr(&sock
->sockaddr
, uri
->dst
.ipv4
, uri
->port
);
326 } else if (uri
->dtype
== LTTNG_DST_IPV6
) {
327 ret
= lttcomm_init_inet6_sockaddr(&sock
->sockaddr
, uri
->dst
.ipv6
, uri
->port
);
332 /* Command URI is invalid */
333 ERR("Relayd invalid URI dst type: %d", uri
->dtype
);
340 lttcomm_destroy_sock(sock
);
346 * Destroy and free lttcomm socket.
348 void lttcomm_destroy_sock(struct lttcomm_sock
*sock
)
354 * Allocate and return a relayd socket object using a given URI to initialize
355 * it and the major/minor version of the supported protocol.
357 * On error, NULL is returned.
359 struct lttcomm_relayd_sock
*
360 lttcomm_alloc_relayd_sock(struct lttng_uri
*uri
, uint32_t major
, uint32_t minor
)
363 struct lttcomm_sock
*tmp_sock
= nullptr;
364 struct lttcomm_relayd_sock
*rsock
= zmalloc
<lttcomm_relayd_sock
>();
369 PERROR("zmalloc relayd sock");
373 /* Allocate socket object from URI */
374 tmp_sock
= lttcomm_alloc_sock_from_uri(uri
);
375 if (tmp_sock
== nullptr) {
380 * Create socket object which basically sets the ops according to the
383 lttcomm_copy_sock(&rsock
->sock
, tmp_sock
);
384 /* Temporary socket pointer not needed anymore. */
385 lttcomm_destroy_sock(tmp_sock
);
386 ret
= lttcomm_create_sock(&rsock
->sock
);
391 rsock
->major
= major
;
392 rsock
->minor
= minor
;
403 * Set socket receiving timeout.
405 int lttcomm_setsockopt_rcv_timeout(int sock
, unsigned int msec
)
410 tv
.tv_sec
= msec
/ 1000;
411 tv
.tv_usec
= (msec
% 1000) * 1000;
413 ret
= setsockopt(sock
, SOL_SOCKET
, SO_RCVTIMEO
, &tv
, sizeof(tv
));
415 PERROR("setsockopt SO_RCVTIMEO");
422 * Set socket sending timeout.
424 int lttcomm_setsockopt_snd_timeout(int sock
, unsigned int msec
)
429 tv
.tv_sec
= msec
/ 1000;
430 tv
.tv_usec
= (msec
% 1000) * 1000;
432 ret
= setsockopt(sock
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
));
434 PERROR("setsockopt SO_SNDTIMEO");
440 int lttcomm_sock_get_port(const struct lttcomm_sock
*sock
, uint16_t *port
)
444 LTTNG_ASSERT(sock
->sockaddr
.type
== LTTCOMM_INET
|| sock
->sockaddr
.type
== LTTCOMM_INET6
);
445 LTTNG_ASSERT(sock
->proto
== LTTCOMM_SOCK_TCP
|| sock
->proto
== LTTCOMM_SOCK_UDP
);
447 switch (sock
->sockaddr
.type
) {
449 *port
= ntohs(sock
->sockaddr
.addr
.sin
.sin_port
);
452 *port
= ntohs(sock
->sockaddr
.addr
.sin6
.sin6_port
);
461 int lttcomm_sock_set_port(struct lttcomm_sock
*sock
, uint16_t port
)
464 LTTNG_ASSERT(sock
->sockaddr
.type
== LTTCOMM_INET
|| sock
->sockaddr
.type
== LTTCOMM_INET6
);
465 LTTNG_ASSERT(sock
->proto
== LTTCOMM_SOCK_TCP
|| sock
->proto
== LTTCOMM_SOCK_UDP
);
467 switch (sock
->sockaddr
.type
) {
469 sock
->sockaddr
.addr
.sin
.sin_port
= htons(port
);
472 sock
->sockaddr
.addr
.sin6
.sin6_port
= htons(port
);
485 env
= getenv(NETWORK_TIMEOUT_ENV
);
490 timeout
= strtol(env
, nullptr, 0);
491 if (errno
!= 0 || timeout
< -1L) {
492 PERROR("Network timeout");
495 network_timeout
= timeout
;
501 unsigned long lttcomm_get_network_timeout()
503 return network_timeout
;
507 * Only valid for an ipv4 and ipv6 bound socket that is already connected to its
510 int lttcomm_populate_sock_from_open_socket(struct lttcomm_sock
*sock
,
512 enum lttcomm_sock_proto protocol
)
515 socklen_t storage_len
;
516 struct sockaddr_storage storage
= {};
521 sock
->proto
= protocol
;
523 storage_len
= sizeof(storage
);
524 ret
= getpeername(fd
, (struct sockaddr
*) &storage
, &storage_len
);
526 ERR("Failed to get peer info for socket %d (errno: %d)", fd
, errno
);
531 if (storage_len
> sizeof(storage
)) {
532 ERR("Failed to get peer info for socket %d: storage size is too small", fd
);
537 switch (storage
.ss_family
) {
539 sock
->sockaddr
.type
= LTTCOMM_INET
;
540 memcpy(&sock
->sockaddr
.addr
, &storage
, sizeof(struct sockaddr_in
));
543 sock
->sockaddr
.type
= LTTCOMM_INET6
;
544 memcpy(&sock
->sockaddr
.addr
, &storage
, sizeof(struct sockaddr_in6
));
551 /* Create a valid socket object with a temporary fd. */
552 ret
= lttcomm_create_sock(sock
);
554 ERR("Failed to create temporary socket object");
559 /* Substitute the fd. */
560 if (sock
->ops
->close(sock
)) {