Linux获取所有网络接口名称

21

我需要收集所有接口名称,包括当前未连接的接口。就像 ifconfig -a 命令一样。

getifaddrs() 函数会多次迭代同一个接口名称。如何使用 getifaddrs() 仅一次性地收集所有接口名称?


6
将数据添加到表格中,并去除重复的条目。 - Some programmer dude
谢谢Joachim,但是没有其他不需要额外处理的方法吗? - tez
7个回答

31

你可以检查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);

22

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;
}

就这样了。


5
你的示例代码存在内存泄漏问题。根据文档(if_nameindex),if_nameindex()函数会动态分配内存,应该通过调用if_freenameindex()来释放内存。 - fetch
1
谢谢指出!我已经相应地更新了我的示例代码。 - Hugues
1
你好,void main(void) 是不正确的。你应该使用 int main() 或者 int main(void)。同时,main 函数应该返回一个值。 - f3xy
1
刚刚更新了,检查了一下 gcc -Wall 不再产生错误了。谢谢;-) - Hugues
这个条件应该是“或”还是“且”?intf->if_index != 0 || intf->if_name != NULL - DirtyV
从if_nameindex(3)的man页面中:«数组的结尾由if_index设置为零且if_name设置为NULL的条目表示» 看起来你完全正确 :-) 我不太记得为什么选择使用OR运算符,也许我认为它比使用AND更快,更安全。如果任何条目具有0索引,则必须是最后一个条目,无论其if_name是什么。 但是,是的,我想使用AND会更有意义.. :-) - Hugues

7

看起来 ifconfig -a 只列出活动接口(至少在 Fedora 19 上是如此)。我知道我有至少一张没有显示的网络卡。无论如何,我得到的列表与以下相同:

ls -1 /sys/class/net

这很容易通过编程实现。

3

我认为这显示了所有接口,至少对于我来说是这样。

ip link show

ls -1 /sys/class/net

仅显示接口名称

lo
p4p1

2

你正在正确的轨道上(它是getifaddrs)。它每个协议族返回每个接口一次,因此您会得到ipv4的eth0和ipv6的一个。如果您只想要每个接口一次,则必须自己对输出进行去重。


1

我需要系统正在使用的主要设备(假设只有一个),例如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

0
使用这个。我添加了适当的注释以便理解。
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);


}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接