IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

Envoi d'une trame ethernet


Sujet :

Réseau C

  1. #1
    Membre actif
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2003
    Messages : 217
    Points : 242
    Points
    242
    Par défaut Envoi d'une trame ethernet
    Bonsoir,

    C'est un problème à la fois simple et complexe que je vais exposer. Simple puisque la question principale est précise, complexe parce qu'elle en amène de nombreuses autres. Je cherche à envoyer directement des trames ethernet, sans passer par le protocole IP.

    Il est légitime de se demander pourquoi je cherche à faire ceci. En réalité, je cherche à implémenter un Wake On Lan, et comme l'indique Wikipedia (pour cela, je n'ai pas non plus cherché à lire la RFC), pour réveiller une machine, il faut envoyer une trame magique FF:FF:FF:FF:FF:FF, suivie de 5 fois (edit, j'y étais presque, en fait c'est 16 fois :p) l'adresse MAC de la carte réseau cible.

    Pour l'implémenter, après de nombreuses recherches, lectures de man, déchiffrages de code source, tests, j'ai réussi à compiler ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <net/if_dl.h>
    #include <netinet/in.h>
    #include <net/if_types.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
     
     
    int main()
    {
     
    	int sock,res;
    	if((sock=socket(PF_INET, SOCK_RAW, IPPROTO_RAW))<0) // C'est une des rares combinaisons d'arguments à fonctionner.
    	{
    		printf("Erreur 1\n");
    		return -1;
    	}
     
    	char msg[] = "test 1";
    	struct sockaddr_dl sll = {
    		sizeof(struct sockaddr_dl),
    		AF_LINK, // Faut bien lui dire quelquepart qu'on manipule des adresses mac.
    		4, // J'ai récupéré ce numéro avec if_nametoindex, mais j'ai essayé avec 0
    		IFT_ETHER, // Je suppose que c'est cela, ma carte réseau est une carte ethernet
    		0,
    		6,
    		12,
    		{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0}
    		/* J'ai essayé en spécifiant {'e', 'n', '0', …} pour le tableau, et les arguments alen à 3, nlen à 6, et slen 12 respectivement pour correspondre à la longueur des données. De même, en fournissant l'adresse mac réelle, cela ne fonctionne pas. */
    	}; // J'ai aussi essayé d'utiliser ascii2addr, même verdict.
    	if((res=sendto(sock, msg, 6*sizeof(char), 0, (struct sockaddr *) &sll, sizeof(struct sockaddr_dl)))<0)
    	{
    		printf("Erreur 2 : %d\n", res);
    		return -2;
    	}
    	printf("%d\n",res); // Affiche systématiquement 6, donc le message a été envoyé.
     
    	return 0;
     
    }
    Donc ce code compile correctement avec gcc. Pour le test, je l'effectue en root sur Mac OS X Leopard, le pc cible démarré (pour les tests) sur une kubuntu 8.10 et correctement connecté (selon le ifconfig). Le résultat est que le système considère la trame envoyée (la fonction sendto me renvoie une valeur positive), mais un sudo tcpdump de chaque côté ne voit pas la trame passer.

    J'aimerais savoir si je m'y prends mal. Comment envoie-t-on une trame ethernet sur des systèmes Unix ?

    J'ai eu beaucoup de mal à trouver de la documentation, le man notamment est piteusement fourni, avez-vous des sources complémentaires ?

    Lors de mes tests, j'ai été très étonné du fait que certaines valeurs ne pouvaient pas être valides. Je m'explique. En utilisant la fonction socket, j'ai fait mes tests avec entre autres PF_LINK et PF_UNSPEC, en voyant qu'aucune combinaison des deux autres arguments ne fonctionnaient. J'ai ensuite lancé un while complet sur les 3 arguments, pour voir que la grosse majorité des PF_* ne pouvaient juste pas être utilisées dans socket, la fonction renvoyant une erreur EPROTONOSUPPORT.
    Est-ce que c'est spécifique à mon noyau ? Est-ce que vous avez des détails sur l'implémentation des sockets dans les noyaux des systèmes les plus courants ?

    Bon, je vais m'arrêter là, si vous arrivez jusque là, j'espère que vous trouverez des éléments de réponse, ou bien une grosse bourde de ma part.
    Je reste à votre disposition pour plus de détails.

    Merci d'avance.

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Un petit exemple plutôt qu'un grand discours : http://aschauf.landshut.org/fh/linux...w/ch01s03.html, je ne sais pas si cela marche.

    Autre chose je pense qu'il faut être root pour pourvoir faire cela.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Membre actif
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2003
    Messages : 217
    Points : 242
    Points
    242
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Un petit exemple plutôt qu'un grand discours : http://aschauf.landshut.org/fh/linux...w/ch01s03.html, je ne sais pas si cela marche.
    Merci, je vais voir ça.

    Citation Envoyé par ram-0000 Voir le message
    Autre chose je pense qu'il faut être root pour pourvoir faire cela.
    Oui, je l'ai précisé mais ça s'est retrouvé noyé dans mon discours, je fais mes tests en root.

  4. #4
    Membre actif
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2003
    Messages : 217
    Points : 242
    Points
    242
    Par défaut
    J'ai regardé l'exemple. Le seul petit problème, c'est qu'il est spécifique à Linux. Je travaille sous Mac OS X (pour au final le porter sur NetBSD mais c'est la même base) et justement n'existent pas (sans équivalent apparement) :
    - La structure sockaddr_ll (La seule structure qui pouvait s'en rapprocher était struct sockaddr_dl).
    - La famille d'adresses AF_PACKET (Je pense que AF_LINK en est proche, mais voilà, comme je disais, socket renvoie une erreur si on essaye de l'utiliser).
    - La constante ETH_P_ALL.

    J'ai dû garder mon ouverture de socket telle quelle (avec PF_LINK, ce qui me plaît moyen…). En définitive la seule chose que j'ai changé, c'est que j'ai rajouté l'entête de la trame ethernet dans le message à envoyer (à la main, parce que bien sûr il n'y a aucune structure définie dans les headers pour la spécifier…).
    Bref, inutile de préciser que cela n'a pas marché, le tcpdump semble laisser paraître que manifestement la trame est interprétée en temps que paquet IP. L'adresse IP est composée de certaines composantes du sockaddr_dl…

    Voilà, je suis en attente d'autres réponses. Je vous remercie. :-/

  5. #5
    Membre actif
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2003
    Messages : 217
    Points : 242
    Points
    242
    Par défaut
    Bon, mon problème n'a pas eu l'air d'avoir déchaîné les passions. J'ai finalement trouvé la solution il y a quelques jours, je viens la rapporter ici pour ceux qui auraient le même genre de problèmes.
    En fait, après de longues recherches, j'ai eu l'idée de directement attaquer le périphérique dev. En regardant le code de la librairie pcap, mon intuition s'est confirmée puisque c'est comme cela qu'il faisaient.

    En fait, sur les systèmes BSD like (donc aussi bien sur mon NetBSD que sur mon Mac OS X), il faut ouvrir un périphérique /dev/bpf* (le premier disponible), l'associer à la carte réseau sur laquelle on veut envoyer la trame, et enfin envoyer une trame contruite à la main.
    Je joins ici le code que j'ai écrit pour implémenter le wake on lan.
    Fichiers attachés Fichiers attachés
    • Type de fichier : c wol.c (3,0 Ko, 263 affichages)

Discussions similaires

  1. Envoi d'une trame via liaison série
    Par Fabien50 dans le forum C++
    Réponses: 48
    Dernier message: 29/04/2009, 09h59
  2. [Réseau] Connexion et envoie d'une trame
    Par ivanoe25 dans le forum Langage
    Réponses: 10
    Dernier message: 29/09/2006, 00h04
  3. Obtenir une trame Ethernet
    Par Scorff dans le forum Développement
    Réponses: 15
    Dernier message: 11/09/2006, 12h22
  4. Problème avec l'envoi d'une trame TCP
    Par fredoBreton dans le forum API, COM et SDKs
    Réponses: 14
    Dernier message: 17/11/2005, 20h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo