1 /*
2  * sma -- Sendmail log analyser
3  *
4  * Copyright (c) 2000, 2001, 2002 Jarkko Turkulainen. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY JARKKO TURKULAINEN ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL JARKKO TURKULAINEN BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $Date: 2003/04/03 12:43:33 $
30  */
31 #include "conf.h"
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <time.h>
37 #include <errno.h>
38 
39 #ifdef USE_REGEXP
40 #include <sys/types.h>
41 #if defined _WIN32
42 #include "regex/regex.h"
43 #else /* defined _WIN32 */
44 #include <regex.h>
45 #endif /* defined _WIN32 */
46 #endif /* defined USE_REGEXP */
47 
48 #if !defined _WIN32
49 #include <unistd.h>
50 #endif
51 
52 #define VERSION		"1.4"
53 #define FORMAT_ASCII	3
54 #define FORMAT_HTML	2
55 #define FORMAT_CLOG	5
56 
57 /* pointer to program name: */
58 extern char *pname;
59 
60 /* current time: */
61 extern time_t tval;
62 extern struct tm *curr;
63 extern struct tm tp;
64 
65 /*
66  * Command line arguments
67  * xflag sets argument x on/off
68  * xchar is pointer to argument string if x requires an argument
69  */
70 extern int aflag;
71 extern int cflag;
72 extern int dflag;
73 extern int hflag;
74 extern int nflag;
75 extern int sflag;
76 extern int qflag;
77 extern int lflag;
78 extern int vflag;
79 extern int wflag;
80 extern unsigned int lnum;
81 extern unsigned int lrnum;
82 extern int rflag;
83 extern unsigned int rnum;
84 extern unsigned int rrnum;
85 extern int bflag;
86 extern const char *bchar;
87 extern int fflag;
88 extern const char *fchar;
89 extern int oflag;
90 extern const char *ochar;
91 extern int Lflag;
92 extern const char *Lchar;
93 extern int Oflag;
94 extern const char *Ochar;
95 extern int Dflag;
96 extern const char *Dchar;
97 extern int pflag;
98 extern int iflag;
99 extern int tflag;
100 extern int dcaddrflag;
101 extern const char *tchar;
102 
103 /* Configuration file parameters: */
104 extern int Hflag;
105 extern const char *Hchar;
106 extern int Cflag;
107 extern const char *Cchar;
108 extern int Fflag;
109 extern const char *tbchar;
110 extern int pgflag;
111 extern const char *bechar;
112 extern const char *cfchar;
113 extern const char *puchar;
114 extern const char *pachar;
115 extern const char *plchar;
116 extern const char *ppchar;
117 extern const char *htchar;
118 extern const char *ftchar;
119 extern int csflag;
120 extern int lrflag;
121 extern int rrflag;
122 extern int clsflag;
123 extern unsigned int stnum;
124 extern unsigned int rsnum;
125 extern unsigned int rsrnum;
126 extern unsigned int epnum;
127 extern unsigned int rpnum;
128 
129 /* Start and end times: */
130 extern char *sstring;
131 extern char *estring;
132 extern char *tstring;
133 extern time_t sstime;
134 extern time_t eetime;
135 extern int syear;
136 extern int smonth;
137 extern int sday;
138 extern int shour;
139 extern int sminute;
140 extern int ssecond;
141 extern int eyear;
142 extern int emonth;
143 extern int eday;
144 extern int ehour;
145 extern int eminute;
146 extern int esecond;
147 
148 /* hash table sizes: */
149 extern int asize;
150 extern int rsize;
151 extern char *hsstring;
152 extern char *hastring;
153 extern char *hrstring;
154 
155 /* sender structure: */
156 struct in {
157 
158 	/* next struct: */
159 	struct in *next;
160 
161 	/* name of the entry: */
162 	char *name;
163 
164 	/* total number of msgs: */
165 	unsigned int num;
166 
167 	/* total size: */
168 	long double size;
169 };
170 
171 /* receiver structure: */
172 struct out {
173 
174 	/* next struct: */
175 	struct out *next;
176 
177 	/* name of the entry: */
178 	char *name;
179 
180 	/* total number of msgs: */
181 	unsigned int num;
182 
183 	/* total size: */
184 	long double size;
185 
186 };
187 
188 /* input relay struct: */
189 struct rin {
190 
191 	/* next */
192 	struct rin *next;
193 
194 	/* name: */
195 	char *name;
196 
197 	/* total number: */
198 	unsigned int num;
199 
200 	/* total size: */
201 	long double size;
202 };
203 
204 /* output relay struct: */
205 struct rout {
206 
207 	/* next */
208 	struct rout *next;
209 
210 	/* name: */
211 	char *name;
212 
213 	/* total number: */
214 	unsigned int num;
215 
216 	/* total size: */
217 	long double size;
218 };
219 
220 /* message id structure: */
221 struct msgid {
222 
223 	/* next */
224 	struct msgid *next;
225 
226 	/* message id */
227 	char *id;
228 
229 	/* msgid */
230 	char *msgid;
231 
232 	/* sender */
233 	char *sender;
234 
235 	/* relay */
236 	char *relay;
237 
238 	/* hour and day */
239 	int hh;
240 	int day;
241 
242 	/* size of the msg */
243 	long double size;
244 
245 	/* number of msgs  */
246 	int num;
247 
248 	/* flags */
249 	int flag;
250 };
251 
252 /*
253  * Structure for out-of-order messages, that is for
254  * messages without "to=" line in log (unknown local user etc.)
255  */
256 struct omsgid {
257 
258 	/* next */
259 	struct omsgid *next;
260 
261 	/* message id */
262 	char *id;
263 
264 	/* flags */
265 	int flags;
266 };
267 
268 /* Relay structure for rulesets: */
269 struct rrelay {
270 
271 	/* next */
272 	struct rrelay *next;
273 
274 	/* name: */
275 	char *name;
276 
277 	/* total number: */
278 	unsigned int num;
279 
280 };
281 
282 /* Structure for ruleset based rejections */
283 struct rule {
284 
285 	/* next */
286 	struct rule *next;
287 
288 	/* Relay structure for rulesets: */
289 	struct rrelay *rrelaytab;
290 	struct rrelay **srrelaytab;
291 	unsigned int reldif;
292 
293 	/* name: */
294 	char *name;
295 
296 	/* total number: */
297 	unsigned int num;
298 
299 };
300 
301 /* Status structure */
302 struct status {
303 
304 	/* next */
305 	struct status *next;
306 
307 	/* name: */
308 	char *name;
309 
310 	/* total number: */
311 	unsigned int num;
312 };
313 
314 /* Envelope pair structure */
315 struct envpair {
316 
317 	/* next */
318 	struct envpair *next;
319 
320 	/* pairs: */
321 	char *fname;
322 	char *tname;
323 
324 	/* total number: */
325 	unsigned int num;
326 
327 	/* total size: */
328 	long double size;
329 };
330 
331 /* Relay pair structure */
332 struct relpair {
333 
334 	/* next */
335 	struct relpair *next;
336 
337 	/* pairs: */
338 	char *fname;
339 	char *tname;
340 
341 	/* total number: */
342 	unsigned int num;
343 
344 	/* total size: */
345 	long double size;
346 };
347 
348 
349 /* host structure: */
350 struct host {
351 
352 	/* next struct: */
353 	struct host *next;
354 
355 	/* name of the entry: */
356 	char *name;
357 
358 	/* envelope pair structures: */
359 	struct envpair **etab;
360 	struct envpair **setab;
361 
362 	/* pointers to in -and out addresses: */
363 	struct in **itab;
364 	struct out **otab;
365 	struct in **sitab;
366         struct out **sotab;
367 
368 	/* relay pair structures: */
369 	struct relpair **rtab;
370 	struct relpair **srtab;
371 
372 	/* pointers to in -and out relays: */
373 	struct rin **ritab;
374 	struct rout **rotab;
375 	struct rin **rsitab;
376 	struct rout **rsotab;
377 
378 	/* ruleset structures */
379 	struct rule **ruletab;
380 	struct rule **sruletab;
381 
382 	/* status structures */
383 	struct status **sttab;
384 	struct status **ssttab;
385 
386 	/* pointer to message id table: */
387 	struct msgid *msgidtab;
388 
389 	/* pointer to out-of-order msg ids: */
390 	struct omsgid *omsgidtab;
391 
392 	/* start and end times: */
393 	time_t ftime;
394 	time_t ltime;
395 	time_t cdtime;
396 	double dtime;
397 	int fday;
398 	int lday;
399 	int fhour;
400 
401 	/* alias table rebuilds: */
402 	int alias;
403 
404 	/* SYSERR: */
405 	int hopc;
406 	int lcerror;
407 	int oserror;
408 
409 	/* daemon starts: */
410 	int dstart;
411 
412 	/* time tables: */
413 	int ihh[24];
414 	float fihh[24];
415 	int idd[7];
416 	float fidd[7];
417 	int ohh[24];
418 	float fohh[24];
419 	int odd[7];
420 	float fodd[7];
421 
422 	/* total number of msgs: */
423 	unsigned long inum;
424 	unsigned long onum;
425 	unsigned long rinum;
426 	unsigned long ronum;
427 	unsigned long gonum;
428 
429 	/* stat-fields: Sent, queued, Host unknown, Deferred ...*/
430 	int sent;
431 	int queu;
432 	int hunk;
433 	int uunk;
434 	int defe;
435 	int rule;
436 	int service;
437 	int other;
438 
439 	/* total size of msgs: */
440 	long double size;
441 	long double isize;
442 	long double osize;
443 	int lsize;
444 	int fhost;
445 
446 	/* total number of different messages: */
447 	unsigned int edif; /* envelope pairs */
448 	unsigned int rrdif; /* relay pairs */
449 	unsigned int idif; /* input envelope */
450 	unsigned int odif; /* output envelope */
451 	unsigned int ridif; /* input relay */
452 	unsigned int rodif; /* output relay */
453 	unsigned int sdif; /* status messages */
454 	unsigned int rdif; /* rejected messages */
455 
456 };
457 
458 /* Filters */
459 extern char *sef;
460 extern char *ref;
461 extern char *srf;
462 extern char *rrf;
463 #ifdef USE_REGEXP
464 extern regex_t csef;
465 extern regex_t cref;
466 extern regex_t csrf;
467 extern regex_t crrf;
468 #endif
469 
470 /* Output file handle: */
471 extern FILE *ofp;
472 
473 /* total number of hosts: */
474 extern int hosts;
475 
476 /* inital host structure: */
477 extern struct host first;
478 
479 /* function definitions: */
480 void usage(void);
481 void error_memory(void);
482 void parse(FILE *, const char *);
483 time_t conv_time(int, int, int, int, int);
484 int conv_mon(const char *);
485 void copying(void);
486 const char * get_name(char *);
487 const char * get_relay_name(char *);
488 unsigned hash(const char *,int);
489 struct host *init_host(const char *);
490 void update_in(struct host *, const char *, int);
491 void remove_in(struct host *, const char *, int);
492 void update_out(struct host *, const char *, int);
493 void update_rin(struct host *, const char *, int);
494 void remove_rin(struct host *, const char *, int);
495 void update_rout(struct host *, const char *, int);
496 int comp_env(const void *, const void *);
497 int comp_in(const void *, const void *);
498 int comp_out(const void *, const void *);
499 int comp_rel(const void *, const void *);
500 int comp_rin(const void *, const void *);
501 int comp_rout(const void *, const void *);
502 int comp_s(const void *, const void *);
503 int comp_r(const void *, const void *);
504 int comp_rrel(const void *, const void *);
505 void sort(struct host *);
506 void average(struct host *, int *, float *, int *, float *);
507 void html(FILE *);
508 void ascii(FILE *);
509 void init(FILE *);
510 int update_msgid(struct host *, const char *, const char *, const char *,
511 	int, int, int, int, const char *);
512 int update_omsgid(struct host *, const char *, int);
513 void check_msgid(struct host *, const char *, int);
514 void remove_msgid(struct host *, const char *);
515 int check_omsgid(struct host *, const char *);
516 struct msgid *get_msgid(struct host *, const char *);
517 char * stripn(char *);
518 char * get_string(char *);
519 void printclog(time_t, const char *, int, const char *, const char *,
520 	const char *, const char *, const char *, int);
521 void update_status(struct host *, const char *);
522 void update_ruleset(struct host *, const char *, const char *);
523 void update_envpair(struct host *, const char *, const char *, int);
524 void update_relpair(struct host *, const char *, const char *, int);
525 void scan_time(time_t *, char *);
526 void dump_config(FILE *);
527 
528 /* macros */
529 #define MIN(a,b) (a > b) ? b : a
530