ipaddress module ValueError('%s has host bits set' % self)
Question:
I am trying to list valid hosts for given network range via Python3, ipaddress
module but I am getting ValueError ValueError('%s has host bits set' % self)
while trying to list all valid hosts.
>>> ip_range=input("Enter IP Range:")
Enter IP Range:192.168.56.101/16
>>> list(ipa.ip_network(ip_range).hosts())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.5/ipaddress.py", line 74, in ip_network
return IPv4Network(address, strict)
File "/usr/local/lib/python3.5/ipaddress.py", line 1536, in __init__
raise ValueError('%s has host bits set' % self)
ValueError: 192.168.56.101/16 has host bits set
Answers:
As stated in documentation:
A ValueError is raised if address does not represent a valid IPv4 or
IPv6 address, or if the network has host bits set.
The number after slash(16 in your case) means, number of bits reserved for subnet, so last 16 bits are your host bits. This method requires those bits as 0 (unset).
You have another option.
From the document mentioned above, we can see that:
If strict is True and host bits are set in the supplied address, then
ValueError is raised. Otherwise, the host bits are masked out to
determine the appropriate network address.
So, please try following again.
ip_range = '192.168.56.101/16'
list(ipaddress.ip_network(ip_range, False).hosts())
Two Solutions
Either you change your input or the code.
1: Changing the input
Above you mentioned your input being 192.168.56.101/16
. The 16
defines the host bits for this ip-range. Python wants you to clear them (set all those bits to 0). Your specified the ip as 192.168.56.101
, while telling there were 16
host bits. Python expected the last 16
bits to be 0
.
In binary the Ip looks like this: 11000000.10101000.00111000.01100101
. You need to clear the last 16 bits. It then looks like this: 11000000.10101000.0.0
(equal to 192.168.0.0
in decimal).
Concluding: You would need to change your input to 192.168.0.0/16
for it to properly work.
2: Changing the code
Looking at the Python Docs:
If strict is True and host bits are set in the supplied address, then
ValueError is raised. Otherwise, the host bits are masked out to
determine the appropriate network address.
So deactivate the strict mode by changing your code:
Change ip_network(target)
to ip_network(target, False)
.
Here you could technically input 192.168.56.101/16
.
References
- Similar question: python-port-scanner-will-not-accept-address-range
- A tool to convert Ips to binary
This answer is late, but I believe it is helpful!
The IP that you are trying to push actually "isn’t valid" and doesn’t match the prefix (/16).
Loading it with the "no strict" False
– will actually provide the network/prefix that should have been provided as an input.
Wanted to share another example to overcome a wrong input from the user’s side, using the netaddr
module
from netaddr import IPNetwork
f = IPNetwork("192.168.56.101/16")
network = list(f.subnet(16))[0]
print(network) <= from this point i would work with this variable
# -- output --
IPNetwork('192.168.0.0/16')
I am trying to list valid hosts for given network range via Python3, ipaddress
module but I am getting ValueError ValueError('%s has host bits set' % self)
while trying to list all valid hosts.
>>> ip_range=input("Enter IP Range:")
Enter IP Range:192.168.56.101/16
>>> list(ipa.ip_network(ip_range).hosts())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.5/ipaddress.py", line 74, in ip_network
return IPv4Network(address, strict)
File "/usr/local/lib/python3.5/ipaddress.py", line 1536, in __init__
raise ValueError('%s has host bits set' % self)
ValueError: 192.168.56.101/16 has host bits set
As stated in documentation:
A ValueError is raised if address does not represent a valid IPv4 or
IPv6 address, or if the network has host bits set.
The number after slash(16 in your case) means, number of bits reserved for subnet, so last 16 bits are your host bits. This method requires those bits as 0 (unset).
You have another option.
From the document mentioned above, we can see that:
If strict is True and host bits are set in the supplied address, then
ValueError is raised. Otherwise, the host bits are masked out to
determine the appropriate network address.
So, please try following again.
ip_range = '192.168.56.101/16'
list(ipaddress.ip_network(ip_range, False).hosts())
Two Solutions
Either you change your input or the code.
1: Changing the input
Above you mentioned your input being 192.168.56.101/16
. The 16
defines the host bits for this ip-range. Python wants you to clear them (set all those bits to 0). Your specified the ip as 192.168.56.101
, while telling there were 16
host bits. Python expected the last 16
bits to be 0
.
In binary the Ip looks like this: 11000000.10101000.00111000.01100101
. You need to clear the last 16 bits. It then looks like this: 11000000.10101000.0.0
(equal to 192.168.0.0
in decimal).
Concluding: You would need to change your input to 192.168.0.0/16
for it to properly work.
2: Changing the code
Looking at the Python Docs:
If strict is True and host bits are set in the supplied address, then
ValueError is raised. Otherwise, the host bits are masked out to
determine the appropriate network address.
So deactivate the strict mode by changing your code:
Change ip_network(target)
to ip_network(target, False)
.
Here you could technically input 192.168.56.101/16
.
References
- Similar question: python-port-scanner-will-not-accept-address-range
- A tool to convert Ips to binary
This answer is late, but I believe it is helpful!
The IP that you are trying to push actually "isn’t valid" and doesn’t match the prefix (/16).
Loading it with the "no strict" False
– will actually provide the network/prefix that should have been provided as an input.
Wanted to share another example to overcome a wrong input from the user’s side, using the netaddr
module
from netaddr import IPNetwork
f = IPNetwork("192.168.56.101/16")
network = list(f.subnet(16))[0]
print(network) <= from this point i would work with this variable
# -- output --
IPNetwork('192.168.0.0/16')