How can I get the IP address of a (Linux) machine?

This Question is almost the same as the previously asked How can I get the IP Address of a local computer? -Question. However I need to find the IP address(es) of a Linux Machine.

So: How do I - programmatically in C++ - detect the IP addresses of the linux server my application is running on. The servers will have at least two IP addresses and I need a specific one (the one in a given network (the public one)).

I'm sure there is a simple function to do that - but where?


To make things a bit clearer:

  • The server will obviously have the "localhost": 127.0.0.1
  • The server will have an internal (management) IP address: 172.16.x.x
  • The server will have an external (public) IP address: 80.190.x.x

I need to find the external IP address to bind my application to it. Obviously I can also bind to INADDR_ANY (and actually that's what I do at the moment). I would prefer to detect the public address, though.


I found the ioctl solution problematic on os x (which is POSIX compliant so should be similiar to linux). However getifaddress() will let you do the same thing easily, it works fine for me on os x 10.5 and should be the same below.

I've done a quick example below which will print all of the machine's IPv4 address, (you should also check the getifaddrs was successful ie returns 0).

I've updated it show IPv6 addresses too.

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

int main (int argc, const char * argv[]) {
    struct ifaddrs * ifAddrStruct=NULL;
    struct ifaddrs * ifa=NULL;
    void * tmpAddrPtr=NULL;

    getifaddrs(&ifAddrStruct);

    for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
        if (!ifa->ifa_addr) {
            continue;
        }
        if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4
            // is a valid IP4 Address
            tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
            char addressBuffer[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
            printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); 
        } else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6
            // is a valid IP6 Address
            tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
            char addressBuffer[INET6_ADDRSTRLEN];
            inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
            printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); 
        } 
    }
    if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct);
    return 0;
}

  1. Create a socket.
  2. Perform ioctl(<socketfd>, SIOCGIFCONF, (struct ifconf)&buffer);

Read /usr/include/linux/if.h for information on the ifconf and ifreq structures. This should give you the IP address of each interface on the system. Also read /usr/include/linux/sockios.h for additional ioctls.


I like jjvainio's answer. As Zan Lnyx says, it uses the local routing table to find the IP address of the ethernet interface that would be used for a connection to a specific external host. By using a connected UDP socket, you can get the information without actually sending any packets. The approach requires that you choose a specific external host. Most of the time, any well-known public IP should do the trick. I like Google's public DNS server address 8.8.8.8 for this purpose, but there may be times you'd want to choose a different external host IP. Here is some code that illustrates the full approach.

void GetPrimaryIp(char* buffer, size_t buflen) 
{
    assert(buflen >= 16);

    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    assert(sock != -1);

    const char* kGoogleDnsIp = "8.8.8.8";
    uint16_t kDnsPort = 53;
    struct sockaddr_in serv;
    memset(&serv, 0, sizeof(serv));
    serv.sin_family = AF_INET;
    serv.sin_addr.s_addr = inet_addr(kGoogleDnsIp);
    serv.sin_port = htons(kDnsPort);

    int err = connect(sock, (const sockaddr*) &serv, sizeof(serv));
    assert(err != -1);

    sockaddr_in name;
    socklen_t namelen = sizeof(name);
    err = getsockname(sock, (sockaddr*) &name, &namelen);
    assert(err != -1);

    const char* p = inet_ntop(AF_INET, &name.sin_addr, buffer, buflen);
    assert(p);

    close(sock);
}

As you have found out there is no such thing as a single "local IP address". Here's how to find out the local address that can be sent out to a specific host.

  1. Create a UDP socket
  2. Connect the socket to an outside address (the host that will eventually receive the local address)
  3. Use getsockname to get the local address