def _handle_authoritative_response( self, dns_response: DNSMessage, requested_domain_name: str, requested_type: int) -> List[ResourceRecord]: """ If an authoritative response is received from the domain name server, then first look for any matching answer records. If there is one or more answer records, return them. If there are no such records, then find a cname record and resolve the domain using its cname value. :param dns_response: the most recently received dns response in the name resolution process. :param requested_domain_name: the domain name we wish to resolve. :param requested_type: the type of address we wish to resolve the domain name to. :raises: DNSNoMatchingResourceRecordError :return: a list of the answer records that match the desired domain name and type, if present. """ answer_resource_records = dns_response.get_matching_answer_records( dns_response.answer_records, requested_domain_name, requested_type) cname_resource_records = dns_response.get_matching_answer_records( dns_response.answer_records, requested_domain_name, 5) if answer_resource_records: return answer_resource_records elif cname_resource_records: cname_domain_name: str = cname_resource_records[0].rdata return self.resolve_domain_name(cname_domain_name, self.starting_dns_server, requested_type) else: raise DNSNoMatchingResourceRecordError( "No matching resource record error: an authoritative response was returned for a desired domain name. However, the authoritative response did not contain any resource records that matched the desired type." )
def test_get_matched_answer_records_single_match(self): """ Test case to match with a single answer record that matches the domain name and type. """ records: List[ResourceRecord] = DNSMessage.get_matching_answer_records( self.resource_records, "name1", 1) self.assertEqual(records, [self.resource_record_1])
def test_get_matched_answer_records_type_mismatch(self): """ Test case to match with a type that doesn't match any record with a given name. """ records: List[ResourceRecord] = DNSMessage.get_matching_answer_records( self.resource_records, "name1", 5) self.assertEqual(len(records), 0)
def test_get_matched_answer_records_domain_name_mismatch(self): """ Test case to match with a domain name that isn't the name of any record. """ records: List[ResourceRecord] = DNSMessage.get_matching_answer_records( self.resource_records, "no-match", 1) self.assertEqual(len(records), 0)
def test_get_matched_answer_records_no_records(self): """ Test case to match on an empty list of records. """ records: List[ResourceRecord] = DNSMessage.get_matching_answer_records( [], "", 1) self.assertEqual(len(records), 0)
def test_get_matched_answer_records_multiple_matches(self): """ Test case to match with two answer records that matches the domain name and type. """ records: List[ResourceRecord] = DNSMessage.get_matching_answer_records( self.resource_records, "name2", 5) self.assertEqual(records, [self.resource_record_2, self.resource_record_4])
def test_get_matched_answer_records_single_match_different_cases(self): """ Test case to match with a single answer record that matches the domain name and type. The searched for domain uses different cases then the case in the matching resource record. """ records: List[ResourceRecord] = DNSMessage.get_matching_answer_records( self.resource_records, "NAME1", 1) self.assertEqual(records, [self.resource_record_1])