⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dns_client_reply.c

📁 DNS 的实现代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    {        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 + -