Copyright ownership transfer
[lttng-ust.git] / src / common / ustcomm.c
CommitLineData
67c5b804 1/*
c0c0989a 2 * SPDX-License-Identifier: LGPL-2.1-only
67c5b804 3 *
f350e97f 4 * Copyright (C) 2011 EfficiOS Inc.
c0c0989a 5 * Copyright (C) 2011-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
67c5b804
MD
6 */
7
67c5b804 8#include <limits.h>
fb31eb73 9#include <stdint.h>
67c5b804
MD
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>
57773204 19#include <errno.h>
11ba4bcb 20#include <fcntl.h>
67c5b804 21
32ce8569 22#include <lttng/ust-ctl.h>
9d315d6d
MJ
23#include "common/ustcomm.h"
24#include "common/ust-fd.h"
25#include "common/macros.h"
9d315d6d
MJ
26#include "common/dynamic-type.h"
27#include "common/logging.h"
32ce8569 28
36c52fff 29#include "common/events.h"
27b98e6c 30#include "common/compat/pthread.h"
7bc53e94 31
74d81a6c
MD
32#define USTCOMM_MAX_SEND_FDS 4
33
53569322
MD
34static
35ssize_t count_fields_recursive(size_t nr_fields,
3d33ca1d 36 const struct lttng_ust_event_field * const *lttng_fields);
53569322 37static
f69fe5fb 38int serialize_one_field(struct lttng_ust_session *session,
249cffb5 39 struct lttng_ust_ctl_field *fields, size_t *iter_output,
28db0827
MD
40 const struct lttng_ust_event_field *lf,
41 const char **prev_field_name);
218deb69 42static
f69fe5fb 43int serialize_fields(struct lttng_ust_session *session,
249cffb5 44 struct lttng_ust_ctl_field *lttng_ust_ctl_fields,
218deb69 45 size_t *iter_output, size_t nr_lttng_fields,
3d33ca1d 46 const struct lttng_ust_event_field * const *lttng_fields);
53569322 47
67c5b804 48/*
74d81a6c 49 * ustcomm_connect_unix_sock
67c5b804 50 *
74d81a6c 51 * Connect to unix socket using the path name.
6548fca4
MD
52 *
53 * Caller handles FD tracker.
67c5b804 54 */
451d66b2 55int ustcomm_connect_unix_sock(const char *pathname, long timeout)
67c5b804
MD
56{
57 struct sockaddr_un sun;
7bc53e94 58 int fd, ret;
67c5b804 59
204d45df
MD
60 /*
61 * libust threads require the close-on-exec flag for all
62 * resources so it does not leak file descriptors upon exec.
6daf0c26 63 * SOCK_CLOEXEC is not used since it is linux specific.
204d45df 64 */
11ba4bcb 65 fd = socket(PF_UNIX, SOCK_STREAM, 0);
67c5b804 66 if (fd < 0) {
32ce8569 67 PERROR("socket");
7bc53e94 68 ret = -errno;
67c5b804
MD
69 goto error;
70 }
451d66b2
MD
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 }
11ba4bcb
MD
80 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
81 if (ret < 0) {
32ce8569 82 PERROR("fcntl");
7bc53e94 83 ret = -errno;
11ba4bcb
MD
84 goto error_fcntl;
85 }
67c5b804
MD
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 /*
0b9aa170
MD
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.
67c5b804 100 */
0b9aa170 101 if (errno != ECONNREFUSED && errno != ECONNRESET
bdd8ca83 102 && errno != ENOENT && errno != EACCES)
8cf811d3 103 PERROR("connect");
7bc53e94 104 ret = -errno;
8cf811d3
MD
105 if (ret == -ECONNREFUSED || ret == -ECONNRESET)
106 ret = -EPIPE;
67c5b804
MD
107 goto error_connect;
108 }
109
110 return fd;
111
112error_connect:
11ba4bcb 113error_fcntl:
7bc53e94
MD
114 {
115 int closeret;
116
117 closeret = close(fd);
118 if (closeret)
32ce8569 119 PERROR("close");
7bc53e94 120 }
67c5b804
MD
121error:
122 return ret;
123}
124
125/*
74d81a6c 126 * ustcomm_accept_unix_sock
67c5b804 127 *
74d81a6c
MD
128 * Do an accept(2) on the sock and return the
129 * new file descriptor. The socket MUST be bind(2) before.
67c5b804 130 */
57773204 131int ustcomm_accept_unix_sock(int sock)
67c5b804
MD
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) {
b869b5ae
MD
140 if (errno != ECONNABORTED)
141 PERROR("accept");
142 new_fd = -errno;
143 if (new_fd == -ECONNABORTED)
144 new_fd = -EPIPE;
67c5b804 145 }
67c5b804 146 return new_fd;
67c5b804
MD
147}
148
149/*
74d81a6c 150 * ustcomm_create_unix_sock
67c5b804 151 *
74d81a6c
MD
152 * Creates a AF_UNIX local socket using pathname
153 * bind the socket upon creation and return the fd.
67c5b804 154 */
57773204 155int ustcomm_create_unix_sock(const char *pathname)
67c5b804
MD
156{
157 struct sockaddr_un sun;
7bc53e94 158 int fd, ret;
67c5b804
MD
159
160 /* Create server socket */
161 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
32ce8569 162 PERROR("socket");
7bc53e94 163 ret = -errno;
67c5b804
MD
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) {
32ce8569 176 PERROR("bind");
7bc53e94
MD
177 ret = -errno;
178 goto error_close;
67c5b804
MD
179 }
180
181 return fd;
182
7bc53e94
MD
183error_close:
184 {
185 int closeret;
186
187 closeret = close(fd);
188 if (closeret) {
32ce8569 189 PERROR("close");
7bc53e94
MD
190 }
191 }
67c5b804
MD
192error:
193 return ret;
194}
195
196/*
74d81a6c 197 * ustcomm_listen_unix_sock
67c5b804 198 *
74d81a6c 199 * Make the socket listen using LTTNG_UST_COMM_MAX_LISTEN.
67c5b804 200 */
57773204 201int ustcomm_listen_unix_sock(int sock)
67c5b804
MD
202{
203 int ret;
204
e41474be 205 ret = listen(sock, LTTNG_UST_COMM_MAX_LISTEN);
67c5b804 206 if (ret < 0) {
7bc53e94 207 ret = -errno;
32ce8569 208 PERROR("listen");
67c5b804
MD
209 }
210
211 return ret;
212}
213
214/*
74d81a6c
MD
215 * ustcomm_close_unix_sock
216 *
ea1c5d69 217 * Close unix socket.
6548fca4
MD
218 *
219 * Handles fd tracker internally.
74d81a6c
MD
220 */
221int ustcomm_close_unix_sock(int sock)
222{
223 int ret;
224
6548fca4 225 lttng_ust_lock_fd_tracker();
74d81a6c 226 ret = close(sock);
6548fca4
MD
227 if (!ret) {
228 lttng_ust_delete_fd_from_tracker(sock);
229 } else {
32ce8569 230 PERROR("close");
74d81a6c
MD
231 ret = -errno;
232 }
6548fca4 233 lttng_ust_unlock_fd_tracker();
74d81a6c
MD
234
235 return ret;
236}
237
ea1c5d69
MD
238/*
239 * ustcomm_shutdown_unix_sock
240 *
241 * Shutdown unix socket. Keeps the file descriptor open, but shutdown
242 * communication.
243 */
244int 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
74d81a6c
MD
256/*
257 * ustcomm_recv_unix_sock
67c5b804 258 *
74d81a6c
MD
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.
67c5b804 263 */
57773204 264ssize_t ustcomm_recv_unix_sock(int sock, void *buf, size_t len)
67c5b804 265{
913b87f1 266 struct msghdr msg;
67c5b804 267 struct iovec iov[1];
89c5b6ec
MD
268 ssize_t ret = -1;
269 size_t len_last;
67c5b804 270
913b87f1
MD
271 memset(&msg, 0, sizeof(msg));
272
67c5b804
MD
273 iov[0].iov_base = buf;
274 iov[0].iov_len = len;
275 msg.msg_iov = iov;
276 msg.msg_iovlen = 1;
277
7e3cfcbe 278 do {
89c5b6ec 279 len_last = iov[0].iov_len;
7e3cfcbe 280 ret = recvmsg(sock, &msg, 0);
89c5b6ec
MD
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));
7bc53e94
MD
287
288 if (ret < 0) {
8cf811d3 289 if (errno != EPIPE && errno != ECONNRESET && errno != ECONNREFUSED)
32ce8569 290 PERROR("recvmsg");
7bc53e94 291 ret = -errno;
8cf811d3 292 if (ret == -ECONNRESET || ret == -ECONNREFUSED)
b869b5ae 293 ret = -EPIPE;
7bc53e94 294
ea1c5d69 295 (void) ustcomm_shutdown_unix_sock(sock);
89c5b6ec
MD
296 } else if (ret > 0) {
297 ret = len;
67c5b804 298 }
89c5b6ec 299 /* ret = 0 means an orderly shutdown. */
67c5b804
MD
300
301 return ret;
302}
303
304/*
74d81a6c 305 * ustcomm_send_unix_sock
67c5b804 306 *
74d81a6c
MD
307 * Send buf data of size len. Using sendmsg API.
308 * Return the size of sent data.
67c5b804 309 */
32ce8569 310ssize_t ustcomm_send_unix_sock(int sock, const void *buf, size_t len)
67c5b804 311{
913b87f1 312 struct msghdr msg;
67c5b804 313 struct iovec iov[1];
7bc53e94 314 ssize_t ret;
67c5b804 315
913b87f1
MD
316 memset(&msg, 0, sizeof(msg));
317
32ce8569 318 iov[0].iov_base = (void *) buf;
67c5b804
MD
319 iov[0].iov_len = len;
320 msg.msg_iov = iov;
321 msg.msg_iovlen = 1;
322
1ea11eab
MD
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 */
51d9d699
MD
330 do {
331 ret = sendmsg(sock, &msg, MSG_NOSIGNAL);
332 } while (ret < 0 && errno == EINTR);
7bc53e94
MD
333
334 if (ret < 0) {
74d81a6c 335 if (errno != EPIPE && errno != ECONNRESET)
32ce8569 336 PERROR("sendmsg");
7bc53e94 337 ret = -errno;
b869b5ae
MD
338 if (ret == -ECONNRESET)
339 ret = -EPIPE;
7bc53e94 340
ea1c5d69 341 (void) ustcomm_shutdown_unix_sock(sock);
67c5b804
MD
342 }
343
344 return ret;
345}
346
347/*
74d81a6c 348 * Send a message accompanied by fd(s) over a unix socket.
67c5b804 349 *
74d81a6c 350 * Returns the size of data sent, or negative error value.
67c5b804 351 */
74d81a6c 352ssize_t ustcomm_send_fds_unix_sock(int sock, int *fds, size_t nb_fd)
67c5b804 353{
913b87f1 354 struct msghdr msg;
67c5b804
MD
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)];
74d81a6c 360 char dummy = 0;
67c5b804 361
913b87f1 362 memset(&msg, 0, sizeof(msg));
74d81a6c 363 memset(tmp, 0, CMSG_SPACE(sizeof_fds) * sizeof(char));
913b87f1 364
74d81a6c
MD
365 if (nb_fd > USTCOMM_MAX_SEND_FDS)
366 return -EINVAL;
67c5b804
MD
367
368 msg.msg_control = (caddr_t)tmp;
369 msg.msg_controllen = CMSG_LEN(sizeof_fds);
370
371 cmptr = CMSG_FIRSTHDR(&msg);
34daae3e
MD
372 if (!cmptr)
373 return -EINVAL;
67c5b804
MD
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
74d81a6c
MD
381 iov[0].iov_base = &dummy;
382 iov[0].iov_len = 1;
67c5b804
MD
383 msg.msg_iov = iov;
384 msg.msg_iovlen = 1;
385
51d9d699 386 do {
0dafcd63 387 ret = sendmsg(sock, &msg, MSG_NOSIGNAL);
51d9d699 388 } while (ret < 0 && errno == EINTR);
7bc53e94 389 if (ret < 0) {
74d81a6c
MD
390 /*
391 * We consider EPIPE and ECONNRESET as expected.
392 */
393 if (errno != EPIPE && errno != ECONNRESET) {
32ce8569 394 PERROR("sendmsg");
74d81a6c 395 }
b869b5ae
MD
396 ret = -errno;
397 if (ret == -ECONNRESET)
398 ret = -EPIPE;
74d81a6c
MD
399 }
400 return ret;
401}
7bc53e94 402
74d81a6c
MD
403/*
404 * Recv a message accompanied by fd(s) from a unix socket.
405 *
74d81a6c
MD
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 */
410ssize_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;
6daf0c26 419 int i;
7bc53e94 420
74d81a6c 421 memset(&msg, 0, sizeof(msg));
67c5b804 422
74d81a6c
MD
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) {
32ce8569 436 PERROR("recvmsg fds");
74d81a6c 437 }
8cf811d3 438 ret = -errno;
b869b5ae
MD
439 if (ret == -ECONNRESET)
440 ret = -EPIPE;
74d81a6c
MD
441 goto end;
442 }
443 if (ret == 0) {
444 /* orderly shutdown */
445 ret = -EPIPE;
446 goto end;
447 }
448 if (ret != 1) {
32ce8569 449 ERR("Error: Received %zd bytes, expected %d\n",
74d81a6c
MD
450 ret, 1);
451 goto end;
452 }
453 if (msg.msg_flags & MSG_CTRUNC) {
32ce8569 454 ERR("Error: Control message truncated.\n");
74d81a6c
MD
455 ret = -1;
456 goto end;
457 }
458 cmsg = CMSG_FIRSTHDR(&msg);
459 if (!cmsg) {
32ce8569 460 ERR("Error: Invalid control message header\n");
74d81a6c
MD
461 ret = -1;
462 goto end;
463 }
464 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
32ce8569 465 ERR("Didn't received any fd\n");
74d81a6c
MD
466 ret = -1;
467 goto end;
468 }
469 if (cmsg->cmsg_len != CMSG_LEN(sizeof_fds)) {
32ce8569 470 ERR("Error: Received %zu bytes of ancillary data, expected %zu\n",
74d81a6c
MD
471 (size_t) cmsg->cmsg_len, (size_t) CMSG_LEN(sizeof_fds));
472 ret = -1;
473 goto end;
474 }
6daf0c26 475
74d81a6c 476 memcpy(fds, CMSG_DATA(cmsg), sizeof_fds);
6daf0c26
JR
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
6b32a5c3 487 ret = nb_fd;
74d81a6c 488end:
67c5b804
MD
489 return ret;
490}
57773204
MD
491
492int 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):
57773204 499 break;
57773204 500 default:
7bc53e94 501 if (len < 0) {
7bc53e94
MD
502 return len;
503 } else {
32ce8569 504 ERR("incorrect message size: %zd\n", len);
7bc53e94
MD
505 return -EINVAL;
506 }
57773204
MD
507 }
508 return 0;
509}
510
511int 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 */
74d81a6c 520 return -EPIPE;
57773204 521 case sizeof(*lur):
5dafeeaa
MD
522 {
523 int err = 0;
524
57773204 525 if (lur->handle != expected_handle) {
32ce8569 526 ERR("Unexpected result message handle: "
74d81a6c
MD
527 "expected: %u vs received: %u\n",
528 expected_handle, lur->handle);
5dafeeaa 529 err = 1;
57773204 530 }
57773204 531 if (lur->cmd != expected_cmd) {
32ce8569 532 ERR("Unexpected result message command "
74d81a6c
MD
533 "expected: %u vs received: %u\n",
534 expected_cmd, lur->cmd);
5dafeeaa
MD
535 err = 1;
536 }
537 if (err) {
57773204 538 return -EINVAL;
5dafeeaa
MD
539 } else {
540 return lur->ret_code;
57773204 541 }
5dafeeaa 542 }
57773204 543 default:
8cf811d3 544 if (len >= 0) {
32ce8569 545 ERR("incorrect message size: %zd\n", len);
7bc53e94 546 }
8cf811d3 547 return len;
57773204
MD
548 }
549}
550
551int 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;
c354a72c
MD
560 ret = ustcomm_recv_app_reply(sock, lur, lum->handle, lum->cmd);
561 if (ret > 0)
562 return -EIO;
563 return ret;
57773204
MD
564}
565
57773204 566/*
74d81a6c
MD
567 * chan_data is allocated internally if this function returns the
568 * expected var_len.
57773204 569 */
74d81a6c 570ssize_t ustcomm_recv_channel_from_sessiond(int sock,
ff0f5728
MD
571 void **_chan_data, uint64_t var_len,
572 int *_wakeup_fd)
57773204 573{
74d81a6c 574 void *chan_data;
ff0f5728 575 ssize_t len, nr_fd;
f5c453e9 576 int wakeup_fd, ret;
57773204 577
fd17d7ce 578 if (var_len > LTTNG_UST_ABI_CHANNEL_DATA_MAX_LEN) {
74d81a6c
MD
579 len = -EINVAL;
580 goto error_check;
57773204 581 }
74d81a6c
MD
582 /* Receive variable length data */
583 chan_data = zmalloc(var_len);
584 if (!chan_data) {
585 len = -ENOMEM;
586 goto error_alloc;
57773204 587 }
74d81a6c
MD
588 len = ustcomm_recv_unix_sock(sock, chan_data, var_len);
589 if (len != var_len) {
590 goto error_recv;
57773204 591 }
ff0f5728 592 /* recv wakeup fd */
6548fca4 593 lttng_ust_lock_fd_tracker();
ff0f5728
MD
594 nr_fd = ustcomm_recv_fds_unix_sock(sock, &wakeup_fd, 1);
595 if (nr_fd <= 0) {
6548fca4 596 lttng_ust_unlock_fd_tracker();
ff0f5728
MD
597 if (nr_fd < 0) {
598 len = nr_fd;
599 goto error_recv;
600 } else {
601 len = -EIO;
602 goto error_recv;
603 }
604 }
f5c453e9
JR
605
606 ret = lttng_ust_add_fd_to_tracker(wakeup_fd);
607 if (ret < 0) {
f5c453e9
JR
608 ret = close(wakeup_fd);
609 if (ret) {
610 PERROR("close on wakeup_fd");
611 }
612 len = -EIO;
20d1999d 613 lttng_ust_unlock_fd_tracker();
f5c453e9
JR
614 goto error_recv;
615 }
616
617 *_wakeup_fd = ret;
6548fca4 618 lttng_ust_unlock_fd_tracker();
f5c453e9 619
74d81a6c
MD
620 *_chan_data = chan_data;
621 return len;
622
623error_recv:
624 free(chan_data);
625error_alloc:
626error_check:
627 return len;
628}
7bc53e94 629
d8d2416d
FD
630ssize_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
666error:
667 return ret;
668}
669
74d81a6c 670int ustcomm_recv_stream_from_sessiond(int sock,
2208d8b5 671 uint64_t *memory_map_size __attribute__((unused)),
74d81a6c
MD
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 */
6548fca4 679 lttng_ust_lock_fd_tracker();
74d81a6c
MD
680 len = ustcomm_recv_fds_unix_sock(sock, fds, 2);
681 if (len <= 0) {
6548fca4 682 lttng_ust_unlock_fd_tracker();
74d81a6c
MD
683 if (len < 0) {
684 ret = len;
685 goto error;
686 } else {
687 ret = -EIO;
688 goto error;
689 }
7bc53e94 690 }
f5c453e9
JR
691
692 ret = lttng_ust_add_fd_to_tracker(fds[0]);
693 if (ret < 0) {
f5c453e9
JR
694 ret = close(fds[0]);
695 if (ret) {
696 PERROR("close on received shm_fd");
697 }
698 ret = -EIO;
20d1999d 699 lttng_ust_unlock_fd_tracker();
f5c453e9
JR
700 goto error;
701 }
702 *shm_fd = ret;
703
704 ret = lttng_ust_add_fd_to_tracker(fds[1]);
705 if (ret < 0) {
f5c453e9
JR
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;
20d1999d 716 lttng_ust_unlock_fd_tracker();
f5c453e9
JR
717 goto error;
718 }
719 *wakeup_fd = ret;
6548fca4 720 lttng_ust_unlock_fd_tracker();
74d81a6c
MD
721 return 0;
722
723error:
57773204
MD
724 return ret;
725}
32ce8569 726
ebabbf58
MD
727ssize_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
fd17d7ce 733 if (var_len > LTTNG_UST_ABI_COUNTER_DATA_MAX_LEN) {
ebabbf58
MD
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
750error_recv:
751 free(counter_data);
752error_alloc:
753error_check:
754 return len;
755}
756
757int 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
792error:
793 return ret;
794}
795
32ce8569
MD
796/*
797 * Returns 0 on success, negative error value on error.
798 */
799int ustcomm_send_reg_msg(int sock,
249cffb5 800 enum lttng_ust_ctl_socket_type type,
32ce8569
MD
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,
046bc54c
JG
806 uint32_t long_alignment,
807 const char *procname)
32ce8569
MD
808{
809 ssize_t len;
249cffb5 810 struct lttng_ust_ctl_reg_msg reg_msg;
32ce8569 811
fd17d7ce 812 reg_msg.magic = LTTNG_UST_ABI_COMM_MAGIC;
32ce8569
MD
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;
046bc54c
JG
826 memset(reg_msg.name, 0, sizeof(reg_msg.name));
827 strncpy(reg_msg.name, procname, sizeof(reg_msg.name) - 1);
32ce8569
MD
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
53569322 838static
4e48b5d2 839ssize_t count_one_type(const struct lttng_ust_type_common *lt)
53569322 840{
a084756d
MD
841 switch (lt->type) {
842 case lttng_ust_type_integer:
843 case lttng_ust_type_float:
844 case lttng_ust_type_string:
53569322 845 return 1;
a084756d
MD
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:
53569322 857 {
3d33ca1d 858 const struct lttng_ust_event_field * const *choices;
53569322
MD
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 /*
cf22367f 867 * Two fields for enum, one field for variant, and
53569322
MD
868 * one field per choice.
869 */
cf22367f 870 return count_fields_recursive(nr_choices, choices) + 3;
53569322 871 }
218deb69 872
53569322
MD
873 default:
874 return -EINVAL;
875 }
876 return 0;
877}
878
879static
880ssize_t count_fields_recursive(size_t nr_fields,
3d33ca1d 881 const struct lttng_ust_event_field * const *lttng_fields)
53569322
MD
882{
883 int i;
884 ssize_t ret, count = 0;
885
886 for (i = 0; i < nr_fields; i++) {
25cff019 887 const struct lttng_ust_event_field *lf;
53569322 888
25cff019 889 lf = lttng_fields[i];
53569322
MD
890 /* skip 'nowrite' fields */
891 if (lf->nowrite)
892 continue;
a084756d 893 ret = count_one_type(lf->type);
53569322
MD
894 if (ret < 0)
895 return ret; /* error */
896 count += ret;
897 }
898 return count;
899}
900
901static
902ssize_t count_ctx_fields_recursive(size_t nr_fields,
4e48b5d2 903 struct lttng_ust_ctx_field *lttng_fields)
53569322
MD
904{
905 int i;
906 ssize_t ret, count = 0;
907
908 for (i = 0; i < nr_fields; i++) {
25cff019 909 const struct lttng_ust_event_field *lf;
53569322 910
4e48b5d2 911 lf = lttng_fields[i].event_field;
53569322
MD
912 /* skip 'nowrite' fields */
913 if (lf->nowrite)
914 continue;
a084756d 915 ret = count_one_type(lf->type);
53569322
MD
916 if (ret < 0)
917 return ret; /* error */
918 count += ret;
919 }
920 return count;
921}
922
31a85ea9
MD
923static
924int serialize_string_encoding(int32_t *ue,
a084756d 925 enum lttng_ust_string_encoding le)
31a85ea9
MD
926{
927 switch (le) {
a084756d 928 case lttng_ust_string_encoding_none:
249cffb5 929 *ue = lttng_ust_ctl_encode_none;
31a85ea9 930 break;
a084756d 931 case lttng_ust_string_encoding_UTF8:
249cffb5 932 *ue = lttng_ust_ctl_encode_UTF8;
31a85ea9 933 break;
a084756d 934 case lttng_ust_string_encoding_ASCII:
249cffb5 935 *ue = lttng_ust_ctl_encode_ASCII;
31a85ea9
MD
936 break;
937 default:
938 return -EINVAL;
939 }
940 return 0;
941}
942
943static
249cffb5 944int serialize_integer_type(struct lttng_ust_ctl_integer_type *uit,
a084756d
MD
945 const struct lttng_ust_type_integer *lit,
946 enum lttng_ust_string_encoding lencoding)
31a85ea9
MD
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;
a084756d 954 if (serialize_string_encoding(&encoding, lencoding))
31a85ea9
MD
955 return -EINVAL;
956 uit->encoding = encoding;
957 uit->alignment = lit->alignment;
958 return 0;
959}
960
32ce8569 961static
f69fe5fb 962int serialize_dynamic_type(struct lttng_ust_session *session,
249cffb5 963 struct lttng_ust_ctl_field *fields, size_t *iter_output,
218deb69 964 const char *field_name)
32ce8569 965{
3d33ca1d 966 const struct lttng_ust_event_field * const *choices;
fd17d7ce 967 char tag_field_name[LTTNG_UST_ABI_SYM_NAME_LEN];
4e48b5d2
MD
968 const struct lttng_ust_type_common *tag_type;
969 const struct lttng_ust_event_field *tag_field_generic;
25cff019 970 struct lttng_ust_event_field tag_field = {
53569322
MD
971 .name = tag_field_name,
972 .nowrite = 0,
973 };
249cffb5 974 struct lttng_ust_ctl_field *uf;
53569322 975 size_t nr_choices, i;
32ce8569
MD
976 int ret;
977
53569322 978 tag_field_generic = lttng_ust_dynamic_type_tag_field();
a084756d 979 tag_type = tag_field_generic->type;
53569322
MD
980
981 /* Serialize enum field. */
fd17d7ce
MD
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';
53569322
MD
984 strncat(tag_field_name,
985 "_tag",
fd17d7ce 986 LTTNG_UST_ABI_SYM_NAME_LEN - strlen(tag_field_name) - 1);
a084756d 987 tag_field.type = tag_type;
53569322 988 ret = serialize_one_field(session, fields, iter_output,
28db0827 989 &tag_field, NULL);
53569322
MD
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
fd17d7ce
MD
999 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1000 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
249cffb5 1001 uf->type.atype = lttng_ust_ctl_atype_variant;
218deb69
MD
1002 uf->type.u.variant_nestable.nr_choices = nr_choices;
1003 strncpy(uf->type.u.variant_nestable.tag_name,
53569322 1004 tag_field_name,
fd17d7ce
MD
1005 LTTNG_UST_ABI_SYM_NAME_LEN);
1006 uf->type.u.variant_nestable.tag_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
218deb69 1007 uf->type.u.variant_nestable.alignment = 0;
53569322
MD
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,
28db0827 1013 iter_output, choices[i], NULL);
53569322
MD
1014 if (ret)
1015 return ret;
1016 }
1017 return 0;
1018}
1019
1020static
f69fe5fb 1021int serialize_one_type(struct lttng_ust_session *session,
249cffb5 1022 struct lttng_ust_ctl_field *fields, size_t *iter_output,
4e48b5d2 1023 const char *field_name, const struct lttng_ust_type_common *lt,
28db0827
MD
1024 enum lttng_ust_string_encoding parent_encoding,
1025 const char *prev_field_name)
53569322 1026{
53569322
MD
1027 int ret;
1028
218deb69 1029 /*
249cffb5 1030 * Serializing a type (rather than a field) generates a lttng_ust_ctl_field
218deb69
MD
1031 * entry with 0-length name.
1032 */
53569322 1033
a084756d
MD
1034 switch (lt->type) {
1035 case lttng_ust_type_integer:
31a85ea9 1036 {
249cffb5
MJ
1037 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1038 struct lttng_ust_ctl_type *ut = &uf->type;
31a85ea9
MD
1039
1040 if (field_name) {
fd17d7ce
MD
1041 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1042 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
31a85ea9
MD
1043 } else {
1044 uf->name[0] = '\0';
1045 }
a084756d
MD
1046 ret = serialize_integer_type(&ut->u.integer, lttng_ust_get_type_integer(lt),
1047 parent_encoding);
31a85ea9
MD
1048 if (ret)
1049 return ret;
249cffb5 1050 ut->atype = lttng_ust_ctl_atype_integer;
31a85ea9
MD
1051 (*iter_output)++;
1052 break;
1053 }
a084756d 1054 case lttng_ust_type_float:
31a85ea9 1055 {
249cffb5
MJ
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;
4e48b5d2 1059 const struct lttng_ust_type_float *lft;
31a85ea9
MD
1060
1061 if (field_name) {
fd17d7ce
MD
1062 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1063 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
31a85ea9
MD
1064 } else {
1065 uf->name[0] = '\0';
1066 }
1067 uft = &ut->u._float;
a084756d 1068 lft = lttng_ust_get_type_float(lt);
31a85ea9
MD
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;
249cffb5 1073 ut->atype = lttng_ust_ctl_atype_float;
31a85ea9
MD
1074 (*iter_output)++;
1075 break;
1076 }
a084756d 1077 case lttng_ust_type_string:
31a85ea9 1078 {
249cffb5
MJ
1079 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1080 struct lttng_ust_ctl_type *ut = &uf->type;
31a85ea9
MD
1081 int32_t encoding;
1082
1083 if (field_name) {
fd17d7ce
MD
1084 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1085 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
31a85ea9
MD
1086 } else {
1087 uf->name[0] = '\0';
1088 }
a084756d 1089 ret = serialize_string_encoding(&encoding, lttng_ust_get_type_string(lt)->encoding);
31a85ea9
MD
1090 if (ret)
1091 return ret;
1092 ut->u.string.encoding = encoding;
249cffb5 1093 ut->atype = lttng_ust_ctl_atype_string;
31a85ea9
MD
1094 (*iter_output)++;
1095 break;
1096 }
a084756d 1097 case lttng_ust_type_array:
218deb69 1098 {
249cffb5
MJ
1099 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1100 struct lttng_ust_ctl_type *ut = &uf->type;
218deb69
MD
1101
1102 if (field_name) {
fd17d7ce
MD
1103 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1104 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
218deb69
MD
1105 } else {
1106 uf->name[0] = '\0';
1107 }
249cffb5 1108 ut->atype = lttng_ust_ctl_atype_array_nestable;
a084756d
MD
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;
218deb69
MD
1111 (*iter_output)++;
1112
1113 ret = serialize_one_type(session, fields, iter_output, NULL,
a084756d 1114 lttng_ust_get_type_array(lt)->elem_type,
28db0827 1115 lttng_ust_get_type_array(lt)->encoding, NULL);
218deb69
MD
1116 if (ret)
1117 return -EINVAL;
1118 break;
1119 }
a084756d 1120 case lttng_ust_type_sequence:
218deb69 1121 {
249cffb5
MJ
1122 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1123 struct lttng_ust_ctl_type *ut = &uf->type;
28db0827 1124 const char *length_name = lttng_ust_get_type_sequence(lt)->length_name;
218deb69
MD
1125
1126 if (field_name) {
fd17d7ce
MD
1127 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1128 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
218deb69
MD
1129 } else {
1130 uf->name[0] = '\0';
1131 }
249cffb5 1132 ut->atype = lttng_ust_ctl_atype_sequence_nestable;
28db0827
MD
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;
218deb69 1141 strncpy(ut->u.sequence_nestable.length_name,
28db0827 1142 length_name, LTTNG_UST_ABI_SYM_NAME_LEN);
fd17d7ce 1143 ut->u.sequence_nestable.length_name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
a084756d 1144 ut->u.sequence_nestable.alignment = lttng_ust_get_type_sequence(lt)->alignment;
218deb69
MD
1145 (*iter_output)++;
1146
1147 ret = serialize_one_type(session, fields, iter_output, NULL,
a084756d 1148 lttng_ust_get_type_sequence(lt)->elem_type,
28db0827 1149 lttng_ust_get_type_sequence(lt)->encoding, NULL);
218deb69
MD
1150 if (ret)
1151 return -EINVAL;
1152 break;
1153 }
a084756d 1154 case lttng_ust_type_dynamic:
53569322 1155 {
218deb69
MD
1156 ret = serialize_dynamic_type(session, fields, iter_output,
1157 field_name);
53569322
MD
1158 if (ret)
1159 return -EINVAL;
1160 break;
1161 }
a084756d 1162 case lttng_ust_type_struct:
218deb69 1163 {
249cffb5 1164 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
218deb69
MD
1165
1166 if (field_name) {
fd17d7ce
MD
1167 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1168 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
218deb69
MD
1169 } else {
1170 uf->name[0] = '\0';
1171 }
249cffb5 1172 uf->type.atype = lttng_ust_ctl_atype_struct_nestable;
a084756d
MD
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;
218deb69
MD
1175 (*iter_output)++;
1176
1177 ret = serialize_fields(session, fields, iter_output,
a084756d
MD
1178 lttng_ust_get_type_struct(lt)->nr_fields,
1179 lttng_ust_get_type_struct(lt)->fields);
218deb69
MD
1180 if (ret)
1181 return -EINVAL;
1182 break;
1183 }
a084756d 1184 case lttng_ust_type_enum:
218deb69 1185 {
249cffb5
MJ
1186 struct lttng_ust_ctl_field *uf = &fields[*iter_output];
1187 struct lttng_ust_ctl_type *ut = &uf->type;
218deb69
MD
1188
1189 if (field_name) {
fd17d7ce
MD
1190 strncpy(uf->name, field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
1191 uf->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
218deb69
MD
1192 } else {
1193 uf->name[0] = '\0';
1194 }
a084756d 1195 strncpy(ut->u.enum_nestable.name, lttng_ust_get_type_enum(lt)->desc->name,
fd17d7ce
MD
1196 LTTNG_UST_ABI_SYM_NAME_LEN);
1197 ut->u.enum_nestable.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
249cffb5 1198 ut->atype = lttng_ust_ctl_atype_enum_nestable;
218deb69
MD
1199 (*iter_output)++;
1200
1201 ret = serialize_one_type(session, fields, iter_output, NULL,
a084756d 1202 lttng_ust_get_type_enum(lt)->container_type,
28db0827 1203 lttng_ust_string_encoding_none, NULL);
218deb69
MD
1204 if (ret)
1205 return -EINVAL;
1206 if (session) {
1207 const struct lttng_enum *_enum;
1208
a084756d 1209 _enum = lttng_ust_enum_get_from_desc(session, lttng_ust_get_type_enum(lt)->desc);
218deb69
MD
1210 if (!_enum)
1211 return -EINVAL;
1212 ut->u.enum_nestable.id = _enum->id;
1213 } else {
1214 ut->u.enum_nestable.id = -1ULL;
1215 }
32ce8569
MD
1216 break;
1217 }
32ce8569
MD
1218 default:
1219 return -EINVAL;
1220 }
1221 return 0;
1222}
1223
218deb69 1224static
f69fe5fb 1225int serialize_one_field(struct lttng_ust_session *session,
249cffb5 1226 struct lttng_ust_ctl_field *fields, size_t *iter_output,
28db0827
MD
1227 const struct lttng_ust_event_field *lf,
1228 const char **prev_field_name_p)
218deb69 1229{
28db0827
MD
1230 const char *prev_field_name = NULL;
1231 int ret;
1232
218deb69
MD
1233 /* skip 'nowrite' fields */
1234 if (lf->nowrite)
1235 return 0;
1236
28db0827
MD
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;
218deb69
MD
1244}
1245
32ce8569 1246static
f69fe5fb 1247int serialize_fields(struct lttng_ust_session *session,
249cffb5 1248 struct lttng_ust_ctl_field *lttng_ust_ctl_fields,
218deb69 1249 size_t *iter_output, size_t nr_lttng_fields,
3d33ca1d 1250 const struct lttng_ust_event_field * const *lttng_fields)
218deb69 1251{
28db0827 1252 const char *prev_field_name = NULL;
218deb69
MD
1253 int ret;
1254 size_t i;
1255
1256 for (i = 0; i < nr_lttng_fields; i++) {
249cffb5 1257 ret = serialize_one_field(session, lttng_ust_ctl_fields,
28db0827
MD
1258 iter_output, lttng_fields[i],
1259 &prev_field_name);
218deb69
MD
1260 if (ret)
1261 return ret;
1262 }
1263 return 0;
1264}
1265
1266static
f69fe5fb 1267int alloc_serialize_fields(struct lttng_ust_session *session,
c785c634 1268 size_t *_nr_write_fields,
249cffb5 1269 struct lttng_ust_ctl_field **lttng_ust_ctl_fields,
32ce8569 1270 size_t nr_fields,
3d33ca1d 1271 const struct lttng_ust_event_field * const *lttng_fields)
32ce8569 1272{
249cffb5 1273 struct lttng_ust_ctl_field *fields;
53569322 1274 int ret;
218deb69 1275 size_t iter_output = 0;
53569322
MD
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 }
32ce8569 1282
53569322 1283 fields = zmalloc(nr_write_fields * sizeof(*fields));
32ce8569
MD
1284 if (!fields)
1285 return -ENOMEM;
1286
218deb69
MD
1287 ret = serialize_fields(session, fields, &iter_output, nr_fields,
1288 lttng_fields);
1289 if (ret)
1290 goto error_type;
32ce8569
MD
1291
1292 *_nr_write_fields = nr_write_fields;
249cffb5 1293 *lttng_ust_ctl_fields = fields;
32ce8569
MD
1294 return 0;
1295
1296error_type:
1297 free(fields);
1298 return ret;
1299}
1300
c785c634 1301static
249cffb5 1302int serialize_entries(struct lttng_ust_ctl_enum_entry **_entries,
c785c634 1303 size_t nr_entries,
3d33ca1d 1304 const struct lttng_ust_enum_entry * const *lttng_entries)
c785c634 1305{
249cffb5 1306 struct lttng_ust_ctl_enum_entry *entries;
c785c634
MD
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++) {
249cffb5 1314 struct lttng_ust_ctl_enum_entry *uentry;
891d6b55 1315 const struct lttng_ust_enum_entry *lentry;
c785c634
MD
1316
1317 uentry = &entries[i];
891d6b55 1318 lentry = lttng_entries[i];
c785c634 1319
a6f80644
MD
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;
fd17d7ce
MD
1324 strncpy(uentry->string, lentry->string, LTTNG_UST_ABI_SYM_NAME_LEN);
1325 uentry->string[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
3e762260 1326
1a37a873 1327 if (lentry->options & LTTNG_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
3e762260 1328 uentry->u.extra.options |=
249cffb5 1329 LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO;
3e762260 1330 }
c785c634
MD
1331 }
1332 *_entries = entries;
1333 return 0;
1334}
1335
83e43212 1336static
f69fe5fb 1337int serialize_ctx_fields(struct lttng_ust_session *session,
53569322 1338 size_t *_nr_write_fields,
249cffb5 1339 struct lttng_ust_ctl_field **lttng_ust_ctl_fields,
83e43212 1340 size_t nr_fields,
4e48b5d2 1341 struct lttng_ust_ctx_field *lttng_fields)
83e43212 1342{
249cffb5 1343 struct lttng_ust_ctl_field *fields;
28db0827 1344 const char *prev_field_name = NULL;
53569322
MD
1345 size_t i, iter_output = 0;
1346 ssize_t nr_write_fields;
28db0827 1347 int ret;
83e43212 1348
53569322
MD
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));
83e43212
MD
1356 if (!fields)
1357 return -ENOMEM;
1358
1359 for (i = 0; i < nr_fields; i++) {
53569322 1360 ret = serialize_one_field(session, fields, &iter_output,
28db0827 1361 lttng_fields[i].event_field, &prev_field_name);
83e43212
MD
1362 if (ret)
1363 goto error_type;
83e43212
MD
1364 }
1365
1366 *_nr_write_fields = nr_write_fields;
249cffb5 1367 *lttng_ust_ctl_fields = fields;
83e43212
MD
1368 return 0;
1369
1370error_type:
1371 free(fields);
1372 return ret;
1373}
1374
32ce8569
MD
1375/*
1376 * Returns 0 on success, negative error value on error.
1377 */
1378int ustcomm_register_event(int sock,
f69fe5fb 1379 struct lttng_ust_session *session,
32ce8569
MD
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 */
3d33ca1d 1386 const struct lttng_ust_event_field * const *lttng_fields,
32ce8569
MD
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;
249cffb5 1400 struct lttng_ust_ctl_field *fields = NULL;
32ce8569
MD
1401 size_t nr_write_fields = 0;
1402 int ret;
1403
1404 memset(&msg, 0, sizeof(msg));
249cffb5 1405 msg.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_EVENT;
32ce8569
MD
1406 msg.m.session_objd = session_objd;
1407 msg.m.channel_objd = channel_objd;
fd17d7ce
MD
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';
32ce8569
MD
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) {
218deb69 1416 ret = alloc_serialize_fields(session, &nr_write_fields, &fields,
32ce8569
MD
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;
c785c634 1430
32ce8569
MD
1431 len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
1432 if (len > 0 && len != sizeof(msg)) {
c785c634
MD
1433 ret = -EIO;
1434 goto error_fields;
32ce8569
MD
1435 }
1436 if (len < 0) {
c785c634
MD
1437 ret = len;
1438 goto error_fields;
32ce8569
MD
1439 }
1440
1441 /* send signature */
1442 len = ustcomm_send_unix_sock(sock, signature, signature_len);
1443 if (len > 0 && len != signature_len) {
6b95617c
MD
1444 ret = -EIO;
1445 goto error_fields;
32ce8569
MD
1446 }
1447 if (len < 0) {
6b95617c
MD
1448 ret = len;
1449 goto error_fields;
32ce8569
MD
1450 }
1451
1452 /* send fields */
1453 if (fields_len > 0) {
1454 len = ustcomm_send_unix_sock(sock, fields, fields_len);
32ce8569 1455 if (len > 0 && len != fields_len) {
c785c634
MD
1456 ret = -EIO;
1457 goto error_fields;
32ce8569
MD
1458 }
1459 if (len < 0) {
c785c634
MD
1460 ret = len;
1461 goto error_fields;
32ce8569
MD
1462 }
1463 }
6b95617c 1464 free(fields);
32ce8569
MD
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);
c785c634 1470 if (len > 0 && len != model_emf_uri_len) {
6b95617c 1471 return -EIO;
c785c634
MD
1472 }
1473 if (len < 0) {
6b95617c 1474 return len;
c785c634 1475 }
32ce8569
MD
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 }
6b95617c 1509 /* Unreached. */
c785c634 1510
6b95617c 1511 /* Error path only. */
c785c634
MD
1512error_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 */
1521int 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 */
3d33ca1d 1525 const struct lttng_ust_enum_entry * const *lttng_entries,
c785c634
MD
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;
249cffb5 1538 struct lttng_ust_ctl_enum_entry *entries = NULL;
c785c634
MD
1539 int ret;
1540
1541 memset(&msg, 0, sizeof(msg));
249cffb5 1542 msg.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_ENUM;
c785c634 1543 msg.m.session_objd = session_objd;
fd17d7ce
MD
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';
c785c634
MD
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
1616error_entries:
1617 free(entries);
1618 return ret;
32ce8569
MD
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 */
1625int ustcomm_register_channel(int sock,
f69fe5fb 1626 struct lttng_ust_session *session,
32ce8569
MD
1627 int session_objd, /* session descriptor */
1628 int channel_objd, /* channel descriptor */
1629 size_t nr_ctx_fields,
4e48b5d2 1630 struct lttng_ust_ctx_field *ctx_fields,
32ce8569
MD
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;
249cffb5 1644 struct lttng_ust_ctl_field *fields = NULL;
32ce8569
MD
1645 int ret;
1646 size_t nr_write_fields = 0;
1647
1648 memset(&msg, 0, sizeof(msg));
249cffb5 1649 msg.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_CHANNEL;
32ce8569
MD
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) {
53569322 1655 ret = serialize_ctx_fields(session, &nr_write_fields, &fields,
32ce8569
MD
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 }
17ea789c
MD
1683 } else {
1684 free(fields);
32ce8569
MD
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}
ff517991
MD
1728
1729/*
1730 * Set socket reciving timeout.
1731 */
1732int 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 */
1752int 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.125733 seconds and 4 git commands to generate.