[PATCHv2 1/3] Use the protocol name of a socket as a hint for peer address resolution

Masatake YAMATO yamato at redhat.com
Wed Dec 10 03:55:06 UTC 2014


For resolving the peer address of socket, all combinations of families
(AF_INET, AF_INET6) and protocols(IPPROTO_TCP, IPPROTO_UDP) were tried.

This patch utilizes the protocol name, getting via getxattr, to specify
the combination.

* util.c (printfd): Pass the protocol name for the given path to
  print_sockaddr_by_inode as the 2nd argument.

* socketutils.c (print_sockaddr_by_inode): Utilize the protocol name
  for the target inode for resolving the peer address of socket.
  If the name is NULL, resolve the address as in the past.
  Use inet_print in the case when no hint is given.
  (inet_print): New helper function for print_sockaddr_by_inode.

Changes in v2 patch (suggested by ldv):

* Simplify inet_print; just use a logical operator.

* Use inet_print in the case when no hint is given.

Signed-off-by: Masatake YAMATO <yamato at redhat.com>
---
 defs.h        |  2 +-
 socketutils.c | 46 +++++++++++++++++++++++++++++++---------------
 util.c        | 11 +++++------
 3 files changed, 37 insertions(+), 22 deletions(-)

diff --git a/defs.h b/defs.h
index 708adf6..a80d1f8 100644
--- a/defs.h
+++ b/defs.h
@@ -696,7 +696,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);
diff --git a/socketutils.c b/socketutils.c
index 80abed5..f57c304 100644
--- a/socketutils.c
+++ b/socketutils.c
@@ -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 cd4b802..9f4caac 100644
--- a/util.c
+++ b/util.c
@@ -461,14 +461,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
-- 
1.9.3





More information about the Strace-devel mailing list