Главная » 2017 » Ноябрь » 18 » man 7 sock_diag
21:36
man 7 sock_diag

SEO sprint - Всё для максимальной раскрутки!





ИМЯ


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).
__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
Номер иноды, соответствующей иноде сокета на диске.

представляющие номера инод сокетов, которые переданы вызову
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];

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

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
Адрес отправителя.
полями этой структуры для указания определённого сокета. Игнорируется при
запросе списка сокетов, а также когда все его элементы равны -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).

Информация о памяти сокетов
Полезные данные, связанные с атрибутами 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)
.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 = (void *) &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;
}

struct rtattr *attr;
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 (attr = (struct rtattr *) (diag + 1);
RTA_OK(attr, rta_len); attr = RTA_NEXT(attr, rta_len)) {
switch (attr->rta_type) {
case UNIX_DIAG_NAME:
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 = {
.nl_family = AF_NETLINK
};
struct iovec iov = {
.iov_base = buf,
.iov_len = sizeof(buf)
};
int flags = 0;

for (;;) {
struct msghdr msg = {
.msg_name = (void *) &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;

const struct nlmsghdr *h = (struct nlmsghdr *) buf;

if (!NLMSG_OK(h, ret)) {
fputs("!NLMSG_OK\n", stderr);

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)



Категория: (7) Различные описания, соглашения и прочее | Просмотров: 511 | Добавил: Администратор | Рейтинг: 0.0/0
Всего комментариев: 0
avatar