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