奇妙なIPv4アドレス表記

   このエントリをはてなブックマークに登録    2017/9/27-2

IPv4アドレス表記といえば、ほとんどの人が「ドット付き十進表記 (dotted decimal notation)」による記述を連想すると思います。 しかし、ドット付き十進表記ではない奇妙な表記が使えることもあります。 機種依存するものの、たとえば、127.0.0.1の代わりに、127.1、0x7f.0x1、0177.0x1、2130706433を使うこともできます。 ドット付き十進表記ではなく、単なる十進数表記、16進数表記、8進数表記、それらが混ざったドット付き表記なども使えてしまうのです。

Webブラウザによっては、上記表記をそのまま解釈します。Webブラウザのアドレスバーに、変なIPv4アドレス表記を入れると、次のようになる場合もあります。


これは、getaddrinfo()、gethostbyname()、inet_aton()などが、上記表記をIPv4アドレスとして受け入れてしまうシステムが存在するためです。 RFC 3986の「7.4. Rare IP Address Formats」でも、このことが紹介されています。

getaddrinfo()などがそれらを受け入れるシステムであれば、たとえば、pingでも同様のことができます。


$ ping 2130706433
PING 2130706433 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.052 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.129 ms

ping 192.168.257とやると、ping 192.168.1.1が実行されます。

getaddrinfo()を使ったサンプル

以下、Cを使ってgetaddrinfo()に色々な変なIPv4アドレスを試すサンプルコードです。


#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

int
main()
{
  char *hostname = "0xcafeface";
  //char *hostname = "0xdeadbeef";
  //char *hostname = "127.1";
  //char *hostname = "2130706433";
  //char *hostname = "127.0x1";
  //char *hostname = "0x7f.0x1";
  //char *hostname = "192.168.257";
  //char *hostname = "192.168.256";
  //char *hostname = "192.11010049";
  //char *hostname = "0177.0x1";

  struct addrinfo hints, *res;
  struct in_addr addr;
  char buf[16];
  int err;

  memset(&hints, 0, sizeof(hints));
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_family = AF_INET;
  if ((err = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
    printf("error %d\n", err);
    return 1;
  }

  addr.s_addr = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr;
  inet_ntop(AF_INET, &addr, buf, sizeof(buf));
  printf("ip address : %s\n", buf);

  freeaddrinfo(res);

  return 0;
}

知っていても何の得ない情報ですが、楽しんでいただければ幸いです。

   このエントリをはてなブックマークに登録