📄 hostcache.c
字号:
/* * Copyright (c) 1997, 1998, 1999 * Inferno Nettverk A/S, Norway. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. The above copyright notice, this list of conditions and the following * disclaimer must appear in all copies of the software, derivative works * or modified versions, and any portions thereof, aswell as in all * supporting documentation. * 2. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by * Inferno Nettverk A/S, Norway. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Inferno Nettverk A/S requests users of this software to return to * * Software Distribution Coordinator or sdc@inet.no * Inferno Nettverk A/S * Oslo Research Park * Gaustadal閑n 21 * N-0349 Oslo * Norway * * any improvements or extensions that they make and grant Inferno Nettverk A/S * the rights to redistribute these changes. * */#include "common.h"static const char rcsid[] ="$Id: hostcache.c,v 1.15 1999/12/22 09:29:24 karls Exp $";__BEGIN_DECLS#if SOCKS_SERVER/* we want the real thing. */#undef gethostbyname#undef gethostbyaddrstatic struct hostent *hostentupdate __P((struct hostent *old, const struct hostent *new));/* * Updates "old" with the contents of "new", freeing any * resources currently used by "old". * Returns: * On success: "old", updated. * On failure: NULL.*/static inthosthash __P((const char *name, size_t size));/* * Calculates a hashvalue for "name" and returns it's value. * Size of hashtable is given by "size".*/static intaddrhash __P((in_addr_t addr, size_t size));/* * Calculates a hashvalue for "addr" and returns it's value. * Size of hashtable is given by "size".*/#endif /* SOCKS_SERVER */static char **listrealloc __P((char ***old, const char ***new, int length));/* * Reallocates "old" and copies in the contents of "new". * The last element of both "old" and "new" must be NULL. * If "length" is less than 0, each element is assumed to * be NUL terminated, otherwise "length" gives the total length * of every string. * Returns: * On success: "**old", with the contents of "new". * On failure: NULL.*/__END_DECLSstruct hostent *hostentdup(hostent) const struct hostent *hostent;{ static struct hostent dupedinit; struct hostent *duped; if ((duped = (struct hostent *)malloc(sizeof(*duped))) == NULL) return NULL; *duped = dupedinit; if ((duped->h_name = strdup(hostent->h_name)) == NULL) { hostentfree(duped); return NULL; } if (listrealloc(&duped->h_aliases, (const char ***)&hostent->h_aliases, -1) == NULL) { hostentfree(duped); return NULL; } duped->h_addrtype = hostent->h_addrtype; duped->h_length = hostent->h_length; if (listrealloc(&duped->h_addr_list, (const char ***)&hostent->h_addr_list, hostent->h_length) == NULL) { hostentfree(duped); return NULL; } return duped;}voidhostentfree(hostent) struct hostent *hostent;{ char **p; if (hostent == NULL) return; free(hostent->h_name); hostent->h_name = NULL; if (hostent->h_aliases != NULL) for (p = hostent->h_aliases; *p != NULL; ++p) free(*p); free(hostent->h_aliases); hostent->h_aliases = NULL; if (hostent->h_addr_list != NULL) for (p = hostent->h_addr_list; *p != NULL; ++p) free(*p); free(hostent->h_addr_list); hostent->h_addr_list = NULL; free(hostent);}static char **listrealloc(old, new, length) char ***old; const char ***new; int length;{ int i, oldi, newi; /* entries we can reallocate, starting at 0. */ oldi = 0; if (*old != NULL) while ((*old)[oldi] != NULL) ++oldi; newi = 0; while ((*new)[newi] != NULL) ++newi; for (i = newi; i < oldi; ++i) free((*old)[i]); if ((*old = (char **)realloc(*old, sizeof(**new) * (newi + 1))) == NULL) return NULL; for (newi = 0; (*new)[newi] != NULL; ++newi, --oldi) { if (((*old)[newi] = (char *)realloc(oldi > 0 ? (*old)[newi] : NULL, length < 0 ? (strlen((*new)[newi]) + 1) : length)) == NULL) return NULL; if (length < 0) strcpy((*old)[newi], (*new)[newi]); else memcpy((*old)[newi], (*new)[newi], (size_t)length); } (*old)[newi] = NULL; return *old;}#if SOCKS_SERVERstruct hostent *cgethostbyname(name) const char *name;{ const char *function = "cgethostbyname()"; static struct { unsigned allocated:1; char host[MAXHOSTNAMELEN]; time_t written; struct hostent hostent; } table[SOCKD_HOSTCACHE], *freehost; static unsigned int hit, miss, count; const time_t timenow = time(NULL); const int hashi = hosthash(name, ELEMENTS(table)); size_t i; struct hostent *hostent;#if SOCKD_CACHESTAT if (++count % SOCKD_CACHESTAT == 0) slog(LOG_INFO, "%s: hit: %d, miss: %d", function, hit, miss);#endif /* SOCKD_CACHESTAT */ for (i = hashi, freehost = NULL; i < ELEMENTS(table); ++i) { if (!table[i].allocated) { if (freehost == NULL) freehost = &table[i]; continue; } if (strcasecmp(table[i].host, name) == 0) { if (difftime(timenow, table[i].written) >= SOCKD_CACHETIMEOUT) { freehost = &table[i]; break; } ++hit; return &table[i].hostent; } } ++miss; if ((hostent = gethostbyname(name)) == NULL) return NULL; if (freehost == NULL) for (i = hashi, freehost = &table[i]; i < ELEMENTS(table); ++i) { if (difftime(timenow, table[i].written) >= SOCKD_CACHETIMEOUT) { freehost = &table[i]; break; } if (freehost->written < table[i].written) { freehost = &table[i]; /* oldest. */ break; } } if (hostentupdate(&freehost->hostent, hostent) == NULL) { freehost->allocated = 0; slog(LOG_WARNING, "%s: %s", NOMEM, function); return NULL; } SASSERTX(strlen(name) < sizeof(freehost->host)); strcpy(freehost->host, name); time(&freehost->written); freehost->allocated = 1; return &freehost->hostent;}struct hostent *cgethostbyaddr(addr, len, type) const char *addr; int len; int type;{ const char *function = "cgethostbyaddr()"; static struct { unsigned allocated:1; in_addr_t addr; time_t written; struct hostent hostent; } table[SOCKD_ADDRESSCACHE], *freehost; static unsigned long int hit, miss, count; const time_t timenow = time(NULL); /* LINTED pointer casts may be troublesome */ const int hashi = addrhash(((const struct in_addr *)addr)->s_addr, ELEMENTS(table)); size_t i; struct hostent *hostent;#if SOCKD_CACHESTAT if (++count % SOCKD_CACHESTAT == 0) slog(LOG_INFO, "%s: hit: %d, miss: %d", function, hit, miss);#endif /* SOCKD_CACHESTAT */ for (i = hashi, freehost = NULL; i < ELEMENTS(table); ++i) { if (!table[i].allocated) { if (freehost == NULL) freehost = &table[i]; continue; } /* LINTED pointer casts may be troublesome */ if (table[i].addr == ((const struct in_addr *)addr)->s_addr) { if (difftime(timenow, table[i].written) >= SOCKD_CACHETIMEOUT) { freehost = &table[i]; break; } ++hit; return &table[i].hostent; } } ++miss; if ((hostent = gethostbyaddr(addr, len, type)) == NULL) return NULL; if (freehost == NULL) for (i = hashi, freehost = &table[i]; i < ELEMENTS(table); ++i) { if (difftime(timenow, table[i].written) >= SOCKD_CACHETIMEOUT) { freehost = &table[i]; break; } if (freehost->written < table[i].written) { freehost = &table[i]; /* oldest. */ break; } } if (hostentupdate(&freehost->hostent, hostent) == NULL) { freehost->allocated = 0; slog(LOG_WARNING, "%s: %s", NOMEM, function); return NULL; } /* LINTED pointer casts may be troublesome */ freehost->addr = ((const struct in_addr *)addr)->s_addr; time(&freehost->written); freehost->allocated = 1; return &freehost->hostent;}static inthosthash(name, size) const char *name; size_t size;{ char *end; unsigned int value; /* end at second dot. */ if ((end = strchr(name, '.')) != NULL) end = strchr(end, '.'); if (end == NULL) end = strchr(name, NUL); SASSERTX(name <= end); value = 0; while (name != end) value = (value << 5) + *name++; /* MAW - DS&A: Horner's rule. */ return value % size;}static intaddrhash(addr, size) in_addr_t addr; size_t size;{ return addr % size;}static struct hostent *hostentupdate(old, new) struct hostent *old; const struct hostent *new;{ if ((old->h_name = (char *)realloc(old->h_name, strlen(new->h_name) + 1)) == NULL) return NULL; strcpy(old->h_name, new->h_name); if (listrealloc(&old->h_aliases, (const char ***)&new->h_aliases, -1) == NULL) return NULL; old->h_addrtype = new->h_addrtype; old->h_length = new->h_length; if (listrealloc(&old->h_addr_list, (const char ***)&new->h_addr_list, new->h_length) == NULL) return NULL; return old;}#endif /* SOCKS_SERVER */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -