Skip to content

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

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

サンプルコード

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/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"))

実行例

1
2
3
4
5
6
7
# ./sample.py
255.255.255.0
0.0.0.255
24
0.0.0.255
255.255.255.0
24

ユニットテスト

サンプルコード

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/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]
            )

実行例

1
2
3
4
5
6
# python3 -m unittest test_sample.py
......
----------------------------------------------------------------------
Ran 6 tests in 0.002s

OK