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