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>
16 #include <sys/types.h>
20 #include <common/common.hpp>
21 #include <common/compat/errno.hpp>
23 #include "sessiond-comm.hpp"
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.
43 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
>();
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
);
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
,
243 const char *ip
, unsigned int port
)
247 LTTNG_ASSERT(sockaddr
);
249 LTTNG_ASSERT(port
> 0 && port
<= 65535);
251 memset(sockaddr
, 0, sizeof(struct lttcomm_sockaddr
));
253 sockaddr
->type
= LTTCOMM_INET
;
254 sockaddr
->addr
.sin
.sin_family
= AF_INET
;
255 sockaddr
->addr
.sin
.sin_port
= htons(port
);
256 ret
= inet_pton(sockaddr
->addr
.sin
.sin_family
, ip
,
257 &sockaddr
->addr
.sin
.sin_addr
);
260 ERR("%s with port %d: unrecognized IPv4 address", ip
, port
);
263 memset(sockaddr
->addr
.sin
.sin_zero
, 0, sizeof(sockaddr
->addr
.sin
.sin_zero
));
270 * Init IPv6 sockaddr structure.
272 int lttcomm_init_inet6_sockaddr(struct lttcomm_sockaddr
*sockaddr
,
273 const char *ip
, unsigned int port
)
277 LTTNG_ASSERT(sockaddr
);
279 LTTNG_ASSERT(port
> 0 && port
<= 65535);
281 memset(sockaddr
, 0, sizeof(struct lttcomm_sockaddr
));
283 sockaddr
->type
= LTTCOMM_INET6
;
284 sockaddr
->addr
.sin6
.sin6_family
= AF_INET6
;
285 sockaddr
->addr
.sin6
.sin6_port
= htons(port
);
286 ret
= inet_pton(sockaddr
->addr
.sin6
.sin6_family
, ip
,
287 &sockaddr
->addr
.sin6
.sin6_addr
);
298 * Return allocated lttcomm socket structure from lttng URI.
300 struct lttcomm_sock
*lttcomm_alloc_sock_from_uri(struct lttng_uri
*uri
)
304 struct lttcomm_sock
*sock
= NULL
;
309 /* Check URI protocol */
310 if (uri
->proto
== LTTNG_TCP
) {
311 _sock_proto
= LTTCOMM_SOCK_TCP
;
313 ERR("Relayd invalid URI proto: %d", uri
->proto
);
317 sock
= lttcomm_alloc_sock((lttcomm_sock_proto
) _sock_proto
);
322 /* Check destination type */
323 if (uri
->dtype
== LTTNG_DST_IPV4
) {
324 ret
= lttcomm_init_inet_sockaddr(&sock
->sockaddr
, uri
->dst
.ipv4
,
329 } else if (uri
->dtype
== LTTNG_DST_IPV6
) {
330 ret
= lttcomm_init_inet6_sockaddr(&sock
->sockaddr
, uri
->dst
.ipv6
,
336 /* Command URI is invalid */
337 ERR("Relayd invalid URI dst type: %d", uri
->dtype
);
344 lttcomm_destroy_sock(sock
);
350 * Destroy and free lttcomm socket.
352 void lttcomm_destroy_sock(struct lttcomm_sock
*sock
)
358 * Allocate and return a relayd socket object using a given URI to initialize
359 * it and the major/minor version of the supported protocol.
361 * On error, NULL is returned.
363 struct lttcomm_relayd_sock
*lttcomm_alloc_relayd_sock(struct lttng_uri
*uri
,
364 uint32_t major
, uint32_t minor
)
367 struct lttcomm_sock
*tmp_sock
= NULL
;
368 struct lttcomm_relayd_sock
*rsock
= zmalloc
<lttcomm_relayd_sock
>();
373 PERROR("zmalloc relayd sock");
377 /* Allocate socket object from URI */
378 tmp_sock
= lttcomm_alloc_sock_from_uri(uri
);
379 if (tmp_sock
== NULL
) {
384 * Create socket object which basically sets the ops according to the
387 lttcomm_copy_sock(&rsock
->sock
, tmp_sock
);
388 /* Temporary socket pointer not needed anymore. */
389 lttcomm_destroy_sock(tmp_sock
);
390 ret
= lttcomm_create_sock(&rsock
->sock
);
395 rsock
->major
= major
;
396 rsock
->minor
= minor
;
407 * Set socket receiving timeout.
409 int lttcomm_setsockopt_rcv_timeout(int sock
, unsigned int msec
)
414 tv
.tv_sec
= msec
/ 1000;
415 tv
.tv_usec
= (msec
% 1000) * 1000;
417 ret
= setsockopt(sock
, SOL_SOCKET
, SO_RCVTIMEO
, &tv
, sizeof(tv
));
419 PERROR("setsockopt SO_RCVTIMEO");
426 * Set socket sending timeout.
428 int lttcomm_setsockopt_snd_timeout(int sock
, unsigned int msec
)
433 tv
.tv_sec
= msec
/ 1000;
434 tv
.tv_usec
= (msec
% 1000) * 1000;
436 ret
= setsockopt(sock
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
));
438 PERROR("setsockopt SO_SNDTIMEO");
444 int lttcomm_sock_get_port(const struct lttcomm_sock
*sock
, uint16_t *port
)
448 LTTNG_ASSERT(sock
->sockaddr
.type
== LTTCOMM_INET
||
449 sock
->sockaddr
.type
== LTTCOMM_INET6
);
450 LTTNG_ASSERT(sock
->proto
== LTTCOMM_SOCK_TCP
||
451 sock
->proto
== LTTCOMM_SOCK_UDP
);
453 switch (sock
->sockaddr
.type
) {
455 *port
= ntohs(sock
->sockaddr
.addr
.sin
.sin_port
);
458 *port
= ntohs(sock
->sockaddr
.addr
.sin6
.sin6_port
);
467 int lttcomm_sock_set_port(struct lttcomm_sock
*sock
, uint16_t port
)
470 LTTNG_ASSERT(sock
->sockaddr
.type
== LTTCOMM_INET
||
471 sock
->sockaddr
.type
== LTTCOMM_INET6
);
472 LTTNG_ASSERT(sock
->proto
== LTTCOMM_SOCK_TCP
||
473 sock
->proto
== LTTCOMM_SOCK_UDP
);
475 switch (sock
->sockaddr
.type
) {
477 sock
->sockaddr
.addr
.sin
.sin_port
= htons(port
);
480 sock
->sockaddr
.addr
.sin6
.sin6_port
= htons(port
);
489 void lttcomm_init(void)
493 env
= getenv(NETWORK_TIMEOUT_ENV
);
498 timeout
= strtol(env
, NULL
, 0);
499 if (errno
!= 0 || timeout
< -1L) {
500 PERROR("Network timeout");
503 network_timeout
= timeout
;
509 unsigned long lttcomm_get_network_timeout(void)
511 return network_timeout
;
515 * Only valid for an ipv4 and ipv6 bound socket that is already connected to its
518 int lttcomm_populate_sock_from_open_socket(
519 struct lttcomm_sock
*sock
,
521 enum lttcomm_sock_proto protocol
)
524 socklen_t storage_len
;
525 struct sockaddr_storage storage
= {};
530 sock
->proto
= protocol
;
532 storage_len
= sizeof(storage
);
533 ret
= getpeername(fd
, (struct sockaddr
*) &storage
,
536 ERR("Failed to get peer info for socket %d (errno: %d)", fd
,
542 if (storage_len
> sizeof(storage
)) {
543 ERR("Failed to get peer info for socket %d: storage size is too small", fd
);
548 switch (storage
.ss_family
) {
550 sock
->sockaddr
.type
= LTTCOMM_INET
;
551 memcpy(&sock
->sockaddr
.addr
, &storage
,
552 sizeof(struct sockaddr_in
));
555 sock
->sockaddr
.type
= LTTCOMM_INET6
;
556 memcpy(&sock
->sockaddr
.addr
, &storage
,
557 sizeof(struct sockaddr_in6
));
564 /* Create a valid socket object with a temporary fd. */
565 ret
= lttcomm_create_sock(sock
);
567 ERR("Failed to create temporary socket object");
572 /* Substitute the fd. */
573 if (sock
->ops
->close(sock
)) {