私は間違ってIPアドレスのドットを見落としてしまい、192.168.072
と入力してしまいました。 驚いたことに、私は192.168.0.58
のマシンに接続しました
192.168.072
をpingすると、192.168.0.58
からの応答が返ってきます
なぜなんでしょうか?
WindowsドメインのPCでやってます
192.168.72
をpingすると192.168.0.72
からの応答が返ってくるので、072
の0
(私の元のミス)が大きいようです
この質問は、今週のスーパーユーザーの質問でした。 詳細については、ブログのエントリーを読むか、ブログに自分で投稿する
380 George Duckett 2012-10-12
誰もがRFCやIPクラスなどで複雑にしすぎています。ping
コマンドがユーザの入力した IP をどのように解析するかを見るために、いくつかのテストを実行してみてください (不要なチャフは取り除かれています)
> ping 1
Pinging 0.0.0.1 with 32 bytes of data:
> ping 1.2
Pinging 1.0.0.2 with 32 bytes of data:
> ping 1.2.3
Pinging 1.2.0.3 with 32 bytes of data:
> ping 1.2.3.4
Pinging 1.2.3.4 with 32 bytes of data:
> ping 1.2.3.4.5
Ping request could not find host 1.2.3.4.5. Please check the name and try again.
> ping 255
Pinging 0.0.0.255 with 32 bytes of data:
> ping 256
Pinging 0.0.1.0 with 32 bytes of data:
ご覧のように、ping
コマンド(Windowsの場合)では、異なるIPアドレス形式を使用することができます。IPv4 アドレスは、以下のように 4 つの部分 (“dotted-quad”) に分割することができます。A.B.C.D
のように、ping
コマンドでは一部を省略することができ、以下のように 0
のデフォルトを埋めることができます
1 part (ping A) : 0.0.0.A
2 parts (ping A.B) : A.0.0.B
3 parts (ping A.B.C) : A.B.0.C
4 parts (ping A.B.C.D) : A.B.C.D
単一の部分のみを供給する場合、それが255以下(オクテットの最大値)であれば、上記のようにオクテットとして扱われますが、255より大きい場合は変換されて次のフィールドにロールオーバーされます(つまり、mod 256
)
4つ以上の部分を提供してもうまくいかないようなエッジケースがいくつかあります(例えば、google.com
のIPにpingを打つと0.74.125.226.4
や74.125.226.4.0
ではうまくいかないなど)
また、16進数表記をドットクォートとフラットの両方で使用することもできますが、各オクテットに0x
を前置してフォーマットする必要があります
このように、(IPv4)IPアドレスを表現する方法はたくさんあります。フラットまたはドットクォード(またはドットトリプル、ドットダブル、またはドットシングル)形式を使用することができ、それぞれについて、10進数、8進数、16進数を使用することができます(または混ぜて使用することもできます)。例えば、google.com
は以下のように ping することができます
google.com
(domain name)74.125.226.4
(dotted decimal)1249763844
(flat decimal)0112.0175.0342.0004
(dotted octal)011237361004
(flat octal)0x4A.0x7D.0xE2.0x04
(dotted hex)0x4A7DE204
(flat hex)74.0175.0xe2.4
(ಠ_ಠ)
(バイナリ表記のサポートが追加されていないのはありがたい!)
アプリケーションです
あなたの場合、192.168.072
にpingすると、上の表の3番目のフォーマット(A.B.0.C
)が使われますので、実際には192.168.0.072
にpingしていることになります。さらに、最後の部分に先頭のゼロがあるので、8進数として扱われ、10進数では58となります
Mystery solved.
Windows ping
コマンドは、入力のための多種多様なフォーマットを可能にし、非標準フォーマットを見てきたような方法で解釈しますが、必ずしもどこでもそのようなフォーマットを使用できるというわけではないことに注意してください。プログラムによっては、ドットクォードの4つの部分をすべて提供することを強制されるかもしれませんし、10進数と8進数の混合とマッチングを許可しないプログラムもあります
また、IPv6アドレスは、解析ロジックと入力フォーマットの許容性をさらに複雑にしています
補遺です
syssが指摘していた、数字の中に無効な文字を使った場合(例えば、八進数を使う場合は8
や9
、16進数を使う場合はg
など)、ping
はそれを認識して、数字のIPアドレスではなく、文字列(-al? -ic?)のURLとして解釈することができます
(データ値の組み合わせの数が指数関数的に爆発的に増加していることに対応するために、おそらく「シンプルな」コードを書こうとして、何度も動脈瘤や心臓発作を起こしてきた者として、私はそれが入力されたすべてのバリエーションを正しく処理するように見えることを評価します
そのため、010.020.030.040
を指定すると期待通りに8.16.24.32
をpingしますが、010.020.030.080
をping
に渡すと、IPアドレスのようなfoo.bar.baz.com
が存在する可能性がある(しかし悲しいことに存在しない)代わりにURLのように扱われます。つまり、トップレベルドメイン080
でサブドメイン010
に020
に030
に030
にpingしようとします。しかし、080
は有効な TLD ではないので (.com
, .net
, およびそれらの仲間のように)、接続は最初のステップですぐに失敗します
無効な文字が別のオクテットにある場合、090.010.010.010
でも同じことが起こる。同様に、0xf.0xf.0xf.0xf
は15.15.15.15
をpingしますが、0xh1.0x1.0xg0.0f
は失敗します
まあ、複数の数字ベースに流暢に対応できないからこうなるんだろうな
常に4-dotted-quad(“40q”? “quaddy-quad”? “cutie-q”? )アドレスを使うようにした方が簡単で安全かもしれません
だから行って、learn some number basesあなたはで誇示し、パーティーの人生であることができるでしょうし、彼らが言うように、人々の10種類があります:バイナリを知っている人とそうでない人
IPv6アドレスのことも考えずに、111のシールの1つだと思います!
571 Synetech 2012-10-12
その理由は2つあります
まず、’0’という接頭辞は、オクタル数を示しています。oct(072) = dec(58)なので、192.168.072 = 192.168.58となります
第二に、その2番目から最後の0は、shorthandとしてIPアドレスから落とすことができます。127.0.0.1は127.0.0.1と解釈され、あなたの場合は192.168.58は192.168.0.58と解釈されます
148 neu242 2012-10-12
八進法についての @neu242 さんの重要な指摘や、IP アドレスは短縮できるという観測に加えて、もう一つの重要な部分は、短縮された IP アドレスがどのように解釈されるかを知っていることです
4つの数字のうちのいくつかが欠けている場合、パーサはバイト列の末尾(または先頭)にゼロフィルバイトを追加するのではないかと簡単に推測することができます。しかし、これは OP が報告した動作とは一致しません。192.168.072 は 192.168.0.58 として解析され、192.168.58.0 でも 0.192.168.58 でもありません
どうやら Windows と Linux の ping (あなたが試したバージョンと私が試したバージョン) は、IP アドレスの引数を解析するために inet_aton() と同等のものを使用しているようです。inet_aton()のmanページにはこう書かれています
The address supplied in cp can have one of the following forms:
a.b.c.d Each of the four numeric parts specifies a byte of the address; the
bytes are assigned in left-to-right order to produce the binary
address.
a.b.c Parts a and b specify the first two bytes of the binary address.
Part c is interpreted as a 16-bit value that defines the rightmost
two bytes of the binary address. This notation is suitable for
specifying (outmoded) Class B network addresses.
a.b Part a specifies the first byte of the binary address. Part b is
interpreted as a 24-bit value that defines the rightmost three bytes
of the binary address. This notation is suitable for specifying
(outmoded) Class C network addresses.
a The value a is interpreted as a 32-bit value that is stored directly
into the binary address without any byte rearrangement.
そこで、以下のようになります。192.168.072
は a.b.c パターンに適合するので、072
(8 進数として解析した後) は、バイナリアドレスの右端 2 バイトを定義する 16 ビットの値として解釈され、0.58
に相当します
上記のルールは、4つの数字のどれかが欠けている場合、必要なゼロフィルバイトは最後に与えられた数字の直前に追加される…ということと等価です。(このように表現すると、最後に与えられた数字が256よりも小さい場合に動作します)
ping の新しいバージョンでは、この種の速記法や八進法の解釈ができないかもしれないことに注意してください。私が見つけた 2010年版の iputils のソースコード (ping を含む) では、IP アドレスの引数を解析するのに inet_aton() ではなく inet_pton() を使用しています。inet_pton() の man ページにはこう書かれています
inet_aton(3) や inet_addr(3) とは異なり、inet_pton() は IPv6 アドレスをサポートしています。一方、inet_aton(3) と inet_addr(3) は、より一般的な数字とドットの表記 (16 進数と 8 進数の形式、および 4 バイトすべてを明示的に書き込む必要のない形式) を許可しているのに対し、inet_pton() はドット十進数表記の IPv4 アドレスのみを受け付けます
102 LarsH 2012-10-12
また、ipはその位置に意味を持たせて整数を足したもので表されることも考慮しなければなりません
192.168.0.58 is :
192 * 256^3
+ 168 * 256^2
+ 0 * 256^1
+ 58 * 256^0
これがかっこいいんですよ
192.168.58は192.168.0.58になるから
0 * 256^1
+ 58 * 256^0
= 58
192.11010106も192.168.0.58になりますから
168 * 256^2
+ 0 * 256^1
+ 58 * 256^0
= 11010106
3232235578も192.168.0.58になるから
192 * 256^3
+ 168 * 256^2
+ 0 * 256^1
+ 58 * 256^0
= 3232235578
24 vesquam 2012-10-12