2010-11-09 18 views

Respuesta

19

Simplemente use getifaddrs(). He aquí un ejemplo:

#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; 
} 

Y aquí está la salida de recibo en mi máquina:

Interface: lo Address: 127.0.0.1 
Interface: eth0 Address: 69.72.234.7 
Interface: eth0:1  Address: 10.207.9.3 
+0

¿por qué tienes 2 eth0? Por cierto, gracias por su respuesta – gvalero87

+0

@ gvalero87 El primer eth0 le dice a la tarjeta de red que se comunique a través de Internet. Ese segundo eth0 se comunica a través de una conexión privada (línea óptica) a un tercero. Es una configuración en la tabla de enrutamiento que el administrador de red armó. – chrisaycock

0

Mira la (de Windows específica) IP Helper API - afortunadamente no es necesario para este ioctl en Windows.

0

usted podría intentar algo así:

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 
} 
+3

Tenga en cuenta que este código fallará en BSD donde el tamaño de la estructura ifreq es variable. No puede suponer que 'ifc.ifc_len/sizeof (struct ifreq)' le dará la cuenta de la interfaz. En su lugar, debe recorrer los elementos de la lista de la siguiente manera: 'struct ifreq * ifr_iterator = ifc.ireq; size_t len; while (i ifr_addr.sa_len; ifr_iterator = (struct ifreq *) ((char *) ifr_iterator + len); i + = len; } ' – Joakim

+0

@Joakim por lo que significa que' '#define ifc_req ifc_ifcu.ifcu_req/* matriz de estructuras ret'd * /' 'técnicamente no es una matriz porque el tamaño varía? Parece que 5.9 ha agregado más cosas. También parece que el código ifconfig.c no tiene SIOCGIFCONF – GorillaApe

+0

@GorillaApe En un sistema puede ser una matriz, en otra no. Hay diferentes implementaciones es mi punto. En Linux esto es una matriz con cada elemento de un tamaño fijo, pero en BSD el tamaño de cada elemento puede variar, por lo que la forma correcta de hacerlo es usar siempre el campo de longitud. Si quieres código portátil, eso es. – Joakim

5

He aquí algunos Linux código de ejemplo que podría ayudarle a cabo.

#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; 
} 

+0

Gracias por una alternativa ioctl. Sin embargo, nunca sé, cuando debería usar 'ioctl' y cuándo' getifaddrs'. – Youda008

+0

Creo que 'ioctl' puede ser algo más portátil, incluso si no se ajusta a un estándar único.Es compatible con la mayoría de los sistemas tipo Unix y Unix y la llamada a la función 'ioctl' apareció por primera vez en la versión 7 AT & T UNIX. Creo que 'getifaddrs' es compatible con BSD y Linux y apareció por primera vez en glibc 2.3. – jschmier

+0

Esto también funciona en Android que no tiene el elemento 'ifaddrs' por alguna razón, pero no en OS X. [Aquí hay un ejemplo] (https://gist.github.com/OrangeTide/909204) que funciona en ambos. – Grishka

2

La solución utilizando getifaddrs() es grande. Sugeriría solo una mejora:

--- chrisaycock 
+++ normando 
@@ -11,7 +11,7 @@ 

    getifaddrs (&ifap); 
    for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 
-  if (ifa->ifa_addr->sa_family==AF_INET) { 
+  if (ifa->ifa_addr && 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); 

Solo porque yo recibí una falla de segmentación.

+0

Recibí una falla de segmentación. Este código lo arregla –

Cuestiones relacionadas