0

what is the correct way to use gethostbyname() in c to retrive the real ip address of the host. Also why would people say DHCP would put this approach in potential danger ?

Mat
  • 202,337
  • 40
  • 393
  • 406
yuan
  • 317
  • 1
  • 4
  • 12
  • https://msdn.microsoft.com/en-us/library/windows/desktop/ms738524(v=vs.85).aspx – Abhineet May 06 '15 at 06:25
  • The *correct* approach is to not use `gethostbyname()` at all. It is deprecated. Use `getaddrinfo()` instead. As for why either is *potentially* dangerous is because it relies on DNS lookups, and DNS attacks and faulty DNS configurations can make false information be reported. – Remy Lebeau May 07 '15 at 02:25

2 Answers2

1

A supplement to Jordan's answer(He has been inactive for 7 years so there is no way to edit his answer...)

  1. A typo
    char * host_name = "mail.google.com";
    
  2. After getting a vector of struct in_addr(v4) or struct in6_addr(v6), you can use inet_ntop() to retrieve the IP address
    #include <string.h>
    #include <arpa/inet.h>
    
    char ip_address[INET6_ADDRSTRLEN]; // sufficient for both v4 and v6 address
    memset(ip_address, 0,  INET6_ADDRSTRLEN);
    
    // for the case of v4
    for (int i = 0; address_list[i] != NULL; i++) {
        inet_ntop(AF_INET, &address_list[i], ip_address, INET_ADDRSTRLEN);
    }
    
    // for the case of v6
    for (int i = 0; address_list[i] != NULL; i++) {
        inet_ntop(AF_INET6, &address_list[i], ip_address, INET_ADDRSTRLEN);
    }
    printf("%s", ip_address);
    
  3. You may notice the weird type of hostent.h_addr_list, why does it have type char **, this is a historical problem.
    Further reading: why-is-h-addr-list-in-struct-hostent-a-char-instead-of-struct-in-addr

Complete code:

#include <stdio.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>

int main() {
    char * hostname = "www.google.com";
    struct hostent * hp = gethostbyname(hostname);
    char ip_address[INET6_ADDRSTRLEN];
    memset(ip_address, 0, INET6_ADDRSTRLEN); 
    struct in_addr ** p1 = NULL;
    struct in6_addr ** p2 = NULL;

    switch (hp->h_addrtype) {
        case AF_INET:
            p1 = (struct in_addr **)hp->h_addr_list;

            for(int i = 0; p1[i]!=NULL; i+=1) {
                inet_ntop(AF_INET, &p1[i], ip_address, INET_ADDRSTRLEN);
                printf("%s\n", ip_address);
                *ip_address = '\0';
            }
            break;
        case AF_INET6:
            p2 = (struct in6_addr **)hp->h_addr_list;
            for(int i = 0; p2[i]!=NULL; i+=1) {
                inet_ntop(AF_INET6, &p2[i], ip_address, INET6_ADDRSTRLEN);
                printf("%s\n", ip_address);
                *ip_address = '\0';
            }
            break;
    }
}
Steve Lau
  • 658
  • 7
  • 13
0

The gethostbyname() function returns information about the host by using DNS to look up the name.

The function's return data type and parameters are shown below:

struct hostent* gethostbyname(const char *name);

An example to extract a list of IP addresses from a hostname (in this case, "mail.google.com") is shown below:

char host_name = "mail.google.com";
struct hostent *host_info = gethostbyname(host_name);

if (host_info == NULL) 
{
    return(-1);
}

if (host_info->h_addrtype == AF_INET)
{
    struct in_addr **address_list = (struct in_addr **)host_info->h_addr_list;
    for(int i = 0; address_list[i] != NULL; i++)
    {
        // use *(address_list[i]) as needed...
    }
}
else if (host_info->h_addrtype == AF_INET6)
{
    struct in6_addr **address_list = (struct in6_addr **)host_info->h_addr_list;
    for(int i = 0; address_list[i] != NULL; i++)
    {
        // use *(address_list[i]) as needed...
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770