Skip to content

Instantly share code, notes, and snippets.

@ISSOtm
Created October 9, 2020 21:49
Show Gist options
  • Save ISSOtm/f8228d69c4c59808ad1bb90669fc9456 to your computer and use it in GitHub Desktop.
Save ISSOtm/f8228d69c4c59808ad1bb90669fc9456 to your computer and use it in GitHub Desktop.
Python script to print info about an IPv4 subnet mask
#!/usr/bin/env python3
import itertools
import sys
if len(sys.argv) < 2:
print(f"Usage: {argv[0]} <subnet mask>\n\tSubnet mask must be in dotted decimal form.", file=sys.stderr)
exit(1)
subnet_mask = sys.argv[1]
# Perform some light validation
# FIXME: the decimal format of each component is *not* checked, so some invalid input may be accepted
components = subnet_mask.split(".")
if len(components) != 4:
print(f"Error: Subnet mask {subnet_mask} is not an IP in dotted decimal form", file=sys.stderr)
exit(1)
# Now, parse the IP components into a 32-bit mask
# Integers are much easier to process than strings...
def ip_component_to_mask(pair):
position,component = pair
try:
component = int(component)
if component < 0 or component > 255:
raise ValueError()
except ValueError:
print("Error: An IP in dotted decimal form must have all components as integers between 0 and 255", file=sys.stderr)
exit(1)
return component << ((3 - position) * 8)
mask = sum(map(ip_component_to_mask, enumerate(components)))
# Now, generate the output
bin_repr = bin(mask)[2:].rjust(32, '0') # Make sure string contains all 32 bits; though, if it doesn't, you probably have a problem.
bin_components = [ bin_repr[i:i+8] for i in range(0,32,8) ]
# Check if the mask is continuous, by looking for the first unset bit, and then for any set bits after that
try:
mask_len = bin_repr.index('0')
# This will throw an exception if either no unsed bit is found, or no set bits follow the first unset one.
# Both of which imply a continuous mask, though the former is invalid. (Not that *we* care, though!)
bin_repr[mask_len:].index('1')
mask_len = -1 # Mark mask as not continuous
except ValueError:
pass
print(f"For given subnet mask {subnet_mask} the following is true:")
if mask_len != -1:
print(f"The subnet can be written as /{mask_len}")
else:
print(f"The subnet cannot be written using a length suffix")
print(f"The raw subnet mask in hex format is {hex(mask)}")
print(f"The binary form of this subnet mask is {bin_components}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment