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

📄 dns_client_cache.c

📁 DNS 的实现代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* find a place to put the name error.  if its already in the cache     * we'll over write it.     */    if ( dmsg->m_questions )    {        if ( dmsg->m_questions->q_type == QT_A ||              dmsg->m_questions->q_type == QT_AAAA ||             dmsg->m_questions->q_type == QT_A6) {            if ((index = search_bynametype(dmsg->m_questions->q_name,                                            dmsg->m_questions->q_type)) < 0)                 index = get_slot();        }        else {            if ((index = search_byaddr(dmsg->m_questions->q_name)) < 0)                index = get_slot();        }    }    if( index == -1 )        return;    ttl = MIN(rr->r_ttl, srec->s_minimum);    ttl = MIN(ttl, DNS_MAXNERRTTL);    hptr = hostRR[index];    hptr->authoritive = hptr->used = 1;    hptr->recursion = hptr->nsflag = hptr->cflag = 0;    hptr->nerrflag = 1;    hptr->ttl = ttl;    hptr->init_time = timer_secs();    if ( dmsg->m_questions->q_type == QT_A ||          dmsg->m_questions->q_type == QT_AAAA ||         dmsg->m_questions->q_type == QT_A6) {        lowercase_copy(hptr->hostname, dmsg->m_questions->q_name);	hptr->ptr_name[0][0] = '\0';	hptr->naddr = 0;        memset(hptr->ipaddr + 0, 0, sizeof(struct sockaddr_storage));        hptr->ipaddr[0].__ss_family =             dmsg->m_questions->q_type == QT_A ? AF_INET : AF_INET6;        hptr->type = QT_A;    }    else {        hptr->hostname[0] = '\0';	hptr->naddr = 1;        convert_addr_arpa(dmsg->m_questions->q_name, &hptr->ipaddr[0]);	lowercase_copy(hptr->ptr_name[0], dmsg->m_questions->q_name);    }}   /* end add_negative2cache() *//* * add_host2cache() * * in this case we're dealing with A, AAAA and A6 records.  here we've asked * for the address of a host.  the records have the IP address in the resource * data section of the record.  note that even though its unlikely, there is a  * possibility the data is in the list already, so we must handle that case.   * if the data is already there we replace it unless our information is not  * considered authoritative and the information already here is.  if not present,  * we find the best position, slot, to put it.  "best" is considered the first  * empty position or a position with dated data or we replace the oldest information  * in the list.  note that we don't free the current information until we know  * we have space for the new data.  that way if there's a memory problem we at  * least still have the old data. */static voidadd_host2cache(int num, DnsRRec *answers, int authority){    MatchRec  mrec;    int type;        type = answers->r_type;       /*     * first we see if this is already in the list.  this should not      * happen often, but it is possible.  the search never returns out     * dated data.  we replace the information everytime, unless our     * information is not from an authoritive NS and the current data     * says it is.  if not already in the list find the best slot to     * put it in.     */    if ((mrec.slot = search_bynametype(answers->r_dname, type)) >= 0) {        if ( !authority && hostRR[mrec.slot]->authoritive )   /* don't replace */           return;    }    else         mrec.slot = get_slot();    if( mrec.slot == -1 )        return;    mrec.match = find_num_match(answers->r_dname, answers, type);    mrec.name = answers->r_dname;    mrec.num = num;    mrec.RR = answers;    mrec.ttl = answers->r_ttl;    mrec.auth = authority;    mrec.ns = 0;        install_matching_records(&mrec, type);}   /* end add_host2cache() *//* * get_slot() * * Allocate memory for a new HostRecord in the cache. Also take * the opportunity to free up slots that contain any out-of-date * entries. */static intget_slot(){    int   i;    BITS  temp = 0xFFFFFFFF;    int   oldest = -1;    BITS  now;    now = timer_secs();    for ( i = 0; i < DNS_RRMAXENTRYS; i++ ) {        if ( !hostRR[i] )        {            hostRR[i] = (HostRecord *)malloc(sizeof(HostRecord));            if( hostRR[i] )            {                memset( hostRR[i], 0, sizeof(HostRecord));                return i;            }            else            {                return -1;            }            // Otherwise we'll end up using the oldest entry        }        // Free up any out-of-date entries        if ((now - hostRR[i]->init_time) > hostRR[i]->ttl) {            free_slot(i);        }        else if ( hostRR[i]->init_time < temp ) {            temp = hostRR[i]->init_time;            oldest = i;        }    }    if( oldest != -1 )    {        if( !hostRR[oldest] )        {            hostRR[i] = (HostRecord *)malloc(sizeof(HostRecord));        }        if( hostRR[oldest] )        {            memset( hostRR[oldest], 0, sizeof(HostRecord));            return oldest;            }    }    return -1;}   /* end get_slot() *//* * add_ns2cache() * * this routine will add the information for an NS record.  an NS record * has the name of an NS in the resource data section of the record.  we need * to look through the additional records for an A, (address), record for it. * if its there we attempt to add it to our list.  an NS record is where the * name server we asked is telling us to try another one instead.  we have to * check for the case of the data already being in our list, if there we * replace it unless it is authoritative.  if not there we find the best slot * to install it.  note that we don't check the answer records for the address. */static voidadd_ns2cache(DnsRRec *nsrecord, int num, DnsRRec *addrecords){    MatchRec mrec;    int type;    for (type = QT_A; type > 0;         type = (type == QT_A ? QT_AAAA : (type == QT_AAAA ? QT_A6 : -1)))    {        if ((mrec.match = find_num_match((char *)nsrecord->r_data, addrecords,             type)) == 0)             continue;                /* see if its already in the list */                if ((mrec.slot = search_byname((const char *)nsrecord->r_data)) >= 0) {            if ( hostRR[mrec.slot]->authoritive )                continue;        }        else             mrec.slot = get_slot();        if( mrec.slot == -1 )            return;                    mrec.name = (char*)nsrecord->r_data;        mrec.num = num;        mrec.RR = addrecords;        mrec.ttl = nsrecord->r_ttl;        mrec.auth = 0;        mrec.ns = 1;        install_matching_records(&mrec, type);    } }   /* end add_ns2cache() *//* * install_matching_records() * * this routine is used to install information when its necessary to look * through a set of resource records for matching data.  for example when * we have an NS record and want the A record from the additional records * in the DNS message. * * pab: note: this routine only installs records of type 'type' * * return:  0 for success, and *         -1 to indicate error. */static intinstall_matching_records(MatchRec *mrec, int type){    int      i, numip;    DnsRRec  *rr;    if( hostRR[mrec->slot] )    {        /* free up the old data, must be called */        memset( hostRR[mrec->slot], 0, sizeof(HostRecord));           }    else    {        mrec->slot = get_slot();        if( mrec->slot == -1 )            return -1;    }    /*      * create the list of IP addresses.  if match is the same as the      * number of RRs then just loop through the entire list. if not,      * we have to get the ones that do match.     */    if ( mrec->match == mrec->num ) {        numip = 0;        rr = mrec->RR;        while ( rr != NULL && numip < MAXIPENTRYS ) {            if (rr->r_type == type)            {                if (type == QT_AAAA || type == QT_A6)                {                    struct sockaddr_in6 *ipaddr = (struct sockaddr_in6 *)                        &hostRR[mrec->slot]->ipaddr[numip];                                        memset(ipaddr, 0, sizeof(struct sockaddr_storage));                    ipaddr->sin6_family = AF_INET6;                    memcpy(&ipaddr->sin6_addr, rr->r_data,                            sizeof(struct in6_addr));                }                else                {                    long2sock(&hostRR[mrec->slot]->ipaddr[numip],                               *(U32 *)rr->r_data);                }            }            numip++;            rr = rr->r_next;        }         hostRR[mrec->slot]->type = type;    }    else {        numip = 0;                rr = find_match_rrecord(mrec->name, mrec->RR, type);        while ( rr != NULL && numip < MAXIPENTRYS ) {            if (type == QT_AAAA || type == QT_A6) {                struct sockaddr_in6 *ipaddr =                     (struct sockaddr_in6 *)&hostRR[mrec->slot]->ipaddr[numip];                                memset(ipaddr, 0, sizeof(struct sockaddr_storage));                ipaddr->sin6_family = AF_INET6;                memcpy(&ipaddr->sin6_addr, rr->r_data, sizeof(struct in6_addr));            }            else {                long2sock(&hostRR[mrec->slot]->ipaddr[numip], *(U32 *)rr->r_data);            }            numip++;            rr = find_match_rrecord(mrec->name, rr->r_next, type);        }         hostRR[mrec->slot]->type = type;        if ( 0 == numip ) {            dprintf("%C error unexpected lack of matching RRs\n");            free_slot(mrec->slot);       /* free up the old data, must be called */            return -1;        }    }    /*      * okay, create the list of PTR name, inverted IP address with      * "in-addr.arpa." on the end.     */    for ( i = 0; i < numip; i++ )         reverse_sockaddr_arpa(&hostRR[mrec->slot]->ipaddr[i],                               hostRR[mrec->slot]->ptr_name[i]);    /* fill in the rest of the elements */    lowercase_copy(hostRR[mrec->slot]->hostname, mrec->name);    hostRR[mrec->slot]->cname[0] = '\0';    hostRR[mrec->slot]->used = 1;    hostRR[mrec->slot]->cflag = hostRR[mrec->slot]->recursion = 0;    hostRR[mrec->slot]->naddr = numip;    hostRR[mrec->slot]->init_time = timer_secs();    hostRR[mrec->slot]->ttl = mrec->ttl;    hostRR[mrec->slot]->authoritive = mrec->auth;    hostRR[mrec->slot]->nsflag = mrec->ns;    return 0;}   /* end install_matching_record() *//* * add_cname2cache() * * a CNAME record is where we asked for the address of a name that turned * out to be an alias.  the CNAME record gives the canonical name for the * host in its resource data section.  we want to cache the alias and if * the address is provided for the canonical name we want to install that * also.  we first see if the alias, which is the domain part of the CNAME * record, is already in our list.  if so, we replace it unless the current * information is from an authoritative NS and our current information is * not.  next, if the NS provided us with the address of the actual host name * in the additional records we install that in our list also. */static voidadd_cname2cache(DnsRRec *crec, DnsRRec *arec, DnsRRec *addrec, int auth){    int      slot, cnt, rcnt = 0;    DnsRRec *rrlist;    MatchRec mrec;    int      type;      /*      * okay, this is a little ugly.  if there's currently an entry for this     * we want to replace it unless we're not the authority and the current     * information says it is.  otherwise we just find a slot and put it     * there.     */    if ((slot = search_byname(crec->r_dname)) >= 0) {        if ( !(!auth && hostRR[slot]->authoritive) ) {            memset(hostRR[slot], 0, sizeof(HostRecord));            hostRR[slot]->cflag = hostRR[slot]->used = 1;            hostRR[slot]->nsflag = 0;            hostRR[slot]->authoritive = auth;            lowercase_copy(hostRR[slot]->cname, (char*)crec->r_data);      /* real host name */            lowercase_copy(hostRR[slot]->hostname, crec->r_dname);  /* alias */            hostRR[slot]->ttl = crec->r_ttl;            hostRR[slot]->init_time = timer_secs();            hostRR[slot]->type = QT_CNAME;        }    }    else {        slot = get_slot();        if( slot == -1 )            return;        hostRR[slot]->cflag = hostRR[slot]->used = 1;        hostRR[slot]->nsflag = 0;        hostRR[slot]->authoritive = auth;        lowercase_copy(hostRR[slot]->cname,(char*) crec->r_data);          /* real host name */        lowercase_copy(hostRR[slot]->hostname, crec->r_dname);      /* alias */        hostRR[slot]->ttl = crec->r_ttl;        hostRR[slot]->init_time = timer_secs();        hostRR[slot]->type = QT_CNAME;    }    /*     * now see if there are any records that have the address of the CNAME.  the     * information should be in the additional records but can also be in the     * answer records so we have to check there first.     */    type = QT_A;    for (type = QT_A;          type > 0;         type = (type == QT_A ? QT_AAAA : (type == QT_AAAA ? QT_A6 : -1)))    {         rcnt = find_num_match((char*)crec->r_data, arec, type);        rcnt += find_num_match((char*)crec->r_data, addrec, type);        if (rcnt == 0)             continue;        /*         * we have some records, find a slot to put this information in.  first         * we see if the record already exist.  if it does we replace it unless         * the current data is authoritive and the new is not.         */        if ((mrec.slot = search_bynametype((char*)crec->r_data, type)) >= 0) {            if ( !auth && hostRR[slot]->authoritive )   /* don't replace */                continue;        }        else             mrec.slot = get_slot();        if( mrec.slot == -1 )            return;                /* create a list of matching A records */                rrlist = NULL;        if ((rcnt = add2listfrommatch((char*)crec->r_data, type, &rrlist, arec)) < 0) {            dprintf("%C error creating address list for CNAME cache\n");            continue;        }        if ((cnt = add2listfrommatch((char*)crec->r_data, type, &rrlist, addrec)) < 0) {            dprintf("%C error creating address list for CNAME\n");

⌨️ 快捷键说明

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