How to know ip address for interfaces in c

190 篇文章 1 订阅


Let's say I'm running a program called IpAddresses.c I want that program to get all IP addresses this device has according to each interface. Just like ifconfig. How can I do that.

I don't know much about ioctl but I read it might help me

share | edit
 
2  
What is your platform? –  Steve Townsend  Nov 9 '10 at 22:39
 
You don't need ioctl() if you have getifaddrs() on your machine. I included an example in my answer below. –  chrisaycock  Nov 9 '10 at 23:47

5 Answers

up vote 3 down vote accepted

Just use getifaddrs(). Here's an example:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>

int main ()
{
    struct ifaddrs *ifap, *ifa;
    struct sockaddr_in *sa;
    char *addr;

    getifaddrs (&ifap);
    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr->sa_family==AF_INET) {
            sa = (struct sockaddr_in *) ifa->ifa_addr;
            addr = inet_ntoa(sa->sin_addr);
            printf("Interface: %s\tAddress: %s\n", ifa->ifa_name, addr);
        }
    }

    freeifaddrs(ifap);
    return 0;
}

And here's the output I get on my machine:

Interface: lo   Address: 127.0.0.1
Interface: eth0 Address: 69.72.234.7
Interface: eth0:1       Address: 10.207.9.3
share | edit
 
why do you have 2 eth0? btw, thnks for your answer –  gvalero87  Nov 10 '10 at 0:32
 
@gvalero87 The first eth0 tells the network card to communicate over the Internet. That second eth0 communicates over a private connection (optical line) to a third party. It's a setting in the routing table that the network admin put together. –  chrisaycock  Nov 10 '10 at 1:33

Check out the (Windows specificIP Helper API - fortunately you don't need ioctl for this on Windows.

share | edit
   

You could try something like that:

struct ifreq ifr[MAX_INTERFACES];
struct ifconf ifc;
memset(ifr, 0, sizeof(ifr));
ifc.ifc_len = sizeof(ifr);
ifc.ifc_req = ifr;

// Get the list of interfaces
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
    fprintf(stderr, "ioctl SIOCGIFCONF failed: %d", errno);
}

for (int i=0; i < ifc.ifc_len/sizeof(struct ifreq); ++i) {
    if (ifr[i].ifr_addr.sa_family != AF_INET) {
        continue;
    }

    // Maybe some more filtering based on SIOCGIFFLAGS

    // Your code
}
share | edit
 
1  
Note that this code will fail on BSD where the size of the ifreq struct is variable. You can't just assumeifc.ifc_len/sizeof(struct ifreq) will give you the interface count. Instead you need to iterate through the elements in the list like this: struct ifreq *ifr_iterator = ifc.ireq; size_t len; while (i < ifc.ifc_len) { /* DO STUFF */ len = IFNAMSIZ + ifr_iterator->ifr_addr.sa_len; ifr_iterator = (struct ifreq *)((char *)ifr_iterator + len); i += len; } –  Joakim  Sep 24 '12 at 9:20

See this other SO question.

In summary, you can use:

  • ioctl(SIOCGIFCONF) -> the traditional ioctl
  • getifaddrs() -> from BSDi, now also on Linux and the BSD's.
  • RTNETLINK (Linux)
share | edit
   

Here's some Linux sample code that might help you out.

#include <stdio.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>

#define INT_TO_ADDR(_addr) \
(_addr & 0xFF), \
(_addr >> 8 & 0xFF), \
(_addr >> 16 & 0xFF), \
(_addr >> 24 & 0xFF)

