238 lines
6.4 KiB
Python
238 lines
6.4 KiB
Python
# 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)
|