【问题标题】:Similar to getifaddrs on old glibc version类似于旧 glibc 版本上的 getifaddrs
【发布时间】:2012-04-16 11:42:27
【问题描述】:

有一个非常有用的函数调用getifaddrs 可以检索所有机器网络地址。问题是我使用的是没有此功能的旧 glibc 版本。有替代品吗?我正在寻找并找到getipnodebyname,但是当地址未映射到 /etc/hosts 文件中时它是无用的。

【问题讨论】:

  • 你使用的是哪个版本的 glibc
  • 考虑到实现是在开源的 glibc 中,您可以采用该实现并将其合并到您的代码中(假设它也与此方法许可证兼容)。请注意,glibc 2.3 于 2002 年发布`

标签: c linux unix networking glibc


【解决方案1】:

要补充上一个答案,这里是SIOCGIFCONF-方法的示例。你必须这样做:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>

int fd;

int get_iface_list(struct ifconf *ifconf)
{
    int rval;
    if((rval = ioctl(fd, SIOCGIFCONF , (char*) ifconf  )) < 0 )
        perror("ioctl(SIOGIFCONF)");

    return rval;
}

int main()
{
    static struct ifreq ifreqs[100];
    static struct ifconf ifc;
    char *ptr;

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0)
        return 1;

    ifc.ifc_buf = (char*) (ifreqs);
    ifc.ifc_len = sizeof(ifreqs);

    if(get_iface_list(&ifc) < 0) return -1;

    /* Go through the list of interfaces */
    for (ptr = ifc.ifc_buf; ptr < ifc.ifc_buf + ifc.ifc_len;)
    {
        struct ifreq *ifr = (struct ifreq*)ptr;
        int len = (sizeof(struct sockaddr) > ifr->ifr_addr.sa_len) ?
                sizeof(struct sockaddr) : ifr->ifr_addr.sa_len;

        ptr += sizeof(ifr->ifr_name) + len;

            /* Do what you need with the ifr-structure.
             * ifr->ifr_addr contains either sockaddr_dl,
             * sockaddr_in or sockaddr_in6 depending on
             * what addresses and L2 protocols the interface
             * has associated in it.
             */
    }

    close(fd);
    return 0;
}

当然,有一些陷阱。根据 Unix 网络编程第 17.6 章,如果参数中指向的数组太小,ioctl(fd, SIOCGIFCONF, array) 在某些平台上可能不会返回错误。然后将连接数据。解决此问题的唯一方法是在循环中调用ioctl(),直到在增加数组大小的同时两次获得相同的结果长度。当然,由于现在是 2012 年,我不确定这有多大意义。

ifreqs 数组的大小在这种情况下纯粹是猜测。请记住,该数组将为与接口关联的每个 L2 和 L3 地址包含一个 struct ifreq。例如,假设您也有 IPv6 地址,对于 lo-interface,您将获得三个条目:以太网、IPv4 和 IPv6。因此保留足够的空间或应用杂物。

要获取广播地址和其他附加信息,您需要在循环中额外调用ioctl()。当然,所有可能的选项都取决于您的操作系统提供的功能。

有关更多信息,我建议阅读 W. Richard Stevens 的 Unix Network Programming。这是关于这个主题的最全面的书。

【讨论】:

  • 谢谢!这正是我所需要的。
【解决方案2】:

执行等效操作的传统方法是对ioctl 执行SIOCGIFCONF 操作。任何套接字都可以用于操作。不过,它不像单个函数调用那么容易。

【讨论】:

  • 在调用SIOCGIFCONF获取接口列表后,在每个接口上调用SIOCGIFFLAGS ioctl,查看是否启动;如果是,则调用SIOCGIFADDR ioctl 来实际获取地址。
猜你喜欢
  • 2018-12-19
  • 2014-11-16
  • 2018-07-21
  • 2021-09-25
  • 2016-08-11
  • 1970-01-01
  • 2021-07-02
  • 2011-07-05
  • 1970-01-01
相关资源
最近更新 更多