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