From adfc156a57c24893db72bee32909c8ca1cf50fff Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 2 Mar 2023 16:45:59 +0900 Subject: [PATCH] lsfd: use extra information loaded from /proc/net/packet Signed-off-by: Masatake YAMATO --- misc-utils/lsfd-sock-xinfo.c | 405 +++++++++++++++++++++++++++++++++++ misc-utils/lsfd.1.adoc | 9 + misc-utils/lsfd.c | 6 + misc-utils/lsfd.h | 2 + 4 files changed, 422 insertions(+) diff --git a/misc-utils/lsfd-sock-xinfo.c b/misc-utils/lsfd-sock-xinfo.c index a305de6b51..3a11b75f00 100644 --- a/misc-utils/lsfd-sock-xinfo.c +++ b/misc-utils/lsfd-sock-xinfo.c @@ -24,6 +24,7 @@ #include /* getifaddrs */ #include /* SCNu16 */ #include /* if_nametoindex */ +#include /* ETH_P_* */ #include /* SS_* */ #include /* NETLINK_* */ #include /* UNIX_PATH_MAX */ @@ -54,6 +55,7 @@ static void load_xinfo_from_proc_udp6(ino_t netns_inode); static void load_xinfo_from_proc_udplite6(ino_t netns_inode); static void load_xinfo_from_proc_raw6(ino_t netns_inode); static void load_xinfo_from_proc_netlink(ino_t netns_inode); +static void load_xinfo_from_proc_packet(ino_t netns_inode); static int self_netns_fd = -1; static struct stat self_netns_sb; @@ -167,6 +169,7 @@ static void load_sock_xinfo_no_nsswitch(struct netns *nsobj) load_xinfo_from_proc_icmp(netns); load_xinfo_from_proc_icmp6(netns); load_xinfo_from_proc_netlink(netns); + load_xinfo_from_proc_packet(netns); if (nsobj) load_ifaces_from_getifaddrs(nsobj); @@ -1615,3 +1618,405 @@ static void load_xinfo_from_proc_netlink(ino_t netns_inode) out: fclose(netlink_fp); } + +/* + * PACKET + */ +struct packet_xinfo { + struct sock_xinfo sock; + uint16_t type; + uint16_t protocol; + unsigned int iface; +}; + +static const char *packet_decode_protocol(uint16_t proto) +{ + switch (proto) { + case 0: + return NULL; + case ETH_P_802_3: + return "802_3"; + case ETH_P_AX25: + return "ax25"; + case ETH_P_ALL: + return "all"; + case ETH_P_802_2: + return "802_2"; + case ETH_P_SNAP: + return "snap"; + case ETH_P_DDCMP: + return "ddcmp"; + case ETH_P_WAN_PPP: + return "wan_ppp"; + case ETH_P_PPP_MP: + return "ppp_mp"; + case ETH_P_LOCALTALK: + return "localtalk"; + case ETH_P_CAN: + return "can"; + case ETH_P_CANFD: + return "canfd"; +#ifdef ETH_P_CANXL + case ETH_P_CANXL: + return "canxl"; +#endif + case ETH_P_PPPTALK: + return "ppptalk"; + case ETH_P_TR_802_2: + return "tr_802_2"; + case ETH_P_MOBITEX: + return "mobitex"; + case ETH_P_CONTROL: + return "control"; + case ETH_P_IRDA: + return "irda"; + case ETH_P_ECONET: + return "econet"; + case ETH_P_HDLC: + return "hdlc"; + case ETH_P_ARCNET: + return "arcnet"; + case ETH_P_DSA: + return "dsa"; + case ETH_P_TRAILER: + return "trailer"; + case ETH_P_PHONET: + return "phonet"; + case ETH_P_IEEE802154: + return "ieee802154"; + case ETH_P_CAIF: + return "caif"; +#ifdef ETH_P_XDSA + case ETH_P_XDSA: + return "xdsa"; +#endif +#ifdef ETH_P_MAP + case ETH_P_MAP: + return "map"; +#endif +#ifdef ETH_P_MCTP + case ETH_P_MCTP: + return "mctp"; +#endif + case ETH_P_LOOP: + return "loop"; + case ETH_P_PUP: + return "pup"; + case ETH_P_PUPAT: + return "pupat"; +#ifdef ETH_P_TSN + case ETH_P_TSN: + return "tsn"; +#endif +#ifdef ETH_P_ERSPAN2 + case ETH_P_ERSPAN2: + return "erspan2"; +#endif + case ETH_P_IP: + return "ip"; + case ETH_P_X25: + return "x25"; + case ETH_P_ARP: + return "arp"; + case ETH_P_BPQ: + return "bpq"; + case ETH_P_IEEEPUP: + return "ieeepup"; + case ETH_P_IEEEPUPAT: + return "ieeepupat"; + case ETH_P_BATMAN: + return "batman"; + case ETH_P_DEC: + return "dec"; + case ETH_P_DNA_DL: + return "dna_dl"; + case ETH_P_DNA_RC: + return "dna_rc"; + case ETH_P_DNA_RT: + return "dna_rt"; + case ETH_P_LAT: + return "lat"; + case ETH_P_DIAG: + return "diag"; + case ETH_P_CUST: + return "cust"; + case ETH_P_SCA: + return "sca"; + case ETH_P_TEB: + return "teb"; + case ETH_P_RARP: + return "rarp"; + case ETH_P_ATALK: + return "atalk"; + case ETH_P_AARP: + return "aarp"; + case ETH_P_8021Q: + return "8021q"; +#ifdef ETH_P_ERSPAN + case ETH_P_ERSPAN: + return "erspan"; +#endif + case ETH_P_IPX: + return "ipx"; + case ETH_P_IPV6: + return "ipv6"; + case ETH_P_PAUSE: + return "pause"; + case ETH_P_SLOW: + return "slow"; + case ETH_P_WCCP: + return "wccp"; + case ETH_P_MPLS_UC: + return "mpls_uc"; + case ETH_P_MPLS_MC: + return "mpls_mc"; + case ETH_P_ATMMPOA: + return "atmmpoa"; +#ifdef ETH_P_PPP_DISC + case ETH_P_PPP_DISC: + return "ppp_disc"; +#endif +#ifdef ETH_P_PPP_SES + case ETH_P_PPP_SES: + return "ppp_ses"; +#endif + case ETH_P_LINK_CTL: + return "link_ctl"; + case ETH_P_ATMFATE: + return "atmfate"; + case ETH_P_PAE: + return "pae"; +#ifdef ETH_P_PROFINET + case ETH_P_PROFINET: + return "profinet"; +#endif +#ifdef ETH_P_REALTEK + case ETH_P_REALTEK: + return "realtek"; +#endif + case ETH_P_AOE: + return "aoe"; +#ifdef ETH_P_ETHERCAT + case ETH_P_ETHERCAT: + return "ethercat"; +#endif + case ETH_P_8021AD: + return "8021ad"; + case ETH_P_802_EX1: + return "802_ex1"; +#ifdef ETH_P_PREAUTH + case ETH_P_PREAUTH: + return "preauth"; +#endif + case ETH_P_TIPC: + return "tipc"; +#ifdef ETH_P_LLDP + case ETH_P_LLDP: + return "lldp"; +#endif +#ifdef ETH_P_MRP + case ETH_P_MRP: + return "mrp"; +#endif +#ifdef ETH_P_MACSEC + case ETH_P_MACSEC: + return "macsec"; +#endif + case ETH_P_8021AH: + return "8021ah"; +#ifdef ETH_P_MVRP + case ETH_P_MVRP: + return "mvrp"; +#endif + case ETH_P_1588: + return "1588"; +#ifdef ETH_P_NCSI + case ETH_P_NCSI: + return "ncsi"; +#endif +#ifdef ETH_P_PRP + case ETH_P_PRP: + return "prp"; +#endif +#ifdef ETH_P_CFM + case ETH_P_CFM: + return "cfm"; +#endif + case ETH_P_FCOE: + return "fcoe"; +#ifdef ETH_P_IBOE + case ETH_P_IBOE: + return "iboe"; +#endif + case ETH_P_TDLS: + return "tdls"; + case ETH_P_FIP: + return "fip"; +#ifdef ETH_P_80221 + case ETH_P_80221: + return "80221"; +#endif +#ifdef ETH_P_HSR + case ETH_P_HSR: + return "hsr"; +#endif +#ifdef ETH_P_NSH + case ETH_P_NSH: + return "nsh"; +#endif +#ifdef ETH_P_LOOPBACK + case ETH_P_LOOPBACK: + return "loopback"; +#endif + case ETH_P_QINQ1: + return "qinq1"; + case ETH_P_QINQ2: + return "qinq2"; + case ETH_P_QINQ3: + return "qinq3"; + case ETH_P_EDSA: + return "edsa"; +#ifdef ETH_P_DSA_8021Q + case ETH_P_DSA_8021Q: + return "dsa_8021q"; +#endif +#ifdef ETH_P_DSA_A5PSW + case ETH_P_DSA_A5PSW: + return "dsa_a5psw"; +#endif +#ifdef ETH_P_IFE + case ETH_P_IFE: + return "ife"; +#endif + case ETH_P_AF_IUCV: + return "af_iucv"; +#ifdef ETH_P_802_3_MIN + case ETH_P_802_3_MIN: + return "802_3_min"; +#endif + default: + return "unknown"; + } +} + +static char *packet_get_name(struct sock_xinfo *sock_xinfo, + struct sock *sock __attribute__((__unused__))) +{ + struct packet_xinfo *pkt = (struct packet_xinfo *)sock_xinfo; + char *str = NULL; + const char *type = sock_decode_type(pkt->type); + const char *proto = packet_decode_protocol(pkt->protocol); + const char *iface = get_iface_name(sock_xinfo->netns_inode, + pkt->iface); + + if (iface && proto) + xasprintf(&str, "type=%s protocol=%s iface=%s", + type, proto, iface); + else if (proto) + xasprintf(&str, "type=%s protocol=%s", + type, proto); + else if (iface) + xasprintf(&str, "type=%s iface=%s", + type, iface); + else + xasprintf(&str, "type=%s", type); + + return str; +} + +static char *packet_get_type(struct sock_xinfo *sock_xinfo __attribute__((__unused__)), + struct sock *sock __attribute__((__unused__))) +{ + const char *str; + struct packet_xinfo *pkt = (struct packet_xinfo *)sock_xinfo; + + str = sock_decode_type(pkt->type); + return xstrdup(str); +} + +static bool packet_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 packet_xinfo *pkt = (struct packet_xinfo *)sock_xinfo; + + switch (column_id) { + case COL_PACKET_IFACE: { + const char *iface; + iface = get_iface_name(sock_xinfo->netns_inode, + pkt->iface); + if (iface) { + *str = xstrdup(iface); + return true; + } + break; + } + case COL_PACKET_PROTOCOL: { + const char *proto; + proto = packet_decode_protocol(pkt->protocol); + if (proto) { + *str = xstrdup(proto); + return true; + } + break; + } + default: + break; + } + return false; +} + +static const struct sock_xinfo_class packet_xinfo_class = { + .get_name = packet_get_name, + .get_type = packet_get_type, + .get_state = NULL, + .get_listening = NULL, + .fill_column = packet_fill_column, + .free = NULL, +}; + +static void load_xinfo_from_proc_packet(ino_t netns_inode) +{ + char line[BUFSIZ]; + FILE *packet_fp; + + packet_fp = fopen("/proc/net/packet", "r"); + if (!packet_fp) + return; + + if (fgets(line, sizeof(line), packet_fp) == NULL) + goto out; + if (!(line[0] == 's' && line[1] == 'k')) + /* Unexpected line */ + goto out; + + while (fgets(line, sizeof(line), packet_fp)) { + uint16_t type; + uint16_t protocol; + unsigned int iface; + unsigned long inode; + struct packet_xinfo *pkt; + + if (sscanf(line, "%*x %*d %" SCNu16 " %" SCNu16 " %u %*d %*d %*d %lu", + &type, &protocol, &iface, &inode) < 4) + continue; + + pkt = xcalloc(1, sizeof(*pkt)); + pkt->sock.class = &packet_xinfo_class; + pkt->sock.inode = (ino_t)inode; + pkt->sock.netns_inode = netns_inode; + + pkt->type = type; + pkt->protocol = protocol; + pkt->iface = iface; + + add_sock_info(&pkt->sock); + } + + out: + fclose(packet_fp); +} diff --git a/misc-utils/lsfd.1.adoc b/misc-utils/lsfd.1.adoc index 4c2497e165..d4d40b26a8 100644 --- a/misc-utils/lsfd.1.adoc +++ b/misc-utils/lsfd.1.adoc @@ -217,6 +217,9 @@ Some files have special formats and information sources: NETLINK::: protocol=_NETLINK.PROTOCOL_[ lport=_NETLINK.LPORT_[ group=_NETLINK.GROUPS_]] + +PACKET::: +type=_SOCK.TYPE_[ protocol=_PACKET.PROTOCOL_][ iface=_PACKET.IFACE_] ++ pidfd::: pid=_TARGET-PID_ comm=_TARGET-COMMAND_ nspid=_TARGET-NSPIDS_ + @@ -266,6 +269,12 @@ The type is `mnt`, `cgroup`, `uts`, `ipc`, `user`, `pid`, `net`, OWNER <``string``>:: Owner of the file. +PACKET.IFACE <``string``>:: +Interface name associated with the packet socket. + +PACKET.PROTOCOL <``string``>:: +L3 protocol associated with the packet socket. + PARTITION <``string``>:: Block device name resolved by `/proc/partition`. diff --git a/misc-utils/lsfd.c b/misc-utils/lsfd.c index 184250c39a..27a0ada01b 100644 --- a/misc-utils/lsfd.c +++ b/misc-utils/lsfd.c @@ -216,6 +216,12 @@ static const struct colinfo infos[] = { [COL_OWNER] = { "OWNER", 0, SCOLS_FL_RIGHT, SCOLS_JSON_STRING, N_("owner of the file") }, + [COL_PACKET_IFACE] = { "PACKET.IFACE", + 0, SCOLS_FL_RIGHT,SCOLS_JSON_STRING, + N_("net interface associated with the packet socket") }, + [COL_PACKET_PROTOCOL] = { "PACKET.PROTOCOL", + 0, SCOLS_FL_RIGHT,SCOLS_JSON_STRING, + N_("L3 protocol associated with the packet socket") }, [COL_PARTITION] = { "PARTITION", 0, SCOLS_FL_RIGHT, SCOLS_JSON_STRING, N_("block device name resolved by /proc/partition") }, diff --git a/misc-utils/lsfd.h b/misc-utils/lsfd.h index d6b22e36e0..ea1c34242f 100644 --- a/misc-utils/lsfd.h +++ b/misc-utils/lsfd.h @@ -67,6 +67,8 @@ enum { COL_NLINK, COL_NS_NAME, COL_NS_TYPE, + COL_PACKET_IFACE, + COL_PACKET_PROTOCOL, COL_PARTITION, COL_PID, COL_PIDFD_COMM, -- 2.47.3