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