diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:40:15 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:40:15 +0000 |
commit | 399644e47874bff147afb19c89228901ac39340e (patch) | |
tree | 1c4c0b733f4c16b5783b41bebb19194a9ef62ad1 /man7/sock_diag.7 | |
parent | Initial commit. (diff) | |
download | manpages-upstream/6.05.01.tar.xz manpages-upstream/6.05.01.zip |
Adding upstream version 6.05.01.upstream/6.05.01
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'man7/sock_diag.7')
-rw-r--r-- | man7/sock_diag.7 | 825 |
1 files changed, 825 insertions, 0 deletions
diff --git a/man7/sock_diag.7 b/man7/sock_diag.7 new file mode 100644 index 0000000..adf47b7 --- /dev/null +++ b/man7/sock_diag.7 @@ -0,0 +1,825 @@ +.\" Copyright (c) 2016 Pavel Emelyanov <xemul@virtuozzo.com> +.\" Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org> +.\" +.\" SPDX-License-Identifier: GPL-2.0-or-later +.TH sock_diag 7 2023-05-03 "Linux man-pages 6.05.01" +.SH NAME +sock_diag \- obtaining information about sockets +.SH SYNOPSIS +.nf +.B #include <sys/socket.h> +.B #include <linux/sock_diag.h> +.BR "#include <linux/unix_diag.h>" " /* for UNIX domain sockets */" +.BR "#include <linux/inet_diag.h>" " /* for IPv4 and IPv6 sockets */" +.PP +.BI "diag_socket = socket(AF_NETLINK, " socket_type ", NETLINK_SOCK_DIAG);" +.fi +.SH DESCRIPTION +The sock_diag netlink subsystem provides a mechanism for obtaining +information about sockets of various address families from the kernel. +This subsystem can be used to obtain information about individual +sockets or request a list of sockets. +.PP +In the request, the caller can specify additional information it would +like to obtain about the socket, for example, memory information or +information specific to the address family. +.PP +When requesting a list of sockets, the caller can specify filters that +would be applied by the kernel to select a subset of sockets to report. +For now, there is only the ability to filter sockets by state (connected, +listening, and so on.) +.PP +Note that sock_diag reports only those sockets that have a name; +that is, either sockets bound explicitly with +.BR bind (2) +or sockets that were automatically bound to an address (e.g., by +.BR connect (2)). +This is the same set of sockets that is available via +.IR /proc/net/unix , +.IR /proc/net/tcp , +.IR /proc/net/udp , +and so on. +.\" +.SS Request +The request starts with a +.I "struct nlmsghdr" +header described in +.BR netlink (7) +with +.I nlmsg_type +field set to +.BR SOCK_DIAG_BY_FAMILY . +It is followed by a header specific to the address family that starts with +a common part shared by all address families: +.PP +.in +4n +.EX +struct sock_diag_req { + __u8 sdiag_family; + __u8 sdiag_protocol; +}; +.EE +.in +.PP +The fields of this structure are as follows: +.TP +.I sdiag_family +An address family. +It should be set to the appropriate +.B AF_* +constant. +.TP +.I sdiag_protocol +Depends on +.IR sdiag_family . +It should be set to the appropriate +.B IPPROTO_* +constant for +.B AF_INET +and +.BR AF_INET6 , +and to 0 otherwise. +.PP +If the +.I nlmsg_flags +field of the +.I "struct nlmsghdr" +header has the +.B NLM_F_DUMP +flag set, it means that a list of sockets is being requested; +otherwise it is a query about an individual socket. +.\" +.SS Response +The response starts with a +.I "struct nlmsghdr" +header and is followed by an array of objects specific to the address family. +The array is to be accessed with the standard +.B NLMSG_* +macros from the +.BR netlink (3) +API. +.PP +Each object is the NLA (netlink attributes) list that is to be accessed +with the +.B RTA_* +macros from +.BR rtnetlink (3) +API. +.\" +.SS UNIX domain sockets +For UNIX domain sockets the request is represented in the following structure: +.PP +.in +4n +.EX +struct unix_diag_req { + __u8 sdiag_family; + __u8 sdiag_protocol; + __u16 pad; + __u32 udiag_states; + __u32 udiag_ino; + __u32 udiag_show; + __u32 udiag_cookie[2]; +}; +.EE +.in +.PP +The fields of this structure are as follows: +.TP +.I sdiag_family +The address family; it should be set to +.BR AF_UNIX . +.PP +.I sdiag_protocol +.PD 0 +.TP +.PD +.I pad +These fields should be set to 0. +.TP +.I udiag_states +This is a bit mask that defines a filter of sockets states. +Only those sockets whose states are in this mask will be reported. +Ignored when querying for an individual socket. +Supported values are: +.PP +.RS 12 +1 << +.B TCP_ESTABLISHED +.PP +1 << +.B TCP_LISTEN +.RE +.TP +.I udiag_ino +This is an inode number when querying for an individual socket. +Ignored when querying for a list of sockets. +.TP +.I udiag_show +This is a set of flags defining what kind of information to report. +Each requested kind of information is reported back as a netlink +attribute as described below: +.RS +.TP +.B UDIAG_SHOW_NAME +The attribute reported in answer to this request is +.BR UNIX_DIAG_NAME . +The payload associated with this attribute is the pathname to which +the socket was bound (a sequence of bytes up to +.B UNIX_PATH_MAX +length). +.TP +.B UDIAG_SHOW_VFS +The attribute reported in answer to this request is +.BR UNIX_DIAG_VFS . +The payload associated with this attribute is represented in the following +structure: +.IP +.in +4n +.EX +struct unix_diag_vfs { + __u32 udiag_vfs_dev; + __u32 udiag_vfs_ino; +}; +.EE +.in +.IP +The fields of this structure are as follows: +.RS +.TP +.I udiag_vfs_dev +The device number of the corresponding on-disk socket inode. +.TP +.I udiag_vfs_ino +The inode number of the corresponding on-disk socket inode. +.RE +.TP +.B UDIAG_SHOW_PEER +The attribute reported in answer to this request is +.BR UNIX_DIAG_PEER . +The payload associated with this attribute is a __u32 value +which is the peer's inode number. +This attribute is reported for connected sockets only. +.TP +.B UDIAG_SHOW_ICONS +The attribute reported in answer to this request is +.BR UNIX_DIAG_ICONS . +The payload associated with this attribute is an array of __u32 values +which are inode numbers of sockets that has passed the +.BR connect (2) +call, but hasn't been processed with +.BR accept (2) +yet. +This attribute is reported for listening sockets only. +.TP +.B UDIAG_SHOW_RQLEN +The attribute reported in answer to this request is +.BR UNIX_DIAG_RQLEN . +The payload associated with this attribute is represented in the following +structure: +.IP +.in +4n +.EX +struct unix_diag_rqlen { + __u32 udiag_rqueue; + __u32 udiag_wqueue; +}; +.EE +.in +.IP +The fields of this structure are as follows: +.RS +.TP +.I udiag_rqueue +For listening sockets: +the number of pending connections. +The length of the array associated with the +.B UNIX_DIAG_ICONS +response attribute is equal to this value. +.IP +For established sockets: +the amount of data in incoming queue. +.TP +.I udiag_wqueue +For listening sockets: +the backlog length which equals to the value passed as the second argument to +.BR listen (2). +.IP +For established sockets: +the amount of memory available for sending. +.RE +.TP +.B UDIAG_SHOW_MEMINFO +The attribute reported in answer to this request is +.BR UNIX_DIAG_MEMINFO . +The payload associated with this attribute is an array of __u32 values +described below in the subsection "Socket memory information". +.PP +The following attributes are reported back without any specific request: +.TP +.B UNIX_DIAG_SHUTDOWN +The payload associated with this attribute is __u8 value which represents +bits of +.BR shutdown (2) +state. +.RE +.TP +.I udiag_cookie +This is an array of opaque identifiers that could be used along with +.I udiag_ino +to specify an individual socket. +It is ignored when querying for a list +of sockets, as well as when all its elements are set to \-1. +.PP +The response to a query for UNIX domain sockets is represented as an array of +.PP +.in +4n +.EX +struct unix_diag_msg { + __u8 udiag_family; + __u8 udiag_type; + __u8 udiag_state; + __u8 pad; + __u32 udiag_ino; + __u32 udiag_cookie[2]; +}; +.EE +.in +.PP +followed by netlink attributes. +.PP +The fields of this structure are as follows: +.TP +.I udiag_family +This field has the same meaning as in +.IR "struct unix_diag_req" . +.TP +.I udiag_type +This is set to one of +.BR SOCK_PACKET , +.BR SOCK_STREAM , +or +.BR SOCK_SEQPACKET . +.TP +.I udiag_state +This is set to one of +.B TCP_LISTEN +or +.BR TCP_ESTABLISHED . +.TP +.I pad +This field is set to 0. +.TP +.I udiag_ino +This is the socket inode number. +.TP +.I udiag_cookie +This is an array of opaque identifiers that could be used in subsequent +queries. +.\" +.SS IPv4 and IPv6 sockets +For IPv4 and IPv6 sockets, +the request is represented in the following structure: +.PP +.in +4n +.EX +struct inet_diag_req_v2 { + __u8 sdiag_family; + __u8 sdiag_protocol; + __u8 idiag_ext; + __u8 pad; + __u32 idiag_states; + struct inet_diag_sockid id; +}; +.EE +.in +.PP +where +.I "struct inet_diag_sockid" +is defined as follows: +.PP +.in +4n +.EX +struct inet_diag_sockid { + __be16 idiag_sport; + __be16 idiag_dport; + __be32 idiag_src[4]; + __be32 idiag_dst[4]; + __u32 idiag_if; + __u32 idiag_cookie[2]; +}; +.EE +.in +.PP +The fields of +.I "struct inet_diag_req_v2" +are as follows: +.TP +.I sdiag_family +This should be set to either +.B AF_INET +or +.B AF_INET6 +for IPv4 or IPv6 sockets respectively. +.TP +.I sdiag_protocol +This should be set to one of +.BR IPPROTO_TCP , +.BR IPPROTO_UDP , +or +.BR IPPROTO_UDPLITE . +.TP +.I idiag_ext +This is a set of flags defining what kind of extended information to report. +Each requested kind of information is reported back as a netlink attribute +as described below: +.RS +.TP +.B INET_DIAG_TOS +The payload associated with this attribute is a __u8 value +which is the TOS of the socket. +.TP +.B INET_DIAG_TCLASS +The payload associated with this attribute is a __u8 value +which is the TClass of the socket. +IPv6 sockets only. +For LISTEN and CLOSE sockets, this is followed by +.B INET_DIAG_SKV6ONLY +attribute with associated __u8 payload value meaning whether the socket +is IPv6-only or not. +.TP +.B INET_DIAG_MEMINFO +The payload associated with this attribute is represented in the following +structure: +.IP +.in +4n +.EX +struct inet_diag_meminfo { + __u32 idiag_rmem; + __u32 idiag_wmem; + __u32 idiag_fmem; + __u32 idiag_tmem; +}; +.EE +.in +.IP +The fields of this structure are as follows: +.RS +.TP 12 +.I idiag_rmem +The amount of data in the receive queue. +.TP +.I idiag_wmem +The amount of data that is queued by TCP but not yet sent. +.TP +.I idiag_fmem +The amount of memory scheduled for future use (TCP only). +.TP +.I idiag_tmem +The amount of data in send queue. +.RE +.TP +.B INET_DIAG_SKMEMINFO +The payload associated with this attribute is an array of __u32 values +described below in the subsection "Socket memory information". +.TP +.B INET_DIAG_INFO +The payload associated with this attribute is specific to the address family. +For TCP sockets, it is an object of type +.IR "struct tcp_info" . +.TP +.B INET_DIAG_CONG +The payload associated with this attribute is a string that describes the +congestion control algorithm used. +For TCP sockets only. +.RE +.TP +.I pad +This should be set to 0. +.TP +.I idiag_states +This is a bit mask that defines a filter of socket states. +Only those sockets whose states are in this mask will be reported. +Ignored when querying for an individual socket. +.TP +.I id +This is a socket ID object that is used in dump requests, in queries +about individual sockets, and is reported back in each response. +Unlike UNIX domain sockets, IPv4 and IPv6 sockets are identified +using addresses and ports. +All values are in network byte order. +.PP +The fields of +.I "struct inet_diag_sockid" +are as follows: +.TP +.I idiag_sport +The source port. +.TP +.I idiag_dport +The destination port. +.TP +.I idiag_src +The source address. +.TP +.I idiag_dst +The destination address. +.TP +.I idiag_if +The interface number the socket is bound to. +.TP +.I idiag_cookie +This is an array of opaque identifiers that could be used along with +other fields of this structure to specify an individual socket. +It is ignored when querying for a list of sockets, as well as +when all its elements are set to \-1. +.PP +The response to a query for IPv4 or IPv6 sockets is represented as an array of +.PP +.in +4n +.EX +struct inet_diag_msg { + __u8 idiag_family; + __u8 idiag_state; + __u8 idiag_timer; + __u8 idiag_retrans; +\& + struct inet_diag_sockid id; +\& + __u32 idiag_expires; + __u32 idiag_rqueue; + __u32 idiag_wqueue; + __u32 idiag_uid; + __u32 idiag_inode; +}; +.EE +.in +.PP +followed by netlink attributes. +.PP +The fields of this structure are as follows: +.TP +.I idiag_family +This is the same field as in +.IR "struct inet_diag_req_v2" . +.TP +.I idiag_state +This denotes socket state as in +.IR "struct inet_diag_req_v2" . +.TP +.I idiag_timer +For TCP sockets, this field describes the type of timer that is currently +active for the socket. +It is set to one of the following constants: +.IP +.PD 0 +.RS 12 +.TP +.B 0 +no timer is active +.TP +.B 1 +a retransmit timer +.TP +.B 2 +a keep-alive timer +.TP +.B 3 +a TIME_WAIT timer +.TP +.B 4 +a zero window probe timer +.RE +.PD +.IP +For non-TCP sockets, this field is set to 0. +.TP +.I idiag_retrans +For +.I idiag_timer +values 1, 2, and 4, this field contains the number of retransmits. +For other +.I idiag_timer +values, this field is set to 0. +.TP +.I idiag_expires +For TCP sockets that have an active timer, this field describes its expiration +time in milliseconds. +For other sockets, this field is set to 0. +.TP +.I idiag_rqueue +For listening sockets: +the number of pending connections. +.IP +For other sockets: +the amount of data in the incoming queue. +.TP +.I idiag_wqueue +For listening sockets: +the backlog length. +.IP +For other sockets: +the amount of memory available for sending. +.TP +.I idiag_uid +This is the socket owner UID. +.TP +.I idiag_inode +This is the socket inode number. +.\" +.SS Socket memory information +The payload associated with +.B UNIX_DIAG_MEMINFO +and +.B INET_DIAG_SKMEMINFO +netlink attributes is an array of the following __u32 values: +.TP +.B SK_MEMINFO_RMEM_ALLOC +The amount of data in receive queue. +.TP +.B SK_MEMINFO_RCVBUF +The receive socket buffer as set by +.BR SO_RCVBUF . +.TP +.B SK_MEMINFO_WMEM_ALLOC +The amount of data in send queue. +.TP +.B SK_MEMINFO_SNDBUF +The send socket buffer as set by +.BR SO_SNDBUF . +.TP +.B SK_MEMINFO_FWD_ALLOC +The amount of memory scheduled for future use (TCP only). +.TP +.B SK_MEMINFO_WMEM_QUEUED +The amount of data queued by TCP, but not yet sent. +.TP +.B SK_MEMINFO_OPTMEM +The amount of memory allocated for the socket's service needs (e.g., socket +filter). +.TP +.B SK_MEMINFO_BACKLOG +The amount of packets in the backlog (not yet processed). +.SH VERSIONS +.B NETLINK_INET_DIAG +was introduced in Linux 2.6.14 and supported +.B AF_INET +and +.B AF_INET6 +sockets only. +In Linux 3.3, it was renamed to +.B NETLINK_SOCK_DIAG +and extended to support +.B AF_UNIX +sockets. +.PP +.B UNIX_DIAG_MEMINFO +and +.B INET_DIAG_SKMEMINFO +were introduced in Linux 3.6. +.SH STANDARDS +Linux. +.SH EXAMPLES +The following example program prints inode number, peer's inode number, +and name of all UNIX domain sockets in the current namespace. +.PP +.EX +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> +#include <linux/sock_diag.h> +#include <linux/unix_diag.h> +\& +static int +send_query(int fd) +{ + struct sockaddr_nl nladdr = { + .nl_family = AF_NETLINK + }; + struct + { + struct nlmsghdr nlh; + struct unix_diag_req udr; + } req = { + .nlh = { + .nlmsg_len = sizeof(req), + .nlmsg_type = SOCK_DIAG_BY_FAMILY, + .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP + }, + .udr = { + .sdiag_family = AF_UNIX, + .udiag_states = \-1, + .udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER + } + }; + struct iovec iov = { + .iov_base = &req, + .iov_len = sizeof(req) + }; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1 + }; +\& + for (;;) { + if (sendmsg(fd, &msg, 0) < 0) { + if (errno == EINTR) + continue; +\& + perror("sendmsg"); + return \-1; + } +\& + return 0; + } +} +\& +static int +print_diag(const struct unix_diag_msg *diag, unsigned int len) +{ + if (len < NLMSG_LENGTH(sizeof(*diag))) { + fputs("short response\en", stderr); + return \-1; + } + if (diag\->udiag_family != AF_UNIX) { + fprintf(stderr, "unexpected family %u\en", diag\->udiag_family); + return \-1; + } +\& + unsigned int rta_len = len \- NLMSG_LENGTH(sizeof(*diag)); + unsigned int peer = 0; + size_t path_len = 0; + char path[sizeof(((struct sockaddr_un *) 0)\->sun_path) + 1]; +\& + for (struct rtattr *attr = (struct rtattr *) (diag + 1); + RTA_OK(attr, rta_len); attr = RTA_NEXT(attr, rta_len)) { + switch (attr\->rta_type) { + case UNIX_DIAG_NAME: + if (!path_len) { + path_len = RTA_PAYLOAD(attr); + if (path_len > sizeof(path) \- 1) + path_len = sizeof(path) \- 1; + memcpy(path, RTA_DATA(attr), path_len); + path[path_len] = \[aq]\e0\[aq]; + } + break; +\& + case UNIX_DIAG_PEER: + if (RTA_PAYLOAD(attr) >= sizeof(peer)) + peer = *(unsigned int *) RTA_DATA(attr); + break; + } + } +\& + printf("inode=%u", diag\->udiag_ino); +\& + if (peer) + printf(", peer=%u", peer); +\& + if (path_len) + printf(", name=%s%s", *path ? "" : "@", + *path ? path : path + 1); +\& + putchar(\[aq]\en\[aq]); + return 0; +} +\& +static int +receive_responses(int fd) +{ + long buf[8192 / sizeof(long)]; + struct sockaddr_nl nladdr; + struct iovec iov = { + .iov_base = buf, + .iov_len = sizeof(buf) + }; + int flags = 0; +\& + for (;;) { + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1 + }; +\& + ssize_t ret = recvmsg(fd, &msg, flags); +\& + if (ret < 0) { + if (errno == EINTR) + continue; +\& + perror("recvmsg"); + return \-1; + } + if (ret == 0) + return 0; +\& + if (nladdr.nl_family != AF_NETLINK) { + fputs("!AF_NETLINK\en", stderr); + return \-1; + } +\& + const struct nlmsghdr *h = (struct nlmsghdr *) buf; +\& + if (!NLMSG_OK(h, ret)) { + fputs("!NLMSG_OK\en", stderr); + return \-1; + } +\& + for (; NLMSG_OK(h, ret); h = NLMSG_NEXT(h, ret)) { + if (h\->nlmsg_type == NLMSG_DONE) + return 0; +\& + if (h\->nlmsg_type == NLMSG_ERROR) { + const struct nlmsgerr *err = NLMSG_DATA(h); +\& + if (h\->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) { + fputs("NLMSG_ERROR\en", stderr); + } else { + errno = \-err\->error; + perror("NLMSG_ERROR"); + } +\& + return \-1; + } +\& + if (h\->nlmsg_type != SOCK_DIAG_BY_FAMILY) { + fprintf(stderr, "unexpected nlmsg_type %u\en", + (unsigned) h\->nlmsg_type); + return \-1; + } +\& + if (print_diag(NLMSG_DATA(h), h\->nlmsg_len)) + return \-1; + } + } +} +\& +int +main(void) +{ + int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG); +\& + if (fd < 0) { + perror("socket"); + return 1; + } +\& + int ret = send_query(fd) || receive_responses(fd); +\& + close(fd); + return ret; +} +.EE +.SH SEE ALSO +.BR netlink (3), +.BR rtnetlink (3), +.BR netlink (7), +.BR tcp (7) |