views:

1676

answers:

7

I'm trying to retrieve the ip address of the local machine in my program. The OS running is Ubuntu 8.10. I tried using gethostname() and gethostbyname to do it. All I can get is 127.0.1.1. I learned that it seems to be a Debian thing: This thread explained it.
The content of my /etc/hosts file is also:
127.0.0.1 localhost
127.0.1.1 mymachine

In this case, is there any other way to programactically (prefer C or C++) to get the ip address without modifying the system file on the machine? Thanks in advance.

g.c.

+1  A: 

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

sigjuice
+1  A: 

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.

E Dominique
Probably I should ask Brain, but that thread was dated back to last year, so I will ask here anyway, in what case a device can have multiple IP addresses? Can the program posted by sigjuice down here list all those IPs? I haven't seen device with multiple IPs, I guess I can't test it myself.
gc
No, the sigjuice solution is just like the Brain solution. An interface can have multiple IPs (though some WLAN interfaces cannot, as an example). It is normally not used, I'd say. Would you need an example that can list them as well? Have you played around with the current examples?
E Dominique
Sorry for taking so long to response, got caught on some other things. Yes, I've tried the examples, and they work. If it won't take you too much time, could you give me an example that can list all?
gc
Well, I seem to have been mistaken. The code (the sigjuice) lists all IPs on all machines I've tested it on, so with some polish you can use that one.
E Dominique
Ok, thanks again. I think I didn't see the difference while running the program because I don't have any device that has multiple IPs.
gc
Binding multiple IPs to a device in Linux (they term it 'IP aliasing') has an interesting side-effect: the IPs are not "first class citizens", that is, the device's primary IP is what is operated on, and any IP address that matches the alias(es) simply "come along for the ride".
Avery Payne
That is why you're probably seeing just a single IP address per interface- I would gamble that it is the "true" IP address that is bound to the device, and not the "aliases".
Avery Payne
+2  A: 

It already was covered here:

http://stackoverflow.com/questions/625663/how-to-get-my-non-loopback-network-ip-address-in-c

qrdl
Did not seem to find the answer I'm looking for
gc
Did you try to follow the link?
qrdl
A: 

Read the man page, probably I'm still new to Linux, no idea what it is talking about, micro? function? command or something else?

Found these two: the one answered by user called brain and http://www.usenet-forums.com/linux-networking/59447-ioctl-siocgifconf.html

The first one seems to work, though I'm still trying to understand how. If anyone can explain a little bit more for newbie as I am, would be greatly appreciated.

gc
+1  A: 

Here's some quick and dirty code that demonstrates SIOCGIFCONF. I get the following output on my Linux machine.

lo: 127.0.0.1
br0: 192.168.0.42
dummy1: 10.0.0.2


#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;
}
sigjuice
A: 

use libdumbnet library, it's included in debian.

A: 

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)
Kyle