侧边栏壁纸
博主头像
noerror

虚灵不寐,众理具而万事出。

  • 累计撰写 239 篇文章
  • 累计创建 9 个标签
  • 累计收到 2 条评论
标签搜索

目 录CONTENT

文章目录

getifaddrs函数用法详解

noerror
2022-11-09 / 0 评论 / 0 点赞 / 180 阅读 / 1,215 字 / 正在检测是否收录...

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_BROADCASTIFF_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);
}
0

评论区