Question

I'm trying to retrieve the IP Address of the local machine in my program. The Operating System is Ubuntu 8.10. I tried using gethostname() and gethostbyname() to retrieve the IP Address. The answer I received is 127.0.1.1. I learned that it seems to be a Debian thing: The document linked here explained the idea.

The content of my /etc/hosts file is:

127.0.0.1 localhost
127.0.1.1 mymachine

In this case, is there any other way to programmatically (prefer C or C++) to get the IP Address without modifying the system file on the machine?

Was it helpful?

Solution

See "netdevice", through man netdevice or on the web.
SIOCGIFCONF can then be used to get an enumeration of all transport layer addresses.

Edit (on manpages): man is a very useful command on Linux (or other UNIX-like systems as well). It shows a brief description of most commands, library functions, programs, etc. Open a shell prompt and type man ls or man netdevice, and you'll see what I mean.

Edit (on general retrieving of IP): The easiest way, if you think the C way is too messy, is a simple shell script like (just from the top of my head):
ifconfig|grep 'inet addr'|awk '{print $2}'|sed 's/addr://g'

Edit (on the Brain solution): What he does is using the if_nameindex() function for finding all network device names, and then the SIOCFIFCONF ioctl on each of these names for finding their IP. As he says, it only lists one IP per device.

OTHER TIPS

Here's some quick and dirty code that demonstrates SIOCGIFCONF :

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int sock, i;
    struct ifreq ifreqs[20];
    struct ifconf ic;

    ic.ifc_len = sizeof ifreqs;
    ic.ifc_req = ifreqs;

    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        perror("socket");
        exit(1);
    }

    if (ioctl(sock, SIOCGIFCONF, &ic) < 0) {
        perror("SIOCGIFCONF");
        exit(1);
    }

    for (i = 0; i < ic.ifc_len/sizeof(struct ifreq); ++i)
        printf("%s: %s\n", ifreqs[i].ifr_name,
                inet_ntoa(((struct sockaddr_in*)&ifreqs[i].ifr_addr)->sin_addr));

    return 0;
}

I get the following output on my Linux machine.

lo: 127.0.0.1
br0: 192.168.0.42
dummy1: 10.0.0.2

So, as per Ken's point:

ip addr show scope global | grep inet | cut -d' ' -f6 | cut -d/ -f1

Shame that when the Debian gods made the "ip" command they didn't think to add a simple command to get just the ip address.

Take a look at the netdevice man page. Call SIOCGIFCONF to obtain a list of all the interfaces and their addresses.

Thanks all for the shares!

For a bash solution, this what I ended up going with:

#!/bin/bash

/sbin/ifconfig|fgrep 'inet addr:'|fgrep -v '127'|cut -d: -f2|awk '{print $1}'|head -n1

The head ensures the primary ip is returned, as multi homed and/or logical interfaces will also be returned without the head.

So if the script was located at /sbin/get_primary_ip, you could do stuff like:

foo=$(get_primary_ip)

ifconfig is deprecated and old. iproute2 is the new stack, use the ip command:

ip addr, and parse from there.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top