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. */
21 #include <sys/types.h>
24 #include <sys/socket.h>
28 #include <sys/epoll.h>
40 static int mkdir_p(const char *path
, mode_t mode
)
49 tmp
= zmalloc(strlen(path
) + 1);
58 while (*path_p
!= '/') {
64 strncpy(tmp
, path
, path_p
- path
);
65 tmp
[path_p
-path
] = '\0';
66 if (tmp
[path_p
- path
- 1] != '/') {
67 result
= mkdir(tmp
, mode
);
69 if (!(errno
== EEXIST
|| errno
== EACCES
|| errno
== EROFS
)) {
70 /* Then this is a real error */
80 result
= mkdir(path
, mode
);
92 static struct sockaddr_un
* create_sock_addr(const char *name
,
93 size_t *sock_addr_size
)
95 struct sockaddr_un
* addr
;
98 alloc_size
= (size_t) (((struct sockaddr_un
*) 0)->sun_path
) +
101 addr
= malloc(alloc_size
);
103 ERR("allocating addr failed");
107 addr
->sun_family
= AF_UNIX
;
108 strcpy(addr
->sun_path
, name
);
110 *sock_addr_size
= alloc_size
;
115 struct ustcomm_sock
* ustcomm_init_sock(int fd
, int epoll_fd
,
116 struct list_head
*list
)
118 struct epoll_event ev
;
119 struct ustcomm_sock
*sock
;
121 sock
= malloc(sizeof(struct ustcomm_sock
));
123 perror("malloc: couldn't allocate ustcomm_sock");
131 if (epoll_ctl(epoll_fd
, EPOLL_CTL_ADD
, sock
->fd
, &ev
) == -1) {
132 perror("epoll_ctl: failed to add socket\n");
137 sock
->epoll_fd
= epoll_fd
;
139 list_add(&sock
->list
, list
);
141 INIT_LIST_HEAD(&sock
->list
);
147 void ustcomm_del_sock(struct ustcomm_sock
*sock
, int keep_in_epoll
)
149 list_del(&sock
->list
);
150 if (!keep_in_epoll
) {
151 if (epoll_ctl(sock
->epoll_fd
, EPOLL_CTL_DEL
, sock
->fd
, NULL
) == -1) {
152 PERROR("epoll_ctl: failed to delete socket");
159 struct ustcomm_sock
* ustcomm_init_named_socket(const char *name
,
164 size_t sock_addr_size
;
165 struct sockaddr_un
* addr
;
166 struct ustcomm_sock
*sock
;
168 fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
174 addr
= create_sock_addr(name
, &sock_addr_size
);
176 ERR("allocating addr, UST thread bailing");
180 result
= access(name
, F_OK
);
183 result
= unlink(name
);
185 PERROR("unlink of socket file");
188 DBG("socket already exists; overwriting");
191 result
= bind(fd
, (struct sockaddr
*)addr
, sock_addr_size
);
197 result
= listen(fd
, 1);
203 sock
= ustcomm_init_sock(fd
, epoll_fd
,
206 ERR("failed to create ustcomm_sock");
222 void ustcomm_del_named_sock(struct ustcomm_sock
*sock
,
223 int keep_socket_file
)
227 struct sockaddr dummy
;
228 struct sockaddr_un
*sockaddr
= NULL
;
233 if(!keep_socket_file
) {
235 /* Get the socket name */
236 alloc_size
= sizeof(dummy
);
237 if (getsockname(fd
, &dummy
, (socklen_t
*)&alloc_size
) < 0) {
238 PERROR("getsockname failed");
242 sockaddr
= zmalloc(alloc_size
);
244 ERR("failed to allocate sockaddr");
248 if (getsockname(fd
, sockaddr
, (socklen_t
*)&alloc_size
) < 0) {
249 PERROR("getsockname failed");
254 result
= stat(sockaddr
->sun_path
, &st
);
256 PERROR("stat (%s)", sockaddr
->sun_path
);
260 /* Paranoid check before deleting. */
261 result
= S_ISSOCK(st
.st_mode
);
263 ERR("The socket we are about to delete is not a socket.");
267 result
= unlink(sockaddr
->sun_path
);
277 ustcomm_del_sock(sock
, keep_socket_file
);
280 int ustcomm_recv_alloc(int sock
,
281 struct ustcomm_header
*header
,
284 struct ustcomm_header peek_header
;
288 /* Just to make the caller fail hard */
291 result
= recv(sock
, &peek_header
, sizeof(peek_header
),
292 MSG_PEEK
| MSG_WAITALL
);
294 if(errno
== ECONNRESET
) {
296 } else if (errno
== EINTR
) {
298 } else if (result
< 0) {
305 memset(&msg
, 0, sizeof(msg
));
307 iov
[0].iov_base
= (char *)header
;
308 iov
[0].iov_len
= sizeof(struct ustcomm_header
);
313 if (peek_header
.size
) {
314 *data
= zmalloc(peek_header
.size
);
319 iov
[1].iov_base
= *data
;
320 iov
[1].iov_len
= peek_header
.size
;
325 result
= recvmsg(sock
, &msg
, MSG_WAITALL
);
328 PERROR("recvmsg failed");
334 /* returns 1 to indicate a message was received
335 * returns 0 to indicate no message was received (end of stream)
336 * returns -1 to indicate an error
338 int ustcomm_recv_fd(int sock
,
339 struct ustcomm_header
*header
,
343 struct ustcomm_header peek_header
;
346 struct cmsghdr
*cmsg
;
347 char buf
[CMSG_SPACE(sizeof(int))];
349 result
= recv(sock
, &peek_header
, sizeof(peek_header
),
350 MSG_PEEK
| MSG_WAITALL
);
352 if(errno
== ECONNRESET
) {
354 } else if (errno
== EINTR
) {
356 } else if (result
< 0) {
363 memset(&msg
, 0, sizeof(msg
));
365 iov
[0].iov_base
= (char *)header
;
366 iov
[0].iov_len
= sizeof(struct ustcomm_header
);
371 if (peek_header
.size
&& data
) {
372 if (peek_header
.size
< 0 ||
373 peek_header
.size
> USTCOMM_DATA_SIZE
) {
374 ERR("big peek header! %d", peek_header
.size
);
378 iov
[1].iov_base
= data
;
379 iov
[1].iov_len
= peek_header
.size
;
384 if (fd
&& peek_header
.fd_included
) {
385 msg
.msg_control
= buf
;
386 msg
.msg_controllen
= sizeof(buf
);
389 result
= recvmsg(sock
, &msg
, MSG_WAITALL
);
392 PERROR("recvmsg failed");
397 if (fd
&& peek_header
.fd_included
) {
398 cmsg
= CMSG_FIRSTHDR(&msg
);
400 while (cmsg
!= NULL
) {
401 if (cmsg
->cmsg_level
== SOL_SOCKET
402 && cmsg
->cmsg_type
== SCM_RIGHTS
) {
403 *fd
= *(int *) CMSG_DATA(cmsg
);
407 cmsg
= CMSG_NXTHDR(&msg
, cmsg
);
410 ERR("Failed to receive file descriptor\n");
417 int ustcomm_recv(int sock
,
418 struct ustcomm_header
*header
,
421 return ustcomm_recv_fd(sock
, header
, data
, NULL
);
425 int ustcomm_send_fd(int sock
,
426 const struct ustcomm_header
*header
,
433 struct cmsghdr
*cmsg
;
434 char buf
[CMSG_SPACE(sizeof(int))];
436 memset(&msg
, 0, sizeof(msg
));
438 iov
[0].iov_base
= (char *)header
;
439 iov
[0].iov_len
= sizeof(struct ustcomm_header
);
444 if (header
->size
&& data
) {
445 iov
[1].iov_base
= (char *)data
;
446 iov
[1].iov_len
= header
->size
;
452 if (fd
&& header
->fd_included
) {
453 msg
.msg_control
= buf
;
454 msg
.msg_controllen
= sizeof(buf
);
455 cmsg
= CMSG_FIRSTHDR(&msg
);
456 cmsg
->cmsg_level
= SOL_SOCKET
;
457 cmsg
->cmsg_type
= SCM_RIGHTS
;
458 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
459 *(int *) CMSG_DATA(cmsg
) = *fd
;
460 msg
.msg_controllen
= cmsg
->cmsg_len
;
463 result
= sendmsg(sock
, &msg
, MSG_NOSIGNAL
);
464 if (result
< 0 && errno
!= EPIPE
) {
465 PERROR("sendmsg failed");
470 int ustcomm_send(int sock
,
471 const struct ustcomm_header
*header
,
474 return ustcomm_send_fd(sock
, header
, data
, NULL
);
477 int ustcomm_req(int sock
,
478 const struct ustcomm_header
*req_header
,
479 const char *req_data
,
480 struct ustcomm_header
*res_header
,
485 result
= ustcomm_send(sock
, req_header
, req_data
);
490 return ustcomm_recv(sock
, res_header
, res_data
);
498 int ustcomm_connect_path(const char *name
, int *connection_fd
)
501 size_t sock_addr_size
;
502 struct sockaddr_un
*addr
;
504 fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
510 addr
= create_sock_addr(name
, &sock_addr_size
);
512 ERR("allocating addr failed");
516 result
= connect(fd
, (struct sockaddr
*)addr
, sock_addr_size
);
518 PERROR("connect (path=%s)", name
);
537 /* Open a connection to a traceable app.
544 int ustcomm_connect_app(pid_t pid
, int *app_fd
)
550 result
= asprintf(&name
, "%s/%d", SOCK_DIR
, pid
);
552 ERR("failed to allocate socket name");
556 result
= ustcomm_connect_path(name
, app_fd
);
558 ERR("failed to connect to app");
567 int ensure_dir_exists(const char *dir
)
575 result
= stat(dir
, &st
);
576 if(result
== -1 && errno
!= ENOENT
) {
579 else if(result
== -1) {
583 /* mkdir mode to 0777 */
584 result
= mkdir_p(dir
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
586 ERR("executing in recursive creation of directory %s", dir
);
594 char * ustcomm_print_data(char *data_field
, int field_size
,
595 int *offset
, const char *format
, ...)
599 char *ptr
= USTCOMM_POISON_PTR
;
601 limit
= field_size
- *offset
;
602 va_start(args
, format
);
603 count
= vsnprintf(&data_field
[*offset
], limit
, format
, args
);
606 if (count
< limit
&& count
> -1) {
607 ptr
= NULL
+ *offset
;
608 *offset
= *offset
+ count
+ 1;
614 char * ustcomm_restore_ptr(char *ptr
, char *data_field
, int data_field_size
)
616 if ((unsigned long)ptr
> data_field_size
||
617 ptr
== USTCOMM_POISON_PTR
) {
621 return data_field
+ (long)ptr
;
624 int ustcomm_pack_trace_info(struct ustcomm_header
*header
,
625 struct ustcomm_trace_info
*trace_inf
,
630 trace_inf
->trace
= ustcomm_print_data(trace_inf
->data
,
631 sizeof(trace_inf
->data
),
635 if (trace_inf
->trace
== USTCOMM_POISON_PTR
) {
639 header
->size
= COMPUTE_MSG_SIZE(trace_inf
, offset
);
645 int ustcomm_unpack_trace_info(struct ustcomm_trace_info
*trace_inf
)
647 trace_inf
->trace
= ustcomm_restore_ptr(trace_inf
->trace
,
649 sizeof(trace_inf
->data
));
650 if (!trace_inf
->trace
) {
657 int ustcomm_pack_channel_info(struct ustcomm_header
*header
,
658 struct ustcomm_channel_info
*ch_inf
,
664 ch_inf
->trace
= ustcomm_print_data(ch_inf
->data
,
665 sizeof(ch_inf
->data
),
669 if (ch_inf
->trace
== USTCOMM_POISON_PTR
) {
673 ch_inf
->channel
= ustcomm_print_data(ch_inf
->data
,
674 sizeof(ch_inf
->data
),
678 if (ch_inf
->channel
== USTCOMM_POISON_PTR
) {
682 header
->size
= COMPUTE_MSG_SIZE(ch_inf
, offset
);
688 int ustcomm_unpack_channel_info(struct ustcomm_channel_info
*ch_inf
)
690 ch_inf
->trace
= ustcomm_restore_ptr(ch_inf
->trace
,
692 sizeof(ch_inf
->data
));
693 if (!ch_inf
->trace
) {
697 ch_inf
->channel
= ustcomm_restore_ptr(ch_inf
->channel
,
699 sizeof(ch_inf
->data
));
700 if (!ch_inf
->channel
) {
707 int ustcomm_pack_buffer_info(struct ustcomm_header
*header
,
708 struct ustcomm_buffer_info
*buf_inf
,
715 buf_inf
->trace
= ustcomm_print_data(buf_inf
->data
,
716 sizeof(buf_inf
->data
),
720 if (buf_inf
->trace
== USTCOMM_POISON_PTR
) {
724 buf_inf
->channel
= ustcomm_print_data(buf_inf
->data
,
725 sizeof(buf_inf
->data
),
729 if (buf_inf
->channel
== USTCOMM_POISON_PTR
) {
733 buf_inf
->ch_cpu
= channel_cpu
;
735 header
->size
= COMPUTE_MSG_SIZE(buf_inf
, offset
);
741 int ustcomm_unpack_buffer_info(struct ustcomm_buffer_info
*buf_inf
)
743 buf_inf
->trace
= ustcomm_restore_ptr(buf_inf
->trace
,
745 sizeof(buf_inf
->data
));
746 if (!buf_inf
->trace
) {
750 buf_inf
->channel
= ustcomm_restore_ptr(buf_inf
->channel
,
752 sizeof(buf_inf
->data
));
753 if (!buf_inf
->channel
) {
760 int ustcomm_pack_marker_info(struct ustcomm_header
*header
,
761 struct ustcomm_marker_info
*marker_inf
,
768 marker_inf
->trace
= ustcomm_print_data(marker_inf
->data
,
769 sizeof(marker_inf
->data
),
773 if (marker_inf
->trace
== USTCOMM_POISON_PTR
) {
778 marker_inf
->channel
= ustcomm_print_data(marker_inf
->data
,
779 sizeof(marker_inf
->data
),
783 if (marker_inf
->channel
== USTCOMM_POISON_PTR
) {
788 marker_inf
->marker
= ustcomm_print_data(marker_inf
->data
,
789 sizeof(marker_inf
->data
),
793 if (marker_inf
->marker
== USTCOMM_POISON_PTR
) {
797 header
->size
= COMPUTE_MSG_SIZE(marker_inf
, offset
);
802 int ustcomm_unpack_marker_info(struct ustcomm_marker_info
*marker_inf
)
804 marker_inf
->trace
= ustcomm_restore_ptr(marker_inf
->trace
,
806 sizeof(marker_inf
->data
));
807 if (!marker_inf
->trace
) {
811 marker_inf
->channel
= ustcomm_restore_ptr(marker_inf
->channel
,
813 sizeof(marker_inf
->data
));
814 if (!marker_inf
->channel
) {
818 marker_inf
->marker
= ustcomm_restore_ptr(marker_inf
->marker
,
820 sizeof(marker_inf
->data
));
821 if (!marker_inf
->marker
) {
828 int ustcomm_pack_sock_path(struct ustcomm_header
*header
,
829 struct ustcomm_sock_path
*sock_path_inf
,
830 const char *socket_path
)
834 sock_path_inf
->sock_path
=
835 ustcomm_print_data(sock_path_inf
->data
,
836 sizeof(sock_path_inf
->data
),
840 if (sock_path_inf
->sock_path
== USTCOMM_POISON_PTR
) {
844 header
->size
= COMPUTE_MSG_SIZE(sock_path_inf
, offset
);
849 int ustcomm_unpack_sock_path(struct ustcomm_sock_path
*sock_path_inf
)
851 sock_path_inf
->sock_path
=
852 ustcomm_restore_ptr(sock_path_inf
->sock_path
,
854 sizeof(sock_path_inf
->data
));
855 if (!sock_path_inf
->sock_path
) {