# 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.db import models from django.urls import reverse from whoisdb.models import MntdObject, WhoisObject, Contact, InetNum import ipaddress # generally allow domains for .dn to be created # allow owners of a subnet to create reverse dns record? class Nameserver(MntdObject): handleSuffix = "NS" # dns name # ip address, if glue # ipv4/ipv6 address? handle = None name = models.CharField(max_length=256) glueIPv4 = models.GenericIPAddressField(protocol='IPv4', blank=True, null=True) glueIPv6 = models.GenericIPAddressField(protocol='IPv6', blank=True, null=True) admin_c = models.ManyToManyField(Contact) def getPK(self): return self.pk def get_absolute_url(self): return reverse("domains:nameserver-show", args=(self.pk,)) def __str__(self): return self.name def getAppName(self): return "domains" def getNoDeleteReasons(self): # nameservers can always be deleted return [] class Domain(MntdObject): handle = None handleSuffix = "DOM" name = models.CharField(max_length=67, unique=True, db_index=True) nameservers = models.ManyToManyField(Nameserver, blank=True) admin_c = models.ManyToManyField(Contact) ds_records = models.TextField(blank=True, verbose_name='DS Records', help_text='DS Records in the format of [id] [crypto-algo] [hash-algo] [hash]') def getPK(self): return self.name def getZone(self): return self.name def get_absolute_url(self): return reverse("domains:domain-show", args=(self.name,)) def __str__(self): return self.name def getAppName(self): return "domains" def getNoDeleteReasons(self): reasons = [] nameservers = Nameserver.objects.filter(name__endswith="." + self.name) for ns in nameservers: # FIXME: check if the nameserver has a glue record.... and also if it is maintained by us reasons.append("Nameserver %s depends on this domain" % ns.name) return reasons @classmethod def fixName(clazz, name): if not name.endswith("."): name += "." return name.lower() class ReverseZone(WhoisObject): handle = None parentNet = models.ForeignKey(InetNum) address = models.GenericIPAddressField(db_index=True) netmask = models.PositiveIntegerField() nameservers = models.ManyToManyField(Nameserver) def getPK(self): return self.pk def prefix(self): """ Helper function, mainly used in templates """ return "%s/%s" % (self.address, self.netmask) def getNetwork(self): return ipaddress.ip_network(self.prefix()) def getZone(self): net = self.parentNet.getNetwork() if net.version == 4: # does not work with python3.4 ## for these we delegate the full domain #if 0 < net.prefixlen < 32 and net.prefixlen % 8 == 0: # zoneParts = net.reverse_pointer.split(".") # return ".".join(zoneParts[1:]) #else: # # return RFC2317 compliant zone # return net.reverse_pointer parts = list(reversed(str(net.network_address).split("."))) domain = ".".join(parts[4 - net.prefixlen // 8:]) + ".in-addr.arpa." if net.prefixlen % 8 == 0: # clean cut! return domain else: # RFC2317 compliant! rfc2317Domain = "%s/%s.%s" % (parts[4 - net.prefixlen // 8 - 1], net.prefixlen, domain) return rfc2317Domain else: ## does not work with python3.4 ## ipv6 ## thefuck ipaddress lib... _the_ _fuck_ #zoneParts = net.reverse_pointer.split(".")[-2 - net.prefixlen // 4:] #return ".".join(zoneParts) parts = list(reversed(net.exploded.split("/")[0].replace(":", "")))[32 - net.prefixlen // 4:] return ".".join(parts) + ".ip6.arpa." def get_absolute_url(self): return reverse("domains:reversezone-show", args=(self.pk,)) def getAppName(self): return "domains" def __str__(self): return "%s @ %s" % (self.prefix(), self.parentNet) def getNoDeleteReasons(self): return [] def canEdit(self, user): if self.parentNet: return self.parentNet.canEdit(user) else: return False