Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get subnet from IP address

I am trying to get subnet for IP address I have.

Eg :

1

Subnet mask : 255.255.255.0

Input : 192.178.2.55

Output : 192.178.2.0

2

Subnet mask : 255.255.0.0

Input : 192.178.2.55

Output : 192.178.0.0

Currently, the way I do it (for subnet 255.255.255.0)

ip =  '192.178.2.55'
subnet = '.'.join(ip.split('.')[:2]) + '.0.0'
subnet
'192.178.0.0'

I see python has ipaddress library. However I could not find a method that could do the above task.

Bonus : Since ipaddress supports IPv4 and IPv6, if the same function could be used for both.

like image 890
Spandan Brahmbhatt Avatar asked Jun 14 '18 23:06

Spandan Brahmbhatt


People also ask

Can I find subnet from IP address?

To calculate the IP Address Subnet you need to perform a bit-wise AND operation (1+1=1, 1+0 or 0+1 =0, 0+0=0) on the host IP address and subnet mask. The result is the subnet address in which the host is situated.

How do I find the number of subnets from an IP address?

To calculate the number of possible subnets, use the formula 2n, where n equals the number of host bits borrowed. For example, if three host bits are borrowed, then n=3. 23 = 8, so eight subnets are possible if three host bits are borrowed.

What is the subnet of my IP address?

Go to System Preferences > Network. Select your network and click Advanced. Click on TCP/IP tab and you will find your IP address along with the subnet mask.


2 Answers

The ipaddress.ip_network function can take any of the string formats that IPv4Network and IPv6Network can take, including the address/mask format.

Since you're not actually passing the network address, but an address within that network with host bits set, you need to use strict=False.

So:

>>> net = ipaddress.ip_network('192.178.2.55/255.255.255.0', strict=False)
>>> net
IPv4Network('192.178.2.0/24')
>>> net.network_address
IPv4Address('192.178.2.0')
>>> net.netmask
IPv4Address('255.255.255.0')

Alternatively, you can use ip_interface and extract the network from there:

>>> iface = ipaddress.ip_interface('192.178.2.55/255.255.255.0')
>>> iface
IPv4Interface('192.178.2.55/24')
>>> iface.network
IPv4Network('192.178.2.0/24')
>>> iface.netmask
IPv4Address('255.255.255.0')
>>> iface.ip
IPv4Address('192.178.2.55')
>>> iface.network.network_address
IPv4Address('192.178.2.0')

Which of the two you want depends on what exactly you're trying to represent. Notice that the Interface types are subclasses of the Address types, and of course they remember the original address that was used to construct them, while the Network classes remember the network address; one of those two is usually the deciding factor.

Both of them will, of course, work just as well with IPv6:

>>> ipaddress.ip_interface('2001:db8::1000/32')
IPv6Interface('2001:db8::1000/32')
>>> ipaddress.ip_interface('2001:db8::1000/32').network.network_address
IPv6Address('2001:db8::')
like image 86
abarnert Avatar answered Nov 02 '22 19:11

abarnert


subnet is simply a binary mask that must be and'ed bitwise with the IP address. You can apply the mask yourself:

".".join(map(str, [i & m # Apply the mask
          for i,m in zip(map(int, ip.split(".")),
                         map(int, subnet.split(".")))]))
#'192.178.2.0'

This solution works only for IPv4 addresses.

like image 45
DYZ Avatar answered Nov 02 '22 19:11

DYZ