ネットワークプログラム(1) ネットワークインターフェースの情報を取得する

int getifaddrs(struct ifaddrs ** ifap)

は、ローカルシステムのネットワークインターフェースの構造体リストを取得することができます。リストの最初を*ifapに格納します。
リストは動的に確保されるので、使い終わったら、freeifaddrs()で開放する必要があります

ヘッダファイル

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

戻り値

0:成功
-1:失敗

構造体 struct ifaddrs

struct ifaddrs
{
  struct ifaddrs *ifa_next;	/*  次の構造体へのポインタ */

  char *ifa_name;		/* インターフェース名  */
  unsigned int ifa_flags;	/* SIOCGIFFLAGS からのフラグ */

  struct sockaddr *ifa_addr;	/* このインターフェースのIPアドレス*/
  struct sockaddr *ifa_netmask; /* このインターフェースのサブネットマスク */
  union
  {
    struct sockaddr *ifu_broadaddr; /* ブロードキャストアドレス */
    struct sockaddr *ifu_dstaddr; /* PtoPアドレス  */
  } ifa_ifu;
#define ifa_broadaddr	ifa_ifu.ifu_broadaddr
#define ifa_dstaddr	ifa_ifu.ifu_dstaddr
  void *ifa_data;		/* (may be unused).  */
};

サンプルソース

#include<iostream>
#include<sys/types.h>
#include<ifaddrs.h>
#include<string>
#include<netinet/in.h>
#include <arpa/inet.h>

using namespace std;
int main(void){
    struct ifaddrs * addrs = nullptr;
    int ret = getifaddrs(&addrs);
    if(ret != 0) {
        fprintf(stderr, "!!! getifaddrs [%s:L%d]\n", __FILE__, __LINE__);
        return 1;
    }
    for(auto p = addrs; p!=nullptr; p=p->ifa_next){
        string interface_name = string(p->ifa_name);
        string disp_ipaddress;
        string disp_netmask;
        sa_family_t address_family = p->ifa_addr->sa_family;
        if(address_family==AF_INET){ // IPv4
            char buffer[INET_ADDRSTRLEN]={0,0,0,0};
            if(p->ifa_addr != nullptr){
                inet_ntop(address_family, &((struct sockaddr_in*)p->ifa_addr)->sin_addr,
                    buffer, INET_ADDRSTRLEN);
                disp_ipaddress = string(buffer);
            }
            if(p->ifa_netmask!=nullptr){
                char buffer[INET_ADDRSTRLEN]={0,0,0,0};
                inet_ntop(address_family, &((struct sockaddr_in*)(p->ifa_netmask))->sin_addr,
                    buffer, INET_ADDRSTRLEN);
         
                disp_netmask = string(buffer);
            }
            printf("IF:%s IPv4: %s  mask:%s\n",
                interface_name.c_str(), disp_ipaddress.c_str(), disp_netmask.c_str());
        }
        else if(address_family == AF_INET6){ // IPv6
            uint32_t scope_id=0;
            if(p->ifa_addr!=nullptr){
                char buffer[INET6_ADDRSTRLEN] = {0,0,0,0};
                inet_ntop(address_family, &((struct sockaddr_in6*)(p->ifa_addr))->sin6_addr,
                buffer, INET6_ADDRSTRLEN);
                disp_ipaddress = string(buffer);
                scope_id = ((struct sockaddr_in6*)(p->ifa_addr))->sin6_scope_id;
            }
            if(p->ifa_netmask!=nullptr){
                char buffer[INET6_ADDRSTRLEN] = {0,};
                inet_ntop(address_family, &((struct sockaddr_in6*)(p->ifa_netmask))->sin6_addr,
                buffer, INET6_ADDRSTRLEN);
                disp_netmask = string(buffer);
            }
            printf("IF:%s IPv6: %s  mask:%s scope id:%d\n",
                interface_name.c_str(), disp_ipaddress.c_str(), disp_netmask.c_str(), scope_id);
        }
    }
    freeifaddrs(addrs);
    return 0;
}


実行結果

$: ~/000-getifaddr$ ./a.out 
IF:lo IPv4: 127.0.0.1  mask:255.0.0.0
IF:wlp3s0 IPv4: 192.168.11.8  mask:255.255.255.0
IF:pan1 IPv4: 10.189.161.1  mask:255.255.255.0
IF:lo IPv6: ::1  mask:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff scope id:0
IF:wlp3s0 IPv6: fe80::60b:a952:40ad:de1a  mask:ffff:ffff:ffff:ffff:: scope id:2

アドレスファミリ(sa_family)

通信の種類を表します。
AF_INET: IPv4
AF_INET6: IPv6



この記事が気に入ったらサポートをしてみませんか?