int main()
{
    struct ifconf ifc;
    struct ifreq ifr[10];
    int sd, ifc_num, addr, bcast, mask, network, i;

    /* Create a socket so we can use ioctl on the file 
     * descriptor to retrieve the interface info. 
     */

    sd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sd > 0)
    {
        ifc.ifc_len = sizeof(ifr);
        ifc.ifc_ifcu.ifcu_buf = (caddr_t)ifr;

        if (ioctl(sd, SIOCGIFCONF, &ifc) == 0)
        {
            ifc_num = ifc.ifc_len / sizeof(struct ifreq);
            printf("%d interfaces found\n", ifc_num);

            for (i = 0; i < ifc_num; ++i)
            {
                if (ifr[i].ifr_addr.sa_family != AF_INET)
                {
                    continue;
                }

                /* display the interface name */
                printf("%d) interface: %s\n", i+1, ifr[i].ifr_name);

                /* Retrieve the IP address, broadcast address, and subnet mask. */
                if (ioctl(sd, SIOCGIFADDR, &ifr[i]) == 0)
                {
                    addr = ((struct sockaddr_in *)(&ifr[i].ifr_addr))->sin_addr.s_addr;
                    printf("%d) address: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(addr));
                }
                if (ioctl(sd, SIOCGIFBRDADDR, &ifr[i]) == 0)
                {
                    bcast = ((struct sockaddr_in *)(&ifr[i].ifr_broadaddr))->sin_addr.s_addr;
                    printf("%d) broadcast: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(bcast));
                }
                if (ioctl(sd, SIOCGIFNETMASK, &ifr[i]) == 0)
                {
                    mask = ((struct sockaddr_in *)(&ifr[i].ifr_netmask))->sin_addr.s_addr;
                    printf("%d) netmask: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(mask));
                }                

                /* Compute the current network value from the address and netmask. */
                network = addr & mask;
                printf("%d) network: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(network));
            }                      
        }

        close(sd);
    }

    return 0;
}
share | edit
   

Let's say I'm running a program called IpAddresses.c I want that program to get all IP addresses this device has according to each interface. Just like ifconfig. How can I do that.

I don't know much about ioctl but I read it might help me

share | edit
 
2  
What is your platform? –  Steve Townsend  Nov 9 '10 at 22:39
 
You don't need ioctl() if you have getifaddrs() on your machine. I included an example in my answer below. –  chrisaycock  Nov 9 '10 at 23:47

5 Answers

up vote 3 down vote accepted

Just use getifaddrs(). Here's an example:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>

int main ()
{
    struct ifaddrs *ifap, *ifa;
    struct sockaddr_in *sa;
    char *addr;

    getifaddrs (&ifap);
    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr->sa_family==AF_INET) {
            sa = (struct sockaddr_in *) ifa->ifa_addr;
            addr = inet_ntoa(sa->sin_addr);
            printf("Interface: %s\tAddress: %s\n", ifa->ifa_name, addr);
        }
    }

    freeifaddrs(ifap);
    return 0;
}

And here's the output I get on my machine:

Interface: lo   Address: 127.0.0.1
Interface: eth0 Address: 69.72.234.7
Interface: eth0:1       Address: 10.207.9.3
share | edit
 
why do you have 2 eth0? btw, thnks for your answer –  gvalero87  Nov 10 '10 at 0:32
 
@gvalero87 The first eth0 tells the network card to communicate over the Internet. That second eth0 communicates over a private connection (optical line) to a third party. It's a setting in the routing table that the network admin put together. –  chrisaycock  Nov 10 '10 at 1:33

Check out the (Windows specificIP Helper API - fortunately you don't need ioctl for this on Windows.

share | edit
   

You could try something like that:

struct ifreq ifr[MAX_INTERFACES];
struct ifconf ifc;
memset(ifr, 0, sizeof(ifr));
ifc.ifc_len = sizeof(ifr);
ifc.ifc_req = ifr;

// Get the list of interfaces
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
    fprintf(stderr, "ioctl SIOCGIFCONF failed: %d", errno);
}

for (int i=0; i < ifc.ifc_len/sizeof(struct ifreq); ++i) {
    if (ifr[i].ifr_addr.sa_family != AF_INET) {
        continue;
    }

    // Maybe some more filtering based on SIOCGIFFLAGS

    // Your code
}
share | edit
 
1  
Note that this code will fail on BSD where the size of the ifreq struct is variable. You can't just assumeifc.ifc_len/sizeof(struct ifreq) will give you the interface count. Instead you need to iterate through the elements in the list like this: struct ifreq *ifr_iterator = ifc.ireq; size_t len; while (i < ifc.ifc_len) { /* DO STUFF */ len = IFNAMSIZ + ifr_iterator->ifr_addr.sa_len; ifr_iterator = (struct ifreq *)((char *)ifr_iterator + len); i += len; } –  Joakim  Sep 24 '12 at 9:20

See this other SO question.

In summary, you can use:

  • ioctl(SIOCGIFCONF) -> the traditional ioctl
  • getifaddrs() -> from BSDi, now also on Linux and the BSD's.
  • RTNETLINK (Linux)
share | edit
   

Here's some Linux sample code that might help you out.

#include <stdio.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>

#define INT_TO_ADDR(_addr) \
(_addr & 0xFF), \
(_addr >> 8 & 0xFF), \
(_addr >> 16 & 0xFF), \
(_addr >> 24 & 0xFF)

int main()
{
    struct ifconf ifc;
    struct ifreq ifr[10];
    int sd, ifc_num, addr, bcast, mask, network, i;

    /* Create a socket so we can use ioctl on the file 
     * descriptor to retrieve the interface info. 
     */

    sd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sd > 0)
    {
        ifc.ifc_len = sizeof(ifr);
        ifc.ifc_ifcu.ifcu_buf = (caddr_t)ifr;

        if (ioctl(sd, SIOCGIFCONF, &ifc) == 0)
        {
            ifc_num = ifc.ifc_len / sizeof(struct ifreq);
            printf("%d interfaces found\n", ifc_num);

            for (i = 0; i < ifc_num; ++i)
            {
                if (ifr[i].ifr_addr.sa_family != AF_INET)
                {
                    continue;
                }

                /* display the interface name */
                printf("%d) interface: %s\n", i+1, ifr[i].ifr_name);

                /* Retrieve the IP address, broadcast address, and subnet mask. */
                if (ioctl(sd, SIOCGIFADDR, &ifr[i]) == 0)
                {
                    addr = ((struct sockaddr_in *)(&ifr[i].ifr_addr))->sin_addr.s_addr;
                    printf("%d) address: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(addr));
                }
                if (ioctl(sd, SIOCGIFBRDADDR, &ifr[i]) == 0)
                {
                    bcast = ((struct sockaddr_in *)(&ifr[i].ifr_broadaddr))->sin_addr.s_addr;
                    printf("%d) broadcast: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(bcast));
                }
                if (ioctl(sd, SIOCGIFNETMASK, &ifr[i]) == 0)
                {
                    mask = ((struct sockaddr_in *)(&ifr[i].ifr_netmask))->sin_addr.s_addr;
                    printf("%d) netmask: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(mask));
                }                

                /* Compute the current network value from the address and netmask. */
                network = addr & mask;
                printf("%d) network: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(network));
            }                      
        }

        close(sd);
    }

    return 0;
}
share | edit
   



Let's say I'm running a program called IpAddresses.c I want that program to get all IP addresses this device has according to each interface. Just like ifconfig. How can I do that.

I don't know much about ioctl but I read it might help me

share | edit
 
2  
What is your platform? –  Steve Townsend  Nov 9 '10 at 22:39
 
You don't need ioctl() if you have getifaddrs() on your machine. I included an example in my answer below. –  chrisaycock  Nov 9 '10 at 23:47

5 Answers

up vote 3 down vote accepted

Just use getifaddrs(). Here's an example:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>

int main ()
{
    struct ifaddrs *ifap, *ifa;
    struct sockaddr_in *sa;
    char *addr;

    getifaddrs (&ifap);
    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr->sa_family==AF_INET) {
            sa = (struct sockaddr_in *) ifa->ifa_addr;
            addr = inet_ntoa(sa->sin_addr);
            printf("Interface: %s\tAddress: %s\n", ifa->ifa_name, addr);
        }
    }

    freeifaddrs(ifap);
    return 0;
}

And here's the output I get on my machine:

Interface: lo   Address: 127.0.0.1
Interface: eth0 Address: 69.72.234.7
Interface: eth0:1       Address: 10.207.9.3
share | edit
 
why do you have 2 eth0? btw, thnks for your answer –  gvalero87  Nov 10 '10 at 0:32
 
@gvalero87 The first eth0 tells the network card to communicate over the Internet. That second eth0 communicates over a private connection (optical line) to a third party. It's a setting in the routing table that the network admin put together. –  chrisaycock  Nov 10 '10 at 1:33

Check out the (Windows specificIP Helper API - fortunately you don't need ioctl for this on Windows.

share | edit
   

You could try something like that:

struct ifreq ifr[MAX_INTERFACES];
struct ifconf ifc;
memset(ifr, 0, sizeof(ifr));
ifc.ifc_len = sizeof(ifr);
ifc.ifc_req = ifr;

// Get the list of interfaces
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
    fprintf(stderr, "ioctl SIOCGIFCONF failed: %d", errno);
}

for (int i=0; i < ifc.ifc_len/sizeof(struct ifreq); ++i) {
    if (ifr[i].ifr_addr.sa_family != AF_INET) {
        continue;
    }

    // Maybe some more filtering based on SIOCGIFFLAGS

    // Your code
}
share | edit
 
1  
Note that this code will fail on BSD where the size of the ifreq struct is variable. You can't just assumeifc.ifc_len/sizeof(struct ifreq) will give you the interface count. Instead you need to iterate through the elements in the list like this: struct ifreq *ifr_iterator = ifc.ireq; size_t len; while (i < ifc.ifc_len) { /* DO STUFF */ len = IFNAMSIZ + ifr_iterator->ifr_addr.sa_len; ifr_iterator = (struct ifreq *)((char *)ifr_iterator + len); i += len; } –  Joakim  Sep 24 '12 at 9:20

See this other SO question.

In summary, you can use:

  • ioctl(SIOCGIFCONF) -> the traditional ioctl
  • getifaddrs() -> from BSDi, now also on Linux and the BSD's.
  • RTNETLINK (Linux)
share | edit
   

Here's some Linux sample code that might help you out.

#include <stdio.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>

#define INT_TO_ADDR(_addr) \
(_addr & 0xFF), \
(_addr >> 8 & 0xFF), \
(_addr >> 16 & 0xFF), \
(_addr >> 24 & 0xFF)

int main()
{
    struct ifconf ifc;
    struct ifreq ifr[10];
    int sd, ifc_num, addr, bcast, mask, network, i;

    /* Create a socket so we can use ioctl on the file 
     * descriptor to retrieve the interface info. 
     */

    sd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sd > 0)
    {
        ifc.ifc_len = sizeof(ifr);
        ifc.ifc_ifcu.ifcu_buf = (caddr_t)ifr;

        if (ioctl(sd, SIOCGIFCONF, &ifc) == 0)
        {
            ifc_num = ifc.ifc_len / sizeof(struct ifreq);
            printf("%d interfaces found\n", ifc_num);

            for (i = 0; i < ifc_num; ++i)
            {
                if (ifr[i].ifr_addr.sa_family != AF_INET)
                {
                    continue;
                }

                /* display the interface name */
                printf("%d) interface: %s\n", i+1, ifr[i].ifr_name);

                /* Retrieve the IP address, broadcast address, and subnet mask. */
                if (ioctl(sd, SIOCGIFADDR, &ifr[i]) == 0)
                {
                    addr = ((struct sockaddr_in *)(&ifr[i].ifr_addr))->sin_addr.s_addr;
                    printf("%d) address: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(addr));
                }
                if (ioctl(sd, SIOCGIFBRDADDR, &ifr[i]) == 0)
                {
                    bcast = ((struct sockaddr_in *)(&ifr[i].ifr_broadaddr))->sin_addr.s_addr;
                    printf("%d) broadcast: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(bcast));
                }
                if (ioctl(sd, SIOCGIFNETMASK, &ifr[i]) == 0)
                {
                    mask = ((struct sockaddr_in *)(&ifr[i].ifr_netmask))->sin_addr.s_addr;
                    printf("%d) netmask: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(mask));
                }                

                /* Compute the current network value from the address and netmask. */
                network = addr & mask;
                printf("%d) network: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(network));
            }                      
        }

        close(sd);
    }

    return 0;
}
share | edit
   


Let's say I'm running a program called IpAddresses.c I want that program to get all IP addresses this device has according to each interface. Just like ifconfig. How can I do that.

I don't know much about ioctl but I read it might help me

share | edit
 
2  
What is your platform? –  Steve Townsend  Nov 9 '10 at 22:39
 
You don't need ioctl() if you have getifaddrs() on your machine. I included an example in my answer below. –  chrisaycock  Nov 9 '10 at 23:47

5 Answers

up vote 3 down vote accepted

Just use getifaddrs(). Here's an example:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>

int main ()
{
    struct ifaddrs *ifap, *ifa;
    struct sockaddr_in *sa;
    char *addr;

    getifaddrs (&ifap);
    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr->sa_family==AF_INET) {
            sa = (struct sockaddr_in *) ifa->ifa_addr;
            addr = inet_ntoa(sa->sin_addr);
            printf("Interface: %s\tAddress: %s\n", ifa->ifa_name, addr);
        }
    }

    freeifaddrs(ifap);
    return 0;
}

And here's the output I get on my machine:

Interface: lo   Address: 127.0.0.1
Interface: eth0 Address: 69.72.234.7
Interface: eth0:1       Address: 10.207.9.3
share | edit
 
why do you have 2 eth0? btw, thnks for your answer –  gvalero87  Nov 10 '10 at 0:32
 
@gvalero87 The first eth0 tells the network card to communicate over the Internet. That second eth0 communicates over a private connection (optical line) to a third party. It's a setting in the routing table that the network admin put together. –  chrisaycock  Nov 10 '10 at 1:33

Check out the (Windows specificIP Helper API - fortunately you don't need ioctl for this on Windows.

share | edit
   

You could try something like that:

struct ifreq ifr[MAX_INTERFACES];
struct ifconf ifc;
memset(ifr, 0, sizeof(ifr));
ifc.ifc_len = sizeof(ifr);
ifc.ifc_req = ifr;

// Get the list of interfaces
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
    fprintf(stderr, "ioctl SIOCGIFCONF failed: %d", errno);
}

for (int i=0; i < ifc.ifc_len/sizeof(struct ifreq); ++i) {
    if (ifr[i].ifr_addr.sa_family != AF_INET) {
        continue;
    }

    // Maybe some more filtering based on SIOCGIFFLAGS

    // Your code
}
share | edit
 
1  
Note that this code will fail on BSD where the size of the ifreq struct is variable. You can't just assumeifc.ifc_len/sizeof(struct ifreq) will give you the interface count. Instead you need to iterate through the elements in the list like this: struct ifreq *ifr_iterator = ifc.ireq; size_t len; while (i < ifc.ifc_len) { /* DO STUFF */ len = IFNAMSIZ + ifr_iterator->ifr_addr.sa_len; ifr_iterator = (struct ifreq *)((char *)ifr_iterator + len); i += len; } –  Joakim  Sep 24 '12 at 9:20

See this other SO question.

In summary, you can use:

  • ioctl(SIOCGIFCONF) -> the traditional ioctl
  • getifaddrs() -> from BSDi, now also on Linux and the BSD's.
  • RTNETLINK (Linux)
share | edit
   

Here's some Linux sample code that might help you out.

#include <stdio.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>

#define INT_TO_ADDR(_addr) \
(_addr & 0xFF), \
(_addr >> 8 & 0xFF), \
(_addr >> 16 & 0xFF), \
(_addr >> 24 & 0xFF)

int main()
{
    struct ifconf ifc;
    struct ifreq ifr[10];
    int sd, ifc_num, addr, bcast, mask, network, i;

    /* Create a socket so we can use ioctl on the file 
     * descriptor to retrieve the interface info. 
     */

    sd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sd > 0)
    {
        ifc.ifc_len = sizeof(ifr);
        ifc.ifc_ifcu.ifcu_buf = (caddr_t)ifr;

        if (ioctl(sd, SIOCGIFCONF, &ifc) == 0)
        {
            ifc_num = ifc.ifc_len / sizeof(struct ifreq);
            printf("%d interfaces found\n", ifc_num);

            for (i = 0; i < ifc_num; ++i)
            {
                if (ifr[i].ifr_addr.sa_family != AF_INET)
                {
                    continue;
                }

                /* display the interface name */
                printf("%d) interface: %s\n", i+1, ifr[i].ifr_name);

                /* Retrieve the IP address, broadcast address, and subnet mask. */
                if (ioctl(sd, SIOCGIFADDR, &ifr[i]) == 0)
                {
                    addr = ((struct sockaddr_in *)(&ifr[i].ifr_addr))->sin_addr.s_addr;
                    printf("%d) address: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(addr));
                }
                if (ioctl(sd, SIOCGIFBRDADDR, &ifr[i]) == 0)
                {
                    bcast = ((struct sockaddr_in *)(&ifr[i].ifr_broadaddr))->sin_addr.s_addr;
                    printf("%d) broadcast: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(bcast));
                }
                if (ioctl(sd, SIOCGIFNETMASK, &ifr[i]) == 0)
                {
                    mask = ((struct sockaddr_in *)(&ifr[i].ifr_netmask))->sin_addr.s_addr;
                    printf("%d) netmask: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(mask));
                }                

                /* Compute the current network value from the address and netmask. */
                network = addr & mask;
                printf("%d) network: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(network));
            }                      
        }

        close(sd);
    }

    return 0;
}
share | edit
   

Let's say I'm running a program called IpAddresses.c I want that program to get all IP addresses this device has according to each interface. Just like ifconfig. How can I do that.

I don't know much about ioctl but I read it might help me

share | edit
 
2  
What is your platform? –  Steve Townsend  Nov 9 '10 at 22:39
 
You don't need ioctl() if you have getifaddrs() on your machine. I included an example in my answer below. –  chrisaycock  Nov 9 '10 at 23:47

5 Answers

up vote 3 down vote accepted

Just use getifaddrs(). Here's an example:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>

int main ()
{
    struct ifaddrs *ifap, *ifa;
    struct sockaddr_in *sa;
    char *addr;

    getifaddrs (&ifap);
    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr->sa_family==AF_INET) {
            sa = (struct sockaddr_in *) ifa->ifa_addr;
            addr = inet_ntoa(sa->sin_addr);
            printf("Interface: %s\tAddress: %s\n", ifa->ifa_name, addr);
        }
    }

    freeifaddrs(ifap);
    return 0;
}

And here's the output I get on my machine:

Interface: lo   Address: 127.0.0.1
Interface: eth0 Address: 69.72.234.7
Interface: eth0:1       Address: 10.207.9.3
share | edit
 
why do you have 2 eth0? btw, thnks for your answer –  gvalero87  Nov 10 '10 at 0:32
 
@gvalero87 The first eth0 tells the network card to communicate over the Internet. That second eth0 communicates over a private connection (optical line) to a third party. It's a setting in the routing table that the network admin put together. –  chrisaycock  Nov 10 '10 at 1:33

Check out the (Windows specificIP Helper API - fortunately you don't need ioctl for this on Windows.

share | edit
   

You could try something like that:

struct ifreq ifr[MAX_INTERFACES];
struct ifconf ifc;
memset(ifr, 0, sizeof(ifr));
ifc.ifc_len = sizeof(ifr);
ifc.ifc_req = ifr;

// Get the list of interfaces
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
    fprintf(stderr, "ioctl SIOCGIFCONF failed: %d", errno);
}

for (int i=0; i < ifc.ifc_len/sizeof(struct ifreq); ++i) {
    if (ifr[i].ifr_addr.sa_family != AF_INET) {
        continue;
    }

    // Maybe some more filtering based on SIOCGIFFLAGS

    // Your code
}
share | edit
 
1  
Note that this code will fail on BSD where the size of the ifreq struct is variable. You can't just assumeifc.ifc_len/sizeof(struct ifreq) will give you the interface count. Instead you need to iterate through the elements in the list like this: struct ifreq *ifr_iterator = ifc.ireq; size_t len; while (i < ifc.ifc_len) { /* DO STUFF */ len = IFNAMSIZ + ifr_iterator->ifr_addr.sa_len; ifr_iterator = (struct ifreq *)((char *)ifr_iterator + len); i += len; } –  Joakim  Sep 24 '12 at 9:20

See this other SO question.

In summary, you can use:

  • ioctl(SIOCGIFCONF) -> the traditional ioctl
  • getifaddrs() -> from BSDi, now also on Linux and the BSD's.
  • RTNETLINK (Linux)
share | edit
   

Here's some Linux sample code that might help you out.

#include <stdio.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>

#define INT_TO_ADDR(_addr) \
(_addr & 0xFF), \
(_addr >> 8 & 0xFF), \
(_addr >> 16 & 0xFF), \
(_addr >> 24 & 0xFF)

int main()
{
    struct ifconf ifc;
    struct ifreq ifr[10];
    int sd, ifc_num, addr, bcast, mask, network, i;

    /* Create a socket so we can use ioctl on the file 
     * descriptor to retrieve the interface info. 
     */

    sd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sd > 0)
    {
        ifc.ifc_len = sizeof(ifr);
        ifc.ifc_ifcu.ifcu_buf = (caddr_t)ifr;

        if (ioctl(sd, SIOCGIFCONF, &ifc) == 0)
        {
            ifc_num = ifc.ifc_len / sizeof(struct ifreq);
            printf("%d interfaces found\n", ifc_num);

            for (i = 0; i < ifc_num; ++i)
            {
                if (ifr[i].ifr_addr.sa_family != AF_INET)
                {
                    continue;
                }

                /* display the interface name */
                printf("%d) interface: %s\n", i+1, ifr[i].ifr_name);

                /* Retrieve the IP address, broadcast address, and subnet mask. */
                if (ioctl(sd, SIOCGIFADDR, &ifr[i]) == 0)
                {
                    addr = ((struct sockaddr_in *)(&ifr[i].ifr_addr))->sin_addr.s_addr;
                    printf("%d) address: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(addr));
                }
                if (ioctl(sd, SIOCGIFBRDADDR, &ifr[i]) == 0)
                {
                    bcast = ((struct sockaddr_in *)(&ifr[i].ifr_broadaddr))->sin_addr.s_addr;
                    printf("%d) broadcast: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(bcast));
                }
                if (ioctl(sd, SIOCGIFNETMASK, &ifr[i]) == 0)
                {
                    mask = ((struct sockaddr_in *)(&ifr[i].ifr_netmask))->sin_addr.s_addr;
                    printf("%d) netmask: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(mask));
                }                

                /* Compute the current network value from the address and netmask. */
                network = addr & mask;
                printf("%d) network: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(network));
            }                      
        }

        close(sd);
    }

    return 0;
}
share | edit
   

Let's say I'm running a program called IpAddresses.c I want that program to get all IP addresses this device has according to each interface. Just like ifconfig. How can I do that.

I don't know much about ioctl but I read it might help me

share | edit
 
2  
What is your platform? –  Steve Townsend  Nov 9 '10 at 22:39
 
You don't need ioctl() if you have getifaddrs() on your machine. I included an example in my answer below. –  chrisaycock  Nov 9 '10 at 23:47

5 Answers

up vote 3 down vote accepted

Just use getifaddrs(). Here's an example:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>

int main ()
{
    struct ifaddrs *ifap, *ifa;
    struct sockaddr_in *sa;
    char *addr;

    getifaddrs (&ifap);
    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr->sa_family==AF_INET) {
            sa = (struct sockaddr_in *) ifa->ifa_addr;
            addr = inet_ntoa(sa->sin_addr);
            printf("Interface: %s\tAddress: %s\n", ifa->ifa_name, addr);
        }
    }

    freeifaddrs(ifap);
    return 0;
}

And here's the output I get on my machine:

Interface: lo   Address: 127.0.0.1
Interface: eth0 Address: 69.72.234.7
Interface: eth0:1       Address: 10.207.9.3
share | edit
 
why do you have 2 eth0? btw, thnks for your answer –  gvalero87  Nov 10 '10 at 0:32
 
@gvalero87 The first eth0 tells the network card to communicate over the Internet. That second eth0 communicates over a private connection (optical line) to a third party. It's a setting in the routing table that the network admin put together. –  chrisaycock  Nov 10 '10 at 1:33

Check out the (Windows specificIP Helper API - fortunately you don't need ioctl for this on Windows.

share | edit
   

You could try something like that:

struct ifreq ifr[MAX_INTERFACES];
struct ifconf ifc;
memset(ifr, 0, sizeof(ifr));
ifc.ifc_len = sizeof(ifr);
ifc.ifc_req = ifr;

// Get the list of interfaces
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
    fprintf(stderr, "ioctl SIOCGIFCONF failed: %d", errno);
}

for (int i=0; i < ifc.ifc_len/sizeof(struct ifreq); ++i) {
    if (ifr[i].ifr_addr.sa_family != AF_INET) {
        continue;
    }

    // Maybe some more filtering based on SIOCGIFFLAGS

    // Your code
}
share | edit
 
1  
Note that this code will fail on BSD where the size of the ifreq struct is variable. You can't just assumeifc.ifc_len/sizeof(struct ifreq) will give you the interface count. Instead you need to iterate through the elements in the list like this: struct ifreq *ifr_iterator = ifc.ireq; size_t len; while (i < ifc.ifc_len) { /* DO STUFF */ len = IFNAMSIZ + ifr_iterator->ifr_addr.sa_len; ifr_iterator = (struct ifreq *)((char *)ifr_iterator + len); i += len; } –  Joakim  Sep 24 '12 at 9:20

See this other SO question.

In summary, you can use:

  • ioctl(SIOCGIFCONF) -> the traditional ioctl
  • getifaddrs() -> from BSDi, now also on Linux and the BSD's.
  • RTNETLINK (Linux)
share | edit
   

Here's some Linux sample code that might help you out.

#include <stdio.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>

#define INT_TO_ADDR(_addr) \
(_addr & 0xFF), \
(_addr >> 8 & 0xFF), \
(_addr >> 16 & 0xFF), \
(_addr >> 24 & 0xFF)

int main()
{
    struct ifconf ifc;
    struct ifreq ifr[10];
    int sd, ifc_num, addr, bcast, mask, network, i;

    /* Create a socket so we can use ioctl on the file 
     * descriptor to retrieve the interface info. 
     */

    sd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sd > 0)
    {
        ifc.ifc_len = sizeof(ifr);
        ifc.ifc_ifcu.ifcu_buf = (caddr_t)ifr;

        if (ioctl(sd, SIOCGIFCONF, &ifc) == 0)
        {
            ifc_num = ifc.ifc_len / sizeof(struct ifreq);
            printf("%d interfaces found\n", ifc_num);

            for (i = 0; i < ifc_num; ++i)
            {
                if (ifr[i].ifr_addr.sa_family != AF_INET)
                {
                    continue;
                }

                /* display the interface name */
                printf("%d) interface: %s\n", i+1, ifr[i].ifr_name);

                /* Retrieve the IP address, broadcast address, and subnet mask. */
                if (ioctl(sd, SIOCGIFADDR, &ifr[i]) == 0)
                {
                    addr = ((struct sockaddr_in *)(&ifr[i].ifr_addr))->sin_addr.s_addr;
                    printf("%d) address: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(addr));
                }
                if (ioctl(sd, SIOCGIFBRDADDR, &ifr[i]) == 0)
                {
                    bcast = ((struct sockaddr_in *)(&ifr[i].ifr_broadaddr))->sin_addr.s_addr;
                    printf("%d) broadcast: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(bcast));
                }
                if (ioctl(sd, SIOCGIFNETMASK, &ifr[i]) == 0)
                {
                    mask = ((struct sockaddr_in *)(&ifr[i].ifr_netmask))->sin_addr.s_addr;
                    printf("%d) netmask: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(mask));
                }                

                /* Compute the current network value from the address and netmask. */
                network = addr & mask;
                printf("%d) network: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(network));
            }                      
        }

        close(sd);
    }

    return 0;
}
share | edit
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值