📄 dns_client_cache.c
字号:
/* 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 + -