Shammer's Philosophy

My private adversaria

gethostbyname2 sample

gethostbyname のサンプルに続いて、gethostbyname2 のサンプルも書いてみた。とりあえず、gethostbyname sample - Shammerismの gethostbyname を gethostbyname2 にしてコンパイルしてみたが、引数違いでエラーとなってしまった。

$ gcc gethostbyname2-c.c
gethostbyname2-c.c:14:32: error: too few arguments to function call, expected 2,
...

man gethostbyname2 をやると、たしかに

     struct hostent *
     gethostbyname2(const char *name, int af);

     struct hostent *
     gethostbyaddr(const void *addr, socklen_t len, int type);

となっている。何か int 型の引数も必要なんだ。Description には

     The name argument passed to gethostbyname() or gethostbyname2() should point to a NUL-terminated
     hostname.  The addr argument passed to gethostbyaddr() should point to an address which is len
     bytes long, in binary form (i.e., not an IP address in human readable ASCII form).  The type
     argument specifies the address family (e.g. AF_INET, AF_INET6, etc.) of this address.

とあるが、af というのはタイプのことだろうか。AF_INET や AF_INET6 の略のように思えるが、man の内容は type として説明されている。これは gethostbyaddr の内容な気がするが、とりあえず試してみたところ、うまくいった。とりあえず、AF_INET を指定する場合は以下のようになる。

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#include <sys/time.h>
#include <stdlib.h>

int main(int argc, char *args[]){
    if( argc == 2 ){
	char *hoststring = args[1];
	struct hostent *hp;
	hp = gethostbyname2(hoststring, AF_INET);
	if( hp == NULL ){
	    printf("No IP associated with %s\n", hoststring);
	}
	else {
	    printf("=== %s Info ===\n", hoststring);
	    char **alias = hp->h_aliases;
	    for( ; *alias != NULL ; alias++ ){
		printf("alias of %s is %s\n", hoststring, *alias);
	    }
	    printf("addrtype of %s is %d\n", hoststring, hp->h_addrtype);
	    char **addrlist = hp->h_addr_list;
	    for( ; *addrlist != NULL ; addrlist++ ){
		printf("%s has IP, %s\n", hp->h_name, inet_ntoa(*((struct in_addr *)addrlist)));
	    }
	}
    }
    else {
	printf("Usage: %s $IP_ADDRESS\n", args[0]);
    }
    return 0;
}
<||
コンパイルと実行結果。
>||
$ gcc gethostbyname2-c.c
$ ./a.out 127.0.0.1
=== 127.0.0.1 Info ===
addrtype of 127.0.0.1 is 2
127.0.0.1 has IP, XXX.XXX.XXX.XXX
$ ./a.out ::1
No IP associated with ::1
$

IPv4 のアドレスを指定したい場合は AF_INET を指定し、IPv6 を使いたい場合は AF_INET6 にするということか?上記実装の AF_INET を AF_INET6 に変更して試すと以下のようになった。

$ gcc gethostbyname2-c.c
$ ./a.out ::1
=== ::1 Info ===
addrtype of ::1 is 30
::1 has IP, XXX.XXX.XXX.XXX
$ ./a.out 127.0.0.1
No IP associated with 127.0.0.1
$

なるほど。両方に対応するにはどうするのだろうか。もしないとすると、IPv6 対応は相当大変になりそうだ。