📄 dns_client_cache.c
字号:
answers->r_type = QT_CNAME; answers->r_class = QC_IN; answers->r_ttl = hPtr->ttl; /* * Search the list and see if we have any information for the actual * host name. If we do, then format that information as additional * RRs. If not, then just return the CNAME answer. */ if ((index = search_bynametype(hPtr->cname, QT_AAAA)) >= 0) { if (hostRR[index]->cflag) { /* * Current implementation does not process correctly * chain of aliases. */ dprintf("%C error CNAME chain for %s\n", hPtr->hostname); dns_dfree(answers->r_data, answers->r_datalen); dns_free_RR(answers); return -1; } hPtr = hostRR[index]; if ((additions = create_RR_list(hPtr->naddr, IP6SIZE)) == NULL) { dprintf("%C allocation error cache query\n"); dns_dfree(answers->r_data, answers->r_datalen); dns_free_RR(answers); return -1; } i = 0; rr = additions; while ( rr != NULL ) { if (hPtr->ipaddr[i].__ss_family == AF_INET6) { memcpy(rr->r_data, &((struct sockaddr_in6 *)&hPtr->ipaddr[i])-> sin6_addr, sizeof(struct in6_addr)); strcpy(rr->r_dname, hPtr->hostname); rr->r_type = hPtr->type; rr->r_class = QC_IN; rr->r_ttl = hPtr->ttl; rr->r_datalen = IP6SIZE; } i++; rr = rr->r_next; } reply->m_dnshdr.naddrr = hPtr->naddr; reply->m_additionals = additions; ret_val = DNS_CNAMEANSWER; /* we got a cname and an address * for actual hostname */ } /* if (search for cname addr ok) */ else { ret_val = DNS_CNAME; /* we got a cname but don't got an * address for hostname */ } reply->m_dnshdr.nansrr = 1; reply->m_answers = answers; return ret_val; } /* cname */ /* * The cache record is not CNAME. This case we just have * answer records that are of the AAAA or A6 type. We need one for every * IP address our cache element has. Remember create_RR_list() also * creates the memory space for the data part of the RR, and fails * unless it can create the entire list. */ if ((answers = create_RR_list(hPtr->naddr, IP6SIZE)) == NULL) { dprintf("%C allocation error cache query\n"); return -1; } i = 0; rr = answers; while ( rr != NULL ) { if (hPtr->ipaddr[i].__ss_family == AF_INET6) { memcpy(rr->r_data, &((struct sockaddr_in6 *)&hPtr->ipaddr[i])-> sin6_addr, sizeof(struct in6_addr)); strcpy(rr->r_dname, hPtr->hostname); rr->r_type = hPtr->type; rr->r_class = QC_IN; rr->r_ttl = hPtr->ttl; rr->r_datalen = IP6SIZE; } rr = rr->r_next; i++; } reply->m_dnshdr.nansrr = hPtr->naddr; reply->m_answers = answers; return DNS_ANSWER;} /* dns_query_cache_byname6() *//* * dns_create_ns_list() * * this routine takes an array of NS_t structures and the number of NSs * desired. we loop through the cache list looking for NS entries, if * we find one, we see if it's a reasonable domain match, and if it is * we add it to the array. * * we loop through the cache list, if the entry is a NS entry we first * verify its not out of date. then we determine the number of domain * parts that match, if the number of more than some minimum, MINMATCHDOMAIN, * we add it to the list of NS we are constructing. the minimum should * be at least 2, matching something.com etc. * * return: number of NS entries added to the list */intdns_create_ns_list(const char *domain, int max, NS_t *list){ Dcmp dm, ns; int i, mcnt; char name[NAMEMAX+1]; BITS now; lowercase_copy(name, domain); dm.dname = name; dm.dparts = count_domain_parts(name); now = timer_secs(); for ( i = 0, mcnt = 0; i < DNS_RRMAXENTRYS && mcnt < max; i++ ) { if( hostRR[i] && hostRR[i]->nsflag ) { if ((now - hostRR[i]->init_time) > hostRR[i]->ttl) { free_slot(i); continue; } ns.dname = hostRR[i]->hostname; ns.dparts = count_domain_parts(hostRR[i]->hostname); if ( count_match(&dm, &ns) >= MINMATCHDOMAIN ) { strcpy(list[mcnt].ns_name, hostRR[i]->hostname); list[mcnt].ns_addr = hostRR[i]->ipaddr[0]; list[mcnt].ns_recursion = hostRR[i]->recursion; list[mcnt].ns_try = 0; list[mcnt].ns_error = 0; mcnt++; } } } return mcnt;} /* end dns_create_ns_list() */ /* dns_query_cache_foraddr6only -- * This routine will search the cache list for the domain name given. This * routine is only interested in returning IPv6 addresses, so if the * matching record is a CNAME we just return no matches found. * * Note: since we can meet more than one host record per each domain, * we don't stop if something goes wrong with some record, * but rather continue searching another matching one. * * PARAMETERS * domain - domain name to query cache of * records - resulting resource records * * RETURNS * number of RRs, or -1 if nothing is found */intdns_query_cache_foraddr6only(IN const char *domain, OUT DnsRRec **records){ int i, j; char name[NAMEMAX+1]; BITS now; DnsRRec *rr; lowercase_copy(name, domain); for (i = 0; i < DNS_RRMAXENTRYS; i++) { if (!hostRR[i]) continue; /* * If we find a match, first verify that its not outdated. If * it is free it and break out of the loop. If not, then see if * its a CNAME entry and if so, we break out of the loop, we're * not interested in anything but Addresses. */ if (strcmp(hostRR[i]->hostname, name) == 0) { now = timer_secs(); if ((now - hostRR[i]->init_time) > hostRR[i]->ttl) { free_slot(i); continue; } if (hostRR[i]->cflag || hostRR[i]->nerrflag) continue; if (hostRR[i]->type != QT_A6 && hostRR[i]->type != QT_AAAA) continue; /* * Allocate enough space for all of the addresses associated with * this domain. we then copy all the IP addresses to individual * RRs. */ if ((*records = create_RR_list(hostRR[i]->naddr, IP6SIZE)) == NULL) { dprintf("%C creating resource list failed\n"); break; } rr = *records; j = 0; while (rr != NULL) { if (hostRR[i]->ipaddr[j].__ss_family != AF_INET6) continue; memcpy(rr->r_data, &((struct sockaddr_in6 *)&hostRR[i]->ipaddr[j++])-> sin6_addr, sizeof(struct in6_addr)); rr->r_type = hostRR[i]->type; rr->r_class = QC_IN; rr->r_datalen = IP6SIZE; strcpy(rr->r_dname, domain); rr = rr->r_next; } return j; } } return -1;} /* end dns_query_cache_foraddr6only() *//* * dns_query_cache_foraddronly() * * this routine will search the cache list for the domain name given. this * routine is only interested in returning addresses, so if the matching * record is a CNAME we just return no matches found. * * pab note: since we can meet more than one host record per each domain, * we don't stop if something goes wrong with some record, * but rather continue searching another matching one. * * return: number of RRs, or * -1 to indicate nothing found */intdns_query_cache_foraddronly(const char *domain, DnsRRec **rrecs){ int i, j; char name[NAMEMAX+1]; BITS now; DnsRRec *rr; lowercase_copy(name, domain); for ( i = 0; i < DNS_RRMAXENTRYS; i++ ) { if ( !hostRR[i] ) continue; /* * pab: the below comment is not right about breaks. * see notice above */ /* * if we find a match, first verify that its not outdated. if * it is free it and break out of the loop. if not, then see if * its a CNAME entry and if so, we break out of the loop, we're * not interested in anything but Addresses. */ if ( strcmp(hostRR[i]->hostname, name) == 0 ) { now = timer_secs(); if ((now - hostRR[i]->init_time) > hostRR[i]->ttl) { free_slot(i); continue; } if ( hostRR[i]->cflag || hostRR[i]->nerrflag ) continue; /* * we don't want IPv6 records here, as this routine * is used for IPv4 lookup only. * but there might be IPv6 records further. */ if (hostRR[i]->type == QT_AAAA || hostRR[i]->type == QT_A6) continue; /* * allocate enough space for all of the addresses associated with * this domain. we then copy all the IP addresses to individual * RRs. */ if ((*rrecs = create_RR_list(hostRR[i]->naddr, IPSIZE)) == NULL) { dprintf("%C creating resource list failed\n"); break; } rr = *rrecs; j = 0; while ( rr != NULL ) { if (hostRR[i]->ipaddr[j].__ss_family != AF_INET) { rr = rr->r_next; continue; } memcpy(rr->r_data, &((struct sockaddr_in *)&hostRR[i]->ipaddr[j++])-> sin_addr, sizeof(U32)); rr->r_type = QT_A; rr->r_class = QC_IN; rr->r_datalen = IPSIZE; strcpy(rr->r_dname, domain); rr = rr->r_next; } return hostRR[i]->naddr; /* return the number of RRs */ } } return -1;} /* end dns_query_cache_foraddronly() *//* * dns_update_resolver_cache() * * this routine will attempt to add information from the DNS response, dmsg, * to our cache. the information contained in the response will typically * depend on the first answer RR type. note that most responses have authoritative * answers, (also called name server, (NS), records). if there are additionals RRs * then there may be addresses for the NS records. */voiddns_update_resolver_cache(DnsMsg *dmsg){ DnsHdr *hdr; DnsRRec *aRR; int authoritive = 0; hdr = &dmsg->m_dnshdr; if ((hdr->flags & DNS_AUTHANS) == DNS_AUTHANS) authoritive = 1; /* if this is a negative reply we only cache it if its from an * authoritive server, otherwise we do nothing. */ if ( (hdr->flags & DNS_RCODE) == DNS_NAMEERR ) { if ( authoritive ) add_negative2cache(dmsg); return; } if ( hdr->nansrr > 0 ) { aRR = dmsg->m_answers; switch(aRR->r_type) { case QT_A: case QT_AAAA: case QT_A6: add_host2cache(hdr->nansrr, aRR, authoritive); break; case QT_NS: add_ns2cache(aRR, hdr->naddrr, dmsg->m_additionals); break; case QT_CNAME: add_cname2cache(aRR, dmsg->m_answers, dmsg->m_additionals, authoritive); break; case QT_PTR: add_ptr2cache(aRR, authoritive); break; default: dprintf("%C unrecognized record type %d, not cached\n", aRR->r_type); return; } } if ( hdr->nauthrr > 0 && hdr->naddrr > 0 ) dns_add_AA2cache(dmsg, authoritive);} /* end dns_update_resolver_cache() *//* * add_negative2cache() * * negative responses can have CNAME records and NS records, but in most * cases will have just an SOA record in the authority section. since it * is unlikely that a response will have CNAMES we will not handle that * case here, see RFC 2308 section 2.1 for possible formats for name errors. * note also that we do not attempt to cache no data replies. */static voidadd_negative2cache(DnsMsg *dmsg){ SOArec *srec = NULL; DnsRRec *rr; HostRecord *hptr; int index = -1; U32 ttl; if ( find_num_record(dmsg->m_answers, QT_CNAME) > 0 ) return; /* * find the SOA record. it should be in the authority section. * note if the record does not exist, then we do not cache this * response, see RFC 2308 section 5. */ rr = dmsg->m_authoritys; while ( rr != NULL ) { if ( rr->r_type == QT_SOA ) { srec = (SOArec *)rr->r_data; break; } rr = rr->r_next; } if ( srec == NULL ) /* no SOA record */ return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -