Make getfdproto return enum instead of string
Introduce a new enum type sock_proto and use it instead of strings for socket protocols identification. * defs.h (sock_proto): New enum. (get_proto_by_name): New function. * socketutils.c (protocols): New static table. (print_sockaddr_by_inode): Use it. Change type of "proto" argument to sock_proto. (get_proto_by_name): New function. * util.c (getfdproto): Use it. Change return type to sock_proto. (printfd): Update.
This commit is contained in:
parent
cb7409c87a
commit
802cc28f39
13
defs.h
13
defs.h
@ -437,6 +437,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 *);
|
||||
|
||||
typedef enum {
|
||||
CFLAG_NONE = 0,
|
||||
CFLAG_ONLY_STATS,
|
||||
@ -636,7 +647,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);
|
||||
|
@ -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 }
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 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;
|
||||
}
|
||||
}
|
||||
|
20
util.c
20
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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user