Fix: set wait/wake fd to -1 before close
[lttng-ust.git] / liblttng-ust-comm / lttng-ust-comm.c
CommitLineData
67c5b804
MD
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
74d81a6c 3 * Copyright (C) 2011-2013 - 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
32ce8569 34#include <lttng/ust-ctl.h>
b728d87e 35#include <ust-comm.h>
74d81a6c 36#include <helper.h>
7bc53e94 37#include <lttng/ust-error.h>
32ce8569
MD
38#include <lttng/ust-events.h>
39#include <usterr-signal-safe.h>
40
41#include "../liblttng-ust/compat.h"
7bc53e94
MD
42
43#define USTCOMM_CODE_OFFSET(code) \
44 (code == LTTNG_UST_OK ? 0 : (code - LTTNG_UST_ERR + 1))
67c5b804 45
74d81a6c
MD
46#define USTCOMM_MAX_SEND_FDS 4
47
67c5b804
MD
48/*
49 * Human readable error message.
50 */
57773204 51static const char *ustcomm_readable_code[] = {
7bc53e94
MD
52 [ USTCOMM_CODE_OFFSET(LTTNG_UST_OK) ] = "Success",
53 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR) ] = "Unknown error",
54 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_NOENT) ] = "No entry",
64b2564e
DG
55 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_EXIST) ] = "Object already exists",
56 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_INVAL) ] = "Invalid argument",
57 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_PERM) ] = "Permission denied",
58 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_NOSYS) ] = "Not implemented",
74d81a6c 59 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_EXITING) ] = "Process is exiting",
32ce8569
MD
60
61 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_INVAL_MAGIC) ] = "Invalid magic number",
62 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_INVAL_SOCKET_TYPE) ] = "Invalid socket type",
63 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_UNSUP_MAJOR) ] = "Unsupported major version",
67c5b804
MD
64};
65
66/*
7bc53e94 67 * lttng_ust_strerror
67c5b804 68 *
7bc53e94
MD
69 * Receives positive error value.
70 * Return ptr to string representing a human readable
71 * error code from the ustcomm_return_code enum.
67c5b804 72 */
7bc53e94 73const char *lttng_ust_strerror(int code)
67c5b804 74{
7bc53e94
MD
75 if (code == LTTNG_UST_OK)
76 return ustcomm_readable_code[USTCOMM_CODE_OFFSET(code)];
77 if (code < LTTNG_UST_ERR)
78 return strerror(code);
79 if (code >= LTTNG_UST_ERR_NR)
80 code = LTTNG_UST_ERR;
81 return ustcomm_readable_code[USTCOMM_CODE_OFFSET(code)];
82
67c5b804
MD
83}
84
85/*
74d81a6c 86 * ustcomm_connect_unix_sock
67c5b804 87 *
74d81a6c 88 * Connect to unix socket using the path name.
67c5b804 89 */
57773204 90int ustcomm_connect_unix_sock(const char *pathname)
67c5b804
MD
91{
92 struct sockaddr_un sun;
7bc53e94 93 int fd, ret;
67c5b804 94
204d45df
MD
95 /*
96 * libust threads require the close-on-exec flag for all
97 * resources so it does not leak file descriptors upon exec.
98 */
11ba4bcb 99 fd = socket(PF_UNIX, SOCK_STREAM, 0);
67c5b804 100 if (fd < 0) {
32ce8569 101 PERROR("socket");
7bc53e94 102 ret = -errno;
67c5b804
MD
103 goto error;
104 }
11ba4bcb
MD
105 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
106 if (ret < 0) {
32ce8569 107 PERROR("fcntl");
7bc53e94 108 ret = -errno;
11ba4bcb
MD
109 goto error_fcntl;
110 }
67c5b804
MD
111
112 memset(&sun, 0, sizeof(sun));
113 sun.sun_family = AF_UNIX;
114 strncpy(sun.sun_path, pathname, sizeof(sun.sun_path));
115 sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
116
117 ret = connect(fd, (struct sockaddr *) &sun, sizeof(sun));
118 if (ret < 0) {
119 /*
120 * Don't print message on connect error, because connect
121 * is used in normal execution to detect if sessiond is
122 * alive.
123 */
7bc53e94 124 ret = -errno;
67c5b804
MD
125 goto error_connect;
126 }
127
128 return fd;
129
130error_connect:
11ba4bcb 131error_fcntl:
7bc53e94
MD
132 {
133 int closeret;
134
135 closeret = close(fd);
136 if (closeret)
32ce8569 137 PERROR("close");
7bc53e94 138 }
67c5b804
MD
139error:
140 return ret;
141}
142
143/*
74d81a6c 144 * ustcomm_accept_unix_sock
67c5b804 145 *
74d81a6c
MD
146 * Do an accept(2) on the sock and return the
147 * new file descriptor. The socket MUST be bind(2) before.
67c5b804 148 */
57773204 149int ustcomm_accept_unix_sock(int sock)
67c5b804
MD
150{
151 int new_fd;
152 struct sockaddr_un sun;
153 socklen_t len = 0;
154
155 /* Blocking call */
156 new_fd = accept(sock, (struct sockaddr *) &sun, &len);
157 if (new_fd < 0) {
b869b5ae
MD
158 if (errno != ECONNABORTED)
159 PERROR("accept");
160 new_fd = -errno;
161 if (new_fd == -ECONNABORTED)
162 new_fd = -EPIPE;
67c5b804 163 }
67c5b804 164 return new_fd;
67c5b804
MD
165}
166
167/*
74d81a6c 168 * ustcomm_create_unix_sock
67c5b804 169 *
74d81a6c
MD
170 * Creates a AF_UNIX local socket using pathname
171 * bind the socket upon creation and return the fd.
67c5b804 172 */
57773204 173int ustcomm_create_unix_sock(const char *pathname)
67c5b804
MD
174{
175 struct sockaddr_un sun;
7bc53e94 176 int fd, ret;
67c5b804
MD
177
178 /* Create server socket */
179 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
32ce8569 180 PERROR("socket");
7bc53e94 181 ret = -errno;
67c5b804
MD
182 goto error;
183 }
184
185 memset(&sun, 0, sizeof(sun));
186 sun.sun_family = AF_UNIX;
187 strncpy(sun.sun_path, pathname, sizeof(sun.sun_path));
188 sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
189
190 /* Unlink the old file if present */
191 (void) unlink(pathname);
192 ret = bind(fd, (struct sockaddr *) &sun, sizeof(sun));
193 if (ret < 0) {
32ce8569 194 PERROR("bind");
7bc53e94
MD
195 ret = -errno;
196 goto error_close;
67c5b804
MD
197 }
198
199 return fd;
200
7bc53e94
MD
201error_close:
202 {
203 int closeret;
204
205 closeret = close(fd);
206 if (closeret) {
32ce8569 207 PERROR("close");
7bc53e94
MD
208 }
209 }
67c5b804
MD
210error:
211 return ret;
212}
213
214/*
74d81a6c 215 * ustcomm_listen_unix_sock
67c5b804 216 *
74d81a6c 217 * Make the socket listen using LTTNG_UST_COMM_MAX_LISTEN.
67c5b804 218 */
57773204 219int ustcomm_listen_unix_sock(int sock)
67c5b804
MD
220{
221 int ret;
222
e41474be 223 ret = listen(sock, LTTNG_UST_COMM_MAX_LISTEN);
67c5b804 224 if (ret < 0) {
7bc53e94 225 ret = -errno;
32ce8569 226 PERROR("listen");
67c5b804
MD
227 }
228
229 return ret;
230}
231
232/*
74d81a6c
MD
233 * ustcomm_close_unix_sock
234 *
235 * Shutdown cleanly a unix socket.
236 */
237int ustcomm_close_unix_sock(int sock)
238{
239 int ret;
240
241 ret = close(sock);
242 if (ret < 0) {
32ce8569 243 PERROR("close");
74d81a6c
MD
244 ret = -errno;
245 }
246
247 return ret;
248}
249
250/*
251 * ustcomm_recv_unix_sock
67c5b804 252 *
74d81a6c
MD
253 * Receive data of size len in put that data into
254 * the buf param. Using recvmsg API.
255 * Return the size of received data.
256 * Return 0 on orderly shutdown.
67c5b804 257 */
57773204 258ssize_t ustcomm_recv_unix_sock(int sock, void *buf, size_t len)
67c5b804 259{
913b87f1 260 struct msghdr msg;
67c5b804 261 struct iovec iov[1];
7bc53e94 262 ssize_t ret;
67c5b804 263
913b87f1
MD
264 memset(&msg, 0, sizeof(msg));
265
67c5b804
MD
266 iov[0].iov_base = buf;
267 iov[0].iov_len = len;
268 msg.msg_iov = iov;
269 msg.msg_iovlen = 1;
270
7e3cfcbe
MD
271 do {
272 ret = recvmsg(sock, &msg, 0);
273 } while (ret < 0 && errno == EINTR);
7bc53e94
MD
274
275 if (ret < 0) {
276 int shutret;
277
74d81a6c 278 if (errno != EPIPE && errno != ECONNRESET)
32ce8569 279 PERROR("recvmsg");
7bc53e94 280 ret = -errno;
b869b5ae
MD
281 if (ret == -ECONNRESET)
282 ret = -EPIPE;
7bc53e94
MD
283
284 shutret = shutdown(sock, SHUT_RDWR);
285 if (shutret)
32ce8569 286 ERR("Socket shutdown error");
67c5b804
MD
287 }
288
289 return ret;
290}
291
292/*
74d81a6c 293 * ustcomm_send_unix_sock
67c5b804 294 *
74d81a6c
MD
295 * Send buf data of size len. Using sendmsg API.
296 * Return the size of sent data.
67c5b804 297 */
32ce8569 298ssize_t ustcomm_send_unix_sock(int sock, const void *buf, size_t len)
67c5b804 299{
913b87f1 300 struct msghdr msg;
67c5b804 301 struct iovec iov[1];
7bc53e94 302 ssize_t ret;
67c5b804 303
913b87f1
MD
304 memset(&msg, 0, sizeof(msg));
305
32ce8569 306 iov[0].iov_base = (void *) buf;
67c5b804
MD
307 iov[0].iov_len = len;
308 msg.msg_iov = iov;
309 msg.msg_iovlen = 1;
310
1ea11eab
MD
311 /*
312 * Using the MSG_NOSIGNAL when sending data from sessiond to
313 * libust, so libust does not receive an unhandled SIGPIPE or
314 * SIGURG. The sessiond receiver side can be made more resilient
315 * by ignoring SIGPIPE, but we don't have this luxury on the
316 * libust side.
317 */
51d9d699
MD
318 do {
319 ret = sendmsg(sock, &msg, MSG_NOSIGNAL);
320 } while (ret < 0 && errno == EINTR);
7bc53e94
MD
321
322 if (ret < 0) {
323 int shutret;
324
74d81a6c 325 if (errno != EPIPE && errno != ECONNRESET)
32ce8569 326 PERROR("sendmsg");
7bc53e94 327 ret = -errno;
b869b5ae
MD
328 if (ret == -ECONNRESET)
329 ret = -EPIPE;
7bc53e94
MD
330
331 shutret = shutdown(sock, SHUT_RDWR);
332 if (shutret)
32ce8569 333 ERR("Socket shutdown error");
67c5b804
MD
334 }
335
336 return ret;
337}
338
339/*
74d81a6c 340 * Send a message accompanied by fd(s) over a unix socket.
67c5b804 341 *
74d81a6c 342 * Returns the size of data sent, or negative error value.
67c5b804 343 */
74d81a6c 344ssize_t ustcomm_send_fds_unix_sock(int sock, int *fds, size_t nb_fd)
67c5b804 345{
913b87f1 346 struct msghdr msg;
67c5b804
MD
347 struct cmsghdr *cmptr;
348 struct iovec iov[1];
349 ssize_t ret = -1;
350 unsigned int sizeof_fds = nb_fd * sizeof(int);
351 char tmp[CMSG_SPACE(sizeof_fds)];
74d81a6c 352 char dummy = 0;
67c5b804 353
913b87f1 354 memset(&msg, 0, sizeof(msg));
74d81a6c 355 memset(tmp, 0, CMSG_SPACE(sizeof_fds) * sizeof(char));
913b87f1 356
74d81a6c
MD
357 if (nb_fd > USTCOMM_MAX_SEND_FDS)
358 return -EINVAL;
67c5b804
MD
359
360 msg.msg_control = (caddr_t)tmp;
361 msg.msg_controllen = CMSG_LEN(sizeof_fds);
362
363 cmptr = CMSG_FIRSTHDR(&msg);
364 cmptr->cmsg_level = SOL_SOCKET;
365 cmptr->cmsg_type = SCM_RIGHTS;
366 cmptr->cmsg_len = CMSG_LEN(sizeof_fds);
367 memcpy(CMSG_DATA(cmptr), fds, sizeof_fds);
368 /* Sum of the length of all control messages in the buffer: */
369 msg.msg_controllen = cmptr->cmsg_len;
370
74d81a6c
MD
371 iov[0].iov_base = &dummy;
372 iov[0].iov_len = 1;
67c5b804
MD
373 msg.msg_iov = iov;
374 msg.msg_iovlen = 1;
375
51d9d699 376 do {
74d81a6c 377 ret = sendmsg(sock, &msg, 0);
51d9d699 378 } while (ret < 0 && errno == EINTR);
7bc53e94 379 if (ret < 0) {
74d81a6c
MD
380 /*
381 * We consider EPIPE and ECONNRESET as expected.
382 */
383 if (errno != EPIPE && errno != ECONNRESET) {
32ce8569 384 PERROR("sendmsg");
74d81a6c 385 }
b869b5ae
MD
386 ret = -errno;
387 if (ret == -ECONNRESET)
388 ret = -EPIPE;
74d81a6c
MD
389 }
390 return ret;
391}
7bc53e94 392
74d81a6c
MD
393/*
394 * Recv a message accompanied by fd(s) from a unix socket.
395 *
396 * Returns the size of received data, or negative error value.
397 *
398 * Expect at most "nb_fd" file descriptors. Returns the number of fd
399 * actually received in nb_fd.
400 * Returns -EPIPE on orderly shutdown.
401 */
402ssize_t ustcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd)
403{
404 struct iovec iov[1];
405 ssize_t ret = 0;
406 struct cmsghdr *cmsg;
407 size_t sizeof_fds = nb_fd * sizeof(int);
408 char recv_fd[CMSG_SPACE(sizeof_fds)];
409 struct msghdr msg;
410 char dummy;
7bc53e94 411
74d81a6c 412 memset(&msg, 0, sizeof(msg));
67c5b804 413
74d81a6c
MD
414 /* Prepare to receive the structures */
415 iov[0].iov_base = &dummy;
416 iov[0].iov_len = 1;
417 msg.msg_iov = iov;
418 msg.msg_iovlen = 1;
419 msg.msg_control = recv_fd;
420 msg.msg_controllen = sizeof(recv_fd);
421
422 do {
423 ret = recvmsg(sock, &msg, 0);
424 } while (ret < 0 && errno == EINTR);
425 if (ret < 0) {
426 if (errno != EPIPE && errno != ECONNRESET) {
32ce8569 427 PERROR("recvmsg fds");
74d81a6c
MD
428 }
429 if (errno == EPIPE || errno == ECONNRESET)
430 ret = -errno;
b869b5ae
MD
431 if (ret == -ECONNRESET)
432 ret = -EPIPE;
74d81a6c
MD
433 goto end;
434 }
435 if (ret == 0) {
436 /* orderly shutdown */
437 ret = -EPIPE;
438 goto end;
439 }
440 if (ret != 1) {
32ce8569 441 ERR("Error: Received %zd bytes, expected %d\n",
74d81a6c
MD
442 ret, 1);
443 goto end;
444 }
445 if (msg.msg_flags & MSG_CTRUNC) {
32ce8569 446 ERR("Error: Control message truncated.\n");
74d81a6c
MD
447 ret = -1;
448 goto end;
449 }
450 cmsg = CMSG_FIRSTHDR(&msg);
451 if (!cmsg) {
32ce8569 452 ERR("Error: Invalid control message header\n");
74d81a6c
MD
453 ret = -1;
454 goto end;
455 }
456 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
32ce8569 457 ERR("Didn't received any fd\n");
74d81a6c
MD
458 ret = -1;
459 goto end;
460 }
461 if (cmsg->cmsg_len != CMSG_LEN(sizeof_fds)) {
32ce8569 462 ERR("Error: Received %zu bytes of ancillary data, expected %zu\n",
74d81a6c
MD
463 (size_t) cmsg->cmsg_len, (size_t) CMSG_LEN(sizeof_fds));
464 ret = -1;
465 goto end;
466 }
467 memcpy(fds, CMSG_DATA(cmsg), sizeof_fds);
468 ret = sizeof_fds;
469end:
67c5b804
MD
470 return ret;
471}
57773204
MD
472
473int ustcomm_send_app_msg(int sock, struct ustcomm_ust_msg *lum)
474{
475 ssize_t len;
476
477 len = ustcomm_send_unix_sock(sock, lum, sizeof(*lum));
478 switch (len) {
479 case sizeof(*lum):
57773204 480 break;
57773204 481 default:
7bc53e94 482 if (len < 0) {
7bc53e94
MD
483 return len;
484 } else {
32ce8569 485 ERR("incorrect message size: %zd\n", len);
7bc53e94
MD
486 return -EINVAL;
487 }
57773204
MD
488 }
489 return 0;
490}
491
492int ustcomm_recv_app_reply(int sock, struct ustcomm_ust_reply *lur,
493 uint32_t expected_handle, uint32_t expected_cmd)
494{
495 ssize_t len;
496
497 memset(lur, 0, sizeof(*lur));
498 len = ustcomm_recv_unix_sock(sock, lur, sizeof(*lur));
499 switch (len) {
500 case 0: /* orderly shutdown */
74d81a6c 501 return -EPIPE;
57773204 502 case sizeof(*lur):
57773204 503 if (lur->handle != expected_handle) {
32ce8569 504 ERR("Unexpected result message handle: "
74d81a6c
MD
505 "expected: %u vs received: %u\n",
506 expected_handle, lur->handle);
57773204
MD
507 return -EINVAL;
508 }
57773204 509 if (lur->cmd != expected_cmd) {
32ce8569 510 ERR("Unexpected result message command "
74d81a6c
MD
511 "expected: %u vs received: %u\n",
512 expected_cmd, lur->cmd);
57773204
MD
513 return -EINVAL;
514 }
7bc53e94 515 return lur->ret_code;
57773204 516 default:
7bc53e94
MD
517 if (len < 0) {
518 /* Transport level error */
74d81a6c
MD
519 if (errno == EPIPE || errno == ECONNRESET)
520 len = -errno;
7bc53e94
MD
521 return len;
522 } else {
32ce8569 523 ERR("incorrect message size: %zd\n", len);
7bc53e94
MD
524 return len;
525 }
57773204
MD
526 }
527}
528
529int ustcomm_send_app_cmd(int sock,
530 struct ustcomm_ust_msg *lum,
531 struct ustcomm_ust_reply *lur)
532{
533 int ret;
534
535 ret = ustcomm_send_app_msg(sock, lum);
536 if (ret)
537 return ret;
c354a72c
MD
538 ret = ustcomm_recv_app_reply(sock, lur, lum->handle, lum->cmd);
539 if (ret > 0)
540 return -EIO;
541 return ret;
57773204
MD
542}
543
57773204 544/*
74d81a6c
MD
545 * chan_data is allocated internally if this function returns the
546 * expected var_len.
57773204 547 */
74d81a6c
MD
548ssize_t ustcomm_recv_channel_from_sessiond(int sock,
549 void **_chan_data, uint64_t var_len)
57773204 550{
74d81a6c
MD
551 void *chan_data;
552 ssize_t len;
57773204 553
74d81a6c
MD
554 if (var_len > LTTNG_UST_CHANNEL_DATA_MAX_LEN) {
555 len = -EINVAL;
556 goto error_check;
57773204 557 }
74d81a6c
MD
558 /* Receive variable length data */
559 chan_data = zmalloc(var_len);
560 if (!chan_data) {
561 len = -ENOMEM;
562 goto error_alloc;
57773204 563 }
74d81a6c
MD
564 len = ustcomm_recv_unix_sock(sock, chan_data, var_len);
565 if (len != var_len) {
566 goto error_recv;
57773204 567 }
74d81a6c
MD
568 *_chan_data = chan_data;
569 return len;
570
571error_recv:
572 free(chan_data);
573error_alloc:
574error_check:
575 return len;
576}
7bc53e94 577
74d81a6c
MD
578int ustcomm_recv_stream_from_sessiond(int sock,
579 uint64_t *memory_map_size,
580 int *shm_fd, int *wakeup_fd)
581{
582 ssize_t len;
583 int ret;
584 int fds[2];
585
586 /* recv shm fd and wakeup fd */
587 len = ustcomm_recv_fds_unix_sock(sock, fds, 2);
588 if (len <= 0) {
589 if (len < 0) {
590 ret = len;
591 goto error;
592 } else {
593 ret = -EIO;
594 goto error;
595 }
7bc53e94 596 }
74d81a6c
MD
597 *shm_fd = fds[0];
598 *wakeup_fd = fds[1];
599 return 0;
600
601error:
57773204
MD
602 return ret;
603}
32ce8569
MD
604
605/*
606 * Returns 0 on success, negative error value on error.
607 */
608int ustcomm_send_reg_msg(int sock,
609 enum ustctl_socket_type type,
610 uint32_t bits_per_long,
611 uint32_t uint8_t_alignment,
612 uint32_t uint16_t_alignment,
613 uint32_t uint32_t_alignment,
614 uint32_t uint64_t_alignment,
615 uint32_t long_alignment)
616{
617 ssize_t len;
618 struct ustctl_reg_msg reg_msg;
619
620 reg_msg.magic = LTTNG_UST_COMM_MAGIC;
621 reg_msg.major = LTTNG_UST_ABI_MAJOR_VERSION;
622 reg_msg.minor = LTTNG_UST_ABI_MINOR_VERSION;
623 reg_msg.pid = getpid();
624 reg_msg.ppid = getppid();
625 reg_msg.uid = getuid();
626 reg_msg.gid = getgid();
627 reg_msg.bits_per_long = bits_per_long;
628 reg_msg.uint8_t_alignment = uint8_t_alignment;
629 reg_msg.uint16_t_alignment = uint16_t_alignment;
630 reg_msg.uint32_t_alignment = uint32_t_alignment;
631 reg_msg.uint64_t_alignment = uint64_t_alignment;
632 reg_msg.long_alignment = long_alignment;
633 reg_msg.socket_type = type;
634 lttng_ust_getprocname(reg_msg.name);
635 memset(reg_msg.padding, 0, sizeof(reg_msg.padding));
636
637 len = ustcomm_send_unix_sock(sock, &reg_msg, sizeof(reg_msg));
638 if (len > 0 && len != sizeof(reg_msg))
639 return -EIO;
640 if (len < 0)
641 return len;
642 return 0;
643}
644
645static
2b213b16
MD
646int serialize_basic_type(enum ustctl_abstract_types *uatype,
647 enum lttng_abstract_types atype,
32ce8569
MD
648 union _ustctl_basic_type *ubt,
649 const union _lttng_basic_type *lbt)
650{
651 switch (atype) {
652 case atype_integer:
653 {
654 struct ustctl_integer_type *uit;
655 const struct lttng_integer_type *lit;
656
657 uit = &ubt->integer;
658 lit = &lbt->integer;
659 uit->size = lit->size;
660 uit->signedness = lit->signedness;
661 uit->reverse_byte_order = lit->reverse_byte_order;
662 uit->base = lit->base;
663 uit->encoding = lit->encoding;
664 uit->alignment = lit->alignment;
2b213b16 665 *uatype = ustctl_atype_integer;
32ce8569
MD
666 break;
667 }
668 case atype_string:
669 {
670 ubt->string.encoding = lbt->string.encoding;
2b213b16 671 *uatype = ustctl_atype_string;
32ce8569
MD
672 break;
673 }
674 case atype_float:
675 {
676 struct ustctl_float_type *uft;
677 const struct lttng_float_type *lft;
678
679 uft = &ubt->_float;
680 lft = &lbt->_float;
681 uft->exp_dig = lft->exp_dig;
682 uft->mant_dig = lft->mant_dig;
683 uft->alignment = lft->alignment;
684 uft->reverse_byte_order = lft->reverse_byte_order;
2b213b16 685 *uatype = ustctl_atype_float;
32ce8569
MD
686 break;
687 }
688 case atype_enum:
689 case atype_array:
690 case atype_sequence:
691 default:
692 return -EINVAL;
693 }
694 return 0;
32ce8569
MD
695}
696
697static
698int serialize_one_type(struct ustctl_type *ut, const struct lttng_type *lt)
699{
700 int ret;
701
702 switch (lt->atype) {
703 case atype_integer:
704 case atype_float:
705 case atype_string:
2b213b16 706 ret = serialize_basic_type(&ut->atype, lt->atype,
32ce8569
MD
707 &ut->u.basic, &lt->u.basic);
708 if (ret)
709 return ret;
710 break;
711 case atype_array:
712 {
713 struct ustctl_basic_type *ubt;
714 const struct lttng_basic_type *lbt;
715 int ret;
716
717 ubt = &ut->u.array.elem_type;
718 lbt = &lt->u.array.elem_type;
719 ut->u.array.length = lt->u.array.length;
2b213b16 720 ret = serialize_basic_type(&ubt->atype, lbt->atype,
32ce8569
MD
721 &ubt->u.basic, &lbt->u.basic);
722 if (ret)
723 return -EINVAL;
2b213b16 724 ut->atype = ustctl_atype_array;
32ce8569
MD
725 break;
726 }
727 case atype_sequence:
728 {
729 struct ustctl_basic_type *ubt;
730 const struct lttng_basic_type *lbt;
731 int ret;
732
733 ubt = &ut->u.sequence.length_type;
734 lbt = &lt->u.sequence.length_type;
2b213b16 735 ret = serialize_basic_type(&ubt->atype, lbt->atype,
32ce8569
MD
736 &ubt->u.basic, &lbt->u.basic);
737 if (ret)
738 return -EINVAL;
739 ubt = &ut->u.sequence.elem_type;
740 lbt = &lt->u.sequence.elem_type;
2b213b16 741 ret = serialize_basic_type(&ubt->atype, lbt->atype,
32ce8569
MD
742 &ubt->u.basic, &lbt->u.basic);
743 if (ret)
744 return -EINVAL;
2b213b16 745 ut->atype = ustctl_atype_sequence;
32ce8569
MD
746 break;
747 }
748 case atype_enum:
749 default:
750 return -EINVAL;
751 }
752 return 0;
753}
754
755static
756int serialize_fields(size_t *_nr_write_fields,
757 struct ustctl_field **ustctl_fields,
758 size_t nr_fields,
759 const struct lttng_event_field *lttng_fields)
760{
761 struct ustctl_field *fields;
762 int i, ret;
763 size_t nr_write_fields = 0;
764
765 fields = zmalloc(nr_fields * sizeof(*fields));
766 if (!fields)
767 return -ENOMEM;
768
769 for (i = 0; i < nr_fields; i++) {
770 struct ustctl_field *f;
771 const struct lttng_event_field *lf;
772
773 f = &fields[nr_write_fields];
774 lf = &lttng_fields[i];
775
776 /* skip 'nowrite' fields */
777 if (lf->nowrite)
778 continue;
779 strncpy(f->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
780 f->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
781 ret = serialize_one_type(&f->type, &lf->type);
782 if (ret)
783 goto error_type;
784 nr_write_fields++;
785 }
786
787 *_nr_write_fields = nr_write_fields;
788 *ustctl_fields = fields;
789 return 0;
790
791error_type:
792 free(fields);
793 return ret;
794}
795
796/*
797 * Returns 0 on success, negative error value on error.
798 */
799int ustcomm_register_event(int sock,
800 int session_objd, /* session descriptor */
801 int channel_objd, /* channel descriptor */
802 const char *event_name, /* event name (input) */
803 int loglevel,
804 const char *signature, /* event signature (input) */
805 size_t nr_fields, /* fields */
806 const struct lttng_event_field *lttng_fields,
807 const char *model_emf_uri,
808 uint32_t *id) /* event id (output) */
809{
810 ssize_t len;
811 struct {
812 struct ustcomm_notify_hdr header;
813 struct ustcomm_notify_event_msg m;
814 } msg;
815 struct {
816 struct ustcomm_notify_hdr header;
817 struct ustcomm_notify_event_reply r;
818 } reply;
819 size_t signature_len, fields_len, model_emf_uri_len;
820 struct ustctl_field *fields;
821 size_t nr_write_fields = 0;
822 int ret;
823
824 memset(&msg, 0, sizeof(msg));
825 msg.header.notify_cmd = USTCTL_NOTIFY_CMD_EVENT;
826 msg.m.session_objd = session_objd;
827 msg.m.channel_objd = channel_objd;
828 strncpy(msg.m.event_name, event_name, LTTNG_UST_SYM_NAME_LEN);
829 msg.m.event_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
830 msg.m.loglevel = loglevel;
831 signature_len = strlen(signature) + 1;
832 msg.m.signature_len = signature_len;
833
834 /* Calculate fields len, serialize fields. */
835 if (nr_fields > 0) {
836 ret = serialize_fields(&nr_write_fields, &fields,
837 nr_fields, lttng_fields);
838 if (ret)
839 return ret;
840 }
841
842 fields_len = sizeof(*fields) * nr_write_fields;
843 msg.m.fields_len = fields_len;
844 if (model_emf_uri) {
845 model_emf_uri_len = strlen(model_emf_uri) + 1;
846 } else {
847 model_emf_uri_len = 0;
848 }
849 msg.m.model_emf_uri_len = model_emf_uri_len;
850 len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
851 if (len > 0 && len != sizeof(msg)) {
852 free(fields);
853 return -EIO;
854 }
855 if (len < 0) {
856 free(fields);
857 return len;
858 }
859
860 /* send signature */
861 len = ustcomm_send_unix_sock(sock, signature, signature_len);
862 if (len > 0 && len != signature_len) {
863 free(fields);
864 return -EIO;
865 }
866 if (len < 0) {
867 free(fields);
868 return len;
869 }
870
871 /* send fields */
872 if (fields_len > 0) {
873 len = ustcomm_send_unix_sock(sock, fields, fields_len);
874 free(fields);
875 if (len > 0 && len != fields_len) {
876 return -EIO;
877 }
878 if (len < 0) {
879 return len;
880 }
881 }
882
883 if (model_emf_uri_len) {
884 /* send model_emf_uri */
885 len = ustcomm_send_unix_sock(sock, model_emf_uri,
886 model_emf_uri_len);
887 if (len > 0 && len != model_emf_uri_len)
888 return -EIO;
889 if (len < 0)
890 return len;
891 }
892
893 /* receive reply */
894 len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
895 switch (len) {
896 case 0: /* orderly shutdown */
897 return -EPIPE;
898 case sizeof(reply):
899 if (reply.header.notify_cmd != msg.header.notify_cmd) {
900 ERR("Unexpected result message command "
901 "expected: %u vs received: %u\n",
902 msg.header.notify_cmd, reply.header.notify_cmd);
903 return -EINVAL;
904 }
905 if (reply.r.ret_code > 0)
906 return -EINVAL;
907 if (reply.r.ret_code < 0)
908 return reply.r.ret_code;
909 *id = reply.r.event_id;
910 DBG("Sent register event notification for name \"%s\": ret_code %d, event_id %u\n",
911 event_name, reply.r.ret_code, reply.r.event_id);
912 return 0;
913 default:
914 if (len < 0) {
915 /* Transport level error */
916 if (errno == EPIPE || errno == ECONNRESET)
917 len = -errno;
918 return len;
919 } else {
920 ERR("incorrect message size: %zd\n", len);
921 return len;
922 }
923 }
924}
925
926/*
927 * Returns 0 on success, negative error value on error.
928 * Returns -EPIPE or -ECONNRESET if other end has hung up.
929 */
930int ustcomm_register_channel(int sock,
931 int session_objd, /* session descriptor */
932 int channel_objd, /* channel descriptor */
933 size_t nr_ctx_fields,
934 const struct lttng_event_field *ctx_fields,
935 uint32_t *chan_id, /* channel id (output) */
936 int *header_type) /* header type (output) */
937{
938 ssize_t len;
939 struct {
940 struct ustcomm_notify_hdr header;
941 struct ustcomm_notify_channel_msg m;
942 } msg;
943 struct {
944 struct ustcomm_notify_hdr header;
945 struct ustcomm_notify_channel_reply r;
946 } reply;
947 size_t fields_len;
948 struct ustctl_field *fields;
949 int ret;
950 size_t nr_write_fields = 0;
951
952 memset(&msg, 0, sizeof(msg));
953 msg.header.notify_cmd = USTCTL_NOTIFY_CMD_CHANNEL;
954 msg.m.session_objd = session_objd;
955 msg.m.channel_objd = channel_objd;
956
957 /* Calculate fields len, serialize fields. */
958 if (nr_ctx_fields > 0) {
959 ret = serialize_fields(&nr_write_fields, &fields,
960 nr_ctx_fields, ctx_fields);
961 if (ret)
962 return ret;
963 }
964
965 fields_len = sizeof(*fields) * nr_write_fields;
966 msg.m.ctx_fields_len = fields_len;
967 len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
968 if (len > 0 && len != sizeof(msg)) {
969 free(fields);
970 return -EIO;
971 }
972 if (len < 0) {
973 free(fields);
974 return len;
975 }
976
977 /* send fields */
978 if (fields_len > 0) {
979 len = ustcomm_send_unix_sock(sock, fields, fields_len);
980 free(fields);
981 if (len > 0 && len != fields_len) {
982 return -EIO;
983 }
984 if (len < 0) {
985 return len;
986 }
987 }
988
989 len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
990 switch (len) {
991 case 0: /* orderly shutdown */
992 return -EPIPE;
993 case sizeof(reply):
994 if (reply.header.notify_cmd != msg.header.notify_cmd) {
995 ERR("Unexpected result message command "
996 "expected: %u vs received: %u\n",
997 msg.header.notify_cmd, reply.header.notify_cmd);
998 return -EINVAL;
999 }
1000 if (reply.r.ret_code > 0)
1001 return -EINVAL;
1002 if (reply.r.ret_code < 0)
1003 return reply.r.ret_code;
1004 *chan_id = reply.r.chan_id;
1005 switch (reply.r.header_type) {
1006 case 1:
1007 case 2:
1008 *header_type = reply.r.header_type;
1009 break;
1010 default:
1011 ERR("Unexpected channel header type %u\n",
1012 reply.r.header_type);
1013 return -EINVAL;
1014 }
1015 DBG("Sent register channel notification: chan_id %d, header_type %d\n",
1016 reply.r.chan_id, reply.r.header_type);
1017 return 0;
1018 default:
1019 if (len < 0) {
1020 /* Transport level error */
1021 if (errno == EPIPE || errno == ECONNRESET)
1022 len = -errno;
1023 return len;
1024 } else {
1025 ERR("incorrect message size: %zd\n", len);
1026 return len;
1027 }
1028 }
1029}
ff517991
MD
1030
1031/*
1032 * Set socket reciving timeout.
1033 */
1034int ustcomm_setsockopt_rcv_timeout(int sock, unsigned int msec)
1035{
1036 int ret;
1037 struct timeval tv;
1038
1039 tv.tv_sec = msec / 1000;
1040 tv.tv_usec = (msec * 1000 % 1000000);
1041
1042 ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
1043 if (ret < 0) {
1044 PERROR("setsockopt SO_RCVTIMEO");
1045 ret = -errno;
1046 }
1047
1048 return ret;
1049}
1050
1051/*
1052 * Set socket sending timeout.
1053 */
1054int ustcomm_setsockopt_snd_timeout(int sock, unsigned int msec)
1055{
1056 int ret;
1057 struct timeval tv;
1058
1059 tv.tv_sec = msec / 1000;
1060 tv.tv_usec = (msec * 1000) % 1000000;
1061
1062 ret = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
1063 if (ret < 0) {
1064 PERROR("setsockopt SO_SNDTIMEO");
1065 ret = -errno;
1066 }
1067
1068 return ret;
1069}
This page took 0.074105 seconds and 4 git commands to generate.