getifaddrs函数用法详解
getifaddrs函数简介
- 头文件包含
#include <sys/types.h>
#include <ifaddrs.h>
- 函数定义
int getifaddrs(struct ifaddrs ** ifap );
void freeifaddrs(struct ifaddrs * ifa );
getifaddrs函数常见使用错误
- 编译错误
warning: implicit declaration of function ‘getifaddrs’ [-Wimplicit-function-declaration]
解决办法:包含头文件
#include <sys/types.h>
#include <ifaddrs.h>
getifaddrs函数详细描述
getifaddrs ()函数创建一个描述本地系统网络接口的结构链表,并将该列表第一项的地址存储在*ifap 中。该列表由ifaddrs结构组成,定义如下:
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;
/* Broadcast address of interface */
struct sockaddr *ifu_dstaddr;
/* Point-to-point destination address */
} ifa_ifu;
#define ifa_broadaddr ifa_ifu.ifu_broadaddr
#define ifa_dstaddr ifa_ifu.ifu_dstaddr
void *ifa_data; /* Address-specific data */
};
ifa_next字段包含指向列表中下一个结构的指针,如果这是列表的最后一项,则为NULL。
ifa_name指向以空结尾的接口名称。
ifa_flags字段包含由 SIOCGIFFLAGS ioctl (2)操作返回的接口标志(有关这些标志的列表,请参见netdevice (7))。
ifa_addr字段指向包含接口地址的结构。(应参考sa_family子字段以确定地址结构的格式。)此字段可能包含空指针。
ifa_netmask字段指向包含与ifa_addr 关联的网络掩码的结构(如果适用于地址族)。此字段可能包含空指针。
根据ifa_flags中是否设置了位 IFF_BROADCAST 或 IFF_POINTOPOINT (一次只能设置一个),ifa_broadaddr将包含与ifa_addr相关联的广播地址(如果适用于地址族),或者ifa_dstaddr将包含点对点接口的目的地址。
ifa_data字段指向包含特定于地址族的数据的缓冲区;如果此接口没有此类数据,则此字段可能为空。
getifaddrs ()返回的数据是动态分配的,当不再需要时,应该使用freeifaddrs ()释放。
getifaddrs函数返回值
成功时,getifaddrs ()返回零;出错时,返回-1,并适当地设置errno。
getifaddrs函数错误码
getifaddrs ()可能会失败,并针对为socket (2)、bind (2)、getsockname (2)、recvmsg (2)、sendto (2)、malloc (3)或realloc (3)指定的任何错误设置errno
getifaddrs函数其他说明
Linux上返回的地址通常是分配给接口的IPv4和IPv6地址,但每个接口也有一个 AF_PACKET 地址,包含有关接口及其物理层的较低级别的详细信息。在这种情况下,ifa_data字段可能包含指向<linux/if_linkh>中定义的"struct rtnl_link_stats" 的指针(在Linux 2.4和更早版本中,<linux/netdeviceh> )中定义的"struct net_device_stats" 包含各种接口属性和统计信息)。
getifaddrs函数使用举例
下面的程序演示了getifaddrs ()、freeifaddrs ()和getnameinfo (3)的用法。下面是我们在一个系统上运行该程序时看到的内容:
$ \fB./a.out\fP
lo AF_PACKET (17)
tx_packets = 524; rx_packets = 524
tx_bytes = 38788; rx_bytes = 38788
wlp3s0 AF_PACKET (17)
tx_packets = 108391; rx_packets = 130245
tx_bytes = 30420659; rx_bytes = 94230014
em1 AF_PACKET (17)
tx_packets = 0; rx_packets = 0
tx_bytes = 0; rx_bytes = 0
lo AF_INET (2)
address: <127.0.0.1>
wlp3s0 AF_INET (2)
address: <192.168.235.137>
lo AF_INET6 (10)
address: <::1>
wlp3s0 AF_INET6 (10)
address: <fe80::7ee9:d3ff:fef5:1a91%wlp3s0>
Program source&
#define _GNU_SOURCE /* To get defns of NI_MAXSERV and NI_MAXHOST */
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/if_link.h>
int main(int argc, char *argv[])
{
struct ifaddrs *ifaddr;
int family, s;
char host[NI_MAXHOST];
if (getifaddrs(&ifaddr) == \-1) {
perror("getifaddrs");
exit(EXIT_FAILURE);
}
/* Walk through linked list, maintaining head pointer so we
can free list later */
for (struct ifaddrs *ifa = ifaddr; ifa != NULL;
ifa = ifa\->ifa_next) {
if (ifa\->ifa_addr == NULL)
continue;
family = ifa\->ifa_addr\->sa_family;
/* Display interface name and family (including symbolic
form of the latter for the common families) */
printf("%\-8s %s (%d)\en",
ifa\->ifa_name,
(family == AF_PACKET) ? "AF_PACKET" :
(family == AF_INET) ? "AF_INET" :
(family == AF_INET6) ? "AF_INET6" : "???",
family);
/* For an AF_INET* interface address, display the address */
if (family == AF_INET || family == AF_INET6) {
s = getnameinfo(ifa\->ifa_addr,
(family == AF_INET) ? sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6),
host, NI_MAXHOST,
NULL, 0, NI_NUMERICHOST);
if (s != 0) {
printf("getnameinfo() failed: %s\en", gai_strerror(s));
exit(EXIT_FAILURE);
}
printf("\et\etaddress: <%s>\en", host);
} else if (family == AF_PACKET && ifa\->ifa_data != NULL) {
struct rtnl_link_stats *stats = ifa\->ifa_data;
printf("\et\ettx_packets = %10u; rx_packets = %10u\en"
"\et\ettx_bytes = %10u; rx_bytes = %10u\en",
stats\->tx_packets, stats\->rx_packets,
stats\->tx_bytes, stats\->rx_bytes);
}
}
freeifaddrs(ifaddr);
exit(EXIT_SUCCESS);
}
评论区