2015-01-08

Table of IPv4 CIDR blocks

数カ月前から、「OS X Mavericks」でのネットワークの再検討をした。その際に、次の資料には明快が説明がありました;
残念なことに、この「4.2 IPv4 CIDR blocks」の表は素人には判りにくいものでした。そこで、Zshの練習を兼ねて、このテーブルを生成するスクリプト「table_ipv4」を制作したので紹介します。

実行結果


u1@MmM11[~/myZsh]% table_ipv4                                                                    21:30:34
---------------------------------------------------------------------------------------------------------
prefix  low   chg rem  rem   -----MASKv4----                            Δ to last        start addresses
 bits   bits  oct bit value  MK3.MK2.MK1.MK0      #Hosts   IPv4/CIDR    IP addr.         of blocks
---------------------------------------------------------------------------------------------------------
  32     0    0    0     0   255.255.255.255           1   a.b.c.d/32   000.000.000.000  d=(1)*{0..255}
  31     1    0    1     1   255.255.255.254           2   a.b.c.d/31   000.000.000.001  d=(2)*{0..127}
  30     2    0    2     3   255.255.255.252           4   a.b.c.d/30   000.000.000.003  d=(4)*{0..63}
  29     3    0    3     7   255.255.255.248           8   a.b.c.d/29   000.000.000.007  d=(8)*{0..31}
  28     4    0    4    15   255.255.255.240          16   a.b.c.d/28   000.000.000.015  d=(16)*{0..15}
  27     5    0    5    31   255.255.255.224          32   a.b.c.d/27   000.000.000.031  d=(32)*{0..7}
  26     6    0    6    63   255.255.255.192          64   a.b.c.d/26   000.000.000.063  d=(64)*{0..3}
  25     7    0    7   127   255.255.255.128         128   a.b.c.d/25   000.000.000.127  d=(128)*{0..1}
---------------------------------------------------------------------------------------------------------
  24     8    1    0     0   255.255.255.000         256   a.b.c.0/24   000.000.000.255  c=(1)*{0..255}
  23     9    1    1     1   255.255.254.000         512   a.b.c.0/23   000.000.001.255  c=(2)*{0..127}
  22    10    1    2     3   255.255.252.000        1024   a.b.c.0/22   000.000.003.255  c=(4)*{0..63}
  21    11    1    3     7   255.255.248.000        2048   a.b.c.0/21   000.000.007.255  c=(8)*{0..31}
  20    12    1    4    15   255.255.240.000        4096   a.b.c.0/20   000.000.015.255  c=(16)*{0..15}
  19    13    1    5    31   255.255.224.000        8192   a.b.c.0/19   000.000.031.255  c=(32)*{0..7}
  18    14    1    6    63   255.255.192.000       16384   a.b.c.0/18   000.000.063.255  c=(64)*{0..3}
  17    15    1    7   127   255.255.128.000       32768   a.b.c.0/17   000.000.127.255  c=(128)*{0..1}
---------------------------------------------------------------------------------------------------------
  16    16    2    0     0   255.255.000.000       65536   a.b.0.0/16   000.000.255.255  b=(1)*{0..255}
  15    17    2    1     1   255.254.000.000      131072   a.b.0.0/15   000.001.255.255  b=(2)*{0..127}
  14    18    2    2     3   255.252.000.000      262144   a.b.0.0/14   000.003.255.255  b=(4)*{0..63}
  13    19    2    3     7   255.248.000.000      524288   a.b.0.0/13   000.007.255.255  b=(8)*{0..31}
  12    20    2    4    15   255.240.000.000     1048576   a.b.0.0/12   000.015.255.255  b=(16)*{0..15}
  11    21    2    5    31   255.224.000.000     2097152   a.b.0.0/11   000.031.255.255  b=(32)*{0..7}
  10    22    2    6    63   255.192.000.000     4194304   a.b.0.0/10   000.063.255.255  b=(64)*{0..3}
   9    23    2    7   127   255.128.000.000     8388608   a.b.0.0/09   000.127.255.255  b=(128)*{0..1}
