]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsfd: use extra information loaded from /proc/net/tcp6
authorMasatake YAMATO <yamato@redhat.com>
Fri, 3 Feb 2023 05:03:23 +0000 (14:03 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Fri, 17 Feb 2023 14:35:47 +0000 (23:35 +0900)
Example output:

  # ./lsfd -Q '(TYPE == "TCPv6") and ((COMMAND == "sshd") or (COMMAND == "test_mkfds"))'
  COMMAND       PID USER ASSOC MODE  TYPE SOURCE MNTID   INODE NAME
  sshd         1137 root     4  rw- TCPv6 sockfs     9   34689 state=listen laddr=[::]:22
  test_mkfds 716926  jet     3  rw- TCPv6 sockfs     9 6042073 state=listen laddr=[::1]:12345
  test_mkfds 716926  jet     4  rw- TCPv6 sockfs     9 6042074 state=established laddr=[::1]:23456 raddr=[::1]:12345
  test_mkfds 716926  jet     5  rw- TCPv6 sockfs     9 6042075 state=established laddr=[::1]:12345 raddr=[::1]:23456

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
misc-utils/lsfd-sock-xinfo.c
misc-utils/lsfd.c
misc-utils/lsfd.h

index 2316fc90ec8eab52232000734e0301e89e447f1c..a5160c75d7206bb20ddff13e47be0f00414558a9 100644 (file)
@@ -19,6 +19,7 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <arpa/inet.h>         /* inet_ntop */
+#include <netinet/in.h>                /* in6_addr */
 #include <fcntl.h>             /* open(2) */
 #include <inttypes.h>          /* SCNu16 */
 #include <linux/net.h>         /* SS_* */
@@ -42,6 +43,7 @@ static void load_xinfo_from_proc_unix(ino_t netns_inode);
 static void load_xinfo_from_proc_raw(ino_t netns_inode);
 static void load_xinfo_from_proc_tcp(ino_t netns_inode);
 static void load_xinfo_from_proc_udp(ino_t netns_inode);
+static void load_xinfo_from_proc_tcp6(ino_t netns_inode);
 
 static int self_netns_fd = -1;
 static struct stat self_netns_sb;
@@ -81,6 +83,7 @@ static void load_sock_xinfo_no_nsswitch(ino_t netns)
        load_xinfo_from_proc_tcp(netns);
        load_xinfo_from_proc_udp(netns);
        load_xinfo_from_proc_raw(netns);
+       load_xinfo_from_proc_tcp6(netns);
 }
 
 static void load_sock_xinfo_with_fd(int fd, ino_t netns)
@@ -420,6 +423,15 @@ static uint32_t kernel32_to_cpu(enum sysfs_byteorder byteorder, uint32_t v)
                return be32_to_cpu(v);
 }
 
+/*
+ * AF_INET6
+ */
+struct inet6_xinfo {
+       struct sock_xinfo sock;
+       struct in6_addr local_addr;
+       struct in6_addr remote_addr;
+};
+
 /*
  * L4 abstract-layer for protocols stacked on IP and IP6.
  */
@@ -469,11 +481,15 @@ static const char *l4_decode_state(enum l4_state st)
 }
 
 struct l4_xinfo {
-       struct inet_xinfo inet;
+       union {
+               struct inet_xinfo inet;
+               struct inet6_xinfo inet6;
+       };
        enum l4_state st;
 };
 
 enum l4_side { L4_LOCAL, L4_REMOTE };
+enum l3_decorator { L3_DECO_START, L3_DECO_END };
 
 struct l4_xinfo_class {
        struct sock_xinfo_class sock;
@@ -484,6 +500,7 @@ struct l4_xinfo_class {
        void * (*get_addr)(struct l4_xinfo *, enum l4_side);
        bool (*is_any_addr)(void *);
        int family;
+       const char *l3_decorator[2];
 };
 
 #define l3_fill_column_handler(L3, SOCK_XINFO, COLUMN_ID, STR) __extension__ \
@@ -533,19 +550,21 @@ static char *tcp_get_name(struct sock_xinfo *sock_xinfo,
        void *raddr = class->get_addr(l4, L4_REMOTE);
        char local_s[BUFSIZ];
        char remote_s[BUFSIZ];
+       const char *start = class->l3_decorator[L3_DECO_START];
+       const char *end = class->l3_decorator[L3_DECO_END];
 
        if (!inet_ntop(class->family, laddr, local_s, sizeof(local_s)))
                xasprintf(&str, "state=%s", st_str);
        else if (l4->st == TCP_LISTEN
                 || !inet_ntop(class->family, raddr, remote_s, sizeof(remote_s)))
-               xasprintf(&str, "state=%s laddr=%s:%"SCNu16,
+               xasprintf(&str, "state=%s laddr=%s%s%s:%"SCNu16,
                          st_str,
-                         local_s, tcp->local_port);
+                         start, local_s, end, tcp->local_port);
        else
-               xasprintf(&str, "state=%s laddr=%s:%"SCNu16" raddr=%s:%"SCNu16,
+               xasprintf(&str, "state=%s laddr=%s%s%s:%"SCNu16" raddr=%s%s%s:%"SCNu16,
                          st_str,
-                         local_s, tcp->local_port,
-                         remote_s, tcp->remote_port);
+                         start, local_s, end, tcp->local_port,
+                         start, remote_s, end, tcp->remote_port);
        return str;
 }
 
@@ -591,7 +610,11 @@ static bool tcp_get_listening(struct sock_xinfo *sock_xinfo,
                                p = tcp->remote_port;                   \
                        }                                               \
                        if (n && inet_ntop(class->family, n, s, sizeof(s))) \
-                               xasprintf(STR, "%s:%"SCNu16, s, p);     \
+                               xasprintf(STR, "%s%s%s:%"SCNu16, \
+                                         class->l3_decorator[L3_DECO_START], \
+                                         s,                            \
+                                         class->l3_decorator[L3_DECO_END], \
+                                         p);                           \
                        break;                                          \
                case COL_##L4##_LPORT:                                  \
                        p = tcp->local_port;                            \
@@ -684,6 +707,7 @@ static const struct l4_xinfo_class tcp_xinfo_class = {
        .get_addr = tcp_xinfo_get_addr,
        .is_any_addr = tcp_xinfo_is_any_addr,
        .family = AF_INET,
+       .l3_decorator = {"", ""},
 };
 
 static bool L4_verify_initial_line(const char *line)
@@ -798,6 +822,7 @@ static const struct l4_xinfo_class udp_xinfo_class = {
        .get_addr = tcp_xinfo_get_addr,
        .is_any_addr = tcp_xinfo_is_any_addr,
        .family = AF_INET,
+       .l3_decorator = {"", ""},
 };
 
 static void load_xinfo_from_proc_udp(ino_t netns_inode)
@@ -917,6 +942,7 @@ static const struct l4_xinfo_class raw_xinfo_class = {
        .get_addr = tcp_xinfo_get_addr,
        .is_any_addr = tcp_xinfo_is_any_addr,
        .family = AF_INET,
+       .l3_decorator = {"", ""},
 };
 
 static void load_xinfo_from_proc_raw(ino_t netns_inode)
@@ -925,3 +951,98 @@ static void load_xinfo_from_proc_raw(ino_t netns_inode)
                                     "/proc/net/raw",
                                     &raw_xinfo_class);
 }
