From: Masatake YAMATO Date: Tue, 20 Sep 2022 21:16:15 +0000 (+0900) Subject: lsfd: use extra information loaded from /proc/net/unix X-Git-Tag: v2.39-rc1~505^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e38e61ca6fcdd60cca7620abe33deae4927a12b;p=thirdparty%2Futil-linux.git lsfd: use extra information loaded from /proc/net/unix The loaded information is displayed at SOCKNETNS, SOCKSTATE, SOCKTYPE, and/or UNIX.PATH columns of UNIX-STREAM and UNIX typed sockets. Signed-off-by: Masatake YAMATO --- diff --git a/misc-utils/lsfd-sock-xinfo.c b/misc-utils/lsfd-sock-xinfo.c index 804e394127..ef994f191c 100644 --- a/misc-utils/lsfd-sock-xinfo.c +++ b/misc-utils/lsfd-sock-xinfo.c @@ -18,8 +18,14 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include /* open(2) */ +#include /* SS_* */ +#include /* UNIX_PATH_MAX */ #include /* for setns(2) */ #include +#include +#include +#include /* SOCK_* */ #include "xalloc.h" #include "nls.h" @@ -28,6 +34,8 @@ #include "lsfd.h" #include "lsfd-sock.h" +static void load_xinfo_from_proc_unix(ino_t netns_inode); + static int self_netns_fd = -1; struct stat self_netns_sb; @@ -60,9 +68,9 @@ static void mark_sock_xinfo_loaded(ino_t ino) errx(EXIT_FAILURE, _("failed to allocate memory")); } -static void load_sock_xinfo_no_nsswitch(ino_t netns __attribute__((__unused__))) +static void load_sock_xinfo_no_nsswitch(ino_t netns) { - /* TODO: load files under /proc/ns */ + load_xinfo_from_proc_unix(netns); } static void load_sock_xinfo_with_fd(int fd, ino_t netns) @@ -165,6 +173,14 @@ static int xinfo_compare(const void *a, const void *b) return 0; } +static void add_sock_info(struct sock_xinfo *xinfo) +{ + struct sock_xinfo **tmp = tsearch(xinfo, &xinfo_tree, xinfo_compare); + + if (tmp == NULL) + errx(EXIT_FAILURE, _("failed to allocate memory")); +} + struct sock_xinfo *get_sock_xinfo(ino_t netns_inode) { struct sock_xinfo **xinfo = tfind(&netns_inode, &xinfo_tree, xinfo_compare); @@ -178,3 +194,187 @@ bool is_nsfs_dev(dev_t dev) { return (dev == self_netns_sb.st_dev); } + +static const char *sock_decode_type(uint16_t type) +{ + switch (type) { + case SOCK_STREAM: + return "stream"; + case SOCK_DGRAM: + return "dgram"; + case SOCK_RAW: + return "raw"; + case SOCK_RDM: + return "rdm"; + case SOCK_SEQPACKET: + return "seqpacket"; + case SOCK_DCCP: + return "dccp"; + case SOCK_PACKET: + return "packet"; + default: + return "unknown"; + } +} + +/* + * Protocol specific code + */ + +/* + * UNIX + */ +struct unix_xinfo { + struct sock_xinfo sock; + int acceptcon; /* flags */ + uint16_t type; + uint8_t st; + char path[ + UNIX_PATH_MAX + + 1 /* for @ */ + + 1 /* \0? */ + ]; +}; + +static const char *unix_decode_state(uint8_t st) +{ + switch (st) { + case SS_FREE: + return "free"; + case SS_UNCONNECTED: + return "unconnected"; + case SS_CONNECTING: + return "connecting"; + case SS_CONNECTED: + return "connected"; + case SS_DISCONNECTING: + return "disconnecting"; + default: + return "unknown"; + } +} + +static char *unix_get_name(struct sock_xinfo *sock_xinfo, + struct sock *sock) +{ + struct unix_xinfo *ux = (struct unix_xinfo *)sock_xinfo; + const char *state = unix_decode_state(ux->st); + char *str = NULL; + + if (sock->protoname && (strcmp(sock->protoname, "UNIX-STREAM") == 0)) + xasprintf(&str, "state=%s%s%s", + (ux->acceptcon)? "listen": state, + *(ux->path)? " path=": "", + *(ux->path)? ux->path: ""); + else + xasprintf(&str, "state=%s%s%s type=%s", + (ux->acceptcon)? "listen": state, + *(ux->path)? " path=": "", + *(ux->path)? ux->path: "", + sock_decode_type(ux->type)); + return str; +} + +static char *unix_get_type(struct sock_xinfo *sock_xinfo, + struct sock *sock __attribute__((__unused__))) +{ + const char *str; + struct unix_xinfo *ux = (struct unix_xinfo *)sock_xinfo; + + str = sock_decode_type(ux->type); + return strdup(str); +} + +static char *unix_get_state(struct sock_xinfo *sock_xinfo, + struct sock *sock __attribute__((__unused__))) +{ + const char *str; + struct unix_xinfo *ux = (struct unix_xinfo *)sock_xinfo; + + if (ux->acceptcon) + return strdup("listen"); + + str = unix_decode_state(ux->st); + return strdup(str); +} + +static bool unix_fill_column(struct proc *proc __attribute__((__unused__)), + struct sock_xinfo *sock_xinfo, + struct sock *sock __attribute__((__unused__)), + struct libscols_line *ln __attribute__((__unused__)), + int column_id, + size_t column_index __attribute__((__unused__)), + char **str) +{ + struct unix_xinfo *ux = (struct unix_xinfo *)sock_xinfo; + + switch(column_id) { + case COL_UNIX_PATH: + if (*ux->path) { + *str = strdup(ux->path); + return true; + } + break; + } + + return false; +} + +static struct sock_xinfo_class unix_xinfo_class = { + .class = "unix", + .get_name = unix_get_name, + .get_type = unix_get_type, + .get_state = unix_get_state, + .fill_column = unix_fill_column, + .free = NULL, +}; + +/* #define UNIX_LINE_LEN 54 + 21 + UNIX_LINE_LEN + 1 */ +#define UNIX_LINE_LEN 256 +static void load_xinfo_from_proc_unix(ino_t netns_inode) +{ + char line[UNIX_LINE_LEN]; + FILE *unix_fp; + + unix_fp = fopen("/proc/net/unix", "r"); + if (!unix_fp) + return; + + if (fgets(line, sizeof(line), unix_fp) == NULL) + goto out; + if (! (line[0] == 'N' && line[1] == 'u' && line[2] == 'm')) + /* Unexpected line */ + goto out; + + while (fgets(line, sizeof(line), unix_fp)) { + uint64_t flags; + uint32_t type; + unsigned int st; + unsigned long inode; + char path[1 + UNIX_PATH_MAX +1]; + struct unix_xinfo *ux; + + memset(path, 0, sizeof(path)); + if (sscanf(line, "%*x: %*x %*x %lx %x %x %lu %s", + &flags, &type, &st, &inode, path) < 4) + continue; + + if (inode == 0) + continue; + + ux = xmalloc(sizeof(struct unix_xinfo)); + ux->sock.class = &unix_xinfo_class; + ux->sock.inode = (ino_t)inode; + ux->sock.netns_inode = netns_inode; + + ux->acceptcon = !!flags; + ux->type = type; + ux->st = st; + strcpy(ux->path, path); + + add_sock_info((struct sock_xinfo *)ux); + } + + out: + fclose(unix_fp); +} diff --git a/misc-utils/lsfd.c b/misc-utils/lsfd.c index cddf82a19f..d403513961 100644 --- a/misc-utils/lsfd.c +++ b/misc-utils/lsfd.c @@ -201,6 +201,8 @@ static struct colinfo infos[] = { N_("file type (cooked)") }, [COL_UID] = { "UID", 0, SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER, N_("user ID number of the process") }, + [COL_UNIX_PATH]={ "UNIX.PATH",0.4,SCOLS_FL_TRUNC,SCOLS_JSON_STRING, + N_("filesystem pathname for UNIX doamin socketo") }, [COL_USER] = { "USER", 0, SCOLS_FL_RIGHT, SCOLS_JSON_STRING, N_("user of the process") }, }; diff --git a/misc-utils/lsfd.h b/misc-utils/lsfd.h index ef83d5ef34..2ab17d27d3 100644 --- a/misc-utils/lsfd.h +++ b/misc-utils/lsfd.h @@ -75,6 +75,7 @@ enum { COL_TID, COL_TYPE, COL_UID, /* process */ + COL_UNIX_PATH, COL_USER, /* process */ COL_FUID, /* file */ COL_OWNER, /* file */ diff --git a/tests/expected/lsfd/column-name b/tests/expected/lsfd/column-name index 0e0ac1d9da..c8364fbf5a 100644 --- a/tests/expected/lsfd/column-name +++ b/tests/expected/lsfd/column-name @@ -2,5 +2,5 @@ ro-regular-file:ASSOC,KNAME,NAME: 0 3 anon_inode:[pidfd] pid=1 comm= nspid=1 pidfd:ASSOC,KNAME,NAME: 0 - 3 socket:[INODENUM] socket:[INODENUM] + 3 socket:[INODENUM] state=connected type=dgram socketpair:ASSOC,KNAME,NAME: 0