如何检查给定的 IP 地址范围仅包含一个 CIDR?
How to check given IP address range contains only one CIDR?
我正在尝试编写一个 Python 脚本来将两个 IP 地址之间的范围转换为 CIDR,
# cidr.py
import argparse
import netaddr
import sys
parser = argparse.ArgumentParser()
parser.add_argument('start_addr')
parser.add_argument('end_addr')
args = parser.parse_args()
start_addr = netaddr.IPAddress(args.start_addr)
end_addr = netaddr.IPAddress(args.end_addr)
if end_addr < start_addr:
print('start address is larger than end address. check arguments.')
sys.exit()
ip_cidr = netaddr.iprange_to_cidrs(start_addr, end_addr)
print(str(ip_cidr))
例如,使用 Salesforce's IP address range 作为参数执行此脚本,
它 returns 正确的 CIDR 表达式。
$ python cidr.py 13.108.0.0 13.111.255.255
[IPNetwork('13.108.0.0/14')]
但是当我修改第二个参数时,它 returns 几个 CIDR。
$ python hoge.py 13.108.0.0 13.211.255.255
[IPNetwork('13.108.0.0/14'), IPNetwork('13.112.0.0/12'), IPNetwork('13.128.0.0/10'), IPNetwork('13.192.0.0/12'), IPNetwork('13.208.0.0/14')]
我想知道2个IP地址的地址范围只有包含1个CIDR表达式。
如何查看?
如果 iprange_to_cidrs
总是 returns 跨越提供的范围所需的最小 IP 范围数(看起来很可能)那么你只需要测试列表的长度 returns.
但是,如果您不想验证情况是否总是如此,可以使用以下方法。
def ip_to_int(ip):
return sum(256**i * int(v) for i, v in enumerate(reversed(ip.split('.'))))
def single_cidr(ip1, ip2):
n1 = ip_to_int(ip1)
n2 = ip_to_int(ip2)
xor = n2 ^ n1
return xor == abs(n2 - n1) and '0' not in bin(xor)[2:]
print(single_cidr('13.108.0.0', '13.111.255.255')) # True
print(single_cidr('13.108.0.0', '13.211.255.255')) # False
此处,xor
包含两个 IP(当转换为整数时)不同的每一位 1。我们希望这个数字等于值之间的差值,并且还小于 2 的幂——这样二进制中的两个 IP 地址以相同的词干开头,然后一个全为 0,而另一个全为 1。
在 '0' not in bin(xor)[2:]
部分中,我们使用这样一个事实,即在初始 0b
之后 bin
的输出将从第一个 1 位开始而不填充任何前导零(例如 65535会是'0b11111111'
),所以我们只需要测试一下初始的0b
.
后面没有0就可以了
我正在尝试编写一个 Python 脚本来将两个 IP 地址之间的范围转换为 CIDR,
# cidr.py
import argparse
import netaddr
import sys
parser = argparse.ArgumentParser()
parser.add_argument('start_addr')
parser.add_argument('end_addr')
args = parser.parse_args()
start_addr = netaddr.IPAddress(args.start_addr)
end_addr = netaddr.IPAddress(args.end_addr)
if end_addr < start_addr:
print('start address is larger than end address. check arguments.')
sys.exit()
ip_cidr = netaddr.iprange_to_cidrs(start_addr, end_addr)
print(str(ip_cidr))
例如,使用 Salesforce's IP address range 作为参数执行此脚本, 它 returns 正确的 CIDR 表达式。
$ python cidr.py 13.108.0.0 13.111.255.255
[IPNetwork('13.108.0.0/14')]
但是当我修改第二个参数时,它 returns 几个 CIDR。
$ python hoge.py 13.108.0.0 13.211.255.255
[IPNetwork('13.108.0.0/14'), IPNetwork('13.112.0.0/12'), IPNetwork('13.128.0.0/10'), IPNetwork('13.192.0.0/12'), IPNetwork('13.208.0.0/14')]
我想知道2个IP地址的地址范围只有包含1个CIDR表达式。 如何查看?
如果 iprange_to_cidrs
总是 returns 跨越提供的范围所需的最小 IP 范围数(看起来很可能)那么你只需要测试列表的长度 returns.
但是,如果您不想验证情况是否总是如此,可以使用以下方法。
def ip_to_int(ip):
return sum(256**i * int(v) for i, v in enumerate(reversed(ip.split('.'))))
def single_cidr(ip1, ip2):
n1 = ip_to_int(ip1)
n2 = ip_to_int(ip2)
xor = n2 ^ n1
return xor == abs(n2 - n1) and '0' not in bin(xor)[2:]
print(single_cidr('13.108.0.0', '13.111.255.255')) # True
print(single_cidr('13.108.0.0', '13.211.255.255')) # False
此处,xor
包含两个 IP(当转换为整数时)不同的每一位 1。我们希望这个数字等于值之间的差值,并且还小于 2 的幂——这样二进制中的两个 IP 地址以相同的词干开头,然后一个全为 0,而另一个全为 1。
在 '0' not in bin(xor)[2:]
部分中,我们使用这样一个事实,即在初始 0b
之后 bin
的输出将从第一个 1 位开始而不填充任何前导零(例如 65535会是'0b11111111'
),所以我们只需要测试一下初始的0b
.