Provided by: manpages-ru_4.21.0-2_all
ИМЯ
sock_diag - возвращает информацию о сокетах
СИНТАКСИС
#include <sys/socket.h> #include <linux/sock_diag.h> #include <linux/unix_diag.h> /* для доменных сокетов UNIX */ #include <linux/inet_diag.h> /* для сокетов IPv4 и IPv6 */ diag_socket = socket(AF_NETLINK, socket_type, NETLINK_SOCK_DIAG);
ОПИСАНИЕ
Подсистема sock_diag netlink предоставляет механизм получения информации о сокетах различных семейств адресов из ядра. Данная подсистема может использоваться для получения информации об отдельных сокетах или запрашивать список сокетов. В запросе вызывающий может указать дополнительную информацию, которую хочется узнать о сокетах, например, информацию о памяти или характерную семейству адресов. Когда запрашивается список сокетов вызывающий может задать фильтры, которые будут применены ядром для выбора возвращаемого набора сокетов. В настоящее время, фильтровать сокеты можно только по состоянию (соединён, слушает и т. д.). Заметим, что sock_diag возвращает только сокеты с именем; то есть, явно привязанные сокеты с помощью bind(2) или автоматически привязанные к адресу сокеты (например, с помощью connect(2)). Данный набор сокетов совпадает со списком в /proc/net/unix, /proc/net/tcp, /proc/net/udp и т. п. Запрос Запрос начинается с заголовка struct nlmsghdr, описанного в netlink(7), в котором поле nlmsg_type равно SOCK_DIAG_BY_FAMILY. За ним следует заголовок, соответствующий семейству адресов, начинающийся с общей части, используемой для всех семейств адресов: struct sock_diag_req { __u8 sdiag_family; __u8 sdiag_protocol; }; Поля этой структуры имеют следующее назначение: sdiag_family Семейство адресов. Должна быть указана соответствующая константа AF_*. sdiag_protocol Зависит от sdiag_family. Должна быть указана соответствующая константа IPPROTO_* при AF_INET и AF_INET6, и 0 в остальных случаях. Если в поле nlmsg_flags заголовка struct nlmsghdr установлен флаг NLM_F_DUMP, то это означает, что запрашивается список сокетов; в противном случае запрашивается информация об конкретном сокете. Ответ Ответ начинается с заголовка struct nlmsghdr, за которым следует массив объектов, соответствующих семейству адресов. Массив доступен через стандартные макросы из NLMSG_* программного интерфейса netlink(3). Каждый объект представляет собой список NLA (атрибутов netlink), которые доступны через макросы RTA_* программного интерфейса rtnetlink(3). Доменные сокеты UNIX Запрос доменных сокетов UNIX описывается в следующей структуре: 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]; }; Поля этой структуры имеют следующее назначение: sdiag_family Семейство адресов; должно быть равно AF_UNIX. sdiag_protocol pad Эти поля должны быть равны 0. udiag_states Битовая маска, описывающая фильтр состояний сокетов. Будут возвращены только сокеты с состояниями из этой маски. Игнорируется, если запрашивается конкретный сокет. Поддерживаемые значения: 1 << TCP_ESTABLISHED 1 << TCP_LISTEN udiag_ino Номер иноды при запросе конкретного сокета. Игнорируется, если запрашивается список сокетов. udiag_show Набор флагов, определяющий тип возвращаемой информации. Каждый запрашиваемый тип информации возвращается в виде атрибута netlink, описанного ниже: UDIAG_SHOW_NAME Атрибут, возвращаемый в ответе на этот запрос — UNIX_DIAG_NAME. Полезные данные, связанные с этим атрибутом — путь, с которым был связан сокет (последовательность байт длиной до UNIX_PATH_MAX). UDIAG_SHOW_VFS Атрибут, возвращаемый в ответе на этот запрос — UNIX_DIAG_VFS. Полезные данные, связанные с этим атрибутом представляются следующей структурой: struct unix_diag_vfs { __u32 udiag_vfs_dev; __u32 udiag_vfs_ino; }; Поля этой структуры имеют следующее назначение: udiag_vfs_dev Номер устройства, соответствующего иноде сокета на диске. udiag_vfs_ino Номер иноды, соответствующей иноде сокета на диске. UDIAG_SHOW_PEER Атрибут, возвращаемый в ответе на этот запрос — UNIX_DIAG_PEER. Полезные данные, связанные с этим атрибутом — значение __u32, представляющее номер иноды ответной стороны. Данный атрибут возвращается только для соединённых сокетов. UDIAG_SHOW_ICONS Атрибут, возвращаемый в ответе на этот запрос — UNIX_DIAG_ICONS. Полезные данные, связанные с этим атрибутом — значения __u32, представляющие номера инод сокетов, которые переданы вызову connect(2), но ещё не были обработаны accept(2). Данный атрибут возвращается, если запрашивается список сокетов. UDIAG_SHOW_RQLEN Атрибут, возвращаемый в ответе на этот запрос — UNIX_DIAG_RQLEN. Полезные данные, связанные с этим атрибутом представляются следующей структурой: struct unix_diag_rqlen { __u32 udiag_rqueue; __u32 udiag_wqueue; }; Поля этой структуры имеют следующее назначение: udiag_rqueue Для слушающих сокетов: количество ожидающих подключений. Этому значению равна длина массива, связанного с атрибутом ответа UNIX_DIAG_ICONS. Для сокетов с установленным соединением: количество данных во входящей очереди. udiag_wqueue Для слушающих сокетов: длина недодела (backlog), равная значению, переданному во втором аргументе listen(2). Для сокетов с установленным соединением: количество памяти, доступной при отправке. UDIAG_SHOW_MEMINFO Атрибут, возвращаемый в ответе на этот запрос — UNIX_DIAG_MEMINFO. Полезные данные, связанные с этим атрибутом представляют собой массив значений с типом __u32,описанный далее в подразделе «Информация о памяти сокетов». Следующие атрибуты возвращаются для любого запроса: UNIX_DIAG_SHUTDOWN Полезные данные, связанные с этим атрибутом, имеют тип __u8 и представляют биты состояния из shutdown(2). udiag_cookie Массив скрытых идентификаторов, которые можно использовать вместе с udiag_ino для указания определённого сокета. Игнорируется при запросе списка сокетов, а также когда все его элементы равны -1. Ответ на запрос о доменных сокетах UNIX представляется в виде массива struct unix_diag_msg { __u8 udiag_family; __u8 udiag_type; __u8 udiag_state; __u8 pad; __u32 udiag_ino; __u32 udiag_cookie[2]; }; и следует за атрибутами netlink. Поля этой структуры имеют следующее назначение: udiag_family Данное поле имеет то же значение что в struct unix_diag_req. udiag_type Может быть SOCK_PACKET, SOCK_STREAM или SOCK_SEQPACKET. udiag_state Может быть TCP_LISTEN или TCP_ESTABLISHED. pad Это поле равно 0. udiag_ino Номер иноды сокета. udiag_cookie Массив скрытых идентификаторов, которые можно использовать в последующих запросах. Сокеты IPv4 и IPv6 Запрос сокетов IPv4 и IPv6 описывается в следующей структуре: struct inet_diag_req_v2 { __u8 sdiag_family; __u8 sdiag_protocol; __u8 idiag_ext; __u8 pad; __u32 idiag_states; struct inet_diag_sockid id; }; где struct inet_diag_sockid определена как: 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]; }; Поля struct inet_diag_req_v2: sdiag_family Должно быть равно AF_INET или AF_INET6 для сокетов IPv4 или IPv6, соответственно. sdiag_protocol Должно быть равно IPPROTO_TCP, IPPROTO_UDP или IPPROTO_UDPLITE. idiag_ext Набор флагов, определяющий тип возвращаемой расширенной информации. Каждый запрашиваемый тип информации возвращается в виде атрибута netlink, описанного ниже: INET_DIAG_TOS Полезные данные, связанные с этим атрибутом, имеют тип __u8 и представляют TOS сокета. INET_DIAG_TCLASS Полезные данные, связанные с этим атрибутом, имеют тип __u8 и представляют TClass сокета. Только для сокетов IPv6. Для сокетов LISTEN и CLOSE эти данные следуют за атрибутом INET_DIAG_SKV6ONLY с значением полезных данных (тип __u8), описывающим является ли сокет только IPv6 или нет. INET_DIAG_MEMINFO Полезные данные, связанные с этим атрибутом представляются следующей структурой: struct inet_diag_meminfo { __u32 idiag_rmem; __u32 idiag_wmem; __u32 idiag_fmem; __u32 idiag_tmem; }; Поля этой структуры имеют следующее назначение: idiag_rmem Количество данных в приёмной очереди. idiag_wmem Количество данных, помещённых в очередь TCP и ещё не отправленных. idiag_fmem Объём памяти, запланированной для использования в будущем (только TCP). idiag_tmem Количество данных в очереди отправки. INET_DIAG_SKMEMINFO Полезные данные, связанные с этим атрибутом представляют собой массив значений с типом __u32,описанный далее в подразделе «Информация о памяти сокетов». INET_DIAG_INFO Полезные данные, связанные с этим атрибутом, относятся к определённому семейству адресов. Для сокетов TCP объект имеет тип struct tcp_info. INET_DIAG_CONG Полезные данные, связанные с этим атрибутом, представляют собой строку, описывающую используемый алгоритм контроля перегрузки. Только для сокетов TCP. pad Должно равняться 0. idiag_states Битовая маска, описывающая фильтр состояний сокета. Будут возвращены только сокеты с состояниями из этой маски. Игнорируется, если запрашивается конкретный сокет. id Идентификатор объекта сокета, использующийся при запросах дампа, в опросах отдельных сокетов и возвращается в каждом ответе. В отличие от доменных сокетов UNIX, сокеты IPv4 и IPv6 опознаются по адресам и портам. Все значения указываются в сетевом порядке байт. Поля struct inet_diag_sockid: idiag_sport Порт отправителя. idiag_dport Порт получателя. idiag_src Адрес отправителя. idiag_dst Адрес получателя. idiag_if Интерфейсный номер к которому привязан сокет. idiag_cookie Массив скрытых идентификаторов, которые можно использовать вместе с другими полями этой структуры для указания определённого сокета. Игнорируется при запросе списка сокетов, а также когда все его элементы равны -1. Ответ на запрос о сокетах IPv4 или IPv6 представляется в виде массива 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; }; и следует за атрибутами netlink. Поля этой структуры имеют следующее назначение: idiag_family Это тоже поле что и в struct inet_diag_req_v2. idiag_state Обозначает состояние сокета как в struct inet_diag_req_v2. idiag_timer Для сокетов TCP это поле описывает тип активного в данный момент таймера сокета. Задаётся одной из следующих констант: 0 таймер не активен 1 таймер повторной передачи 2 таймер поддержания соединения 3 таймер TIME_WAIT 4 таймер проверки нулевым окном Для сокетов не TCP, значение этого поля равно 0. idiag_retrans Если idiag_timer содержит 1, 2 и 4, то это поле содержит количество повторных передач. При других значениях idiag_timer это поле равно 0. idiag_expires Для сокетов TCP, имеющих активный таймер, это поле описывает его время окончания в миллисекундах. Для других сокетов значение этого поля равно 0. idiag_rqueue Для слушающих сокетов: количество ожидающих подключений. Для других сокетов: количество данных во входящей очереди. idiag_wqueue Для слушающих сокетов: длина недодела (backlog). Для других сокетов: количество памяти, доступной при отправке. idiag_uid Идентификатор пользователя, владеющего сокетом. idiag_inode Номер иноды сокета. Информация о памяти сокетов Полезные данные, связанные с атрибутами netlink UNIX_DIAG_MEMINFO и INET_DIAG_SKMEMINFO, представляют собой массив следующих значений с типом __u32: SK_MEMINFO_RMEM_ALLOC Количество данных в приёмной очереди. SK_MEMINFO_RCVBUF Приёмный буфер сокета, заданный SO_RCVBUF. SK_MEMINFO_WMEM_ALLOC Количество данных в очереди отправки. SK_MEMINFO_SNDBUF Буфер отправки сокета, заданный SO_SNDBUF. SK_MEMINFO_FWD_ALLOC Объём памяти, запланированной для использования в будущем (только TCP). SK_MEMINFO_WMEM_QUEUED Количество данных, помещённых в очередь TCP, но ещё не отправленных. SK_MEMINFO_OPTMEM Объем памяти, выделенный для служебных нужд сокета (например, для сокетного фильтра). SK_MEMINFO_BACKLOG Количество пакетов в памяти недодела (не обработанных).
ВЕРСИИ
Программный интерфейс NETLINK_INET_DIAG появился в Linux 2.6.14 и поддерживал только сокеты AF_INET и AF_INET6. В Linux 3.3 он был переименован в NETLINK_SOCK_DIAG и появилась поддержка сокетов AF_UNIX. Программный интерфейс UNIX_DIAG_MEMINFO и INET_DIAG_SKMEMINFO появился в Linux 3.6.
СТАНДАРТЫ
Программный интерфейс NETLINK_SOCK_DIAG есть только в Linux.
ПРИМЕРЫ
Следующий пример программы печатает номер иноды, номер иноды противоположной стороны и имена всех доменных сокетов UNIX в текущем пространстве имён. #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("короткий ответ\n", stderr); return -1; } if (diag->udiag_family != AF_UNIX) { fprintf(stderr, "неожиданное семейство %u\n", 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] = '\0'; } break; case UNIX_DIAG_PEER: if (RTA_PAYLOAD(attr) >= sizeof(peer)) peer = *(unsigned int *) RTA_DATA(attr); break; } } printf("инода=%u", diag->udiag_ino); if (peer) printf(", другая сторона=%u", peer); if (path_len) printf(", имя=%s%s", *path ? "" : "@", *path ? path : path + 1); putchar('\n'); 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\n", stderr); return -1; } const struct nlmsghdr *h = (struct nlmsghdr *) buf; if (!NLMSG_OK(h, ret)) { fputs("!NLMSG_OK\n", 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\n", stderr); } else { errno = -err->error; perror("NLMSG_ERROR"); } return -1; } if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY) { fprintf(stderr, "неожиданный nlmsg_type %u\n", (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; }
СМ. ТАКЖЕ
netlink(3), rtnetlink(3), netlink(7), tcp(7)
ПЕРЕВОД
Русский перевод этой страницы руководства был сделан Alexander Golubev <fatzer2@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Hotellook, Nikita <zxcvbnm3230@mail.ru>, Spiros Georgaras <sng@hellug.gr>, Vladislav <ivladislavefimov@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com> Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ. Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на ⟨man-pages-ru-talks@lists.sourceforge.net⟩.