/* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)db_lookup.c 4.14.1 (2.11BSD GTE) 1/1/94"; #endif /* * Table lookup routines. */ #include #include #include #include "db.h" struct hashbuf *hashtab; /* root hash table */ struct hashbuf *fcachetab; /* hash table of cache read from file */ #ifdef DEBUG extern int debug; extern FILE *ddt; #endif /* * Lookup 'name' and return a pointer to the namebuf; * NULL otherwise. If 'insert', insert name into tables. * Wildcard lookups are handled. */ struct namebuf * nlookup(name, htpp, fname, insert) char *name; struct hashbuf **htpp; char **fname; int insert; { register struct namebuf *np; register char *cp; register int c; register unsigned hval; register struct hashbuf *htp; struct namebuf *parent = NULL; htp = *htpp; hval = 0; *fname = "???"; for (cp = name; c = *cp++; ) { if (c == '.') { parent = np = nlookup(cp, htpp, fname, insert); if (np == NULL) return (NULL); if (*fname != cp) return (np); if ((htp = np->n_hash) == NULL) { if (!insert) { if (np->n_dname[0] == '*' && np->n_dname[1] == '\0') *fname = name; return (np); } htp = savehash((struct hashbuf *)NULL); np->n_hash = htp; } *htpp = htp; break; } hval <<= HASHSHIFT; hval += c & HASHMASK; } c = *--cp; *cp = '\0'; /* * Lookup this label in current hash table. */ for (np = htp->h_tab[hval % htp->h_size]; np != NULL; np = np->n_next) { #ifdef ALLOW_UPDATES /* Note: at this point, if np->n_data is NULL, we could be in one of two situations: Either we have come across a name for which all the RRs have been (dynamically) deleted, or else we have come across a name which has no RRs associated with it because it is just a place holder (e.g., EDU). In the former case, we would like to delete the namebuf, since it is no longer of use, but in the latter case we need to hold on to it, so future lookups that depend on it don't fail. The only way I can see of doing this is to always leave the namebufs around (although then the memory usage continues to grow whenever names are added, and can never shrink back down completely when all their associated RRs are deleted). */ #endif ALLOW_UPDATES if (np->n_hashval == hval && strcasecmp(name, np->n_dname) == 0) { *cp = c; *fname = name; return (np); } } if (!insert) { /* * look for wildcard in this hash table */ hval = ('*' & HASHMASK) % htp->h_size; for (np = htp->h_tab[hval]; np != NULL; np = np->n_next) { if (np->n_dname[0] == '*' && np->n_dname[1] == '\0') { *cp = c; *fname = name; return (np); } } *cp = c; return (parent); } np = savename(name); np->n_parent = parent; np->n_hashval = hval; hval %= htp->h_size; np->n_next = htp->h_tab[hval]; htp->h_tab[hval] = np; /* increase hash table size */ if (++htp->h_cnt > htp->h_size * 2) { *htpp = savehash(htp); if (parent == NULL) { if (htp == hashtab) hashtab = *htpp; else fcachetab = *htpp; } else parent->n_hash = *htpp; htp = *htpp; } *cp = c; *fname = name; return (np); } /* * Does the data record match the class and type? */ match(dp, class, type) register struct databuf *dp; register int class, type; { #ifdef DEBUG if (debug >= 5) fprintf(ddt,"match(0x%x, %d, %d) %d, %d\n", dp, class, type, dp->d_class, dp->d_type); #endif if (dp->d_class != class && class != C_ANY) return (0); if (dp->d_type != type && type != T_ANY) return (0); return (1); }