ustcomm: implement shutdown API
[lttng-ust.git] / src / common / ustcomm.c
1 /*
2 * SPDX-License-Identifier: LGPL-2.1-only
3 *
4 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
5 * Copyright (C) 2011-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 */
7
8 #include <limits.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/socket.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <sys/un.h>
17 #include <unistd.h>
18 #include <assert.h>
19 #include <errno.h>
20 #include <fcntl.h>
21
22 #include <lttng/ust-ctl.h>
23 #include "common/ustcomm.h"
24 #include "common/ust-fd.h"
25 #include "common/macros.h"
26 #include "common/dynamic-type.h"
27 #include "common/logging.h"
28
29 #include "common/events.h"
30 #include "common/compat/pthread.h"
31
32 #define USTCOMM_MAX_SEND_FDS 4
33
34 static
35 ssize_t count_fields_recursive(size_t nr_fields,
36 const struct lttng_ust_event_field * const *lttng_fields);
37 static
38 int serialize_one_field(struct lttng_ust_session *session,
39 struct lttng_ust_ctl_field *fields, size_t *iter_output,
40 const struct lttng_ust_event_field *lf,
41 const char **prev_field_name);
42 static
43 int serialize_fields(struct lttng_ust_session *session,
44 struct lttng_ust_ctl_field *lttng_ust_ctl_fields,
45 size_t *iter_output, size_t nr_lttng_fields,
46 const struct lttng_ust_event_field * const *lttng_fields);
47
48 /*
49 * ustcomm_connect_unix_sock
50 *
51 * Connect to unix socket using the path name.
52 *
53 * Caller handles FD tracker.
54 */
55 int ustcomm_connect_unix_sock(const char *pathname, long timeout)
56 {
57 struct sockaddr_un sun;
58 int fd, ret;
59
60 /*
61 * libust threads require the close-on-exec flag for all
62 * resources so it does not leak file descriptors upon exec.
63 * SOCK_CLOEXEC is not used since it is linux specific.
64 */
65 fd = socket(PF_UNIX, SOCK_STREAM, 0);
66 if (fd < 0) {
67 PERROR("socket");
68 ret = -errno;
69 goto error;
70 }
71 if (timeout >= 0) {
72 /* Give at least 10ms. */
73 if (timeout < 10)
74 timeout = 10;
75 ret = ustcomm_setsockopt_snd_timeout(fd, timeout);
76 if (ret < 0) {
77 WARN("Error setting connect socket send timeout");
78 }
79 }
80 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
81 if (ret < 0) {
82 PERROR("fcntl");
83 ret = -errno;
84 goto error_fcntl;
85 }
86
87 memset(&sun, 0, sizeof(sun));
88 sun.sun_family = AF_UNIX;
89 strncpy(sun.sun_path, pathname, sizeof(sun.sun_path));
90 sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
91
92 ret = connect(fd, (struct sockaddr *) &sun, sizeof(sun));
93 if (ret < 0) {
94 /*
95 * Don't print message on connect ENOENT error, because
96 * connect is used in normal execution to detect if
97 * sessiond is alive. ENOENT is when the unix socket
98 * file does not exist, and ECONNREFUSED is when the
99 * file exists but no sessiond is listening.
100 */
101 if (errno != ECONNREFUSED && errno != ECONNRESET
102 && errno != ENOENT && errno != EACCES)
103 PERROR("connect");
104 ret = -errno;
105 if (ret == -ECONNREFUSED || ret == -ECONNRESET)
106 ret = -EPIPE;
107 goto error_connect;
108 }
109
110 return fd;
111
112 error_connect:
113 error_fcntl:
114 {
115 int closeret;
116
117 closeret = close(fd);
118 if (closeret)
119 PERROR("close");
120 }
121 error:
122 return ret;
123 }
124
125 /*
126 * ustcomm_accept_unix_sock
127 *
128 * Do an accept(2) on the sock and return the
129 * new file descriptor. The socket MUST be bind(2) before.
130 */
131 int ustcomm_accept_unix_sock(int sock)
132 {
133 int new_fd;
134 struct sockaddr_un sun;
135 socklen_t len = 0;
136
137 /* Blocking call */
138 new_fd = accept(sock, (struct sockaddr *) &sun, &len);
139 if (new_fd < 0) {
140 if (errno != ECONNABORTED)
141 PERROR("accept");
142 new_fd = -errno;
143 if (new_fd == -ECONNABORTED)
144 new_fd = -EPIPE;
145 }
146 return new_fd;
147 }
148
149 /*
150 * ustcomm_create_unix_sock
151 *
152 * Creates a AF_UNIX local socket using pathname
153 * bind the socket upon creation and return the fd.
154 */
155 int ustcomm_create_unix_sock(const char *pathname)
156 {
157 struct sockaddr_un sun;
158 int fd, ret;
159
160 /* Create server socket */
161 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
162 PERROR("socket");
163 ret = -errno;
164 goto error;
165 }
166
167 memset(&sun, 0, sizeof(sun));
168 sun.sun_family = AF_UNIX;
169 strncpy(sun.sun_path, pathname, sizeof(sun.sun_path));
170 sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
171
172 /* Unlink the old file if present */
173 (void) unlink(pathname);
174 ret = bind(fd, (struct sockaddr *) &sun, sizeof(sun));
175 if (ret < 0) {
176 PERROR("bind");
177 ret = -errno;
178 goto error_close;
179 }
180
181 return fd;
182
183 error_close:
184 {
185 int closeret;
186
187 closeret = close(fd);
188 if (closeret) {
189 PERROR("close");
190 }
191 }
192 error:
193 return ret;
194 }
195
196 /*
197 * ustcomm_listen_unix_sock
198 *
199 * Make the socket listen using LTTNG_UST_COMM_MAX_LISTEN.
200 */
201 int ustcomm_listen_unix_sock(int sock)
202 {
203 int ret;
204
205 ret = listen(sock, LTTNG_UST_COMM_MAX_LISTEN);
206 if (ret < 0) {
207 ret = -errno;
208 PERROR("listen");
209 }
210
211 return ret;
212 }
213
214 /*
215 * ustcomm_close_unix_sock
216 *
217 * Close unix socket.
218 *
219 * Handles fd tracker internally.
220 */
221 int ustcomm_close_unix_sock(int sock)
222 {
223 int ret;
224
225 lttng_ust_lock_fd_tracker();
226 ret = close(sock);
227 if (!ret) {
228 lttng_ust_delete_fd_from_tracker(sock);
229 } else {
230 PERROR("close");
231 ret = -errno;
232 }
233 lttng_ust_unlock_fd_tracker();
234
235 return ret;
236 }
237
238 /*
239 * ustcomm_shutdown_unix_sock
240 *
241 * Shutdown unix socket. Keeps the file descriptor open, but shutdown
242 * communication.
243 */
244 int ustcomm_shutdown_unix_sock(int sock)
245 {
246 int ret;
247
248 ret = shutdown(sock, SHUT_RDWR);
249 if (ret) {
250 PERROR("Socket shutdown error");
251 ret = -errno;
252 }
253 return ret;
254 }
255
256 /*
257 * ustcomm_recv_unix_sock
258 *
259 * Receive data of size len in put that data into
260 * the buf param. Using recvmsg API.
261 * Return the size of received data.
262 * Return 0 on orderly shutdown.
263 */
264 ssize_t ustcomm_recv_unix_sock(int sock, void *buf, size_t len)
265 {
266 struct msghdr msg;
267 struct iovec iov[1];
268 ssize_t ret = -1;
269 size_t len_last;
270
271 memset(&msg, 0, sizeof(msg));
272
273 iov[0].iov_base = buf;
274 iov[0].iov_len = len;
275 msg.msg_iov = iov;
276 msg.msg_iovlen = 1;
277
278 do {
279 len_last = iov[0].iov_len;
280 ret = recvmsg(sock, &msg, 0);
281 if (ret > 0) {
282 iov[0].iov_base += ret;
283 iov[0].iov_len -= ret;
284 assert(ret <= len_last);
285 }
286 } while ((ret > 0 && ret < len_last) || (ret < 0 && errno == EINTR));
287
288 if (ret < 0) {
289 if (errno != EPIPE && errno != ECONNRESET && errno != ECONNREFUSED)
290 PERROR("recvmsg");
291 ret = -errno;
292 if (ret == -ECONNRESET || ret == -ECONNREFUSED)
293 ret = -EPIPE;
294
295 (void) ustcomm_shutdown_unix_sock(sock);
296 } else if (ret > 0) {
297 ret = len;
298 }
299 /* ret = 0 means an orderly shutdown. */
300
301 return ret;
302 }
303
304 /*
305 * ustcomm_send_unix_sock
306 *
307 * Send buf data of size len. Using sendmsg API.
308 * Return the size of sent data.
309 */
310 ssize_t ustcomm_send_unix_sock(int sock, const void *buf, size_t len)
311 {
312 struct msghdr msg;
313 struct iovec iov[1];
314 ssize_t ret;
315
316 memset(&msg, 0, sizeof(msg));
317
318 iov[0].iov_base = (void *) buf;
319 iov[0].iov_len = len;
320 msg.msg_iov = iov;
321 msg.msg_iovlen = 1;
322
323 /*
324 * Using the MSG_NOSIGNAL when sending data from sessiond to
325 * libust, so libust does not receive an unhandled SIGPIPE or
326 * SIGURG. The sessiond receiver side can be made more resilient
327 * by ignoring SIGPIPE, but we don't have this luxury on the
328 * libust side.
329 */
330 do {
331 ret = sendmsg(sock, &msg, MSG_NOSIGNAL);
332 } while (ret < 0 && errno == EINTR);
333
334 if (ret < 0) {
335 if (errno != EPIPE && errno != ECONNRESET)
336 PERROR("sendmsg");
337 ret = -errno;
338 if (ret == -ECONNRESET)
339 ret = -EPIPE;
340
341 (void) ustcomm_shutdown_unix_sock(sock);
342 }
343
344 return ret;
345 }
346
347 /*
348 * Send a message accompanied by fd(s) over a unix socket.
349 *
350 * Returns the size of data sent, or negative error value.
351 */
352 ssize_t ustcomm_send_fds_unix_sock(int sock, int *fds, size_t nb_fd)
353 {
354 struct msghdr msg;
355 struct cmsghdr *cmptr;
356 struct iovec iov[1];
357 ssize_t ret = -1;
358 unsigned int sizeof_fds = nb_fd * sizeof(int);
359 char tmp[CMSG_SPACE(sizeof_fds)];
360 char dummy = 0;
361
362 memset(&msg, 0, sizeof(msg));
363 memset(tmp, 0, CMSG_SPACE(sizeof_fds) * sizeof(char));
364
365 if (nb_fd > USTCOMM_MAX_SEND_FDS)
366 return -EINVAL;
367
368 msg.msg_control = (caddr_t)tmp;
369 msg.msg_controllen = CMSG_LEN(sizeof_fds);
370
371 cmptr = CMSG_FIRSTHDR(&msg);
372 if (!cmptr)
373 return -EINVAL;
374 cmptr->cmsg_level = SOL_SOCKET;
375 cmptr->cmsg_type = SCM_RIGHTS;
376 cmptr->cmsg_len = CMSG_LEN(sizeof_fds);
377 memcpy(CMSG_DATA(cmptr), fds, sizeof_fds);
378 /* Sum of the length of all control messages in the buffer: */
379 msg.msg_controllen = cmptr->cmsg_len;
380
381 iov[0].iov_base = &dummy;
382 iov[0].iov_len = 1;
383 msg.msg_iov = iov;
384 msg.msg_iovlen = 1;
385
386 do {
387 ret = sendmsg(sock, &msg, MSG_NOSIGNAL);
388 } while (ret < 0 && errno == EINTR);
389 if (ret < 0) {
390 /*
391 * We consider EPIPE and ECONNRESET as expected.
392 */
393 if (errno != EPIPE && errno != ECONNRESET) {
394 PERROR("sendmsg");
395 }
396 ret = -errno;
397 if (ret == -ECONNRESET)
398 ret = -EPIPE;
399 }
400 return ret;
401 }
402
403 /*
404 * Recv a message accompanied by fd(s) from a unix socket.
405 *
406 * Expect at most "nb_fd" file descriptors. Returns the number of fd
407 * actually received in nb_fd.
408 * Returns -EPIPE on orderly shutdown.
409 */
410 ssize_t ustcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd)
411 {
412 struct iovec iov[1];
413 ssize_t ret = 0;
414 struct cmsghdr *cmsg;
415 size_t sizeof_fds = nb_fd * sizeof(int);
416 char recv_fd[CMSG_SPACE(sizeof_fds)];
417 struct msghdr msg;
418 char dummy;
419 int i;
420
421 memset(&msg, 0, sizeof(msg));
422
423 /* Prepare to receive the structures */
424 iov[0].iov_base = &dummy;
425 iov[0].iov_len = 1;
426 msg.msg_iov = iov;
427 msg.msg_iovlen = 1;
428 msg.msg_control = recv_fd;
429 msg.msg_controllen = sizeof(recv_fd);
430
431 do {
432 ret = recvmsg(sock, &msg, 0);
433 } while (ret < 0 && errno == EINTR);
434 if (ret < 0) {
435 if (errno != EPIPE && errno != ECONNRESET) {
436 PERROR("recvmsg fds");
437 }
438 ret = -errno;
439 if (ret == -ECONNRESET)
440 ret = -EPIPE;
441 goto end;
442 }
443 if (ret == 0) {
444 /* orderly shutdown */
445 ret = -EPIPE;
446 goto end;
447 }
448 if (ret != 1) {
449 ERR("Error: Received %zd bytes, expected %d\n",
450 ret, 1);
451 goto end;
452 }
453 if (msg.msg_flags & MSG_CTRUNC) {
454 ERR("Error: Control message truncated.\n");
455 ret = -1;
456 goto end;
457 }
458 cmsg = CMSG_FIRSTHDR(&msg);
459 if (!cmsg) {
460 ERR("Error: Invalid control message header\n");
461 ret = -1;
462 goto end;
463 }
464 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
465 ERR("Didn't received any fd\n");
466 ret = -1;
467 goto end;
468 }
469 if (cmsg->cmsg_len != CMSG_LEN(sizeof_fds)) {
470 ERR("Error: Received %zu bytes of ancillary data, expected %zu\n",
471 (size_t) cmsg->cmsg_len, (size_t) CMSG_LEN(sizeof_fds));
472 ret = -1;
473 goto end;
474 }
475
476 memcpy(fds, CMSG_DATA(cmsg), sizeof_fds);
477
478 /* Set FD_CLOEXEC */
479 for (i = 0; i < nb_fd; i++) {
480 ret = fcntl(fds[i], F_SETFD, FD_CLOEXEC);
481 if (ret < 0) {
482 PERROR("fcntl failed to set FD_CLOEXEC on fd %d",
483 fds[i]);
484 }
485 }
486
487 ret = nb_fd;
488 end:
489 return ret;
490 }
491
492 int ustcomm_send_app_msg(int sock, struct ustcomm_ust_msg *lum)
493 {
494 ssize_t len;
495
496 len = ustcomm_send_unix_sock(sock, lum, sizeof(*lum));
497 switch (len) {
498 case sizeof(*lum):
499 break;
500 default:
501 if (len < 0) {
502 return len;
503 } else {
504 ERR("incorrect message size: %zd\n", len);
505 return -EINVAL;
506 }
507 }
508 return 0;
509 }
510
511 int ustcomm_recv_app_reply(int sock, struct ustcomm_ust_reply *lur,
512 uint32_t expected_handle, uint32_t expected_cmd)
513 {
514 ssize_t len;
515
516 memset(lur, 0, sizeof(*lur));
517 len = ustcomm_recv_unix_sock(sock, lur, sizeof(*lur));
518 switch (len) {
519 case 0: /* orderly shutdown */
520 return -EPIPE;
521 case sizeof(*lur):
522 {
523 int err = 0;
524
525 if (lur->handle != expected_handle) {
526 ERR("Unexpected result message handle: "
527 "expected: %u vs received: %u\n",
528 expected_handle, lur->handle);
529 err = 1;
530 }
531 if (lur->cmd != expected_cmd) {
532 ERR("Unexpected result message command "
533 "expected: %u vs received: %u\n",
534 expected_cmd, lur->cmd);
535 err = 1;
536 }
537 if (err) {
538 return -EINVAL;
539 } else {
540 return lur->ret_code;
541 }
542 }
543 default:
544 if (len >= 0) {
545 ERR("incorrect message size: %zd\n", len);
546 }
547 return len;
548 }
549 }
550
551 int ustcomm_send_app_cmd(int sock,
552 struct ustcomm_ust_msg *lum,
553 struct ustcomm_ust_reply *lur)
554 {
555 int ret;
556
557 ret = ustcomm_send_app_msg(sock, lum);
558 if (ret)
559 return ret;
560 ret = ustcomm_recv_app_reply(sock, lur, lum->handle, lum->cmd);
561 if (ret > 0)
562 return -EIO;
563 return ret;
564 }
565
566 /*
567 * chan_data is allocated internally if this function returns the
568 * expected var_len.
569 */
570 ssize_t ustcomm_recv_channel_from_sessiond(int sock,
571 void **_chan_data, uint64_t var_len,
572 int *_wakeup_fd)
573 {
574 void *chan_data;
575 ssize_t len, nr_fd;
576 int wakeup_fd, ret;
577
578 if (var_len > LTTNG_UST_ABI_CHANNEL_DATA_MAX_LEN) {
579 len = -EINVAL;
580 goto error_check;
581 }
582 /* Receive variable length data */
583 chan_data = zmalloc(var_len);
584 if (!chan_data) {
585 len = -ENOMEM;
586 goto error_alloc;
587 }
588 len = ustcomm_recv_unix_sock(sock, chan_data, var_len);
589 if (len != var_len) {
590 goto error_recv;
591 }
592 /* recv wakeup fd */
593 lttng_ust_lock_fd_tracker();
594 nr_fd = ustcomm_recv_fds_unix_sock(sock, &wakeup_fd, 1);
595 if (nr_fd <= 0) {
596 lttng_ust_unlock_fd_tracker();
597 if (nr_fd < 0) {
598 len = nr_fd;
599 goto error_recv;
600 } else {
601 len = -EIO;
602 goto error_recv;
603 }
604 }
605
606 ret = lttng_ust_add_fd_to_tracker(wakeup_fd);
607 if (ret < 0) {
608 ret = close(wakeup_fd);
609 if (ret) {
610 PERROR("close on wakeup_fd");
611 }
612 len = -EIO;
613 lttng_ust_unlock_fd_tracker();
614 goto error_recv;
615 }
616
617 *_wakeup_fd = ret;
618 lttng_ust_unlock_fd_tracker();
619
620 *_chan_data = chan_data;
621 return len;
622
623 error_recv:
624 free(chan_data);
625 error_alloc:
626 error_check:
627 return len;
628 }
629
630 ssize_t ustcomm_recv_event_notifier_notif_fd_from_sessiond(int sock,
631 int *_event_notifier_notif_fd)
632 {
633 ssize_t nr_fd;
634 int event_notifier_notif_fd, ret;
635
636 /* Receive event_notifier notification fd */
637 lttng_ust_lock_fd_tracker();
638 nr_fd = ustcomm_recv_fds_unix_sock(sock, &event_notifier_notif_fd, 1);
639 if (nr_fd <= 0) {
640 lttng_ust_unlock_fd_tracker();
641 if (nr_fd < 0) {
642 ret = nr_fd;
643 goto error;
644 } else {
645 ret = -EIO;
646 goto error;
647 }
648 }
649
650 ret = lttng_ust_add_fd_to_tracker(event_notifier_notif_fd);
651 if (ret < 0) {
652 ret = close(event_notifier_notif_fd);
653 if (ret) {
654 PERROR("close on event_notifier notif fd");
655 }
656 ret = -EIO;
657 lttng_ust_unlock_fd_tracker();
658 goto error;
659 }
660
661 *_event_notifier_notif_fd = ret;
662 lttng_ust_unlock_fd_tracker();
663
664 ret = nr_fd;
665
666 error:
667 return ret;
668 }
669
670 int ustcomm_recv_stream_from_sessiond(int sock,
671 uint64_t *memory_map_size __attribute__((unused)),
672 int *shm_fd, int *wakeup_fd)
673 {
674 ssize_t len;
675 int ret;
676 int fds[2];
677
678 /* recv shm fd and wakeup fd */
679 lttng_ust_lock_fd_tracker();
680 len = ustcomm_recv_fds_unix_sock(sock, fds, 2);
681 if (len <= 0) {
682 lttng_ust_unlock_fd_tracker();
683 if (len < 0) {
684 ret = len;
685 goto error;
686 } else {
687 ret = -EIO;
688 goto error;
689 }
690 }
691
692 ret = lttng_ust_add_fd_to_tracker(fds[0]);
693 if (ret < 0) {
694 ret = close(fds[0]);
695 if (ret) {
696 PERROR("close on received shm_fd");
697 }
698 ret = -EIO;
699 lttng_ust_unlock_fd_tracker();
700 goto error;
701 }
702 *shm_fd = ret;
703
704 ret = lttng_ust_add_fd_to_tracker(fds[1]);
705 if (ret < 0) {
706 ret = close(*shm_fd);
707 if (ret) {
708 PERROR("close on shm_fd");
709 }
710 *shm_fd = -1;
711 ret = close(fds[1]);
712 if (ret) {
713 PERROR("close on received wakeup_fd");
714 }
715 ret = -EIO;
716 lttng_ust_unlock_fd_tracker();
717 goto error;
718 }
719 *wakeup_fd = ret;
720 lttng_ust_unlock_fd_tracker();
721 return 0;
722
723 error:
724 return ret;
725 }
726
727 ssize_t ustcomm_recv_counter_from_sessiond(int sock,
728 void **_counter_data, uint64_t var_len)
729 {
730 void *counter_data;
731 ssize_t len;
732
733 if (var_len > LTTNG_UST_ABI_COUNTER_DATA_MAX_LEN) {
734 len = -EINVAL;
735 goto error_check;
736 }
737 /* Receive variable length data */
738 counter_data = zmalloc(var_len);
739 if (!counter_data) {
740 len = -ENOMEM;
741 goto error_alloc;
742 }
743 len = ustcomm_recv_unix_sock(sock, counter_data, var_len);
744 if (len != var_len) {
745 goto error_recv;
746 }
747 *_counter_data = counter_data;
748 return len;
749
750 error_recv:
751 free(counter_data);
752 error_alloc:
753 error_check:
754 return len;
755 }
756
757 int ustcomm_recv_counter_shm_from_sessiond(int sock,
758 int *shm_fd)
759 {
760 ssize_t len;
761 int ret;
762 int fds[1];
763
764 /* recv shm fd fd */
765 lttng_ust_lock_fd_tracker();
766 len = ustcomm_recv_fds_unix_sock(sock, fds, 1);
767 if (len <= 0) {
768 lttng_ust_unlock_fd_tracker();
769 if (len < 0) {
770 ret = len;
771 goto error;
772 } else {
773 ret = -EIO;
774 goto error;
775 }
776 }
777
778 ret = lttng_ust_add_fd_to_tracker(fds[0]);
779 if (ret < 0) {
780 ret = close(fds[0]);
781 if (ret) {
782 PERROR("close on received shm_fd");
783 }
784 ret = -EIO;
785 lttng_ust_unlock_fd_tracker();
786 goto error;
787 }
788 *shm_fd = ret;
789 lttng_ust_unlock_fd_tracker();
790 return 0;
791
792 error:
793 return ret;
794 }
795
796 /*
797 * Returns 0 on success, negative error value on error.
798 */
799 int ustcomm_send_reg_msg(int sock,
800 enum lttng_ust_ctl_socket_type type,
801 uint32_t bits_per_long,
802 uint32_t uint8_t_alignment,
803 uint32_t uint16_t_alignment,
804 uint32_t uint32_t_alignment,
805 uint32_t uint64_t_alignment,
806 uint32_t long_alignment)
807 {
808 ssize_t len;
809 struct lttng_ust_ctl_reg_msg reg_msg;
810
811 reg_msg.magic = LTTNG_UST_ABI_COMM_MAGIC;
812 reg_msg.major = LTTNG_UST_ABI_MAJOR_VERSION;
813 reg_msg.minor = LTTNG_UST_ABI_MINOR_VERSION;
814 reg_msg.pid = getpid();
815 reg_msg.ppid = getppid();
816 reg_msg.uid = getuid();
817 reg_msg.gid = getgid();
818 reg_msg.bits_per_long = bits_per_long;
819 reg_msg.uint8_t_alignment = uint8_t_alignment;
820 reg_msg.uint16_t_alignment = uint16_t_alignment;
821 reg_msg.uint32_t_alignment = uint32_t_alignment;
822 reg_msg.uint64_t_alignment = uint64_t_alignment;
823 reg_msg.long_alignment = long_alignment;
824 reg_msg.socket_type = type;
825 lttng_pthread_getname_np(reg_msg.name, LTTNG_UST_ABI_PROCNAME_LEN);
826 memset(reg_msg.padding, 0, sizeof(reg_msg.padding));
827
828 len = ustcomm_send_unix_sock(sock, &reg_msg, sizeof(reg_msg));
829 if (len > 0 && len != sizeof(reg_msg))
830 return -EIO;
831 if (len < 0)
832 return len;
833 return 0;
834 }
835
836 static
837 ssize_t count_one_type(const struct lttng_ust_type_common *lt)
838 {
839 switch (lt->type) {
840 case lttng_ust_type_integer:
841 case lttng_ust_type_float:
842 case lttng_ust_type_string:
843 return 1;
844 case lttng_ust_type_enum:
845 return count_one_type(lttng_ust_get_type_enum(lt)->container_type) + 1;
846 case lttng_ust_type_array:
847 return count_one_type(lttng_ust_get_type_array(lt)->elem_type) + 1;
848 case lttng_ust_type_sequence:
849 return count_one_type(lttng_ust_get_type_sequence(lt)->elem_type) + 1;
850 case lttng_ust_type_struct:
851 return count_fields_recursive(lttng_ust_get_type_struct(lt)->nr_fields,
852 lttng_ust_get_type_struct(lt)->fields) + 1;
853
854 case lttng_ust_type_dynamic:
855 {
856 const struct lttng_ust_event_field * const *choices;
857 size_t nr_choices;
858 int ret;
859
860 ret = lttng_ust_dynamic_type_choices(&nr_choices,
861 &choices);
862 if (ret)
863 return ret;
864 /*
865 * Two fields for enum, one field for variant, and
866 * one field per choice.
867 */
868 return count_fields_recursive(nr_choices, choices) + 3;
869 }
870
871 default:
872 return -EINVAL;
873 }
874 return 0;
875 }
876
877 static
878 ssize_t count_fields_recursive(size_t nr_fields,
879 const struct lttng_ust_event_field * const *lttng_fields)
880 {
881 int i;
882 ssize_t ret, count = 0;
883
884 for (i = 0; i < nr_fields; i++) {
885 const struct lttng_ust_event_field *lf;
886
887 lf = lttng_fields[i];
888 /* skip 'nowrite' fields */
889 if (lf->nowrite)
890 continue;
891 ret = count_one_type(lf->type);
892 if (ret < 0)
893 return ret; /* error */
894 count += ret;
895 }
896 return count;
897 }
898
899 static
900 ssize_t count_ctx_fields_recursive(size_t nr_fields,
901 struct lttng_ust_ctx_field *lttng_fields)
902 {
903 int i;
904 ssize_t ret, count = 0;
905
906 for (i = 0; i < nr_fields; i++) {
907 const struct lttng_ust_event_field *lf;
908
909 lf = lttng_fields[i].event_field;
910 /* skip 'nowrite' fields */
911 if (lf->nowrite)
912 continue;
913 ret = count_one_type(lf->type);
914 if (ret < 0)
915 return ret; /* error */
916 count += ret;
917 }
918 return count;
919 }
920
921 static
922 int serialize_string_encoding(int32_t *ue,
923 enum lttng_ust_string_encoding le)
924 {
925 switch (le) {
926 case lttng_ust_string_encoding_none:
927 *ue = lttng_ust_ctl_encode_none;
928 break;
929 case lttng_ust_string_encoding_UTF8:
930 *ue = lttng_ust_ctl_encode_UTF8;
931 break;
932 case lttng_ust_string_encoding_ASCII:
933 *ue = lttng_ust_ctl_encode_ASCII;
934 break;
935 default:
936 return -EINVAL;
937 }
938 return 0;
939 }
940
941 static
942 int serialize_integer_type(struct lttng_ust_ctl_integer_type *uit,
943 const struct lttng_ust_type_integer *lit,
944 enum lttng_ust_string_encoding lencoding)
945 {
946 int32_t encoding;
947
948 uit->size = lit->size;
949 uit->signedness = lit->signedness;
950 uit->reverse_byte_order = lit->reverse_byte_order;
951 uit->base = lit->base;
952 if (serialize_string_encoding(&encoding, lencoding))
953 return -EINVAL;
954 uit->encoding = encoding;
955 uit->alignment = lit->alignment;
956 return 0;
957 }
958
959 static
960 int serialize_dynamic_type(struct lttng_ust_session *session,
961 struct lttng_ust_ctl_field *fields, size_t *iter_output,
962 const char *field_name)
963 {
964 const struct lttng_ust_event_field * const *choices;
965 char tag_field_name[LTTNG_UST_ABI_SYM_NAME_LEN];
966 const struct lttng_ust_type_common *tag_type;
967 const struct lttng_ust_event_field *tag_field_generic;
968 struct lttng_ust_event_field tag_field = {
969 .name = tag_field_name,
970 .nowrite = 0,
971 };
972 struct lttng_ust_ctl_field *uf;
973 size_t nr_choices, i;
974 int ret;
975
976 tag_field_generic = lttng_ust_dynamic_type_tag_field();
977 tag_type = tag_field_generic->type;
978
979 /* Serialize enum field. */
980 strncpy(tag_field_name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
981 tag_field_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
982 strncat(tag_field_name,
983 "_tag",
984 LTTNG_UST_ABI_SYM_NAME_LEN - strlen(tag_field_name) - 1);
985 tag_field.type = tag_type;
986 ret = serialize_one_field(session, fields, iter_output,
987 &tag_field, NULL);
988 if (ret)
989 return ret;
990
991 /* Serialize variant field. */
992 uf = &fields[*iter_output];
993 ret = lttng_ust_dynamic_type_choices(&nr_choices, &choices);
994 if (ret)
995 return ret;
996
997 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
998 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
999 uf->type.atype = lttng_ust_ctl_atype_variant;
1000 uf->type.u.variant_nestable.nr_choices = nr_choices;
1001 strncpy(uf->type.u.variant_nestable.tag_name,
1002 tag_field_name,
1003 LTTNG_UST_ABI_SYM_NAME_LEN);
1004 uf->type.u.variant_nestable.tag_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1005 uf->type.u.variant_nestable.alignment = 0;
1006 (*iter_output)++;
1007
1008 /* Serialize choice fields after variant. */
1009 for (i = 0; i < nr_choices; i++) {
1010 ret = serialize_one_field(session, fields,
1011 iter_output, choices[i], NULL);
1012 if (ret)
1013 return ret;
1014 }
1015 return 0;
1016 }
1017
1018 static
1019 int serialize_one_type(struct lttng_ust_session *session,
1020 struct lttng_ust_ctl_field *fields, size_t *iter_output,
1021 const char *field_name, const struct lttng_ust_type_common *lt,
1022 enum lttng_ust_string_encoding parent_encoding,
1023 const char *prev_field_name)
1024 {
1025 int ret;
1026
1027 /*
1028 * Serializing a type (rather than a field) generates a lttng_ust_ctl_field
1029 * entry with 0-length name.
1030 */
1031
1032 switch (lt->type) {
1033 case lttng_ust_type_integer:
1034 {
1035 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1036 struct lttng_ust_ctl_type *ut = &uf->type;
1037
1038 if (field_name) {
1039 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1040 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1041 } else {
1042 uf->name[0] = '\0';
1043 }
1044 ret = serialize_integer_type(&ut->u.integer, lttng_ust_get_type_integer(lt),
1045 parent_encoding);
1046 if (ret)
1047 return ret;
1048 ut->atype = lttng_ust_ctl_atype_integer;
1049 (*iter_output)++;
1050 break;
1051 }
1052 case lttng_ust_type_float:
1053 {
1054 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1055 struct lttng_ust_ctl_type *ut = &uf->type;
1056 struct lttng_ust_ctl_float_type *uft;
1057 const struct lttng_ust_type_float *lft;
1058
1059 if (field_name) {
1060 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1061 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1062 } else {
1063 uf->name[0] = '\0';
1064 }
1065 uft = &ut->u._float;
1066 lft = lttng_ust_get_type_float(lt);
1067 uft->exp_dig = lft->exp_dig;
1068 uft->mant_dig = lft->mant_dig;
1069 uft->alignment = lft->alignment;
1070 uft->reverse_byte_order = lft->reverse_byte_order;
1071 ut->atype = lttng_ust_ctl_atype_float;
1072 (*iter_output)++;
1073 break;
1074 }
1075 case lttng_ust_type_string:
1076 {
1077 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1078 struct lttng_ust_ctl_type *ut = &uf->type;
1079 int32_t encoding;
1080
1081 if (field_name) {
1082 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1083 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1084 } else {
1085 uf->name[0] = '\0';
1086 }
1087 ret = serialize_string_encoding(&encoding, lttng_ust_get_type_string(lt)->encoding);
1088 if (ret)
1089 return ret;
1090 ut->u.string.encoding = encoding;
1091 ut->atype = lttng_ust_ctl_atype_string;
1092 (*iter_output)++;
1093 break;
1094 }
1095 case lttng_ust_type_array:
1096 {
1097 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1098 struct lttng_ust_ctl_type *ut = &uf->type;
1099
1100 if (field_name) {
1101 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1102 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1103 } else {
1104 uf->name[0] = '\0';
1105 }
1106 ut->atype = lttng_ust_ctl_atype_array_nestable;
1107 ut->u.array_nestable.length = lttng_ust_get_type_array(lt)->length;
1108 ut->u.array_nestable.alignment = lttng_ust_get_type_array(lt)->alignment;
1109 (*iter_output)++;
1110
1111 ret = serialize_one_type(session, fields, iter_output, NULL,
1112 lttng_ust_get_type_array(lt)->elem_type,
1113 lttng_ust_get_type_array(lt)->encoding, NULL);
1114 if (ret)
1115 return -EINVAL;
1116 break;
1117 }
1118 case lttng_ust_type_sequence:
1119 {
1120 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1121 struct lttng_ust_ctl_type *ut = &uf->type;
1122 const char *length_name = lttng_ust_get_type_sequence(lt)->length_name;
1123
1124 if (field_name) {
1125 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1126 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1127 } else {
1128 uf->name[0] = '\0';
1129 }
1130 ut->atype = lttng_ust_ctl_atype_sequence_nestable;
1131 /*
1132 * If length_name field is NULL, use the previous field
1133 * as length.
1134 */
1135 if (!length_name)
1136 length_name = prev_field_name;
1137 if (!length_name)
1138 return -EINVAL;
1139 strncpy(ut->u.sequence_nestable.length_name,
1140 length_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1141 ut->u.sequence_nestable.length_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1142 ut->u.sequence_nestable.alignment = lttng_ust_get_type_sequence(lt)->alignment;
1143 (*iter_output)++;
1144
1145 ret = serialize_one_type(session, fields, iter_output, NULL,
1146 lttng_ust_get_type_sequence(lt)->elem_type,
1147 lttng_ust_get_type_sequence(lt)->encoding, NULL);
1148 if (ret)
1149 return -EINVAL;
1150 break;
1151 }
1152 case lttng_ust_type_dynamic:
1153 {
1154 ret = serialize_dynamic_type(session, fields, iter_output,
1155 field_name);
1156 if (ret)
1157 return -EINVAL;
1158 break;
1159 }
1160 case lttng_ust_type_struct:
1161 {
1162 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1163
1164 if (field_name) {
1165 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1166 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1167 } else {
1168 uf->name[0] = '\0';
1169 }
1170 uf->type.atype = lttng_ust_ctl_atype_struct_nestable;
1171 uf->type.u.struct_nestable.nr_fields = lttng_ust_get_type_struct(lt)->nr_fields;
1172 uf->type.u.struct_nestable.alignment = lttng_ust_get_type_struct(lt)->alignment;
1173 (*iter_output)++;
1174
1175 ret = serialize_fields(session, fields, iter_output,
1176 lttng_ust_get_type_struct(lt)->nr_fields,
1177 lttng_ust_get_type_struct(lt)->fields);
1178 if (ret)
1179 return -EINVAL;
1180 break;
1181 }
1182 case lttng_ust_type_enum:
1183 {
1184 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1185 struct lttng_ust_ctl_type *ut = &uf->type;
1186
1187 if (field_name) {
1188 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1189 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1190 } else {
1191 uf->name[0] = '\0';
1192 }
1193 strncpy(ut->u.enum_nestable.name, lttng_ust_get_type_enum(lt)->desc->name,
1194 LTTNG_UST_ABI_SYM_NAME_LEN);
1195 ut->u.enum_nestable.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1196 ut->atype = lttng_ust_ctl_atype_enum_nestable;
1197 (*iter_output)++;
1198
1199 ret = serialize_one_type(session, fields, iter_output, NULL,
1200 lttng_ust_get_type_enum(lt)->container_type,
1201 lttng_ust_string_encoding_none, NULL);
1202 if (ret)
1203 return -EINVAL;
1204 if (session) {
1205 const struct lttng_enum *_enum;
1206
1207 _enum = lttng_ust_enum_get_from_desc(session, lttng_ust_get_type_enum(lt)->desc);
1208 if (!_enum)
1209 return -EINVAL;
1210 ut->u.enum_nestable.id = _enum->id;
1211 } else {
1212 ut->u.enum_nestable.id = -1ULL;
1213 }
1214 break;
1215 }
1216 default:
1217 return -EINVAL;
1218 }
1219 return 0;
1220 }
1221
1222 static
1223 int serialize_one_field(struct lttng_ust_session *session,
1224 struct lttng_ust_ctl_field *fields, size_t *iter_output,
1225 const struct lttng_ust_event_field *lf,
1226 const char **prev_field_name_p)
1227 {
1228 const char *prev_field_name = NULL;
1229 int ret;
1230
1231 /* skip 'nowrite' fields */
1232 if (lf->nowrite)
1233 return 0;
1234
1235 if (prev_field_name_p)
1236 prev_field_name = *prev_field_name_p;
1237 ret = serialize_one_type(session, fields, iter_output, lf->name, lf->type,
1238 lttng_ust_string_encoding_none, prev_field_name);
1239 if (prev_field_name_p)
1240 *prev_field_name_p = lf->name;
1241 return ret;
1242 }
1243
1244 static
1245 int serialize_fields(struct lttng_ust_session *session,
1246 struct lttng_ust_ctl_field *lttng_ust_ctl_fields,
1247 size_t *iter_output, size_t nr_lttng_fields,
1248 const struct lttng_ust_event_field * const *lttng_fields)
1249 {
1250 const char *prev_field_name = NULL;
1251 int ret;
1252 size_t i;
1253
1254 for (i = 0; i < nr_lttng_fields; i++) {
1255 ret = serialize_one_field(session, lttng_ust_ctl_fields,
1256 iter_output, lttng_fields[i],
1257 &prev_field_name);
1258 if (ret)
1259 return ret;
1260 }
1261 return 0;
1262 }
1263
1264 static
1265 int alloc_serialize_fields(struct lttng_ust_session *session,
1266 size_t *_nr_write_fields,
1267 struct lttng_ust_ctl_field **lttng_ust_ctl_fields,
1268 size_t nr_fields,
1269 const struct lttng_ust_event_field * const *lttng_fields)
1270 {
1271 struct lttng_ust_ctl_field *fields;
1272 int ret;
1273 size_t iter_output = 0;
1274 ssize_t nr_write_fields;
1275
1276 nr_write_fields = count_fields_recursive(nr_fields, lttng_fields);
1277 if (nr_write_fields < 0) {
1278 return (int) nr_write_fields;
1279 }
1280
1281 fields = zmalloc(nr_write_fields * sizeof(*fields));
1282 if (!fields)
1283 return -ENOMEM;
1284
1285 ret = serialize_fields(session, fields, &iter_output, nr_fields,
1286 lttng_fields);
1287 if (ret)
1288 goto error_type;
1289
1290 *_nr_write_fields = nr_write_fields;
1291 *lttng_ust_ctl_fields = fields;
1292 return 0;
1293
1294 error_type:
1295 free(fields);
1296 return ret;
1297 }
1298
1299 static
1300 int serialize_entries(struct lttng_ust_ctl_enum_entry **_entries,
1301 size_t nr_entries,
1302 const struct lttng_ust_enum_entry * const *lttng_entries)
1303 {
1304 struct lttng_ust_ctl_enum_entry *entries;
1305 int i;
1306
1307 /* Serialize the entries */
1308 entries = zmalloc(nr_entries * sizeof(*entries));
1309 if (!entries)
1310 return -ENOMEM;
1311 for (i = 0; i < nr_entries; i++) {
1312 struct lttng_ust_ctl_enum_entry *uentry;
1313 const struct lttng_ust_enum_entry *lentry;
1314
1315 uentry = &entries[i];
1316 lentry = lttng_entries[i];
1317
1318 uentry->start.value = lentry->start.value;
1319 uentry->start.signedness = lentry->start.signedness;
1320 uentry->end.value = lentry->end.value;
1321 uentry->end.signedness = lentry->end.signedness;
1322 strncpy(uentry->string, lentry->string, LTTNG_UST_ABI_SYM_NAME_LEN);
1323 uentry->string[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1324
1325 if (lentry->options & LTTNG_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
1326 uentry->u.extra.options |=
1327 LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO;
1328 }
1329 }
1330 *_entries = entries;
1331 return 0;
1332 }
1333
1334 static
1335 int serialize_ctx_fields(struct lttng_ust_session *session,
1336 size_t *_nr_write_fields,
1337 struct lttng_ust_ctl_field **lttng_ust_ctl_fields,
1338 size_t nr_fields,
1339 struct lttng_ust_ctx_field *lttng_fields)
1340 {
1341 struct lttng_ust_ctl_field *fields;
1342 const char *prev_field_name = NULL;
1343 size_t i, iter_output = 0;
1344 ssize_t nr_write_fields;
1345 int ret;
1346
1347 nr_write_fields = count_ctx_fields_recursive(nr_fields,
1348 lttng_fields);
1349 if (nr_write_fields < 0) {
1350 return (int) nr_write_fields;
1351 }
1352
1353 fields = zmalloc(nr_write_fields * sizeof(*fields));
1354 if (!fields)
1355 return -ENOMEM;
1356
1357 for (i = 0; i < nr_fields; i++) {
1358 ret = serialize_one_field(session, fields, &iter_output,
1359 lttng_fields[i].event_field, &prev_field_name);
1360 if (ret)
1361 goto error_type;
1362 }
1363
1364 *_nr_write_fields = nr_write_fields;
1365 *lttng_ust_ctl_fields = fields;
1366 return 0;
1367
1368 error_type:
1369 free(fields);
1370 return ret;
1371 }
1372
1373 /*
1374 * Returns 0 on success, negative error value on error.
1375 */
1376 int ustcomm_register_event(int sock,
1377 struct lttng_ust_session *session,
1378 int session_objd, /* session descriptor */
1379 int channel_objd, /* channel descriptor */
1380 const char *event_name, /* event name (input) */
1381 int loglevel,
1382 const char *signature, /* event signature (input) */
1383 size_t nr_fields, /* fields */
1384 const struct lttng_ust_event_field * const *lttng_fields,
1385 const char *model_emf_uri,
1386 uint32_t *id) /* event id (output) */
1387 {
1388 ssize_t len;
1389 struct {
1390 struct ustcomm_notify_hdr header;
1391 struct ustcomm_notify_event_msg m;
1392 } msg;
1393 struct {
1394 struct ustcomm_notify_hdr header;
1395 struct ustcomm_notify_event_reply r;
1396 } reply;
1397 size_t signature_len, fields_len, model_emf_uri_len;
1398 struct lttng_ust_ctl_field *fields = NULL;
1399 size_t nr_write_fields = 0;
1400 int ret;
1401
1402 memset(&msg, 0, sizeof(msg));
1403 msg.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_EVENT;
1404 msg.m.session_objd = session_objd;
1405 msg.m.channel_objd = channel_objd;
1406 strncpy(msg.m.event_name, event_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1407 msg.m.event_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1408 msg.m.loglevel = loglevel;
1409 signature_len = strlen(signature) + 1;
1410 msg.m.signature_len = signature_len;
1411
1412 /* Calculate fields len, serialize fields. */
1413 if (nr_fields > 0) {
1414 ret = alloc_serialize_fields(session, &nr_write_fields, &fields,
1415 nr_fields, lttng_fields);
1416 if (ret)
1417 return ret;
1418 }
1419
1420 fields_len = sizeof(*fields) * nr_write_fields;
1421 msg.m.fields_len = fields_len;
1422 if (model_emf_uri) {
1423 model_emf_uri_len = strlen(model_emf_uri) + 1;
1424 } else {
1425 model_emf_uri_len = 0;
1426 }
1427 msg.m.model_emf_uri_len = model_emf_uri_len;
1428
1429 len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
1430 if (len > 0 && len != sizeof(msg)) {
1431 ret = -EIO;
1432 goto error_fields;
1433 }
1434 if (len < 0) {
1435 ret = len;
1436 goto error_fields;
1437 }
1438
1439 /* send signature */
1440 len = ustcomm_send_unix_sock(sock, signature, signature_len);
1441 if (len > 0 && len != signature_len) {
1442 ret = -EIO;
1443 goto error_fields;
1444 }
1445 if (len < 0) {
1446 ret = len;
1447 goto error_fields;
1448 }
1449
1450 /* send fields */
1451 if (fields_len > 0) {
1452 len = ustcomm_send_unix_sock(sock, fields, fields_len);
1453 if (len > 0 && len != fields_len) {
1454 ret = -EIO;
1455 goto error_fields;
1456 }
1457 if (len < 0) {
1458 ret = len;
1459 goto error_fields;
1460 }
1461 }
1462 free(fields);
1463
1464 if (model_emf_uri_len) {
1465 /* send model_emf_uri */
1466 len = ustcomm_send_unix_sock(sock, model_emf_uri,
1467 model_emf_uri_len);
1468 if (len > 0 && len != model_emf_uri_len) {
1469 return -EIO;
1470 }
1471 if (len < 0) {
1472 return len;
1473 }
1474 }
1475
1476 /* receive reply */
1477 len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
1478 switch (len) {
1479 case 0: /* orderly shutdown */
1480 return -EPIPE;
1481 case sizeof(reply):
1482 if (reply.header.notify_cmd != msg.header.notify_cmd) {
1483 ERR("Unexpected result message command "
1484 "expected: %u vs received: %u\n",
1485 msg.header.notify_cmd, reply.header.notify_cmd);
1486 return -EINVAL;
1487 }
1488 if (reply.r.ret_code > 0)
1489 return -EINVAL;
1490 if (reply.r.ret_code < 0)
1491 return reply.r.ret_code;
1492 *id = reply.r.event_id;
1493 DBG("Sent register event notification for name \"%s\": ret_code %d, event_id %u\n",
1494 event_name, reply.r.ret_code, reply.r.event_id);
1495 return 0;
1496 default:
1497 if (len < 0) {
1498 /* Transport level error */
1499 if (errno == EPIPE || errno == ECONNRESET)
1500 len = -errno;
1501 return len;
1502 } else {
1503 ERR("incorrect message size: %zd\n", len);
1504 return len;
1505 }
1506 }
1507 /* Unreached. */
1508
1509 /* Error path only. */
1510 error_fields:
1511 free(fields);
1512 return ret;
1513 }
1514
1515 /*
1516 * Returns 0 on success, negative error value on error.
1517 * Returns -EPIPE or -ECONNRESET if other end has hung up.
1518 */
1519 int ustcomm_register_enum(int sock,
1520 int session_objd, /* session descriptor */
1521 const char *enum_name, /* enum name (input) */
1522 size_t nr_entries, /* entries */
1523 const struct lttng_ust_enum_entry * const *lttng_entries,
1524 uint64_t *id)
1525 {
1526 ssize_t len;
1527 struct {
1528 struct ustcomm_notify_hdr header;
1529 struct ustcomm_notify_enum_msg m;
1530 } msg;
1531 struct {
1532 struct ustcomm_notify_hdr header;
1533 struct ustcomm_notify_enum_reply r;
1534 } reply;
1535 size_t entries_len;
1536 struct lttng_ust_ctl_enum_entry *entries = NULL;
1537 int ret;
1538
1539 memset(&msg, 0, sizeof(msg));
1540 msg.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_ENUM;
1541 msg.m.session_objd = session_objd;
1542 strncpy(msg.m.enum_name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1543 msg.m.enum_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1544
1545 /* Calculate entries len, serialize entries. */
1546 if (nr_entries > 0) {
1547 ret = serialize_entries(&entries,
1548 nr_entries, lttng_entries);
1549 if (ret)
1550 return ret;
1551 }
1552
1553 entries_len = sizeof(*entries) * nr_entries;
1554 msg.m.entries_len = entries_len;
1555
1556 len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
1557 if (len > 0 && len != sizeof(msg)) {
1558 ret = -EIO;
1559 goto error_entries;
1560 }
1561 if (len < 0) {
1562 ret = len;
1563 goto error_entries;
1564 }
1565
1566 /* send entries */
1567 if (entries_len > 0) {
1568 len = ustcomm_send_unix_sock(sock, entries, entries_len);
1569 if (len > 0 && len != entries_len) {
1570 ret = -EIO;
1571 goto error_entries;
1572 }
1573 if (len < 0) {
1574 ret = len;
1575 goto error_entries;
1576 }
1577 }
1578 free(entries);
1579 entries = NULL;
1580
1581 /* receive reply */
1582 len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
1583 switch (len) {
1584 case 0: /* orderly shutdown */
1585 return -EPIPE;
1586 case sizeof(reply):
1587 if (reply.header.notify_cmd != msg.header.notify_cmd) {
1588 ERR("Unexpected result message command "
1589 "expected: %u vs received: %u\n",
1590 msg.header.notify_cmd, reply.header.notify_cmd);
1591 return -EINVAL;
1592 }
1593 if (reply.r.ret_code > 0)
1594 return -EINVAL;
1595 if (reply.r.ret_code < 0)
1596 return reply.r.ret_code;
1597 *id = reply.r.enum_id;
1598 DBG("Sent register enum notification for name \"%s\": ret_code %d\n",
1599 enum_name, reply.r.ret_code);
1600 return 0;
1601 default:
1602 if (len < 0) {
1603 /* Transport level error */
1604 if (errno == EPIPE || errno == ECONNRESET)
1605 len = -errno;
1606 return len;
1607 } else {
1608 ERR("incorrect message size: %zd\n", len);
1609 return len;
1610 }
1611 }
1612 return ret;
1613
1614 error_entries:
1615 free(entries);
1616 return ret;
1617 }
1618
1619 /*
1620 * Returns 0 on success, negative error value on error.
1621 * Returns -EPIPE or -ECONNRESET if other end has hung up.
1622 */
1623 int ustcomm_register_channel(int sock,
1624 struct lttng_ust_session *session,
1625 int session_objd, /* session descriptor */
1626 int channel_objd, /* channel descriptor */
1627 size_t nr_ctx_fields,
1628 struct lttng_ust_ctx_field *ctx_fields,
1629 uint32_t *chan_id, /* channel id (output) */
1630 int *header_type) /* header type (output) */
1631 {
1632 ssize_t len;
1633 struct {
1634 struct ustcomm_notify_hdr header;
1635 struct ustcomm_notify_channel_msg m;
1636 } msg;
1637 struct {
1638 struct ustcomm_notify_hdr header;
1639 struct ustcomm_notify_channel_reply r;
1640 } reply;
1641 size_t fields_len;
1642 struct lttng_ust_ctl_field *fields = NULL;
1643 int ret;
1644 size_t nr_write_fields = 0;
1645
1646 memset(&msg, 0, sizeof(msg));
1647 msg.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_CHANNEL;
1648 msg.m.session_objd = session_objd;
1649 msg.m.channel_objd = channel_objd;
1650
1651 /* Calculate fields len, serialize fields. */
1652 if (nr_ctx_fields > 0) {
1653 ret = serialize_ctx_fields(session, &nr_write_fields, &fields,
1654 nr_ctx_fields, ctx_fields);
1655 if (ret)
1656 return ret;
1657 }
1658
1659 fields_len = sizeof(*fields) * nr_write_fields;
1660 msg.m.ctx_fields_len = fields_len;
1661 len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
1662 if (len > 0 && len != sizeof(msg)) {
1663 free(fields);
1664 return -EIO;
1665 }
1666 if (len < 0) {
1667 free(fields);
1668 return len;
1669 }
1670
1671 /* send fields */
1672 if (fields_len > 0) {
1673 len = ustcomm_send_unix_sock(sock, fields, fields_len);
1674 free(fields);
1675 if (len > 0 && len != fields_len) {
1676 return -EIO;
1677 }
1678 if (len < 0) {
1679 return len;
1680 }
1681 } else {
1682 free(fields);
1683 }
1684
1685 len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
1686 switch (len) {
1687 case 0: /* orderly shutdown */
1688 return -EPIPE;
1689 case sizeof(reply):
1690 if (reply.header.notify_cmd != msg.header.notify_cmd) {
1691 ERR("Unexpected result message command "
1692 "expected: %u vs received: %u\n",
1693 msg.header.notify_cmd, reply.header.notify_cmd);
1694 return -EINVAL;
1695 }
1696 if (reply.r.ret_code > 0)
1697 return -EINVAL;
1698 if (reply.r.ret_code < 0)
1699 return reply.r.ret_code;
1700 *chan_id = reply.r.chan_id;
1701 switch (reply.r.header_type) {
1702 case 1:
1703 case 2:
1704 *header_type = reply.r.header_type;
1705 break;
1706 default:
1707 ERR("Unexpected channel header type %u\n",
1708 reply.r.header_type);
1709 return -EINVAL;
1710 }
1711 DBG("Sent register channel notification: chan_id %d, header_type %d\n",
1712 reply.r.chan_id, reply.r.header_type);
1713 return 0;
1714 default:
1715 if (len < 0) {
1716 /* Transport level error */
1717 if (errno == EPIPE || errno == ECONNRESET)
1718 len = -errno;
1719 return len;
1720 } else {
1721 ERR("incorrect message size: %zd\n", len);
1722 return len;
1723 }
1724 }
1725 }
1726
1727 /*
1728 * Set socket reciving timeout.
1729 */
1730 int ustcomm_setsockopt_rcv_timeout(int sock, unsigned int msec)
1731 {
1732 int ret;
1733 struct timeval tv;
1734
1735 tv.tv_sec = msec / 1000;
1736 tv.tv_usec = (msec * 1000 % 1000000);
1737
1738 ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
1739 if (ret < 0) {
1740 PERROR("setsockopt SO_RCVTIMEO");
1741 ret = -errno;
1742 }
1743
1744 return ret;
1745 }
1746
1747 /*
1748 * Set socket sending timeout.
1749 */
1750 int ustcomm_setsockopt_snd_timeout(int sock, unsigned int msec)
1751 {
1752 int ret;
1753 struct timeval tv;
1754
1755 tv.tv_sec = msec / 1000;
1756 tv.tv_usec = (msec * 1000) % 1000000;
1757
1758 ret = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
1759 if (ret < 0) {
1760 PERROR("setsockopt SO_SNDTIMEO");
1761 ret = -errno;
1762 }
1763
1764 return ret;
1765 }
This page took 0.125322 seconds and 4 git commands to generate.