Рассчитать маску сети из списка IP-адресов - PullRequest
0 голосов
/ 14 июля 2020

У меня есть список IPv4-адресов, находящихся в одной сети. Я хотел бы рассчитать сетевую маску для этой сети с учетом списка IP-адресов.

Список:

192.168.2.2
192.168.2.3
192.168.2.4

Результирующая сетевая маска: 255.255.255.0

Текущий алгоритм: если октеты различаются, поместите 0 в эту позицию маски сети, иначе поместите 255.

prev_ip = None
current_netmask = [255,255,255,255]
for ip in ip_list:
  if prev_ip != None:
    for i in range(0,4):
      if ip.split('.')[i] != prev_ip.split('.')[i]:
        current_netmask[i] = 0
  prev_ip = ip    

Моя проблема в том, что эта сетевая маска не всегда верна, и я знаю, что возможны другие маски сети (кроме тех, которые состоят из Комбинации 0 и 255)

1 Ответ

3 голосов
/ 14 июля 2020

Думаю, сработает. Преобразует адреса в целые числа, начинается с маски всех единиц и постепенно обнуляет возрастающие биты, начиная с наименее значимого, в то время как IP-адреса различаются при побитовом и с маской. (Каждый новый IP-адрес нужно сравнивать только с одним из уже рассмотренных IP-адресов, поскольку на этом этапе маска уже отражает сравнение с другими рассматриваемыми IP-адресами, отсюда и строка с vals[0].) Наконец, маска снова преобразуется в точечную. четырехугольное представление.

def to_int(ip):
    bytes = [int(s) for s in ip.split(".")]
    return sum(val<<(8*i) for i, val in enumerate(reversed(bytes)))

def from_int(val):
    r = []
    while val:
        r.append(val & 0xFF)
        val >>= 8
    if len(r) < 4:
        r.extend([0] * (4-len(r)))
    return ".".join(map(str, reversed(r)))

def get_mask(ips):
    vals = [to_int(ip) for ip in ips]
    mask = 0xFFFFFFFF
    bit = 1
    for val in vals[1:]:
        while vals[0] & mask != val & mask:
            mask &= ~bit
            bit <<= 1
    return from_int(mask)

ips = ["192.168.2.2", "192.168.2.3", "192.168.2.4"]
print(get_mask(ips))

дает:

255.255.255.248
...