Fix I/O-related error values in ustctl
[lttng-ust.git] / liblttng-ust-comm / lttng-ust-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 * 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,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
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
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>
31 #include <errno.h>
32 #include <fcntl.h>
33
34 #include <ust-comm.h>
35 #include <lttng/ust-error.h>
36
37 #define USTCOMM_CODE_OFFSET(code) \
38 (code == LTTNG_UST_OK ? 0 : (code - LTTNG_UST_ERR + 1))
39
40 /*
41 * Human readable error message.
42 */
43 static const char *ustcomm_readable_code[] = {
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",
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",
51 };
52
53 /*
54 * lttng_ust_strerror
55 *
56 * Receives positive error value.
57 * Return ptr to string representing a human readable
58 * error code from the ustcomm_return_code enum.
59 */
60 const char *lttng_ust_strerror(int code)
61 {
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
70 }
71
72 /*
73 * ustcomm_connect_unix_sock
74 *
75 * Connect to unix socket using the path name.
76 */
77 int ustcomm_connect_unix_sock(const char *pathname)
78 {
79 struct sockaddr_un sun;
80 int fd, ret;
81
82 /*
83 * libust threads require the close-on-exec flag for all
84 * resources so it does not leak file descriptors upon exec.
85 */
86 fd = socket(PF_UNIX, SOCK_STREAM, 0);
87 if (fd < 0) {
88 perror("socket");
89 ret = -errno;
90 goto error;
91 }
92 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
93 if (ret < 0) {
94 perror("fcntl");
95 ret = -errno;
96 goto error_fcntl;
97 }
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 */
111 ret = -errno;
112 goto error_connect;
113 }
114
115 return fd;
116
117 error_connect:
118 error_fcntl:
119 {
120 int closeret;
121
122 closeret = close(fd);
123 if (closeret)
124 perror("close");
125 }
126 error:
127 return ret;
128 }
129
130 /*
131 * ustcomm_accept_unix_sock
132 *
133 * Do an accept(2) on the sock and return the
134 * new file descriptor. The socket MUST be bind(2) before.
135 */
136 int ustcomm_accept_unix_sock(int sock)
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");
146 return -errno;
147 }
148 return new_fd;
149 }
150
151 /*
152 * ustcomm_create_unix_sock
153 *
154 * Creates a AF_UNIX local socket using pathname
155 * bind the socket upon creation and return the fd.
156 */
157 int ustcomm_create_unix_sock(const char *pathname)
158 {
159 struct sockaddr_un sun;
160 int fd, ret;
161
162 /* Create server socket */
163 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
164 perror("socket");
165 ret = -errno;
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");
179 ret = -errno;
180 goto error_close;
181 }
182
183 return fd;
184
185 error_close:
186 {
187 int closeret;
188
189 closeret = close(fd);
190 if (closeret) {
191 perror("close");
192 }
193 }
194 error:
195 return ret;
196 }
197
198 /*
199 * ustcomm_listen_unix_sock
200 *
201 * Make the socket listen using LTTNG_UST_COMM_MAX_LISTEN.
202 */
203 int ustcomm_listen_unix_sock(int sock)
204 {
205 int ret;
206
207 ret = listen(sock, LTTNG_UST_COMM_MAX_LISTEN);
208 if (ret < 0) {
209 ret = -errno;
210 perror("listen");
211 }
212
213 return ret;
214 }
215
216 /*
217 * ustcomm_recv_unix_sock
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 */
223 ssize_t ustcomm_recv_unix_sock(int sock, void *buf, size_t len)
224 {
225 struct msghdr msg;
226 struct iovec iov[1];
227 ssize_t ret;
228
229 memset(&msg, 0, sizeof(msg));
230
231 iov[0].iov_base = buf;
232 iov[0].iov_len = len;
233 msg.msg_iov = iov;
234 msg.msg_iovlen = 1;
235
236 do {
237 ret = recvmsg(sock, &msg, 0);
238 } while (ret < 0 && errno == EINTR);
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");
250 }
251
252 return ret;
253 }
254
255 /*
256 * ustcomm_send_unix_sock
257 *
258 * Send buf data of size len. Using sendmsg API.
259 * Return the size of sent data.
260 */
261 ssize_t ustcomm_send_unix_sock(int sock, void *buf, size_t len)
262 {
263 struct msghdr msg;
264 struct iovec iov[1];
265 ssize_t ret;
266
267 memset(&msg, 0, sizeof(msg));
268
269 iov[0].iov_base = buf;
270 iov[0].iov_len = len;
271 msg.msg_iov = iov;
272 msg.msg_iovlen = 1;
273
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 */
281 do {
282 ret = sendmsg(sock, &msg, MSG_NOSIGNAL);
283 } while (ret < 0 && errno == EINTR);
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");
295 }
296
297 return ret;
298 }
299
300 /*
301 * ustcomm_close_unix_sock
302 *
303 * Shutdown cleanly a unix socket.
304 */
305 int ustcomm_close_unix_sock(int sock)
306 {
307 int ret;
308
309 ret = close(sock);
310 if (ret < 0) {
311 perror("close");
312 ret = -errno;
313 }
314
315 return ret;
316 }
317
318 /*
319 * ustcomm_send_fds_unix_sock
320 *
321 * Send multiple fds on a unix socket.
322 */
323 ssize_t ustcomm_send_fds_unix_sock(int sock, void *buf, int *fds, size_t nb_fd, size_t len)
324 {
325 struct msghdr msg;
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
332 memset(&msg, 0, sizeof(msg));
333
334 /*
335 * Note: we currently only support sending a single FD per
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
356 do {
357 ret = sendmsg(sock, &msg, MSG_NOSIGNAL);
358 } while (ret < 0 && errno == EINTR);
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");
370 }
371
372 return ret;
373 }
374
375 int 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):
382 break;
383 default:
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 }
392 }
393 return 0;
394 }
395
396 int 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 */
405 return -EINVAL;
406 case sizeof(*lur):
407 if (lur->handle != expected_handle) {
408 fprintf(stderr, "Unexpected result message handle\n");
409 return -EINVAL;
410 }
411 if (lur->cmd != expected_cmd) {
412 fprintf(stderr, "Unexpected result message command\n");
413 return -EINVAL;
414 }
415 return lur->ret_code;
416 default:
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 }
426 }
427 }
428
429 int 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;
438 ret = ustcomm_recv_app_reply(sock, lur, lum->handle, lum->cmd);
439 if (ret > 0)
440 return -EIO;
441 return ret;
442 }
443
444 /*
445 * Receives a single fd from socket.
446 *
447 * Returns negative error value on error, or file descriptor number on
448 * success.
449 */
450 int ustcomm_recv_fd(int sock)
451 {
452 struct iovec iov[1];
453 int ret = 0;
454 int data_fd;
455 struct cmsghdr *cmsg;
456 char recv_fd[CMSG_SPACE(sizeof(int))];
457 struct msghdr msg;
458 union {
459 unsigned char vc[4];
460 int vi;
461 } tmp;
462 int i;
463
464 memset(&msg, 0, sizeof(msg));
465
466 /* Prepare to receive the structures */
467 iov[0].iov_base = &data_fd;
468 iov[0].iov_len = sizeof(data_fd);
469 msg.msg_iov = iov;
470 msg.msg_iovlen = 1;
471 msg.msg_control = recv_fd;
472 msg.msg_controllen = sizeof(recv_fd);
473
474 do {
475 ret = recvmsg(sock, &msg, 0);
476 } while (ret < 0 && errno == EINTR);
477 if (ret < 0) {
478 if (errno != EPIPE) {
479 perror("recvmsg");
480 }
481 ret = -errno;
482 goto end;
483 }
484 if (ret != sizeof(data_fd)) {
485 fprintf(stderr, "Received %d bytes, expected %zd", ret, sizeof(data_fd));
486 ret = -EINVAL;
487 goto end;
488 }
489 cmsg = CMSG_FIRSTHDR(&msg);
490 if (!cmsg) {
491 fprintf(stderr, "Invalid control message header\n");
492 ret = -EINVAL;
493 goto end;
494 }
495 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
496 fprintf(stderr, "Didn't received any fd\n");
497 ret = -EINVAL;
498 goto end;
499 }
500 /* this is our fd */
501 for (i = 0; i < sizeof(int); i++)
502 tmp.vc[i] = CMSG_DATA(cmsg)[i];
503 ret = tmp.vi;
504 /*
505 * Useful for fd leak debug.
506 * fprintf(stderr, "received fd %d\n", ret);
507 */
508 end:
509 if (ret < 0) {
510 int shutret;
511
512 shutret = shutdown(sock, SHUT_RDWR);
513 if (shutret)
514 fprintf(stderr, "Socket shutdown error");
515 }
516 return ret;
517 }
This page took 0.04005 seconds and 5 git commands to generate.