views:

63

answers:

2

I've been working through a small tutorial on how to build a basic packet sniffer for Linux. I got everything working, and I now want to add IP-to-host mapping.

Everything was working before I added this function:

void IPtoHostname(char *ipaddress, char *hostname){
    struct hostent *host;
    in_addr_t ip = inet_addr(ipaddress);
    if (!hostname){
        puts("Can't allocate memory...");
        exit(-1);
    }
    host = gethostbyaddr((char *)&ip, 32, AF_INET);
    hostname = strdup(host->h_name);
}

This basically takes a string IP address ("192.168.28.18") ipaddress and fills in that IP's hostname ("who.cares.com") into hostname.

=================================== EDIT ================================

Apparently, this appears to be an issue with my understanding gethostbyaddr() (I apologize for the misnomeric question title and the nasty little edit), as after rewriting the function to:

void IPtoHostname(char *ipaddress, char **hostname){
    struct hostent *host;
    in_addr_t ip = inet_addr(ipaddress);
    host = gethostbyaddr((char *)&ip, 32, AF_INET);
    if (!host){
        puts("Packet damage?");
        return;
    }
    *hostname = strdup(host->h_name);
}

It prints out packet damage. Every single time.

+3  A: 

Nothing is up with strlen. You need to pass in char **hostname, then set *hostname equal to host->h_name, assuming you're doing your strlen outside of IPToHostName. You're setting a local copy of your hostname pointer.

So you have something like this:

char myip[]  = "123.45.67.89";
char *myhost = NULL;

IPToHostname(myip, myhost); /* this sets its own local copy of myhost, which is on the stack */

/* At this point, myhost is still null!! */

If you change it to be like the code below it'll probably do what you want.

void IPtoHostname(char *ipaddress, char **hostname)
{
    assert(hostname); /* you'll need to include assert.h for this - it'll abort your program in debug mode if hostname is null */

    struct hostent *host;
    in_addr_t ip = inet_addr(ipaddress);
    if (!hostname)
    {
        puts("Can't allocate memory...");
        exit(-1);
    }
    host = gethostbyaddr((char *)&ip, 32, AF_INET);
    *hostname = strdup(host->h_name);
}

char myip[]  = "123.45.67.89";
char *myhost = NULL;

IPtoHostname(myip, &myhost);
George
Actually, as it turns out, gethostbyaddr was at fault here. Thanks for the tip, though.
new123456
A: 

Wow... Never fight POSIX. I eventually wrote my function to this:

#define MAXHOST 256

char *IPtoHostname(char *ipaddress){
    struct in_addr iaddr;
    inet_pton(AF_INET, ipaddress, &iaddr);
    struct sockaddr_in saddr;
    saddr.sin_family =  AF_INET;
    saddr.sin_addr = iaddr;

    char *hostname = (char *)malloc(sizeof(char) * MAXHOST);
    if (getnameinfo((struct sockaddr*)&saddr, 32, hostname, MAXHOST, NULL, 0, 0) == -1){
        puts("Cannot reverse engineer IP");
        return;
    }
    return hostname;
}

And it works!

new123456