Fix: ustctl: return -EPIPE to sessiond if connection is closed
[lttng-ust.git] / liblttng-ust-comm / lttng-ust-comm.c
1 /*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 * Copyright (C) 2011-2013 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
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,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
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
18 */
19
20 #define _GNU_SOURCE
21 #include <limits.h>
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>
31 #include <errno.h>
32 #include <fcntl.h>
33
34 #include <lttng/ust-ctl.h>
35 #include <ust-comm.h>
36 #include <helper.h>
37 #include <lttng/ust-error.h>
38 #include <lttng/ust-events.h>
39 #include <usterr-signal-safe.h>
40
41 #include "../liblttng-ust/compat.h"
42
43 #define USTCOMM_CODE_OFFSET(code) \
44 (code == LTTNG_UST_OK ? 0 : (code - LTTNG_UST_ERR + 1))
45
46 #define USTCOMM_MAX_SEND_FDS 4
47
48 /*
49 * Human readable error message.
50 */
51 static const char *ustcomm_readable_code[] = {
52 [ USTCOMM_CODE_OFFSET(LTTNG_UST_OK) ] = "Success",
53 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR) ] = "Unknown error",
54 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_NOENT) ] = "No entry",
55 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_EXIST) ] = "Object already exists",
56 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_INVAL) ] = "Invalid argument",
57 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_PERM) ] = "Permission denied",
58 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_NOSYS) ] = "Not implemented",
59 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_EXITING) ] = "Process is exiting",
60
61 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_INVAL_MAGIC) ] = "Invalid magic number",
62 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_INVAL_SOCKET_TYPE) ] = "Invalid socket type",
63 [ USTCOMM_CODE_OFFSET(LTTNG_UST_ERR_UNSUP_MAJOR) ] = "Unsupported major version",
64 };
65
66 /*
67 * lttng_ust_strerror
68 *
69 * Receives positive error value.
70 * Return ptr to string representing a human readable
71 * error code from the ustcomm_return_code enum.
72 */
73 const char *lttng_ust_strerror(int code)
74 {
75 if (code == LTTNG_UST_OK)
76 return ustcomm_readable_code[USTCOMM_CODE_OFFSET(code)];
77 if (code < LTTNG_UST_ERR)
78 return strerror(code);
79 if (code >= LTTNG_UST_ERR_NR)
80 code = LTTNG_UST_ERR;
81 return ustcomm_readable_code[USTCOMM_CODE_OFFSET(code)];
82
83 }
84
85 /*
86 * ustcomm_connect_unix_sock
87 *
88 * Connect to unix socket using the path name.
89 */
90 int ustcomm_connect_unix_sock(const char *pathname)
91 {
92 struct sockaddr_un sun;
93 int fd, ret;
94
95 /*
96 * libust threads require the close-on-exec flag for all
97 * resources so it does not leak file descriptors upon exec.
98 */
99 fd = socket(PF_UNIX, SOCK_STREAM, 0);
100 if (fd < 0) {
101 PERROR("socket");
102 ret = -errno;
103 goto error;
104 }
105 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
106 if (ret < 0) {
107 PERROR("fcntl");
108 ret = -errno;
109 goto error_fcntl;
110 }
111
112 memset(&sun, 0, sizeof(sun));
113 sun.sun_family = AF_UNIX;
114 strncpy(sun.sun_path, pathname, sizeof(sun.sun_path));
115 sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
116
117 ret = connect(fd, (struct sockaddr *) &sun, sizeof(sun));
118 if (ret < 0) {
119 /*
120 * Don't print message on connect error, because connect
121 * is used in normal execution to detect if sessiond is
122 * alive.
123 */
124 ret = -errno;
125 goto error_connect;
126 }
127
128 return fd;
129
130 error_connect:
131 error_fcntl:
132 {
133 int closeret;
134
135 closeret = close(fd);
136 if (closeret)
137 PERROR("close");
138 }
139 error:
140 return ret;
141 }
142
143 /*
144 * ustcomm_accept_unix_sock
145 *
146 * Do an accept(2) on the sock and return the
147 * new file descriptor. The socket MUST be bind(2) before.
148 */
149 int ustcomm_accept_unix_sock(int sock)
150 {
151 int new_fd;
152 struct sockaddr_un sun;
153 socklen_t len = 0;
154
155 /* Blocking call */
156 new_fd = accept(sock, (struct sockaddr *) &sun, &len);
157 if (new_fd < 0) {
158 if (errno != ECONNABORTED)
159 PERROR("accept");
160 new_fd = -errno;
161 if (new_fd == -ECONNABORTED)
162 new_fd = -EPIPE;
163 }
164 return new_fd;
165 }
166
167 /*
168 * ustcomm_create_unix_sock
169 *
170 * Creates a AF_UNIX local socket using pathname
171 * bind the socket upon creation and return the fd.
172 */
173 int ustcomm_create_unix_sock(const char *pathname)
174 {
175 struct sockaddr_un sun;
176 int fd, ret;
177
178 /* Create server socket */
179 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
180 PERROR("socket");
181 ret = -errno;
182 goto error;
183 }
184
185 memset(&sun, 0, sizeof(sun));
186 sun.sun_family = AF_UNIX;
187 strncpy(sun.sun_path, pathname, sizeof(sun.sun_path));
188 sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
189
190 /* Unlink the old file if present */
191 (void) unlink(pathname);
192 ret = bind(fd, (struct sockaddr *) &sun, sizeof(sun));
193 if (ret < 0) {
194 PERROR("bind");
195 ret = -errno;
196 goto error_close;
197 }
198
199 return fd;
200
201 error_close:
202 {
203 int closeret;
204
205 closeret = close(fd);
206 if (closeret) {
207 PERROR("close");
208 }
209 }
210 error:
211 return ret;
212 }
213
214 /*
215 * ustcomm_listen_unix_sock
216 *
217 * Make the socket listen using LTTNG_UST_COMM_MAX_LISTEN.
218 */
219 int ustcomm_listen_unix_sock(int sock)
220 {
221 int ret;
222
223 ret = listen(sock, LTTNG_UST_COMM_MAX_LISTEN);
224 if (ret < 0) {
225 ret = -errno;
226 PERROR("listen");
227 }
228
229 return ret;
230 }
231
232 /*
233 * ustcomm_close_unix_sock
234 *
235 * Shutdown cleanly a unix socket.
236 */
237 int ustcomm_close_unix_sock(int sock)
238 {
239 int ret;
240
241 ret = close(sock);
242 if (ret < 0) {
243 PERROR("close");
244 ret = -errno;
245 }
246
247 return ret;
248 }
249
250 /*
251 * ustcomm_recv_unix_sock
252 *
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.
257 */
258 ssize_t ustcomm_recv_unix_sock(int sock, void *buf, size_t len)
259 {
260 struct msghdr msg;
261 struct iovec iov[1];
262 ssize_t ret;
263
264 memset(&msg, 0, sizeof(msg));
265
266 iov[0].iov_base = buf;
267 iov[0].iov_len = len;
268 msg.msg_iov = iov;
269 msg.msg_iovlen = 1;
270
271 do {
272 ret = recvmsg(sock, &msg, 0);
273 } while (ret < 0 && errno == EINTR);
274
275 if (ret < 0) {
276 int shutret;
277
278 if (errno != EPIPE && errno != ECONNRESET)
279 PERROR("recvmsg");
280 ret = -errno;
281 if (ret == -ECONNRESET)
282 ret = -EPIPE;
283
284 shutret = shutdown(sock, SHUT_RDWR);
285 if (shutret)
286 ERR("Socket shutdown error");
287 }
288
289 return ret;
290 }
291
292 /*
293 * ustcomm_send_unix_sock
294 *
295 * Send buf data of size len. Using sendmsg API.
296 * Return the size of sent data.
297 */
298 ssize_t ustcomm_send_unix_sock(int sock, const void *buf, size_t len)
299 {
300 struct msghdr msg;
301 struct iovec iov[1];
302 ssize_t ret;
303
304 memset(&msg, 0, sizeof(msg));
305
306 iov[0].iov_base = (void *) buf;
307 iov[0].iov_len = len;
308 msg.msg_iov = iov;
309 msg.msg_iovlen = 1;
310
311 /*
312 * Using the MSG_NOSIGNAL when sending data from sessiond to
313 * libust, so libust does not receive an unhandled SIGPIPE or
314 * SIGURG. The sessiond receiver side can be made more resilient
315 * by ignoring SIGPIPE, but we don't have this luxury on the
316 * libust side.
317 */
318 do {
319 ret = sendmsg(sock, &msg, MSG_NOSIGNAL);
320 } while (ret < 0 && errno == EINTR);
321
322 if (ret < 0) {
323 int shutret;
324
325 if (errno != EPIPE && errno != ECONNRESET)
326 PERROR("sendmsg");
327 ret = -errno;
328 if (ret == -ECONNRESET)
329 ret = -EPIPE;
330
331 shutret = shutdown(sock, SHUT_RDWR);
332 if (shutret)
333 ERR("Socket shutdown error");
334 }
335
336 return ret;
337 }
338
339 /*
340 * Send a message accompanied by fd(s) over a unix socket.
341 *
342 * Returns the size of data sent, or negative error value.
343 */
344 ssize_t ustcomm_send_fds_unix_sock(int sock, int *fds, size_t nb_fd)
345 {
346 struct msghdr msg;
347 struct cmsghdr *cmptr;
348 struct iovec iov[1];
349 ssize_t ret = -1;
350 unsigned int sizeof_fds = nb_fd * sizeof(int);
351 char tmp[CMSG_SPACE(sizeof_fds)];
352 char dummy = 0;
353
354 memset(&msg, 0, sizeof(msg));
355 memset(tmp, 0, CMSG_SPACE(sizeof_fds) * sizeof(char));
356
357 if (nb_fd > USTCOMM_MAX_SEND_FDS)
358 return -EINVAL;
359
360 msg.msg_control = (caddr_t)tmp;
361 msg.msg_controllen = CMSG_LEN(sizeof_fds);
362
363 cmptr = CMSG_FIRSTHDR(&msg);
364 cmptr->cmsg_level = SOL_SOCKET;
365 cmptr->cmsg_type = SCM_RIGHTS;
366 cmptr->cmsg_len = CMSG_LEN(sizeof_fds);
367 memcpy(CMSG_DATA(cmptr), fds, sizeof_fds);
368 /* Sum of the length of all control messages in the buffer: */
369 msg.msg_controllen = cmptr->cmsg_len;
370
371 iov[0].iov_base = &dummy;
372 iov[0].iov_len = 1;
373 msg.msg_iov = iov;
374 msg.msg_iovlen = 1;
375
376 do {
377 ret = sendmsg(sock, &msg, 0);
378 } while (ret < 0 && errno == EINTR);
379 if (ret < 0) {
380 /*
381 * We consider EPIPE and ECONNRESET as expected.
382 */
383 if (errno != EPIPE && errno != ECONNRESET) {
384 PERROR("sendmsg");
385 }
386 ret = -errno;
387 if (ret == -ECONNRESET)
388 ret = -EPIPE;
389 }
390 return ret;
391 }
392
393 /*
394 * Recv a message accompanied by fd(s) from a unix socket.
395 *
396 * Returns the size of received data, or negative error value.
397 *
398 * Expect at most "nb_fd" file descriptors. Returns the number of fd
399 * actually received in nb_fd.
400 * Returns -EPIPE on orderly shutdown.
401 */
402 ssize_t ustcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd)
403 {
404 struct iovec iov[1];
405 ssize_t ret = 0;
406 struct cmsghdr *cmsg;
407 size_t sizeof_fds = nb_fd * sizeof(int);
408 char recv_fd[CMSG_SPACE(sizeof_fds)];
409 struct msghdr msg;
410 char dummy;
411
412 memset(&msg, 0, sizeof(msg));
413
414 /* Prepare to receive the structures */
415 iov[0].iov_base = &dummy;
416 iov[0].iov_len = 1;
417 msg.msg_iov = iov;
418 msg.msg_iovlen = 1;
419 msg.msg_control = recv_fd;
420 msg.msg_controllen = sizeof(recv_fd);
421
422 do {
423 ret = recvmsg(sock, &msg, 0);
424 } while (ret < 0 && errno == EINTR);
425 if (ret < 0) {
426 if (errno != EPIPE && errno != ECONNRESET) {
427 PERROR("recvmsg fds");
428 }
429 if (errno == EPIPE || errno == ECONNRESET)
430 ret = -errno;
431 if (ret == -ECONNRESET)
432 ret = -EPIPE;
433 goto end;
434 }
435 if (ret == 0) {
436 /* orderly shutdown */
437 ret = -EPIPE;
438 goto end;
439 }
440 if (ret != 1) {
441 ERR("Error: Received %zd bytes, expected %d\n",
442 ret, 1);
443 goto end;
444 }
445 if (msg.msg_flags & MSG_CTRUNC) {
446 ERR("Error: Control message truncated.\n");
447 ret = -1;
448 goto end;
449 }
450 cmsg = CMSG_FIRSTHDR(&msg);
451 if (!cmsg) {
452 ERR("Error: Invalid control message header\n");
453 ret = -1;
454 goto end;
455 }
456 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
457 ERR("Didn't received any fd\n");
458 ret = -1;
459 goto end;
460 }
461 if (cmsg->cmsg_len != CMSG_LEN(sizeof_fds)) {
462 ERR("Error: Received %zu bytes of ancillary data, expected %zu\n",
463 (size_t) cmsg->cmsg_len, (size_t) CMSG_LEN(sizeof_fds));
464 ret = -1;
465 goto end;
466 }
467 memcpy(fds, CMSG_DATA(cmsg), sizeof_fds);
468 ret = sizeof_fds;
469 end:
470 return ret;
471 }
472
473 int ustcomm_send_app_msg(int sock, struct ustcomm_ust_msg *lum)
474 {
475 ssize_t len;
476
477 len = ustcomm_send_unix_sock(sock, lum, sizeof(*lum));
478 switch (len) {
479 case sizeof(*lum):
480 break;
481 default:
482 if (len < 0) {
483 return len;
484 } else {
485 ERR("incorrect message size: %zd\n", len);
486 return -EINVAL;
487 }
488 }
489 return 0;
490 }
491
492 int ustcomm_recv_app_reply(int sock, struct ustcomm_ust_reply *lur,
493 uint32_t expected_handle, uint32_t expected_cmd)
494 {
495 ssize_t len;
496
497 memset(lur, 0, sizeof(*lur));
498 len = ustcomm_recv_unix_sock(sock, lur, sizeof(*lur));
499 switch (len) {
500 case 0: /* orderly shutdown */
501 return -EPIPE;
502 case sizeof(*lur):
503 if (lur->handle != expected_handle) {
504 ERR("Unexpected result message handle: "
505 "expected: %u vs received: %u\n",
506 expected_handle, lur->handle);
507 return -EINVAL;
508 }
509 if (lur->cmd != expected_cmd) {
510 ERR("Unexpected result message command "
511 "expected: %u vs received: %u\n",
512 expected_cmd, lur->cmd);
513 return -EINVAL;
514 }
515 return lur->ret_code;
516 default:
517 if (len < 0) {
518 /* Transport level error */
519 if (errno == EPIPE || errno == ECONNRESET)
520 len = -errno;
521 return len;
522 } else {
523 ERR("incorrect message size: %zd\n", len);
524 return len;
525 }
526 }
527 }
528
529 int ustcomm_send_app_cmd(int sock,
530 struct ustcomm_ust_msg *lum,
531 struct ustcomm_ust_reply *lur)
532 {
533 int ret;
534
535 ret = ustcomm_send_app_msg(sock, lum);
536 if (ret)
537 return ret;
538 ret = ustcomm_recv_app_reply(sock, lur, lum->handle, lum->cmd);
539 if (ret > 0)
540 return -EIO;
541 return ret;
542 }
543
544 /*
545 * chan_data is allocated internally if this function returns the
546 * expected var_len.
547 */
548 ssize_t ustcomm_recv_channel_from_sessiond(int sock,
549 void **_chan_data, uint64_t var_len)
550 {
551 void *chan_data;
552 ssize_t len;
553
554 if (var_len > LTTNG_UST_CHANNEL_DATA_MAX_LEN) {
555 len = -EINVAL;
556 goto error_check;
557 }
558 /* Receive variable length data */
559 chan_data = zmalloc(var_len);
560 if (!chan_data) {
561 len = -ENOMEM;
562 goto error_alloc;
563 }
564 len = ustcomm_recv_unix_sock(sock, chan_data, var_len);
565 if (len != var_len) {
566 goto error_recv;
567 }
568 *_chan_data = chan_data;
569 return len;
570
571 error_recv:
572 free(chan_data);
573 error_alloc:
574 error_check:
575 return len;
576 }
577
578 int ustcomm_recv_stream_from_sessiond(int sock,
579 uint64_t *memory_map_size,
580 int *shm_fd, int *wakeup_fd)
581 {
582 ssize_t len;
583 int ret;
584 int fds[2];
585
586 /* recv shm fd and wakeup fd */
587 len = ustcomm_recv_fds_unix_sock(sock, fds, 2);
588 if (len <= 0) {
589 if (len < 0) {
590 ret = len;
591 goto error;
592 } else {
593 ret = -EIO;
594 goto error;
595 }
596 }
597 *shm_fd = fds[0];
598 *wakeup_fd = fds[1];
599 return 0;
600
601 error:
602 return ret;
603 }
604
605 /*
606 * Returns 0 on success, negative error value on error.
607 */
608 int ustcomm_send_reg_msg(int sock,
609 enum ustctl_socket_type type,
610 uint32_t bits_per_long,
611 uint32_t uint8_t_alignment,
612 uint32_t uint16_t_alignment,
613 uint32_t uint32_t_alignment,
614 uint32_t uint64_t_alignment,
615 uint32_t long_alignment)
616 {
617 ssize_t len;
618 struct ustctl_reg_msg reg_msg;
619
620 reg_msg.magic = LTTNG_UST_COMM_MAGIC;
621 reg_msg.major = LTTNG_UST_ABI_MAJOR_VERSION;
622 reg_msg.minor = LTTNG_UST_ABI_MINOR_VERSION;
623 reg_msg.pid = getpid();
624 reg_msg.ppid = getppid();
625 reg_msg.uid = getuid();
626 reg_msg.gid = getgid();
627 reg_msg.bits_per_long = bits_per_long;
628 reg_msg.uint8_t_alignment = uint8_t_alignment;
629 reg_msg.uint16_t_alignment = uint16_t_alignment;
630 reg_msg.uint32_t_alignment = uint32_t_alignment;
631 reg_msg.uint64_t_alignment = uint64_t_alignment;
632 reg_msg.long_alignment = long_alignment;
633 reg_msg.socket_type = type;
634 lttng_ust_getprocname(reg_msg.name);
635 memset(reg_msg.padding, 0, sizeof(reg_msg.padding));
636
637 len = ustcomm_send_unix_sock(sock, &reg_msg, sizeof(reg_msg));
638 if (len > 0 && len != sizeof(reg_msg))
639 return -EIO;
640 if (len < 0)
641 return len;
642 return 0;
643 }
644
645 static
646 int serialize_basic_type(enum ustctl_abstract_types *uatype,
647 enum lttng_abstract_types atype,
648 union _ustctl_basic_type *ubt,
649 const union _lttng_basic_type *lbt)
650 {
651 switch (atype) {
652 case atype_integer:
653 {
654 struct ustctl_integer_type *uit;
655 const struct lttng_integer_type *lit;
656
657 uit = &ubt->integer;
658 lit = &lbt->integer;
659 uit->size = lit->size;
660 uit->signedness = lit->signedness;
661 uit->reverse_byte_order = lit->reverse_byte_order;
662 uit->base = lit->base;
663 uit->encoding = lit->encoding;
664 uit->alignment = lit->alignment;
665 *uatype = ustctl_atype_integer;
666 break;
667 }
668 case atype_string:
669 {
670 ubt->string.encoding = lbt->string.encoding;
671 *uatype = ustctl_atype_string;
672 break;
673 }
674 case atype_float:
675 {
676 struct ustctl_float_type *uft;
677 const struct lttng_float_type *lft;
678
679 uft = &ubt->_float;
680 lft = &lbt->_float;
681 uft->exp_dig = lft->exp_dig;
682 uft->mant_dig = lft->mant_dig;
683 uft->alignment = lft->alignment;
684 uft->reverse_byte_order = lft->reverse_byte_order;
685 *uatype = ustctl_atype_float;
686 break;
687 }
688 case atype_enum:
689 case atype_array:
690 case atype_sequence:
691 default:
692 return -EINVAL;
693 }
694 return 0;
695 }
696
697 static
698 int serialize_one_type(struct ustctl_type *ut, const struct lttng_type *lt)
699 {
700 int ret;
701
702 switch (lt->atype) {
703 case atype_integer:
704 case atype_float:
705 case atype_string:
706 ret = serialize_basic_type(&ut->atype, lt->atype,
707 &ut->u.basic, &lt->u.basic);
708 if (ret)
709 return ret;
710 break;
711 case atype_array:
712 {
713 struct ustctl_basic_type *ubt;
714 const struct lttng_basic_type *lbt;
715 int ret;
716
717 ubt = &ut->u.array.elem_type;
718 lbt = &lt->u.array.elem_type;
719 ut->u.array.length = lt->u.array.length;
720 ret = serialize_basic_type(&ubt->atype, lbt->atype,
721 &ubt->u.basic, &lbt->u.basic);
722 if (ret)
723 return -EINVAL;
724 ut->atype = ustctl_atype_array;
725 break;
726 }
727 case atype_sequence:
728 {
729 struct ustctl_basic_type *ubt;
730 const struct lttng_basic_type *lbt;
731 int ret;
732
733 ubt = &ut->u.sequence.length_type;
734 lbt = &lt->u.sequence.length_type;
735 ret = serialize_basic_type(&ubt->atype, lbt->atype,
736 &ubt->u.basic, &lbt->u.basic);
737 if (ret)
738 return -EINVAL;
739 ubt = &ut->u.sequence.elem_type;
740 lbt = &lt->u.sequence.elem_type;
741 ret = serialize_basic_type(&ubt->atype, lbt->atype,
742 &ubt->u.basic, &lbt->u.basic);
743 if (ret)
744 return -EINVAL;
745 ut->atype = ustctl_atype_sequence;
746 break;
747 }
748 case atype_enum:
749 default:
750 return -EINVAL;
751 }
752 return 0;
753 }
754
755 static
756 int serialize_fields(size_t *_nr_write_fields,
757 struct ustctl_field **ustctl_fields,
758 size_t nr_fields,
759 const struct lttng_event_field *lttng_fields)
760 {
761 struct ustctl_field *fields;
762 int i, ret;
763 size_t nr_write_fields = 0;
764
765 fields = zmalloc(nr_fields * sizeof(*fields));
766 if (!fields)
767 return -ENOMEM;
768
769 for (i = 0; i < nr_fields; i++) {
770 struct ustctl_field *f;
771 const struct lttng_event_field *lf;
772
773 f = &fields[nr_write_fields];
774 lf = &lttng_fields[i];
775
776 /* skip 'nowrite' fields */
777 if (lf->nowrite)
778 continue;
779 strncpy(f->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
780 f->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
781 ret = serialize_one_type(&f->type, &lf->type);
782 if (ret)
783 goto error_type;
784 nr_write_fields++;
785 }
786
787 *_nr_write_fields = nr_write_fields;
788 *ustctl_fields = fields;
789 return 0;
790
791 error_type:
792 free(fields);
793 return ret;
794 }
795
796 /*
797 * Returns 0 on success, negative error value on error.
798 */
799 int ustcomm_register_event(int sock,
800 int session_objd, /* session descriptor */
801 int channel_objd, /* channel descriptor */
802 const char *event_name, /* event name (input) */
803 int loglevel,
804 const char *signature, /* event signature (input) */
805 size_t nr_fields, /* fields */
806 const struct lttng_event_field *lttng_fields,
807 const char *model_emf_uri,
808 uint32_t *id) /* event id (output) */
809 {
810 ssize_t len;
811 struct {
812 struct ustcomm_notify_hdr header;
813 struct ustcomm_notify_event_msg m;
814 } msg;
815 struct {
816 struct ustcomm_notify_hdr header;
817 struct ustcomm_notify_event_reply r;
818 } reply;
819 size_t signature_len, fields_len, model_emf_uri_len;
820 struct ustctl_field *fields;
821 size_t nr_write_fields = 0;
822 int ret;
823
824 memset(&msg, 0, sizeof(msg));
825 msg.header.notify_cmd = USTCTL_NOTIFY_CMD_EVENT;
826 msg.m.session_objd = session_objd;
827 msg.m.channel_objd = channel_objd;
828 strncpy(msg.m.event_name, event_name, LTTNG_UST_SYM_NAME_LEN);
829 msg.m.event_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
830 msg.m.loglevel = loglevel;
831 signature_len = strlen(signature) + 1;
832 msg.m.signature_len = signature_len;
833
834 /* Calculate fields len, serialize fields. */
835 if (nr_fields > 0) {
836 ret = serialize_fields(&nr_write_fields, &fields,
837 nr_fields, lttng_fields);
838 if (ret)
839 return ret;
840 }
841
842 fields_len = sizeof(*fields) * nr_write_fields;
843 msg.m.fields_len = fields_len;
844 if (model_emf_uri) {
845 model_emf_uri_len = strlen(model_emf_uri) + 1;
846 } else {
847 model_emf_uri_len = 0;
848 }
849 msg.m.model_emf_uri_len = model_emf_uri_len;
850 len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
851 if (len > 0 && len != sizeof(msg)) {
852 free(fields);
853 return -EIO;
854 }
855 if (len < 0) {
856 free(fields);
857 return len;
858 }
859
860 /* send signature */
861 len = ustcomm_send_unix_sock(sock, signature, signature_len);
862 if (len > 0 && len != signature_len) {
863 free(fields);
864 return -EIO;
865 }
866 if (len < 0) {
867 free(fields);
868 return len;
869 }
870
871 /* send fields */
872 if (fields_len > 0) {
873 len = ustcomm_send_unix_sock(sock, fields, fields_len);
874 free(fields);
875 if (len > 0 && len != fields_len) {
876 return -EIO;
877 }
878 if (len < 0) {
879 return len;
880 }
881 }
882
883 if (model_emf_uri_len) {
884 /* send model_emf_uri */
885 len = ustcomm_send_unix_sock(sock, model_emf_uri,
886 model_emf_uri_len);
887 if (len > 0 && len != model_emf_uri_len)
888 return -EIO;
889 if (len < 0)
890 return len;
891 }
892
893 /* receive reply */
894 len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
895 switch (len) {
896 case 0: /* orderly shutdown */
897 return -EPIPE;
898 case sizeof(reply):
899 if (reply.header.notify_cmd != msg.header.notify_cmd) {
900 ERR("Unexpected result message command "
901 "expected: %u vs received: %u\n",
902 msg.header.notify_cmd, reply.header.notify_cmd);
903 return -EINVAL;
904 }
905 if (reply.r.ret_code > 0)
906 return -EINVAL;
907 if (reply.r.ret_code < 0)
908 return reply.r.ret_code;
909 *id = reply.r.event_id;
910 DBG("Sent register event notification for name \"%s\": ret_code %d, event_id %u\n",
911 event_name, reply.r.ret_code, reply.r.event_id);
912 return 0;
913 default:
914 if (len < 0) {
915 /* Transport level error */
916 if (errno == EPIPE || errno == ECONNRESET)
917 len = -errno;
918 return len;
919 } else {
920 ERR("incorrect message size: %zd\n", len);
921 return len;
922 }
923 }
924 }
925
926 /*
927 * Returns 0 on success, negative error value on error.
928 * Returns -EPIPE or -ECONNRESET if other end has hung up.
929 */
930 int ustcomm_register_channel(int sock,
931 int session_objd, /* session descriptor */
932 int channel_objd, /* channel descriptor */
933 size_t nr_ctx_fields,
934 const struct lttng_event_field *ctx_fields,
935 uint32_t *chan_id, /* channel id (output) */
936 int *header_type) /* header type (output) */
937 {
938 ssize_t len;
939 struct {
940 struct ustcomm_notify_hdr header;
941 struct ustcomm_notify_channel_msg m;
942 } msg;
943 struct {
944 struct ustcomm_notify_hdr header;
945 struct ustcomm_notify_channel_reply r;
946 } reply;
947 size_t fields_len;
948 struct ustctl_field *fields;
949 int ret;
950 size_t nr_write_fields = 0;
951
952 memset(&msg, 0, sizeof(msg));
953 msg.header.notify_cmd = USTCTL_NOTIFY_CMD_CHANNEL;
954 msg.m.session_objd = session_objd;
955 msg.m.channel_objd = channel_objd;
956
957 /* Calculate fields len, serialize fields. */
958 if (nr_ctx_fields > 0) {
959 ret = serialize_fields(&nr_write_fields, &fields,
960 nr_ctx_fields, ctx_fields);
961 if (ret)
962 return ret;
963 }
964
965 fields_len = sizeof(*fields) * nr_write_fields;
966 msg.m.ctx_fields_len = fields_len;
967 len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
968 if (len > 0 && len != sizeof(msg)) {
969 free(fields);
970 return -EIO;
971 }
972 if (len < 0) {
973 free(fields);
974 return len;
975 }
976
977 /* send fields */
978 if (fields_len > 0) {
979 len = ustcomm_send_unix_sock(sock, fields, fields_len);
980 free(fields);
981 if (len > 0 && len != fields_len) {
982 return -EIO;
983 }
984 if (len < 0) {
985 return len;
986 }
987 }
988
989 len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
990 switch (len) {
991 case 0: /* orderly shutdown */
992 return -EPIPE;
993 case sizeof(reply):
994 if (reply.header.notify_cmd != msg.header.notify_cmd) {
995 ERR("Unexpected result message command "
996 "expected: %u vs received: %u\n",
997 msg.header.notify_cmd, reply.header.notify_cmd);
998 return -EINVAL;
999 }
1000 if (reply.r.ret_code > 0)
1001 return -EINVAL;
1002 if (reply.r.ret_code < 0)
1003 return reply.r.ret_code;
1004 *chan_id = reply.r.chan_id;
1005 switch (reply.r.header_type) {
1006 case 1:
1007 case 2:
1008 *header_type = reply.r.header_type;
1009 break;
1010 default:
1011 ERR("Unexpected channel header type %u\n",
1012 reply.r.header_type);
1013 return -EINVAL;
1014 }
1015 DBG("Sent register channel notification: chan_id %d, header_type %d\n",
1016 reply.r.chan_id, reply.r.header_type);
1017 return 0;
1018 default:
1019 if (len < 0) {
1020 /* Transport level error */
1021 if (errno == EPIPE || errno == ECONNRESET)
1022 len = -errno;
1023 return len;
1024 } else {
1025 ERR("incorrect message size: %zd\n", len);
1026 return len;
1027 }
1028 }
1029 }
1030
1031 /*
1032 * Set socket reciving timeout.
1033 */
1034 int ustcomm_setsockopt_rcv_timeout(int sock, unsigned int msec)
1035 {
1036 int ret;
1037 struct timeval tv;
1038
1039 tv.tv_sec = msec / 1000;
1040 tv.tv_usec = (msec * 1000 % 1000000);
1041
1042 ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
1043 if (ret < 0) {
1044 PERROR("setsockopt SO_RCVTIMEO");
1045 ret = -errno;
1046 }
1047
1048 return ret;
1049 }
1050
1051 /*
1052 * Set socket sending timeout.
1053 */
1054 int ustcomm_setsockopt_snd_timeout(int sock, unsigned int msec)
1055 {
1056 int ret;
1057 struct timeval tv;
1058
1059 tv.tv_sec = msec / 1000;
1060 tv.tv_usec = (msec * 1000) % 1000000;
1061
1062 ret = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
1063 if (ret < 0) {
1064 PERROR("setsockopt SO_SNDTIMEO");
1065 ret = -errno;
1066 }
1067
1068 return ret;
1069 }
This page took 0.051168 seconds and 5 git commands to generate.