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