⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipcache.c

📁 -
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: ipcache.c,v 1.210 1998/12/05 00:54:30 wessels Exp $ * * DEBUG: section 14    IP Cache * AUTHOR: Harvest Derived * * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * *  Squid is the result of efforts by numerous individuals from the *  Internet community.  Development is led by Duane Wessels of the *  National Laboratory for Applied Network Research and funded by the *  National Science Foundation.  Squid is Copyrighted (C) 1998 by *  Duane Wessels and the University of California San Diego.  Please *  see the COPYRIGHT file for full details.  Squid incorporates *  software developed and/or copyrighted by other sources.  Please see *  the CREDITS file for full details. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. *   *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. *   *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"static struct {    int requests;    int replies;    int hits;    int misses;    int pending_hits;    int negative_hits;    int errors;    int ghbn_calls;		/* # calls to blocking gethostbyname() */    int release_locked;} IpcacheStats;static dlink_list lru_list;static FREE ipcacheFreeEntry;static HLPCB ipcacheHandleReply;static IPH dummy_handler;static int ipcacheExpiredEntry(ipcache_entry *);static int ipcache_testname(void);static ipcache_entry *ipcacheAddNew(const char *, const struct hostent *, ipcache_status_t);static ipcache_entry *ipcacheParse(const char *buf);static ipcache_entry *ipcache_create(const char *name);static ipcache_entry *ipcache_get(const char *);static void ipcacheAddHostent(ipcache_entry *, const struct hostent *);static void ipcacheAddPending(ipcache_entry *, IPH *, void *);static void ipcacheChangeKey(ipcache_entry * i);static void ipcacheLockEntry(ipcache_entry *);static void ipcacheStatPrint(ipcache_entry *, StoreEntry *);static void ipcacheUnlockEntry(ipcache_entry *);static void ipcache_call_pending(ipcache_entry *);static void ipcache_release(ipcache_entry *);static ipcache_addrs static_addrs;static hash_table *ip_table = NULL;static char ipcache_status_char[] ={    'C',    'N',    'P',    'D'};static long ipcache_low = 180;static long ipcache_high = 200;#if LIBRESOLV_DNS_TTL_HACKextern int _dns_ttl_;#endifstatic intipcache_testname(void){    wordlist *w = NULL;    debug(14, 1) ("Performing DNS Tests...\n");    if ((w = Config.dns_testname_list) == NULL)	return 1;    for (; w; w = w->next) {	IpcacheStats.ghbn_calls++;	if (gethostbyname(w->key) != NULL)	    return 1;    }    return 0;}/* removes the given ipcache entry */static voidipcache_release(ipcache_entry * i){    hash_link *table_entry = NULL;    if ((table_entry = hash_lookup(ip_table, i->name)) == NULL) {	snprintf(tmp_error_buf, ERROR_BUF_SZ, "ipcache_release: key '%s' not found\n", i->name);	fatal_dump(tmp_error_buf);    }    assert(i == (ipcache_entry *) table_entry);    if (i->locks) {	i->expires = squid_curtime;	ipcacheChangeKey(i);	IpcacheStats.release_locked++;	return;    }    hash_remove_link(ip_table, table_entry);    dlinkDelete(&i->lru, &lru_list);    if (i->status == IP_CACHED) {	safe_free(i->addrs.in_addrs);	safe_free(i->addrs.bad_mask);	debug(14, 5) ("ipcache_release: Released IP cached record for '%s'.\n",	    i->name);    }    safe_free(i->name);    safe_free(i->error_message);    memFree(i, MEM_IPCACHE_ENTRY);    return;}static ipcache_entry *ipcache_get(const char *name){    assert(ip_table != NULL);    return (ipcache_entry *) hash_lookup(ip_table, name);}static intipcacheExpiredEntry(ipcache_entry * i){    if (i->status == IP_PENDING)	return 0;    if (i->status == IP_DISPATCHED)	return 0;    if (i->locks != 0)	return 0;    if (i->addrs.count == 0)	return 1;    if (i->expires > squid_curtime)	return 0;    return 1;}voidipcache_purgelru(void *voidnotused){    dlink_node *m;    dlink_node *prev = NULL;    ipcache_entry *i;    int removed = 0;    eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1);    for (m = lru_list.tail; m; m = prev) {	if (memInUse(MEM_IPCACHE_ENTRY) < ipcache_low)	    break;	prev = m->prev;	i = m->data;	if (i->status == IP_PENDING)	    continue;	if (i->status == IP_DISPATCHED)	    continue;	if (i->locks != 0)	    continue;	ipcache_release(i);	removed++;    }    debug(14, 9) ("ipcache_purgelru: removed %d entries\n", removed);}/* create blank ipcache_entry */static ipcache_entry *ipcache_create(const char *name){    static ipcache_entry *i;    i = memAllocate(MEM_IPCACHE_ENTRY);    i->name = xstrdup(name);    i->expires = squid_curtime + Config.negativeDnsTtl;    hash_join(ip_table, (hash_link *) i);    dlinkAdd(i, &i->lru, &lru_list);    return i;}static voidipcacheAddHostent(ipcache_entry * i, const struct hostent *hp){    int addr_count = 0;    int k;    safe_free(i->addrs.in_addrs);    safe_free(i->addrs.bad_mask);    while ((addr_count < 255) && *(hp->h_addr_list + addr_count))	++addr_count;    i->addrs.count = (unsigned char) addr_count;    i->addrs.in_addrs = xcalloc(addr_count, sizeof(struct in_addr));    i->addrs.bad_mask = xcalloc(addr_count, sizeof(unsigned char));    i->addrs.badcount = 0;    for (k = 0; k < addr_count; k++)	xmemcpy(&i->addrs.in_addrs[k].s_addr,	    *(hp->h_addr_list + k),	    hp->h_length);}static ipcache_entry *ipcacheAddNew(const char *name, const struct hostent *hp, ipcache_status_t status){    ipcache_entry *i;    if (ipcache_get(name))	fatal_dump("ipcacheAddNew: somebody adding a duplicate!");    debug(14, 10) ("ipcacheAddNew: Adding '%s', status=%c\n",	name,	ipcache_status_char[status]);    i = ipcache_create(name);    if (hp)	ipcacheAddHostent(i, hp);    i->status = status;    i->lastref = squid_curtime;    return i;}/* walks down the pending list, calling handlers */static voidipcache_call_pending(ipcache_entry * i){    ip_pending *p = NULL;    int nhandler = 0;    i->lastref = squid_curtime;    ipcacheLockEntry(i);    while (i->pending_head != NULL) {	p = i->pending_head;	i->pending_head = p->next;	if (p->handler) {	    nhandler++;	    dns_error_message = i->error_message;	    if (cbdataValid(p->handlerData)) {		p->handler(i->status == IP_CACHED ? &i->addrs : NULL,		    p->handlerData);	    }	    cbdataUnlock(p->handlerData);	}	memFree(p, MEM_IPCACHE_PENDING);    }    i->pending_head = NULL;	/* nuke list */    debug(14, 10) ("ipcache_call_pending: Called %d handlers.\n", nhandler);    ipcacheUnlockEntry(i);}static ipcache_entry *ipcacheParse(const char *inbuf){    LOCAL_ARRAY(char, buf, DNS_INBUF_SZ);    char *token;    static ipcache_entry i;    int j;    int k;    int ipcount = 0;    int ttl;    char A[32][16];    memset(&i, '\0', sizeof(i));    i.expires = squid_curtime;    i.status = IP_NEGATIVE_CACHED;    if (inbuf == NULL) {	debug(14, 1) ("ipcacheParse: Got <NULL> reply\n");	i.error_message = xstrdup("Internal Squid Error");	return &i;    }    xstrncpy(buf, inbuf, DNS_INBUF_SZ);    debug(14, 5) ("ipcacheParse: parsing: {%s}\n", buf);    token = strtok(buf, w_space);    if (NULL == token) {	debug(14, 1) ("ipcacheParse: Got <NULL>, expecting '$addr'\n");	return &i;    }    if (0 == strcmp(token, "$fail")) {	i.expires = squid_curtime + Config.negativeDnsTtl;	token = strtok(NULL, "\n");	assert(NULL != token);	i.error_message = xstrdup(token);	return &i;    }    if (0 != strcmp(token, "$addr")) {	debug(14, 1) ("ipcacheParse: Got '%s', expecting '$addr'\n", token);	return &i;    }    token = strtok(NULL, w_space);    if (NULL == token) {	debug(14, 1) ("ipcacheParse: Got <NULL>, expecting TTL\n");	return &i;    }    i.status = IP_CACHED;    ttl = atoi(token);    if (ttl > 0)	i.expires = squid_curtime + ttl;    else	i.expires = squid_curtime + Config.positiveDnsTtl;    while (NULL != (token = strtok(NULL, w_space))) {	xstrncpy(A[ipcount], token, 16);	if (++ipcount == 32)	    break;    }    if (0 == ipcount) {	i.addrs.in_addrs = NULL;	i.addrs.bad_mask = NULL;    } else {	i.addrs.in_addrs = xcalloc(ipcount, sizeof(struct in_addr));	i.addrs.bad_mask = xcalloc(ipcount, sizeof(unsigned char));    }    for (j = 0, k = 0; k < ipcount; k++) {	if (safe_inet_addr(A[k], &i.addrs.in_addrs[j]))	    j++;	else	    debug(14, 1) ("ipcacheParse: Invalid IP address '%s'\n", A[k]);    }    i.addrs.count = (unsigned char) j;    return &i;}static voidipcacheHandleReply(void *data, char *reply){    int n;    generic_cbdata *c = data;    ipcache_entry *i = c->data;    ipcache_entry *x = NULL;    assert(i->status == IP_DISPATCHED);    assert(i->locks);    cbdataFree(c);    c = NULL;    n = ++IpcacheStats.replies;    statHistCount(&Counter.dns.svc_time, tvSubMsec(i->request_time, current_time));    x = ipcacheParse(reply);    assert(x);    i->status = x->status;    i->addrs = x->addrs;    i->error_message = x->error_message;    i->expires = x->expires;    ipcache_call_pending(i);    ipcacheUnlockEntry(i);	/* unlock from IP_DISPATCHED */}static voidipcacheAddPending(ipcache_entry * i, IPH * handler, void *handlerData){    ip_pending *pending = memAllocate(MEM_IPCACHE_PENDING);    ip_pending **I = NULL;    i->lastref = squid_curtime;    pending->handler = handler;    pending->handlerData = handlerData;    cbdataLock(handlerData);    for (I = &(i->pending_head); *I; I = &((*I)->next));    *I = pending;}voidipcache_nbgethostbyname(const char *name, IPH * handler, void *handlerData){    ipcache_entry *i = NULL;    const ipcache_addrs *addrs = NULL;    generic_cbdata *c;    assert(handler != NULL);    debug(14, 4) ("ipcache_nbgethostbyname: Name '%s'.\n", name);    IpcacheStats.requests++;    if (name == NULL || name[0] == '\0') {	debug(14, 4) ("ipcache_nbgethostbyname: Invalid name!\n");	handler(NULL, handlerData);	return;    }    if ((addrs = ipcacheCheckNumeric(name))) {	handler(addrs, handlerData);	return;    }    if ((i = ipcache_get(name))) {	if (ipcacheExpiredEntry(i)) {	    ipcache_release(i);	    i = NULL;	}    }    if (i == NULL) {	/* MISS: No entry, create the new one */	debug(14, 5) ("ipcache_nbgethostbyname: MISS for '%s'\n", name);	IpcacheStats.misses++;	i = ipcacheAddNew(name, NULL, IP_PENDING);	ipcacheAddPending(i, handler, handlerData);	i->request_time = current_time;    } else if (i->status == IP_CACHED || i->status == IP_NEGATIVE_CACHED) {	/* HIT */	debug(14, 4) ("ipcache_nbgethostbyname: HIT for '%s'\n", name);	if (i->status == IP_NEGATIVE_CACHED)	    IpcacheStats.negative_hits++;	else	    IpcacheStats.hits++;	ipcacheAddPending(i, handler, handlerData);	ipcache_call_pending(i);	return;    } else if (i->status == IP_PENDING || i->status == IP_DISPATCHED) {	debug(14, 4) ("ipcache_nbgethostbyname: PENDING for '%s'\n", name);	IpcacheStats.pending_hits++;	ipcacheAddPending(i, handler, handlerData);	if (squid_curtime - i->expires > 600) {	    debug(14, 0) ("ipcache_nbgethostbyname: '%s' PENDING for %d seconds, aborting\n", name, (int) (squid_curtime + Config.negativeDnsTtl - i->expires));	    ipcacheChangeKey(i);	    ipcache_call_pending(i);	}	return;    } else {	fatal_dump("ipcache_nbgethostbyname: BAD ipcache_entry status");    }    /* for HIT, PENDING, DISPATCHED we've returned.  For MISS we submit */    c = xcalloc(1, sizeof(*c));    c->data = i;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -