Created
October 9, 2020 21:49
-
-
Save ISSOtm/f8228d69c4c59808ad1bb90669fc9456 to your computer and use it in GitHub Desktop.
Python script to print info about an IPv4 subnet mask
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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