Provided by: manpages-fr_4.23.1-1_all bug

NOM

       sock_diag – Obtention d’informations à propos des sockets

SYNOPSIS

       #include <sys/socket.h>
       #include <linux/sock_diag.h>
       #include <linux/unix_diag.h> /* pour sockets de domaine UNIX */
       #include <linux/inet_diag.h> /* pour sockets IPv4 et IPv6 */

       diag_socket = socket(AF_NETLINK, socket_type, NETLINK_SOCK_DIAG);

DESCRIPTION

       Le  sous-système  netlink de sock_diag fournit un mécanisme pour obtenir les informations sur les sockets
       de diverses familles d’adresses du noyau. Ce sous-système peut être utilisé pour obtenir des informations
       à propos de sockets particuliers ou pour obtenir la liste des sockets.

       Dans la requête, l’appelant peut indiquer les informations supplémentaires qu’il désire obtenir à  propos
       du  socket,  par  exemple,  les informations sur la mémoire ou les informations spécifiques à une famille
       d’adresses.

       Lors d’une requête d’une liste de sockets, l’appelant peut indiquer des filtres à appliquer par le  noyau
       pour  sélectionner  un sous-ensemble de sockets. Pour l’instant, il est seulement possible de filtrer les
       sockets par état (connecté, à l’écoute, etc).

       Remarquez que sock_diag rapporte seulement les sockets ayant un nom. C’est-à-dire soit les  sockets  liés
       explicitement  avec  bind(2)  ou les sockets qui ont été automatiquement liés à une adresse (par exemple,
       par connect(2)). C’est le même ensemble de sockets disponible à l’aide de /proc/net/unix,  /proc/net/tcp,
       /proc/net/udp, etc.

   Requête
       La  requête débute par un en-tête struct nlmsghdr décrit dans netlink(7) avec un champ nlmsg_type réglé à
       SOCK_DIAG_BY_FAMILY. Il est suivi par un en-tête spécifique à une famille d’adresses qui débute  par  une
       partie commune partagée 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 être réglée à la constante AF_* appropriée.

       sdiag_protocol
              Fonction  de  sdiag_family. Il devrait être réglé à la constante IPPROTO_* appropriée pour AF_INET
              et AF_INET6, et à 0 autrement.

       Si le champ nlmsg_flags de l’en-tête struct nlmsghdr a  l’indicateur  NLM_F_DUMP  défini,  cela  signifie
       qu’une liste de sockets est demandée. Sinon, il s’agit d’une requête concernant un socket particulier.

   Réponse
       La  réponse  débute avec un en-tête struct nlmsghdr et est suivie par un tableau d’objets spécifique à 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 requête est décrite 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 être AF_UNIX.

       sdiag_protocol
       pad    Ces champs devraient être réglés à 0.

       udiag_states
              C’est  un  masque  de  bits  définissant un filtre d’états des sockets. Seuls les sockets dont les
              états sont dans le masque seront rapportés. Il est  ignoré  lors  d’une  requête  pour  un  socket
              particulier. Les valeurs autorisées sont :

                   1 << TCP_ESTABLISHED

                   1 << TCP_LISTEN

       udiag_ino
              C’est  un  numéro  d’inœud lors d’une requête pour un socket particulier. Il est ignoré lors d’une
              requête pour une liste de sockets.

       udiag_show
              C’est un ensemble d’indicateurs définissant quelle sorte  d’information  rapporter.  Chaque  sorte
              d’information est rapportée sous forme d’attribut netlink comme décrit ci-dessous :

              UDIAG_SHOW_NAME
                     L’attribut  rapporté  dans  la  réponse à cette requête est UNIX_DIAG_NAME. La charge utile
                     associée à cet attribut est le nom de chemin auquel le  socket  a  été  lié  (une  séquence
                     d’octets de taille maximale UNIX_PATH_MAX).

              UDIAG_SHOW_VFS
                     L’attribut  rapporté  dans  la  réponse  à cette requête est UNIX_DIAG_VFS. La charge utile
                     associée à cet attribut est décrite 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 numéro de périphérique de l’inœud correspondant de socket sur le disque.

                     udiag_vfs_ino
                            Le numéro d’inœud de l’inœud correspondant de socket sur le disque.

              UDIAG_SHOW_PEER
                     L’attribut rapporté dans la réponse à cette requête est  UNIX_DIAG_PEER.  La  charge  utile
                     associée  à  cet  attribut  est  une  valeur  __u32  qui est le numéro d’inœud du pair. Cet
                     attribut est rapporté seulement pour les sockets connectés.

              UDIAG_SHOW_ICONS
                     L’attribut rapporté dans la réponse à cette requête est UNIX_DIAG_ICONS.  La  charge  utile
                     associée  à  cet  attribut est un tableau de valeurs __u32 qui sont des numéros d’inœuds de
                     sockets qui ont passé l’appel connect(2),  mais  qui  n’ont  pas  encore  été  traités  par
                     accept(2). Cet attribut est rapporté seulement pour les sockets à l’écoute.

              UDIAG_SHOW_RQLEN
                     L’attribut  rapporté  dans  la réponse à cette requête est UNIX_DIAG_RQLEN. La charge utile
                     associée à cet attribut est décrite 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 à l’écoute : le nombre de  connexions  en  attente.  La  taille  du
                            tableau associé à l’attribut de la réponse UNIX_DIAG_ICONS est égale à cette valeur.

                            Pour les sockets établis : la quantité de données dans la file d’attente entrante.

                     udiag_wqueue
                            Pour  les  sockets  à  l’écoute  :  la taille de l’arriéré qui est égale à la valeur
                            passée comme second argument à listen(2).

                            Pour les sockets établis : la quantité de mémoire disponible pour l’émission.

              UDIAG_SHOW_MEMINFO
                     L’attribut rapporté dans la réponse à cette requête est UNIX_DIAG_MEMINFO. La charge  utile
                     associée  à  cet  attribut  est  un  tableau de valeurs __u32 décrites dans la sous-section
                     « Informations sur la mémoire de socket ».

              Les attributs suivants sont rapportés sans requête particulière :

              UNIX_DIAG_SHUTDOWN
                     La charge utile associée à cet attribut est une valeur __u8 représentant les bits de l’état
                     de shutdown(2).

       udiag_cookie
              C’est un tableau d’identificateurs opaques pouvant être utilisés avec udiag_ino pour  indiquer  un
              socket  particulier. Il est ignoré lors de la requête d’une liste de sockets ainsi que lorsque ses
              éléments sont réglés à -1.

       La réponse à une requête de sockets de domaine UNIX est décrite 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 même signification que struct unix_diag_req.

       udiag_type
              Ce champ est réglé à SOCK_PACKET, SOCK_STREAM ou SOCK_SEQPACKET.

       udiag_state
              Ce champ est réglé à TCP_LISTEN ou TCP_ESTABLISHED.

       pad    Ce champ est réglé à 0.

       udiag_ino
              Ce champ est le numéro d’inœud de socket.

       udiag_cookie
              Ce champ est un  tableau  d’identificateurs  opaques  pouvant  être  utilisés  dans  des  requêtes
              ultérieures.

   Sockets IPv4 et IPv6
       Pour les sockets IPv4 et IPv6, la requête est décrite 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;
           };

       où struct inet_diag_sockid est défini 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 être soit AF_INET ou AF_INET6 pour les sockets IPv4 ou IPv6 respectivement.

       sdiag_protocol
              Cela devrait être réglé à IPPROTO_TCP, IPPROTO_UDP ou IPPROTO_UDPLITE.

       idiag_ext
              C’est  un  ensemble  d’indicateurs  définissant  quelle sorte d’informations étendues à rapporter.
              Chaque  sorte  d’informations  est  rapportée  sous  forme  d’attribut  de  netlink  comme  décrit
              ci-dessous :

              INET_DIAG_TOS
                     La charge utile associée à cet attribut est une valeur __u8 qui est le TOS du socket.

              INET_DIAG_TCLASS
                     La  charge  utile  associée  à 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 associée __u8 de charge utile signifiant si le socket est
                     seulement IPv6 ou non.

              INET_DIAG_MEMINFO
                     La charge utile associée à cet attribut est décrite 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 quantité de données dans la file de réception.

                     idiag_wmem  La quantité de données mises dans la file par TCP mais non encore envoyées.

                     idiag_fmem  La quantité de mémoire prévue pour une utilisation future (TCP uniquement).

                     idiag_tmem  La quantité de données dans la file d’émission.

              INET_DIAG_SKMEMINFO
                     La charge utile associée à cet attribut est un tableau de valeurs __u32 décrites ci-dessous
                     dans la sous-section « Informations sur la mémoire de socket ».

              INET_DIAG_INFO
                     La  charge  utile  associée à cet attribut est spécifique à la famille d’adresses. Pour les
                     sockets TCP, c’est un objet de type struct tcp_info.

              INET_DIAG_CONG
                     La charge utile associée avec  cet  attribut  est  une  chaîne  décrivant  l’algorithme  de
                     contrôle de congestion utilisé. Uniquement pour les sockets TCP.

       pad    Cela devrait être réglé à 0.

       idiag_states
              C’est  un  masque  de  bits  définissant un filtre d’états des sockets. Seuls les sockets dont les
              états sont dans le masque seront rapportés. Il est  ignoré  lors  d’une  requête  pour  un  socket
              particulier.

       id     C’est  un  objet d’ID de socket utilisé dans les requêtes de vidage, dans les requêtes à propos de
              sockets particuliers et qui est rapporté dans chaque réponse. Au contraire des sockets de  domaine
              UNIX,  les sockets IPv4 et IPv6 sont identifiés en utilisant des adresses et des ports. Toutes les
              valeurs sont dans l’ordre d’octets du réseau.

       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 numéro d’interface auquel le socket est lié.

       idiag_cookie
              C’est un tableau d’identificateurs opaques pouvant être utilisés dans  d’autres  champs  de  cette
              structure  pour indiquer un socket particulier. Il est ignoré lors d’une requête pour une liste de
              sockets, de même que lorsque tous ses éléments sont réglés à -1.

       La réponse à une requête de sockets IPv4 ou IPv6 est décrite 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 même champ que dans struct inet_diag_req_v2.

       idiag_state
              Cela indique l’état comme dans struct inet_diag_req_v2.

       idiag_timer
              Pour les sockets TCP, ce champ décrit le type de temporisateur actuellement actif pour le  socket.
              Il est réglé à 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 fenêtre nulle

              Pour les sockets non TCP, ce champ doit être réglé à 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 réglé à 0.

       idiag_expires
              Pour  les  sockets  TCP  ayant  un temporisateur actif, ce champ indique son délai d’expiration en
              milliseconde. Pour les autres sockets, ce champ est réglé à 0.

       idiag_rqueue
              Pour les sockets à l’écoute : le nombre de connexions en attente.

              Pour les autres sockets : la quantité de données dans la file d’attente entrante.

       idiag_wqueue
              Pour les sockets à l’écoute : la taille de l’arriéré.

              Pour les autres sockets : la quantité de mémoire disponible pour l’envoi.

       idiag_uid
              C’est l’UID du propriétaire du socket.

       idiag_inode
              Ce champ est le numéro d’inœud de socket.

   Informations sur la mémoire du socket
       La charge utile associée avec les attributs UNIX_DIAG_MEMINFO et INET_DIAG_SKMEMINFO de  netlink  est  un
       tableau des valeurs __u32 suivantes :

       SK_MEMINFO_RMEM_ALLOC
              La quantité de données dans la file d’attente de réception.

       SK_MEMINFO_RCVBUF
              Le tampon de réception de socket comme réglé par SO_RCVBUF.

       SK_MEMINFO_WMEM_ALLOC
              La quantité de données dans la file d’émission.

       SK_MEMINFO_SNDBUF
              Le tampon d’émission de socket comme réglé par SO_SNDBUF.

       SK_MEMINFO_FWD_ALLOC
              La quantité de mémoire prévue pour une utilisation future (TCP uniquement).

       SK_MEMINFO_WMEM_QUEUED
              La quantité de données mises en attente par TCP, mais pas encore envoyées.

       SK_MEMINFO_OPTMEM
              La  quantité  de  mémoire  allouée  pour  les besoins du service du socket (par exemple, filtre du
              socket).

       SK_MEMINFO_BACKLOG
              La quantité de paquets dans l’arriéré (pas encore traité).

