socket programming program network how c linux networking

programming - usando el código C para obtener la misma información que ifconfig



socket tcp c linux (6)

Así es como obtengo MAC y MTU en mi código:

void getMACAddress(std::string _iface,unsigned char MAC[6]) { int fd = socket(AF_INET, SOCK_DGRAM, 0); struct ifreq ifr; ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name , _iface.c_str() , IFNAMSIZ-1); ioctl(fd, SIOCGIFHWADDR, &ifr); for(unsigned int i=0;i<6;i++) MAC[i] = ifr.ifr_hwaddr.sa_data[i]; ioctl(fd, SIOCGIFMTU, &ifr); close(fd); printf("MTU: %d/n",ifr.ifr_mtu); printf("MAC:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x/n",MAC[0],MAC[1],MAC[2],MAC[3],MAC[4],MAC[5]); }

¿Hay alguna forma en Linux, usando código C, para obtener la misma información que devolvería "ifconfig eth0"? Me interesan cosas como la dirección IP, el estado del enlace y la dirección MAC.

Aquí hay un ejemplo de salida de ifconfig:

eth0 Link encap:Ethernet HWaddr 00:0F:20:CF:8B:42 inet addr:217.149.127.10 Bcast:217.149.127.63 Mask:255.255.255.192 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:2472694671 errors:1 dropped:0 overruns:0 frame:0 TX packets:44641779 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:1761467179 (1679.8 Mb) TX bytes:2870928587 (2737.9 Mb) Interrupt:28


Hay un enfoque más simple. copiado de http://man7.org/linux/man-pages/man3/getifaddrs.3.html

#include <arpa/inet.h> #include <sys/socket.h> #include <netdb.h> #include <ifaddrs.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <linux/if_link.h> int main(int argc, char *argv[]) { struct ifaddrs *ifaddr, *ifa; int family, s, n; char host[NI_MAXHOST]; if (getifaddrs(&ifaddr) == -1) { perror("getifaddrs"); exit(EXIT_FAILURE); } /* Walk through linked list, maintaining head pointer so we can free list later */ for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { if (ifa->ifa_addr == NULL) continue; family = ifa->ifa_addr->sa_family; /* Display interface name and family (including symbolic form of the latter for the common families) */ printf("%-8s %s (%d)/n", ifa->ifa_name, (family == AF_PACKET) ? "AF_PACKET" : (family == AF_INET) ? "AF_INET" : (family == AF_INET6) ? "AF_INET6" : "???", family); /* For an AF_INET* interface address, display the address */ if (family == AF_INET || family == AF_INET6) { s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (s != 0) { printf("getnameinfo() failed: %s/n", gai_strerror(s)); exit(EXIT_FAILURE); } printf("/t/taddress: <%s>/n", host); } else if (family == AF_PACKET && ifa->ifa_data != NULL) { struct rtnl_link_stats *stats = (struct rtnl_link_stats *)ifa->ifa_data; printf("/t/ttx_packets = %10u; rx_packets = %10u/n" "/t/ttx_bytes = %10u; rx_bytes = %10u/n", stats->tx_packets, stats->rx_packets, stats->tx_bytes, stats->rx_bytes); } } freeifaddrs(ifaddr); exit(EXIT_SUCCESS); }



Una forma de llegar al fondo de problemas como este, especialmente en los casos en que no se tiene una fuente, es muy strace .

Le proporciona una lista de todas las llamadas al sistema realizadas por cualquier programa que pase, junto con sus argumentos y valores devueltos. Si su programa solo descarga información y se cierra en lugar de ejecutarse durante un tiempo prolongado, puede ser bastante sencillo hacer que un hombre haga todas las llamadas al sistema que ve para que le proporcionen la información que está buscando.

Cuando corro

strace ifconfig

Algunas de las llamadas interesantes son:

open("/proc/net/dev", O_RDONLY) = 6

seguido de un montón de ioctls, corroborando la respuesta de @ payne:

ioctl(5, SIOCGIFFLAGS, {ifr_name="eth0", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0 ioctl(5, SIOCGIFHWADDR, {ifr_name="eth0", ifr_hwaddr=84:2b:2b:b7:9e:6d}) = 0 ioctl(5, SIOCGIFMETRIC, {ifr_name="eth0", ifr_metric=0}) = 0 ioctl(5, SIOCGIFMTU, {ifr_name="eth0", ifr_mtu=1500}) = 0



void parse_ioctl(const char *ifname) { printf("%s/n", "scarf rosari..."); int sock; struct ifreq ifr; struct sockaddr_in *ipaddr; char address[INET_ADDRSTRLEN]; size_t ifnamelen; /* copy ifname to ifr object */ ifnamelen = strlen(ifname); if (ifnamelen >= sizeof(ifr.ifr_name)) { printf("error :%s/n", ifr.ifr_name); return ; } memcpy(ifr.ifr_name, ifname, ifnamelen); ifr.ifr_name[ifnamelen] = ''/0''; /* open socket */ sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock < 0) { printf("error :%s/n", "unable to open socket.."); return; } /* process mac */ if (ioctl(sock, SIOCGIFHWADDR, &ifr) != -1) { printf("Mac address: %02x:%02x:%02x:%02x:%02x:%02x/n", (unsigned char)ifr.ifr_hwaddr.sa_data[0], (unsigned char)ifr.ifr_hwaddr.sa_data[1], (unsigned char)ifr.ifr_hwaddr.sa_data[2], (unsigned char)ifr.ifr_hwaddr.sa_data[3], (unsigned char)ifr.ifr_hwaddr.sa_data[4], (unsigned char)ifr.ifr_hwaddr.sa_data[5]); } /* process mtu */ if (ioctl(sock, SIOCGIFMTU, &ifr) != -1) { printf("MTU: %d/n", ifr.ifr_mtu); } /* die if cannot get address */ if (ioctl(sock, SIOCGIFADDR, &ifr) == -1) { close(sock); return; } /* process ip */ ipaddr = (struct sockaddr_in *)&ifr.ifr_addr; if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) { printf("Ip address: %s/n", address); } /* try to get broadcast */ if (ioctl(sock, SIOCGIFBRDADDR, &ifr) != -1) { ipaddr = (struct sockaddr_in *)&ifr.ifr_broadaddr; if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) { printf("Broadcast: %s/n", address); } } /* try to get mask */ if (ioctl(sock, SIOCGIFNETMASK, &ifr) != -1) { ipaddr = (struct sockaddr_in *)&ifr.ifr_netmask; if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) { printf("Netmask: %s/n", address); } } close(sock); }

uso:

parse_ioctl("eth0");