sock_diag(7) | Miscellaneous Information Manual | sock_diag(7) |
ИМЯ¶
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_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_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
- Номер иноды сокета.
- Массив скрытых идентификаторов, которые можно использовать в последующих запросах.
Сокеты 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
- Интерфейсный номер к которому привязан сокет.
- Массив скрытых идентификаторов, которые можно использовать вместе с другими полями этой структуры для указания определённого сокета. Игнорируется при запросе списка сокетов, а также когда все его элементы равны -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.
СТАНДАРТЫ¶
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("short response\n", stderr);
return -1;
}
if (diag->udiag_family != AF_UNIX) {
fprintf(stderr, "unexpected family %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("inode=%u", diag->udiag_ino);
if (peer)
printf(", peer=%u", peer);
if (path_len)
printf(", name=%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, "unexpected 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; }
СМОТРИТЕ ТАКЖЕ¶
ПЕРЕВОД¶
Русский перевод этой страницы руководства разработал 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 (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику по его адресу электронной почты или по адресу списка рассылки русских переводчиков.
2 мая 2024 г. | Linux man-pages (unreleased) |