如何检查给定的 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就可以了