getifaddrs
すべてのマシン ネットワーク アドレスを取得する非常に便利な関数呼び出しがあります。問題は、この機能を持たない古いバージョンの glibc を使用していることです。それに代わるものはありますか?探していて見つけましgetipnodebyname
たが、アドレスが /etc/hosts ファイルにマップされていない場合は役に立ちません。
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ネットワークプログラミングを読むことをお勧めします。これは、この主題についての最も包括的な本です。
同等の操作を行う従来の方法は、 へのSIOCGIFCONF
操作でしたioctl
。操作には任意のソケットを使用できます。ただし、単一の関数呼び出しほど簡単ではありません。