common: compile libcommon as C++
[lttng-tools.git] / src / common / unix.cpp
CommitLineData
0d37f2bc 1/*
ab5be9fa
MJ
2 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
0d37f2bc 4 *
ab5be9fa 5 * SPDX-License-Identifier: GPL-2.0-only
0d37f2bc 6 *
0d37f2bc
DG
7 */
8
6c1c0768 9#define _LGPL_SOURCE
0d37f2bc
DG
10#include <limits.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <sys/stat.h>
15#include <sys/types.h>
16#include <unistd.h>
0d37f2bc 17
90e535ef 18#include <common/common.h>
edf4b93e 19#include <common/compat/errno.h>
2038dd6c 20#include <common/sessiond-comm/sessiond-comm.h>
fe489250 21#include <common/fd-handle.h>
0d37f2bc
DG
22
23#include "unix.h"
24
25/*
26 * Connect to unix socket using the path name.
27 */
28int lttcomm_connect_unix_sock(const char *pathname)
29{
665886a6 30 struct sockaddr_un s_un;
0d37f2bc
DG
31 int fd, ret, closeret;
32
7f8bf467
JG
33 if (strlen(pathname) >= sizeof(s_un.sun_path)) {
34 ERR("unix socket address (\"%s\") is longer than the platform's limit (%zu > %zu).",
35 pathname, strlen(pathname) + 1,
36 sizeof(s_un.sun_path));
37 ret = -ENAMETOOLONG;
38 goto error;
39 }
40
0d37f2bc
DG
41 fd = socket(PF_UNIX, SOCK_STREAM, 0);
42 if (fd < 0) {
43 PERROR("socket");
44 ret = fd;
45 goto error;
46 }
47
665886a6
MJ
48 memset(&s_un, 0, sizeof(s_un));
49 s_un.sun_family = AF_UNIX;
50 strncpy(s_un.sun_path, pathname, sizeof(s_un.sun_path));
51 s_un.sun_path[sizeof(s_un.sun_path) - 1] = '\0';
0d37f2bc 52
665886a6 53 ret = connect(fd, (struct sockaddr *) &s_un, sizeof(s_un));
0d37f2bc
DG
54 if (ret < 0) {
55 /*
56 * Don't print message on connect error, because connect is used in
57 * normal execution to detect if sessiond is alive.
58 */
59 goto error_connect;
60 }
61
62 return fd;
63
64error_connect:
65 closeret = close(fd);
66 if (closeret) {
67 PERROR("close");
68 }
69error:
70 return ret;
71}
72
73/*
74 * Do an accept(2) on the sock and return the new file descriptor. The socket
75 * MUST be bind(2) before.
76 */
77int lttcomm_accept_unix_sock(int sock)
78{
79 int new_fd;
665886a6 80 struct sockaddr_un s_un;
50786a72 81 socklen_t len = sizeof(s_un);
0d37f2bc
DG
82
83 /* Blocking call */
665886a6 84 new_fd = accept(sock, (struct sockaddr *) &s_un, &len);
0d37f2bc
DG
85 if (new_fd < 0) {
86 PERROR("accept");
87 }
88
89 return new_fd;
90}
91
7567352f
MD
92int lttcomm_create_anon_unix_socketpair(int *fds)
93{
94 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fds) < 0) {
95 PERROR("socketpair");
96 return -1;
97 }
98 return 0;
99}
100
0d37f2bc
DG
101/*
102 * Creates a AF_UNIX local socket using pathname bind the socket upon creation
103 * and return the fd.
104 */
105int lttcomm_create_unix_sock(const char *pathname)
106{
665886a6 107 struct sockaddr_un s_un;
7f8bf467 108 int fd = -1;
0d37f2bc
DG
109 int ret = -1;
110
7f8bf467
JG
111 if (strlen(pathname) >= sizeof(s_un.sun_path)) {
112 ERR("unix socket address (\"%s\") is longer than the platform's limit (%zu > %zu).",
113 pathname, strlen(pathname) + 1,
114 sizeof(s_un.sun_path));
115 ret = -ENAMETOOLONG;
116 goto error;
117 }
118
0d37f2bc
DG
119 /* Create server socket */
120 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
121 PERROR("socket");
122 goto error;
123 }
124
665886a6
MJ
125 memset(&s_un, 0, sizeof(s_un));
126 s_un.sun_family = AF_UNIX;
127 strncpy(s_un.sun_path, pathname, sizeof(s_un.sun_path));
128 s_un.sun_path[sizeof(s_un.sun_path) - 1] = '\0';
0d37f2bc
DG
129
130 /* Unlink the old file if present */
131 (void) unlink(pathname);
665886a6 132 ret = bind(fd, (struct sockaddr *) &s_un, sizeof(s_un));
0d37f2bc
DG
133 if (ret < 0) {
134 PERROR("bind");
135 goto error;
136 }
137
138 return fd;
139
140error:
17e75273
DG
141 if (fd >= 0) {
142 if (close(fd) < 0) {
143 PERROR("close create unix sock");
144 }
145 }
0d37f2bc
DG
146 return ret;
147}
148
149/*
150 * Make the socket listen using LTTNG_SESSIOND_COMM_MAX_LISTEN.
151 */
152int lttcomm_listen_unix_sock(int sock)
153{
154 int ret;
155
156 ret = listen(sock, LTTNG_SESSIOND_COMM_MAX_LISTEN);
157 if (ret < 0) {
158 PERROR("listen");
159 }
160
161 return ret;
162}
163
164/*
165 * Receive data of size len in put that data into the buf param. Using recvmsg
166 * API.
167 *
168 * Return the size of received data.
169 */
170ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len)
171{
172 struct msghdr msg;
173 struct iovec iov[1];
174 ssize_t ret = -1;
7c5aef62 175 size_t len_last;
0d37f2bc 176
a0377dfe
FD
177 LTTNG_ASSERT(sock);
178 LTTNG_ASSERT(buf);
179 LTTNG_ASSERT(len > 0);
982583bd 180
0d37f2bc
DG
181 memset(&msg, 0, sizeof(msg));
182
183 iov[0].iov_base = buf;
184 iov[0].iov_len = len;
185 msg.msg_iov = iov;
186 msg.msg_iovlen = 1;
187
188 do {
7c5aef62 189 len_last = iov[0].iov_len;
fbb1fd3a 190 ret = lttng_recvmsg_nosigpipe(sock, &msg);
7c5aef62 191 if (ret > 0) {
a6bc4ca9 192 iov[0].iov_base = (char *) iov[0].iov_base + ret;
7c5aef62 193 iov[0].iov_len -= ret;
a0377dfe 194 LTTNG_ASSERT(ret <= len_last);
7c5aef62
DG
195 }
196 } while ((ret > 0 && ret < len_last) || (ret < 0 && errno == EINTR));
0d37f2bc
DG
197 if (ret < 0) {
198 PERROR("recvmsg");
7c5aef62
DG
199 } else if (ret > 0) {
200 ret = len;
0d37f2bc 201 }
7c5aef62 202 /* Else ret = 0 meaning an orderly shutdown. */
0d37f2bc
DG
203
204 return ret;
205}
206
c72435ad
JG
207/*
208 * Receive data of size len in put that data into the buf param. Using recvmsg
209 * API. Only use with sockets set in non-blocking mode.
210 *
44c180ca
JR
211 * NOTE: EPIPE errors are NOT reported. This call expects the socket to be in a
212 * poll set. The poll loop will handle the EPIPE original cause.
213 *
c72435ad
JG
214 * Return the size of received data.
215 */
c72435ad
JG
216ssize_t lttcomm_recv_unix_sock_non_block(int sock, void *buf, size_t len)
217{
218 struct msghdr msg;
219 struct iovec iov[1];
220 ssize_t ret;
221
a0377dfe
FD
222 LTTNG_ASSERT(sock);
223 LTTNG_ASSERT(buf);
224 LTTNG_ASSERT(len > 0);
982583bd 225
c72435ad
JG
226 memset(&msg, 0, sizeof(msg));
227
228 iov[0].iov_base = buf;
229 iov[0].iov_len = len;
230 msg.msg_iov = iov;
231 msg.msg_iovlen = 1;
232
233retry:
234 ret = lttng_recvmsg_nosigpipe(sock, &msg);
235 if (ret < 0) {
236 if (errno == EINTR) {
237 goto retry;
238 } else {
44c180ca
JR
239 /*
240 * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected.
241 */
242 if (errno == EAGAIN || errno == EWOULDBLOCK ||
243 errno == EPIPE) {
244 /*
245 * Nothing was recv.
246 */
247 ret = 0;
248 goto end;
c72435ad 249 }
44c180ca
JR
250
251 /* Unexpected error */
252 PERROR("recvmsg");
253 ret = -1;
c72435ad
JG
254 goto end;
255 }
256 }
5b86bd5e 257
c72435ad
JG
258end:
259 return ret;
260}
261
0d37f2bc
DG
262/*
263 * Send buf data of size len. Using sendmsg API.
264 *
265 * Return the size of sent data.
266 */
c2d69327 267ssize_t lttcomm_send_unix_sock(int sock, const void *buf, size_t len)
0d37f2bc
DG
268{
269 struct msghdr msg;
270 struct iovec iov[1];
c72435ad 271 ssize_t ret;
0d37f2bc 272
a0377dfe
FD
273 LTTNG_ASSERT(sock);
274 LTTNG_ASSERT(buf);
275 LTTNG_ASSERT(len > 0);
982583bd 276
0d37f2bc
DG
277 memset(&msg, 0, sizeof(msg));
278
c2d69327 279 iov[0].iov_base = (void *) buf;
0d37f2bc
DG
280 iov[0].iov_len = len;
281 msg.msg_iov = iov;
282 msg.msg_iovlen = 1;
283
c72435ad
JG
284 while (iov[0].iov_len) {
285 ret = sendmsg(sock, &msg, 0);
286 if (ret < 0) {
287 if (errno == EINTR) {
288 continue;
289 } else {
290 /*
291 * Only warn about EPIPE when quiet mode is
292 * deactivated.
293 * We consider EPIPE as expected.
294 */
295 if (errno != EPIPE || !lttng_opt_quiet) {
296 PERROR("sendmsg");
297 }
298 goto end;
299 }
300 }
301 iov[0].iov_len -= ret;
a6bc4ca9 302 iov[0].iov_base = (char *) iov[0].iov_base + ret;
c72435ad
JG
303 }
304 ret = len;
305end:
306 return ret;
307}
308
309/*
310 * Send buf data of size len. Using sendmsg API.
311 * Only use with non-blocking sockets. The difference with the blocking version
312 * of the function is that this one does not retry to send on partial sends,
313 * except if the interruption was caused by a signal (EINTR).
314 *
44c180ca
JR
315 * NOTE: EPIPE errors are NOT reported. This call expects the socket to be in a
316 * poll set. The poll loop will handle the EPIPE original cause.
317 *
c72435ad
JG
318 * Return the size of sent data.
319 */
c72435ad
JG
320ssize_t lttcomm_send_unix_sock_non_block(int sock, const void *buf, size_t len)
321{
322 struct msghdr msg;
323 struct iovec iov[1];
324 ssize_t ret;
325
a0377dfe
FD
326 LTTNG_ASSERT(sock);
327 LTTNG_ASSERT(buf);
328 LTTNG_ASSERT(len > 0);
982583bd 329
c72435ad
JG
330 memset(&msg, 0, sizeof(msg));
331
332 iov[0].iov_base = (void *) buf;
333 iov[0].iov_len = len;
334 msg.msg_iov = iov;
335 msg.msg_iovlen = 1;
336
337retry:
0d37f2bc
DG
338 ret = sendmsg(sock, &msg, 0);
339 if (ret < 0) {
c72435ad
JG
340 if (errno == EINTR) {
341 goto retry;
342 } else {
44c180ca
JR
343 /*
344 * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected.
345 */
346 if (errno == EAGAIN || errno == EWOULDBLOCK ||
347 errno == EPIPE) {
348 /*
349 * This can happen in non blocking mode.
350 * Nothing was sent.
351 */
352 ret = 0;
353 goto end;
c72435ad 354 }
44c180ca
JR
355
356 /* Unexpected error */
357 PERROR("sendmsg");
358 ret = -1;
c72435ad 359 goto end;
0d37f2bc
DG
360 }
361 }
c72435ad 362end:
0d37f2bc
DG
363 return ret;
364}
365
366/*
367 * Shutdown cleanly a unix socket.
368 */
369int lttcomm_close_unix_sock(int sock)
370{
371 int ret, closeret;
372
373 /* Shutdown receptions and transmissions */
374 ret = shutdown(sock, SHUT_RDWR);
375 if (ret < 0) {
376 PERROR("shutdown");
377 }
378
379 closeret = close(sock);
380 if (closeret) {
381 PERROR("close");
382 }
383
384 return ret;
385}
386
387/*
388 * Send a message accompanied by fd(s) over a unix socket.
389 *
390 * Returns the size of data sent, or negative error value.
391 */
ac2f30af 392ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd)
0d37f2bc
DG
393{
394 struct msghdr msg;
395 struct cmsghdr *cmptr;
396 struct iovec iov[1];
397 ssize_t ret = -1;
398 unsigned int sizeof_fds = nb_fd * sizeof(int);
399 char tmp[CMSG_SPACE(sizeof_fds)];
400 char dummy = 0;
401
a0377dfe
FD
402 LTTNG_ASSERT(sock);
403 LTTNG_ASSERT(fds);
404 LTTNG_ASSERT(nb_fd > 0);
982583bd 405
0d37f2bc 406 memset(&msg, 0, sizeof(msg));
b3f35e02 407 memset(tmp, 0, sizeof(tmp));
0d37f2bc
DG
408
409 if (nb_fd > LTTCOMM_MAX_SEND_FDS)
410 return -EINVAL;
411
412 msg.msg_control = (caddr_t)tmp;
413 msg.msg_controllen = CMSG_LEN(sizeof_fds);
414
415 cmptr = CMSG_FIRSTHDR(&msg);
1d8d0328
MJ
416 if (!cmptr) {
417 return -1;
418 }
b3f35e02 419
0d37f2bc
DG
420 cmptr->cmsg_level = SOL_SOCKET;
421 cmptr->cmsg_type = SCM_RIGHTS;
422 cmptr->cmsg_len = CMSG_LEN(sizeof_fds);
423 memcpy(CMSG_DATA(cmptr), fds, sizeof_fds);
424 /* Sum of the length of all control messages in the buffer: */
425 msg.msg_controllen = cmptr->cmsg_len;
426
427 iov[0].iov_base = &dummy;
428 iov[0].iov_len = 1;
429 msg.msg_iov = iov;
430 msg.msg_iovlen = 1;
431
432 do {
433 ret = sendmsg(sock, &msg, 0);
434 } while (ret < 0 && errno == EINTR);
435 if (ret < 0) {
436 /*
437 * Only warn about EPIPE when quiet mode is deactivated.
438 * We consider EPIPE as expected.
439 */
440 if (errno != EPIPE || !lttng_opt_quiet) {
441 PERROR("sendmsg");
442 }
443 }
444 return ret;
445}
446
fe489250
JG
447/*
448 * Send the fd(s) of a payload view over a unix socket.
449 *
450 * Returns the size of data sent, or negative error value.
451 */
452static
453ssize_t _lttcomm_send_payload_view_fds_unix_sock(int sock,
454 struct lttng_payload_view *view,
455 bool blocking)
456{
457 int i;
458 ssize_t ret;
459 struct lttng_dynamic_array raw_fds;
460 const int fd_count = lttng_payload_view_get_fd_handle_count(view);
461
462 lttng_dynamic_array_init(&raw_fds, sizeof(int), NULL);
463
3545ccee
JR
464 if (fd_count < 0) {
465 ret = -LTTNG_ERR_INVALID;
466 goto end;
467 }
468
fe489250
JG
469 /*
470 * Prepare a contiguous array of file descriptors to send them.
471 *
472 * Note that the reference to each fd is released during the iteration;
473 * we're just getting the numerical value of the fds to conform to the
474 * syscall's interface. We rely on the fact that "view" must remain
475 * valid for the duration of the call and that the underlying payload
476 * owns a reference to the fd_handles.
477 */
478 for (i = 0; i < fd_count; i++) {
479 struct fd_handle *handle =
480 lttng_payload_view_pop_fd_handle(view);
481 const int raw_fd = fd_handle_get_fd(handle);
482 const int add_ret = lttng_dynamic_array_add_element(
483 &raw_fds, &raw_fd);
484
485 fd_handle_put(handle);
486 if (add_ret) {
487 ret = -LTTNG_ERR_NOMEM;
488 goto end;
489 }
490 }
491
492 if (blocking) {
493 ret = lttcomm_send_fds_unix_sock(sock,
494 (const int *) raw_fds.buffer.data, fd_count);
495 } else {
496 ret = lttcomm_send_fds_unix_sock_non_block(sock,
497 (const int *) raw_fds.buffer.data, fd_count);
498 }
499
500end:
501 lttng_dynamic_array_reset(&raw_fds);
502 return ret;
503}
504
fe489250
JG
505ssize_t lttcomm_send_payload_view_fds_unix_sock(int sock,
506 struct lttng_payload_view *view)
507{
508 return _lttcomm_send_payload_view_fds_unix_sock(sock, view, true);
509}
510
fe489250
JG
511ssize_t lttcomm_send_payload_view_fds_unix_sock_non_block(int sock,
512 struct lttng_payload_view *view)
513{
514 return _lttcomm_send_payload_view_fds_unix_sock(sock, view, false);
515}
516
b72ce630
JR
517/*
518 * Send a message accompanied by fd(s) over a unix socket.
519 * Only use for non blocking socket.
520 *
521 * Returns the size of data sent, or negative error value.
522 */
b72ce630
JR
523ssize_t lttcomm_send_fds_unix_sock_non_block(int sock, const int *fds, size_t nb_fd)
524{
525 struct msghdr msg;
526 struct cmsghdr *cmptr;
527 struct iovec iov[1];
528 ssize_t ret = -1;
529 unsigned int sizeof_fds = nb_fd * sizeof(int);
530 char tmp[CMSG_SPACE(sizeof_fds)];
531 char dummy = 0;
532
a0377dfe
FD
533 LTTNG_ASSERT(sock);
534 LTTNG_ASSERT(fds);
535 LTTNG_ASSERT(nb_fd > 0);
982583bd 536
b72ce630
JR
537 memset(&msg, 0, sizeof(msg));
538 memset(tmp, 0, sizeof(tmp));
539
540 if (nb_fd > LTTCOMM_MAX_SEND_FDS)
541 return -EINVAL;
542
543 msg.msg_control = (caddr_t)tmp;
544 msg.msg_controllen = CMSG_LEN(sizeof_fds);
545
546 cmptr = CMSG_FIRSTHDR(&msg);
547 if (!cmptr) {
548 return -1;
549 }
550
551 cmptr->cmsg_level = SOL_SOCKET;
552 cmptr->cmsg_type = SCM_RIGHTS;
553 cmptr->cmsg_len = CMSG_LEN(sizeof_fds);
554 memcpy(CMSG_DATA(cmptr), fds, sizeof_fds);
555 /* Sum of the length of all control messages in the buffer: */
556 msg.msg_controllen = cmptr->cmsg_len;
557
558 iov[0].iov_base = &dummy;
559 iov[0].iov_len = 1;
560 msg.msg_iov = iov;
561 msg.msg_iovlen = 1;
562
563retry:
564 ret = sendmsg(sock, &msg, 0);
565 if (ret < 0) {
566 if (errno == EINTR) {
567 goto retry;
568 } else {
569 /*
570 * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected.
571 */
572 if (errno == EAGAIN || errno == EWOULDBLOCK) {
573 /*
574 * This can happen in non blocking mode.
575 * Nothing was sent.
576 */
577 ret = 0;
578 goto end;
579 }
580
581 if (errno == EPIPE) {
582 /* Expected error, pass error to caller */
583 DBG3("EPIPE on sendmsg");
584 ret = -1;
585 goto end;
586 }
587
588 /* Unexpected error */
589 PERROR("sendmsg");
590 ret = -1;
591 goto end;
592 }
593 }
594
595end:
596 return ret;
597}
598
0d37f2bc
DG
599/*
600 * Recv a message accompanied by fd(s) from a unix socket.
601 *
602 * Returns the size of received data, or negative error value.
603 *
604 * Expect at most "nb_fd" file descriptors. Returns the number of fd
605 * actually received in nb_fd.
606 */
607ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd)
608{
609 struct iovec iov[1];
610 ssize_t ret = 0;
611 struct cmsghdr *cmsg;
612 size_t sizeof_fds = nb_fd * sizeof(int);
b3f35e02 613
ba49ae8c
MJ
614#ifdef __linux__
615/* Account for the struct ucred cmsg in the buffer size */
616#define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds) + CMSG_SPACE(sizeof(struct ucred))
617#else
618#define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds)
619#endif /* __linux__ */
620
621 char recv_buf[LTTNG_SOCK_RECV_FDS_BUF_SIZE];
0d37f2bc
DG
622 struct msghdr msg;
623 char dummy;
624
a0377dfe
FD
625 LTTNG_ASSERT(sock);
626 LTTNG_ASSERT(fds);
627 LTTNG_ASSERT(nb_fd > 0);
982583bd 628
0d37f2bc
DG
629 memset(&msg, 0, sizeof(msg));
630
631 /* Prepare to receive the structures */
632 iov[0].iov_base = &dummy;
633 iov[0].iov_len = 1;
634 msg.msg_iov = iov;
635 msg.msg_iovlen = 1;
b3f35e02
FD
636
637 cmsg = (struct cmsghdr *) recv_buf;
638 cmsg->cmsg_len = CMSG_LEN(sizeof_fds);
639 cmsg->cmsg_level = SOL_SOCKET;
640 cmsg->cmsg_type = SCM_RIGHTS;
641
642 msg.msg_control = cmsg;
643 msg.msg_controllen = CMSG_LEN(sizeof(recv_buf));
644 msg.msg_flags = 0;
0d37f2bc 645
b72ce630
JR
646retry:
647 ret = lttng_recvmsg_nosigpipe(sock, &msg);
0d37f2bc 648 if (ret < 0) {
b72ce630
JR
649 if (errno == EINTR) {
650 goto retry;
651 } else {
652 /* We consider EPIPE and EAGAIN as expected. */
653 if (!lttng_opt_quiet &&
654 (errno != EPIPE && errno != EAGAIN)) {
655 PERROR("recvmsg");
656 }
657 goto end;
658 }
659 }
660
661 if (ret != 1) {
662 fprintf(stderr, "Error: Received %zd bytes, expected %d\n",
663 ret, 1);
0d37f2bc
DG
664 goto end;
665 }
b3f35e02 666
b72ce630
JR
667 if (msg.msg_flags & MSG_CTRUNC) {
668 fprintf(stderr, "Error: Control message truncated.\n");
669 ret = -1;
670 goto end;
671 }
672
673 /*
674 * If the socket was configured with SO_PASSCRED, the kernel will add a
675 * control message (cmsg) to the ancillary data of the unix socket. We
676 * need to expect a cmsg of the SCM_CREDENTIALS as the first control
677 * message.
678 */
679 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
680 if (cmsg->cmsg_level != SOL_SOCKET) {
681 fprintf(stderr, "Error: The socket needs to be of type SOL_SOCKET\n");
682 ret = -1;
683 goto end;
684 }
685 if (cmsg->cmsg_type == SCM_RIGHTS) {
686 /*
687 * We found the controle message for file descriptors,
688 * now copy the fds to the fds ptr and return success.
689 */
690 if (cmsg->cmsg_len != CMSG_LEN(sizeof_fds)) {
691 fprintf(stderr, "Error: Received %zu bytes of"
692 "ancillary data for FDs, expected %zu\n",
693 (size_t) cmsg->cmsg_len,
694 (size_t) CMSG_LEN(sizeof_fds));
695 ret = -1;
696 goto end;
697 }
698 memcpy(fds, CMSG_DATA(cmsg), sizeof_fds);
699 ret = sizeof_fds;
700 goto end;
701 }
702#ifdef __linux__
703 if (cmsg->cmsg_type == SCM_CREDENTIALS) {
704 /*
705 * Expect credentials to be sent when expecting fds even
706 * if no credential were include in the send(). The
707 * kernel adds them...
708 */
709 ret = -1;
710 }
711#endif /* __linux__ */
712 }
713end:
714 return ret;
715}
716
fe489250
JG
717static
718void close_raw_fd(void *ptr)
719{
720 const int raw_fd = *((const int *) ptr);
721
722 if (raw_fd >= 0) {
723 const int ret = close(raw_fd);
724
725 if (ret) {
726 PERROR("Failed to close file descriptor %d", raw_fd);
727 }
728 }
729}
730
731static
732enum lttng_error_code add_fds_to_payload(struct lttng_dynamic_array *raw_fds,
733 struct lttng_payload *payload)
734{
735 int i;
736 enum lttng_error_code ret_code = LTTNG_OK;
737 const int fd_count = lttng_dynamic_array_get_count(raw_fds);
738
739 for (i = 0; i < fd_count; i++) {
740 int ret;
741 struct fd_handle *handle;
742 int *raw_fd = (int *) lttng_dynamic_array_get_element(
743 raw_fds, i);
744
a0377dfe 745 LTTNG_ASSERT(*raw_fd != -1);
5dbd9742 746
fe489250
JG
747 handle = fd_handle_create(*raw_fd);
748 if (!handle) {
749 ret_code = LTTNG_ERR_NOMEM;
750 goto end;
751 }
752
753 /* FD ownership transferred to the handle. */
754 *raw_fd = -1;
755
756 ret = lttng_payload_push_fd_handle(payload, handle);
757 fd_handle_put(handle);
758 if (ret) {
759 ret_code = LTTNG_ERR_NOMEM;
760 goto end;
761 }
762 }
763
764end:
765 return ret_code;
766}
767
768static
769ssize_t _lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd,
770 struct lttng_payload *payload, bool blocking)
771{
5dbd9742 772 int i = 0;
fe489250
JG
773 enum lttng_error_code add_ret;
774 ssize_t ret;
5dbd9742 775 int default_value = -1;
fe489250
JG
776 struct lttng_dynamic_array raw_fds;
777
a0377dfe
FD
778 LTTNG_ASSERT(sock);
779 LTTNG_ASSERT(payload);
780 LTTNG_ASSERT(nb_fd > 0);
982583bd 781
fe489250 782 lttng_dynamic_array_init(&raw_fds, sizeof(int), close_raw_fd);
5dbd9742
JR
783
784 for (i = 0; i < nb_fd; i++) {
785 if (lttng_dynamic_array_add_element(&raw_fds, &default_value)) {
786 ret = -LTTNG_ERR_NOMEM;
787 goto end;
788 }
fe489250
JG
789 }
790
791 if (blocking) {
792 ret = lttcomm_recv_fds_unix_sock(
793 sock, (int *) raw_fds.buffer.data, nb_fd);
794 } else {
795 ret = lttcomm_recv_fds_unix_sock_non_block(
796 sock, (int *) raw_fds.buffer.data, nb_fd);
797 }
798
b3ba184e 799 if (ret <= 0) {
fe489250
JG
800 goto end;
801 }
802
803 add_ret = add_fds_to_payload(&raw_fds, payload);
804 if (add_ret != LTTNG_OK) {
805 ret = - (int) add_ret;
806 goto end;
807 }
808
809end:
810 lttng_dynamic_array_reset(&raw_fds);
811 return ret;
812}
813
fe489250
JG
814ssize_t lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd,
815 struct lttng_payload *payload)
816{
817 return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, true);
818}
819
fe489250
JG
820ssize_t lttcomm_recv_payload_fds_unix_sock_non_block(int sock, size_t nb_fd,
821 struct lttng_payload *payload)
822{
823 return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, false);
824}
825
b72ce630
JR
826/*
827 * Recv a message accompanied by fd(s) from a non-blocking unix socket.
828 * Only use with non-blocking sockets.
829 *
830 * Returns the size of received data, or negative error value.
831 *
832 * Expect at most "nb_fd" file descriptors.
833 *
834 * Note that based on our comprehension, partial reception of fds is not
835 * possible since the FDs are actually in the control message. It is all or
836 * nothing, still the sender side can send the wrong number of fds.
837 */
b72ce630
JR
838ssize_t lttcomm_recv_fds_unix_sock_non_block(int sock, int *fds, size_t nb_fd)
839{
840 struct iovec iov[1];
841 ssize_t ret = 0;
842 struct cmsghdr *cmsg;
843 size_t sizeof_fds = nb_fd * sizeof(int);
844
a0377dfe
FD
845 LTTNG_ASSERT(sock);
846 LTTNG_ASSERT(fds);
847 LTTNG_ASSERT(nb_fd > 0);
982583bd 848
b72ce630
JR
849#ifdef __linux__
850/* Account for the struct ucred cmsg in the buffer size */
851#define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds) + CMSG_SPACE(sizeof(struct ucred))
852#else
853#define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds)
854#endif /* __linux__ */
855
856 char recv_buf[LTTNG_SOCK_RECV_FDS_BUF_SIZE];
857 struct msghdr msg;
858 char dummy;
859
860 memset(&msg, 0, sizeof(msg));
861
862 /* Prepare to receive the structures */
863 iov[0].iov_base = &dummy;
864 iov[0].iov_len = 1;
865 msg.msg_iov = iov;
866 msg.msg_iovlen = 1;
867
868 cmsg = (struct cmsghdr *) recv_buf;
869 cmsg->cmsg_len = CMSG_LEN(sizeof_fds);
870 cmsg->cmsg_level = SOL_SOCKET;
871 cmsg->cmsg_type = SCM_RIGHTS;
872
873 msg.msg_control = cmsg;
874 msg.msg_controllen = CMSG_LEN(sizeof(recv_buf));
875 msg.msg_flags = 0;
876
877retry:
878 ret = lttng_recvmsg_nosigpipe(sock, &msg);
879 if (ret < 0) {
880 if (errno == EINTR) {
881 goto retry;
882 } else {
883 /*
884 * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected.
885 */
886 if (errno == EAGAIN || errno == EWOULDBLOCK) {
887 /*
888 * This can happen in non blocking mode.
889 * Nothing was recv.
890 */
891 ret = 0;
892 goto end;
893 }
894
895 if (errno == EPIPE) {
896 /* Expected error, pass error to caller */
897 DBG3("EPIPE on recvmsg");
898 ret = -1;
899 goto end;
900 }
901
902 /* Unexpected error */
903 PERROR("recvmsg");
904 ret = -1;
905 goto end;
906 }
907 }
908
0d37f2bc
DG
909 if (ret != 1) {
910 fprintf(stderr, "Error: Received %zd bytes, expected %d\n",
911 ret, 1);
912 goto end;
913 }
b3f35e02 914
0d37f2bc
DG
915 if (msg.msg_flags & MSG_CTRUNC) {
916 fprintf(stderr, "Error: Control message truncated.\n");
917 ret = -1;
918 goto end;
919 }
b3f35e02
FD
920
921 /*
922 * If the socket was configured with SO_PASSCRED, the kernel will add a
923 * control message (cmsg) to the ancillary data of the unix socket. We
924 * need to expect a cmsg of the SCM_CREDENTIALS as the first control
925 * message.
926 */
927 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
b3f35e02
FD
928 if (cmsg->cmsg_level != SOL_SOCKET) {
929 fprintf(stderr, "Error: The socket needs to be of type SOL_SOCKET\n");
930 ret = -1;
931 goto end;
932 }
933 if (cmsg->cmsg_type == SCM_RIGHTS) {
934 /*
935 * We found the controle message for file descriptors,
936 * now copy the fds to the fds ptr and return success.
937 */
938 if (cmsg->cmsg_len != CMSG_LEN(sizeof_fds)) {
939 fprintf(stderr, "Error: Received %zu bytes of"
940 "ancillary data for FDs, expected %zu\n",
941 (size_t) cmsg->cmsg_len,
942 (size_t) CMSG_LEN(sizeof_fds));
943 ret = -1;
944 goto end;
945 }
946 memcpy(fds, CMSG_DATA(cmsg), sizeof_fds);
947 ret = sizeof_fds;
948 goto end;
949 }
ba49ae8c 950#ifdef __linux__
b3f35e02
FD
951 if (cmsg->cmsg_type == SCM_CREDENTIALS) {
952 /*
953 * Expect credentials to be sent when expecting fds even
954 * if no credential were include in the send(). The
955 * kernel adds them...
956 */
b3f35e02
FD
957 ret = -1;
958 }
ba49ae8c 959#endif /* __linux__ */
0d37f2bc 960 }
0d37f2bc
DG
961end:
962 return ret;
963}
964
965/*
966 * Send a message with credentials over a unix socket.
967 *
968 * Returns the size of data sent, or negative error value.
969 */
e368fb43 970ssize_t lttcomm_send_creds_unix_sock(int sock, const void *buf, size_t len)
0d37f2bc
DG
971{
972 struct msghdr msg;
973 struct iovec iov[1];
974 ssize_t ret = -1;
9bc1a4b4 975#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
976 struct cmsghdr *cmptr;
977 size_t sizeof_cred = sizeof(lttng_sock_cred);
978 char anc_buf[CMSG_SPACE(sizeof_cred)];
979 lttng_sock_cred *creds;
8bbffd54
MJ
980
981 memset(anc_buf, 0, CMSG_SPACE(sizeof_cred) * sizeof(char));
9bc1a4b4 982#endif /* __linux__, __CYGWIN__ */
0d37f2bc
DG
983
984 memset(&msg, 0, sizeof(msg));
985
a0377dfe
FD
986 LTTNG_ASSERT(sock);
987 LTTNG_ASSERT(buf);
988 LTTNG_ASSERT(len > 0);
982583bd 989
e368fb43 990 iov[0].iov_base = (void *) buf;
0d37f2bc
DG
991 iov[0].iov_len = len;
992 msg.msg_iov = iov;
993 msg.msg_iovlen = 1;
994
9bc1a4b4 995#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
996 msg.msg_control = (caddr_t) anc_buf;
997 msg.msg_controllen = CMSG_LEN(sizeof_cred);
998
999 cmptr = CMSG_FIRSTHDR(&msg);
1d8d0328
MJ
1000 if (!cmptr) {
1001 return -1;
1002 }
0d37f2bc
DG
1003 cmptr->cmsg_level = SOL_SOCKET;
1004 cmptr->cmsg_type = LTTNG_SOCK_CREDS;
1005 cmptr->cmsg_len = CMSG_LEN(sizeof_cred);
1006
1007 creds = (lttng_sock_cred*) CMSG_DATA(cmptr);
1008
1009 LTTNG_SOCK_SET_UID_CRED(creds, geteuid());
1010 LTTNG_SOCK_SET_GID_CRED(creds, getegid());
1011 LTTNG_SOCK_SET_PID_CRED(creds, getpid());
9bc1a4b4 1012#endif /* __linux__, __CYGWIN__ */
0d37f2bc
DG
1013
1014 do {
1015 ret = sendmsg(sock, &msg, 0);
1016 } while (ret < 0 && errno == EINTR);
1017 if (ret < 0) {
1018 /*
1019 * Only warn about EPIPE when quiet mode is deactivated.
1020 * We consider EPIPE as expected.
1021 */
1022 if (errno != EPIPE || !lttng_opt_quiet) {
1023 PERROR("sendmsg");
1024 }
1025 }
1026 return ret;
1027}
1028
1029/*
1030 * Recv a message accompanied with credentials from a unix socket.
1031 *
1032 * Returns the size of received data, or negative error value.
1033 */
1034ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len,
1035 lttng_sock_cred *creds)
1036{
1037 struct msghdr msg;
1038 struct iovec iov[1];
1039 ssize_t ret;
4100e49a 1040 size_t len_last;
9bc1a4b4 1041#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
1042 struct cmsghdr *cmptr;
1043 size_t sizeof_cred = sizeof(lttng_sock_cred);
1044 char anc_buf[CMSG_SPACE(sizeof_cred)];
9bc1a4b4 1045#endif /* __linux__, __CYGWIN__ */
0d37f2bc 1046
a0377dfe
FD
1047 LTTNG_ASSERT(sock);
1048 LTTNG_ASSERT(buf);
1049 LTTNG_ASSERT(len > 0);
1050 LTTNG_ASSERT(creds);
0d37f2bc 1051
982583bd 1052 memset(&msg, 0, sizeof(msg));
0d37f2bc
DG
1053
1054 /* Prepare to receive the structures */
1055 iov[0].iov_base = buf;
1056 iov[0].iov_len = len;
1057 msg.msg_iov = iov;
1058 msg.msg_iovlen = 1;
1059
9bc1a4b4 1060#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
1061 msg.msg_control = anc_buf;
1062 msg.msg_controllen = sizeof(anc_buf);
9bc1a4b4 1063#endif /* __linux__, __CYGWIN__ */
0d37f2bc
DG
1064
1065 do {
4100e49a 1066 len_last = iov[0].iov_len;
0d37f2bc 1067 ret = recvmsg(sock, &msg, 0);
4100e49a 1068 if (ret > 0) {
a6bc4ca9 1069 iov[0].iov_base = (char *) iov[0].iov_base + ret;
4100e49a 1070 iov[0].iov_len -= ret;
a0377dfe 1071 LTTNG_ASSERT(ret <= len_last);
4100e49a
DG
1072 }
1073 } while ((ret > 0 && ret < len_last) || (ret < 0 && errno == EINTR));
0d37f2bc
DG
1074 if (ret < 0) {
1075 PERROR("recvmsg fds");
1076 goto end;
4100e49a
DG
1077 } else if (ret > 0) {
1078 ret = len;
0d37f2bc 1079 }
4100e49a 1080 /* Else ret = 0 meaning an orderly shutdown. */
0d37f2bc 1081
9bc1a4b4 1082#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
1083 if (msg.msg_flags & MSG_CTRUNC) {
1084 fprintf(stderr, "Error: Control message truncated.\n");
1085 ret = -1;
1086 goto end;
1087 }
1088
1089 cmptr = CMSG_FIRSTHDR(&msg);
1090 if (cmptr == NULL) {
1091 fprintf(stderr, "Error: Invalid control message header\n");
1092 ret = -1;
1093 goto end;
1094 }
1095
1096 if (cmptr->cmsg_level != SOL_SOCKET ||
1097 cmptr->cmsg_type != LTTNG_SOCK_CREDS) {
1098 fprintf(stderr, "Didn't received any credentials\n");
1099 ret = -1;
1100 goto end;
1101 }
1102
1103 if (cmptr->cmsg_len != CMSG_LEN(sizeof_cred)) {
1104 fprintf(stderr, "Error: Received %zu bytes of ancillary data, expected %zu\n",
1105 (size_t) cmptr->cmsg_len, (size_t) CMSG_LEN(sizeof_cred));
1106 ret = -1;
1107 goto end;
1108 }
1109
1110 memcpy(creds, CMSG_DATA(cmptr), sizeof_cred);
9bc1a4b4
JG
1111#elif (defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__))
1112 if (lttng_get_unix_socket_peer_creds(sock, creds)) {
1113 fprintf(stderr, "ARG\n");
1114 ret = -1;
1115 goto end;
0d37f2bc
DG
1116 }
1117#else
1118#error "Please implement credential support for your OS."
9bc1a4b4 1119#endif /* __linux__, __CYGWIN__ */
0d37f2bc
DG
1120
1121end:
1122 return ret;
1123}
1124
1125/*
1126 * Set socket option to use credentials passing.
1127 */
9bc1a4b4 1128#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
1129int lttcomm_setsockopt_creds_unix_sock(int sock)
1130{
1131 int ret, on = 1;
1132
1133 /* Set socket for credentials retrieval */
1134 ret = setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
1135 if (ret < 0) {
1136 PERROR("setsockopt creds unix sock");
1137 }
1138 return ret;
1139}
9bc1a4b4 1140#elif (defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__))
0d37f2bc
DG
1141int lttcomm_setsockopt_creds_unix_sock(int sock)
1142{
1143 return 0;
1144}
1145#else
1146#error "Please implement credential support for your OS."
1147#endif /* __linux__ */
This page took 0.112471 seconds and 4 git commands to generate.