-
-static size_t calc_hostent_buffer_size(const struct hostent* hp)
-{
- char** p;
- size_t count = 0;
- assert(0 != hp);
-
- /*
- * space for name
- */
- count += (strlen(hp->h_name) + 1);
- /*
- * space for aliases
- */
- for (p = hp->h_aliases; *p; ++p)
- count += (strlen(*p) + 1 + sizeof(char*));
- /*
- * space for addresses
- */
- for (p = hp->h_addr_list; *p; ++p)
- count += (hp->h_length + sizeof(char*));
- /*
- * space for 2 nulls to terminate h_aliases and h_addr_list
- */
- count += (2 * sizeof(char*));
- return count;
-}
-
-
-/*
- * dup_hostent - Duplicate a hostent struct, allocate only enough memory for
- * the data we're putting in it.
- */
-static void dup_hostent(struct Hostent* new_hp, struct hostent* hp)
-{
- char* p;
- char** ap;
- char** pp;
- int alias_count = 0;
- int addr_count = 0;
- size_t bytes_needed = 0;
-
- assert(0 != new_hp);
- assert(0 != hp);
-
- /* how much buffer do we need? */
- bytes_needed += (strlen(hp->h_name) + 1);
-
- pp = hp->h_aliases;
- while (*pp) {
- bytes_needed += (strlen(*pp++) + 1 + sizeof(char*));
- ++alias_count;
- }
- pp = hp->h_addr_list;
- while (*pp++) {
- bytes_needed += (hp->h_length + sizeof(char*));
- ++addr_count;
- }
- /* Reserve space for 2 nulls to terminate h_aliases and h_addr_list */
- bytes_needed += (2 * sizeof(char*));
-
- /* Allocate memory */
- new_hp->buf = (char*) MyMalloc(bytes_needed);
-
- new_hp->h.h_addrtype = hp->h_addrtype;
- new_hp->h.h_length = hp->h_length;
-
- /* first write the address list */
- pp = hp->h_addr_list;
- ap = new_hp->h.h_addr_list =
- (char**)(new_hp->buf + ((alias_count + 1) * sizeof(char*)));
- p = (char*)ap + ((addr_count + 1) * sizeof(char*));
- while (*pp)
- {
- *ap++ = p;
- memcpy(p, *pp++, hp->h_length);
- p += hp->h_length;
- }
- *ap = 0;
- /* next write the name */
- new_hp->h.h_name = p;
- strcpy(p, hp->h_name);
- p += (strlen(p) + 1);
-
- /* last write the alias list */
- pp = hp->h_aliases;
- ap = new_hp->h.h_aliases = (char**) new_hp->buf;
- while (*pp) {
- *ap++ = p;
- strcpy(p, *pp++);
- p += (strlen(p) + 1);
- }
- *ap = 0;
-}
-
-/*
- * update_hostent - Add records to a Hostent struct in place.
- */
-static void update_hostent(struct Hostent* hp, char** addr, char** alias)
-{
- char* p;
- char** ap;
- char** pp;
- int alias_count = 0;
- int addr_count = 0;
- char* buf = NULL;
- size_t bytes_needed = 0;
-
- if (!hp || !hp->buf)
- return;
-
- /* how much buffer do we need? */
- bytes_needed = strlen(hp->h.h_name) + 1;
- pp = hp->h.h_aliases;
- while (*pp) {
- bytes_needed += (strlen(*pp++) + 1 + sizeof(char*));
- ++alias_count;
- }
- if (alias) {
- pp = alias;
- while (*pp) {
- bytes_needed += (strlen(*pp++) + 1 + sizeof(char*));
- ++alias_count;
- }
- }
- pp = hp->h.h_addr_list;
- while (*pp++) {
- bytes_needed += (hp->h.h_length + sizeof(char*));
- ++addr_count;
- }
- if (addr) {
- pp = addr;
- while (*pp++) {
- bytes_needed += (hp->h.h_length + sizeof(char*));
- ++addr_count;
- }
- }
- /* Reserve space for 2 nulls to terminate h_aliases and h_addr_list */
- bytes_needed += 2 * sizeof(char*);
-
- /* Allocate memory */
- buf = (char*) MyMalloc(bytes_needed);
- assert(0 != buf);
-
- /* first write the address list */
- pp = hp->h.h_addr_list;
- ap = hp->h.h_addr_list =
- (char**)(buf + ((alias_count + 1) * sizeof(char*)));
- p = (char*)ap + ((addr_count + 1) * sizeof(char*));
- while (*pp) {
- memcpy(p, *pp++, hp->h.h_length);
- *ap++ = p;
- p += hp->h.h_length;
- }
- if (addr) {
- while (*addr) {
- memcpy(p, *addr++, hp->h.h_length);
- *ap++ = p;
- p += hp->h.h_length;
- }
- }
- *ap = 0;
-
- /* next write the name */
- strcpy(p, hp->h.h_name);
- hp->h.h_name = p;
- p += (strlen(p) + 1);
-
- /* last write the alias list */
- pp = hp->h.h_aliases;
- ap = hp->h.h_aliases = (char**) buf;
- while (*pp) {
- strcpy(p, *pp++);
- *ap++ = p;
- p += (strlen(p) + 1);
- }
- if (alias) {
- while (*alias) {
- strcpy(p, *alias++);
- *ap++ = p;
- p += (strlen(p) + 1);
- }
- }
- *ap = 0;
- /* release the old buffer */
- p = hp->buf;
- hp->buf = buf;
- MyFree(p);
-}
-
-/*
- * hash_number - IP address hash function
- */
-static int hash_number(const unsigned char* ip)
-{
- /* could use loop but slower */
- unsigned int hashv;
- const u_char* p = (const u_char*) ip;
-
- assert(0 != p);
-
- hashv = *p++;
- hashv += hashv + *p++;
- hashv += hashv + *p++;
- hashv += hashv + *p;
- hashv %= ARES_CACSIZE;
- return hashv;
-}
-
-/*
- * hash_name - hostname hash function
- */
-static int hash_name(const char* name)
-{
- unsigned int hashv = 0;
- const u_char* p = (const u_char*) name;
-
- assert(0 != p);
-
- for (; *p && *p != '.'; ++p)
- hashv += *p;
- hashv %= ARES_CACSIZE;
- return hashv;
-}
-
-/*
- * add_to_cache - Add a new cache item to the queue and hash table.
- */
-static struct CacheEntry* add_to_cache(struct CacheEntry* ocp)
-{
- int hashv;
-
- assert(0 != ocp);
-
- ocp->list_next = cacheTop;
- cacheTop = ocp;
-
- hashv = hash_name(ocp->he.h.h_name);
-
- ocp->hname_next = hashtable[hashv].name_list;
- hashtable[hashv].name_list = ocp;
-
- hashv = hash_number((const unsigned char*) ocp->he.h.h_addr);
-
- ocp->hnum_next = hashtable[hashv].num_list;
- hashtable[hashv].num_list = ocp;
-
- /*
- * LRU deletion of excessive cache entries.
- */
- if (++cachedCount > MAXCACHED) {
- struct CacheEntry* cp;
- struct CacheEntry* cp_next;
- for (cp = ocp->list_next; cp; cp = cp_next) {
- cp_next = cp->list_next;
- rem_cache(cp);
- }
- }
- ++cainfo.ca_adds;
- return ocp;
-}
-
-/*
- * update_list - does not alter the cache structure passed. It is assumed that
- * it already contains the correct expire time, if it is a new entry. Old
- * entries have the expirey time updated.
-*/
-static void update_list(struct ResRequest* request, struct CacheEntry* cachep)
-{
- struct CacheEntry* cp = cachep;
- char* s;
- char* t;
- int i;
- int j;
- char** ap;
- char* addrs[RES_MAXADDRS + 1];
- char* aliases[RES_MAXALIASES + 1];
-
- /*
- * search for the new cache item in the cache list by hostname.
- * If found, move the entry to the top of the list and return.
- */
- ++cainfo.ca_updates;
-
- if (!request)
- return;
- /*
- * Compare the cache entry against the new record. Add any
- * previously missing names for this entry.
- */
- *aliases = 0;
- ap = aliases;
- for (i = 0, s = request->he.h.h_name; s; s = request->he.h.h_aliases[i++]) {
- for (j = 0, t = cp->he.h.h_name; t; t = cp->he.h.h_aliases[j++]) {
- if (0 == ircd_strcmp(t, s))
- break;
- }
- if (!t) {
- *ap++ = s;
- *ap = 0;
- }
- }
- /*
- * Do the same again for IP#'s.
- */
- *addrs = 0;
- ap = addrs;
- for (i = 0; (s = request->he.h.h_addr_list[i]); i++) {
- for (j = 0; (t = cp->he.h.h_addr_list[j]); j++) {
- if (!memcmp(t, s, sizeof(struct in_addr)))
- break;
- }
- if (!t) {
- *ap++ = s;
- *ap = 0;
- }
- }
- if (*addrs || *aliases)
- update_hostent(&cp->he, addrs, aliases);
-}
-
-/*
- * find_cache_name - find name in nameserver cache
- */
-static struct CacheEntry* find_cache_name(const char* name)
-{
- struct CacheEntry* cp;
- char* s;
- int hashv;
- int i;
-
- assert(0 != name);
- hashv = hash_name(name);
-
- cp = hashtable[hashv].name_list;
-
- for (; cp; cp = cp->hname_next) {
- for (i = 0, s = cp->he.h.h_name; s; s = cp->he.h.h_aliases[i++]) {
- if (0 == ircd_strcmp(s, name)) {
- ++cainfo.ca_na_hits;
- return cp;
- }
- }
- }
-
- for (cp = cacheTop; cp; cp = cp->list_next) {
- /*
- * if no aliases or the hash value matches, we've already
- * done this entry and all possiblilities concerning it.
- */
- if (!cp->he.h.h_name || hashv == hash_name(cp->he.h.h_name))
- continue;
- for (i = 0, s = cp->he.h.h_aliases[i]; s; s = cp->he.h.h_aliases[++i]) {
- if (0 == ircd_strcmp(name, s)) {
- ++cainfo.ca_na_hits;
- return cp;
- }
- }
- }
- return NULL;
-}
-
-/*
- * find_cache_number - find a cache entry by ip# and update its expire time
- */
-static struct CacheEntry* find_cache_number(struct ResRequest* request,
- const char* addr)
-{
- struct CacheEntry* cp;
- int hashv;
- int i;
-
- assert(0 != addr);
- hashv = hash_number((const unsigned char*) addr);
- cp = hashtable[hashv].num_list;
-
- for (; cp; cp = cp->hnum_next) {
- for (i = 0; cp->he.h.h_addr_list[i]; ++i) {
- if (!memcmp(cp->he.h.h_addr_list[i], addr, sizeof(struct in_addr))) {
- ++cainfo.ca_nu_hits;
- return cp;
- }
- }
- }
- for (cp = cacheTop; cp; cp = cp->list_next) {
- /*
- * single address entry...would have been done by hashed
- * search above...
- * if the first IP# has the same hashnumber as the IP# we
- * are looking for, its been done already.
- */
- if (!cp->he.h.h_addr_list[1] ||
- hashv == hash_number((const unsigned char*) cp->he.h.h_addr_list[0]))
- continue;
- for (i = 1; cp->he.h.h_addr_list[i]; ++i) {
- if (!memcmp(cp->he.h.h_addr_list[i], addr, sizeof(struct in_addr))) {
- ++cainfo.ca_nu_hits;
- return cp;
- }
- }
- }
- return NULL;
-}
-
-static struct CacheEntry* make_cache(struct ResRequest* request)
-{
- struct CacheEntry* cp;
- int i;
- struct hostent* hp;
- assert(0 != request);
-
- hp = &request->he.h;
- /*
- * shouldn't happen but it just might...
- */
- assert(0 != hp->h_name);
-/* assert(0 != hp->h_addr_list[0]); */
- if (!hp->h_name || !hp->h_addr_list[0])
- return NULL;
- /*
- * Make cache entry. First check to see if the cache already exists
- * and if so, return a pointer to it.
- */
- for (i = 0; hp->h_addr_list[i]; ++i) {
- if ((cp = find_cache_number(request, hp->h_addr_list[i]))) {
- update_list(request, cp);
- return cp;
- }
- }
- /*
- * a matching entry wasnt found in the cache so go and make one up.
- */
- cp = (struct CacheEntry*) MyMalloc(sizeof(struct CacheEntry));
- assert(0 != cp);
-
- memset(cp, 0, sizeof(struct CacheEntry));
- dup_hostent(&cp->he, hp);
- cp->reply.hp = &cp->he.h;
- /*
- * hmmm... we could time out the cache after 10 minutes regardless
- * would that be reasonable since we don't save the reply?
- */
-#if 0
- if (request->ttl < AR_TTL) {
- ++reinfo.re_shortttl;
- cp->ttl = AR_TTL;
- }
- else
- cp->ttl = request->ttl;
-#else
- cp->ttl = AR_TTL;
-#endif
- cp->expireat = CurrentTime + cp->ttl;
- return add_to_cache(cp);
-}
-
-/*
- * rem_cache - delete a cache entry from the cache structures
- * and lists and return all memory used for the cache back to the memory pool.
- */
-static void rem_cache(struct CacheEntry* ocp)
-{
- struct CacheEntry** cp;
- int hashv;
- struct hostent* hp;
- assert(0 != ocp);
-
-
- if (0 < ocp->reply.ref_count) {
- if (ocp->expireat < CurrentTime) {
- ocp->expireat = CurrentTime + AR_TTL;
- Debug((DEBUG_DNS, "Resolver: referenced cache entry not removed for: %s",
- ocp->he.h.h_name));
- }
- return;
- }
- /*
- * remove cache entry from linked list
- */
- for (cp = &cacheTop; *cp; cp = &((*cp)->list_next)) {
- if (*cp == ocp) {
- *cp = ocp->list_next;
- break;
- }
- }
- hp = &ocp->he.h;
- /*
- * remove cache entry from hashed name list
- */
- assert(0 != hp->h_name);
- hashv = hash_name(hp->h_name);
-
- for (cp = &hashtable[hashv].name_list; *cp; cp = &((*cp)->hname_next)) {
- if (*cp == ocp) {
- *cp = ocp->hname_next;
- break;
- }
- }
- /*
- * remove cache entry from hashed number list
- */
- hashv = hash_number((const unsigned char*) hp->h_addr);
- assert(-1 < hashv);
-
- for (cp = &hashtable[hashv].num_list; *cp; cp = &((*cp)->hnum_next)) {
- if (*cp == ocp) {
- *cp = ocp->hnum_next;
- break;
- }
- }
- /*
- * free memory used to hold the various host names and the array
- * of alias pointers.
- */
- MyFree(ocp->he.buf);
- MyFree(ocp);
- --cachedCount;
- ++cainfo.ca_dels;
-}
-
-void flush_resolver_cache(void)
-{
- /*
- * stubbed - iterate cache and remove everything that isn't referenced
- */
-}
-