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

📄 dns_client_cache.c

📁 DNS 的实现代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* ############################################################################ (c) Copyright Virata Limited 2001 ## Virata Limited Confidential and Proprietary## The following software source code ("Software") is strictly confidential and# is proprietary to Virata Limited ("Virata").  It may only be read, used,# copied, adapted, modified or otherwise dealt with by you if you have# entered into a confidentiality agreement with Virata and then subject to the# terms of that confidentiality agreement and any other applicable agreement# between you and Virata.  If you are in any doubt as to whether you are # entitled to access, read, use, copy, adapt, modify or otherwise deal with# the Software or whether you are entitled to disclose the Software to any# other person you should contact Virata.  If you have not entered into a# confidentiality agreement with Virata granting access to this Software you# should forthwith return all media, copies and printed listings containing# the Software to Virata. ## Virata reserves the right to take legal action against you should you breach# the above provisions.## If you are unsure, or to report violations, please contact # support@virata.com# ##########################################################################*//* * file:  dns_client_cache.c * * description: this file contains routines that will implement the cache *              for the resolver. * */#include "config.h"#include <stdio.h>#include <stdlib.h>   /* for atoi() */#include <string.h>#include "timelib.h"#include "errno.h"#include "dns_client_cache.h"#include "dns_client_resource.h"typedef struct {    int        slot;      /* slot or position in the list to install this element */    const char *name;     /* host or domain name */    int        num;       /* number of elements in the list of RRs */    DnsRRec    *RR;       /* array of RR (resource records) */    int        match;     /* number of RRs in the list that match the name */    U32        ttl;       /* time to live for this entry */    U16        auth;      /* was the NS who sent this an authority or not */    U16        ns;        /* is this entry for a NS (name server) */} MatchRec;static HostRecord  *hostRR[DNS_RRMAXENTRYS];static XX_CacheEnt *Local_XX_Cache[DNS_MAX_XX_LOCAL_ENT]; static void add_host2cache(int, DnsRRec *, int);static void add_ns2cache(DnsRRec *, int, DnsRRec *);static void add_cname2cache(DnsRRec *, DnsRRec *, DnsRRec *, int);static void add_ptr2cache(DnsRRec *, int);static void add_negative2cache(DnsMsg *);static int  get_slot(void);static void free_slot(int);static int  search_byname(const char *);static int search_bynametype(IN const char *name, IN int type);static int  search_byaddr(const char *);static int  install_matching_records(MatchRec *, int type);static void  print_hostrecord(HostRecord *hr);#ifdef DNS_DEBUGvoid  print_cache_resource(void);void  print_rlist(DnsRRec *list);#endifstatic int add2listfrommatch(const char *domain, U16 type, DnsRRec **head, DnsRRec *list);static int copy_RR(DnsRRec *to, DnsRRec *from);static DnsRRec *create_RR_list(int num, int size);#ifdef DNS_DEBUGextern void  print_resource_record(DnsRRec *);#endifstatic void add_RR_to_XX_cache(int num, DnsRRec *answers, int authority) ; static int  get_XX_cache_slot(void); static void free_XX_cache_slot(int i); static void print_rrdata(DnsRRec *rr);/* * dns_query_cache_byname() * * this routine will search our list using the name.  if an element is found * what we do depends on what the element is.  if it a CNAME type, that means * the name we searched for is just an alias.  we fill in a CNAME RR.  then * we need to search the cache list for the actual host name, the canonical * name.  if found, we then must create additional RRs for this information. * if not a CNAME type then we will just have answer RRs. * * return:  0 for success and *         -1 to indicate an error, (which will be a memory allocation error) */intdns_query_cache_byname(const char *domain, DnsMsg *reply){    int         i, index;    DnsRRec     *answers, *additions, *rr;    HostRecord  *hptr;    if ((index = search_bynametype(domain, QT_A)) < 0)         return -1;    /*      * first see if the entry is for a NAME ERROR, that is does it     * indicate the name doesn't exist.  if so just set the flag in the     * DnsMsg header and return. then we need to see if this is a CNAME     * entry.  if it is, then we search our list to see if we have an      * entry for the actual host name. allocate space for the answer,      * and fill it in.     */    reply->m_dnshdr.nquest = reply->m_dnshdr.nauthrr = reply->m_dnshdr.naddrr = 0;    hptr = hostRR[index];    if ( hptr->nerrflag ) {                      /* name error */        reply->m_dnshdr.flags = DNS_NAMEERR;	return 0;    }    if ( hptr->cflag ) {                         /* cname */        if ((answers = dns_get_RR()) == NULL) {            dprintf("%C allocation error cache query\n");#ifdef DNS_DEBUG            print_resource_pool();#endif            return -1;        }        strcpy(answers->r_dname, hptr->hostname);  /* copy the alias, same as domain */        answers->r_datalen = strlen(hptr->cname) + 1;        if ((answers->r_data = dns_dalloc(answers->r_datalen)) == NULL) {            dprintf("%C allocation error cache query\n");#ifdef DNS_DEBUG            print_resource_pool();#endif            dns_free_RR(answers);            return -1;        }        strcpy((char*)answers->r_data, hptr->cname);     /* copy the actual host name */        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_A)) >= 0) {            if ( hostRR[index]->cflag ) {                dprintf("%C error CNAME cycle for %s\n", hptr->hostname);                /* something to consider: may want to flush these entries                  * if there is a CNAME cycle                  */                dns_dfree(answers->r_data, answers->r_datalen);                dns_free_RR(answers);                return -1;            }            hptr = hostRR[index];            /* note that create_RR_list() allocates space for the r_data too.             * it fails if it cannot create the entire list.             */            if ((additions = create_RR_list(hptr->naddr, IPSIZE)) == 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_INET) {                    memcpy(rr->r_data,                            &((struct sockaddr_in *)                             &hptr->ipaddr[i])->sin_addr,                           sizeof(U32));                    strcpy(rr->r_dname, hptr->hostname);                    rr->r_type = QT_A;                    rr->r_class = QC_IN;                    rr->r_ttl = hptr->ttl;                    rr->r_datalen = IPSIZE;                }                i++;                rr = rr->r_next;            }            reply->m_dnshdr.naddrr = hptr->naddr;            reply->m_additionals = additions;        }        reply->m_dnshdr.nansrr = 1;        reply->m_answers = answers;        return 0;    }    /*      * okay, not a CNAME, format the response.  this case we just have      * answer records that are of the A 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, IPSIZE)) == NULL) {        dprintf("%C allocation error cache query\n");        return -1;    }    i = 0;    rr = answers;    while ( rr != NULL ) {        if (hptr->ipaddr[i].__ss_family == AF_INET)        {            memcpy(rr->r_data, &((struct sockaddr_in *)&hptr->ipaddr[i])                   ->sin_addr, sizeof(U32));            strcpy(rr->r_dname, hptr->hostname);            rr->r_type = QT_A;            rr->r_class = QC_IN;            rr->r_ttl = hptr->ttl;            rr->r_datalen = IPSIZE;        }        rr = rr->r_next;        i++;    }    reply->m_dnshdr.nansrr = hptr->naddr;    reply->m_answers = answers;    return 0;}   /* end dns_query_cache_byname() *//* * dns_query_cache_byaddr() * * this routine searches the cache list for an entry using the address.  the * address as we receive it is converted for a DNS query.  for example: * 11.22.33.44 becomes 44.33.22.11.in-addr.arpa.  it is converted back by * the search routine.  we don't have to worry about CNAME records here because * they don't have addresses associated with them.  if we find the record we're * looking for we just have to format it. * * return:  0 for success and *         -1 to indicate we didn't find it, or an error,  *            (which will be a memory allocation error) */intdns_query_cache_byaddr(const char *addr, DnsMsg *reply){    int         index;    DnsRRec     *answer;    HostRecord  *hptr;    if ((index = search_byaddr(addr)) < 0)         return -1;    reply->m_dnshdr.nquest = reply->m_dnshdr.nauthrr = reply->m_dnshdr.naddrr = 0;    hptr = hostRR[index];    /* we have to check to see if the entry is for a negative reply, if so     * then set the name error bit in the flag and return.     */    if ( hptr->nerrflag ) {        reply->m_dnshdr.flags = DNS_NAMEERR;	return 0;    }    if ((answer = dns_get_RR()) == NULL) {        dprintf("%C allocation error acquiring new RR\n");#ifdef DNS_DEBUG        print_resource_pool();#endif        return -1;    }    answer->r_datalen = strlen(hptr->hostname) + 1;    if ((answer->r_data = dns_dalloc(answer->r_datalen)) == NULL) {        dprintf("%C allocation error attempting to get data space\n");#ifdef DNS_DEBUG        print_resource_pool();#endif        free(answer);        return -1;    }    strcpy(answer->r_dname, addr);    strcpy((char*)answer->r_data, hptr->hostname);    answer->r_type = QT_PTR;    answer->r_class = QC_IN;    answer->r_ttl = hptr->ttl;    reply->m_dnshdr.nansrr = 1;    reply->m_answers = answer;    return 0;}   /* end dns_query_cache_byaddr() *//* * dns_query_cache_ns() * * this routine will attempt to find a name server, NS, entry matching the * domain name given.  if found we check to see that its not an outdated * entry and if it isn't fill in the NS_t structure with the matching entry's * data.  if the matching record is outdated we free it and return that we * didn't find anything.  note that names stored in our cache list are in * lower case so we convert the domain name to lowercase.  some strings returned * from a NS are in uppercase others in lowercase.  comparisons are supposed * to be case insensitive, see RFC 1034. * * return:  0 for success, and *         -1 to indicate an error. */intdns_query_cache_ns(const char *domain, NS_t *nsinfo){    int   i;    char  name[NAMEMAX+1];    BITS  now;    lowercase_copy(name, domain);    for ( i = 0; i < DNS_RRMAXENTRYS; i++ ) {        if ( 0 == hostRR[i] || !hostRR[i]->nsflag )            continue;        if ( strcmp(hostRR[i]->hostname, name) == 0 ) {            now = timer_secs();            if ((now - hostRR[i]->init_time) > hostRR[i]->ttl) {                free_slot(i);                continue;            }             strcpy(nsinfo->ns_name, hostRR[i]->hostname);            nsinfo->ns_addr = hostRR[i]->ipaddr[0];            nsinfo->ns_recursion = hostRR[i]->recursion;            nsinfo->ns_error = 0;            return 0;        }    }    return -1;}   /* end dns_query_cache_ns() *//* dns_query_cache_byname6 -- *     find IPv6 host address information in the cache  * * PARAMETERS *     question    - dns query to perform in cache *     reply       - resulting answer message * * RETURNS *     -1               there is no appropriate entry in the cache *     DNS_NEGATIVE     cache has nothing to say *     DNS_ANSWER       there is a direct answer *     DNS_CNAMEANSWER  it is a cname, but cache returns *                      results in additional RRs  *     DNS_CNAME        it is a cname, and cache does not *                      contain relevant IP.  */intdns_query_cache_byname6(IN DnsQuestion *question, OUT DnsMsg *reply){    int         i, index, ret_val;    DnsRRec     *answers, *additions, *rr;    HostRecord  *hPtr;    /* The search will be performed for both QT_AAAA and QT_A6 types */    if ((index = search_bynametype(question->q_name, QT_AAAA)) < 0)    {        return -1;    }    /*      * First see if the entry is for a NAME ERROR, that is does it     * indicate the name doesn't exist.  If so just set the flag in the     * DnsMsg header and return. Then we need to see if this is a CNAME     * entry.  If it is, then we search our list to see if we have an      * entry for the actual host name. Allocate space for the answer,      * and fill it in.     */    reply->m_dnshdr.nquest = reply->m_dnshdr.nauthrr = reply->m_dnshdr.naddrr = 0;    hPtr = hostRR[index];    if (hPtr->nerrflag)     {        reply->m_dnshdr.flags = DNS_NAMEERR;        return DNS_NEGATIVE;    }     if (hPtr->cflag)     {        if ((answers = dns_get_RR()) == NULL)         {            dprintf("%C allocation error cache query\n");#ifdef DNS_DEBUG            print_resource_pool();#endif            return -1;        }        strcpy(answers->r_dname, hPtr->hostname);  /* copy the alias, same as domain */        answers->r_datalen = strlen(hPtr->cname) + 1;        if ((answers->r_data = dns_dalloc(answers->r_datalen)) == NULL)         {            dprintf("%C allocation error cache query\n");#ifdef DNS_DEBUG            print_resource_pool();#endif            dns_free_RR(answers);            return -1;        }        strcpy((char*)answers->r_data, hPtr->cname);     /* copy the actual host name */

⌨️ 快捷键说明

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