Volviendo a un artículo anterior donde hallábamos la dirección IP de un dispositivo, he decidido extender un poco la funcionalidad para poder hallar más información acerca de un dispositivo de red.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <sys/types.h> #include <sys/ioctl.h> #include <net/if.h> #include <string.h> #define get_addr(var) (*(struct in_addr *) &var.ifr_addr.sa_data[2]) int getdevinfo(char * ifname) { int sock; struct ifreq ifr; sock=socket(AF_INET, SOCK_DGRAM, 0); if (sock<0) return -1; /* No puedo crear el socket */ ifr.ifr_addr.sa_family = AF_INET; strcpy(ifr.ifr_name, ifname); if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) return -2; /* No encuentro el dispositivo */ printf("IP de %s: %s\n", ifname, inet_ntoa( get_addr(ifr))); if (ioctl(sock, SIOCGIFBRDADDR, &ifr)<0) return -3; /* Fallo al obtener broadcast */ if (get_addr(ifr).s_addr!=0) /* Si la direccion es 0.0.0.0 */ printf ("Broadcast de %s: %s\n", ifname, inet_ntoa(get_addr(ifr))); if (ioctl(sock, SIOCGIFNETMASK, &ifr)<0) return -4; /* Fallo al obtener máscara */ printf("Máscara de %s: %s\n", ifname, inet_ntoa(get_addr(ifr))); if (ioctl(sock, SIOCGIFHWADDR, &ifr)<0) return -5; /* Fallo al obtener direccion hw */ if (ifr.ifr_hwaddr.sa_family<=32) /* Los que tienen dirección hardware, puede que no sea siempre así */ printf("Dirección HW de %s: %.2X.%.2X.%.2X.%.2X.%.2X.%.2X\n", ifname, (unsigned char)ifr.ifr_addr.sa_data[0], (unsigned char)ifr.ifr_addr.sa_data[1], (unsigned char)ifr.ifr_addr.sa_data[2], (unsigned char)ifr.ifr_addr.sa_data[3], (unsigned char)ifr.ifr_addr.sa_data[4], (unsigned char)ifr.ifr_addr.sa_data[5]); close(sock); return 0; } int main(int argc, char *argv[]) { getdevinfo("eth0"); } |
Hemos hecho una macro llamada get_addr que nos va a ahorrar mucho trabajo, aunque podremos optimizar un poco más, y sobre todo, dar la posibilidad de reutilizar la información obtenida, y no sólo mostrarla en pantalla. La dirección hardware del dispositivo la dejaremos como cadena, pero las demás direcciones como struct sockaddr o struct sockaddr_in nos serán más útiles, sobre todo si nuestra aplicación hace uso de ellas:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <sys/types.h> #include <sys/ioctl.h> #include <net/if.h> #include <string.h> struct ifinfo { struct sockaddr addr; struct sockaddr mask; struct sockaddr brdc; char hwaddr[18]; }; #define get_addr(var) (*(struct in_addr *) &var.sa_data[2]) int getdevinfo(char * ifname, struct ifinfo *info) { int sock; struct ifreq ifr; unsigned char *hwaddr; sock=socket(AF_INET, SOCK_DGRAM, 0); if (sock<0) return -1; /* No puedo crear el socket */ ifr.ifr_addr.sa_family = AF_INET; strcpy(ifr.ifr_name, ifname); if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) return -2; /* No encuentro el dispositivo */ info->addr=ifr.ifr_addr; if (ioctl(sock, SIOCGIFBRDADDR, &ifr)<0) return -3; /* Fallo al obtener broadcast */ info->brdc=ifr.ifr_addr; if (ioctl(sock, SIOCGIFNETMASK, &ifr)<0) return -4; /* Fallo al obtener máscara */ info->mask=ifr.ifr_addr; if (ioctl(sock, SIOCGIFHWADDR, &ifr)<0) return -5; /* Fallo al obtener direccion hw */ if (ifr.ifr_hwaddr.sa_family<=32) /* Los que tienen dirección hardware, puede que no sea siempre así */ { hwaddr = (unsigned char*)ifr.ifr_addr.sa_data; sprintf (info->hwaddr, "%.2X.%.2X.%.2X.%.2X.%.2X.%.2X", hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); } else info->hwaddr[0]='\0'; close(sock); return 0; } void printdevinfo(const struct ifinfo *info) { printf ("IP: %s\n", inet_ntoa(get_addr(info->addr))); printf ("Máscara: %s\n", inet_ntoa(get_addr(info->mask))); printf ("Broadcast: %s\n", inet_ntoa(get_addr(info->brdc))); printf ("HW: %s\n", info->hwaddr); } int main(int argc, char *argv[]) { struct ifinfo ifnfo; getdevinfo("eth0", &ifnfo); printdevinfo(&ifnfo); } |
Un apunte más, estoy limitando los dispositivos que tienen dirección hardware a los que en el miembro sa_family devuelven un valor menor o igual que 32, aunque puede que en algunos sistemas, o en un futuro, pasado o presente no sea así; para ver los dispositivos que tienen dirección hardware conviene mirar el archivo /usr/include/linux/if_arp.h
Pingback: Bitacoras.com /