Python 3: create a list of possible ip addresses from a CIDR notation
Asked Answered
I

7

35

I have been handed the task of creating a function in python (3.1) that will take a CIDR notation and return the list of possible ip addresses. I have looked around python.org and found this: http://docs.python.org/dev/py3k/library/ipaddr.html

but i haven't seen anything that will fill this need... I would be very grateful for any assistance anyone cares to kick my way. thanks in advance. :-)

Irreligion answered 21/12, 2009 at 19:39 Comment(4)
Might want to go back and accept some answers to your questions if they were helpful...Southerland
I have used IPy (c0re.23.nu/c0de/IPy) on Python 2.x, and now am in the process of porting it to Python 3. I will post a link as an answer once I am done.Cepeda
@AJ: IPy is also a good choice, but I recommended netaddr because I like it better. :)Acervate
Update: I have submitted a new version of IPy to its current maintainer for review. Given the holidays, I'm not sure when this will be released, but I will post a link once it is.Cepeda
A
81

In Python 3 as simple as

>>> import ipaddress
>>> [str(ip) for ip in ipaddress.IPv4Network('192.0.2.0/28')]
['192.0.2.0', '192.0.2.1', '192.0.2.2',
'192.0.2.3', '192.0.2.4', '192.0.2.5',
'192.0.2.6', '192.0.2.7', '192.0.2.8',
'192.0.2.9', '192.0.2.10', '192.0.2.11',
'192.0.2.12', '192.0.2.13', '192.0.2.14',
'192.0.2.15']
Allsopp answered 6/12, 2018 at 9:37 Comment(3)
this works directly on the python3 terminal but how about in a .py file??Palatinate
@Palatinate The first two lines of this answer can go into a .py file, minus the >>> at the head of each line. In the second line, you should assign the list to a variable which you can then view or do other operations on. If you put [str(ip) for ip in ipaddress.IPv4Network('192.0.2.0/28')] as-is into a file and then run it, there will be no output. But assign it to a variable like ip_list = [str(ip) for ip in ipaddress.IPv4Network('192.0.2.0/28')], then you can print(ip_list) for example to see the list.Globin
Please note that this answer provides a list of addresses which include both the network address (192.0.2.0) and the broadcast address (192.0.2.15) which are not usable for assigning to a host. This is correct behavior for Python, but could lead to confusion with other stakeholders if they are not familiar with networking.Planking
A
51

If you aren't married to using the built-in module, there is a project called netaddr that is the best module I have used for working with IP networks.

Have a look at the IP Tutorial which illustrates how easy it is working with networks and discerning their IPs. Simple example:

>>> from netaddr import IPNetwork
>>> for ip in IPNetwork('192.0.2.0/23'):
...    print '%s' % ip
...
192.0.2.0
192.0.2.1
192.0.2.2
192.0.2.3
...
192.0.3.252
192.0.3.253
192.0.3.254
192.0.3.255
Acervate answered 21/12, 2009 at 21:50 Comment(1)
interesting but how is the mapping done? is there a deterministic formula that maps the CIDR networks to the single IP addresses? Or one needs a database to do the mapping?Stereoscopic
P
14

I would prefer to do a little math rather than to install an external module, no one has the same taste with me?

#!/usr/bin/env python
# python cidr.py 192.168.1.1/24

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)))
Payment answered 18/5, 2017 at 9:12 Comment(3)
Note that this excludes the broadcast address, which may or may not be what you want. Remove the -1 when computing "end" to include it.Canoodle
@Peter, removing the -1 only works on even IP addresses (e.g. where the 4th octet ends in an even number). Add end += 1 as the line just after subtracting 1.Hatty
@jfky could you please explain this math?Purposeless
T
3

Have you checked out iptools? It seems to be a fairly good fit.

Twinkle answered 21/12, 2009 at 19:43 Comment(2)
Given that it seems to not support Python 2.3, it would probably require at least a nominal amount of effort to support Python 3.1.Millen
I've updated iptools to support Python 2.3, 2.5, 2.6 and 3.1.Fingerling
J
2

We can get this by using ipaddress lib of Python if you are not interested in playing with python logics. Else above solutions are enough.

import ipaddress
  
def get_ip_from_subnet(ip_subnet):

    ips= ipaddress.ip_network(ip_subnet)
    ip_list=[str(ip) for ip in ips]
    return ip_list

ip_subnet= "192.168.2.0/24"
print(get_ip_from_subnet(ip_subnet))
Juliettejulina answered 17/6, 2021 at 13:12 Comment(0)
M
1

It's not in the documentation, but browsing the source suggests that ipaddr implements __iter__ and iterhosts, which is exactly what you want.


Err, nevermind.

  1. It looks like ipaddr.py was added to stdlib in 3.1 beta, but removed by 3.1 rc.
  2. I was looking at the sources from the original ipaddr.py, which seems to have evolved separately from the copy at python.org.

You could just bundle the latter.

Millen answered 21/12, 2009 at 20:6 Comment(0)
G
0

Below code will generate range of IPs on providing IP and subnet. Expand the CIDR notation like(255.255.255.0)

from netaddr import *

def getFirstIp(ipAddress,subnet):
  ipBin = IPNetwork(ipAddress).ip.bits().split('.')
  subBin = IPNetwork(subnet).ip.bits().split('.')
  zipped = zip(ipBin,subBin)
  netIdList = []
  for octets in zipped:
    netIdList.append(''.join(str(b) for b in (map((lambda x: int(x[0])*int(x[1])),zip(list(octets[0]),list(octets[1]))))))
  firstIp = ''
  firstIp = '.'.join(str(int(oct,2)) for oct in netIdList)
  return firstIp


def getLastIp(ipAddress,subnet):
  ipBin = IPNetwork(ipAddress).ip.bits().split('.')
  subBin = IPNetwork(subnet).ip.bits().split('.')
  #print ipBin
  #print subBin
  revsubBin = []
  for octets in subBin:
    revB = ''.join('1' if(b == '0') else '0' for b in octets)
    revsubBin.append(revB)
  zipped = zip(ipBin,revsubBin)
  netIdList = []
  for octets in zipped:
    netIdList.append(''.join(str(b) for b in (map((lambda x: 0 if(int(x[0]) == 0 and int(x[1]) == 0) else 1),zip(list(octets[0]),list(octets[1]))))))
  #print netIdList
  lastIp = ''
  lastIp = '.'.join(str(int(oct,2)) for oct in netIdList)
  return lastIp

def getRangeOfIps(firstIp,lastIp):
  start= int(IPAddress(firstIp))
  end = int(IPAddress(lastIp))
  ipList = []
  for ip in range(start,end+1):
    ipList.append(str(IPAddress(ip)))
  return ipList

def manipulateIP():
 firstIp = getFirstIp(ipAddress,subnet)
 lastIp = getLastIp(ipAddress,subnet)
 ipList = getRangeOfIps(firstIp,lastIp)  
 print ipList 
Gerik answered 23/9, 2016 at 6:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.