getifaddrs 函数详解

getifaddrs 函数用于获取系统中所有网络接口的信息。它返回一个链表,链表中的每个节点包含一个 struct ifaddrs 结构,该结构定义在 ifaddrs.h 头文件中。下面是关于 getifaddrs 函数和 struct ifaddrs 结构的详细解析:

1. getifaddrs 函数

int getifaddrs(struct ifaddrs **ifap);
  • 参数 ifap 是一个指向 struct ifaddrs 结构指针的指针。当函数成功执行后,ifap 将指向一个链表,链表中包含了系统中所有网络接口的信息。

  • 返回值:如果成功,返回值为 0;如果有错误发生,返回值为 -1,并设置 errno 变量以指示错误类型。

2. struct ifaddrs 结构

struct ifaddrs {
    struct ifaddrs  *ifa_next;    // 指向下一个接口信息结构的指针
    char            *ifa_name;    // 接口名称
    unsigned int     ifa_flags;   // 接口标志
    struct sockaddr *ifa_addr;    // 接口地址
    struct sockaddr *ifa_netmask; // 接口子网掩码
    // 其他成员...
};
  • ifa_next:指向下一个接口信息结构的指针,形成了一个链表结构,通过遍历该链表可以获取系统中所有网络接口的信息。

  • ifa_name:接口名称,例如 "eth0"、"wlan0" 等。

  • ifa_flags:接口的标志,包含了一系列标志位,可以用于判断接口的状态和特性。

  • ifa_addr:指向 struct sockaddr 类型的指针,包含了接口的地址信息,如IP地址。

  • ifa_netmask:指向 struct sockaddr 类型的指针,包含了接口的子网掩码信息。

  • 其他成员:还有一些其他成员,包含了更多的接口信息,如广播地址、点对点地址等。

        通过遍历返回的链表,你可以获取系统中所有网络接口的信息,包括它们的名称、地址、子网掩码等。这对于网络编程和系统管理非常有用。

3.使用举例

        当使用 getifaddrs 函数时,你可以遍历返回的链表,检查每个接口的信息。以下是一个简单的示例程序,演示如何使用 getifaddrs 函数来获取系统中所有网络接口的信息,并检查是否存在名为 "tun0" 的接口:

        

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netinet/in.h>

int main() {
    struct ifaddrs *ifaddr, *ifa;
    
    if (getifaddrs(&ifaddr) == -1) {
        perror("getifaddrs");
        exit(EXIT_FAILURE);
    }

    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr == NULL) {
            continue;
        }

        if (ifa->ifa_addr->sa_family == AF_INET && strcmp(ifa->ifa_name, "tun0") == 0) {
            printf("Found tun0 interface\n");
            // 在这里可以获取tun0接口的更多信息
        }
    }

    freeifaddrs(ifaddr);
    return 0;
}

        在这个示例程序中,我们使用 getifaddrs 函数获取了系统中所有网络接口的信息,并遍历了返回的链表。在每次迭代中,我们检查接口的地址家族是否是 AF_INET,并且接口名称是否为 "tun0"。如果是,就输出一条消息表示找到了名为 "tun0" 的接口。你也可以在这里获取更多关于 "tun0" 接口的信息,如IP地址、子网掩码等。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是getifaddrs函数的源码实现,它定义在头文件<ifaddrs.h>中: ```c #include <sys/socket.h> #include <ifaddrs.h> int getifaddrs(struct ifaddrs **ifap); void freeifaddrs(struct ifaddrs *ifa); struct ifaddrs { struct ifaddrs *ifa_next; /* Next item in list */ char *ifa_name; /* Name of interface */ unsigned int ifa_flags; /* Flags from SIOCGIFFLAGS */ struct sockaddr *ifa_addr; /* Address of interface */ struct sockaddr *ifa_netmask; /* Netmask of interface */ union { struct sockaddr *ifu_broadaddr; struct sockaddr *ifu_dstaddr; } ifa_ifu; #define ifa_broadaddr ifa_ifu.ifu_broadaddr #define ifa_dstaddr ifa_ifu.ifu_dstaddr void *ifa_data; /* Address-specific data */ }; ``` getifaddrs函数返回系统中所有网络接口的基本信息,包括接口名称、地址和标志等。它的参数ifap是一个指向ifaddrs结构体链表的指针,函数将通过该指针返回结果。freeifaddrs函数用于释放该链表。 以下是getifaddrs函数的具体实现: ```c #include <errno.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <netinet/in.h> #include <net/if.h> #include <ifaddrs.h> int getifaddrs(struct ifaddrs **ifap) { int fd, err, n; struct ifreq ifr; struct ifconf ifc; char buf[1024]; ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) return -1; if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { close(fd); return -1; } *ifap = NULL; for (n = 0; n < ifc.ifc_len; ) { struct ifaddrs *ifa; struct sockaddr_in *sin; ifr = ((struct ifreq *)(ifc.ifc_buf + n))->ifr_name; n += sizeof(ifr); if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { err = errno; close(fd); return err; } if ((ifr.ifr_flags & IFF_UP) == 0) continue; ifa = malloc(sizeof(struct ifaddrs)); if (ifa == NULL) { close(fd); return -1; } memset(ifa, 0, sizeof(struct ifaddrs)); ifa->ifa_flags = ifr.ifr_flags; ifa->ifa_name = strdup(ifr.ifr_name); sin = (struct sockaddr_in *)&ifr.ifr_addr; memcpy(&ifa->ifa_addr, sin, sizeof(struct sockaddr)); if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0) { err = errno; freeifaddrs(ifa); close(fd); return err; } sin = (struct sockaddr_in *)&ifr.ifr_addr; memcpy(&ifa->ifa_netmask, sin, sizeof(struct sockaddr)); if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0) { if (ifr.ifr_flags & IFF_POINTOPOINT) { memcpy(&ifa->ifa_dstaddr, sin, sizeof(struct sockaddr)); } } else { sin = (struct sockaddr_in *)&ifr.ifr_addr; memcpy(&ifa->ifa_broadaddr, sin, sizeof(struct sockaddr)); } if ((*ifap) != NULL) { ifa->ifa_next = (*ifap); } *ifap = ifa; } close(fd); return 0; } void freeifaddrs(struct ifaddrs *ifa) { if (ifa == NULL) return; freeifaddrs(ifa->ifa_next); free(ifa->ifa_name); free(ifa); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值