unix

UNIX(7)                    Manuel du programmeur Linux                   UNIX(7)



NOM
       unix – Sockets pour communications locales entre processus

SYNOPSIS
       #include <sys/socket.h>
       #include <sys/un.h>

       unix_socket = socket(AF_UNIX, type, 0);
       error = socketpair(AF_UNIX, type, 0, int *sv);

DESCRIPTION
       La famille de sockets AF_UNIX (aussi connue sous le nom de AF_LOCAL) sert
       à communiquer efficacement entre processus sur la même machine.
       Traditionnellement, les sockets de domaine UNIX peuvent ne pas être
       nommés ou bien être liés à un chemin d'accès de système de fichiers,
       lequel sera marqué comme étant de type socket. Linux gère également un
       espace de noms abstrait, indépendant du système de fichiers.

       Les types de sockets valables dans le domaine UNIX sont : SOCK_STREAM
       pour un socket orienté flux et SOCK_DGRAM pour un socket orienté
       datagramme qui préserve les limites entre messages (comme sur la plupart
       des implémentations UNIX, les sockets datagramme de domaine UNIX sont
       toujours fiables et ne réordonnent pas les datagrammes), et (depuis
       Linux 2.6.4) SOCK_SEQPACKET pour un socket orienté connexion, préservant
       les limites entre messages et délivrant les messages dans l'ordre où ils
       ont été envoyés.

       Les sockets de domaine UNIX prennent en charge la transmission de
       descripteurs de fichier ou d'accréditations d'un processus à l'autre en
       utilisant des données annexes.

   Format d'adresse
       Une adresse de socket de domaine UNIX est représentée dans la structure
       suivante :

           struct sockaddr_un {
               sa_family_t sun_family;               /* AF_UNIX */
               char        sun_path[108];            /* Chemin d’accès */
           };

       Le champ sun_family contient toujours AF_UNIX. Dans Linux, sun_path a
       pour taille 108 octets. Consultez NOTES, ci-dessous.

       Divers appels système (par exemple, bind(2), connect(2) et sendto(2))
       prennent un argument sockaddr_un en entrée. D’autres appels système (par
       exemple, getsockname(2), getpeername(2), recvfrom(2) et accept(2))
       renvoient un argument de ce type.

       Trois types d’adresse sont remarquables dans la structure sockaddr_un :

       *  chemin d'accès : un socket de domaine UNIX peut être lié, avec
          bind(2), à un système de fichiers dont le chemin d'accès est une
          chaîne de caractères terminée par l’octet NULL. Lorsque l'adresse du
          socket est obtenue (avec un des appels système ci-dessus) sa longueur
          vaut

              offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1

          et sun_path contient le chemin avec un octet NULL final. (Dans Linux,
          l’expression ci-dessus offsetof() est égale à la même valeur que
          sizeof(sa_family_t), mais quelques autres implémentations incluent
          d’autres champs avant sun_path, aussi l’expression offsetof() plus
          portable décrit la taille de la structure d’adresse.)

          Pour plus de détails sur les sockets chemin, voir ci-après.

       *  sans_nom : un socket flux qui n'a pas été lié à un chemin d'accès avec
          bind(2) n'a pas de nom. De la même façon, les deux sockets créés avec
          socketpair(2) ne sont pas nommés. Lorsque l'adresse d'un socket sans
          nom est obtenue, sa longueur vaut sizeof(sa_family_t) et il n'est pas
          nécessaire de vérifier sun_path.

       *  abstrait : une adresse de socket abstrait se distingue d’un socket de
          chemin par le fait que sun_path[0] est un octet NULL (« \0 »).
          L'adresse du socket dans cet espace de noms est donnée par le reste
          des octets dans sun_path qui sont enrobés dans la longueur indiquée de
          la structure d'adresse. (Les octets NULL dans le nom n'ont pas de
          signification particulière.) Le nom n'a aucun rapport avec les chemins
          d'accès de systèmes de fichiers. Lorsque l'adresse d'un socket
          abstrait est obtenue, l'addrlen obtenue est plus grande que
          sizeof(sa_family_t) (c'est-à-dire plus grande que 2), et le nom du
          socket est contenu dans les premiers bits
          (addrlen - sizeof(sa_family_t)) de sun_path.

   Sockets chemin d’accès
       Lors de la liaison d’un socket à un chemin, quelques règles doivent être
       observées pour une portabilité maximale et une facilité de codage :

       *  Le chemin dans sun_path doit être terminé par un octet NULL ;

       *  La taille du chemin, y compris l’octet NULL final, ne doit pas excéder
          la taille de sun_path ;

       *  L’argument addrlen décrivant la structure enfermant sockaddr_un doit
          avoir une valeur d’au moins :

              offsetof(struct sockaddr_un, sun_path)+strlen(addr.sun_path)+1

          ou, plus simplement, addrlen peut être indiqué comme
          sizeof(struct sockaddr_un).

       Il y a quelques variations dans la façon dont les implémentations gèrent
       les adresses de socket de domaine UNIX qui ne suivent pas les règles
       ci-dessus.Par exemple, quelques implémentations (mais pas toutes)
       ajoutent un octet NULL final si aucun n’est présent dans le sun_path
       fourni.

       Lors du codage d’applications portables, il faut penser que certaines
       implémentations ont un sun_path aussi court que 92 octets.

       Divers appels système (accept(2), recvfrom(2), getsockname(2),
       getpeername(2)) renvoient les structures d’adresse de socket. Lorsque
       appliqué à des sockets de domaine UNIX, l’argument « value-result »
       addrlen fourni à l’appel devrait être initialisé comme ci-dessus. Au
       renvoi, l’argument est réglé pour indiquer la taille réelle de la
       structure d’adresse. L’appelant devrait vérifier la valeur renvoyée dans
       cet argument. Si la valeur de sortie excède la valeur d’entrée, alors il
       n’y a aucune garantie qu’un octet NULL final soit présent dans sun_path.
       (Consultez BOGUES.)

   Permissions et appartenance des sockets chemin d’accès
       Dans l’implémentation de Linux, les sockets chemin d'accès respectent les
       permissions du répertoire dans lequel ils sont. La création d’un nouveau
       socket échoue si le processus n’a pas les permissions d’écriture et de
       recherche (exécution) dans le répertoire où le socket est créé.

       Dans Linux, la connexion à un objet de socket flux nécessite la
       permission en écriture sur ce socket. De même, l’envoi d’un datagramme à
       un socket datagramme nécessite la permission en écriture sur ce socket.
       POSIX ne fait aucune déclaration sur les effets des permissions sur un
       fichier de socket, et sur certains systèmes (par exemple, les BSD
       anciens) les permissions de socket sont ignorées. Les programmes
       portables ne devraient pas se fier à cette fonctionnalité pour la
       sécurité.

       Lors de la création d’un nouveau socket, le propriétaire et le groupe
       d’un fichier de socket sont définis selon les règles habituelles. Le
       fichier de socket a toutes les permissions activées, autres que celles
       désactivées par le processus umask(2).

       Le propriétaire, le groupe et les permissions d’un socket chemin d'accès
       peuvent être modifiés (avec chown(2) et chmod(2)).

   Sockets abstraits
       Les permissions de socket n’ont aucun sens pour les sockets abstraits :
       le processus umask(2) n’a aucun effet lors de la liaison d’un socket
       abstrait et modifier le propriétaire et les permissions de l’objet (avec
       fchown(2) et fchmod(2)) n’a aucun effet sur l’accessibilité du socket.

       Les sockets abstraits disparaissent automatiquement quand toutes les
       références de socket ouvertes sont refermées.

       L’espace de noms de sockets abstraits est une extension non portable de
       Linux.

   Options de socket
       Pour des raisons historiques, les options de ces sockets sont indiquées
       avec un type SOL_SOCKET même si elles sont spécifiques à AF_UNIX. Elles
       peuvent être définies avec setsockopt(2) et lues avec getsockopt(2) en
       indiquant SOL_SOCKET comme famille de sockets.

       SO_PASSCRED
              Activer cette option de socket provoque la réception des
              accréditations du processus émetteur dans un message
              SCM_CREDENTIALS annexe dans chaque message reçu ultérieur. Les
              accréditations renvoyées sont celles indiquées par l’émetteur en
              utilisant SCM_CREDENTIALS ou celles par défaut qui incluent le
              PID, l’ID utilisateur réel et l’ID groupe réel de l’émetteur si
              celui-ci ne précise pas les données auxiliaires SCM_CREDENTIALS.

              Lorsque cette option est active et le socket non encore connecté,
              un nom unique dans l'espace de noms abstrait sera généré
              automatiquement.

              La valeur donnée comme argument pour setsockopt(2) et renvoyée
              comme résultat de getsockopt(2) est un indicateur booléen entier.

       SO_PASSSEC
              Activer la réception de l’étiquette de sécurité SELinux du socket
              pair dans un message annexe de type SCM_SECURITY (voir
              ci-dessous).

              La valeur donnée comme argument pour setsockopt(2) et renvoyée
              comme résultat de getsockopt(2) est un indicateur booléen entier.

              L’option SO_PASSSEC est gérée par les sockets datagramme de
              domaine UNIX depuis Linux 2.6.18. La prise en charge pour les
              sockets flux de domaine UNIX a été ajoutée dans Linux 4.2.

       SO_PEEK_OFF
              Consulter socket(7).

       SO_PEERCRED
              Cette option de socket en écriture exclusivement renvoie les
              accréditations du processus pair connecté à ce socket. Les
              accréditations renvoyées sont celles effectives au moment de
              l’appel à connect(2) ou socketpair(2).

              L’argument de getsockopt(2) est un pointeur vers une structure
              ucred. Est définie la macro de test de fonctionnalité _GNU_SOURCE
              pour obtenir la définition de cette structure à partir de
              <sys/socket.h>.

              L’utilisation de cette option est possible seulement pour les
              sockets flux AF_UNIX connectés et pour les pairs de sockets flux
              et datagramme AF_UNIX créés en utilisant socketpair(2).

       SO_PEERSEC
              Cette option de socket en écriture exclusivement renvoie le
              contexte de sécurité du socket pair connecté à ce socket. Par
              défaut, cela sera le même que le contexte de sécurité du processus
              ayant créé le socket pair à moins qu’il ne soit écrasé par la
              politique ou par un processus ayant les permissions requises.

              L’argument de getsockopt(2) est un pointeur vers un tampon de la
              longueur indiquée en octets dans lequel la chaîne de contexte de
              sécurité sera copiée. Si la taille du tampon est inférieure à
              celle de la chaîne du contexte de sécurité, alors getsockopt(2)
              renvoie -1, définit errno à ERANGE et renvoie la taille requise à
              l’aide de optlen. L’appelant doit allouer initialement au moins
              NAME_MAX octets pour le tampon, bien que cela ne soit pas garanti
              d'être suffisant. Redimensionner le tampon à la taille renvoyée et
              réessayer peut être nécessaire.

              La chaîne de contexte de sécurité peut inclure un octet NULL final
              dans la taille renvoyée, mais il n’est pas garanti que ce soit
              fait : un contexte de sécurité « abc » peut être représenté soit
              par {'a','b','c'} de taille 3, ou {'a','b','c','\0'} de taille 4,
              qui sont considérés comme interchangeables. La chaîne peut être
              affichée, mais ne contient pas d’octet NULL final, et elle est
              dans un encodage non précisé (en particulier, il n’est pas garanti
              que ce soit ASCII ou UTF-8).

              L’utilisation de cette option pour les sockets dans la famille
              d’adresses AF_UNIX est prise en charge depuis Linux 2.6.2 pour les
              sockets flux connectés et aussi, depuis Linux 4.18, pour les pairs
              de socket flux et datagramme créés en utilisant socketpair(2).

   Fonctionnalité d'autolien (« autobind »)
       Si un appel bind(2) indique addrlen comme sizeof(sa_family_t), ou si
       l'option de socket SO_PASSCRED était indiquée pour un socket qui n'était
       pas lié explicitement à une adresse, alors le socket est autolié à une
       adresse abstraite. L'adresse est constituée d'un octet NULL suivi par
       cinq octets de l'ensemble de caractères [0-9a-f]. Le nombre d'adresses
       autoliées est donc limité à 2^20 (à partir de Linux 2.1.15, quand la
       fonctionnalité d'autolien a été ajoutée, huit octets étaient utilisés et
       le nombre d'adresses autoliées était donc limité à 2^32. La modification
       à cinq octets est intervenue avec Linux 2.3.15).

   API des sockets
       Les paragraphes suivants décrivent des détails spécifiques aux domaines
       et des fonctionnalités de l'API des sockets de domaine UNIX non prises en
       charge sous Linux.

       Les sockets de domaine UNIX ne prennent pas en charge la transmission de
       données hors-bande (l'indicateur MSG_OOB de send(2) et recv(2)).

       L'indicateur MSG_MORE de send(2) n'est pas pris en charge sur les sockets
       de domaine UNIX.

       Avant Linux 3.4, l'utilisation de MSG_TRUNC dans le paramètre flags de
       recv(2) n'était pas prise en charge par les sockets de domaine UNIX.

       L'option SO_SNDBUF de socket a un effet pour les sockets de domaine UNIX,
       mais l’option SO_RCVBUF n'en a pas. Pour les sockets datagramme, la
       valeur SO_SNDBUF impose une limite supérieure à la taille des datagrammes
       sortants. Cette limite est calculée comme le double de la valeur de
       l'option, moins 32 octets utilisés par le surdébit.

   Messages annexes
       Les données annexes sont envoyées et reçues en utilisant sendmsg(2) et
       recvmsg(2). Pour des raisons historiques, les messages annexes listés
       ci-dessous sont indiqués avec un type SOL_SOCKET même s'ils sont
       spécifiques AF_UNIX. Pour les envoyer, définissez le champ cmsg_level de
       la structure cmsghdr à SOL_SOCKET et le champ cmsg_type au type. Pour
       plus de détails, consultez cmsg(3).

       SCM_RIGHTS
              Envoyer ou recevoir un jeu de descripteurs de fichier ouverts d’un
              autre processus. La partie données contient un tableau d’entiers
              de descripteurs de fichier.

              Couramment, cette opération est appelée « passage d’un descripteur
              de fichier » à un autre processus. Cependant, plus précisément, ce
              qui a été passé est une référence à une description de fichier
              ouvert (consultez open(2)), et, dans le processus récepteur, il
              est probable qu’un numéro différent de descripteur de fichier sera
              utilisé. Sémantiquement, cette opération est équivalente à
              dupliquer (dup(2)) un descripteur de fichier dans une table de
              descripteurs de fichier d’un autre processus.

              Si le tampon utilisé pour recevoir les données annexes contenant
              les descripteurs de fichier est trop petit (ou absent), alors les
              données annexes sont tronquées (ou ignorées) et les descripteurs
              de fichier en excès sont automatiquement clos dans le processus
              récepteur.

              Si le nombre de descripteurs de fichier reçus dans les données
              annexes conduit le processus à dépasser la limite de ressources
              RLIMIT_NOFILE (consultez getrlimit(2)), les descripteurs de
              fichier en excès sont automatiquement clos dans le processus
              récepteur.

              La constante du noyau SCM_MAX_FD définit une limite au nombre de
              descripteurs de fichier dans la table. Essayer d’envoyer une table
              plus grande que cette limite provoque l’échec de sendmsg(2) avec
              l’erreur EINVAL. SCM_MAX_FD a la valeur 253 (ou 255 dans les
              noyaux avant 2.6.38).

       SCM_CREDENTIALS
              Envoyer ou recevoir les accréditations UNIX. Cela peut servir à
              l'authentification. Les accréditations sont passées en message
              annexe struct ucred. Cette structure est définie dans
              <sys/socket.h> comme ceci :

                  struct ucred {
                      pid_t pid;    /* PID processus émetteur */
                      uid_t uid;    /* UID processus émetteur */
                      gid_t gid;    /* GID processus émetteur */
                  };

              Depuis la glibc 2.8, la macro de test de fonctionnalités
              _GNU_SOURCE doit être définie (avant d'inclure tout fichier d'en‐
              tête) afin d'obtenir la définition de cette structure.

              Les accréditations que l'émetteur envoie sont vérifiées par le
              noyau. Un processus privilégié est autorisé à indiquer des valeurs
              qui ne correspondent pas aux siennes. L'émetteur doit indiquer son
              propre PID (sauf s'il a la capacité CAP_SYS_ADMIN), auquel cas le
              PID de n’importe quel processus existants peut être indiqué, son
              ID utilisateur réel, son ID utilisateur effectif ou son « saved
              set-user-ID » (sauf s'il a la capacité CAP_SETUID) et son ID
              groupe réel, son ID groupe effectif ou son « saved set-group-ID »
              (sauf s'il a la capacité CAP_SETGID).

              Pour recevoir un message struct ucred, l’option SO_PASSCRED doit
              être activée sur le socket.

       SCM_SECURITY
              Recevoir le contexte de sécurité SELinux (l’étiquette de sécurité)
              du socket pair. Les données annexes reçues sont une chaîne
              terminée par un octet NULL final contenant le contexte de
              sécurité. Le récepteur doit au moins allouer NAME_MAX octets dans
              la partie données du message annexe pour ces données.

              Pour recevoir le contexte de sécurité, l’option SO_PASSSEC doit
              être activée sur le socket (voir ci-dessus).

       Lors de l’envoi des données annexes avec sendmsg(2), seul un élément de
       chacun des types ci-dessus peut être inclus dans le message envoyé.

       Au moins un octet des données réelles doit être envoyé lors de l’envoi
       des données annexes. Sur Linux, cela est nécessaire pour envoyer avec
       succès les données annexes sur un socket flux de domaine UNIX. Lors de
       l’envoi des données annexes à travers un socket datagramme de domaine
       UNIX, il n’est pas nécessaire sur Linux d’envoyer en accompagnement une
       donnée quelconque réelle. Cependant, les applications portables devraient
       aussi inclure au moins un octet des données réelles lors de l’envoi de
       données annexes à travers un socket datagramme.

       Lors de la réception à partir d’un socket flux, les données annexes
       forment une sorte de barrière pour les données reçues. Par exemple, en
       supposant que l’émetteur transmet comme suit :

              1. sendmsg(2) de quatre octets sans données annexes.
              2. sendmsg(2) d’un octet avec données annexes.
              3. sendmsg(2) de quatre octets sans données annexes.

       En supposant que le récepteur réalise maintenant des appels recvmsg(2)
       avec chacun une taille de tampon de 20 octets, le premier appel recevra
       5 octets de données, avec les données annexes envoyées par le second
       appel sendmsg(2). Le prochain appel recevra les 4 octets de données
       restants.

       Si l’espace alloué pour recevoir les données annexes entrantes est trop
       petit, alors ces données sont tronquées au nombre d’en-têtes qui peuvent
       loger dans le tampon fourni (ou, dans le cas de liste de descripteurs de
       fichier SCM_RIGHTS, cette liste peut être tronquée). Si aucun tampon
       n’est fourni pour les données annexes entrantes (c’est-à-dire si le champ
       msg_control de la structure msghdr fourni à recvmsg(2) est NULL), alors
       les données annexes entrantes sont ignorées. Dans les deux cas,
       l’indicateur MSG_CTRUNC sera réglé dans la valeur msg.msg_flags renvoyée
       par recvmsg(2).

   Ioctls
       Les appels ioctl(2) suivants renvoient des informations dans value. La
       syntaxe correcte est :

              int value;
              error = ioctl(unix_socket, ioctl_type, &value);

       ioctl_type peut être :

       SIOCINQ
              Pour les sockets SOCK_STREAM, cet appel renvoie la quantité de
              données non lues dans le tampon de réception. Le socket ne doit
              pas être dans l'état LISTEN, sinon l'erreur EINVAL est renvoyée.
              SIOCINQ est défini dans <linux/sockios.h>. Une alternative est
              d'utiliser le synonyme FIONREAD défini dans <sys/ioctl.h>. Pour
              les sockets SOCK_DGRAM, la valeur renvoyée est la même que pour
              les sockets datagramme de domaine Internet. Consultez udp(7).

ERREURS
       EADDRINUSE
              L'adresse locale indiquée est déjà utilisée ou l'objet de socket
              de système de fichiers existe déjà.

       EBADF  Cette erreur peut survenir pour sendmsg(2) lors de l’envoi d’un
              descripteur de fichier pour des données annexes au travers d’un
              socket de domaine UNIX (consultez la description de SCM_RIGHTS
              ci-dessus) et indique que le numéro de descripteur de fichier
              envoyé n’est pas valable (par exemple, ce n’est pas un descripteur
              de fichier ouvert).

       ECONNREFUSED
              L'adresse distante indiquée par connect(2) n'était pas un socket
              en écoute. Cette erreur peut également se produire si le nom de
              chemin cible n'est pas un socket.

       ECONNRESET
              Le socket distant a été fermé de manière inattendue.

       EFAULT Adresse mémoire utilisateur incorrecte.

       EINVAL Argument passé non valable. Une cause habituelle est que la valeur
              de AF_UNIX n'était pas indiquée dans le champ sun_type des
              adresses passées ou que le socket était dans un état non valable
              pour l'opération appliquée.

       EISCONN
              connect(2) a été appelée sur un socket déjà connecté ou l'adresse
              cible a été indiquée sur un socket connecté.

       ENOENT Le chemin de l'adresse distante indiquée à connect(2) n'existait
              pas.

       ENOMEM Plus assez de mémoire.

       ENOTCONN
              L'opération nécessite une adresse cible, mais le socket n'est pas
              connecté.

       EOPNOTSUPP
              Opération de flux appelée sur un socket non orienté flux ou
              tentative d'utiliser une option de données hors-bande.

       EPERM  L'émetteur a transmis des accréditations incorrectes dans
              struct ucred.

       EPIPE  Le socket distant a été fermé à cause d’un socket flux. Si activé,
              un signal SIGPIPE est émis également. Cela peut être évité en
              passant l'indicateur MSG_NOSIGNAL dans send(2) ou sendmsg(2).

       EPROTONOSUPPORT
              Le protocole fourni n'est pas AF_UNIX.

       EPROTOTYPE
              Le socket distant ne correspond pas au type de socket local
              (SOCK_DGRAM versus SOCK_STREAM)

       ESOCKTNOSUPPORT
              Type de socket inconnu.

       ESRCH  Lors de l’envoi d’un message annexe contenant des accréditations
              (SCM_CREDENTIALS), l’appelant a indiqué un PID ne correspondant à
              aucun processus existant.

       ETOOMANYREFS
              Cette erreur peut se produire pour sendmsg(2) lors de l’envoi d’un
              descripteur de fichier pour des données annexes à travers un
              socket de domaine UNIX (consultez la description de SCM_RIGHTS,
              ci-dessus). Cela se produit si le nombre de descripteurs de
              fichier « en cours » excède la limite de ressources RLIMIT_NOFILE
              et si l’appelant n’a pas la capacité CAP_SYS_RESOURCE. Un
              descripteur de fichier en cours est un descripteur qui a été
              envoyé en utilisant sendmsg(2) mais qui n’a pas encore été accepté
              dans le processus récepteur en utilisant recvmsg(2).

              Cette erreur est décelée depuis Linux 4.5 (et dans quelques
              versions précédentes dans lesquelles le correctif a été
              rétroporté). Dans les versions du noyau précédentes, il était
              possible d’avoir un nombre illimité de descripteurs de fichier en
              cours en envoyant chaque descripteur de fichier avec sendmsg(2) et
              ensuite en fermant le descripteur de fichier de telle façon qu’il
              ne soit pas pris en compte pour la limite de ressources
              RLIMIT_NOFILE.

       D'autres erreurs peuvent être déclenchées par la couche générique de
       socket ou par le système de fichiers lors de la génération d’un objet
       socket de système de fichiers. Consultez les pages de manuel
       correspondantes pour plus de détails.

VERSIONS
       SCM_CREDENTIALS et l'espace de noms abstrait ont été introduits avec
       Linux 2.2 et ne doivent pas être utilisés dans des programmes portables.
       (Certains systèmes dérivés de BSD prennent aussi en charge le passage
       d'accréditations, mais les détails d'implémentation diffèrent).

NOTES
       Lier un socket avec un nom de fichier crée un socket dans le système de
       fichiers que l’appelant doit détruire lorsqu'il n'est plus utile (en
       utilisant unlink(2)). La sémantique habituelle la plus proche d’UNIX
       s'applique ; le socket peut être délié à tout moment et sera finalement
       supprimé du système de fichiers lorsque sa dernière référence sera
       fermée.

       To pass file descriptors or credentials over a SOCK_STREAM socket, you
       must send or receive at least one byte of nonancillary data in the same
       sendmsg(2)  or recvmsg(2)  call.

       Les sockets flux de domaine UNIX ne prennent pas en charge la notion de
       données hors-bande.

BOGUES
       Lors de la liaison d’un socket à une adresse, Linux est une des
       implémentations qui ajoute un octet NULL final si aucun n’est fourni dans
       sun_path. Dans la plupart des cas cela ne pose aucun problème : quand
       l’adresse du socket est récupérée, elle sera plus grande d’un octet que
       celle fournie lors de la liaison du socket. Cependant, il existe un cas
       où un comportement déroutant peut se produire : si 108 octets non NULL
       sont fournis quand un socket est lié, alors l’ajout de l’octet NULL final
       incorpore la longueur du nom de chemin au-delà de sizeof(sun_path). Par
       conséquent, lors de la récupération de l’adresse du socket (par exemple,
       à l’aide de accept(2)), si l’argument addrlen de l’entrée pour l’appel de
       récupération est indiqué comme sizeof(struct sockaddr_un), alors la
       structure d’adresse renvoyée n’aura pas d’octet NULL final dans sun_path.

       De plus, quelques implémentations n’ont pas besoin d’octet NULL final
       lors de liaison d’un socket (l’argument addrlen est utilisé pour
       déterminer la taille de sun_path) et lorsqu’une adresse de socket est
       récupérée sur ces implémentations, il n’y a pas d’octet NULL final dans
       sun_path.

       Les applications qui récupèrent les adresses de socket peuvent coder (de
       manière portable) pour gérer la possibilité d’absence d’octet NULL final
       dans sun_path en respectant le fait que le nombre d’octets autorisés dans
       le nom de chemin est :

           strnlen(addr.sun_path, addrlen - offsetof(sockaddr_un, sun_path))

       Sinon, une application peut récupérer l’adresse de socket en allouant un
       tampon de taille sizeof(struct sockaddr_un)+1 mis à zéro avant la
       récupération. L’appel de récupération peut préciser addrlen comme
       sizeof(struct sockaddr_un) et l’octet zéro supplémentaire assure qu’il y
       aura un octet NULL final dans la chaîne renvoyée dans sun_path :

           void *addrp;

           addrlen = sizeof(struct sockaddr_un);
           addrp = malloc(addrlen + 1);
           if (addrp == NULL)
               /* Gérer l’erreur */ ;
           memset(addrp, 0, addrlen + 1);

           if (getsockname(sfd, (struct sockaddr *) addrp, &addrlen)) == -1)
               /* Gérer l’erreur */ ;

           printf("sun_path = %s\n", ((struct sockaddr_un *) addrp)->sun_path);

       Cette sorte de désordre peut être évité s’il est garanti que les
       applications qui créent les sockets de chemin suivent les règles exposées
       ci-dessus dans Sockets chemin d’accès.

EXEMPLES
       Le code suivant démontre l’utilisation de sockets de paquets ordonnés
       pour une communication inter-processus locale. Il est constitué de deux
       programmes. Le programme serveur attend une connexion d’un programme
       client. Le client envoie chacun de ses arguments de ligne de commande
       dans des messages séparés. Le serveur traite les messages entrants comme
       des entiers et fait leur somme. Le client envoie la chaîne de commande
       « END ». Le serveur renvoie un message contenant la somme des entiers du
       client. Le client affiche la somme et quitte. Le serveur attend la
       connexion d’un nouveau client. Pour stopper le serveur, le client est
       appelé avec l’argument de ligne de commande « DOWN ».

       La sortie suivante a été enregistrée alors que le serveur fonctionnait en
       arrière-plan et en exécutant le client de façon répétée. L’exécution du
       programme du serveur se termine quand il reçoit la commande « DOWN ».

   Sortie de l’exemple
           $ ./server &
           [1] 25887
           $ ./client 3 4
           Result = 7
           $ ./client 11 -5
           Result = 6
           $ ./client DOWN
           Result = 0
           [1]+  Done                    ./server
           $

   Source du programme

       /*
        * Fichier connection.h
        */

       #define SOCKET_NAME "/tmp/9Lq7BNBnBycd6nxy.socket"
       #define BUFFER_SIZE 12

       /*
        * Fichier server.c
        */

       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <sys/socket.h>
       #include <sys/un.h>
       #include <unistd.h>
       #include "connection.h"

       int
       main(int argc, char *argv[])
       {
           struct sockaddr_un name;
           int down_flag = 0;
           int ret;
           int connection_socket;
           int data_socket;
           int result;
           char buffer[BUFFER_SIZE];

           /* Création du socket local. */

           connection_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
           if (connection_socket == -1) {
               perror("socket");
               exit(EXIT_FAILURE);
           }

           /*
            * Pour la portabilité effacer la structure entière, puisque
            * quelques implémentations ont des champs (non standard)
            * supplémentaires dans la structure.
            */

           memset(&name, 0, sizeof(name));

           /* Liaison du socket au nom de socket. */

           name.sun_family = AF_UNIX;
           strncpy(name.sun_path, SOCKET_NAME, sizeof(name.sun_path) - 1);

           ret = bind(connection_socket, (const struct sockaddr *) &name,
                      sizeof(name));
           if (ret == -1) {
               perror("bind");
               exit(EXIT_FAILURE);
           }

           /*
            * Préparation à accepter les connexions. La taille de réserve
            * est réglée à 20. Aussi tandis qu’une requête est traitée,
            * d’autres peuvent être en attente.
            */

           ret = listen(connection_socket, 20);
           if (ret == -1) {
               perror("listen");
               exit(EXIT_FAILURE);
           }

           /* Ceci est la boucle principale pour gérer les connexions. */

           for (;;) {

               /* Attendre des connexions entrantes. */

               data_socket = accept(connection_socket, NULL, NULL);
               if (data_socket == -1) {
                   perror("accept");
                   exit(EXIT_FAILURE);
               }

               result = 0;
               for (;;) {

                   /* Attendre le prochain paquet de données. */

                   ret = read(data_socket, buffer, sizeof(buffer));
                   if (ret == -1) {
                       perror("read");
                       exit(EXIT_FAILURE);
                   }

                   /* Assurer que le tampon soit terminé par NULL. */

                   buffer[sizeof(buffer) - 1] = 0;

                   /* Gérer les commandes. */

                   if (!strncmp(buffer, "DOWN", sizeof(buffer))) {
                       down_flag = 1;
                       break;
                   }

                   if (!strncmp(buffer, "END", sizeof(buffer))) {
                       break;
                   }

                   /* Faire la somme des termes reçus. */

                   result += atoi(buffer);
               }

               /* Envoyer le résultat. */

               sprintf(buffer, "%d", result);
               ret = write(data_socket, buffer, sizeof(buffer));
               if (ret == -1) {
                   perror("write");
                   exit(EXIT_FAILURE);
               }

               /* Fermer le socket. */

               close(data_socket);

               /* Quitter avec la commande DOWN. */

               if (down_flag) {
                   break;
               }
           }

           close(connection_socket);

           /* Délier le socket. */

           unlink(SOCKET_NAME);

           exit(EXIT_SUCCESS);
       }

       /*
        * Fichier client.c
        */

       #include <errno.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <sys/socket.h>
       #include <sys/un.h>
       #include <unistd.h>
       #include "connection.h"

       int
       main(int argc, char *argv[])
       {
           struct sockaddr_un addr;
           int ret;
           int data_socket;
           char buffer[BUFFER_SIZE];

           /* Création du socket local. */

           data_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
           if (data_socket == -1) {
               perror("socket");
               exit(EXIT_FAILURE);
           }

           /*
            * Pour la portabilité effacer la structure entière, puisque
            * quelques implémentations ont des champs (non standard)
            * supplémentaires dans la structure.
            */

           memset(&addr, 0, sizeof(addr));

           /* Connecter le socket à l’adresse de socket. */

           addr.sun_family = AF_UNIX;
           strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);

           ret = connect(data_socket, (const struct sockaddr *) &addr,
                          sizeof(addr));
           if (ret == -1) {
               fprintf(stderr, "Le serveur est arrêté.\n");
               exit(EXIT_FAILURE);
           }

           /* Envoyer les arguments. */

           for (int i = 1; i < argc; ++i) {
               ret = write(data_socket, argv[i], strlen(argv[i]) + 1);
               if (ret == -1) {
                   perror("write");
                   break;
               }
           }

           /* Résultat de la requête. */

           strcpy(buffer, "END");
           ret = write(data_socket, buffer, strlen(buffer) + 1);
           if (ret == -1) {
               perror("write");
               exit(EXIT_FAILURE);
           }

           /* Recevoir le résultat. */

           ret = read(data_socket, buffer, sizeof(buffer));
           if (ret == -1) {
               perror("read");
               exit(EXIT_FAILURE);
           }

           /* Assurer que le tampon soit terminé par NULL. */

           buffer[sizeof(buffer) - 1] = 0;

           printf("Result = %s\n", buffer);

           /* Fermer le socket. */

           close(data_socket);

           exit(EXIT_SUCCESS);
       }

       For examples of the use of SCM_RIGHTS, see cmsg(3)  and
       seccomp_unotify(2).

VOIR AUSSI
       recvmsg(2), sendmsg(2), socket(2), socketpair(2), cmsg(3),
       capabilities(7), credentials(7), socket(7), udp(7)

COLOPHON
       Cette page fait partie de la publication 5.13 du projet man-pages Linux.
       Une description du projet et des instructions pour signaler des anomalies
       et la dernière version de cette page peuvent être trouvées à l'adresse
       https://www.kernel.org/doc/man-pages/.


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 ⟨⟩.




Linux                             22 mars 2021                           UNIX(7)