6dfec5eac4d68f047e14855a579ee156921d9f00
[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 const char *procname)
808 {
809 ssize_t len;
810 struct lttng_ust_ctl_reg_msg reg_msg;
811
812 reg_msg.magic = LTTNG_UST_ABI_COMM_MAGIC;
813 reg_msg.major = LTTNG_UST_ABI_MAJOR_VERSION;
814 reg_msg.minor = LTTNG_UST_ABI_MINOR_VERSION;
815 reg_msg.pid = getpid();
816 reg_msg.ppid = getppid();
817 reg_msg.uid = getuid();
818 reg_msg.gid = getgid();
819 reg_msg.bits_per_long = bits_per_long;
820 reg_msg.uint8_t_alignment = uint8_t_alignment;
821 reg_msg.uint16_t_alignment = uint16_t_alignment;
822 reg_msg.uint32_t_alignment = uint32_t_alignment;
823 reg_msg.uint64_t_alignment = uint64_t_alignment;
824 reg_msg.long_alignment = long_alignment;
825 reg_msg.socket_type = type;
826 memset(reg_msg.name, 0, sizeof(reg_msg.name));
827 strncpy(reg_msg.name, procname, sizeof(reg_msg.name) - 1);
828 memset(reg_msg.padding, 0, sizeof(reg_msg.padding));
829
830 len = ustcomm_send_unix_sock(sock, &reg_msg, sizeof(reg_msg));
831 if (len > 0 && len != sizeof(reg_msg))
832 return -EIO;
833 if (len < 0)
834 return len;
835 return 0;
836 }
837
838 static
839 ssize_t count_one_type(const struct lttng_ust_type_common *lt)
840 {
841 switch (lt->type) {
842 case lttng_ust_type_integer:
843 case lttng_ust_type_float:
844 case lttng_ust_type_string:
845 return 1;
846 case lttng_ust_type_enum:
847 return count_one_type(lttng_ust_get_type_enum(lt)->container_type) + 1;
848 case lttng_ust_type_array:
849 return count_one_type(lttng_ust_get_type_array(lt)->elem_type) + 1;
850 case lttng_ust_type_sequence:
851 return count_one_type(lttng_ust_get_type_sequence(lt)->elem_type) + 1;
852 case lttng_ust_type_struct:
853 return count_fields_recursive(lttng_ust_get_type_struct(lt)->nr_fields,
854 lttng_ust_get_type_struct(lt)->fields) + 1;
855
856 case lttng_ust_type_dynamic:
857 {
858 const struct lttng_ust_event_field * const *choices;
859 size_t nr_choices;
860 int ret;
861
862 ret = lttng_ust_dynamic_type_choices(&nr_choices,
863 &choices);
864 if (ret)
865 return ret;
866 /*
867 * Two fields for enum, one field for variant, and
868 * one field per choice.
869 */
870 return count_fields_recursive(nr_choices, choices) + 3;
871 }
872
873 default:
874 return -EINVAL;
875 }
876 return 0;
877 }
878
879 static
880 ssize_t count_fields_recursive(size_t nr_fields,
881 const struct lttng_ust_event_field * const *lttng_fields)
882 {
883 int i;
884 ssize_t ret, count = 0;
885
886 for (i = 0; i < nr_fields; i++) {
887 const struct lttng_ust_event_field *lf;
888
889 lf = lttng_fields[i];
890 /* skip 'nowrite' fields */
891 if (lf->nowrite)
892 continue;
893 ret = count_one_type(lf->type);
894 if (ret < 0)
895 return ret; /* error */
896 count += ret;
897 }
898 return count;
899 }
900
901 static
902 ssize_t count_ctx_fields_recursive(size_t nr_fields,
903 struct lttng_ust_ctx_field *lttng_fields)
904 {
905 int i;
906 ssize_t ret, count = 0;
907
908 for (i = 0; i < nr_fields; i++) {
909 const struct lttng_ust_event_field *lf;
910
911 lf = lttng_fields[i].event_field;
912 /* skip 'nowrite' fields */
913 if (lf->nowrite)
914 continue;
915 ret = count_one_type(lf->type);
916 if (ret < 0)
917 return ret; /* error */
918 count += ret;
919 }
920 return count;
921 }
922
923 static
924 int serialize_string_encoding(int32_t *ue,
925 enum lttng_ust_string_encoding le)
926 {
927 switch (le) {
928 case lttng_ust_string_encoding_none:
929 *ue = lttng_ust_ctl_encode_none;
930 break;
931 case lttng_ust_string_encoding_UTF8:
932 *ue = lttng_ust_ctl_encode_UTF8;
933 break;
934 case lttng_ust_string_encoding_ASCII:
935 *ue = lttng_ust_ctl_encode_ASCII;
936 break;
937 default:
938 return -EINVAL;
939 }
940 return 0;
941 }
942
943 static
944 int serialize_integer_type(struct lttng_ust_ctl_integer_type *uit,
945 const struct lttng_ust_type_integer *lit,
946 enum lttng_ust_string_encoding lencoding)
947 {
948 int32_t encoding;
949
950 uit->size = lit->size;
951 uit->signedness = lit->signedness;
952 uit->reverse_byte_order = lit->reverse_byte_order;
953 uit->base = lit->base;
954 if (serialize_string_encoding(&encoding, lencoding))
955 return -EINVAL;
956 uit->encoding = encoding;
957 uit->alignment = lit->alignment;
958 return 0;
959 }
960
961 static
962 int serialize_dynamic_type(struct lttng_ust_session *session,
963 struct lttng_ust_ctl_field *fields, size_t *iter_output,
964 const char *field_name)
965 {
966 const struct lttng_ust_event_field * const *choices;
967 char tag_field_name[LTTNG_UST_ABI_SYM_NAME_LEN];
968 const struct lttng_ust_type_common *tag_type;
969 const struct lttng_ust_event_field *tag_field_generic;
970 struct lttng_ust_event_field tag_field = {
971 .name = tag_field_name,
972 .nowrite = 0,
973 };
974 struct lttng_ust_ctl_field *uf;
975 size_t nr_choices, i;
976 int ret;
977
978 tag_field_generic = lttng_ust_dynamic_type_tag_field();
979 tag_type = tag_field_generic->type;
980
981 /* Serialize enum field. */
982 strncpy(tag_field_name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
983 tag_field_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
984 strncat(tag_field_name,
985 "_tag",
986 LTTNG_UST_ABI_SYM_NAME_LEN - strlen(tag_field_name) - 1);
987 tag_field.type = tag_type;
988 ret = serialize_one_field(session, fields, iter_output,
989 &tag_field, NULL);
990 if (ret)
991 return ret;
992
993 /* Serialize variant field. */
994 uf = &fields[*iter_output];
995 ret = lttng_ust_dynamic_type_choices(&nr_choices, &choices);
996 if (ret)
997 return ret;
998
999 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1000 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1001 uf->type.atype = lttng_ust_ctl_atype_variant;
1002 uf->type.u.variant_nestable.nr_choices = nr_choices;
1003 strncpy(uf->type.u.variant_nestable.tag_name,
1004 tag_field_name,
1005 LTTNG_UST_ABI_SYM_NAME_LEN);
1006 uf->type.u.variant_nestable.tag_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1007 uf->type.u.variant_nestable.alignment = 0;
1008 (*iter_output)++;
1009
1010 /* Serialize choice fields after variant. */
1011 for (i = 0; i < nr_choices; i++) {
1012 ret = serialize_one_field(session, fields,
1013 iter_output, choices[i], NULL);
1014 if (ret)
1015 return ret;
1016 }
1017 return 0;
1018 }
1019
1020 static
1021 int serialize_one_type(struct lttng_ust_session *session,
1022 struct lttng_ust_ctl_field *fields, size_t *iter_output,
1023 const char *field_name, const struct lttng_ust_type_common *lt,
1024 enum lttng_ust_string_encoding parent_encoding,
1025 const char *prev_field_name)
1026 {
1027 int ret;
1028
1029 /*
1030 * Serializing a type (rather than a field) generates a lttng_ust_ctl_field
1031 * entry with 0-length name.
1032 */
1033
1034 switch (lt->type) {
1035 case lttng_ust_type_integer:
1036 {
1037 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1038 struct lttng_ust_ctl_type *ut = &uf->type;
1039
1040 if (field_name) {
1041 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1042 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1043 } else {
1044 uf->name[0] = '\0';
1045 }
1046 ret = serialize_integer_type(&ut->u.integer, lttng_ust_get_type_integer(lt),
1047 parent_encoding);
1048 if (ret)
1049 return ret;
1050 ut->atype = lttng_ust_ctl_atype_integer;
1051 (*iter_output)++;
1052 break;
1053 }
1054 case lttng_ust_type_float:
1055 {
1056 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1057 struct lttng_ust_ctl_type *ut = &uf->type;
1058 struct lttng_ust_ctl_float_type *uft;
1059 const struct lttng_ust_type_float *lft;
1060
1061 if (field_name) {
1062 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1063 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1064 } else {
1065 uf->name[0] = '\0';
1066 }
1067 uft = &ut->u._float;
1068 lft = lttng_ust_get_type_float(lt);
1069 uft->exp_dig = lft->exp_dig;
1070 uft->mant_dig = lft->mant_dig;
1071 uft->alignment = lft->alignment;
1072 uft->reverse_byte_order = lft->reverse_byte_order;
1073 ut->atype = lttng_ust_ctl_atype_float;
1074 (*iter_output)++;
1075 break;
1076 }
1077 case lttng_ust_type_string:
1078 {
1079 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1080 struct lttng_ust_ctl_type *ut = &uf->type;
1081 int32_t encoding;
1082
1083 if (field_name) {
1084 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1085 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1086 } else {
1087 uf->name[0] = '\0';
1088 }
1089 ret = serialize_string_encoding(&encoding, lttng_ust_get_type_string(lt)->encoding);
1090 if (ret)
1091 return ret;
1092 ut->u.string.encoding = encoding;
1093 ut->atype = lttng_ust_ctl_atype_string;
1094 (*iter_output)++;
1095 break;
1096 }
1097 case lttng_ust_type_array:
1098 {
1099 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1100 struct lttng_ust_ctl_type *ut = &uf->type;
1101
1102 if (field_name) {
1103 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1104 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1105 } else {
1106 uf->name[0] = '\0';
1107 }
1108 ut->atype = lttng_ust_ctl_atype_array_nestable;
1109 ut->u.array_nestable.length = lttng_ust_get_type_array(lt)->length;
1110 ut->u.array_nestable.alignment = lttng_ust_get_type_array(lt)->alignment;
1111 (*iter_output)++;
1112
1113 ret = serialize_one_type(session, fields, iter_output, NULL,
1114 lttng_ust_get_type_array(lt)->elem_type,
1115 lttng_ust_get_type_array(lt)->encoding, NULL);
1116 if (ret)
1117 return -EINVAL;
1118 break;
1119 }
1120 case lttng_ust_type_sequence:
1121 {
1122 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1123 struct lttng_ust_ctl_type *ut = &uf->type;
1124 const char *length_name = lttng_ust_get_type_sequence(lt)->length_name;
1125
1126 if (field_name) {
1127 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1128 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1129 } else {
1130 uf->name[0] = '\0';
1131 }
1132 ut->atype = lttng_ust_ctl_atype_sequence_nestable;
1133 /*
1134 * If length_name field is NULL, use the previous field
1135 * as length.
1136 */
1137 if (!length_name)
1138 length_name = prev_field_name;
1139 if (!length_name)
1140 return -EINVAL;
1141 strncpy(ut->u.sequence_nestable.length_name,
1142 length_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1143 ut->u.sequence_nestable.length_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1144 ut->u.sequence_nestable.alignment = lttng_ust_get_type_sequence(lt)->alignment;
1145 (*iter_output)++;
1146
1147 ret = serialize_one_type(session, fields, iter_output, NULL,
1148 lttng_ust_get_type_sequence(lt)->elem_type,
1149 lttng_ust_get_type_sequence(lt)->encoding, NULL);
1150 if (ret)
1151 return -EINVAL;
1152 break;
1153 }
1154 case lttng_ust_type_dynamic:
1155 {
1156 ret = serialize_dynamic_type(session, fields, iter_output,
1157 field_name);
1158 if (ret)
1159 return -EINVAL;
1160 break;
1161 }
1162 case lttng_ust_type_struct:
1163 {
1164 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1165
1166 if (field_name) {
1167 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1168 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1169 } else {
1170 uf->name[0] = '\0';
1171 }
1172 uf->type.atype = lttng_ust_ctl_atype_struct_nestable;
1173 uf->type.u.struct_nestable.nr_fields = lttng_ust_get_type_struct(lt)->nr_fields;
1174 uf->type.u.struct_nestable.alignment = lttng_ust_get_type_struct(lt)->alignment;
1175 (*iter_output)++;
1176
1177 ret = serialize_fields(session, fields, iter_output,
1178 lttng_ust_get_type_struct(lt)->nr_fields,
1179 lttng_ust_get_type_struct(lt)->fields);
1180 if (ret)
1181 return -EINVAL;
1182 break;
1183 }
1184 case lttng_ust_type_enum:
1185 {
1186 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1187 struct lttng_ust_ctl_type *ut = &uf->type;
1188
1189 if (field_name) {
1190 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1191 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1192 } else {
1193 uf->name[0] = '\0';
1194 }
1195 strncpy(ut->u.enum_nestable.name, lttng_ust_get_type_enum(lt)->desc->name,
1196 LTTNG_UST_ABI_SYM_NAME_LEN);
1197 ut->u.enum_nestable.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1198 ut->atype = lttng_ust_ctl_atype_enum_nestable;
1199 (*iter_output)++;
1200
1201 ret = serialize_one_type(session, fields, iter_output, NULL,
1202 lttng_ust_get_type_enum(lt)->container_type,
1203 lttng_ust_string_encoding_none, NULL);
1204 if (ret)
1205 return -EINVAL;
1206 if (session) {
1207 const struct lttng_enum *_enum;
1208
1209 _enum = lttng_ust_enum_get_from_desc(session, lttng_ust_get_type_enum(lt)->desc);
1210 if (!_enum)
1211 return -EINVAL;
1212 ut->u.enum_nestable.id = _enum->id;
1213 } else {
1214 ut->u.enum_nestable.id = -1ULL;
1215 }
1216 break;
1217 }
1218 default:
1219 return -EINVAL;
1220 }
1221 return 0;
1222 }
1223
1224 static
1225 int serialize_one_field(struct lttng_ust_session *session,
1226 struct lttng_ust_ctl_field *fields, size_t *iter_output,
1227 const struct lttng_ust_event_field *lf,
1228 const char **prev_field_name_p)
1229 {
1230 const char *prev_field_name = NULL;
1231 int ret;
1232
1233 /* skip 'nowrite' fields */
1234 if (lf->nowrite)
1235 return 0;
1236
1237 if (prev_field_name_p)
1238 prev_field_name = *prev_field_name_p;
1239 ret = serialize_one_type(session, fields, iter_output, lf->name, lf->type,
1240 lttng_ust_string_encoding_none, prev_field_name);
1241 if (prev_field_name_p)
1242 *prev_field_name_p = lf->name;
1243 return ret;
1244 }
1245
1246 static
1247 int serialize_fields(struct lttng_ust_session *session,
1248 struct lttng_ust_ctl_field *lttng_ust_ctl_fields,
1249 size_t *iter_output, size_t nr_lttng_fields,
1250 const struct lttng_ust_event_field * const *lttng_fields)
1251 {
1252 const char *prev_field_name = NULL;
1253 int ret;
1254 size_t i;
1255
1256 for (i = 0; i < nr_lttng_fields; i++) {
1257 ret = serialize_one_field(session, lttng_ust_ctl_fields,
1258 iter_output, lttng_fields[i],
1259 &prev_field_name);
1260 if (ret)
1261 return ret;
1262 }
1263 return 0;
1264 }
1265
1266 static
1267 int alloc_serialize_fields(struct lttng_ust_session *session,
1268 size_t *_nr_write_fields,
1269 struct lttng_ust_ctl_field **lttng_ust_ctl_fields,
1270 size_t nr_fields,
1271 const struct lttng_ust_event_field * const *lttng_fields)
1272 {
1273 struct lttng_ust_ctl_field *fields;
1274 int ret;
1275 size_t iter_output = 0;
1276 ssize_t nr_write_fields;
1277
1278 nr_write_fields = count_fields_recursive(nr_fields, lttng_fields);
1279 if (nr_write_fields < 0) {
1280 return (int) nr_write_fields;
1281 }
1282
1283 fields = zmalloc(nr_write_fields * sizeof(*fields));
1284 if (!fields)
1285 return -ENOMEM;
1286
1287 ret = serialize_fields(session, fields, &iter_output, nr_fields,
1288 lttng_fields);
1289 if (ret)
1290 goto error_type;
1291
1292 *_nr_write_fields = nr_write_fields;
1293 *lttng_ust_ctl_fields = fields;
1294 return 0;
1295
1296 error_type:
1297 free(fields);
1298 return ret;
1299 }
1300
1301 static
1302 int serialize_entries(struct lttng_ust_ctl_enum_entry **_entries,
1303 size_t nr_entries,
1304 const struct lttng_ust_enum_entry * const *lttng_entries)
1305 {
1306 struct lttng_ust_ctl_enum_entry *entries;
1307 int i;
1308
1309 /* Serialize the entries */
1310 entries = zmalloc(nr_entries * sizeof(*entries));
1311 if (!entries)
1312 return -ENOMEM;
1313 for (i = 0; i < nr_entries; i++) {
1314 struct lttng_ust_ctl_enum_entry *uentry;
1315 const struct lttng_ust_enum_entry *lentry;
1316
1317 uentry = &entries[i];
1318 lentry = lttng_entries[i];
1319
1320 uentry->start.value = lentry->start.value;
1321 uentry->start.signedness = lentry->start.signedness;
1322 uentry->end.value = lentry->end.value;
1323 uentry->end.signedness = lentry->end.signedness;
1324 strncpy(uentry->string, lentry->string, LTTNG_UST_ABI_SYM_NAME_LEN);
1325 uentry->string[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1326
1327 if (lentry->options & LTTNG_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
1328 uentry->u.extra.options |=
1329 LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO;
1330 }
1331 }
1332 *_entries = entries;
1333 return 0;
1334 }
1335
1336 static
1337 int serialize_ctx_fields(struct lttng_ust_session *session,
1338 size_t *_nr_write_fields,
1339 struct lttng_ust_ctl_field **lttng_ust_ctl_fields,
1340 size_t nr_fields,
1341 struct lttng_ust_ctx_field *lttng_fields)
1342 {
1343 struct lttng_ust_ctl_field *fields;
1344 const char *prev_field_name = NULL;
1345 size_t i, iter_output = 0;
1346 ssize_t nr_write_fields;
1347 int ret;
1348
1349 nr_write_fields = count_ctx_fields_recursive(nr_fields,
1350 lttng_fields);
1351 if (nr_write_fields < 0) {
1352 return (int) nr_write_fields;
1353 }
1354
1355 fields = zmalloc(nr_write_fields * sizeof(*fields));
1356 if (!fields)
1357 return -ENOMEM;
1358
1359 for (i = 0; i < nr_fields; i++) {
1360 ret = serialize_one_field(session, fields, &iter_output,
1361 lttng_fields[i].event_field, &prev_field_name);
1362 if (ret)
1363 goto error_type;
1364 }
1365
1366 *_nr_write_fields = nr_write_fields;
1367 *lttng_ust_ctl_fields = fields;
1368 return 0;
1369
1370 error_type:
1371 free(fields);
1372 return ret;
1373 }
1374
1375 /*
1376 * Returns 0 on success, negative error value on error.
1377 */
1378 int ustcomm_register_event(int sock,
1379 struct lttng_ust_session *session,
1380 int session_objd, /* session descriptor */
1381 int channel_objd, /* channel descriptor */
1382 const char *event_name, /* event name (input) */
1383 int loglevel,
1384 const char *signature, /* event signature (input) */
1385 size_t nr_fields, /* fields */
1386 const struct lttng_ust_event_field * const *lttng_fields,
1387 const char *model_emf_uri,
1388 uint32_t *id) /* event id (output) */
1389 {
1390 ssize_t len;
1391 struct {
1392 struct ustcomm_notify_hdr header;
1393 struct ustcomm_notify_event_msg m;
1394 } msg;
1395 struct {
1396 struct ustcomm_notify_hdr header;
1397 struct ustcomm_notify_event_reply r;
1398 } reply;
1399 size_t signature_len, fields_len, model_emf_uri_len;
1400 struct lttng_ust_ctl_field *fields = NULL;
1401 size_t nr_write_fields = 0;
1402 int ret;
1403
1404 memset(&msg, 0, sizeof(msg));
1405 msg.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_EVENT;
1406 msg.m.session_objd = session_objd;
1407 msg.m.channel_objd = channel_objd;
1408 strncpy(msg.m.event_name, event_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1409 msg.m.event_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1410 msg.m.loglevel = loglevel;
1411 signature_len = strlen(signature) + 1;
1412 msg.m.signature_len = signature_len;
1413
1414 /* Calculate fields len, serialize fields. */
1415 if (nr_fields > 0) {
1416 ret = alloc_serialize_fields(session, &nr_write_fields, &fields,
1417 nr_fields, lttng_fields);
1418 if (ret)
1419 return ret;
1420 }
1421
1422 fields_len = sizeof(*fields) * nr_write_fields;
1423 msg.m.fields_len = fields_len;
1424 if (model_emf_uri) {
1425 model_emf_uri_len = strlen(model_emf_uri) + 1;
1426 } else {
1427 model_emf_uri_len = 0;
1428 }
1429 msg.m.model_emf_uri_len = model_emf_uri_len;
1430
1431 len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
1432 if (len > 0 && len != sizeof(msg)) {
1433 ret = -EIO;
1434 goto error_fields;
1435 }
1436 if (len < 0) {
1437 ret = len;
1438 goto error_fields;
1439 }
1440
1441 /* send signature */
1442 len = ustcomm_send_unix_sock(sock, signature, signature_len);
1443 if (len > 0 && len != signature_len) {
1444 ret = -EIO;
1445 goto error_fields;
1446 }
1447 if (len < 0) {
1448 ret = len;
1449 goto error_fields;
1450 }
1451
1452 /* send fields */
1453 if (fields_len > 0) {
1454 len = ustcomm_send_unix_sock(sock, fields, fields_len);
1455 if (len > 0 && len != fields_len) {
1456 ret = -EIO;
1457 goto error_fields;
1458 }
1459 if (len < 0) {
1460 ret = len;
1461 goto error_fields;
1462 }
1463 }
1464 free(fields);
1465
1466 if (model_emf_uri_len) {
1467 /* send model_emf_uri */
1468 len = ustcomm_send_unix_sock(sock, model_emf_uri,
1469 model_emf_uri_len);
1470 if (len > 0 && len != model_emf_uri_len) {
1471 return -EIO;
1472 }
1473 if (len < 0) {
1474 return len;
1475 }
1476 }
1477
1478 /* receive reply */
1479 len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
1480 switch (len) {
1481 case 0: /* orderly shutdown */
1482 return -EPIPE;
1483 case sizeof(reply):
1484 if (reply.header.notify_cmd != msg.header.notify_cmd) {
1485 ERR("Unexpected result message command "
1486 "expected: %u vs received: %u\n",
1487 msg.header.notify_cmd, reply.header.notify_cmd);
1488 return -EINVAL;
1489 }
1490 if (reply.r.ret_code > 0)
1491 return -EINVAL;
1492 if (reply.r.ret_code < 0)
1493 return reply.r.ret_code;
1494 *id = reply.r.event_id;
1495 DBG("Sent register event notification for name \"%s\": ret_code %d, event_id %u\n",
1496 event_name, reply.r.ret_code, reply.r.event_id);
1497 return 0;
1498 default:
1499 if (len < 0) {
1500 /* Transport level error */
1501 if (errno == EPIPE || errno == ECONNRESET)
1502 len = -errno;
1503 return len;
1504 } else {
1505 ERR("incorrect message size: %zd\n", len);
1506 return len;
1507 }
1508 }
1509 /* Unreached. */
1510
1511 /* Error path only. */
1512 error_fields:
1513 free(fields);
1514 return ret;
1515 }
1516
1517 /*
1518 * Returns 0 on success, negative error value on error.
1519 * Returns -EPIPE or -ECONNRESET if other end has hung up.
1520 */
1521 int ustcomm_register_enum(int sock,
1522 int session_objd, /* session descriptor */
1523 const char *enum_name, /* enum name (input) */
1524 size_t nr_entries, /* entries */
1525 const struct lttng_ust_enum_entry * const *lttng_entries,
1526 uint64_t *id)
1527 {
1528 ssize_t len;
1529 struct {
1530 struct ustcomm_notify_hdr header;
1531 struct ustcomm_notify_enum_msg m;
1532 } msg;
1533 struct {
1534 struct ustcomm_notify_hdr header;
1535 struct ustcomm_notify_enum_reply r;
1536 } reply;
1537 size_t entries_len;
1538 struct lttng_ust_ctl_enum_entry *entries = NULL;
1539 int ret;
1540
1541 memset(&msg, 0, sizeof(msg));
1542 msg.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_ENUM;
1543 msg.m.session_objd = session_objd;
1544 strncpy(msg.m.enum_name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1545 msg.m.enum_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
1546
1547 /* Calculate entries len, serialize entries. */
1548 if (nr_entries > 0) {
1549 ret = serialize_entries(&entries,
1550 nr_entries, lttng_entries);
1551 if (ret)
1552 return ret;
1553 }
1554
1555 entries_len = sizeof(*entries) * nr_entries;
1556 msg.m.entries_len = entries_len;
1557
1558 len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
1559 if (len > 0 && len != sizeof(msg)) {
1560 ret = -EIO;
1561 goto error_entries;
1562 }
1563 if (len < 0) {
1564 ret = len;
1565 goto error_entries;
1566 }
1567
1568 /* send entries */
1569 if (entries_len > 0) {
1570 len = ustcomm_send_unix_sock(sock, entries, entries_len);
1571 if (len > 0 && len != entries_len) {
1572 ret = -EIO;
1573 goto error_entries;
1574 }
1575 if (len < 0) {
1576 ret = len;
1577 goto error_entries;
1578 }
1579 }
1580 free(entries);
1581 entries = NULL;
1582
1583 /* receive reply */
1584 len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
1585 switch (len) {
1586 case 0: /* orderly shutdown */
1587 return -EPIPE;
1588 case sizeof(reply):
1589 if (reply.header.notify_cmd != msg.header.notify_cmd) {
1590 ERR("Unexpected result message command "
1591 "expected: %u vs received: %u\n",
1592 msg.header.notify_cmd, reply.header.notify_cmd);
1593 return -EINVAL;
1594 }
1595 if (reply.r.ret_code > 0)
1596 return -EINVAL;
1597 if (reply.r.ret_code < 0)
1598 return reply.r.ret_code;
1599 *id = reply.r.enum_id;
1600 DBG("Sent register enum notification for name \"%s\": ret_code %d\n",
1601 enum_name, reply.r.ret_code);
1602 return 0;
1603 default:
1604 if (len < 0) {
1605 /* Transport level error */
1606 if (errno == EPIPE || errno == ECONNRESET)
1607 len = -errno;
1608 return len;
1609 } else {
1610 ERR("incorrect message size: %zd\n", len);
1611 return len;
1612 }
1613 }
1614 return ret;
1615
1616 error_entries:
1617 free(entries);
1618 return ret;
1619 }
1620
1621 /*
1622 * Returns 0 on success, negative error value on error.
1623 * Returns -EPIPE or -ECONNRESET if other end has hung up.
1624 */
1625 int ustcomm_register_channel(int sock,
1626 struct lttng_ust_session *session,
1627 int session_objd, /* session descriptor */
1628 int channel_objd, /* channel descriptor */
1629 size_t nr_ctx_fields,
1630 struct lttng_ust_ctx_field *ctx_fields,
1631 uint32_t *chan_id, /* channel id (output) */
1632 int *header_type) /* header type (output) */
1633 {
1634 ssize_t len;
1635 struct {
1636 struct ustcomm_notify_hdr header;
1637 struct ustcomm_notify_channel_msg m;
1638 } msg;
1639 struct {
1640 struct ustcomm_notify_hdr header;
1641 struct ustcomm_notify_channel_reply r;
1642 } reply;
1643 size_t fields_len;
1644 struct lttng_ust_ctl_field *fields = NULL;
1645 int ret;
1646 size_t nr_write_fields = 0;
1647
1648 memset(&msg, 0, sizeof(msg));
1649 msg.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_CHANNEL;
1650 msg.m.session_objd = session_objd;
1651 msg.m.channel_objd = channel_objd;
1652
1653 /* Calculate fields len, serialize fields. */
1654 if (nr_ctx_fields > 0) {
1655 ret = serialize_ctx_fields(session, &nr_write_fields, &fields,
1656 nr_ctx_fields, ctx_fields);
1657 if (ret)
1658 return ret;
1659 }
1660
1661 fields_len = sizeof(*fields) * nr_write_fields;
1662 msg.m.ctx_fields_len = fields_len;
1663 len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
1664 if (len > 0 && len != sizeof(msg)) {
1665 free(fields);
1666 return -EIO;
1667 }
1668 if (len < 0) {
1669 free(fields);
1670 return len;
1671 }
1672
1673 /* send fields */
1674 if (fields_len > 0) {
1675 len = ustcomm_send_unix_sock(sock, fields, fields_len);
1676 free(fields);
1677 if (len > 0 && len != fields_len) {
1678 return -EIO;
1679 }
1680 if (len < 0) {
1681 return len;
1682 }
1683 } else {
1684 free(fields);
1685 }
1686
1687 len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
1688 switch (len) {
1689 case 0: /* orderly shutdown */
1690 return -EPIPE;
1691 case sizeof(reply):
1692 if (reply.header.notify_cmd != msg.header.notify_cmd) {
1693 ERR("Unexpected result message command "
1694 "expected: %u vs received: %u\n",
1695 msg.header.notify_cmd, reply.header.notify_cmd);
1696 return -EINVAL;
1697 }
1698 if (reply.r.ret_code > 0)
1699 return -EINVAL;
1700 if (reply.r.ret_code < 0)
1701 return reply.r.ret_code;
1702 *chan_id = reply.r.chan_id;
1703 switch (reply.r.header_type) {
1704 case 1:
1705 case 2:
1706 *header_type = reply.r.header_type;
1707 break;
1708 default:
1709 ERR("Unexpected channel header type %u\n",
1710 reply.r.header_type);
1711 return -EINVAL;
1712 }
1713 DBG("Sent register channel notification: chan_id %d, header_type %d\n",
1714 reply.r.chan_id, reply.r.header_type);
1715 return 0;
1716 default:
1717 if (len < 0) {
1718 /* Transport level error */
1719 if (errno == EPIPE || errno == ECONNRESET)
1720 len = -errno;
1721 return len;
1722 } else {
1723 ERR("incorrect message size: %zd\n", len);
1724 return len;
1725 }
1726 }
1727 }
1728
1729 /*
1730 * Set socket receiving timeout.
1731 */
1732 int ustcomm_setsockopt_rcv_timeout(int sock, unsigned int msec)
1733 {
1734 int ret;
1735 struct timeval tv;
1736
1737 tv.tv_sec = msec / 1000;
1738 tv.tv_usec = (msec * 1000 % 1000000);
1739
1740 ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
1741 if (ret < 0) {
1742 PERROR("setsockopt SO_RCVTIMEO");
1743 ret = -errno;
1744 }
1745
1746 return ret;
1747 }
1748
1749 /*
1750 * Set socket sending timeout.
1751 */
1752 int ustcomm_setsockopt_snd_timeout(int sock, unsigned int msec)
1753 {
1754 int ret;
1755 struct timeval tv;
1756
1757 tv.tv_sec = msec / 1000;
1758 tv.tv_usec = (msec * 1000) % 1000000;
1759
1760 ret = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
1761 if (ret < 0) {
1762 PERROR("setsockopt SO_SNDTIMEO");
1763 ret = -errno;
1764 }
1765
1766 return ret;
1767 }
This page took 0.065254 seconds and 3 git commands to generate.