インタフェイス情報取得 - ifconfigもどき
ソケットに対するioctlを用いてネットワークインタフェイスに関する情報を取得する。
参考資料:UNIXネットワークプログラミング16章
ifconfigのソースでも同様のことをやっている。
表示をなるべくifconfigに近づけた。
但し、こちらはダウンさせたインタフェイスは表示されないが、
ifconfigではダウンしているインタフェイスも表示される。
// printinfo.c // // print interface information // just like ifconfig command... // based on UNIX network programming chapter 16. #include <stdio.h> #include <net/if.h> #include <stdarg.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <linux/sockios.h> #include <linux/in.h> void get_ifi_info(void); void print_ifreq(int sock, struct ifreq* ifr); int print_flags(int sock, struct ifreq* ifr); void print_mtu(int sock, struct ifreq* ifr); void print_inet(int sock, struct ifreq* ifr); void print_arp(int sock, struct ifreq* ifr); void print_netmask(int sock, struct ifreq* ifr); void print_broadcast(int sock, struct ifreq* ifr); void print_addr(int sock, struct ifreq* ifr, int request, char *tag); void err_quit(const char *fmt, ...); void yydump(char *p, int length); #define DEBUG_PRINT printf("%s:%d\n", __FUNCTION__, __LINE__); //----------------------------------------- int main(int argc, char **argv) { get_ifi_info(); exit(0); } //----------------------------------------- void get_ifi_info(void) { int sockfd, len, ret; char *buf, *ptr; struct ifconf ifc; struct ifreq *ifr; sockfd = socket(AF_INET, SOCK_DGRAM, 0); len = 100 * sizeof(struct ifreq); // assume enough size buf = malloc(len); ifc.ifc_len = len; ifc.ifc_buf = buf; ret = ioctl(sockfd, SIOCGIFCONF, &ifc); if(ret < 0){ err_quit("iotcl error: ret:%d errno:%s", ret, strerror(errno)); } for(ptr = buf;ptr < buf + ifc.ifc_len; ptr += sizeof(struct ifreq)){ ifr = (struct ifreq*)ptr; print_ifreq(sockfd, ifr); } close(sockfd); } //----------------------------------------- void print_ifreq(int sock, struct ifreq* ifr) { struct ifreq ifrcopy; struct sockaddr *sa; int ret, flags; // print interface name printf("%s : ",ifr->ifr_name); flags = print_flags(sock, ifr); print_mtu(sock, ifr); sa = &ifr->ifr_addr; switch(sa->sa_family){ case AF_INET: printf("\t"); print_inet(sock, ifr); print_netmask(sock, ifr); if(flags & IFF_BROADCAST) print_broadcast(sock, ifr); printf("\n"); printf("\t"); print_arp(sock, ifr); printf("\n"); break; default: printf("Unknown type: %d\n", sa->sa_family); break; } printf("\n"); } //----------------------------------------- int print_flags(int sock, struct ifreq* ifr) { struct ifreq ifrcopy; int ret; int flags = 0; memcpy(&ifrcopy, ifr, sizeof(struct ifreq)); ret = ioctl(sock, SIOCGIFFLAGS, &ifrcopy); if(ret < 0){ err_quit("iotcl error: ret:%d errno:%s", ret, strerror(errno)); } flags = ifrcopy.ifr_flags; printf("flags=%d < ", flags); if(flags & IFF_UP) printf("UP "); if(flags & IFF_BROADCAST) printf("BROADCAST "); if(flags & IFF_DEBUG) printf("DEBUG "); if(flags & IFF_LOOPBACK) printf("LOOPBACK "); if(flags & IFF_POINTOPOINT) printf("P2P"); if(flags & IFF_NOTRAILERS) printf("NOTRAILERS "); if(flags & IFF_RUNNING) printf("RUNNING "); if(flags & IFF_NOARP) printf("NOARP "); if(flags & IFF_PROMISC) printf("PROMISC "); if(flags & IFF_ALLMULTI) printf("ALLMULTI "); if(flags & IFF_MASTER) printf("MASTER "); if(flags & IFF_SLAVE) printf("SLAVE "); if(flags & IFF_MULTICAST) printf("MULTICAST "); if(flags & IFF_PORTSEL) printf("PORTSEL "); if(flags & IFF_AUTOMEDIA) printf("AUTOMEDIA "); if(flags & IFF_DYNAMIC) printf("DYNAMIC "); printf("> "); return flags; } //----------------------------------------- void print_mtu(int sock, struct ifreq* ifr) { struct ifreq ifrcopy; int ret; int mtu = 0; memcpy(&ifrcopy, ifr, sizeof(struct ifreq)); ret = ioctl(sock, SIOCGIFMTU, &ifrcopy); if(ret < 0){ err_quit("iotcl error: ret:%d errno:%s", ret, strerror(errno)); } mtu = ifrcopy.ifr_mtu; printf("mtu %d\n", mtu); } //----------------------------------------- void print_arp(int sock, struct ifreq* ifr) { struct ifreq ifrcopy; struct sockaddr *sa; int ret; int mtu = 0; unsigned char *p; memcpy(&ifrcopy, ifr, sizeof(struct ifreq)); ret = ioctl(sock, SIOCGIFHWADDR, &ifrcopy); if(ret < 0){ err_quit("iotcl error: ret:%d errno:%s", ret, strerror(errno)); } sa = &ifrcopy.ifr_hwaddr; p = sa->sa_data; printf("ether %x:%x:%x:%x:%x:%x", *(p+0), *(p+1), *(p+2), *(p+3), *(p+4), *(p+5)); } //----------------------------------------- void print_inet(int sock, struct ifreq* ifr) { print_addr(sock, ifr, SIOCGIFADDR, "inet"); } //----------------------------------------- void print_netmask(int sock, struct ifreq* ifr) { print_addr(sock, ifr, SIOCGIFNETMASK, "netmask"); } //----------------------------------------- void print_broadcast(int sock, struct ifreq* ifr) { print_addr(sock, ifr, SIOCGIFBRDADDR, "broadcast"); } //----------------------------------------- void print_addr(int sock, struct ifreq* ifr, int request, char *tag) { struct ifreq ifrcopy; struct sockaddr_in *sa; int ret; memcpy(&ifrcopy, ifr, sizeof(struct ifreq)); ret = ioctl(sock, request, &ifrcopy); if(ret < 0){ err_quit("iotcl error: ret:%d errno:%s", ret, strerror(errno)); } sa = (struct sockaddr_in*)&ifrcopy.ifr_addr; printf("%s %s ", tag, inet_ntoa(sa->sin_addr)); } //----------------------------------------- void err_quit(const char *fmt, ...) { #define MAXLINE 4096 int errno_save, n; char buf[MAXLINE+1]; va_list ap; va_start(ap, fmt); vsnprintf(buf, MAXLINE, fmt, ap); n = strlen(buf); strcat(buf, "\n"); fflush(stdout); fputs(buf, stderr); fflush(stderr); va_end(ap); exit(1); } //----------------------------------------- void yydump(char *p, int length) { int address = (int)p; char data[17]; int i; char buf[128]; char tmp[32]; data[16] = 0; /* for string terminator */ printf("Start Addr:[%p] Length:[%d]\n", p, length); for(;length>0;){ sprintf(buf, "%08X :", address); for(i=0;i<16;i++){ data[i] = *p++; length--; /* data is out of range */ if(length < 0){ sprintf(tmp, " "); strcat(buf, tmp); data[i] = ' '; } else{ sprintf(tmp, "%02X", (unsigned char)data[i]); strcat(buf, tmp); /* eliminate undisplayable character */ if((data[i] < 0x20) || (0x7E < data[i])){ data[i] = '.'; } } } sprintf(tmp, " : %s\n", data); strcat(buf, tmp); address += 16; printf("%s",buf); } printf("\n"); }