]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsfd: use extra information loaded from /proc/net/udp
authorMasatake YAMATO <yamato@redhat.com>
Mon, 17 Oct 2022 18:11:44 +0000 (03:11 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Wed, 19 Oct 2022 20:15:09 +0000 (05:15 +0900)
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
misc-utils/lsfd-sock-xinfo.c
misc-utils/lsfd.1.adoc
misc-utils/lsfd.c
misc-utils/lsfd.h

index 2000e25a4a827cc104fc77fc5f0c263d9017f584..3d1625b6b65855d06c28d5fd8f14e54f1300fce2 100644 (file)
@@ -37,6 +37,7 @@
 
 static void load_xinfo_from_proc_unix(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 int self_netns_fd = -1;
 struct stat self_netns_sb;
@@ -74,6 +75,7 @@ static void load_sock_xinfo_no_nsswitch(ino_t netns)
 {
        load_xinfo_from_proc_unix(netns);
        load_xinfo_from_proc_tcp(netns);
+       load_xinfo_from_proc_udp(netns);
 }
 
 static void load_sock_xinfo_with_fd(int fd, ino_t netns)
@@ -532,56 +534,58 @@ static bool tcp_get_listening(struct sock_xinfo *sock_xinfo,
        return tcp->st == TCP_LISTEN;
 }
 
-static bool tcp_fill_column(struct proc *proc,
-                           struct sock_xinfo *sock_xinfo,
-                           struct sock *sock,
-                           struct libscols_line *ln,
-                           int column_id,
-                           size_t column_index,
-                           char **str)
-{
-       struct tcp_xinfo *tcp = (struct tcp_xinfo *)sock_xinfo;
-       struct inet_xinfo *inet = (struct inet_xinfo *)sock_xinfo;
-       struct in_addr n;
-       bool has_laddr = false;
-       char s[INET_ADDRSTRLEN];
-       unsigned int p;
-       bool has_lport = false;
-
-       if (inet_fill_column(proc, (struct inet_xinfo *)sock_xinfo, sock, ln,
-                            column_id, column_index, str))
-               return true;
-
-       switch(column_id) {
-       case COL_TCP_LADDR:
-               n.s_addr = inet->local_addr;
-               has_laddr = true;
-               p = (unsigned int)tcp->local_port;
-               /* FALL THROUGH */
-       case COL_TCP_RADDR:
-               if (!has_laddr) {
-                       n.s_addr = inet->remote_addr;
-                       p = (unsigned int)tcp->remote_port;
-               }
-               if (inet_ntop(AF_INET, &n, s, sizeof(s)))
-                       xasprintf(str, "%s:%u", s, p);
-               break;
-       case COL_TCP_LPORT:
-               p = (unsigned int)tcp->local_port;
-               has_lport = true;
-               /* FALL THROUGH */
-       case COL_TCP_RPORT:
-               if (!has_lport)
-                       p = (unsigned int)tcp->remote_port;
-               xasprintf(str, "%u", p);
-               break;
-       default:
-               return false;
+#define define_fill_column_func(l3,L3)                                 \
+       static bool l3##_fill_column(struct proc *proc,                 \
+                                    struct sock_xinfo *sock_xinfo,     \
+                                    struct sock *sock,                 \
+                                    struct libscols_line *ln,          \
+                                    int column_id,                     \
+                                    size_t column_index,               \
+                                    char **str)                        \
+       {                                                               \
+               struct tcp_xinfo *tcp = (struct tcp_xinfo *)sock_xinfo; \
+               struct inet_xinfo *inet = (struct inet_xinfo *)sock_xinfo; \
+               struct in_addr n;                                       \
+               bool has_laddr = false;                                 \
+               char s[INET_ADDRSTRLEN];                                \
+               unsigned int p;                                         \
+               bool has_lport = false;                                 \
+                                                                       \
+               if (inet_fill_column(proc, (struct inet_xinfo *)sock_xinfo, sock, ln, \
+                                    column_id, column_index, str))     \
+                       return true;                                    \
+                                                                       \
+               switch(column_id) {                                     \
+               case COL_##L3##_LADDR:                                  \
+                       n.s_addr = inet->local_addr;                    \
+                       has_laddr = true;                               \
+                       p = (unsigned int)tcp->local_port;              \
+                       /* FALL THROUGH */                              \
+               case COL_##L3##_RADDR:                                  \
+                       if (!has_laddr) {                               \
+                               n.s_addr = inet->remote_addr;           \
+                               p = (unsigned int)tcp->remote_port;     \
+                       }                                               \
+                       if (inet_ntop(AF_INET, &n, s, sizeof(s)))       \
+                               xasprintf(str, "%s:%u", s, p);          \
+                       break;                                          \
+               case COL_##L3##_LPORT:                                  \
+                       p = (unsigned int)tcp->local_port;              \
+                       has_lport = true;                               \
+                       /* FALL THROUGH */                              \
+               case COL_##L3##_RPORT:                                  \
+                       if (!has_lport)                                 \
+                               p = (unsigned int)tcp->remote_port;     \
+                       xasprintf(str, "%u", p);                        \
+                       break;                                          \
+               default:                                                \
+                       return false;                                   \
+               }                                                       \
+                                                                       \
+               return true;                                            \
        }
 
-       return true;
-}
-
+define_fill_column_func(tcp, TCP);
 static struct sock_xinfo_class tcp_xinfo_class = {
        .class = "tcp",
        .get_name = tcp_get_name,
@@ -593,19 +597,20 @@ static struct sock_xinfo_class tcp_xinfo_class = {
 };
 
 #define TCP_LINE_LEN 256
-static void load_xinfo_from_proc_tcp(ino_t netns_inode)
+static void load_xinfo_from_proc_inet_L3(ino_t netns_inode, const char *proc_file,
+                                        bool (*verify_initial_line)(const char *),
+                                        struct sock_xinfo_class *class)
 {
        char line[TCP_LINE_LEN];
        FILE *tcp_fp;
 
-       tcp_fp = fopen("/proc/net/tcp", "r");
+       tcp_fp = fopen(proc_file, "r");
        if (!tcp_fp)
                return;
 
        if (fgets(line, sizeof(line), tcp_fp) == NULL)
                goto out;
-       if (!(line[0] == ' ' && line[1] == ' '
-             && line[2] == 's' && line[3] == 'l'))
+       if (!verify_initial_line(line))
                /* Unexpected line */
                goto out;
 
@@ -631,7 +636,7 @@ static void load_xinfo_from_proc_tcp(ino_t netns_inode)
                tcp = xmalloc(sizeof(struct tcp_xinfo));
                inet = (struct inet_xinfo *)tcp;
                sock = (struct sock_xinfo *)inet;
-               sock->class = &tcp_xinfo_class;
+               sock->class = class;
                sock->inode = (ino_t)inode;
                sock->netns_inode = netns_inode;
                inet->local_addr = local_addr;
@@ -646,3 +651,77 @@ static void load_xinfo_from_proc_tcp(ino_t netns_inode)
  out:
        fclose(tcp_fp);
 }
+
+static bool tcp_verify_initial_line(const char *line)
+{
+       return (line[0] == ' ' && line[1] == ' '
+               && line[2] == 's' && line[3] == 'l');
+}
+
+static void load_xinfo_from_proc_tcp(ino_t netns_inode)
+{
+       load_xinfo_from_proc_inet_L3(netns_inode,
+                                    "/proc/net/tcp", tcp_verify_initial_line,
+                                    &tcp_xinfo_class);
+}
+
+/*
+ * UDP
+ */
+static char *udp_get_name(struct sock_xinfo *sock_xinfo,
+                         struct sock *sock  __attribute__((__unused__)))
+{
+       char *str = NULL;
+       struct inet_xinfo *inet = ((struct inet_xinfo *)sock_xinfo);
+       struct tcp_xinfo *tcp = ((struct tcp_xinfo *)sock_xinfo);
+       struct in_addr local_n, remote_n;
+       char local_s[INET_ADDRSTRLEN], remote_s[INET_ADDRSTRLEN];
+
+       local_n.s_addr = inet->local_addr;
+       remote_n.s_addr = inet->remote_addr;
+       if (!inet_ntop(AF_INET, &local_n, local_s, sizeof(local_s)))
+               xasprintf(&str, "state=%s", tcp_decode_state(tcp->st));
+       else if ((remote_n.s_addr == 0 && tcp->remote_port == 0)
+                || !inet_ntop(AF_INET, &remote_n, remote_s, sizeof(remote_s)))
+               xasprintf(&str, "state=%s laddr=%s:%u",
+                         tcp_decode_state(tcp->st),
+                         local_s, tcp->local_port);
+       else
+               xasprintf(&str, "state=%s laddr=%s:%u raddr=%s:%u",
+                         tcp_decode_state(tcp->st),
+                         local_s, tcp->local_port,
+                         remote_s, tcp->remote_port);
+       return str;
+}
+
+static char *udp_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)),
+                         struct sock *sock __attribute__((__unused__)))
+{
+       return strdup("dgram");
+}
+
+define_fill_column_func(udp, UDP);
+static struct sock_xinfo_class udp_xinfo_class = {
+       .class = "udp",
+       .get_name = udp_get_name,
+       .get_type = udp_get_type,
+       .get_state = tcp_get_state,
+       .get_listening = NULL,
+       .fill_column = udp_fill_column,
+       .free = NULL,
+};
+
+static bool udp_verify_initial_line(const char *line)
+{
+       return (line[0] == ' ' && line[1] == ' ' && line[2] == ' '
+               && line[3] == 's' && line[4] == 'l');
+}
+
+
+static void load_xinfo_from_proc_udp(ino_t netns_inode)
+{
+       load_xinfo_from_proc_inet_L3(netns_inode,
+                                    "/proc/net/udp",
+                                    udp_verify_initial_line,
+                                    &udp_xinfo_class);
+}
index 5bf8dee7b61e1b0d0907883728d5a4933cd90430..ce833a5a9858f1185cfa85a908f262b826db2984 100644 (file)
@@ -214,6 +214,11 @@ pid=_TARGET-PID_ comm=_TARGET-COMMAND_ nspid=_TARGET-NSPIDS_
 TCP:::
 state=_SOCK.STATE_[ laddr=_TCP.LADDR_:_TCP.LPORT_ [ raddr=_TCP.RADDR_:_TCP.RPORT_]]
 +
