2012-04-16 4 views
0

非常に便利な関数呼び出し​​があり、すべてのmachinネットワークアドレスを取得します。問題は、私はこの機能を持たない古いglibcバージョンを使用していることです。それに代わるものはありますか?私は探していたし、getipnodebynameを見つけましたが、アドレスが/ etc/hostsファイルにマップされていない場合は使用できません。古いglibcバージョンのgetifaddrsに似ています

+0

あなたが使用しているglibcのバージョン –

+0

実装がglibc(オープンソース)であることを考慮すると、実装を取ってコードに組み込むことができます(このアプローチではライセンス互換です) 。 glibc 2.3が2002年にリリースされたことを心配しています。 – Petesh

答えて

2

これまでの回答を追加するには、SIOCGIFCONF - 接近の例を次に示します。

#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <netinet/in.h> 
#include <net/if.h> 
#include <arpa/inet.h> 

int fd; 

int get_iface_list(struct ifconf *ifconf) 
{ 
    int rval; 
    if((rval = ioctl(fd, SIOCGIFCONF , (char*) ifconf )) < 0) 
     perror("ioctl(SIOGIFCONF)"); 

    return rval; 
} 

int main() 
{ 
    static struct ifreq ifreqs[100]; 
    static struct ifconf ifc; 
    char *ptr; 

    fd = socket(AF_INET, SOCK_DGRAM, 0); 
    if (fd < 0) 
     return 1; 

    ifc.ifc_buf = (char*) (ifreqs); 
    ifc.ifc_len = sizeof(ifreqs); 

    if(get_iface_list(&ifc) < 0) return -1; 

    /* Go through the list of interfaces */ 
    for (ptr = ifc.ifc_buf; ptr < ifc.ifc_buf + ifc.ifc_len;) 
    { 
     struct ifreq *ifr = (struct ifreq*)ptr; 
     int len = (sizeof(struct sockaddr) > ifr->ifr_addr.sa_len) ? 
       sizeof(struct sockaddr) : ifr->ifr_addr.sa_len; 

     ptr += sizeof(ifr->ifr_name) + len; 

      /* Do what you need with the ifr-structure. 
      * ifr->ifr_addr contains either sockaddr_dl, 
      * sockaddr_in or sockaddr_in6 depending on 
      * what addresses and L2 protocols the interface 
      * has associated in it. 
      */ 
    } 

    close(fd); 
    return 0; 
} 

もちろん、いくつかの落とし穴があります。 Unixネットワークプログラミングの章17.6によると、ioctl(fd, SIOCGIFCONF, array)は、引数に指定された配列が小さすぎると、一部のプラットフォームでエラーを返さないことがあります。データが連結されます。この問題を回避するには、配列のサイズを大きくしながら同じ結果の長さを2回取得するまで、ループ内でioctl()を呼び出します。もちろん、これは2012年なので、これはもはやどのように関係があるのか​​よくわかりません。

サイズifreqsの配列は、この場合はまったく推測です。ただし、アレイには、インターフェイスに関連付けられたすべてのL2およびL3アドレスに対して1つのstruct ifreqが含まれます。たとえば、IPv6アドレスも持っていると仮定すると、lo-interfaceにはethernet、IPv4、IPv6の3つのエントリがあります。したがって、十分なスペースを確保するか、またはkludgeを適用してください。

ブロードキャストアドレスやその他の追加情報を取得するには、ループ内でさらにioctl()コールが必要です。可能なすべてのオプションは、OSが提供するものによって異なります。

詳細については、W. Richard StevensのUnix Network Programmingをお読みください。それはこの主題について最も包括的な本です。

+0

ありがとう!それがまさに私が必要なものです。 – gumik

2

同等の処理を行う伝統的な方法は、SIOCGIFCONFの操作をioctlにすることでした。どのソケットも操作に使用できます。 1つの関数呼び出しほど簡単ではありません。

+1

'SIOCGIFCONF'を呼び出してインタフェースのリストを取得した後、それぞれのインタフェースで' SIOCGIFFLAGS' ioctlを呼び出して起動しているかどうかを確認します。そうであれば、実際にアドレスをフェッチするために 'SIOCGIFADDR' ioctlを呼び出します。 – caf

関連する問題