📄 dns_client_reply.c
字号:
{ DNSC_TRACE("DNS reply not valid for standard query\n");#ifdef DNS_DEBUG print_dns_message(&query->dnsreply); #endif dnsmsg_cleanup(&query->dnsreply); dns_response_timeout(query); DNSC_DEBUG("exit - verify_dns_response failed\n"); return; } /* Check that its not a negative return */ if ((nrc = dns_negative_replycheck(query)) < 0) { DNSC_DEBUG("negative reply is received\n"); /* If it was AAAA question, ignore response and try again with A6 one */ if (query->qtype == aaaa_type) { int i; query->qtype = a6_type; query->qstate = wf_a6; for (i = 0; i < query->dm.num_svr; i++) query->ns_addrs[i].ns_try = 0; dnsmsg_cleanup(&query->dnsreply); if (dns_query(query) < 0) { MSG_D_DNS_GET_NODEBYNAME(dmsg, query->reply); dmsg->error = ETRYAGAIN; sendreply(query->reply); free_querystate(query); DNSC_DEBUG("exit - dns_query for A6 failed\n"); return; } DNSC_DEBUG("exit - dns_query for A6 sent\n"); return; } if (query->next_srch < 0) { MSG_D_DNS_GET_NODEBYNAME(dmsg, query->reply); if (nrc == -2) { dmsg->error = EHOSTNOTFOUND; dns_update_resolver_cache(&query->dnsreply); } else dmsg->error = ENODATA; /* we don't cache no data */ sendreply(query->reply); dnsmsg_cleanup(&query->dnsreply); free_querystate(query);#ifdef DNS_DEBUG print_responding_server(query); print_dns_message(&query->dnsreply); #endif } else { if (nrc == -2) dns_update_resolver_cache(&query->dnsreply); dnsmsg_cleanup(&query->dnsreply); dns_start_next_search6(query); } DNSC_DEBUG("exit\n"); return; } /* Reply is not negative */ dnsmsg = &query->dnsreply; if (find_match_rrecord(query->domain, dnsmsg->m_answers, QT_CNAME) != NULL) { DNSC_DEBUG("exit - CNAME - call dns_cname6_reply\n"); return dns_cname6_reply(query); } if (find_match_rrecord(query->domain, dnsmsg->m_answers, QT_AAAA) != NULL || find_match_rrecord(query->domain, dnsmsg->m_answers, QT_A6) != NULL) { dns_fmt_ip6_answer(query, dnsmsg); dns_update_resolver_cache(dnsmsg); sendreply(query->reply);#ifdef DNS_DEBUG if (dns_verbosity > 0) { print_responding_server(query); print_dns_message(dnsmsg); }#endif dnsmsg_cleanup(dnsmsg); free_querystate(query); DNSC_DEBUG("exit - match AAAA or A6\n"); return; } /* * If we didn't get the answer or weren't told our domain name was a CNAME * we see if there's a "delegation". That is did the server tell us to try * another server. If not we clean up and try the next server. We check * the answer section for the NS record, then if there are no answer records * and there are some NS records in the authority section, its a delegation, * see the referral response in section 2.2 of RFC 2308. */ rr = dnsmsg->m_answers; ns = dnsmsg->m_authoritys; if (find_num_record(rr, QT_NS) > 0 || find_num_record(ns, QT_NS) > 0) { DNSC_DEBUG("exit - NS - call dns_ns_reply\n"); return dns_ns_reply(query); } dnsmsg_cleanup(&query->dnsreply); dns_response_timeout(query); DNSC_DEBUG("exit\n");} /* dns_response_std6_query *//* * dns_response_std_query() * * this routine handles responses for standard queries. this is the case * where we want an IP address for a domain name. we validate the DNS message * and then look for our answer. the reply could contain an A type which would * have the address we're looking for, a CNAME record or an NS record telling * us to try another name server. if there's any other type, its an error. */voiddns_response_std_query(QueryState *query){ DnsMsg *dnsmsg; DnsRRec *rr, *ns; int nrc; DNSC_DEBUG("entry\n"); if ( verify_dns_response(query) < 0) { dprintf("%C DNS reply not valid for standard query\n");#ifdef DNS_DEBUG print_dns_message(&query->dnsreply); #endif dnsmsg_cleanup(&query->dnsreply); dns_response_timeout(query); return; } /* check that its not a negative return */ if ((nrc = dns_negative_replycheck(query)) < 0) { /* the NS says the domain does not exist or there's no data. if there is * another element of the search list to try then do that, otherwise clean * up and return the error. */ if ( query->next_srch < 0 ) { MSG_D_DNS_GET_ADDRBYNAME(dmsg, query->reply); if ( nrc == -2 ) { dmsg->error = EHOSTNOTFOUND; dns_update_resolver_cache(&query->dnsreply); } else dmsg->error = ENODATA; /* we don't cache no data */ sendreply(query->reply); dnsmsg_cleanup(&query->dnsreply); free_querystate(query);#ifdef DNS_DEBUG print_responding_server(query); print_dns_message(&query->dnsreply); #endif } else { if ( nrc == -2 ) dns_update_resolver_cache(&query->dnsreply); dnsmsg_cleanup(&query->dnsreply); dns_start_next_search(query); } return; } /* * the reply is okay and its not a negative reply, now see if we got the * answer we're looking for. if we got an A record then we did. so, format * the response, update the cache, send the reply, then clean up. */ dnsmsg = &query->dnsreply; if ( find_match_rrecord(query->domain, dnsmsg->m_answers, QT_CNAME) != NULL ) { dns_cname_reply(query); return; } if ( find_match_rrecord(query->domain, dnsmsg->m_answers, QT_A) != NULL ) { fmt_ip_answer(query, dnsmsg); dns_update_resolver_cache(dnsmsg); sendreply(query->reply);#ifdef DNS_DEBUG if ( dns_verbosity > 0 ) { print_responding_server(query); print_dns_message(dnsmsg); }#endif dnsmsg_cleanup(dnsmsg); free_querystate(query); return; } /* * if we didn't get the answer or weren't told our domain name was a CNAME * we see if there's a "delegation". that is did the server tell us to try * another server. if not we clean up and try the next server. we check * the answer section for the NS record, then if there are no answer records * and there are some NS records in the authority section, its a delegation, * see the referral response in section 2.2 of RFC 2308. */ rr = dnsmsg->m_answers; ns = dnsmsg->m_authoritys; if ( find_num_record(rr, QT_NS) > 0 || find_num_record(ns, QT_NS) > 0 ) return dns_ns_reply(query); dnsmsg_cleanup(&query->dnsreply); dns_response_timeout(query);} /* end dns_response_std_query() *//* dns_cname6_reply -- * This routine extracts data from CNAME replies. * * PARAMETERS * query - query state structure * * RETURNS * N/A */static voiddns_cname6_reply(IN QueryState *query){ Qinfo_t qInfo; nslook_t *hp; DnsRRec *cRR; DnsMsg *dnsmsg = &query->dnsreply; DNSC_DEBUG("entry\n"); /* * First get the CNAME record, we already know it exists since that's * why this routine was called. */ cRR = find_match_rrecord(query->domain, dnsmsg->m_answers, QT_CNAME); if (cRR == NULL) { DNSC_TRACE("error no CNAME record when expected\n"); dnsmsg_cleanup(dnsmsg); dns_response_timeout(query); DNSC_DEBUG("exit - find_match_rrecord CNAME failed\n"); return; } /* * Now see if there are any AAAA or A6 records for the CNAME. * If not then we try the cache. If nothing from the cache then * we need to start another query for the CNAME. */ if (find_match_rrecord(cRR->r_data, dnsmsg->m_answers, QT_AAAA) == NULL && find_match_rrecord(cRR->r_data, dnsmsg->m_answers, QT_A6) == NULL && find_match_rrecord(cRR->r_data, dnsmsg->m_additionals, QT_AAAA) == NULL && find_match_rrecord(cRR->r_data, dnsmsg->m_additionals, QT_A6) == NULL) { /* For IPv6 we always use cache */ DnsMsg dns_answer; DnsRRec *rr = NULL; int nrr; /* * If our answer is in the cache we format our results and * then hand it up. */ memset(&dns_answer, 0, sizeof(dns_answer)); if ((nrr = dns_query_cache_foraddr6only(cRR->r_data, &rr)) > 0) { dns_answer.m_dnshdr.nansrr = nrr; dns_answer.m_answers = rr; strcpy(query->cname, query->domain); strcpy(query->domain, cRR->r_data); query->qtype = ac_type; dns_fmt_cname6_answer(query, &dns_answer); sendreply(query->reply); dnsmsg_cleanup(&dns_answer); dnsmsg_cleanup(dnsmsg); free_querystate(query); DNSC_DEBUG("exit - cache for addr6 success\n"); return; } /* * Nothing in the cache, so we need to construct a new query for the * CNAME. Cache any useful information, it could come in handy when * the new query creates its name server list. If we already have * an active query outstanding, clean up and exit. We only want one * outstanding query at a time. */ dns_add_AA2cache(dnsmsg, 0); if (query->nxquery != NULL) { dnsmsg_cleanup(dnsmsg); DNSC_DEBUG("exit - (query->nxquery != NULL)\n"); return; } /* * We also have a limit on how many queries we allow for a particular * request. If a new query will exceed that limit, then we don't do * it. */ if ((query->nquerys + 1) > MAXQUERYDEPTH) { dnsmsg_cleanup(dnsmsg); dns_response_timeout(query); DNSC_DEBUG("exit - too many queries\n"); return; } /* * So, looks like we're going to do the new query. Get a hostent * structure and an ATMOS_MESSAGE. Fill in the necessary information * to indicate its a query for a cname and kick off the query. */ if ((hp = dns_hent_alloc()) == NULL) {#ifdef DNS_DEBUG print_resource_pool();#endif dnsmsg_cleanup(dnsmsg); dns_response_timeout(query); DNSC_DEBUG("exit - dns_hent_alloc failed\n"); return; } memset(&qInfo, 0, sizeof(qInfo)); qInfo.qtype = aaaa_t; strcpy(hp->name, cRR->r_data); qInfo.hostname = hp->name; qInfo.cache_flag = TRUE; qInfo.qcnt = ++query->nquerys; qInfo.amsg = &hp->amsg; if (start_new_query(&qInfo) < 0) { DNSC_DEBUG("attempt to start internal query failed\n"); dns_hent_free(hp); dnsmsg_cleanup(dnsmsg); dns_response_timeout(query); DNSC_DEBUG("exit - start_new_query failed\n"); return; } query->nxquery = &hp->amsg; /* we use this to find this query later */ query->qstate = wf_cqaddr; query->dns_qreply = cname6_reply; dnsmsg_cleanup(dnsmsg); /* clean up */ DNSC_DEBUG("exit - new query started\n"); return; } /* * We have at least one matching record. So we've got our answer. Handle * formating and such. */ dns_fmt_cname6_answer(query, &query->dnsreply);#ifdef DNS_DEBUG if (dns_verbosity > 0) { print_responding_server(query); print_dns_message(&query->dnsreply); }#endif dns_update_resolver_cache(&query->dnsreply); sendreply(query->reply); dnsmsg_cleanup(&query->dnsreply); /* be sure to clean up */ free_querystate(query); /* and to free the query state structure */ DNSC_DEBUG("exit - success\n");} /* dns_cname6_reply *//* * dns_cname_reply() * * this is called when the server tells us the domain name we were looking for * is an alias for another name. we already know the CNAME record exists in the * answer section. we get that and then look for an address record for it. the * A record could be in the answer section or in the additional records. (probably * in the answer section but we'll check both.) if not found in either section * then the server didn't know it. we modify the current query to look for the * new name. */static voiddns_cname_reply(QueryState *query){ Qinfo_t qinfo; nslook_t *hp; DnsRRec *cRR; DnsMsg *dnsmsg = &query->dnsreply; /* first get the CNAME record, we already know it exists since that's * why this routine was called. */ if ((cRR = find_match_rrecord(query->domain, dnsmsg->m_answers, QT_CNAME)) == NULL) { dprintf("%C: error no CNAME record when expected\n"); dnsmsg_cleanup(dnsmsg); dns_response_timeout(query); return; } /* * now see if there are any A records for the CNAME. if not then we try the * cache. if nothing from the cache then we need to start another query * for the CNAME. */ if ( find_match_rrecord(cRR->r_data, dnsmsg->m_answers, QT_A) == NULL && find_match_rrecord(cRR->r_data, dnsmsg->m_additionals, QT_A) == NULL) { /* if okay by the user try the cache. */ if ( TRUE == query->use_cache ) { DnsMsg dns_answer; DnsRRec *rr = NULL; int nrr; /* if our answer is in the cache we format our results and * then hand it up. */ memset(&dns_answer, 0, sizeof(dns_answer)); if ((nrr = dns_query_cache_foraddronly(cRR->r_data, &rr)) > 0 ) { /* * found the cname in the cache. set this up so that we can * use fmt_cname_answer() to format the results. set the query * state with the canonical name as the domain and the alias as * the cname element. change the query type to indicate the * set up we have here. we have to do this because the response * from the cache is not part of the DNS response. */ dns_answer.m_dnshdr.nansrr = nrr; dns_answer.m_answers = rr; strcpy(query->cname, query->domain); strcpy(query->domain, cRR->r_data); query->qtype = ac_type; fmt_cname_answer(query, &dns_answer); sendreply(query->reply); dnsmsg_cleanup(&dns_answer); dnsmsg_cleanup(dnsmsg); free_querystate(query); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -