[FreeBSD] 自ホストのIPアドレス情報を得る

FreeBSD上で自ホストのIPアドレスを取得したい。
W.R.StevensのUNIX network programimingの Chapter 9 unameの例にあるソースコードは正しく動作することを確認した。

#include "unp.h"
#include <sys/utsname.h>
char **
my_addrs(int *addrtype)
{
struct hostent *hptr;
struct utsname myname;
if (uname(&myname) h_addrtype;
return (hptr->h_addr_list);
}

UNIX系の普通の運用ではホスト名を付けることが多いし、DNSの設定も正しくできていることからこれが動作することは間違いないだろう。
ただ、組込み系だとホスト名が付いているとは限らない状態も考えられるしDNSへのアクセスはないことが多い。したがってgethostbynameではうまく行かない可能性がある。
そこで別の方法を試すことにした。UNIX Network Programmingには上記を含めて3通りの方法が説明されている。
Chapter 16のioctlの章にはSIOCGIFCONFを使った例が出てくる。手元のFreeBSDで動作させることを前提にエラー対策を省いたりしてみた。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#ifndef max
#define max(a,b) (((a)>(b))?(a):(b))
#endif
int
main(int argc, char **argv)
{
int fd;
struct ifconf ifc;
struct ifreq *ifr;
int len;
char *buf, *ptr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
len = 100 * sizeof(struct ifreq);
if ((buf = malloc(len)) == NULL)
{
perror("malloc");
return -1;
}
ifc.ifc_len = len;
ifc.ifc_buf = buf;
if (ioctl(fd, SIOCGIFCONF, &ifc) < 0)
{
if (errno != EINVAL)
{
perror("ioctl error");
return -1;
}
}
printf("len %d\n",ifc.ifc_len);
ifr = (struct ifreq *)buf;
for (ptr = buf; ifr ifr_name);
printf("adress family %d\n",ifr->ifr_addr.sa_family);
printf("size1 %d",sizeof(ifr->ifr_name));
printf(", size2 %d\n",sizeof(struct sockaddr));
if (ifr->ifr_addr.sa_family == AF_INET)
{
struct sockaddr_in *padr;
padr = (struct sockaddr_in *)&ifr->ifr_addr;
printf("address %s\n", inet_ntoa(padr->sin_addr));
}
len = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len);
ptr += sizeof(ifr->ifr_name) + len;
ifr = (struct ifreq *)ptr;
}
}

UNIX Network Progr
ammingでは、ioctlからデータ長が返ってこない場合に備えた対策などどのようなプラットフォームでも動作するように書かれている。
組込み系であればOSをある程度特定して良いので、確実に動作するとわかっていれば無駄な記述はしなくても良いと思う。

広告
%d人のブロガーが「いいね」をつけました。