Initial commit
This commit is contained in:
commit
12f27bb122
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*~
|
11
README.md
Normal file
11
README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# compressIPv4
|
||||||
|
|
||||||
|
IPv4 addresses are typically written down as octets, e.g. `127.0.0.1`.
|
||||||
|
However the addresses seem to be actually interpreted as one large number (after conversion into binary).
|
||||||
|
This allows for funny things, like to call `http://0x7f000001:9000` to open a HTTP service on your local host, listenting on port 9000.
|
||||||
|
|
||||||
|
This repo holds a shiny tool to do the converstion for you.
|
||||||
|
It's inspired by [a blog post from 2021](https://daniel.haxx.se/blog/2021/04/19/curl-those-funny-ipv4-addresses) by the [curl CEO](https://mastodon.social/@bagder/113979166039412014).
|
||||||
|
<!--
|
||||||
|
vim:syntax=markdown:fileencoding=utf-8:ts=4:expandtab:linebreak:wrap
|
||||||
|
-->
|
92
compressIPv4.py
Executable file
92
compressIPv4.py
Executable file
@ -0,0 +1,92 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
# Nils Freydank <nils.freydan@datenschutz-ist-voll-doof.de>, 2025
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
__version__: str = "1.0.0"
|
||||||
|
__author__: str = "Nils Freydank <nils.freydank@datenschutz-ist-voll-doof.de>"
|
||||||
|
__copyright__: str = "MIT"
|
||||||
|
|
||||||
|
|
||||||
|
def get_compressed_v4(addr_v4: str, hex_out: bool = False) -> Union[int, str]:
|
||||||
|
"""
|
||||||
|
Read the canonical IPv4 address and compress it into a single number.
|
||||||
|
|
||||||
|
:param addr_v4: String containing the IPv4 address in dotted notation.
|
||||||
|
:param hex_out: Opt. control if the output should be hex instead of int.
|
||||||
|
:return: Integer with the compressed, decimal "IPv4 addr" - or hex string.
|
||||||
|
Return -1 or "-0x1" for invalid addresses.
|
||||||
|
|
||||||
|
Note: Function may explode in funny ways due to missed input checks.
|
||||||
|
"""
|
||||||
|
LEN_BIN_BLOCK_MAX: int = 8 # i.e. len(str(bin(255)).replace("0b", ""))
|
||||||
|
MAX_ADDR_POSSIBLE: int = 2**32 - 1 # full 32bit, i.e. 255.255.255.255
|
||||||
|
compressed_addr: str = ""
|
||||||
|
try:
|
||||||
|
blocks: list[str] = addr_v4.split(".")
|
||||||
|
bin_addr: str = ""
|
||||||
|
for block in blocks:
|
||||||
|
bin_block: str = str(bin(int(block))).replace("0b", "")
|
||||||
|
# Make sure to align each block properly to 8 bit.
|
||||||
|
len_delta: int = LEN_BIN_BLOCK_MAX - len(bin_block)
|
||||||
|
bin_addr = bin_addr + len_delta * "0" + bin_block
|
||||||
|
# Nice try. Put a valid IPv4 address inside, next time.
|
||||||
|
if (compressed_addr := int(bin_addr, 2)) > MAX_ADDR_POSSIBLE:
|
||||||
|
compressed_addr = -1
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
print("Something broke, maybe an invalid address?")
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
return hex(compressed_addr) if hex_out else compressed_addr
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# First, run some checks.
|
||||||
|
assert get_compressed_v4("0.0.0.1") == 1
|
||||||
|
assert get_compressed_v4("0.0.0.1", False) == 1
|
||||||
|
assert get_compressed_v4("0.0.0.1", True) == "0x1"
|
||||||
|
|
||||||
|
assert get_compressed_v4("0") == 0
|
||||||
|
assert get_compressed_v4("0", False) == 0
|
||||||
|
assert get_compressed_v4("0", True) == "0x0"
|
||||||
|
|
||||||
|
assert get_compressed_v4("256.0.0.0") == -1
|
||||||
|
assert get_compressed_v4("256.0.0.0", False) == -1
|
||||||
|
assert get_compressed_v4("256.0.0.0", True) == "-0x1"
|
||||||
|
|
||||||
|
assert get_compressed_v4("255.255.255.255") == 2**32 - 1
|
||||||
|
assert get_compressed_v4("255.255.255.255", False) == 2**32 - 1
|
||||||
|
assert get_compressed_v4("255.255.255.255", True) == hex(2**32 - 1)
|
||||||
|
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
|
parser = ArgumentParser()
|
||||||
|
parser.add_argument("ip_v4_address", help="IPv4 address that shall be compressed")
|
||||||
|
parser.add_argument(
|
||||||
|
"--hex", dest="hex", help="convert into hexadecimal", action="store_true"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--quiet",
|
||||||
|
dest="quiet",
|
||||||
|
help="be quiet do not print the greeter",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
out_hex: bool = True if args.hex else False
|
||||||
|
|
||||||
|
if not args.quiet:
|
||||||
|
# Greet the user.
|
||||||
|
print("~" * 65)
|
||||||
|
print(f" v4 address fun, v{__version__}.")
|
||||||
|
print(f" by {__author__}")
|
||||||
|
print(f" use according to {__copyright__} license instructions")
|
||||||
|
print("~" * 65)
|
||||||
|
|
||||||
|
if args.ip_v4_address:
|
||||||
|
print(get_compressed_v4(args.ip_v4_address, out_hex))
|
||||||
|
|
||||||
|
# vim:syntax=python:fileencoding=utf-8:ts=4:expandtab:linebreak:wrap
|
Loading…
x
Reference in New Issue
Block a user