void dnscache_reset (dnscache_t *dnscache) { size_t i; if (dnscache->records) { for (i = 0; i < dnscache->used; i++) { buffer_free (&(dnscache->records[i].name)); rr_list_free (dnscache->records[i].rr_list, MAX_HOSTS); dnscache->records[i].nhosts = 0; } } dnscache->used = 0; }
void dnscache_free (dnscache_t *dnscache) { size_t i; if (dnscache->records) { for (i = 0; i < dnscache->used; i++) { buffer_free (&(dnscache->records[i].name)); rr_list_free (dnscache->records[i].rr_list, MAX_HOSTS); } free (dnscache->records); dnscache->records = NULL; } if (dnscache->index) { free (dnscache->index); dnscache->index = NULL; } dnscache->size = 0; dnscache->used = 0; }
static RRset *conv_trick_rrset (RRset *rrs_a, uint16_t qtype, int pref) { const char *fn = "conv_trick_rrset()"; RR_List *rrl = NULL, *rrl_tmp; RRset *rrs_new = NULL; RR *rr_a = NULL, *rr_new = NULL; u_char *rd, *rd_new = NULL; syslog (LOG_DEBUG, "%s: start", fn); /* parse A resource record set */ rrl = rr_list_of_rrset (rrs_a); if (!rrl) return NULL; /* convert each RR_List data */ for (rrl_tmp = rrl; rrl_tmp->next; rrl_tmp = rrl_tmp->next) { int rdlen; u_char *rd_addr; rr_a = rrl_tmp->rrp; rrl_tmp->rrp = NULL; /* kept in rr_a */ rd = rr_rdata (rr_a); rdlen = sizeof(struct in6_addr); if (qtype == RT_A6) rdlen++; /* size of prefix length */ rd_new = malloc (rdlen); if (!rd_new) break; rd_addr = (qtype == RT_AAAA) ? rd_new : (rd_new + 1); memcpy (rd_addr, T.prefix[pref], 12); memcpy (rd_addr + 12, rd, 4); if (qtype == RT_A6) *rd_new = 0; /* plen is 0 */ rr_new = rr_alloc (rr_a->ttl, rdlen, rd_new); if (!rr_new) break; free (rd_new); rd_new = NULL; /* kept in rr_new */ rrl_tmp->rrp = rr_new; rr_new = NULL; /* kept in rrl_tmp->rrp */ free (rr_a); rr_a = NULL; } /* assemble A6/AAAA rrset */ rrs_new = rrset_create (qtype, rrs_a->key.info->r_class, rrs_a->key.info->owner_len, rrset_owner (rrs_a), rrl); /* cleanup */ if (rr_a) free (rr_a); if (rr_new) free (rr_new); if (rrl) rr_list_free (rrl); if (rd_new) free (rd_new); return rrs_new; }
eDnsStatus dnscache_lookup (dnscache_t *dnscache, const char *dname, int type, size_t max_hosts, off_t *index, time_t current_time) { dnscache_entry_t *record; rr_t *rr_list; buffer_t name; unsigned int position; int min_ttl; int lookup; size_t len; size_t i; if (max_hosts > MAX_HOSTS) { return DNS_ERROR; } if (search (dnscache, dname, type, &position) < 0) { /* DNS cache miss. */ buffer_init (&name, 64); len = strlen (dname); if (buffer_allocate (&name, len + 1) < 0) { buffer_free (&name); return DNS_ERROR; } memcpy (name.data, dname, len + 1); name.used = len + 1; if (allocate (dnscache) < 0) { buffer_free (&name); return DNS_ERROR; } /* We might have emptied the cache. */ if (dnscache->used == 0) { position = 0; } record = &(dnscache->records[dnscache->used]); memcpy (&record->name, &name, sizeof (buffer_t)); record->type = type; record->timestamp = current_time; rr_list_init (record->rr_list, MAX_HOSTS); record->nhosts = 0; record->status = dns_lookup (dname, type, max_hosts, record->rr_list, &record->nhosts); *index = dnscache->used; if (position < dnscache->used) { memmove (&(dnscache->index[position + 1]), &(dnscache->index[position]), (dnscache->used - position) * sizeof (off_t)); } dnscache->index[position] = dnscache->used++; return record->status; } *index = dnscache->index[position]; record = &(dnscache->records[*index]); rr_list = record->rr_list; if ((record->status == DNS_HOST_NOT_FOUND) || (record->status == DNS_NO_DATA)) { if (record->timestamp + QUERY_MIN_INTERVAL >= current_time) { return record->status; } lookup = 1; } else if (record->status != DNS_SUCCESS) { lookup = 1; } else { /* Compute the minimum TTL. */ min_ttl = rr_list[0].ttl; for (i = 1; i < record->nhosts; i++) { if (rr_list[i].ttl < min_ttl) { min_ttl = rr_list[i].ttl; } } /* If the TTL has already expired... */ if (record->timestamp + min_ttl < current_time) { lookup = 1; } else { lookup = 0; } } if (lookup) { rr_list_free (rr_list, MAX_HOSTS); record->status = dns_lookup (dname, type, max_hosts, rr_list, &record->nhosts); record->timestamp = current_time; } return record->status; }