Question

Let's say I have a text file contains a bunch of ip ranges like this:

x.x.x.x-y.y.y.y
x.x.x.x-y.y.y.y
x.x.x.x-y.y.y.y
x.x.x.x-y.y.y.y
x.x.x.x-y.y.y.y

x.x.x.x is start value and y.y.y.y is end value of range.

How can I convert these ip ranges to all possible IPs in a new text file in python?

PS: This question is not same as any of my previous questions. I asked "how to generate all possible ips from cidr notations" in my previous question. But in here I ask "how to generate from ip range list". These are different things.

Was it helpful?

Solution

This function returns all ip addresses like from start to end:

def ips(start, end):
    import socket, struct
    start = struct.unpack('>I', socket.inet_aton(start))[0]
    end = struct.unpack('>I', socket.inet_aton(end))[0]
    return [socket.inet_ntoa(struct.pack('>I', i)) for i in range(start, end)]

These are the building blocks to build it on your own:

>>> import socket, struct
>>> ip = '0.0.0.5'
>>> i = struct.unpack('>I', socket.inet_aton(ip))[0]
>>> i
5
>>> i += 1
>>> socket.inet_ntoa(struct.pack('>I', i))
'0.0.0.6'

Example:

ips('1.2.3.4', '1.2.4.5')
['1.2.3.4', '1.2.3.5', '1.2.3.6', '1.2.3.7', ..., '1.2.3.253', '1.2.3.254', '1.2.3.255', '1.2.4.0', '1.2.4.1', '1.2.4.2', '1.2.4.3', '1.2.4.4']

Read from file

In your case you can read from a file like this:

with open('file') as f:
    for line in f:
        start, end = line.strip().split('-')
        # ....

OTHER TIPS

Python 3 only, for IPv4, same idea with @User but use new Python3 standard library: ipaddress

IPv4 is represented by 4 bytes. So next IP is actually next number, a range of IPs can be represented as a range of integer numbers.

0.0.0.1 is 1

0.0.0.2 is 2

...

0.0.0.255 is 255

0.0.1.0 is 256

0.0.1.1 is 257

By code (ignore the In []: and Out []:)

In [68]: from ipaddress import ip_address

In [69]: ip_address('0.0.0.1')
Out[69]: IPv4Address('0.0.0.1')

In [70]: ip_address('0.0.0.1').packed
Out[70]: b'\x00\x00\x00\x01'

In [71]: int(ip_address('0.0.0.1').packed.hex(), 16)
Out[71]: 1

In [72]: int(ip_address('0.0.1.0').packed.hex(), 16)
Out[72]: 256

In [73]: int(ip_address('0.0.1.1').packed.hex(), 16)
Out[73]: 257

ip.packed.hex() returns the hexadecimal form of 4 bytes, as it is in hexadecimal, it is shorter (e.g: 0xff hex == 255 decimal == 0b11111111 binary), and thus, often used for representing bytes. int(hex, 16) returns integer value corresponding to the hex value as it is more human friendly, and can be used as input for ip_address.

from ipaddress import ip_address

def ips(start, end):
    '''Return IPs in IPv4 range, inclusive.'''
    start_int = int(ip_address(start).packed.hex(), 16)
    end_int = int(ip_address(end).packed.hex(), 16)
    return [ip_address(ip).exploded for ip in range(start_int, end_int)]


ips('192.168.1.240', '192.168.2.5')

Returns:

['192.168.1.240',
 '192.168.1.241',
 '192.168.1.242',
 '192.168.1.243',
 '192.168.1.244',
 '192.168.1.245',
 '192.168.1.246',
 '192.168.1.247',
 '192.168.1.248',
 '192.168.1.249',
 '192.168.1.250',
 '192.168.1.251',
 '192.168.1.252',
 '192.168.1.253',
 '192.168.1.254',
 '192.168.1.255',
 '192.168.2.0',
 '192.168.2.1',
 '192.168.2.2',
 '192.168.2.3',
 '192.168.2.4']

try This:

def ip_range(start_ip,end_ip):
start = list(map(int,start_ip.split('.')))
end = list(map(int,end_ip.split('.')))
iprange=[]
while start!=list(map(int,end_ip.split('.'))):
    for i in range(len(start)-1,-1,-1):
        if start[i]<255:
            start[i]+=1
            break
        else:
            start[i]=0
    iprange.append('.'.join(map(str,start)))
return iprange

Use ipaddress and range()

import ipaddress

print([ipaddress.ip_address(i).exploded for i in range(int(ipaddress.ip_address(first_ip)), int(ipaddress.ip_address(last_ip)))])
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top