PACKET
Section: Manuel de l'administrateur Linux (7) Updated: 25 juillet 2003 Index
NOM
SYNOPSIS
DESCRIPTION
TYPES D'ADRESSE
OPTIONS DES SOCKETS
IOCTLS
GESTION D'ERREUR
COMPATIBILITÉ
NOTES
ERREURS
VERSIONS
BOGUES
AUTEURS
VOIR AUSSI
TRADUCTION
NOM
packet, PF_PACKET - Interface par paquet au niveau périphérique.
SYNOPSIS
DESCRIPTION
Les sockets packets sont utilisées pour envoyer ou recevoir des paquets de données
bruts au pilote de périphérique (Niveau OSI 2).
Elles permettent d'implémenter des modules protocoles dans l'espace utilisateur
au dessus du niveau physique.
L'argument
socket_type
est soit
SOCK_RAW
pour les paquets incluant l'en-tête du niveau liaison, soit
SOCK_DGRAM
pour les paquets préparés sans l'en-tête de la couche liaison. Les informations de l'en-tête
du niveau liaison sont disponibles dans un format commun, par l'intermédiaire d'un
sockaddr_ll.
protocol
est un numéro de protocole IEEE 802.3 dans l'ordre des octets du réseau. Voir le fichier d'en-tête
<linux/if_ether.h>
pour avoir une liste des protocoles autorisés. Lorsque le numéro demandé
est
htons(ETH_P_ALL)
alors tous les protocoles sont reçus.
Tous les paquets entrants du protocole indiqué seront passés à la socket packet avant d'être
transmis aux protocoles implémentés dans le noyau.
Seuls les processus avec un UID effectif nul ou la capacité
CAP_NET_RAW
peuvent ouvrir des sockets packet.
Les paquets des sockets
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, l'adresse est toujours examinée et fournie dans une structure standard
sockaddr_ll
Lors de l'émission d'un paquet, le buffer fourni par l'utilisateur doit contenir l'en-tête du niveau
physique. Le paquet est alors mis en file 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 ajoute toujours d'autres en-têtes.
SOCK_RAW
est identique mais non compatible avec l'ancien
SOCK_PACKET
de Linux 2.0.
SOCK_DGRAM
opère à un niveau légèrement plus élevé. L'en-tête du niveau physique est supprimé avant que le
paquet ne soit transmis à l'utilisateur. Les paquets envoyés par une socket packet
SOCK_DGRAM
reçoivent un en-tête de niveau physique correct, en fonction des informations dans
l'adresse destination
sockaddr_ll
avant d'être mis en file.
Par défaut tous les paquets du type de protocole indiqué sont
passés à la 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 la socket à une interface. Seuls les champs d'adresse
sll_protocol
et
sll_ifindex
sont utilisés pour l'attachement.
L'opération
connect(3)
n'est pas supportée sur les sockets packet.
Lorsque l'attribut
MSG_TRUNC
est transmis à
recvmsg(2),
recv(2),
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 buffer.
TYPES D'ADRESSE
La structure sockaddr_ll est une adresse du niveau physique dépendant du périphérique.
-
struct sockaddr_ll {
unsigned short sll_family; /* Toujours AF_PACKET */
unsigned short sll_protocol; /* Protocole niveau physique */
int sll_ifindex; /* Numéro d'interface */
unsigned short sll_hatype; /* Type d'en-tête */
unsigned char sll_pkttype; /* Type de paquet */
unsigned char sll_halen; /* Longueur de l'adresse */
unsigned char sll_addr[8]; /* Adresse niveau physique */
};
sll_protocol
est le type de protocole standard ethernet, dans l'ordre des octets du réseau,
comme défini dans le fichier d'en-tête
linux/if_ether.h.
Par défaut il s'agit du protocole de la socket.
sll_ifindex
est le numéro de l'interface
(voir
netdevice(2));
0 correspond à n'importe quelle interface (autorisé uniquement pour l'attachement).
sll_hatype
est un type ARP, comme défini dans le fichier d'en-tête
linux/if_arp.h
Le champ
sll_pkttype
contient le type de paquet. Les types valides sont
PACKET_HOST
pour un paquet destiné à l'hôte local,
PACKET_BROADCAST
pour un paquet broadcast du niveau physique,
PACKET_MULTICAST
pour un paquet envoyé à une adresse multicast du niveau 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 une socket packet.
Ceci n'a de signification qu'en réception.
sll_addr
et
sll_halen
contiennent l'adresse de niveau physique (par exemple IEEE 802.3) et sa longueur. L'interprétation
exacte dépend du périphérique.
Lorsqu'on envoie des paquets, il suffit d'indiquer
sll_family,
sll_addr,
sll_halen,
sll_ifindex.
Les autres champs devraient être à zéro.
sll_hatype
et
sll_pkttype
sont remplis en réception pour information.
Pour l'attachement, seuls
sll_protocol
et
sll_ifindex
sont utilisés.
OPTIONS DES SOCKETS
Les options des sockets packets permettent de configurer le multicasting du niveau physique
et le mode promiscuous. Cela fonctionne en appelant
setsockopt(2)
sur une socket packet avec SOL_PACKET et l'option
PACKET_ADD_MEMBERSHIP
pour ajouter un attachement ou
PACKET_DROP_MEMBERSHIP
pour en supprimer un.
Toutes les deux attendent une structure
packet_mreq
en argument :
-
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 niveau physique */
};
mr_ifindex
contient le numéro de l'interface dont le statut doit
être modifié.
Le paramètre
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 la socket au groupe multicast de niveau physique indiqué dans
mr_address
et
mr_alen,
et
PACKET_MR_ALLMULTI
demande à la socket de recevoir tous les paquets multicast arrivant sur l'interface.
De plus, les ioctls classiques
SIOCSIFFLAGS,
SIOCADDMULTI,
SIOCDELMULTI
peuvent donner les mêmes résultats.
IOCTLS
SIOCGSTAMP
peut servir à obtenir l'horodatage du dernier paquet reçu. L'argument est une
structure
struct timeval.
De plus, les ioctls standards définis dans
netdevice(7)
et
socket(7)
sont valides sur les sockets packets.
GESTION D'ERREUR
Les sockets packets ne gère 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.
COMPATIBILITÉ
Sous Linux 2.0, la seule manière d'obtenir une socket packet était l'appel
socket(PF_INET, SOCK_PACKET, protocol).
Ceci est encore supporté mais 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 du niveau 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 caractère nul, par exemple eth0.
Cette structure est obsolète et ne doit pas être employé dans des nouveaux programmes.
NOTES
Pour la portabilité, il est conseillé d'utiliser les fonctionnalités
PF_PACKET
par l'intermédiaire de l'interface
pcap(3);
bien que cela ne couvre qu'un sous-ensembles des
possibilités de
PF_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. A la place, ils sont fournis à l'utilisateur
sous le protocole
ETH_P_802_2
sans en-tête LLC ajouté. Il n'est donc pas possible de faire d'attachement
ETH_P_802_3;
L'attachement
ETH_P_802_2
doit être réalisé à la place, et le multiplexage de protocole doit être réalisé manuellement.
Le comportement par défaut en émission est l'encapsulation Ethernet DIX standard, avec le
protocole renseigné.
Les sockets packets ne sont pas soumises aux chaînes de firewall en entrée ou sortie.
ERREURS
- ENETDOWN
-
L'interface n'est pas en marche.
- ENOTCONN
-
No interface address passed.
- ENODEV
-
Unknown device name or interface index specified in interface address.
- EMSGSIZE
-
Le paquet est plus grand que le MTU de l'interface.
- ENOBUFS
-
Pas assez de mémoire pour le paquet.
- EFAULT
-
Adresse mémoire invalide.
- EINVAL
-
Argument invalide.
- ENXIO
-
Numéro d'interface illégal.
- EPERM
-
L'utilisateur n'a pas les privilèges nécessaires pour l'opération.
- EADDRNOTAVAIL
-
Adresse de groupe multicast inconnue.
- ENOENT
-
Pas de paquet reçu.
De plus, d'autres erreurs peuvent être engendrées par le pilote bas-niveau.
VERSIONS
PF_PACKET
est une nouveauté de Linux 2.2. Les versions Linux précédente ne supportaient que
SOCK_PACKET.
BOGUES
La GlibC 2.1 ne définit pas la constante symbolique
SOL_PACKET.
Pour contourner ce problème, il est conseillé d'écrire :
-
#ifndef SOL_PACKET
#define SOL_PACKET 263
#endif
Ceci est corrigé dans les dernières versions de la GlibC et ne se produit pas sur les LibC5.
La gestion des en-têtes LLC IEEE 802.2/802.3 devrait être considérée comme un bogue.
Les filtres des sockets ne sont pas documentés.
L'extension
MSG_TRUNC
de recmsg est une bidouille horrible et devrait être remplacée par un message de commande.
Il n'y a actuellement aucun moyen d'obtenir l'adresse de destination originale des
paquets via SOCK_DGRAM.
AUTEURS
Cette page de manuel a été écrite par Andi Kleen avec l'aide de Matthew Wilcox.
PF_PACKET sous Linux 2.2 a été implémenté
par Alexey Kuznetsov, d'après du code d'Alan Cox et d'autres.
VOIR AUSSI
ip(7),
socket(7),
socket(2),
raw(7),
pcap(3).
RFC 894 pour l'encapsulation standard Ethernet.
RFC 1700 pour l'encapsulation IP IEEE 802.3.
Le fichier d'en-tête
linux/if_ether.h
pour les protocoles du niveau physique.
TRADUCTION
Christophe Blaess, 2001-2003.
|