📄 dns_client_cache.c
字号:
dns_free_rrlist(rrlist); continue; } rcnt += cnt; mrec.name =(char*) crec->r_data; mrec.num = rcnt; mrec.RR = rrlist; mrec.ttl = crec->r_ttl; mrec.auth = auth; mrec.ns = 0; install_matching_records(&mrec, type); dns_free_rrlist(rrlist); } } /* end add_cname2cache() *//* * add_ptr2cache() * * a PTR query is where we have an IP address and request the host name for * that address. the IP address is in a format used for the query and is * in the r_dname, domain name, section of the record, the host name is in * the r_data, or resource data section. we first see if the host name * already exists in the list, if so we only replace it if the new data is * from an authority and the current is not. */static voidadd_ptr2cache(DnsRRec *record, int auth){ int slot; int qtype; struct sockaddr_storage ipaddr; /* * first we determine the family of the address and hence the type of * the request we'll assign to the cache record */ convert_addr_arpa(record->r_dname, &ipaddr); if (ipaddr.__ss_family != AF_INET && ipaddr.__ss_family != AF_INET6) {#ifdef DNS_DEBUG dprintf("add_ptr2cache: queer reverse domain");#endif return; } if (ipaddr.__ss_family == AF_INET) { qtype = QT_A; } else { qtype = QT_AAAA; } /* * see if the host name is already in the list. if so, we only replace * it if the new data is from an authority and you current data is not. */ if ((slot = search_bynametype((char*)record->r_data, qtype)) >= 0) { if ( !(auth && !hostRR[slot]->authoritive) ) return; } else slot = get_slot(); if( slot == -1 ) return; lowercase_copy(hostRR[slot]->ptr_name[0], record->r_dname); lowercase_copy(hostRR[slot]->hostname, (char*)record->r_data); hostRR[slot]->ipaddr[0] = ipaddr; hostRR[slot]->used = hostRR[slot]->naddr = 1; hostRR[slot]->nsflag = hostRR[slot]->cflag = hostRR[slot]->recursion = 0; hostRR[slot]->authoritive = auth; hostRR[slot]->ttl = record->r_ttl; hostRR[slot]->init_time = timer_secs(); hostRR[slot]->type = qtype;} /* end add_ptr2cache() *//* * dns_add_AA2cache() * * here we look at the authority, or NS records, from the DNS reply. most of * the time, probably always, a DNS reply that gives NS records will also give * address records for them in the additional records. we look through the * NS records and see if there is an address record for it in the additional * records, if so we attempt to add it to our list. we have to see if the * data is currently in the cache, if so, then only replace it if this reply * is from an authoritive NS and the current data is not. */voiddns_add_AA2cache(DnsMsg *dmsg, int auth){ DnsRRec *nsrec; DnsRRec *addrec; int num; MatchRec mrec; nsrec = dmsg->m_authoritys; addrec = dmsg->m_additionals; num = dmsg->m_dnshdr.naddrr; while ( nsrec != NULL ) { int type; for (type = QT_A; type > 0; type = (type == QT_A ? QT_AAAA : (type == QT_AAAA ? QT_A6 : -1))) { mrec.match = find_num_match((char*)nsrec->r_data, addrec, type); if (mrec.match != 0) { /* if there is, see if the data is already in our list, if so * we only replace the data if we are the authority and the current * data is not. */ if ((mrec.slot = search_bynametype((char*)nsrec->r_data, type)) >= 0) { if ( !(auth && !hostRR[mrec.slot]->authoritive) ) continue; } else mrec.slot = get_slot(); if( mrec.slot == -1 ) return; mrec.name = (char*)nsrec->r_data; mrec.num = num; mrec.RR = addrec; mrec.ttl = nsrec->r_ttl; mrec.auth = auth; mrec.ns = 1; if (install_matching_records(&mrec, type) < 0) continue; } } nsrec = nsrec->r_next; } } /* end dns_add_AA2cache() */ /* * search_bynametype -- * This routine looks for a cache record of a particular type. * Note, type of returned record will not necessarily match * the requested type: the only restriction is that IPv4 and * IPv6 types are not mixed. * * PARAMETERS * name - domain name to find * type - type of record (see above note) * * RETURNS index of the position with a matching hostname, or * -1 to indicate there wasn't one. */static intsearch_bynametype(IN const char *name, IN int type){ int i; char copy[NAMEMAX+1]; BITS now; lowercase_copy(copy, name); for (i = 0; i < DNS_RRMAXENTRYS; i++) { /* * Skip records that don't contain a host name. This is possible * if we cached a name error record for a PTR query. */ if (!hostRR[i] || hostRR[i]->hostname[0] == '\0') continue; /* * About type: asking for address type (A, AAAA, A6) does * not imply exact matching of types. Rather, we only require * that IPv6 records not override IPv4 records. * However, other record types, (CNAME), require exact * type match. */ switch (type) { case QT_A: if (hostRR[i]->type == QT_AAAA || hostRR[i]->type == QT_A6) continue; break; case QT_AAAA: case QT_A6: if (hostRR[i]->type == QT_A) continue; break; default: if (hostRR[i]->type != type) continue; break; } /* * If we find a match, then great, but first we need to make * sure the record is not past its time to live. If the * record is outdated, we free it and continue the search. */ if (strcmp(hostRR[i]->hostname, copy) == 0) { now = timer_secs(); if ((now - hostRR[i]->init_time) > hostRR[i]->ttl) { free_slot(i); continue; } return i; } } return -1;} /* end search_bynametype() *//* * search_byname() * * this routine will just loop through the elements in the list. we compare * the hostname to the name given. all hostnames, and cnames, should be in * lower case in the list. we force the input string to be so. * * return: index of the position with a matching hostname, or * -1 to indicate there wasn't one. */static intsearch_byname(const char *name){ int i; char copy[NAMEMAX+1]; BITS now; lowercase_copy(copy, name); for ( i = 0; i < DNS_RRMAXENTRYS; i++ ) { /* skip records that don't contain a host name. this is possible * if we cached a name error record for a PTR query. */ if ( !hostRR[i] || hostRR[i]->hostname[0] == '\0' ) continue; /* * if we find a match, then great, but first we need to make * sure the record is not past its time to live. if the * record is outdated, we free it, quit the search and return * that we didn't find it. */ if ( strcmp(hostRR[i]->hostname, copy) == 0 ) { now = timer_secs(); if ((now - hostRR[i]->init_time) > hostRR[i]->ttl) { free_slot(i); break; } return i; } } return -1;} /* end search_byname() *//* * search_byaddr() * * this routine will search the list for an IP address. we get the address as * an inverted string, in the format used for DNS queries, for example: * IP = 12.23.34.55 would look like "55.34.23.12.in-addr.arpa". * we convert it back for the search. * if there is more that one IP address with an entry we * search the list. note that we need to verify that the record is not outdated * before we return it. if its outdated we free that record and quit the search. * pab note: convertion of IPv6 ".ip6.int" and ".ip6.arpa" is also included. * * return: index of the matching HostRecord, or * -1 to indicate not found. */static intsearch_byaddr(const char *addr){ int i, j; struct sockaddr_storage ip; BITS now; convert_addr_arpa(addr, &ip); for ( i = 0; i < DNS_RRMAXENTRYS; i++ ) { if ( !hostRR[i] ) continue; /* * search the list of IP addresses. if we find a match, that's the * one we're looking for. first determine if its outdated and if * so, free it and return we didn't find the information we were * looking for. */ for ( j = 0; j < hostRR[i]->naddr; j++ ) { if ( SOCKEQUAL(&ip, &hostRR[i]->ipaddr[j]) ) { now = timer_secs(); if ((now - hostRR[i]->init_time) > hostRR[i]->ttl) { free_slot(i); return -1; } return i; } } } return -1;} /* end search_byaddr() *//* * dns_flush_resolver_cache() * * this routine will release all entries in the cache. */voiddns_flush_resolver_cache(){ int i; for ( i = 0; i < DNS_RRMAXENTRYS; i++ ) { if ( !hostRR[i] ) continue; else free_slot(i); }} /* end dns_flush_resolver_cache() *//* dns_flush_resolver_entry6 -- * This routine searches for the entry with hostname matching name. * If an IPv6 entry is found the entry is freed. * * PARAMETERS * name - domain name of to flush * * RETURNS * n/a */voiddns_flush_resolver_entry6(IN const char *name){ int index; if ((index = search_bynametype(name, QT_AAAA)) >= 0) free_slot(index);} /* end dns_flush_resolver_entry6() *//* * dns_flush_resolver_entry() * * this routine searches for the entry with hostname matching name. if * found the entry is freed. * * pab note: this routine will not flush an IPv6 entry */voiddns_flush_resolver_entry(const char *name){ int index; if ((index = search_byname(name)) >= 0 && hostRR[index]->type != QT_AAAA && hostRR[index]->type != QT_A6) free_slot(index);} /* end dns_flush_resolver_entry() *//* * dns_flush_resolver_entry_ip() * * this routine searches for an entry by using an IP address. if the entry * is found it is freed. to use search_byaddr() it is necessary to invert the * IP address as would be done in a PTR query. */voiddns_flush_resolver_entry_ip(U32 ip){ char ipaddr[NAMEMAX+1]; int index; reverse_ip_addr(ip, ipaddr); if ((index = search_byaddr(ipaddr)) >= 0) free_slot(index);} /* end dns_flush_resolver_entry_ip() *//* * dns_flush_resolver_entry_ip6 -- * This routine searches for an entry by using an IPv6 address. * If the entry is found it is freed. To use search_byaddr() it * is necessary to invert the IP address as would be done in a PTR query. * * PARAMETERS * ip - IPv6 address of entry to be flushed * * RETURNS * n/a */voiddns_flush_resolver_entry_ip6(IN struct in6_addr *ip){ char ipaddr[NAMEMAX+1]; int index; struct sockaddr_storage tmp; data2sock(&tmp, ip);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -