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