Forum Linux.général [Résolut] Recevoir une réponse a mon ping (en C)

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
1
7
mai
2021

J'ai besoin de ping la même ip via 2 gateways. (multi homing)

donc:
sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)
je fait mon packet, puis:
sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll))
Puis en bloquant j'attends n'importe quel packet:
recvfrom(sockfd, sendbuf, sizeof(sendbuf), 0, (struct sockaddr*)&socket_address, &src_addr_size)
Et je suis bloqué car je ne recois rien.

Quel serai le meilleur moyen de recevoir les réponses pour filtrer puis décoder la réponse à mon ping?

Mon code complet:
https://pastebin.com/4GtRC3DJ

  • # le Principe...

    Posté par  . Évalué à 3. Dernière modification le 07 mai 2021 à 09:55.

    serait de ne pas bloquer,
    car là, si tu reçois un truc, tu le prend, et tu attends autre chose

    il faudrait plutot attendre un signal de la carte (interruption je crois)
    pour déclencher la boucle de lecture
    seulement il te faut lire les protocoles car un packet ping à un certain format donc une certaine taille, une réponse aura un format, et un packet TCP/IP en aura un autre

    bref tu vas devoir réinventer la gestion des protocoles dans ton programme

    sinon c'est la magie de l'opensource tu vas chercher les sources de l'outil "ping" pour voir comment il réagit.

    il me semble que l'outil ping permet aussi de preciser l'interface ou l'IP source avec laquelle tu ping

    • [^] # Re: le Principe...

      Posté par  (site web personnel) . Évalué à 2.

      Merci de ton aide, j'ai corrigé le post pour dire que je suis bloqué dans la fonction car je ne reçois rien (je la ferai async via epoll quand je corrigerai ce problème).

      Je suis bien conscient que je vais devoir décoder les différents protocole (ethernet, IPv4, ICMP), au même titre que j'ai du encodé mon packet ethernet (OSI Layer 2 oblige).

      Les sources sur internet ne m'ont pas aidé et la plus part utilise directement l'icmp, pas l'ethernet.

      Mon projet libre: http://ultracopier-fr.first-world.info/, mon jeu libre: http://catchchallenger.first-world.info/

      • [^] # Re: le Principe...

        Posté par  . Évalué à 2.

        Les sources sur internet ne m'ont pas aidé et la plus part utilise directement l'icmp, pas l'ethernet.

        en meme temps un ping au niveau protocole c'est de l'ICMP

        maintenant si ton "ping" c'est envoyé une requête qui n'est pas un ping pour detecter que la passerelle est UP, ce n'est en effet plus de l'ICMP et il faut revoir comment on ouvre/referme le flux.

        est-ce qu'un "ping" normal passe entre la machine et la passerelle ?
        est-ce qu'un netcat/socat vers la passerelle et le port que tu vises fonctionne ?

        • [^] # Re: le Principe...

          Posté par  (site web personnel, Mastodon) . Évalué à 1.

          Les sources sur internet ne m'ont pas aidé et la plus part utilise directement l'icmp, pas l'ethernet.

          en meme temps un ping au niveau protocole c'est de l'ICMP

          Attention… ICMP c'est plusieurs choses (types) dont la commande ping utilise une partie et la commande traceroute une autre. Dans le man sur Mac OS (donc implémentation BSD), je peux lire :

          The ping utility uses the ICMP protocol's mandatory ECHO_REQUEST datagram to elicit an ICMP ECHO_RESPONSE from a host or gateway.

          Et là où tu as raison, c'est que c'est la partie ECHO REPLY (types 8 et 0) qui est utilisée traditionnellement.
          Mais quelques ping (et psping de Microsoft), ainsi que les commandes echoping/hping/mtr/nping par exemple, permettent d'utiliser TCP et/ou UDP… Dans ces cas on veut souvent tester un port et on pourrait utiliser aussi nc ou nmap entre autres. Le ping est en fait la notion de savoir si un hôte est joignable ou pas.

          “It is seldom that liberty of any kind is lost all at once.” ― David Hume

        • [^] # Re: le Principe...

          Posté par  (site web personnel) . Évalué à 2.

          Bonjour, manuellement tout fonctione ICMP ECHO_REQUEST, ICMP ECHO_RESPONSE.
          Actuellement c'est mon programme qui ne reçois pas le paquet.

          Mon projet libre: http://ultracopier-fr.first-world.info/, mon jeu libre: http://catchchallenger.first-world.info/

      • [^] # Re: le Principe...

        Posté par  . Évalué à 3.

        Bonjour alpha_one_x86,

        Je suis bien conscient que je vais devoir décoder les différents protocole (ethernet, IPv4, ICMP), au même titre que j'ai du encodé mon packet ethernet (OSI Layer 2 oblige).

        Les sources sur internet ne m'ont pas aidé et la plus part utilise directement l'icmp, pas l'ethernet.

        En fait, si ce que tu souhaites faire est bien un ping (au sens ICMP), je ne pense pas qu'il soit nécessaire (ni même vraiment souhaitable d'ailleurs) de descendre jusqu'à la couche Ethernet.
        Une solution à base de socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) doit fonctionner. (ce qui correspond probablement à ce que tu as trouvé sur le net ?)

        Mais comme tu veux que le paquet ICMP echo sorte par la bonne interface, il suffit juste de faire un bind() de cette socket sur l'adresse IP de l'interface de sortie à utiliser. (Tu peux mettre 0 pour le port dans ce cas)

        C'est d'ailleurs exactement ce que fait ping avec l'option -I chez moi (visible avec strace). Je pense que c'est l'option dont parle Neox.

        Ainsi tu ne "descends" pas en dessous de la couche IP, et donc grâce au modèle OSI :

        • tu ne présupposes plus rien quant au type de réseau de niveau 2 (qui n'a pas à être Ethernet forcément)
        • si c'est de l'Ethernet, tu n'as pas à gérer des adresses MAC, il y aura résolution ARP
        • les 2 machines n'ont plus à être sur le même réseau de niveau 2, si demain tu insères un routeur intermédiaire par exemple

        Ça pourrait déjà bien simplifier les choses, y compris pour le décodage de la réponse.

        Sinon, pour voir les paquets réseau qui sortent et rentrent, rien de tel que wireshark, ou tout simplement tcpdump. Par exemple dans ton cas :

        tcpdump -v -n -e icmp
        

        En espérant ne pas répondre trop à côté de a plaque :)

        • [^] # Re: le Principe...

          Posté par  . Évalué à 1.

          En relisant mieux la question, je me rends compte que j'ai plutôt bien réussi à répondre à côté de la plaque :)

          Donc on oublie ma réponse précédente, désolé pour le bruit…

        • [^] # Re: le Principe...

          Posté par  (site web personnel) . Évalué à 2.

          Bonjour, merci pour cette réponse pertinente, mon programme actuel utilise déjà socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), mais je n'est pas su envoyé sur une passerelle spécifique. https://github.com/Confiared/epollpingmultihoming
          Je m'en sert pour choisir la bonne passerelle et le bon FAI par ip (192.168.100.1 FAI 1, 192.168.1.2 FAI 2), utilisé les adresses mac ne me pose pas de problème dans mon cas.

          Mon projet libre: http://ultracopier-fr.first-world.info/, mon jeu libre: http://catchchallenger.first-world.info/

          • [^] # Re: le Principe...

            Posté par  . Évalué à 3.

            simplifie toi la vie

            si tu as 2 FAI, et 2 reseaux, j'imagine que tu veux pinguer un équipement derriere le FAI (un DNS publique par exemple)

            si tu prend 2 notes publiques au pif 8.8.8.8 et 6.6.6.6
            ajoutes les routes spécifique pour chacun par la box de chaque opérateur

            ip r a 8.8.8.8 via 192.168.1.1
            ip r a 6.6.6.6 via 192.168.100.254

            ensuite dans ton programme tu fais juste un ping 8.8.8.8 => ca teste le FAI 192.168.1.x
            et quand tu ping 6.6.6.6 ca teste le FAI 192.168.100.x

            • [^] # Re: le Principe...

              Posté par  (site web personnel) . Évalué à 2.

              C'est déjà ce que je fait et c'est ce qui pose problème.
              Une IP spécifique peu être accessible que depuis un FAI et une autre IP depuis l'autre FAI.
              Je m'en suis sortie en écrivant les paquets ethernet à la main.

              Mon projet libre: http://ultracopier-fr.first-world.info/, mon jeu libre: http://catchchallenger.first-world.info/

              • [^] # Re: le Principe...

                Posté par  . Évalué à 3.

                Une IP spécifique peu être accessible que depuis un FAI et une autre IP depuis l'autre FAI.

                donc la route devrait etre prise en compte dans ton "ping"
                mais si tu forces l'interface, forcement ce n'est plus bon

                et si tu veux que ton programme soit générique, il vaut mieux faire ton ping sans selection de route (ou le prévoir dans l'interface)

                et configurer les routes comme indiqué pour qu'un paquet pour 6.6.6.6 parte par l'interface 1 et 8.8.8.8 par l'interface 2

                mais c'est l'OS qui va s'en charger pour toi.

                • [^] # Re: le Principe...

                  Posté par  (site web personnel) . Évalué à 2. Dernière modification le 23 mai 2021 à 15:33.

                  C'est ce que je fessait et cela générais beaucoup de problème

                  Mon projet libre: http://ultracopier-fr.first-world.info/, mon jeu libre: http://catchchallenger.first-world.info/

                  • [^] # Re: le Principe...

                    Posté par  . Évalué à 2.

                    C'est ce que je fessait et cela générais beaucoup de problème

                    lesquels ?

                    • [^] # Re: le Principe...

                      Posté par  (site web personnel) . Évalué à 2.

                      • X peut être accessible depuis 1.0.0.1 (FAI 1)
                      • Y peut être accessible depuis 1.0.0.2 (FAI 2)
                      • Z peut être accessible depuis 1.0.0.1 et 1.0.0.2 (FAI 1 et 2) avec une détection de route par destination je peu avoir toute les ip accessible. Ce que je ne pas faire si je regarde juste si le FAI 1 ou 2 est fonctionnel.

                      Mon projet libre: http://ultracopier-fr.first-world.info/, mon jeu libre: http://catchchallenger.first-world.info/

  • # capability/setuid/root ?

    Posté par  . Évalué à 2.

    Hello,
    je ne sais pas si c'est toujours le cas, mais il me semble que pour envoyer des paquets ICMP, il faut des droits élevés, qui sont obtenus soit en lançant le programme en root, soit en donnant les bons droits (avec setcap), soit en ayant le binaire setuid.

    Est-ce le cas ?

    Et, question un peu basique : es-tu certain que le paquet est bien envoyé ? C'est à dire tu le vois partir de la machine A, et arriver sur la machine B.

    • [^] # Re: capability/setuid/root ?

      Posté par  (site web personnel) . Évalué à 2.

      Je confirme, mon programmes tourne en root pour cela, et pour avoir le droit pour changer les routes.

      Le paquete est bien envoyé et recu par la machine (vérifié avec dumpcap/wireshark)

      Mon projet libre: http://ultracopier-fr.first-world.info/, mon jeu libre: http://catchchallenger.first-world.info/

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.