IPv4のサブネットマスク絡みの変換

最近会社で聞かれて答えたことをまとめてみました。

IPv4のサブネットマスク絡みの変換を聞かれました。つまり、以下のような変換です。

* 変換その1：以下を相互に変換
 * サブネットマスク：Prefix形式 "/27"
 * サブネットマスク：IPアドレス形式 "255.255.255.224"
 * IPアドレス数＝32
* 変換その2：IPアドレス＋サブネットマスク⇒IPアドレス範囲
 * xxx.xxx.xxx.74/27 ⇒ xxx.xxx.xxx.64 ～ xxx.xxx.xxx.95

これを聞かれるときは大抵ネットワークが繋がる場所です。そのため、検索で事足りることが大半です。例えば"[WEB便利ノート](https://note.cman.jp/)"の"[サブネットマスク計算](https://note.cman.jp/network/subnetmask.cgi)"などが見つかります。

ここでは、そのような手段を取りづらい場面での変換方法を記します。

但し、大まかな概念を理解している前提とします。つまり、以下のような変換ができることを前提とします。

* 変換その1：以下を相互変換
 * サブネットマスク：Prefix形式 "/24"
 * サブネットマスク：IPアドレス形式 "255.255.255.0"
 * IPアドレス数＝256
* 変換その2：IPアドレス＋サブネットマスク ⇒ IPアドレス範囲
 * xxx.xxx.xxx.74/24 ⇒ xxx.xxx.xxx.0 ～ xxx.xxx.xxx.255

そのうえで、8ビット未満が登場するケースをなかなか覚えられないという人を対象としています。

# 覚え方

以下の順に覚えます。

* サブネットマスク：Prefix形式 ⇔ IPアドレス数
* サブネットマスク：IPアドレス形式 ⇔ IPアドレス数
* サブネットマスク：Prefix形式 ⇔ サブネットマスク：IPアドレス形式
* IPアドレス＋サブネットマスク：Prefix ⇒ IPアドレス範囲

説明の中で、"^"は累乗、"XOR"は排他的論理和を表します。BASICの演算子と同じ表記です。

以下の説明では、8ビット未満となるオクテットが第4オクテットに収まる場合を説明しています。つまり"8ビット未満の端数部分の変換"方法です。8ビット未満となるオクテットが第3オクテット以前となる場合は、"8ビット単位での変換"と"8ビット未満の端数部分の変換"を組み合わせてください。

## サブネットマスク：Prefix形式 ⇔ IPアドレス数

題材とした"/27"で説明します。"サブネットマスク：Prefix形式"から"IPアドレス数"に変換するには、以下の順に変換します。

* サブネットマスク：Prefix形式 "/27"
* 頭から1が続くビット数 ＝ 27
* 末尾に0が続くビット数 ＝ ( 8 * 4 ) - 27 ＝ 32 - 27 ＝ 5
* IPアドレス数 ＝ 2 ^ 5 ＝ 32

"/24"の変換ができる人であれば、この説明だけで十分でしょう。Prefixの増加減少とIPアドレス数の増加減少とで、"方向が逆方向"＆"尺度が同じでない"ので分かりにくく感じるだけです。

逆方向の変換は、上記を逆に考えるだけです。

* IPアドレス数 ＝ 32
* 32の2進数表記 ＝ 100000
* 末尾に0が続くビット数 ＝ 5
* 頭から1が続くビット数 ＝ ( 8 * 4 ) - 5 ＝ 27
* サブネットマスク：Prefix形式 "/27"

IPアドレス数とその2進数表記の部分は曖昧に書いてあります。ここに出てくる数はプログラムで重要な数たちです。これくらいは覚えておいてもいいでしょう。第4オクテットのことだけを考えれば、覚えるのは9つで済みます。0～7の8つと言いたいところですが、8も併せて覚えておいてよいでしょう。

|ビット数|IPアドレス数|
|-------:|-----------:|
|       0|           1|
|       1|           2|
|       2|           4|
|       3|           8|
|       4|          16|
|       5|          32|
|       6|          64|
|       7|         128|
|       8|         256|

## サブネットマスク：IPアドレス形式 ⇔ IPアドレス数

題材とした"/27"で説明します。IPアドレス数は32でした。"IPアドレス数"から"サブネットマスク：IPアドレス形式"に変換するには、以下の順に変換します。

* IPアドレス数 ＝ 32
* IPアドレスの第4オクテット ＝ 256 - 32 ＝ 224
* サブネットマスク：IPアドレス形式 ＝ 255.255.255.224

