summaryrefslogtreecommitdiffstats
path: root/man/man7/sock_diag.7
diff options
context:
space:
mode:
Diffstat (limited to 'man/man7/sock_diag.7')
-rw-r--r--man/man7/sock_diag.7825
1 files changed, 825 insertions, 0 deletions
diff --git a/man/man7/sock_diag.7 b/man/man7/sock_diag.7
new file mode 100644
index 000000000..962c3edf3
--- /dev/null
+++ b/man/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 (date) "Linux man-pages (unreleased)"
+.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 */"
+.P
+.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.
+.P
+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.
+.P
+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.)
+.P
+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:
+.P
+.in +4n
+.EX
+struct sock_diag_req {
+ __u8 sdiag_family;
+ __u8 sdiag_protocol;
+};
+.EE
+.in
+.P
+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.
+.P
+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.
+.P
+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:
+.P
+.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
+.P
+The fields of this structure are as follows:
+.TP
+.I sdiag_family
+The address family; it should be set to
+.BR AF_UNIX .
+.P
+.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:
+.P
+.RS 12
+1 <<
+.B TCP_ESTABLISHED
+.P
+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".
+.P
+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.
+.P
+The response to a query for UNIX domain sockets is represented as an array of
+.P
+.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
+.P
+followed by netlink attributes.
+.P
+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:
+.P
+.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
+.P
+where
+.I "struct inet_diag_sockid"
+is defined as follows:
+.P
+.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
+.P
+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.
+.P
+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.
+.P
+The response to a query for IPv4 or IPv6 sockets is represented as an array of
+.P
+.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
+.P
+followed by netlink attributes.
+.P
+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.
+.P
+.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.
+.P
+.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)