1

I'm trying to check if the user is trying to assign a reserved address. At the moment we are reserving the first 5 and the last 5 addresses for future use. The way I do it atm is really slow and wont work effectively in case of ipv6 switch. Is there any other way to optimize the check?

def verify_ip_subnet(ip_address, subnet_address):
    new_subnet = subnet_address.split('/')[1].strip()
    if int(new_subnet) == 16:
        new_vpn_range = []
        new_vpn_range.append(subnet_address.split('/')[0].strip())
        new_count = 0
        for address in ipaddress.ip_network(subnet_address).hosts():
            if new_count == 0 or new_count == 1 or new_count == 2 or new_count == 3 or new_count == 4 or new_count == 65531 or new_count == 65532 or new_count == 65533:
                new_vpn_range.append(str(address))
                new_count += 1
        if ip_address in new_vpn_range:
            return False
    if int(new_subnet) == 24:
        new_vpn_range = []
        new_vpn_range.append(subnet_address.split('/')[0].strip())
        new_count = 0
        for address in ipaddress.ip_network(subnet_address).hosts():
            if new_count == 0 or new_count == 1 or new_count == 2 or new_count == 3 or new_count == 4 or new_count == 251 or new_count == 252 or new_count == 253:
                new_vpn_range.append(str(address))
                new_count += 1
            if ip_address in new_vpn_range:
                return False

Here is an example of the import:

ip_address = '10.8.0.5'
subnet_address = '10.8.0.0/16'

The other way is to use num_addresses in this case I am able to check for the first 5 reserved ones, however if I try to check for the last 5 the index goes out of range. Here is an example how I check them:

ip_check = ipaddress.ip_network(subnet_address)
for i in range(6):
    if str(ip_check[i]) == ip_address:
        return False

last_address = ip_check.num_addresses
print(last_address)
print(ip_check[last_address])
yasa
  • 126
  • 7

1 Answers1

1

If you want to know if the IP is reserved for other general purposes you can use ipaddress.ip_address that has a Boolean attribute (is_reserved) to know if an ip is reserved for IPv4 and IPv6:

# Changing your variable name to avoid confusion with module function
>>> from ipaddress import ip_address, ip_network
>>> ip = ip_address('10.8.0.5')
>>> ip.is_reserved
True
>>> ip_v6 = ip_address('10.8.0.5')
>>> ip_v6.is_reserved
True
>>> subnet = ip_network('10.8.0.0/16')
>>> ip in subnet
True

There are many other attributes as is_private,is_global,is_loopback...

As you want to specify the first and last five you could use the same code that you used but the error was in the last line as index starts at 0.

I modified to use the ip_address function instead:

>>> from ipaddress import ip_address, ip_network
>>> # Range of reserved IPs from the beginning and end of the IP network
>>> RESERVED_RANGE = 6
>>> ip = ip_address('10.8.0.4')
>>> subnet = ip_network('10.8.0.0/16')
>>> 
>>> for i in range(RESERVED_RANGE):
>>>     print(i, subnet[i], end=", ")
>>>     # To only have on iteration for first and last 
>>>     # I'm using "~" a bitwise operator that returns the complement of i
>>>     # You can see on the printed output below how it works
>>>     print(~i, subnet[~i])
>>>     if ip == subnet[i] or ip == subnet[~i]:        
>>>         break
>>> 
>>> num_address = subnet.num_addresses
>>> print("Number of address", num_address)
>>> print("Last IP in subnet", subnet[num_address - 1])
0 10.8.0.0, -1 10.8.255.255
1 10.8.0.1, -2 10.8.255.254
2 10.8.0.2, -3 10.8.255.253
3 10.8.0.3, -4 10.8.255.252
4 10.8.0.4, -5 10.8.255.251
Number of address 65536
Last IP in subnet 10.8.255.255