Question

Pour une communication entre deux hôtes, je dois envoyer l'adresse IP de mon hôte à l'autre site. Le problème est que si je demande mon adresse IP, il se peut que je récupère mon adresse IP de bouclage local (127.x.x.x), et non l'adresse IP du réseau (Ethernet).

J'utilise le code suivant:

char myhostname[32];


gethostname(myhostname, 32);
hp = gethostbyname(myhostname);
unsigned my_ip = *(unsigned*)(hp->h_addr);

if( (my_ip % 256) == 127) {
  /* Wrong IP adress as it's 127.x.x.x */
  printf("Error, local IP address!");
  return;
}

La seule façon de le résoudre est de s’assurer que mon nom d’hôte dans / etc / hosts se trouve derrière la véritable adresse réseau et non dans le bouclage local (valeur par défaut pour Ubuntu, par exemple).

Existe-t-il un moyen de résoudre ce problème sans s'appuyer sur le contenu de / etc / hosts?

Modifier: J'ai modifié le code ci-dessus afin qu'il utilise getaddrinfo, mais je récupère toujours le numéro du périphérique de bouclage (127.0,0,1) au lieu de la véritable adresse IP:

struct addrinfo hint = {0};
struct addrinfo *aip = NULL;
unsigned ip = 0;
struct sockaddr_in *sinp = NULL;

hint.ai_family = AF_INET; /* IPv4 */
hint.ai_socktype = SOCK_STREAM;

if(getaddrinfo(hostname, NULL, &hint, &aip) != 0) {
    return 0;
}
sinp = (struct sockaddr_in *) aip->ai_addr;
ip   = *(unsigned *) &sinp->sin_addr;

(J'avais l'habitude de récupérer une liste de 3 addrinfo avec les trois SOCK_STREAM, SOCK_DGRAM et SOCK_RAW, mais le conseil l'empêche)

Donc ma question est toujours valable ...

Était-ce utile?

La solution

Il existe une fonction POSIX getaddrinfo () qui renvoie la liste d'adresses liée pour un nom d'hôte donné. Il vous suffit donc de parcourir cette liste et de rechercher une adresse sans retour en boucle.

Voir man getaddrinfo .

Autres conseils

Pas une réponse, mais un commentaire pertinent: sachez que dès que vous commencez à envoyer des informations d’adresse dans le contenu des paquets, vous courez le risque de rendre votre application incapable de fonctionner sur NAT: ing routeurs et / ou via des pare-feu.

Ces technologies reposent sur les informations contenues dans les en-têtes de paquets IP pour garder une trace du trafic. Si les applications échangent des informations d'adressage à l'intérieur de paquets, lorsqu'elles restent invisibles lors de cette inspection, elles risquent de se rompre.

Bien sûr, cela pourrait être totalement hors de propos pour votre candidature, mais j’ai pensé que cela valait la peine d’être souligné dans ce contexte.

L'adresse d'origine sera incluse dans le paquet envoyé ... il n'est pas nécessaire de dupliquer cette information. Il est obtenu lors de l'acceptation de la communication de l'hôte distant (voir le guide de mise en réseau de beej, en particulier la partie sur accept () )

Je viens de rencontrer une situation dans laquelle, lorsque seul / etc / hosts contient des informations et lorsque j'ai utilisé getaddrinfo pour obtenir la liste d'adresses IP, il renvoyait 127.0.0.1 à chaque fois. Il s'est avéré que le nom d'hôte s'appelait localhost ... ce qui est souvent facile à négliger. Voici ce qui s'est passé:

Le fichier / etc / hosts:
127.0.0.1 localhost.localdomain localhost foo
:: 1 localhost6.localdomain6 localhost6
172.16.1.248 foo
172.16.1.249 bie
172.16.1.250 bletch

Donc, maintenant, lorsque vous appelez getaddrinfo avec host = " toto " ;, il renvoie 127.0.0.1 3 fois. L’erreur ici est que foo apparaît à la fois sur la ligne avec "127.0.0.1" et "172.16.1.248". Une fois que j'ai supprimé foo de la ligne avec "127.0.0.1" les choses ont bien fonctionné.

J'espère que cela aide quelqu'un.

Regardez ceci: Découverte de la propriété intellectuelle publique par programmation

Notez que dans certains cas, un ordinateur peut avoir plusieurs adresses IP autres que le bouclage. Dans ce cas, les réponses à cette question indiquent comment obtenir celle qui est exposée à Internet.

Même si l'ordinateur ne dispose que d'une seule interface réseau physique (hypothèse que les netbooks peuvent ou non conserver, même les netbooks ont deux - Ethernet et WLAN), les VPN peuvent ajouter encore plus d'adresses IP. Dans tous les cas, l'hôte de l'autre côté devrait pouvoir déterminer l'adresse IP utilisée par votre hôte pour le contacter.

Vous êtes presque là. Je ne sais pas comment vous obtenez my_ip de hp .

gethostbyname () renvoie un pointeur sur une structure hostent qui comporte un champ h_addr_list .

Le champ h_addr_list est une liste de toutes les adresses IP liées à cet hôte, avec une terminaison nulle.

Je pense que vous obtenez l'adresse de bouclage parce que c'est la première entrée de h_addr_list .

EDIT: Cela devrait fonctionner à peu près comme ceci:

gethostname(myhostname, 32);
hp = gethostbyname(myhostname);
unsigned my_ip = *(unsigned*)(hp->h_addr);

for (int i = 0; hp->h_addr_list[i] != 0; ++i) {
  if (hp->h_addr_list[i] != INADDR_LOOPBACK) {
    // hp->addr_list[i] is a non-loopback address
  }
}
// no address found

Si / etc / hosts est toujours là et reste identique, la recherche de toutes les entrées de h_addr_list ne vous aidera pas.

Votre nouveau code enregistre l'utilisation d'IPv4 (dans le champ hint.ai_family), ce qui est une idée terrible.

Hormis cela, vous êtes proches, vous devez simplement parcourir les résultats de getaddrinfo. Votre code n’obtient que la première adresse IP, mais il y a un champ aip- & ai; ai_next à suivre ...

struct addrinfo {
       ...
       struct addrinfo *ai_next;       /* next structure in linked list */
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top