Mercurial > notdcc
comparison dccd/dump-clients/dump-clients.c @ 0:c7f6b056b673
First import of vendor version
author | Peter Gervai <grin@grin.hu> |
---|---|
date | Tue, 10 Mar 2009 13:49:58 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c7f6b056b673 |
---|---|
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 } |