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