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