2 * Copyright (C) 2009 Pierre-Marc Fournier
3 * 2010 Nils Carlson <nils.carlson@ericsson.com>
4 * 2011 David Goulet <david.goulet@polymtl.ca>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <sys/epoll.h>
32 #include <sys/socket.h>
34 #include <sys/types.h>
38 #include "libustcomm.h"
41 #define MAX_SOCK_PATH_BASE_LEN 100
46 * Set sock_name to the libust socket path using the pid
47 * and the base directory dir_name.
49 static int get_sock_name(char *dir_name
, pid_t pid
, char *sock_name
)
51 struct dirent
*dirent
;
52 char sock_path_base
[MAX_SOCK_PATH_BASE_LEN
];
56 dir
= opendir(dir_name
);
58 ERR("ustcomm sock name opendir %s", dir_name
);
62 snprintf(sock_path_base
, MAX_SOCK_PATH_BASE_LEN
- 1, "%ld", (long) pid
);
63 len
= strlen(sock_path_base
);
65 DBG("Socket directory %s", sock_path_base
);
67 while ((dirent
= readdir(dir
))) {
68 if (!strcmp(dirent
->d_name
, ".") ||
69 !strcmp(dirent
->d_name
, "..") ||
70 !strcmp(dirent
->d_name
, "ust-consumer") ||
71 dirent
->d_type
== DT_DIR
||
72 strncmp(dirent
->d_name
, sock_path_base
, len
) != 0) {
76 if (snprintf(sock_name
, PATH_MAX
- 1, "%s/%s", dir_name
, dirent
->d_name
) < 0) {
77 perror("path longer than PATH_MAX?");
94 * Create a sockaddr structure for unic socket.
96 static struct sockaddr_un
*create_sock_addr(const char *name
, size_t *sock_addr_size
)
98 struct sockaddr_un
* addr
;
101 alloc_size
= (size_t) (((struct sockaddr_un
*) 0)->sun_path
) +
104 addr
= malloc(alloc_size
);
106 ERR("allocating addr failed");
110 addr
->sun_family
= AF_UNIX
;
111 strcpy(addr
->sun_path
, name
);
113 *sock_addr_size
= alloc_size
;
119 * connect_app_non_root
121 * Open a connection to a non root traceable app.
122 * On error, return -1 else 0
124 static int connect_app_non_root(pid_t pid
, int *app_fd
)
129 char sock_name
[PATH_MAX
];
131 dir_name
= ustcomm_user_sock_dir();
136 if (get_sock_name(dir_name
, pid
, sock_name
)) {
141 result
= ustcomm_connect_path(sock_name
, app_fd
);
143 ERR("failed to connect to app");
157 * Open a connection to a root traceable app.
158 * On error, return -1 else 0
160 static int connect_app_root(pid_t pid
, int *app_fd
)
163 struct dirent
*dirent
;
164 char dir_name
[PATH_MAX
], sock_name
[PATH_MAX
];
167 tmp_dir
= opendir(USER_TMP_DIR
);
172 while ((dirent
= readdir(tmp_dir
))) {
173 if (!strncmp(dirent
->d_name
, USER_SOCK_DIR_BASE
,
174 strlen(USER_SOCK_DIR_BASE
))) {
176 if (snprintf(dir_name
, PATH_MAX
- 1, "%s/%s", USER_TMP_DIR
,
177 dirent
->d_name
) < 0) {
181 if (get_sock_name(dir_name
, pid
, sock_name
)) {
185 result
= ustcomm_connect_path(sock_name
, app_fd
);
200 * time_and_pid_from_socket_name
202 * Get time from socket name
204 static int time_and_pid_from_socket_name(char *sock_name
, unsigned long *time
,
207 char *saveptr
, *pid_m_time_str
;
208 char *sock_basename
= strdup(basename(sock_name
));
210 if (!sock_basename
) {
214 /* This is the pid */
215 pid_m_time_str
= strtok_r(sock_basename
, ".", &saveptr
);
216 if (!pid_m_time_str
) {
221 *pid
= (pid_t
)strtoul(pid_m_time_str
, NULL
, 10);
226 /* This should be the time-stamp */
227 pid_m_time_str
= strtok_r(NULL
, ".", &saveptr
);
228 if (!pid_m_time_str
) {
233 *time
= strtoul(pid_m_time_str
, NULL
, 10);
246 * ustcomm_is_socket_live
248 * Check if socket is available and "living".
250 int ustcomm_is_socket_live(char *sock_name
, pid_t
*read_pid
)
252 time_t time_from_pid
;
253 unsigned long time_from_sock
;
256 if (time_and_pid_from_socket_name(sock_name
, &time_from_sock
, &pid
)) {
264 time_from_pid
= ustcomm_pid_st_mtime(pid
);
265 if (!time_from_pid
) {
269 if ((unsigned long) time_from_pid
== time_from_sock
) {
279 * Init socket for communication between libust and libustcomm.
281 struct ustcomm_sock
*ustcomm_init_sock(int fd
, int epoll_fd
,
282 struct cds_list_head
*list
)
284 struct epoll_event ev
;
285 struct ustcomm_sock
*sock
;
287 sock
= malloc(sizeof(struct ustcomm_sock
));
289 perror("malloc: couldn't allocate ustcomm_sock");
297 if (epoll_ctl(epoll_fd
, EPOLL_CTL_ADD
, sock
->fd
, &ev
) == -1) {
298 perror("epoll_ctl: failed to add socket\n");
303 sock
->epoll_fd
= epoll_fd
;
305 cds_list_add(&sock
->list
, list
);
307 CDS_INIT_LIST_HEAD(&sock
->list
);
316 * Delete socket and remove it from the epoll set.
318 void ustcomm_del_sock(struct ustcomm_sock
*sock
, int keep_in_epoll
)
320 cds_list_del(&sock
->list
);
321 if (!keep_in_epoll
) {
322 if (epoll_ctl(sock
->epoll_fd
, EPOLL_CTL_DEL
, sock
->fd
, NULL
) == -1) {
323 perror("epoll_ctl: failed to delete socket");
331 * ustcomm_init_named_socket
333 * Init unix named socket
335 struct ustcomm_sock
*ustcomm_init_named_socket(const char *name
, int epoll_fd
)
339 size_t sock_addr_size
;
340 struct sockaddr_un
* addr
;
341 struct ustcomm_sock
*sock
;
343 fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
349 addr
= create_sock_addr(name
, &sock_addr_size
);
351 ERR("allocating addr, UST thread bailing");
355 result
= access(name
, F_OK
);
358 result
= unlink(name
);
360 perror("unlink of socket file");
363 DBG("socket already exists; overwriting");
366 result
= bind(fd
, (struct sockaddr
*)addr
, sock_addr_size
);
372 result
= listen(fd
, 1);
378 sock
= ustcomm_init_sock(fd
, epoll_fd
, NULL
);
380 ERR("failed to create ustcomm_sock");
397 * ustcomm_del_named_sock
399 * Delete named socket
401 void ustcomm_del_named_sock(struct ustcomm_sock
*sock
, int keep_socket_file
)
405 struct sockaddr dummy
;
406 struct sockaddr_un
*sockaddr
= NULL
;
411 if(!keep_socket_file
) {
413 /* Get the socket name */
414 alloc_size
= sizeof(dummy
);
415 if (getsockname(fd
, &dummy
, (socklen_t
*)&alloc_size
) < 0) {
416 perror("getsockname failed");
420 sockaddr
= malloc(alloc_size
);
422 ERR("failed to allocate sockaddr");
426 if (getsockname(fd
, sockaddr
, (socklen_t
*)&alloc_size
) < 0) {
427 perror("getsockname failed");
432 result
= stat(sockaddr
->sun_path
, &st
);
434 ERR("stat (%s)", sockaddr
->sun_path
);
438 /* Paranoid check before deleting. */
439 result
= S_ISSOCK(st
.st_mode
);
441 ERR("The socket we are about to delete is not a socket.");
445 result
= unlink(sockaddr
->sun_path
);
455 ustcomm_del_sock(sock
, keep_socket_file
);
461 * Receive data and allocate data reception buffers.
463 int ustcomm_recv_alloc(int sock
, struct ustcomm_header
*header
, char **data
)
466 struct ustcomm_header peek_header
;
470 /* Just to make the caller fail hard */
473 result
= recv(sock
, &peek_header
, sizeof(peek_header
), MSG_PEEK
| MSG_WAITALL
);
475 if(errno
== ECONNRESET
) {
477 } else if (errno
== EINTR
) {
479 } else if (result
< 0) {
486 memset(&msg
, 0, sizeof(msg
));
488 iov
[0].iov_base
= (char *)header
;
489 iov
[0].iov_len
= sizeof(struct ustcomm_header
);
494 if (peek_header
.size
) {
495 *data
= malloc(peek_header
.size
);
500 iov
[1].iov_base
= *data
;
501 iov
[1].iov_len
= peek_header
.size
;
506 result
= recvmsg(sock
, &msg
, MSG_WAITALL
);
509 perror("recvmsg failed");
518 * Receive data from fd.
519 * returns 1 to indicate a message was received
520 * returns 0 to indicate no message was received (end of stream)
521 * returns -1 to indicate an error
523 int ustcomm_recv_fd(int sock
, struct ustcomm_header
*header
, char *data
, int *fd
)
526 struct ustcomm_header peek_header
;
529 struct cmsghdr
*cmsg
;
530 char buf
[CMSG_SPACE(sizeof(int))];
532 result
= recv(sock
, &peek_header
, sizeof(peek_header
), MSG_PEEK
| MSG_WAITALL
);
534 if(errno
== ECONNRESET
) {
536 } else if (errno
== EINTR
) {
538 } else if (result
< 0) {
545 memset(&msg
, 0, sizeof(msg
));
547 iov
[0].iov_base
= (char *)header
;
548 iov
[0].iov_len
= sizeof(struct ustcomm_header
);
553 if (peek_header
.size
&& data
) {
554 if (peek_header
.size
< 0 ||
555 peek_header
.size
> USTCOMM_DATA_SIZE
) {
556 ERR("big peek header! %ld", peek_header
.size
);
560 iov
[1].iov_base
= data
;
561 iov
[1].iov_len
= peek_header
.size
;
566 if (fd
&& peek_header
.fd_included
) {
567 msg
.msg_control
= buf
;
568 msg
.msg_controllen
= sizeof(buf
);
571 result
= recvmsg(sock
, &msg
, MSG_WAITALL
);
574 perror("recvmsg failed");
579 if (fd
&& peek_header
.fd_included
) {
580 cmsg
= CMSG_FIRSTHDR(&msg
);
582 while (cmsg
!= NULL
) {
583 if (cmsg
->cmsg_level
== SOL_SOCKET
584 && cmsg
->cmsg_type
== SCM_RIGHTS
) {
585 *fd
= *(int *) CMSG_DATA(cmsg
);
589 cmsg
= CMSG_NXTHDR(&msg
, cmsg
);
592 ERR("Failed to receive file descriptor\n");
604 int ustcomm_recv(int sock
, struct ustcomm_header
*header
, char *data
)
606 return ustcomm_recv_fd(sock
, header
, data
, NULL
);
614 int ustcomm_send_fd(int sock
, const struct ustcomm_header
*header
,
615 const char *data
, int *fd
)
620 struct cmsghdr
*cmsg
;
621 char buf
[CMSG_SPACE(sizeof(int))];
623 memset(&msg
, 0, sizeof(msg
));
625 iov
[0].iov_base
= (char *)header
;
626 iov
[0].iov_len
= sizeof(struct ustcomm_header
);
631 if (header
->size
&& data
) {
632 iov
[1].iov_base
= (char *)data
;
633 iov
[1].iov_len
= header
->size
;
639 if (fd
&& header
->fd_included
) {
640 msg
.msg_control
= buf
;
641 msg
.msg_controllen
= sizeof(buf
);
642 cmsg
= CMSG_FIRSTHDR(&msg
);
643 cmsg
->cmsg_level
= SOL_SOCKET
;
644 cmsg
->cmsg_type
= SCM_RIGHTS
;
645 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
646 *(int *) CMSG_DATA(cmsg
) = *fd
;
647 msg
.msg_controllen
= cmsg
->cmsg_len
;
650 result
= sendmsg(sock
, &msg
, MSG_NOSIGNAL
);
651 if (result
< 0 && errno
!= EPIPE
) {
652 perror("sendmsg failed");
662 int ustcomm_send(int sock
, const struct ustcomm_header
*header
, const char *data
)
664 return ustcomm_send_fd(sock
, header
, data
, NULL
);
670 * Do a request to the libust socket which means sending data and
673 int ustcomm_req(int sock
,
674 const struct ustcomm_header
*req_header
,
675 const char *req_data
,
676 struct ustcomm_header
*res_header
,
681 result
= ustcomm_send(sock
, req_header
, req_data
);
686 return ustcomm_recv(sock
, res_header
, res_data
);
690 * ustcomm_connect_path
697 int ustcomm_connect_path(const char *name
, int *connection_fd
)
700 size_t sock_addr_size
;
701 struct sockaddr_un
*addr
;
703 fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
709 addr
= create_sock_addr(name
, &sock_addr_size
);
711 ERR("allocating addr failed");
715 result
= connect(fd
, (struct sockaddr
*)addr
, sock_addr_size
);
717 perror("ustcomm connect path");
736 * ustcomm_user_sock_dir
738 * Returns the current users socket directory, must be freed.
740 char *ustcomm_user_sock_dir(void)
743 char *sock_dir
= NULL
;
745 result
= asprintf(&sock_dir
, "/tmp/ust-app-socks/");
747 ERR("string overflow allocating directory name");
755 * ustcomm_pid_st_mtime
757 * Return time of the process pid creation.
759 time_t ustcomm_pid_st_mtime(pid_t pid
)
761 struct stat proc_stat
;
762 char proc_name
[PATH_MAX
];
764 if (snprintf(proc_name
, PATH_MAX
- 1, "/proc/%ld", (long) pid
) < 0) {
768 if (stat(proc_name
, &proc_stat
)) {
772 return proc_stat
.st_mtime
;
776 * ustcomm_connect_app
778 * Connect to libust application using the pid.
780 int ustcomm_connect_app(pid_t pid
, int *app_fd
)
785 return connect_app_non_root(pid
, app_fd
);
787 return connect_app_root(pid
, app_fd
);
795 * Print data in a data_field.
797 char *ustcomm_print_data(char *data_field
, int field_size
,
798 int *offset
, const char *format
, ...)
802 char *ptr
= USTCOMM_POISON_PTR
;
804 limit
= field_size
- *offset
;
805 va_start(args
, format
);
806 count
= vsnprintf(&data_field
[*offset
], limit
, format
, args
);
809 if (count
< limit
&& count
> -1) {
810 ptr
= NULL
+ *offset
;
811 *offset
= *offset
+ count
+ 1;
818 * ustcomm_restore_ptr
820 char *ustcomm_restore_ptr(char *ptr
, char *data_field
, int data_field_size
)
822 if ((unsigned long)ptr
> data_field_size
|| ptr
== USTCOMM_POISON_PTR
) {
826 return data_field
+ (long)ptr
;
830 * ustcomm_pack_single_field
832 int ustcomm_pack_single_field(struct ustcomm_header
*header
,
833 struct ustcomm_single_field
*single_field
,
838 single_field
->field
= ustcomm_print_data(single_field
->data
,
839 sizeof(single_field
->data
),
843 if (single_field
->field
== USTCOMM_POISON_PTR
) {
847 header
->size
= COMPUTE_MSG_SIZE(single_field
, offset
);
853 * ustcomm_unpack_single_field
855 int ustcomm_unpack_single_field(struct ustcomm_single_field
*single_field
)
857 single_field
->field
= ustcomm_restore_ptr(single_field
->field
,
859 sizeof(single_field
->data
));
860 if (!single_field
->field
) {
868 * ustcomm_pack_channel_info
870 int ustcomm_pack_channel_info(struct ustcomm_header
*header
,
871 struct ustcomm_channel_info
*ch_inf
, const char *trace
, const char *channel
)
875 ch_inf
->trace
= ustcomm_print_data(ch_inf
->data
,
876 sizeof(ch_inf
->data
), &offset
, trace
);
878 if (ch_inf
->trace
== USTCOMM_POISON_PTR
) {
882 ch_inf
->channel
= ustcomm_print_data(ch_inf
->data
,
883 sizeof(ch_inf
->data
), &offset
, channel
);
885 if (ch_inf
->channel
== USTCOMM_POISON_PTR
) {
889 header
->size
= COMPUTE_MSG_SIZE(ch_inf
, offset
);
895 * ustcomm_unpack_channel_info
897 int ustcomm_unpack_channel_info(struct ustcomm_channel_info
*ch_inf
)
899 ch_inf
->trace
= ustcomm_restore_ptr(ch_inf
->trace
,
900 ch_inf
->data
, sizeof(ch_inf
->data
));
901 if (!ch_inf
->trace
) {
905 ch_inf
->channel
= ustcomm_restore_ptr(ch_inf
->channel
,
906 ch_inf
->data
, sizeof(ch_inf
->data
));
907 if (!ch_inf
->channel
) {
915 * ustcomm_pack_buffer_info
917 int ustcomm_pack_buffer_info(struct ustcomm_header
*header
,
918 struct ustcomm_buffer_info
*buf_inf
,
919 const char *trace
, const char *channel
, int channel_cpu
)
923 buf_inf
->trace
= ustcomm_print_data(buf_inf
->data
,
924 sizeof(buf_inf
->data
), &offset
, trace
);
926 if (buf_inf
->trace
== USTCOMM_POISON_PTR
) {
930 buf_inf
->channel
= ustcomm_print_data(buf_inf
->data
,
931 sizeof(buf_inf
->data
), &offset
, channel
);
933 if (buf_inf
->channel
== USTCOMM_POISON_PTR
) {
937 buf_inf
->ch_cpu
= channel_cpu
;
939 header
->size
= COMPUTE_MSG_SIZE(buf_inf
, offset
);
945 * ustcomm_unpack_buffer_info
947 int ustcomm_unpack_buffer_info(struct ustcomm_buffer_info
*buf_inf
)
949 buf_inf
->trace
= ustcomm_restore_ptr(buf_inf
->trace
,
950 buf_inf
->data
, sizeof(buf_inf
->data
));
951 if (!buf_inf
->trace
) {
955 buf_inf
->channel
= ustcomm_restore_ptr(buf_inf
->channel
,
956 buf_inf
->data
, sizeof(buf_inf
->data
));
957 if (!buf_inf
->channel
) {
965 * ustcomm_pack_ust_marker_info
967 int ustcomm_pack_ust_marker_info(struct ustcomm_header
*header
,
968 struct ustcomm_ust_marker_info
*ust_marker_inf
,
969 const char *trace
, const char *channel
, const char *ust_marker
)
973 ust_marker_inf
->trace
= ustcomm_print_data(ust_marker_inf
->data
,
974 sizeof(ust_marker_inf
->data
), &offset
, trace
);
976 if (ust_marker_inf
->trace
== USTCOMM_POISON_PTR
) {
981 ust_marker_inf
->channel
= ustcomm_print_data(ust_marker_inf
->data
,
982 sizeof(ust_marker_inf
->data
), &offset
, channel
);
984 if (ust_marker_inf
->channel
== USTCOMM_POISON_PTR
) {
989 ust_marker_inf
->ust_marker
= ustcomm_print_data(ust_marker_inf
->data
,
990 sizeof(ust_marker_inf
->data
), &offset
, ust_marker
);
992 if (ust_marker_inf
->ust_marker
== USTCOMM_POISON_PTR
) {
996 header
->size
= COMPUTE_MSG_SIZE(ust_marker_inf
, offset
);
1002 * ustcomm_unpack_ust_marker_info
1004 int ustcomm_unpack_ust_marker_info(struct ustcomm_ust_marker_info
*ust_marker_inf
)
1006 ust_marker_inf
->trace
= ustcomm_restore_ptr(ust_marker_inf
->trace
,
1007 ust_marker_inf
->data
,
1008 sizeof(ust_marker_inf
->data
));
1009 if (!ust_marker_inf
->trace
) {
1013 ust_marker_inf
->channel
= ustcomm_restore_ptr(ust_marker_inf
->channel
,
1014 ust_marker_inf
->data
, sizeof(ust_marker_inf
->data
));
1015 if (!ust_marker_inf
->channel
) {
1019 ust_marker_inf
->ust_marker
= ustcomm_restore_ptr(ust_marker_inf
->ust_marker
,
1020 ust_marker_inf
->data
, sizeof(ust_marker_inf
->data
));
1021 if (!ust_marker_inf
->ust_marker
) {