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


Хотите сделать посильный вклад в развитие Ubuntu и русскоязычного сообщества?
Помогите нам с документацией!

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

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

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2627
    • Просмотр профиля
Доброго времени.
Появилась такая задача. Нужно найти алгоритм, и написать код.
Последнее сделаю и сам, а с первым нужна помощь.
Пример: Диапазон 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

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

Оффлайн ALiEN175

  • Старожил
  • *
  • Сообщений: 3985
  • 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 :: Nvidia 8500GT :: XFCE
SAMSUNG N150 :: Intel Atom N450 :: 2 GB RAM :: Intel GMA3150 :: XFCE

Оффлайн ReNzRv

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

m-svo,
Спасибо, похоже то что надо. Теперь задача как поправить этот скрипт чтобы получить список всех адресов...
Код: Python
  1. #!/usr/bin/env python
  2.  
  3. import sys
  4. import os
  5. #from blessings import Terminal
  6.  
  7. # Going to set up colors for a future project, not completed yet
  8. #term = Terminal()
  9.  
  10. # Get address string and CIDR string from command line
  11. xaddr = raw_input("IP address: ") # need to validate input of IP address
  12. xcidr = raw_input("CIDR notation, NO / mark!: ")
  13. addr = xaddr.split('.')
  14. cidr = int(xcidr)
  15.  
  16. # Initialize the netmask and calculate based on CIDR mask
  17. mask = [0, 0, 0, 0]
  18. for i in range(cidr):
  19.     mask[i/8] = mask[i/8] + (1 << (7 - i % 8))
  20.  
  21. # Initialize net and binary and netmask (net) with addr to get network
  22. net = []
  23. for i in range(4):
  24.     net.append(int(addr[i]) & mask[i])
  25.  
  26. # Duplicate net into broad array, gather host bits, and generate broadcast
  27. broad = list(net)
  28. brange = 32 - cidr
  29. for i in range(brange):
  30.     broad[3 - i/8] = broad[3 - i/8] + (1 << (i % 8))
  31.  
  32. # This gives you usable hosts for the given subnet
  33. xhost = 2 ** brange - 2
  34. host = "{:,}".format(xhost)
  35.  
  36. # Initialize o for wildcard mask (imask) with broadcast - net
  37. o = [0, 0, 0, 0]
  38. for i in range(4):
  39.         o[i] = broad[i] - net[i]
  40.  
  41. # This gives the wildcard mask for the given subnet    
  42. imask = []
  43. for i in range (4):
  44.         imask.append(int(o[i]) & broad[i])
  45.  
  46. # Print information, mapping integer lists to strings for easy printing
  47. print 'Here are your results:..............'
  48. print "Address: " , xaddr
  49. print "Netmask: " , ".".join(map(str, mask))
  50. print "Wildcard Mask: " , ".".join(map(str, imask))
  51. print "Network: " , ".".join(map(str, net))
  52. print "Usable IPs: " , host
  53. print "Broadcast: " , ".".join(map(str, broad))
  54.  
  55. raw_input("Press any key to exit...")
  56.  

Оффлайн The Green Side

  • Активист
  • *
  • Сообщений: 825
    • Просмотр профиля
А, вам развёрнутый список нужен.
Нашёл скрипт, переписал его на 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
  1. #!/usr/bin/env python3
  2. #Jeremy Galloway // root at cypherg dot com
  3.  
  4. from netaddr import IPNetwork
  5. import sys
  6.  
  7. if len(sys.argv) < 2:
  8.         print ('example usage: python cidrExpand.py cidrRanges.txt >> output.txt')
  9.  
  10. with open(sys.argv[1], 'r') as cidrRanges:
  11.         for line in cidrRanges:
  12.                 ip = IPNetwork(line)
  13.                 for ip in ip:
  14.                         print (ip)
  15.  

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

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2627
    • Просмотр профиля
m-svo,
Спс, я уже тоже нашел скрипт, только без установки модуля и 3 питона:
Код: Python
  1. #!/usr/bin/env python
  2.  
  3. import sys, struct, socket
  4.  
  5. (ip, cidr) = sys.argv[1].split('/')
  6. cidr = int(cidr)
  7. host_bits = 32 - cidr
  8. i = struct.unpack('>I', socket.inet_aton(ip))[0] # note the endianness
  9. start = (i >> host_bits) << host_bits # clear the host bits
  10. end = start | ((1 << host_bits) - 1)
  11.  
  12. # excludes the first and last address in the subnet
  13. for i in range(start, end):
  14.     print(socket.inet_ntoa(struct.pack('>I',i)))
  15.  
Все ок, кроме одного: Последний адрес на один меньше, т.е. 254 а не 255


Пользователь добавил сообщение 01 Февраль 2020, 21:05:45:
Исправил:
Код: Python
  1. #!/usr/bin/env python
  2.  
  3. import sys, struct, socket
  4.  
  5. (ip, cidr) = sys.argv[1].split('/')
  6. cidr = int(cidr)
  7. host_bits = 32 - cidr
  8. i = struct.unpack('>I', socket.inet_aton(ip))[0] # note the endianness
  9. start = (i >> host_bits) << host_bits # clear the host bits
  10. end = start | (1 << host_bits)
  11.  
  12. # excludes the first and last address in the subnet
  13. for i in range(start, end):
  14.     print(socket.inet_ntoa(struct.pack('>I',i)))
  15.  
« Последнее редактирование: 01 Февраль 2020, 21:05:45 от ReNzRv »

Оффлайн The Green Side

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

Оффлайн ReNzRv

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

 

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