2

A friend used the following snippet of code to retrieve the local IP address of the host in his LAN.

int buffersize = 512;
char name[buffersize];

if(gethostname(name, buffersize) == -1){
    Exception excep("Failed to retrieve the name of the computer");
    excep.raise();
}

struct hostent *hp = gethostbyname(name);
if(hp == NULL){
    Exception excep("Failed to retrieve the IP address of the local host");
    excep.raise();
}

struct in_addr **addr_list = (struct in_addr **)hp->h_addr_list;
for(int i = 0; addr_list[i] != NULL; i++) {
    qDebug() << QString(inet_ntoa(*addr_list[i]));
}

It appears to work fine on his Mac. He said that the last IP address in that array was the one he needed to know. However, I got these values on my Linux laptop...

127.0.0.2
192.168.5.1
1.2.3.0

These looks similar to the values used by my adapters, but not the same. Here's some ifconfig data:

eth0      Link encap:Ethernet  HWaddr 1C:C1:DE:91:54:1A  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
wlan0     Link encap:Ethernet  HWaddr [bleep]
          inet addr:192.168.1.6  Bcast:192.168.1.255  Mask:255.255.255.0

It appears that some of the bits were scrambled. Are we missing a crucial conversion here?

Pieter
  • 31,619
  • 76
  • 167
  • 242
  • I tested your code on Windows (VS2010; so didn't use Exception and QString) and it's returning ok values for IP addresses. – Bojan Komazec Nov 12 '11 at 19:28
  • Maybe there's a difference in the way my hosts saves certain data? I've been told that networks have a universally agreed way of representing data and that's why you have to do "network to host" and "host to network" conversions on certain things. – Pieter Nov 12 '11 at 19:36
  • `inet_ntoa` is deprecated, as it turns out. But then how do I decode each of the strings in `addr_list`, which according to manpages are encoded in network byte order, back to host order? I tried `ntohs()` on each character, but that didn't have the expected result. – Pieter Nov 12 '11 at 22:03
  • possible duplicate of [Get the IP Address of local computer](http://stackoverflow.com/questions/122208/get-the-ip-address-of-local-computer) – Robᵩ Nov 12 '11 at 22:09
  • There are lots of people who suggest the solution you found. They are wrong -- using gethostname() and gethostbyname() is not very robust. Try this answer: http://stackoverflow.com/questions/122208/get-the-ip-address-of-local-computer/1317284#1317284, or call [`getsockname()`](http://www.kernel.org/doc/man-pages/online/pages/man2/getsockname.2.html) on a connected socket. – Robᵩ Nov 12 '11 at 22:13

2 Answers2

0

If you really use Qt, you can use this code

foreach (const QHostAddress& address, QNetworkInterface::allAddresses() ) {
        qDebug() << address.toString();
    }

If you are not using Qt, you can study, how it is made there.

Lol4t0
  • 12,444
  • 4
  • 29
  • 65
  • I'm making this for a Computer Networking course assignment and they won't allow us to use external libraries to do anything network-related so that we'd gain more insight into the low-level stuff. This looks useful for future projects though, thanks. – Pieter Nov 13 '11 at 10:01
0

The method you suggest relies upon a "correct" local host name, and a "correctly" configured DNS system. I put "correct" in quotes, because having a local host name that is not registered with DNS is perfectly valid for every purpose, except your program.

If you have a connected socket (or can generate a connected socket), I suggest you use getsockname() to find a local IP address. (Note: not the local IP address -- you could have several.)

Here is a sample program that does that. Obviously, most of it is connecting to google.com and printing the result. Only the call to getsockname() is germane to your question.

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

#include <stdio.h>
#include <errno.h>
#include <unistd.h>


int main(int ac, char **av) {
    addrinfo *res;
    if(getaddrinfo("google.com", "80", 0, &res)) {
        fprintf(stderr, "Can't lookup google.com\n");
        return 1;
    }

    bool connected = false;
    for(; res; res=res->ai_next) {
        int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
        if(fd < 0) {
            perror("socket");
            continue;
        }

       if( connect(fd, res->ai_addr, res->ai_addrlen) ) {
           perror("connect");
           close(fd);
           continue;
       }

       sockaddr_in me;
       socklen_t socklen = sizeof(me);
       if( getsockname(fd, (sockaddr*)&me, &socklen) ) {
           perror("getsockname");
           close(fd);
           continue;
       }

       if(socklen > sizeof(me)) {
           close(fd);
           continue;
       }

       char name[64];
       if(getnameinfo((sockaddr*)&me, socklen, name, sizeof name, 0, 0, NI_NUMERICHOST)) {
           fprintf(stderr, "getnameinfo failed\n");
           close(fd);
           continue;
        }
        printf("%s ->", name);

       if(getnameinfo(res->ai_addr, res->ai_addrlen, name, sizeof name, 0, 0, NI_NUMERICHOST)) {
           fprintf(stderr, "getnameinfo failed\n");
           close(fd);
           continue;
        }
        printf("%s\n", name);
        close(fd);
    }
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308