def legal_dns_owner_name(self, name, record_type, allow_underscores=False): uber_hyphen = re.compile(r'---+') uber_underscore = re.compile(r'__+') if record_type == dns.SRV_OWNER or allow_underscores: valid_chars = re.compile(r'^[a-zA-Z\-_0-9]*$') else: valid_chars = re.compile(r'^[a-zA-Z\-0-9]+$') if not name.endswith('.'): raise DNSError("Name not fully qualified") for n in name[:-1].split("."): if n.startswith("-") or n.endswith("-"): raise DNSError( "Illegal name: '%s'; Cannot start or end with '-'" % (name,)) if uber_hyphen.search(n): raise DNSError( "Illegal name: '%s'; More than two '-' in a row" % (name, )) if not valid_chars.search(n): raise DNSError( "Illegal name: '%s'; Invalid character(s)" % (name, )) if record_type == dns.SRV_OWNER: if uber_underscore.search(n): raise DNSError( "Illegal name: '%s'; More than one '_' in a row" % (name, ))
def dns_reg_owner_ok(self, name, record_type, allow_underscores=False): """ Checks if it is legal to register a record of type record_type with given name. Raises an exception if record_type is illegal, or name is illegal. Returns: - dns_owner_ref: reference to dns_owner or None if non-existing - same_type: boolean set to true if a record of the same type exists. """ dns_owner = DnsOwner.DnsOwner(self._db) self.legal_dns_owner_name(name, record_type, allow_underscores) try: dns_owner.find_by_name(name) except Errors.NotFoundError: return None, None owner_types = self._find.find_dns_owners(dns_owner.entity_id) if dns.CNAME_OWNER in owner_types: raise DNSError("%s is already a CNAME" % (name, )) if record_type == dns.CNAME_OWNER: if owner_types: raise DNSError("%s already exists" % (name, )) if record_type == dns.HOST_INFO: if dns.HOST_INFO in owner_types: raise DNSError("%s already exists" % (name, )) # TODO: This should probarbly be rewritten, since it is a bit ugly. # The difference between A- and AAAA-records is minimal, so this is # enough for now. if record_type in (dns.A_RECORD, dns.AAAA_RECORD,): if dns.A_RECORD in owner_types or dns.AAAA_RECORD in owner_types: return dns_owner.entity_id, True return dns_owner.entity_id, False
def remove_arecord(self, a_record_id, try_dns_remove=False): """Remove an a-record identified by a_record_id. Will also update override_revmap and remove the entry in ip_number if it is no longer referred to by other tables. :param int a_record_id: The ARecords id. :param bool try_dns_remove: Remove the DNSOwner too. """ ip_type = dns.IP_NUMBER record_type = dns.A_RECORD arecord = ARecord.ARecord(self._db) try: arecord.find(a_record_id) ip_number_id = arecord.ip_number_id ipnumber = IPNumber.IPNumber(self._db) except Errors.NotFoundError: arecord = AAAARecord.AAAARecord(self._db) arecord.find(a_record_id) ip_type = dns.IPv6_NUMBER record_type = dns.AAAA_RECORD ip_number_id = arecord.ipv6_number_id ipnumber = IPv6Number.IPv6Number(self._db) ipnumber.find(ip_number_id) dns_owner_id = arecord.dns_owner_id arecord._delete() refs = self._find.find_referers(ip_number_id=ipnumber.entity_id, ip_type=ip_type) if dns.REV_IP_NUMBER in refs: self._update_override(ipnumber.entity_id, dns_owner_id) refs = self._find.find_referers(ip_number_id=ipnumber.entity_id, ip_type=ip_type) if not (dns.REV_IP_NUMBER in refs or record_type in refs): # IP no longer used ipnumber.delete() # Assert that any cname/srv targets still point to atleast one # a-record. Assert that host_info has atleast one associated # a_record. # TODO: This check should be somewhere that makes it is easier # to always enforce this constraint. refs = set(self._find.find_referers(dns_owner_id=dns_owner_id, ip_type=dns.IP_NUMBER)) refs.update(self._find.find_referers(dns_owner_id=dns_owner_id, ip_type=dns.IPv6_NUMBER)) if not any(r_type in refs for r_type in (dns.A_RECORD, dns.AAAA_RECORD)): if dns.SRV_TARGET in refs or dns.CNAME_TARGET in refs: raise DNSError("Host is used as target for CNAME or SRV") if try_dns_remove: self.remove_dns_owner(dns_owner_id)
def _verify_mac_format(self, mac_adr): """Checks that the given MAC-address is written with an acceptable format. If so, it returns the MAC address on the standardized format. Acceptable formats: * Valid seperators are ':', '-', '.' and ' ' * Numbers are hexa-decimal. Capitalization doesn't matter * Seperators between every 2 or 4 numbers Standardized format: * Only ':' used as seperator, between every two numbers * Only lowercase hexa-decimal numbers. @type mac_adr: string @param mac_adr: The MAC address that is to be verified @rtype: string @return: The MAC-address as formatted to the standard format @raise DNSError: If mac_adr isn't formatted in any valid way """ # Prepare error message for possible later use error_msg = ("Invalid MAC-address: '%s'. " % mac_adr + "Try something like '01:23:45:67:89:ab' instead") # Standardize case mac_adr = mac_adr.lower() # Standardize seperator character for char in ('-', '.', ' '): mac_adr = mac_adr.replace(char, ":") # Standardize if using Cisco format or no seperators at all for index in (2, 5, 8, 11, 14): try: if not mac_adr[index] == ':': mac_adr = mac_adr[0:index] + ':' + mac_adr[index:] except IndexError: raise DNSError(error_msg) if not re.search("^([a-f0-9]{2}:){5}[a-f0-9]{2}$", mac_adr): raise DNSError(error_msg) return mac_adr
def remove_dns_owner(self, dns_owner_id): refs = self._find.find_referers(dns_owner_id=dns_owner_id) if refs: raise DNSError("dns_owner still refered in %s" % str(refs)) dns_owner = DnsOwner.DnsOwner(self._db) dns_owner.find(dns_owner_id) if not self._find.find_overrides(dns_owner_id=dns_owner_id): dns_owner.delete() else: for t in dns_owner.get_traits().keys(): try: dns_owner.delete_trait(t) except errors.NotFoundError: pass dns_owner.mx_set_id = None dns_owner.write_db()
def alter_entity_note(self, owner_id, trait, dta): dta = dta.strip() if trait == self.const.trait_dns_contact: mail_ok_re = re.compile(cereconf.DNS_EMAIL_REGEXP) if dta and not mail_ok_re.match(dta): raise DNSError("'%s' does not look like an e-mail address" % dta) self._dns_owner.clear() self._dns_owner.find(owner_id) if not dta: try: self._dns_owner.delete_trait(trait) except Errors.NotFoundError: # Already deleted, noop pass return "removed" if self._dns_owner.populate_trait(trait, strval=dta) == 'INSERT': action = "added" else: action = 'updated' self._dns_owner.write_db() return action
def ip_to_long(ip): try: return struct.unpack('!L', socket.inet_aton(ip))[0] except socket.error, msg: raise DNSError("Bad IP: %s" % msg)
def ip_to_long(ip): """Convert an IPv6 IP address to long format.""" try: hi, lo = struct.unpack('!QQ', socket.inet_pton(socket.AF_INET6, ip)) except socket.error, msg: raise DNSError("Bad IP: %s" % msg)