---------------------------------------------------------------------------------------------------------
   8    24    3    0     0   255.000.000.000    16777216   a.0.0.0/08   000.255.255.255  a=(1)*{0..255}
   7    25    3    1     1   254.000.000.000    33554432   a.0.0.0/07   001.255.255.255  a=(2)*{0..127}
   6    26    3    2     3   252.000.000.000    67108864   a.0.0.0/06   003.255.255.255  a=(4)*{0..63}
   5    27    3    3     7   248.000.000.000   134217728   a.0.0.0/05   007.255.255.255  a=(8)*{0..31}
   4    28    3    4    15   240.000.000.000   268435456   a.0.0.0/04   015.255.255.255  a=(16)*{0..15}
   3    29    3    5    31   224.000.000.000   536870912   a.0.0.0/03   031.255.255.255  a=(32)*{0..7}
   2    30    3    6    63   192.000.000.000  1073741824   a.0.0.0/02   063.255.255.255  a=(64)*{0..3}
   1    31    3    7   127   128.000.000.000  2147483648   a.0.0.0/01   127.255.255.255  a=(128)*{0..1}
---------------------------------------------------------------------------------------------------------
   0    32    4    0     0   000.000.000.000  4294967296   0.0.0.0/00   255.255.255.255  0
---------------------------------------------------------------------------------------------------------
u1@MmM11[~/myZsh]%                                                                               21:30:41

このtable_ipv4での特徴をまとめる;
  • 右端列「start addresses of blocks」を直裁的に示した点だ。
    • 「routing prefix」がOctet(8bit)変化するごとに、相似した変化が観察できる。
  • 「routing prefixが32,31」は「ホスト数が1,2」に対応しているので特殊である。
    • 「4.2 IPv4 CIDR blocks」には、その論拠が引用されている
  • MKSKv4と「Δ to last IP adde.」都の対応する成分を加えると「255」だ。例えば、「routing prefix」=17では;
    • (255.255.128.0)+(0.0.127.255)=(255.255.255.255)
  • 右端列「start addresses of blocks」は見やすい。{0..n}は(0~n)までの任意整数。 
    • 「routing prefix」がOctet(8bit)変化するごとに、相似した変化が観察できる。
  • 「routing prefixが32,31」は「ホスト数が1,2」に対応しているので特殊である。
    • 「4.2 IPv4 CIDR blocks」には、その論拠が引用されている。

スクリプト 


#!/bin/zsh 

# table_ipv4

# reference:
#  Classless Inter-Domain Routing 
#   http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing 4.2 IPv4 CIDR blocks


IP_CIDR_Delta(){
 # IP_CIDR_Delta ipv4 delta ddelta

 local PTipv4=$1
 local ipc
 ipc=${(P)PTipv4}
 ipc=($(echo "$ipc"))

 local PTdelta=$2
 local dlt
 dlt=${(P)PTdelta}
 dlt=($(echo "$dlt"))

 local PTddelta=$3
 local ddlt
 ddlt=${(P)PTddelta}
 ddlt=($(echo "$ddlt"))

 
 local nn=$((1))     # array        [1][2][3][4]
 local ocn=$((3))    # octet number  3  2  1  0
  #echo "ipc=$ipc  dlt=$dlt  ddlt=$ddlt"
  #echo "cho=$cho  rmv=$rmv"

 # Δ to last IP address
 for nn in {1..4}; do
  ocn=$((4-nn)) 
  if [ $ocn -gt $cho ]; then 
   # $choより左のoctet=0
   dlt[$nn]=$((0))
  elif [ $ocn -eq $cho ]; then
   # $choto同一のoctet=$rmvの値
   dlt[$nn]=$(($rmv))
  else
   # $choより右のoctet=255
   dlt[$nn]=$((255))
  fi
 done

 # IPv4 CIDR block notation
 # ipc: quad-dotted decimal notation: a.b.c.d/(routing prefix) 0<=a/b/c/d<=255
 # ddlt: δΔ
 case $cho in
  0)
   ddlt='d'
   ipc=('a' 'b' 'c' 'd');;
  1)
   ddlt='c'
   ipc=('a' 'b' 'c' '0');;
  2)
   ddlt='b'
   ipc=('a' 'b' '0' '0');;
  3)
   ddlt='a'
   ipc=('a' '0' '0' '0');;
  4)
   ddlt='0'
   ipc=('0' '0' '0' '0');;
 esac
 
 ipc=$(echo $ipc | tr ' ' '.')
 ### dlt=$(echo $dlt | tr ' ' '.')
  #echo "ipc=$ipc  dlt=$dlt  ddlt=$ddlt"
  #echo "ipc=$ipc"
 eval "$PTipv4='$ipc'"
 eval "$PTdelta='$dlt'"
 eval "$PTddelta='$ddlt'"

}


