[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