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

Reply via email to