t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

VBA × Network学習:プレフィックス長からサブネットマスクに変換する

今回は久々にVBA。
ネットワーク学習で苦手なサブネット回りの計算をしてみようと思う。

IPアドレスとサブネットマスクを表記する方法として、プレフィックス長表記(またはCIDR表記)という方法があり、たとえば192.168.1.0/24と書くとIPアドレスが192.168.1.0でサブネットマスクは255.255.255.0という意味になる。

IPアドレスやサブネットマスクの実態は32ビットのデジタルデータ(二進数)で、これを8ビットずつに区切って10進数で表されている。
255.255.255.0はそれぞれ2進数に直すと、11111111.11111111.11111111.00000000となる。このとき1が先頭が24個並んでいるので/24という表記になっているわけだ。

この表記は簡潔に書けて良いんだけど、ネットワークの学習をしているとパッとサブネットに直したいときがある。

これが/8、/16、/24など、都合よくドットの区切り目でわかれているようなケースはナチュラルマスクといって、255か0で構成されるので覚えるのも簡単だが、中途半端な位置で切れていると変換するのもなかなか大変。

ということでVBAコードを書いてみた。

Sub PrefixLengthToSubnetMask()
    Dim i
    For i = 0 To 32
        Debug.Print "Prefix /" & i, Subnet(i)
    Next
End Sub

Function Subnet(prefix) As Variant
    '最後にJoin使うためにあえて数値ではなくVariantで配列宣言
    Dim subnet_(1 To 4) As Variant
    
    Dim octet As Integer
    Dim bit_in_octet As Integer
    Dim current_bit As Integer
    
    For octet = 1 To 4
        'Variantなので0で初期化しないとブランク文字になってしまう。
        subnet_(octet) = 0
        For bit_in_octet = 0 To 7
            current_bit = current_bit + 1
            If current_bit <= prefix Then
                subnet_(octet) = subnet_(octet) + 2 ^ (7 - bit_in_octet)
            End If
        Next
    Next
    Subnet = Join(subnet_, ".")
End Function

余談だけど最近はラズパイとかLinuxでのpythonコーディングが増えて変数名はスネークケースの方が読みやすく感じてしまう。
どっぷりVBAに漬かってた頃はキャメル・パスカルが読みやすいと考えていたんだけど、今書いてみると単なる思い込みだった可能性が高いと思い始めた。

当時VB.Netのコーディングガイドライン本だったり、Microsoftのコードだったりを参考にガイドラインを作ったんだけど、現時点ではキャメル・パスカルについては先例を踏襲したという以外にそうする理由を見いだせない。自分で過去に書いたガイドラインから思い切り違反しているのでガイドラインの方を改定してしまいたい気持ちもありつつ、VBAコミュニティはキャメルケースとかパスカルケースが主流だと思われるので悩ましいところ。

さて、実行結果は次のとおり。

Prefix /0  0.0.0.0
Prefix /1  128.0.0.0
Prefix /2  192.0.0.0
Prefix /3  224.0.0.0
Prefix /4  240.0.0.0
Prefix /5  248.0.0.0
Prefix /6  252.0.0.0
Prefix /7  254.0.0.0
Prefix /8  255.0.0.0
Prefix /9  255.128.0.0
Prefix /10  255.192.0.0
Prefix /11  255.224.0.0
Prefix /12  255.240.0.0
Prefix /13  255.248.0.0
Prefix /14  255.252.0.0
Prefix /15  255.254.0.0
Prefix /16  255.255.0.0
Prefix /17  255.255.128.0
Prefix /18  255.255.192.0
Prefix /19  255.255.224.0
Prefix /20  255.255.240.0
Prefix /21  255.255.248.0
Prefix /22  255.255.252.0
Prefix /23  255.255.254.0
Prefix /24  255.255.255.0
Prefix /25  255.255.255.128
Prefix /26  255.255.255.192
Prefix /27  255.255.255.224
Prefix /28  255.255.255.240
Prefix /29  255.255.255.248
Prefix /30  255.255.255.252
Prefix /31  255.255.255.254
Prefix /32  255.255.255.255

ポイントはコード中の以下の部分。

If current_bit <= prefix Then
    subnet_(octet) = subnet_(octet) + 2 ^ (7 - bit_in_octet)
End If

ちょっと分かりにくいと思うのでPrefix /29の場合を例に最後の8オクテットを図示したものを張っておこうと思う。

今後の展望

今回ご紹介したのはIPアドレス・サブネットマスク回りの様々な計算を実行できるクラスモジュールを作りたいという目的の一部分である。
今後記事にするかどうかは分からないけど、とりあえず自分用の計算クラスを作るところまではやってみようと思う。

以上

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。