Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Найти алгоритм получения списка IP адресов из диапазона  (Прочитано 561 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2628
    • Просмотр профиля
Доброго времени.
Появилась такая задача. Нужно найти алгоритм, и написать код.
Последнее сделаю и сам, а с первым нужна помощь.
Пример: Диапазон 1.0.0.0/8 и ему соответствует список адресов: 1.0.0.0 - 1.255.255.255
Да именно так, а не 1.0.0.0 - 1.0.0.8.
Немного теории:
https://ru.m.wikipedia.org/wiki/%D0%9C%D0%B0%D1%81%D0%BA%D0%B0_%D0%BF%D0%BE%D0%B4%D1%81%D0%B5%D1%82%D0%B8
https://ru.stackoverflow.com/questions/241252/%D0%A7%D1%82%D0%BE-%D1%82%D0%B0%D0%BA%D0%BE%D0%B5-24-16-%D0%B2-ip-%D0%B0%D0%B4%D1%80%D0%B5%D1%81%D0%B0%D1%85

Есть вот такой онлайн калькулятор:
http://www.subnet-calculator.com/cidr.php
Там указывается ip, Mask Bits (это как раз и есть цифра после /)
и в результате в поле CIDR Address Range пишет ip входящие в этот диапазон.

В теме сетей и адресов слабо разбираюсь если что.
За помощь возможна мат. благодарность.

Оффлайн The Green Side

  • Старожил
  • *
  • Сообщений: 1175
    • Просмотр профиля
А алгоритм обязательно находить? Он просто сложный, там в другой системе исчисления считается.
Готовых калькуляторов полно, вот, например, на Python2
Debian Testing (Gnome), Ubuntu Server 18.04

Оффлайн ALiEN175

  • Модератор форума
  • Старожил
  • *
  • Сообщений: 4714
  • Capture the truth
    • Просмотр профиля
ReNzRv, ipcalc - взять min host, max host, заполнять в цикле. Не самый лучший способ. 
$: ipcalc 1.0.0.0/8
Address:   1.0.0.0              00000001. 00000000.00000000.00000000
Netmask:   255.0.0.0 = 8        11111111. 00000000.00000000.00000000
Wildcard:  0.255.255.255        00000000. 11111111.11111111.11111111
=>
Network:   1.0.0.0/8            00000001. 00000000.00000000.00000000
HostMin:   1.0.0.1              00000001. 00000000.00000000.00000001
HostMax:   1.255.255.254        00000001. 11111111.11111111.11111110
Broadcast: 1.255.255.255        00000001. 11111111.11111111.11111111
Hosts/Net: 16777214              Class A
ASUS P5K-C :: Intel Xeon E5450 :: 8 GB RAM :: Radeon R7 260X :: XFCE
SAMSUNG N150 :: Intel Atom N450 :: 2 GB RAM :: Intel GMA3150 :: XFCE

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2628
    • Просмотр профиля
ALiEN175,
В десятичной системе заполнять в цикле не получится :(
Потому что например если взять диапазон 188.126.32.0/20, то последний адрес будет 188.126.47.254

m-svo,
Спасибо, похоже то что надо. Теперь задача как поправить этот скрипт чтобы получить список всех адресов...
Код: (python) [Выделить]
#!/usr/bin/env python

import sys
import os
#from blessings import Terminal

# Going to set up colors for a future project, not completed yet
#term = Terminal()

# Get address string and CIDR string from command line
xaddr = raw_input("IP address: ") # need to validate input of IP address
xcidr = raw_input("CIDR notation, NO / mark!: ")
addr = xaddr.split('.')
cidr = int(xcidr)

# Initialize the netmask and calculate based on CIDR mask
mask = [0, 0, 0, 0]
for i in range(cidr):
    mask[i/8] = mask[i/8] + (1 << (7 - i % 8))

# Initialize net and binary and netmask (net) with addr to get network
net = []
for i in range(4):
    net.append(int(addr[i]) & mask[i])

# Duplicate net into broad array, gather host bits, and generate broadcast
broad = list(net)
brange = 32 - cidr
for i in range(brange):
    broad[3 - i/8] = broad[3 - i/8] + (1 << (i % 8))

# This gives you usable hosts for the given subnet
xhost = 2 ** brange - 2
host = "{:,}".format(xhost)

# Initialize o for wildcard mask (imask) with broadcast - net
o = [0, 0, 0, 0]
for i in range(4):
o[i] = broad[i] - net[i]

# This gives the wildcard mask for the given subnet
imask = []
for i in range (4):
imask.append(int(o[i]) & broad[i])

# Print information, mapping integer lists to strings for easy printing
print 'Here are your results:..............'
print "Address: " , xaddr
print "Netmask: " , ".".join(map(str, mask))
print "Wildcard Mask: " , ".".join(map(str, imask))
print "Network: " , ".".join(map(str, net))
print "Usable IPs: " , host
print "Broadcast: " , ".".join(map(str, broad))

raw_input("Press any key to exit...")

Оффлайн The Green Side

  • Старожил
  • *
  • Сообщений: 1175
    • Просмотр профиля
А, вам развёрнутый список нужен.
Нашёл скрипт, переписал его на Python3 (4 скобки добавил  ;D)
Оказывается, в Питоне есть модуль netaddr, там всё, что нужно

sudo apt install python3-netaddr
networks.txt
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16

cidrExpand.py
Код: (Python) [Выделить]
#!/usr/bin/env python3
#Jeremy Galloway // root at cypherg dot com

from netaddr import IPNetwork
import sys

if len(sys.argv) < 2:
        print ('example usage: python cidrExpand.py cidrRanges.txt >> output.txt')

with open(sys.argv[1], 'r') as cidrRanges:
        for line in cidrRanges:
                ip = IPNetwork(line)
                for ip in ip:
                        print (ip)

python3 cidrExpand.py networks.txt > out.txt
« Последнее редактирование: 01 Февраль 2020, 21:03:11 от m-svo »
Debian Testing (Gnome), Ubuntu Server 18.04

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2628
    • Просмотр профиля
m-svo,
Спс, я уже тоже нашел скрипт, только без установки модуля и 3 питона:
Код: (python) [Выделить]
#!/usr/bin/env python

import sys, struct, socket

(ip, cidr) = sys.argv[1].split('/')
cidr = int(cidr)
host_bits = 32 - cidr
i = struct.unpack('>I', socket.inet_aton(ip))[0] # note the endianness
start = (i >> host_bits) << host_bits # clear the host bits
end = start | ((1 << host_bits) - 1)

# excludes the first and last address in the subnet
for i in range(start, end):
    print(socket.inet_ntoa(struct.pack('>I',i)))
Все ок, кроме одного: Последний адрес на один меньше, т.е. 254 а не 255


Пользователь добавил сообщение 01 Февраль 2020, 21:05:45:
Исправил:
Код: (python) [Выделить]
#!/usr/bin/env python

import sys, struct, socket

(ip, cidr) = sys.argv[1].split('/')
cidr = int(cidr)
host_bits = 32 - cidr
i = struct.unpack('>I', socket.inet_aton(ip))[0] # note the endianness
start = (i >> host_bits) << host_bits # clear the host bits
end = start | (1 << host_bits)

# excludes the first and last address in the subnet
for i in range(start, end):
    print(socket.inet_ntoa(struct.pack('>I',i)))
« Последнее редактирование: 01 Февраль 2020, 21:05:45 от ReNzRv »

Оффлайн The Green Side

  • Старожил
  • *
  • Сообщений: 1175
    • Просмотр профиля
upd: дубликат вышел, я то же самое сделал  :)
Debian Testing (Gnome), Ubuntu Server 18.04

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2628
    • Просмотр профиля
m-svo,
Ага ;), но спс все равно

 

Страница сгенерирована за 0.104 секунд. Запросов: 27.