2016-12-29 52 views
1

我想知道如何創建一個腳本,需要一個CIDR標記像該子網的所有IP:計算使用Python 2.7內置的模塊只

204.15.20.0/22 

,並計算在該範圍內的所有可能的IP地址。

204.15.20.0 
... 
... 
204.15.23.255 

現在我終於知道這背後的數學,我不知道我怎麼會做出這樣的Python模塊。

我所知道的現成可用的模塊,如netaddr.IPNetwork(),但我不知道我會怎麼做,只使用內置模塊在Python 2.7

謝謝:)

+0

您可以將該地址更改爲一個整數,並從那裏使用'range'。 – tdelaney

+0

我不認爲這就是它的工作原理,因爲一個八位字節只能有255的最大值(b11111111) – Snowlav

+0

@UrielEli不是重複的,我知道它在我的OP中所說的背後的數學。我想知道如何在Python中使用內置模塊來完成它。 – Snowlav

回答

3

您可以使用socketstruct模塊的組合在IPv4地址和整數之間進行轉換。之後,它會掩蓋整數地址,並從cidr值中找出子網中值的範圍。

import re 
import socket 
import struct 

def inet_atoi(ipv4_str): 
    """Convert dotted ipv4 string to int""" 
    # note: use socket for packed binary then struct to unpack 
    return struct.unpack("!I", socket.inet_aton(ipv4_str))[0] 

def inet_itoa(ipv4_int): 
    """Convert int to dotted ipv4 string""" 
    # note: use struct to pack then socket to string 
    return socket.inet_ntoa(struct.pack("!I", ipv4_int)) 

def ipv4_range(ipaddr): 
    """Return a list of IPv4 address contianed in a cidr address range""" 
    # split out for example 192.168.1.1:22/24 
    ipv4_str, port_str, cidr_str = re.match(
     r'([\d\.]+)(:\d+)?(/\d+)?', ipaddr).groups() 

    # convert as needed 
    ipv4_int = inet_atoi(ipv4_str) 
    port_str = port_str or '' 
    cidr_str = cidr_str or '' 
    cidr_int = int(cidr_str[1:]) if cidr_str else 0 

    # mask ipv4 
    ipv4_base = ipv4_int & (0xffffffff << (32 - cidr_int)) 

    # generate list 
    addrs = [inet_itoa(ipv4_base + val) 
     for val in range(1 << (32 - cidr_int) + 2)] 
    return addrs 

print(ipv4_range('204.15.20.0/22'))