Python で「プリフィックス / ネットマスク / ワイルドカード」を相互変換する

George Shuklin さんが Wildcard masks operations in Python という記事で「Python でワイルドカードを操作する方法」をまとめてくださっています。 ワイルドカードが関連しないケースも含め、「プリフィックス長」「ネットマスク」「ワイルドカード」を相互変換する Python サンプルコードをメモしておきます。

サンプルコード

#!/usr/bin/env python3

from ipaddress import IPv4Address

def prefixlen_to_netmask(prefixlen: int) -> str:
    return str(IPv4Address(int(IPv4Address._make_netmask(prefixlen)[0])))

def prefixlen_to_wildcard(prefixlen: int) -> str:
    return str(
        IPv4Address(int(IPv4Address._make_netmask(prefixlen)[0]) ^ (2**32 - 1))
    )

def netmask_to_prefixlen(netmask: str) -> int:
    return IPv4Address._prefix_from_ip_int(int(IPv4Address(netmask)))

def netmask_to_wildcard(netmask: str) -> str:
    return str(IPv4Address(int(IPv4Address(netmask)) ^ (2**32 - 1)))

def wildcard_to_netmask(wildcard: str) -> str:
    return str(IPv4Address(int(IPv4Address(wildcard)) ^ (2**32 - 1)))

def wildcard_to_prefixlen(wildcard: str) -> int:
    return IPv4Address._prefix_from_ip_int(int(IPv4Address(wildcard)) ^ (2**32 - 1))

print(prefixlen_to_netmask(24))
print(prefixlen_to_wildcard(24))
print(netmask_to_prefixlen("255.255.255.0"))
print(netmask_to_wildcard("255.255.255.0"))
print(wildcard_to_netmask("0.0.0.255"))
print(wildcard_to_prefixlen("0.0.0.255"))

実行例

# ./sample.py
255.255.255.0
0.0.0.255
24
0.0.0.255
255.255.255.0
24

ユニットテスト

サンプルコード

#!/usr/bin/env python3

import unittest

import sample

PREFIXLEN = 0
NETMASK = 1
WILDCARD = 2

values = [
    [0, "0.0.0.0", "255.255.255.255"],
    [1, "128.0.0.0", "127.255.255.255"],
    [2, "192.0.0.0", "63.255.255.255"],
    [3, "224.0.0.0", "31.255.255.255"],
    [4, "240.0.0.0", "15.255.255.255"],
    [5, "248.0.0.0", "7.255.255.255"],
    [6, "252.0.0.0", "3.255.255.255"],
    [7, "254.0.0.0", "1.255.255.255"],
    [8, "255.0.0.0", "0.255.255.255"],
    [9, "255.128.0.0", "0.127.255.255"],
    [10, "255.192.0.0", "0.63.255.255"],
    [11, "255.224.0.0", "0.31.255.255"],
    [12, "255.240.0.0", "0.15.255.255"],
    [13, "255.248.0.0", "0.7.255.255"],
    [14, "255.252.0.0", "0.3.255.255"],
    [15, "255.254.0.0", "0.1.255.255"],
    [16, "255.255.0.0", "0.0.255.255"],
    [17, "255.255.128.0", "0.0.127.255"],
    [18, "255.255.192.0", "0.0.63.255"],
    [19, "255.255.224.0", "0.0.31.255"],
    [20, "255.255.240.0", "0.0.15.255"],
    [21, "255.255.248.0", "0.0.7.255"],
    [22, "255.255.252.0", "0.0.3.255"],
    [23, "255.255.254.0", "0.0.1.255"],
    [24, "255.255.255.0", "0.0.0.255"],
    [25, "255.255.255.128", "0.0.0.127"],
    [26, "255.255.255.192", "0.0.0.63"],
    [27, "255.255.255.224", "0.0.0.31"],
    [28, "255.255.255.240", "0.0.0.15"],
    [29, "255.255.255.248", "0.0.0.7"],
    [30, "255.255.255.252", "0.0.0.3"],
    [31, "255.255.255.254", "0.0.0.1"],
    [32, "255.255.255.255", "0.0.0.0"],
]

class TestSample(unittest.TestCase):
    def test_prefixlen_to_netmask(self):
        for value in values:
            self.assertEqual(
                sample.prefixlen_to_netmask(value[PREFIXLEN]), value[NETMASK]
            )

    def test_prefixlen_to_wildcard(self):
        for value in values:
            self.assertEqual(
                sample.prefixlen_to_wildcard(value[PREFIXLEN]), value[WILDCARD]
            )

    def test_netmask_to_prefixlen(self):
        for value in values:
            self.assertEqual(
                sample.netmask_to_prefixlen(value[NETMASK]), value[PREFIXLEN]
            )

    def test_netmask_to_wildcard(self):
        for value in values:
            self.assertEqual(
                sample.netmask_to_wildcard(value[NETMASK]), value[WILDCARD]
            )

    def test_wildcard_to_netmask(self):
        for value in values:
            self.assertEqual(
                sample.wildcard_to_netmask(value[WILDCARD]), value[NETMASK]
            )

    def test_wildcard_to_prefixlen(self):
        for value in values:
            self.assertEqual(
                sample.wildcard_to_prefixlen(value[WILDCARD]), value[PREFIXLEN]
            )

実行例

# python3 -m unittest test_sample.py
......
----------------------------------------------------------------------
Ran 6 tests in 0.002s

OK

コメント

タイトルとURLをコピーしました