From: Masatake YAMATO Date: Mon, 17 Oct 2022 18:11:44 +0000 (+0900) Subject: lsfd: use extra information loaded from /proc/net/udp X-Git-Tag: v2.39-rc1~472^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=92a0dbce7c779923bd2a6fd7c53470ff6982ea50;p=thirdparty%2Futil-linux.git lsfd: use extra information loaded from /proc/net/udp Signed-off-by: Masatake YAMATO --- diff --git a/misc-utils/lsfd-sock-xinfo.c b/misc-utils/lsfd-sock-xinfo.c index 2000e25a4a..3d1625b6b6 100644 --- a/misc-utils/lsfd-sock-xinfo.c +++ b/misc-utils/lsfd-sock-xinfo.c @@ -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); +} diff --git a/misc-utils/lsfd.1.adoc b/misc-utils/lsfd.1.adoc index 5bf8dee7b6..ce833a5a98 100644 --- a/misc-utils/lsfd.1.adoc +++ b/misc-utils/lsfd.1.adoc @@ -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. diff --git a/misc-utils/lsfd.c b/misc-utils/lsfd.c index b109c1a9f3..a7e88aea4c 100644 --- a/misc-utils/lsfd.c +++ b/misc-utils/lsfd.c @@ -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, diff --git a/misc-utils/lsfd.h b/misc-utils/lsfd.h index 3c15cbf99c..ccf33ae41c 100644 --- a/misc-utils/lsfd.h +++ b/misc-utils/lsfd.h @@ -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 */