From: Zubin Mithra <[email protected]> * defs.h: Add Add header files netinet/in.h, sys/socket.h, arpa/inet.h, linux/netlink.h and linux/inet_diag.h. Change type of show_fd_path to unsigned int. Add macros SOCK_DIAG_BY_FAMILY, SOCKET_BUFFER_SIZE. Add structs sock_diag_req, inet_diag_req_v2. * strace.c (init): Change usage of show_fd_path. * util.c (parse_response): New function to parse and print ip, port from a message response. (send_query): New function. (receive_responses): New function. (printsockdetails): New function. (printfd): Modified to use printsockdetails.
Signed-off-by: Zubin Mithra <[email protected]> --- defs.h | 24 ++++++++++- strace.c | 4 +- util.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 172 insertions(+), 4 deletions(-) diff --git a/defs.h b/defs.h index 1a3b483..6959cdb 100644 --- a/defs.h +++ b/defs.h @@ -67,6 +67,11 @@ #include <time.h> #include <sys/time.h> #include <sys/syscall.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <linux/netlink.h> +#include <linux/inet_diag.h> #ifndef HAVE_STRERROR const char *strerror(int); @@ -562,7 +567,7 @@ extern bool iflag; extern bool count_wallclock; extern unsigned int qflag; extern bool not_failing_only; -extern bool show_fd_path; +extern unsigned int show_fd_path; extern bool hide_log_until_execve; /* are we filtering traces based on paths? */ extern const char **paths_selected; @@ -580,6 +585,23 @@ extern unsigned os_release; #undef KERNEL_VERSION #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#define SOCK_DIAG_BY_FAMILY 20 +#define SOCKET_BUFFER_SIZE (getpagesize() < 8192L ? getpagesize() : 8192L) + +struct sock_diag_req { + __u8 sdiag_family; + __u8 sdiag_protocol; +}; + +struct inet_diag_req_v2 { + __u8 sdiag_family; + __u8 sdiag_protocol; + __u8 idiag_ext; + __u8 pad; + __u32 idiag_states; + struct inet_diag_sockid id; +}; + enum bitness_t { BITNESS_CURRENT = 0, BITNESS_32 }; void error_msg(const char *fmt, ...) __attribute__ ((format(printf, 1, 2))); diff --git a/strace.c b/strace.c index 4154cde..2bc5c67 100644 --- a/strace.c +++ b/strace.c @@ -129,7 +129,7 @@ static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP; bool not_failing_only = 0; /* Show path associated with fd arguments */ -bool show_fd_path = 0; +unsigned int show_fd_path = 0; static bool detach_on_execve = 0; /* Are we "strace PROG" and need to skip detach on first execve? */ @@ -1734,7 +1734,7 @@ init(int argc, char *argv[]) xflag++; break; case 'y': - show_fd_path = 1; + show_fd_path++; break; case 'v': qualify("abbrev=none"); diff --git a/util.c b/util.c index 33482d5..5608449 100644 --- a/util.c +++ b/util.c @@ -404,13 +404,159 @@ printnum_int(struct tcb *tcp, long addr, const char *fmt) tprints("]"); } +int +parse_response(struct inet_diag_msg *diag_msg, int inodenr) { + char remote_addr_buf[INET6_ADDRSTRLEN]; + int rport; + + if (diag_msg->idiag_inode != inodenr) + return -1; + + memset(remote_addr_buf, 0, sizeof(remote_addr_buf)); + + switch(diag_msg->idiag_family) { + case AF_INET: + inet_ntop(diag_msg->idiag_family, + (struct in_addr*) &(diag_msg->id.idiag_dst), + remote_addr_buf, INET_ADDRSTRLEN); + break; + case AF_INET6: + inet_ntop(diag_msg->idiag_family, + (struct in_addr*) &(diag_msg->id.idiag_dst), + remote_addr_buf, INET6_ADDRSTRLEN); + break; + default: + 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[4]; + + 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 +parse_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(int inodenr) +{ + int sockfd; + int i, j; + int protocols[] = {IPPROTO_TCP, IPPROTO_UDP}; + int families[] = {AF_INET, AF_INET6}; + int plen = sizeof(protocols)/sizeof(protocols[0]); + int flen = sizeof(families)/sizeof(families[0]); + + //Create the monitoring socket + if((sockfd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_INET_DIAG)) == -1) + return -1; + + for (i = 0; i < plen; i++) { + for (j = 0; j < flen; j++) { + if (send_query(sockfd, protocols[i], families[j]) < 0) { + close(sockfd); + return -1; + } + if (parse_responses(sockfd, inodenr) == 0) { + close(sockfd); + return 0; + } + } + } + close(sockfd); + return -1; +} + void printfd(struct tcb *tcp, int fd) { char path[PATH_MAX + 1]; - if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) + if (show_fd_path == 1 && getfdpath(tcp, fd, path, sizeof(path)) >= 0) tprintf("%d<%s>", fd, path); + else if (show_fd_path > 1 && getfdpath(tcp, fd, path, sizeof(path)) >= 0) { + char *ptr = NULL; + int inodenr; + ptr = strstr(path, "socket:["); + if (ptr != path) { + tprintf("%d<%s>", fd, path); + } + else { + int retval; + ptr = path + 8; + path[strlen(path)-1] = '\0'; + inodenr = strtol(ptr, NULL, 10); + tprintf("%d<", fd); + retval = printsockdetails(inodenr); + if (retval == -1) tprintf("socket:[%d]",inodenr); + tprints(">"); + } + } else tprintf("%d", fd); } -- 1.8.4 ------------------------------------------------------------------------------ Want fast and easy access to all the code in your enterprise? Index and search up to 200,000 lines of code with a free copy of Black Duck Code Sight - the same software that powers the world's largest code search on Ohloh, the Black Duck Open Hub! Try it now. http://p.sf.net/sfu/bds _______________________________________________ Strace-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/strace-devel
