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

📄 dns_client_cache.c

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