1 /* Copyright (C) 2009 Pierre-Marc Fournier
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 /* API used by UST components to communicate with each other via sockets. */
22 #include <sys/types.h>
26 #include <sys/socket.h>
30 #include <sys/epoll.h>
42 static int mkdir_p(const char *path
, mode_t mode
)
51 tmp
= zmalloc(strlen(path
) + 1);
60 while (*path_p
!= '/') {
66 strncpy(tmp
, path
, path_p
- path
);
67 tmp
[path_p
-path
] = '\0';
68 if (tmp
[path_p
- path
- 1] != '/') {
69 result
= mkdir(tmp
, mode
);
71 if (!(errno
== EEXIST
|| errno
== EACCES
|| errno
== EROFS
)) {
72 /* Then this is a real error */
82 result
= mkdir(path
, mode
);
94 static struct sockaddr_un
* create_sock_addr(const char *name
,
95 size_t *sock_addr_size
)
97 struct sockaddr_un
* addr
;
100 alloc_size
= (size_t) (((struct sockaddr_un
*) 0)->sun_path
) +
103 addr
= malloc(alloc_size
);
105 ERR("allocating addr failed");
109 addr
->sun_family
= AF_UNIX
;
110 strcpy(addr
->sun_path
, name
);
112 *sock_addr_size
= alloc_size
;
117 struct ustcomm_sock
* ustcomm_init_sock(int fd
, int epoll_fd
,
118 struct cds_list_head
*list
)
120 struct epoll_event ev
;
121 struct ustcomm_sock
*sock
;
123 sock
= malloc(sizeof(struct ustcomm_sock
));
125 perror("malloc: couldn't allocate ustcomm_sock");
133 if (epoll_ctl(epoll_fd
, EPOLL_CTL_ADD
, sock
->fd
, &ev
) == -1) {
134 perror("epoll_ctl: failed to add socket\n");
139 sock
->epoll_fd
= epoll_fd
;
141 cds_list_add(&sock
->list
, list
);
143 CDS_INIT_LIST_HEAD(&sock
->list
);
149 void ustcomm_del_sock(struct ustcomm_sock
*sock
, int keep_in_epoll
)
151 cds_list_del(&sock
->list
);
152 if (!keep_in_epoll
) {
153 if (epoll_ctl(sock
->epoll_fd
, EPOLL_CTL_DEL
, sock
->fd
, NULL
) == -1) {
154 PERROR("epoll_ctl: failed to delete socket");
161 struct ustcomm_sock
* ustcomm_init_named_socket(const char *name
,
166 size_t sock_addr_size
;
167 struct sockaddr_un
* addr
;
168 struct ustcomm_sock
*sock
;
170 fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
176 addr
= create_sock_addr(name
, &sock_addr_size
);
178 ERR("allocating addr, UST thread bailing");
182 result
= access(name
, F_OK
);
185 result
= unlink(name
);
187 PERROR("unlink of socket file");
190 DBG("socket already exists; overwriting");
193 result
= bind(fd
, (struct sockaddr
*)addr
, sock_addr_size
);
199 result
= listen(fd
, 1);
205 sock
= ustcomm_init_sock(fd
, epoll_fd
,
208 ERR("failed to create ustcomm_sock");
224 void ustcomm_del_named_sock(struct ustcomm_sock
*sock
,
225 int keep_socket_file
)
229 struct sockaddr dummy
;
230 struct sockaddr_un
*sockaddr
= NULL
;
235 if(!keep_socket_file
) {
237 /* Get the socket name */
238 alloc_size
= sizeof(dummy
);
239 if (getsockname(fd
, &dummy
, (socklen_t
*)&alloc_size
) < 0) {
240 PERROR("getsockname failed");
244 sockaddr
= zmalloc(alloc_size
);
246 ERR("failed to allocate sockaddr");
250 if (getsockname(fd
, sockaddr
, (socklen_t
*)&alloc_size
) < 0) {
251 PERROR("getsockname failed");
256 result
= stat(sockaddr
->sun_path
, &st
);
258 PERROR("stat (%s)", sockaddr
->sun_path
);
262 /* Paranoid check before deleting. */
263 result
= S_ISSOCK(st
.st_mode
);
265 ERR("The socket we are about to delete is not a socket.");
269 result
= unlink(sockaddr
->sun_path
);
279 ustcomm_del_sock(sock
, keep_socket_file
);
282 int ustcomm_recv_alloc(int sock
,
283 struct ustcomm_header
*header
,
286 struct ustcomm_header peek_header
;
290 /* Just to make the caller fail hard */
293 result
= recv(sock
, &peek_header
, sizeof(peek_header
),
294 MSG_PEEK
| MSG_WAITALL
);
296 if(errno
== ECONNRESET
) {
298 } else if (errno
== EINTR
) {
300 } else if (result
< 0) {
307 memset(&msg
, 0, sizeof(msg
));
309 iov
[0].iov_base
= (char *)header
;
310 iov
[0].iov_len
= sizeof(struct ustcomm_header
);
315 if (peek_header
.size
) {
316 *data
= zmalloc(peek_header
.size
);
321 iov
[1].iov_base
= *data
;
322 iov
[1].iov_len
= peek_header
.size
;
327 result
= recvmsg(sock
, &msg
, MSG_WAITALL
);
330 PERROR("recvmsg failed");
336 /* returns 1 to indicate a message was received
337 * returns 0 to indicate no message was received (end of stream)
338 * returns -1 to indicate an error
340 int ustcomm_recv_fd(int sock
,
341 struct ustcomm_header
*header
,
345 struct ustcomm_header peek_header
;
348 struct cmsghdr
*cmsg
;
349 char buf
[CMSG_SPACE(sizeof(int))];
351 result
= recv(sock
, &peek_header
, sizeof(peek_header
),
352 MSG_PEEK
| MSG_WAITALL
);
354 if(errno
== ECONNRESET
) {
356 } else if (errno
== EINTR
) {
358 } else if (result
< 0) {
365 memset(&msg
, 0, sizeof(msg
));
367 iov
[0].iov_base
= (char *)header
;
368 iov
[0].iov_len
= sizeof(struct ustcomm_header
);
373 if (peek_header
.size
&& data
) {
374 if (peek_header
.size
< 0 ||
375 peek_header
.size
> USTCOMM_DATA_SIZE
) {
376 ERR("big peek header! %ld", peek_header
.size
);
380 iov
[1].iov_base
= data
;
381 iov
[1].iov_len
= peek_header
.size
;
386 if (fd
&& peek_header
.fd_included
) {
387 msg
.msg_control
= buf
;
388 msg
.msg_controllen
= sizeof(buf
);
391 result
= recvmsg(sock
, &msg
, MSG_WAITALL
);
394 PERROR("recvmsg failed");
399 if (fd
&& peek_header
.fd_included
) {
400 cmsg
= CMSG_FIRSTHDR(&msg
);
402 while (cmsg
!= NULL
) {
403 if (cmsg
->cmsg_level
== SOL_SOCKET
404 && cmsg
->cmsg_type
== SCM_RIGHTS
) {
405 *fd
= *(int *) CMSG_DATA(cmsg
);
409 cmsg
= CMSG_NXTHDR(&msg
, cmsg
);
412 ERR("Failed to receive file descriptor\n");
419 int ustcomm_recv(int sock
,
420 struct ustcomm_header
*header
,
423 return ustcomm_recv_fd(sock
, header
, data
, NULL
);
427 int ustcomm_send_fd(int sock
,
428 const struct ustcomm_header
*header
,
435 struct cmsghdr
*cmsg
;
436 char buf
[CMSG_SPACE(sizeof(int))];
438 memset(&msg
, 0, sizeof(msg
));
440 iov
[0].iov_base
= (char *)header
;
441 iov
[0].iov_len
= sizeof(struct ustcomm_header
);
446 if (header
->size
&& data
) {
447 iov
[1].iov_base
= (char *)data
;
448 iov
[1].iov_len
= header
->size
;
454 if (fd
&& header
->fd_included
) {
455 msg
.msg_control
= buf
;
456 msg
.msg_controllen
= sizeof(buf
);
457 cmsg
= CMSG_FIRSTHDR(&msg
);
458 cmsg
->cmsg_level
= SOL_SOCKET
;
459 cmsg
->cmsg_type
= SCM_RIGHTS
;
460 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
461 *(int *) CMSG_DATA(cmsg
) = *fd
;
462 msg
.msg_controllen
= cmsg
->cmsg_len
;
465 result
= sendmsg(sock
, &msg
, MSG_NOSIGNAL
);
466 if (result
< 0 && errno
!= EPIPE
) {
467 PERROR("sendmsg failed");
472 int ustcomm_send(int sock
,
473 const struct ustcomm_header
*header
,
476 return ustcomm_send_fd(sock
, header
, data
, NULL
);
479 int ustcomm_req(int sock
,
480 const struct ustcomm_header
*req_header
,
481 const char *req_data
,
482 struct ustcomm_header
*res_header
,
487 result
= ustcomm_send(sock
, req_header
, req_data
);
492 return ustcomm_recv(sock
, res_header
, res_data
);
500 int ustcomm_connect_path(const char *name
, int *connection_fd
)
503 size_t sock_addr_size
;
504 struct sockaddr_un
*addr
;
506 fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
512 addr
= create_sock_addr(name
, &sock_addr_size
);
514 ERR("allocating addr failed");
518 result
= connect(fd
, (struct sockaddr
*)addr
, sock_addr_size
);
520 PERROR("connect (path=%s)", name
);
538 /* Returns the current users socket directory, must be freed */
539 char *ustcomm_user_sock_dir(void)
542 char *sock_dir
= NULL
;
544 result
= asprintf(&sock_dir
, "%s%s", USER_SOCK_DIR
,
547 ERR("string overflow allocating directory name");
554 static int time_and_pid_from_socket_name(char *sock_name
, unsigned long *time
,
557 char *saveptr
, *pid_m_time_str
;
558 char *sock_basename
= strdup(basename(sock_name
));
560 if (!sock_basename
) {
564 /* This is the pid */
565 pid_m_time_str
= strtok_r(sock_basename
, ".", &saveptr
);
566 if (!pid_m_time_str
) {
571 *pid
= (pid_t
)strtoul(pid_m_time_str
, NULL
, 10);
576 /* This should be the time-stamp */
577 pid_m_time_str
= strtok_r(NULL
, ".", &saveptr
);
578 if (!pid_m_time_str
) {
583 *time
= strtoul(pid_m_time_str
, NULL
, 10);
595 time_t ustcomm_pid_st_mtime(pid_t pid
)
597 struct stat proc_stat
;
598 char proc_name
[PATH_MAX
];
600 if (snprintf(proc_name
, PATH_MAX
- 1, "/proc/%ld", (long) pid
) < 0) {
604 if (stat(proc_name
, &proc_stat
)) {
608 return proc_stat
.st_mtime
;
611 int ustcomm_is_socket_live(char *sock_name
, pid_t
*read_pid
)
613 time_t time_from_pid
;
614 unsigned long time_from_sock
;
617 if (time_and_pid_from_socket_name(sock_name
, &time_from_sock
, &pid
)) {
625 time_from_pid
= ustcomm_pid_st_mtime(pid
);
626 if (!time_from_pid
) {
630 if ((unsigned long) time_from_pid
== time_from_sock
) {
637 #define MAX_SOCK_PATH_BASE_LEN 100
639 static int ustcomm_get_sock_name(char *dir_name
, pid_t pid
, char *sock_name
)
641 struct dirent
*dirent
;
642 char sock_path_base
[MAX_SOCK_PATH_BASE_LEN
];
644 DIR *dir
= opendir(dir_name
);
646 snprintf(sock_path_base
, MAX_SOCK_PATH_BASE_LEN
- 1,
648 len
= strlen(sock_path_base
);
650 while ((dirent
= readdir(dir
))) {
651 if (!strcmp(dirent
->d_name
, ".") ||
652 !strcmp(dirent
->d_name
, "..") ||
653 !strcmp(dirent
->d_name
, "ust-consumer") ||
654 dirent
->d_type
== DT_DIR
||
655 strncmp(dirent
->d_name
, sock_path_base
, len
)) {
659 if (ustcomm_is_socket_live(dirent
->d_name
, NULL
)) {
660 if (snprintf(sock_name
, PATH_MAX
- 1, "%s/%s",
661 dir_name
, dirent
->d_name
) < 0) {
662 PERROR("path longer than PATH_MAX?");
675 /* Open a connection to a traceable app.
682 static int connect_app_non_root(pid_t pid
, int *app_fd
)
687 char sock_name
[PATH_MAX
];
689 dir_name
= ustcomm_user_sock_dir();
693 if (ustcomm_get_sock_name(dir_name
, pid
, sock_name
)) {
698 result
= ustcomm_connect_path(sock_name
, app_fd
);
700 ERR("failed to connect to app");
713 static int connect_app_root(pid_t pid
, int *app_fd
)
716 struct dirent
*dirent
;
717 char dir_name
[PATH_MAX
], sock_name
[PATH_MAX
];
720 tmp_dir
= opendir(USER_TMP_DIR
);
725 while ((dirent
= readdir(tmp_dir
))) {
726 if (!strncmp(dirent
->d_name
, USER_SOCK_DIR_BASE
,
727 strlen(USER_SOCK_DIR_BASE
))) {
729 if (snprintf(dir_name
, PATH_MAX
- 1, "%s/%s", USER_TMP_DIR
,
730 dirent
->d_name
) < 0) {
734 if (ustcomm_get_sock_name(dir_name
, pid
, sock_name
)) {
738 result
= ustcomm_connect_path(sock_name
, app_fd
);
752 int ustcomm_connect_app(pid_t pid
, int *app_fd
)
757 return connect_app_non_root(pid
, app_fd
);
759 return connect_app_root(pid
, app_fd
);
764 int ensure_dir_exists(const char *dir
, mode_t mode
)
769 if (!strcmp(dir
, ""))
772 result
= stat(dir
, &st
);
773 if (result
< 0 && errno
!= ENOENT
) {
775 } else if (result
< 0) {
779 result
= mkdir_p(dir
, mode
);
781 ERR("executing in recursive creation of directory %s", dir
);
785 if (st
.st_mode
!= mode
) {
786 result
= chmod(dir
, mode
);
788 ERR("couldn't set directory mode on %s", dir
);
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;
817 char * ustcomm_restore_ptr(char *ptr
, char *data_field
, int data_field_size
)
819 if ((unsigned long)ptr
> data_field_size
||
820 ptr
== USTCOMM_POISON_PTR
) {
824 return data_field
+ (long)ptr
;
827 int ustcomm_pack_single_field(struct ustcomm_header
*header
,
828 struct ustcomm_single_field
*single_field
,
833 single_field
->field
= ustcomm_print_data(single_field
->data
,
834 sizeof(single_field
->data
),
838 if (single_field
->field
== USTCOMM_POISON_PTR
) {
842 header
->size
= COMPUTE_MSG_SIZE(single_field
, offset
);
847 int ustcomm_unpack_single_field(struct ustcomm_single_field
*single_field
)
849 single_field
->field
= ustcomm_restore_ptr(single_field
->field
,
851 sizeof(single_field
->data
));
852 if (!single_field
->field
) {
859 int ustcomm_pack_channel_info(struct ustcomm_header
*header
,
860 struct ustcomm_channel_info
*ch_inf
,
866 ch_inf
->trace
= ustcomm_print_data(ch_inf
->data
,
867 sizeof(ch_inf
->data
),
871 if (ch_inf
->trace
== USTCOMM_POISON_PTR
) {
875 ch_inf
->channel
= ustcomm_print_data(ch_inf
->data
,
876 sizeof(ch_inf
->data
),
880 if (ch_inf
->channel
== USTCOMM_POISON_PTR
) {
884 header
->size
= COMPUTE_MSG_SIZE(ch_inf
, offset
);
890 int ustcomm_unpack_channel_info(struct ustcomm_channel_info
*ch_inf
)
892 ch_inf
->trace
= ustcomm_restore_ptr(ch_inf
->trace
,
894 sizeof(ch_inf
->data
));
895 if (!ch_inf
->trace
) {
899 ch_inf
->channel
= ustcomm_restore_ptr(ch_inf
->channel
,
901 sizeof(ch_inf
->data
));
902 if (!ch_inf
->channel
) {
909 int ustcomm_pack_buffer_info(struct ustcomm_header
*header
,
910 struct ustcomm_buffer_info
*buf_inf
,
917 buf_inf
->trace
= ustcomm_print_data(buf_inf
->data
,
918 sizeof(buf_inf
->data
),
922 if (buf_inf
->trace
== USTCOMM_POISON_PTR
) {
926 buf_inf
->channel
= ustcomm_print_data(buf_inf
->data
,
927 sizeof(buf_inf
->data
),
931 if (buf_inf
->channel
== USTCOMM_POISON_PTR
) {
935 buf_inf
->ch_cpu
= channel_cpu
;
937 header
->size
= COMPUTE_MSG_SIZE(buf_inf
, offset
);
943 int ustcomm_unpack_buffer_info(struct ustcomm_buffer_info
*buf_inf
)
945 buf_inf
->trace
= ustcomm_restore_ptr(buf_inf
->trace
,
947 sizeof(buf_inf
->data
));
948 if (!buf_inf
->trace
) {
952 buf_inf
->channel
= ustcomm_restore_ptr(buf_inf
->channel
,
954 sizeof(buf_inf
->data
));
955 if (!buf_inf
->channel
) {
962 int ustcomm_pack_ust_marker_info(struct ustcomm_header
*header
,
963 struct ustcomm_ust_marker_info
*ust_marker_inf
,
966 const char *ust_marker
)
970 ust_marker_inf
->trace
= ustcomm_print_data(ust_marker_inf
->data
,
971 sizeof(ust_marker_inf
->data
),
975 if (ust_marker_inf
->trace
== USTCOMM_POISON_PTR
) {
980 ust_marker_inf
->channel
= ustcomm_print_data(ust_marker_inf
->data
,
981 sizeof(ust_marker_inf
->data
),
985 if (ust_marker_inf
->channel
== USTCOMM_POISON_PTR
) {
990 ust_marker_inf
->ust_marker
= ustcomm_print_data(ust_marker_inf
->data
,
991 sizeof(ust_marker_inf
->data
),
995 if (ust_marker_inf
->ust_marker
== USTCOMM_POISON_PTR
) {
999 header
->size
= COMPUTE_MSG_SIZE(ust_marker_inf
, offset
);
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
,
1015 sizeof(ust_marker_inf
->data
));
1016 if (!ust_marker_inf
->channel
) {
1020 ust_marker_inf
->ust_marker
= ustcomm_restore_ptr(ust_marker_inf
->ust_marker
,
1021 ust_marker_inf
->data
,
1022 sizeof(ust_marker_inf
->data
));
1023 if (!ust_marker_inf
->ust_marker
) {