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): Add. * socketutils.h (socket_protocols): New enum. * socketutils.c (print_sockaddr_by_inode): Move proto to int. * util.c (socket_protocol_strings): New global structure. (getfdproto): Return int instead of string. (printfd): Change type of proto. --- defs.h | 2 +- socketutils.c | 61 ++++++++++++++++++++++++++++++++++++++--------------------- socketutils.h | 42 ++++++++++++++++++++++++++++++++++++++++ util.c | 34 ++++++++++++++++++++++++--------- 4 files changed, 107 insertions(+), 32 deletions(-) create mode 100644 socketutils.h diff --git a/defs.h b/defs.h index f7a85ca..594a292 100644 --- a/defs.h +++ b/defs.h @@ -631,7 +631,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 int); 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..0ac8463 100644 --- a/socketutils.c +++ b/socketutils.c @@ -438,44 +438,61 @@ netlink_print(const int fd, const unsigned long inode) netlink_parse_response); } +#include "socketutils.h" /* 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, const char *const proto_name) +print_sockaddr_by_inode(const unsigned long inode, const int 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 } - }; - 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 != -1) { + r = true; + + switch (proto) { + case TCP: + r = tcp_v4_print(fd, inode); + break; + case UDP: + r = udp_v4_print(fd, inode); + break; + case TCPv6: + r = tcp_v6_print(fd, inode); + break; + case UDPv6: + r = udp_v6_print(fd, inode); + break; + case UNIX: + r = unix_print(fd, inode); + break; + case NETLINK: + r = netlink_print(fd, inode); + break; + default: + r = false; } if (!r) { - tprintf("%s:[%lu]", proto_name, inode); + tprintf("%s:[%lu]", + socket_protocol_strings[proto], + inode); r = true; } } else { - for (i = 0; i < ARRAY_SIZE(protocols); ++i) { - if ((r = protocols[i].print(fd, inode))) + + bool (*const protocols_print[])(int, unsigned long) = + { + tcp_v4_print, udp_v4_print, + tcp_v6_print, udp_v6_print, + unix_print, netlink_print + }; + + for (i = 0; i < ARRAY_SIZE(protocols_print); ++i) { + if ((r = protocols_print[i](fd, inode))) break; } } diff --git a/socketutils.h b/socketutils.h new file mode 100644 index 0000000..647c460 --- /dev/null +++ b/socketutils.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015 Fabien Siron <fabien.si...@epita.fr> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SOCKETUTILS_H +# define SOCKETUTILS_H + +enum { + NETLINK = 0, + TCP = 1, + TCPv6, + UDP, + UDPv6, + UNIX +} socket_protocols; + +extern const char *socket_protocol_strings[]; + +#endif diff --git a/util.c b/util.c index 9c8c978..b810fd0 100644 --- a/util.c +++ b/util.c @@ -472,30 +472,47 @@ sprinttime(time_t t) return buf; } -static char * -getfdproto(struct tcb *tcp, int fd, char *buf, unsigned bufsize) +const char *socket_protocol_strings[] = { + "NETLINK", + "TCP", + "TCPv6", + "UDP", + "UDPv6", + "UNIX", +}; + +static int +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 -1; sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd); r = getxattr(path, "system.sockprotoname", buf, bufsize - 1); if (r <= 0) - return NULL; + return -1; else { + unsigned int i; /* * 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; + for (i = 0; i < ARRAY_SIZE(socket_protocol_strings); ++i) { + if (strcmp(socket_protocol_strings[i], buf) == 0) + return i; + } + + return -1; } #else - return NULL; + return -1; #endif } @@ -516,9 +533,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 int 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. https://ad.doubleclick.net/ddm/clk/305295220;132659582;e _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel