0
|
1 /* Distributed Checksum Clearinghouse |
|
2 * |
|
3 * dump list of dccd clients |
|
4 * |
|
5 * Copyright (c) 2008 by Rhyolite Software, LLC |
|
6 * |
|
7 * This agreement is not applicable to any entity which sells anti-spam |
|
8 * solutions to others or provides an anti-spam solution as part of a |
|
9 * security solution sold to other entities, or to a private network |
|
10 * which employs the DCC or uses data provided by operation of the DCC |
|
11 * but does not provide corresponding data to other users. |
|
12 * |
|
13 * Permission to use, copy, modify, and distribute this software without |
|
14 * changes for any purpose with or without fee is hereby granted, provided |
|
15 * that the above copyright notice and this permission notice appear in all |
|
16 * copies and any distributed versions or copies are either unchanged |
|
17 * or not called anything similar to "DCC" or "Distributed Checksum |
|
18 * Clearinghouse". |
|
19 * |
|
20 * Parties not eligible to receive a license under this agreement can |
|
21 * obtain a commercial license to use DCC by contacting Rhyolite Software |
|
22 * at sales@rhyolite.com. |
|
23 * |
|
24 * A commercial license would be for Distributed Checksum and Reputation |
|
25 * Clearinghouse software. That software includes additional features. This |
|
26 * free license for Distributed ChecksumClearinghouse Software does not in any |
|
27 * way grant permision to use Distributed Checksum and Reputation Clearinghouse |
|
28 * software |
|
29 * |
|
30 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL |
|
31 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES |
|
32 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC |
|
33 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES |
|
34 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
|
35 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, |
|
36 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
|
37 * SOFTWARE. |
|
38 * |
|
39 * Rhyolite Software DCC 1.3.103-1.20 $Revision$ |
|
40 */ |
|
41 |
|
42 #include "dccd_defs.h" |
|
43 |
|
44 static const char *homedir; |
|
45 |
|
46 u_char grey_on; |
|
47 static u_char nonames, quiet, avg; |
|
48 |
|
49 |
|
50 static void NRATTRIB |
|
51 usage(void) |
|
52 { |
|
53 fprintf(stderr, "usage: [-anqg] [-h homedir] [ifile1 ifile2 ...]\n"); |
|
54 exit(1); |
|
55 } |
|
56 |
|
57 |
|
58 |
|
59 static void PATTRIB(1,2) |
|
60 error_msg(const char *p, ...) |
|
61 { |
|
62 va_list args; |
|
63 |
|
64 fflush(stdout); |
|
65 |
|
66 va_start(args, p); |
|
67 vfprintf(stderr, p, args); |
|
68 va_end(args); |
|
69 putchar('\n'); |
|
70 } |
|
71 |
|
72 |
|
73 |
|
74 static u_char |
|
75 clients_read(const char *fname, FILE *f, off_t pos, void *buf, int buf_len) |
|
76 { |
|
77 int i; |
|
78 |
|
79 if (fseeko(f, pos, 0)) { |
|
80 error_msg("fseeko(%s,%d): %s", fname, (int)pos, ERROR_STR()); |
|
81 fclose(f); |
|
82 return 0; |
|
83 } |
|
84 |
|
85 i = fread(buf, buf_len, 1, f); |
|
86 if (i == 1) |
|
87 return 1; |
|
88 |
|
89 if (feof(f)) |
|
90 return 0; |
|
91 |
|
92 error_msg("fread(%s): %s", fname, ERROR_STR()); |
|
93 fclose(f); |
|
94 return 0; |
|
95 } |
|
96 |
|
97 |
|
98 |
|
99 static void |
|
100 dump_file(const char *fname0) |
|
101 { |
|
102 # define PAT_REQUESTS L_DWPAT(7)" "L_DWPAT(6)" " |
|
103 # define PAT_REQUESTS_B "%7s %6s " |
|
104 # define PAT_AVGS "%7d %6d %4.1f " |
|
105 # define PAT_AVGS_B " %14s " |
|
106 # define PAT_DATE_ID "%-14s %6d%c" |
|
107 # define PAT_DATE_ID_B "%-14s %6s " |
|
108 # define PAT_VERS "%1d " |
|
109 # define PAT_VERS_B "%1s " |
|
110 # define PAT_DELAY "%5.3f " |
|
111 # define PAT_DELAY_B "%5s " |
|
112 DCC_PATH fname; |
|
113 FILE *f; |
|
114 struct stat sb; |
|
115 CLIENTS_HEADER header; |
|
116 RL_DATA data; |
|
117 struct { |
|
118 u_int hosts; |
|
119 u_int requests; |
|
120 u_int nops; |
|
121 } versions[DCC_PKT_VERSION_MAX+1]; |
|
122 time_t secs; |
|
123 struct tm tm; |
|
124 char date_buf[40]; |
|
125 char date_buf2[40]; |
|
126 int inflate; |
|
127 double delay_us; |
|
128 DCC_SOCKU su; |
|
129 char name[DCC_MAXDOMAINLEN]; |
|
130 char sustr[DCC_SU2STR_SIZE]; |
|
131 off_t pos; |
|
132 int total, active, i; |
|
133 |
|
134 if (!fnm2abs(fname, fname0, 0)) { |
|
135 error_msg("name \"%s\" too long", fname0); |
|
136 exit(1); |
|
137 } |
|
138 |
|
139 printf("%s\n", fname); |
|
140 |
|
141 f = fopen(fname, "r"); |
|
142 if (!f) { |
|
143 error_msg("stat(%s): %s", |
|
144 fname, ERROR_STR()); |
|
145 exit(1); |
|
146 } |
|
147 if (0 > fstat(fileno(f), &sb)) { |
|
148 error_msg("stat(%s): %s", fname, ERROR_STR()); |
|
149 exit(1); |
|
150 } |
|
151 pos = sb.st_size; |
|
152 if (pos < ISZ(header) |
|
153 || ((pos - ISZ(header)) % ISZ(RL_DATA)) != 0) { |
|
154 error_msg("%s has invalid size %d", fname, (int)pos); |
|
155 exit(1); |
|
156 } |
|
157 |
|
158 if (!clients_read(fname, f, 0, &header, sizeof(header))) |
|
159 exit(1); |
|
160 if (strcmp(header.magic, CLIENTS_MAGIC(0)) |
|
161 && strcmp(header.magic, CLIENTS_MAGIC(1))) { |
|
162 error_msg("unrecognized magic in %s", fname); |
|
163 exit(1); |
|
164 } |
|
165 if (header.hash_len > RL_MIN_MAX_MAX) { |
|
166 error_msg("unrecognized hash_len=%d in %s", |
|
167 header.hash_len, fname); |
|
168 exit(1); |
|
169 } |
|
170 strftime(date_buf, sizeof(date_buf), "%m/%d %X", |
|
171 gmtime_r(&header.now, &tm)); |
|
172 strftime(date_buf2, sizeof(date_buf2), "%m/%d %X", |
|
173 gmtime_r(&header.cleared, &tm)); |
|
174 printf("recorded %s cleared %s anon delay=", date_buf, date_buf2); |
|
175 if (header.anon_delay_us == DCC_ANON_DELAY_FOREVER) { |
|
176 printf("forever"); |
|
177 } else { |
|
178 printf("%d", header.anon_delay_us/1000); |
|
179 if (header.anon_delay_inflate != DCC_ANON_INFLATE_OFF) |
|
180 printf(",%d", header.anon_delay_inflate); |
|
181 } |
|
182 putchar('\n'); |
|
183 |
|
184 if (avg) |
|
185 printf(PAT_REQUESTS_B |
|
186 PAT_AVGS_B |
|
187 PAT_DATE_ID_B |
|
188 PAT_VERS_B |
|
189 PAT_DELAY_B "\n", |
|
190 "ops", "nops", |
|
191 "averages", |
|
192 " last seen", "ID", |
|
193 "V", |
|
194 "delay"); |
|
195 else |
|
196 printf(PAT_REQUESTS_B |
|
197 PAT_DATE_ID_B |
|
198 PAT_VERS_B |
|
199 PAT_DELAY_B "\n", |
|
200 "ops", "nops", |
|
201 " last seen", "ID", |
|
202 "V", |
|
203 "delay"); |
|
204 |
|
205 total = 0; |
|
206 active = 0; |
|
207 memset(versions, 0, sizeof(versions)); |
|
208 while ((pos -= ISZ(RL_DATA)) >= ISZ(header)) { |
|
209 if (!clients_read(fname, f, pos, &data, sizeof(data))) |
|
210 break; |
|
211 |
|
212 ++total; |
|
213 if (data.requests) |
|
214 ++active; |
|
215 |
|
216 if (data.pkt_vers < DIM(versions)) |
|
217 i = data.pkt_vers; |
|
218 else |
|
219 i = 0; |
|
220 ++versions[i].hosts; |
|
221 versions[i].requests += data.requests; |
|
222 versions[i].nops += data.nops; |
|
223 |
|
224 if (quiet) |
|
225 continue; |
|
226 |
|
227 if (data.requests != 0 || data.nops != 0) { |
|
228 printf(PAT_REQUESTS, |
|
229 data.requests, data.nops); |
|
230 } else { |
|
231 printf(PAT_REQUESTS_B, "-", "-"); |
|
232 } |
|
233 |
|
234 if (avg) { |
|
235 if (data.requests_avg != 0 || data.nops_avg != 0) { |
|
236 secs = header.now - data.requests_avg_start; |
|
237 printf(PAT_AVGS, |
|
238 data.requests_avg, data.nops_avg, |
|
239 secs / (60*60*1.0)); |
|
240 } else { |
|
241 printf(PAT_AVGS_B, ""); |
|
242 } |
|
243 } |
|
244 |
|
245 strftime(date_buf, sizeof(date_buf), "%m/%d %X", |
|
246 gmtime_r(&data.last_used, &tm)); |
|
247 if (data.clnt_id == DCC_ID_ANON) |
|
248 printf(PAT_DATE_ID_B, date_buf, ""); |
|
249 else if (data.clnt_id == DCC_ID_SRVR_ROGUE) |
|
250 printf(PAT_DATE_ID_B, date_buf, "server"); |
|
251 else |
|
252 printf(PAT_DATE_ID, date_buf, data.clnt_id, |
|
253 (data.flags & RL_FG_ANON) ? '*' : ' '); |
|
254 |
|
255 if (data.pkt_vers != 0) |
|
256 printf(PAT_VERS, data.pkt_vers); |
|
257 else if (data.clnt_id == DCC_ID_SRVR_ROGUE) |
|
258 printf(PAT_VERS_B, ""); |
|
259 else |
|
260 printf(PAT_VERS_B, "?"); |
|
261 |
|
262 if (data.flags & RL_FG_PASSWD) { |
|
263 printf(PAT_DELAY_B, "pass"); |
|
264 } else if (data.flags & RL_FG_UKN_ID) { |
|
265 printf(PAT_DELAY_B, "ID"); |
|
266 } else if (data.flags & RL_FG_BL_ADDR) { |
|
267 printf(PAT_DELAY_B, "A BL"); |
|
268 } else if (data.flags & RL_FG_BL_ID) { |
|
269 printf(PAT_DELAY_B, "ID BL"); |
|
270 } else if (data.flags & RL_FG_BL_BAD) { |
|
271 printf(PAT_DELAY_B, "BAD"); |
|
272 } else if ((data.flags & RL_FG_ANON) |
|
273 && header.anon_delay_inflate != 0) { |
|
274 inflate = 1 + (RL_REQUESTS_AVG(&data) |
|
275 / header.anon_delay_inflate); |
|
276 if (inflate > (DCC_ANON_DELAY_MAX |
|
277 / header.anon_delay_us)) { |
|
278 delay_us = DCC_ANON_DELAY_MAX; |
|
279 } else { |
|
280 delay_us = inflate*header.anon_delay_us; |
|
281 } |
|
282 printf(PAT_DELAY, delay_us/DCC_US); |
|
283 } else { |
|
284 printf(PAT_DELAY_B, ""); |
|
285 } |
|
286 |
|
287 dcc_mk_su(&su, AF_INET6, &data.clnt_addr, 0); |
|
288 if (nonames) { |
|
289 printf("%s\n", |
|
290 dcc_su2str2(sustr, sizeof(sustr), &su)); |
|
291 } else { |
|
292 printf("%-16s %s\n", |
|
293 dcc_su2str2(sustr, sizeof(sustr), &su), |
|
294 dcc_su2name(name, sizeof(name), &su)); |
|
295 } |
|
296 } |
|
297 |
|
298 fclose(f); |
|
299 |
|
300 printf("%d of %d records active\n\n", active, total); |
|
301 |
|
302 printf("version hosts requests nops\n"); |
|
303 for (i = 0; i < DIM(versions); ++i) { |
|
304 if (versions[i].hosts == 0) |
|
305 continue; |
|
306 printf("%6d %6d %8d %8d\n", |
|
307 i, versions[i].hosts, |
|
308 versions[i].requests, versions[i].nops); |
|
309 } |
|
310 |
|
311 printf("\n * anonymous\n"); |
|
312 printf(" pass bad password\n"); |
|
313 printf(" ID unknown ID\n"); |
|
314 printf(" A BL address blacklist\n"); |
|
315 printf(" ID BL ID blacklist\n"); |
|
316 printf(" BAD otherwise bad\n"); |
|
317 } |
|
318 |
|
319 |
|
320 |
|
321 int NRATTRIB |
|
322 main(int argc, char **argv) |
|
323 { |
|
324 int i; |
|
325 |
|
326 avg = 0; |
|
327 nonames = 0; |
|
328 quiet = 0; |
|
329 |
|
330 while ((i = getopt(argc, argv, "anqgh:")) != -1) { |
|
331 switch (i) { |
|
332 case 'a': |
|
333 ++avg; |
|
334 break; |
|
335 |
|
336 case 'n': |
|
337 nonames = 1; |
|
338 break; |
|
339 |
|
340 case 'q': |
|
341 quiet = 1; |
|
342 break; |
|
343 |
|
344 case 'g': |
|
345 grey_on = 1; |
|
346 break; |
|
347 |
|
348 case 'h': |
|
349 homedir = optarg; |
|
350 break; |
|
351 |
|
352 default: |
|
353 usage(); |
|
354 } |
|
355 } |
|
356 argc -= optind; |
|
357 argv += optind; |
|
358 |
|
359 dcc_cdhome(0, homedir, 1); |
|
360 |
|
361 if (argc == 0) { |
|
362 dump_file(CLIENTS_NM()); |
|
363 } else { |
|
364 for (i = 0; i < argc; ++i) { |
|
365 dump_file(argv[i]); |
|
366 } |
|
367 } |
|
368 |
|
369 exit(0); |
|
370 } |