这个是参考了网上的和工作中的一些代码写成的。
内容如下:
#include <sys/ioctl.h> #include <net/if.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #define MAXNIC 20 int main(void) { int sockfd = socket(AF_INET, SOCK_STREAM, 0); struct ifconf ifconfig; struct ifreq ifr[MAXNIC]; memset(ifr, 0, sizeof(ifr)); memset(&ifconfig, 0, sizeof(ifconfig)); ifconfig.ifc_req = ifr; ifconfig.ifc_len = sizeof(ifr); if(ioctl(sockfd, SIOCGIFCONF, &ifconfig) == -1) { perror("ioctl SIOCGIFCONF: "); exit(1); } int nNIC = ifconfig.ifc_len / sizeof(ifr[0]); printf("number if NIC is %d\n", nNIC); int i; for( i = 0; i < nNIC; i++) { //!!! We must make a copy of the previous ifreq structure before //calling ioctl with SIOCGIFFLAGS, because this function can change //the other fields of ifreq. struct ifreq ifreq_copy; memcpy(&ifreq_copy, &ifconfig.ifc_req[i], sizeof(ifreq_copy)); if(ioctl(sockfd, SIOCGIFFLAGS, &ifreq_copy) == -1) { perror("ioctl SIOCGIFFLAGS: "); exit(2); } // ifconfig.ifc_req[i].ifr_flags = ifreq_copy.ifr_flags; // printf("checking %s\n", ifconfig.ifc_req[i].ifr_name); // printf("family = %hd\n", ifconfig.ifc_req[i].ifr_addr.sa_family); //printf("up flag: %x, %x\n", ifconfig.ifc_req[i].ifr_flags & IFF_UP, IFF_UP); //printf("is loopback :%x, %x\n", ifconfig.ifc_req[i].ifr_flags & IFF_LOOPBACK , IFF_LOOPBACK); if((ifreq_copy.ifr_flags & IFF_UP) == IFF_UP && (ifreq_copy.ifr_flags & IFF_LOOPBACK) != IFF_LOOPBACK && ifconfig.ifc_req[i].ifr_addr.sa_family == AF_INET ) { char ip[INET_ADDRSTRLEN]; struct sockaddr_in *address = (struct sockaddr_in *)&ifconfig.ifc_req[i].ifr_addr; inet_ntop(AF_INET, &address->sin_addr, ip, sizeof(ip)); printf("%s\t%s\n", ifconfig.ifc_req[i].ifr_name, ip); } } }
第37行的memcpy是非常必要的,因为i后面的那个ioctl会改变ifreq其他成员的值!
原因是因为struct ifreq 里面有一个 union:
struct ifreq { char ifr_name[IFNAMSIZ]; /* Interface name */ union { struct sockaddr ifr_addr; struct sockaddr ifr_dstaddr; struct sockaddr ifr_broadaddr; struct sockaddr ifr_netmask; struct sockaddr ifr_hwaddr; short ifr_flags; int ifr_ifindex; int ifr_metric; int ifr_mtu; struct ifmap ifr_map; char ifr_slave[IFNAMSIZ]; char ifr_newname[IFNAMSIZ]; char *ifr_data; }; };
我开始的时候,没有加这个memcpy,结果,打印出来的 ifr_addr.sa_family怎么都不对, 查了半天才发现原因。