[PATCH v5] Print ip and port associated with descriptor with -yy
zubin.mithra at gmail.com
zubin.mithra at gmail.com
Mon Aug 11 08:47:15 UTC 2014
From: Zubin Mithra <zubin.mithra at gmail.com>
* 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 <zubin.mithra at gmail.com>
---
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
More information about the Strace-devel
mailing list