packet
Table des matières
Retour à l'index
NOM
packet – Interface de paquets au niveau du périphérique
SYNOPSIS
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <net/ethernet.h> /* Les protocoles L2 */
packet_socket = socket(AF_PACKET, int type_socket, int protocole);
DESCRIPTION
Les sockets packet sont utilisés pour envoyer ou recevoir des paquets bruts
au pilote de périphérique (couche 2 OSI). Ils permettent d'implémenter des
modules de protocole dans l'espace utilisateur au-dessus de la couche
physique.
The socket_type is either SOCK_RAW for raw packets including the
link-level header or SOCK_DGRAM for cooked packets with the link-level
header removed. The link-level header information is available in a common
format in a sockaddr_ll structure. protocol is the IEEE 802.3
protocol number in network byte order. See the
<linux/if_ether.h> include file for a list of allowed protocols.
When protocol is set to htons(ETH_P_ALL), then all protocols are
received. All incoming packets of that protocol type will be passed to the
packet socket before they are passed to the protocols implemented in the
kernel. If protocol is set to zero, no packets are received. bind(2)
can optionally be called with a nonzero sll_protocol to start receiving
packets for the protocols specified.
Pour pouvoir créer des sockets packet, un processus doit posséder la
capacité CAP_NET_RAW dans l’espace de noms utilisateur qui régit son
espace de noms réseau.
Les paquets SOCK_RAW sont transmis depuis et vers le pilote de
périphérique sans aucune modification des données des paquets. Lors de la
réception d’un paquet, l'adresse est toujours examinée et fournie dans une
structure standard d’adresse sockaddr_ll. Lors de l'émission d'un paquet,
le tampon fourni par l'utilisateur doit contenir l'en-tête de couche
physique. Le paquet est alors mis en attente sans modification à l'attention
du pilote de périphérique correspondant à l'interface définie par l'adresse
de destination. Certains pilotes de périphérique ajoutent toujours d'autres
en-têtes. SOCK_RAW est similaire mais non compatible avec l'ancien
AF_INET/SOCK_PACKET de Linux 2.0.
SOCK_DGRAM opère à un niveau légèrement plus élevé. L'en-tête de couche
physique est supprimé avant que le paquet ne soit transmis à
l'utilisateur. Les paquets envoyés par un socket packet SOCK_DGRAM
reçoivent un en-tête de couche physique correct basé sur les informations
dans l'adresse destination sockaddr_ll avant d'être mis en attente.
Par défaut, tous les paquets du type de protocole indiqué sont passés au
socket packet. Pour ne recevoir que les paquets d'une interface donnée,
utilisez bind(2) en indiquant une adresse dans une struct sockaddr_ll
pour attacher le socket à une interface. Les champs utilisés pour la liaison
sont sll_family (devrait être AF_PACKET), sll_protocol et
sll_ifindex.
L'opération connect(2) n'est pas prise en charge sur les sockets packet.
Lorsque l'attribut MSG_TRUNC est transmis à recvmsg(2), recv(2) ou
recvfrom(2), la véritable longueur du paquet sur le réseau est toujours
renvoyée, même si elle est plus grande que le tampon.
Types d’adresses
La structure sockaddr_ll est une adresse de couche physique indépendante
du périphérique.
struct sockaddr_ll {
unsigned short sll_family; /* Toujours AF_PACKET */
unsigned short sll_protocol; /* Protocole couche physique */
int sll_ifindex; /* Numéro d'interface */
unsigned short sll_hatype; /* Type de matériel ARP */
unsigned char sll_pkttype; /* Type de paquet */
unsigned char sll_halen; /* Longueur de l'adresse */
unsigned char sll_addr[8]; /* Adresse couche physique */
};
Les membres de cette structure sont les suivants :
- sll_protocol
-
est le type normalisé du protocole Ethernet dans l’ordre des octets du
réseau tel que défini dans le fichier d’en-tête
<linux/if_ether.h>. C’est par défaut le protocole du socket.
- sll_ifindex
-
est le numéro d’interface (consultez netdevice(7)). 0 correspond à
n’importe quelle interface (autorisée uniquement pour la
liaison). sll_hatype est un type ARP tel que défini dans le fichier
d’en-tête <linux/if_arp.h>.
- sll_pkttype
-
contient le type de paquet. Les types valables sont PACKET_HOST pour un
paquet destiné à l'hôte local, PACKET_BROADCAST pour un paquet broadcast
de couche physique, PACKET_MULTICAST pour un paquet envoyé à une adresse
multicast de couche physique, PACKET_OTHERHOST pour un paquet destiné à
un autre hôte capturé par un pilote de périphérique en mode promiscuous et
PACKET_OUTGOING pour un paquet provenant de l'hôte local rebouclé sur un
socket packet. Cela n'a de signification qu'en réception.
- sll_addr
-
sll_halen
contiennent l'adresse de couche physique (par exemple IEEE 802.3) et sa
longueur. L'interprétation exacte dépend du périphérique.
Lorsque des paquets sont envoyés, il suffit d'indiquer sll_family,
sll_addr, sll_halen, sll_ifindex et sll_protocol. Les autres
champs devraient être à zéro. sll_hatype et sll_pkttype sont remplis
en réception pour information.
Options de socket
Les options du socket packet sont configurées en appelant setsockopt(2)
avec le niveau SOL_PACKET.
- PACKET_ADD_MEMBERSHIP
-
- PACKET_DROP_MEMBERSHIP
-
Les options des sockets packet permettent de configurer le multicasting de
couche physique et le mode promiscuous. PACKET_ADD_MEMBERSHIP ajoute une
liaison et PACKET_DROP_MEMBERSHIP la supprime. Les deux options attendent
une structure packet_mreq en paramètre :
-
struct packet_mreq {
int mr_ifindex; /* Numéro d'interface */
unsigned short mr_type; /* Action */
unsigned short mr_alen; /* Longueur d'adresse */
unsigned char mr_address[8]; /* Adresse couche physique */
};
-
mr_ifindex contient le numéro de l'interface dont l'état doit être
modifié. Le champ mr_type indique l'action à
effectuer. PACKET_MR_PROMISC valide la réception de tous les paquets
circulant sur le segment de réseau commun (souvent appelé « mode
promiscuous »), PACKET_MR_MULTICAST attache le socket au groupe
multicast de couche physique indiqué dans mr_address et mr_alen, et
PACKET_MR_ALLMULTI demande au socket de recevoir tous les paquets
multicast arrivant sur l'interface.
-
De plus, les ioctls classiques SIOCSIFFLAGS, SIOCADDMULTI et
SIOCDELMULTI peuvent parvenir au même résultat.
- PACKET_AUXDATA (depuis Linux 2.6.21)
-
Si cette option est activée, le socket packet fournit avec chaque paquet une
structure de métadonnées à l’aide du champ de contrôle de recvmsg(2). La
structure peut être lue avec cmsg(3). Elle est définie ci-dessous :
-
struct tpacket_auxdata {
__u32 tp_status;
__u32 tp_len; /* Longueur du paquet */
__u32 tp_snaplen; /* Longueur capturée */
__u16 tp_mac;
__u16 tp_net;
__u16 tp_vlan_tci;
__u16 tp_vlan_tpid; /* Depuis Linux 3.14 ; précédemment
c’était des octets de remplissage
non utilisés */
};
- PACKET_FANOUT (depuis Linux 3.1)
-
Pour s’adapter au nombre de traitements des threads, les sockets packet
peuvent former un groupe de déploiement. Dans ce mode, tous les paquets
correspondants sont mis en attente dans un seul socket du groupe. Un socket
rejoint un groupe de déploiement en appelant setsockopt(2) avec le niveau
SOL_PACKET et l’option PACKET_FANOUT. Tous les espaces de noms réseau
peuvent avoir jusqu’à 65536 groupes indépendants. Un socket sélectionne un
groupe en encodant l’identifiant dans les 16 premiers bits de la valeur
d’entier de cette option. Le premier socket packet à rejoindre un groupe le
crée implicitement. Pour réussir à rejoindre un groupe existant, les sockets
packet suivants doivent avoir le même protocole, la même configuration de
périphérique, le même mode de déploiement et les mêmes attributs (voir
ci-dessous). Les sockets packet ne peuvent quitter un groupe de déploiement
qu’en fermant le socket. Le groupe est supprimé quand le dernier socket est
fermé.
-
Le déploiement gère plusieurs algorithmes pour répartir le trafic entre les
sockets comme suit :
-
- -
-
Le mode par défaut, PACKET_FANOUT_HASH, envoie les paquets du même flux
au même socket pour maintenir l’ordre par flux. Pour chaque paquet, il
choisit un socket en prenant le hachage du flux de paquets modulo le nombre
de sockets dans le groupe, où le hachage du flux est un hachage sur les
adresses de la couche réseau et les champs facultatifs de port de la couche
transport.
- -
-
Le mode répartition de charge PACKET_FANOUT_LB met en œuvre un algorithme
de tourniquet (round-robin).
- -
-
PACKET_FANOUT_CPU sélectionne le socket en se basant sur le CPU sur
lequel le paquet arrive.
- -
-
PACKET_FANOUT_ROLLOVER traite toutes les données sur un seul socket,
allant sur le suivant quand le socket devient débordé.
- -
-
PACKET_FANOUT_RND sélectionne le socket en utilisant un générateur de
nombres pseudo-aléatoires.
- -
-
PACKET_FANOUT_QM (disponible depuis Linux 3.14) sélectionne le socket en
utilisant le queue_mapping enregistré du tampon de socket (SKB) reçu.
-
Les modes de déploiement acceptent des options supplémentaires. La
fragmentation d’IP force les paquets du même flux à avoir des hachages de
flux différents. L’attribut PACKET_FANOUT_FLAG_DEFRAG, si défini, force
la défragmentation de paquets avant l’application du déploiement, pour
conserver l’ordre même dans ce cas. Le mode de déploiement et les options
sont communiqués sur les deuxièmes 16 bits de la valeur d’entier de cette
option. L’attribut PACKET_FANOUT_FLAG_ROLLOVER active le mécanisme de
déplacement comme une stratégie de sauvegarde : si l’algorithme de
déploiement originel sélectionne un socket débordé, le paquet se déplace
vers le suivant disponible.
- PACKET_LOSS (avec PACKET_TX_RING)
-
Lorsqu'un paquet malformé est trouvé dans le tampon circulaire de
transmission, le comportement par défaut est de réinitialiser son
tp_status à TP_STATUS_WRONG_FORMAT et d'abandonner immédiatement la
transmission. Le paquet malformé ainsi que les paquets suivants mis en file
d'attente voient leur transmission bloquée. L'erreur de format doit être
corrigée, la valeur tp_status associée doit être réinitialisée à
TP_STATUS_SEND_REQUEST et le processus de transmission redémarré par
l'intermédiaire de l'interface send(2). Cependant, si PACKET_LOSS est
défini, tout paquet malformé est ignoré, son tp_status est réinitialisé à
TP_STATUS_AVAILABLE et le processus de transmission continue.
- PACKET_RESERVE (avec PACKET_RX_RING)
-
Par défaut, un tampon circulaire de réception des paquets écrit les paquets
juste après la structure de métadonnées et le remplissage d'alignement. La
valeur d’entier de cette option réserve une possibilité de transmission
supplémentaire.
- PACKET_RX_RING
-
Créer un tampon circulaire projeté en mémoire pour la réception asynchrone
de paquets. Le socket packet réserve une zone contiguë d’espace d’adresse
d’application, la dispose dans un tableau d’emplacements de paquet et copie
les paquets (jusqu’à tp_snaplen) dans les emplacements suivants. Tous les
paquets sont précédés d’une structure de métadonnées similaire à
tpacket_auxdata. Les champs de protocole encodent la position des données
dès le début de l’en-tête de métadonnées. tp_net stocke la position de la
couche réseau. Si le socket packet est de type SOCK_DGRAM, alors
tp_mac est la même. S’il est de type SOCK_RAW, alors ce champ stocke
la position de la trame de couche liaison. Le socket packet et l’application
communiquent le début et la fin du tampon circulaire à l’aide du champ
tp_status. Tous les emplacements avec tp_status valant
TP_STATUS_KERNEL appartiennent au socket packet. Après avoir rempli un
emplacement, il modifie l’état de l’emplacement pour qu’il appartienne à
l’application. Lors d’une opération normale, la nouvelle valeur de
tp_status a au moins son bit TP_STATUS_USER activé, pour signaler
qu’un paquet reçu a été stocké. Lorsque l’application a terminé de traiter
un paquet, elle transfère la propriété de l’emplacement au socket en
redéfinissant tp_status à TP_STATUS_KERNEL.
-
Les sockets packet mettent en œuvre plusieurs variantes du tampon circulaire
de paquets. Des précisions sur cette mise en place sont disponibles dans
Documentation/networking/packet_mmap.rst dans l'arborescence des sources
du noyau Linux.
- PACKET_STATISTICS
-
Récupérer les statistiques du socket packet sous la forme d'une structure
-
struct tpacket_stats {
unsigned int tp_packets; /* Décompte total des paquets */
unsigned int tp_drops; /* Décompte des paquets jetés */
};
-
Recevoir les statistiques réinitialise les compteurs internes. La structure
de statistiques est différente lorsque le tampon circulaire utilisé est de
type TPACKET_V3.
- PACKET_TIMESTAMP (avec PACKET_RX_RING ; depuis Linux 2.6.36)
-
Le tampon circulaire de réception des paquets stocke un horodatage dans
l’en-tête de métadonnées. Par défaut, c’est un horodatage logiciel généré
quand le paquet est copié dans le tampon circulaire. Cette option d’entier
sélectionne le type d’horodatage. En plus du fonctionnement par défaut, il
gère deux formats matériels décrits dans
Documentation/networking/timestamping.rst dans l'arborescence des sources
du noyau Linux.
- PACKET_TX_RING (depuis Linux 2.6.31)
-
Créer un tampon circulaire projeté en mémoire pour la transmission de
paquets. Cette option est similaire à PACKET_RX_RING et accepte les mêmes
arguments. L’application écrit des paquets dans des emplacements avec
tp_status égal à TP_STATUS_AVAILABLE et les programme pour
transmission en modifiant tp_status à la valeur
TP_STATUS_SEND_REQUEST. Quand les paquets sont prêts à être transmis,
l’application appelle send(2) ou une de ses variantes. Les champs buf
et len de cet appel sont ignorés. Si une adresse est passée en utilisant
sendto(2) ou sendmsg(2), alors cela écrase le socket par défaut. En
cas de transmission réussie, le socket réinitialise tp_status à
TP_STATUS_AVAILABLE. Il interrompt immédiatement la transmission en cas
d’erreur sauf si PACKET_LOSS est définie.
- PACKET_VERSION (avec PACKET_RX_RING ; depuis Linux 2.6.27)
-
Par défaut, PACKET_RX_RING crée un tampon circulaire de réception des
paquets de variante TPACKET_V1. Pour créer une autre variante, configurer
la variante voulue en définissant l’option d’entier avant de créer le tampon
circulaire.
- PACKET_QDISC_BYPASS (depuis Linux 3.14)
-
Par défaut, les paquets envoyés par un socket packet passent par la couche
qdisc du noyau, dédiée au contrôle de trafic, ce qui répond bien à la
majorité des cas d'utilisation. Les équipements de génération de trafic qui
utilisent des sockets packet pour inonder par force brute le réseau — par
exemple pour tester des appareils en charge comme le fait pktgen — peuvent
contourner cette couche de contrôle en définissant cette option à 1. Un
effet secondaire est l'absence de mise en mémoire tampon des paquets par la
couche qdisc, ce qui peut provoquer des pertes de paquets lorsque les files
de transmission du périphérique réseau sont pleines. L'utilisation de cette
option est à vos risques et périls.
Ioctls
SIOCGSTAMP peut servir à obtenir l'horodatage du dernier paquet reçu. Le
paramètre est une variable struct timeval.
De plus, les ioctls standards définis dans netdevice(7) et socket(7)
sont valables sur les sockets packet.
Traitement des erreurs
Les sockets packet ne gèrent pas d'autres erreurs que celles se produisant
durant la transmission des paquets au pilote de périphérique. Elles ne
traitent pas le concept de file d'erreurs.
ERREURS
- EADDRNOTAVAIL
-
Adresse de groupe multicast inconnue.
- EFAULT
-
Adresse mémoire incorrecte.
- EINVAL
-
Argument incorrect.
- EMSGSIZE
-
Le paquet est plus grand que le MTU de l'interface.
- ENETDOWN
-
L'interface n'est pas active.
- ENOBUFS
-
Pas assez de mémoire pour le paquet.
- ENODEV
-
Le nom du périphérique ou le numéro d’interface indiqué dans l'adresse de
l'interface est inconnu.
- ENOENT
-
Pas de paquet reçu.
- ENOTCONN
-
Aucune adresse d'interface n'a été passée.
- ENXIO
-
Numéro d'interface non valable dans son adresse.
- EPERM
-
L'utilisateur n'a pas les privilèges nécessaires pour l'opération.
De plus, d'autres erreurs peuvent être engendrées par le pilote bas niveau.
VERSIONS
AF_PACKET est une nouveauté de Linux 2.2. Les versions précédentes de
Linux ne prenaient en charge que SOCK_PACKET.
NOTES
Pour la portabilité, il est conseillé d'utiliser les fonctionnalités
AF_PACKET par l'intermédiaire de l'interface pcap(3), bien que cela ne
couvre qu'un sous-ensemble des possibilités de AF_PACKET.
Les sockets packet SOCK_DGRAM n'essayent pas de créer ou de traiter les
en-têtes IEEE 802.2 LLC pour une trame IEEE 802.3. Lorsque le protocole
ETH_P_802_3 est indiqué en émission, le noyau crée la trame 802.3 et
remplit le champ de longueur. L'utilisateur doit fournir l'en-tête LLC pour
obtenir un paquet entièrement conforme. Les paquets 802.3 entrants ne sont
pas multiplexés sur les champs du protocole DSAP/SSAP. À la place, ils sont
fournis à l'utilisateur sous le protocole ETH_P_802_2 avec un en-tête LLC
ajouté. La liaison ETH_P_802_3 n’est donc pas possible, la liaison
ETH_P_802_2 doit être utilisée à la place, et vous devez réaliser le
multiplexage de protocoles vous-même. Le comportement par défaut en émission
est l’encapsulation Ethernet DIX standard, avec le protocole renseigné.
Les sockets packet ne sont pas soumis aux chaînes de pare-feu en entrée ou
sortie.
Compatibilité
Avec Linux 2.0, la seule façon d’obtenir un socket paquet était avec
l’appel :
socket(AF_INET, SOCK_PACKET, protocole)
C’est encore pris en charge mais obsolète et fortement déconseillé. La
principale différence entre les deux méthodes est que SOCK_PACKET utilise
l'ancienne struct sockaddr_pkt pour indiquer l'interface, ce qui ne
fournit aucune indépendance vis-à-vis de la couche physique.
struct sockaddr_pkt {
unsigned short spkt_family;
unsigned char spkt_device[14];
unsigned short spkt_protocol;
};
spkt_family contient le type de périphérique, spkt_protocol est le
type de protocole IEEE 802.3 comme défini dans <sys/if_ether.h>
et spkt_device est le nom du périphérique sous forme de chaîne terminée
par un octet NULL, par exemple eth0.
Cette structure est obsolète et ne doit pas être employée dans des nouveaux
programmes.
BOGUES
Gestion des en-têtes LLC
La gestion des en-têtes LLC IEEE 802.2/802.3 devrait être considérée comme
un bogue.
Problèmes avec MSG_TRUNC
L'extension MSG_TRUNC de recvmsg(2) est une bidouille horrible et
devrait être remplacée par un message de contrôle. Il n'y a actuellement
aucun moyen d'obtenir l'adresse de destination originelle des paquets à
l’aide de SOCK_DGRAM.
spkt_device device name truncation
The spkt_device field of sockaddr_pkt has a size of 14 bytes, which is
less than the constant IFNAMSIZ defined in <net/if.h> which is
16 bytes and describes the system limit for a network interface name. This
means the names of network devices longer than 14 bytes will be truncated to
fit into spkt_device. All these lengths include the terminating null
byte ('\0')).
Issues from this with old code typically show up with very long interface
names used by the Predictable Network Interface Names feature enabled by
default in many modern Linux distributions.
The preferred solution is to rewrite code to avoid SOCK_PACKET. Possible
user solutions are to disable Predictable Network Interface Names or to
rename the interface to a name of at most 13 bytes, for example using the
ip(8) tool.
Problèmes de documentation
Les filtres des sockets ne sont pas documentés.
VOIR AUSSI
socket(2), pcap(3), capabilities(7), ip(7), raw(7),
socket(7), ip(8),
RFC 894 pour l'encapsulation IP Ethernet standard. RFC 1700 pour
l'encapsulation IP IEEE 802.3.
Le fichier d'en-tête <linux/if_ether.h> pour les protocoles de
couche physique.
L'arbre des sources du noyau Linux. /Documentation/networking/filter.rst
décrit comment appliquer des filtres Berkeley de paquets aux sockets
packet. /tools/testing/selftests/net/psock_tpacket.c contient un exemple
de code source pour toutes les versions de PACKET_RX_RING et
PACKET_TX_RING.
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
-
- Types d’adresses
-
- Options de socket
-
- Ioctls
-
- Traitement des erreurs
-
- ERREURS
-
- VERSIONS
-
- NOTES
-
- Compatibilité
-
- BOGUES
-
- Gestion des en-têtes LLC
-
- Problèmes avec MSG_TRUNC
-
- spkt_device device name truncation
-
- Problèmes de documentation
-
- VOIR AUSSI
-
- TRADUCTION
-
This document was created by
man2html,
using the manual pages.
Time: 05:06:38 GMT, September 19, 2025