转自:http://blog.sina.com.cn/mailofzxf
在Linux下有两个方法获取网卡列表:分析文件/proc/net/dev 和 通过ioctl()调用。代码如下。
#define MAX_INTERFACES 100
#define FIRST_INTERFACE 0
#define PROC_NET_DEV "/proc/net/dev"
// interfaces related: man netdevice(7)
int interfaces_count = -1; // we do not know the count at first,
// but this varies according to modules loaded!
struct ifreq interfaces [MAX_INTERFACES FIRST_INTERFACE]; // name/ip
struct ifreq interfaces_mask [MAX_INTERFACES FIRST_INTERFACE]; // netmask
struct ifreq interfaces_index [MAX_INTERFACES FIRST_INTERFACE]; // ifr_ifindex
struct ifreq interfaces_hwaddr[MAX_INTERFACES FIRST_INTERFACE]; // hwaddr
struct ifreq interfaces_flag [MAX_INTERFACES FIRST_INTERFACE]; // flags
static int get_interface_names_by_proc_file()
{
#define SKIP_BLANK(p, end) while(isspace(*p) && (p < buf end)) p ;
#define GOTO_EOL(p, end) while((*p!='\n' && *p!='\r') && (p < buf end)) p ;
#define ZERO_EOL(p, end) while((*p=='\n' || *p=='\r') && (p < buf end)) *p = 0;
#define IS_EOL(c) (c=='\n' || c=='\r')
int net_inf_count = 0;
int alloc_size = 4096;
char *buf = NULL;
char *p, *head, *tail;
int fd, read_count;
fd = open(PROC_NET_DEV, O_RDONLY);
if(fd < 0) {
ERR("open: %s\n", strerror(errno));
return -11;
}
while(1) {
buf = (char*)realloc(buf, alloc_size);
if(buf == NULL) {
close(fd);
return -12;
}
lseek(fd, 0, SEEK_SET);
read_count = read(fd, buf, alloc_size);
if(read_count <= 0) {
free(buf);
close(fd);
return -13;
}
if(read_count < alloc_size)
break;
alloc_size <<= 1;
}
buf[read_count] = 0; // to terminate the string
head = buf;
while(head < buf read_count) {
p = head;
GOTO_EOL(p, read_count)
ZERO_EOL(p, read_count)
tail = p;
p = strchr(head, ':');
if(p) {
// a line containing a interface device:
*p = 0;
SKIP_BLANK(head, read_count)
strncpy_0(interfaces[net_inf_count].ifr_name, head, IFNAMSIZ);
//RPT(" #intf_No: - -- %s\n", net_inf_count, head);
net_inf_count ;
} else {
// This is the header line.
}
head = tail;
}
free(buf);
close(fd);
return net_inf_count;
}
static int get_interface_confs_by_ioctl()
{
struct ifreq ioctl_devs[MAX_INTERFACES FIRST_INTERFACE];
int inf_count, idx, pos;
struct ifconf ifc;
int fd, res;
fd = socket(AF_INET, SOCK_DGRAM, 0); // any family, any type!
if(fd < 0) {
ERR("socket error: %s\n", strerror(errno));
return -1;
}
ifc.ifc_len = sizeof(ioctl_devs);
ifc.ifc_buf = (caddr_t)ioctl_devs;
res = ioctl (fd, SIOCGIFCONF, (char*) &ifc);
if (!res) {
inf_count = ifc.ifc_len / sizeof(struct ifreq);
} else {
close(fd);
ERR("%s(%d): ioctl(SIOCGIFCONF): %s. Are you ROOT?\n", __FILE__, __LINE__, strerror(errno));
return -1;
}
if(interfaces_count < 0) {
interfaces_count = inf_count;
memcpy((char*)interfaces, (char*)ioctl_devs, inf_count*sizeof(ioctl_devs[0]));
} else {
// copy the IP addr:
for(pos=0; pos<inf_count; pos ) {
for(idx=FIRST_INTERFACE; idx<interfaces_count FIRST_INTERFACE; idx ) {
if(!strcmp( interfaces[idx].ifr_name, ioctl_devs[pos].ifr_name )) {
memcpy((char*)&interfaces[idx].ifr_addr,
(char*)&ioctl_devs[pos].ifr_addr,
sizeof(ioctl_devs[pos].ifr_addr)
);
break;
}
}
}
}
#if 0 // To ensure that intf_name & IP are assigned in interfaces!
for(idx=FIRST_INTERFACE; idx<interfaces_count FIRST_INTERFACE; idx ) {
char ip_addr_str[IPADDR_STR_LEN];
RPT("#- dev=%s, IP=%s\n", idx, interfaces[idx].ifr_name,
inet_ntoa(inaddrr(interfaces[idx])));
}
#endif
// to get other conf of interfaces...
{
// to get ifr_netmask:
for(idx=FIRST_INTERFACE; idx<interfaces_count FIRST_INTERFACE; idx ) {
memcpy(interfaces_mask[idx].ifr_name, interfaces[idx].ifr_name, \
sizeof(interfaces[idx].ifr_name) );
if(ioctl(fd, SIOCGIFNETMASK, (char*) &interfaces_mask[idx]) < 0) {
//ERR("%s(%d): ioctl(SIOCGIFNETMASK) err: %s\n", __FILE__, __LINE__,
// strerror(errno));
memset((char*)&(interfaces_index[idx].ifr_netmask), 0, sizeof(interfaces_index[idx].ifr_netmask));
}
}
// to get ifr_ifindex:
for(idx=FIRST_INTERFACE; idx<interfaces_count FIRST_INTERFACE; idx ) {
memcpy(interfaces_index[idx].ifr_name, interfaces[idx].ifr_name, \
sizeof(interfaces[idx].ifr_name) );
if(ioctl(fd, SIOCGIFINDEX, (char*) &interfaces_index[idx]) < 0) {
ERR("%s(%d): ioctl(SIOCGIFINDEX) err: %s\n", __FILE__, __LINE__, strerror(errno));
interfaces_index[idx].ifr_ifindex = -1;
}
}
// to get HW addr:
for(idx=FIRST_INTERFACE; idx<interfaces_count FIRST_INTERFACE; idx ) {
memcpy(interfaces_hwaddr[idx].ifr_name, interfaces[idx].ifr_name, \
sizeof(interfaces[idx].ifr_name) );
if(ioctl(fd, SIOCGIFHWADDR, (char*) &interfaces_hwaddr[idx]) < 0) {
ERR("%s(%d): ioctl(SIOCGIFHWADDR): %s\n", __FILE__, __LINE__, strerror(errno));
for(pos=0; pos<ETH_ALEN; pos )
INTF_MAC(idx)[pos] = 0;
}
}
// to get flags:
for(idx=FIRST_INTERFACE; idx<interfaces_count FIRST_INTERFACE; idx ) {
memcpy(interfaces_flag[idx].ifr_name, interfaces[idx].ifr_name, \
sizeof(interfaces[idx].ifr_name) );
if(ioctl(fd, SIOCGIFFLAGS, (char*) &interfaces_flag[idx]) < 0) {
ERR("%s(%d): ioctl(SIOCGIFHWADDR): %s\n", __FILE__, __LINE__, strerror(errno));
interfaces_flag[idx].ifr_flags = 0;
}
}
}
close(fd);
return 0;
}