+
+/*
+ * TCP6
+ */
+static struct sock_xinfo *tcp6_xinfo_scan_line(const struct sock_xinfo_class *class,
+                                              char * line,
+                                              ino_t netns_inode,
+                                              enum sysfs_byteorder byteorder)
+{
+       uint32_t local_addr[4];
+       unsigned int local_port;
+       uint32_t remote_addr[4];
+       unsigned int remote_port;
+       unsigned int st;
+       unsigned long inode;
+       struct tcp_xinfo *tcp;
+       struct inet6_xinfo *inet6;
+       struct sock_xinfo *sock;
+
+       if (sscanf(line,
+                  "%*d: "
+                  "%08x%08x%08x%08x:%04x "
+                  "%08x%08x%08x%08x:%04x "
+                  "%x %*x:%*x %*x:%*x %*x %*u %*d %lu ",
+                  local_addr+0, local_addr+1, local_addr+2, local_addr+3, &local_port,
+                  remote_addr+0, remote_addr+1, remote_addr+2, remote_addr+3, &remote_port,
+                  &st, &inode) != 12)
+               return NULL;
+
+       if (inode == 0)
+               return NULL;
+
+       tcp = xmalloc(sizeof(struct tcp_xinfo));
+       inet6 = &tcp->l4.inet6;
+       sock = &inet6->sock;
+       sock->class = class;
+       sock->inode = (ino_t)inode;
+       sock->netns_inode = netns_inode;
+       tcp->local_port = local_port;
+       for (int i = 0; i < 4; i++) {
+               inet6->local_addr.s6_addr32[i] = kernel32_to_cpu(byteorder, local_addr[i]);
+               inet6->remote_addr.s6_addr32[i] = kernel32_to_cpu(byteorder, remote_addr[i]);
+       }
+       tcp->remote_port = remote_port;
+       tcp->l4.st = st;
+
+       return sock;
+}
+
+static bool tcp6_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)
+{
+       return l3_fill_column_handler(INET6, sock_xinfo, column_id, str)
+               || l4_fill_column_handler(TCP, sock_xinfo, column_id, str);
+}
+
+static void *tcp6_xinfo_get_addr(struct l4_xinfo * l4, enum l4_side side)
+{
+       return (side == L4_LOCAL)
+               ? &l4->inet6.local_addr
+               : &l4->inet6.remote_addr;
+}
+
+static bool tcp6_xinfo_is_any_addr(void *addr)
+{
+       return IN6_ARE_ADDR_EQUAL(addr, &(struct in6_addr)IN6ADDR_ANY_INIT);
+}
+
+static const struct l4_xinfo_class tcp6_xinfo_class = {
+       .sock = {
+               .get_name = tcp_get_name,
+               .get_type = tcp_get_type,
+               .get_state = tcp_get_state,
+               .get_listening = tcp_get_listening,
+               .fill_column = tcp6_fill_column,
+               .free = NULL,
+       },
+       .scan_line = tcp6_xinfo_scan_line,
+       .get_addr = tcp6_xinfo_get_addr,
+       .is_any_addr = tcp6_xinfo_is_any_addr,
+       .family = AF_INET6,
+       .l3_decorator = {"[", "]"},
+};
+
+static void load_xinfo_from_proc_tcp6(ino_t netns_inode)
+{
+       load_xinfo_from_proc_inet_L4(netns_inode,
+                                    "/proc/net/tcp6",
+                                    &tcp6_xinfo_class);
+}
index 31a9311d8e4e5ed1f2b009258368ac255ae08478..7f6275ee8b172d61a58df5ee7fe4ff5a57244f82 100644 (file)
@@ -151,6 +151,10 @@ static const struct colinfo infos[] = {
                N_("local IP address") },
        [COL_INET_RADDR]={"INET.RADDR",0,SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
                N_("remote IP address") },
+       [COL_INET6_LADDR]={"INET6.LADDR",0,SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
+               N_("local IPv6 address") },
+       [COL_INET6_RADDR]={"INET6.RADDR",0,SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
+               N_("remote IPv6 address") },
        [COL_KNAME]   = { "KNAME",  0.4, SCOLS_FL_TRUNC, SCOLS_JSON_STRING,
                N_("name of the file (raw)") },
        [COL_KTHREAD] = { "KTHREAD",  0, SCOLS_FL_RIGHT, SCOLS_JSON_BOOLEAN,
index 3b12c60c63e6ac2f577172074014217c55d70647..3023af13b04512efb4ef90259ae73cb3e8e3765a 100644 (file)
@@ -51,6 +51,8 @@ enum {
        COL_INODE,
        COL_INET_LADDR,
        COL_INET_RADDR,
+       COL_INET6_LADDR,
+       COL_INET6_RADDR,
        COL_KNAME,
        COL_KTHREAD,
        COL_MAJMIN,