但し、IPアドレス数からの変換というシチュエーションで、第3オクテット以前まで食い込む、つまりIPアドレス数が256を超える場合はあまりないと思います。

引き算で計算している部分の変換を説明しておきます。以下のように計算しています。

* IPアドレス数 ＝ 32
* "32"は2進数表記で"100000"(0が5ビット分続く)
* 8ビットで、残りの上位ビットを全て"1"とした"11100000"(224)が求める値
* 2進数で "11100000" ＝ "11111111"(255) XOR "00011111"(下位5ビット分が全て1)(2^5-1)
* 全ONとのXORだから単純に引き算するだけで計算できる
* 255 XOR ( 2 ^ 5 - 1 ) ＝ 255 - ( 2 ^ 5 - 1 ) ＝ ( 255 + 1 ) - ( 2 ^ 5 ) ＝ 256 - 32 ＝ 224

逆方向の変換も同様です。

* サブネットマスク：IPアドレス形式 ＝ 255.255.255.224
* IPアドレスの第4オクテット ＝ 224
* IPアドレス数 ＝ 256 - 224 ＝ 32

これまた"単純に引き算するだけで計算できる"ことを利用しています。

## サブネットマスク：Prefix形式 ⇔ サブネットマスク：IPアドレス形式

IPアドレス数を経由します。ほとんど同じことを説明することになってしまいますが、説明します。

題材とした"/27"で説明すると、"サブネットマスク：Prefix形式"から"サブネットマスク：IPアドレス形式"に変換するには、以下の順に変換します。

* サブネットマスク：Prefix形式 "/27"
* 頭から1が続くビット数 ＝ 27
* 末尾に0が続くビット数 ＝ ( 8 * 4 ) - 27 ＝ 32 - 27 ＝ 5
* IPアドレス数 ＝ 2 ^ 5 ＝ 32
* サブネットマスク：IPアドレスの第4オクテット ＝ 256 - 32 ＝ 224
* サブネットマスク：IPアドレス形式 ＝ 255.255.255.224

逆方向の変換も同様です。

* サブネットマスク：IPアドレス形式 ＝ 255.255.255.224
* サブネットマスク：IPアドレスの第4オクテット ＝ 224
* IPアドレス数 ＝ 256 - 224 ＝ 32
* 32の2進数表記 ＝ 100000
* 末尾に0が続くビット数 ＝ 5
* 頭から1が続くビット数 ＝ ( 8 * 4 ) - 5 ＝ 27
* サブネットマスク：Prefix形式 "/27"

## IPアドレス＋サブネットマスク：Prefix ⇒ IPアドレス範囲

題材とした"xxx.xxx.xxx.74/27"で説明します。律義に変換するなら、以下のようになります。

* サブネットマスク：Prefix "/27"
* IPアドレス数 ＝ 32
* 開始までのブロック数 ＝ IPアドレス第4オクテット ÷ IPアドレス数 ＝ 74 ÷ 32 ＝ 2 余り 10
* 開始 ＝ 32 * 2 ＝ 64
* 終了 ＝ 開始 + IPアドレス数 - 1 ＝ 64 + 32 - 1 ＝ 95
* 範囲 ＝ xxx.xxx.xxx.64 ～ xxx.xxx.xxx.95

IPアドレス数を求めた後は、概算で求めてから補正すればいいでしょう。例えば"xxx.xxx.xxx.190/27"なら

* 開始までのブロック数 ≒ 190 ÷ 30 ≒ 6
* 開始 ＝ 32 * 6 ＝ 64 * 3 ＝ 128 + 64 ＝ 192
* 終了 ＝ 192 + 32 - 1 ＝ 223
* 範囲 ＝ 192 ～ 223

として、下方向に範囲外なので1ブロック分32個分マイナスして

* 範囲 ＝ 160 ～ 191

とすれば合います。

# まとめ

理屈を知っていれば、暗記していなくても計算で出てきます。そして最終的には、数をこなすことで以下の表を自然と暗記することになると思います。

|サブネットマスク Prefix|末尾の0の ビット数|IPアドレス数|サブネットマスク IPアドレス形式|
|--:|--:|--:|--:|
|32| 0|  1|255|
|31| 1|  2|254|
|30| 2|  4|252|
|29| 3|  8|248|
|28| 4| 16|240|
|27| 5| 32|224|
|26| 6| 64|192|
|25| 7|128|128|
|24| 8|256|  0|

最後に簡単にまとめておきます。表の2列目と3列目は、この記事の途中に出てきた表と同じです。表の1列目と2列目、表の3列目と4列目の関係は、単なる引き算です。