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 }