sock_diag(7) Miscellaneous Information Manual sock_diag(7) NOM sock_diag - Obtention d'informations a propos des sockets SYNOPSIS #include #include #include /* pour sockets de domaine UNIX */ #include /* pour sockets IPv4 et IPv6 */ diag_socket = socket(AF_NETLINK, socket_type, NETLINK_SOCK_DIAG); DESCRIPTION Le sous-systeme netlink de sock_diag fournit un mecanisme pour obtenir les informations sur les sockets de diverses familles d'adresses du noyau. Ce sous-systeme peut etre utilise pour obtenir des informations a propos de sockets particuliers ou pour obtenir la liste des sockets. Dans la requete, l'appelant peut indiquer les informations supplementaires qu'il desire obtenir a propos du socket, par exemple, les informations sur la memoire ou les informations specifiques a une famille d'adresses. Lors d'une requete d'une liste de sockets, l'appelant peut indiquer des filtres a appliquer par le noyau pour selectionner un sous-ensemble de sockets. Pour l'instant, il est seulement possible de filtrer les sockets par etat (connecte, a l'ecoute, etc). Remarquez que sock_diag rapporte seulement les sockets ayant un nom. C'est-a-dire soit les sockets lies explicitement avec bind(2) ou les sockets qui ont ete automatiquement lies a une adresse (par exemple, par connect(2)). C'est le meme ensemble de sockets disponible a l'aide de /proc/net/unix, /proc/net/tcp, /proc/net/udp, etc. Requete La requete debute par un en-tete struct nlmsghdr decrit dans netlink(7) avec un champ nlmsg_type regle a SOCK_DIAG_BY_FAMILY. Il est suivi par un en-tete specifique a une famille d'adresses qui debute par une partie commune partagee par toutes les familles d'adresses : struct sock_diag_req { __u8 sdiag_family; __u8 sdiag_protocol; }; Les membres de cette structure sont les suivants : sdiag_family Une famille d'adresses. Elle devrait etre reglee a la constante AF_* appropriee. sdiag_protocol Fonction de sdiag_family. Il devrait etre regle a la constante IPPROTO_* appropriee pour AF_INET et AF_INET6, et a 0 autrement. Si le champ nlmsg_flags de l'en-tete struct nlmsghdr a l'indicateur NLM_F_DUMP defini, cela signifie qu'une liste de sockets est demandee. Sinon, il s'agit d'une requete concernant un socket particulier. Reponse La reponse debute avec un en-tete struct nlmsghdr et est suivie par un tableau d'objets specifique a la famille d'adresses. Le tableau est accessible avec les macros NLMSG_* standards de l'API de netlink(3). Chaque objet est la liste NLA (attributs netlink) accessible avec les macros RTA_* de l'API de rtnetlink(3). Sockets de domaine UNIX Pour les sockets de domaine UNIX, la requete est decrite dans la structure suivante : 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]; }; Les membres de cette structure sont les suivants : sdiag_family La famille d'adresses. Elle devrait etre AF_UNIX. sdiag_protocol pad Ces champs devraient etre regles a 0. udiag_states C'est un masque de bits definissant un filtre d'etats des sockets. Seuls les sockets dont les etats sont dans le masque seront rapportes. Il est ignore lors d'une requete pour un socket particulier. Les valeurs autorisees sont : 1 << TCP_ESTABLISHED 1 << TCP_LISTEN udiag_ino C'est un numero d'inoeud lors d'une requete pour un socket particulier. Il est ignore lors d'une requete pour une liste de sockets. udiag_show C'est un ensemble d'indicateurs definissant quelle sorte d'information rapporter. Chaque sorte d'information est rapportee sous forme d'attribut netlink comme decrit ci-dessous : UDIAG_SHOW_NAME L'attribut rapporte dans la reponse a cette requete est UNIX_DIAG_NAME. La charge utile associee a cet attribut est le nom de chemin auquel le socket a ete lie (une sequence d'octets de taille maximale UNIX_PATH_MAX). UDIAG_SHOW_VFS L'attribut rapporte dans la reponse a cette requete est UNIX_DIAG_VFS. La charge utile associee a cet attribut est decrite dans la structure suivante : struct unix_diag_vfs { __u32 udiag_vfs_dev; __u32 udiag_vfs_ino; }; Les membres de cette structure sont les suivants : udiag_vfs_dev Le numero de peripherique de l'inoeud correspondant de socket sur le disque. udiag_vfs_ino Le numero d'inoeud de l'inoeud correspondant de socket sur le disque. UDIAG_SHOW_PEER L'attribut rapporte dans la reponse a cette requete est UNIX_DIAG_PEER. La charge utile associee a cet attribut est une valeur __u32 qui est le numero d'inoeud du pair. Cet attribut est rapporte seulement pour les sockets connectes. UDIAG_SHOW_ICONS L'attribut rapporte dans la reponse a cette requete est UNIX_DIAG_ICONS. La charge utile associee a cet attribut est un tableau de valeurs __u32 qui sont des numeros d'inoeuds de sockets qui ont passe l'appel connect(2), mais qui n'ont pas encore ete traites par accept(2). Cet attribut est rapporte seulement pour les sockets a l'ecoute. UDIAG_SHOW_RQLEN L'attribut rapporte dans la reponse a cette requete est UNIX_DIAG_RQLEN. La charge utile associee a cet attribut est decrite dans la structure suivante : struct unix_diag_rqlen { __u32 udiag_rqueue; __u32 udiag_wqueue; }; Les membres de cette structure sont les suivants : udiag_rqueue Pour les sockets a l'ecoute : le nombre de connexions en attente. La taille du tableau associe a l'attribut de la reponse UNIX_DIAG_ICONS est egale a cette valeur. Pour les sockets etablis : la quantite de donnees dans la file d'attente entrante. udiag_wqueue Pour les sockets a l'ecoute : la taille de l'arriere qui est egale a la valeur passee comme second argument a listen(2). Pour les sockets etablis : la quantite de memoire disponible pour l'emission. UDIAG_SHOW_MEMINFO L'attribut rapporte dans la reponse a cette requete est UNIX_DIAG_MEMINFO. La charge utile associee a cet attribut est un tableau de valeurs __u32 decrites dans la sous-section << Informations sur la memoire de socket >>. Les attributs suivants sont rapportes sans requete particuliere : UNIX_DIAG_SHUTDOWN La charge utile associee a cet attribut est une valeur __u8 representant les bits de l'etat de shutdown(2). udiag_cookie C'est un tableau d'identificateurs opaques pouvant etre utilises avec udiag_ino pour indiquer un socket particulier. Il est ignore lors de la requete d'une liste de sockets ainsi que lorsque ses elements sont regles a -1. La reponse a une requete de sockets de domaine UNIX est decrite sous forme de tableau de struct unix_diag_msg { __u8 udiag_family; __u8 udiag_type; __u8 udiag_state; __u8 pad; __u32 udiag_ino; __u32 udiag_cookie[2]; }; suivis par les attributs de netlink. Les membres de cette structure sont les suivants : udiag_family Ce champ a la meme signification que struct unix_diag_req. udiag_type Ce champ est regle a SOCK_PACKET, SOCK_STREAM ou SOCK_SEQPACKET. udiag_state Ce champ est regle a TCP_LISTEN ou TCP_ESTABLISHED. pad Ce champ est regle a 0. udiag_ino Ce champ est le numero d'inoeud de socket. udiag_cookie Ce champ est un tableau d'identificateurs opaques pouvant etre utilises dans des requetes ulterieures. Sockets IPv4 et IPv6 Pour les sockets IPv4 et IPv6, la requete est decrite dans la structure suivante : struct inet_diag_req_v2 { __u8 sdiag_family; __u8 sdiag_protocol; __u8 idiag_ext; __u8 pad; __u32 idiag_states; struct inet_diag_sockid id; }; ou struct inet_diag_sockid est defini comme suit : 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]; }; Les champs de struct inet_diag_req_v2 sont comme suit : sdiag_family Cela devrait etre soit AF_INET ou AF_INET6 pour les sockets IPv4 ou IPv6 respectivement. sdiag_protocol Cela devrait etre regle a IPPROTO_TCP, IPPROTO_UDP ou IPPROTO_UDPLITE. idiag_ext C'est un ensemble d'indicateurs definissant quelle sorte d'informations etendues a rapporter. Chaque sorte d'informations est rapportee sous forme d'attribut de netlink comme decrit ci-dessous : INET_DIAG_TOS La charge utile associee a cet attribut est une valeur __u8 qui est le TOS du socket. INET_DIAG_TCLASS La charge utile associee a cet attribut est une valeur __u8 qui est la TClass du socket -- sockets IPv6 uniquement. Pour les sockets LISTEN et CLOSE, cela est suivi par l'attribut INET_DIAG_SKV6ONLY avec la valeur associee __u8 de charge utile signifiant si le socket est seulement IPv6 ou non. INET_DIAG_MEMINFO La charge utile associee a cet attribut est decrite dans la structure suivante : struct inet_diag_meminfo { __u32 idiag_rmem; __u32 idiag_wmem; __u32 idiag_fmem; __u32 idiag_tmem; }; Les membres de cette structure sont les suivants : idiag_rmem La quantite de donnees dans la file de reception. idiag_wmem La quantite de donnees mises dans la file par TCP mais non encore envoyees. idiag_fmem La quantite de memoire prevue pour une utilisation future (TCP uniquement). idiag_tmem La quantite de donnees dans la file d'emission. INET_DIAG_SKMEMINFO La charge utile associee a cet attribut est un tableau de valeurs __u32 decrites ci-dessous dans la sous-section << Informations sur la memoire de socket >>. INET_DIAG_INFO La charge utile associee a cet attribut est specifique a la famille d'adresses. Pour les sockets TCP, c'est un objet de type struct tcp_info. INET_DIAG_CONG La charge utile associee avec cet attribut est une chaine decrivant l'algorithme de controle de congestion utilise. Uniquement pour les sockets TCP. pad Cela devrait etre regle a 0. idiag_states C'est un masque de bits definissant un filtre d'etats des sockets. Seuls les sockets dont les etats sont dans le masque seront rapportes. Il est ignore lors d'une requete pour un socket particulier. id C'est un objet d'ID de socket utilise dans les requetes de vidage, dans les requetes a propos de sockets particuliers et qui est rapporte dans chaque reponse. Au contraire des sockets de domaine UNIX, les sockets IPv4 et IPv6 sont identifies en utilisant des adresses et des ports. Toutes les valeurs sont dans l'ordre d'octets du reseau. Les champs de struct inet_diag_sockid sont comme suit : idiag_sport Le port de la source. idiag_dport Le port de la destination. idiag_src L'adresse de la source. idiag_dst L'adresse de la destination. idiag_if Le numero d'interface auquel le socket est lie. idiag_cookie C'est un tableau d'identificateurs opaques pouvant etre utilises dans d'autres champs de cette structure pour indiquer un socket particulier. Il est ignore lors d'une requete pour une liste de sockets, de meme que lorsque tous ses elements sont regles a -1. La reponse a une requete de sockets IPv4 ou IPv6 est decrite sous forme d'un tableau de 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; }; suivis par les attributs de netlink. Les membres de cette structure sont les suivants : idiag_family c'est le meme champ que dans struct inet_diag_req_v2. idiag_state Cela indique l'etat comme dans struct inet_diag_req_v2. idiag_timer Pour les sockets TCP, ce champ decrit le type de temporisateur actuellement actif pour le socket. Il est regle a une des constantes suivantes : 0 aucun temporisateur actif 1 un temporisateur de retransmission 2 un temporisateur d'entretien 3 un temporisateur TIME_WAIT 4 un temporisateur de sonde de fenetre nulle Pour les sockets non TCP, ce champ doit etre regle a 0. idiag_retrans Pour les valeurs 1, 2 et 4 d'idiag_timer, ce champ contient le nombre de retransmissions. Pour les autres valeurs d'idiag_timer, ce champ est regle a 0. idiag_expires Pour les sockets TCP ayant un temporisateur actif, ce champ indique son delai d'expiration en milliseconde. Pour les autres sockets, ce champ est regle a 0. idiag_rqueue Pour les sockets a l'ecoute : le nombre de connexions en attente. Pour les autres sockets : la quantite de donnees dans la file d'attente entrante. idiag_wqueue Pour les sockets a l'ecoute : la taille de l'arriere. Pour les autres sockets : la quantite de memoire disponible pour l'envoi. idiag_uid C'est l'UID du proprietaire du socket. idiag_inode Ce champ est le numero d'inoeud de socket. Informations sur la memoire du socket La charge utile associee avec les attributs UNIX_DIAG_MEMINFO et INET_DIAG_SKMEMINFO de netlink est un tableau des valeurs __u32 suivantes : SK_MEMINFO_RMEM_ALLOC La quantite de donnees dans la file d'attente de reception. SK_MEMINFO_RCVBUF Le tampon de reception de socket comme regle par SO_RCVBUF. SK_MEMINFO_WMEM_ALLOC La quantite de donnees dans la file d'emission. SK_MEMINFO_SNDBUF Le tampon d'emission de socket comme regle par SO_SNDBUF. SK_MEMINFO_FWD_ALLOC La quantite de memoire prevue pour une utilisation future (TCP uniquement). SK_MEMINFO_WMEM_QUEUED La quantite de donnees mises en attente par TCP, mais pas encore envoyees. SK_MEMINFO_OPTMEM La quantite de memoire allouee pour les besoins du service du socket (par exemple, filtre du socket). SK_MEMINFO_BACKLOG La quantite de paquets dans l'arriere (pas encore traite). VERSIONS NETLINK_INET_DIAG a ete introduit dans Linux 2.6.14 et ne gere que les sockets AF_INET et AF_INET6. Dans Linux 3.3, il a ete renomme NETLINK_SOCK_DIAG et etendu pour gerer les sockets AF_UNIX. UNIX_DIAG_MEMINFO et INET_DIAG_SKMEMINFO ont ete introduits dans Linux 3.6. STANDARDS Linux. EXEMPLES L'exemple suivant affiche le numero d'inoeud, le numero d'inoeud du pair et le nom de tous les sockets de domaine UNIX dans l'espace de noms en cours. #include #include #include #include #include #include #include #include #include #include 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; } VOIR AUSSI netlink(3), rtnetlink(3), netlink(7), tcp(7) TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot et Jean-Paul Guillonneau Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.06 31 octobre 2023 sock_diag(7)