getMASKv4(){
#set -x
#### getMASKv4 mk 

 local PTmk=$1   # pointer of mk in the main 
 local -a msk   # local array,msk for MASKv4
 msk=${(P)PTmk}   # read msk as scalar
 msk=($(echo $msk))  # transfer scalar to array
  #echo "msk =$msk"
       # pfb="PreFix Bits"
 lb=$((32-$pfb))   # lb="LowBits"
 hts=$((2**$lb))   # Host addresses: including
       #          1. Network address, 
       #          2. Router address,
       #          3. Broadcast address.

 cho=$((lb/8))   # CHanging Octal
 rem=$((lb%8))   # REMainder of octal
 rmv=$((2**$rem-1))  # ReMainder Vallue
  #echo "mid=$mid rem=$rem"

 local n=$((0))   # array number in the next for-loop
 
 # Main loop for msk[$n] with $cho
 for oc in {3..0}; do 
  n=$((4-oc))
  if [ $oc -gt $cho ]; then
   msk[$n]=$((255))
  elif [ $oc -eq $cho ]; then
   msk[$n]=$((255-$rmv))
  else
   msk[$n]=$((0))
  fi 
 done
 
 IP_CIDR_Delta ipv4 delta ddelta

 eval "$PTmk='$msk'"

}

#----------------- main ---------------------------------------------- 
pfb=$((0))    # pfb="PreFix Bits"
lb=$((32))    # lb="LowBits"
n=$((4))    # running parameter
cho=$((0))    # CHanging Octal
rem=$((0))    # REMainder of octal
rmv=$((0))    # ReMainder Vallue
hts=$((0))    # Host addresses
mk=( 3 2 1 0 )   # array,mk for MASKv4 obtained at getMASKv4
#echo "mk=$mk   #mk=$#mk"

ipv4=('a' 'b' 'c' 'd') # obtained at IP_CIDR_Delta in getMASKv4
delta=(0 0 0 0)   # same above
ddelta='d'    # same above

# Header print
echo ---------------------------------------------------------------------------------------------------------
printf "prefix  low   chg rem  rem   -----MASKv4----                            Δ to last        start addresses\n" 
printf " bits   bits  oct bit value  MK3.MK2.MK1.MK0      #Hosts   IPv4/CIDR    IP addr.         of blocks\n"  

# Main Loop
for pfb in {32..0}; do
 if [ $(($pfb%8)) -eq 0 ] ; then
  echo ---------------------------------------------------------------------------------------------------------
 fi

 getMASKv4 mk    # call functions getMASKv4 and IP_CIDR_Delta
 mk=($(echo $mk))   # transform scalar to array
 delta=($(echo "$delta")) # transform scalar to array

 local eqlp='=('
 local rpst0d=')*{0..'
 local ddelN=$(($rmv+1))
 local last=$((255/ddelN))
 local rponly='}'
 

   
 printf "  %2d   %3d    %1d    %1d   %3d   %.3d.%.3d.%.3d.%.3d  %10d"\
  $pfb $lb $cho $rem $rmv $mk[1] $mk[2] $mk[3] $mk[4] $hts 
 printf "   %s/%.2d   %.3d.%.3d.%.3d.%.3d"\
  $ipv4 $pfb  $delta[1] $delta[2] $delta[3] $delta[4] 

 if [ "$ddelta" = '0' ]; then
  echo "  0"
 else
  printf "  %s%s%d%s%d%s\n"\
   ${ddelta} $eqlp $ddelN $rpst0d $last $rponly
 fi  
done
echo ---------------------------------------------------------------------------------------------------------

感想


CIDRブロックは素人には判りにくい。32ビットの2進数を8ビット毎に纏めて10進数にして、ドットで繋げ、その最後に「/」の後ろに「routing prefix」のだから。
寧ろ、あるプライベートIPv4ブロックのなかでの;
  • Network address
  • Host(PC, Printer, iPhone, iPad,TV, so on) address
  • Router address
  • Broadcast address
をセットにして説明すれば、細かな数式に触れずに、「必要最小限の設定」を容易に設定できるようになると思います。

このページの履歴

  1. 開始 2015-01-08(木) 20:30
  2. 追加 2015-01-10(土) 18:15 table_ipv4での特徴



注目の投稿

Terminalでの、なんちゃってViモドキ

近頃、ようやくKarabiner-Elementsに慣れてきたので、 Terminalで動作する「擬似Vi-Mode」を作って見たので、ご紹介します。 『概要』 「擬似Vi-Mode」の所以は、方向キー「←↓↑→」を通常の「hjkl」ではなくて「jkil」としました。これ...