1. Introduction

When we design a network, we always need to know how many addresses do we need in this network. Also, we would like to know the range of IP addresses in our network so that we can assign an address for each device in the network.

In this tutorial, we’re going to show a simple method to find the range of IP addresses given a subnet mask.

2. Problem Explanation

In IPv4, the IP address consists of 32 bits number. And we represent it by 4 octets (8-bits each). Usually, when we refer to a network, we also refer to a subnet. This subnet can be a number (for example /24), and we can write it like an IP address (example /255.255.255.0). From this subnet, we’d like to find out what are the IP addresses in this network.

For example, if we have a network 192.168.0.1/24 (or with subnet 255.255.255.0), then we have 256 usable addresses from 192.168.0.0 up to 192.168.0.255.

3. Algorithm Idea

In general, if we deal with the IP address as a 32-bit number, and we have a subnet mask of x, then the subnet mask theoretically can take values between [0, 32] . Then, we have two things to estimate, what are the number of possible addresses with the given subnet mask, and what is the starting address.

We can get the number of possible addresses easily by the following formula 2^{(32 - x)}. That means if we have a subnet mask of 0, then the possible addresses are 2^{32}. And if we have a subnet mask of 32, then the possible number of addresses is 2^0 = 1, which means the given address is the only possible address in this case. One more example the case of subnet mask of /24, we will have 2^{(32 - 24)} = 2^{8} = 256 addresses.

Then, we need to interpret this subnet mask in the octets form. If we have a subnetmask of /24, we are actually having a 32-bit number that has the left most 24-bits as ones and the rest are zeros:

subnet mask decimal

24

subnet mask binary

11111111111111111111111100000000

subnet mask decimal octets

255

255

255

0

subnet mask binary octets

11111111

11111111

11111111

00000000

From the previous table, we can see how the subnet mask can be interpreted. So, if we have an IP address like 192.168.0.10/24, we can write it down in a table to show the binary octets compared to:

IP address decimal octets

192

168

0

10

IP address binary octets

11000000

10101000

00000000

00001010

4. Subnet Starting Address

To find the starting address in the following subnet mask, we simply do binary “and” operation between the IP address and the subnet mask:

IP and subnet mask

192.168.0.10/24

IP address binary octets

11000000

10101000

00000000

00001010

subnet mask binary octets

11111111

11111111

11111111

00000000

First IP binary octets

11000000

10101000

00000000

00000000

First IP decimal octets

192

168

0

0

5. Subnet Last Address

Finally, we calculate the last IP address by applying the “or” operation on it with the bitwise binary inverse of the subnet mask to the first IP address:

IP and subnet mask

192.168.0.10/24

subnet mask binary octets

11111111

11111111

11111111

00000000

First IP binary octets

11000000

10101000

00000000

00000000

inverse subnet mask binary octets

00000000

00000000

00000000

11111111

Last IP binary octets

11000000

10101000

00000000

11111111

Last IP decimal octets

192

168

0

255

With these simple steps, we know how to find the number of possible IP addresses. We can also find the first and last IP addresses and the range becomes from 192.168.0.0 up to 192.168.0.255.

6. Examples

The same idea happens if we have a subnet mask that is not exactly at one of the octets. Let’s see and example of 192.168.0.10/30. By following the same idea we have 2^2 = 4 possible IP addresses:

192.168.0.10/30

decimal

binary

IP address

192.168.0.10

11000000.10101000.00000000.00001010

subnet mask

255.255.255.252

11111111.11111111.11111111.11111100

First IP

192.168.0.8

11000000.10101000.00000000.00001000

inverse subnet mask

0.0.0.3

00000000.00000000.00000000.00000011

Last IP

192.168.0.11

11000000.10101000.00000000.00001011

Let’s take one more example where the subnet mask is not in the last octet like 10.0.0.0/20. In this case we have 2^{(32 - 20)} = 2^{12} = 4096 possible IP address:

10.0.0.0/20

decimal

binary

IP address

10.0.0.0

00001010.00000000.00000000.00000000

subnet mask

255.255.240.0

11111111.11111111.11110000.00000000

First IP

10.0.0.0

00001010.00000000.00000000.00000000

inverse subnet mask

0.0.15.255

00000000.00000000.00001111.11111111

Last IP

10.0.15.255

00001010.00000000.00001111.11111111

Luckily, in most programming languages, we don’t need to convert between binary and decimal to do the binary operations. So, we can apply the binary operations directly on most countable numbers (like integers or chars). In other words, we can represent the IP address by a 32-bit number or using 4 digits 8-bits each (like characters or bytes).

7. IPv6

In IPv6, the same idea for the subnet is similar to the IPv4. But the difference is in the size of the address and the allowed range. The IPv6 address has 128 bits compared to 32 bits in IPv4. The address is represented in 8 segments compared to 4 octets in the IPv4. Each segment is 4 hex numbers taking range from 0 to FFFF compared to 8-bits per octet in IPv4 with the decimal range 0 to 255. The separation between blocks in IPv6 is a colon (:) compared to dot (.) used in IPv4.

In general, we can get the number of the available IP addresses the same way we did it in IPv4. So, if we have a subnet of size x, then we have 2^{128 - x} available IP addresses. And we can get the first one of them by applying bitwise and with a mask of size 128 bits, where the first x bits are ones and the rest are zeros. And we can get the last address by adding the first address to the inverse of the mask (128 bits with the first x bits as zeros and the rest are ones).

Let’s see an IPv6 example for 2001:124A:2000:1000:0000:0000:0000:0000/48. Notice that each segment is written as 4 hex digits which equal 16-binary bits. The number of addresses will be 2^{128 - 48} = 2^{80}:

hex

IP address

2001:124A:2000:1000:0000:0000:0000:0000

subnet mask

FFFF:FFFF:FFFF:0000:0000:0000:0000:0000

First IP

2001:124A:2000:0000:0000:0000:0000:0000

inverse subnet mask

0000:0000:0000:FFFF:FFFF:FFFF:FFFF:FFFF

Last IP

2001:124A:2000:FFFF:FFFF:FFFF:FFFF:FFFF

Notice that FFFF is equivalent to 16 ones 1111111111111111. Another note is that the IPv6 address can also take short forms by removing leading zeros in any segment.

Thus, we write our example first address:

2001:124A:2000:0:0:0:0:0

And another shortened form is to replace one of the sequences of empty segments (all zero segments) with a double colon. So, the other shortened form of this address becomes:

2001:124A:2000::

Note that the shortened version does not allow more than one time for omitting the zeros segments. So, if we have and address:

2001:124A:2000:0000:0000:1234:0000:0000

IP adress mask

The shortened version will be:

2001:124A:2000::1234:0:0

Or:

2001:124A:2000:0:0:1234::

In this shortened version, we can know how many zeros are removed because we know that we have 128 bits divided into 8 segments. Thus, we know how many segments are removed from the 8 and these are the zeros omitted.

8. Complexity

The time and space complexities of finding the range of IP addresses are O(1) because we just need to put the subnet mask in a formula to find the range.

9. Conclusion

In this article, we have explained a simple method to estimate the range of possible IP addresses from the subnet mask.