VERSIONS

       NETLINK_INET_DIAG a été introduit dans Linux 2.6.14 et ne gère que les sockets AF_INET et AF_INET6.  Dans
       Linux 3.3, il a été renommé NETLINK_SOCK_DIAG et étendu pour gérer les sockets AF_UNIX.

       UNIX_DIAG_MEMINFO et INET_DIAG_SKMEMINFO ont été introduits dans Linux 3.6.

STANDARDS

       Linux.

EXEMPLES

       L’exemple  suivant  affiche le numéro d’inœud, le numéro d’inœud du pair et le nom de tous les sockets de
       domaine UNIX dans l’espace de noms en cours.

       #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;
       }

VOIR AUSSI

       netlink(3), rtnetlink(3), netlink(7), tcp(7)

TRADUCTION

       La  traduction  française   de   cette   page   de   manuel   a   été   créée   par   Christophe   Blaess
       <https://www.blaess.fr/christophe/>,   Stéphan   Rafin   <stephan.rafin@laposte.net>,   Thierry   Vignaud
       <tvignaud@mandriva.com>, François Micaux, Alain Portal  <aportal@univ-montp2.fr>,  Jean-Philippe  Guérard
       <fevrier@tigreraye.org>,   Jean-Luc   Coulon   (f5ibh)   <jean-luc.coulon@wanadoo.fr>,   Julien   Cristau
       <jcristau@debian.org>,     Thomas     Huriaux      <thomas.huriaux@gmail.com>,      Nicolas      François
       <nicolas.francois@centraliens.net>,     Florentin     Duneau    <fduneau@gmail.com>,    Simon    Paillard
       <simon.paillard@resel.enst-bretagne.fr>,    Denis    Barbier    <barbier@debian.org>,    David     Prévot
       <david@tilapin.org> et Jean-Paul Guillonneau <guillonneau.jeanpaul@free.fr>

       Cette  traduction  est  une  documentation libre ; veuillez vous reporter à la GNU General Public License
       version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

       Si vous découvrez un bogue dans la traduction de cette page de manuel,  veuillez  envoyer  un  message  à
       debian-l10n-french@lists.debian.org.

Pages du manuel de Linux 6.8                       2 mai 2024                                       sock_diag(7)