Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all bug

名前

       getifaddrs, freeifaddrs - インターフェースのアドレスを取得する

書式

       #include <sys/types.h>
       #include <ifaddrs.h>

       int getifaddrs(struct ifaddrs **ifap);

       void freeifaddrs(struct ifaddrs *ifa);

説明

       getifaddrs()  関数は、ローカルシステムのネットワークインターフェース情報を表す構造体の連結
       リストを作成し、 リストの先頭の要素のアドレスを *ifap に格納する。 リストは ifaddrs 構造体
       で構成される。 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_broadaddrifa_addr  に対応するブロード
       キャストが入るか   (そのアドレスファミリーでブロードキャストがある場合)、  ifa_dstaddr  に
       point-to-point インターフェースの宛先アドレスが入るかが決まる。

       ifa_data フィールドは、 アドレスファミリー固有のデータが入ったバッファーへのポインターであ
       る。 そのインターフェースでこのようなデータがない場合には、 このフィールドは NULL となる。

       getifaddrs()  が返すデータは動的に確保される。 必要なくなった際には freeifaddrs() を使って
       解放すべきである。

返り値

       成功すると、 getifaddrs は 0 を返す。 エラーの場合、 -1  が返り、  errno  が適切に設定され
       る。

エラー

       getifaddrs()    は失敗する場合があり、その場合には    errno   には   socket(2),   bind(2),
       getsockname(2), recvmsg(2), sendto(2), malloc(3), realloc(3)  に対して規定されているエラー
       のいずれかが設定される。

バージョン

       getifaddrs()  関数は glibc 2.3 で初めて登場したが、 glibc 2.3.3 より前のバージョンの実装で
       は IPv4 アドレスだけがサポートされていた。 IPv6 のサポートは  glibc  2.3.3  で追加された。
       IPv4 以外のアドレスファミリーが getifaddrs で利用できるのは、 netlink をサポートするカーネ
       ルの場合だけである。

属性

       この節で使用されている用語の説明については、 attributes(7) を参照。

       ┌────────────────────────────┬───────────────┬─────────┐
       │インターフェース属性      │
       ├────────────────────────────┼───────────────┼─────────┤
       │getifaddrs(), freeifaddrs() │ Thread safety │ MT-Safe │
       └────────────────────────────┴───────────────┴─────────┘

準拠

       POSIX.1 にはない。 この関数は BSDi で初めて登場し、 BSD 系のシステムに存在するが、  ドキュ
       メント上はかなり動作が異なり、アドレス毎ではなくインターフェース毎に  1 エントリーを返す。
       このことは、 インターフェースがアドレスを持たない場合には ifa_addr  や他のフィールドは実際
       に NULL になり、 インターフェースに IP アドレスが割り当てられている場合には リンクレベルの
       アドレスは返されない、ということを意味する。 また、 ifa_broadaddrifa_dstaddr  のどちら
       を選択するかを決める方法は、 システムにより異なる。

注意

       Linux  では、  返されるアドレスは通常インターフェースに割り当てられた IPv4 アドレスと IPv6
       アドレスになるが、   これ以外にインターフェース毎に一つ   AF_PACKET   アドレスも返される。
       AF_PACKET  アドレスには、 インターフェースとその物理層に関する低レベルの詳細が格納される。
       この場合、 ifa_data フィールドには、 <linux/if_link.h> で定義される struct rtnl_link_stats
       (Linux  2.4  以前では <linux/netdevice.h> で定義される struct net_device_stats) へのポイン
       ターが格納される。 この構造体には、インターフェースの様々な属性や統計情報が入る。

       以下のプログラムは getifaddrs(), freeifaddrs(), getnameinfo(3) の使用例である。 以下はこの
       プログラムをあるシステムで実行した際の出力である。

           $ ./a.out
           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>

   プログラムのソース

       #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)\n",
                      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\n", gai_strerror(s));
                       exit(EXIT_FAILURE);
                   }

                   printf("\t\taddress: <%s>\n", host);

               } else if (family == AF_PACKET && ifa->ifa_data != NULL) {
                   struct rtnl_link_stats *stats = ifa->ifa_data;

                   printf("\t\ttx_packets = %10u; rx_packets = %10u\n"
                          "\t\ttx_bytes   = %10u; rx_bytes   = %10u\n",
                          stats->tx_packets, stats->rx_packets,
                          stats->tx_bytes, stats->rx_bytes);
               }
           }

           freeifaddrs(ifaddr);
           exit(EXIT_SUCCESS);
       }

関連項目

       bind(2), getsockname(2), socket(2), packet(7), ifconfig(8)

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの
       説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。