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.h>
21 #include <common/compat/errno.h>
23 #include "sessiond-comm.h"
26 #include <common/unix.h>
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
;
183 sock
= (lttcomm_sock
*) zmalloc(sizeof(lttcomm_sock
));
185 PERROR("zmalloc create sock");
197 * Return an allocated lttcomm socket structure and copy src content into
198 * the newly created socket.
200 * This is mostly useful when lttcomm_sock are passed between process where the
201 * fd and ops have to be changed within the correct address space.
203 struct lttcomm_sock
*lttcomm_alloc_copy_sock(struct lttcomm_sock
*src
)
205 struct lttcomm_sock
*sock
;
210 sock
= lttcomm_alloc_sock(src
->proto
);
215 lttcomm_copy_sock(sock
, src
);
222 * Create and copy socket from an allocated lttcomm socket structure.
224 * This is mostly useful when lttcomm_sock are passed between process where the
225 * fd and ops have to be changed within the correct address space.
227 void lttcomm_copy_sock(struct lttcomm_sock
*dst
, struct lttcomm_sock
*src
)
233 dst
->proto
= src
->proto
;
236 /* Copy sockaddr information from original socket */
237 memcpy(&dst
->sockaddr
, &src
->sockaddr
, sizeof(dst
->sockaddr
));
241 * Init IPv4 sockaddr structure.
243 int lttcomm_init_inet_sockaddr(struct lttcomm_sockaddr
*sockaddr
,
244 const char *ip
, unsigned int port
)
248 LTTNG_ASSERT(sockaddr
);
250 LTTNG_ASSERT(port
> 0 && port
<= 65535);
252 memset(sockaddr
, 0, sizeof(struct lttcomm_sockaddr
));
254 sockaddr
->type
= LTTCOMM_INET
;
255 sockaddr
->addr
.sin
.sin_family
= AF_INET
;
256 sockaddr
->addr
.sin
.sin_port
= htons(port
);
257 ret
= inet_pton(sockaddr
->addr
.sin
.sin_family
, ip
,
258 &sockaddr
->addr
.sin
.sin_addr
);
261 ERR("%s with port %d: unrecognized IPv4 address", ip
, port
);
264 memset(sockaddr
->addr
.sin
.sin_zero
, 0, sizeof(sockaddr
->addr
.sin
.sin_zero
));
271 * Init IPv6 sockaddr structure.
273 int lttcomm_init_inet6_sockaddr(struct lttcomm_sockaddr
*sockaddr
,
274 const char *ip
, unsigned int port
)
278 LTTNG_ASSERT(sockaddr
);
280 LTTNG_ASSERT(port
> 0 && port
<= 65535);
282 memset(sockaddr
, 0, sizeof(struct lttcomm_sockaddr
));
284 sockaddr
->type
= LTTCOMM_INET6
;
285 sockaddr
->addr
.sin6
.sin6_family
= AF_INET6
;
286 sockaddr
->addr
.sin6
.sin6_port
= htons(port
);
287 ret
= inet_pton(sockaddr
->addr
.sin6
.sin6_family
, ip
,
288 &sockaddr
->addr
.sin6
.sin6_addr
);
299 * Return allocated lttcomm socket structure from lttng URI.
301 struct lttcomm_sock
*lttcomm_alloc_sock_from_uri(struct lttng_uri
*uri
)
305 struct lttcomm_sock
*sock
= NULL
;
310 /* Check URI protocol */
311 if (uri
->proto
== LTTNG_TCP
) {
312 _sock_proto
= LTTCOMM_SOCK_TCP
;
314 ERR("Relayd invalid URI proto: %d", uri
->proto
);
318 sock
= lttcomm_alloc_sock((lttcomm_sock_proto
) _sock_proto
);
323 /* Check destination type */
324 if (uri
->dtype
== LTTNG_DST_IPV4
) {
325 ret
= lttcomm_init_inet_sockaddr(&sock
->sockaddr
, uri
->dst
.ipv4
,
330 } else if (uri
->dtype
== LTTNG_DST_IPV6
) {
331 ret
= lttcomm_init_inet6_sockaddr(&sock
->sockaddr
, uri
->dst
.ipv6
,
337 /* Command URI is invalid */
338 ERR("Relayd invalid URI dst type: %d", uri
->dtype
);
345 lttcomm_destroy_sock(sock
);
351 * Destroy and free lttcomm socket.
353 void lttcomm_destroy_sock(struct lttcomm_sock
*sock
)
359 * Allocate and return a relayd socket object using a given URI to initialize
360 * it and the major/minor version of the supported protocol.
362 * On error, NULL is returned.
364 struct lttcomm_relayd_sock
*lttcomm_alloc_relayd_sock(struct lttng_uri
*uri
,
365 uint32_t major
, uint32_t minor
)
368 struct lttcomm_sock
*tmp_sock
= NULL
;
369 struct lttcomm_relayd_sock
*rsock
= NULL
;
373 rsock
= (lttcomm_relayd_sock
*) zmalloc(sizeof(*rsock
));
375 PERROR("zmalloc relayd sock");
379 /* Allocate socket object from URI */
380 tmp_sock
= lttcomm_alloc_sock_from_uri(uri
);
381 if (tmp_sock
== NULL
) {
386 * Create socket object which basically sets the ops according to the
389 lttcomm_copy_sock(&rsock
->sock
, tmp_sock
);
390 /* Temporary socket pointer not needed anymore. */
391 lttcomm_destroy_sock(tmp_sock
);
392 ret
= lttcomm_create_sock(&rsock
->sock
);
397 rsock
->major
= major
;
398 rsock
->minor
= minor
;
409 * Set socket receiving timeout.
411 int lttcomm_setsockopt_rcv_timeout(int sock
, unsigned int msec
)
416 tv
.tv_sec
= msec
/ 1000;
417 tv
.tv_usec
= (msec
% 1000) * 1000;
419 ret
= setsockopt(sock
, SOL_SOCKET
, SO_RCVTIMEO
, &tv
, sizeof(tv
));
421 PERROR("setsockopt SO_RCVTIMEO");
428 * Set socket sending timeout.
430 int lttcomm_setsockopt_snd_timeout(int sock
, unsigned int msec
)
435 tv
.tv_sec
= msec
/ 1000;
436 tv
.tv_usec
= (msec
% 1000) * 1000;
438 ret
= setsockopt(sock
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
));
440 PERROR("setsockopt SO_SNDTIMEO");
446 int lttcomm_sock_get_port(const struct lttcomm_sock
*sock
, uint16_t *port
)
450 LTTNG_ASSERT(sock
->sockaddr
.type
== LTTCOMM_INET
||
451 sock
->sockaddr
.type
== LTTCOMM_INET6
);
452 LTTNG_ASSERT(sock
->proto
== LTTCOMM_SOCK_TCP
||
453 sock
->proto
== LTTCOMM_SOCK_UDP
);
455 switch (sock
->sockaddr
.type
) {
457 *port
= ntohs(sock
->sockaddr
.addr
.sin
.sin_port
);
460 *port
= ntohs(sock
->sockaddr
.addr
.sin6
.sin6_port
);
469 int lttcomm_sock_set_port(struct lttcomm_sock
*sock
, uint16_t port
)
472 LTTNG_ASSERT(sock
->sockaddr
.type
== LTTCOMM_INET
||
473 sock
->sockaddr
.type
== LTTCOMM_INET6
);
474 LTTNG_ASSERT(sock
->proto
== LTTCOMM_SOCK_TCP
||
475 sock
->proto
== LTTCOMM_SOCK_UDP
);
477 switch (sock
->sockaddr
.type
) {
479 sock
->sockaddr
.addr
.sin
.sin_port
= htons(port
);
482 sock
->sockaddr
.addr
.sin6
.sin6_port
= htons(port
);
491 void lttcomm_init(void)
495 env
= getenv(NETWORK_TIMEOUT_ENV
);
500 timeout
= strtol(env
, NULL
, 0);
501 if (errno
!= 0 || timeout
< -1L) {
502 PERROR("Network timeout");
505 network_timeout
= timeout
;
511 unsigned long lttcomm_get_network_timeout(void)
513 return network_timeout
;
517 * Only valid for an ipv4 and ipv6 bound socket that is already connected to its
520 int lttcomm_populate_sock_from_open_socket(
521 struct lttcomm_sock
*sock
,
523 enum lttcomm_sock_proto protocol
)
526 socklen_t storage_len
;
527 struct sockaddr_storage storage
= {};
532 sock
->proto
= protocol
;
534 storage_len
= sizeof(storage
);
535 ret
= getpeername(fd
, (struct sockaddr
*) &storage
,
538 ERR("Failed to get peer info for socket %d (errno: %d)", fd
,
544 if (storage_len
> sizeof(storage
)) {
545 ERR("Failed to get peer info for socket %d: storage size is too small", fd
);
550 switch (storage
.ss_family
) {
552 sock
->sockaddr
.type
= LTTCOMM_INET
;
553 memcpy(&sock
->sockaddr
.addr
, &storage
,
554 sizeof(struct sockaddr_in
));
557 sock
->sockaddr
.type
= LTTCOMM_INET6
;
558 memcpy(&sock
->sockaddr
.addr
, &storage
,
559 sizeof(struct sockaddr_in6
));
566 /* Create a valid socket object with a temporary fd. */
567 ret
= lttcomm_create_sock(sock
);
569 ERR("Failed to create temporary socket object");
574 /* Substitute the fd. */
575 if (sock
->ops
->close(sock
)) {