+UDP:::
+state=_SOCK.STATE_[ laddr=_UDP.LADDR_:_UDP.LPORT_ [ raddr=_UDP.RADDR_:_UDP.RPORT_]]
++
+*lsfd* hides ``raddr=`` if _UDP.RADDR_ is ``0.0.0.0`` and _UDP.RPORT_ is 0.
++
 UNIX-STREAM:::
 state=_SOCK.STATE_[ path=_UNIX.PATH_]
 +
@@ -313,6 +318,18 @@ Cooked version of STTYPE. It is same as STTYPE with exceptions.
 For SOCK, print the value for SOCK.PROTONAME.
 For UNKN, print the value for AINODECLASS if SOURCE is anon_inodefs.
 
+UDP.LADDR <``string``>::
+Local IP address and local UDP port.
+
+UDP.LPORT <``integer``>::
+Local UDP port.
+
+UDP.RADDR <``string``>::
+Remote IP address and remote UDP port.
+
+UDP.RPORT <``integer``>::
+Remote UDP port.
+
 UID <``number``>::
 User ID number.
 
index b109c1a9f3dae2b7ee0fe68f6d591e7186844b87..a7e88aea4cacc6d1d2b10111032a92a036d644df 100644 (file)
@@ -213,6 +213,14 @@ static struct colinfo infos[] = {
                N_("thread ID of the process opening the file") },
        [COL_TYPE]    = { "TYPE",     0, SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
                N_("file type (cooked)") },
+       [COL_UDP_LADDR]={ "UDP.LADDR",0, SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
+               N_("local UDP address (INET address:UDP port)") },
+       [COL_UDP_RADDR]={"UDP.RADDR", 0, SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
+               N_("remote UDP address (INET address:UDP port)") },
+       [COL_UDP_LPORT]={"UDP.LPORT", 0, SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER,
+               N_("local UDP port") },
+       [COL_UDP_RPORT]={"UDP.RPORT", 0, SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER,
+               N_("remote UDP port") },
        [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,
index 3c15cbf99cac7ab59bedb36a7b252e3a3f154cdc..ccf33ae41ce04dc933617f2cfa094cfa7b8a2390 100644 (file)
@@ -81,6 +81,10 @@ enum {
        COL_TCP_RPORT,
        COL_TID,
        COL_TYPE,
+       COL_UDP_LADDR,
+       COL_UDP_RADDR,
+       COL_UDP_LPORT,
+       COL_UDP_RPORT,
        COL_UID,                /* process */
        COL_UNIX_PATH,
        COL_USER,               /* process */