From: Zubin Mithra <[email protected]> * Makefile.am (strace_SOURCES): Add socketutils.c. * configure.ac (AC_CHECK_HEADERS): Add linux/inet_diag.h, linux/netlink.h, linux/sock_diag.h. (AC_CHECK_TYPES): Add inet_diag_req_v2. * defs.h (get_pagesize): Add declaration. (printsockdetails): Add declaration. * mem.c (get_pagesize): Remove static keyword. * socketutils.c (printsockdetails): New function. (send_query): New function. (receive_responses): New function to receive msg responses. (parse_response): New function to parse a received response. * util.c (printfd): Modify to use printsockdetails. * strace.c (usage): Update to add -yy option. * strace.1: Add description of -yy option.
Signed-off-by: Zubin Mithra <[email protected]> --- Makefile.am | 1 + configure.ac | 5 ++ defs.h | 3 +- mem.c | 2 +- socketutils.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ strace.1 | 3 + strace.c | 1 + util.c | 25 ++++++-- 8 files changed, 213 insertions(+), 6 deletions(-) create mode 100644 socketutils.c diff --git a/Makefile.am b/Makefile.am index be05946..ae01416 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,6 +45,7 @@ strace_SOURCES = \ scsi.c \ signal.c \ sock.c \ + socketutils.c \ strace.c \ stream.c \ syscall.c \ diff --git a/configure.ac b/configure.ac index 9aeb3a6..21dcc0e 100644 --- a/configure.ac +++ b/configure.ac @@ -228,8 +228,11 @@ AC_CHECK_HEADERS(m4_normalize([ inttypes.h ioctls.h linux/capability.h + linux/inet_diag.h + linux/netlink.h linux/perf_event.h linux/ptrace.h + linux/sock_diag.h linux/utsname.h mqueue.h netinet/sctp.h @@ -258,6 +261,8 @@ AC_CHECK_HEADERS([netinet/tcp.h netinet/udp.h],,, [#include <netinet/in.h>]) AC_CHECK_MEMBERS([struct msghdr.msg_control],,, [#include <sys/socket.h>]) +AC_CHECK_TYPES([struct inet_diag_req_v2],,, [#include <linux/inet_diag.h]) + AC_CHECK_TYPES([struct __old_kernel_stat],,, [#include <asm/stat.h>]) AC_CHECK_TYPES([struct pt_all_user_regs, struct ia64_fpreg, struct ptrace_peeksiginfo_args],,, diff --git a/defs.h b/defs.h index 625cac6..e0e9f77 100644 --- a/defs.h +++ b/defs.h @@ -67,7 +67,6 @@ #include <time.h> #include <sys/time.h> #include <sys/syscall.h> - #ifndef HAVE_STRERROR const char *strerror(int); #endif @@ -605,6 +604,7 @@ extern void print_pc(struct tcb *); extern int trace_syscall(struct tcb *); extern void count_syscall(struct tcb *, const struct timeval *); extern void call_summary(FILE *); +extern unsigned long get_pagesize(); #if defined(AVR32) \ || defined(I386) \ @@ -694,6 +694,7 @@ extern void printsiginfo(siginfo_t *, int); extern void printsiginfo_at(struct tcb *tcp, long addr); #endif extern void printfd(struct tcb *, int); +extern int printsockdetails(uint32_t); extern void print_dirfd(struct tcb *, int); extern void printsock(struct tcb *, long, int); extern void print_sock_optmgmt(struct tcb *, long, int); diff --git a/mem.c b/mem.c index 6ecd363..356c54e 100644 --- a/mem.c +++ b/mem.c @@ -34,7 +34,7 @@ #include <asm/mman.h> #include <sys/mman.h> -static unsigned long +unsigned long get_pagesize() { static unsigned long pagesize; diff --git a/socketutils.c b/socketutils.c new file mode 100644 index 0000000..79e4d07 --- /dev/null +++ b/socketutils.c @@ -0,0 +1,179 @@ +#include "defs.h" +#include <netinet/in.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <netlink/netlink.h> + +#ifdef HAVE_LINUX_NETLINK_H +# include <linux/netlink.h> +#endif + +#ifdef HAVE_LINUX_SOCK_DIAG_H +# include <linux/sock_diag.h> +#else +# define SOCK_DIAG_BY_FAMILY 20 + struct sock_diag_req { + __u8 sdiag_family; + __u8 sdiag_protocol; + }; +#endif + +#define SOCKET_BUFFER_SIZE (getpagesize() < 8192L ? getpagesize() : 8192L) + +#ifdef HAVE_LINUX_INET_DIAG_H +# include <linux/inet_diag.h> +#else + struct inet_diag_sockid { + __be16 idiag_sport; + __be16 idiag_dport; + __be32 idiag_src[4]; + __be32 idiag_dst[4]; + __u32 idiag_if; + __u32 idiag_cookie[2]; + #define INET_DIAG_NOCOOKIE (~0U) + }; +#endif + +/* Not all linux/inet_diag.h have v2 */ +#ifndef HAVE_STRUCT_INET_DIAG_REQ_V2 + struct inet_diag_req_v2 { + __u8 sdiag_family; + __u8 sdiag_protocol; + __u8 idiag_ext; + __u8 pad; + __u32 idiag_states; + struct inet_diag_sockid id; + }; +#endif + +int +parse_response(struct inet_diag_msg *diag_msg, int inodenr) +{ + char remote_addr_buf[INET6_ADDRSTRLEN]; + int rport; + char *ret; + + if (diag_msg->idiag_inode != inodenr) + return -1; + + switch(diag_msg->idiag_family) { + case AF_INET: + ret = inet_ntop(diag_msg->idiag_family, + (struct in_addr*) &(diag_msg->id.idiag_dst), + remote_addr_buf, INET_ADDRSTRLEN); + break; + case AF_INET6: + ret = inet_ntop(diag_msg->idiag_family, + (struct in_addr*) &(diag_msg->id.idiag_dst), + remote_addr_buf, INET6_ADDRSTRLEN); + break; + default: + return -1; + } + + if (!ret) + return -1; + + if (remote_addr_buf[0] == 0) + return -1; + rport = ntohs(diag_msg->id.idiag_dport); + tprintf("%s:%d", remote_addr_buf, rport); + return 0; +} + +int +send_query(int sockfd, int proto, int family) +{ + struct msghdr msg; + struct nlmsghdr nlh; + struct inet_diag_req_v2 conn_req; + struct sockaddr_nl sa; + struct iovec iov[2]; + + memset(&msg, 0, sizeof(msg)); + memset(&sa, 0, sizeof(sa)); + memset(&nlh, 0, sizeof(nlh)); + memset(&conn_req, 0, sizeof(conn_req)); + + sa.nl_family = AF_NETLINK; + conn_req.sdiag_family = family; + conn_req.sdiag_protocol = proto; + conn_req.idiag_states = -1; + + nlh.nlmsg_len = NLMSG_LENGTH(sizeof(conn_req)); + nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; + + nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY; + iov[0].iov_base = (void*) &nlh; + iov[0].iov_len = sizeof(nlh); + iov[1].iov_base = (void*) &conn_req; + iov[1].iov_len = sizeof(conn_req); + + msg.msg_name = (void*) &sa; + msg.msg_namelen = sizeof(sa); + msg.msg_iov = iov; + msg.msg_iovlen = 2; + + return sendmsg(sockfd, &msg, 0); +} + +int +receive_responses(int sockfd, int inodenr) +{ + char recv_buf[SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + struct inet_diag_msg *diag_msg; + int numbytes = 0; + while (1) { + numbytes = recv(sockfd, recv_buf, sizeof(recv_buf), 0); + nlh = (struct nlmsghdr*) recv_buf; + + while (NLMSG_OK(nlh, numbytes)) { + if (nlh->nlmsg_type == NLMSG_DONE) + return -1; + + else if (nlh->nlmsg_type == NLMSG_ERROR) + return -1; + + diag_msg = (struct inet_diag_msg*) NLMSG_DATA(nlh); + if (parse_response(diag_msg, inodenr) == 0) + return 0; + + nlh = NLMSG_NEXT(nlh, numbytes); + } + } + return -1; +} + +/* Given an inode number of a socket, print out the details + * of the remote ip address and remote port */ +int +printsockdetails(uint32_t inodenr) +{ + int sockfd, retval = -1; + size_t i, j; + int protocols[] = {IPPROTO_TCP, IPPROTO_UDP}; + int families[] = {AF_INET, AF_INET6}; + size_t plen = ARRAY_SIZE(protocols); + size_t flen = ARRAY_SIZE(families); + + /* Create the monitoring socket */ + sockfd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_INET_DIAG); + if (sockfd == -1) + return -1; + + for (i = 0; i < plen; i++) { + for (j = 0; j < flen; j++) { + if (send_query(sockfd, protocols[i], families[j]) < 0) { + goto end; + } + if (receive_responses(sockfd, inodenr) == 0) { + retval = 0; + goto end; + } + } + } +end: + close(sockfd); + return retval; +} diff --git a/strace.1 b/strace.1 index 2a24c38..57d6cc1 100644 --- a/strace.1 +++ b/strace.1 @@ -321,6 +321,9 @@ Print all strings in hexadecimal string format. .B \-y Print paths associated with file descriptor arguments. .TP +.B \-yy +Print extended decoded paths for socket file descriptors. +.TP .BI "\-a " column Align return values in a specific column (default column 40). .TP diff --git a/strace.c b/strace.c index 2bc5c67..7973922 100644 --- a/strace.c +++ b/strace.c @@ -216,6 +216,7 @@ usage: strace [-CdffhiqrtttTvVxxy] [-I n] [-e expr]...\n\ -v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\ -x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ -y -- print paths associated with file descriptor arguments\n\ +-yy -- print paths associated with file descriptor arguments\n\ -h -- print help message, -V -- print version\n\ -a column -- alignment COLUMN for printing syscall results (default %d)\n\ -b execve -- detach on this syscall\n\ diff --git a/util.c b/util.c index c78e962..446a619 100644 --- a/util.c +++ b/util.c @@ -404,10 +404,27 @@ void printfd(struct tcb *tcp, int fd) { char path[PATH_MAX + 1]; - - if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) - tprintf("%d<%s>", fd, path); - else + if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) { + static const char socket_prefix[] = "socket:["; + const size_t socket_prefix_len = sizeof(socket_prefix) - 1; + size_t path_len; + + if (show_fd_path > 1 && + strncmp(path, socket_prefix, socket_prefix_len) == 0 && + path[(path_len = strlen(path)) - 1] == ']') { + unsigned long inodenr; + path[path_len - 1] = '\0'; + inodenr = strtoul(path + socket_prefix_len, NULL, 10); + tprintf("%d<", fd); + if (printsockdetails(inodenr) < 0) { + path[path_len - 1] = ']'; + tprints(path); + } + tprints(">"); + } else { + tprintf("%d<%s>", fd, path); + } + } else tprintf("%d", fd); } -- 1.8.4 ------------------------------------------------------------------------------ _______________________________________________ Strace-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/strace-devel
