This commit aims to avoid future string comparisons with getfdproto function in changing its return type. It also adapts the functions that use it.
* defs.h (print_sockaddr_by_inode, get_proto_by_name): Add. (sock_proto): New enum. * socketutils.c (print_sockaddr_by_inode): Move proto to int. (get_proto_by_name): New function. (protocols): New static table. * util.c (getfdproto): Return sock_proto instead of string. (printfd): Change type of proto. --- defs.h | 13 +++++++++++- socketutils.c | 63 ++++++++++++++++++++++++++++++++++++----------------------- util.c | 20 ++++++++++--------- 3 files changed, 62 insertions(+), 34 deletions(-) diff --git a/defs.h b/defs.h index 724d4f3..ab06921 100644 --- a/defs.h +++ b/defs.h @@ -431,6 +431,17 @@ extern const struct xlat whence_codes[]; # define NEED_UID16_PARSERS 0 #endif +enum sock_proto { + SOCK_PROTO_UNKNOWN, + SOCK_PROTO_UNIX, + SOCK_PROTO_TCP, + SOCK_PROTO_UDP, + SOCK_PROTO_TCPv6, + SOCK_PROTO_UDPv6, + SOCK_PROTO_NETLINK +}; +extern enum sock_proto get_proto_by_name(const char *const name); + typedef enum { CFLAG_NONE = 0, CFLAG_ONLY_STATS, @@ -630,7 +641,7 @@ extern void printpathn(struct tcb *, long, unsigned int); #define TIMESPEC_TEXT_BUFSIZE \ (sizeof(intmax_t)*3 * 2 + sizeof("{tv_sec=%jd, tv_nsec=%jd}")) extern void printfd(struct tcb *, int); -extern bool print_sockaddr_by_inode(const unsigned long, const char *); +extern bool print_sockaddr_by_inode(const unsigned long, const enum sock_proto); extern bool print_sockaddr_by_inode_cached(const unsigned long); extern void print_dirfd(struct tcb *, int); extern void printsock(struct tcb *, long, int); diff --git a/socketutils.c b/socketutils.c index 5d8d3ed..4a39522 100644 --- a/socketutils.c +++ b/socketutils.c @@ -438,44 +438,59 @@ netlink_print(const int fd, const unsigned long inode) netlink_parse_response); } +static const struct { + const char *const name; + bool (*const print)(int, unsigned long); +} protocols[] = { + [SOCK_PROTO_UNIX] = { "UNIX", unix_print }, + [SOCK_PROTO_TCP] = { "TCP", tcp_v4_print }, + [SOCK_PROTO_UDP] = { "UDP", udp_v4_print }, + [SOCK_PROTO_TCPv6] = { "TCPv6", tcp_v6_print }, + [SOCK_PROTO_UDPv6] = { "UDPv6", udp_v6_print }, + [SOCK_PROTO_NETLINK] = { "NETLINK", netlink_print } +}; + /* Given an inode number of a socket, print out the details * of the ip address and port. */ + +enum sock_proto +get_proto_by_name(const char *const name) +{ + unsigned int i; + for (i = (unsigned int) SOCK_PROTO_UNKNOWN + 1; + i < ARRAY_SIZE(protocols); ++i) { + if (protocols[i].name && !strcmp(name, protocols[i].name)) + return (enum sock_proto) i; + } + return SOCK_PROTO_UNKNOWN; +} + bool -print_sockaddr_by_inode(const unsigned long inode, const char *const proto_name) +print_sockaddr_by_inode(const unsigned long inode, const enum sock_proto proto) { - static const struct { - const char *const name; - bool (*const print)(int, unsigned long); - } protocols[] = { - { "TCP", tcp_v4_print }, - { "UDP", udp_v4_print }, - { "TCPv6", tcp_v6_print }, - { "UDPv6", udp_v6_print }, - { "UNIX", unix_print }, - { "NETLINK", netlink_print } - }; + if ((unsigned int) proto >= ARRAY_SIZE(protocols) || + (proto != SOCK_PROTO_UNKNOWN && !protocols[proto].print)) + return false; const int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG); if (fd < 0) return false; bool r = false; - unsigned int i; - - if (proto_name) { - for (i = 0; i < ARRAY_SIZE(protocols); ++i) { - if (strcmp(proto_name, protocols[i].name) == 0) { - r = protocols[i].print(fd, inode); - break; - } - } + if (proto != SOCK_PROTO_UNKNOWN) { + r = protocols[proto].print(fd, inode); if (!r) { - tprintf("%s:[%lu]", proto_name, inode); + tprintf("%s:[%lu]", protocols[proto].name, inode); r = true; } } else { - for (i = 0; i < ARRAY_SIZE(protocols); ++i) { - if ((r = protocols[i].print(fd, inode))) + unsigned int i; + for (i = (unsigned int) SOCK_PROTO_UNKNOWN + 1; + i < ARRAY_SIZE(protocols); ++i) { + if (!protocols[i].print) + continue; + r = protocols[i].print(fd, inode); + if (r) break; } } diff --git a/util.c b/util.c index ea2e869..d6956bc 100644 --- a/util.c +++ b/util.c @@ -472,30 +472,33 @@ sprinttime(time_t t) return buf; } -static char * -getfdproto(struct tcb *tcp, int fd, char *buf, unsigned bufsize) +static enum sock_proto +getfdproto(struct tcb *tcp, int fd) { #ifdef HAVE_SYS_XATTR_H + size_t bufsize = 256; + char buf[bufsize]; ssize_t r; char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3]; if (fd < 0) - return NULL; + return SOCK_PROTO_UNKNOWN; sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd); r = getxattr(path, "system.sockprotoname", buf, bufsize - 1); if (r <= 0) - return NULL; + return SOCK_PROTO_UNKNOWN; else { /* * This is a protection for the case when the kernel * side does not append a null byte to the buffer. */ buf[r] = '\0'; - return buf; + + return get_proto_by_name(buf); } #else - return NULL; + return SOCK_PROTO_UNKNOWN; #endif } @@ -516,9 +519,8 @@ printfd(struct tcb *tcp, int fd) strtoul(path + socket_prefix_len, NULL, 10); if (!print_sockaddr_by_inode_cached(inode)) { - char buf[256]; - const char *proto = - getfdproto(tcp, fd, buf, sizeof(buf)); + const enum sock_proto proto = + getfdproto(tcp, fd); if (!print_sockaddr_by_inode(inode, proto)) tprints(path); } -- 2.8.3 ------------------------------------------------------------------------------ What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports. http://pubads.g.doubleclick.net/gampad/clk?id=1444514421&iu=/41014381 _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel