这个是参考了网上的和工作中的一些代码写成的。
内容如下:
#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;
};
};
39行的代码会改变ifr_flags的值,这样也就改变了其它成员的值。
我开始的时候,没有加这个memcpy,结果,打印出来的 ifr_addr.sa_family怎么都不对, 查了半天才发现原因。