てきとうなメモ

本の感想とか技術メモとか

gethostbynameの引数にipアドレスを指定した場合の動作

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

int main(int argc, char **argv) {
  struct hostent *host = gethostbyname(argv[1]);
  printf("h_name = %s\n", host->h_name);
  printf("ip = ");
  for (char **addrp = host->h_addr_list; *addrp != NULL; addrp++) {
    struct in_addr addr;
    addr.s_addr = *((in_addr_t *) *addrp);
    char* ip = inet_ntoa(addr);
    printf(" %s", ip);
  }
  printf("\n");
}
$ gcc -std=c99 gethostbyname.c
$ ./a.out www.google.com
h_name = www.google.com
ip =  216.58.220.196
$ ./a.out 216.58.220.196
h_name = 216.58.220.196
ip =  216.58.220.196

ホスト名とIPアドレス両方に対応したアプリを作る場合、条件分岐しなくてよいので便利ではあるのだけども、統一感はないかな。SUSやPOSIXとしてはIPアドレスを指定した場合の動作は定義していない。

The name argument of gethostbyname() shall be a node name; the behavior of gethostbyname() when passed a numeric address string is unspecified. For IPv4, a numeric address string shall be in the dotted-decimal notation described in inet_addr().

The Base Specifications Issue 6

W. Richard StevensのUnix Network Programmingのp.308によると、RloginがIPアドレスに対応していなかったかららしい

This code was added because the Rlogin client accepts only a hostname, calling gethostbyname, and will not accept a dotted-decimal string[Vixie 1996]

アプリ側の問題をライブラリ側で実装するのはどうなんだろうと一瞬思ったが、他のアプリにとっても便利だと思うのでまあいいのか

4.3BSD-Renoの頃]にはこのコードは入っているな

struct hostent *
gethostbyname(name)
	char *name;
{
...

				if ((host_addr.s_addr = inet_addr(name)) == -1) {
					h_errno = HOST_NOT_FOUND;
					return((struct hostent *) NULL);
				}
				host.h_name = name;
				host.h_aliases = host_aliases;
				host_aliases[0] = NULL;
				host.h_addrtype = AF_INET;
				host.h_length = sizeof(u_long);
				h_addr_ptrs[0] = (char *)&host_addr;
				h_addr_ptrs[1] = (char *)0;
#if BSD >= 43 || defined(h_addr)	/* new-style hostent structure */
				host.h_addr_list = h_addr_ptrs;
#else
				host.h_addr = h_addr_ptrs[0];
#endif
				return (&host);