2016-12-29 41 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'))