Provided by: manpages-fr_4.18.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

       L’API NETLINK_SOCK_DIAG est spécifique à 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  ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩   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⟩.