From: Masatake YAMATO Date: Wed, 10 Dec 2014 03:55:06 +0000 (+0900) Subject: Use the protocol name of a socket as a hint for peer address resolution X-Git-Tag: v4.10~276 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f605e92365c7479d59ccfac3a294089f89359715;p=strace Use the protocol name of a socket as a hint for peer address resolution 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 Signed-off-by: Dmitry V. Levin --- diff --git a/defs.h b/defs.h index 0958d703..c865110c 100644 --- 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); diff --git a/socketutils.c b/socketutils.c index 80abed55..f57c304f 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 fb5476f0..b7476cf2 100644 --- 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