diff options
Diffstat (limited to 'contrib/bind/bin/named/db_glue.c')
-rw-r--r-- | contrib/bind/bin/named/db_glue.c | 318 |
1 files changed, 179 insertions, 139 deletions
diff --git a/contrib/bind/bin/named/db_glue.c b/contrib/bind/bin/named/db_glue.c index bc6aed4..f1fae69 100644 --- a/contrib/bind/bin/named/db_glue.c +++ b/contrib/bind/bin/named/db_glue.c @@ -1,6 +1,6 @@ #if !defined(lint) && !defined(SABER) -static char sccsid[] = "@(#)db_glue.c 4.4 (Berkeley) 6/1/90"; -static char rcsid[] = "$Id: db_glue.c,v 8.27 1998/02/14 00:41:39 halley Exp $"; +static const char sccsid[] = "@(#)db_glue.c 4.4 (Berkeley) 6/1/90"; +static const char rcsid[] = "$Id: db_glue.c,v 8.39 1999/10/15 19:48:57 vixie Exp $"; #endif /* not lint */ /* @@ -57,7 +57,7 @@ static char rcsid[] = "$Id: db_glue.c,v 8.27 1998/02/14 00:41:39 halley Exp $"; */ /* - * Portions Copyright (c) 1996, 1997 by Internet Software Consortium. + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -79,6 +79,8 @@ static char rcsid[] = "$Id: db_glue.c,v 8.27 1998/02/14 00:41:39 halley Exp $"; #include <sys/uio.h> #include <sys/param.h> #include <sys/stat.h> +#include <sys/socket.h> +#include <sys/un.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -147,6 +149,7 @@ destroyservicelist() { freestr(slp->proto); memput(slp, sizeof *slp); } + servicelist = NULL; } void @@ -183,6 +186,7 @@ destroyprotolist() { freestr(plp->name); memput(plp, sizeof *plp); } + protolist = NULL; } static int @@ -451,29 +455,11 @@ getname(struct namebuf *np, char *buf, int buflen) { *cp = '\0'; } -/* - * Compute hash value from data. - */ -u_int -dhash(const u_char *dp, int dlen) { - u_char *cp; - u_int hval; - int n; - - n = dlen; - if (n > 8) - n = 8; - hval = 0; - while (--n >= 0) { - hval <<= 1; - hval += *dp++; - } - return (hval % INVHASHSZ); -} - /* u_int * nhash(name) * compute hash for this name and return it; ignore case differences + * note: + * this logic is intended to produce the same result as nlookup()'s. */ u_int nhash(const char *name) { @@ -481,136 +467,190 @@ nhash(const char *name) { u_int hval; hval = 0; - while ((ch = (u_char)*name++) != (u_char)'\0') { - if (isascii(ch) && isupper(ch)) - ch = tolower(ch); - hval <<= 1; - hval += ch; - } - return (hval % INVHASHSZ); + while ((ch = (u_char)*name++) != (u_char)'\0') + HASHIMILATE(hval, ch); + return (hval); } -/* -** SAMEDOMAIN -- Check whether a name belongs to a domain -** ------------------------------------------------------ -** -** Returns: -** TRUE if the given name lies in the domain. -** FALSE otherwise. -** -** Trailing dots are first removed from name and domain. -** Always compare complete subdomains, not only whether the -** domain name is the trailing string of the given name. -** -** "host.foobar.top" lies in "foobar.top" and in "top" and in "" -** but NOT in "bar.top" -*/ +void +db_freedata(struct databuf *dp) { + int bytes = DATASIZE(dp->d_size); -int -samedomain(const char *a, const char *b) { - size_t la, lb; - int diff, i, escaped; - const char *cp; - - la = strlen(a); - lb = strlen(b); - - /* ignore a trailing label separator (i.e. an unescaped dot) in 'a' */ - if (la && a[la-1] == '.') { - escaped = 0; - /* note this loop doesn't get executed if la==1 */ - for (i = la - 2; i >= 0; i--) - if (a[i] == '\\') { - if (escaped) - escaped = 0; - else - escaped = 1; - } else { - break; - } - if (!escaped) - la--; - } - /* ignore a trailing label separator (i.e. an unescaped dot) in 'b' */ - if (lb && b[lb-1] == '.') { - escaped = 0; - /* note this loop doesn't get executed if lb==1 */ - for (i = lb - 2; i >= 0; i--) - if (b[i] == '\\') { - if (escaped) - escaped = 0; - else - escaped = 1; - } else { - break; - } - if (!escaped) - lb--; - } + if (dp->d_rcnt != 0) + panic("db_freedata: d_rcnt != 0", NULL); + if ((dp->d_flags & (DB_F_ACTIVE|DB_F_FREE)) != 0) + panic("db_freedata: %s set", + (dp->d_flags & DB_F_FREE) != 0 ? "DB_F_FREE" : + "DB_F_ACTIVE"); + if (dp->d_next != NULL) + panic("db_free: d_next != NULL", NULL); + dp->d_flags |= DB_F_FREE; + memput(dp, bytes); +} - /* lb==0 means 'b' is the root domain, so 'a' must be in 'b'. */ - if (lb == 0) - return (1); +struct lame_hash { + struct lame_hash *next; + char *zone; + char *server; + time_t when; + unsigned int hval; +} **lame_hash = NULL; - /* 'b' longer than 'a' means 'a' can't be in 'b'. */ - if (lb > la) - return (0); +static int lame_hash_size = 0; +static int lame_hash_cnt = 0; - /* We use strncasecmp because we might be trying to - * ignore a trailing dot. */ - if (lb == la) - return (strncasecmp(a, b, lb) == 0); +void +db_lame_add(char *zone, char *server, time_t when) { + unsigned int hval = nhash(zone); + struct lame_hash *last, *this; + struct lame_hash **new; + int n; + int newsize; + + db_lame_clean(); + + /* grow / initalise hash table */ + if (lame_hash_cnt >= lame_hash_size) { + if (lame_hash_size == 0) + newsize = hashsizes[0]; + else { + for (n = 0; (newsize = hashsizes[n++]) != 0; (void)NULL) + if (lame_hash_size == newsize) { + newsize = hashsizes[n]; + break; + } + if (newsize == 0) + newsize = lame_hash_size * 2 + 1; + } + new = memget(newsize * sizeof this); + if (new == NULL) + return; + memset(new, 0, newsize * sizeof this); + for (n = 0 ; n < lame_hash_size; n++) { + this = lame_hash[n]; + while (this) { + last = this; + this = this->next; + last->next = new[hval%newsize]; + new[hval%newsize] = last; + } + } + if (lame_hash != NULL) + memput(lame_hash, lame_hash_size * sizeof this); + lame_hash = new; + lame_hash_size = newsize; + } - /* Ok, we know la > lb. */ + last = NULL; + this = lame_hash[hval%lame_hash_size]; + while (this) { + if ((ns_samename(this->server, server) == 1) && + (ns_samename(this->zone, zone) == 1)) { + this->when = when; + return; + } + last = this; + this = this->next; + } + this = memget(sizeof *this); + if (this == NULL) + return; + this->server = savestr(server, 0); + this->zone = savestr(zone, 0); + if (this->server == NULL || this->zone == NULL) { + if (this->server != NULL) + freestr(this->server); + if (this->zone != NULL) + freestr(this->zone); + memput(this, sizeof *this); + return; + } + this->when = when; + this->hval = hval; + this->next = NULL; + if (last != NULL) + last->next = this; + else + lame_hash[hval%lame_hash_size] = this; + lame_hash_cnt++; +} - diff = la - lb; +time_t +db_lame_find(char *zone, struct databuf *dp) { + unsigned int hval = nhash(zone); + struct lame_hash *this; - /* If 'a' is only 1 character longer than 'b', then it can't be - a subdomain of 'b' (because of the need for the '.' label - separator). */ - if (diff < 2) + if (lame_hash_size == 0) { + /* db_lame_destroy() must have been called. */ + dp->d_flags &= ~DB_F_LAME; return (0); + } - /* If the character before the last 'lb' characters of 'b' - isn't '.', then it can't be a match (this lets us avoid - having "foobar.com" match "bar.com"). */ - if (a[diff-1] != '.') - return (0); + db_lame_clean(); /* Remove expired record so that we can + * clear DB_F_LAME when there are no + * additions. */ - /* We're not sure about that '.', however. It could be escaped - and thus not a really a label separator. */ - escaped=0; - for (i = diff-2; i >= 0; i--) - if (a[i] == '\\') { - if (escaped) - escaped = 0; - else - escaped = 1; - } - else - break; - if (escaped) - return (0); - - /* We use strncasecmp because we might be trying to - * ignore trailing dots. */ - cp = a + diff; - return (strncasecmp(cp, b, lb) == 0); + this = lame_hash[hval % lame_hash_size]; + while (this) { + if ((ns_samename(this->server, (char*)dp->d_data) == 1) && + (ns_samename(this->zone, zone) == 1)) + return (this->when); + this = this->next; + } + dp->d_flags &= ~DB_F_LAME; + return (0); } void -db_freedata(struct databuf *dp) { - int bytes = (dp->d_type == T_NS) ? - DATASIZE(dp->d_size)+INT32SZ : DATASIZE(dp->d_size); +db_lame_clean(void) { + int i; + struct lame_hash *last, *this; + + for (i = 0 ; i < lame_hash_size; i++) { + last = NULL; + this = lame_hash[i]; + while (this != NULL) { + if (this->when < tt.tv_sec) { + freestr(this->zone); + freestr(this->server); + if (last != NULL) { + last->next = this->next; + memput(this, sizeof *this); + this = last->next; + } else { + lame_hash[i] = this->next; + memput(this, sizeof *this); + this = lame_hash[i]; + } + lame_hash_cnt--; + } else { + last = this; + this = this->next; + } + } + } +} - if (dp->d_rcnt != 0) - panic("db_freedata: d_rcnt != 0", NULL); - if ((dp->d_flags & (DB_F_ACTIVE|DB_F_FREE)) != 0) - panic("db_freedata: %s set", - (dp->d_flags & DB_F_FREE) != 0 ? "DB_F_FREE" : - "DB_F_ACTIVE"); - if (dp->d_next != NULL) - panic("db_free: d_next != NULL", NULL); - dp->d_flags |= DB_F_FREE; - memput(dp, bytes); +void +db_lame_destroy(void) { + int i; + struct lame_hash *last, *this; + + if (lame_hash_size == 0) + return; + + for (i = 0 ; i < lame_hash_size; i++) { + this = lame_hash[i]; + while (this != NULL) { + last = this; + this = this->next; + freestr(last->zone); + freestr(last->server); + memput(last, sizeof *this); + } + } + memput(lame_hash, lame_hash_size * sizeof this); + lame_hash_cnt = 0; + lame_hash_size = 0; + lame_hash = NULL; } |