UNIX
Table des matières
Retour à l'index
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.
Formats 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 */
};
The sun_family field always contains AF_UNIX. On Linux, sun_path
is 108 bytes in size; see also BUGS, below.
Various system calls (for example, bind(2), connect(2), and
sendto(2)) take a sockaddr_un argument as input. Some other system
calls (for example, getsockname(2), getpeername(2), recvfrom(2),
and accept(2)) return an argument of this type.
Trois types d’adresse sont remarquables dans la structure sockaddr_un :
- pathname
-
a UNIX domain socket can be bound to a null-terminated filesystem pathname
using bind(2). When the address of a pathname socket is returned (by one
of the system calls noted above), its length is
-
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.
- unnamed
-
A stream socket that has not been bound to a pathname using bind(2) has
no name. Likewise, the two sockets created by socketpair(2) are
unnamed. When the address of an unnamed socket is returned, its length is
sizeof(sa_family_t), and sun_path should not be inspected.
- abstract
-
an abstract socket address is distinguished (from a pathname socket) by the
fact that sun_path[0] is a null byte ('\0'). The socket's
address in this namespace is given by the additional bytes in sun_path
that are covered by the specified length of the address structure. (Null
bytes in the name have no special significance.) The name has no connection
with filesystem pathnames. When the address of an abstract socket is
returned, the returned addrlen is greater than sizeof(sa_family_t)
(i.e., greater than 2), and the name of the socket is contained in the first
(addrlen - sizeof(sa_family_t)) bytes of 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
-
This read-only socket option returns the credentials of the peer process
connected to this socket. The returned credentials are those that were in
effect at the time of the call to connect(2), listen(2), or
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 lecture 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 peuvent être nécessaires.
-
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 »)
If a bind(2) call specifies addrlen as sizeof(sa_family_t), or the
SO_PASSCRED socket option was specified for a socket that was not
explicitly bound to an address, then the socket is autobound to an abstract
address. The address consists of a null byte followed by 5 bytes in the
character set [0-9a-f]. Thus, there is a limit of 2ha20 autobind
addresses. (From Linux 2.1.15, when the autobind feature was added, 8 bytes
were used, and the limit was thus 2ha32 autobind addresses. The change
to 5 bytes came in 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.
-
The kernel constant SCM_MAX_FD defines a limit on the number of file
descriptors in the array. Attempting to send an array larger than this
limit causes sendmsg(2) to fail with the error EINVAL. SCM_MAX_FD
has the value 253 (or 255 before Linux 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é.
- ENFILE
-
La limite du nombre total de fichiers ouverts pour le système entier a été
atteinte.
- 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
When binding a socket to an address, Linux is one of the implementations
that append a null terminator if none is supplied in sun_path. In most
cases this is unproblematic: when the socket address is retrieved, it will
be one byte longer than that supplied when the socket was bound. However,
there is one case where confusing behavior can result: if 108 non-null bytes
are supplied when a socket is bound, then the addition of the null
terminator takes the length of the pathname beyond sizeof(sun_path).
Consequently, when retrieving the socket address (for example, via
accept(2)), if the input addrlen argument for the retrieving call is
specified as sizeof(struct sockaddr_un), then the returned address
structure won't have a null terminator in 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)
/* Handle error */ ;
memset(addrp, 0, addrlen + 1);
if (getsockname(sfd, (struct sockaddr *) addrp, &addrlen)) == -1)
/* handle error */ ;
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
/*
* File connection.h
*/
#ifndef CONNECTION_H
#define CONNECTION_H
#define SOCKET_NAME "/tmp/9Lq7BNBnBycd6nxy.socket"
#define BUFFER_SIZE 12
#endif // include guard
/*
* File server.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include "connection.h"
int
main(void)
{
int down_flag = 0;
int ret;
int connection_socket;
int data_socket;
int result;
ssize_t r, w;
struct sockaddr_un name;
char buffer[BUFFER_SIZE];
/* Create local socket. */
connection_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (connection_socket == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
/*
* For portability clear the whole structure, since some
* implementations have additional (nonstandard) fields in
* the structure.
*/
memset(&name, 0, sizeof(name));
/* Bind socket to socket name. */
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);
}
/*
* Prepare for accepting connections. The backlog size is set
* to 20. So while one request is being processed other requests
* can be waiting.
*/
ret = listen(connection_socket, 20);
if (ret == -1) {
perror("listen");
exit(EXIT_FAILURE);
}
/* This is the main loop for handling connections. */
for (;;) {
/* Wait for incoming connection. */
data_socket = accept(connection_socket, NULL, NULL);
if (data_socket == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
result = 0;
for (;;) {
/* Wait for next data packet. */
r = read(data_socket, buffer, sizeof(buffer));
if (r == -1) {
perror("read");
exit(EXIT_FAILURE);
}
/* Ensure buffer is 0-terminated. */
buffer[sizeof(buffer) - 1] = 0;
/* Handle commands. */
if (!strncmp(buffer, "DOWN", sizeof(buffer))) {
down_flag = 1;
continue;
}
if (!strncmp(buffer, "END", sizeof(buffer))) {
break;
}
if (down_flag) {
continue;
}
/* Add received summand. */
result += atoi(buffer);
}
/* Send result. */
sprintf(buffer, "%d", result);
w = write(data_socket, buffer, sizeof(buffer));
if (w == -1) {
perror("write");
exit(EXIT_FAILURE);
}
/* Close socket. */
close(data_socket);
/* Quit on DOWN command. */
if (down_flag) {
break;
}
}
close(connection_socket);
/* Unlink the socket. */
unlink(SOCKET_NAME);
exit(EXIT_SUCCESS);
}
/*
* File client.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include "connection.h"
int
main(int argc, char *argv[])
{
int ret;
int data_socket;
ssize_t r, w;
struct sockaddr_un addr;
char buffer[BUFFER_SIZE];
/* Create local socket. */
data_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (data_socket == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
/*
* For portability clear the whole structure, since some
* implementations have additional (nonstandard) fields in
* the structure.
*/
memset(&addr, 0, sizeof(addr));
/* Connect socket to socket address. */
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, "The server is down.\n");
exit(EXIT_FAILURE);
}
/* Send arguments. */
for (int i = 1; i < argc; ++i) {
w = write(data_socket, argv[i], strlen(argv[i]) + 1);
if (w == -1) {
perror("write");
break;
}
}
/* Request result. */
strcpy(buffer, "END");
w = write(data_socket, buffer, strlen(buffer) + 1);
if (w == -1) {
perror("write");
exit(EXIT_FAILURE);
}
/* Receive result. */
r = read(data_socket, buffer, sizeof(buffer));
if (r == -1) {
perror("read");
exit(EXIT_FAILURE);
}
/* Ensure buffer is 0-terminated. */
buffer[sizeof(buffer) - 1] = 0;
printf("Result = %s\n", buffer);
/* Close 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)
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 à
Index
- NOM
-
- SYNOPSIS
-
- DESCRIPTION
-
- Formats d'adresse
-
- Sockets chemin d’accès
-
- Permissions et appartenance des sockets chemin d’accès
-
- Sockets abstraits
-
- Options de socket
-
- Fonctionnalité d'autolien (« autobind »)
-
- API des sockets
-
- Messages annexes
-
- Ioctls
-
- ERREURS
-
- VERSIONS
-
- NOTES
-
- BOGUES
-
- EXEMPLES
-
- Sortie de l’exemple
-
- Source du programme
-
- VOIR AUSSI
-
- TRADUCTION
-
This document was created by
man2html,
using the manual pages.
Time: 05:06:38 GMT, September 19, 2025