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