我需要收集所有接口名称,包括当前未连接的接口。就像 ifconfig -a
命令一样。
getifaddrs()
函数会多次迭代同一个接口名称。如何使用 getifaddrs()
仅一次性地收集所有接口名称?
我需要收集所有接口名称,包括当前未连接的接口。就像 ifconfig -a
命令一样。
getifaddrs()
函数会多次迭代同一个接口名称。如何使用 getifaddrs()
仅一次性地收集所有接口名称?
你可以检查getifaddrs返回结果中属于AF_PACKET族的条目。在我的系统上,这似乎列出了所有接口:
struct ifaddrs *addrs,*tmp;
getifaddrs(&addrs);
tmp = addrs;
while (tmp)
{
if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_PACKET)
printf("%s\n", tmp->ifa_name);
tmp = tmp->ifa_next;
}
freeifaddrs(addrs);
getifaddrs()仅会返回您的接口地址,而不是接口本身。
如果您的任何接口没有地址,或没有所请求的地址族的地址,例如'AF_PACKET',该怎么办?
这里有一个示例,我有一个隧道接口(使用OpenVPN连接),并且正在列出每个网络接口的getifaddrs()所有条目:
[0] 1: lo address family: 17 (AF_PACKET) b4:11:00:00:00:01
address family: 2 (AF_INET) address: <127.0.0.1>
address family: 10 (AF_INET6) address: <::1>
[...]
[5] 10: tun0 address family: 2 (AF_INET) address: <172.16.0.14>
[EOF]
哎呀,"tun0" 接口上没有 AF_PACKET,但是它确实存在于系统中。
你应该使用 if_nameindex() 系统调用,它可以完全满足你的需求。换句话说,如果没有参数,它将返回系统上所有接口的列表:
#include <net/if.h>
#include <stdio.h>
int main (void)
{
struct if_nameindex *if_nidxs, *intf;
if_nidxs = if_nameindex();
if ( if_nidxs != NULL )
{
for (intf = if_nidxs; intf->if_index != 0 || intf->if_name != NULL; intf++)
{
printf("%s\n", intf->if_name);
}
if_freenameindex(if_nidxs);
}
return 0;
}
就这样了。
void main(void)
是不正确的。你应该使用 int main()
或者 int main(void)
。同时,main 函数应该返回一个值。 - f3xygcc -Wall
不再产生错误了。谢谢;-) - Huguesintf->if_index != 0 || intf->if_name != NULL
- DirtyVOR
运算符,也许我认为它比使用AND
更快,更安全。如果任何条目具有0索引,则必须是最后一个条目,无论其if_name
是什么。
但是,是的,我想使用AND
会更有意义.. :-) - Hugues看起来 ifconfig -a
只列出活动接口(至少在 Fedora 19 上是如此)。我知道我有至少一张没有显示的网络卡。无论如何,我得到的列表与以下相同:
ls -1 /sys/class/net
我认为这显示了所有接口,至少对于我来说是这样。
ip link show
ls -1 /sys/class/net
仅显示接口名称
lo
p4p1
你正在正确的轨道上(它是getifaddrs)。它每个协议族返回每个接口一次,因此您会得到ipv4的eth0和ipv6的一个。如果您只想要每个接口一次,则必须自己对输出进行去重。
我需要系统正在使用的主要设备(假设只有一个),例如eth0 wlan0或RHEL7尝试执行的任何设备...
我最好的解决方案是这个:
#!/bin/bash
# -- Get me the interface for the main ip on system
for each in $(ls -1 /sys/class/net) ;do
result=$(ip addr show $each | awk '$1 == "inet" {gsub(/\/.*$/, "", $2); print $2}' | grep "$(hostname -I | cut -d' ' -f1)")
if [ ! -z "${result// }" ] && [ -d /sys/class/net/${each// } ] ;then
echo "Device: $each IP: $result"
break;
fi
done
示例输出:
./maineth.sh
Device: enp0s25 IP: 192.168.1.6
void extract_network_interface_names()
{
/* DEFINITION
* #include <net/if.h>
* struct if_nameindex * if_nameindex() : function that returns a pointer.
* The if_nameindex() function returns an array of if_nameindex structs. There is one struct for each network interface
* The if_nameindex struct contains at least the following members:
* unsigned int if_index : which is the index of each network interface {1,2,..n}
* char * if_name : which is the name of the interface=the C style string= an array of characters terminated in the NULL character \0
*
* The end of the array of struct is indicated by an entry with if_index=0 && if_name=NULL
* The if_nameindex() function returns an array of structs if successful, or NULL if some error occurred or not enough memory is available
*/
puts("Extracting network interface names...");
puts("Listing all available network interface names on this machine...");
puts("********************************");
int counter_network_interfaces=0;
struct if_nameindex * interface_indexes;
struct if_nameindex * interface;
interface_indexes=if_nameindex();
if(interface_indexes==NULL) //Some error occurred during the execution of if_nameindex() function or there is no enough memory available
{
perror("If_nameindex");
printf("Ooops...error while extracting the network interface names.\n");
exit(EXIT_FAILURE);
}
//Loop through the elements of the array of if_nameindex structs
for(interface=interface_indexes;interface->if_index!=0 && interface->if_name!=NULL;interface++)
{
counter_network_interfaces++;
printf("There exists a network interface called \"%s\" with index %d. \n",interface->if_name, interface->if_index);
}
puts("*******************************");
printf("In total, there is a number of %d network interfaces on this machine.\n",counter_network_interfaces);
}