[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