Files
Nirodan 7827cda224 Add targeted comments for non-obvious constraints and invariants
- logger.py: note why log path uses abspath(__file__) instead of a relative path
- token.py: note why [7:] slice is safe (startswith already verified)
- ipcalc.py: explain /32 single-host and /31 RFC-3021 point-to-point special
  cases; explain why (~netmask) must be masked with 0xFFFFFFFF (Python ~int
  returns a negative arbitrary-precision value, not a 32-bit unsigned integer)
- notes.py: document the module-level _table_ready flag lifetime; explain why
  tzinfo is stripped before passing datetime to mysql-connector
- admin.py: document the module-level _tables_initialized flag lifetime

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 10:08:55 +02:00

65 lines
2.4 KiB
Python

from flask import Blueprint, request, jsonify
import ipaddress
from util.logger import logger
from auth.token import verify_token
ipcalc_blueprint = Blueprint('ipcalc_tool', __name__)
@ipcalc_blueprint.route('/api/ip/calculate', methods=['POST'])
def ip_calculate():
user = verify_token()
if not user:
return jsonify({"message": "Nicht autorisiert"}), 401
try:
data = request.get_json(silent=True) or {}
cidr = data.get("cidr", "").strip()
try:
network = ipaddress.IPv4Network(cidr, strict=False)
except ValueError as e:
return jsonify({"message": f"Ungültige CIDR-Notation: {e}"}), 400
prefix = network.prefixlen
net_int = int(network.network_address)
bcast_int = int(network.broadcast_address)
# Avoid materialising millions of host objects for large networks.
if prefix == 32:
# Single-host route: the address is both network and host.
total_hosts = 1
first_host = str(network.network_address)
last_host = str(network.network_address)
elif prefix == 31:
# RFC 3021 point-to-point: both addresses are usable hosts,
# there is no dedicated network or broadcast address.
total_hosts = 2
first_host = str(network.network_address)
last_host = str(network.broadcast_address)
else:
total_hosts = network.num_addresses - 2
first_host = str(ipaddress.IPv4Address(net_int + 1))
last_host = str(ipaddress.IPv4Address(bcast_int - 1))
netmask_int = int(network.netmask)
# Python's ~ on an int yields a negative arbitrary-precision value;
# mask to 32 bits to get the correct unsigned wildcard address.
wildcard = str(ipaddress.IPv4Address((~netmask_int) & 0xFFFFFFFF))
ip_class = "Privat" if network.is_private else "Öffentlich"
return jsonify({
"network": str(network.network_address),
"broadcast": str(network.broadcast_address),
"netmask": str(network.netmask),
"wildcard": wildcard,
"first_host": first_host,
"last_host": last_host,
"total_hosts": total_hosts,
"prefix_length": prefix,
"ip_class": ip_class,
})
except Exception as e:
logger.error(f"Fehler ipcalc: {e}")
return jsonify({"message": "Fehler bei der Berechnung"}), 500