first commit
This commit is contained in:
84
.venv/lib/python3.12/site-packages/hetzner/util/addr.py
Normal file
84
.venv/lib/python3.12/site-packages/hetzner/util/addr.py
Normal file
@@ -0,0 +1,84 @@
|
||||
import socket
|
||||
import struct
|
||||
|
||||
|
||||
def parse_ipv4(addr):
|
||||
"""
|
||||
Return a numeric representation of the given IPv4 address.
|
||||
"""
|
||||
binary_ip = socket.inet_pton(socket.AF_INET, addr)
|
||||
return struct.unpack('!L', binary_ip)[0]
|
||||
|
||||
|
||||
def parse_ipv6(addr):
|
||||
"""
|
||||
Return a numeric representation of the given IPv6 address.
|
||||
"""
|
||||
binary_ip = socket.inet_pton(socket.AF_INET6, addr)
|
||||
high, low = struct.unpack('!QQ', binary_ip)
|
||||
return high << 64 | low
|
||||
|
||||
|
||||
def parse_ipaddr(addr, is_ipv6=None):
|
||||
"""
|
||||
Parse IP address and return a tuple consisting of a boolean indicating
|
||||
whether the given address is an IPv6 address and the numeric representation
|
||||
of the address.
|
||||
|
||||
If is_ipv6 is either True or False, the specific address type is enforced
|
||||
and only the parsed address is returned instead of a tuple.
|
||||
"""
|
||||
if is_ipv6 is None:
|
||||
try:
|
||||
return False, parse_ipv4(addr)
|
||||
except socket.error:
|
||||
return True, parse_ipv6(addr)
|
||||
elif is_ipv6:
|
||||
return parse_ipv6(addr)
|
||||
else:
|
||||
return parse_ipv4(addr)
|
||||
|
||||
|
||||
def get_ipv4_range(numeric_netaddr, prefix_len):
|
||||
"""
|
||||
Return the smallest and biggest possible IPv4 address of the specified
|
||||
network address (in numeric representation) and prefix length.
|
||||
"""
|
||||
mask_inverted = 32 - prefix_len
|
||||
mask_bin = 0xffffffff >> mask_inverted << mask_inverted
|
||||
range_start = numeric_netaddr & mask_bin
|
||||
range_end = range_start | (1 << mask_inverted) - 1
|
||||
return range_start, range_end
|
||||
|
||||
|
||||
def get_ipv6_range(numeric_netaddr, prefix_len):
|
||||
"""
|
||||
Return the smallest and biggest possible IPv6 address of the specified
|
||||
network address (in numeric representation) and prefix length.
|
||||
"""
|
||||
mask_bin_full = 0xffffffffffffffffffffffffffffffff
|
||||
mask_inverted = 128 - prefix_len
|
||||
mask_bin = mask_bin_full >> mask_inverted << mask_inverted
|
||||
range_start = numeric_netaddr & mask_bin
|
||||
range_end = range_start | (1 << mask_inverted) - 1
|
||||
return range_start, range_end
|
||||
|
||||
|
||||
def ipv4_bin2addr(numeric_addr):
|
||||
"""
|
||||
Convert a numeric representation of the given IPv4 address into quad-dotted
|
||||
notation.
|
||||
"""
|
||||
packed = struct.pack('!L', numeric_addr)
|
||||
return socket.inet_ntop(socket.AF_INET, packed)
|
||||
|
||||
|
||||
def ipv6_bin2addr(numeric_addr):
|
||||
"""
|
||||
Convert a numeric representation of the given IPv6 address into a shortened
|
||||
hexadecimal notiation separated by colons.
|
||||
"""
|
||||
high = numeric_addr >> 64
|
||||
low = numeric_addr & 0xffffffffffffffff
|
||||
packed = struct.pack('!QQ', high, low)
|
||||
return socket.inet_ntop(socket.AF_INET6, packed)
|
||||
Reference in New Issue
Block a user