]> granicus.if.org Git - strace/commitdiff
Use the protocol name of a socket as a hint for peer address resolution
authorMasatake YAMATO <yamato@redhat.com>
Wed, 10 Dec 2014 03:55:06 +0000 (12:55 +0900)
committerDmitry V. Levin <ldv@altlinux.org>
Tue, 16 Dec 2014 04:08:20 +0000 (04:08 +0000)
To resolve the peer address of socket, all combinations of families
(AF_INET, AF_INET6) and protocols(IPPROTO_TCP, IPPROTO_UDP) were tried.
This change utilizes the protocol name obtained via getxattr to specify
the right combination.

* socketutils.c (inet_print): New helper function.
(print_sockaddr_by_inode): Use it.  Utilize the protocol name
associated with the given inode for resolving the peer socket
address.  If the protocol name is NULL, resolve the address
by trying combinations of families and protocols as before.
* defs.h (print_sockaddr_by_inode): Update prototype.
* util.c (printfd): Pass the protocol name associated with
the given path to print_sockaddr_by_inode as the 2nd argument.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
defs.h
socketutils.c
util.c

diff --git a/defs.h b/defs.h
index 0958d703d8f9b412597a205b88e669295ff47c86..c865110c454de999312a92908de3d0d113b9e6b3 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -712,7 +712,7 @@ extern void printsiginfo(siginfo_t *, int);
 extern void printsiginfo_at(struct tcb *tcp, long addr);
 #endif
 extern void printfd(struct tcb *, int);
-extern bool print_sockaddr_by_inode(const unsigned long);
+extern bool print_sockaddr_by_inode(const unsigned long, const char *);
 extern void print_dirfd(struct tcb *, int);
 extern void printsock(struct tcb *, long, int);
 extern void print_sock_optmgmt(struct tcb *, long, int);
index 80abed55b318abb88106647cc0381ee41936b4c3..f57c304fc4921ac602c37becc0c316d2b54b49d5 100644 (file)
@@ -138,33 +138,49 @@ receive_responses(const int fd, const unsigned long inode)
        }
 }
 
+static bool
+inet_print(int fd, int family, int protocol, const unsigned long inode)
+{
+       return send_query(fd, family, protocol)
+               && receive_responses(fd, inode);
+}
+
 /* Given an inode number of a socket, print out the details
  * of the ip address and port. */
 bool
-print_sockaddr_by_inode(const unsigned long inode)
+print_sockaddr_by_inode(const unsigned long inode, const char *proto_name)
 {
-       const int families[] = {AF_INET, AF_INET6};
-       const int protocols[] = {IPPROTO_TCP, IPPROTO_UDP};
-       const size_t flen = ARRAY_SIZE(families);
-       const size_t plen = ARRAY_SIZE(protocols);
-       size_t fi, pi;
        int fd;
+       bool r = false;
 
        fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG);
        if (fd < 0)
                return false;
 
-       for (fi = 0; fi < flen; ++fi) {
-               for (pi = 0; pi < plen; ++pi) {
-                       if (!send_query(fd, families[fi], protocols[pi]))
-                               continue;
-                       if (receive_responses(fd, inode)) {
-                               close(fd);
-                               return true;
+       if (proto_name) {
+               if (strcmp(proto_name, "TCP") == 0)
+                       r = inet_print(fd, AF_INET, IPPROTO_TCP, inode);
+               else if (strcmp(proto_name, "UDP") == 0)
+                       r = inet_print(fd, AF_INET, IPPROTO_UDP, inode);
+               else if (strcmp(proto_name, "TCPv6") == 0)
+                       r = inet_print(fd, AF_INET6, IPPROTO_TCP, inode);
+               else if (strcmp(proto_name, "UDPv6") == 0)
+                       r = inet_print(fd, AF_INET6, IPPROTO_UDP, inode);
+       } else {
+               const int families[] = {AF_INET, AF_INET6};
+               const int protocols[] = {IPPROTO_TCP, IPPROTO_UDP};
+               const size_t flen = ARRAY_SIZE(families);
+               const size_t plen = ARRAY_SIZE(protocols);
+               size_t fi, pi;
+
+               for (fi = 0; fi < flen; ++fi) {
+                       for (pi = 0; pi < plen; ++pi) {
+                               if ((r = inet_print(fd, families[fi], protocols[pi], inode)))
+                                       goto out;
                        }
                }
        }
-
+out:
        close(fd);
-       return false;
+       return r;
 }
diff --git a/util.c b/util.c
index fb5476f04e4ed5323788f03f7202b0c8348ad86c..b7476cf281b3a967038a59f39451335d9358f51f 100644 (file)
--- a/util.c
+++ b/util.c
@@ -482,14 +482,13 @@ printfd(struct tcb *tcp, int fd)
                    strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
                    path[(path_len = strlen(path)) - 1] == ']') {
                        unsigned long inodenr;
+#define PROTO_NAME_LEN 32
+                       char proto_buf[PROTO_NAME_LEN];
+                       const char *proto =
+                               getfdproto(tcp, fd, proto_buf, PROTO_NAME_LEN);
                        inodenr = strtoul(path + socket_prefix_len, NULL, 10);
                        tprintf("%d<", fd);
-                       if (!print_sockaddr_by_inode(inodenr)) {
-#define PROTO_NAME_LEN 32
-                               char proto_buf[PROTO_NAME_LEN];
-                               const char *proto =
-                                       getfdproto(tcp, fd, proto_buf, PROTO_NAME_LEN);
-
+                       if (!print_sockaddr_by_inode(inodenr, proto)) {
                                if (proto)
                                        tprintf("%s:[%lu]", proto, inodenr);
                                else