client_db.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:9k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: client_db.c,v 1.43 1998/12/05 00:54:18 wessels Exp $
  3.  *
  4.  * DEBUG: section 0     Client Database
  5.  * AUTHOR: Duane Wessels
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "squid.h"
  35. static hash_table *client_table = NULL;
  36. static ClientInfo *clientdbAdd(struct in_addr addr);
  37. static FREE clientdbFreeItem;
  38. static ClientInfo *
  39. clientdbAdd(struct in_addr addr)
  40. {
  41.     ClientInfo *c;
  42.     c = memAllocate(MEM_CLIENT_INFO);
  43.     c->key = xstrdup(inet_ntoa(addr));
  44.     c->addr = addr;
  45.     hash_join(client_table, (hash_link *) c);
  46.     Counter.client_http.clients++;
  47.     return c;
  48. }
  49. void
  50. clientdbInit(void)
  51. {
  52.     if (client_table)
  53. return;
  54.     client_table = hash_create((HASHCMP *) strcmp, 467, hash_string);
  55.     cachemgrRegister("client_list",
  56. "Cache Client List",
  57. clientdbDump,
  58. 0, 1);
  59. }
  60. void
  61. clientdbUpdate(struct in_addr addr, log_type ltype, protocol_t p, size_t size)
  62. {
  63.     char *key;
  64.     ClientInfo *c;
  65.     if (!Config.onoff.client_db)
  66. return;
  67.     key = inet_ntoa(addr);
  68.     c = (ClientInfo *) hash_lookup(client_table, key);
  69.     if (c == NULL)
  70. c = clientdbAdd(addr);
  71.     if (c == NULL)
  72. debug_trap("clientdbUpdate: Failed to add entry");
  73.     if (p == PROTO_HTTP) {
  74. c->Http.n_requests++;
  75. c->Http.result_hist[ltype]++;
  76. kb_incr(&c->Http.kbytes_out, size);
  77. if (isTcpHit(ltype))
  78.     kb_incr(&c->Http.hit_kbytes_out, size);
  79.     } else if (p == PROTO_ICP) {
  80. c->Icp.n_requests++;
  81. c->Icp.result_hist[ltype]++;
  82. kb_incr(&c->Icp.kbytes_out, size);
  83. if (LOG_UDP_HIT == ltype)
  84.     kb_incr(&c->Icp.hit_kbytes_out, size);
  85.     }
  86. }
  87. #define CUTOFF_SECONDS 3600
  88. int
  89. clientdbCutoffDenied(struct in_addr addr)
  90. {
  91.     char *key;
  92.     int NR;
  93.     int ND;
  94.     double p;
  95.     ClientInfo *c;
  96.     if (!Config.onoff.client_db)
  97. return 0;
  98.     key = inet_ntoa(addr);
  99.     c = (ClientInfo *) hash_lookup(client_table, key);
  100.     if (c == NULL)
  101. return 0;
  102.     /*
  103.      * If we are in a cutoff window, we don't send a reply
  104.      */
  105.     if (squid_curtime - c->cutoff.time < CUTOFF_SECONDS)
  106. return 1;
  107.     /*
  108.      * Calculate the percent of DENIED replies since the last
  109.      * cutoff time.
  110.      */
  111.     NR = c->Icp.n_requests - c->cutoff.n_req;
  112.     if (NR < 150)
  113. NR = 150;
  114.     ND = c->Icp.result_hist[LOG_UDP_DENIED] - c->cutoff.n_denied;
  115.     p = 100.0 * ND / NR;
  116.     if (p < 95.0)
  117. return 0;
  118.     debug(1, 0) ("WARNING: Probable misconfigured neighbor at %sn", key);
  119.     debug(1, 0) ("WARNING: %d of the last %d ICP replies are DENIEDn", ND, NR);
  120.     debug(1, 0) ("WARNING: No replies will be sent for the next %d secondsn",
  121. CUTOFF_SECONDS);
  122.     c->cutoff.time = squid_curtime;
  123.     c->cutoff.n_req = c->Icp.n_requests;
  124.     c->cutoff.n_denied = c->Icp.result_hist[LOG_UDP_DENIED];
  125.     return 1;
  126. }
  127. void
  128. clientdbDump(StoreEntry * sentry)
  129. {
  130.     ClientInfo *c;
  131.     log_type l;
  132.     int icp_total = 0;
  133.     int icp_hits = 0;
  134.     int http_total = 0;
  135.     int http_hits = 0;
  136.     storeAppendPrintf(sentry, "Cache Clients:n");
  137.     hash_first(client_table);
  138.     while ((c = (ClientInfo *) hash_next(client_table))) {
  139. storeAppendPrintf(sentry, "Address: %sn", c->key);
  140. storeAppendPrintf(sentry, "Name: %sn", fqdnFromAddr(c->addr));
  141. storeAppendPrintf(sentry, "    ICP Requests %dn",
  142.     c->Icp.n_requests);
  143. for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; l++) {
  144.     if (c->Icp.result_hist[l] == 0)
  145. continue;
  146.     icp_total += c->Icp.result_hist[l];
  147.     if (LOG_UDP_HIT == l)
  148. icp_hits += c->Icp.result_hist[l];
  149.     storeAppendPrintf(sentry,
  150. "        %-20.20s %7d %3d%%n",
  151. log_tags[l],
  152. c->Icp.result_hist[l],
  153. percent(c->Icp.result_hist[l], c->Icp.n_requests));
  154. }
  155. storeAppendPrintf(sentry, "    HTTP Requests %dn",
  156.     c->Http.n_requests);
  157. for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; l++) {
  158.     if (c->Http.result_hist[l] == 0)
  159. continue;
  160.     http_total += c->Http.result_hist[l];
  161.     if (isTcpHit(l))
  162. http_hits += c->Http.result_hist[l];
  163.     storeAppendPrintf(sentry,
  164. "        %-20.20s %7d %3d%%n",
  165. log_tags[l],
  166. c->Http.result_hist[l],
  167. percent(c->Http.result_hist[l], c->Http.n_requests));
  168. }
  169. storeAppendPrintf(sentry, "n");
  170.     }
  171.     storeAppendPrintf(sentry, "TOTALSn");
  172.     storeAppendPrintf(sentry, "ICP : %d Queries, %d Hits (%3d%%)n",
  173. icp_total, icp_hits, percent(icp_hits, icp_total));
  174.     storeAppendPrintf(sentry, "HTTP: %d Requests, %d Hits (%3d%%)n",
  175. http_total, http_hits, percent(http_hits, http_total));
  176. }
  177. static void
  178. clientdbFreeItem(void *data)
  179. {
  180.     ClientInfo *c = data;
  181.     safe_free(c->key);
  182.     memFree(c, MEM_CLIENT_INFO);
  183. }
  184. void
  185. clientdbFreeMemory(void)
  186. {
  187.     hashFreeItems(client_table, clientdbFreeItem);
  188.     hashFreeMemory(client_table);
  189.     client_table = NULL;
  190. }
  191. #if SQUID_SNMP
  192. int
  193. meshCtblGetRowFn(oid * New, oid * Oid)
  194. {
  195.     ClientInfo *c = NULL;
  196.     if (!Oid[0] && !Oid[1] && !Oid[2] && !Oid[3]) {
  197. hash_first(client_table);
  198. c = (ClientInfo *) hash_next(client_table);
  199. hash_last(client_table);
  200.     } else {
  201. char key[15];
  202. snprintf(key, sizeof(key), "%d.%d.%d.%d", Oid[0], Oid[1], Oid[2], Oid[3]);
  203. c = (ClientInfo *) hash_lookup(client_table, key);
  204. if (NULL != c)
  205.     c = c->next;
  206.     }
  207.     if (!c)
  208. return 0;
  209.     addr2oid(c->addr, New);
  210.     return 1;
  211. }
  212. variable_list *
  213. snmp_meshCtblFn(variable_list * Var, snint * ErrP)
  214. {
  215.     variable_list *Answer;
  216.     static char key[15];
  217.     ClientInfo *c = NULL;
  218.     int aggr = 0;
  219.     log_type l;
  220.     Answer = snmp_var_new(Var->name, Var->name_length);
  221.     *ErrP = SNMP_ERR_NOERROR;
  222.     snprintf(key, sizeof(key), "%d.%d.%d.%d", Var->name[LEN_SQ_NET + 3], Var->name[LEN_SQ_NET + 4],
  223. Var->name[LEN_SQ_NET + 5], Var->name[LEN_SQ_NET + 6]);
  224.     debug(49, 5) ("snmp_meshCtblFn: [%s] requested!n", key);
  225.     c = (ClientInfo *) hash_lookup(client_table, key);
  226.     if (c == NULL) {
  227. debug(49, 5) ("snmp_meshCtblFn: not found.n");
  228. *ErrP = SNMP_ERR_NOSUCHNAME;
  229. snmp_var_free(Answer);
  230. return (NULL);
  231.     }
  232.     switch (Var->name[LEN_SQ_NET + 2]) {
  233.     case MESH_CTBL_ADDR:
  234. Answer->type = SMI_IPADDRESS;
  235. Answer->val_len = sizeof(snint);
  236. Answer->val.integer = xmalloc(Answer->val_len);
  237. *(Answer->val.integer) = (snint) c->addr.s_addr;
  238. break;
  239.     case MESH_CTBL_HTBYTES:
  240. Answer->val_len = sizeof(snint);
  241. Answer->val.integer = xmalloc(Answer->val_len);
  242. Answer->type = SMI_COUNTER32;
  243. *(Answer->val.integer) = (snint) c->Http.kbytes_out.kb;
  244. break;
  245.     case MESH_CTBL_HTREQ:
  246. Answer->val_len = sizeof(snint);
  247. Answer->val.integer = xmalloc(Answer->val_len);
  248. Answer->type = SMI_COUNTER32;
  249. *(Answer->val.integer) = (snint) c->Http.n_requests;
  250. break;
  251.     case MESH_CTBL_HTHITS:
  252. aggr = 0;
  253. for (l = 0; l < LOG_TYPE_MAX; l++) {
  254.     if (isTcpHit(l))
  255. aggr += c->Http.result_hist[l];
  256. }
  257. Answer->val_len = sizeof(snint);
  258. Answer->val.integer = xmalloc(Answer->val_len);
  259. Answer->type = SMI_COUNTER32;
  260. *(Answer->val.integer) = (snint) aggr;
  261. break;
  262.     case MESH_CTBL_HTHITBYTES:
  263. Answer->val_len = sizeof(snint);
  264. Answer->val.integer = xmalloc(Answer->val_len);
  265. Answer->type = SMI_COUNTER32;
  266. *(Answer->val.integer) = (snint) c->Http.hit_kbytes_out.kb;
  267. break;
  268.     case MESH_CTBL_ICPBYTES:
  269. Answer->val_len = sizeof(snint);
  270. Answer->val.integer = xmalloc(Answer->val_len);
  271. Answer->type = SMI_COUNTER32;
  272. *(Answer->val.integer) = (snint) c->Icp.kbytes_out.kb;
  273. break;
  274.     case MESH_CTBL_ICPREQ:
  275. Answer->val_len = sizeof(snint);
  276. Answer->val.integer = xmalloc(Answer->val_len);
  277. Answer->type = SMI_COUNTER32;
  278. *(Answer->val.integer) = (snint) c->Icp.n_requests;
  279. break;
  280.     case MESH_CTBL_ICPHITS:
  281. aggr = c->Icp.result_hist[LOG_UDP_HIT];
  282. Answer->val_len = sizeof(snint);
  283. Answer->val.integer = xmalloc(Answer->val_len);
  284. Answer->type = SMI_COUNTER32;
  285. *(Answer->val.integer) = (snint) aggr;
  286. break;
  287.     case MESH_CTBL_ICPHITBYTES:
  288. Answer->val_len = sizeof(snint);
  289. Answer->val.integer = xmalloc(Answer->val_len);
  290. Answer->type = SMI_COUNTER32;
  291. *(Answer->val.integer) = (snint) c->Icp.hit_kbytes_out.kb;
  292. break;
  293.     default:
  294. *ErrP = SNMP_ERR_NOSUCHNAME;
  295. snmp_var_free(Answer);
  296. debug(49, 5) ("snmp_meshCtblFn: illegal column.n");
  297. return (NULL);
  298.     }
  299.     return Answer;
  300. }
  301. #endif /*SQUID_SNMP */