port: FreeBSD has no ENODATA, alias it to ENOATTR
[lttng-tools.git] / src / common / sessiond-comm / sessiond-comm.c
1 /*
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
6 *
7 */
8
9 #define _LGPL_SOURCE
10 #include <assert.h>
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18 #include <inttypes.h>
19
20 #include <common/common.h>
21 #include <common/compat/errno.h>
22
23 #include "sessiond-comm.h"
24
25 /* For Unix socket */
26 #include <common/unix.h>
27 /* For Inet socket */
28 #include "inet.h"
29 /* For Inet6 socket */
30 #include "inet6.h"
31
32 #define NETWORK_TIMEOUT_ENV "LTTNG_NETWORK_SOCKET_TIMEOUT"
33
34 static struct lttcomm_net_family net_families[] = {
35 { LTTCOMM_INET, lttcomm_create_inet_sock },
36 { LTTCOMM_INET6, lttcomm_create_inet6_sock },
37 };
38
39 /*
40 * Human readable error message.
41 */
42 static const char *lttcomm_readable_code[] = {
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",
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",
60 [ LTTCOMM_ERR_INDEX(LTTCOMM_CONSUMERD_RELAYD_FAIL) ] = "Error on remote relayd",
61
62 /* Last element */
63 [ LTTCOMM_ERR_INDEX(LTTCOMM_NR) ] = "Unknown error code"
64 };
65
66 static unsigned long network_timeout;
67
68 /*
69 * Return ptr to string representing a human readable error code from the
70 * lttcomm_return_code enum.
71 *
72 * These code MUST be negative in other to treat that as an error value.
73 */
74 LTTNG_HIDDEN
75 const char *lttcomm_get_readable_code(enum lttcomm_return_code code)
76 {
77 code = -code;
78
79 if (code < LTTCOMM_CONSUMERD_COMMAND_SOCK_READY || code > LTTCOMM_NR) {
80 code = LTTCOMM_NR;
81 }
82
83 return lttcomm_readable_code[LTTCOMM_ERR_INDEX(code)];
84 }
85
86 /*
87 * Create socket from an already allocated lttcomm socket structure and init
88 * sockaddr in the lttcomm sock.
89 */
90 LTTNG_HIDDEN
91 int lttcomm_create_sock(struct lttcomm_sock *sock)
92 {
93 int ret, _sock_type, _sock_proto, domain;
94
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;
102 }
103
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 }
117
118 ret = net_families[domain].create(sock, _sock_type, _sock_proto);
119 if (ret < 0) {
120 goto error;
121 }
122
123 error:
124 return ret;
125 }
126
127 /*
128 * Return allocated lttcomm socket structure.
129 */
130 LTTNG_HIDDEN
131 struct lttcomm_sock *lttcomm_alloc_sock(enum lttcomm_sock_proto proto)
132 {
133 struct lttcomm_sock *sock;
134
135 sock = zmalloc(sizeof(struct lttcomm_sock));
136 if (sock == NULL) {
137 PERROR("zmalloc create sock");
138 goto end;
139 }
140
141 sock->proto = proto;
142 sock->fd = -1;
143
144 end:
145 return sock;
146 }
147
148 /*
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.
154 */
155 LTTNG_HIDDEN
156 struct lttcomm_sock *lttcomm_alloc_copy_sock(struct lttcomm_sock *src)
157 {
158 struct lttcomm_sock *sock;
159
160 /* Safety net */
161 assert(src);
162
163 sock = lttcomm_alloc_sock(src->proto);
164 if (sock == NULL) {
165 goto alloc_error;
166 }
167
168 lttcomm_copy_sock(sock, src);
169
170 alloc_error:
171 return sock;
172 }
173
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 */
180 LTTNG_HIDDEN
181 void 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));
192 }
193
194 /*
195 * Init IPv4 sockaddr structure.
196 */
197 LTTNG_HIDDEN
198 int 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;
216 ERR("%s with port %d: unrecognized IPv4 address", ip, port);
217 goto error;
218 }
219 memset(sockaddr->addr.sin.sin_zero, 0, sizeof(sockaddr->addr.sin.sin_zero));
220
221 error:
222 return ret;
223 }
224
225 /*
226 * Init IPv6 sockaddr structure.
227 */
228 LTTNG_HIDDEN
229 int 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
250 error:
251 return ret;
252 }
253
254 /*
255 * Return allocated lttcomm socket structure from lttng URI.
256 */
257 LTTNG_HIDDEN
258 struct 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
301 error:
302 lttcomm_destroy_sock(sock);
303 alloc_error:
304 return NULL;
305 }
306
307 /*
308 * Destroy and free lttcomm socket.
309 */
310 LTTNG_HIDDEN
311 void lttcomm_destroy_sock(struct lttcomm_sock *sock)
312 {
313 free(sock);
314 }
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 */
322 LTTNG_HIDDEN
323 struct 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
361 error_free:
362 free(rsock);
363 error:
364 return NULL;
365 }
366
367 /*
368 * Set socket receiving timeout.
369 */
370 LTTNG_HIDDEN
371 int 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 */
390 LTTNG_HIDDEN
391 int 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
407 LTTNG_HIDDEN
408 int 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
431 LTTNG_HIDDEN
432 int 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
454 LTTNG_HIDDEN
455 void 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
475 LTTNG_HIDDEN
476 unsigned long lttcomm_get_network_timeout(void)
477 {
478 return network_timeout;
479 }
This page took 0.038745 seconds and 4 git commands to generate.