Add libc errno translation layer to UST error code
[deliverable/lttng-ust.git] / liblttng-ust-comm / lttng-ust-comm.c
CommitLineData
67c5b804
MD
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
15f672f9 3 * Copyright (C) 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
67c5b804 4 *
15f672f9
MD
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; only
8 * version 2.1 of the License.
9 *
10 * This library is distributed in the hope that it will be useful,
67c5b804 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15f672f9
MD
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
67c5b804
MD
18 */
19
20#define _GNU_SOURCE
21#include <limits.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/socket.h>
26#include <sys/stat.h>
27#include <sys/types.h>
28#include <sys/un.h>
29#include <unistd.h>
30#include <assert.h>
57773204 31#include <errno.h>
11ba4bcb 32#include <fcntl.h>
67c5b804 33
b728d87e 34#include <ust-comm.h>
7bc53e94
MD
35#include <lttng/ust-error.h>
36
37#define USTCOMM_CODE_OFFSET(code) \
38 (code == LTTNG_UST_OK ? 0 : (code - LTTNG_UST_ERR + 1))
67c5b804
MD
39
40/*
41 * Human readable error message.
42 */
57773204 43static const char *ustcomm_readable_code[] = {
7bc53e94
MD
44 [ USTCOMM_CODE_OFFSET(LTTNG_UST_OK) ] = "Success",
45 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR) ] = "Unknown error",
46 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_NOENT) ] = "No entry",
64b2564e
DG
47 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_EXIST) ] = "Object already exists",
48 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_INVAL) ] = "Invalid argument",
49 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_PERM) ] = "Permission denied",
50 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_NOSYS) ] = "Not implemented",
67c5b804
MD
51};
52
53/*
7bc53e94 54 * lttng_ust_strerror
67c5b804 55 *
7bc53e94
MD
56 * Receives positive error value.
57 * Return ptr to string representing a human readable
58 * error code from the ustcomm_return_code enum.
67c5b804 59 */
7bc53e94 60const char *lttng_ust_strerror(int code)
67c5b804 61{
7bc53e94
MD
62 if (code == LTTNG_UST_OK)
63 return ustcomm_readable_code[USTCOMM_CODE_OFFSET(code)];
64 if (code < LTTNG_UST_ERR)
65 return strerror(code);
66 if (code >= LTTNG_UST_ERR_NR)
67 code = LTTNG_UST_ERR;
68 return ustcomm_readable_code[USTCOMM_CODE_OFFSET(code)];
69
67c5b804
MD
70}
71
72/*
57773204 73 * ustcomm_connect_unix_sock
67c5b804
MD
74 *
75 * Connect to unix socket using the path name.
76 */
57773204 77int ustcomm_connect_unix_sock(const char *pathname)
67c5b804
MD
78{
79 struct sockaddr_un sun;
7bc53e94 80 int fd, ret;
67c5b804 81
204d45df
MD
82 /*
83 * libust threads require the close-on-exec flag for all
84 * resources so it does not leak file descriptors upon exec.
85 */
11ba4bcb 86 fd = socket(PF_UNIX, SOCK_STREAM, 0);
67c5b804
MD
87 if (fd < 0) {
88 perror("socket");
7bc53e94 89 ret = -errno;
67c5b804
MD
90 goto error;
91 }
11ba4bcb
MD
92 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
93 if (ret < 0) {
94 perror("fcntl");
7bc53e94 95 ret = -errno;
11ba4bcb
MD
96 goto error_fcntl;
97 }
67c5b804
MD
98
99 memset(&sun, 0, sizeof(sun));
100 sun.sun_family = AF_UNIX;
101 strncpy(sun.sun_path, pathname, sizeof(sun.sun_path));
102 sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
103
104 ret = connect(fd, (struct sockaddr *) &sun, sizeof(sun));
105 if (ret < 0) {
106 /*
107 * Don't print message on connect error, because connect
108 * is used in normal execution to detect if sessiond is
109 * alive.
110 */
7bc53e94 111 ret = -errno;
67c5b804
MD
112 goto error_connect;
113 }
114
115 return fd;
116
117error_connect:
11ba4bcb 118error_fcntl:
7bc53e94
MD
119 {
120 int closeret;
121
122 closeret = close(fd);
123 if (closeret)
124 perror("close");
125 }
67c5b804
MD
126error:
127 return ret;
128}
129
130/*
57773204 131 * ustcomm_accept_unix_sock
67c5b804
MD
132 *
133 * Do an accept(2) on the sock and return the
134 * new file descriptor. The socket MUST be bind(2) before.
135 */
57773204 136int ustcomm_accept_unix_sock(int sock)
67c5b804
MD
137{
138 int new_fd;
139 struct sockaddr_un sun;
140 socklen_t len = 0;
141
142 /* Blocking call */
143 new_fd = accept(sock, (struct sockaddr *) &sun, &len);
144 if (new_fd < 0) {
145 perror("accept");
7bc53e94 146 return -errno;
67c5b804 147 }
67c5b804 148 return new_fd;
67c5b804
MD
149}
150
151/*
57773204 152 * ustcomm_create_unix_sock
67c5b804
MD
153 *
154 * Creates a AF_UNIX local socket using pathname
155 * bind the socket upon creation and return the fd.
156 */
57773204 157int ustcomm_create_unix_sock(const char *pathname)
67c5b804
MD
158{
159 struct sockaddr_un sun;
7bc53e94 160 int fd, ret;
67c5b804
MD
161
162 /* Create server socket */
163 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
164 perror("socket");
7bc53e94 165 ret = -errno;
67c5b804
MD
166 goto error;
167 }
168
169 memset(&sun, 0, sizeof(sun));
170 sun.sun_family = AF_UNIX;
171 strncpy(sun.sun_path, pathname, sizeof(sun.sun_path));
172 sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
173
174 /* Unlink the old file if present */
175 (void) unlink(pathname);
176 ret = bind(fd, (struct sockaddr *) &sun, sizeof(sun));
177 if (ret < 0) {
178 perror("bind");
7bc53e94
MD
179 ret = -errno;
180 goto error_close;
67c5b804
MD
181 }
182
183 return fd;
184
7bc53e94
MD
185error_close:
186 {
187 int closeret;
188
189 closeret = close(fd);
190 if (closeret) {
191 perror("close");
192 }
193 }
67c5b804
MD
194error:
195 return ret;
196}
197
198/*
57773204 199 * ustcomm_listen_unix_sock
67c5b804 200 *
e41474be 201 * Make the socket listen using LTTNG_UST_COMM_MAX_LISTEN.
67c5b804 202 */
57773204 203int ustcomm_listen_unix_sock(int sock)
67c5b804
MD
204{
205 int ret;
206
e41474be 207 ret = listen(sock, LTTNG_UST_COMM_MAX_LISTEN);
67c5b804 208 if (ret < 0) {
7bc53e94 209 ret = -errno;
67c5b804
MD
210 perror("listen");
211 }
212
213 return ret;
214}
215
216/*
57773204 217 * ustcomm_recv_unix_sock
67c5b804
MD
218 *
219 * Receive data of size len in put that data into
220 * the buf param. Using recvmsg API.
221 * Return the size of received data.
222 */
57773204 223ssize_t ustcomm_recv_unix_sock(int sock, void *buf, size_t len)
67c5b804 224{
913b87f1 225 struct msghdr msg;
67c5b804 226 struct iovec iov[1];
7bc53e94 227 ssize_t ret;
67c5b804 228
913b87f1
MD
229 memset(&msg, 0, sizeof(msg));
230
67c5b804
MD
231 iov[0].iov_base = buf;
232 iov[0].iov_len = len;
233 msg.msg_iov = iov;
234 msg.msg_iovlen = 1;
235
7e3cfcbe
MD
236 do {
237 ret = recvmsg(sock, &msg, 0);
238 } while (ret < 0 && errno == EINTR);
7bc53e94
MD
239
240 if (ret < 0) {
241 int shutret;
242
243 if (errno != EPIPE)
244 perror("recvmsg");
245 ret = -errno;
246
247 shutret = shutdown(sock, SHUT_RDWR);
248 if (shutret)
249 fprintf(stderr, "Socket shutdown error");
67c5b804
MD
250 }
251
252 return ret;
253}
254
255/*
57773204 256 * ustcomm_send_unix_sock
67c5b804
MD
257 *
258 * Send buf data of size len. Using sendmsg API.
259 * Return the size of sent data.
260 */
57773204 261ssize_t ustcomm_send_unix_sock(int sock, void *buf, size_t len)
67c5b804 262{
913b87f1 263 struct msghdr msg;
67c5b804 264 struct iovec iov[1];
7bc53e94 265 ssize_t ret;
67c5b804 266
913b87f1
MD
267 memset(&msg, 0, sizeof(msg));
268
67c5b804
MD
269 iov[0].iov_base = buf;
270 iov[0].iov_len = len;
271 msg.msg_iov = iov;
272 msg.msg_iovlen = 1;
273
1ea11eab
MD
274 /*
275 * Using the MSG_NOSIGNAL when sending data from sessiond to
276 * libust, so libust does not receive an unhandled SIGPIPE or
277 * SIGURG. The sessiond receiver side can be made more resilient
278 * by ignoring SIGPIPE, but we don't have this luxury on the
279 * libust side.
280 */
51d9d699
MD
281 do {
282 ret = sendmsg(sock, &msg, MSG_NOSIGNAL);
283 } while (ret < 0 && errno == EINTR);
7bc53e94
MD
284
285 if (ret < 0) {
286 int shutret;
287
288 if (errno != EPIPE)
289 perror("recvmsg");
290 ret = -errno;
291
292 shutret = shutdown(sock, SHUT_RDWR);
293 if (shutret)
294 fprintf(stderr, "Socket shutdown error");
67c5b804
MD
295 }
296
297 return ret;
298}
299
300/*
57773204 301 * ustcomm_close_unix_sock
67c5b804
MD
302 *
303 * Shutdown cleanly a unix socket.
304 */
57773204 305int ustcomm_close_unix_sock(int sock)
67c5b804
MD
306{
307 int ret;
308
e6973a89 309 ret = close(sock);
67c5b804 310 if (ret < 0) {
e6973a89 311 perror("close");
7bc53e94 312 ret = -errno;
67c5b804
MD
313 }
314
315 return ret;
316}
317
318/*
57773204 319 * ustcomm_send_fds_unix_sock
67c5b804
MD
320 *
321 * Send multiple fds on a unix socket.
322 */
57773204 323ssize_t ustcomm_send_fds_unix_sock(int sock, void *buf, int *fds, size_t nb_fd, size_t len)
67c5b804 324{
913b87f1 325 struct msghdr msg;
67c5b804
MD
326 struct cmsghdr *cmptr;
327 struct iovec iov[1];
328 ssize_t ret = -1;
329 unsigned int sizeof_fds = nb_fd * sizeof(int);
330 char tmp[CMSG_SPACE(sizeof_fds)];
331
913b87f1
MD
332 memset(&msg, 0, sizeof(msg));
333
67c5b804 334 /*
7bc53e94 335 * Note: we currently only support sending a single FD per
67c5b804
MD
336 * message.
337 */
338 assert(nb_fd == 1);
339
340 msg.msg_control = (caddr_t)tmp;
341 msg.msg_controllen = CMSG_LEN(sizeof_fds);
342
343 cmptr = CMSG_FIRSTHDR(&msg);
344 cmptr->cmsg_level = SOL_SOCKET;
345 cmptr->cmsg_type = SCM_RIGHTS;
346 cmptr->cmsg_len = CMSG_LEN(sizeof_fds);
347 memcpy(CMSG_DATA(cmptr), fds, sizeof_fds);
348 /* Sum of the length of all control messages in the buffer: */
349 msg.msg_controllen = cmptr->cmsg_len;
350
351 iov[0].iov_base = buf;
352 iov[0].iov_len = len;
353 msg.msg_iov = iov;
354 msg.msg_iovlen = 1;
355
51d9d699
MD
356 do {
357 ret = sendmsg(sock, &msg, MSG_NOSIGNAL);
358 } while (ret < 0 && errno == EINTR);
7bc53e94
MD
359
360 if (ret < 0) {
361 int shutret;
362
363 if (errno != EPIPE)
364 perror("recvmsg");
365 ret = -errno;
366
367 shutret = shutdown(sock, SHUT_RDWR);
368 if (shutret)
369 fprintf(stderr, "Socket shutdown error");
67c5b804
MD
370 }
371
372 return ret;
373}
57773204
MD
374
375int ustcomm_send_app_msg(int sock, struct ustcomm_ust_msg *lum)
376{
377 ssize_t len;
378
379 len = ustcomm_send_unix_sock(sock, lum, sizeof(*lum));
380 switch (len) {
381 case sizeof(*lum):
57773204 382 break;
57773204 383 default:
7bc53e94
MD
384 if (len < 0) {
385 if (len == -ECONNRESET)
386 fprintf(stderr, "remote end closed connection\n");
387 return len;
388 } else {
389 fprintf(stderr, "incorrect message size: %zd\n", len);
390 return -EINVAL;
391 }
57773204
MD
392 }
393 return 0;
394}
395
396int ustcomm_recv_app_reply(int sock, struct ustcomm_ust_reply *lur,
397 uint32_t expected_handle, uint32_t expected_cmd)
398{
399 ssize_t len;
400
401 memset(lur, 0, sizeof(*lur));
402 len = ustcomm_recv_unix_sock(sock, lur, sizeof(*lur));
403 switch (len) {
404 case 0: /* orderly shutdown */
57773204
MD
405 return -EINVAL;
406 case sizeof(*lur):
57773204 407 if (lur->handle != expected_handle) {
c1ee6c90 408 fprintf(stderr, "Unexpected result message handle\n");
57773204
MD
409 return -EINVAL;
410 }
57773204 411 if (lur->cmd != expected_cmd) {
c1ee6c90 412 fprintf(stderr, "Unexpected result message command\n");
57773204
MD
413 return -EINVAL;
414 }
7bc53e94 415 return lur->ret_code;
57773204 416 default:
7bc53e94
MD
417 if (len < 0) {
418 /* Transport level error */
419 if (len == -ECONNRESET)
420 fprintf(stderr, "remote end closed connection\n");
421 return len;
422 } else {
423 fprintf(stderr, "incorrect message size: %zd\n", len);
424 return len;
425 }
57773204
MD
426 }
427}
428
429int ustcomm_send_app_cmd(int sock,
430 struct ustcomm_ust_msg *lum,
431 struct ustcomm_ust_reply *lur)
432{
433 int ret;
434
435 ret = ustcomm_send_app_msg(sock, lum);
436 if (ret)
437 return ret;
7bc53e94 438 return ustcomm_recv_app_reply(sock, lur, lum->handle, lum->cmd);
57773204
MD
439}
440
57773204
MD
441/*
442 * Receives a single fd from socket.
443 *
7bc53e94
MD
444 * Returns negative error value on error, or file descriptor number on
445 * success.
57773204
MD
446 */
447int ustcomm_recv_fd(int sock)
448{
449 struct iovec iov[1];
450 int ret = 0;
451 int data_fd;
452 struct cmsghdr *cmsg;
453 char recv_fd[CMSG_SPACE(sizeof(int))];
913b87f1 454 struct msghdr msg;
57773204
MD
455 union {
456 unsigned char vc[4];
457 int vi;
458 } tmp;
459 int i;
460
913b87f1
MD
461 memset(&msg, 0, sizeof(msg));
462
57773204
MD
463 /* Prepare to receive the structures */
464 iov[0].iov_base = &data_fd;
465 iov[0].iov_len = sizeof(data_fd);
466 msg.msg_iov = iov;
467 msg.msg_iovlen = 1;
468 msg.msg_control = recv_fd;
469 msg.msg_controllen = sizeof(recv_fd);
470
7e3cfcbe
MD
471 do {
472 ret = recvmsg(sock, &msg, 0);
473 } while (ret < 0 && errno == EINTR);
474 if (ret < 0) {
45d35b9f
MD
475 if (errno != EPIPE) {
476 perror("recvmsg");
477 }
7bc53e94 478 ret = -errno;
57773204
MD
479 goto end;
480 }
481 if (ret != sizeof(data_fd)) {
7210fb23 482 fprintf(stderr, "Received %d bytes, expected %zd", ret, sizeof(data_fd));
7bc53e94 483 ret = -EINVAL;
57773204
MD
484 goto end;
485 }
486 cmsg = CMSG_FIRSTHDR(&msg);
487 if (!cmsg) {
c1ee6c90 488 fprintf(stderr, "Invalid control message header\n");
7bc53e94 489 ret = -EINVAL;
57773204
MD
490 goto end;
491 }
492 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
c1ee6c90 493 fprintf(stderr, "Didn't received any fd\n");
7bc53e94 494 ret = -EINVAL;
57773204
MD
495 goto end;
496 }
497 /* this is our fd */
498 for (i = 0; i < sizeof(int); i++)
499 tmp.vc[i] = CMSG_DATA(cmsg)[i];
500 ret = tmp.vi;
e55f988e
MD
501 /*
502 * Useful for fd leak debug.
503 * fprintf(stderr, "received fd %d\n", ret);
504 */
57773204 505end:
7bc53e94
MD
506 if (ret < 0) {
507 int shutret;
508
509 shutret = shutdown(sock, SHUT_RDWR);
510 if (shutret)
511 fprintf(stderr, "Socket shutdown error");
512 }
57773204
MD
513 return ret;
514}
This page took 0.072093 seconds and 5 git commands to generate.