0

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

4

2 に答える 2

2

前の答えに追加するために、ここにSIOCGIFCONF-approachの例があります。あなたはこのようなことをしなければなりません:

#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)、引数で指定された配列が小さすぎる場合、一部のプラットフォームではエラーが返されない場合があります。その後、データが連結されます。これを回避する唯一の方法ioctl()は、配列のサイズを増やしながら同じ結果の長さを2回取得するまで、ループを呼び出すことです。もちろん、これは2012年なので、これがどれほど関連性があるかはわかりません。

この場合、配列のサイズifreqsは純粋に推測です。ただし、配列にはstruct ifreq、インターフェイスに関連付けられているL2およびL3アドレスごとに1つ含まれることに注意してください。たとえば、IPv6アドレスもあるとすると、lo-interfaceの場合、イーサネット、IPv4、およびIPv6の3つのエントリを取得します。したがって、十分なスペースを確保するか、クラッジを適用してください。

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

詳細については、W。リチャードスティーブンスによるUnixネットワークプログラミングを読むことをお勧めします。これは、この主題についての最も包括的な本です。

于 2012-04-16T20:03:12.867 に答える
2

同等の操作を行う従来の方法は、 へのSIOCGIFCONF操作でしたioctl。操作には任意のソケットを使用できます。ただし、単一の関数呼び出しほど簡単ではありません。

于 2012-04-16T13:18:36.620 に答える