| packet(7) | Miscellaneous Information Manual | packet(7) |
packet – Interface de paquets au niveau du périphérique
#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);
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.
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 :
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.
Les options du socket packet sont configurées en appelant setsockopt(2) avec le niveau SOL_PACKET.
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 */
};
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 */
};
struct tpacket_stats {
unsigned int tp_packets; /* Décompte total des paquets */
unsigned int tp_drops; /* Décompte des paquets jetés */
};
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.
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.
De plus, d'autres erreurs peuvent être engendrées par le pilote bas niveau.
AF_PACKET est une nouveauté de Linux 2.2. Les versions précédentes de Linux ne prenaient en charge que SOCK_PACKET.
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.
Avec Linux 2.0, la seule façon d’obtenir un socket paquet était avec l’appel :
socket(AF_INET, SOCK_PACKET, protocol)
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.
La gestion des en-têtes LLC IEEE 802.2/802.3 devrait être considérée comme un bogue.
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.
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.
Les filtres des sockets ne sont pas documentés.
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.
La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org> et Jean-Paul Guillonneau <guillonneau.jeanpaul@free.fr>
Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.
| 5 février 2023 | Pages du manuel de Linux 6.03 |