raw – Sockets raw IPv4 sous Linux
#include <sys/socket.h>
#include <netinet/in.h>
raw_socket = socket(AF_INET, SOCK_RAW, int protocole);
Les sockets raw (bruts, sans protocole) permettent d'implémenter de
nouveaux protocoles IPv4 dans l'espace utilisateur. Un socket raw
reçoit ou envoie des datagrammes bruts sans les en-têtes de
couche de liaison.
La couche IPv4 génère des en-têtes IP lorsqu'elle envoie un
paquet, à moins que l'option
IP_HDRINCL de socket ne soit
activée sur le socket. Lorsqu'elle est activée, le socket doit
contenir l'en-tête IP. Pour la réception, l'en-tête IP
est toujours inclus dans le paquet.
Dans le but de créer un socket raw, un processus doit avoir la
capacité
CAP_NET_RAW dans l’espace de noms utilisateur
qui régit son espace de noms réseau.
Tous les paquets ou les erreurs correspondant au numéro de
protocole indiqué pour le socket raw sont transmis à ce
socket. Pour voir une liste des protocoles autorisés, consultez les
numéros assignés dans
http://www.iana.org/assignments/protocol-numbers/
et
getprotobyname(3).
Un protocole
IPPROTO_RAW implique l'activation de
IP_HDRINCL et
autorise l'émission suivant n'importe quel protocole IP indiqué
dans l'en-tête. La réception de tous les protocoles IP avec
IPPROTO_RAW n'est pas possible avec les sockets raw.
Champs d'en-tête IP modifiés en émission par
IP_HDRINCL
|
|
Somme de contrôle d’IP |
Toujours rempli |
Adresse de socket |
Rempli si composé de zéros |
ID de paquet |
Rempli si composé de zéros |
Longueur totale |
Toujours rempli |
Si
IP_HDRINCL est indiqué et si l'en-tête IP a une adresse
de destination différente de zéro, alors l'adresse de
destination du socket est utilisée pour router le paquet. Quand
MSG_DONTROUTE est indiqué, l'adresse de destination devrait
toujours viser une interface locale. Sinon, un examen de la table de routage a
quand même lieu, mais les routes avec une passerelle sont
ignorées.
Si
IP_HDRINCL n'est pas indiqué, les options d'en-tête IP
peuvent être définies sur les sockets raw avec
setsockopt(2) ; consultez
ip(7) pour plus d'informations.
Depuis Linux 2.2 tous les champs d'en-tête IP et les options
peuvent être définis en utilisant les options IP de socket. Cela
signifie que les sockets raw ne servent en général que pour les
nouveaux protocoles ou les protocoles sans interface utilisateur (comme ICMP).
Lorsqu'un paquet est reçu, il est passé à tous les sockets
raw qui ont été attachés à son protocole avant
d'être transmis aux gestionnaires des autres protocoles (par exemple
les modules des protocoles du noyau).
Pour envoyer et recevoir des datagrammes (
sendto(2),
recvfrom(2)
et similaires), les sockets raw utilisent la structure d'adresse
sockaddr_in standard, définie dans
ip(7). Le champ
sin_port pourrait être utilisé pour indiquer un
numéro de protocole IP, mais il est ignoré pour
l'émission dans Linux 2.2 et les versions suivantes et devrait
être toujours mis à zéro (voir paragraphe BOGUES). Pour
les paquets entrants
sin_port est réglé à
zéro.
Les options des sockets raw peuvent être écrites avec
setsockopt(2) et lues avec
getsockopt(2) en passant l'attribut
de famille
IPPROTO_RAW.
- ICMP_FILTER
- Activer un filtre spécial sur les sockets raw
liés au protocole IPPROTO_ICMP. La valeur a un bit
défini pour chaque type de message ICMP qui doit être
rejeté. La valeur par défaut est de ne filtrer aucun message
ICMP.
De plus, toutes les options
IPPROTO_IP de
ip(7) valables pour les
sockets datagrammes sont prises en charge.
Les erreurs provenant du réseau ne sont transmises à l'utilisateur
que lorsque le socket est connecté ou si le drapeau
IP_RECVERR
est actif. Pour les sockets connectés, seules
EMSGSIZE et
EPROTO sont transmises pour compatibilité. Avec
IP_RECVERR, toutes les erreurs réseau sont sauvegardées
dans la file d'erreurs.
- EACCES
- L'utilisateur essaye d'envoyer sur une adresse broadcast
sans avoir le drapeau broadcast sur le socket.
- EFAULT
- Une adresse mémoire incorrecte a été
fournie.
- EINVAL
- Argument incorrect.
- EMSGSIZE
- Paquet trop grand. Soit la recherche du MTU d’un
chemin donné (Path MTU discovery — PMTUd)) est active
(voir l'attribut IP_MTU_DISCOVER de socket), soit la taille du
paquet dépasse le maximum autorisé par IPv4
(64 Ko).
- EOPNOTSUPP
- Un attribut incorrect a été transmis à
un appel de socket (comme MSG_OOB).
- EPERM
- L'utilisateur n'a pas la permission d'ouvrir des sockets
raw. Seuls les processus avec un UID effectif égal à
zéro ou ayant la capacité CAP_NET_RAW peuvent le
faire.
- EPROTO
- Une erreur ICMP est arrivée, indiquant un
problème de paramétrage.
IP_RECVERR et
ICMP_FILTER sont nouveaux dans Linux 2.2. Ce
sont des extensions Linux qui ne doivent pas être employées dans
des programmes portables.
Linux 2.0 assurait une compatibilité bogue-à-bogue avec le
code des sockets raw de BSD lorsque l’option
SO_BSDCOMPAT de
socket était utilisée. Cela a été supprimé
depuis Linux 2.2.
Par défaut, les sockets bruts utilisent la détection du MTU
(« Maximum Transmission Unit ») pour le chemin.
Cela signifie que le noyau garde en mémoire le MTU vers une adresse IP
cible spécifique et renvoie
EMSGSIZE lorsqu'un paquet raw
dépasse cette taille. Dans ce cas, l'application doit diminuer la
taille du paquet. La détection du MTU d’un chemin peut aussi
être désactivée en utilisant l'option de socket
IP_MTU_DISCOVER ou le fichier
/proc/sys/net/ipv4/ip_no_pmtu_disc, consultez
ip(7) pour plus de
détails. Lorsque cette option est désactivée, les sockets
raw fragmenteront les paquets sortants qui dépassent le MTU de
l'interface. C’est cependant découragé, pour des raisons
de performance et de fiabilité.
Un socket raw peut être attaché à une adresse locale
spécifique en utilisant l'appel
bind(2). S’il n'est pas
attaché, tous les paquets du protocole IP indiqué sont
reçus. De plus, un socket raw peut être attaché à
un périphérique réseau particulier avec
SO_BINDTODEVICE ; consultez
socket(7).
Un socket
IPPROTO_RAW ne fonctionne qu'en émission. Si vous
désirez vraiment recevoir tous les paquets IP, utilisez un socket
packet(7) avec le protocole
ETH_P_IP. Notez que les sockets
packet ne réassemblent pas les fragments IP contrairement aux sockets
raw.
Si vous voulez recevoir tous les paquets ICMP pour un socket datagram, il est
souvent préférable d'utiliser
IP_RECVERR sur ce socket
particulier, consultez
ip(7).
Les sockets raw peuvent exploiter tous les protocoles IP sous Linux, même
les protocoles comme ICMP ou TCP qui ont un module de protocole dans le noyau.
Dans ce cas, les paquets sont passés à la fois au module du
noyau et au(x) socket(s) raw. Ce comportement n'est pas portable, de
nombreuses autres implémentations des sockets BSD ont leurs propres
limites à ce sujet.
Linux ne modifie jamais les en-têtes fournis par l'utilisateur (sauf pour
remplir les champs ne contenant que des zéros comme cela est
décrit pour
IP_HDRINCL). Ça diffère de nombreuses
autres implémentations des sockets raw.
Les sockets raw sont en général peu portables et devraient
être évités dans les programmes destinés à
être portables.
L'émission sur les sockets raw devrait employer le protocole IP dans
sin_port ; cette possibilité a été perdue
dans Linux 2.2. Une solution est d'utiliser
IP_HDRINCL.
Les extensions de mandataire transparent ne sont pas décrites.
Lorsque l'option
IP_HDRINCL est active, les datagrammes ne seront pas
fragmentés et sont limités au MTU de l'interface.
Utiliser le protocole IP indiqué dans
sin_port en émission
a été supprimé dans Linux 2.2. Le protocole auquel
le socket a été lié ou celui indiqué dans l'appel
socket(2) initial est toujours utilisé.
recvmsg(2),
sendmsg(2),
capabilities(7),
ip(7),
socket(7)
RFC 1191 pour la recherche du MTU de chemin.
RFC 791
et le fichier d'en-tête
<linux/ip.h> pour le protocole IP.
La traduction française de cette page de manuel a été
créée par Christophe Blaess
<
https://www.blaess.fr/christophe/>, Stéphan Rafin
<
[email protected]>, Thierry Vignaud
<
[email protected]>, François Micaux, Alain Portal
<
[email protected]>, Jean-Philippe Guérard
<
[email protected]>, Jean-Luc Coulon (f5ibh)
<
[email protected]>, Julien Cristau
<
[email protected]>, Thomas Huriaux <
[email protected]>,
Nicolas François <
[email protected]>, Florentin
Duneau <
[email protected]>, Simon Paillard
<
[email protected]>, Denis Barbier
<
[email protected]>, David Prévot <
[email protected]> et
Jean-Paul Guillonneau <
[email protected]>
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 à
[email protected]