[PATCH v4] Print ip and port associated with descriptor with -yy

zubin.mithra at gmail.com zubin.mithra at gmail.com
Fri Aug 8 06:39:20 UTC 2014


From: Zubin Mithra <zubin.mithra at gmail.com>

* 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 <zubin.mithra at gmail.com>
---
 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





More information about the Strace-devel mailing list