# This file is part of dnmgmt, a number resource management system # Licensed under GNU General Public License v3 or later # Written by Sebastian Lohff (seba@someserver.de) #from django.shortcuts import render from django.http import JsonResponse from django.core.exceptions import ValidationError from django.contrib.auth.views import login_required from django.db.models import Q from whoisdb.models import ASBlock, ASNumber, InetNum from domains.models import Domain, ReverseZone from dnmgmt.settings import TLD_NAMESERVERS from .dnshelper import checkDomain as helperCheckDomain import ipaddress @login_required def asblockFreeAS(request): ret = { "success": False, "errorMsg": None, "number": -1, } try: blockName = request.GET.get('block', None) if not blockName: raise ValidationError("No block given") try: mnts = request.user.maintainer_set.all() block = ASBlock.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct().get(handle=blockName) if block.asblock_set.count() > 0: raise ValidationError("AS Block already has sub AS Blocks") if block.asnumber_set.count() > 0: num = block.asnumber_set.order_by("-number")[0].number + 1 if num > block.asEnd: num = None for n in range(block.asBegin, block.asEnd + 1): try: ASNumber.objects.get(number=n) except ASNumber.DoesNotExist: num = n break if not num: raise ValidationError("No free AS Number in block") ret["number"] = num else: ret["number"] = block.asBegin except ASBlock.DoesNotExist: raise ValidationError("Could not get AS Block") ret["success"] = True except ValidationError as e: ret["errorMsg"] = e.message return JsonResponse(ret) @login_required def freeSubnet(request): ret = { "success": False, "errorMsg": None, "network": None, } try: parentRangeName = request.GET.get('parentRange', None) if not parentRangeName: raise ValidationError("No subnet given") parentRange = None try: mnts = request.user.maintainer_set.all() parentRange = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct().get(handle=parentRangeName) except InetNum.DoesNotExist: raise ValidationError("Parent range does not exist / is not maintained by you") prefixLen = 0 try: prefixLen = request.GET.get("prefixLen", None) if not prefixLen: if parentRange.protocol == InetNum.IPv4: prefixLen = 27 else: prefixLen = 60 prefixLen = int(prefixLen) if prefixLen < 8 or \ (parentRange.protocol == InetNum.IPv4 and prefixLen > 32) or \ (parentRange.protocol == InetNum.IPv6 and prefixLen > 128): raise ValidationError("Given prefix length is out of range") except ValueError: raise ValidationError("PrefixLen is not a number") usableNet = None # FIXME: use first biggest usable netblock... #biggestNet = parentRange.inetnum_set.order_by("-address") #if biggestNet # candidateNet = # and (biggestNet.getNetwork().broadcast_address.: # try using next network in range # ordering does not work, as order_by sorts alphabetically # ==> the set is short, we can iterate through all. no sense in unpacking the SQL magic #biggestNets = parentRange.inetnum_set.order_by("-address") biggestNet = None for ipRange in parentRange.inetnum_set.all(): if not biggestNet or ipRange.getNetwork() > biggestNet: biggestNet = ipRange.getNetwork() if biggestNet: candidateNet = ipaddress.ip_network("%s/%s" % (biggestNet.broadcast_address + 1, biggestNet.prefixlen)) print("biggest net", biggestNet, "candidate", candidateNet) if candidateNet.network_address in parentRange.getNetwork(): usableNet = candidateNet # check if there are still networks left in range if not usableNet: # search for free network nets = list(parentRange.getNetwork().subnets()) for subRange in parentRange.inetnum_set.all(): newNet = None for net in nets: if subRange.getNetwork().network_address in net: newNet = net if not newNet: # critical error, we want a 500 here raise ValueError("Subnet not in range") nets.remove(newNet) nets.extend(newNet.address_exclude(subRange.getNetwork())) nets = sorted(nets) for net in nets: if net.prefixlen <= prefixLen: usableNet = net break if not usableNet: raise ValidationError("No space left in given range") ret["network"] = "%s/%s" % (usableNet.network_address, prefixLen) ret["success"] = True except ValidationError as e: ret["errorMsg"] = e.message return JsonResponse(ret) @login_required def getSubnet(request): ret = { "success": False, "errorMsg": None, "network": None, } try: netName = request.GET.get('net', None) mnts = request.user.maintainer_set.all() nets = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct() net = nets.get(handle=netName) ret["success"] = True ret["network"] = net.prefix() except InetNum.DoesNotExist: ret["errorMsg"] = "Chosen network does not exist" return JsonResponse(ret) @login_required def checkDomain(request): ret = { "success": False, "errorMsg": None, "domain": None, "result": None, } try: domainName = Domain.fixName(request.GET.get('domain', '')) domain = Domain.objects.get(name=domainName) #if not domain.canEdit(request.user): # raise Domain.DoesNotExist() ret["success"] = True ret["domain"] = domain.name # FIXME: change this if we ever have more than one... ret["result"] = helperCheckDomain(domain.name, TLD_NAMESERVERS[0], domain.nameservers.all()) except Domain.DoesNotExist: ret["errorMsg"] = "Domain does not exist" return JsonResponse(ret) @login_required def checkRzone(request): ret = { "success": False, "errorMsg": None, "domain": None, "result": None, } try: rzonePk = int(request.GET.get('domain', '')) rzone = ReverseZone.objects.get(pk=rzonePk) #if not rzone.canEdit(request.user): # raise ReverseZone.DoesNotExist() ret["success"] = True # FIXME: change this if we ever have more than one... ret["result"] = helperCheckDomain(rzone.getZone(), TLD_NAMESERVERS[0], rzone.nameservers.all()) except (ReverseZone.DoesNotExist, ValueError): ret["errorMsg"] = "ReverseZone does not exist" return JsonResponse(ret) def getROA(request): roa = {} for asn in ASNumber.objects.all(): nets = [] for net in asn.inetnum_set.all(): nets.append(net.prefix()) if nets: roa[asn.number] = nets return JsonResponse(roa)