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

📄 dns_client_reply.c

📁 DNS 的实现代码
💻 C
📖 第 1 页 / 共 4 页
字号:
find_ns_record(QueryState *qstate, Dcmp *domain, DnsMsg *dmsg){    DnsRRec  *RR;    Dcmp     ns;    DNSC_DEBUG("entry\n");    RR = dmsg->m_answers;    while ( RR != NULL && RR->r_type == QT_NS ) {        ns.dname = RR->r_data;	ns.dparts = count_domain_parts(ns.dname);        if ( validate_domain(domain, &ns) == 0 ) {	    if ( find_replaceable_ns(qstate, domain, &ns) >= 0 )		return RR;	}	RR = RR->r_next;    }    RR = dmsg->m_authoritys;    while ( RR != NULL && RR->r_type == QT_NS ) {        ns.dname = RR->r_data;	ns.dparts = count_domain_parts(ns.dname);        if ( validate_domain(domain, &ns) == 0 ) {	    if ( find_replaceable_ns(qstate, domain, &ns) >= 0 )		return RR;	}	RR = RR->r_next;    }    return NULL;}   /* end find_ns_record() */#ifdef DNS_HAVE_IP6STACK/* * ns6_reply -- *     This routine called when an internal query results are returned.   *  * PARAMETERS *     query - query state structure * * RETURNS *     n/a */static voidns6_reply(IN QueryState *query){    struct hostent  *hent;    nslook_t        *hp;    int              index;    Dcmp             domain;    Dcmp             ns;    Qinfo_t          qInfo;    MSG_D_DNS_GET_NODEBYNAME(dmsg, query->nxquery);    DNSC_DEBUG("entry\n");    hent = dmsg->hent;    if (ESUCCESS == dmsg->error)     {        domain.dname = query->domain;	domain.dparts = count_domain_parts(query->domain);	ns.dname = (char *)hent->h_name;	ns.dparts = count_domain_parts(ns.dname);        if ((index = find_replaceable_ns(query, &domain, &ns)) >= 0)         {            if (hent->h_addr_list && hent->h_addr_list[0])            {                data2sock(&query->ns_addrs[index].ns_addr,                          hent->h_addr_list[0]);                strcpy(query->ns_addrs[index].ns_name, hent->h_name);                query->ns_addrs[index].ns_try = 0;                query->ns_addrs[index].ns_error = 0;                query->ns_addrs[index].ns_recursion = 0;                if ( index >= query->num_ns )                    query->num_ns = index + 1;            }	}        dns_hent_msg_free(query->nxquery);        query->nxquery = NULL;        dns_response_timeout(query);	return;    }    dns_hent_msg_free(query->nxquery);    query->nxquery = NULL;    if ((hp = dns_hent_alloc()) == NULL)     {        dprintf("%C no free dns_hostent structures for internal NS query\n");#ifdef DNS_DEBUG	print_resource_pool();#endif	dns_response_timeout(query);	return;    }    hp->hent.h_numaddrs = ENTADDRS;   /* set for the max amount */    qInfo.qtype = addr_t;    strcpy(hp->name, query->domain);    qInfo.hostname = hp->name;    qInfo.cache_flag = query->use_cache;    qInfo.qcnt = query->nquerys;    qInfo.amsg = &hp->amsg;    qInfo.hptr = &hp->hent;    if (start_new_query(&qInfo) < 0)     {        dprintf("%C; attempt to start internal NS query failed\n");	dns_hent_free(hp);	dns_response_timeout(query);	return;    }    query->nxquery = &hp->amsg;        /* we use this to find this query later */    query->qstate = wf_nsaddr;    query->dns_qreply = ns_reply;      /* set the handler */    return;}   /* end ns6_reply() */#endif/* * ns_reply() * * this routine called when an internal query results are returned.  this routine * is set up for the waiting query when the internal query is kicked off.  the * query was for the address of a name server suggested by another name server * in its response.  if the query was successful we determine the name server in * our name server list that should be replaced by this new one.  then, we replace * the name server.  successful or not we free up the message and dns_hostent structure * once we're done with it.  then we proceed as if a response had timed out. */voidns_reply(QueryState *query){    struct dns_hostent  *hptr;    int                 index;    Dcmp                domain;    Dcmp                ns;    MSG_D_DNS_GET_ADDRBYNAME(dmsg, query->nxquery);    DNSC_DEBUG("entry\n");    hptr = dmsg->hptr;    if ( ESUCCESS == dmsg->error ) {        domain.dname = query->domain;	domain.dparts = count_domain_parts(query->domain);	ns.dname = hptr->h_name;	ns.dparts = count_domain_parts(ns.dname);        if ((index = find_replaceable_ns(query, &domain, &ns)) >= 0) {	    long2sock(&query->ns_addrs[index].ns_addr, hptr->h_addr_list[0]);	    strcpy(query->ns_addrs[index].ns_name, hptr->h_name);	    query->ns_addrs[index].ns_try = 0;	    query->ns_addrs[index].ns_error = 0;	    query->ns_addrs[index].ns_recursion = 0;	    if ( index >= query->num_ns )	        query->num_ns = index + 1;	}    }    dns_hent_host_free(hptr);    query->nxquery = NULL;    dns_response_timeout(query);}   /* end ns_reply() *//* cname6_reply -- *     This routine is called when an internal query results are  *     returned for a CNAME query of a IPv6 request.    * * PARAMETERS *     query - query state structure * * RETURNS *     N/A */static voidcname6_reply(QueryState *query){    struct hostent  *result;    struct hostent  *hent;    int              i, numAddrs;    MSG_D_DNS_GET_NODEBYNAME(rmsg, query->reply);    MSG_D_DNS_GET_NODEBYNAME(nxmsg, query->nxquery);    DNSC_DEBUG("entry\n");    result = nxmsg->hent;    if (ESUCCESS == nxmsg->error)     {        do {            ASSERT(rmsg->hent == NULL);            if ((hent = dns_alloc_struct_hostent()) == NULL)                break;                            hent->h_addrtype = AF_INET6;            hent->h_length = sizeof(struct in6_addr);                            if (dns_alloc_hostname(hent, result->h_name) == NULL)                break;            /* copy aliases */            if (dns_alloc_aliases(hent, 1) == NULL)                break;            hent->h_aliases[0] = malloc(strlen(query->domain) + 1);            if (hent->h_aliases[0] == NULL)            {                dns_freehostent(hent);                break;            }            strcpy(hent->h_aliases[0], query->domain);            /*              * Now copy addresses.              * First determine how many addresses there are              */            numAddrs = 0;            if (result->h_addr_list != NULL)            {                char **tmp;                for (tmp = result->h_addr_list; *tmp; tmp++)                    numAddrs++;            }            if (dns_alloc_addrlist(hent, numAddrs, AF_INET6) == NULL)                break;            /* Copy all addresses */            for ( i = 0; i < numAddrs; i++ )            {                memcpy(hent->h_addr_list[i], result->h_addr_list[i],                       sizeof(struct in6_addr));            }                        rmsg->hent = hent;            rmsg->error = ESUCCESS;            sendreply(query->reply);            dns_hent_msg_free(query->nxquery);            free_querystate(query);            DNSC_DEBUG("exit - success\n");            return;        } while (FALSE);        /* We get here only if there were problems with malloc() */        rmsg->hent = NULL;        rmsg->error = ENOMEM;    }    dns_hent_msg_free(query->nxquery);    query->nxquery = NULL;    dns_response_timeout(query);    DNSC_DEBUG("exit - request failed\n");} /* cname6_reply *//* * cname_reply() * * this routine is called when an internal query results are returned for a CNAME * query.  the routine is set up at the time the CNAME query is started.  in this * case if the CNAME query was successful we just need to copy the information * to our dns_hostent structure for returning.  we copy the domain name from the * starting query to the alias, since that's what the name server told us it was. * we copy as many IP addresses as we have or at least as many as was asked for. * we then just free up the resources and return the results to the caller. * * if the internal query was a failure, then there's something strange since * the other name server reply told us to use the CNAME.  any other error indicates * a problem with either the name server or our domain imformation.  we handle * this like we would a regular time out and hope the problem has cleared.  if * not it'll be caught later. */voidcname_reply(QueryState *query){    struct dns_hostent  *cn;    struct dns_hostent  *hptr;    int                 i;    MSG_D_DNS_GET_ADDRBYNAME(rmsg, query->reply);    MSG_D_DNS_GET_ADDRBYNAME(nxmsg, query->nxquery);    DNSC_DEBUG("entry\n");    cn = nxmsg->hptr;    if ( ESUCCESS == nxmsg->error ) {        hptr = rmsg->hptr;	strcpy(hptr->h_name, cn->h_name);	strcpy(hptr->h_alias, query->domain);	hptr->h_numaddrs = MIN(hptr->h_numaddrs, cn->h_numaddrs);	for ( i = 0; i < hptr->h_numaddrs; i++ )	    hptr->h_addr_list[i] = cn->h_addr_list[i];	rmsg->error = ESUCCESS;	sendreply(query->reply);	free_querystate(query);	dns_hent_host_free(cn);	return;    }    dns_hent_host_free(cn);    query->nxquery = NULL;    dns_response_timeout(query);}   /* end cname_reply() *//* * dns_response_XX_query() * * this routine handles responses for NAPTR/SRV queries.   * Returns: None */voiddns_response_XX_query(QueryState *query){    DnsMsg  *dnsmsg;    DnsRRec *rr, *ns;    int     nrc;    BOOL    sendreply_flag = FALSE;    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_XX_negative_replycheck(query)) != ESUCCESS)     {        MSG_D_DNS_GET_RR(dmsg, query->reply);            dmsg->error = nrc;        sendreply(query->reply);        dnsmsg_cleanup(&query->dnsreply);        free_querystate(query);#ifdef DNS_DEBUG        print_responding_server(query);        print_dns_message(&query->dnsreply); #endif        return;    } /* If negative reply from server */    /*      * the reply is okay and its not a negative reply, now see if we got the      * answer we're looking for.  if we got a NAPTR or SRV record then we did.  so, format      * the response, update the cache, send the reply, then clean up.     */    dnsmsg = &query->dnsreply;    if (query->qtype == naptr_type)    {        if (find_match_rrecord(query->domain, dnsmsg->m_answers, QT_NAPTR) != NULL)        {            sendreply_flag = TRUE;        }    }        if (query->qtype == srv_type)    {        if (find_match_rrecord(query->domain, dnsmsg->m_answers, QT_SRV) != NULL)        {            sendreply_flag = TRUE;        }    }            if (sendreply_flag == TRUE)    {        fmt_XX_answer(query, dnsmsg->m_answers);        dns_update_XX_cache(dnsmsg);        sendreply(query->reply);        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);    DNSC_DEBUG("exit\n");    return;}   /* end dns_response_XX_query() *//* * dns_XX_negative_replycheck() * * this routine checks whether the reply for a NAPTR/SRV query is  * negative or not * * Returns: None */static intdns_XX_negative_replycheck(QueryState *query){    DnsMsg  *dnsmsg;    DNSC_DEBUG("entry\n");    /* name error replies will have the rcode section of the flags field     * set to the name error.     */    dnsmsg = &query->dnsreply;    if ((dnsmsg->m_dnshdr.flags & DNS_RCODE) == DNS_NAMEERR)     {        DNSC_DEBUG("exit - failure - no name error\n");        return EHOSTNOTFOUND;                       /* name error reply */    }    /*     * no data replies have the rcode section set to no error.  the reply     * will have "no relevant answers in the answer section.  the authority     * section will contain an SOA record, or there will be no NS records     * there", see section 2.2 of RFC 2308.     *     * we assume the DNS message has already been verified so if there is     * no name error then there is no errors given in the flag field.  first     * see if there are any "relevant" answer records.  relevant in this     * case means no A records for our domain.  then see if there is an     * SOA record or there are no NS records in the authority section.     */    if ( (query->qtype == naptr_type) && (find_num_match(query->domain, dnsmsg->m_answers, QT_NAPTR) == 0) )    {        return ENODATA;    }    if ( (query->qtype == srv_type) && (find_num_match(query->domain, dnsmsg->m_answers, QT_SRV) == 0) )    {        return ENODATA;    }        DNSC_DEBUG("exit - success\n");        return ESUCCESS;}   /* end dns_XX_negative_replycheck() */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -